Changeset View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 586 Lines • ▼ Show 20 Lines | "Order.Garrison": function(msg) { | ||||
// Also pack when we are in range. | // Also pack when we are in range. | ||||
if (this.CanPack()) | if (this.CanPack()) | ||||
{ | { | ||||
this.PushOrderFront("Pack", { "force": true }); | this.PushOrderFront("Pack", { "force": true }); | ||||
return ACCEPT_ORDER; | return ACCEPT_ORDER; | ||||
} | } | ||||
if (this.CheckGarrisonRange(msg.data.target)) | if (msg.data.garrison ? this.CheckGarrisonRange(msg.data.target) : | ||||
this.CheckOccupyTurretRange(msg.data.target)) | |||||
this.SetNextState("INDIVIDUAL.GARRISON.GARRISONING"); | this.SetNextState("INDIVIDUAL.GARRISON.GARRISONING"); | ||||
else | else | ||||
this.SetNextState("INDIVIDUAL.GARRISON.APPROACHING"); | this.SetNextState("INDIVIDUAL.GARRISON.APPROACHING"); | ||||
return ACCEPT_ORDER; | return ACCEPT_ORDER; | ||||
}, | }, | ||||
"Order.Ungarrison": function(msg) { | "Order.Ungarrison": function(msg) { | ||||
// Note that this order MUST succeed, or we break | // Note that this order MUST succeed, or we break | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | "Order.Attack": function(msg) { | ||||
if (cmpAttack && cmpAttack.CanAttackAsFormation()) | if (cmpAttack && cmpAttack.CanAttackAsFormation()) | ||||
this.SetNextState("COMBAT.ATTACKING"); | this.SetNextState("COMBAT.ATTACKING"); | ||||
else | else | ||||
this.SetNextState("MEMBER"); | this.SetNextState("MEMBER"); | ||||
return ACCEPT_ORDER; | return ACCEPT_ORDER; | ||||
}, | }, | ||||
"Order.Garrison": function(msg) { | "Order.Garrison": function(msg) { | ||||
if (!Engine.QueryInterface(msg.data.target, IID_GarrisonHolder)) | if (!Engine.QueryInterface(msg.data.target, | ||||
msg.data.garrison ? IID_GarrisonHolder : IID_TurretHolder)) | |||||
return this.FinishOrder(); | return this.FinishOrder(); | ||||
if (!this.CheckGarrisonRange(msg.data.target)) | if (!(msg.data.garrison ? this.CheckGarrisonRange(msg.data.target) : | ||||
this.CheckOccupyTurretRange(msg.data.target))) | |||||
{ | { | ||||
if (!this.CheckTargetVisible(msg.data.target)) | if (!this.CheckTargetVisible(msg.data.target)) | ||||
return this.FinishOrder(); | return this.FinishOrder(); | ||||
this.SetNextState("GARRISON.APPROACHING"); | this.SetNextState("GARRISON.APPROACHING"); | ||||
} | } | ||||
else | else | ||||
this.SetNextState("GARRISON.GARRISONING"); | this.SetNextState("GARRISON.GARRISONING"); | ||||
▲ Show 20 Lines • Show All 337 Lines • ▼ Show 20 Lines | "PATROL": { | ||||
++this.stopSurveying; | ++this.stopSurveying; | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"GARRISON": { | "GARRISON": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | if (!(this.order.data.garrison ? this.MoveToGarrisonRange(this.order.data.target) : | ||||
cmpFormation.SetRearrange(true); | this.MoveToOccupyTurretRange(this.order.data.target))) | ||||
cmpFormation.MoveMembersIntoFormation(true, true); | |||||
if (!this.MoveToGarrisonRange(this.order.data.target)) | |||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
// If the garrisonholder should pickup, warn it so it can take needed action. | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
let cmpGarrisonHolder = Engine.QueryInterface(this.order.data.target, IID_GarrisonHolder); | cmpFormation.SetRearrange(true); | ||||
if (cmpGarrisonHolder && cmpGarrisonHolder.CanPickup(this.entity)) | cmpFormation.MoveMembersIntoFormation(true, true); | ||||
// If the holder should pickup, warn it so it can take needed action. | |||||
let cmpHolder = Engine.QueryInterface(this.order.data.target, this.order.data.garrison ? IID_GarrisonHolder : IID_TurretHolder); | |||||
if (cmpHolder && cmpHolder.CanPickup(this.entity)) | |||||
{ | { | ||||
this.pickup = this.order.data.target; // temporary, deleted in "leave" | this.pickup = this.order.data.target; // temporary, deleted in "leave" | ||||
Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); | ||||
} | } | ||||
return false; | return false; | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
if (this.pickup) | if (this.pickup) | ||||
{ | { | ||||
Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | ||||
delete this.pickup; | delete this.pickup; | ||||
} | } | ||||
}, | }, | ||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | ||||
if (msg.likelyFailure || msg.likelySuccess) | if (msg.likelyFailure || msg.likelySuccess) | ||||
this.SetNextState("GARRISONING"); | this.SetNextState("GARRISONING"); | ||||
}, | }, | ||||
}, | }, | ||||
"GARRISONING": { | "GARRISONING": { | ||||
"enter": function() { | "enter": function() { | ||||
this.CallMemberFunction("Garrison", [this.order.data.target, false]); | this.CallMemberFunction(this.order.data.garrison ? "Garrison" : "OccupyTurret", [this.order.data.target, false]); | ||||
// We might have been disbanded due to the lack of members. | // We might have been disbanded due to the lack of members. | ||||
if (Engine.QueryInterface(this.entity, IID_Formation).GetMemberCount()) | if (Engine.QueryInterface(this.entity, IID_Formation).GetMemberCount()) | ||||
this.SetNextState("MEMBER"); | this.SetNextState("MEMBER"); | ||||
return true; | return true; | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 2,055 Lines • ▼ Show 20 Lines | "REPAIR": { | ||||
// 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": { | ||||
"APPROACHING": { | "APPROACHING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.CanGarrison(this.order.data.target)) | if (this.order.data.garrison ? !this.CanGarrison(this.order.data.target) : | ||||
!this.CanOccupyTurret(this.order.data.target)) | |||||
wraitii: Likewise, is there a common function name that would make sense? Would it make sense to… | |||||
Not Done Inline ActionsI'm thinking that we has such a function for most tasks, e.g. CanGather, CanDeposit, etc. Perhaps we need a common UnitAI Interface function like we have MoveTo and CheckRange wraitii: I'm thinking that we has such a function for most tasks, e.g. CanGather, CanDeposit, etc. | |||||
Not Done Inline ActionsIf we assume that every component is responsible for at most one task, we can easily to this. this.CanDo(IID, target) -> cmp.CanDo(target)? Freagarach: If we assume that every component is responsible for at most one task, we can easily to this. | |||||
Not Done Inline ActionsWe could have additional parameters this.CanDo(IID, target, data). If a component needs more than two tasks, we could always have _some_ duplication anyways. Alternatively, if we had a function creating the FSM state, we could pass this as an argument. I know you disliked that in a past diff, but I think it holds merit. wraitii: We could have additional parameters `this.CanDo(IID, target, data)`.
If a component needs more… | |||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
if (!this.MoveToGarrisonRange(this.order.data.target)) | if (this.order.data.garrison ? !this.MoveToGarrisonRange(this.order.data.target) : | ||||
!this.MoveToOccupyTurretRange(this.order.data.target)) | |||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
if (this.pickup) | if (this.pickup) | ||||
Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | ||||
let cmpGarrisonHolder = Engine.QueryInterface(this.order.data.target, IID_GarrisonHolder); | let cmpHolder = Engine.QueryInterface(this.order.data.target, this.order.data.garrison ? IID_GarrisonHolder : IID_TurretHolder); | ||||
if (cmpGarrisonHolder && cmpGarrisonHolder.CanPickup(this.entity)) | if (cmpHolder && cmpHolder.CanPickup(this.entity)) | ||||
{ | { | ||||
this.pickup = this.order.data.target; | this.pickup = this.order.data.target; | ||||
Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); | ||||
} | } | ||||
return false; | return false; | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
if (this.pickup) | if (this.pickup) | ||||
{ | { | ||||
Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); | ||||
delete this.pickup; | delete this.pickup; | ||||
} | } | ||||
this.StopMoving(); | this.StopMoving(); | ||||
}, | }, | ||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | ||||
if (!msg.likelyFailure && !msg.likelySuccess) | if (!msg.likelyFailure && !msg.likelySuccess) | ||||
return; | return; | ||||
if (this.CheckGarrisonRange(this.order.data.target)) | if (this.order.data.garrison ? this.CheckGarrisonRange(this.order.data.target) : | ||||
this.CheckOccupyTurretRange(this.order.data.target)) | |||||
this.SetNextState("GARRISONING"); | this.SetNextState("GARRISONING"); | ||||
else | else | ||||
{ | { | ||||
// Unable to reach the target, try again (or follow if it is a moving target) | // Unable to reach the target, try again (or follow if it is a moving target) | ||||
// except if the target does not exist anymore or its orders have changed. | // except if the target does not exist anymore or its orders have changed. | ||||
if (this.pickup) | if (this.pickup) | ||||
{ | { | ||||
let cmpUnitAI = Engine.QueryInterface(this.pickup, IID_UnitAI); | let cmpUnitAI = Engine.QueryInterface(this.pickup, IID_UnitAI); | ||||
if (!cmpUnitAI || (!cmpUnitAI.HasPickupOrder(this.entity) && !cmpUnitAI.IsIdle())) | if (!cmpUnitAI || (!cmpUnitAI.HasPickupOrder(this.entity) && !cmpUnitAI.IsIdle())) | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
}, | }, | ||||
"GARRISONING": { | "GARRISONING": { | ||||
"enter": function() { | "enter": function() { | ||||
let target = this.order.data.target; | let target = this.order.data.target; | ||||
if (this.order.data.garrison) | |||||
{ | |||||
let cmpGarrisonable = Engine.QueryInterface(this.entity, IID_Garrisonable); | let cmpGarrisonable = Engine.QueryInterface(this.entity, IID_Garrisonable); | ||||
if (!cmpGarrisonable || !cmpGarrisonable.Garrison(target)) | if (!cmpGarrisonable || !cmpGarrisonable.Garrison(target)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
} | |||||
else | |||||
{ | |||||
let cmpTurretable = Engine.QueryInterface(this.entity, IID_Turretable); | |||||
if (!cmpTurretable || !cmpTurretable.OccupyTurret(target)) | |||||
Not Done Inline ActionsIs there a common function name that would make sense? wraitii: Is there a common function name that would make sense? | |||||
{ | |||||
this.FinishOrder(); | |||||
return true; | |||||
} | |||||
} | |||||
if (this.formationController) | if (this.formationController) | ||||
{ | { | ||||
let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation); | ||||
if (cmpFormation) | if (cmpFormation) | ||||
{ | { | ||||
let rearrange = cmpFormation.rearrange; | let rearrange = cmpFormation.rearrange; | ||||
cmpFormation.SetRearrange(false); | cmpFormation.SetRearrange(false); | ||||
▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | UnitAI.prototype.Init = function() | ||||
this.formationAnimationVariant = undefined; | this.formationAnimationVariant = undefined; | ||||
this.cheeringTime = +(this.template.CheeringTime || 0); | this.cheeringTime = +(this.template.CheeringTime || 0); | ||||
this.SetStance(this.template.DefaultStance); | this.SetStance(this.template.DefaultStance); | ||||
}; | }; | ||||
UnitAI.prototype.IsTurret = function() | UnitAI.prototype.IsTurret = function() | ||||
{ | { | ||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | if (!this.isGarrisoned) | ||||
return cmpPosition && cmpPosition.GetTurretParent() != INVALID_ENTITY; | return false; | ||||
let cmpTurretable = Engine.QueryInterface(this.entity, IID_Turretable); | |||||
return cmpTurretable && cmpTurretable.HolderID() != INVALID_ENTITY; | |||||
}; | }; | ||||
Not Done Inline ActionsThis is horrible :p wraitii: This is horrible :p | |||||
UnitAI.prototype.IsFormationController = function() | UnitAI.prototype.IsFormationController = function() | ||||
{ | { | ||||
return (this.template.FormationController == "true"); | return (this.template.FormationController == "true"); | ||||
}; | }; | ||||
UnitAI.prototype.IsFormationMember = function() | UnitAI.prototype.IsFormationMember = function() | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 692 Lines • ▼ Show 20 Lines | |||||
UnitAI.prototype.BackToWork = function() | UnitAI.prototype.BackToWork = function() | ||||
{ | { | ||||
if (this.workOrders.length == 0) | if (this.workOrders.length == 0) | ||||
return false; | return false; | ||||
if (this.isGarrisoned) | if (this.isGarrisoned) | ||||
{ | { | ||||
if (this.IsTurret()) | |||||
{ | |||||
let cmpTurretable = Engine.QueryInterface(this.entity, IID_Turretable); | |||||
if (!cmpTurretable || !cmpTurretable.LeaveTurret()) | |||||
return false; | |||||
} | |||||
let cmpGarrisonable = Engine.QueryInterface(this.entity, IID_Garrisonable); | let cmpGarrisonable = Engine.QueryInterface(this.entity, IID_Garrisonable); | ||||
if (!cmpGarrisonable || !cmpGarrisonable.UnGarrison(false)) | if (!cmpGarrisonable || !cmpGarrisonable.UnGarrison(false)) | ||||
return false; | return false; | ||||
} | } | ||||
this.orderQueue = []; | this.orderQueue = []; | ||||
this.AddOrders(this.workOrders); | this.AddOrders(this.workOrders); | ||||
▲ Show 20 Lines • Show All 595 Lines • ▼ Show 20 Lines | UnitAI.prototype.MoveFormationToTargetAttackRange = function(target) | ||||
if (!cmpFormationAttack) | if (!cmpFormationAttack) | ||||
return false; | return false; | ||||
let range = cmpFormationAttack.GetRange(target); | let range = cmpFormationAttack.GetRange(target); | ||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | ||||
return this.AbleToMove(cmpUnitMotion) && cmpUnitMotion.MoveToTargetRange(target, range.min, range.max); | return this.AbleToMove(cmpUnitMotion) && cmpUnitMotion.MoveToTargetRange(target, range.min, range.max); | ||||
}; | }; | ||||
UnitAI.prototype.MoveToGarrisonRange = function(target) | UnitAI.prototype.MoveToGarrisonRange = function(target) | ||||
{ | { | ||||
if (!this.CheckTargetVisible(target)) | if (!this.CheckTargetVisible(target)) | ||||
return false; | return false; | ||||
var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | ||||
if (!cmpGarrisonHolder) | if (!cmpGarrisonHolder) | ||||
return false; | return false; | ||||
var range = cmpGarrisonHolder.GetLoadingRange(); | var range = cmpGarrisonHolder.GetLoadingRange(); | ||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | ||||
return this.AbleToMove(cmpUnitMotion) && cmpUnitMotion.MoveToTargetRange(target, range.min, range.max); | return this.AbleToMove(cmpUnitMotion) && cmpUnitMotion.MoveToTargetRange(target, range.min, range.max); | ||||
}; | }; | ||||
UnitAI.prototype.MoveToOccupyTurretRange = function(target) | |||||
{ | |||||
if (!this.CheckTargetVisible(target)) | |||||
return false; | |||||
let cmpTurretHolder = Engine.QueryInterface(target, IID_TurretHolder); | |||||
if (!cmpTurretHolder) | |||||
return false; | |||||
let range = cmpTurretHolder.GetLoadingRange(); | |||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | |||||
return this.AbleToMove(cmpUnitMotion) && cmpUnitMotion.MoveToTargetRange(target, range.min, range.max); | |||||
}; | |||||
/** | /** | ||||
Not Done Inline ActionsThese two functions have no reason to exist. MoveTo({ 'target': X }, IID_GarrisonHolder/IID_TurretHolder) ought to be enough. wraitii: These two functions have no reason to exist. `MoveTo({ 'target': X }… | |||||
Not Done Inline ActionsApart from the fact that we don't query our own range here, but that of our target. And in the general GetRange we don't pass a target (which we should do). Freagarach: Apart from the fact that we don't query our own range here, but that of our target. And in the… | |||||
Not Done Inline ActionsAh, you're right. That could be changed easily though as you note. wraitii: Ah, you're right. That could be changed easily though as you note. | |||||
* Generic dispatcher for other Check...Range functions. | * Generic dispatcher for other Check...Range functions. | ||||
* @param iid - Interface ID (optional) implementing GetRange | * @param iid - Interface ID (optional) implementing GetRange | ||||
* @param type - Range type for the interface call | * @param type - Range type for the interface call | ||||
*/ | */ | ||||
UnitAI.prototype.CheckRange = function(data, iid, type) | UnitAI.prototype.CheckRange = function(data, iid, type) | ||||
{ | { | ||||
if (data.target) | if (data.target) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | UnitAI.prototype.CheckFormationTargetAttackRange = function(target) | ||||
if (!cmpFormationAttack) | if (!cmpFormationAttack) | ||||
return false; | return false; | ||||
let range = cmpFormationAttack.GetRange(target); | let range = cmpFormationAttack.GetRange(target); | ||||
let cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | let cmpObstructionManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ObstructionManager); | ||||
return cmpObstructionManager.IsInTargetRange(this.entity, target, range.min, range.max, false); | return cmpObstructionManager.IsInTargetRange(this.entity, target, range.min, range.max, false); | ||||
}; | }; | ||||
UnitAI.prototype.CheckGarrisonRange = function(target) | UnitAI.prototype.CheckGarrisonRange = function(target) | ||||
{ | { | ||||
let cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | let cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); | ||||
if (!cmpGarrisonHolder) | if (!cmpGarrisonHolder) | ||||
return false; | return false; | ||||
let range = cmpGarrisonHolder.GetLoadingRange(); | let range = cmpGarrisonHolder.GetLoadingRange(); | ||||
return this.CheckTargetRangeExplicit(target, range.min, range.max); | return this.CheckTargetRangeExplicit(target, range.min, range.max); | ||||
}; | }; | ||||
UnitAI.prototype.CheckOccupyTurretRange = function(target) | |||||
{ | |||||
let cmpTurretHolder = Engine.QueryInterface(target, IID_TurretHolder); | |||||
if (!cmpTurretHolder) | |||||
return false; | |||||
let range = cmpTurretHolder.GetLoadingRange(); | |||||
return this.CheckTargetRangeExplicit(target, range.min, range.max); | |||||
}; | |||||
/** | /** | ||||
Not Done Inline ActionsLikewise these should just be CheckRange with the proper IID wraitii: Likewise these should just be `CheckRange` with the proper IID | |||||
Not Done Inline ActionsIdem. Freagarach: Idem. | |||||
* Returns true if the target entity is visible through the FoW/SoD. | * Returns true if the target entity is visible through the FoW/SoD. | ||||
*/ | */ | ||||
UnitAI.prototype.CheckTargetVisible = function(target) | UnitAI.prototype.CheckTargetVisible = function(target) | ||||
{ | { | ||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
if (!cmpOwnership) | if (!cmpOwnership) | ||||
return false; | return false; | ||||
▲ Show 20 Lines • Show All 416 Lines • ▼ Show 20 Lines | if (pushFront) | ||||
this.PushOrderFront(type, data); | this.PushOrderFront(type, data); | ||||
else if (queued) | else if (queued) | ||||
this.PushOrder(type, data); | this.PushOrder(type, data); | ||||
else | else | ||||
{ | { | ||||
// May happen if an order arrives on the same turn the unit is garrisoned | // May happen if an order arrives on the same turn the unit is garrisoned | ||||
// in that case, just forget the order as this will lead to an infinite loop. | // in that case, just forget the order as this will lead to an infinite loop. | ||||
// ToDo: Fix that by checking for the ability to move on orders that need that. | // ToDo: Fix that by checking for the ability to move on orders that need that. | ||||
if (this.isGarrisoned && !this.IsTurret() && type != "Ungarrison") | if (this.isGarrisoned && type != "Ungarrison") | ||||
return; | return; | ||||
this.ReplaceOrder(type, data); | this.ReplaceOrder(type, data); | ||||
} | } | ||||
}; | }; | ||||
/** | /** | ||||
* Adds guard/escort order to the queue, forced by the player. | * Adds guard/escort order to the queue, forced by the player. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
if (target == this.entity) | if (target == this.entity) | ||||
return; | return; | ||||
if (!this.CanGarrison(target)) | if (!this.CanGarrison(target)) | ||||
{ | { | ||||
this.WalkToTarget(target, queued); | this.WalkToTarget(target, queued); | ||||
return; | return; | ||||
} | } | ||||
this.AddOrder("Garrison", { "target": target, "force": true }, queued, pushFront); | this.AddOrder("Garrison", { "target": target, "force": true, "garrison": true }, queued, pushFront); | ||||
}; | }; | ||||
/** | /** | ||||
* Adds ungarrison order to the queue. | * Adds ungarrison order to the queue. | ||||
*/ | */ | ||||
UnitAI.prototype.Ungarrison = function() | UnitAI.prototype.Ungarrison = function() | ||||
{ | { | ||||
if (!this.isGarrisoned) | if (!this.isGarrisoned) | ||||
return; | return; | ||||
this.AddOrder("Ungarrison", null, false); | this.AddOrder("Ungarrison", null, false); | ||||
}; | }; | ||||
/** | /** | ||||
* Adds garrison order to the queue, forced by the player. | |||||
*/ | |||||
UnitAI.prototype.OccupyTurret = function(target, queued, pushFront) | |||||
{ | |||||
if (target == this.entity) | |||||
return; | |||||
if (!this.CanOccupyTurret(target)) | |||||
{ | |||||
this.WalkToTarget(target, queued); | |||||
return; | |||||
} | |||||
this.AddOrder("Garrison", { "target": target, "force": true, "garrison": false }, queued, pushFront); | |||||
}; | |||||
/** | |||||
* Adds gather order to the queue, forced by the player | * Adds gather order to the queue, forced by the player | ||||
* until the target is reached | * until the target is reached | ||||
*/ | */ | ||||
UnitAI.prototype.Gather = function(target, queued, pushFront) | UnitAI.prototype.Gather = function(target, queued, pushFront) | ||||
{ | { | ||||
this.PerformGather(target, queued, true, pushFront); | this.PerformGather(target, queued, true, pushFront); | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 822 Lines • ▼ Show 20 Lines | UnitAI.prototype.CanRepair = function(target) | ||||
var cmpRepairable = Engine.QueryInterface(target, IID_Repairable); | var cmpRepairable = Engine.QueryInterface(target, IID_Repairable); | ||||
if (!cmpFoundation && !cmpRepairable) | if (!cmpFoundation && !cmpRepairable) | ||||
return false; | return false; | ||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
return cmpOwnership && IsOwnedByAllyOfPlayer(cmpOwnership.GetOwner(), target); | return cmpOwnership && IsOwnedByAllyOfPlayer(cmpOwnership.GetOwner(), target); | ||||
}; | }; | ||||
UnitAI.prototype.CanOccupyTurret = function(target) | |||||
{ | |||||
// Formation controllers should always respond to commands | |||||
// (then the individual units can make up their own minds). | |||||
if (this.IsFormationController()) | |||||
return true; | |||||
let cmpTurretable = Engine.QueryInterface(this.entity, IID_Turretable); | |||||
return cmpTurretable && cmpTurretable.CanOccupy(target); | |||||
}; | |||||
UnitAI.prototype.CanPack = function() | UnitAI.prototype.CanPack = function() | ||||
{ | { | ||||
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | var cmpPack = Engine.QueryInterface(this.entity, IID_Pack); | ||||
return cmpPack && !cmpPack.IsPacking() && !cmpPack.IsPacked(); | return cmpPack && !cmpPack.IsPacking() && !cmpPack.IsPacked(); | ||||
}; | }; | ||||
UnitAI.prototype.CanUnpack = function() | UnitAI.prototype.CanUnpack = function() | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 180 Lines • Show Last 20 Lines |
Likewise, is there a common function name that would make sense? Would it make sense to implement a function that takes an argument 'IID_something' instead?