Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | "Order.FormationWalk": function(msg) { | ||||
// 1. If packed, we can move. | // 1. If packed, we can move. | ||||
// 2. If unpacked, we first need to pack, then follow case 1. | // 2. If unpacked, we first need to pack, then follow case 1. | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return; | return; | ||||
} | } | ||||
var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | |||||
cmpUnitMotion.MoveToFormationOffset(msg.data.target, msg.data.x, msg.data.z); | |||||
this.SetNextState("FORMATIONMEMBER.WALKING"); | this.SetNextState("FORMATIONMEMBER.WALKING"); | ||||
}, | }, | ||||
// Special orders: | // Special orders: | ||||
// (these will be overridden by various states) | // (these will be overridden by various states) | ||||
"Order.LeaveFoundation": function(msg) { | "Order.LeaveFoundation": function(msg) { | ||||
// If foundation is not ally of entity, or if entity is unpacked siege, | // If foundation is not ally of entity, or if entity is unpacked siege, | ||||
// ignore the order | // ignore the order | ||||
if (!IsOwnedByAllyOfEntity(this.entity, msg.data.target) && !Engine.QueryInterface(SYSTEM_ENTITY, IID_CeasefireManager).IsCeasefireActive() || | if (!IsOwnedByAllyOfEntity(this.entity, msg.data.target) && !Engine.QueryInterface(SYSTEM_ENTITY, IID_CeasefireManager).IsCeasefireActive() || | ||||
this.IsPacking() || this.CanPack() || this.IsTurret()) | this.IsPacking() || this.CanPack() || this.IsTurret()) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// Move a tile outside the building | |||||
// Move a tile outside the building if necessary. | |||||
let range = 4; | let range = 4; | ||||
if (this.MoveToTargetRangeExplicit(msg.data.target, range, range)) | if (this.CheckTargetRangeExplicit(msg.data.target, range, -1)) | ||||
Stan: Not sure we need the braces here. Or could be an early return maybe ? | |||||
{ | this.FinishOrder(); | ||||
// We've started walking to the given point | |||||
this.SetNextState("INDIVIDUAL.WALKING"); | |||||
} | |||||
else | else | ||||
{ | { | ||||
// We are already at the target, or can't move at all | this.order.data.min = range; | ||||
this.FinishOrder(); | this.SetNextState("INDIVIDUAL.WALKING"); | ||||
} | } | ||||
}, | }, | ||||
// Individual orders: | // Individual orders: | ||||
// (these will switch the unit out of formation mode) | // (these will switch the unit out of formation mode) | ||||
"Order.Stop": function(msg) { | "Order.Stop": function(msg) { | ||||
// We have no control over non-domestic animals. | // We have no control over non-domestic animals. | ||||
Show All 28 Lines | "Order.Walk": function(msg) { | ||||
// 2. If unpacked, we first need to pack, then follow case 1. | // 2. If unpacked, we first need to pack, then follow case 1. | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return; | return; | ||||
} | } | ||||
this.SetHeldPosition(this.order.data.x, this.order.data.z); | this.SetHeldPosition(this.order.data.x, this.order.data.z); | ||||
if (!this.order.data.max) | |||||
this.MoveToPoint(this.order.data.x, this.order.data.z); | |||||
else | |||||
this.MoveToPointRange(this.order.data.x, this.order.data.z, this.order.data.min, this.order.data.max); | |||||
if (this.IsAnimal()) | if (this.IsAnimal()) | ||||
this.SetNextState("ANIMAL.WALKING"); | this.SetNextState("ANIMAL.WALKING"); | ||||
else | else | ||||
this.SetNextState("INDIVIDUAL.WALKING"); | this.SetNextState("INDIVIDUAL.WALKING"); | ||||
}, | }, | ||||
"Order.WalkAndFight": function(msg) { | "Order.WalkAndFight": function(msg) { | ||||
// Let players move captured domestic animals around | // Let players move captured domestic animals around | ||||
if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret()) | if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret()) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// For packable units: | // For packable units: | ||||
// 1. If packed, we can move. | // 1. If packed, we can move. | ||||
// 2. If unpacked, we first need to pack, then follow case 1. | // 2. If unpacked, we first need to pack, then follow case 1. | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return; | return; | ||||
} | } | ||||
this.SetHeldPosition(this.order.data.x, this.order.data.z); | this.SetHeldPosition(this.order.data.x, this.order.data.z); | ||||
this.MoveToPoint(this.order.data.x, this.order.data.z); | |||||
if (this.IsAnimal()) | if (this.IsAnimal()) | ||||
this.SetNextState("ANIMAL.WALKING"); // WalkAndFight not applicable for animals | this.SetNextState("ANIMAL.WALKING"); // WalkAndFight not applicable for animals | ||||
else | else | ||||
this.SetNextState("INDIVIDUAL.WALKINGANDFIGHTING"); | this.SetNextState("INDIVIDUAL.WALKINGANDFIGHTING"); | ||||
}, | }, | ||||
"Order.WalkToTarget": function(msg) { | "Order.WalkToTarget": function(msg) { | ||||
// Let players move captured domestic animals around | // Let players move captured domestic animals around | ||||
if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret()) | if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret()) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// For packable units: | // For packable units: | ||||
// 1. If packed, we can move. | // 1. If packed, we can move. | ||||
// 2. If unpacked, we first need to pack, then follow case 1. | // 2. If unpacked, we first need to pack, then follow case 1. | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return; | return; | ||||
} | } | ||||
var ok = this.MoveToTarget(this.order.data.target); | |||||
Not Done Inline Actionsvar → let. Stan: var → let. | |||||
Not Done Inline ActionsActually, that variable could be inlined. Stan: Actually, that variable could be inlined. | |||||
Not Done Inline ActionsCould be a ternary. Stan: Could be a ternary. | |||||
Not Done Inline Actionsinline while at it bb: inline while at it | |||||
if (ok) | if (this.CheckTargetRangeExplicit(this.order.data.target, 0, 0)) | ||||
{ | { | ||||
// We've started walking to the given point | // We are already at the target, or can't move at all | ||||
this.FinishOrder(); | |||||
return 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"); | ||||
} | |||||
else | |||||
{ | |||||
// We are already at the target, or can't move at all | |||||
this.StopMoving(); | |||||
this.FinishOrder(); | |||||
} | |||||
}, | }, | ||||
"Order.PickupUnit": function(msg) { | "Order.PickupUnit": function(msg) { | ||||
var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); | var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); | ||||
if (!cmpGarrisonHolder || cmpGarrisonHolder.IsFull()) | if (!cmpGarrisonHolder || cmpGarrisonHolder.IsFull()) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
if (this.CheckTargetRangeExplicit(this.order.data.target, 0, 0)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return; | |||||
} | |||||
// Check if we need to move TODO implement a better way to know if we are on the shoreline | // Check if we need to move TODO implement a better way to know if we are on the shoreline | ||||
var needToMove = true; | var needToMove = true; | ||||
var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||
if (this.lastShorelinePosition && cmpPosition && (this.lastShorelinePosition.x == cmpPosition.GetPosition().x) | if (this.lastShorelinePosition && cmpPosition && (this.lastShorelinePosition.x == cmpPosition.GetPosition().x) | ||||
&& (this.lastShorelinePosition.z == cmpPosition.GetPosition().z)) | && (this.lastShorelinePosition.z == cmpPosition.GetPosition().z)) | ||||
{ | { | ||||
// we were already on the shoreline, and have not moved since | // we were already on the shoreline, and have not moved since | ||||
if (DistanceBetweenEntities(this.entity, this.order.data.target) < 50) | if (DistanceBetweenEntities(this.entity, this.order.data.target) < 50) | ||||
needToMove = false; | needToMove = false; | ||||
} | } | ||||
// TODO: what if the units are on a cliff ? the ship will go below the cliff | if (needToMove) | ||||
Not Done Inline ActionsDoes that affect the todo on top ? Stan: Does that affect the todo on top ? | |||||
Done Inline ActionsNope, that would be the global region thingy I guess. wraitii: Nope, that would be the global region thingy I guess. | |||||
// and the units won't be able to garrison. Should go to the nearest (accessible) shore | |||||
if (needToMove && this.MoveToTarget(this.order.data.target)) | |||||
{ | |||||
this.SetNextState("INDIVIDUAL.PICKUP.APPROACHING"); | this.SetNextState("INDIVIDUAL.PICKUP.APPROACHING"); | ||||
} | |||||
else | else | ||||
{ | |||||
// We are already at the target, or can't move at all | |||||
this.StopMoving(); | |||||
this.SetNextState("INDIVIDUAL.PICKUP.LOADING"); | this.SetNextState("INDIVIDUAL.PICKUP.LOADING"); | ||||
} | |||||
}, | }, | ||||
"Order.Guard": function(msg) { | "Order.Guard": function(msg) { | ||||
if (!this.AddGuard(this.order.data.target)) | if (!this.AddGuard(this.order.data.target)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
if (this.MoveToTargetRangeExplicit(this.isGuardOf, 0, this.guardRange)) | if (!this.CheckTargetRangeExplicit(this.isGuardOf, 0, this.guardRange)) | ||||
this.SetNextState("INDIVIDUAL.GUARD.ESCORTING"); | this.SetNextState("INDIVIDUAL.GUARD.ESCORTING"); | ||||
else | else | ||||
this.SetNextState("INDIVIDUAL.GUARD.GUARDING"); | this.SetNextState("INDIVIDUAL.GUARD.GUARDING"); | ||||
}, | }, | ||||
"Order.Flee": function(msg) { | "Order.Flee": function(msg) { | ||||
// We use the distance between the entities to account for ranged attacks | // We use the distance between the entities to account for ranged attacks | ||||
var distance = DistanceBetweenEntities(this.entity, this.order.data.target) + (+this.template.FleeDistance); | let distance = DistanceBetweenEntities(this.entity, this.order.data.target) + (+this.template.FleeDistance); | ||||
var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | if (this.CheckTargetRangeExplicit(this.order.data.target, distance, distance)) | ||||
if (cmpUnitMotion.MoveToTargetRange(this.order.data.target, distance, -1)) | |||||
{ | { | ||||
// We've started fleeing from the given target | this.FinishOrder(); | ||||
return; | |||||
} | |||||
if (this.IsAnimal()) | if (this.IsAnimal()) | ||||
this.SetNextState("ANIMAL.FLEEING"); | this.SetNextState("ANIMAL.FLEEING"); | ||||
else | else | ||||
this.SetNextState("INDIVIDUAL.FLEEING"); | this.SetNextState("INDIVIDUAL.FLEEING"); | ||||
} | |||||
else | |||||
{ | |||||
// We are already at the target, or can't move at all | |||||
this.StopMoving(); | |||||
this.FinishOrder(); | |||||
} | |||||
}, | }, | ||||
"Order.Attack": function(msg) { | "Order.Attack": function(msg) { | ||||
// Check the target is alive | // Check the target is alive | ||||
if (!this.TargetIsAlive(this.order.data.target)) | if (!this.TargetIsAlive(this.order.data.target)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// Work out how to attack the given target | // Work out how to attack the given target | ||||
var type = this.GetBestAttackAgainst(this.order.data.target, this.order.data.allowCapture); | var type = this.GetBestAttackAgainst(this.order.data.target, this.order.data.allowCapture); | ||||
if (!type) | if (!type) | ||||
{ | { | ||||
// Oops, we can't attack at all | // Oops, we can't attack at all | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
this.order.data.attackType = type; | this.order.data.attackType = type; | ||||
// If we are already at the target, try attacking it from here | // If we are already at the target, try attacking it from here | ||||
if (this.CheckTargetAttackRange(this.order.data.target, this.order.data.attackType)) | if (this.CheckTargetAttackRange(this.order.data.target, this.order.data.attackType)) | ||||
{ | { | ||||
this.StopMoving(); | |||||
// For packable units within attack range: | // For packable units within attack range: | ||||
// 1. If unpacked, we can attack the target. | // 1. If unpacked, we can attack the target. | ||||
// 2. If packed, we first need to unpack, then follow case 1. | // 2. If packed, we first need to unpack, then follow case 1. | ||||
if (this.CanUnpack()) | if (this.CanUnpack()) | ||||
{ | { | ||||
this.PushOrderFront("Unpack", { "force": true }); | this.PushOrderFront("Unpack", { "force": true }); | ||||
return; | return; | ||||
} | } | ||||
if (this.order.data.attackType == this.oldAttackType) | |||||
{ | |||||
if (this.IsAnimal()) | |||||
this.SetNextState("ANIMAL.COMBAT.ATTACKING"); | |||||
else | |||||
this.SetNextState("INDIVIDUAL.COMBAT.ATTACKING"); | |||||
} | |||||
else | |||||
{ | |||||
if (this.IsAnimal()) | if (this.IsAnimal()) | ||||
this.SetNextState("ANIMAL.COMBAT.ATTACKING"); | this.SetNextState("ANIMAL.COMBAT.ATTACKING"); | ||||
else | else | ||||
this.SetNextState("INDIVIDUAL.COMBAT.ATTACKING"); | this.SetNextState("INDIVIDUAL.COMBAT.ATTACKING"); | ||||
} | |||||
return; | return; | ||||
} | } | ||||
// If we can't reach the target, but are standing ground, then abandon this attack order. | // If we can't reach the target, but are standing ground, then abandon this attack order. | ||||
// Unless we're hunting, that's a special case where we should continue attacking our target. | // Unless we're hunting, that's a special case where we should continue attacking our target. | ||||
if (this.GetStance().respondStandGround && !this.order.data.force && !this.order.data.hunting || this.IsTurret()) | if (this.GetStance().respondStandGround && !this.order.data.force && !this.order.data.hunting || this.IsTurret()) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// For packable units out of attack range: | // For packable units out of attack range: | ||||
// 1. If packed, we need to move to attack range and then unpack. | // 1. If packed, we need to move to attack range and then unpack. | ||||
// 2. If unpacked, we first need to pack, then follow case 1. | // 2. If unpacked, we first need to pack, then follow case 1. | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return; | return; | ||||
} | } | ||||
// Try to move within attack range | |||||
if (this.MoveToTargetAttackRange(this.order.data.target, this.order.data.attackType)) | |||||
{ | |||||
// We've started walking to the given point | |||||
if (this.IsAnimal()) | if (this.IsAnimal()) | ||||
this.SetNextState("ANIMAL.COMBAT.APPROACHING"); | this.SetNextState("ANIMAL.COMBAT.APPROACHING"); | ||||
else | else | ||||
this.SetNextState("INDIVIDUAL.COMBAT.APPROACHING"); | this.SetNextState("INDIVIDUAL.COMBAT.APPROACHING"); | ||||
return; | |||||
} | |||||
// We can't reach the target, and can't move towards it, | |||||
// so abandon this attack order | |||||
this.FinishOrder(); | |||||
}, | }, | ||||
"Order.Patrol": function(msg) { | "Order.Patrol": function(msg) { | ||||
if (this.IsAnimal() || this.IsTurret()) | if (this.IsAnimal() || this.IsTurret()) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return; | return; | ||||
} | } | ||||
this.MoveToPoint(this.order.data.x, this.order.data.z); | |||||
this.SetNextState("INDIVIDUAL.PATROL"); | this.SetNextState("INDIVIDUAL.PATROL"); | ||||
}, | }, | ||||
"Order.Heal": function(msg) { | "Order.Heal": function(msg) { | ||||
// Check the target is alive | // Check the target is alive | ||||
if (!this.TargetIsAlive(this.order.data.target)) | if (!this.TargetIsAlive(this.order.data.target)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// Healers can't heal themselves. | // Healers can't heal themselves. | ||||
if (this.order.data.target == this.entity) | if (this.order.data.target == this.entity) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// Check if the target is in range | // Check if the target is in range | ||||
if (this.CheckTargetRange(this.order.data.target, IID_Heal)) | if (this.CheckTargetRange(this.order.data.target, IID_Heal)) | ||||
{ | { | ||||
this.StopMoving(); | |||||
this.SetNextState("INDIVIDUAL.HEAL.HEALING"); | this.SetNextState("INDIVIDUAL.HEAL.HEALING"); | ||||
return; | return; | ||||
} | } | ||||
// If we can't reach the target, but are standing ground, | // If we can't reach the target, but are standing ground, | ||||
// then abandon this heal order | // then abandon this heal order | ||||
if (this.GetStance().respondStandGround && !this.order.data.force) | if (this.GetStance().respondStandGround && !this.order.data.force) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// Try to move within heal range | |||||
if (this.MoveToTargetRange(this.order.data.target, IID_Heal)) | |||||
{ | |||||
// We've started walking to the given point | |||||
this.SetNextState("INDIVIDUAL.HEAL.APPROACHING"); | this.SetNextState("INDIVIDUAL.HEAL.APPROACHING"); | ||||
return; | |||||
} | |||||
// We can't reach the target, and can't move towards it, | |||||
// so abandon this heal order | |||||
this.FinishOrder(); | |||||
}, | }, | ||||
"Order.Gather": function(msg) { | "Order.Gather": function(msg) { | ||||
// If the target is still alive, we need to kill it first | // If the target is still alive, we need to kill it first | ||||
if (this.MustKillGatherTarget(this.order.data.target)) | if (this.MustKillGatherTarget(this.order.data.target)) | ||||
{ | { | ||||
// Make sure we can attack the target, else we'll get very stuck | // Make sure we can attack the target, else we'll get very stuck | ||||
if (!this.GetBestAttackAgainst(this.order.data.target, false)) | if (!this.GetBestAttackAgainst(this.order.data.target, false)) | ||||
Show All 19 Lines | if (this.MustKillGatherTarget(this.order.data.target)) | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
this.PushOrderFront("Attack", { "target": this.order.data.target, "force": !!this.order.data.force, "hunting": true, "allowCapture": false }); | this.PushOrderFront("Attack", { "target": this.order.data.target, "force": !!this.order.data.force, "hunting": true, "allowCapture": false }); | ||||
return; | return; | ||||
} | } | ||||
// Try to move within range | if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer)) | ||||
if (this.MoveToTargetRange(this.order.data.target, IID_ResourceGatherer)) | |||||
{ | |||||
// We've started walking to the given point | |||||
this.SetNextState("INDIVIDUAL.GATHER.APPROACHING"); | |||||
} | |||||
else | |||||
{ | |||||
// We are already at the target, or can't move at all, | |||||
// so try gathering it from here. | |||||
// TODO: need better handling of the can't-reach-target case | |||||
this.StopMoving(); | |||||
this.SetNextState("INDIVIDUAL.GATHER.GATHERING"); | this.SetNextState("INDIVIDUAL.GATHER.GATHERING"); | ||||
} | else | ||||
this.SetNextState("INDIVIDUAL.GATHER.APPROACHING"); | |||||
}, | }, | ||||
"Order.GatherNearPosition": function(msg) { | "Order.GatherNearPosition": function(msg) { | ||||
// Move the unit to the position to gather from. | |||||
this.MoveToPoint(this.order.data.x, this.order.data.z); | |||||
this.SetNextState("INDIVIDUAL.GATHER.WALKING"); | this.SetNextState("INDIVIDUAL.GATHER.WALKING"); | ||||
}, | }, | ||||
"Order.ReturnResource": function(msg) { | "Order.ReturnResource": function(msg) { | ||||
// Check if the dropsite is already in range | // Check if the dropsite is already in range | ||||
if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer) && this.CanReturnResource(this.order.data.target, true)) | if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer) && this.CanReturnResource(this.order.data.target, true)) | ||||
{ | { | ||||
var cmpResourceDropsite = Engine.QueryInterface(this.order.data.target, IID_ResourceDropsite); | var cmpResourceDropsite = Engine.QueryInterface(this.order.data.target, IID_ResourceDropsite); | ||||
if (cmpResourceDropsite) | if (cmpResourceDropsite) | ||||
{ | { | ||||
// Dump any resources we can | // Dump any resources we can | ||||
var dropsiteTypes = cmpResourceDropsite.GetTypes(); | var dropsiteTypes = cmpResourceDropsite.GetTypes(); | ||||
Engine.QueryInterface(this.entity, IID_ResourceGatherer).CommitResources(dropsiteTypes); | Engine.QueryInterface(this.entity, IID_ResourceGatherer).CommitResources(dropsiteTypes); | ||||
// Stop showing the carried resource animation. | // Stop showing the carried resource animation. | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
// Our next order should always be a Gather, | // Our next order should always be a Gather, | ||||
// so just switch back to that order | // so just switch back to that order | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
// Try to move to the dropsite | |||||
if (this.MoveToTargetRange(this.order.data.target, IID_ResourceGatherer)) | |||||
{ | |||||
// We've started walking to the target | |||||
this.SetNextState("INDIVIDUAL.RETURNRESOURCE.APPROACHING"); | this.SetNextState("INDIVIDUAL.RETURNRESOURCE.APPROACHING"); | ||||
return; | |||||
} | |||||
// Oops, we can't reach the dropsite. | |||||
// Maybe we should try to pick another dropsite, to find an | |||||
// accessible one? | |||||
// For now, just give up. | |||||
this.StopMoving(); | |||||
this.FinishOrder(); | |||||
return; | |||||
}, | }, | ||||
"Order.Trade": function(msg) { | "Order.Trade": function(msg) { | ||||
// We must check if this trader has both markets in case it was a back-to-work order | // We must check if this trader has both markets in case it was a back-to-work order | ||||
var cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | var cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | ||||
if (!cmpTrader || !cmpTrader.HasBothMarkets()) | if (!cmpTrader || !cmpTrader.HasBothMarkets()) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// TODO find the nearest way-point from our position, and start with it | // TODO find the nearest way-point from our position, and start with it | ||||
this.waypoints = undefined; | this.waypoints = undefined; | ||||
if (this.MoveToMarket(this.order.data.target)) | |||||
// We've started walking to the next market | |||||
this.SetNextState("TRADE.APPROACHINGMARKET"); | this.SetNextState("TRADE.APPROACHINGMARKET"); | ||||
else | |||||
this.FinishOrder(); | |||||
}, | }, | ||||
"Order.Repair": function(msg) { | "Order.Repair": function(msg) { | ||||
// Try to move within range | // Try to move within range | ||||
if (this.MoveToTargetRange(this.order.data.target, IID_Builder)) | if (this.CheckTargetRange(this.order.data.target, IID_Builder)) | ||||
{ | |||||
// We've started walking to the given point | |||||
this.SetNextState("INDIVIDUAL.REPAIR.APPROACHING"); | |||||
} | |||||
else | |||||
{ | |||||
// We are already at the target, or can't move at all, | |||||
// so try repairing it from here. | |||||
// TODO: need better handling of the can't-reach-target case | |||||
this.StopMoving(); | |||||
this.SetNextState("INDIVIDUAL.REPAIR.REPAIRING"); | this.SetNextState("INDIVIDUAL.REPAIR.REPAIRING"); | ||||
} | else | ||||
this.SetNextState("INDIVIDUAL.REPAIR.APPROACHING"); | |||||
}, | }, | ||||
"Order.Garrison": function(msg) { | "Order.Garrison": function(msg) { | ||||
if (this.IsTurret()) | if (this.IsTurret()) | ||||
{ | { | ||||
this.SetNextState("IDLE"); | this.SetNextState("IDLE"); | ||||
return; | return; | ||||
} | } | ||||
else if (this.IsGarrisoned()) | else if (this.IsGarrisoned()) | ||||
{ | { | ||||
this.SetNextState("INDIVIDUAL.GARRISON.GARRISONED"); | this.SetNextState("INDIVIDUAL.GARRISON.GARRISONED"); | ||||
return; | return; | ||||
} | } | ||||
// For packable units: | // For packable units: | ||||
// 1. If packed, we can move to the garrison target. | // 1. If packed, we can move to the garrison target. | ||||
// 2. If unpacked, we first need to pack, then follow case 1. | // 2. If unpacked, we first need to pack, then follow case 1. | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return; | return; | ||||
} | } | ||||
if (this.MoveToGarrisonRange(this.order.data.target)) | |||||
{ | |||||
this.SetNextState("INDIVIDUAL.GARRISON.APPROACHING"); | this.SetNextState("INDIVIDUAL.GARRISON.APPROACHING"); | ||||
} | |||||
else | |||||
{ | |||||
// We do a range check before actually garrisoning | |||||
this.StopMoving(); | |||||
this.SetNextState("INDIVIDUAL.GARRISON.GARRISONED"); | |||||
} | |||||
}, | }, | ||||
"Order.Ungarrison": function() { | "Order.Ungarrison": function() { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
this.isGarrisoned = false; | this.isGarrisoned = false; | ||||
}, | }, | ||||
"Order.Cheering": function(msg) { | "Order.Cheering": function(msg) { | ||||
this.SetNextState("INDIVIDUAL.CHEERING"); | this.SetNextState("INDIVIDUAL.CHEERING"); | ||||
}, | }, | ||||
"Order.Pack": function(msg) { | "Order.Pack": function(msg) { | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | |||||
this.StopMoving(); | |||||
this.SetNextState("INDIVIDUAL.PACKING"); | this.SetNextState("INDIVIDUAL.PACKING"); | ||||
} | |||||
}, | }, | ||||
"Order.Unpack": function(msg) { | "Order.Unpack": function(msg) { | ||||
if (this.CanUnpack()) | if (this.CanUnpack()) | ||||
{ | |||||
this.StopMoving(); | |||||
this.SetNextState("INDIVIDUAL.UNPACKING"); | this.SetNextState("INDIVIDUAL.UNPACKING"); | ||||
} | |||||
}, | }, | ||||
"Order.CancelPack": function(msg) { | "Order.CancelPack": function(msg) { | ||||
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | ||||
if (cmpPack && cmpPack.IsPacking() && !cmpPack.IsPacked()) | if (cmpPack && cmpPack.IsPacking() && !cmpPack.IsPacked()) | ||||
cmpPack.CancelPack(); | cmpPack.CancelPack(); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
"Order.CancelUnpack": function(msg) { | "Order.CancelUnpack": function(msg) { | ||||
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | ||||
if (cmpPack && cmpPack.IsPacking() && cmpPack.IsPacked()) | if (cmpPack && cmpPack.IsPacking() && cmpPack.IsPacked()) | ||||
cmpPack.CancelPack(); | cmpPack.CancelPack(); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
// States for the special entity representing a group of units moving in formation: | // States for the special entity representing a group of units moving in formation: | ||||
"FORMATIONCONTROLLER": { | "FORMATIONCONTROLLER": { | ||||
"Order.Walk": function(msg) { | "Order.Walk": function(msg) { | ||||
this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); | this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); | ||||
this.MoveToPoint(this.order.data.x, this.order.data.z); | |||||
this.SetNextState("WALKING"); | this.SetNextState("WALKING"); | ||||
}, | }, | ||||
"Order.WalkAndFight": function(msg) { | "Order.WalkAndFight": function(msg) { | ||||
this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); | this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); | ||||
this.MoveToPoint(this.order.data.x, this.order.data.z); | |||||
this.SetNextState("WALKINGANDFIGHTING"); | this.SetNextState("WALKINGANDFIGHTING"); | ||||
}, | }, | ||||
"Order.MoveIntoFormation": function(msg) { | "Order.MoveIntoFormation": function(msg) { | ||||
this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); | this.CallMemberFunction("SetHeldPosition", [msg.data.x, msg.data.z]); | ||||
this.MoveToPoint(this.order.data.x, this.order.data.z); | |||||
this.SetNextState("FORMING"); | this.SetNextState("FORMING"); | ||||
}, | }, | ||||
// Only used by other orders to walk there in formation | // Only used by other orders to walk there in formation | ||||
"Order.WalkToTargetRange": function(msg) { | "Order.WalkToTargetRange": function(msg) { | ||||
if (this.MoveToTargetRangeExplicit(this.order.data.target, this.order.data.min, this.order.data.max)) | if (!this.CheckTargetRangeExplicit(this.order.data.target, this.order.data.min, this.order.data.max)) | ||||
this.SetNextState("WALKING"); | this.SetNextState("WALKING"); | ||||
else | else | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
"Order.WalkToTarget": function(msg) { | "Order.WalkToTarget": function(msg) { | ||||
if (this.MoveToTarget(this.order.data.target)) | if (!this.CheckTargetRangeExplicit(this.order.data.target, 0, 0)) | ||||
this.SetNextState("WALKING"); | this.SetNextState("WALKING"); | ||||
else | else | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
"Order.WalkToPointRange": function(msg) { | "Order.WalkToPointRange": function(msg) { | ||||
if (this.MoveToPointRange(this.order.data.x, this.order.data.z, this.order.data.min, this.order.data.max)) | if (!this.CheckPointRangeExplicit(this.order.data.x, this.order.data.z, this.order.data.min, this.order.data.max)) | ||||
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.MoveToPoint(this.order.data.x, this.order.data.z); | |||||
this.SetNextState("PATROL"); | this.SetNextState("PATROL"); | ||||
}, | }, | ||||
"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 All 13 Lines | "Order.Attack": function(msg) { | ||||
target = cmpTargetUnitAI.GetFormationController(); | target = cmpTargetUnitAI.GetFormationController(); | ||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | ||||
// Check if we are already in range, otherwise walk there | // Check if we are already in range, otherwise walk there | ||||
if (!this.CheckTargetAttackRange(target, target)) | if (!this.CheckTargetAttackRange(target, target)) | ||||
{ | { | ||||
if (this.TargetIsAlive(target) && this.CheckTargetVisible(target)) | if (this.TargetIsAlive(target) && this.CheckTargetVisible(target)) | ||||
{ | { | ||||
if (this.MoveToTargetAttackRange(target, target)) | |||||
{ | |||||
this.SetNextState("COMBAT.APPROACHING"); | this.SetNextState("COMBAT.APPROACHING"); | ||||
return; | return; | ||||
} | } | ||||
} | |||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
this.CallMemberFunction("Attack", [target, allowCapture, false]); | this.CallMemberFunction("Attack", [target, allowCapture, false]); | ||||
if (cmpAttack.CanAttackAsFormation()) | if (cmpAttack.CanAttackAsFormation()) | ||||
this.SetNextState("COMBAT.ATTACKING"); | this.SetNextState("COMBAT.ATTACKING"); | ||||
else | else | ||||
this.SetNextState("MEMBER"); | this.SetNextState("MEMBER"); | ||||
Show All 10 Lines | "Order.Garrison": function(msg) { | ||||
{ | { | ||||
if (!this.CheckTargetVisible(msg.data.target)) | if (!this.CheckTargetVisible(msg.data.target)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// Out of range; move there in formation | |||||
if (this.MoveToGarrisonRange(msg.data.target)) | |||||
{ | |||||
this.SetNextState("GARRISON.APPROACHING"); | this.SetNextState("GARRISON.APPROACHING"); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
} | |||||
this.SetNextState("GARRISON.GARRISONING"); | this.SetNextState("GARRISON.GARRISONING"); | ||||
}, | }, | ||||
"Order.Gather": function(msg) { | "Order.Gather": function(msg) { | ||||
if (this.MustKillGatherTarget(msg.data.target)) | if (this.MustKillGatherTarget(msg.data.target)) | ||||
{ | { | ||||
// The target was visible when this order was given, | // The target was visible when this order was given, | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | "IDLE": { | ||||
"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() { | |||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
}, | |||||
"leave": function() { | |||||
this.StopMoving(); | |||||
}, | |||||
"MoveStarted": function(msg) { | "MoveStarted": function(msg) { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
cmpFormation.SetRearrange(true); | cmpFormation.SetRearrange(true); | ||||
cmpFormation.MoveMembersIntoFormation(true, true); | cmpFormation.MoveMembersIntoFormation(true, true); | ||||
}, | }, | ||||
"MoveCompleted": function(msg) { | "MoveCompleted": function(msg) { | ||||
if (this.FinishOrder()) | if (this.FinishOrder()) | ||||
this.CallMemberFunction("ResetFinishOrder", []); | this.CallMemberFunction("ResetFinishOrder", []); | ||||
}, | }, | ||||
}, | }, | ||||
"WALKINGANDFIGHTING": { | "WALKINGANDFIGHTING": { | ||||
"enter": function(msg) { | "enter": function(msg) { | ||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
this.StartTimer(0, 1000); | this.StartTimer(0, 1000); | ||||
}, | }, | ||||
"leave": function() { | |||||
this.StopMoving(); | |||||
}, | |||||
"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) { | ||||
this.StopTimer(); | this.StopTimer(); | ||||
}, | }, | ||||
Show All 21 Lines | "PATROL": { | ||||
} | } | ||||
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.FinishOrder(); | |||||
return true; | |||||
} | |||||
this.StartTimer(0, 1000); | this.StartTimer(0, 1000); | ||||
}, | }, | ||||
"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) { | ||||
this.StopTimer(); | this.StopTimer(); | ||||
this.StopMoving(); | |||||
delete this.patrolStartPosOrder; | delete this.patrolStartPosOrder; | ||||
}, | }, | ||||
"MoveStarted": function(msg) { | "MoveStarted": function(msg) { | ||||
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); | ||||
}, | }, | ||||
Show All 34 Lines | "GARRISON":{ | ||||
{ | { | ||||
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() { | |||||
if (!this.MoveToGarrisonRange(this.order.data.target)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
}, | |||||
"leave": function() { | |||||
this.StopMoving(); | |||||
}, | |||||
"MoveStarted": function(msg) { | "MoveStarted": function(msg) { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
cmpFormation.SetRearrange(true); | cmpFormation.SetRearrange(true); | ||||
cmpFormation.MoveMembersIntoFormation(true, true); | cmpFormation.MoveMembersIntoFormation(true, true); | ||||
}, | }, | ||||
"MoveCompleted": function(msg) { | "MoveCompleted": function(msg) { | ||||
this.SetNextState("GARRISONING"); | this.SetNextState("GARRISONING"); | ||||
Show All 10 Lines | "GARRISON":{ | ||||
} | } | ||||
this.CallMemberFunction("Garrison", [this.order.data.target, false]); | this.CallMemberFunction("Garrison", [this.order.data.target, false]); | ||||
this.SetNextState("MEMBER"); | this.SetNextState("MEMBER"); | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
"FORMING": { | "FORMING": { | ||||
"enter": function() { | |||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
}, | |||||
"leave": function() { | |||||
this.StopMoving(); | |||||
}, | |||||
"MoveStarted": function(msg) { | "MoveStarted": function(msg) { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
cmpFormation.SetRearrange(true); | cmpFormation.SetRearrange(true); | ||||
cmpFormation.MoveMembersIntoFormation(true, false); | cmpFormation.MoveMembersIntoFormation(true, false); | ||||
}, | }, | ||||
"MoveCompleted": function(msg) { | "MoveCompleted": function(msg) { | ||||
if (this.FinishOrder()) | if (this.FinishOrder()) | ||||
{ | { | ||||
this.CallMemberFunction("ResetFinishOrder", []); | this.CallMemberFunction("ResetFinishOrder", []); | ||||
return; | return; | ||||
} | } | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
cmpFormation.FindInPosition(); | cmpFormation.FindInPosition(); | ||||
} | } | ||||
}, | }, | ||||
"COMBAT": { | "COMBAT": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | |||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
}, | |||||
"leave": function() { | |||||
this.StopMoving(); | |||||
}, | |||||
"MoveStarted": function(msg) { | "MoveStarted": function(msg) { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
cmpFormation.SetRearrange(true); | cmpFormation.SetRearrange(true); | ||||
cmpFormation.MoveMembersIntoFormation(true, true); | cmpFormation.MoveMembersIntoFormation(true, true); | ||||
}, | }, | ||||
"MoveCompleted": function(msg) { | "MoveCompleted": function(msg) { | ||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | ||||
▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | "Order.LeaveFoundation": function(msg) { | ||||
if (!IsOwnedByAllyOfEntity(this.entity, msg.data.target) && !Engine.QueryInterface(SYSTEM_ENTITY, IID_CeasefireManager).IsCeasefireActive() || | if (!IsOwnedByAllyOfEntity(this.entity, msg.data.target) && !Engine.QueryInterface(SYSTEM_ENTITY, IID_CeasefireManager).IsCeasefireActive() || | ||||
this.IsPacking() || this.CanPack() || this.IsTurret()) | this.IsPacking() || this.CanPack() || this.IsTurret()) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// Move a tile outside the building | // Move a tile outside the building | ||||
let range = 4; | let range = 4; | ||||
if (this.MoveToTargetRangeExplicit(msg.data.target, range, range)) | if (this.CheckTargetRangeExplicit(msg.data.target, range, range)) | ||||
{ | { | ||||
// We've started walking to the given point | // We are already at the target, or can't move at all | ||||
this.SetNextState("WALKINGTOPOINT"); | this.FinishOrder(); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// We are already at the target, or can't move at all | this.order.data.min = range; | ||||
this.FinishOrder(); | this.SetNextState("WALKINGTOPOINT"); | ||||
} | } | ||||
}, | }, | ||||
"IDLE": { | "IDLE": { | ||||
"enter": function() { | "enter": function() { | ||||
if (this.IsAnimal()) | if (this.IsAnimal()) | ||||
this.SetNextState("ANIMAL.IDLE"); | this.SetNextState("ANIMAL.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); | |||||
cmpUnitMotion.MoveToFormationOffset(this.order.data.target, this.order.data.x, this.order.data.z); | |||||
var cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | ||||
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); | var 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"); | ||||
Show All 19 Lines | "FORMATIONMEMBER": { | ||||
}, | }, | ||||
// 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); | var 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)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.StopMoving(); | |||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
// States for entities not part of a formation: | // States for entities not part of a formation: | ||||
"INDIVIDUAL": { | "INDIVIDUAL": { | ||||
▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | "IDLE": { | ||||
this.isIdle = true; | this.isIdle = true; | ||||
Engine.PostMessage(this.entity, MT_UnitIdleChanged, { "idle": this.isIdle }); | Engine.PostMessage(this.entity, MT_UnitIdleChanged, { "idle": this.isIdle }); | ||||
} | } | ||||
}, | }, | ||||
}, | }, | ||||
"WALKING": { | "WALKING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return; | |||||
} | |||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
}, | }, | ||||
"leave": function () { | |||||
this.SelectAnimation("idle"); | |||||
this.StopMoving(); | |||||
}, | |||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
"WALKINGANDFIGHTING": { | "WALKINGANDFIGHTING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return; | |||||
} | |||||
// 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"); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
this.FindWalkAndFightTargets(); | this.FindWalkAndFightTargets(); | ||||
}, | }, | ||||
"leave": function(msg) { | "leave": function(msg) { | ||||
this.StopMoving(); | |||||
this.StopTimer(); | this.StopTimer(); | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
"PATROL": { | "PATROL": { | ||||
"enter": function() { | "enter": function() { | ||||
// Memorize the origin position in case that we want to go back | // Memorize the origin position in case that we want to go back | ||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||
if (!cmpPosition || !cmpPosition.IsInWorld()) | if (!cmpPosition || !cmpPosition.IsInWorld() || | ||||
!this.MoveTo(this.order.data)) | |||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
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.StartTimer(0, 1000); | ||||
this.SetAnimationVariant("combat"); | this.SetAnimationVariant("combat"); | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | |||||
this.StopTimer(); | this.StopTimer(); | ||||
delete this.patrolStartPosOrder; | delete this.patrolStartPosOrder; | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
this.FindWalkAndFightTargets(); | this.FindWalkAndFightTargets(); | ||||
}, | }, | ||||
Show All 10 Lines | "INDIVIDUAL": { | ||||
"GUARD": { | "GUARD": { | ||||
"RemoveGuard": function() { | "RemoveGuard": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
"ESCORTING": { | "ESCORTING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveToTargetRangeExplicit(this.isGuardOf, 0, this.guardRange)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return; | |||||
} | |||||
// 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"); | ||||
this.SetHeldPositionOnEntity(this.isGuardOf); | this.SetHeldPositionOnEntity(this.isGuardOf); | ||||
return false; | return false; | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
// Check the target is alive | // Check the target is alive | ||||
if (!this.TargetIsAlive(this.isGuardOf)) | if (!this.TargetIsAlive(this.isGuardOf)) | ||||
{ | { | ||||
this.StopMoving(); | |||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
this.SetHeldPositionOnEntity(this.isGuardOf); | this.SetHeldPositionOnEntity(this.isGuardOf); | ||||
}, | }, | ||||
"leave": function(msg) { | "leave": function(msg) { | ||||
this.StopMoving(); | |||||
this.ResetSpeedMultiplier(); | this.ResetSpeedMultiplier(); | ||||
this.StopTimer(); | this.StopTimer(); | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
}, | }, | ||||
"MoveStarted": function(msg) { | "MoveStarted": function(msg) { | ||||
// Adapt the speed to the one of the target if needed | // Adapt the speed to the one of the target if needed | ||||
var cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | var cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | ||||
if (cmpObstructionManager.IsInTargetRange(this.entity, this.isGuardOf, 0, 3 * this.guardRange, true)) | if (cmpObstructionManager.IsInTargetRange(this.entity, this.isGuardOf, 0, 3 * this.guardRange, true)) | ||||
{ | { | ||||
var cmpUnitAI = Engine.QueryInterface(this.isGuardOf, IID_UnitAI); | var cmpUnitAI = Engine.QueryInterface(this.isGuardOf, IID_UnitAI); | ||||
if (cmpUnitAI) | if (cmpUnitAI) | ||||
{ | { | ||||
var speed = cmpUnitAI.GetWalkSpeed(); | var speed = cmpUnitAI.GetWalkSpeed(); | ||||
if (speed < this.GetWalkSpeed()) | if (speed < this.GetWalkSpeed()) | ||||
this.SetSpeedMultiplier(speed / this.GetWalkSpeed()); | this.SetSpeedMultiplier(speed / this.GetWalkSpeed()); | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.ResetSpeedMultiplier(); | this.ResetSpeedMultiplier(); | ||||
if (!this.MoveToTargetRangeExplicit(this.isGuardOf, 0, this.guardRange)) | if (this.CheckTargetRangeExplicit(this.isGuardOf, 0, this.guardRange)) | ||||
this.SetNextState("GUARDING"); | this.SetNextState("GUARDING"); | ||||
Not Done Inline ActionsDon't think that is correct, since we could be out of range, and then we need to move again bb: Don't think that is correct, since we could be out of range, and then we need to move again | |||||
}, | }, | ||||
}, | }, | ||||
"GUARDING": { | "GUARDING": { | ||||
"enter": function() { | "enter": function() { | ||||
this.StopMoving(); | |||||
this.StartTimer(1000, 1000); | this.StartTimer(1000, 1000); | ||||
this.SetHeldPositionOnEntity(this.entity); | this.SetHeldPositionOnEntity(this.entity); | ||||
this.SetAnimationVariant("combat"); | this.SetAnimationVariant("combat"); | ||||
this.SelectAnimation("idle"); | this.SelectAnimation("idle"); | ||||
return false; | return false; | ||||
}, | }, | ||||
"LosRangeUpdate": function(msg) { | "LosRangeUpdate": function(msg) { | ||||
// Start attacking one of the newly-seen enemy (if any) | // Start attacking one of the newly-seen enemy (if any) | ||||
if (this.GetStance().targetVisibleEnemies) | if (this.GetStance().targetVisibleEnemies) | ||||
this.AttackEntitiesByPreference(msg.data.added); | this.AttackEntitiesByPreference(msg.data.added); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
// Check the target is alive | // Check the target is alive | ||||
if (!this.TargetIsAlive(this.isGuardOf)) | if (!this.TargetIsAlive(this.isGuardOf)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
// then check is the target has moved | // Then check is the target has moved and try following it. | ||||
if (this.MoveToTargetRangeExplicit(this.isGuardOf, 0, this.guardRange)) | // TODO: find out what to do if we cannot move. | ||||
if (!this.CheckTargetRangeExplicit(this.isGuardOf, 0, this.guardRange) && | |||||
this.MoveToTargetRangeExplicit(this.isGuardOf, 0, this.guardRange)) | |||||
this.SetNextState("ESCORTING"); | this.SetNextState("ESCORTING"); | ||||
else | else | ||||
{ | { | ||||
// if nothing better to do, check if the guarded needs to be healed or repaired | // if nothing better to do, check if the guarded needs to be healed or repaired | ||||
var cmpHealth = Engine.QueryInterface(this.isGuardOf, IID_Health); | var cmpHealth = Engine.QueryInterface(this.isGuardOf, IID_Health); | ||||
if (cmpHealth && (cmpHealth.GetHitpoints() < cmpHealth.GetMaxHitpoints())) | if (cmpHealth && (cmpHealth.GetHitpoints() < cmpHealth.GetMaxHitpoints())) | ||||
{ | { | ||||
if (this.CanHeal(this.isGuardOf)) | if (this.CanHeal(this.isGuardOf)) | ||||
this.PushOrderFront("Heal", { "target": this.isGuardOf, "force": false }); | this.PushOrderFront("Heal", { "target": this.isGuardOf, "force": false }); | ||||
else if (this.CanRepair(this.isGuardOf)) | else if (this.CanRepair(this.isGuardOf)) | ||||
this.PushOrderFront("Repair", { "target": this.isGuardOf, "autocontinue": false, "force": false }); | this.PushOrderFront("Repair", { "target": this.isGuardOf, "autocontinue": false, "force": false }); | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"leave": function(msg) { | "leave": function(msg) { | ||||
this.StopTimer(); | this.StopTimer(); | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
"FLEEING": { | "FLEEING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return; | |||||
} | |||||
this.PlaySound("panic"); | this.PlaySound("panic"); | ||||
// Run quickly | // Run quickly | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
this.SetSpeedMultiplier(this.GetRunMultiplier()); | this.SetSpeedMultiplier(this.GetRunMultiplier()); | ||||
}, | }, | ||||
"HealthChanged": function() { | "HealthChanged": function() { | ||||
this.SetSpeedMultiplier(this.GetRunMultiplier()); | this.SetSpeedMultiplier(this.GetRunMultiplier()); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.ResetSpeedMultiplier(); | this.ResetSpeedMultiplier(); | ||||
this.StopMoving(); | |||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
// When we've run far enough, stop fleeing | // When we've run far enough, stop fleeing | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
// TODO: what if we run into more enemies while fleeing? | // TODO: what if we run into more enemies while fleeing? | ||||
Show All 9 Lines | "COMBAT": { | ||||
// If we're already in combat mode, ignore anyone else who's attacking us | // If we're already in combat mode, ignore anyone else who's attacking us | ||||
// unless it's a melee attack since they may be blocking our way to the target | // unless it's a melee attack since they may be blocking our way to the target | ||||
if (msg.data.type == "Melee" && (this.GetStance().targetAttackersAlways || !this.order.data.force)) | if (msg.data.type == "Melee" && (this.GetStance().targetAttackersAlways || !this.order.data.force)) | ||||
this.RespondToTargetedEntities([msg.data.attacker]); | this.RespondToTargetedEntities([msg.data.attacker]); | ||||
}, | }, | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveToTargetAttackRange(this.order.data.target, this.order.data.attackType)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return; | |||||
} | |||||
// 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); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
// Show carried resources when walking. | // Show carried resources when walking. | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
this.StopMoving(); | |||||
this.StopTimer(); | this.StopTimer(); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force, IID_Attack, this.order.data.attackType)) | if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force, IID_Attack, this.order.data.attackType)) | ||||
{ | { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | "COMBAT": { | ||||
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; | return; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
this.StopMoving(); | |||||
var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | var 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; | var prepare = this.attackTimers.prepare; | ||||
if (this.lastAttacked) | if (this.lastAttacked) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | "COMBAT": { | ||||
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") | ||||
this.RespondToTargetedEntities([msg.data.attacker]); | this.RespondToTargetedEntities([msg.data.attacker]); | ||||
}, | }, | ||||
}, | }, | ||||
"CHASING": { | "CHASING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return; | |||||
} | |||||
// 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); | var cmpUnitAI = Engine.QueryInterface(this.order.data.target, IID_UnitAI); | ||||
if (cmpUnitAI && cmpUnitAI.IsFleeing()) | if (cmpUnitAI && cmpUnitAI.IsFleeing()) | ||||
{ | { | ||||
// Run after a fleeing target | // Run after a fleeing target | ||||
this.SetSpeedMultiplier(this.GetRunMultiplier()); | this.SetSpeedMultiplier(this.GetRunMultiplier()); | ||||
} | } | ||||
this.StartTimer(1000, 1000); | this.StartTimer(1000, 1000); | ||||
}, | }, | ||||
"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.StopTimer(); | this.StopTimer(); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force, IID_Attack, this.order.data.attackType)) | if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force, IID_Attack, this.order.data.attackType)) | ||||
{ | { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
// Return to our original position | // Return to our original position | ||||
if (this.GetStance().respondHoldGround) | if (this.GetStance().respondHoldGround) | ||||
this.WalkToHeldPosition(); | this.WalkToHeldPosition(); | ||||
} | } | ||||
}, | }, | ||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.SetNextState("ATTACKING"); | this.SetNextState("ATTACKING"); | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
"GATHER": { | "GATHER": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
this.SelectAnimation("move"); | |||||
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); | var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | ||||
var cmpMirage = Engine.QueryInterface(this.gatheringTarget, IID_Mirage); | var 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))) | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | "GATHER": { | ||||
{ | { | ||||
this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); | this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
// We can gather from out target, so try to move there. | |||||
if (!this.MoveTo(this.order.data, IID_ResourceGatherer)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
this.SelectAnimation("move"); | |||||
return false; | return false; | ||||
}, | }, | ||||
"MoveCompleted": function(msg) { | "MoveCompleted": function(msg) { | ||||
if (msg.data.error) | if (msg.data.error) | ||||
{ | { | ||||
// We failed to reach the target | // We failed to reach the target | ||||
Show All 36 Lines | "GATHER": { | ||||
return; | return; | ||||
} | } | ||||
// We reached the target - start gathering from it now | // We reached the target - start gathering from it now | ||||
this.SetNextState("GATHERING"); | this.SetNextState("GATHERING"); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | |||||
this.SetDefaultAnimationVariant(); | |||||
if (!this.gatheringTarget) | |||||
return; | |||||
// don't use ownership because this is called after a conversion/resignation | // don't use ownership because this is called after a conversion/resignation | ||||
// and the ownership would be invalid then. | // and the ownership would be invalid then. | ||||
var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | ||||
if (cmpSupply) | if (cmpSupply) | ||||
cmpSupply.RemoveGatherer(this.entity); | cmpSupply.RemoveGatherer(this.entity); | ||||
delete this.gatheringTarget; | delete this.gatheringTarget; | ||||
this.SetDefaultAnimationVariant(); | |||||
}, | }, | ||||
}, | }, | ||||
// Walking to a good place to gather resources near, used by GatherNearPosition | // Walking to a good place to gather resources near, used by GatherNearPosition | ||||
"WALKING": { | "WALKING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return; | |||||
} | |||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
}, | }, | ||||
"leave": function() { | |||||
this.StopMoving(); | |||||
}, | |||||
"MoveCompleted": function(msg) { | "MoveCompleted": function(msg) { | ||||
var resourceType = this.order.data.type; | var resourceType = this.order.data.type; | ||||
var resourceTemplate = this.order.data.template; | var resourceTemplate = this.order.data.template; | ||||
// Try to find another nearby target of the same specific type | // Try to find another nearby target of the same specific type | ||||
// Also don't switch to a different type of huntable animal | // Also don't switch to a different type of huntable animal | ||||
var nearby = this.FindNearbyResource(function(ent, type, template) { | var nearby = this.FindNearbyResource(function(ent, type, template) { | ||||
return ( | return ( | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | "GATHER": { | ||||
// 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.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
var typename = "gather_" + this.order.data.type.specific; | var typename = "gather_" + this.order.data.type.specific; | ||||
this.SelectAnimation(typename); | this.SelectAnimation(typename); | ||||
} | } | ||||
return false; | return false; | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | "GATHER": { | ||||
// Can't reach the target, or it doesn't exist any more | // Can't reach the target, or it doesn't exist any more | ||||
// We want to carry on gathering resources in the same area as | // We want to carry on gathering resources in the same area as | ||||
// the old one. So try to get close to the old resource's | // the old one. So try to get close to the old resource's | ||||
// last known position | // last known position | ||||
var maxRange = 8; // get close but not too close | var maxRange = 8; // get close but not too close | ||||
if (this.order.data.lastPos && | if (this.order.data.lastPos && | ||||
this.MoveToPointRange(this.order.data.lastPos.x, this.order.data.lastPos.z, | this.MoveToPointRange(this.order.data.lastPos.x, this.order.data.lastPos.z, 0, maxRange)) | ||||
0, maxRange)) | |||||
{ | { | ||||
this.SetNextState("APPROACHING"); | this.SetNextState("APPROACHING"); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// We're already in range, can't get anywhere near it or the target is exhausted. | // We're already in range, can't get anywhere near it or the target is exhausted. | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | "HEAL": { | ||||
"Attacked": function(msg) { | "Attacked": function(msg) { | ||||
// If we stand ground we will rather die than flee | // If we stand ground we will rather die than flee | ||||
if (!this.GetStance().respondStandGround && !this.order.data.force) | if (!this.GetStance().respondStandGround && !this.order.data.force) | ||||
this.Flee(msg.data.attacker, false); | this.Flee(msg.data.attacker, false); | ||||
}, | }, | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (this.CheckTargetRange(this.order.data.target, IID_Heal)) | |||||
{ | |||||
this.SetNextState("HEALING"); | |||||
return true; | |||||
} | |||||
if (!this.MoveTo(this.order.data, IID_Heal)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
this.StartTimer(1000, 1000); | this.StartTimer(1000, 1000); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
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)) | ||||
{ | { | ||||
this.StopMoving(); | // Return to our original position unless we have a better order. | ||||
this.FinishOrder(); | if (!this.FinishOrder() && this.GetStance().respondHoldGround) | ||||
// Return to our original position | |||||
if (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); | var 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; | var prepare = this.healTimers.prepare; | ||||
if (this.lastHealed) | if (this.lastHealed) | ||||
{ | { | ||||
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | ||||
var repeatLeft = this.lastHealed + this.healTimers.repeat - cmpTimer.GetTime(); | var repeatLeft = this.lastHealed + this.healTimers.repeat - cmpTimer.GetTime(); | ||||
prepare = Math.max(prepare, repeatLeft); | prepare = Math.max(prepare, repeatLeft); | ||||
} | } | ||||
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); | ||||
Show All 28 Lines | "HEAL": { | ||||
// 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; | ||||
} | } | ||||
if (this.MoveToTargetRange(target, IID_Heal)) | this.SetNextState("HEAL.APPROACHING"); | ||||
{ | |||||
this.SetNextState("HEAL.CHASING"); | |||||
return; | |||||
} | |||||
} | } | ||||
} | } | ||||
// Can't reach it, healed to max hp or doesn't exist any more - give up | // Can't reach it, healed to max hp or doesn't exist any more - give up | ||||
if (this.FinishOrder()) | if (this.FinishOrder()) | ||||
return; | return; | ||||
// Heal another one | // Heal another one | ||||
if (this.FindNewHealTargets()) | if (this.FindNewHealTargets()) | ||||
return; | return; | ||||
// Return to our original position | // Return to our original position | ||||
if (this.GetStance().respondHoldGround) | if (this.GetStance().respondHoldGround) | ||||
this.WalkToHeldPosition(); | this.WalkToHeldPosition(); | ||||
}, | }, | ||||
}, | }, | ||||
"CHASING": { | |||||
"enter": function() { | |||||
this.SelectAnimation("move"); | |||||
this.StartTimer(1000, 1000); | |||||
}, | |||||
"leave": function() { | |||||
this.StopTimer(); | |||||
}, | |||||
"Timer": function(msg) { | |||||
if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force, IID_Heal, null)) | |||||
{ | |||||
this.StopMoving(); | |||||
this.FinishOrder(); | |||||
// Return to our original position | |||||
if (this.GetStance().respondHoldGround) | |||||
this.WalkToHeldPosition(); | |||||
} | |||||
}, | |||||
"MoveCompleted": function() { | |||||
this.SetNextState("HEALING"); | |||||
}, | |||||
}, | |||||
}, | }, | ||||
// Returning to dropsite | // Returning to dropsite | ||||
"RETURNRESOURCE": { | "RETURNRESOURCE": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
}, | }, | ||||
"MoveCompleted": 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"); | ||||
}, | |||||
"MoveCompleted": function() { | |||||
// Check the dropsite is in range and we can return our resource there | // Check the dropsite is in range and we can return our resource there | ||||
// (we didn't get stopped before reaching it) | // (we didn't get stopped before reaching it) | ||||
if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer) && this.CanReturnResource(this.order.data.target, true)) | if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer) && this.CanReturnResource(this.order.data.target, true)) | ||||
{ | { | ||||
var cmpResourceDropsite = Engine.QueryInterface(this.order.data.target, IID_ResourceDropsite); | var cmpResourceDropsite = Engine.QueryInterface(this.order.data.target, IID_ResourceDropsite); | ||||
if (cmpResourceDropsite) | if (cmpResourceDropsite) | ||||
{ | { | ||||
// Dump any resources we can | // Dump any resources we can | ||||
Show All 34 Lines | |||||
"TRADE": { | "TRADE": { | ||||
"Attacked": function(msg) { | "Attacked": function(msg) { | ||||
// Ignore attack | // Ignore attack | ||||
// TODO: Inform player | // TODO: Inform player | ||||
}, | }, | ||||
"APPROACHINGMARKET": { | "APPROACHINGMARKET": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveToMarket(this.order.data.target)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return; | |||||
} | |||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
}, | }, | ||||
"leave": function() { | |||||
this.StopMoving(); | |||||
}, | |||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
if (this.waypoints && this.waypoints.length) | if (this.waypoints && this.waypoints.length) | ||||
{ | { | ||||
if (!this.MoveToMarket(this.order.data.target)) | if (!this.MoveToMarket(this.order.data.target)) | ||||
this.StopTrading(); | this.StopTrading(); | ||||
} | } | ||||
else | else | ||||
this.PerformTradeAndMoveToNextMarket(this.order.data.target); | this.PerformTradeAndMoveToNextMarket(this.order.data.target); | ||||
Show All 9 Lines | "TRADE": { | ||||
if (otherMarket) | if (otherMarket) | ||||
this.WalkToTarget(otherMarket); | this.WalkToTarget(otherMarket); | ||||
}, | }, | ||||
}, | }, | ||||
"REPAIR": { | "REPAIR": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
}, | }, | ||||
"leave": function() { | |||||
this.StopMoving(); | |||||
}, | |||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.SetNextState("REPAIRING"); | this.SetNextState("REPAIRING"); | ||||
}, | }, | ||||
}, | }, | ||||
"REPAIRING": { | "REPAIRING": { | ||||
"enter": function() { | "enter": function() { | ||||
// 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 | ||||
Show All 25 Lines | "REPAIR": { | ||||
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; | ||||
} | } | ||||
this.StopMoving(); | |||||
let cmpBuilderList = QueryBuilderListInterface(this.repairTarget); | let cmpBuilderList = QueryBuilderListInterface(this.repairTarget); | ||||
if (cmpBuilderList) | if (cmpBuilderList) | ||||
cmpBuilderList.AddBuilder(this.entity); | cmpBuilderList.AddBuilder(this.entity); | ||||
this.SelectAnimation("build"); | this.SelectAnimation("build"); | ||||
this.StartTimer(1000, 1000); | this.StartTimer(1000, 1000); | ||||
return false; | return false; | ||||
}, | }, | ||||
Show All 17 Lines | "REPAIR": { | ||||
var cmpBuilder = Engine.QueryInterface(this.entity, IID_Builder); | var cmpBuilder = Engine.QueryInterface(this.entity, IID_Builder); | ||||
cmpBuilder.PerformBuilding(this.repairTarget); | cmpBuilder.PerformBuilding(this.repairTarget); | ||||
// if the building is completed, the leave() function will be called | // if the building is completed, the leave() function will be called | ||||
// by the ConstructionFinished message | // by the ConstructionFinished message | ||||
// in that case, the repairTarget is deleted, and we can just return | // in that case, the repairTarget is deleted, and we can just return | ||||
if (!this.repairTarget) | if (!this.repairTarget) | ||||
return; | return; | ||||
if (this.MoveToTargetRange(this.repairTarget, IID_Builder)) | let inRange = this.CheckTargetRange(this.repairTarget, IID_Builder); | ||||
if (!inRange && this.MoveToTargetRange(this.repairTarget, IID_Builder)) | |||||
this.SetNextState("APPROACHING"); | this.SetNextState("APPROACHING"); | ||||
else if (!this.CheckTargetRange(this.repairTarget, IID_Builder)) | else if (!inRange) | ||||
this.FinishOrder(); //can't approach and isn't in reach | this.FinishOrder(); //can't approach and isn't in reach | ||||
Done Inline ActionsHere is an example where we really want MoveToTargetRange to return "false" if the goal is unreachable, and not if movement isn't necessary. wraitii: Here is an example where we really want MoveToTargetRange to return "false" if the goal is… | |||||
Not Done Inline ActionsMaybe more straightforward written as: let isInRange = this.CheckTargetRange(this.repairTarget, IID_Builder); if (!isInRange) { if (this.MoveToTargetRange(this.repairTarget, IID_Builder)) { this.SetNextState("APPROACHING"); return; } // Can't approach and isn't in reach this.FinishOrder(); } Stan: Maybe more straightforward written as:
```lang=js
let isInRange = this.CheckTargetRange(this. | |||||
}, | }, | ||||
}, | }, | ||||
"ConstructionFinished": function(msg) { | "ConstructionFinished": function(msg) { | ||||
if (msg.data.entity != this.order.data.target) | if (msg.data.entity != this.order.data.target) | ||||
return; // ignore other buildings | return; // ignore other buildings | ||||
// Save the current order's data in case we need it later | // Save the current order's data in case we need it later | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | "GARRISON": { | ||||
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)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
}, | }, | ||||
"leave": function() { | |||||
this.StopMoving(); | |||||
}, | |||||
"MoveCompleted": function() { | "MoveCompleted": function() { | ||||
this.SetNextState("GARRISONED"); | this.SetNextState("GARRISONED"); | ||||
}, | }, | ||||
}, | }, | ||||
"GARRISONED": { | "GARRISONED": { | ||||
"enter": function() { | "enter": function() { | ||||
if (this.order.data.target) | if (this.order.data.target) | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | "GARRISON": { | ||||
var cmpUnitAI = Engine.QueryInterface(this.pickup, IID_UnitAI); | var 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.MoveToTarget(target)) | if (!this.CheckTargetRangeExplicit(target, 0, 0) && this.MoveToTarget(target)) | ||||
{ | { | ||||
this.SetNextState("APPROACHING"); | this.SetNextState("APPROACHING"); | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Garrisoning failed for some reason, so finish the order | // Garrisoning failed for some reason, so finish the order | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
Show All 23 Lines | "CHEERING": { | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
"PACKING": { | "PACKING": { | ||||
"enter": function() { | "enter": function() { | ||||
this.StopMoving(); | |||||
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | ||||
cmpPack.Pack(); | cmpPack.Pack(); | ||||
}, | }, | ||||
"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(); | |||||
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | ||||
cmpPack.Unpack(); | cmpPack.Unpack(); | ||||
}, | }, | ||||
"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)) | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
}, | }, | ||||
"leave": function() { | |||||
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.SelectAnimation("idle"); | this.SelectAnimation("idle"); | ||||
var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); | var 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 All 22 Lines | "Attacked": function(msg) { | ||||
{ | { | ||||
// Never flee, stop what we were doing | // Never flee, stop what we were doing | ||||
this.SetNextState("IDLE"); | this.SetNextState("IDLE"); | ||||
} | } | ||||
}, | }, | ||||
"Order.LeaveFoundation": function(msg) { | "Order.LeaveFoundation": function(msg) { | ||||
// Move a tile outside the building | // Move a tile outside the building | ||||
var range = 4; | var range = 4; | ||||
Not Done Inline ActionsShould probably be a global constant or something. Not related to this diff I guess. Only three ocurrences 229 let range = 4; 1326 let range = 4; 3095 var range = 4 Stan: Should probably be a global constant or something. Not related to this diff I guess.
Only… | |||||
if (this.MoveToTargetRangeExplicit(msg.data.target, range, range)) | if (this.CheckTargetRangeExplicit(msg.data.target, range, range)) | ||||
{ | { | ||||
Not Done Inline ActionsI remember @elexis saying we should indent with four spaces instead of tabs for ifs statements Stan: I remember @elexis saying we should indent with four spaces instead of tabs for ifs statements | |||||
// We've started walking to the given point | this.FinishOrder(); | ||||
this.SetNextState("WALKING"); | return; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// We are already at the target, or can't move at all | this.order.data.min = range; | ||||
this.FinishOrder(); | this.SetNextState("WALKING"); | ||||
} | } | ||||
}, | }, | ||||
"IDLE": { | "IDLE": { | ||||
// (We need an IDLE state so that FinishOrder works) | // (We need an IDLE state so that FinishOrder works) | ||||
"enter": function() { | "enter": function() { | ||||
// Start feeding immediately | // Start feeding immediately | ||||
this.SetNextState("FEEDING"); | this.SetNextState("FEEDING"); | ||||
return true; | return true; | ||||
}, | }, | ||||
}, | }, | ||||
"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)); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | |||||
this.StopTimer(); | this.StopTimer(); | ||||
this.SetFacePointAfterMove(true); | this.SetFacePointAfterMove(true); | ||||
}, | }, | ||||
"LosRangeUpdate": function(msg) { | "LosRangeUpdate": function(msg) { | ||||
if (this.template.NaturalBehaviour == "skittish") | if (this.template.NaturalBehaviour == "skittish") | ||||
{ | { | ||||
if (msg.data.added.length > 0) | if (msg.data.added.length > 0) | ||||
▲ Show 20 Lines • Show All 1,090 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
UnitAI.prototype.StopMoving = function() | UnitAI.prototype.StopMoving = function() | ||||
{ | { | ||||
var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | ||||
cmpUnitMotion.StopMoving(); | cmpUnitMotion.StopMoving(); | ||||
}; | }; | ||||
/** | |||||
* Generic dispatcher for other MoveTo functions. | |||||
* @param iid - Interface ID (optional) implementing GetRange | |||||
* @param type - Range type for the interface call | |||||
* @returns whether the move succeeded or failed. | |||||
*/ | |||||
UnitAI.prototype.MoveTo = function(data, iid, type) | |||||
{ | |||||
if (data["target"]) | |||||
{ | |||||
if (data["min"] || data["max"]) | |||||
return this.MoveToTargetRangeExplicit(data.target, data.min || -1, data.max || -1); | |||||
else | |||||
{ | |||||
if (!iid) | |||||
return this.MoveToTarget(data.target); | |||||
else | |||||
return this.MoveToTargetRange(data.target, iid, type); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
if (data["min"] || data["max"]) | |||||
return this.MoveToPointRange(data.x, data.z, data.min || -1, data.max || -1); | |||||
else | |||||
return this.MoveToPoint(data.x, data.z); | |||||
} | |||||
} | |||||
UnitAI.prototype.MoveToPoint = function(x, z) | UnitAI.prototype.MoveToPoint = function(x, z) | ||||
{ | { | ||||
var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | ||||
return cmpUnitMotion.MoveToPointRange(x, z, 0, 0); | return cmpUnitMotion.MoveToPointRange(x, z, 0, 0); | ||||
}; | }; | ||||
UnitAI.prototype.MoveToPointRange = function(x, z, rangeMin, rangeMax) | UnitAI.prototype.MoveToPointRange = function(x, z, rangeMin, rangeMax) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,724 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
Not sure we need the braces here. Or could be an early return maybe ?