Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | UnitAI.prototype.UnitFsmSpec = { | ||||
"TradingCanceled": function(msg) { | "TradingCanceled": function(msg) { | ||||
// ignore | // ignore | ||||
}, | }, | ||||
"GuardedAttacked": function(msg) { | "GuardedAttacked": function(msg) { | ||||
// ignore | // ignore | ||||
}, | }, | ||||
"OrderTargetRenamed": function() { | |||||
// By default, trigger an exit-reenter | |||||
// so that state preconditions are checked against the new entity | |||||
// (there is no reason to assume the target is still valid). | |||||
this.SetNextState(this.GetCurrentState()); | |||||
}, | |||||
// Formation handlers: | // Formation handlers: | ||||
"FormationLeave": function(msg) { | "FormationLeave": function(msg) { | ||||
// ignore when we're not in FORMATIONMEMBER | // ignore when we're not in FORMATIONMEMBER | ||||
}, | }, | ||||
// Called when being told to walk as part of a formation | // Called when being told to walk as part of a formation | ||||
"Order.FormationWalk": function(msg) { | "Order.FormationWalk": function(msg) { | ||||
▲ Show 20 Lines • Show All 1,576 Lines • ▼ Show 20 Lines | "FLEEING": { | ||||
this.PlaySound("panic"); | this.PlaySound("panic"); | ||||
// Run quickly | // Run quickly | ||||
this.SetSpeedMultiplier(this.GetRunMultiplier()); | this.SetSpeedMultiplier(this.GetRunMultiplier()); | ||||
return false; | return false; | ||||
}, | }, | ||||
"OrderTargetRenamed": function(msg) { | |||||
// To avoid replaying the panic sound, handle this explicitly. | |||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | |||||
if (this.CheckTargetRangeExplicit(this.order.data.target, this.order.data.distanceToFlee, -1) || | |||||
!cmpUnitMotion || !cmpUnitMotion.MoveToTargetRange(this.order.data.target, this.order.data.distanceToFlee, -1)) | |||||
this.FinishOrder(); | |||||
}, | |||||
"HealthChanged": function() { | "HealthChanged": function() { | ||||
this.SetSpeedMultiplier(this.GetRunMultiplier()); | this.SetSpeedMultiplier(this.GetRunMultiplier()); | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.ResetSpeedMultiplier(); | this.ResetSpeedMultiplier(); | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 173 Lines • ▼ Show 20 Lines | "COMBAT": { | ||||
if (cmpBuildingAI) | if (cmpBuildingAI) | ||||
cmpBuildingAI.SetUnitAITarget(0); | cmpBuildingAI.SetUnitAITarget(0); | ||||
this.StopTimer(); | this.StopTimer(); | ||||
this.ResetAnimation(); | this.ResetAnimation(); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
let target = this.order.data.target; | let target = this.order.data.target; | ||||
let attackType = this.order.data.attackType; | |||||
// Check the target is still alive and attackable | // Check the target is still alive and attackable | ||||
if (!this.CanAttack(target)) | if (!this.CanAttack(target)) | ||||
{ | { | ||||
this.SetNextState("COMBAT.FINDINGNEWTARGET"); | this.SetNextState("COMBAT.FINDINGNEWTARGET"); | ||||
return; | return; | ||||
} | } | ||||
this.RememberTargetPosition(); | this.RememberTargetPosition(); | ||||
if (this.order.data.hunting && this.orderQueue.length > 1 && this.orderQueue[1].type === "Gather") | if (this.order.data.hunting && this.orderQueue.length > 1 && this.orderQueue[1].type === "Gather") | ||||
this.RememberTargetPosition(this.orderQueue[1].data); | this.RememberTargetPosition(this.orderQueue[1].data); | ||||
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); | ||||
this.lastAttacked = cmpTimer.GetTime() - msg.lateness; | this.lastAttacked = cmpTimer.GetTime() - msg.lateness; | ||||
this.FaceTowardsTarget(target); | this.FaceTowardsTarget(target); | ||||
// BuildingAI has it's own attack-routine | // BuildingAI has it's own attack-routine | ||||
let cmpBuildingAI = Engine.QueryInterface(this.entity, IID_BuildingAI); | let cmpBuildingAI = Engine.QueryInterface(this.entity, IID_BuildingAI); | ||||
if (!cmpBuildingAI) | if (!cmpBuildingAI) | ||||
{ | { | ||||
let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | ||||
cmpAttack.PerformAttack(this.order.data.attackType, target); | cmpAttack.PerformAttack(attackType, target); | ||||
} | } | ||||
// PerformAttack might have triggered messages that moved us to another state. | |||||
// (use 'ends with' to handle animals/formation members copying our state). | |||||
if (!this.GetCurrentState().endsWith("COMBAT.ATTACKING")) | |||||
return; | |||||
// Check we can still reach the target for the next attack | // Check we can still reach the target for the next attack | ||||
if (this.CheckTargetAttackRange(target, this.order.data.attackType)) | if (this.CheckTargetAttackRange(target, attackType)) | ||||
{ | { | ||||
if (this.resyncAnimation) | if (this.resyncAnimation) | ||||
{ | { | ||||
this.SetAnimationSync(this.attackTimers.repeat, this.attackTimers.repeat); | this.SetAnimationSync(this.attackTimers.repeat, this.attackTimers.repeat); | ||||
this.resyncAnimation = false; | this.resyncAnimation = false; | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 940 Lines • ▼ Show 20 Lines | "REPAIR": { | ||||
let nearbyFoundation = this.FindNearbyFoundation(this.TargetPosOrEntPos(msg.data.newentity)); | let nearbyFoundation = this.FindNearbyFoundation(this.TargetPosOrEntPos(msg.data.newentity)); | ||||
if (nearbyFoundation) | if (nearbyFoundation) | ||||
{ | { | ||||
this.AddOrder("Repair", { "target": nearbyFoundation, "autocontinue": oldData.autocontinue, "force": false }, true); | this.AddOrder("Repair", { "target": nearbyFoundation, "autocontinue": oldData.autocontinue, "force": false }, true); | ||||
return; | return; | ||||
} | } | ||||
// Unit was approaching and there's nothing to do now, so switch to walking | // Unit was approaching and there's nothing to do now, so switch to walking | ||||
if (oldState === "INDIVIDUAL.REPAIR.APPROACHING") | if (oldState.endsWith("REPAIR.APPROACHING")) | ||||
wraitii: should probably update here also. This is from rP9797 . | |||||
// We're already walking to the given point, so add this as a order. | // We're already walking to the given point, so add this as a order. | ||||
this.WalkToTarget(msg.data.newentity, true); | this.WalkToTarget(msg.data.newentity, true); | ||||
}, | }, | ||||
}, | }, | ||||
"GARRISON": { | "GARRISON": { | ||||
"leave": function() { | "leave": function() { | ||||
// If a pickup has been requested and not yet canceled, cancel it. | // If a pickup has been requested and not yet canceled, cancel it. | ||||
▲ Show 20 Lines • Show All 1,175 Lines • ▼ Show 20 Lines | UnitAI.prototype.OnGlobalConstructionFinished = function(msg) | ||||
// construction message - ideally we could scope it to only the one we're building | // construction message - ideally we could scope it to only the one we're building | ||||
this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg}); | this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg}); | ||||
}; | }; | ||||
UnitAI.prototype.OnGlobalEntityRenamed = function(msg) | UnitAI.prototype.OnGlobalEntityRenamed = function(msg) | ||||
{ | { | ||||
let changed = false; | let changed = false; | ||||
for (let order of this.orderQueue) | let currentOrderChanged = false; | ||||
for (let i = 0; i < this.orderQueue.length; ++i) | |||||
{ | { | ||||
let order = this.orderQueue[i]; | |||||
if (order.data && order.data.target && order.data.target == msg.entity) | if (order.data && order.data.target && order.data.target == msg.entity) | ||||
StanUnsubmitted Not Done Inline ActionsDo we need to check twice for order.data or can it merged somehow to early continue? Stan: Do we need to check twice for order.data or can it merged somehow to early continue? | |||||
wraitiiAuthorUnsubmitted Done Inline ActionsSeems a little annoying for limited benefit to be honest. wraitii: Seems a little annoying for limited benefit to be honest. | |||||
{ | { | ||||
changed = true; | changed = true; | ||||
if (i == 0) | |||||
currentOrderChanged = true; | |||||
order.data.target = msg.newentity; | order.data.target = msg.newentity; | ||||
} | } | ||||
if (order.data && order.data.formationTarget && order.data.formationTarget == msg.entity) | if (order.data && order.data.formationTarget && order.data.formationTarget == msg.entity) | ||||
{ | { | ||||
changed = true; | changed = true; | ||||
if (i == 0) | |||||
currentOrderChanged = true; | |||||
order.data.formationTarget = msg.newentity; | order.data.formationTarget = msg.newentity; | ||||
} | } | ||||
} | } | ||||
if (this.repairTarget && this.repairTarget == msg.entity) | if (!changed) | ||||
this.repairTarget = msg.newentity; | return; | ||||
if (currentOrderChanged) | |||||
this.UnitFsm.ProcessMessage(this, { "type": "OrderTargetRenamed", "data": msg }); | |||||
if (changed) | |||||
Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | ||||
}; | }; | ||||
UnitAI.prototype.OnAttacked = function(msg) | UnitAI.prototype.OnAttacked = function(msg) | ||||
{ | { | ||||
if (msg.fromStatusEffect) | if (msg.fromStatusEffect) | ||||
return; | return; | ||||
this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg}); | this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg}); | ||||
▲ Show 20 Lines • Show All 2,217 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
should probably update here also. This is from rP9797 .