Skip to content

Commit a81e34c

Browse files
committed
EMP implementation of overstun. TODO disarm.
1 parent ba93386 commit a81e34c

5 files changed

Lines changed: 59 additions & 28 deletions

File tree

LuaRules/Gadgets/unit_boolean_disable.lua

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ for wid = 1, #WeaponDefs do
4444
}
4545
wantedWeaponList[#wantedWeaponList + 1] = wid
4646
elseif wd.paralyzer or wd.customParams.extra_damage then
47-
local paraTime = wd.paralyzer and wd.damages.paralyzeDamageTime or wd.customParams.extra_paratime
47+
local paraTime = wd.paralyzer and wd.customParams.emp_paratime or wd.customParams.extra_paratime
4848
paraWeapons[wid] = paraTime * FRAMES_PER_SECOND
4949
wantedWeaponList[#wantedWeaponList + 1] = wid
5050
end
@@ -228,7 +228,6 @@ function gadget:UnitPreDamaged(unitID, unitDefID, unitTeam, damage, paralyzer,
228228
if paralyzer and (partialUnitID[unitID] or paraUnitID[unitID]) then
229229
addParalysisDamageToUnit(unitID, damage, paraWeapons[weaponDefID], overstunDamageMult[weaponDefID])
230230
end
231-
232231
return damage
233232
end
234233

LuaRules/Gadgets/unit_paralysis_damage.lua

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,33 @@ local spGetUnitHealth = Spring.GetUnitHealth
2323
local spGetUnitArmored = Spring.GetUnitArmored
2424
local spAddUnitDamage = Spring.AddUnitDamage
2525

26+
local DECAY_SECONDS = 40 -- how long it takes to decay 100% para to 0
27+
2628
local normalDamageMult = {}
2729
local wantedWeaponList = {}
2830
local paraTime = {}
2931
local overstunDamageMult = {}
32+
local overstunTime = {}
3033
-- Note that having EMP damage decay N times faster when above 100% is mathematically
3134
-- equivalent multiplying all incoming EMP damage above 100% by of 1/N.
3235

3336
for wdid = 1, #WeaponDefs do
3437
local wd = WeaponDefs[wdid]
3538
if wd.paralyzer then
3639
wantedWeaponList[#wantedWeaponList + 1] = wdid
40+
paraTime[wdid] = math.max(1, wd.customParams.emp_paratime)
3741
else
3842
local rawDamage = tonumber(wd.customParams.raw_damage or 0)
3943
if wd.customParams and wd.customParams.extra_damage and rawDamage > 0 then
4044
normalDamageMult[wdid] = wd.customParams.extra_damage/rawDamage
41-
4245
-- engine rounds down, but paratime 0 means real damage
4346
paraTime[wdid] = math.max(1, wd.customParams.extra_paratime)
44-
4547
wantedWeaponList[#wantedWeaponList + 1] = wdid
4648
end
4749
end
50+
if wd.customParams and wd.customParams.overstun_time then
51+
overstunTime[wdid] = tonumber(wd.customParams.overstun_time)
52+
end
4853
if wd.customParams and wd.customParams.overstun_damage_mult then
4954
overstunDamageMult[wdid] = tonumber(wd.customParams.overstun_damage_mult)
5055
end
@@ -58,27 +63,41 @@ function gadget:UnitDamaged_GetWantedWeaponDef()
5863
return wantedWeaponList
5964
end
6065

66+
local function GetStunDamage(weaponDefID, damage, health, maxHealth, paralyzeDamage)
67+
if not (weaponDefID and overstunDamageMult[weaponDefID]) then
68+
return damage*maxHealth/health
69+
end
70+
71+
local rawDamage = damage*maxHealth/health
72+
if maxHealth <= paralyzeDamage then
73+
--Spring.Echo("Above", rawDamage*overstunDamageMult[weaponDefID])
74+
return rawDamage*overstunDamageMult[weaponDefID]
75+
end
76+
local damageGap = (maxHealth - paralyzeDamage)
77+
if rawDamage <= damageGap then
78+
--Spring.Echo("damageGap", maxHealth, paralyzeDamage, damageGap, rawDamage)
79+
return rawDamage
80+
end
81+
--Spring.Echo("Partial", maxHealth, paralyzeDamage, damageGap, rawDamage, damageGap + (rawDamage - damageGap)*overstunDamageMult[weaponDefID])
82+
return damageGap + (rawDamage - damageGap)*overstunDamageMult[weaponDefID]
83+
end
84+
6185
function gadget:UnitPreDamaged(unitID, unitDefID, unitTeam, damage, paralyzer,
6286
weaponDefID, attackerID, attackerDefID, attackerTeam)
6387
if paralyzer then -- the weapon deals paralysis damage
6488
local health, maxHealth, paralyzeDamage = spGetUnitHealth(unitID)
6589
if health and maxHealth and health > 0 then -- taking no chances.
66-
if not (weaponDefID and overstunDamageMult[weaponDefID]) then
67-
return damage*maxHealth/health
68-
end
69-
70-
local rawDamage = damage*maxHealth/health
71-
if maxHealth <= paralyzeDamage then
72-
--Spring.Echo("Above", rawDamage*overstunDamageMult[weaponDefID])
73-
return rawDamage*overstunDamageMult[weaponDefID]
90+
local damage = GetStunDamage(weaponDefID, damage, health, maxHealth, paralyzeDamage)
91+
if overstunTime[weaponDefID] > 0 then
92+
-- Overstun allows units to stun for an addition time (usually 1 second) if the current stun time on the unit is within that range.
93+
local currentStunTime = (paralyzeDamage/maxHealth - 1) * DECAY_SECONDS
94+
local maxTime = math.max(paraTime[weaponDefID], math.min(paraTime[weaponDefID], currentStunTime) + overstunTime[weaponDefID])
95+
-- Solve the following for damage to limit damage by stun time:
96+
-- stun time = ((damage + paralyzeDamage)/maxHealth - 1) * DECAY_SECONDS
97+
damage = (maxTime/DECAY_SECONDS + 1)*maxHealth - paralyzeDamage
7498
end
75-
local damageGap = (maxHealth - paralyzeDamage)
76-
if rawDamage <= damageGap then
77-
--Spring.Echo("damageGap", maxHealth, paralyzeDamage, damageGap, rawDamage)
78-
return rawDamage
79-
end
80-
--Spring.Echo("Partial", maxHealth, paralyzeDamage, damageGap, rawDamage, damageGap + (rawDamage - damageGap)*overstunDamageMult[weaponDefID])
81-
return damageGap + (rawDamage - damageGap)*overstunDamageMult[weaponDefID]
99+
--Spring.Echo("damage", damage, ((damage + paralyzeDamage)/maxHealth - 1) * DECAY_SECONDS, paralyzeDamage, math.random())
100+
return damage
82101
end
83102
end
84103

@@ -88,13 +107,11 @@ end
88107
function gadget:UnitDamaged(unitID, unitDefID, unitTeam, damage, paralyzer, weaponDefID, attackerID)
89108
local mult = normalDamageMult[weaponDefID]
90109
if mult and not paralyzer then
91-
92110
-- Don't apply armour twice.
93111
local armored, armorMult = spGetUnitArmored(unitID)
94112
if armored then
95113
mult = mult/armorMult
96114
end
97-
98-
spAddUnitDamage(unitID, mult*damage, paraTime[weaponDefID], attackerID, weaponDefID)
115+
spAddUnitDamage(unitID, mult*damage, paraTime[weaponDefID] + overstunTime[weaponDefID], attackerID, weaponDefID)
99116
end
100117
end

LuaUI/Widgets/dbg_wiki_export.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ local function getDamages(wd)
165165
if wd.paralyzer then
166166
damw = val
167167
if stun_time == 0 then
168-
stun_time = wd.damages.paralyzeDamageTime
168+
stun_time = tonumber(wd.customParams.emp_paratime)
169169
end
170170
else
171171
dam = val

LuaUI/Widgets/gui_contextmenu.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ local function weapons2Table(cells, ws, unitID)
551551
if wd.paralyzer then
552552
damw = val
553553
if stun_time == 0 then
554-
stun_time = wd.damages.paralyzeDamageTime
554+
stun_time = tonumber(wd.customParams.emp_paratime)
555555
end
556556
else
557557
dam = val
@@ -1786,7 +1786,7 @@ local function printunitinfo(ud, buttonWidth, unitID)
17861786
if (weaponStats.paralyzer) then
17871787
statschildren[#statschildren+1] = Label:New{ caption = numformat(damageValue) .. " (P)", textColor = colorCyan, }
17881788
statschildren[#statschildren+1] = Label:New{ caption = 'Max EMP time: ', textColor = color.stats_fg, }
1789-
statschildren[#statschildren+1] = Label:New{ caption = numformat(weaponStats.damages.paralyzeDamageTime) .. "s", textColor = color.stats_fg, }
1789+
statschildren[#statschildren+1] = Label:New{ caption = numformat(wepCp.emp_paratime) .. "s", textColor = color.stats_fg, }
17901790
else
17911791
local damageSlow = (wepCp.timeslow_damagefactor or 0)*damageValue
17921792
local damageText

gamedata/weapondefs_post.lua

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,24 @@ for _, weaponDef in pairs(WeaponDefs) do
159159
end
160160
end
161161

162+
--------------------------------------------------------------------------------
163+
--------------------------------------------------------------------------------
164+
--
165+
-- Allow one more second of stun so that gadgets can handle fractional seconds
166+
167+
for _, weaponDef in pairs(WeaponDefs) do
168+
if weaponDef.customparams.disarmdamagemult or weaponDef.paralyzetime then
169+
weaponDef.customparams.overstun_time = weaponDef.customparams.overstun_time or 1
170+
end
171+
if weaponDef.paralyzetime then
172+
if not weaponDef.paralyzer then
173+
weaponDef.customparams.extra_paratime = weaponDef.paralyzetime
174+
end
175+
weaponDef.customparams.emp_paratime = weaponDef.paralyzetime
176+
weaponDef.paralyzetime = weaponDef.paralyzetime + weaponDef.customparams.overstun_time
177+
end
178+
end
179+
162180
--------------------------------------------------------------------------------
163181
--------------------------------------------------------------------------------
164182
--
@@ -400,9 +418,6 @@ end
400418
-- ???
401419

402420
for _, weaponDef in pairs(WeaponDefs) do
403-
if weaponDef.paralyzetime and not weaponDef.paralyzer then
404-
weaponDef.customparams.extra_paratime = weaponDef.paralyzetime
405-
end
406421
if not weaponDef.predictboost then
407422
weaponDef.predictboost = 1
408423
end

0 commit comments

Comments
 (0)