Skip to content

Commit

Permalink
Shields rework bugfixes 2 (#4144)
Browse files Browse the repository at this point in the history
- reduce flickering of shield at 0% by having a 1 second minimum downtime
- fix bug with populating unitdef data tables with the last weapon in the unitdef causing cortex commanders to become invincible
- make recharge rate constant, transfer the overcharge to the shield charge when it comes back online
  • Loading branch information
SethDGamre authored Jan 10, 2025
1 parent fd04cde commit 0479257
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 19 deletions.
4 changes: 0 additions & 4 deletions gamedata/alldefs_post.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1560,10 +1560,6 @@ function WeaponDef_Post(name, wDef)
end
end

if modOptions.evocom == true and wDef.weapontype == "DGun" then
wDef.interceptedbyshieldtype = 1
end

if modOptions.multiplier_shieldpower then
if wDef.shield then
local multiplier = modOptions.multiplier_shieldpower
Expand Down
40 changes: 25 additions & 15 deletions luarules/gadgets/unit_shield_behaviour.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ local reworkEnabled = Spring.GetModOptions().shieldsrework --remove when shi
local shieldModulo = Game.gameSpeed
local shieldOnUnitRulesParamIndex = 531313
local INLOS = { inlos = true }
local minDownTime = 1 * Game.gameSpeed -- measured in frames

local spGetUnitShieldState = Spring.GetUnitShieldState
local spSetUnitShieldState = Spring.SetUnitShieldState
Expand Down Expand Up @@ -53,6 +54,8 @@ local projectileShieldHitCache = {}
local highestWeapDefDamages = {}
local armoredUnitDefs = {}

local gameFrame = 0

for weaponDefID, weaponDef in ipairs(WeaponDefs) do

if weaponDef.type == 'Flame' or weaponDef.customParams.overpenetrate then --overpenetration and flame projectiles aren't deleted when striking the shield. For compatibility with shield blocking type overrides.
Expand Down Expand Up @@ -125,13 +128,14 @@ for unitDefID, unitDef in pairs(UnitDefs) do

for i, weaponsData in pairs(unitDef.weapons) do
local wDefData = WeaponDefs[weaponsData.weaponDef]
if wDefData.shieldPowerRegen then
if wDefData.shieldPowerRegen and wDefData.shieldPowerRegen > 0 then
data.shieldWeaponNumber = i
data.shieldPowerRegen = wDefData.shieldPowerRegen
data.shieldPowerRegenEnergy = wDefData.shieldPowerRegenEnergy
end
end
shieldUnitDefs[unitDefID] = data
Spring.Echo(unitDef.name, data)
end

if unitDef.weapons then
Expand Down Expand Up @@ -196,7 +200,8 @@ function gadget:UnitFinished(unitID, unitDefID, unitTeam)
shieldEnabled = false, -- Virtualized enabled/disabled state until engine equivalent is changed
shieldDamage = 0, -- This stores the value of damages populated in ShieldPreDamaged(), then applied in GameFrame() all at once
shieldCoverageChecked = false, -- Used to prevent expensive unit coverage checks being performed more than once per cycle
overKillDamage = 0
overKillDamage = 0,
shieldDownTime = 0
}
setCoveredUnits(unitID)
end
Expand Down Expand Up @@ -231,6 +236,7 @@ local function suspendShield(unitID, weaponNum)

spSetUnitShieldState(unitID, weaponNum, false)
shieldData.shieldEnabled = false
shieldData.shieldDownTime = gameFrame + minDownTime
spSetUnitRulesParam(unitID, shieldOnUnitRulesParamIndex, 0, INLOS)
end

Expand Down Expand Up @@ -280,6 +286,8 @@ local shieldCheckChunkSize = 10
local shieldCheckEndIndex = 1

function gadget:GameFrame(frame)
gameFrame = frame

if not reworkEnabled then return end --remove when shield rework is permanent
for shieldUnitID, _ in pairs(shieldCheckFlags) do
local shieldData = shieldUnitsData[shieldUnitID]
Expand All @@ -291,7 +299,7 @@ function gadget:GameFrame(frame)
shieldPower = shieldPower - shieldData.shieldDamage

if shieldPower < 0 then
shieldData.overKillDamage = -shieldPower --invert the negative value
shieldData.overKillDamage = shieldPower --stored as a negative value
shieldPower = 0
end

Expand All @@ -313,21 +321,23 @@ function gadget:GameFrame(frame)
local shieldActive = spGetUnitIsActive(shieldUnitID)

if frame % shieldModulo == 0 then
if shieldActive and shieldData.overKillDamage ~= 0 then
local ratio = 1
if shieldData.overKillDamage < shieldData.shieldPowerRegen then
ratio = shieldData.overKillDamage / shieldData.shieldPowerRegen
end
local usedEnergy = spUseUnitResource(shieldUnitID, "e", shieldData.shieldPowerRegenEnergy * ratio)
if usedEnergy then
shieldData.overKillDamage = mathMax(shieldData.overKillDamage - shieldData.shieldPowerRegen, 0)
if shieldActive then
if shieldData.overKillDamage ~= 0 then
local usedEnergy = spUseUnitResource(shieldUnitID, "e", shieldData.shieldPowerRegenEnergy)
if usedEnergy then
shieldData.overKillDamage = shieldData.overKillDamage + shieldData.shieldPowerRegen
end
end
end

if not shieldActive then
else
--if shield is manually turned off, set shield charge to 0
spSetUnitShieldState(shieldUnitID, shieldData.shieldWeaponNumber, 0)
end
if not shieldData.shieldEnabled and shieldData.overKillDamage == 0 then

if not shieldData.shieldEnabled and shieldData.shieldDownTime < frame and shieldData.overKillDamage >= 0 then
if shieldData.overKillDamage ~= 0 then
spSetUnitShieldState(shieldUnitID, shieldData.shieldWeaponNumber, shieldData.overKillDamage)
shieldData.overKillDamage = 0
end
shieldData.shieldEnabled = true
spSetUnitRulesParam(shieldUnitID, shieldOnUnitRulesParamIndex, 1, INLOS)
spSetUnitShieldRechargeDelay(shieldUnitID, shieldData.shieldWeaponNumber, 0)
Expand Down

0 comments on commit 0479257

Please sign in to comment.