Skip to content

Commit

Permalink
Feature: Stateful factory guard (#2665)
Browse files Browse the repository at this point in the history
* mex deselection

* basic working version of factory guard gadget+widget

* Clean up custom commands

* working updates from EditUnitCmdDesc

* Everything in gadget, remove factory guard option

* add grid hotkey, ctrl+g
  • Loading branch information
thehobojoe authored Mar 2, 2024
1 parent dc85e74 commit 55effc8
Show file tree
Hide file tree
Showing 13 changed files with 198 additions and 251 deletions.
2 changes: 2 additions & 0 deletions language/en/interface.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@
"resurrect_tooltip": "Revive wrecks to become units again (click-drag for area)",
"guard": "Guard",
"guard_tooltip": "Guard another unit against enemy units attacking it",
"factoryguard": "Factory Guard",
"factoryguard_tooltip": "Builders produced by this factory will automatically guard it",
"wait": "Wait",
"wait_tooltip": "Pause a unit/factory on processing command/build queues",
"repair": "Repair",
Expand Down
68 changes: 0 additions & 68 deletions luarules/configs/customcmds.h.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,86 +12,18 @@

-- if you add a command, please order it by ID!

CMD_RETREAT = 10000
CMD_RETREAT_ZONE = 10001
CMD_SETHAVEN = CMD_RETREAT_ZONE
CMD_RESETFIRE = 10003
CMD_RESETMOVE = 10004
CMD_BUILDPREV = 10005
CMD_RADIALBUILDMENU = 10006

CMD_FACTORY_GUARD = 13921
CMD_AREA_GUARD = 13922
CMD_STOP_PRODUCTION = 13923

CMD_SHOOTNOW = 18000

CMD_BUILD = 10010

CMD_AREA_MEX = 30100
CMD_MORPH = 31210
CMD_EMBARK = 31200
CMD_DISEMBARK = 31201
CMD_TRANSPORTTO = 31202
CMD_STEALTH = 32100
CMD_CLOAK_SHIELD = 32101
CMD_MANUAL_LAUNCH = 32102
CMD_MINE = 32105 -- easymetal2
CMD_REARM = 32768 -- bomber control
CMD_FIND_PAD = 32769 -- bomber control
CMD_UNIT_FLOAT_STATE = 33412
CMD_PRIORITY = 34220
CMD_MISC_PRIORITY = 34221
CMD_UNIT_BOMBER_DIVE_STATE = 34281 -- bomber dive
CMD_AP_FLY_STATE = 34569 -- unit_air_plants
CMD_AP_AUTOREPAIRLEVEL = 34570 -- unit_air_plants
CMD_UNIT_SET_TARGET = 34923 -- unit_target_on_the_move
CMD_UNIT_CANCEL_TARGET = 34924
CMD_UNIT_SET_TARGET_CIRCLE = 34925
CMD_ONECLICK_WEAPON = 35000
CMD_PLACE_BEACON = 35170
CMD_WAIT_AT_BEACON = 35171
CMD_ABANDON_PW = 35200
CMD_ANTINUKEZONE = 35130 -- ceasefire
CMD_UNIT_KILL_SUBORDINATES = 35821 -- unit_capture
CMD_UNIT_AI = 36214
CMD_WANT_CLOAK = 37382
CMD_DONT_FIRE_AT_RADAR = 38372 -- fire at radar toggle gadget
CMD_JUMP = 38521
CMD_TURN = 38530
CMD_TIMEWARP = 38522
CMD_AIR_STRAFE = 39381

-- terraform
CMD_RAMP = 39734
CMD_LEVEL = 39736
CMD_RAISE = 39737
CMD_SMOOTH = 39738
CMD_RESTORE = 39739
CMD_BUMPY = 39740
CMD_TERRAFORM_INTERNAL = 39801

CMD_RAW_MOVE = 39812

CMD_ALTITUDE = 39999

-- not included here, just listed
--[[
CMD_PURCHASE = 32601 -- planetwars, range up to 32601 + #purchases
CMD_MORPH_STOP = 32210 -- range up to 32210 + #morphs
CMD_MORPH = 31210 -- ditto
]]--

-- deprecated
--[[
CMD_PLANTBOMB = 32523
CMD_AUTOREPAIR = 33250 -- up to 33250 + 3
CMD_AUTORECLAIM = 33251
CMD_AUTOASSIST = 33252
CMD_AUTOATTACK = 33253
CMD_PRIORITY= 34220
CobButton = 34520 -- up to 32520 + different cob buttons
CMD_SCRAMBLE = 35128
CMD_WRECK = 36734
CMD_RESTOREBOMB = 39735
]]--
181 changes: 181 additions & 0 deletions luarules/gadgets/unit_factory_guard.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@

if not gadgetHandler:IsSyncedCode() then
return
end


function gadget:GetInfo()
return {
name = "Factory Guard",
desc = "Adds a factory guard state command to factories",
author = "Hobo Joe",
date = "Feb 2024",
license = "GNU GPL, v2 or later",
layer = 0,
enabled = true
}
end


local spGetUnitBuildFacing = Spring.GetUnitBuildFacing
local spGetUnitPosition = Spring.GetUnitPosition
local spGetUnitRadius = Spring.GetUnitRadius
local spGiveOrderToUnit = Spring.GiveOrderToUnit
local spInsertUnitCmdDesc = Spring.InsertUnitCmdDesc
local spEditUnitCmdDesc = Spring.EditUnitCmdDesc
local spFindUnitCmdDesc = Spring.FindUnitCmdDesc

local CMD_GUARD = CMD.GUARD
local CMD_MOVE = CMD.MOVE

include("luarules/configs/customcmds.h.lua")

local factoryGuardCmdDesc = {
id = CMD_FACTORY_GUARD,
type = CMDTYPE.ICON_MODE,
tooltip = 'factoryguard_tooltip',
name = 'factoryguard',
cursor = 'cursornormal',
action = 'factoryguard',
params = { 0, "factoryguard", "factoryguard" }, -- named like this for translation - 0 is off, 1 is on
}


local isFactory = {}
local isAssistBuilder = {}
for unitDefID, unitDef in pairs(UnitDefs) do
if unitDef.isFactory then
local buildOptions = unitDef.buildOptions

for i = 1, #buildOptions do
local buildOptDefID = buildOptions[i]
local buildOpt = UnitDefs[buildOptDefID]

if (buildOpt and buildOpt.isBuilder and buildOpt.canAssist) then
isFactory[unitDefID] = true -- only factories that can build builders are included
break
end
end
end
if unitDef.isBuilder and unitDef.canAssist then
isAssistBuilder[unitDefID] = true
end
end


local function setFactoryGuardState(unitID, state)
local cmdDescID = spFindUnitCmdDesc(unitID, CMD_FACTORY_GUARD)
if cmdDescID then
factoryGuardCmdDesc.params[1] = state
spEditUnitCmdDesc(unitID, cmdDescID, {params = factoryGuardCmdDesc.params})
end
end


function gadget:AllowCommand(unitID, unitDefID, teamID, cmdID, cmdParams, cmdOptions)
if cmdID == CMD_FACTORY_GUARD and isFactory[unitDefID] then
setFactoryGuardState(unitID, cmdParams[1])
return false -- command was used
end
return true -- command was not used
end


--------------------------------------------------------------------------------
-- Guard Command Handling

local function GuardFactory(unitID, unitDefID, factID, factDefID)

if not isFactory[factDefID] then
-- is this a factory?
return
end
if not isAssistBuilder[unitDefID] then
-- can this unit assist?
return
end

local x, y, z = spGetUnitPosition(factID)
if (not x) then
return
end

local radius = spGetUnitRadius(factID)
if (not radius) then
return
end
local dist = radius * 2

local facing = spGetUnitBuildFacing(factID)
if (not facing) then
return
end

-- facing values { S = 0, E = 1, N = 2, W = 3 }
local dx, dz -- down vector
local rx, rz -- right vector
if (facing == 0) then
dx, dz = 0, dist
rx, rz = dist, 0
elseif (facing == 1) then
dx, dz = dist, 0
rx, rz = 0, -dist
elseif (facing == 2) then
dx, dz = 0, -dist
rx, rz = -dist, 0
else
dx, dz = -dist, 0
rx, rz = 0, dist
end

local OrderUnit = spGiveOrderToUnit

OrderUnit(unitID, CMD_MOVE, { x + dx, y, z + dz }, { "" })
if Spring.TestMoveOrder(unitDefID, x + dx + rx, y, z + dz + rz) then
OrderUnit(unitID, CMD_MOVE, { x + dx + rx, y, z + dz + rz }, { "shift" })
if Spring.TestMoveOrder(unitDefID, x + rx, y, z + rz) then
OrderUnit(unitID, CMD_MOVE, { x + rx, y, z + rz }, { "shift" })
end
elseif Spring.TestMoveOrder(unitDefID, x + dx - rx, y, z + dz - rz) then
OrderUnit(unitID, CMD_MOVE, { x + dx - rx, y, z + dz - rz }, { "shift" })
if Spring.TestMoveOrder(unitDefID, x - rx, y, z - rz) then
OrderUnit(unitID, CMD_MOVE, { x - rx, y, z - rz }, { "shift" })
end
end
OrderUnit(unitID, CMD_GUARD, { factID }, { "shift" })
end


function gadget:UnitFromFactory(unitID, unitDefID, unitTeam,
factID, factDefID, userOrders)
if (userOrders) then
return -- already has user assigned orders
end

local factoryGuardCmdDescID = Spring.FindUnitCmdDesc(factID, CMD_FACTORY_GUARD) -- get CmdDescID
local cmdDesc = Spring.GetUnitCmdDescs(factID, factoryGuardCmdDescID)[1] -- use CmdDescID to get state of that cmd (comes back as a table, we get the first element)
local factoryGuardEnabled = cmdDesc.params[1] == "1"
if not cmdDesc or not factoryGuardEnabled then -- if state is missing or false, do nothing
return
end

GuardFactory(unitID, unitDefID, factID, factDefID)
end


--------------------------------------------------------------------------------
-- Unit Handling

function gadget:UnitCreated(unitID, unitDefID, _)
if isFactory[unitDefID] then
factoryGuardCmdDesc.params[1] = 0
spInsertUnitCmdDesc(unitID, factoryGuardCmdDesc)
end
end

function gadget:Initialize()
for _, unitID in ipairs(Spring.GetAllUnits()) do
gadget:UnitCreated(unitID, Spring.GetUnitDefID(unitID))
end
end
--------------------------------------------------------------------------------
1 change: 0 additions & 1 deletion luarules/gadgets/unit_target_on_the_move.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ function gadget:GetInfo()
}
end

