Changeset View
Standalone View
binaries/data/mods/public/simulation/components/UnitAI.js
Show First 20 Lines • Show All 2,085 Lines • ▼ Show 20 Lines | "GATHER": { | ||||
var nearby = this.FindNearbyResource(function(ent, type, template) { | var nearby = this.FindNearbyResource(function(ent, type, template) { | ||||
return ( | return ( | ||||
ent != oldTarget | ent != oldTarget | ||||
&& ((type.generic == "treasure" && oldType.generic == "treasure") | && ((type.generic == "treasure" && oldType.generic == "treasure") | ||||
|| (type.specific == oldType.specific | || (type.specific == oldType.specific | ||||
&& (type.specific != "meat" || oldTemplate == template))) | && (type.specific != "meat" || oldTemplate == template))) | ||||
); | ); | ||||
}, oldTarget); | }, oldTarget); | ||||
if (nearby) | if (nearby) | ||||
Polakrity: From there. | |||||
{ | { | ||||
this.PerformGather(nearby, false, false); | this.PerformGather(nearby, false, false); | ||||
return true; | return true; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// It's probably better in this case, to avoid units getting stuck around a dropsite | // It's probably better in this case, to avoid units getting stuck around a dropsite | ||||
// in a "Target is far away, full, nearby are no good resources, return to dropsite" loop | // in a "Target is far away, full, nearby are no good resources, return to dropsite" loop | ||||
Show All 35 Lines | "GATHER": { | ||||
if (msg.data.error) | if (msg.data.error) | ||||
{ | { | ||||
// We failed to reach the target | // We failed to reach the target | ||||
// remove us from the list of entities gathering from Resource. | // remove us from the list of entities gathering from Resource. | ||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | ||||
if (cmpSupply && cmpOwnership) | if (cmpSupply && cmpOwnership) | ||||
cmpSupply.RemoveGatherer(this.entity, cmpOwnership.GetOwner()); | cmpSupply.RemoveGatherer(this.entity, cmpOwnership.GetOwner()); | ||||
Not Done Inline ActionsWhat's the point of this if else ? Both case remove the entity no ? Stan: What's the point of this if else ? Both case remove the entity no ? | |||||
Done Inline Actionswhen you have ownership, it deletes directly from that player, if you have not, it tries to delete from every player Silier: when you have ownership, it deletes directly from that player, if you have not, it tries to… | |||||
else if (cmpSupply) | else if (cmpSupply) | ||||
cmpSupply.RemoveGatherer(this.entity); | cmpSupply.RemoveGatherer(this.entity); | ||||
// Save the current order's data in case we need it later | // Save the current order's data in case we need it later | ||||
var oldType = this.order.data.type; | var oldType = this.order.data.type; | ||||
var oldTarget = this.order.data.target; | var oldTarget = this.order.data.target; | ||||
var oldTemplate = this.order.data.template; | var oldTemplate = this.order.data.template; | ||||
Show All 28 Lines | "GATHER": { | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
if (!this.gatheringTarget) | if (!this.gatheringTarget) | ||||
return; | return; | ||||
// don't use ownership because this is called after a conversion/resignation | // don't use ownership because this is called after a conversion/resignation | ||||
Not Done Inline ActionsUppercase. Polakrity: Uppercase. | |||||
// and the ownership would be invalid then. | // and the ownership would be invalid then. | ||||
var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | ||||
if (cmpSupply) | if (cmpSupply) | ||||
cmpSupply.RemoveGatherer(this.entity); | cmpSupply.RemoveGatherer(this.entity); | ||||
delete this.gatheringTarget; | delete this.gatheringTarget; | ||||
}, | }, | ||||
}, | }, | ||||
Show All 40 Lines | "GATHER": { | ||||
// Nothing better to do: go back to dropsite | // Nothing better to do: go back to dropsite | ||||
var nearby = this.FindNearestDropsite(resourceType.generic); | var nearby = this.FindNearestDropsite(resourceType.generic); | ||||
if (nearby) | if (nearby) | ||||
{ | { | ||||
this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); | this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); | ||||
return; | return; | ||||
} | } | ||||
// No dropsites, just give up | // No dropsites, just give up | ||||
Not Done Inline Actionsshoudln't we delete this.gatheringTarget like above ? Stan: shoudln't we delete this.gatheringTarget like above ? | |||||
Done Inline Actionsnot defined in WALKING branch so there is nothing to delete :) Silier: not defined in WALKING branch so there is nothing to delete :) | |||||
}, | }, | ||||
}, | }, | ||||
"GATHERING": { | "GATHERING": { | ||||
"enter": function() { | "enter": function() { | ||||
this.gatheringTarget = this.order.data.target; // deleted in "leave". | this.gatheringTarget = this.order.data.target; // deleted in "leave". | ||||
// Check if the resource is full. | // Check if the resource is full. | ||||
if (this.gatheringTarget) | if (this.gatheringTarget) | ||||
{ | { | ||||
// Check that we can gather from the resource we're supposed to gather from. | // Check that we can gather from the resource we're supposed to gather from. | ||||
// Will only be added if we're not already in. | // Will only be added if we're not already in. | ||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | ||||
if (!cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity)) | if (!cmpOwnership || !cmpSupply || !cmpSupply.AddGatherer(cmpOwnership.GetOwner(), this.entity)) | ||||
{ | { | ||||
this.gatheringTarget = INVALID_ENTITY; | this.gatheringTarget = INVALID_ENTITY; | ||||
this.StartTimer(0); | this.StartTimer(0); | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
// If this order was forced, the player probably gave it, but now we've reached the target | // If this order was forced, the player probably gave it, but now we've reached the target | ||||
// switch to an unforced order (can be interrupted by attacks) | // switch to an unforced order (can be interrupted by attacks) | ||||
this.order.data.force = false; | this.order.data.force = false; | ||||
this.order.data.autoharvest = true; | this.order.data.autoharvest = true; | ||||
// Calculate timing based on gather rates | // Calculate timing based on gather rates | ||||
// This allows the gather rate to control how often we gather, instead of how much. | // This allows the gather rate to control how often we gather, instead of how much. | ||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | ||||
var rate = cmpResourceGatherer.GetTargetGatherRate(this.gatheringTarget); | let rate = cmpResourceGatherer.GetTargetGatherRate(this.gatheringTarget); | ||||
if (!rate) | if (!rate) | ||||
{ | { | ||||
// Try to find another target if the current one stopped existing | // Try to find another target if the current one stopped existing | ||||
if (!Engine.QueryInterface(this.gatheringTarget, IID_Identity)) | if (!Engine.QueryInterface(this.gatheringTarget, IID_Identity)) | ||||
{ | { | ||||
// Let the Timer logic handle this | // Let the Timer logic handle this | ||||
this.StartTimer(0); | this.StartTimer(0); | ||||
return false; | return false; | ||||
} | } | ||||
// No rate, give up on gathering | // No rate, give up on gathering | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return true; | return true; | ||||
} | } | ||||
// Scale timing interval based on rate, and start timer | // Scale timing interval based on rate, and start timer | ||||
// The offset should be at least as long as the repeat time so we use the same value for both. | // The offset should be at least as long as the repeat time so we use the same value for both. | ||||
var offset = 1000/rate; | let offset = 1000 / rate; | ||||
Not Done Inline ActionsMaybe u can change this comment now. Polakrity: Maybe u can change this comment now. | |||||
Done Inline Actionsno, comment is still correct because parameters usage in StartTimer Silier: no, comment is still correct because parameters usage in StartTimer | |||||
var repeat = offset; | this.StartTimer(offset, offset); | ||||
Not Done Inline ActionsSpaces. Stan: Spaces. | |||||
this.StartTimer(offset, repeat); | |||||
// We want to start the gather animation as soon as possible, | // We want to start the gather animation as soon as possible, | ||||
// but only if we're actually at the target and it's still alive | // but only if we're actually at the target and it's still alive | ||||
// (else it'll look like we're chopping empty air). | // (else it'll look like we're chopping empty air). | ||||
// (If it's not alive, the Timer handler will deal with sending us | // (If it's not alive, the Timer handler will deal with sending us | ||||
// off to a different target.) | // off to a different target.) | ||||
if (this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer)) | if (this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer)) | ||||
{ | { | ||||
this.StopMoving(); | this.StopMoving(); | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
var typename = "gather_" + this.order.data.type.specific; | let typename = "gather_" + this.order.data.type.specific; | ||||
this.SelectAnimation(typename); | this.SelectAnimation(typename); | ||||
} | } | ||||
return false; | return false; | ||||
}, | }, | ||||
"leave": function() { | "leave": function() { | ||||
this.StopTimer(); | this.StopTimer(); | ||||
// don't use ownership because this is called after a conversion/resignation | // don't use ownership because this is called after a conversion/resignation | ||||
Not Done Inline ActionsUppercase. Polakrity: Uppercase. | |||||
// and the ownership would be invalid then. | // and the ownership would be invalid then. | ||||
var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | ||||
if (cmpSupply) | if (cmpSupply) | ||||
cmpSupply.RemoveGatherer(this.entity); | cmpSupply.RemoveGatherer(this.entity); | ||||
delete this.gatheringTarget; | delete this.gatheringTarget; | ||||
// Show the carried resource, if we've gathered anything. | // Show the carried resource, if we've gathered anything. | ||||
this.SetDefaultAnimationVariant(); | this.SetDefaultAnimationVariant(); | ||||
}, | }, | ||||
"Timer": function(msg) { | "Timer": function(msg) { | ||||
var resourceTemplate = this.order.data.template; | let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | ||||
var resourceType = this.order.data.type; | |||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); | |||||
if (!cmpOwnership) | if (!cmpOwnership) | ||||
return; | return; | ||||
var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | let resourceTemplate = this.order.data.template; | ||||
let resourceType = this.order.data.type; | |||||
let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply); | |||||
if (cmpSupply && cmpSupply.IsAvailable(cmpOwnership.GetOwner(), this.entity)) | if (cmpSupply && cmpSupply.IsAvailable(cmpOwnership.GetOwner(), this.entity)) | ||||
{ | { | ||||
// Check we can still reach and gather from the target | // Check we can still reach and gather from the target | ||||
if (this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer) && this.CanGather(this.gatheringTarget)) | if (this.CanGather(this.gatheringTarget) && this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer)) | ||||
{ | { | ||||
// Gather the resources: | // Gather the resources: | ||||
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | |||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | |||||
// Try to gather treasure | // Try to gather treasure | ||||
if (cmpResourceGatherer.TryInstantGather(this.gatheringTarget)) | if (cmpResourceGatherer.TryInstantGather(this.gatheringTarget)) | ||||
return; | return; | ||||
// If we've already got some resources but they're the wrong type, | // If we've already got some resources but they're the wrong type, | ||||
// drop them first to ensure we're only ever carrying one type | // drop them first to ensure we're only ever carrying one type | ||||
if (cmpResourceGatherer.IsCarryingAnythingExcept(resourceType.generic)) | if (cmpResourceGatherer.IsCarryingAnythingExcept(resourceType.generic)) | ||||
cmpResourceGatherer.DropResources(); | cmpResourceGatherer.DropResources(); | ||||
// Collect from the target | // Collect from the target | ||||
var status = cmpResourceGatherer.PerformGather(this.gatheringTarget); | let status = cmpResourceGatherer.PerformGather(this.gatheringTarget); | ||||
// If we've collected as many resources as possible, | // If we've collected as many resources as possible, | ||||
// return to the nearest dropsite | // return to the nearest dropsite | ||||
if (status.filled) | if (status.filled) | ||||
{ | { | ||||
var nearby = this.FindNearestDropsite(resourceType.generic); | let nearestDropsite = this.FindNearestDropsite(resourceType.generic); | ||||
if (nearby) | if (nearestDropsite) | ||||
{ | { | ||||
// (Keep this Gather order on the stack so we'll | // (Keep this Gather order on the stack so we'll | ||||
// continue gathering after returning) | // continue gathering after returning) | ||||
this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); | this.PushOrderFront("ReturnResource", { "target": nearestDropsite, "force": false }); | ||||
return; | return; | ||||
} | } | ||||
// Oh no, couldn't find any drop sites. Give up on gathering. | // Oh no, couldn't find any drop sites. Give up on gathering. | ||||
this.FinishOrder(); | this.FinishOrder(); | ||||
return; | return; | ||||
} | } | ||||
Show All 11 Lines | "GATHER": { | ||||
} | } | ||||
// Can't reach the target, or it doesn't exist any more | // Can't reach the target, or it doesn't exist any more | ||||
// We want to carry on gathering resources in the same area as | // We want to carry on gathering resources in the same area as | ||||
// the old one. So try to get close to the old resource's | // the old one. So try to get close to the old resource's | ||||
// last known position | // last known position | ||||
var maxRange = 8; // get close but not too close | |||||
if (this.order.data.lastPos && | if (this.order.data.lastPos && | ||||
this.MoveToPointRange(this.order.data.lastPos.x, this.order.data.lastPos.z, 0, maxRange)) | this.MoveToPointRange(this.order.data.lastPos.x, this.order.data.lastPos.z, 0, 8)) | ||||
Not Done Inline ActionsWhy 8 ? There is a range variable that's usually 4 also for some reason and should be a global. Stan: Why 8 ? There is a range variable that's usually 4 also for some reason and should be a global. | |||||
Done Inline Actionslooks like 4 represents distance of one tile, so here are 2 tiles ? you would need to ask philip Silier: looks like 4 represents distance of one tile, so here are 2 tiles ? you would need to ask philip | |||||
Not Done Inline ActionsMaybe then instead make the range/tilesize = 4 a global variable, then use it * 2 here ? Stan: Maybe then instead make the range/tilesize = 4 a global variable, then use it * 2 here ? | |||||
Not Done Inline ActionsHe is better to avoid magic number, no? Polakrity: He is better to avoid magic number, no? | |||||
Not Done Inline ActionsWell I don't know if we can get the tilesize from the engine :) Stan: Well I don't know if we can get the tilesize from the engine :) | |||||
{ | { | ||||
this.SetNextState("APPROACHING"); | this.SetNextState("APPROACHING"); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// We're already in range, can't get anywhere near it or the target is exhausted. | // We're already in range, can't get anywhere near it or the target is exhausted. | ||||
var herdPos = this.order.data.initPos; | let herdPos = this.order.data.initPos; | ||||
// Give up on this order and try our next queued order | // Give up on this order and try our next queued order | ||||
// but first check what is our next order and, if needed, insert a returnResource order | // but first check what is our next order and, if needed, insert a returnResource order | ||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | ||||
if (cmpResourceGatherer.IsCarrying(resourceType.generic) && | if (cmpResourceGatherer.IsCarrying(resourceType.generic) && | ||||
this.orderQueue.length > 1 && this.orderQueue[1] !== "ReturnResource" && | this.orderQueue.length > 1 && this.orderQueue[1] !== "ReturnResource" && | ||||
(this.orderQueue[1].type !== "Gather" || this.orderQueue[1].data.type.generic !== resourceType.generic)) | (this.orderQueue[1].type !== "Gather" || this.orderQueue[1].data.type.generic !== resourceType.generic)) | ||||
{ | { | ||||
let nearby = this.FindNearestDropsite(resourceType.generic); | let nearby = this.FindNearestDropsite(resourceType.generic); | ||||
Not Done Inline ActionsnearestDropsite like above. Polakrity: nearestDropsite like above. | |||||
if (nearby) | if (nearby) | ||||
this.orderQueue.splice(1, 0, { "type": "ReturnResource", "data": { "target": nearby, "force": false } }); | this.orderQueue.splice(1, 0, { "type": "ReturnResource", "data": { "target": nearby, "force": false } }); | ||||
} | } | ||||
if (this.FinishOrder()) | if (this.FinishOrder()) | ||||
return; | return; | ||||
// No remaining orders - pick a useful default behaviour | // No remaining orders - pick a useful default behaviour | ||||
// Try to find a new resource of the same specific type near our current position: | // Try to find a new resource of the same specific type near our current position: | ||||
// Also don't switch to a different type of huntable animal | // Also don't switch to a different type of huntable animal | ||||
var nearby = this.FindNearbyResource(function(ent, type, template) { | let nearbyResource = this.FindNearbyResource(function(ent, type, template) { | ||||
Not Done Inline Actionsarrow function ? Stan: arrow function ? | |||||
return ( | return ( | ||||
(type.generic == "treasure" && resourceType.generic == "treasure") | (type.generic == "treasure" && resourceType.generic == "treasure") | ||||
|| (type.specific == resourceType.specific | || (type.specific == resourceType.specific | ||||
&& (type.specific != "meat" || resourceTemplate == template)) | && (type.specific != "meat" || resourceTemplate == template)) | ||||
); | ); | ||||
}); | }); | ||||
if (nearby) | if (nearbyResource) | ||||
{ | { | ||||
this.PerformGather(nearby, false, false); | this.PerformGather(nearbyResource, false, false); | ||||
return; | return; | ||||
} | } | ||||
// If hunting, try to go to the initial herd position to see if we are more lucky | // If hunting, try to go to the initial herd position to see if we are more lucky | ||||
if (herdPos) | if (herdPos) | ||||
{ | { | ||||
this.GatherNearPosition(herdPos.x, herdPos.z, resourceType, resourceTemplate); | this.GatherNearPosition(herdPos.x, herdPos.z, resourceType, resourceTemplate); | ||||
return; | return; | ||||
} | } | ||||
// Nothing else to gather - if we're carrying anything then we should | // Nothing else to gather - if we're carrying anything then we should | ||||
// drop it off, and if not then we might as well head to the dropsite | // drop it off, and if not then we might as well head to the dropsite | ||||
// anyway because that's a nice enough place to congregate and idle | // anyway because that's a nice enough place to congregate and idle | ||||
var nearby = this.FindNearestDropsite(resourceType.generic); | let nearbyDropsites = this.FindNearestDropsite(resourceType.generic); | ||||
if (nearby) | if (nearbyDropsites) | ||||
{ | { | ||||
this.PushOrderFront("ReturnResource", { "target": nearby, "force": false }); | this.PushOrderFront("ReturnResource", { "target": nearbyDropsites, "force": false }); | ||||
return; | return; | ||||
} | } | ||||
// No dropsites - just give up | // No dropsites - just give up | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
▲ Show 20 Lines • Show All 3,280 Lines • ▼ Show 20 Lines | UnitAI.prototype.CanGarrison = function(target) | ||||
return true; | return true; | ||||
}; | }; | ||||
UnitAI.prototype.CanGather = function(target) | UnitAI.prototype.CanGather = function(target) | ||||
{ | { | ||||
if (this.IsTurret()) | if (this.IsTurret()) | ||||
return false; | return false; | ||||
// The target must be a valid resource supply, or the mirage of one. | // The target must be a valid resource supply, or the mirage of one. | ||||
var cmpResourceSupply = QueryMiragedInterface(target, IID_ResourceSupply); | let cmpResourceSupply = QueryMiragedInterface(target, IID_ResourceSupply); | ||||
if (!cmpResourceSupply) | if (!cmpResourceSupply) | ||||
return false; | return false; | ||||
// 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; | ||||
// Verify that we're able to respond to Gather commands | // Verify that we're able to respond to Gather commands | ||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer); | ||||
if (!cmpResourceGatherer) | if (!cmpResourceGatherer) | ||||
return false; | return false; | ||||
// Verify that we can gather from this target | // Verify that we can gather from this target | ||||
if (!cmpResourceGatherer.GetTargetGatherRate(target)) | if (!cmpResourceGatherer.GetTargetGatherRate(target)) | ||||
return false; | return false; | ||||
// No need to verify ownership as we should be able to gather from | // No need to verify ownership as we should be able to gather from | ||||
▲ Show 20 Lines • Show All 279 Lines • Show Last 20 Lines |
From there.