Index: binaries/data/config/default.cfg =================================================================== --- binaries/data/config/default.cfg +++ binaries/data/config/default.cfg @@ -310,6 +310,7 @@ backtowork = "Y" ; The unit will go back to work unload = "U" ; Unload garrisoned units when a building/mechanical unit is selected unloadturrets = "U" ; Unload turreted units. +leaveturret = "U" ; Leave turret point. move = "" ; Modifier to move to a point instead of another action (e.g. gather) attack = Ctrl ; Modifier to attack instead of another action (e.g. capture) attackmove = Ctrl ; Modifier to attackmove when clicking on a point Index: binaries/data/mods/public/gui/hotkeys/spec/ingame.json =================================================================== --- binaries/data/mods/public/gui/hotkeys/spec/ingame.json +++ binaries/data/mods/public/gui/hotkeys/spec/ingame.json @@ -31,6 +31,10 @@ "name": "Unload Turrets", "desc": "Unload turreted units." }, + "session.leaveturret": { + "name": "Leave Turret Point", + "desc": "Order an entity to leave a turret point." + }, "session.unloadtype": { "name": "Unload unit type", "desc": "Modifier to unload all units of type." Index: binaries/data/mods/public/gui/session/hotkeys/misc.xml =================================================================== --- binaries/data/mods/public/gui/session/hotkeys/misc.xml +++ binaries/data/mods/public/gui/session/hotkeys/misc.xml @@ -36,6 +36,10 @@ unloadAllTurrets(); + + leaveTurretPoints(); + + stopUnits(g_Selection.toList()); Index: binaries/data/mods/public/gui/session/input.js =================================================================== --- binaries/data/mods/public/gui/session/input.js +++ binaries/data/mods/public/gui/session/input.js @@ -17,6 +17,7 @@ const ACTION_REPAIR = 2; const ACTION_GUARD = 3; const ACTION_PATROL = 4; +const ACTION_OCCUPY_TURRET = 5; var preSelectedAction = ACTION_NONE; const INPUT_NORMAL = 0; Index: binaries/data/mods/public/gui/session/selection_panels_helpers.js =================================================================== --- binaries/data/mods/public/gui/session/selection_panels_helpers.js +++ binaries/data/mods/public/gui/session/selection_panels_helpers.js @@ -487,6 +487,20 @@ }); } +function leaveTurretPoints() +{ + let entities = g_Selection.toList().filter(entity => { + let entState = GetEntityState(entity); + return entState && entState.turretable && + entState.turretable.holder != INVALID_ENTITY; + }); + + Engine.PostNetworkCommand({ + "type": "leave-turret", + "entities": entities + }); +} + function backToWork() { Engine.PostNetworkCommand({ Index: binaries/data/mods/public/gui/session/unit_actions.js =================================================================== --- binaries/data/mods/public/gui/session/unit_actions.js +++ binaries/data/mods/public/gui/session/unit_actions.js @@ -730,10 +730,10 @@ }, "preSelectedActionCheck": function(target, selection) { - return preSelectedAction == ACTION_GARRISON && + return preSelectedAction == ACTION_OCCUPY_TURRET && (this.actionCheck(target, selection) || { "type": "none", - "cursor": "action-garrison-disabled", + "cursor": "action-occupy-turret-disabled", "target": null }); }, @@ -747,7 +747,7 @@ let actionInfo = getActionInfo("occupy-turret", target, selection); return actionInfo.possible && { "type": "occupy-turret", - "cursor": "action-garrison", + "cursor": "action-occupy-turret", "tooltip": actionInfo.tooltip, "target": target }; @@ -1421,7 +1421,8 @@ "garrison": { "getInfo": function(entStates) { - if (entStates.every(entState => !entState.unitAI || entState.turretParent || false)) + if (entStates.every(entState => !entState.garrisonable || + entState.garrisonable.holder != INVALID_ENTITY)) return false; return { @@ -1439,6 +1440,28 @@ "allowedPlayers": ["Player"] }, + "occupy-turret": { + "getInfo": function(entStates) + { + if (entStates.every(entState => !entState.turretable || + entState.turretable.holder != INVALID_ENTITY)) + return false; + + return { + "tooltip": colorizeHotkey("%(hotkey)s" + " ", "session.occupyturret") + + translate("Order the selected units to occupy a turret point."), + "icon": "occupy-turret.png", + "enabled": true + }; + }, + "execute": function() + { + inputState = INPUT_PRESELECTEDACTION; + preSelectedAction = ACTION_OCCUPY_TURRET; + }, + "allowedPlayers": ["Player"] + }, + "leave-turret": { "getInfo": function(entStates) { @@ -1447,21 +1470,15 @@ return false; return { - "tooltip": translate("Unload"), - "icon": "garrison-out.png", + "tooltip": colorizeHotkey("%(hotkey)s" + " ", "session.leaveturret") + + translate("Unload"), + "icon": "leave-turret.png", "enabled": true }; }, "execute": function(entStates) { - if (!entStates.length) - return; - - Engine.PostNetworkCommand({ - "type": "leave-turret", - "entities": entStates.filter(entState => entState.turretable && - entState.turretable.holder != INVALID_ENTITY).map(entState => entState.id) - }); + leaveTurretPoints(); }, "allowedPlayers": ["Player"] }, Index: binaries/data/mods/public/simulation/components/UnitAI.js =================================================================== --- binaries/data/mods/public/simulation/components/UnitAI.js +++ binaries/data/mods/public/simulation/components/UnitAI.js @@ -5607,6 +5607,9 @@ */ UnitAI.prototype.Garrison = function(target, queued, pushFront) { + // Not allowed to garrison when occupying a turret, at the moment. + if (this.isGarrisoned) + return; if (target == this.entity) return; if (!this.CanGarrison(target))