--include("LuaRules/Configs/customcmds.h.lua")

local CMD_UNIT_SET_TARGET_NO_GROUND = 34922
local CMD_UNIT_SET_TARGET = 34923
Expand Down
2 changes: 1 addition & 1 deletion luaui/Widgets/cmd_area_mex.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function widget:GetInfo()
}
end

local CMD_AREA_MEX = 10100
VFS.Include("luarules/configs/customcmds.h.lua")

local spGetActiveCommand = Spring.GetActiveCommand
local spGetMapDrawMode = Spring.GetMapDrawMode
Expand Down
1 change: 0 additions & 1 deletion luaui/Widgets/cmd_guard_remove.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ function widget:GetInfo()
end

include("keysym.h.lua")
VFS.Include("LuaRules/Configs/customcmds.h.lua")

local spGetGameFrame = Spring.GetGameFrame
local spGetCommandQueue = Spring.GetCommandQueue
Expand Down
1 change: 0 additions & 1 deletion luaui/Widgets/gui_gridmenu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ startUnits = nil


include("keysym.h.lua")
VFS.Include("luarules/configs/customcmds.h.lua")


SYMKEYS = table.invert(KEYSYMS)
Expand Down
2 changes: 0 additions & 2 deletions luaui/Widgets/gui_options.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4275,11 +4275,9 @@ function init()
end,
},

