1
0
forked from 0ad/0ad

Return Gathering to A23 behaviour - Make units try to gather near the target resource's position instead of their position.

Units were incorrectly looking at resources near their position
following 7d53fb19a2.

Fixes #5477.

Differential Revision: https://code.wildfiregames.com/D2034
This was SVN commit r22428.
This commit is contained in:
wraitii 2019-07-03 17:57:16 +00:00
parent 5fef05d780
commit 8a38cfb7cf

View File

@ -529,6 +529,7 @@ UnitAI.prototype.UnitFsmSpec = {
}
this.RememberTargetPosition();
this.order.data.initPos = this.order.data.lastPos;
if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer))
this.SetNextState("INDIVIDUAL.GATHER.GATHERING");
@ -2059,12 +2060,13 @@ UnitAI.prototype.UnitFsmSpec = {
this.SetNextState("GATHERING");
return true;
}
this.SelectAnimation("move");
return false;
},
"MovementUpdate": function(msg) {
// If we failed, the GATHERING timer will handle finding a valid resource.
// The GATHERING timer will handle finding a valid resource.
this.SetNextState("GATHERING");
},
@ -2100,7 +2102,8 @@ UnitAI.prototype.UnitFsmSpec = {
"MovementUpdate": function(msg) {
// If we failed, the GATHERING timer will handle finding a valid resource.
this.SetNextState("GATHERING");
if (msg.error || this.CheckRange(this.order.data))
this.SetNextState("GATHERING");
},
},
@ -2181,22 +2184,21 @@ UnitAI.prototype.UnitFsmSpec = {
},
"Timer": function(msg) {
var resourceTemplate = this.order.data.template;
var resourceType = this.order.data.type;
let resourceTemplate = this.order.data.template;
let resourceType = this.order.data.type;
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
if (!cmpOwnership)
return;
var cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply);
let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply);
if (cmpSupply && cmpSupply.IsAvailable(cmpOwnership.GetOwner(), this.entity))
{
// Check we can still reach and gather from the target
if (this.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer) && this.CanGather(this.gatheringTarget))
{
// Gather the resources:
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
// Try to gather treasure
if (cmpResourceGatherer.TryInstantGather(this.gatheringTarget))
@ -2208,13 +2210,13 @@ UnitAI.prototype.UnitFsmSpec = {
cmpResourceGatherer.DropResources();
// 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,
// return to the nearest dropsite
if (status.filled)
{
var nearby = this.FindNearestDropsite(resourceType.generic);
let nearby = this.FindNearestDropsite(resourceType.generic);
if (nearby)
{
// (Keep this Gather order on the stack so we'll
@ -2253,15 +2255,14 @@ UnitAI.prototype.UnitFsmSpec = {
return;
}
}
}
// 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
// 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) &&
this.orderQueue.length > 1 && this.orderQueue[1] !== "ReturnResource" &&
(this.orderQueue[1].type !== "Gather" || this.orderQueue[1].data.type.generic !== resourceType.generic))
@ -2277,13 +2278,14 @@ UnitAI.prototype.UnitFsmSpec = {
// 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
var nearby = this.FindNearbyResource(function(ent, type, template) {
let nearby = this.FindNearbyResource(function(ent, type, template) {
return (
(type.generic == "treasure" && resourceType.generic == "treasure")
|| (type.specific == resourceType.specific
&& (type.specific != "meat" || resourceTemplate == template))
(type.generic == "treasure" && resourceType.generic == "treasure") ||
(type.specific == resourceType.specific &&
(type.specific != "meat" || resourceTemplate == template))
);
});
}, new Vector2D(herdPos.x, herdPos.z));
if (nearby)
{
this.PerformGather(nearby, false, false);
@ -2301,7 +2303,7 @@ UnitAI.prototype.UnitFsmSpec = {
// 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
var nearby = this.FindNearestDropsite(resourceType.generic);
nearby = this.FindNearestDropsite(resourceType.generic);
if (nearby)
{
this.PushOrderFront("ReturnResource", { "target": nearby, "force": false });
@ -2640,16 +2642,16 @@ UnitAI.prototype.UnitFsmSpec = {
return; // ignore other buildings
// Save the current order's data in case we need it later
var oldData = this.order.data;
let oldData = this.order.data;
// Save the current state so we can continue walking if necessary
// FinishOrder() below will switch to IDLE if there's no order, which sets the idle animation.
// Idle animation while moving towards finished construction looks weird (ghosty).
var oldState = this.GetCurrentState();
let oldState = this.GetCurrentState();
// Drop any resource we can if we are in range when the construction finishes
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
var cmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite);
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
let cmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite);
if (cmpResourceGatherer && cmpResourceDropsite && this.CheckTargetRange(msg.data.newentity, IID_Builder) &&
this.CanReturnResource(msg.data.newentity, true))
{
@ -2694,13 +2696,18 @@ UnitAI.prototype.UnitFsmSpec = {
// the build command should look for nearby resources to gather
if ((oldData.force || oldData.autoharvest) && this.CanReturnResource(msg.data.newentity, false))
{
var cmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite);
var types = cmpResourceDropsite.GetTypes();
let types = cmpResourceDropsite.GetTypes();
let pos;
let cmpPosition = Engine.QueryInterface(msg.data.newentity, IID_Position);
if (cmpPosition && cmpPosition.IsInWorld())
pos = cmpPosition.GetPosition2D();
// TODO: Slightly undefined behavior here, we don't know what type of resource will be collected,
// may cause problems for AIs (especially hunting fast animals), but avoid ugly hacks to fix that!
var nearby = this.FindNearbyResource(function(ent, type, template) {
let nearby = this.FindNearbyResource(function(ent, type, template) {
return (types.indexOf(type.generic) != -1);
}, msg.data.newentity);
}, pos);
if (nearby)
{
this.PerformGather(nearby, true, false);
@ -2709,7 +2716,7 @@ UnitAI.prototype.UnitFsmSpec = {
}
// Look for a nearby foundation to help with
var nearbyFoundation = this.FindNearbyFoundation();
let nearbyFoundation = this.FindNearbyFoundation();
if (nearbyFoundation)
{
this.AddOrder("Repair", { "target": nearbyFoundation, "autocontinue": oldData.autocontinue, "force": false }, true);
@ -2718,10 +2725,8 @@ UnitAI.prototype.UnitFsmSpec = {
// Unit was approaching and there's nothing to do now, so switch to walking
if (oldState === "INDIVIDUAL.REPAIR.APPROACHING")
{
// We're already walking to the given point, so add this as a order.
this.WalkToTarget(msg.data.newentity, true);
}
},
},
@ -3903,40 +3908,40 @@ UnitAI.prototype.MustKillGatherTarget = function(ent)
/**
* Returns the entity ID of the nearest resource supply where the given
* filter returns true, or undefined if none can be found.
* if target if given, the nearest is computed versus this target position.
* if position (as a vector2D) is given, the nearest is computed versus this position.
* TODO: extend this to exclude resources that already have lots of
* gatherers.
*/
UnitAI.prototype.FindNearbyResource = function(filter, target)
UnitAI.prototype.FindNearbyResource = function(filter, position)
{
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
if (!cmpOwnership || cmpOwnership.GetOwner() == INVALID_PLAYER)
return undefined;
var owner = cmpOwnership.GetOwner();
let owner = cmpOwnership.GetOwner();
// We accept resources owned by Gaia or any player
var players = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetAllPlayers();
let players = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetAllPlayers();
var range = 64; // TODO: what's a sensible number?
let range = 64; // TODO: what's a sensible number?
var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
let entity = this.entity;
if (target)
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
let pos = position;
if (!pos)
{
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
if (cmpPosition && cmpPosition.IsInWorld())
entity = target;
pos = cmpPosition.GetPosition2D();
}
var nearby = cmpRangeManager.ExecuteQuery(entity, 0, range, players, IID_ResourceSupply);
let nearby = cmpRangeManager.ExecuteQueryAroundPos(pos, 0, range, players, IID_ResourceSupply);
return nearby.find(ent => {
if (!this.CanGather(ent) || !this.CheckTargetVisible(ent))
return false;
var cmpResourceSupply = Engine.QueryInterface(ent, IID_ResourceSupply);
var type = cmpResourceSupply.GetType();
var amount = cmpResourceSupply.GetCurrentAmount();
let cmpResourceSupply = Engine.QueryInterface(ent, IID_ResourceSupply);
let type = cmpResourceSupply.GetType();
let amount = cmpResourceSupply.GetCurrentAmount();
var template = cmpTemplateManager.GetCurrentTemplateName(ent);
let template = cmpTemplateManager.GetCurrentTemplateName(ent);
// Remove "resource|" prefix from template names, if present.
if (template.indexOf("resource|") != -1)
template = template.slice(9);
@ -5031,6 +5036,7 @@ UnitAI.prototype.PerformGather = function(target, queued, force)
};
this.RememberTargetPosition(order);
order.initPos = order.lastPos;
this.AddOrder("Gather", order, queued);
};