Changeset View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 1,681 Lines • ▼ Show 20 Lines | "WALKING": { | ||||
if (msg.likelyFailure || msg.obstructed && this.RelaxedMaxRangeCheck(this.order.data, this.DefaultRelaxedMaxRange) || | if (msg.likelyFailure || msg.obstructed && this.RelaxedMaxRangeCheck(this.order.data, this.DefaultRelaxedMaxRange) || | ||||
this.CheckRange(this.order.data)) | this.CheckRange(this.order.data)) | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
"WALKINGANDFIGHTING": { | "WALKINGANDFIGHTING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveTo(this.order.data)) | if (!this.MoveTo(this.order.data)) | ||||
Stan: this.order.data.iid || undefined necessary ? | |||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
// Show weapons rather than carried resources. | // Show weapons rather than carried resources. | ||||
Done Inline Actions+ return false ? Stan: + return false ? | |||||
this.SetAnimationVariant("combat"); | this.SetAnimationVariant("combat"); | ||||
this.StartTimer(0, 1000); | this.StartTimer(0, 1000); | ||||
return false; | return false; | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
this.FindWalkAndFightTargets(); | this.FindWalkAndFightTargets(); | ||||
}, | }, | ||||
"leave": function(msg) { | "leave": function(msg) { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.StopTimer(); | this.StopTimer(); | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
}, | }, | ||||
"MovementUpdate": function(msg) { | "MovementUpdate": function(msg) { | ||||
// If it looks like the path is failing, and we are close enough stop anyways. | // If it looks like the path is failing, and we are close enough stop anyways. | ||||
// This avoids pathing for an unreachable goal and reduces lag considerably. | // This avoids pathing for an unreachable goal and reduces lag considerably. | ||||
if (msg.likelyFailure || msg.obstructed && this.RelaxedMaxRangeCheck(this.order.data, this.DefaultRelaxedMaxRange) || | if (msg.likelyFailure || msg.obstructed && this.RelaxedMaxRangeCheck(this.order.data, this.DefaultRelaxedMaxRange) || | ||||
this.CheckRange(this.order.data)) | this.CheckRange(this.order.data)) | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
Done Inline Actions+ return false ? Stan: + return false ? | |||||
Done Inline ActionsNot needed. Freagarach: Not needed. | |||||
"PATROL": { | "PATROL": { | ||||
"enter": function() { | "enter": function() { | ||||
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.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
▲ Show 20 Lines • Show All 1,814 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
UnitAI.prototype.UnsetGarrisoned = function() | UnitAI.prototype.UnsetGarrisoned = function() | ||||
{ | { | ||||
delete this.isGarrisoned; | delete this.isGarrisoned; | ||||
this.SetMobile(); | this.SetMobile(); | ||||
}; | }; | ||||
UnitAI.prototype.GetGarrisonHolder = function() | |||||
{ | |||||
if (!this.isGarrisoned) | |||||
return INVALID_ENTITY; | |||||
let cmpGarrisonable = Engine.QueryInterface(this.entity, IID_Garrisonable); | |||||
return cmpGarrisonable ? cmpGarrisonable.HolderID() : INVALID_ENTITY; | |||||
}; | |||||
UnitAI.prototype.ShouldRespondToEndOfAlert = function() | UnitAI.prototype.ShouldRespondToEndOfAlert = function() | ||||
{ | { | ||||
return !this.orderQueue.length || this.orderQueue[0].type == "Garrison"; | return !this.orderQueue.length || this.orderQueue[0].type == "Garrison"; | ||||
}; | }; | ||||
UnitAI.prototype.SetImmobile = function() | UnitAI.prototype.SetImmobile = function() | ||||
{ | { | ||||
if (this.isImmobile) | if (this.isImmobile) | ||||
▲ Show 20 Lines • Show All 2,653 Lines • ▼ Show 20 Lines | UnitAI.prototype.GetQueryRange = function(iid) | ||||
if (iid === IID_Vision) | if (iid === IID_Vision) | ||||
{ | { | ||||
ret.max = visionRange; | ret.max = visionRange; | ||||
return ret; | return ret; | ||||
} | } | ||||
if (this.GetStance().respondStandGround) | if (this.GetStance().respondStandGround) | ||||
{ | { | ||||
let range = this.GetRange(iid); | let range = this.GetRange(iid); | ||||
if (!range) | if (!range) | ||||
return ret; | return ret; | ||||
Done Inline ActionsThese can be called using this.GetRange(iid). Freagarach: These can be called using `this.GetRange(iid)`. | |||||
ret.min = range.min; | ret.min = range.min; | ||||
ret.max = Math.min(range.max, visionRange); | ret.max = Math.min(range.max, visionRange); | ||||
} | } | ||||
else if (this.GetStance().respondChase) | else if (this.GetStance().respondChase) | ||||
ret.max = visionRange; | ret.max = visionRange; | ||||
else if (this.GetStance().respondHoldGround) | else if (this.GetStance().respondHoldGround) | ||||
{ | { | ||||
let range = this.GetRange(iid); | let range = this.GetRange(iid); | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
UnitAI.prototype.GetRange = function(iid, type) | UnitAI.prototype.GetRange = function(iid, type) | ||||
{ | { | ||||
let component = Engine.QueryInterface(this.entity, iid); | let component = Engine.QueryInterface(this.entity, iid); | ||||
if (!component) | if (!component) | ||||
return undefined; | return undefined; | ||||
return component.GetRange(type); | return component.GetRange(type); | ||||
}; | }; | ||||
Done Inline ActionsYou want this to be GetTurrets, not GetTurretPoints. wraitii: You want this to be GetTurrets, not GetTurretPoints. | |||||
UnitAI.prototype.CanAttack = function(target) | UnitAI.prototype.CanAttack = function(target) | ||||
{ | { | ||||
// Formation controllers should always respond to commands | // Formation controllers should always respond to commands | ||||
// (then the individual units can make up their own minds) | // (then the individual units can make up their own minds) | ||||
if (this.IsFormationController()) | if (this.IsFormationController()) | ||||
return true; | return true; | ||||
let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | let cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); | ||||
return cmpAttack && cmpAttack.CanAttack(target); | return cmpAttack && cmpAttack.CanAttack(target); | ||||
}; | }; | ||||
UnitAI.prototype.CanGarrison = function(target) | UnitAI.prototype.CanGarrison = function(target) | ||||
{ | { | ||||
// Formation controllers should always respond to commands | // Formation controllers should always respond to commands | ||||
Done Inline Actionsif(!cgh) return false ? Stan: if(!cgh) return false ? | |||||
// (then the individual units can make up their own minds). | // (then the individual units can make up their own minds). | ||||
if (this.IsFormationController()) | if (this.IsFormationController()) | ||||
Done Inline Actionsearly return if no vgp ? just an idea Stan: early return if no vgp ? just an idea | |||||
return true; | return true; | ||||
let cmpGarrisonable = Engine.QueryInterface(this.entity, IID_Garrisonable); | let cmpGarrisonable = Engine.QueryInterface(this.entity, IID_Garrisonable); | ||||
return cmpGarrisonable && cmpGarrisonable.CanGarrison(target); | return cmpGarrisonable && cmpGarrisonable.CanGarrison(target); | ||||
Done Inline Actionsreturn visibleGarrisonPoints.some() ? Stan: return visibleGarrisonPoints.some() ? | |||||
}; | }; | ||||
UnitAI.prototype.CanGather = function(target) | UnitAI.prototype.CanGather = function(target) | ||||
{ | { | ||||
// Formation controllers should always respond to commands | // Formation controllers should always respond to commands | ||||
// (then the individual units can make up their own minds). | // (then the individual units can make up their own minds). | ||||
if (this.IsFormationController()) | if (this.IsFormationController()) | ||||
return true; | return true; | ||||
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | ||||
return cmpResourceGatherer && cmpResourceGatherer.CanGather(target); | return cmpResourceGatherer && cmpResourceGatherer.CanGather(target); | ||||
}; | }; | ||||
Done Inline ActionsI guess the default param is useless ? Stan: I guess the default param is useless ? | |||||
UnitAI.prototype.CanHeal = function(target) | UnitAI.prototype.CanHeal = function(target) | ||||
{ | { | ||||
// Formation controllers should always respond to commands | // Formation controllers should always respond to commands | ||||
// (then the individual units can make up their own minds) | // (then the individual units can make up their own minds) | ||||
if (this.IsFormationController()) | if (this.IsFormationController()) | ||||
return true; | return true; | ||||
Done Inline ActionsMaybe CanSubUnitPerform(action, target, types) Stan: Maybe `CanSubUnitPerform(action, target, types)` | |||||
let cmpHeal = Engine.QueryInterface(this.entity, IID_Heal); | let cmpHeal = Engine.QueryInterface(this.entity, IID_Heal); | ||||
return cmpHeal && cmpHeal.CanHeal(target); | return cmpHeal && cmpHeal.CanHeal(target); | ||||
}; | }; | ||||
/** | /** | ||||
* Check if the entity can return carried resources at @param target | * Check if the entity can return carried resources at @param target | ||||
* @param checkCarriedResource check we are carrying resources | * @param checkCarriedResource check we are carrying resources | ||||
* @param cmpResourceGatherer if present, use this directly instead of re-querying. | * @param cmpResourceGatherer if present, use this directly instead of re-querying. | ||||
*/ | */ | ||||
UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource, cmpResourceGatherer = undefined) | UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource, cmpResourceGatherer = undefined) | ||||
{ | { | ||||
// Formation controllers should always respond to commands | // Formation controllers should always respond to commands | ||||
// (then the individual units can make up their own minds). | // (then the individual units can make up their own minds). | ||||
if (this.IsFormationController()) | if (this.IsFormationController()) | ||||
return true; | return true; | ||||
if (!cmpResourceGatherer) | if (!cmpResourceGatherer) | ||||
cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | ||||
Done Inline ActionsEarly continue ? Stan: Early continue ? | |||||
return cmpResourceGatherer && cmpResourceGatherer.CanReturnResource(target, checkCarriedResource); | return cmpResourceGatherer && cmpResourceGatherer.CanReturnResource(target, checkCarriedResource); | ||||
}; | }; | ||||
Done Inline ActionsCan it have a negative range ? Stan: Can it have a negative range ? | |||||
UnitAI.prototype.CanTrade = function(target) | UnitAI.prototype.CanTrade = function(target) | ||||
{ | { | ||||
Done Inline ActionsDunno if reduce would be faster https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max Stan: Dunno if reduce would be faster https://developer.mozilla.org/en… | |||||
Done Inline ActionsThen you'd need to make an array first? Freagarach: Then you'd need to make an array first? | |||||
// Formation controllers should always respond to commands | // Formation controllers should always respond to commands | ||||
// (then the individual units can make up their own minds). | // (then the individual units can make up their own minds). | ||||
if (this.IsFormationController()) | if (this.IsFormationController()) | ||||
return true; | return true; | ||||
Done Inline ActionsI guess you coud inline that ? Still dislike multiple return types (One could maybe add a boolean to the result object) Stan: I guess you coud inline that ? Still dislike multiple return types (One could maybe add a… | |||||
let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | ||||
return cmpTrader && cmpTrader.CanTrade(target); | return cmpTrader && cmpTrader.CanTrade(target); | ||||
}; | }; | ||||
UnitAI.prototype.CanRepair = function(target) | UnitAI.prototype.CanRepair = function(target) | ||||
{ | { | ||||
// Formation controllers should always respond to commands | // Formation controllers should always respond to commands | ||||
▲ Show 20 Lines • Show All 196 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | let cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
return cmpFormation && cmpFormation.GetMembers().every(ent => { | return cmpFormation && cmpFormation.GetMembers().every(ent => { | ||||
let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); | let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); | ||||
return cmpUnitAI[funcname].apply(cmpUnitAI, args); | return cmpUnitAI[funcname].apply(cmpUnitAI, args); | ||||
}); | }); | ||||
}; | }; | ||||
/** | |||||
* Add order to UnitAI components of all subunits. | |||||
Done Inline Actions@param ? Stan: @param ? | |||||
*/ | |||||
UnitAI.prototype.DelegateOrder = function(order) | |||||
{ | |||||
if (!order || !order.type) | |||||
return; | |||||
let cmpTurretHolder = Engine.QueryInterface(this.entity, IID_TurretHolder); | |||||
if (!cmpTurretHolder) | |||||
return; | |||||
for (let turret of cmpTurretHolder.GetEntities()) | |||||
Done Inline ActionsForEach slower than for (var x of y) Pros: You can pass the index in the callback We tend to avoid imperative style loops when we can use .some(), .find() etc. If it was a map instead of an array, that would be logical, Cons Seems to be slower/ have more overhead https://coderwall.com/p/kvzbpa/don-t-use-array-foreach-use-for-instead / http://jsperf.com/fast-array-foreach / https://jsperf.com/sdngjkn Less straightforward to read. Some other links https://medium.com/front-end-weekly/stop-array-foreach-and-start-using-filter-map-some-reduce-functions-298b4dabfa09 https://stackoverflow.com/questions/43821759/why-array-foreach-is-slower-than-for-loop-in-javascript Stan: ForEach slower than for (var x of y)
Pros:
You can pass the index in the callback… | |||||
{ | |||||
let cmpUnitAI = Engine.QueryInterface(turret, IID_UnitAI); | |||||
Done Inline ActionsEarly return ? Stan: Early return ?
| |||||
if (cmpUnitAI) | |||||
Done Inline ActionsShouldn't that be true (as in forced, because it's delegated by the player) ? Stan: Shouldn't that be true (as in forced, because it's delegated by the player) ? | |||||
Done Inline ActionsThis false is whether it is queued or not. The forced is within the order. Freagarach: This `false` is whether it is queued or not. The forced is within the `order`. | |||||
{ | |||||
let currentOrder = cmpUnitAI.GetOrders()[0]; | |||||
if (!currentOrder || !currentOrder.data || !currentOrder.data.target || | |||||
Done Inline ActionsCan it be undefined? Stan: Can it be undefined? | |||||
Done Inline ActionsIt can't be empty as long as the entity is garrisoned ^^ Freagarach: It can't be empty as long as the entity is garrisoned ^^ | |||||
currentOrder.data.target != order.target || currentOrder.type != order.type) | |||||
cmpUnitAI.AddOrder(order.type, order, false); | |||||
} | |||||
} | |||||
}; | |||||
/** | |||||
* @return {boolean} - Whether the passing of the order to our superunit has succeeded. | |||||
*/ | |||||
UnitAI.prototype.EscalateOrder = function(order) | |||||
{ | |||||
if (!order || !order.type || !this.isGarrisoned) | |||||
return false; | |||||
let cmpTurretable = Engine.QueryInterface(this.entity, IID_Turretable); | |||||
if (!cmpTurretable) | |||||
return false; | |||||
let turretHolder = cmpTurretable.HolderID(); | |||||
let cmpTurretHolderUnitAI = Engine.QueryInterface(turretHolder, IID_UnitAI); | |||||
if (!cmpTurretHolderUnitAI) | |||||
return false; | |||||
if (cmpTurretHolderUnitAI.IsIdle()) | |||||
{ | |||||
cmpTurretHolderUnitAI.AddOrder(order.type, order.data, false); | |||||
return true; | |||||
} | |||||
return false; | |||||
}; | |||||
wraitiiUnsubmitted Done Inline ActionsYou no longer need these I believe. wraitii: You no longer need these I believe. | |||||
UnitAI.prototype.UnitFsm = new FSM(UnitAI.prototype.UnitFsmSpec); | UnitAI.prototype.UnitFsm = new FSM(UnitAI.prototype.UnitFsmSpec); | ||||
Engine.RegisterComponentType(IID_UnitAI, "UnitAI", UnitAI); | Engine.RegisterComponentType(IID_UnitAI, "UnitAI", UnitAI); |
this.order.data.iid || undefined necessary ?