Index: ps/trunk/binaries/data/mods/public/gui/session/input.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/session/input.js +++ ps/trunk/binaries/data/mods/public/gui/session/input.js @@ -299,7 +299,8 @@ return false; } - var selection = g_Selection.toList(); + let selection = Engine.HotkeyIsPressed("session.orderone") && + popOneFromSelection({ "type": "construct", "target": placementSupport }) || g_Selection.toList(); Engine.PostNetworkCommand({ "type": "construct", @@ -315,7 +316,7 @@ }); Engine.GuiInterfaceCall("PlaySound", { "name": "order_build", "entity": selection[0] }); - if (!queued) + if (!queued || !g_Selection.toList().length) placementSupport.Reset(); else placementSupport.RandomizeActorSeed(); @@ -331,8 +332,8 @@ return false; } - var wallPlacementInfo = updateBuildingPlacementPreview(); // entities making up the wall (wall segments, towers, ...) - if (!(wallPlacementInfo === false || typeof(wallPlacementInfo) === "object")) + let wallPlacementInfo = updateBuildingPlacementPreview(); // entities making up the wall (wall segments, towers, ...) + if (!(wallPlacementInfo === false || typeof wallPlacementInfo === "object")) { error("Invalid updateBuildingPlacementPreview return value: " + uneval(wallPlacementInfo)); return false; @@ -341,8 +342,10 @@ if (!wallPlacementInfo) return false; - var selection = g_Selection.toList(); - var cmd = { + let selection = Engine.HotkeyIsPressed("session.orderone") && + popOneFromSelection({ "type": "construct", "target": placementSupport }) || g_Selection.toList(); + + let cmd = { "type": "construct-wall", "autorepair": true, "autocontinue": true, @@ -357,7 +360,7 @@ // make sure that there's at least one non-tower entity getting built, to prevent silly edge cases where the start and end // point are too close together for the algorithm to place a wall segment inbetween, and only the towers are being previewed // (this is somewhat non-ideal and hardcode-ish) - var hasWallSegment = false; + let hasWallSegment = false; for (let piece of cmd.pieces) { if (piece.template != cmd.wallSet.templates.tower) // TODO: hardcode-ish :( @@ -584,7 +587,7 @@ var queued = Engine.HotkeyIsPressed("session.queue"); if (tryPlaceBuilding(queued)) { - if (queued) + if (queued && g_Selection.toList().length) inputState = INPUT_BUILDING_PLACEMENT; else inputState = INPUT_NORMAL; @@ -750,7 +753,7 @@ var queued = Engine.HotkeyIsPressed("session.queue"); if (tryPlaceBuilding(queued)) { - if (queued) + if (queued && g_Selection.toList().length) inputState = INPUT_BUILDING_PLACEMENT; else inputState = INPUT_NORMAL; @@ -1144,6 +1147,21 @@ return handleUnitAction(Engine.GetTerrainAtScreenPoint(ev.x, ev.y), action); } +function popOneFromSelection(action) +{ + // Pick the first unit that can do this order. + let unit = g_Selection.find(entity => + ["preSelectedActionCheck", "hotkeyActionCheck", "actionCheck"].some(method => + g_UnitActions[action.type][method] && + g_UnitActions[action.type][method](action.target || undefined, [entity]) + )); + if (unit) + { + g_Selection.removeList([unit]); + return [unit]; + } + return null; +} function positionUnitsFreehandSelectionMouseMove(ev) { @@ -1236,22 +1254,8 @@ return false; } - let selection = g_Selection.toList(); - if (Engine.HotkeyIsPressed("session.orderone")) - { - // Pick the first unit that can do this order. - let unit = selection.find(entity => - ["preSelectedActionCheck", "hotkeyActionCheck", "actionCheck"].some(method => - g_UnitActions[action.type][method] && - g_UnitActions[action.type][method](action.target || undefined, [entity]) - )); - if (unit) - { - selection = [unit]; - g_Selection.removeList(selection); - } - } - + let selection = Engine.HotkeyIsPressed("session.orderone") && + popOneFromSelection(action) || g_Selection.toList(); // If the session.queue hotkey is down, add the order to the unit's order queue instead // of running it immediately return g_UnitActions[action.type].execute(target, action, selection, Engine.HotkeyIsPressed("session.queue")); Index: ps/trunk/binaries/data/mods/public/gui/session/selection.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/session/selection.js +++ ps/trunk/binaries/data/mods/public/gui/session/selection.js @@ -390,6 +390,14 @@ return ents; }; +EntitySelection.prototype.find = function(condition) +{ + for (let ent in this.selected) + if (condition(ent)) + return +ent; + return null; +}; + EntitySelection.prototype.setHighlightList = function(ents) { var highlighted = {}; Index: ps/trunk/binaries/data/mods/public/gui/session/unit_actions.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/session/unit_actions.js +++ ps/trunk/binaries/data/mods/public/gui/session/unit_actions.js @@ -340,6 +340,20 @@ "specificness": 7, }, + // "Fake" action to check if an entity can be ordered to "construct" + // which is handled differently from repair as the target does not exist. + "construct": + { + "preSelectedActionCheck": function(target, selection) + { + let state = GetEntityState(selection[0]); + if (state && state.builder && target.constructor.name == "PlacementSupport") + return { "type": "construct" }; + return false; + }, + "specificness": 0, + }, + "repair": { "execute": function(target, action, selection, queued)