Changeset View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show All 18 Lines | "<element name='FleeDistance'>" + | |||||||||||||||||||||||||||||||||
"<ref name='positiveDecimal'/>" + | "<ref name='positiveDecimal'/>" + | |||||||||||||||||||||||||||||||||
"</element>" + | "</element>" + | |||||||||||||||||||||||||||||||||
"<element name='CanGuard'>" + | "<element name='CanGuard'>" + | |||||||||||||||||||||||||||||||||
"<data type='boolean'/>" + | "<data type='boolean'/>" + | |||||||||||||||||||||||||||||||||
"</element>" + | "</element>" + | |||||||||||||||||||||||||||||||||
"<element name='CanPatrol'>" + | "<element name='CanPatrol'>" + | |||||||||||||||||||||||||||||||||
"<data type='boolean'/>" + | "<data type='boolean'/>" + | |||||||||||||||||||||||||||||||||
"</element>" + | "</element>" + | |||||||||||||||||||||||||||||||||
"<element name='PatrolWaitTime'>" + | ||||||||||||||||||||||||||||||||||
Freagarach: Seconds, minutes, ms? | ||||||||||||||||||||||||||||||||||
wraitiiAuthorUnsubmitted Done Inline ActionsIt's multiples of a second, I changed to an integer to enforce that. wraitii: It's multiples of a second, I changed to an integer to enforce that. | ||||||||||||||||||||||||||||||||||
FreagarachUnsubmitted Not Done Inline ActionsAny specific reason to limit it to integers? Freagarach: Any specific reason to limit it to integers? | ||||||||||||||||||||||||||||||||||
wraitiiAuthorUnsubmitted Done Inline ActionsYes, since I'm using a timer of 1000 seconds you can't really use decimals in a meaningful way. wraitii: Yes, since I'm using a timer of 1000 seconds you can't really use decimals in a meaningful way. | ||||||||||||||||||||||||||||||||||
"<ref name='nonNegativeDecimal'/>" + | ||||||||||||||||||||||||||||||||||
"</element>" + | ||||||||||||||||||||||||||||||||||
"<optional>" + | "<optional>" + | |||||||||||||||||||||||||||||||||
"<interleave>" + | "<interleave>" + | |||||||||||||||||||||||||||||||||
"<element name='NaturalBehaviour' a:help='Behaviour of the unit in the absence of player commands (intended for animals)'>" + | "<element name='NaturalBehaviour' a:help='Behaviour of the unit in the absence of player commands (intended for animals)'>" + | |||||||||||||||||||||||||||||||||
"<choice>" + | "<choice>" + | |||||||||||||||||||||||||||||||||
"<value a:help='Will actively attack any unit it encounters, even if not threatened'>violent</value>" + | "<value a:help='Will actively attack any unit it encounters, even if not threatened'>violent</value>" + | |||||||||||||||||||||||||||||||||
"<value a:help='Will attack nearby units if it feels threatened (if they linger within LOS for too long)'>aggressive</value>" + | "<value a:help='Will attack nearby units if it feels threatened (if they linger within LOS for too long)'>aggressive</value>" + | |||||||||||||||||||||||||||||||||
"<value a:help='Will attack nearby units if attacked'>defensive</value>" + | "<value a:help='Will attack nearby units if attacked'>defensive</value>" + | |||||||||||||||||||||||||||||||||
"<value a:help='Will never attack units but will attempt to flee when attacked'>passive</value>" + | "<value a:help='Will never attack units but will attempt to flee when attacked'>passive</value>" + | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | var g_OrdersCancelUnpacking = new Set([ | |||||||||||||||||||||||||||||||||
"WalkToTarget", | "WalkToTarget", | |||||||||||||||||||||||||||||||||
"Patrol", | "Patrol", | |||||||||||||||||||||||||||||||||
"Garrison" | "Garrison" | |||||||||||||||||||||||||||||||||
]); | ]); | |||||||||||||||||||||||||||||||||
// When leaving a foundation, we want to be clear of it by this distance. | // When leaving a foundation, we want to be clear of it by this distance. | |||||||||||||||||||||||||||||||||
var g_LeaveFoundationRange = 4; | var g_LeaveFoundationRange = 4; | |||||||||||||||||||||||||||||||||
// See ../helpers/FSM.js for some documentation of this FSM specification syntax | // See ../helpers/FSM.js for some documentation of this FSM specification syntax | |||||||||||||||||||||||||||||||||
Not Done Inline ActionsAny reason it's not in the prototype? Stan: Any reason it's not in the prototype? | ||||||||||||||||||||||||||||||||||
Not Done Inline ActionsI guess it could be const then also pretty sure you don't need the return ? () => {return a } == () => a ? Stan: I guess it could be const then also pretty sure you don't need the return ?
() => {return a }… | ||||||||||||||||||||||||||||||||||
Not Done Inline ActionsDon't think this is the way to avoid duplication in the unitAI. Also formations don;t need the animation changes. I rather go in the way of D2662, but that needs further designing. For now just clutter along in the messy fsm imo bb: Don't think this is the way to avoid duplication in the unitAI. Also formations don;t need the… | ||||||||||||||||||||||||||||||||||
Done Inline ActionsI don't need to store this, it's used to generate the FSM spec. wraitii: I don't need to store this, it's used to generate the FSM spec. | ||||||||||||||||||||||||||||||||||
Done Inline ActionsIt makes it slightly easier to navigate for me since Sublime picks up on the dict better, but ay', I'll revert that change. wraitii: It makes it slightly easier to navigate for me since Sublime picks up on the dict better, but… | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.UnitFsmSpec = { | UnitAI.prototype.UnitFsmSpec = { | |||||||||||||||||||||||||||||||||
// Default event handlers: | // Default event handlers: | |||||||||||||||||||||||||||||||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | |||||||||||||||||||||||||||||||||
// ignore spurious movement messages | // ignore spurious movement messages | |||||||||||||||||||||||||||||||||
// (these can happen when stopping moving at the same time | // (these can happen when stopping moving at the same time | |||||||||||||||||||||||||||||||||
// as switching states) | // as switching states) | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | UnitAI.prototype.UnitFsmSpec = { | |||||||||||||||||||||||||||||||||
"Order.FormationWalk": function(msg) { | "Order.FormationWalk": function(msg) { | |||||||||||||||||||||||||||||||||
// Let players move captured domestic animals around | // Let players move captured domestic animals around | |||||||||||||||||||||||||||||||||
if (this.IsAnimal() && !this.IsDomestic() || !this.AbleToMove()) | if (this.IsAnimal() && !this.IsDomestic() || !this.AbleToMove()) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// For packable units: | // For packable units: | |||||||||||||||||||||||||||||||||
Not Done Inline Actionsslightly out of scope, but why aren't we using a rangeQuery here and depend on timers? bb: slightly out of scope, but why aren't we using a rangeQuery here and depend on timers? | ||||||||||||||||||||||||||||||||||
Done Inline ActionsMh, what do you mean? The point is to pretend we're looking around, so I don't see how a range query would help? wraitii: Mh, what do you mean? The point is to pretend we're looking around, so I don't see how a range… | ||||||||||||||||||||||||||||||||||
Not Done Inline Actions
Freagarach: > slightly out of scope, but why aren't we using a rangeQuery here and depend on timers?
| ||||||||||||||||||||||||||||||||||
Not Done Inline ActionsSame comment applies to the (current) Patrolling state: we currently idle and check every 1000ms if there is some target near. But why we have this timer? Why not an active rangeQuery that informs us when a unit is close, so we react on that? Anyway seems out of scope for this patch though. bb: Same comment applies to the (current) Patrolling state: we currently idle and check every… | ||||||||||||||||||||||||||||||||||
Done Inline ActionsAh, yes, I see. wraitii: Ah, yes, I see.
I need a timer here anyways because the unit needs to stop "looking around"… | ||||||||||||||||||||||||||||||||||
Not Done Inline ActionsFreagarach: #5822 | ||||||||||||||||||||||||||||||||||
// 1. If packed, we can move. | // 1. If packed, we can move. | |||||||||||||||||||||||||||||||||
Not Done Inline ActionsInstead of hardcoding it, rather make it a template value. bb: Instead of hardcoding it, rather make it a template value. | ||||||||||||||||||||||||||||||||||
Done Inline Actions? wraitii: ? | ||||||||||||||||||||||||||||||||||
// 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; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
this.SetNextState("FORMATIONMEMBER.WALKING"); | this.SetNextState("FORMATIONMEMBER.WALKING"); | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | if (this.CanPack()) | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
if (this.CheckRange(this.order.data)) | if (this.CheckRange(this.order.data)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
// We are already at the target, or can't move at all | // We are already at the target, or can't move at all | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (consistent-return) Method 'Order.WalkToTarget' expected no return value. Lint: ESLintBear (consistent-return): `Method 'Order.WalkToTarget' expected no return value.` | ||||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// It's not too bad if we don't arrive at exactly the right position. | // It's not too bad if we don't arrive at exactly the right position. | |||||||||||||||||||||||||||||||||
this.order.data.relaxed = true; | this.order.data.relaxed = true; | |||||||||||||||||||||||||||||||||
if (this.IsAnimal()) | if (this.IsAnimal()) | |||||||||||||||||||||||||||||||||
this.SetNextState("ANIMAL.WALKING"); | this.SetNextState("ANIMAL.WALKING"); | |||||||||||||||||||||||||||||||||
else | else | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | "Order.Patrol": function(msg) { | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// It's not too bad if we don't arrive at exactly the right position. | // It's not too bad if we don't arrive at exactly the right position. | |||||||||||||||||||||||||||||||||
this.order.data.relaxed = true; | this.order.data.relaxed = true; | |||||||||||||||||||||||||||||||||
this.SetNextState("INDIVIDUAL.PATROL"); | this.SetNextState("INDIVIDUAL.PATROL.PATROLLING"); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"Order.Heal": function(msg) { | "Order.Heal": function(msg) { | |||||||||||||||||||||||||||||||||
// Check the target is alive | // Check the target is alive | |||||||||||||||||||||||||||||||||
if (!this.TargetIsAlive(this.order.data.target)) | if (!this.TargetIsAlive(this.order.data.target)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | "Order.WalkToPointRange": function(msg) { | |||||||||||||||||||||||||||||||||
if (!this.CheckRange(this.order.data)) | if (!this.CheckRange(this.order.data)) | |||||||||||||||||||||||||||||||||
this.SetNextState("WALKING"); | this.SetNextState("WALKING"); | |||||||||||||||||||||||||||||||||
else | else | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"Order.Patrol": function(msg) { | "Order.Patrol": function(msg) { | |||||||||||||||||||||||||||||||||
this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); | this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); | |||||||||||||||||||||||||||||||||
this.SetNextState("PATROL"); | this.SetNextState("PATROL.PATROLLING"); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"Order.Guard": function(msg) { | "Order.Guard": function(msg) { | |||||||||||||||||||||||||||||||||
this.CallMemberFunction("Guard", [msg.data.target, false]); | this.CallMemberFunction("Guard", [msg.data.target, false]); | |||||||||||||||||||||||||||||||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | |||||||||||||||||||||||||||||||||
cmpFormation.Disband(); | cmpFormation.Disband(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | "Order.Garrison": function(msg) { | |||||||||||||||||||||||||||||||||
if (!this.CheckGarrisonRange(msg.data.target)) | if (!this.CheckGarrisonRange(msg.data.target)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!this.CheckTargetVisible(msg.data.target)) | if (!this.CheckTargetVisible(msg.data.target)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
else | else | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-else-return) Unnecessary 'else' after 'return'. Lint: ESLintBear (no-else-return): `Unnecessary 'else' after 'return'.` | ||||||||||||||||||||||||||||||||||
this.SetNextState("GARRISON.APPROACHING"); | this.SetNextState("GARRISON.APPROACHING"); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
this.SetNextState("GARRISON.GARRISONING"); | this.SetNextState("GARRISON.GARRISONING"); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 186 Lines • ▼ Show 20 Lines | "WALKINGANDFIGHTING": { | |||||||||||||||||||||||||||||||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | |||||||||||||||||||||||||||||||||
if (msg.likelyFailure || this.CheckRange(this.order.data)) | if (msg.likelyFailure || this.CheckRange(this.order.data)) | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"PATROL": { | "PATROL": { | |||||||||||||||||||||||||||||||||
"enter": function(msg) { | "enter": function() { | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (consistent-return) Expected to return a value at the end of method 'enter'. Lint: ESLintBear (consistent-return): `Expected to return a value at the end of method 'enter'.` | ||||||||||||||||||||||||||||||||||
FreagarachUnsubmitted Done Inline ActionsLinter. Freagarach: Linter. | ||||||||||||||||||||||||||||||||||
// Memorize the origin position in case that we want to go back | // Memorize the origin position in case that we want to go back | |||||||||||||||||||||||||||||||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | |||||||||||||||||||||||||||||||||
if (!cmpPosition || !cmpPosition.IsInWorld()) | if (!cmpPosition || !cmpPosition.IsInWorld()) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||||||||||||||||||||||||||||||||
cmpFormation.SetRearrange(true); | ||||||||||||||||||||||||||||||||||
cmpFormation.MoveMembersIntoFormation(true, true, "combat"); | ||||||||||||||||||||||||||||||||||
if (!this.patrolStartPosOrder) | if (!this.patrolStartPosOrder) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.patrolStartPosOrder = cmpPosition.GetPosition(); | this.patrolStartPosOrder = cmpPosition.GetPosition(); | |||||||||||||||||||||||||||||||||
this.patrolStartPosOrder.targetClasses = this.order.data.targetClasses; | this.patrolStartPosOrder.targetClasses = this.order.data.targetClasses; | |||||||||||||||||||||||||||||||||
this.patrolStartPosOrder.allowCapture = this.order.data.allowCapture; | this.patrolStartPosOrder.allowCapture = this.order.data.allowCapture; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
if (!this.MoveTo(this.order.data)) | this.SetAnimationVariant("combat"); | |||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"leave": function() { | ||||||||||||||||||||||||||||||||||
delete this.patrolStartPosOrder; | ||||||||||||||||||||||||||||||||||
this.SetDefaultAnimationVariant(); | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"PATROLLING": { | ||||||||||||||||||||||||||||||||||
"enter": function() { | ||||||||||||||||||||||||||||||||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||||||||||||||||||||||||||||||||
if (!cmpPosition || !cmpPosition.IsInWorld() || | ||||||||||||||||||||||||||||||||||
!this.MoveTo(this.order.data)) | ||||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
this.StartTimer(0, 1000); | this.StartTimer(0, 1000); | |||||||||||||||||||||||||||||||||
let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||||||||||||||||||||||||||||||||
cmpFormation.SetRearrange(true); | ||||||||||||||||||||||||||||||||||
cmpFormation.MoveMembersIntoFormation(true, true, "combat"); | ||||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"Timer": function(msg) { | "leave": function() { | |||||||||||||||||||||||||||||||||
// Check if there are no enemies to attack | this.StopMoving(); | |||||||||||||||||||||||||||||||||
this.FindWalkAndFightTargets(); | this.StopTimer(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"leave": function(msg) { | "Timer": function(msg) { | |||||||||||||||||||||||||||||||||
this.StopTimer(); | this.FindWalkAndFightTargets(); | |||||||||||||||||||||||||||||||||
this.StopMoving(); | ||||||||||||||||||||||||||||||||||
delete this.patrolStartPosOrder; | ||||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | |||||||||||||||||||||||||||||||||
if (!msg.likelyFailure && !this.CheckRange(this.order.data)) | if (!msg.likelyFailure && !msg.likelySuccess && !this.RelaxedMaxRangeCheck(this.order.data, this.DefaultRelaxedMaxRange)) | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||
* A-B-A-B-..: | ||||||||||||||||||||||||||||||||||
* if the user only commands one patrol order, the patrol will be between | ||||||||||||||||||||||||||||||||||
* the last position and the defined waypoint | ||||||||||||||||||||||||||||||||||
* A-B-C-..-A-B-..: | ||||||||||||||||||||||||||||||||||
* otherwise, the patrol is only between the given patrol commands and the | ||||||||||||||||||||||||||||||||||
* last position is not included (last position = the position where the unit | ||||||||||||||||||||||||||||||||||
* is located at the time of the first patrol order) | ||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||
if (this.orderQueue.length == 1) | if (this.orderQueue.length == 1) | |||||||||||||||||||||||||||||||||
this.PushOrder("Patrol", this.patrolStartPosOrder); | this.PushOrder("Patrol", this.patrolStartPosOrder); | |||||||||||||||||||||||||||||||||
this.PushOrder(this.order.type, this.order.data); | this.PushOrder(this.order.type, this.order.data); | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.SetNextState("CHECKINGWAYPOINT"); | |||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"CHECKINGWAYPOINT": { | ||||||||||||||||||||||||||||||||||
"enter": function() { | ||||||||||||||||||||||||||||||||||
this.StartTimer(0, 1000); | ||||||||||||||||||||||||||||||||||
this.stopSurveying = 0; | ||||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"leave": function() { | ||||||||||||||||||||||||||||||||||
this.StopTimer(); | ||||||||||||||||||||||||||||||||||
delete this.stopSurveying; | ||||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"Timer": function(msg) { | ||||||||||||||||||||||||||||||||||
if (this.stopSurveying > this.template.PatrolWaitTime) | ||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||
this.FinishOrder(); | ||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
this.FindWalkAndFightTargets(); | ||||||||||||||||||||||||||||||||||
this.stopSurveying++; | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
FreagarachUnsubmitted Not Done Inline Actions
? Freagarach: ? | ||||||||||||||||||||||||||||||||||
wraitiiAuthorUnsubmitted Done Inline ActionsHm, to be honest I'd rather not keep using that FSM feature. Id anything, I'd go back to the "call a function that returns a dict" approach for this. wraitii: Hm, to be honest I'd rather not keep using that FSM feature. Id anything, I'd go back to the… | ||||||||||||||||||||||||||||||||||
FreagarachUnsubmitted Not Done Inline ActionsWell, it is still there and greatly reduces duplication, so IMHO there is no reason for not using it? Freagarach: Well, it is still there and greatly reduces duplication, so IMHO there is no reason for not… | ||||||||||||||||||||||||||||||||||
wraitiiAuthorUnsubmitted Done Inline ActionsCore reason is I disagree that it "greatly reduces duplication" since the rest of the patrol state is also mostly duplicated, and in generation formations are duplicated. wraitii: Core reason is I disagree that it "greatly reduces duplication" since the rest of the patrol… | ||||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"GARRISON":{ | "GARRISON":{ | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (key-spacing) Missing space before value for key 'GARRISON'. Lint: ESLintBear (key-spacing): `Missing space before value for key 'GARRISON'.` | ||||||||||||||||||||||||||||||||||
"APPROACHING": { | "APPROACHING": { | |||||||||||||||||||||||||||||||||
"enter": function() { | "enter": function() { | |||||||||||||||||||||||||||||||||
if (!this.MoveToGarrisonRange(this.order.data.target)) | if (!this.MoveToGarrisonRange(this.order.data.target)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 565 Lines • ▼ Show 20 Lines | "WALKINGANDFIGHTING": { | |||||||||||||||||||||||||||||||||
// stop anyways. This avoids pathing for an unreachable goal and reduces lag considerably. | // stop anyways. This avoids pathing for an unreachable goal and reduces lag considerably. | |||||||||||||||||||||||||||||||||
if (msg.likelyFailure || msg.obstructed && this.RelaxedMaxRangeCheck(this.order.data, this.DefaultRelaxedMaxRange) || | if (msg.likelyFailure || msg.obstructed && this.RelaxedMaxRangeCheck(this.order.data, this.DefaultRelaxedMaxRange) || | |||||||||||||||||||||||||||||||||
this.CheckRange(this.order.data)) | this.CheckRange(this.order.data)) | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"PATROL": { | "PATROL": { | |||||||||||||||||||||||||||||||||
"enter": function() { | "enter": function() { | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (consistent-return) Expected to return a value at the end of method 'enter'. Lint: ESLintBear (consistent-return): `Expected to return a value at the end of method 'enter'.` | ||||||||||||||||||||||||||||||||||
FreagarachUnsubmitted Done Inline ActionsLinter. Freagarach: Linter. | ||||||||||||||||||||||||||||||||||
// Memorize the origin position in case that we want to go back | // Memorize the origin position in case that we want to go back | |||||||||||||||||||||||||||||||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | |||||||||||||||||||||||||||||||||
if (!cmpPosition || !cmpPosition.IsInWorld() || | if (!cmpPosition || !cmpPosition.IsInWorld()) | |||||||||||||||||||||||||||||||||
!this.MoveTo(this.order.data)) | ||||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
if (!this.patrolStartPosOrder) | if (!this.patrolStartPosOrder) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.patrolStartPosOrder = cmpPosition.GetPosition(); | this.patrolStartPosOrder = cmpPosition.GetPosition(); | |||||||||||||||||||||||||||||||||
this.patrolStartPosOrder.targetClasses = this.order.data.targetClasses; | this.patrolStartPosOrder.targetClasses = this.order.data.targetClasses; | |||||||||||||||||||||||||||||||||
this.patrolStartPosOrder.allowCapture = this.order.data.allowCapture; | this.patrolStartPosOrder.allowCapture = this.order.data.allowCapture; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
this.StartTimer(0, 1000); | ||||||||||||||||||||||||||||||||||
this.SetAnimationVariant("combat"); | this.SetAnimationVariant("combat"); | |||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"leave": function() { | ||||||||||||||||||||||||||||||||||
delete this.patrolStartPosOrder; | ||||||||||||||||||||||||||||||||||
this.SetDefaultAnimationVariant(); | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"PATROLLING": { | ||||||||||||||||||||||||||||||||||
"enter": function() { | ||||||||||||||||||||||||||||||||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||||||||||||||||||||||||||||||||
if (!cmpPosition || !cmpPosition.IsInWorld() || | ||||||||||||||||||||||||||||||||||
!this.MoveTo(this.order.data)) | ||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||
this.FinishOrder(); | ||||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
this.StartTimer(0, 1000); | ||||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"leave": function() { | "leave": function() { | |||||||||||||||||||||||||||||||||
this.StopMoving(); | this.StopMoving(); | |||||||||||||||||||||||||||||||||
this.StopTimer(); | this.StopTimer(); | |||||||||||||||||||||||||||||||||
delete this.patrolStartPosOrder; | ||||||||||||||||||||||||||||||||||
this.SetDefaultAnimationVariant(); | ||||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"Timer": function(msg) { | "Timer": function(msg) { | |||||||||||||||||||||||||||||||||
this.FindWalkAndFightTargets(); | this.FindWalkAndFightTargets(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | |||||||||||||||||||||||||||||||||
if (!msg.likelyFailure && !msg.likelySuccess && !this.RelaxedMaxRangeCheck(this.order.data, this.DefaultRelaxedMaxRange)) | if (!msg.likelyFailure && !msg.likelySuccess && !this.RelaxedMaxRangeCheck(this.order.data, this.DefaultRelaxedMaxRange)) | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
if (this.orderQueue.length == 1) | if (this.orderQueue.length == 1) | |||||||||||||||||||||||||||||||||
this.PushOrder("Patrol", this.patrolStartPosOrder); | this.PushOrder("Patrol", this.patrolStartPosOrder); | |||||||||||||||||||||||||||||||||
this.PushOrder(this.order.type, this.order.data); | this.PushOrder(this.order.type, this.order.data); | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.SetNextState("CHECKINGWAYPOINT"); | |||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"CHECKINGWAYPOINT": { | ||||||||||||||||||||||||||||||||||
"enter": function() { | ||||||||||||||||||||||||||||||||||
this.StartTimer(0, 1000); | ||||||||||||||||||||||||||||||||||
this.stopSurveying = 0; | ||||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"leave": function() { | ||||||||||||||||||||||||||||||||||
this.StopTimer(); | ||||||||||||||||||||||||||||||||||
delete this.stopSurveying; | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"Timer": function(msg) { | ||||||||||||||||||||||||||||||||||
if (this.stopSurveying > this.template.PatrolWaitTime) | ||||||||||||||||||||||||||||||||||
FreagarachUnsubmitted Not Done Inline ActionsThis makes them wait at least one second (also birds). Freagarach: This makes them wait at least one second (also birds). | ||||||||||||||||||||||||||||||||||
Done Inline ActionsDoes one need a conversion to number here? (+this.template.PatrolWaitTime) Freagarach: Does one need a conversion to number here? (`+this.template.PatrolWaitTime`) | ||||||||||||||||||||||||||||||||||
wraitiiAuthorUnsubmitted Done Inline ActionsChanged to >= wraitii: Changed to >= | ||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||
this.FinishOrder(); | ||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
this.FindWalkAndFightTargets(); | ||||||||||||||||||||||||||||||||||
this.stopSurveying++; | ||||||||||||||||||||||||||||||||||
Done Inline Actions
? Freagarach: ? | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"GUARD": { | "GUARD": { | |||||||||||||||||||||||||||||||||
"RemoveGuard": function() { | "RemoveGuard": function() { | |||||||||||||||||||||||||||||||||
this.StopMoving(); | this.StopMoving(); | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 367 Lines • ▼ Show 20 Lines | "COMBAT": { | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
// TODO: respond to target deaths immediately, rather than waiting | // TODO: respond to target deaths immediately, rather than waiting | |||||||||||||||||||||||||||||||||
// until the next Timer event | // until the next Timer event | |||||||||||||||||||||||||||||||||
"Attacked": function(msg) { | "Attacked": function(msg) { | |||||||||||||||||||||||||||||||||
// If we are capturing and are attacked by something that we would not capture, attack that entity instead | // If we are capturing and are attacked by something that we would not capture, attack that entity instead | |||||||||||||||||||||||||||||||||
if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force) | if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force) | |||||||||||||||||||||||||||||||||
&& this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture") | && this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture") | |||||||||||||||||||||||||||||||||
Lint: JSHintBear Misleading line break before '&&'; readers may interpret this as an expression boundary. Lint: JSHintBear: `Misleading line break before '&&'; readers may interpret this as an expression boundary.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (operator-linebreak) '&&' should be placed at the end of the line. Lint: ESLintBear (operator-linebreak): `'&&' should be placed at the end of the line.` | ||||||||||||||||||||||||||||||||||
this.RespondToTargetedEntities([msg.data.attacker]); | this.RespondToTargetedEntities([msg.data.attacker]); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"FINDINGNEWTARGET": { | "FINDINGNEWTARGET": { | |||||||||||||||||||||||||||||||||
"enter": function() { | "enter": function() { | |||||||||||||||||||||||||||||||||
// Try to find the formation the target was a part of. | // Try to find the formation the target was a part of. | |||||||||||||||||||||||||||||||||
let cmpFormation = Engine.QueryInterface(this.order.data.target, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.order.data.target, IID_Formation); | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | "COMBAT": { | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"leave": function() { | "leave": function() { | |||||||||||||||||||||||||||||||||
this.StopMoving(); | this.StopMoving(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | |||||||||||||||||||||||||||||||||
// If it looks like the path is failing, and we are close enough (3 tiles) from wanted range | // If it looks like the path is failing, and we are close enough (3 tiles) from wanted range | |||||||||||||||||||||||||||||||||
// stop anyways. This avoids pathing for an unreachable goal and reduces lag considerably. | // stop anyways. This avoids pathing for an unreachable goal and reduces lag considerably. | |||||||||||||||||||||||||||||||||
if (msg.likelyFailure || | if (msg.likelyFailure || | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-trailing-spaces) Trailing spaces not allowed. Lint: ESLintBear (no-trailing-spaces): `Trailing spaces not allowed.` | ||||||||||||||||||||||||||||||||||
msg.obstructed && this.RelaxedMaxRangeCheck(this.order.data, this.order.data.max + this.DefaultRelaxedMaxRange) || | msg.obstructed && this.RelaxedMaxRangeCheck(this.order.data, this.order.data.max + this.DefaultRelaxedMaxRange) || | |||||||||||||||||||||||||||||||||
!msg.obstructed && this.CheckRange(this.order.data)) | !msg.obstructed && this.CheckRange(this.order.data)) | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 285 Lines • ▼ Show 20 Lines | "GATHER": { | |||||||||||||||||||||||||||||||||
if (previousTarget == ent) | if (previousTarget == ent) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
if (type.generic == "treasure" && resourceType.generic == "treasure") | if (type.generic == "treasure" && resourceType.generic == "treasure") | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
return type.specific == resourceType.specific && | return type.specific == resourceType.specific && | |||||||||||||||||||||||||||||||||
(type.specific != "meat" || resourceTemplate == template); | (type.specific != "meat" || resourceTemplate == template); | |||||||||||||||||||||||||||||||||
}); | }); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (indent) Expected indentation of 6 tabs but found 5. Lint: ESLintBear (indent): `Expected indentation of 6 tabs but found 5.` | ||||||||||||||||||||||||||||||||||
if (nearbyResource) | if (nearbyResource) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.PerformGather(nearbyResource, false, false); | this.PerformGather(nearbyResource, false, false); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// Failing that, try to move there and se if we are more lucky: maybe there are resources in FOW. | // Failing that, try to move there and se if we are more lucky: maybe there are resources in FOW. | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 600 Lines • ▼ Show 20 Lines | "CHEERING": { | |||||||||||||||||||||||||||||||||
this.StartTimer(2800, 2800); | this.StartTimer(2800, 2800); | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"leave": function() { | "leave": function() { | |||||||||||||||||||||||||||||||||
this.StopTimer(); | this.StopTimer(); | |||||||||||||||||||||||||||||||||
this.ResetAnimation(); | this.ResetAnimation(); | |||||||||||||||||||||||||||||||||
if (this.formationAnimationVariant) | if (this.formationAnimationVariant) | |||||||||||||||||||||||||||||||||
this.SetAnimationVariant(this.formationAnimationVariant) | this.SetAnimationVariant(this.formationAnimationVariant) | |||||||||||||||||||||||||||||||||
Lint: JSHintBear Missing semicolon. Lint: JSHintBear: `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (semi) Missing semicolon. Lint: ESLintBear (semi): `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
else | else | |||||||||||||||||||||||||||||||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | |||||||||||||||||||||||||||||||||
var cmpResistance = Engine.QueryInterface(this.entity, IID_Resistance); | var cmpResistance = Engine.QueryInterface(this.entity, IID_Resistance); | |||||||||||||||||||||||||||||||||
cmpResistance.SetInvulnerability(false); | cmpResistance.SetInvulnerability(false); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"Timer": function(msg) { | "Timer": function(msg) { | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 197 Lines • ▼ Show 20 Lines | "FEEDING": { | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"FLEEING": "INDIVIDUAL.FLEEING", // reuse the same fleeing behaviour for animals | "FLEEING": "INDIVIDUAL.FLEEING", // reuse the same fleeing behaviour for animals | |||||||||||||||||||||||||||||||||
"COMBAT": "INDIVIDUAL.COMBAT", // reuse the same combat behaviour for animals | "COMBAT": "INDIVIDUAL.COMBAT", // reuse the same combat behaviour for animals | |||||||||||||||||||||||||||||||||
"WALKING": "INDIVIDUAL.WALKING", // reuse the same walking behaviour for animals | "WALKING": "INDIVIDUAL.WALKING", // reuse the same walking behaviour for animals | |||||||||||||||||||||||||||||||||
// only used for domestic animals | // only used for domestic animals | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (indent) Expected indentation of 2 tabs but found 7. Lint: ESLintBear (indent): `Expected indentation of 2 tabs but found 7.` | ||||||||||||||||||||||||||||||||||
// Reuse the same garrison behaviour for animals. | // Reuse the same garrison behaviour for animals. | |||||||||||||||||||||||||||||||||
"GARRISON": "INDIVIDUAL.GARRISON", | "GARRISON": "INDIVIDUAL.GARRISON", | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.Init = function() | UnitAI.prototype.Init = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
Show All 33 Lines | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.IsFormationMember = function() | UnitAI.prototype.IsFormationMember = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
return (this.formationController != INVALID_ENTITY); | return (this.formationController != INVALID_ENTITY); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.IsAnimal = function() | UnitAI.prototype.IsAnimal = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
return (this.template.NaturalBehaviour ? true : false); | return (this.template.NaturalBehaviour ? true : false); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-unneeded-ternary) Unnecessary use of boolean literals in conditional expression. Lint: ESLintBear (no-unneeded-ternary): `Unnecessary use of boolean literals in conditional expression.` | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.IsDangerousAnimal = function() | UnitAI.prototype.IsDangerousAnimal = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
return (this.IsAnimal() && (this.template.NaturalBehaviour == "violent" || | return (this.IsAnimal() && (this.template.NaturalBehaviour == "violent" || | |||||||||||||||||||||||||||||||||
this.template.NaturalBehaviour == "aggressive")); | this.template.NaturalBehaviour == "aggressive")); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 123 Lines • ▼ Show 20 Lines | if (msg.to != INVALID_PLAYER && msg.from != INVALID_PLAYER) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.orderQueue.length = Math.min(this.orderQueue.length, 1); | this.orderQueue.length = Math.min(this.orderQueue.length, 1); | |||||||||||||||||||||||||||||||||
Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
else | else | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
let index = this.GetCurrentState().indexOf("."); | let index = this.GetCurrentState().indexOf("."); | |||||||||||||||||||||||||||||||||
if (index != -1) | if (index != -1) | |||||||||||||||||||||||||||||||||
this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0,index)); | this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0,index)); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (comma-spacing) A space is required after ','. Lint: ESLintBear (comma-spacing): `A space is required after ','.` | ||||||||||||||||||||||||||||||||||
this.Stop(false); | this.Stop(false); | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
this.workOrders = []; | this.workOrders = []; | |||||||||||||||||||||||||||||||||
let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | |||||||||||||||||||||||||||||||||
if (cmpTrader) | if (cmpTrader) | |||||||||||||||||||||||||||||||||
cmpTrader.StopTrading(); | cmpTrader.StopTrading(); | |||||||||||||||||||||||||||||||||
Show All 40 Lines | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.OnPickupCanceled = function(msg) | UnitAI.prototype.OnPickupCanceled = function(msg) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
for (let i = 0; i < this.orderQueue.length; ++i) | for (let i = 0; i < this.orderQueue.length; ++i) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity) | if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity) | |||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
if (i == 0) | if (i == 0) | |||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg}); | this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg}); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required after '{'. Lint: ESLintBear (object-curly-spacing): `A space is required after '{'.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required before '}'. Lint: ESLintBear (object-curly-spacing): `A space is required before '}'.` | ||||||||||||||||||||||||||||||||||
else | else | |||||||||||||||||||||||||||||||||
this.orderQueue.splice(i, 1); | this.orderQueue.splice(i, 1); | |||||||||||||||||||||||||||||||||
Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | |||||||||||||||||||||||||||||||||
break; | break; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | UnitAI.prototype.SetupAttackRangeQuery = function(enable = true) | |||||||||||||||||||||||||||||||||
let range = this.GetQueryRange(IID_Attack); | let range = this.GetQueryRange(IID_Attack); | |||||||||||||||||||||||||||||||||
this.losAttackRangeQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, players, IID_Resistance, cmpRangeManager.GetEntityFlagMask("normal")); | this.losAttackRangeQuery = cmpRangeManager.CreateActiveQuery(this.entity, range.min, range.max, players, IID_Resistance, cmpRangeManager.GetEntityFlagMask("normal")); | |||||||||||||||||||||||||||||||||
if (enable) | if (enable) | |||||||||||||||||||||||||||||||||
cmpRangeManager.EnableActiveQuery(this.losAttackRangeQuery); | cmpRangeManager.EnableActiveQuery(this.losAttackRangeQuery); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
//// FSM linkage functions //// | //// FSM linkage functions //// | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
// Setting the next state to the current state will leave/re-enter the top-most substate. | // Setting the next state to the current state will leave/re-enter the top-most substate. | |||||||||||||||||||||||||||||||||
UnitAI.prototype.SetNextState = function(state) | UnitAI.prototype.SetNextState = function(state) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.UnitFsm.SetNextState(this, state); | this.UnitFsm.SetNextState(this, state); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.DeferMessage = function(msg) | UnitAI.prototype.DeferMessage = function(msg) | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | UnitAI.prototype.PushOrderAfterForced = function(type, data) | |||||||||||||||||||||||||||||||||
else | else | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
for (let i = 1; i < this.orderQueue.length; ++i) | for (let i = 1; i < this.orderQueue.length; ++i) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (this.orderQueue[i].data && this.orderQueue[i].data.force) | if (this.orderQueue[i].data && this.orderQueue[i].data.force) | |||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
if (this.orderQueue[i].type == type) | if (this.orderQueue[i].type == type) | |||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
this.orderQueue.splice(i, 0, {"type": type, "data": data}); | this.orderQueue.splice(i, 0, {"type": type, "data": data}); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required after '{'. Lint: ESLintBear (object-curly-spacing): `A space is required after '{'.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required before '}'. Lint: ESLintBear (object-curly-spacing): `A space is required before '}'.` | ||||||||||||||||||||||||||||||||||
Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
this.PushOrder(type, data); | this.PushOrder(type, data); | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | UnitAI.prototype.ReplaceOrder = function(type, data) | |||||||||||||||||||||||||||||||||
if (this.order && this.order.type == "Cheering") | if (this.order && this.order.type == "Cheering") | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var order = { "type": type, "data": data }; | var order = { "type": type, "data": data }; | |||||||||||||||||||||||||||||||||
var cheeringOrder = this.orderQueue.shift(); | var cheeringOrder = this.orderQueue.shift(); | |||||||||||||||||||||||||||||||||
this.orderQueue = [cheeringOrder, order]; | this.orderQueue = [cheeringOrder, order]; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
else if (this.IsPacking() && type != "CancelPack" && type != "CancelUnpack") | else if (this.IsPacking() && type != "CancelPack" && type != "CancelUnpack") | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var order = { "type": type, "data": data }; | var order = { "type": type, "data": data }; | |||||||||||||||||||||||||||||||||
Lint: JSHintBear 'order' is already defined. Lint: JSHintBear: `'order' is already defined.` | ||||||||||||||||||||||||||||||||||
var packingOrder = this.orderQueue.shift(); | var packingOrder = this.orderQueue.shift(); | |||||||||||||||||||||||||||||||||
if (type == "Attack") | if (type == "Attack") | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
// The Attack order is able to handle a packing unit, while other orders can't. | // The Attack order is able to handle a packing unit, while other orders can't. | |||||||||||||||||||||||||||||||||
this.orderQueue = [packingOrder]; | this.orderQueue = [packingOrder]; | |||||||||||||||||||||||||||||||||
this.PushOrderFront(type, data, true); | this.PushOrderFront(type, data, true); | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
else if (packingOrder.type == "Unpack" && g_OrdersCancelUnpacking.has(type)) | else if (packingOrder.type == "Unpack" && g_OrdersCancelUnpacking.has(type)) | |||||||||||||||||||||||||||||||||
Show All 36 Lines | for (let order of this.orderQueue) | |||||||||||||||||||||||||||||||||
if (order.data) | if (order.data) | |||||||||||||||||||||||||||||||||
orders.push(clone(order.data)); | orders.push(clone(order.data)); | |||||||||||||||||||||||||||||||||
return orders; | return orders; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.UpdateWorkOrders = function(type) | UnitAI.prototype.UpdateWorkOrders = function(type) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var isWorkType = type => type == "Gather" || type == "Trade" || type == "Repair" || type == "ReturnResource"; | var isWorkType = type => type == "Gather" || type == "Trade" || type == "Repair" || type == "ReturnResource"; | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-shadow) 'type' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'type' is already declared in the upper scope.` | ||||||||||||||||||||||||||||||||||
// If we are being re-affected to a work order, forget the previous ones | // If we are being re-affected to a work order, forget the previous ones | |||||||||||||||||||||||||||||||||
if (isWorkType(type)) | if (isWorkType(type)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.workOrders = []; | this.workOrders = []; | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
Show All 14 Lines | if (cmpUnitAI) | |||||||||||||||||||||||||||||||||
this.workOrders = cmpUnitAI.orderQueue.slice(i); | this.workOrders = cmpUnitAI.orderQueue.slice(i); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// If nothing found, take the unit orders | // If nothing found, take the unit orders | |||||||||||||||||||||||||||||||||
for (var i = 0; i < this.orderQueue.length; ++i) | for (var i = 0; i < this.orderQueue.length; ++i) | |||||||||||||||||||||||||||||||||
Lint: JSHintBear 'i' is already defined. Lint: JSHintBear: `'i' is already defined.` | ||||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (isWorkType(this.orderQueue[i].type)) | if (isWorkType(this.orderQueue[i].type)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.workOrders = this.orderQueue.slice(i); | this.workOrders = this.orderQueue.slice(i); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.TimerHandler = function(data, lateness) | UnitAI.prototype.TimerHandler = function(data, lateness) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
// Reset the timer | // Reset the timer | |||||||||||||||||||||||||||||||||
if (data.timerRepeat === undefined) | if (data.timerRepeat === undefined) | |||||||||||||||||||||||||||||||||
this.timer = undefined; | this.timer = undefined; | |||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness}); | this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness}); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required after '{'. Lint: ESLintBear (object-curly-spacing): `A space is required after '{'.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required before '}'. Lint: ESLintBear (object-curly-spacing): `A space is required before '}'.` | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* Set up the UnitAI timer to run after 'offset' msecs, and then | * Set up the UnitAI timer to run after 'offset' msecs, and then | |||||||||||||||||||||||||||||||||
* every 'repeat' msecs until StopTimer is called. A "Timer" message | * every 'repeat' msecs until StopTimer is called. A "Timer" message | |||||||||||||||||||||||||||||||||
* will be sent each time the timer runs. | * will be sent each time the timer runs. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.StartTimer = function(offset, repeat) | UnitAI.prototype.StartTimer = function(offset, repeat) | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | UnitAI.prototype.OnGlobalEntityRenamed = function(msg) | |||||||||||||||||||||||||||||||||
Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.OnAttacked = function(msg) | UnitAI.prototype.OnAttacked = function(msg) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (msg.fromStatusEffect) | if (msg.fromStatusEffect) | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg}); | this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg}); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required before '}'. Lint: ESLintBear (object-curly-spacing): `A space is required before '}'.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required after '{'. Lint: ESLintBear (object-curly-spacing): `A space is required after '{'.` | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.OnGuardedAttacked = function(msg) | UnitAI.prototype.OnGuardedAttacked = function(msg) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data}); | this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data}); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required before '}'. Lint: ESLintBear (object-curly-spacing): `A space is required before '}'.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required after '{'. Lint: ESLintBear (object-curly-spacing): `A space is required after '{'.` | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.OnHealthChanged = function(msg) | UnitAI.prototype.OnHealthChanged = function(msg) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to}); | this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to}); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required before '}'. Lint: ESLintBear (object-curly-spacing): `A space is required before '}'.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required after '{'. Lint: ESLintBear (object-curly-spacing): `A space is required after '{'.` | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.OnRangeUpdate = function(msg) | UnitAI.prototype.OnRangeUpdate = function(msg) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (msg.tag == this.losRangeQuery) | if (msg.tag == this.losRangeQuery) | |||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, { "type": "LosRangeUpdate", "data": msg }); | this.UnitFsm.ProcessMessage(this, { "type": "LosRangeUpdate", "data": msg }); | |||||||||||||||||||||||||||||||||
else if (msg.tag == this.losHealRangeQuery) | else if (msg.tag == this.losHealRangeQuery) | |||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, { "type": "LosHealRangeUpdate", "data": msg }); | this.UnitFsm.ProcessMessage(this, { "type": "LosHealRangeUpdate", "data": msg }); | |||||||||||||||||||||||||||||||||
else if (msg.tag == this.losAttackRangeQuery) | else if (msg.tag == this.losAttackRangeQuery) | |||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, { "type": "LosAttackRangeUpdate", "data": msg }); | this.UnitFsm.ProcessMessage(this, { "type": "LosAttackRangeUpdate", "data": msg }); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.OnPackFinished = function(msg) | UnitAI.prototype.OnPackFinished = function(msg) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed}); | this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed}); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required before '}'. Lint: ESLintBear (object-curly-spacing): `A space is required before '}'.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required after '{'. Lint: ESLintBear (object-curly-spacing): `A space is required after '{'.` | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
//// Helper functions to be called by the FSM //// | //// Helper functions to be called by the FSM //// | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.GetWalkSpeed = function() | UnitAI.prototype.GetWalkSpeed = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | |||||||||||||||||||||||||||||||||
if (!cmpUnitMotion) | if (!cmpUnitMotion) | |||||||||||||||||||||||||||||||||
return 0; | return 0; | |||||||||||||||||||||||||||||||||
return cmpUnitMotion.GetWalkSpeed(); | return cmpUnitMotion.GetWalkSpeed(); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 692 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* Try to find one of the given entities which can be attacked, | * Try to find one of the given entities which can be attacked, | |||||||||||||||||||||||||||||||||
* and start attacking it. | * and start attacking it. | |||||||||||||||||||||||||||||||||
* Returns true if it found something to attack. | * Returns true if it found something to attack. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.AttackVisibleEntity = function(ents) | UnitAI.prototype.AttackVisibleEntity = function(ents) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var target = ents.find(target => this.CanAttack(target)); | var target = ents.find(target => this.CanAttack(target)); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-shadow) 'target' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'target' is already declared in the upper scope.` | ||||||||||||||||||||||||||||||||||
if (!target) | if (!target) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": true }); | this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": true }); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* Try to find one of the given entities which can be attacked | * Try to find one of the given entities which can be attacked | |||||||||||||||||||||||||||||||||
* and which is close to the hold position, and start attacking it. | * and which is close to the hold position, and start attacking it. | |||||||||||||||||||||||||||||||||
* Returns true if it found something to attack. | * Returns true if it found something to attack. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.AttackEntityInZone = function(ents) | UnitAI.prototype.AttackEntityInZone = function(ents) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var target = ents.find(target => | var target = ents.find(target => | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-shadow) 'target' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'target' is already declared in the upper scope.` | ||||||||||||||||||||||||||||||||||
this.CanAttack(target) | this.CanAttack(target) | |||||||||||||||||||||||||||||||||
&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true)) | && this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true)) | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (operator-linebreak) '&&' should be placed at the end of the line. Lint: ESLintBear (operator-linebreak): `'&&' should be placed at the end of the line.` | ||||||||||||||||||||||||||||||||||
Lint: JSHintBear Misleading line break before '&&'; readers may interpret this as an expression boundary. Lint: JSHintBear: `Misleading line break before '&&'; readers may interpret this as an expression boundary.` | ||||||||||||||||||||||||||||||||||
&& (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target)) | && (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target)) | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (operator-linebreak) '&&' should be placed at the end of the line. Lint: ESLintBear (operator-linebreak): `'&&' should be placed at the end of the line.` | ||||||||||||||||||||||||||||||||||
Lint: JSHintBear Misleading line break before '&&'; readers may interpret this as an expression boundary. Lint: JSHintBear: `Misleading line break before '&&'; readers may interpret this as an expression boundary.` | ||||||||||||||||||||||||||||||||||
); | ); | |||||||||||||||||||||||||||||||||
if (!target) | if (!target) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": true }); | this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": true }); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* Try to respond to healable entities. | * Try to respond to healable entities. | |||||||||||||||||||||||||||||||||
* Returns true if it responded. | * Returns true if it responded. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.RespondToHealableEntities = function(ents) | UnitAI.prototype.RespondToHealableEntities = function(ents) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
let ent = ents.find(ent => this.CanHeal(ent)); | let ent = ents.find(ent => this.CanHeal(ent)); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-shadow) 'ent' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'ent' is already declared in the upper scope.` | ||||||||||||||||||||||||||||||||||
if (!ent) | if (!ent) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
this.PushOrderFront("Heal", { "target": ent, "force": false }); | this.PushOrderFront("Heal", { "target": ent, "force": false }); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* Returns true if we should stop following the target entity. | * Returns true if we should stop following the target entity. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.ShouldAbandonChase = function(target, force, iid, type) | UnitAI.prototype.ShouldAbandonChase = function(target, force, iid, type) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
// Forced orders shouldn't be interrupted. | // Forced orders shouldn't be interrupted. | |||||||||||||||||||||||||||||||||
if (force) | if (force) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
// If we are guarding/escorting, don't abandon as long as the guarded unit is in target range of the attacker | // If we are guarding/escorting, don't abandon as long as the guarded unit is in target range of the attacker | |||||||||||||||||||||||||||||||||
if (this.isGuardOf) | if (this.isGuardOf) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI); | var cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-multi-spaces) Multiple spaces found before 'Engine'. Lint: ESLintBear (no-multi-spaces): `Multiple spaces found before 'Engine'.` | ||||||||||||||||||||||||||||||||||
var cmpAttack = Engine.QueryInterface(target, IID_Attack); | var cmpAttack = Engine.QueryInterface(target, IID_Attack); | |||||||||||||||||||||||||||||||||
if (cmpUnitAI && cmpAttack && | if (cmpUnitAI && cmpAttack && | |||||||||||||||||||||||||||||||||
cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type))) | cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type))) | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-shadow) 'type' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'type' is already declared in the upper scope.` | ||||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (indent) Expected indentation of 3 tabs but found 4. Lint: ESLintBear (indent): `Expected indentation of 3 tabs but found 4.` | ||||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// Stop if we're in hold-ground mode and it's too far from the holding point | // Stop if we're in hold-ground mode and it's too far from the holding point | |||||||||||||||||||||||||||||||||
if (this.GetStance().respondHoldGround) | if (this.GetStance().respondHoldGround) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!this.CheckTargetDistanceFromHeldPosition(target, iid, type)) | if (!this.CheckTargetDistanceFromHeldPosition(target, iid, type)) | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
Show All 21 Lines | if (!this.AbleToMove()) | |||||||||||||||||||||||||||||||||
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) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
let cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI); | let cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-multi-spaces) Multiple spaces found before 'Engine'. Lint: ESLintBear (no-multi-spaces): `Multiple spaces found before 'Engine'.` | ||||||||||||||||||||||||||||||||||
let cmpAttack = Engine.QueryInterface(target, IID_Attack); | let cmpAttack = Engine.QueryInterface(target, IID_Attack); | |||||||||||||||||||||||||||||||||
if (cmpUnitAI && cmpAttack && | if (cmpUnitAI && cmpAttack && | |||||||||||||||||||||||||||||||||
cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type))) | cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type))) | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
if (force) | if (force) | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
//// External interface functions //// | //// External interface functions //// | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.SetFormationController = function(ent) | UnitAI.prototype.SetFormationController = function(ent) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.formationController = ent; | this.formationController = ent; | |||||||||||||||||||||||||||||||||
// Set obstruction group, so we can walk through members | // Set obstruction group, so we can walk through members | |||||||||||||||||||||||||||||||||
// of our own formation (or ourself if not in formation) | // of our own formation (or ourself if not in formation) | |||||||||||||||||||||||||||||||||
var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); | var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | UnitAI.prototype.Guard = function(target, queued) | |||||||||||||||||||||||||||||||||
// if we already had an old guard order, do nothing if the target is the same | // if we already had an old guard order, do nothing if the target is the same | |||||||||||||||||||||||||||||||||
// and the order is running, otherwise remove the previous order | // and the order is running, otherwise remove the previous order | |||||||||||||||||||||||||||||||||
if (this.isGuardOf) | if (this.isGuardOf) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (this.isGuardOf == target && this.order && this.order.type == "Guard") | if (this.isGuardOf == target && this.order && this.order.type == "Guard") | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
else | else | |||||||||||||||||||||||||||||||||
this.RemoveGuard(); | this.RemoveGuard(); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-else-return) Unnecessary 'else' after 'return'. Lint: ESLintBear (no-else-return): `Unnecessary 'else' after 'return'.` | ||||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
this.AddOrder("Guard", { "target": target, "force": false }, queued); | this.AddOrder("Guard", { "target": target, "force": false }, queued); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.AddGuard = function(target) | UnitAI.prototype.AddGuard = function(target) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!this.CanGuard()) | if (!this.CanGuard()) | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 316 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | |||||||||||||||||||||||||||||||||
if (!cmpTrader) | if (!cmpTrader) | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
cmpTrader.RemoveTargetMarket(target); | cmpTrader.RemoveTargetMarket(target); | |||||||||||||||||||||||||||||||||
if (this.IsFormationController()) | if (this.IsFormationController()) | |||||||||||||||||||||||||||||||||
this.CallMemberFunction("CancelSetupTradeRoute", [target]); | this.CallMemberFunction("CancelSetupTradeRoute", [target]); | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (semi) Missing semicolon. Lint: ESLintBear (semi): `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
Lint: JSHintBear Missing semicolon. Lint: JSHintBear: `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* Adds trade order to the queue. Either walk to the first market, or | * Adds trade order to the queue. Either walk to the first market, or | |||||||||||||||||||||||||||||||||
* start a new route. Not forced, so it can be interrupted by attacks. | * start a new route. Not forced, so it can be interrupted by attacks. | |||||||||||||||||||||||||||||||||
* The possible route may be given directly as a SetupTradeRoute argument | * The possible route may be given directly as a SetupTradeRoute argument | |||||||||||||||||||||||||||||||||
* if coming from a RallyPoint, or through this.expectedRoute if a user command. | * if coming from a RallyPoint, or through this.expectedRoute if a user command. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.SetupTradeRoute = function(target, source, route, queued) | UnitAI.prototype.SetupTradeRoute = function(target, source, route, queued) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!this.CanTrade(target)) | if (!this.CanTrade(target)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.WalkToTarget(target, queued); | this.WalkToTarget(target, queued); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// AI has currently no access to BackToWork | // AI has currently no access to BackToWork | |||||||||||||||||||||||||||||||||
let cmpPlayer = QueryOwnerInterface(this.entity); | let cmpPlayer = QueryOwnerInterface(this.entity); | |||||||||||||||||||||||||||||||||
if (cmpPlayer && cmpPlayer.IsAI() && !this.IsFormationController() && | if (cmpPlayer && cmpPlayer.IsAI() && !this.IsFormationController() && | |||||||||||||||||||||||||||||||||
this.workOrders.length && this.workOrders[0].type == "Trade") | this.workOrders.length && this.workOrders[0].type == "Trade") | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | |||||||||||||||||||||||||||||||||
if (cmpTrader.HasBothMarkets() && | if (cmpTrader.HasBothMarkets() && | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-trailing-spaces) Trailing spaces not allowed. Lint: ESLintBear (no-trailing-spaces): `Trailing spaces not allowed.` | ||||||||||||||||||||||||||||||||||
(cmpTrader.GetFirstMarket() == target && cmpTrader.GetSecondMarket() == source || | (cmpTrader.GetFirstMarket() == target && cmpTrader.GetSecondMarket() == source || | |||||||||||||||||||||||||||||||||
cmpTrader.GetFirstMarket() == source && cmpTrader.GetSecondMarket() == target)) | cmpTrader.GetFirstMarket() == source && cmpTrader.GetSecondMarket() == target)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.BackToWork(); | this.BackToWork(); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 291 Lines • ▼ Show 20 Lines | for (var ent of cmpFormation.members) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!cmpUnitAI.CanAttack(targ)) | if (!cmpUnitAI.CanAttack(targ)) | |||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
if (this.order.data.targetClasses) | if (this.order.data.targetClasses) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var cmpIdentity = Engine.QueryInterface(targ, IID_Identity); | var cmpIdentity = Engine.QueryInterface(targ, IID_Identity); | |||||||||||||||||||||||||||||||||
var targetClasses = this.order.data.targetClasses; | var targetClasses = this.order.data.targetClasses; | |||||||||||||||||||||||||||||||||
if (targetClasses.attack && cmpIdentity | if (targetClasses.attack && cmpIdentity | |||||||||||||||||||||||||||||||||
&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) | && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (operator-linebreak) '&&' should be placed at the end of the line. Lint: ESLintBear (operator-linebreak): `'&&' should be placed at the end of the line.` | ||||||||||||||||||||||||||||||||||
Lint: JSHintBear Misleading line break before '&&'; readers may interpret this as an expression boundary. Lint: JSHintBear: `Misleading line break before '&&'; readers may interpret this as an expression boundary.` | ||||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
if (targetClasses.avoid && cmpIdentity | if (targetClasses.avoid && cmpIdentity | |||||||||||||||||||||||||||||||||
&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) | && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (operator-linebreak) '&&' should be placed at the end of the line. Lint: ESLintBear (operator-linebreak): `'&&' should be placed at the end of the line.` | ||||||||||||||||||||||||||||||||||
Lint: JSHintBear Misleading line break before '&&'; readers may interpret this as an expression boundary. Lint: JSHintBear: `Misleading line break before '&&'; readers may interpret this as an expression boundary.` | ||||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
// Only used by the AIs to prevent some choices of targets | // Only used by the AIs to prevent some choices of targets | |||||||||||||||||||||||||||||||||
if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ]) | if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ]) | |||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
this.PushOrderFront("Attack", { "target": targ, "force": false, "allowCapture": this.order.data.allowCapture }); | this.PushOrderFront("Attack", { "target": targ, "force": false, "allowCapture": this.order.data.allowCapture }); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
var targets = this.GetTargetsFromUnit(); | var targets = this.GetTargetsFromUnit(); | |||||||||||||||||||||||||||||||||
Lint: JSHintBear 'targets' is already defined. Lint: JSHintBear: `'targets' is already defined.` | ||||||||||||||||||||||||||||||||||
for (var targ of targets) | for (var targ of targets) | |||||||||||||||||||||||||||||||||
Lint: JSHintBear 'targ' is already defined. Lint: JSHintBear: `'targ' is already defined.` | ||||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!this.CanAttack(targ)) | if (!this.CanAttack(targ)) | |||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
if (this.order.data.targetClasses) | if (this.order.data.targetClasses) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var cmpIdentity = Engine.QueryInterface(targ, IID_Identity); | var cmpIdentity = Engine.QueryInterface(targ, IID_Identity); | |||||||||||||||||||||||||||||||||
Lint: JSHintBear 'cmpIdentity' is already defined. Lint: JSHintBear: `'cmpIdentity' is already defined.` | ||||||||||||||||||||||||||||||||||
var targetClasses = this.order.data.targetClasses; | var targetClasses = this.order.data.targetClasses; | |||||||||||||||||||||||||||||||||
Lint: JSHintBear 'targetClasses' is already defined. Lint: JSHintBear: `'targetClasses' is already defined.` | ||||||||||||||||||||||||||||||||||
if (cmpIdentity && targetClasses.attack | if (cmpIdentity && targetClasses.attack | |||||||||||||||||||||||||||||||||
&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) | && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (operator-linebreak) '&&' should be placed at the end of the line. Lint: ESLintBear (operator-linebreak): `'&&' should be placed at the end of the line.` | ||||||||||||||||||||||||||||||||||
Lint: JSHintBear Misleading line break before '&&'; readers may interpret this as an expression boundary. Lint: JSHintBear: `Misleading line break before '&&'; readers may interpret this as an expression boundary.` | ||||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
if (cmpIdentity && targetClasses.avoid | if (cmpIdentity && targetClasses.avoid | |||||||||||||||||||||||||||||||||
&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) | && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (operator-linebreak) '&&' should be placed at the end of the line. Lint: ESLintBear (operator-linebreak): `'&&' should be placed at the end of the line.` | ||||||||||||||||||||||||||||||||||
Lint: JSHintBear Misleading line break before '&&'; readers may interpret this as an expression boundary. Lint: JSHintBear: `Misleading line break before '&&'; readers may interpret this as an expression boundary.` | ||||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
// Only used by the AIs to prevent some choices of targets | // Only used by the AIs to prevent some choices of targets | |||||||||||||||||||||||||||||||||
if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ]) | if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ]) | |||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
this.PushOrderFront("Attack", { "target": targ, "force": false, "allowCapture": this.order.data.allowCapture }); | this.PushOrderFront("Attack", { "target": targ, "force": false, "allowCapture": this.order.data.allowCapture }); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | if (!orderData) | |||||||||||||||||||||||||||||||||
orderData = this.order.data; | orderData = this.order.data; | |||||||||||||||||||||||||||||||||
let cmpPosition = Engine.QueryInterface(orderData.target, IID_Position); | let cmpPosition = Engine.QueryInterface(orderData.target, IID_Position); | |||||||||||||||||||||||||||||||||
if (cmpPosition && cmpPosition.IsInWorld()) | if (cmpPosition && cmpPosition.IsInWorld()) | |||||||||||||||||||||||||||||||||
orderData.lastPos = cmpPosition.GetPosition(); | orderData.lastPos = cmpPosition.GetPosition(); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.SetHeldPosition = function(x, z) | UnitAI.prototype.SetHeldPosition = function(x, z) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.heldPosition = {"x": x, "z": z}; | this.heldPosition = {"x": x, "z": z}; | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required before '}'. Lint: ESLintBear (object-curly-spacing): `A space is required before '}'.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (object-curly-spacing) A space is required after '{'. Lint: ESLintBear (object-curly-spacing): `A space is required after '{'.` | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.SetHeldPositionOnEntity = function(entity) | UnitAI.prototype.SetHeldPositionOnEntity = function(entity) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | |||||||||||||||||||||||||||||||||
if (!cmpPosition || !cmpPosition.IsInWorld()) | if (!cmpPosition || !cmpPosition.IsInWorld()) | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
var pos = cmpPosition.GetPosition(); | var pos = cmpPosition.GetPosition(); | |||||||||||||||||||||||||||||||||
Show All 10 Lines | UnitAI.prototype.WalkToHeldPosition = function() | |||||||||||||||||||||||||||||||||
if (this.heldPosition) | if (this.heldPosition) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.AddOrder("Walk", { "x": this.heldPosition.x, "z": this.heldPosition.z, "force": false }, false); | this.AddOrder("Walk", { "x": this.heldPosition.x, "z": this.heldPosition.z, "force": false }, false); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
//// Helper functions //// | //// Helper functions //// | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* General getter for ranges. | * General getter for ranges. | |||||||||||||||||||||||||||||||||
* | * | |||||||||||||||||||||||||||||||||
* @param {number} iid | * @param {number} iid | |||||||||||||||||||||||||||||||||
* @param {string} type - [Optional] | * @param {string} type - [Optional] | |||||||||||||||||||||||||||||||||
* @return {Object | undefined} - The range in the form | * @return {Object | undefined} - The range in the form | |||||||||||||||||||||||||||||||||
* { "min": number, "max": number } | * { "min": number, "max": number } | |||||||||||||||||||||||||||||||||
* Object."elevationBonus": number may be present when iid == IID_Attack. | * Object."elevationBonus": number may be present when iid == IID_Attack. | |||||||||||||||||||||||||||||||||
* Returns undefined when the entity does not have the requested component. | * Returns undefined when the entity does not have the requested component. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.GetRange = function(iid, type) | UnitAI.prototype.GetRange = function(iid, type) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
let component = Engine.QueryInterface(this.entity, iid); | let component = Engine.QueryInterface(this.entity, iid); | |||||||||||||||||||||||||||||||||
if (!component) | if (!component) | |||||||||||||||||||||||||||||||||
return undefined; | return undefined; | |||||||||||||||||||||||||||||||||
return component.GetRange(type); | return component.GetRange(type); | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
Lint: JSHintBear Missing semicolon. Lint: JSHintBear: `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (semi) Missing semicolon. Lint: ESLintBear (semi): `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.CanAttack = function(target) | UnitAI.prototype.CanAttack = function(target) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
// Formation controllers should always respond to commands | // Formation controllers should always respond to commands | |||||||||||||||||||||||||||||||||
// (then the individual units can make up their own minds) | // (then the individual units can make up their own minds) | |||||||||||||||||||||||||||||||||
if (this.IsFormationController()) | if (this.IsFormationController()) | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.IsPacking = function() | 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 //// | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.IsAttackingAsFormation = function() | UnitAI.prototype.IsAttackingAsFormation = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | |||||||||||||||||||||||||||||||||
return cmpAttack && cmpAttack.CanAttackAsFormation() | return cmpAttack && cmpAttack.CanAttackAsFormation() | |||||||||||||||||||||||||||||||||
&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING"; | && this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING"; | |||||||||||||||||||||||||||||||||
Lint: JSHintBear Misleading line break before '&&'; readers may interpret this as an expression boundary. Lint: JSHintBear: `Misleading line break before '&&'; readers may interpret this as an expression boundary.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (operator-linebreak) '&&' should be placed at the end of the line. Lint: ESLintBear (operator-linebreak): `'&&' should be placed at the end of the line.` | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
//// Animal specific functions //// | //// Animal specific functions //// | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
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. | |||||||||||||||||||||||||||||||||
// And to avoid getting stuck in obstacles or narrow spaces, each side | // And to avoid getting stuck in obstacles or narrow spaces, each side | |||||||||||||||||||||||||||||||||
// of the polygon is obtained by trying to go away from a point situated | // of the polygon is obtained by trying to go away from a point situated | |||||||||||||||||||||||||||||||||
// half a meter backwards of the current position, after rotation. | // half a meter backwards of the current position, after rotation. | |||||||||||||||||||||||||||||||||
Show All 34 Lines | UnitAI.prototype.SetFacePointAfterMove = function(val) | |||||||||||||||||||||||||||||||||
if (cmpMotion) | if (cmpMotion) | |||||||||||||||||||||||||||||||||
cmpMotion.SetFacePointAfterMove(val); | cmpMotion.SetFacePointAfterMove(val); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.GetFacePointAfterMove = function() | UnitAI.prototype.GetFacePointAfterMove = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | |||||||||||||||||||||||||||||||||
return cmpUnitMotion && cmpUnitMotion.GetFacePointAfterMove(); | return cmpUnitMotion && cmpUnitMotion.GetFacePointAfterMove(); | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
Lint: JSHintBear Missing semicolon. Lint: JSHintBear: `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (semi) Missing semicolon. Lint: ESLintBear (semi): `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.AttackEntitiesByPreference = function(ents) | UnitAI.prototype.AttackEntitiesByPreference = function(ents) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!ents.length) | if (!ents.length) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | |||||||||||||||||||||||||||||||||
if (!cmpAttack) | if (!cmpAttack) | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 82 Lines • Show Last 20 Lines |
Seconds, minutes, ms?