Skip to content
Open
1 change: 1 addition & 0 deletions changelog/snippets/fix.7051.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- (#7051) Fix a unit-transfer exploit that adds silo progress to nuke subs and the Seraphim battleship for free.
4 changes: 3 additions & 1 deletion engine/Core/Blueprints/WeaponBlueprint.lua
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,9 @@
---@field RateOfFire number
--- if this weapon will find new target on miss events
---@field ReTargetOnMiss? boolean
--- if `true`, will set the orange work progress bar to display the reload progress of this weapon
--- if `true`, will set the orange work progress bar to display the reload progress of this weapon.
--- Should not be used for units with silo weapons, as the work progress of the reload will transfer
--- as silo build progress after unit transfer.
---@field RenderFireClock? boolean
--- used by the XSL0402 (Othuy "lighting storm") to define the time to re-aquire a new target before going
--- through the next lighting strike process
Expand Down
4 changes: 2 additions & 2 deletions lua/SimUtils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ function TransferUnitsOwnership(units, toArmy, captured, noRestrictions)

-- B E F O R E
local orientation = unit:GetOrientation()
local workprogress = unit:GetWorkProgress()
local siloWorkProgress = unit:IsUnitState("SiloBuildingAmmo") and unit:GetWorkProgress() or 0
local numNukes = unit:GetNukeSiloAmmoCount() -- nuclear missiles; SML or SMD
local numTacMsl = unit:GetTacticalSiloAmmoCount()
local massKilled = unit.VetExperience
Expand Down Expand Up @@ -448,7 +448,7 @@ function TransferUnitsOwnership(units, toArmy, captured, noRestrictions)
end

if newUnit.Blueprint.CategoriesHash["SILO"] then
newUnit:GiveNukeSiloBlocks(workprogress)
newUnit:GiveNukeSiloBlocks(siloWorkProgress)
end

local newShield = newUnit.MyShield
Expand Down
5 changes: 5 additions & 0 deletions lua/sim/Unit.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2556,6 +2556,11 @@ Unit = ClassUnit(moho.unit_methods, IntelComponent, VeterancyComponent, DebugUni
self.SiloWeapon = weapon
self.SiloProjectile = weapon:GetProjectileBlueprint()

-- Prevent work progress set by weapons using `RenderFireClock` from
-- turning into silo progress after ownership transfer of a unit paused
-- in the silo build state without having updated progress by the engine.
self:SetWorkProgress(0)

-- for AI events
self.Brain:OnUnitSiloBuildStart(self, weapon)
end,
Expand Down
12 changes: 8 additions & 4 deletions lua/sim/weapons/DefaultProjectileWeapon.lua
Original file line number Diff line number Diff line change
Expand Up @@ -935,10 +935,14 @@ DefaultProjectileWeapon = ClassWeapon(Weapon) {
local unit = self.unit
local clockTime = math.round(10 * rateOfFire)
local totalTime = clockTime
while clockTime >= 0 and
not self:BeenDestroyed() and
not unit.Dead do
unit:SetWorkProgress(1 - clockTime / totalTime)
while clockTime >= 0
and not self:BeenDestroyed()
and not unit.Dead
do
-- do not override work progress that is used for replenishing silo ammo upon unit transfer
if not unit:IsUnitState("SiloBuildingAmmo") then
unit:SetWorkProgress(1 - clockTime / totalTime)
end
clockTime = clockTime - 1
WaitSeconds(0.1)
end
Expand Down
Loading