From 508cc0d4c7f8eae26f0d3755492feae042c04bf9 Mon Sep 17 00:00:00 2001 From: sanderd17 Date: Wed, 11 Sep 2013 17:50:49 +0000 Subject: [PATCH] Add preferred classes to BuildingAI. Patch by jammus. Fixes #1985 This was SVN commit r13823. --- .../simulation/components/BuildingAI.js | 31 +++++++----- .../public/simulation/helpers/WeightedList.js | 47 +++++++++++++++++++ 2 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 binaries/data/mods/public/simulation/helpers/WeightedList.js diff --git a/binaries/data/mods/public/simulation/components/BuildingAI.js b/binaries/data/mods/public/simulation/components/BuildingAI.js index 840588044f..dd50f9bc2f 100644 --- a/binaries/data/mods/public/simulation/components/BuildingAI.js +++ b/binaries/data/mods/public/simulation/components/BuildingAI.js @@ -169,16 +169,11 @@ BuildingAI.prototype.OnRangeUpdate = function(msg) else if (msg.tag != this.enemyUnitsQuery) return; - const restrictedClasses = cmpAttack.GetRestrictedClasses(attackType); - if (msg.added.length > 0) { for each (var entity in msg.added) { - var cmpIdentity = Engine.QueryInterface(entity, IID_Identity); - var targetClasses = cmpIdentity.GetClassesList(); - - if (!targetClasses.some(function(c){return restrictedClasses.indexOf(c) > -1;})) + if (cmpAttack.CanAttack(entity)) this.targetUnits.push(entity); } } @@ -285,20 +280,32 @@ BuildingAI.prototype.FireArrows = function() this.arrowsLeft ); } - var clonedTargets = this.targetUnits.slice(); + if (arrowsToFire <= 0) + { + this.currentRound++; + return; + } + var targets = new WeightedList(); + for (var i = 0; i < this.targetUnits.length; i++) + { + var target = this.targetUnits[i], + weight = (cmpAttack.GetPreference(target) || 0) + 1 + targets.add(target, weight); + } for (var i = 0;i < arrowsToFire;i++) { - var target = clonedTargets[Math.floor(Math.random() * this.targetUnits.length)]; - if (target && this.CheckTargetVisible(target)) + var selectedIndex = targets.randomIndex(), + selectedTarget = targets.itemAt(selectedIndex); + if (selectedTarget && this.CheckTargetVisible(selectedTarget)) { - cmpAttack.PerformAttack(attackType, target); + cmpAttack.PerformAttack(attackType, selectedTarget); PlaySound("attack", this.entity); } else { - clonedTargets.splice(clonedTargets.indexOf(target),1); + targets.removeAt(selectedIndex); i--; // one extra arrow left to fire - if(clonedTargets.length < 1) + if(targets.length() < 1) { this.arrowsLeft += arrowsToFire; // no targets found in this round, save arrows and go to next round diff --git a/binaries/data/mods/public/simulation/helpers/WeightedList.js b/binaries/data/mods/public/simulation/helpers/WeightedList.js new file mode 100644 index 0000000000..5fe0646b17 --- /dev/null +++ b/binaries/data/mods/public/simulation/helpers/WeightedList.js @@ -0,0 +1,47 @@ +var WeightedList = function() +{ + this.elements = [ ]; + this.totalWeight = 0; +}; + +WeightedList.prototype.length = function() +{ + return this.elements.length; +}; + +WeightedList.prototype.push = function(item, weight) +{ + if (weight === undefined) + weight = 1; + this.totalWeight += weight; + this.elements.push({ "item": item, "weight": weight }); +}; + +WeightedList.prototype.removeAt = function(index) +{ + var element = this.elements.splice(index, 1)[0]; + if (element) + this.totalWeight -= element.weight; +}; + +WeightedList.prototype.itemAt = function(index) +{ + var element = this.elements[index]; + return element ? element.item : null; +}; + +WeightedList.prototype.randomIndex = function() { + var element, + targetWeight = Math.random() * this.totalWeight, + cumulativeWeight = 0; + for (var index = 0; index < this.elements.length; index++) + { + element = this.elements[index]; + cumulativeWeight += element.weight; + if (cumulativeWeight >= targetWeight) + return index; + } + return -1; +}; + +Engine.RegisterGlobal("WeightedList", WeightedList);