Index: binaries/data/mods/public/simulation/components/UnitAI.js =================================================================== --- binaries/data/mods/public/simulation/components/UnitAI.js +++ binaries/data/mods/public/simulation/components/UnitAI.js @@ -450,6 +450,12 @@ return; } + if (!this.ShouldMoveToTargetAttackRange()) + { + this.FinishOrder(); + return; + } + // For packable units out of attack range: // 1. If packed, we need to move to attack range and then unpack. // 2. If unpacked, we first need to pack, then follow case 1. @@ -1930,6 +1936,11 @@ if (!this.CheckTargetAttackRange(target, this.order.data.attackType)) { + if (!this.ShouldMoveToTargetAttackRange()) + { + this.SetNextState("COMBAT.FINDINGNEWTARGET"); + return true; + } if (this.CanPack()) { this.PushOrderFront("Pack", { "force": true }); @@ -4538,14 +4549,8 @@ */ UnitAI.prototype.MoveToTargetAttackRange = function(target, type) { - // for formation members, the formation will take care of the range check - if (this.IsFormationMember()) - { - let cmpFormationUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); - if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation()) - return false; - } - + if (!this.ShouldMoveToTargetAttackRange()) + return false; let cmpFormation = Engine.QueryInterface(target, IID_Formation); if (cmpFormation) target = cmpFormation.GetClosestMember(this.entity); @@ -4672,6 +4677,18 @@ }; /** + * Return false if entity is part of formation and formation is attacking as one +*/ +UnitAI.prototype.ShouldMoveToTargetAttackRange = function() +{ + if (!this.IsFormationMember()) + return true; + // For formation members, the formation will take care of the range check + let cmpFormationUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); + return !cmpFormationUnitAI || !cmpFormationUnitAI.IsAttackingAsFormation(); +} + +/** * Check if the target is inside the attack range * For melee attacks, this goes straigt to the regular range calculation * For ranged attacks, the parabolic formula is used to accout for bigger ranges @@ -4679,15 +4696,6 @@ */ UnitAI.prototype.CheckTargetAttackRange = function(target, type) { - // for formation members, the formation will take care of the range check - if (this.IsFormationMember()) - { - let cmpFormationUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); - if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation() && - cmpFormationUnitAI.order.data.target == target) - return true; - } - let cmpFormation = Engine.QueryInterface(target, IID_Formation); if (cmpFormation) target = cmpFormation.GetClosestMember(this.entity); @@ -5013,7 +5021,7 @@ */ UnitAI.prototype.ShouldChaseTargetedEntity = function(target, force) { - if (this.IsTurret()) + if (this.IsTurret() || !this.ShouldMoveToTargetAttackRange()) return false; if (this.GetStance().respondChase) @@ -6244,9 +6252,12 @@ UnitAI.prototype.IsAttackingAsFormation = function() { - var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); - return cmpAttack && cmpAttack.CanAttackAsFormation() - && this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING"; + let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); + if (!cmpAttack || !cmpAttack.CanAttackAsFormation()) + return false; + let state = this.GetCurrentState(); + return state == "FORMATIONCONTROLLER.COMBAT.ATTACKING" || + state == "FORMATIONCONTROLLER.COMBAT.APPROACHING"; }; //// Animal specific functions ////