Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 490 Lines • ▼ Show 20 Lines | "Order.Gather": function(msg) { | ||||
if (!this.CanGather(msg.data.target)) | if (!this.CanGather(msg.data.target)) | ||||
{ | { | ||||
this.SetNextState("INDIVIDUAL.GATHER.FINDINGNEWTARGET"); | this.SetNextState("INDIVIDUAL.GATHER.FINDINGNEWTARGET"); | ||||
return ACCEPT_ORDER; | return ACCEPT_ORDER; | ||||
} | } | ||||
if (this.MustKillGatherTarget(msg.data.target)) | if (this.MustKillGatherTarget(msg.data.target)) | ||||
{ | { | ||||
const bestAttack = Engine.QueryInterface(this.entity, IID_Attack)?.GetBestAttackAgainst(msg.data.target, false); | |||||
// 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(msg.data.target, false)) | if (!bestAttack) | ||||
{ | { | ||||
// Oops, we can't attack at all - give up | // Oops, we can't attack at all - give up | ||||
// TODO: should do something so the player knows why this failed | // TODO: should do something so the player knows why this failed | ||||
return this.FinishOrder(); | return this.FinishOrder(); | ||||
} | } | ||||
// The target was visible when this order was issued, | // The target was visible when this order was issued, | ||||
// but could now be invisible again. | // but could now be invisible again. | ||||
if (!this.CheckTargetVisible(msg.data.target)) | if (!this.CheckTargetVisible(msg.data.target)) | ||||
Show All 9 Lines | if (this.MustKillGatherTarget(msg.data.target)) | ||||
"x": msg.data.lastPos.x, | "x": msg.data.lastPos.x, | ||||
"z": msg.data.lastPos.z, | "z": msg.data.lastPos.z, | ||||
"type": msg.data.type, | "type": msg.data.type, | ||||
"template": msg.data.template | "template": msg.data.template | ||||
}); | }); | ||||
return ACCEPT_ORDER; | return ACCEPT_ORDER; | ||||
} | } | ||||
if (!this.AbleToMove() && !this.CheckTargetRange(msg.data.target, IID_Attack, bestAttack)) | |||||
return this.FinishOrder(); | |||||
this.PushOrderFront("Attack", { "target": msg.data.target, "force": !!msg.data.force, "hunting": true, "allowCapture": false }); | this.PushOrderFront("Attack", { "target": msg.data.target, "force": !!msg.data.force, "hunting": true, "allowCapture": false }); | ||||
return ACCEPT_ORDER; | return ACCEPT_ORDER; | ||||
} | } | ||||
// If the unit is full go to the nearest dropsite instead of trying to gather. | // If the unit is full go to the nearest dropsite instead of trying to gather. | ||||
if (!cmpResourceGatherer.CanCarryMore(msg.data.type.generic)) | if (!cmpResourceGatherer.CanCarryMore(msg.data.type.generic)) | ||||
{ | { | ||||
this.SetNextState("INDIVIDUAL.GATHER.RETURNINGRESOURCE"); | this.SetNextState("INDIVIDUAL.GATHER.RETURNINGRESOURCE"); | ||||
▲ Show 20 Lines • Show All 2,910 Lines • ▼ Show 20 Lines | UnitAI.prototype.Init = function() | ||||
this.isGuardOf = undefined; | this.isGuardOf = undefined; | ||||
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() | /** | ||||
* @param {cmpTurretable} cmpTurretable - Optionally the component to save a query here. | |||||
* @return {boolean} - Whether we are occupying a turret point. | |||||
*/ | |||||
UnitAI.prototype.IsTurret = function(cmpTurretable) | |||||
{ | { | ||||
if (!this.isGarrisoned) | if (!cmpTurretable) | ||||
return false; | cmpTurretable = Engine.QueryInterface(this.entity, IID_Turretable); | ||||
let cmpTurretable = Engine.QueryInterface(this.entity, IID_Turretable); | |||||
return cmpTurretable && cmpTurretable.HolderID() != INVALID_ENTITY; | return cmpTurretable && cmpTurretable.HolderID() != INVALID_ENTITY; | ||||
}; | }; | ||||
UnitAI.prototype.IsFormationController = function() | UnitAI.prototype.IsFormationController = function() | ||||
{ | { | ||||
return (this.template.FormationController == "true"); | return (this.template.FormationController == "true"); | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
/** | /** | ||||
* @param cmpUnitMotion - optionally pass unitMotion to avoid querying it here | * @param cmpUnitMotion - optionally pass unitMotion to avoid querying it here | ||||
* @returns true if the entity can move, i.e. has UnitMotion and isn't immobile. | * @returns true if the entity can move, i.e. has UnitMotion and isn't immobile. | ||||
*/ | */ | ||||
UnitAI.prototype.AbleToMove = function(cmpUnitMotion) | UnitAI.prototype.AbleToMove = function(cmpUnitMotion) | ||||
{ | { | ||||
if (this.isImmobile || this.IsTurret()) | if (this.isImmobile) | ||||
return false; | return false; | ||||
if (!cmpUnitMotion) | if (!cmpUnitMotion) | ||||
cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | ||||
return !!cmpUnitMotion; | return !!cmpUnitMotion; | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 296 Lines • ▼ Show 20 Lines | if (!this.orderQueue.length) | ||||
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); | let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); | ||||
let template = cmpTemplateManager.GetCurrentTemplateName(this.entity); | let template = cmpTemplateManager.GetCurrentTemplateName(this.entity); | ||||
error("FinishOrder called for entity " + this.entity + " (" + template + ") when order queue is empty\n" + stack); | error("FinishOrder called for entity " + this.entity + " (" + template + ") when order queue is empty\n" + stack); | ||||
} | } | ||||
this.orderQueue.shift(); | this.orderQueue.shift(); | ||||
this.order = this.orderQueue[0]; | this.order = this.orderQueue[0]; | ||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | |||||
if (this.orderQueue.length && (this.isGarrisoned || this.IsFormationController() || | if (this.orderQueue.length && (this.isGarrisoned || this.IsFormationController() || | ||||
cmpPosition && cmpPosition.IsInWorld())) | Engine.QueryInterface(this.entity, IID_Position)?.IsInWorld())) | ||||
{ | { | ||||
let ret = this.UnitFsm.ProcessMessage(this, { | let ret = this.UnitFsm.ProcessMessage(this, { | ||||
"type": "Order."+this.order.type, | "type": "Order."+this.order.type, | ||||
"data": this.order.data | "data": this.order.data | ||||
}); | }); | ||||
Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | ||||
▲ Show 20 Lines • Show All 270 Lines • ▼ Show 20 Lines | UnitAI.prototype.UpdateWorkOrders = function(type) | ||||
} | } | ||||
}; | }; | ||||
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 && !Engine.QueryInterface(this.entity, IID_Garrisonable)?.UnGarrison(false)) | ||||
{ | |||||
if (this.IsTurret()) | |||||
{ | |||||
let cmpTurretable = Engine.QueryInterface(this.entity, IID_Turretable); | |||||
if (!cmpTurretable || !cmpTurretable.LeaveTurret()) | |||||
return false; | return false; | ||||
} | |||||
let cmpGarrisonable = Engine.QueryInterface(this.entity, IID_Garrisonable); | const cmpTurretable = Engine.QueryInterface(this.entity, IID_Turretable); | ||||
if (!cmpGarrisonable || !cmpGarrisonable.UnGarrison(false)) | if (this.IsTurret(cmpTurretable) && !cmpTurretable.LeaveTurret()) | ||||
return false; | return false; | ||||
} | |||||
this.orderQueue = []; | this.orderQueue = []; | ||||
this.AddOrders(this.workOrders); | this.AddOrders(this.workOrders); | ||||
Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() }); | ||||
if (this.IsFormationMember()) | if (this.IsFormationMember()) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 685 Lines • ▼ Show 20 Lines | UnitAI.prototype.CheckFormationTargetAttackRange = function(target) | ||||
return cmpObstructionManager.IsInTargetRange(this.entity, target, range.min, range.max, false); | return cmpObstructionManager.IsInTargetRange(this.entity, target, range.min, range.max, false); | ||||
}; | }; | ||||
/** | /** | ||||
* 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); | if (this.isGarrisoned) | ||||
return false; | |||||
const cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | |||||
if (!cmpOwnership) | if (!cmpOwnership) | ||||
return false; | return false; | ||||
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); | const cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); | ||||
if (!cmpRangeManager) | if (!cmpRangeManager) | ||||
return false; | return false; | ||||
// Entities that are hidden and miraged are considered visible | // Entities that are hidden and miraged are considered visible | ||||
var cmpFogging = Engine.QueryInterface(target, IID_Fogging); | const cmpFogging = Engine.QueryInterface(target, IID_Fogging); | ||||
if (cmpFogging && cmpFogging.IsMiraged(cmpOwnership.GetOwner())) | if (cmpFogging && cmpFogging.IsMiraged(cmpOwnership.GetOwner())) | ||||
return true; | return true; | ||||
if (cmpRangeManager.GetLosVisibility(target, cmpOwnership.GetOwner()) == "hidden") | if (cmpRangeManager.GetLosVisibility(target, cmpOwnership.GetOwner()) == "hidden") | ||||
return false; | return false; | ||||
// Either visible directly, or visible in fog | // Either visible directly, or visible in fog | ||||
return true; | return true; | ||||
▲ Show 20 Lines • Show All 644 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
/** | /** | ||||
* Adds garrison order to the queue, forced by the player. | * Adds garrison order to the queue, forced by the player. | ||||
*/ | */ | ||||
UnitAI.prototype.Garrison = function(target, queued, pushFront) | UnitAI.prototype.Garrison = function(target, queued, pushFront) | ||||
{ | { | ||||
// Not allowed to garrison when occupying a turret, at the moment. | // Not allowed to garrison when occupying a turret, at the moment. | ||||
if (this.isGarrisoned) | if (this.isGarrisoned || this.IsTurret()) | ||||
return; | return; | ||||
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, "garrison": 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 && !this.IsTurret()) | ||||
return; | return; | ||||
this.AddOrder("Ungarrison", null, false); | this.AddOrder("Ungarrison", null, false); | ||||
}; | }; | ||||
/** | /** | ||||
* Adds garrison order to the queue, forced by the player. | * Adds garrison order to the queue, forced by the player. | ||||
*/ | */ | ||||
UnitAI.prototype.OccupyTurret = function(target, queued, pushFront) | UnitAI.prototype.OccupyTurret = function(target, queued, pushFront) | ||||
▲ Show 20 Lines • Show All 353 Lines • ▼ Show 20 Lines | UnitAI.prototype.SwitchToStance = function(stance) | ||||
this.SetStance(stance); | this.SetStance(stance); | ||||
// Reset the range queries, since the range depends on stance. | // Reset the range queries, since the range depends on stance. | ||||
this.SetupRangeQueries(); | this.SetupRangeQueries(); | ||||
}; | }; | ||||
UnitAI.prototype.SetTurretStance = function() | UnitAI.prototype.SetTurretStance = function() | ||||
{ | { | ||||
this.SetImmobile(); | |||||
this.previousStance = undefined; | this.previousStance = undefined; | ||||
if (this.GetStance().respondStandGround) | if (this.GetStance().respondStandGround) | ||||
return; | return; | ||||
for (let stance in g_Stances) | for (let stance in g_Stances) | ||||
{ | { | ||||
if (!g_Stances[stance].respondStandGround) | if (!g_Stances[stance].respondStandGround) | ||||
continue; | continue; | ||||
this.previousStance = this.GetStanceName(); | this.previousStance = this.GetStanceName(); | ||||
this.SwitchToStance(stance); | this.SwitchToStance(stance); | ||||
return; | return; | ||||
} | } | ||||
}; | }; | ||||
UnitAI.prototype.ResetTurretStance = function() | UnitAI.prototype.ResetTurretStance = function() | ||||
{ | { | ||||
this.SetMobile(); | |||||
if (!this.previousStance) | if (!this.previousStance) | ||||
return; | return; | ||||
this.SwitchToStance(this.previousStance); | this.SwitchToStance(this.previousStance); | ||||
this.previousStance = undefined; | this.previousStance = undefined; | ||||
}; | }; | ||||
/** | /** | ||||
* Resets the losRangeQuery. | * Resets the losRangeQuery. | ||||
▲ Show 20 Lines • Show All 560 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator