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_CALLTOARMS = 5; var preSelectedAction = ACTION_NONE; const INPUT_NORMAL = 0; 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 @@ -236,6 +236,41 @@ "specificness": 10, }, + "call-to-arms": { + "execute": function(target, action, selection, queued) + { + let targetClasses; + if (Engine.HotkeyIsPressed("session.attackmoveUnit")) + targetClasses = { "attack": ["Unit"] }; + else + targetClasses = { "attack": ["Unit", "Structure"] }; + + Engine.PostNetworkCommand({ + "type": "call-to-arms", + "entities": selection, + "target": target, + "targetClasses": targetClasses, + "queued": false, + "allowCapture": false + }); + }, + "getActionInfo": function(entState, targetState) + { + return { "possible": true }; + }, + "preSelectedActionCheck": function(target, selection) + { + if (preSelectedAction != ACTION_CALLTOARMS || !getActionInfo("attack-move", target, selection).possible) + return false; + return { + "type": "call-to-arms", + "cursor": "action-attack", + "target": target + }; + }, + "specificness": 50, + }, + "patrol": { "execute": function(target, action, selection, queued) @@ -1095,6 +1130,22 @@ }, }, + "call-to-arms": { + "getInfo": function(entStates) + { + return { + "tooltip": colorizeHotkey("%(hotkey)s" + " ", "session.returnresources") + + translate("Send the selected units on attack move to the specified location after dropping resources."), + "icon": "attack-request.png" + }; + }, + "execute": function(entStates) + { + inputState = INPUT_PRESELECTEDACTION; + preSelectedAction = ACTION_CALLTOARMS; + }, + }, + "garrison": { "getInfo": function(entStates) { 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 @@ -4935,6 +4935,30 @@ }; /** + * Adds CallToArms order to queue, forced by the player, + * targeting the nearest dropsite. + * + * @param {float[]} target.x, target.y, target.z - the x,y,z-values to where the units need to walk (after dropping resources) + * @param {string[]} targetClasses + * @param {boolean} allowCapture + * @param {boolean} queued - Whether the order is queued or not + */ +UnitAI.prototype.CallToArms = function(target, targetClasses, allowCapture, queued) +{ + let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); + let resourceType; + if (cmpResourceGatherer) + resourceType = cmpResourceGatherer.GetMainCarryingType(); + let nearby = this.FindNearestDropsite(resourceType); + if (nearby) + this.AddOrder("ReturnResource", { "target": nearby, "force": true }, queued); + else + this.AddOrder("Stop", { "force": true }, queued); + + this.AddOrder("WalkAndFight", { "x": target.x, "z": target.z, "targetClasses": targetClasses, "allowCapture": allowCapture, "force": true }, true); +}; + +/** * Adds walk-to-target order to queue, this only occurs in response * to a player order, and so is forced. */ Index: binaries/data/mods/public/simulation/helpers/Commands.js =================================================================== --- binaries/data/mods/public/simulation/helpers/Commands.js +++ binaries/data/mods/public/simulation/helpers/Commands.js @@ -269,6 +269,13 @@ } }, + "call-to-arms": function(player, cmd, data) + { + GetFormationUnitAIs(data.entities, player).forEach(cmpUnitAI => { + cmpUnitAI.CallToArms(cmd.target, cmd.targetClasses, cmd.allowCapture, cmd.queued); + }); + }, + "remove-guard": function(player, cmd, data) { for (let ent of data.entities)