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' a:help='Number of seconds to wait in between patrol waypoints.'>" + | ||||||||||||||||||||||||||||||||||
Freagarach: Seconds, minutes, ms? | ||||||||||||||||||||||||||||||||||
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. | ||||||||||||||||||||||||||||||||||
Not Done Inline ActionsAny specific reason to limit it to integers? Freagarach: Any specific reason to limit it to integers? | ||||||||||||||||||||||||||||||||||
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. | ||||||||||||||||||||||||||||||||||
"<data type='nonNegativeInteger'/>" + | ||||||||||||||||||||||||||||||||||
"</element>" + | ||||||||||||||||||||||||||||||||||
"<optional>" + | "<optional>" + | |||||||||||||||||||||||||||||||||
"<element name='CheeringTime'>" + | "<element name='CheeringTime'>" + | |||||||||||||||||||||||||||||||||
"<data type='nonNegativeInteger'/>" + | "<data type='nonNegativeInteger'/>" + | |||||||||||||||||||||||||||||||||
"</element>" + | "</element>" + | |||||||||||||||||||||||||||||||||
"</optional>" + | "</optional>" + | |||||||||||||||||||||||||||||||||
"<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)'>" + | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 111 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; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.notifyToCheerInRange = 30; | UnitAI.prototype.notifyToCheerInRange = 30; | |||||||||||||||||||||||||||||||||
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… | ||||||||||||||||||||||||||||||||||
// See ../helpers/FSM.js for some documentation of this FSM specification syntax | // See ../helpers/FSM.js for some documentation of this FSM specification syntax | |||||||||||||||||||||||||||||||||
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 | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | UnitAI.prototype.UnitFsmSpec = { | |||||||||||||||||||||||||||||||||
// Called when being told to walk as part of a formation | // Called when being told to walk as part of a formation | |||||||||||||||||||||||||||||||||
"Order.FormationWalk": function(msg) { | "Order.FormationWalk": function(msg) { | |||||||||||||||||||||||||||||||||
if (!this.AbleToMove()) | if (!this.AbleToMove()) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
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 | ||||||||||||||||||||||||||||||||||
if (this.CanPack()) | if (this.CanPack()) | |||||||||||||||||||||||||||||||||
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: ? | ||||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
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 82 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.` | ||||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
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 | |||||||||||||||||||||||||||||||||
this.SetNextState("INDIVIDUAL.WALKING"); | this.SetNextState("INDIVIDUAL.WALKING"); | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | "Order.Patrol": function(msg) { | |||||||||||||||||||||||||||||||||
if (this.CanPack()) | if (this.CanPack()) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
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) { | |||||||||||||||||||||||||||||||||
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 236 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 43 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 176 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() { | |||||||||||||||||||||||||||||||||
Done Inline ActionsLinter. Freagarach: Linter. | ||||||||||||||||||||||||||||||||||
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; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// Memorize the origin position in case that we want to go back. | // Memorize the origin position in case that we want to go back. | |||||||||||||||||||||||||||||||||
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"); | |||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"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); | ||||||||||||||||||||||||||||||||||
let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | |||||||||||||||||||||||||||||||||
cmpFormation.SetRearrange(true); | cmpFormation.SetRearrange(true); | |||||||||||||||||||||||||||||||||
cmpFormation.MoveMembersIntoFormation(true, true, "combat"); | cmpFormation.MoveMembersIntoFormation(true, true, "combat"); | |||||||||||||||||||||||||||||||||
this.StartTimer(0, 1000); | ||||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"Timer": function(msg) { | "leave": function() { | |||||||||||||||||||||||||||||||||
this.FindWalkAndFightTargets(); | this.StopMoving(); | |||||||||||||||||||||||||||||||||
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; | ||||||||||||||||||||||||||||||||||
// TODO: pick a proper animation | ||||||||||||||||||||||||||||||||||
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; | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
Not Done Inline Actions
? Freagarach: ? | ||||||||||||||||||||||||||||||||||
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… | ||||||||||||||||||||||||||||||||||
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… | ||||||||||||||||||||||||||||||||||
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": { | |||||||||||||||||||||||||||||||||
"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 555 Lines • ▼ Show 20 Lines | "WALKINGANDFIGHTING": { | |||||||||||||||||||||||||||||||||
// This avoids pathing for an unreachable goal and reduces lag considerably. | // 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() { | |||||||||||||||||||||||||||||||||
Done Inline ActionsLinter. Freagarach: Linter. | ||||||||||||||||||||||||||||||||||
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; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// Memorize the origin position in case that we want to go back. | // Memorize the origin position in case that we want to go back. | |||||||||||||||||||||||||||||||||
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"); | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"leave": function() { | "leave": function() { | |||||||||||||||||||||||||||||||||
this.StopMoving(); | ||||||||||||||||||||||||||||||||||
this.StopTimer(); | ||||||||||||||||||||||||||||||||||
delete this.patrolStartPosOrder; | delete this.patrolStartPosOrder; | |||||||||||||||||||||||||||||||||
this.SetDefaultAnimationVariant(); | 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; | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"leave": function() { | ||||||||||||||||||||||||||||||||||
this.StopMoving(); | ||||||||||||||||||||||||||||||||||
this.StopTimer(); | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"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; | ||||||||||||||||||||||||||||||||||
// TODO: pick a proper animation | ||||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"leave": function() { | ||||||||||||||||||||||||||||||||||
this.StopTimer(); | ||||||||||||||||||||||||||||||||||
delete this.stopSurveying; | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
"Timer": function(msg) { | ||||||||||||||||||||||||||||||||||
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`) | ||||||||||||||||||||||||||||||||||
Done Inline ActionsChanged to >= wraitii: Changed to >= | ||||||||||||||||||||||||||||||||||
if (this.stopSurveying >= +this.template.PatrolWaitTime) | ||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||
this.FinishOrder(); | ||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
this.FindWalkAndFightTargets(); | ||||||||||||||||||||||||||||||||||
Done Inline Actions
? Freagarach: ? | ||||||||||||||||||||||||||||||||||
++this.stopSurveying; | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"GUARD": { | "GUARD": { | |||||||||||||||||||||||||||||||||
"RemoveGuard": function() { | "RemoveGuard": function() { | |||||||||||||||||||||||||||||||||
this.StopMoving(); | this.StopMoving(); | |||||||||||||||||||||||||||||||||
this.FinishOrder(); | this.FinishOrder(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 362 Lines • ▼ Show 20 Lines | "COMBAT": { | |||||||||||||||||||||||||||||||||
this.SetNextState("FINDINGNEWTARGET"); | this.SetNextState("FINDINGNEWTARGET"); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
// 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 (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": { | |||||||||||||||||||||||||||||||||
"Order.Cheer": function() { | "Order.Cheer": function() { | |||||||||||||||||||||||||||||||||
if (!this.cheeringTime) | if (!this.cheeringTime) | |||||||||||||||||||||||||||||||||
return { "discardOrder": true }; | return { "discardOrder": true }; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 457 Lines • ▼ Show 20 Lines | "GATHER": { | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// 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. | |||||||||||||||||||||||||||||||||
// Only move if we are some distance away (TODO: pick the distance better?) | // Only move if we are some distance away (TODO: pick the distance better?) | |||||||||||||||||||||||||||||||||
if (!this.CheckPointRangeExplicit(initPos.x, initPos.z, 0, 10)) | if (!this.CheckPointRangeExplicit(initPos.x, initPos.z, 0, 10)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.GatherNearPosition(initPos.x, initPos.z, resourceType, resourceTemplate); | this.GatherNearPosition(initPos.x, initPos.z, resourceType, resourceTemplate); | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (indent) Expected indentation of 6 tabs but found 5. Lint: ESLintBear (indent): `Expected indentation of 6 tabs but found 5.` | ||||||||||||||||||||||||||||||||||
// Nothing else to gather - if we're carrying anything then we should | // Nothing else to gather - if we're carrying anything then we should | |||||||||||||||||||||||||||||||||
// drop it off, and if not then we might as well head to the dropsite | // drop it off, and if not then we might as well head to the dropsite | |||||||||||||||||||||||||||||||||
// anyway because that's a nice enough place to congregate and idle | // anyway because that's a nice enough place to congregate and idle | |||||||||||||||||||||||||||||||||
let nearestDropsite = this.FindNearestDropsite(resourceType.generic); | let nearestDropsite = this.FindNearestDropsite(resourceType.generic); | |||||||||||||||||||||||||||||||||
if (nearestDropsite) | if (nearestDropsite) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 795 Lines • ▼ Show 20 Lines | "CHEERING": { | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"leave": function() { | "leave": function() { | |||||||||||||||||||||||||||||||||
this.StopTimer(); | this.StopTimer(); | |||||||||||||||||||||||||||||||||
this.ResetAnimation(); | this.ResetAnimation(); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"LosRangeUpdate": function(msg) { | "LosRangeUpdate": function(msg) { | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (indent) Expected indentation of 2 tabs but found 7. Lint: ESLintBear (indent): `Expected indentation of 2 tabs but found 7.` | ||||||||||||||||||||||||||||||||||
if (msg && msg.data && msg.data.added && msg.data.added.length) | if (msg && msg.data && msg.data.added && msg.data.added.length) | |||||||||||||||||||||||||||||||||
this.RespondToSightedEntities(msg.data.added); | this.RespondToSightedEntities(msg.data.added); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
"LosAttackRangeUpdate": function(msg) { | "LosAttackRangeUpdate": function(msg) { | |||||||||||||||||||||||||||||||||
if (this.template.NaturalBehaviour == "violent" && msg && msg.data && msg.data.added && msg.data.added.length) | if (this.template.NaturalBehaviour == "violent" && msg && msg.data && msg.data.added && msg.data.added.length) | |||||||||||||||||||||||||||||||||
this.AttackVisibleEntity(msg.data.added); | this.AttackVisibleEntity(msg.data.added); | |||||||||||||||||||||||||||||||||
}, | }, | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | return (this.IsAnimal() && (this.template.NaturalBehaviour == "violent" || | |||||||||||||||||||||||||||||||||
this.template.NaturalBehaviour == "aggressive")); | this.template.NaturalBehaviour == "aggressive")); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.IsHealer = function() | UnitAI.prototype.IsHealer = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
return Engine.QueryInterface(this.entity, IID_Heal); | return Engine.QueryInterface(this.entity, IID_Heal); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.IsIdle = function() | UnitAI.prototype.IsIdle = function() | |||||||||||||||||||||||||||||||||
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.` | ||||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
return this.isIdle; | return this.isIdle; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.IsGarrisoned = function() | UnitAI.prototype.IsGarrisoned = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
return this.isGarrisoned; | return this.isGarrisoned; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | if (msg.to != INVALID_PLAYER && msg.from != INVALID_PLAYER) | |||||||||||||||||||||||||||||||||
if (cmpTrader) | if (cmpTrader) | |||||||||||||||||||||||||||||||||
cmpTrader.StopTrading(); | cmpTrader.StopTrading(); | |||||||||||||||||||||||||||||||||
this.SetStance(this.template.DefaultStance); | this.SetStance(this.template.DefaultStance); | |||||||||||||||||||||||||||||||||
if (this.IsTurret()) | if (this.IsTurret()) | |||||||||||||||||||||||||||||||||
this.SetTurretStance(); | this.SetTurretStance(); | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (comma-spacing) A space is required after ','. Lint: ESLintBear (comma-spacing): `A space is required after ','.` | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.OnDestroy = function() | UnitAI.prototype.OnDestroy = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
// Switch to an empty state to let states execute their leave handlers. | // Switch to an empty state to let states execute their leave handlers. | |||||||||||||||||||||||||||||||||
this.UnitFsm.SwitchToNextState(this, ""); | this.UnitFsm.SwitchToNextState(this, ""); | |||||||||||||||||||||||||||||||||
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); | let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); | |||||||||||||||||||||||||||||||||
if (this.losRangeQuery) | if (this.losRangeQuery) | |||||||||||||||||||||||||||||||||
cmpRangeManager.DestroyActiveQuery(this.losRangeQuery); | cmpRangeManager.DestroyActiveQuery(this.losRangeQuery); | |||||||||||||||||||||||||||||||||
Show All 37 Lines | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* Wrapper function that sets up the LOS, healer and attack range queries. | * Wrapper function that sets up the LOS, healer and attack range queries. | |||||||||||||||||||||||||||||||||
* This should be called whenever our ownership changes. | * This should be called whenever our ownership changes. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.SetupRangeQueries = function() | UnitAI.prototype.SetupRangeQueries = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
// Only skittish animals use this for now. | // Only skittish animals use this for now. | |||||||||||||||||||||||||||||||||
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 '{'.` | ||||||||||||||||||||||||||||||||||
if (this.template.NaturalBehaviour && this.template.NaturalBehaviour == "skittish") | if (this.template.NaturalBehaviour && this.template.NaturalBehaviour == "skittish") | |||||||||||||||||||||||||||||||||
this.SetupLOSRangeQuery(); | this.SetupLOSRangeQuery(); | |||||||||||||||||||||||||||||||||
if (this.IsHealer()) | if (this.IsHealer()) | |||||||||||||||||||||||||||||||||
this.SetupHealRangeQuery(); | this.SetupHealRangeQuery(); | |||||||||||||||||||||||||||||||||
if (Engine.QueryInterface(this.entity, IID_Attack)) | if (Engine.QueryInterface(this.entity, IID_Attack)) | |||||||||||||||||||||||||||||||||
this.SetupAttackRangeQuery(); | this.SetupAttackRangeQuery(); | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.DeferMessage = function(msg) | UnitAI.prototype.DeferMessage = function(msg) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.UnitFsm.DeferMessage(this, msg); | this.UnitFsm.DeferMessage(this, msg); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.GetCurrentState = function() | UnitAI.prototype.GetCurrentState = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
return this.UnitFsm.GetCurrentState(this); | return this.UnitFsm.GetCurrentState(this); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.FsmStateNameChanged = function(state) | UnitAI.prototype.FsmStateNameChanged = function(state) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
Engine.PostMessage(this.entity, MT_UnitAIStateChanged, { "to": state }); | Engine.PostMessage(this.entity, MT_UnitAIStateChanged, { "to": state }); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | UnitAI.prototype.PushOrderAfterForced = function(type, data) | |||||||||||||||||||||||||||||||||
Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* For a unit that is packing and trying to attack something, | * For a unit that is packing and trying to attack something, | |||||||||||||||||||||||||||||||||
* either cancel packing or continue with packing, as appropriate. | * either cancel packing or continue with packing, as appropriate. | |||||||||||||||||||||||||||||||||
* Precondition: if the unit is packing/unpacking, then orderQueue | * Precondition: if the unit is packing/unpacking, then orderQueue | |||||||||||||||||||||||||||||||||
* should have the Attack order at index 0, | * should have the Attack order at index 0, | |||||||||||||||||||||||||||||||||
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 '}'.` | ||||||||||||||||||||||||||||||||||
* and the Pack/Unpack order at index 1. | * and the Pack/Unpack order at index 1. | |||||||||||||||||||||||||||||||||
* This precondition holds because if we are packing while processing "Order.Attack", | * This precondition holds because if we are packing while processing "Order.Attack", | |||||||||||||||||||||||||||||||||
* then we must have come from ReplaceOrder, which guarantees it. | * then we must have come from ReplaceOrder, which guarantees it. | |||||||||||||||||||||||||||||||||
* | * | |||||||||||||||||||||||||||||||||
* @param {boolean} requirePacked - true if the unit needs to be packed to continue attacking, | * @param {boolean} requirePacked - true if the unit needs to be packed to continue attacking, | |||||||||||||||||||||||||||||||||
* false if it needs to be unpacked. | * false if it needs to be unpacked. | |||||||||||||||||||||||||||||||||
* @return {boolean} true if the unit can attack now, false if it must continue packing (or unpacking) first. | * @return {boolean} true if the unit can attack now, false if it must continue packing (or unpacking) first. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | UnitAI.prototype.UpdateWorkOrders = function(type) | |||||||||||||||||||||||||||||||||
if (this.workOrders.length) | if (this.workOrders.length) | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
if (this.IsFormationMember()) | if (this.IsFormationMember()) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
var cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); | var cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); | |||||||||||||||||||||||||||||||||
if (cmpUnitAI) | if (cmpUnitAI) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-shadow) 'type' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'type' is already declared in the upper scope.` | ||||||||||||||||||||||||||||||||||
for (var i = 0; i < cmpUnitAI.orderQueue.length; ++i) | for (var i = 0; i < cmpUnitAI.orderQueue.length; ++i) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (isWorkType(cmpUnitAI.orderQueue[i].type)) | if (isWorkType(cmpUnitAI.orderQueue[i].type)) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.workOrders = cmpUnitAI.orderQueue.slice(i); | this.workOrders = cmpUnitAI.orderQueue.slice(i); | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
Show All 10 Lines | for (var i = 0; i < this.orderQueue.length; ++i) | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.BackToWork = function() | UnitAI.prototype.BackToWork = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (this.workOrders.length == 0) | if (this.workOrders.length == 0) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
Lint: JSHintBear 'i' is already defined. Lint: JSHintBear: `'i' is already defined.` | ||||||||||||||||||||||||||||||||||
if (this.IsGarrisoned()) | if (this.IsGarrisoned()) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
let cmpGarrisonHolder = Engine.QueryInterface(this.GetGarrisonHolder(), IID_GarrisonHolder); | let cmpGarrisonHolder = Engine.QueryInterface(this.GetGarrisonHolder(), IID_GarrisonHolder); | |||||||||||||||||||||||||||||||||
if (!cmpGarrisonHolder || !cmpGarrisonHolder.PerformEject([this.entity], false)) | if (!cmpGarrisonHolder || !cmpGarrisonHolder.PerformEject([this.entity], false)) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
this.orderQueue = []; | this.orderQueue = []; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
* 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) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (this.timer) | if (this.timer) | |||||||||||||||||||||||||||||||||
error("Called StartTimer when there's already an active timer"); | error("Called StartTimer when there's already an active timer"); | |||||||||||||||||||||||||||||||||
var data = { "timerRepeat": repeat }; | var data = { "timerRepeat": repeat }; | |||||||||||||||||||||||||||||||||
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 '}'.` | ||||||||||||||||||||||||||||||||||
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | |||||||||||||||||||||||||||||||||
if (repeat === undefined) | if (repeat === undefined) | |||||||||||||||||||||||||||||||||
this.timer = cmpTimer.SetTimeout(this.entity, IID_UnitAI, "TimerHandler", offset, data); | this.timer = cmpTimer.SetTimeout(this.entity, IID_UnitAI, "TimerHandler", offset, data); | |||||||||||||||||||||||||||||||||
else | else | |||||||||||||||||||||||||||||||||
this.timer = cmpTimer.SetInterval(this.entity, IID_UnitAI, "TimerHandler", offset, repeat, data); | this.timer = cmpTimer.SetInterval(this.entity, IID_UnitAI, "TimerHandler", offset, repeat, data); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
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}); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.OnRangeUpdate = function(msg) | UnitAI.prototype.OnRangeUpdate = function(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 '}'.` | ||||||||||||||||||||||||||||||||||
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) | |||||||||||||||||||||||||||||||||
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 '{'.` | ||||||||||||||||||||||||||||||||||
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) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
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 '}'.` | ||||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed}); | this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed}); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
//// Helper functions to be called by the FSM //// | //// Helper functions to be called by the FSM //// | |||||||||||||||||||||||||||||||||
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(); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.GetRunMultiplier = function() | UnitAI.prototype.GetRunMultiplier = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
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 '{'.` | ||||||||||||||||||||||||||||||||||
var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | |||||||||||||||||||||||||||||||||
if (!cmpUnitMotion) | if (!cmpUnitMotion) | |||||||||||||||||||||||||||||||||
return 0; | return 0; | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
return cmpUnitMotion.GetRunMultiplier(); | return cmpUnitMotion.GetRunMultiplier(); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* Returns true if the target exists and has non-zero hitpoints. | * Returns true if the target exists and has non-zero hitpoints. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.TargetIsAlive = function(ent) | UnitAI.prototype.TargetIsAlive = function(ent) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 681 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 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) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-shadow) 'target' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'target' is already declared in the upper scope.` | ||||||||||||||||||||||||||||||||||
var target = ents.find(target => | var target = ents.find(target => | |||||||||||||||||||||||||||||||||
this.CanAttack(target) | this.CanAttack(target) | |||||||||||||||||||||||||||||||||
&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true)) | && this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true)) | |||||||||||||||||||||||||||||||||
&& (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target)) | && (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target)) | |||||||||||||||||||||||||||||||||
); | ); | |||||||||||||||||||||||||||||||||
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 respond appropriately given our current stance, | * Try to respond appropriately given our current stance, | |||||||||||||||||||||||||||||||||
* given a list of entities that match our stance's target criteria. | * given a list of entities that match our stance's target criteria. | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-shadow) 'target' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'target' is already declared in the upper scope.` | ||||||||||||||||||||||||||||||||||
* Returns true if it responded. | * Returns true if it responded. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
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.` | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.RespondToTargetedEntities = function(ents) | UnitAI.prototype.RespondToTargetedEntities = function(ents) | |||||||||||||||||||||||||||||||||
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 (!ents.length) | if (!ents.length) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
if (this.GetStance().respondChase) | if (this.GetStance().respondChase) | |||||||||||||||||||||||||||||||||
return this.AttackVisibleEntity(ents); | return this.AttackVisibleEntity(ents); | |||||||||||||||||||||||||||||||||
if (this.GetStance().respondStandGround) | if (this.GetStance().respondStandGround) | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* 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) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!this.CheckTargetVisible(target)) | if (!this.CheckTargetVisible(target)) | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-shadow) 'ent' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'ent' is already declared in the upper scope.` | ||||||||||||||||||||||||||||||||||
// 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) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
Show All 9 Lines | if (!this.CheckTargetDistanceFromHeldPosition(target, iid, type)) | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
// Stop if it's left our vision range, unless we're especially persistent. | // Stop if it's left our vision range, unless we're especially persistent. | |||||||||||||||||||||||||||||||||
if (!this.GetStance().respondChaseBeyondVision) | if (!this.GetStance().respondChaseBeyondVision) | |||||||||||||||||||||||||||||||||
if (!this.CheckTargetIsInVisionRange(target)) | if (!this.CheckTargetIsInVisionRange(target)) | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-shadow) 'type' is already declared in the upper scope. Lint: ESLintBear (no-shadow): `'type' is already declared in the upper scope.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (indent) Expected indentation of 3 tabs but found 4. Lint: ESLintBear (indent): `Expected indentation of 3 tabs but found 4.` | ||||||||||||||||||||||||||||||||||
/* | /* | |||||||||||||||||||||||||||||||||
* Returns whether we should chase the targeted entity, | * Returns whether we should chase the targeted entity, | |||||||||||||||||||||||||||||||||
* given our current stance. | * given our current stance. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.ShouldChaseTargetedEntity = function(target, force) | UnitAI.prototype.ShouldChaseTargetedEntity = function(target, force) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!this.AbleToMove()) | if (!this.AbleToMove()) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
Show All 13 Lines | UnitAI.prototype.ShouldChaseTargetedEntity = function(target, force) | |||||||||||||||||||||||||||||||||
return force; | return force; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
//// External interface functions //// | //// External interface functions //// | |||||||||||||||||||||||||||||||||
UnitAI.prototype.SetFormationController = function(ent) | UnitAI.prototype.SetFormationController = function(ent) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
this.formationController = ent; | this.formationController = ent; | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-multi-spaces) Multiple spaces found before 'Engine'. Lint: ESLintBear (no-multi-spaces): `Multiple spaces found before 'Engine'.` | ||||||||||||||||||||||||||||||||||
// 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); | |||||||||||||||||||||||||||||||||
if (cmpObstruction) | if (cmpObstruction) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (ent == INVALID_ENTITY) | if (ent == INVALID_ENTITY) | |||||||||||||||||||||||||||||||||
cmpObstruction.SetControlGroup(this.entity); | cmpObstruction.SetControlGroup(this.entity); | |||||||||||||||||||||||||||||||||
else | else | |||||||||||||||||||||||||||||||||
cmpObstruction.SetControlGroup(ent); | cmpObstruction.SetControlGroup(ent); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
// If we were removed from a formation, let the FSM switch back to INDIVIDUAL | // If we were removed from a formation, let the FSM switch back to INDIVIDUAL | |||||||||||||||||||||||||||||||||
if (ent == INVALID_ENTITY) | if (ent == INVALID_ENTITY) | |||||||||||||||||||||||||||||||||
this.UnitFsm.ProcessMessage(this, { "type": "FormationLeave" }); | this.UnitFsm.ProcessMessage(this, { "type": "FormationLeave" }); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.GetFormationController = function() | UnitAI.prototype.GetFormationController = function() | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
/** | /** | |||||||||||||||||||||||||||||||||
* @return {boolean} - Whether it makes sense to guard the given entity. | * @return {boolean} - Whether it makes sense to guard the given entity. | |||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
UnitAI.prototype.ShouldGuard = function(target) | UnitAI.prototype.ShouldGuard = function(target) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
return this.TargetIsAlive(target) || | return this.TargetIsAlive(target) || | |||||||||||||||||||||||||||||||||
Engine.QueryInterface(target, IID_Capturable) || | Engine.QueryInterface(target, IID_Capturable) || | |||||||||||||||||||||||||||||||||
Engine.QueryInterface(target, IID_StatusEffectsReceiver); | Engine.QueryInterface(target, IID_StatusEffectsReceiver); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (no-else-return) Unnecessary 'else' after 'return'. Lint: ESLintBear (no-else-return): `Unnecessary 'else' after 'return'.` | ||||||||||||||||||||||||||||||||||
UnitAI.prototype.AddGuard = function(target) | UnitAI.prototype.AddGuard = function(target) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!this.CanGuard()) | if (!this.CanGuard()) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
var cmpGuard = Engine.QueryInterface(target, IID_Guard); | var cmpGuard = Engine.QueryInterface(target, IID_Guard); | |||||||||||||||||||||||||||||||||
if (!cmpGuard) | if (!cmpGuard) | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 311 Lines • ▼ Show 20 Lines | ||||||||||||||||||||||||||||||||||
*/ | */ | |||||||||||||||||||||||||||||||||
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; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (semi) Missing semicolon. Lint: ESLintBear (semi): `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
Lint: JSHintBear Missing semicolon. Lint: JSHintBear: `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
// 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() && | |||||||||||||||||||||||||||||||||
(cmpTrader.GetFirstMarket() == target && cmpTrader.GetSecondMarket() == source || | (cmpTrader.GetFirstMarket() == target && cmpTrader.GetSecondMarket() == source || | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 307 Lines • ▼ Show 20 Lines | for (var ent of cmpFormation.members) | |||||||||||||||||||||||||||||||||
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; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
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.` | ||||||||||||||||||||||||||||||||||
var targets = this.GetTargetsFromUnit(); | var targets = this.GetTargetsFromUnit(); | |||||||||||||||||||||||||||||||||
for (var targ of targets) | for (var targ of targets) | |||||||||||||||||||||||||||||||||
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 (!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); | |||||||||||||||||||||||||||||||||
var targetClasses = this.order.data.targetClasses; | var targetClasses = this.order.data.targetClasses; | |||||||||||||||||||||||||||||||||
if (cmpIdentity && targetClasses.attack | if (cmpIdentity && targetClasses.attack | |||||||||||||||||||||||||||||||||
&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) | && !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack)) | |||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
if (cmpIdentity && targetClasses.avoid | if (cmpIdentity && targetClasses.avoid | |||||||||||||||||||||||||||||||||
&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) | && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid)) | |||||||||||||||||||||||||||||||||
continue; | continue; | |||||||||||||||||||||||||||||||||
Lint: JSHintBear 'targets' is already defined. Lint: JSHintBear: `'targets' is already defined.` | ||||||||||||||||||||||||||||||||||
// Only used by the AIs to prevent some choices of targets | // Only used by the AIs to prevent some choices of targets | |||||||||||||||||||||||||||||||||
Lint: JSHintBear 'targ' is already defined. Lint: JSHintBear: `'targ' is already defined.` | ||||||||||||||||||||||||||||||||||
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; | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
Lint: JSHintBear 'cmpIdentity' is already defined. Lint: JSHintBear: `'cmpIdentity' is already defined.` | ||||||||||||||||||||||||||||||||||
Lint: JSHintBear 'targetClasses' is already defined. Lint: JSHintBear: `'targetClasses' is already defined.` | ||||||||||||||||||||||||||||||||||
// healers on a walk-and-fight order should heal injured units | // healers on a walk-and-fight order should heal injured units | |||||||||||||||||||||||||||||||||
if (this.IsHealer()) | if (this.IsHealer()) | |||||||||||||||||||||||||||||||||
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.` | ||||||||||||||||||||||||||||||||||
return this.FindNewHealTargets(); | return this.FindNewHealTargets(); | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
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.` | ||||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.GetTargetsFromUnit = function() | UnitAI.prototype.GetTargetsFromUnit = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
if (!this.losAttackRangeQuery) | if (!this.losAttackRangeQuery) | |||||||||||||||||||||||||||||||||
return []; | return []; | |||||||||||||||||||||||||||||||||
if (!this.GetStance().targetVisibleEnemies) | if (!this.GetStance().targetVisibleEnemies) | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | UnitAI.prototype.SetHeldPositionOnEntity = function(entity) | |||||||||||||||||||||||||||||||||
if (!cmpPosition || !cmpPosition.IsInWorld()) | if (!cmpPosition || !cmpPosition.IsInWorld()) | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
var pos = cmpPosition.GetPosition(); | var pos = cmpPosition.GetPosition(); | |||||||||||||||||||||||||||||||||
this.SetHeldPosition(pos.x, pos.z); | this.SetHeldPosition(pos.x, pos.z); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.GetHeldPosition = function() | UnitAI.prototype.GetHeldPosition = function() | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
return this.heldPosition; | return this.heldPosition; | |||||||||||||||||||||||||||||||||
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.WalkToHeldPosition = function() | 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; | |||||||||||||||||||||||||||||||||
Show All 10 Lines | ||||||||||||||||||||||||||||||||||
* @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); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
if (!component) | if (!component) | |||||||||||||||||||||||||||||||||
return undefined; | return undefined; | |||||||||||||||||||||||||||||||||
return component.GetRange(type); | return component.GetRange(type); | |||||||||||||||||||||||||||||||||
} | } | |||||||||||||||||||||||||||||||||
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; | |||||||||||||||||||||||||||||||||
let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | |||||||||||||||||||||||||||||||||
return cmpAttack && cmpAttack.CanAttack(target); | return cmpAttack && cmpAttack.CanAttack(target); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
UnitAI.prototype.CanGarrison = function(target) | UnitAI.prototype.CanGarrison = function(target) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
Lint: JSHintBear Missing semicolon. Lint: JSHintBear: `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (semi) Missing semicolon. Lint: ESLintBear (semi): `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
// 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; | |||||||||||||||||||||||||||||||||
let cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | let cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | |||||||||||||||||||||||||||||||||
if (!cmpGarrisonHolder) | if (!cmpGarrisonHolder) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | return cmpAttack && cmpAttack.CanAttackAsFormation() | |||||||||||||||||||||||||||||||||
&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING"; | && this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING"; | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
//// Animal specific functions //// | //// Animal specific functions //// | |||||||||||||||||||||||||||||||||
UnitAI.prototype.MoveRandomly = function(distance) | UnitAI.prototype.MoveRandomly = function(distance) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
// To minimize drift all across the map, animals describe circles | // To minimize drift all across the map, animals describe circles | |||||||||||||||||||||||||||||||||
// approximated by polygons. | // approximated by polygons. | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
// 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. | |||||||||||||||||||||||||||||||||
// We also add a fluctuation on the length of each side of the polygon (dist) | // We also add a fluctuation on the length of each side of the polygon (dist) | |||||||||||||||||||||||||||||||||
// which, in addition to making the move more random, helps escaping narrow spaces | // which, in addition to making the move more random, helps escaping narrow spaces | |||||||||||||||||||||||||||||||||
// with bigger values of dist. | // with bigger values of dist. | |||||||||||||||||||||||||||||||||
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.` | ||||||||||||||||||||||||||||||||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | |||||||||||||||||||||||||||||||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | |||||||||||||||||||||||||||||||||
Lint: ESLintBear (spaced-comment) Expected space or tab after '//' in comment. Lint: ESLintBear (spaced-comment): `Expected space or tab after '//' in comment.` | ||||||||||||||||||||||||||||||||||
if (!cmpPosition || !cmpPosition.IsInWorld() || !cmpUnitMotion) | if (!cmpPosition || !cmpPosition.IsInWorld() || !cmpUnitMotion) | |||||||||||||||||||||||||||||||||
return; | return; | |||||||||||||||||||||||||||||||||
let pos = cmpPosition.GetPosition(); | let pos = cmpPosition.GetPosition(); | |||||||||||||||||||||||||||||||||
let ang = cmpPosition.GetRotation().y; | let ang = cmpPosition.GetRotation().y; | |||||||||||||||||||||||||||||||||
if (!this.roamAngle) | if (!this.roamAngle) | |||||||||||||||||||||||||||||||||
{ | { | |||||||||||||||||||||||||||||||||
Show All 34 Lines | UnitAI.prototype.AttackEntitiesByPreference = function(ents) | |||||||||||||||||||||||||||||||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | |||||||||||||||||||||||||||||||||
if (!cmpAttack) | if (!cmpAttack) | |||||||||||||||||||||||||||||||||
return false; | return false; | |||||||||||||||||||||||||||||||||
var attackfilter = function(e) { | var attackfilter = function(e) { | |||||||||||||||||||||||||||||||||
var cmpOwnership = Engine.QueryInterface(e, IID_Ownership); | var cmpOwnership = Engine.QueryInterface(e, IID_Ownership); | |||||||||||||||||||||||||||||||||
if (cmpOwnership && cmpOwnership.GetOwner() > 0) | if (cmpOwnership && cmpOwnership.GetOwner() > 0) | |||||||||||||||||||||||||||||||||
return true; | return true; | |||||||||||||||||||||||||||||||||
Lint: JSHintBear Missing semicolon. Lint: JSHintBear: `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
Lint: ESLintBear (semi) Missing semicolon. Lint: ESLintBear (semi): `Missing semicolon.` | ||||||||||||||||||||||||||||||||||
var cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI); | var cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI); | |||||||||||||||||||||||||||||||||
return cmpUnitAI && (!cmpUnitAI.IsAnimal() || cmpUnitAI.IsDangerousAnimal()); | return cmpUnitAI && (!cmpUnitAI.IsAnimal() || cmpUnitAI.IsDangerousAnimal()); | |||||||||||||||||||||||||||||||||
}; | }; | |||||||||||||||||||||||||||||||||
let entsByPreferences = {}; | let entsByPreferences = {}; | |||||||||||||||||||||||||||||||||
let preferences = []; | let preferences = []; | |||||||||||||||||||||||||||||||||
let entsWithoutPref = []; | let entsWithoutPref = []; | |||||||||||||||||||||||||||||||||
for (let ent of ents) | for (let ent of ents) | |||||||||||||||||||||||||||||||||
▲ Show 20 Lines • Show All 88 Lines • Show Last 20 Lines |
Seconds, minutes, ms?