Changeset View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 743 Lines • ▼ Show 20 Lines | "Order.Stop": function(msg) { | ||||
cmpFormation.ResetOrderVariant(); | cmpFormation.ResetOrderVariant(); | ||||
if (!this.IsAttackingAsFormation()) | if (!this.IsAttackingAsFormation()) | ||||
this.CallMemberFunction("Stop", [false]); | this.CallMemberFunction("Stop", [false]); | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
"Order.Attack": function(msg) { | "Order.Attack": function(msg) { | ||||
var target = msg.data.target; | let target = msg.data.target; | ||||
var allowCapture = msg.data.allowCapture; | let allowCapture = msg.data.allowCapture; | ||||
var cmpTargetUnitAI = Engine.QueryInterface(target, IID_UnitAI); | let cmpTargetUnitAI = Engine.QueryInterface(target, IID_UnitAI); | ||||
if (cmpTargetUnitAI && cmpTargetUnitAI.IsFormationMember()) | if (cmpTargetUnitAI && cmpTargetUnitAI.IsFormationMember()) | ||||
target = cmpTargetUnitAI.GetFormationController(); | target = cmpTargetUnitAI.GetFormationController(); | ||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | |||||
// Check if we are already in range, otherwise walk there | // Check if we are already in range, otherwise walk there | ||||
Stan: Move down ? | |||||
if (!this.CheckTargetAttackRange(target, target)) | if (!this.CheckFormationTargetAttackRange(target)) | ||||
{ | { | ||||
if (this.TargetIsAlive(target) && this.CheckTargetVisible(target)) | if (this.TargetIsAlive(target) && this.CheckTargetVisible(target)) | ||||
{ | { | ||||
this.SetNextState("COMBAT.APPROACHING"); | this.SetNextState("COMBAT.APPROACHING"); | ||||
return; | return; | ||||
} | } | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
this.CallMemberFunction("Attack", [target, allowCapture, false]); | this.CallMemberFunction("Attack", [target, allowCapture, false]); | ||||
if (cmpAttack.CanAttackAsFormation()) | let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | ||||
if (cmpAttack && cmpAttack.CanAttackAsFormation()) | |||||
this.SetNextState("COMBAT.ATTACKING"); | this.SetNextState("COMBAT.ATTACKING"); | ||||
else | else | ||||
this.SetNextState("MEMBER"); | this.SetNextState("MEMBER"); | ||||
}, | }, | ||||
"Order.Garrison": function(msg) { | "Order.Garrison": function(msg) { | ||||
if (!Engine.QueryInterface(msg.data.target, IID_GarrisonHolder)) | if (!Engine.QueryInterface(msg.data.target, IID_GarrisonHolder)) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 358 Lines • ▼ Show 20 Lines | "FORMING": { | ||||
cmpFormation.FindInPosition(); | cmpFormation.FindInPosition(); | ||||
} | } | ||||
}, | }, | ||||
"COMBAT": { | "COMBAT": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveFormationToTargetAttackRange(this.order.data.target)) | ||||
Done Inline ActionsThis should be enough to get into the range, timer is not necessary Silier: This should be enough to get into the range, timer is not necessary | |||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
Not Done Inline ActionsMissing check ? Stan: Missing check ? | |||||
cmpFormation.SetRearrange(true); | cmpFormation.SetRearrange(true); | ||||
cmpFormation.MoveMembersIntoFormation(true, true, "combat"); | cmpFormation.MoveMembersIntoFormation(true, true, "combat"); | ||||
return false; | return false; | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | ||||
Not Done Inline ActionsCheck for cmpAttack ? Stan: Check for cmpAttack ? | |||||
Not Done Inline ActionsWe can't arrive here without the cmpAttack and at many places where similar code is executed there aren't any checks for it. So I don't know ;) Freagarach: We can't arrive here without the `cmpAttack` and at many places where similar code is executed… | |||||
Not Done Inline ActionsMmmh I guess it's the same for above then ? You could move it down next to the cmpAttack check. Stan: Mmmh I guess it's the same for above then ? You could move it down next to the cmpAttack check. | |||||
let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | ||||
this.CallMemberFunction("Attack", [this.order.data.target, this.order.data.allowCapture, false]); | this.CallMemberFunction("Attack", [this.order.data.target, this.order.data.allowCapture, false]); | ||||
if (cmpAttack.CanAttackAsFormation()) | if (cmpAttack.CanAttackAsFormation()) | ||||
this.SetNextState("COMBAT.ATTACKING"); | this.SetNextState("COMBAT.ATTACKING"); | ||||
else | else | ||||
this.SetNextState("MEMBER"); | this.SetNextState("MEMBER"); | ||||
}, | }, | ||||
}, | }, | ||||
"ATTACKING": { | "ATTACKING": { | ||||
// Wait for individual members to finish | // Wait for individual members to finish | ||||
"enter": function(msg) { | "enter": function(msg) { | ||||
var target = this.order.data.target; | let target = this.order.data.target; | ||||
var allowCapture = this.order.data.allowCapture; | let allowCapture = this.order.data.allowCapture; | ||||
// Check if we are already in range, otherwise walk there | // Check if we are already in range, otherwise walk there | ||||
if (!this.CheckTargetAttackRange(target, target)) | if (!this.CheckFormationTargetAttackRange(target)) | ||||
{ | { | ||||
if (this.TargetIsAlive(target) && this.CheckTargetVisible(target)) | if (this.TargetIsAlive(target) && this.CheckTargetVisible(target)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": allowCapture }); | this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": allowCapture }); | ||||
return true; | return true; | ||||
} | } | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
Not Done Inline ActionsI guess check can be skipped here too ? @wraitii any input ? Stan: I guess check can be skipped here too ? @wraitii any input ? | |||||
// TODO fix the rearranging while attacking as formation | // TODO fix the rearranging while attacking as formation | ||||
cmpFormation.SetRearrange(!this.IsAttackingAsFormation()); | cmpFormation.SetRearrange(!this.IsAttackingAsFormation()); | ||||
cmpFormation.MoveMembersIntoFormation(false, false, "combat"); | cmpFormation.MoveMembersIntoFormation(false, false, "combat"); | ||||
this.StartTimer(200, 200); | this.StartTimer(200, 200); | ||||
return false; | return false; | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
var target = this.order.data.target; | let target = this.order.data.target; | ||||
var allowCapture = this.order.data.allowCapture; | let allowCapture = this.order.data.allowCapture; | ||||
// Check if we are already in range, otherwise walk there | // Check if we are already in range, otherwise walk there | ||||
if (!this.CheckTargetAttackRange(target, target)) | if (!this.CheckFormationTargetAttackRange(target)) | ||||
{ | { | ||||
if (this.TargetIsAlive(target) && this.CheckTargetVisible(target)) | if (this.TargetIsAlive(target) && this.CheckTargetVisible(target)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": allowCapture }); | this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": allowCapture }); | ||||
return; | return; | ||||
} | } | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
▲ Show 20 Lines • Show All 3,313 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
if (!this.CheckTargetVisible(target)) | if (!this.CheckTargetVisible(target)) | ||||
return false; | return false; | ||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | ||||
return cmpUnitMotion && cmpUnitMotion.MoveToTargetRange(target, min, max); | return cmpUnitMotion && cmpUnitMotion.MoveToTargetRange(target, min, max); | ||||
}; | }; | ||||
/** | |||||
* Move unit so we hope the target is in the attack range of the formation. | |||||
* | |||||
* @param {number} target - The target entity ID to attack. | |||||
* @return {boolean} - Whether the order to move has succeeded. | |||||
*/ | |||||
UnitAI.prototype.MoveFormationToTargetAttackRange = function(target) | |||||
{ | |||||
let cmpTargetFormation = Engine.QueryInterface(target, IID_Formation); | |||||
if (cmpTargetFormation) | |||||
target = cmpTargetFormation.GetClosestMember(this.entity); | |||||
if (!this.CheckTargetVisible(target) || this.IsTurret()) | |||||
return false; | |||||
let cmpFormationAttack = Engine.QueryInterface(this.entity, IID_Attack); | |||||
if (!cmpFormationAttack) | |||||
return false; | |||||
let range = cmpFormationAttack.GetRange(target); | |||||
FreagarachAuthorUnsubmitted Done Inline ActionsNote that we could use the general getter for ranges here (and below), but since we pass a target and not a type, I didn't do that. Freagarach: Note that we could use the general getter for ranges here (and below), but since we pass a… | |||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | |||||
return cmpUnitMotion && cmpUnitMotion.MoveToTargetRange(target, range.min, range.max); | |||||
}; | |||||
Done Inline Actionscan probably return cmpUnitMotion && cmpFormation && cmpUnitMotion.MoveToTargetRange(target, range.min, range.max); And nuke the last line. Dunno if you should check for range not being undefined or something. Stan: can probably
```lang=js
return cmpUnitMotion && cmpFormation && cmpUnitMotion. | |||||
Done Inline ActionsWhen cmpFormationAttack is defined, the range is also defined :) Freagarach: When `cmpFormationAttack` is defined, the range is also defined :) | |||||
Done Inline Actionsmove cmpFormation check to top as here has no other usage, but i dont think it is needed anyway Silier: move cmpFormation check to top as here has no other usage, but i dont think it is needed anyway | |||||
UnitAI.prototype.MoveToGarrisonRange = function(target) | UnitAI.prototype.MoveToGarrisonRange = function(target) | ||||
{ | { | ||||
if (!this.CheckTargetVisible(target)) | if (!this.CheckTargetVisible(target)) | ||||
return false; | return false; | ||||
var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | ||||
if (!cmpGarrisonHolder) | if (!cmpGarrisonHolder) | ||||
return false; | return false; | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
UnitAI.prototype.CheckTargetRangeExplicit = function(target, min, max) | UnitAI.prototype.CheckTargetRangeExplicit = function(target, min, max) | ||||
{ | { | ||||
let cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | let cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | ||||
return cmpObstructionManager.IsInTargetRange(this.entity, target, min, max, false); | return cmpObstructionManager.IsInTargetRange(this.entity, target, min, max, false); | ||||
}; | }; | ||||
/** | |||||
* Check if the target is inside the attack range of the formation. | |||||
* | |||||
* @param {number} target - The target entity ID to attack. | |||||
* @return {boolean} - Whether the entity is within attacking distance. | |||||
*/ | |||||
UnitAI.prototype.CheckFormationTargetAttackRange = function(target) | |||||
{ | |||||
let cmpTargetFormation = Engine.QueryInterface(target, IID_Formation); | |||||
if (cmpTargetFormation) | |||||
target = cmpTargetFormation.GetClosestMember(this.entity); | |||||
let cmpFormationAttack = Engine.QueryInterface(this.entity, IID_Attack); | |||||
if (!cmpFormationAttack) | |||||
return false; | |||||
let range = cmpFormationAttack.GetRange(target); | |||||
let cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | |||||
return cmpObstructionManager.IsInTargetRange(this.entity, target, range.min, range.max, false); | |||||
Done Inline Actionswhy true ? Silier: why true ? | |||||
}; | |||||
UnitAI.prototype.CheckGarrisonRange = function(target) | UnitAI.prototype.CheckGarrisonRange = function(target) | ||||
{ | { | ||||
var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | ||||
if (!cmpGarrisonHolder) | if (!cmpGarrisonHolder) | ||||
return false; | return false; | ||||
var range = cmpGarrisonHolder.GetLoadingRange(); | var range = cmpGarrisonHolder.GetLoadingRange(); | ||||
var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); | var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); | ||||
▲ Show 20 Lines • Show All 1,621 Lines • Show Last 20 Lines |
Move down ?