Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 444 Lines • ▼ Show 20 Lines | "Order.Attack": function(msg) { | ||||
// If we can't reach the target, but are standing ground, then abandon this attack order. | // If we can't reach the target, but are standing ground, then abandon this attack order. | ||||
// Unless we're hunting, that's a special case where we should continue attacking our target. | // Unless we're hunting, that's a special case where we should continue attacking our target. | ||||
if (this.GetStance().respondStandGround && !this.order.data.force && !this.order.data.hunting || this.IsTurret()) | if (this.GetStance().respondStandGround && !this.order.data.force && !this.order.data.hunting || this.IsTurret()) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
if (!this.ShouldMoveToTargetAttackRange()) | |||||
Silier: i could merge that | |||||
Not Done Inline ActionsCan you still? Stan: Can you still? | |||||
Done Inline ActionsProbably not Silier: Probably not | |||||
{ | |||||
this.FinishOrder(); | |||||
return; | |||||
} | |||||
// For packable units out of attack range: | // For packable units out of attack range: | ||||
// 1. If packed, we need to move to attack range and then unpack. | // 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. | // 2. If unpacked, we first need to pack, then follow case 1. | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return; | return; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,462 Lines • ▼ Show 20 Lines | "COMBAT": { | ||||
} | } | ||||
if (!this.CanAttack(target)) | if (!this.CanAttack(target)) | ||||
{ | { | ||||
this.SetNextState("COMBAT.FINDINGNEWTARGET"); | this.SetNextState("COMBAT.FINDINGNEWTARGET"); | ||||
return true; | return true; | ||||
} | } | ||||
if (!this.CheckTargetAttackRange(target, this.order.data.attackType)) | if (this.ShouldMoveToTargetAttackRange() && | ||||
!this.CheckTargetAttackRange(target, this.order.data.attackType)) | |||||
{ | { | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return true; | return true; | ||||
} | } | ||||
this.SetNextState("COMBAT.APPROACHING"); | this.SetNextState("COMBAT.APPROACHING"); | ||||
▲ Show 20 Lines • Show All 2,593 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* Move unit so we hope the target is in the attack range | * Move unit so we hope the target is in the attack range | ||||
* for melee attacks, this goes straight to the default range checks | * for melee attacks, this goes straight to the default range checks | ||||
* for ranged attacks, the parabolic range is used | * for ranged attacks, the parabolic range is used | ||||
*/ | */ | ||||
UnitAI.prototype.MoveToTargetAttackRange = function(target, type) | UnitAI.prototype.MoveToTargetAttackRange = function(target, type) | ||||
{ | { | ||||
// for formation members, the formation will take care of the range check | if (!this.ShouldMoveToTargetAttackRange()) | ||||
if (this.IsFormationMember()) | |||||
{ | |||||
let cmpFormationUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); | |||||
if (cmpFormationUnitAI && cmpFormationUnitAI.IsAttackingAsFormation()) | |||||
return false; | return false; | ||||
} | |||||
let cmpFormation = Engine.QueryInterface(target, IID_Formation); | let cmpFormation = Engine.QueryInterface(target, IID_Formation); | ||||
if (cmpFormation) | if (cmpFormation) | ||||
target = cmpFormation.GetClosestMember(this.entity); | target = cmpFormation.GetClosestMember(this.entity); | ||||
if (type != "Ranged") | if (type != "Ranged") | ||||
return this.MoveToTargetRange(target, IID_Attack, type); | return this.MoveToTargetRange(target, IID_Attack, type); | ||||
if (!this.CheckTargetVisible(target)) | if (!this.CheckTargetVisible(target)) | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | UnitAI.prototype.CheckTargetRange = function(target, iid, type) | ||||
if (!range) | if (!range) | ||||
return false; | return false; | ||||
let cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | let cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | ||||
return cmpObstructionManager.IsInTargetRange(this.entity, target, range.min, range.max, false); | return cmpObstructionManager.IsInTargetRange(this.entity, target, range.min, range.max, false); | ||||
}; | }; | ||||
/** | /** | ||||
* Return false if entity is part of formation and formation is attacking as one | |||||
*/ | |||||
UnitAI.prototype.ShouldMoveToTargetAttackRange = function() | |||||
Done Inline ActionsI guess it needs better name Silier: I guess it needs better name | |||||
{ | |||||
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); | |||||
if (!cmpFormationUnitAI) | |||||
return true; | |||||
return !cmpFormationUnitAI.IsAttackingAsFormation(); | |||||
} | |||||
/** | |||||
* Check if the target is inside the attack range | * Check if the target is inside the attack range | ||||
* For melee attacks, this goes straigt to the regular range calculation | * For melee attacks, this goes straigt to the regular range calculation | ||||
* For ranged attacks, the parabolic formula is used to accout for bigger ranges | * For ranged attacks, the parabolic formula is used to accout for bigger ranges | ||||
* when the target is lower, and smaller ranges when the target is higher | * when the target is lower, and smaller ranges when the target is higher | ||||
*/ | */ | ||||
UnitAI.prototype.CheckTargetAttackRange = function(target, type) | 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); | let cmpFormation = Engine.QueryInterface(target, IID_Formation); | ||||
if (cmpFormation) | if (cmpFormation) | ||||
target = cmpFormation.GetClosestMember(this.entity); | target = cmpFormation.GetClosestMember(this.entity); | ||||
if (type != "Ranged") | if (type != "Ranged") | ||||
return this.CheckTargetRange(target, IID_Attack, type); | return this.CheckTargetRange(target, IID_Attack, type); | ||||
let targetCmpPosition = Engine.QueryInterface(target, IID_Position); | let targetCmpPosition = Engine.QueryInterface(target, IID_Position); | ||||
▲ Show 20 Lines • Show All 309 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
/* | /* | ||||
* Returns whether we should chase the targeted entity, | * Returns whether we should chase the targeted entity, | ||||
* given our current stance. | * given our current stance. | ||||
*/ | */ | ||||
UnitAI.prototype.ShouldChaseTargetedEntity = function(target, force) | UnitAI.prototype.ShouldChaseTargetedEntity = function(target, force) | ||||
{ | { | ||||
if (this.IsTurret()) | if (this.IsTurret() || !this.ShouldMoveToTargetAttackRange()) | ||||
return false; | return false; | ||||
if (this.GetStance().respondChase) | if (this.GetStance().respondChase) | ||||
return true; | return true; | ||||
// If we are guarding/escorting, chase at least as long as the guarded unit is in target range of the attacker | // If we are guarding/escorting, chase at least as long as the guarded unit is in target range of the attacker | ||||
if (this.isGuardOf) | if (this.isGuardOf) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,214 Lines • ▼ Show 20 Lines | UnitAI.prototype.IsPacking = function() | ||||
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | ||||
return cmpPack && cmpPack.IsPacking(); | return cmpPack && cmpPack.IsPacking(); | ||||
}; | }; | ||||
//// Formation specific functions //// | //// Formation specific functions //// | ||||
UnitAI.prototype.IsAttackingAsFormation = function() | UnitAI.prototype.IsAttackingAsFormation = function() | ||||
{ | { | ||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | ||||
return cmpAttack && cmpAttack.CanAttackAsFormation() | if (!cmpAttack || !cmpAttack.CanAttackAsFormation()) | ||||
&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING"; | return false;&& | ||||
let state = this.GetCurrentState(); | |||||
return state == "FORMATIONCONTROLLER.COMBAT.ATTACKING" || | |||||
state == "FORMATIONCONTROLLER.COMBAT.APPROACHING"; | |||||
}; | }; | ||||
//// Animal specific functions //// | //// Animal specific functions //// | ||||
UnitAI.prototype.MoveRandomly = function(distance) | UnitAI.prototype.MoveRandomly = function(distance) | ||||
{ | { | ||||
// To minimize drift all across the map, animals describe circles | // To minimize drift all across the map, animals describe circles | ||||
// approximated by polygons. | // approximated by polygons. | ||||
▲ Show 20 Lines • Show All 122 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
i could merge that