{ id = "factoryguard", group = "game", category = types.basic, widget = "FactoryGuard", name = Spring.I18N('ui.settings.option.factory') .. widgetOptionColor .. " " .. Spring.I18N('ui.settings.option.factoryguard'), type = "bool", value = GetWidgetToggleValue("FactoryGuard"), description = Spring.I18N('ui.settings.option.factoryguard_descr') },
{ id = "factoryholdpos", group = "game", category = types.basic, widget = "Factory hold position", name = widgetOptionColor .. " " .. Spring.I18N('ui.settings.option.factoryholdpos'), type = "bool", value = GetWidgetToggleValue("Factory hold position"), description = Spring.I18N('ui.settings.option.factoryholdpos_descr') },
{ id = "factoryrepeat", group = "game", category = types.basic, widget = "Factory Auto-Repeat", name = widgetOptionColor .. " " .. Spring.I18N('ui.settings.option.factoryrepeat'), type = "bool", value = GetWidgetToggleValue("Factory Auto-Repeat"), description = Spring.I18N('ui.settings.option.factoryrepeat_descr') },


{ id = "transportai", group = "game", category = types.basic, widget = "Transport AI", name = Spring.I18N('ui.settings.option.transportai'), type = "bool", value = GetWidgetToggleValue("Transport AI"), description = Spring.I18N('ui.settings.option.transportai_descr') },

