diff --git a/binaries/data/mods/public/simulation/components/Promotion.js b/binaries/data/mods/public/simulation/components/Promotion.js index 015e1bcd59..81f32131ed 100644 --- a/binaries/data/mods/public/simulation/components/Promotion.js +++ b/binaries/data/mods/public/simulation/components/Promotion.js @@ -67,7 +67,7 @@ Promotion.prototype.Promote = function(promotedTemplateName) var cmpPromotedUnitAI = Engine.QueryInterface(promotedUnitEntity, IID_UnitAI); cmpPromotedUnitAI.SetHeldPosition(cmpCurrentUnitAI.GetHeldPosition()); if (cmpCurrentUnitAI.GetStanceName()) - cmpPromotedUnitAI.SetStance(cmpCurrentUnitAI.GetStanceName()); + cmpPromotedUnitAI.SwitchToStance(cmpCurrentUnitAI.GetStanceName()); cmpPromotedUnitAI.Cheer(); var orders = cmpCurrentUnitAI.GetOrders(); cmpPromotedUnitAI.AddOrders(orders); diff --git a/binaries/data/mods/public/simulation/components/UnitAI.js b/binaries/data/mods/public/simulation/components/UnitAI.js index c9578ec24e..88a4815741 100644 --- a/binaries/data/mods/public/simulation/components/UnitAI.js +++ b/binaries/data/mods/public/simulation/components/UnitAI.js @@ -283,15 +283,8 @@ var UnitFsmSpec = { }, "Order.Gather": function(msg) { - //If target is not visible anymore, give up - if (!this.CheckTargetVisible(this.order.data.target)) - { - this.FinishOrder(); - return; - } - // If the target is still alive, we need to kill it first - if (this.MustKillGatherTarget(this.order.data.target)) + if (this.MustKillGatherTarget(this.order.data.target) && this.CheckTargetVisible(this.order.data.target)) { // Make sure we can attack the target, else we'll get very stuck if (!this.GetBestAttack()) @@ -381,6 +374,9 @@ var UnitFsmSpec = { "FORMATIONCONTROLLER": { "Order.Walk": function(msg) { + var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); + cmpFormation.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); + this.MoveToPoint(this.order.data.x, this.order.data.z); this.SetNextState("WALKING"); }, @@ -733,6 +729,22 @@ var UnitFsmSpec = { // TODO: respond to target deaths immediately, rather than waiting // until the next Timer event + + "Attacked": function(msg) { + if (this.order.data.target != msg.data.attacker) + { + // If we're attacked by a close enemy stronger than our current target, we choose to attack him + if (this.GetStance().targetAttackers && msg.data.type == "Melee") + { + var ents = [this.order.data.target, msg.data.attacker]; + SortEntitiesByPriority(ents); + if (ents[0] != this.order.data.target) + { + this.RespondToTargetedEntities(ents); + } + } + } + }, }, "CHASING": { @@ -2360,6 +2372,7 @@ UnitAI.prototype.FindNewTargets = function() if (!this.GetStance().targetVisibleEnemies) return false; + SortEntitiesByPriority(ents); return this.RespondToTargetedEntities(ents); }; diff --git a/binaries/data/mods/public/simulation/helpers/Entity.js b/binaries/data/mods/public/simulation/helpers/Entity.js index 1b3fe3dd09..9b89e1548f 100755 --- a/binaries/data/mods/public/simulation/helpers/Entity.js +++ b/binaries/data/mods/public/simulation/helpers/Entity.js @@ -17,4 +17,34 @@ function DistanceBetweenEntities(first, second) return horizDistance; } +/** + * Returns entities ordered by decreasing priority + * Do not alter order when units have the same priority + */ +function SortEntitiesByPriority(ents) +{ + // Priority list, weakers first + var types = ["Structure", "Worker"]; + + ents.sort(function (a, b) { + var cmpIdentityA = Engine.QueryInterface(a, IID_Identity); + var cmpIdentityB = Engine.QueryInterface(b, IID_Identity); + if (!cmpIdentityA || !cmpIdentityB) + return 0; + var classesA = cmpIdentityA.GetClassesList(); + var classesB = cmpIdentityB.GetClassesList(); + for each (var type in types) + { + var inA = classesA.indexOf(type) != -1; + var inB = classesB.indexOf(type) != -1; + if (inA && !inB) + return +1; + if (inB && !inA) + return -1; + } + return 0; + }); +} + Engine.RegisterGlobal("DistanceBetweenEntities", DistanceBetweenEntities); +Engine.RegisterGlobal("SortEntitiesByPriority", SortEntitiesByPriority);