Changeset View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 1,472 Lines • ▼ Show 20 Lines | |||||
this.StopMoving(); | this.StopMoving(); | ||||
this.StopTimer(); | this.StopTimer(); | ||||
delete this.patrolStartPosOrder; | delete this.patrolStartPosOrder; | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
this.FindWalkAndFightTargets(); | this.FindWalkAndFightTargets(); | ||||
}, | }, | ||||
Stan: this.order.data.iid || undefined necessary ? | |||||
"MovementUpdate": function() { | "MovementUpdate": function() { | ||||
if (!this.CheckRange(this.order.data)) | if (!this.CheckRange(this.order.data)) | ||||
return; | return; | ||||
Done Inline Actions+ return false ? Stan: + return false ? | |||||
if (this.orderQueue.length == 1) | if (this.orderQueue.length == 1) | ||||
this.PushOrder("Patrol", this.patrolStartPosOrder); | this.PushOrder("Patrol", this.patrolStartPosOrder); | ||||
this.PushOrder(this.order.type, this.order.data); | this.PushOrder(this.order.type, this.order.data); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
}, | }, | ||||
"GUARD": { | "GUARD": { | ||||
"RemoveGuard": function() { | "RemoveGuard": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
}, | }, | ||||
"ESCORTING": { | "ESCORTING": { | ||||
"enter": function() { | "enter": function() { | ||||
if (!this.MoveToTargetRangeExplicit(this.isGuardOf, 0, this.guardRange)) | if (!this.MoveToTargetRangeExplicit(this.isGuardOf, 0, this.guardRange)) | ||||
{ | { | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
// Show weapons rather than carried resources. | // Show weapons rather than carried resources. | ||||
this.SetAnimationVariant("combat"); | this.SetAnimationVariant("combat"); | ||||
Done Inline Actions+ return false ? Stan: + return false ? | |||||
Done Inline ActionsNot needed. Freagarach: Not needed. | |||||
this.StartTimer(0, 1000); | this.StartTimer(0, 1000); | ||||
this.SelectAnimation("move"); | this.SelectAnimation("move"); | ||||
this.SetHeldPositionOnEntity(this.isGuardOf); | this.SetHeldPositionOnEntity(this.isGuardOf); | ||||
return false; | return false; | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
▲ Show 20 Lines • Show All 3,474 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
// AI has currently no access to BackToWork | // AI has currently no access to BackToWork | ||||
let cmpPlayer = QueryOwnerInterface(this.entity); | let cmpPlayer = QueryOwnerInterface(this.entity); | ||||
if (cmpPlayer && cmpPlayer.IsAI() && !this.IsFormationController() && | if (cmpPlayer && cmpPlayer.IsAI() && !this.IsFormationController() && | ||||
this.workOrders.length && this.workOrders[0].type == "Trade") | this.workOrders.length && this.workOrders[0].type == "Trade") | ||||
{ | { | ||||
let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader); | ||||
if (cmpTrader.HasBothMarkets() && | if (cmpTrader.HasBothMarkets() && | ||||
(cmpTrader.GetFirstMarket() == target && cmpTrader.GetSecondMarket() == source || | (cmpTrader.GetFirstMarket() == target && cmpTrader.GetSecondMarket() == source || | ||||
cmpTrader.GetFirstMarket() == source && cmpTrader.GetSecondMarket() == target)) | cmpTrader.GetFirstMarket() == source && cmpTrader.GetSecondMarket() == target)) | ||||
{ | { | ||||
this.BackToWork(); | this.BackToWork(); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 557 Lines • ▼ Show 20 Lines | |||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
if (!cmpOwnership || !(IsOwnedByPlayer(cmpOwnership.GetOwner(), target) || IsOwnedByAllyOfPlayer(cmpOwnership.GetOwner(), target))) | if (!cmpOwnership || !(IsOwnedByPlayer(cmpOwnership.GetOwner(), target) || IsOwnedByAllyOfPlayer(cmpOwnership.GetOwner(), target))) | ||||
return false; | return false; | ||||
// Verify that the target is not unhealable (or at max health) | // Verify that the target is not unhealable (or at max health) | ||||
var cmpHealth = Engine.QueryInterface(target, IID_Health); | var cmpHealth = Engine.QueryInterface(target, IID_Health); | ||||
if (!cmpHealth || cmpHealth.IsUnhealable()) | if (!cmpHealth || cmpHealth.IsUnhealable()) | ||||
return false; | return false; | ||||
// Verify that the target has no unhealable class | // Verify that the target has no unhealable class | ||||
var cmpIdentity = Engine.QueryInterface(target, IID_Identity); | var cmpIdentity = Engine.QueryInterface(target, IID_Identity); | ||||
Done Inline ActionsThese can be called using this.GetRange(iid). Freagarach: These can be called using `this.GetRange(iid)`. | |||||
if (!cmpIdentity) | if (!cmpIdentity) | ||||
return false; | return false; | ||||
if (MatchesClassList(cmpIdentity.GetClassesList(), cmpHeal.GetUnhealableClasses())) | if (MatchesClassList(cmpIdentity.GetClassesList(), cmpHeal.GetUnhealableClasses())) | ||||
return false; | return false; | ||||
// Verify that the target is a healable class | // Verify that the target is a healable class | ||||
if (MatchesClassList(cmpIdentity.GetClassesList(), cmpHeal.GetHealableClasses())) | if (MatchesClassList(cmpIdentity.GetClassesList(), cmpHeal.GetHealableClasses())) | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | |||||
UnitAI.prototype.MoveRandomly = function(distance) | UnitAI.prototype.MoveRandomly = function(distance) | ||||
{ | { | ||||
// To minimize drift all across the map, animals describe circles | // To minimize drift all across the map, animals describe circles | ||||
// approximated by polygons. | // approximated by polygons. | ||||
// And to avoid getting stuck in obstacles or narrow spaces, each side | // And to avoid getting stuck in obstacles or narrow spaces, each side | ||||
// of the polygon is obtained by trying to go away from a point situated | // of the polygon is obtained by trying to go away from a point situated | ||||
// half a meter backwards of the current position, after rotation. | // half a meter backwards of the current position, after rotation. | ||||
// We also add a fluctuation on the length of each side of the polygon (dist) | // We also add a fluctuation on the length of each side of the polygon (dist) | ||||
Done Inline Actionsearly return if no vgp ? just an idea Stan: early return if no vgp ? just an idea | |||||
// which, in addition to making the move more random, helps escaping narrow spaces | // which, in addition to making the move more random, helps escaping narrow spaces | ||||
// with bigger values of dist. | // with bigger values of dist. | ||||
Done Inline Actionsif(!cgh) return false ? Stan: if(!cgh) return false ? | |||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); | ||||
let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); | ||||
if (!cmpPosition || !cmpPosition.IsInWorld() || !cmpUnitMotion) | if (!cmpPosition || !cmpPosition.IsInWorld() || !cmpUnitMotion) | ||||
return; | return; | ||||
let pos = cmpPosition.GetPosition(); | let pos = cmpPosition.GetPosition(); | ||||
let ang = cmpPosition.GetRotation().y; | let ang = cmpPosition.GetRotation().y; | ||||
if (!this.roamAngle) | if (!this.roamAngle) | ||||
{ | { | ||||
this.roamAngle = (randBool() ? 1 : -1) * Math.PI / 6; | this.roamAngle = (randBool() ? 1 : -1) * Math.PI / 6; | ||||
ang -= this.roamAngle / 2; | ang -= this.roamAngle / 2; | ||||
this.startAngle = ang; | this.startAngle = ang; | ||||
} | } | ||||
else if (Math.abs((ang - this.startAngle + Math.PI) % (2 * Math.PI) - Math.PI) < Math.abs(this.roamAngle / 2)) | else if (Math.abs((ang - this.startAngle + Math.PI) % (2 * Math.PI) - Math.PI) < Math.abs(this.roamAngle / 2)) | ||||
this.roamAngle *= randBool() ? 1 : -1; | this.roamAngle *= randBool() ? 1 : -1; | ||||
let halfDelta = randFloat(this.roamAngle / 4, this.roamAngle * 3 / 4); | let halfDelta = randFloat(this.roamAngle / 4, this.roamAngle * 3 / 4); | ||||
Done Inline ActionsI guess the default param is useless ? Stan: I guess the default param is useless ? | |||||
// First half rotation to decrease the impression of immediate rotation | // First half rotation to decrease the impression of immediate rotation | ||||
ang += halfDelta; | ang += halfDelta; | ||||
cmpUnitMotion.FaceTowardsPoint(pos.x + 0.5 * Math.sin(ang), pos.z + 0.5 * Math.cos(ang)); | cmpUnitMotion.FaceTowardsPoint(pos.x + 0.5 * Math.sin(ang), pos.z + 0.5 * Math.cos(ang)); | ||||
// Then second half of the rotation | // Then second half of the rotation | ||||
ang += halfDelta; | ang += halfDelta; | ||||
let dist = randFloat(0.5, 1.5) * distance; | let dist = randFloat(0.5, 1.5) * distance; | ||||
cmpUnitMotion.MoveToPointRange(pos.x - 0.5 * Math.sin(ang), pos.z - 0.5 * Math.cos(ang), dist, dist); | cmpUnitMotion.MoveToPointRange(pos.x - 0.5 * Math.sin(ang), pos.z - 0.5 * Math.cos(ang), dist, dist); | ||||
}; | }; | ||||
Show All 20 Lines | |||||
return true; | return true; | ||||
var cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI); | var cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI); | ||||
return cmpUnitAI && (!cmpUnitAI.IsAnimal() || cmpUnitAI.IsDangerousAnimal()); | return cmpUnitAI && (!cmpUnitAI.IsAnimal() || cmpUnitAI.IsDangerousAnimal()); | ||||
}; | }; | ||||
let entsByPreferences = {}; | let entsByPreferences = {}; | ||||
let preferences = []; | let preferences = []; | ||||
let entsWithoutPref = []; | let entsWithoutPref = []; | ||||
for (let ent of ents) | for (let ent of ents) | ||||
Done Inline Actionsreturn visibleGarrisonPoints.some() ? Stan: return visibleGarrisonPoints.some() ? | |||||
{ | { | ||||
if (!attackfilter(ent)) | if (!attackfilter(ent)) | ||||
continue; | continue; | ||||
let pref = cmpAttack.GetPreference(ent); | let pref = cmpAttack.GetPreference(ent); | ||||
if (pref === null || pref === undefined) | if (pref === null || pref === undefined) | ||||
entsWithoutPref.push(ent); | entsWithoutPref.push(ent); | ||||
else if (!entsByPreferences[pref]) | else if (!entsByPreferences[pref]) | ||||
{ | { | ||||
Show All 22 Lines | |||||
{ | { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
if (!cmpFormation) | if (!cmpFormation) | ||||
return; | return; | ||||
cmpFormation.GetMembers().forEach(ent => { | cmpFormation.GetMembers().forEach(ent => { | ||||
var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); | var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); | ||||
cmpUnitAI[funcname].apply(cmpUnitAI, args); | cmpUnitAI[funcname].apply(cmpUnitAI, args); | ||||
}); | }); | ||||
Done Inline ActionsEarly continue ? Stan: Early continue ? | |||||
}; | }; | ||||
/** | /** | ||||
Done Inline ActionsCan it have a negative range ? Stan: Can it have a negative range ? | |||||
* 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. | ||||
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? | |||||
*/ | */ | ||||
UnitAI.prototype.TestAllMemberFunction = function(funcname, args) | UnitAI.prototype.TestAllMemberFunction = function(funcname, args) | ||||
{ | { | ||||
var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); | ||||
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… | |||||
if (!cmpFormation) | if (!cmpFormation) | ||||
return false; | return false; | ||||
return cmpFormation.GetMembers().every(ent => { | return cmpFormation.GetMembers().every(ent => { | ||||
var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); | var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); | ||||
return cmpUnitAI[funcname].apply(cmpUnitAI, args); | return cmpUnitAI[funcname].apply(cmpUnitAI, args); | ||||
}); | }); | ||||
}; | }; | ||||
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); | ||||
Context not available. | |||||
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`. | |||||
Done Inline ActionsEarly return ? Stan: Early return ?
| |||||
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… | |||||
Done Inline ActionsMaybe CanSubUnitPerform(action, target, types) Stan: Maybe `CanSubUnitPerform(action, target, types)` | |||||
Done Inline Actions@param ? Stan: @param ? | |||||
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 ^^ | |||||
Done Inline ActionsYou want this to be GetTurrets, not GetTurretPoints. wraitii: You want this to be GetTurrets, not GetTurretPoints. | |||||
Done Inline ActionsYou no longer need these I believe. wraitii: You no longer need these I believe. |
this.order.data.iid || undefined necessary ?