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
@@ -1041,8 +1041,10 @@
"entities": selection,
"x": position.x,
"z": position.z,
+ "target": action.target,
"data": action.data,
- "queued": queued
+ "queued": queued,
+ "pushFront": pushFront
});
// Display rally point at the new coordinates, to avoid display lag
@@ -1246,11 +1248,13 @@
"target": null,
"tooltip": actionInfo.tooltip
};
-
+ if (Engine.HotkeyIsPressed("session.autorallypoint"))
+ target = null;
return actionInfo.possible && {
"type": "set-rallypoint",
"cursor": actionInfo.cursor,
"data": actionInfo.data,
+ "target": target,
"tooltip": actionInfo.tooltip,
"position": actionInfo.position,
"firstAbleEntity": actionInfo.entity
Index: binaries/data/mods/public/simulation/components/BuildingAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/BuildingAI.js
+++ binaries/data/mods/public/simulation/components/BuildingAI.js
@@ -28,6 +28,7 @@
this.archersGarrisoned = 0;
this.arrowsLeft = 0;
this.targetUnits = [];
+ this.focusTargets = [];
};
BuildingAI.prototype.OnGarrisonedUnitsChanged = function(msg)
@@ -50,6 +51,7 @@
BuildingAI.prototype.OnOwnershipChanged = function(msg)
{
this.targetUnits = [];
+ this.focusTargets = [];
this.SetupRangeQuery();
this.SetupGaiaRangeQuery();
};
@@ -267,6 +269,22 @@
};
/**
+ * Adds index to keep track of the user-targeted units supporting a queue
+ * @param {ent} - Target of rallypoint selection when selection is an enemy unit from unit_actions.js
+ */
+BuildingAI.prototype.AddFocusTarget = function(ent, queued, push)
+{
+ if (!ent || this.targetUnits.indexOf(ent) === -1)
+ return;
+ if (queued)
+ this.focusTargets.push({"entityId": ent});
+ else if (push)
+ this.focusTargets.unshift({"entityId": ent});
+ else
+ this.focusTargets = [{"entityId": ent}];
+};
+
+/**
* Fire arrows with random temporal distribution on prefered targets.
* Called 'roundCount' times every 'RepeatTime' seconds when there are units in the range.
*/
@@ -298,7 +316,7 @@
arrowsToFire = this.arrowsLeft;
else
arrowsToFire = Math.min(
- randIntInclusive(0, 2 * this.GetArrowCount() / roundCount),
+ randIntInclusive(1, 3 * this.GetArrowCount() / roundCount),
this.arrowsLeft
);
@@ -308,25 +326,32 @@
return;
}
- // Add targets to a weighted list, to allow preferences.
- let targets = new WeightedList();
- let maxPreference = this.MAX_PREFERENCE_BONUS;
- let addTarget = function(target)
+ // Add targets to a list.
+ let targets = [];
+ let addTarget = function(target)
{
- let preference = cmpAttack.GetPreference(target);
- let weight = 1;
-
- if (preference !== null && preference !== undefined)
- weight += maxPreference / (1 + preference);
-
- targets.push(target, weight);
+ const pref = (cmpAttack.GetPreference(target) ?? 49);
+ targets.push({"entityId": target, "preference": pref});
};
-
// Add the UnitAI target separately, as the UnitMotion and RangeManager implementations differ.
if (this.unitAITarget && this.targetUnits.indexOf(this.unitAITarget) == -1)
- addTarget(this.unitAITarget);
- for (let target of this.targetUnits)
- addTarget(target);
+ addTarget(this.unitAITarget);
+ else if (this.unitAITarget && this.targetUnits.indexOf(this.unitAITarget) != -1)
+ this.focusTargets = [{"entityId": this.unitAITarget}];
+ if (!this.focusTargets.length)
+ {
+ for (let target of this.targetUnits)
+ addTarget(target);
+ // Sort targets by preference and then by proximity.
+ targets.sort( (a,b) => {
+ if (a.preference > b.preference) return 1;
+ else if (a.preference < b.preference) return -1;
+ else if (PositionHelper.DistanceBetweenEntities(this.entity,a.entityId) > PositionHelper.DistanceBetweenEntities(this.entity,b.entityId)) return 1;
+ return -1;
+ });
+ }
+ else
+ targets = this.focusTargets;
// The obstruction manager performs approximate range checks.
// so we need to verify them here.
@@ -335,10 +360,12 @@
const range = cmpAttack.GetRange(attackType);
const yOrigin = cmpAttack.GetAttackYOrigin(attackType);
- let firedArrows = 0;
- while (firedArrows < arrowsToFire && targets.length())
- {
- const selectedTarget = targets.randomItem();
+ let firedArrows = 0;
+ let targetIndex = 0;
+ while (firedArrows < arrowsToFire && targetIndex < targets.length)
+ {
+
+ let selectedTarget = targets[targetIndex].entityId;
if (this.CheckTargetVisible(selectedTarget) && cmpObstructionManager.IsInTargetParabolicRange(
this.entity,
selectedTarget,
@@ -350,13 +377,14 @@
cmpAttack.PerformAttack(attackType, selectedTarget);
PlaySound("attack_" + attackType.toLowerCase(), this.entity);
++firedArrows;
- continue;
}
-
- // Could not attack target, try a different target.
- targets.remove(selectedTarget);
+ else
+ {
+ // Could not attack target, try a different target.
+ ++targetIndex
+ }
}
-
+ targets.splice(0, targetIndex);
this.arrowsLeft -= firedArrows;
++this.currentRound;
};
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
@@ -435,6 +435,8 @@
{
for (let ent of data.entities)
{
+ if (cmd.data.command == "attack" && cmd.data.target)
+ Engine.QueryInterface(ent, IID_BuildingAI)?.AddFocusTarget(cmd.target, cmd.queued, cmd.pushFront);
var cmpRallyPoint = Engine.QueryInterface(ent, IID_RallyPoint);
if (cmpRallyPoint)
{
Index: binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml
+++ binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml
@@ -17,7 +17,7 @@
2000
100
- 1.5
+ 2
50
false
Index: binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml
+++ binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml
@@ -11,7 +11,7 @@
2000
100
- 1.5
+ 3
50
false