Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 874 Lines • ▼ Show 20 Lines | "FORMATIONCONTROLLER": { | ||||
"Order.Unpack": function(msg) { | "Order.Unpack": function(msg) { | ||||
this.CallMemberFunction("Unpack", [false]); | this.CallMemberFunction("Unpack", [false]); | ||||
this.SetNextState("MEMBER"); | this.SetNextState("MEMBER"); | ||||
}, | }, | ||||
"IDLE": { | "IDLE": { | ||||
"enter": function(msg) { | "enter": function(msg) { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
cmpFormation.SetRearrange(false); | cmpFormation.SetRearrange(false); | ||||
return false; | |||||
}, | }, | ||||
"MoveStarted": function() { | "MoveStarted": function() { | ||||
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); | cmpFormation.MoveMembersIntoFormation(true, true); | ||||
} | } | ||||
}, | }, | ||||
"WALKING": { | "WALKING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MoveStarted": function(msg) { | "MoveStarted": function(msg) { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
Show All 10 Lines | "FORMATIONCONTROLLER": { | ||||
"WALKINGANDFIGHTING": { | "WALKINGANDFIGHTING": { | ||||
"enter": function(msg) { | "enter": function(msg) { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.StartTimer(0, 1000); | this.StartTimer(0, 1000); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
// check if there are no enemies to attack | // check if there are no enemies to attack | ||||
Show All 18 Lines | "FORMATIONCONTROLLER": { | ||||
"PATROL": { | "PATROL": { | ||||
"enter": function(msg) { | "enter": function(msg) { | ||||
// 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; | 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; | ||||
} | } | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.StartTimer(0, 1000); | this.StartTimer(0, 1000); | ||||
return false; | |||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
// Check if there are no enemies to attack | // Check if there are no enemies to attack | ||||
this.FindWalkAndFightTargets(); | this.FindWalkAndFightTargets(); | ||||
}, | }, | ||||
"leave": function(msg) { | "leave": function(msg) { | ||||
Show All 25 Lines | "PATROL": { | ||||
this.PushOrder(this.order.type, this.order.data); | this.PushOrder(this.order.type, this.order.data); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
"GARRISON":{ | "GARRISON":{ | ||||
"enter": function() { | "enter": function() { | ||||
// If the garrisonholder should pickup, warn it so it can take needed action | // If the garrisonholder should pickup, warn it so it can take needed action | ||||
var cmpGarrisonHolder = Engine.QueryInterface(this.order.data.target, IID_GarrisonHolder); | let cmpGarrisonHolder = Engine.QueryInterface(this.order.data.target, IID_GarrisonHolder); | ||||
if (cmpGarrisonHolder && cmpGarrisonHolder.CanPickup(this.entity)) | if (cmpGarrisonHolder && cmpGarrisonHolder.CanPickup(this.entity)) | ||||
{ | { | ||||
this.pickup = this.order.data.target; // temporary, deleted in "leave" | this.pickup = this.order.data.target; // temporary, deleted in "leave" | ||||
Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); | ||||
} | } | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
// If a pickup has been requested and not yet canceled, cancel it | // If a pickup has been requested and not yet canceled, cancel it | ||||
if (this.pickup) | if (this.pickup) | ||||
{ | { | ||||
Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | ||||
delete this.pickup; | delete this.pickup; | ||||
} | } | ||||
}, | }, | ||||
"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; | ||||
} | } | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MoveStarted": function(msg) { | "MoveStarted": function(msg) { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
Show All 11 Lines | "GARRISON":{ | ||||
// If a pickup has been requested, cancel it as it will be requested by members | // If a pickup has been requested, cancel it as it will be requested by members | ||||
if (this.pickup) | if (this.pickup) | ||||
{ | { | ||||
Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | ||||
delete this.pickup; | delete this.pickup; | ||||
} | } | ||||
this.CallMemberFunction("Garrison", [this.order.data.target, false]); | this.CallMemberFunction("Garrison", [this.order.data.target, false]); | ||||
this.SetNextState("MEMBER"); | this.SetNextState("MEMBER"); | ||||
return true; | |||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
"FORMING": { | "FORMING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MoveStarted": function(msg) { | "MoveStarted": function(msg) { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
Show All 17 Lines | "FORMATIONCONTROLLER": { | ||||
"COMBAT": { | "COMBAT": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MoveStarted": function(msg) { | "MoveStarted": function(msg) { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
Show All 9 Lines | "COMBAT": { | ||||
else | else | ||||
this.SetNextState("MEMBER"); | this.SetNextState("MEMBER"); | ||||
}, | }, | ||||
}, | }, | ||||
"ATTACKING": { | "ATTACKING": { | ||||
// Wait for individual members to finish | // Wait for individual members to finish | ||||
"enter": function(msg) { | "enter": function(msg) { | ||||
var target = this.order.data.target; | let target = this.order.data.target; | ||||
var allowCapture = this.order.data.allowCapture; | let allowCapture = this.order.data.allowCapture; | ||||
// Check if we are already in range, otherwise walk there | // Check if we are already in range, otherwise walk there | ||||
if (!this.CheckTargetAttackRange(target, target)) | if (!this.CheckTargetAttackRange(target, target)) | ||||
{ | { | ||||
if (this.TargetIsAlive(target) && this.CheckTargetVisible(target)) | if (this.TargetIsAlive(target) && this.CheckTargetVisible(target)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": allowCapture }); | this.PushOrderFront("Attack", { "target": target, "force": false, "allowCapture": allowCapture }); | ||||
return true; | return true; | ||||
} | } | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
// TODO fix the rearranging while attacking as formation | // TODO fix the rearranging while attacking as formation | ||||
cmpFormation.SetRearrange(!this.IsAttackingAsFormation()); | cmpFormation.SetRearrange(!this.IsAttackingAsFormation()); | ||||
cmpFormation.MoveMembersIntoFormation(false, false); | cmpFormation.MoveMembersIntoFormation(false, false); | ||||
this.StartTimer(200, 200); | this.StartTimer(200, 200); | ||||
return false; | return false; | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
Show All 20 Lines | "COMBAT": { | ||||
cmpFormation.SetRearrange(true); | cmpFormation.SetRearrange(true); | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
"MEMBER": { | "MEMBER": { | ||||
// Wait for individual members to finish | // Wait for individual members to finish | ||||
"enter": function(msg) { | "enter": function(msg) { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
cmpFormation.SetRearrange(false); | cmpFormation.SetRearrange(false); | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.StartTimer(1000, 1000); | this.StartTimer(1000, 1000); | ||||
return false; | |||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
// Have all members finished the task? | // Have all members finished the task? | ||||
if (!this.TestAllMemberFunction("HasFinishedOrder", [])) | if (!this.TestAllMemberFunction("HasFinishedOrder", [])) | ||||
return; | return; | ||||
this.CallMemberFunction("ResetFinishOrder", []); | this.CallMemberFunction("ResetFinishOrder", []); | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | "IDLE": { | ||||
else | else | ||||
this.SetNextState("INDIVIDUAL.IDLE"); | this.SetNextState("INDIVIDUAL.IDLE"); | ||||
return true; | return true; | ||||
}, | }, | ||||
}, | }, | ||||
"WALKING": { | "WALKING": { | ||||
"enter": function() { | "enter": function() { | ||||
var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | ||||
cmpUnitMotion.MoveToFormationOffset(this.order.data.target, this.order.data.x, this.order.data.z); | cmpUnitMotion.MoveToFormationOffset(this.order.data.target, this.order.data.x, this.order.data.z); | ||||
var cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | ||||
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); | let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); | ||||
if (cmpFormation && cmpVisual) | if (cmpFormation && cmpVisual) | ||||
{ | { | ||||
cmpVisual.ReplaceMoveAnimation("walk", cmpFormation.GetFormationAnimation(this.entity, "walk")); | cmpVisual.ReplaceMoveAnimation("walk", cmpFormation.GetFormationAnimation(this.entity, "walk")); | ||||
cmpVisual.ReplaceMoveAnimation("run", cmpFormation.GetFormationAnimation(this.entity, "run")); | cmpVisual.ReplaceMoveAnimation("run", cmpFormation.GetFormationAnimation(this.entity, "run")); | ||||
} | } | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
// Occurs when the unit has reached its destination and the controller | // Occurs when the unit has reached its destination and the controller | ||||
// is done moving. The controller is notified. | // is done moving. The controller is notified. | ||||
"MoveCompleted": function(msg) { | "MoveCompleted": function(msg) { | ||||
// We can only finish this order if the move was really completed. | // We can only finish this order if the move was really completed. | ||||
if (!msg.data.error && this.FinishOrder()) | if (!msg.data.error && this.FinishOrder()) | ||||
return; | return; | ||||
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); | var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); | ||||
if (cmpVisual) | if (cmpVisual) | ||||
{ | { | ||||
cmpVisual.ResetMoveAnimation("walk"); | cmpVisual.ResetMoveAnimation("walk"); | ||||
cmpVisual.ResetMoveAnimation("run"); | cmpVisual.ResetMoveAnimation("run"); | ||||
} | } | ||||
var cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | ||||
if (cmpFormation) | if (cmpFormation) | ||||
cmpFormation.SetInPosition(this.entity); | cmpFormation.SetInPosition(this.entity); | ||||
}, | }, | ||||
}, | }, | ||||
// Special case used by Order.LeaveFoundation | // Special case used by Order.LeaveFoundation | ||||
"WALKINGTOPOINT": { | "WALKINGTOPOINT": { | ||||
"enter": function() { | "enter": function() { | ||||
var cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | ||||
if (cmpFormation) | if (cmpFormation) | ||||
cmpFormation.UnsetInPosition(this.entity); | cmpFormation.UnsetInPosition(this.entity); | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
// States for entities not part of a formation: | // States for entities not part of a formation: | ||||
"INDIVIDUAL": { | "INDIVIDUAL": { | ||||
"enter": function() { | "enter": function() { | ||||
// Sanity-checking | // Sanity-checking | ||||
if (this.IsAnimal()) | if (this.IsAnimal()) | ||||
error("Animal got moved into INDIVIDUAL.* state"); | error("Animal got moved into INDIVIDUAL.* state"); | ||||
return false; | |||||
}, | }, | ||||
"Attacked": function(msg) { | "Attacked": function(msg) { | ||||
// Respond to attack if we always target attackers or during unforced orders | // Respond to attack if we always target attackers or during unforced orders | ||||
if (this.GetStance().targetAttackersAlways || !this.order || !this.order.data || !this.order.data.force) | if (this.GetStance().targetAttackersAlways || !this.order || !this.order.data || !this.order.data.force) | ||||
this.RespondToTargetedEntities([msg.data.attacker]); | this.RespondToTargetedEntities([msg.data.attacker]); | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | "GuardedAttacked": function(msg) { | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"IDLE": { | "IDLE": { | ||||
"enter": function() { | "enter": function() { | ||||
// Switch back to idle animation to guarantee we won't | // Switch back to idle animation to guarantee we won't | ||||
// get stuck with an incorrect animation | // get stuck with an incorrect animation | ||||
var animationName = "idle"; | let animationName = "idle"; | ||||
if (this.IsFormationMember()) | if (this.IsFormationMember()) | ||||
{ | { | ||||
var cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | ||||
if (cmpFormation) | if (cmpFormation) | ||||
animationName = cmpFormation.GetFormationAnimation(this.entity, animationName); | animationName = cmpFormation.GetFormationAnimation(this.entity, animationName); | ||||
} | } | ||||
this.SelectAnimation(animationName); | this.SelectAnimation(animationName); | ||||
// If we have some orders, it is because we are in an intermediary state | // If we have some orders, it is because we are in an intermediary state | ||||
// from FinishOrder (SetNextState("IDLE") is only executed when we get | // from FinishOrder (SetNextState("IDLE") is only executed when we get | ||||
// a ProcessMessage), and thus we should not start another order which could | // a ProcessMessage), and thus we should not start another order which could | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | "INDIVIDUAL": { | ||||
"WALKING": { | "WALKING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
"leave": function () { | "leave": function () { | ||||
this.SelectAnimation("idle"); | this.SelectAnimation("idle"); | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
"WALKINGANDFIGHTING": { | "WALKINGANDFIGHTING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
// Show weapons rather than carried resources. | // Show weapons rather than carried resources. | ||||
this.SetAnimationVariant("combat"); | this.SetAnimationVariant("combat"); | ||||
this.StartTimer(0, 1000); | this.StartTimer(0, 1000); | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
this.FindWalkAndFightTargets(); | this.FindWalkAndFightTargets(); | ||||
}, | }, | ||||
"leave": function(msg) { | "leave": function(msg) { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
Show All 22 Lines | "PATROL": { | ||||
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.StartTimer(0, 1000); | ||||
this.SetAnimationVariant("combat"); | this.SetAnimationVariant("combat"); | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.StopTimer(); | this.StopTimer(); | ||||
delete this.patrolStartPosOrder; | delete this.patrolStartPosOrder; | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | "FLEEING": { | ||||
return true; | return true; | ||||
} | } | ||||
this.PlaySound("panic"); | this.PlaySound("panic"); | ||||
// Run quickly | // Run quickly | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
this.SetSpeedMultiplier(this.GetRunMultiplier()); | this.SetSpeedMultiplier(this.GetRunMultiplier()); | ||||
return false; | |||||
}, | }, | ||||
"HealthChanged": function() { | "HealthChanged": function() { | ||||
this.SetSpeedMultiplier(this.GetRunMultiplier()); | this.SetSpeedMultiplier(this.GetRunMultiplier()); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.ResetSpeedMultiplier(); | this.ResetSpeedMultiplier(); | ||||
Show All 29 Lines | "COMBAT": { | ||||
return true; | return true; | ||||
} | } | ||||
// Show weapons rather than carried resources. | // Show weapons rather than carried resources. | ||||
this.SetAnimationVariant("combat"); | this.SetAnimationVariant("combat"); | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
this.StartTimer(1000, 1000); | this.StartTimer(1000, 1000); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
// Show carried resources when walking. | // Show carried resources when walking. | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.StopTimer(); | this.StopTimer(); | ||||
}, | }, | ||||
Show All 35 Lines | "COMBAT": { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
}, | }, | ||||
"ATTACKING": { | "ATTACKING": { | ||||
"enter": function() { | "enter": function() { | ||||
var target = this.order.data.target; | let target = this.order.data.target; | ||||
var cmpFormation = Engine.QueryInterface(target, IID_Formation); | let cmpFormation = Engine.QueryInterface(target, IID_Formation); | ||||
// if the target is a formation, save the attacking formation, and pick a member | // if the target is a formation, save the attacking formation, and pick a member | ||||
if (cmpFormation) | if (cmpFormation) | ||||
{ | { | ||||
this.order.data.formationTarget = target; | this.order.data.formationTarget = target; | ||||
target = cmpFormation.GetClosestMember(this.entity); | target = cmpFormation.GetClosestMember(this.entity); | ||||
this.order.data.target = target; | this.order.data.target = target; | ||||
} | } | ||||
// Check the target is still alive and attackable | // Check the target is still alive and attackable | ||||
if (this.CanAttack(target) && !this.CheckTargetAttackRange(target, this.order.data.attackType)) | if (this.CanAttack(target) && !this.CheckTargetAttackRange(target, this.order.data.attackType)) | ||||
{ | { | ||||
// Can't reach it - try to chase after it | // Can't reach it - try to chase after it | ||||
if (this.ShouldChaseTargetedEntity(target, this.order.data.force)) | if (this.ShouldChaseTargetedEntity(target, this.order.data.force)) | ||||
{ | { | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return; | return false; | ||||
} | } | ||||
if (this.MoveToTargetAttackRange(target, this.order.data.attackType)) | if (this.MoveToTargetAttackRange(target, this.order.data.attackType)) | ||||
{ | { | ||||
this.SetNextState("COMBAT.CHASING"); | this.SetNextState("COMBAT.CHASING"); | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
this.StopMoving(); | this.StopMoving(); | ||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | ||||
this.attackTimers = cmpAttack.GetTimers(this.order.data.attackType); | this.attackTimers = cmpAttack.GetTimers(this.order.data.attackType); | ||||
// If the repeat time since the last attack hasn't elapsed, | // If the repeat time since the last attack hasn't elapsed, | ||||
// delay this attack to avoid attacking too fast. | // delay this attack to avoid attacking too fast. | ||||
var prepare = this.attackTimers.prepare; | let prepare = this.attackTimers.prepare; | ||||
if (this.lastAttacked) | if (this.lastAttacked) | ||||
{ | { | ||||
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | ||||
var repeatLeft = this.lastAttacked + this.attackTimers.repeat - cmpTimer.GetTime(); | let repeatLeft = this.lastAttacked + this.attackTimers.repeat - cmpTimer.GetTime(); | ||||
prepare = Math.max(prepare, repeatLeft); | prepare = Math.max(prepare, repeatLeft); | ||||
} | } | ||||
this.oldAttackType = this.order.data.attackType; | this.oldAttackType = this.order.data.attackType; | ||||
// add prefix + no capital first letter for attackType | // add prefix + no capital first letter for attackType | ||||
var animationName = "attack_" + this.order.data.attackType.toLowerCase(); | let animationName = "attack_" + this.order.data.attackType.toLowerCase(); | ||||
if (this.IsFormationMember()) | if (this.IsFormationMember()) | ||||
{ | { | ||||
var cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | ||||
if (cmpFormation) | if (cmpFormation) | ||||
animationName = cmpFormation.GetFormationAnimation(this.entity, animationName); | animationName = cmpFormation.GetFormationAnimation(this.entity, animationName); | ||||
} | } | ||||
this.SetAnimationVariant("combat"); | this.SetAnimationVariant("combat"); | ||||
this.SelectAnimation(animationName); | this.SelectAnimation(animationName); | ||||
this.SetAnimationSync(prepare, this.attackTimers.repeat); | this.SetAnimationSync(prepare, this.attackTimers.repeat); | ||||
this.StartTimer(prepare, this.attackTimers.repeat); | this.StartTimer(prepare, this.attackTimers.repeat); | ||||
// TODO: we should probably only bother syncing projectile attacks, not melee | // TODO: we should probably only bother syncing projectile attacks, not melee | ||||
// If using a non-default prepare time, re-sync the animation when the timer runs. | // If using a non-default prepare time, re-sync the animation when the timer runs. | ||||
this.resyncAnimation = (prepare != this.attackTimers.prepare) ? true : false; | this.resyncAnimation = (prepare != this.attackTimers.prepare) ? true : false; | ||||
this.FaceTowardsTarget(this.order.data.target); | this.FaceTowardsTarget(this.order.data.target); | ||||
var cmpBuildingAI = Engine.QueryInterface(this.entity, IID_BuildingAI); | let cmpBuildingAI = Engine.QueryInterface(this.entity, IID_BuildingAI); | ||||
if (cmpBuildingAI) | if (cmpBuildingAI) | ||||
cmpBuildingAI.SetUnitAITarget(this.order.data.target); | cmpBuildingAI.SetUnitAITarget(this.order.data.target); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
var cmpBuildingAI = Engine.QueryInterface(this.entity, IID_BuildingAI); | var cmpBuildingAI = Engine.QueryInterface(this.entity, IID_BuildingAI); | ||||
if (cmpBuildingAI) | if (cmpBuildingAI) | ||||
cmpBuildingAI.SetUnitAITarget(0); | cmpBuildingAI.SetUnitAITarget(0); | ||||
this.StopTimer(); | this.StopTimer(); | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | "COMBAT": { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
// Show weapons rather than carried resources. | // Show weapons rather than carried resources. | ||||
this.SetAnimationVariant("combat"); | this.SetAnimationVariant("combat"); | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
var cmpUnitAI = Engine.QueryInterface(this.order.data.target, IID_UnitAI); | let cmpUnitAI = Engine.QueryInterface(this.order.data.target, IID_UnitAI); | ||||
if (cmpUnitAI && cmpUnitAI.IsFleeing()) | |||||
{ | |||||
// Run after a fleeing target | // Run after a fleeing target | ||||
if (cmpUnitAI && cmpUnitAI.IsFleeing()) | |||||
this.SetSpeedMultiplier(this.GetRunMultiplier()); | this.SetSpeedMultiplier(this.GetRunMultiplier()); | ||||
} | |||||
this.StartTimer(1000, 1000); | this.StartTimer(1000, 1000); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.ResetSpeedMultiplier(); | this.ResetSpeedMultiplier(); | ||||
// Show carried resources when walking. | // Show carried resources when walking. | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
this.StopMoving(); | this.StopMoving(); | ||||
Show All 19 Lines | "INDIVIDUAL": { | ||||
}, | }, | ||||
"GATHER": { | "GATHER": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
this.gatheringTarget = this.order.data.target; // temporary, deleted in "leave". | this.gatheringTarget = this.order.data.target; // temporary, deleted in "leave". | ||||
// check that we can gather from the resource we're supposed to gather from. | // check that we can gather from the resource we're supposed to gather from. | ||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | ||||
var cmpMirage = Engine.QueryInterface(this.gatheringTarget, IID_Mirage); | let cmpMirage = Engine.QueryInterface(this.gatheringTarget, IID_Mirage); | ||||
if ((!cmpMirage || !cmpMirage.Mirages(IID_ResourceSupply)) && | if ((!cmpMirage || !cmpMirage.Mirages(IID_ResourceSupply)) && | ||||
(!cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity)) || | (!cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity)) || | ||||
!this.MoveTo(this.order.data, IID_ResourceGatherer)) | !this.MoveTo(this.order.data, IID_ResourceGatherer)) | ||||
{ | { | ||||
// The GATHERING timer will handle finding a valid resource. | // The GATHERING timer will handle finding a valid resource. | ||||
this.SetNextState("GATHERING"); | this.SetNextState("GATHERING"); | ||||
return true; | return true; | ||||
} | } | ||||
Show All 26 Lines | "GATHER": { | ||||
"WALKING": { | "WALKING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MoveCompleted": function(msg) { | "MoveCompleted": function(msg) { | ||||
// The GATHERING timer will handle finding a valid resource. | // The GATHERING timer will handle finding a valid resource. | ||||
Show All 19 Lines | "GATHER": { | ||||
// If this order was forced, the player probably gave it, but now we've reached the target | // If this order was forced, the player probably gave it, but now we've reached the target | ||||
// switch to an unforced order (can be interrupted by attacks) | // switch to an unforced order (can be interrupted by attacks) | ||||
this.order.data.force = false; | this.order.data.force = false; | ||||
this.order.data.autoharvest = true; | this.order.data.autoharvest = true; | ||||
// Calculate timing based on gather rates | // Calculate timing based on gather rates | ||||
// This allows the gather rate to control how often we gather, instead of how much. | // This allows the gather rate to control how often we gather, instead of how much. | ||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | ||||
var rate = cmpResourceGatherer.GetTargetGatherRate(this.gatheringTarget); | let rate = cmpResourceGatherer.GetTargetGatherRate(this.gatheringTarget); | ||||
if (!rate) | if (!rate) | ||||
{ | { | ||||
// Try to find another target if the current one stopped existing | // Try to find another target if the current one stopped existing | ||||
if (!Engine.QueryInterface(this.gatheringTarget, IID_Identity)) | if (!Engine.QueryInterface(this.gatheringTarget, IID_Identity)) | ||||
{ | { | ||||
// Let the Timer logic handle this | // Let the Timer logic handle this | ||||
this.StartTimer(0); | this.StartTimer(0); | ||||
return false; | return false; | ||||
} | } | ||||
// No rate, give up on gathering | // No rate, give up on gathering | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
// Scale timing interval based on rate, and start timer | // Scale timing interval based on rate, and start timer | ||||
// The offset should be at least as long as the repeat time so we use the same value for both. | // The offset should be at least as long as the repeat time so we use the same value for both. | ||||
var offset = 1000/rate; | let offset = 1000 / rate; | ||||
var repeat = offset; | let repeat = offset; | ||||
this.StartTimer(offset, repeat); | this.StartTimer(offset, repeat); | ||||
// We want to start the gather animation as soon as possible, | // We want to start the gather animation as soon as possible, | ||||
// but only if we're actually at the target and it's still alive | // but only if we're actually at the target and it's still alive | ||||
// (else it'll look like we're chopping empty air). | // (else it'll look like we're chopping empty air). | ||||
// (If it's not alive, the Timer handler will deal with sending us | // (If it's not alive, the Timer handler will deal with sending us | ||||
// off to a different target.) | // off to a different target.) | ||||
if (this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer)) | if (this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer)) | ||||
{ | { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
var typename = "gather_" + this.order.data.type.specific; | let typename = "gather_" + this.order.data.type.specific; | ||||
this.SelectAnimation(typename); | this.SelectAnimation(typename); | ||||
} | } | ||||
return false; | return false; | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopTimer(); | this.StopTimer(); | ||||
▲ Show 20 Lines • Show All 161 Lines • ▼ Show 20 Lines | "HEAL": { | ||||
if (!this.MoveTo(this.order.data, IID_Heal)) | if (!this.MoveTo(this.order.data, IID_Heal)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
this.StartTimer(1000, 1000); | this.StartTimer(1000, 1000); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.StopTimer(); | this.StopTimer(); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force, IID_Heal, null)) | if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force, IID_Heal, null)) | ||||
{ | { | ||||
// Return to our original position unless we have a better order. | // Return to our original position unless we have a better order. | ||||
if (!this.FinishOrder() && this.GetStance().respondHoldGround) | if (!this.FinishOrder() && this.GetStance().respondHoldGround) | ||||
this.WalkToHeldPosition(); | this.WalkToHeldPosition(); | ||||
} | } | ||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.SetNextState("HEALING"); | this.SetNextState("HEALING"); | ||||
}, | }, | ||||
}, | }, | ||||
"HEALING": { | "HEALING": { | ||||
"enter": function() { | "enter": function() { | ||||
var cmpHeal = Engine.QueryInterface(this.entity, IID_Heal); | let cmpHeal = Engine.QueryInterface(this.entity, IID_Heal); | ||||
this.healTimers = cmpHeal.GetTimers(); | this.healTimers = cmpHeal.GetTimers(); | ||||
// If the repeat time since the last heal hasn't elapsed, | // If the repeat time since the last heal hasn't elapsed, | ||||
// delay the action to avoid healing too fast. | // delay the action to avoid healing too fast. | ||||
var prepare = this.healTimers.prepare; | let prepare = this.healTimers.prepare; | ||||
if (this.lastHealed) | if (this.lastHealed) | ||||
{ | { | ||||
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | ||||
var repeatLeft = this.lastHealed + this.healTimers.repeat - cmpTimer.GetTime(); | let repeatLeft = this.lastHealed + this.healTimers.repeat - cmpTimer.GetTime(); | ||||
prepare = Math.max(prepare, repeatLeft); | prepare = Math.max(prepare, repeatLeft); | ||||
} | } | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.SelectAnimation("heal"); | this.SelectAnimation("heal"); | ||||
this.SetAnimationSync(prepare, this.healTimers.repeat); | this.SetAnimationSync(prepare, this.healTimers.repeat); | ||||
this.StartTimer(prepare, this.healTimers.repeat); | this.StartTimer(prepare, this.healTimers.repeat); | ||||
// If using a non-default prepare time, re-sync the animation when the timer runs. | // If using a non-default prepare time, re-sync the animation when the timer runs. | ||||
this.resyncAnimation = (prepare != this.healTimers.prepare) ? true : false; | this.resyncAnimation = (prepare != this.healTimers.prepare) ? true : false; | ||||
this.FaceTowardsTarget(this.order.data.target); | this.FaceTowardsTarget(this.order.data.target); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopTimer(); | this.StopTimer(); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
var target = this.order.data.target; | var target = this.order.data.target; | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | "RETURNRESOURCE": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
// Switch back to idle animation to guarantee we won't | // Switch back to idle animation to guarantee we won't | ||||
// get stuck with the carry animation after stopping moving | // get stuck with the carry animation after stopping moving | ||||
this.SelectAnimation("idle"); | this.SelectAnimation("idle"); | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | "TRADE": { | ||||
"APPROACHINGMARKET": { | "APPROACHINGMARKET": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveToMarket(this.order.data.target)) | if (!this.MoveToMarket(this.order.data.target)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
if (this.waypoints && this.waypoints.length) | if (this.waypoints && this.waypoints.length) | ||||
Show All 21 Lines | "REPAIR": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.SetNextState("REPAIRING"); | this.SetNextState("REPAIRING"); | ||||
Show All 22 Lines | "REPAIR": { | ||||
{ | { | ||||
if (this.MoveToTargetRange(this.repairTarget, IID_Builder)) | if (this.MoveToTargetRange(this.repairTarget, IID_Builder)) | ||||
this.SetNextState("APPROACHING"); | this.SetNextState("APPROACHING"); | ||||
else | else | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
// Check if the target is still repairable | // Check if the target is still repairable | ||||
var cmpHealth = Engine.QueryInterface(this.repairTarget, IID_Health); | let cmpHealth = Engine.QueryInterface(this.repairTarget, IID_Health); | ||||
if (cmpHealth && cmpHealth.GetHitpoints() >= cmpHealth.GetMaxHitpoints()) | if (cmpHealth && cmpHealth.GetHitpoints() >= cmpHealth.GetMaxHitpoints()) | ||||
{ | { | ||||
// The building was already finished/fully repaired before we arrived; | // The building was already finished/fully repaired before we arrived; | ||||
// let the ConstructionFinished handler handle this. | // let the ConstructionFinished handler handle this. | ||||
this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget}); | this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget}); | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | "REPAIR": { | ||||
this.WalkToTarget(msg.data.newentity, true); | this.WalkToTarget(msg.data.newentity, true); | ||||
} | } | ||||
}, | }, | ||||
}, | }, | ||||
"GARRISON": { | "GARRISON": { | ||||
"enter": function() { | "enter": function() { | ||||
// If the garrisonholder should pickup, warn it so it can take needed action | // If the garrisonholder should pickup, warn it so it can take needed action | ||||
var cmpGarrisonHolder = Engine.QueryInterface(this.order.data.target, IID_GarrisonHolder); | let cmpGarrisonHolder = Engine.QueryInterface(this.order.data.target, IID_GarrisonHolder); | ||||
if (cmpGarrisonHolder && cmpGarrisonHolder.CanPickup(this.entity)) | if (cmpGarrisonHolder && cmpGarrisonHolder.CanPickup(this.entity)) | ||||
{ | { | ||||
this.pickup = this.order.data.target; // temporary, deleted in "leave" | this.pickup = this.order.data.target; // temporary, deleted in "leave" | ||||
Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); | ||||
} | } | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
// If a pickup has been requested and not yet canceled, cancel it | // If a pickup has been requested and not yet canceled, cancel it | ||||
if (this.pickup) | if (this.pickup) | ||||
{ | { | ||||
Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | ||||
delete this.pickup; | delete this.pickup; | ||||
} | } | ||||
}, | }, | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.SetNextState("GARRISONED"); | this.SetNextState("GARRISONED"); | ||||
}, | }, | ||||
}, | }, | ||||
"GARRISONED": { | "GARRISONED": { | ||||
"enter": function() { | "enter": function() { | ||||
let target; | |||||
if (this.order.data.target) | if (this.order.data.target) | ||||
var target = this.order.data.target; | target = this.order.data.target; | ||||
else | else | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
if (this.IsGarrisoned()) | if (this.IsGarrisoned()) | ||||
return false; | return false; | ||||
// Check that we can garrison here | // Check that we can garrison here | ||||
if (this.CanGarrison(target)) | if (this.CanGarrison(target)) | ||||
{ | { | ||||
// Check that we're in range of the garrison target | // Check that we're in range of the garrison target | ||||
if (this.CheckGarrisonRange(target)) | if (this.CheckGarrisonRange(target)) | ||||
{ | { | ||||
var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | let cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | ||||
// Check that garrisoning succeeds | // Check that garrisoning succeeds | ||||
if (cmpGarrisonHolder.Garrison(this.entity)) | if (cmpGarrisonHolder.Garrison(this.entity)) | ||||
{ | { | ||||
this.isGarrisoned = true; | this.isGarrisoned = true; | ||||
if (this.formationController) | if (this.formationController) | ||||
{ | { | ||||
var cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | ||||
if (cmpFormation) | if (cmpFormation) | ||||
{ | { | ||||
// disable rearrange for this removal, | // disable rearrange for this removal, | ||||
// but enable it again for the next | // but enable it again for the next | ||||
// move command | // move command | ||||
var rearrange = cmpFormation.rearrange; | let rearrange = cmpFormation.rearrange; | ||||
cmpFormation.SetRearrange(false); | cmpFormation.SetRearrange(false); | ||||
cmpFormation.RemoveMembers([this.entity]); | cmpFormation.RemoveMembers([this.entity]); | ||||
cmpFormation.SetRearrange(rearrange); | cmpFormation.SetRearrange(rearrange); | ||||
} | } | ||||
} | } | ||||
// Check if we are garrisoned in a dropsite | // Check if we are garrisoned in a dropsite | ||||
var cmpResourceDropsite = Engine.QueryInterface(target, IID_ResourceDropsite); | let cmpResourceDropsite = Engine.QueryInterface(target, IID_ResourceDropsite); | ||||
if (cmpResourceDropsite && this.CanReturnResource(target, true)) | if (cmpResourceDropsite && this.CanReturnResource(target, true)) | ||||
{ | { | ||||
// Dump any resources we can | // Dump any resources we can | ||||
var dropsiteTypes = cmpResourceDropsite.GetTypes(); | let dropsiteTypes = cmpResourceDropsite.GetTypes(); | ||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | ||||
if (cmpResourceGatherer) | if (cmpResourceGatherer) | ||||
{ | { | ||||
cmpResourceGatherer.CommitResources(dropsiteTypes); | cmpResourceGatherer.CommitResources(dropsiteTypes); | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
} | } | ||||
} | } | ||||
// If a pickup has been requested, remove it | // If a pickup has been requested, remove it | ||||
if (this.pickup) | if (this.pickup) | ||||
{ | { | ||||
var cmpHolderPosition = Engine.QueryInterface(target, IID_Position); | let cmpHolderPosition = Engine.QueryInterface(target, IID_Position); | ||||
var cmpHolderUnitAI = Engine.QueryInterface(target, IID_UnitAI); | let cmpHolderUnitAI = Engine.QueryInterface(target, IID_UnitAI); | ||||
if (cmpHolderUnitAI && cmpHolderPosition) | if (cmpHolderUnitAI && cmpHolderPosition) | ||||
cmpHolderUnitAI.lastShorelinePosition = cmpHolderPosition.GetPosition(); | cmpHolderUnitAI.lastShorelinePosition = cmpHolderPosition.GetPosition(); | ||||
Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | ||||
delete this.pickup; | delete this.pickup; | ||||
} | } | ||||
if (this.IsTurret()) | if (this.IsTurret()) { | ||||
this.SetNextState("IDLE"); | this.SetNextState("IDLE"); | ||||
return true; | |||||
} | |||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// Unable to reach the target, try again (or follow if it is a moving target) | // Unable to reach the target, try again (or follow if it is a moving target) | ||||
// except if the does not exits anymore or its orders have changed | // except if the does not exits anymore or its orders have changed | ||||
if (this.pickup) | if (this.pickup) | ||||
{ | { | ||||
var cmpUnitAI = Engine.QueryInterface(this.pickup, IID_UnitAI); | let cmpUnitAI = Engine.QueryInterface(this.pickup, IID_UnitAI); | ||||
if (!cmpUnitAI || !cmpUnitAI.HasPickupOrder(this.entity)) | if (!cmpUnitAI || !cmpUnitAI.HasPickupOrder(this.entity)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
if (!this.CheckTargetRangeExplicit(target, 0, 0) && this.MoveToTarget(target)) | if (!this.CheckTargetRangeExplicit(target, 0, 0) && this.MoveToTarget(target)) | ||||
{ | { | ||||
this.SetNextState("APPROACHING"); | this.SetNextState("APPROACHING"); | ||||
return false; | return true; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Garrisoning failed for some reason, so finish the order | // Garrisoning failed for some reason, so finish the order | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
} | } | ||||
}, | }, | ||||
}, | }, | ||||
"CHEERING": { | "CHEERING": { | ||||
"enter": function() { | "enter": function() { | ||||
// Unit is invulnerable while cheering | // Unit is invulnerable while cheering | ||||
var cmpDamageReceiver = Engine.QueryInterface(this.entity, IID_DamageReceiver); | let cmpDamageReceiver = Engine.QueryInterface(this.entity, IID_DamageReceiver); | ||||
cmpDamageReceiver.SetInvulnerability(true); | cmpDamageReceiver.SetInvulnerability(true); | ||||
this.SelectAnimation("promotion"); | this.SelectAnimation("promotion"); | ||||
this.StartTimer(2800, 2800); | this.StartTimer(2800, 2800); | ||||
return false; | return false; | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopTimer(); | this.StopTimer(); | ||||
var cmpDamageReceiver = Engine.QueryInterface(this.entity, IID_DamageReceiver); | var cmpDamageReceiver = Engine.QueryInterface(this.entity, IID_DamageReceiver); | ||||
cmpDamageReceiver.SetInvulnerability(false); | cmpDamageReceiver.SetInvulnerability(false); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
"PACKING": { | "PACKING": { | ||||
"enter": function() { | "enter": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | let cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | ||||
cmpPack.Pack(); | cmpPack.Pack(); | ||||
return false; | |||||
}, | }, | ||||
"PackFinished": function(msg) { | "PackFinished": function(msg) { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
}, | }, | ||||
"Attacked": function(msg) { | "Attacked": function(msg) { | ||||
// Ignore attacks while packing | // Ignore attacks while packing | ||||
}, | }, | ||||
}, | }, | ||||
"UNPACKING": { | "UNPACKING": { | ||||
"enter": function() { | "enter": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | let cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | ||||
cmpPack.Unpack(); | cmpPack.Unpack(); | ||||
return false; | |||||
}, | }, | ||||
"PackFinished": function(msg) { | "PackFinished": function(msg) { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
}, | }, | ||||
"Attacked": function(msg) { | "Attacked": function(msg) { | ||||
// Ignore attacks while unpacking | // Ignore attacks while unpacking | ||||
}, | }, | ||||
}, | }, | ||||
"PICKUP": { | "PICKUP": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.SetNextState("LOADING"); | this.SetNextState("LOADING"); | ||||
}, | }, | ||||
"PickupCanceled": function() { | "PickupCanceled": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
"LOADING": { | "LOADING": { | ||||
"enter": function() { | "enter": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.SelectAnimation("idle"); | this.SelectAnimation("idle"); | ||||
var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); | let cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); | ||||
if (!cmpGarrisonHolder || cmpGarrisonHolder.IsFull()) | if (!cmpGarrisonHolder || cmpGarrisonHolder.IsFull()) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | "ANIMAL": { | ||||
"ROAMING": { | "ROAMING": { | ||||
"enter": function() { | "enter": function() { | ||||
// Walk in a random direction | // Walk in a random direction | ||||
this.SelectAnimation("walk", false, 1); | this.SelectAnimation("walk", false, 1); | ||||
this.SetFacePointAfterMove(false); | this.SetFacePointAfterMove(false); | ||||
this.MoveRandomly(+this.template.RoamDistance); | this.MoveRandomly(+this.template.RoamDistance); | ||||
// Set a random timer to switch to feeding state | // Set a random timer to switch to feeding state | ||||
this.StartTimer(randIntInclusive(+this.template.RoamTimeMin, +this.template.RoamTimeMax)); | this.StartTimer(randIntInclusive(+this.template.RoamTimeMin, +this.template.RoamTimeMax)); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.StopTimer(); | this.StopTimer(); | ||||
this.SetFacePointAfterMove(true); | this.SetFacePointAfterMove(true); | ||||
}, | }, | ||||
Show All 29 Lines | "ANIMAL": { | ||||
}, | }, | ||||
"FEEDING": { | "FEEDING": { | ||||
"enter": function() { | "enter": function() { | ||||
// Stop and eat for a while | // Stop and eat for a while | ||||
this.SelectAnimation("feeding"); | this.SelectAnimation("feeding"); | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.StartTimer(randIntInclusive(+this.template.FeedTimeMin, +this.template.FeedTimeMax)); | this.StartTimer(randIntInclusive(+this.template.FeedTimeMin, +this.template.FeedTimeMax)); | ||||
return false; | |||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopTimer(); | this.StopTimer(); | ||||
}, | }, | ||||
"LosRangeUpdate": function(msg) { | "LosRangeUpdate": function(msg) { | ||||
if (this.template.NaturalBehaviour == "skittish") | if (this.template.NaturalBehaviour == "skittish") | ||||
▲ Show 20 Lines • Show All 2,818 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator