Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 956 Lines • ▼ Show 20 Lines | "WALKING": { | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | ||||
if (msg.likelyFailure || this.CheckRange(this.order.data)) | if (msg.likelyFailure || this.CheckRange(this.order.data)) | ||||
{ | |||||
this.FinishOrder(); | this.FinishOrder(); | ||||
this.CallMemberFunction("ResetFinishOrder", []); | |||||
} | |||||
}, | }, | ||||
}, | }, | ||||
"WALKINGANDFIGHTING": { | "WALKINGANDFIGHTING": { | ||||
"enter": function(msg) { | "enter": function(msg) { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
Show All 13 Lines | "WALKINGANDFIGHTING": { | ||||
"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(); | ||||
}, | }, | ||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | ||||
if (msg.likelyFailure || this.CheckRange(this.order.data)) | if (msg.likelyFailure || this.CheckRange(this.order.data)) | ||||
{ | |||||
this.FinishOrder(); | this.FinishOrder(); | ||||
this.CallMemberFunction("ResetFinishOrder", []); | |||||
} | |||||
}, | }, | ||||
}, | }, | ||||
"PATROL": { | "PATROL": { | ||||
"enter": function(msg) { | "enter": function(msg) { | ||||
// Memorize the origin position in case that we want to go back | // Memorize the origin position in case that we want to go back | ||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||
if (!cmpPosition || !cmpPosition.IsInWorld()) | if (!cmpPosition || !cmpPosition.IsInWorld()) | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | "FORMING": { | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | ||||
if (!msg.likelyFailure && !this.CheckRange(this.order.data)) | if (!msg.likelyFailure && !this.CheckRange(this.order.data)) | ||||
return; | return; | ||||
if (this.FinishOrder()) | this.FinishOrder(); | ||||
{ | |||||
this.CallMemberFunction("ResetFinishOrder", []); | |||||
return; | |||||
} | |||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | |||||
cmpFormation.FindInPosition(); | |||||
} | } | ||||
}, | }, | ||||
"COMBAT": { | "COMBAT": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveFormationToTargetAttackRange(this.order.data.target)) | if (!this.MoveFormationToTargetAttackRange(this.order.data.target)) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | "MEMBER": { | ||||
cmpFormation.SetRearrange(false); | cmpFormation.SetRearrange(false); | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.StartTimer(1000, 1000); | this.StartTimer(1000, 1000); | ||||
return false; | return false; | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
// Have all members finished the task? | // Have all members finished the task? | ||||
if (!this.TestAllMemberFunction("HasFinishedOrder", [])) | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
if (cmpFormation && !cmpFormation.AreAllMembersWaiting()) | |||||
return; | return; | ||||
this.CallMemberFunction("ResetFinishOrder", []); | |||||
// Execute the next order | // Execute the next order | ||||
if (this.FinishOrder()) | if (this.FinishOrder()) | ||||
{ | { | ||||
// if WalkAndFight order, look for new target before moving again | // if WalkAndFight order, look for new target before moving again | ||||
if (this.IsWalkingAndFighting()) | if (this.IsWalkingAndFighting()) | ||||
this.FindWalkAndFightTargets(); | this.FindWalkAndFightTargets(); | ||||
return; | return; | ||||
} | } | ||||
return false; | return false; | ||||
}, | }, | ||||
"leave": function(msg) { | "leave": function(msg) { | ||||
this.StopTimer(); | this.StopTimer(); | ||||
let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
cmpFormation.MoveToMembersCenter(); | cmpFormation.MoveToMembersCenter(); | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
// States for entities moving as part of a formation: | // States for entities moving as part of a formation: | ||||
"FORMATIONMEMBER": { | "FORMATIONMEMBER": { | ||||
"FormationLeave": function(msg) { | "FormationLeave": function(msg) { | ||||
// We're not in a formation anymore, so no need to track this. | |||||
this.finishedOrder = false; | |||||
// Stop moving as soon as the formation disbands | // Stop moving as soon as the formation disbands | ||||
this.StopMoving(); | this.StopMoving(); | ||||
// If the controller handled an order but some members rejected it, | // If the controller handled an order but some members rejected it, | ||||
// they will have no orders and be in the FORMATIONMEMBER.IDLE state. | // they will have no orders and be in the FORMATIONMEMBER.IDLE state. | ||||
if (this.orderQueue.length) | if (this.orderQueue.length) | ||||
{ | { | ||||
// We're leaving the formation, so stop our FormationWalk order | // We're leaving the formation, so stop our FormationWalk order | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | "WALKING": { | ||||
atDestination = this.CheckPointRangeExplicit(pos.X + this.order.data.x, pos.Y + this.order.data.z, 0, 1); | atDestination = this.CheckPointRangeExplicit(pos.X + this.order.data.x, pos.Y + this.order.data.z, 0, 1); | ||||
} | } | ||||
if (!atDestination && !msg.likelyFailure) | if (!atDestination && !msg.likelyFailure) | ||||
return; | return; | ||||
if (this.FinishOrder()) | if (this.FinishOrder()) | ||||
return; | return; | ||||
let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | |||||
if (cmpFormation) | |||||
cmpFormation.SetInPosition(this.entity); | |||||
delete this.formationOffset; | delete this.formationOffset; | ||||
}, | }, | ||||
}, | }, | ||||
// 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); | |||||
if (cmpFormation) | |||||
cmpFormation.UnsetInPosition(this.entity); | |||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 1,969 Lines • ▼ Show 20 Lines | |||||
UnitAI.prototype.Init = function() | UnitAI.prototype.Init = function() | ||||
{ | { | ||||
this.orderQueue = []; // current order is at the front of the list | this.orderQueue = []; // current order is at the front of the list | ||||
this.order = undefined; // always == this.orderQueue[0] | this.order = undefined; // always == this.orderQueue[0] | ||||
this.formationController = INVALID_ENTITY; // entity with IID_Formation that we belong to | this.formationController = INVALID_ENTITY; // entity with IID_Formation that we belong to | ||||
this.isGarrisoned = false; | this.isGarrisoned = false; | ||||
this.isIdle = false; | this.isIdle = false; | ||||
this.isImmobile = false; // True if the unit is currently unable to move (garrisoned,...) | this.isImmobile = false; // True if the unit is currently unable to move (garrisoned,...) | ||||
this.finishedOrder = false; // used to find if all formation members finished the order | |||||
this.heldPosition = undefined; | this.heldPosition = undefined; | ||||
// Queue of remembered works | // Queue of remembered works | ||||
this.workOrders = []; | this.workOrders = []; | ||||
this.isGuardOf = undefined; | this.isGuardOf = undefined; | ||||
Show All 19 Lines | UnitAI.prototype.IsFormationController = function() | ||||
return (this.template.FormationController == "true"); | return (this.template.FormationController == "true"); | ||||
}; | }; | ||||
UnitAI.prototype.IsFormationMember = function() | UnitAI.prototype.IsFormationMember = function() | ||||
{ | { | ||||
return (this.formationController != INVALID_ENTITY); | return (this.formationController != INVALID_ENTITY); | ||||
}; | }; | ||||
UnitAI.prototype.HasFinishedOrder = function() | |||||
{ | |||||
return this.finishedOrder; | |||||
}; | |||||
UnitAI.prototype.ResetFinishOrder = function() | |||||
{ | |||||
this.finishedOrder = false; | |||||
}; | |||||
UnitAI.prototype.IsAnimal = function() | UnitAI.prototype.IsAnimal = function() | ||||
{ | { | ||||
return (this.template.NaturalBehaviour ? true : false); | return (this.template.NaturalBehaviour ? true : false); | ||||
}; | }; | ||||
UnitAI.prototype.IsDangerousAnimal = function() | UnitAI.prototype.IsDangerousAnimal = function() | ||||
{ | { | ||||
return (this.IsAnimal() && (this.template.NaturalBehaviour == "violent" || | return (this.IsAnimal() && (this.template.NaturalBehaviour == "violent" || | ||||
▲ Show 20 Lines • Show All 346 Lines • ▼ Show 20 Lines | UnitAI.prototype.FinishOrder = function() | ||||
// Check if there are queued formation orders | // Check if there are queued formation orders | ||||
if (this.IsFormationMember()) | if (this.IsFormationMember()) | ||||
{ | { | ||||
this.SetNextState("FORMATIONMEMBER.IDLE"); | this.SetNextState("FORMATIONMEMBER.IDLE"); | ||||
let cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); | let cmpUnitAI = Engine.QueryInterface(this.formationController, IID_UnitAI); | ||||
if (cmpUnitAI) | if (cmpUnitAI) | ||||
{ | { | ||||
// Inform the formation controller that we finished this task | // Inform the formation controller that we finished this task | ||||
this.finishedOrder = true; | let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | ||||
cmpFormation.SetWaitingOnController(this.entity); | |||||
// We don't want to carry out the default order | // We don't want to carry out the default order | ||||
// if there are still queued formation orders left | // if there are still queued formation orders left | ||||
if (cmpUnitAI.GetOrders().length > 1) | if (cmpUnitAI.GetOrders().length > 1) | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
return false; | return false; | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 2,587 Lines • ▼ Show 20 Lines | for (let pref of preferences) | ||||
if (this.RespondToTargetedEntities(entsByPreferences[pref])) | if (this.RespondToTargetedEntities(entsByPreferences[pref])) | ||||
return true; | return true; | ||||
} | } | ||||
return this.RespondToTargetedEntities(entsWithoutPref); | return this.RespondToTargetedEntities(entsWithoutPref); | ||||
}; | }; | ||||
/** | /** | ||||
* Call obj.funcname(args) on UnitAI components of all formation members. | * Call UnitAI.funcname(args) on all formation members. | ||||
* @param resetWaitingEntities - If true, call ResetWaitingEntities first. | |||||
* If the controller wants to wait on its members to finish their order, | |||||
* this needs to be reset before sending new orders (in case they instafail) | |||||
* so it makes sense to do it here. | |||||
* Only set this to false if you're sure it's safe. | |||||
*/ | */ | ||||
UnitAI.prototype.CallMemberFunction = function(funcname, args) | UnitAI.prototype.CallMemberFunction = function(funcname, args, resetWaitingEntities = true) | ||||
{ | { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
if (!cmpFormation) | if (!cmpFormation) | ||||
return; | return; | ||||
if (resetWaitingEntities) | |||||
cmpFormation.ResetWaitingEntities(); | |||||
cmpFormation.GetMembers().forEach(ent => { | cmpFormation.GetMembers().forEach(ent => { | ||||
var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); | let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); | ||||
cmpUnitAI[funcname].apply(cmpUnitAI, args); | cmpUnitAI[funcname].apply(cmpUnitAI, args); | ||||
}); | }); | ||||
}; | }; | ||||
/** | /** | ||||
* Call obj.functname(args) on UnitAI components of all formation members, | * Call obj.functname(args) on UnitAI components of all formation members, | ||||
* and return true if all calls return true. | * and return true if all calls return true. | ||||
*/ | */ | ||||
Show All 15 Lines |
Wildfire Games · Phabricator