mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-07-01 13:07:22 +00:00
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:
@@ -529,6 +529,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.RememberTargetPosition();
|
this.RememberTargetPosition();
|
||||||
|
this.order.data.initPos = this.order.data.lastPos;
|
||||||
|
|
||||||
if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer))
|
if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer))
|
||||||
this.SetNextState("INDIVIDUAL.GATHER.GATHERING");
|
this.SetNextState("INDIVIDUAL.GATHER.GATHERING");
|
||||||
@@ -2059,12 +2060,13 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
this.SetNextState("GATHERING");
|
this.SetNextState("GATHERING");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.SelectAnimation("move");
|
this.SelectAnimation("move");
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
"MovementUpdate": function(msg) {
|
"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");
|
this.SetNextState("GATHERING");
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -2100,7 +2102,8 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
|
|
||||||
"MovementUpdate": function(msg) {
|
"MovementUpdate": function(msg) {
|
||||||
// If we failed, the GATHERING timer will handle finding a valid resource.
|
// 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) {
|
"Timer": function(msg) {
|
||||||
var resourceTemplate = this.order.data.template;
|
let resourceTemplate = this.order.data.template;
|
||||||
var resourceType = this.order.data.type;
|
let resourceType = this.order.data.type;
|
||||||
|
|
||||||
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
|
let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
|
||||||
if (!cmpOwnership)
|
if (!cmpOwnership)
|
||||||
return;
|
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))
|
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.CheckTargetRange(this.gatheringTarget, IID_ResourceGatherer) && this.CanGather(this.gatheringTarget))
|
||||||
{
|
{
|
||||||
// Gather the resources:
|
// Gather the resources:
|
||||||
|
|
||||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
|
let 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))
|
||||||
@@ -2208,13 +2210,13 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
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 nearby = this.FindNearestDropsite(resourceType.generic);
|
||||||
if (nearby)
|
if (nearby)
|
||||||
{
|
{
|
||||||
// (Keep this Gather order on the stack so we'll
|
// (Keep this Gather order on the stack so we'll
|
||||||
@@ -2253,15 +2255,14 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
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))
|
||||||
@@ -2277,13 +2278,14 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
|
|
||||||
// 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 nearby = this.FindNearbyResource(function(ent, type, template) {
|
||||||
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))
|
||||||
);
|
);
|
||||||
});
|
}, new Vector2D(herdPos.x, herdPos.z));
|
||||||
|
|
||||||
if (nearby)
|
if (nearby)
|
||||||
{
|
{
|
||||||
this.PerformGather(nearby, false, false);
|
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
|
// 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);
|
nearby = this.FindNearestDropsite(resourceType.generic);
|
||||||
if (nearby)
|
if (nearby)
|
||||||
{
|
{
|
||||||
this.PushOrderFront("ReturnResource", { "target": nearby, "force": false });
|
this.PushOrderFront("ReturnResource", { "target": nearby, "force": false });
|
||||||
@@ -2640,16 +2642,16 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
return; // ignore other buildings
|
return; // ignore other buildings
|
||||||
|
|
||||||
// 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 oldData = this.order.data;
|
let oldData = this.order.data;
|
||||||
|
|
||||||
// Save the current state so we can continue walking if necessary
|
// 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.
|
// 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).
|
// 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
|
// Drop any resource we can if we are in range when the construction finishes
|
||||||
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
|
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
|
||||||
var cmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite);
|
let cmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite);
|
||||||
if (cmpResourceGatherer && cmpResourceDropsite && this.CheckTargetRange(msg.data.newentity, IID_Builder) &&
|
if (cmpResourceGatherer && cmpResourceDropsite && this.CheckTargetRange(msg.data.newentity, IID_Builder) &&
|
||||||
this.CanReturnResource(msg.data.newentity, true))
|
this.CanReturnResource(msg.data.newentity, true))
|
||||||
{
|
{
|
||||||
@@ -2694,13 +2696,18 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
// the build command should look for nearby resources to gather
|
// the build command should look for nearby resources to gather
|
||||||
if ((oldData.force || oldData.autoharvest) && this.CanReturnResource(msg.data.newentity, false))
|
if ((oldData.force || oldData.autoharvest) && this.CanReturnResource(msg.data.newentity, false))
|
||||||
{
|
{
|
||||||
var cmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite);
|
let types = cmpResourceDropsite.GetTypes();
|
||||||
var 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,
|
// 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!
|
// 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);
|
return (types.indexOf(type.generic) != -1);
|
||||||
}, msg.data.newentity);
|
}, pos);
|
||||||
|
|
||||||
if (nearby)
|
if (nearby)
|
||||||
{
|
{
|
||||||
this.PerformGather(nearby, true, false);
|
this.PerformGather(nearby, true, false);
|
||||||
@@ -2709,7 +2716,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Look for a nearby foundation to help with
|
// Look for a nearby foundation to help with
|
||||||
var nearbyFoundation = this.FindNearbyFoundation();
|
let nearbyFoundation = this.FindNearbyFoundation();
|
||||||
if (nearbyFoundation)
|
if (nearbyFoundation)
|
||||||
{
|
{
|
||||||
this.AddOrder("Repair", { "target": nearbyFoundation, "autocontinue": oldData.autocontinue, "force": false }, true);
|
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
|
// Unit was approaching and there's nothing to do now, so switch to walking
|
||||||
if (oldState === "INDIVIDUAL.REPAIR.APPROACHING")
|
if (oldState === "INDIVIDUAL.REPAIR.APPROACHING")
|
||||||
{
|
|
||||||
// We're already walking to the given point, so add this as a order.
|
// We're already walking to the given point, so add this as a order.
|
||||||
this.WalkToTarget(msg.data.newentity, true);
|
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
|
* Returns the entity ID of the nearest resource supply where the given
|
||||||
* filter returns true, or undefined if none can be found.
|
* 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
|
* TODO: extend this to exclude resources that already have lots of
|
||||||
* gatherers.
|
* 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)
|
if (!cmpOwnership || cmpOwnership.GetOwner() == INVALID_PLAYER)
|
||||||
return undefined;
|
return undefined;
|
||||||
var owner = cmpOwnership.GetOwner();
|
let owner = cmpOwnership.GetOwner();
|
||||||
|
|
||||||
// We accept resources owned by Gaia or any player
|
// 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);
|
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
|
||||||
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||||
let entity = this.entity;
|
let pos = position;
|
||||||
if (target)
|
if (!pos)
|
||||||
{
|
{
|
||||||
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
|
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
|
||||||
if (cmpPosition && cmpPosition.IsInWorld())
|
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 => {
|
return nearby.find(ent => {
|
||||||
if (!this.CanGather(ent) || !this.CheckTargetVisible(ent))
|
if (!this.CanGather(ent) || !this.CheckTargetVisible(ent))
|
||||||
return false;
|
return false;
|
||||||
var cmpResourceSupply = Engine.QueryInterface(ent, IID_ResourceSupply);
|
let cmpResourceSupply = Engine.QueryInterface(ent, IID_ResourceSupply);
|
||||||
var type = cmpResourceSupply.GetType();
|
let type = cmpResourceSupply.GetType();
|
||||||
var amount = cmpResourceSupply.GetCurrentAmount();
|
let amount = cmpResourceSupply.GetCurrentAmount();
|
||||||
|
|
||||||
var template = cmpTemplateManager.GetCurrentTemplateName(ent);
|
let template = cmpTemplateManager.GetCurrentTemplateName(ent);
|
||||||
// Remove "resource|" prefix from template names, if present.
|
// Remove "resource|" prefix from template names, if present.
|
||||||
if (template.indexOf("resource|") != -1)
|
if (template.indexOf("resource|") != -1)
|
||||||
template = template.slice(9);
|
template = template.slice(9);
|
||||||
@@ -5031,6 +5036,7 @@ UnitAI.prototype.PerformGather = function(target, queued, force)
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.RememberTargetPosition(order);
|
this.RememberTargetPosition(order);
|
||||||
|
order.initPos = order.lastPos;
|
||||||
|
|
||||||
this.AddOrder("Gather", order, queued);
|
this.AddOrder("Gather", order, queued);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user