{ id = "onlyfighterspatrol", group = "game", category = types.basic, widget = "OnlyFightersPatrol", name = Spring.I18N('ui.settings.option.onlyfighterspatrol'), type = "bool", value = GetWidgetToggleValue("Autoquit"), description = Spring.I18N('ui.settings.option.onlyfighterspatrol_descr') },
Expand Down
4 changes: 4 additions & 0 deletions luaui/Widgets/gui_ordermenu.lua
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,10 @@ function widget:UnitCommand(unitID, unitDefID, unitTeam, cmdID, cmdOpts, cmdPara
end
end

function widget:CommandsChanged() -- required to read changes from EditUnitCmdDesc
doUpdateClock = os_clock() + 0.01
end

function widget:SelectionChanged(sel)
clickCountDown = 2
clickedCellDesiredState = nil
Expand Down
11 changes: 4 additions & 7 deletions luaui/Widgets/gui_reclaim_field_highlight.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ function widget:GetInfo()
}
end

VFS.Include("LuaRules/Configs/customcmds.h.lua")


--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Options
Expand Down Expand Up @@ -417,7 +414,7 @@ local spGetCameraVectors = Spring.GetCameraVectors

local screenx, screeny
local gaiaTeamId = spGetGaiaTeamID()
local clusterizingNeeded = false -- Used to check if clusterizing neds to be run, set by FeatureCreated/Removed
local clusterizingNeeded = false -- Used to check if clusterizing neds to be run, set by FeatureCreated/Removed

local minDistance = 300
local minSqDistance = minDistance^2
Expand All @@ -426,7 +423,7 @@ local minFeatureMetal = 9 -- Tick
local E2M = 1 / 70 -- Converter ratio
local minDim = 100

local checkFrequency = 30
local checkFrequency = 30

local drawEnabled = true
local actionActive = false
Expand Down Expand Up @@ -908,7 +905,7 @@ function widget:Update(dt)
cameraScale = sqrt((cameraDist / 600)) --number is an "optimal" view distance
else
cameraScale = 1.0
end
end
end

function widget:GameFrame(frame)
Expand Down Expand Up @@ -1005,4 +1002,4 @@ function widget:Shutdown()
if drawFeatureClusterTextList then
glDeleteList(drawFeatureClusterTextList)
end
end
end
Loading

0 comments on commit 55effc8

Please sign in to comment.