1
0
forked from mirrors/0ad

Make CommitResources accept a target, not a type.

This moves some resource committing logic from `UnitAI` to
`ResourceGatherer`.
Allows easier modification by modders, and cleaner separation of
concerns.

Check if the carried resources actually changed before sending the
message.

Make all paths through Repair.ConstructionFinished return resources.

Patch by: Freagarach
Reviewed By: wraitii
Differential Revision: https://code.wildfiregames.com/D2664
This was SVN commit r23733.
This commit is contained in:
wraitii
2020-06-04 11:01:06 +00:00
parent 7440523ade
commit cdfa6cb8b4
2 changed files with 76 additions and 73 deletions
@@ -294,22 +294,32 @@ ResourceGatherer.prototype.IsCarryingAnythingExcept = function(exceptedType)
/**
* Transfer our carried resources to our owner immediately.
* Only resources of the given types will be transferred.
* (This should typically be called after reaching a dropsite).
* Only resources of the appropriate types will be transferred.
* (This should typically be called after reaching a dropsite.)
*
* @param {number} target - The target entity ID to drop resources at.
*/
ResourceGatherer.prototype.CommitResources = function(types)
ResourceGatherer.prototype.CommitResources = function(target)
{
let cmpResourceDropsite = Engine.QueryInterface(target, IID_ResourceDropsite);
if (!cmpResourceDropsite)
return;
let cmpPlayer = QueryOwnerInterface(this.entity);
if (!cmpPlayer)
return;
if (cmpPlayer)
for (let type of types)
if (type in this.carrying)
{
cmpPlayer.AddResource(type, this.carrying[type]);
delete this.carrying[type];
}
let changed = false;
for (let type in this.carrying)
if (cmpResourceDropsite.AcceptsType(type))
{
cmpPlayer.AddResource(type, this.carrying[type]);
delete this.carrying[type];
changed = true;
}
Engine.PostMessage(this.entity, MT_ResourceCarryingChanged, { "to": this.GetCarryingStatus() });
if (changed)
Engine.PostMessage(this.entity, MT_ResourceCarryingChanged, { "to": this.GetCarryingStatus() });
};
/**
@@ -579,23 +579,19 @@ UnitAI.prototype.UnitFsmSpec = {
"Order.ReturnResource": function(msg) {
// Check if the dropsite is already in range
if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer) && this.CanReturnResource(this.order.data.target, true))
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer) &&
this.CanReturnResource(this.order.data.target, true, cmpResourceGatherer))
{
var cmpResourceDropsite = Engine.QueryInterface(this.order.data.target, IID_ResourceDropsite);
if (cmpResourceDropsite)
{
// Dump any resources we can
var dropsiteTypes = cmpResourceDropsite.GetTypes();
cmpResourceGatherer.CommitResources(this.order.data.target);
Engine.QueryInterface(this.entity, IID_ResourceGatherer).CommitResources(dropsiteTypes);
// Stop showing the carried resource animation.
this.SetDefaultAnimationVariant();
// Stop showing the carried resource animation.
this.SetDefaultAnimationVariant();
// Our next order should always be a Gather,
// so just switch back to that order
this.FinishOrder();
return;
}
// Our next order should always be a Gather,
// so just switch back to that order.
this.FinishOrder();
return;
}
this.SetNextState("INDIVIDUAL.RETURNRESOURCE.APPROACHING");
},
@@ -2694,25 +2690,19 @@ UnitAI.prototype.UnitFsmSpec = {
"MovementUpdate": function(msg) {
// Check the dropsite is in range and we can return our resource there
// (we didn't get stopped before reaching it)
if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer) && this.CanReturnResource(this.order.data.target, true))
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
if (this.CheckTargetRange(this.order.data.target, IID_ResourceGatherer) &&
this.CanReturnResource(this.order.data.target, true, cmpResourceGatherer))
{
let cmpResourceDropsite = Engine.QueryInterface(this.order.data.target, IID_ResourceDropsite);
if (cmpResourceDropsite)
{
// Dump any resources we can
let dropsiteTypes = cmpResourceDropsite.GetTypes();
cmpResourceGatherer.CommitResources(this.order.data.target);
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
cmpResourceGatherer.CommitResources(dropsiteTypes);
// Stop showing the carried resource animation.
this.SetDefaultAnimationVariant();
// Stop showing the carried resource animation.
this.SetDefaultAnimationVariant();
// Our next order should always be a Gather,
// so just switch back to that order
this.FinishOrder();
return;
}
// Our next order should always be a Gather,
// so just switch back to that order.
this.FinishOrder();
return;
}
if (msg.obstructed)
@@ -2721,8 +2711,6 @@ UnitAI.prototype.UnitFsmSpec = {
// If we are here: we are in range but not carrying the right resources (or resources at all),
// the dropsite was destroyed, or we couldn't reach it, or ownership changed.
// Look for a new one.
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
let genericType = cmpResourceGatherer.GetMainCarryingType();
let nearby = this.FindNearestDropsite(genericType);
if (nearby)
@@ -2898,12 +2886,10 @@ UnitAI.prototype.UnitFsmSpec = {
// Drop any resource we can if we are in range when the construction finishes
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))
let canReturnResources = this.CanReturnResource(msg.data.newentity, true, cmpResourceGatherer);
if (this.CheckTargetRange(msg.data.newentity, IID_Builder) && canReturnResources)
{
let dropsiteTypes = cmpResourceDropsite.GetTypes();
cmpResourceGatherer.CommitResources(dropsiteTypes);
cmpResourceGatherer.CommitResources(msg.data.newentity);
this.SetDefaultAnimationVariant();
}
@@ -2911,14 +2897,22 @@ UnitAI.prototype.UnitFsmSpec = {
// Switch to the next order (if any)
if (this.FinishOrder())
{
if (this.CanReturnResource(msg.data.newentity, true))
if (canReturnResources)
{
// We aren't in range, but we can still return resources there: always do so.
this.SetDefaultAnimationVariant();
this.PushOrderFront("ReturnResource", { "target": msg.data.newentity, "force": false });
}
return;
}
if (canReturnResources)
{
// We aren't in range, but we can still return resources there: always do so.
this.SetDefaultAnimationVariant();
this.PushOrderFront("ReturnResource", { "target": msg.data.newentity, "force": false });
}
// No remaining orders - pick a useful default behaviour
// If autocontinue explicitly disabled (e.g. by AI) then
@@ -2930,19 +2924,16 @@ UnitAI.prototype.UnitFsmSpec = {
// the build command should start gathering from it
if ((oldData.force || oldData.autoharvest) && this.CanGather(msg.data.newentity))
{
if (this.CanReturnResource(msg.data.newentity, true))
{
this.SetDefaultAnimationVariant();
this.PushOrder("ReturnResource", { "target": msg.data.newentity, "force": false });
}
this.PerformGather(msg.data.newentity, true, false);
return;
}
// If this building was e.g. a farmstead of ours, entities that received
// 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, cmpResourceGatherer))
{
let cmpResourceDropsite = Engine.QueryInterface(msg.data.newentity, IID_ResourceDropsite);
let types = cmpResourceDropsite.GetTypes();
let pos;
let cmpPosition = Engine.QueryInterface(msg.data.newentity, IID_Position);
@@ -3059,18 +3050,12 @@ UnitAI.prototype.UnitFsmSpec = {
}
}
// Check if we are garrisoned in a dropsite
var cmpResourceDropsite = Engine.QueryInterface(target, IID_ResourceDropsite);
if (cmpResourceDropsite && this.CanReturnResource(target, true))
// Check if we are garrisoned in a dropsite.
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
if (this.CanReturnResource(target, true, cmpResourceGatherer))
{
// Dump any resources we can
var dropsiteTypes = cmpResourceDropsite.GetTypes();
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
if (cmpResourceGatherer)
{
cmpResourceGatherer.CommitResources(dropsiteTypes);
this.SetDefaultAnimationVariant();
}
cmpResourceGatherer.CommitResources(target);
this.SetDefaultAnimationVariant();
}
// If a pickup has been requested, remove it
@@ -6158,7 +6143,12 @@ UnitAI.prototype.CanHeal = function(target)
return cmpHeal && cmpHeal.CanHeal(target);
};
UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource)
/**
* Check if the entity can return carried resources at @param target
* @param checkCarriedResource check we are carrying resources
* @param cmpResourceGatherer if present, use this directly instead of re-querying.
*/
UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource, cmpResourceGatherer = undefined)
{
if (this.IsTurret())
return false;
@@ -6168,12 +6158,15 @@ UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource)
return true;
// Verify that we're able to respond to ReturnResource commands
var cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
if (!cmpResourceGatherer)
return false;
{
cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
if (!cmpResourceGatherer)
return false;
}
// Verify that the target is a dropsite
var cmpResourceDropsite = Engine.QueryInterface(target, IID_ResourceDropsite);
let cmpResourceDropsite = Engine.QueryInterface(target, IID_ResourceDropsite);
if (!cmpResourceDropsite)
return false;
@@ -6181,16 +6174,16 @@ UnitAI.prototype.CanReturnResource = function(target, checkCarriedResource)
{
// Verify that we are carrying some resources,
// and can return our current resource to this target
var type = cmpResourceGatherer.GetMainCarryingType();
let type = cmpResourceGatherer.GetMainCarryingType();
if (!type || !cmpResourceDropsite.AcceptsType(type))
return false;
}
// Verify that the dropsite is owned by this entity's player (or a mutual ally's if allowed)
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
if (cmpOwnership && IsOwnedByPlayer(cmpOwnership.GetOwner(), target))
return true;
var cmpPlayer = QueryOwnerInterface(this.entity);
let cmpPlayer = QueryOwnerInterface(this.entity);
return cmpPlayer && cmpPlayer.HasSharedDropsites() && cmpResourceDropsite.IsShared() &&
cmpOwnership && IsOwnedByMutualAllyOfPlayer(cmpOwnership.GetOwner(), target);
};