Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assisting engineers track new construction orders #6176

Merged
merged 6 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog/snippets/features.6169.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(#6169) Shoulder pods (ACU drones) now track the focus of their parent unit more closely and will automatically switch to any engineering task their parent starts. Additionally, pods can now be properly assisted by other engineering units, and assist commands targeting them will persist when the pod attaches/detaches from the parent.

(#6169) The abort pathfinding key action on a lead unit will refocus any assisting engineers on the leader's task.
16 changes: 8 additions & 8 deletions lua/sim/Unit.lua
Original file line number Diff line number Diff line change
Expand Up @@ -854,14 +854,6 @@ Unit = ClassUnit(moho.unit_methods, IntelComponent, VeterancyComponent) {
self:CheckAssistersFocus()
self:DoUnitCallbacks('OnStartReclaim', target)

-- Force me to move on to the guard properly when done
local guard = self:GetGuardedUnit()
if guard then
IssueToUnitClearCommands(self)
IssueReclaim({self}, target)
IssueGuard({self}, guard)
end

-- add state to be able to show the amount reclaimed in the UI
if target.IsProp then
self.OnStartReclaimPropStartTick = GetGameTick() + 2
Expand Down Expand Up @@ -2775,6 +2767,14 @@ Unit = ClassUnit(moho.unit_methods, IntelComponent, VeterancyComponent) {
end
end,

---Called via hotkey to refocus any assisting engineers
---@param self Unit
RefocusAssisters = function(self)
local engineerGuards = EntityCategoryFilterDown(categories.ENGINEER, self:GetGuards())
IssueClearCommands(engineerGuards)
IssueGuard(engineerGuards, self)
end,

---@param self Unit
---@param built Unit
---@param order string
Expand Down
1 change: 1 addition & 0 deletions lua/sim/commands/abort-navigation.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function AbortNavigation(units, doPrint)
if not IsDestroyed(unit) then
local navigator = unit:GetNavigator()
navigator:AbortMove()
unit:RefocusAssisters()
end
end

Expand Down
199 changes: 199 additions & 0 deletions lua/sim/units/uef/TConstructionPodUnit.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
local TConstructionUnit = import("/lua/terranunits.lua").TConstructionUnit
local oldGetGuards = TConstructionUnit.GetGuards

---@class TConstructionPodUnit : TConstructionUnit
---@field Pod string
---@field Parent Unit
---@field guardCache table
---@field guardDummy Unit
TConstructionPodUnit = ClassUnit(TConstructionUnit) {
Parent = nil,

---@param self TConstructionPodUnit
OnCreate = function(self)
TConstructionUnit.OnCreate(self)
self.guardDummy = CreateUnitHPR('ZXA0003', self:GetArmy(), 0,0,0,0,0,0)
self.guardDummy:AttachTo(self, -1)
self.Trash:Add(self.guardDummy)
end,

---@param self TConstructionPodUnit
---@param bit number
OnScriptBitSet = function(self, bit)
TConstructionUnit.OnScriptBitSet(self, bit)
if bit == 1 then
self.rebuildDrone = true
end
end,

---@param self TConstructionPodUnit
---@param bit number
OnScriptBitClear = function(self, bit)
TConstructionUnit.OnScriptBitClear(self, bit)
if bit == 1 then
self.rebuildDrone = false
end
end,

---@param self TConstructionPodUnit
---@param transport Unit
---@param bone number
OnAttachedToTransport = function(self, transport, bone)
local guards = self:GetGuards()
IssueClearCommands(guards)
IssueGuard(guards, self.guardDummy)
TConstructionUnit.OnAttachedToTransport(self, transport, bone)
end,

---@param self TConstructionPodUnit
---@param transport Unit
---@param bone number
OnDetachedFromTransport = function(self, transport, bone)
TConstructionUnit.OnDetachedFromTransport(self, transport, bone)
local guards = self.guardDummy:GetGuards()
IssueClearCommands(guards)
IssueGuard(guards, self)
end,

---@param self TConstructionPodUnit
---@param parent Unit
---@param podName string
SetParent = function(self, parent, podName)
self.Parent = parent
self.Pod = podName
self:SetScriptBit('RULEUTC_WeaponToggle', true)
end,

---@param self TConstructionPodUnit
---@param unitBeingBuilt Unit
---@param order string
OnStartBuild = function(self, unitBeingBuilt, order)
TConstructionUnit.OnStartBuild(self, unitBeingBuilt, order)
self:FocusAssistersOnCurrentTask()
end,

---@param self TConstructionPodUnit
---@param built Unit
---@param order string
OnStopBuild = function(self, built, order)
TConstructionUnit.OnStopBuild(self, built, order)
-- Check if we finished our build task and clear our cached command if so
if self.guardCache and built:GetFractionComplete() == 1 then
self.guardCache = nil
end
end,

---@param self TConstructionPodUnit
---@param target Unit|Prop
OnStartReclaim = function(self, target)
TConstructionUnit.OnStartReclaim(self, target)
self:FocusAssistersOnCurrentTask()
end,

---@param self TConstructionPodUnit
---@param target Unit|Prop
OnStopReclaim = function(self, target)
TConstructionUnit.OnStopReclaim(self, target)
-- Check if we finished our reclaim task and clear our cached commaand if so
if self.guardCache and table.empty(target) then
self.guardCache = nil
end
end,

---@param self TConstructionPodUnit
---@param unitBeingRepaired Unit
OnStartRepair = function(self, unitBeingRepaired)
TConstructionUnit.OnStartRepair(self, unitBeingRepaired)
self:FocusAssistersOnCurrentTask()
end,

---@param self TConstructionPodUnit
FocusAssistersOnCurrentTask = function(self)

if self.Dead then
return
end

local engineerGuards = self:GetGuards()

-- Make sure we've got some assisters to work with
if not next(engineerGuards) then
self.guardCache = nil
return
end

-- Make sure we're performing an engineering task
if not (self:IsUnitState('Reclaiming')
or self:IsUnitState('Building')
or self:IsUnitState('Repairing')) then
return
end

local command
if self:IsUnitState('Reclaiming') then
command = IssueReclaim
elseif self:IsUnitState('Repairing') or self:IsUnitState('Building') then
command = IssueRepair
end

-- We only need to worry about refocusing our guards if we currently have an engineering target
local target = self:GetFocusUnit() or self:GetCommandQueue()[1].target
if target then
IssueClearCommands(engineerGuards)
command(engineerGuards, target)
IssueGuard(engineerGuards, self)
self.guardCache = engineerGuards
self.guardCache.target = target
self.guardCache.command = command
end
end,

---Called via hotkey to refocus assisters on our current task
---@param self TConstructionPodUnit
RefocusAssisters = function(self)
local engineerGuards = EntityCategoryFilterDown(categories.ENGINEER, self:GetGuards())
IssueClearCommands(engineerGuards)
if self.guardCache then
LOG('We have a guard cache')
self.guardCache.command(engineerGuards, self.guardCache.target)
end
IssueGuard(engineerGuards, self)
end,

---Override get guards to pick up our assist cache
---@param self TConstructionPodUnit
GetGuards = function(self)
local guards = oldGetGuards(self)
local count = 0
if self.guardCache then
local firstCommand, secondCommand
local target = self.guardCache.target
for _, guard in ipairs(self.guardCache) do
firstCommand, secondCommand = unpack(guard:GetCommandQueue())
if firstCommand.target == target
and secondCommand.target == self then
table.insert(guards, guard)
count = count + 1
end
end
end
if count > 0 then
print(string.format('Found %d cached guards', count))
end
return guards
end,

---@param self TConstructionPodUnit
---@param instigator Unit
---@param type string
---@param overkillRatio number
OnKilled = function(self, instigator, type, overkillRatio)
self.Parent:NotifyOfPodDeath(self.Pod, self.rebuildDrone)
self.Parent = nil
TConstructionUnit.OnKilled(self, instigator, type, overkillRatio)
end,

CreateWreckage = function (self, overkillRatio)
-- Don't make wreckage
end,
}
1 change: 1 addition & 0 deletions lua/terranunits.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ TAirStagingPlatformUnit = import('/lua/sim/units/uef/TAirStagingPlatformUnit.lua
TAirUnit = import('/lua/sim/units/uef/TAirUnit.lua').TAirUnit
TConcreteStructureUnit = import('/lua/sim/units/uef/TConcreteStructureUnit.lua').TConcreteStructureUnit
TConstructionUnit = import('/lua/sim/units/uef/TConstructionUnit.lua').TConstructionUnit
TConstructionPodUnit = import('/lua/sim/units/uef/TConstructionPodUnit.lua').TConstructionPodUnit
TEnergyCreationUnit = import('/lua/sim/units/uef/TEnergyCreationUnit.lua').TEnergyCreationUnit
TEnergyStorageUnit = import('/lua/sim/units/uef/TEnergyStorageUnit.lua').TEnergyStorageUnit
THoverLandUnit = import('/lua/sim/units/uef/THoverLandUnit.lua').THoverLandUnit
Expand Down
42 changes: 4 additions & 38 deletions units/UEA0001/UEA0001_script.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,9 @@
-- Copyright © 2005 Gas Powered Games, Inc. All rights reserved.
-----------------------------------------------------------------

local TConstructionUnit = import("/lua/terranunits.lua").TConstructionUnit
local TConstructionPodUnit = import("/lua/terranunits.lua").TConstructionPodUnit

---@class UEA0001 : TConstructionUnit
UEA0001 = ClassUnit(TConstructionUnit) {
Parent = nil,
---@class UEA0001 : TConstructionPodUnit
UEA0001 = ClassUnit(TConstructionPodUnit) {}

OnScriptBitSet = function(self, bit)
TConstructionUnit.OnScriptBitSet(self, bit)
if bit == 1 then
self.rebuildDrone = true
end
end,

OnScriptBitClear = function(self, bit)
TConstructionUnit.OnScriptBitClear(self, bit)
if bit == 1 then
self.rebuildDrone = false
end
end,

SetParent = function(self, parent, podName)
self.Parent = parent
self.Pod = podName
self:SetScriptBit('RULEUTC_WeaponToggle', true)
end,

OnKilled = function(self, instigator, type, overkillRatio)
self.Parent:NotifyOfPodDeath(self.Pod, self.rebuildDrone)
self.Parent = nil
TConstructionUnit.OnKilled(self, instigator, type, overkillRatio)
end,

-- Don't make wreckage
CreateWreckage = function (self, overkillRatio)
overkillRatio = 1.1
TConstructionUnit.CreateWreckage(self, overkillRatio)
end,
}

TypeClass = UEA0001
TypeClass = UEA0001
42 changes: 4 additions & 38 deletions units/UEA0003/UEA0003_script.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,9 @@
-- Copyright © 2005 Gas Powered Games, Inc. All rights reserved.
-----------------------------------------------------------------

local TConstructionUnit = import("/lua/terranunits.lua").TConstructionUnit
local TConstructionPodUnit = import("/lua/terranunits.lua").TConstructionPodUnit

---@class UEA0003 : TConstructionUnit
UEA0003 = ClassUnit(TConstructionUnit) {
Parent = nil,
---@class UEA0003 : TConstructionPodUnit
UEA0003 = ClassUnit(TConstructionPodUnit) {}

OnScriptBitSet = function(self, bit)
TConstructionUnit.OnScriptBitSet(self, bit)
if bit == 1 then
self.rebuildDrone = true
end
end,

OnScriptBitClear = function(self, bit)
TConstructionUnit.OnScriptBitClear(self, bit)
if bit == 1 then
self.rebuildDrone = false
end
end,

SetParent = function(self, parent, podName)
self.Parent = parent
self.Pod = podName
self:SetScriptBit('RULEUTC_WeaponToggle', true)
end,

OnKilled = function(self, instigator, type, overkillRatio)
self.Parent:NotifyOfPodDeath(self.Pod, self.rebuildDrone)
self.Parent = nil
TConstructionUnit.OnKilled(self, instigator, type, overkillRatio)
end,

-- Don't make wreckage
CreateWreckage = function (self, overkillRatio)
overkillRatio = 1.1
TConstructionUnit.CreateWreckage(self, overkillRatio)
end,
}

TypeClass = UEA0003
TypeClass = UEA0003
Loading