Select formations as a whole by default.
One can override this behaviour by using a hotkey when (de)selecting entities. The aim of this system is to reduce micromanagement a bit. Differential revision: https://code.wildfiregames.com/D2175 Comments by: @Angen, @azayrahmad, @Langbart, @marder, @Stan, @submariner, @wowgetoffyourcellphone, @wraitii Refs. #4545 This was SVN commit r25939.
This commit is contained in:
parent
7382a4885b
commit
a70a20fd42
@ -284,6 +284,7 @@ idleworker = Period, NumDecimal ; Select next idle worker
|
|||||||
idlewarrior = Slash, NumDivide ; Select next idle warrior
|
idlewarrior = Slash, NumDivide ; Select next idle warrior
|
||||||
idleunit = BackSlash ; Select next idle unit
|
idleunit = BackSlash ; Select next idle unit
|
||||||
offscreen = Alt ; Include offscreen units in selection
|
offscreen = Alt ; Include offscreen units in selection
|
||||||
|
singleselection = "" ; Select only one entity of a formation.
|
||||||
[hotkey.selection.group.add]
|
[hotkey.selection.group.add]
|
||||||
0 = "Shift+0", "Shift+Num0"
|
0 = "Shift+0", "Shift+Num0"
|
||||||
1 = "Shift+1", "Shift+Num1"
|
1 = "Shift+1", "Shift+Num1"
|
||||||
|
@ -55,6 +55,10 @@
|
|||||||
"name": "Include offscreen",
|
"name": "Include offscreen",
|
||||||
"desc": "Include offscreen units in selection."
|
"desc": "Include offscreen units in selection."
|
||||||
},
|
},
|
||||||
|
"selection.singleselection": {
|
||||||
|
"name": "Single selection",
|
||||||
|
"desc": "Select only one entity of a formation."
|
||||||
|
},
|
||||||
"selection.group.save.0": {
|
"selection.group.save.0": {
|
||||||
"name": "Set Control Group 0",
|
"name": "Set Control Group 0",
|
||||||
"desc": "Save current selection as Control Group 0."
|
"desc": "Save current selection as Control Group 0."
|
||||||
|
@ -1170,7 +1170,7 @@ function popOneFromSelection(action)
|
|||||||
));
|
));
|
||||||
if (unit)
|
if (unit)
|
||||||
{
|
{
|
||||||
g_Selection.removeList([unit]);
|
g_Selection.removeList([unit], true);
|
||||||
return [unit];
|
return [unit];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -284,9 +284,9 @@ EntitySelection.prototype.addList = function(ents, quiet, force = false)
|
|||||||
if (firstEntState && firstEntState.player != g_ViewedPlayer && !force)
|
if (firstEntState && firstEntState.player != g_ViewedPlayer && !force)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let added = [];
|
const added = [];
|
||||||
|
|
||||||
for (const ent of ents)
|
for (const ent of this.addFormationMembers(ents))
|
||||||
{
|
{
|
||||||
if (this.selected.size >= g_MaxSelectionSize)
|
if (this.selected.size >= g_MaxSelectionSize)
|
||||||
break;
|
break;
|
||||||
@ -324,11 +324,15 @@ EntitySelection.prototype.addList = function(ents, quiet, force = false)
|
|||||||
this.onChange();
|
this.onChange();
|
||||||
};
|
};
|
||||||
|
|
||||||
EntitySelection.prototype.removeList = function(ents)
|
/**
|
||||||
|
* @param {number[]} ents - The entities to remove.
|
||||||
|
* @param {boolean} dontAddFormationMembers - If true we need to exclude adding formation members.
|
||||||
|
*/
|
||||||
|
EntitySelection.prototype.removeList = function(ents, dontAddFormationMembers = false)
|
||||||
{
|
{
|
||||||
var removed = [];
|
const removed = [];
|
||||||
|
|
||||||
for (let ent of ents)
|
for (const ent of dontAddFormationMembers ? ents : this.addFormationMembers(ents))
|
||||||
if (this.selected.has(ent))
|
if (this.selected.has(ent))
|
||||||
{
|
{
|
||||||
this.groups.removeEnt(ent);
|
this.groups.removeEnt(ent);
|
||||||
@ -407,9 +411,10 @@ EntitySelection.prototype.filter = function(condition)
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
EntitySelection.prototype.setHighlightList = function(ents)
|
EntitySelection.prototype.setHighlightList = function(entities)
|
||||||
{
|
{
|
||||||
const highlighted = new Set();
|
const highlighted = new Set();
|
||||||
|
const ents = this.addFormationMembers(entities);
|
||||||
for (const ent of ents)
|
for (const ent of ents)
|
||||||
highlighted.add(ent);
|
highlighted.add(ent);
|
||||||
|
|
||||||
@ -461,6 +466,28 @@ EntitySelection.prototype.selectAndMoveTo = function(entityID)
|
|||||||
Engine.CameraMoveTo(entState.position.x, entState.position.z);
|
Engine.CameraMoveTo(entState.position.x, entState.position.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the formation members of a selected entities to the selection.
|
||||||
|
* @param {number[]} entities - The entity IDs of selected entities.
|
||||||
|
* @return {number[]} - Some more entity IDs if part of a formation was selected.
|
||||||
|
*/
|
||||||
|
EntitySelection.prototype.addFormationMembers = function(entities)
|
||||||
|
{
|
||||||
|
if (!entities.length || Engine.HotkeyIsPressed("selection.singleselection"))
|
||||||
|
return entities;
|
||||||
|
|
||||||
|
const result = new Set(entities);
|
||||||
|
for (const entity of entities)
|
||||||
|
{
|
||||||
|
const entState = GetEntityState(+entity);
|
||||||
|
if (entState?.unitAI?.formation)
|
||||||
|
for (const member of GetEntityState(+entState.unitAI.formation).formation.members)
|
||||||
|
result.add(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache some quantities which depends only on selection
|
* Cache some quantities which depends only on selection
|
||||||
*/
|
*/
|
||||||
|
@ -281,6 +281,12 @@ GuiInterface.prototype.GetEntityState = function(player, ent)
|
|||||||
"controllable": cmpIdentity.IsControllable()
|
"controllable": cmpIdentity.IsControllable()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cmpFormation = Engine.QueryInterface(ent, IID_Formation);
|
||||||
|
if (cmpFormation)
|
||||||
|
ret.formation = {
|
||||||
|
"members": cmpFormation.GetMembers()
|
||||||
|
};
|
||||||
|
|
||||||
let cmpPosition = Engine.QueryInterface(ent, IID_Position);
|
let cmpPosition = Engine.QueryInterface(ent, IID_Position);
|
||||||
if (cmpPosition && cmpPosition.IsInWorld())
|
if (cmpPosition && cmpPosition.IsInWorld())
|
||||||
ret.position = cmpPosition.GetPosition();
|
ret.position = cmpPosition.GetPosition();
|
||||||
@ -416,7 +422,8 @@ GuiInterface.prototype.GetEntityState = function(player, ent)
|
|||||||
"isGuarding": cmpUnitAI.IsGuardOf(),
|
"isGuarding": cmpUnitAI.IsGuardOf(),
|
||||||
"canPatrol": cmpUnitAI.CanPatrol(),
|
"canPatrol": cmpUnitAI.CanPatrol(),
|
||||||
"selectableStances": cmpUnitAI.GetSelectableStances(),
|
"selectableStances": cmpUnitAI.GetSelectableStances(),
|
||||||
"isIdle": cmpUnitAI.IsIdle()
|
"isIdle": cmpUnitAI.IsIdle(),
|
||||||
|
"formation": cmpUnitAI.GetFormationController()
|
||||||
};
|
};
|
||||||
|
|
||||||
let cmpGuard = Engine.QueryInterface(ent, IID_Guard);
|
let cmpGuard = Engine.QueryInterface(ent, IID_Guard);
|
||||||
|
@ -10,6 +10,7 @@ Engine.LoadComponentScript("interfaces/Resistance.js");
|
|||||||
Engine.LoadComponentScript("interfaces/DeathDamage.js");
|
Engine.LoadComponentScript("interfaces/DeathDamage.js");
|
||||||
Engine.LoadComponentScript("interfaces/EndGameManager.js");
|
Engine.LoadComponentScript("interfaces/EndGameManager.js");
|
||||||
Engine.LoadComponentScript("interfaces/EntityLimits.js");
|
Engine.LoadComponentScript("interfaces/EntityLimits.js");
|
||||||
|
Engine.LoadComponentScript("interfaces/Formation.js");
|
||||||
Engine.LoadComponentScript("interfaces/Foundation.js");
|
Engine.LoadComponentScript("interfaces/Foundation.js");
|
||||||
Engine.LoadComponentScript("interfaces/Garrisonable.js");
|
Engine.LoadComponentScript("interfaces/Garrisonable.js");
|
||||||
Engine.LoadComponentScript("interfaces/GarrisonHolder.js");
|
Engine.LoadComponentScript("interfaces/GarrisonHolder.js");
|
||||||
|
Loading…
Reference in New Issue
Block a user