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.focusTarget = false;
};
BuildingAI.prototype.OnGarrisonedUnitsChanged = function(msg)
@@ -267,6 +268,18 @@
};
/**
+ * Sets the index to keep track of the user-targeted unit
+ * This value returns to 0 when the unit leaves
+ */
+BuildingAI.prototype.SetFocusTarget = function(ent)
+{
+ if (ent !== false && this.targetUnits.indexOf(ent) !== -1)
+ this.focusTarget = ent;
+ else
+ this.focusTarget = false
+};
+
+/**
* Fire arrows with random temporal distribution on prefered targets.
* Called 'roundCount' times every 'RepeatTime' seconds when there are units in the range.
*/
@@ -308,25 +321,20 @@
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 = target === this.focusTarget ? 0 :
+ (cmpAttack.GetPreference(target) ?? 49) + 1;
+ targets.push({"entityId": target, "preference": pref});
+ //Need to make space for pref 0, which will be the user selected target.
+ }.bind(this);
// Add the UnitAI target separately, as the UnitMotion and RangeManager implementations differ.
if (this.unitAITarget && this.targetUnits.indexOf(this.unitAITarget) == -1)
- addTarget(this.unitAITarget);
+ addTarget(this.unitAITarget);
for (let target of this.targetUnits)
- addTarget(target);
+ addTarget(target);
// The obstruction manager performs approximate range checks.
// so we need to verify them here.
@@ -335,10 +343,18 @@
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;
+ // 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;
+ });
+
+ while (firedArrows < arrowsToFire && targets.length > 0)
+ {
+ let selectedTarget = targets[0].entityId
if (this.CheckTargetVisible(selectedTarget) && cmpObstructionManager.IsInTargetParabolicRange(
this.entity,
selectedTarget,
@@ -352,11 +368,13 @@
++firedArrows;
continue;
}
-
+ else
+ {
// Could not attack target, try a different target.
- targets.remove(selectedTarget);
+ targets.splice(0,1);
+ this.focusTarget = false;
+ }
}
-
this.arrowsLeft -= firedArrows;
++this.currentRound;
};
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
+ 3
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
+ 4
50
false