Autocontinue after gathering a treasure.

Follow-up to ea96e81098.
Also adds the ability to gather near a position (e.g. when ungarrisoning
with a rally point set on a treasure that is gone).
Gathering treasures should now behave exactly the same as prior to the
split.

Differential revision: D3580
Comments by: @wraitii
This was SVN commit r24999.
This commit is contained in:
Freagarach 2021-03-03 18:20:49 +00:00
parent c879308ad6
commit 97addf2aa7
5 changed files with 112 additions and 11 deletions

View File

@ -812,6 +812,7 @@ var g_UnitActions =
"entities": selection, "entities": selection,
"target": action.target, "target": action.target,
"queued": queued, "queued": queued,
"autocontinue": true,
"formation": g_AutoFormation.getNull() "formation": g_AutoFormation.getNull()
}); });
@ -989,9 +990,13 @@ var g_UnitActions =
else if (targetState && targetState.treasure) else if (targetState && targetState.treasure)
{ {
cursor = "action-collect-treasure"; cursor = "action-collect-treasure";
data.command = "collect-treasure-near-position";
if (!targetState.speed)
{
data.command = "collect-treasure"; data.command = "collect-treasure";
data.target = targetState.id; data.target = targetState.id;
} }
}
else if (entState.market && targetState && targetState.market && else if (entState.market && targetState && targetState.market &&
entState.id != targetState.id && entState.id != targetState.id &&
(!entState.market.naval || targetState.market.naval) && (!entState.market.naval || targetState.market.naval) &&

View File

@ -859,11 +859,12 @@ m.Entity = m.Class({
return this; return this;
}, },
"collectTreasure": function(target, queued = false) { "collectTreasure": function(target, autocontinue = false, queued = false) {
Engine.PostCommand(PlayerID, { Engine.PostCommand(PlayerID, {
"type": "collect-treasure", "type": "collect-treasure",
"entities": [this.id()], "entities": [this.id()],
"target": target.id(), "target": target.id(),
"autocontinue": autocontinue,
"queued": queued "queued": queued
}); });
return this; return this;

View File

@ -649,6 +649,15 @@ UnitAI.prototype.UnitFsmSpec = {
return ACCEPT_ORDER; return ACCEPT_ORDER;
}, },
"Order.CollectTreasureNearPosition": function(msg) {
let nearbyTreasure = this.FindNearbyTreasure(msg.data.x, msg.data.z);
if (nearbyTreasure)
this.CollectTreasure(nearbyTreasure, oldData.autocontinue, true);
else
this.SetNextState("COLLECTTREASURE");
return ACCEPT_ORDER;
},
// States for the special entity representing a group of units moving in formation: // States for the special entity representing a group of units moving in formation:
"FORMATIONCONTROLLER": { "FORMATIONCONTROLLER": {
@ -2872,7 +2881,7 @@ UnitAI.prototype.UnitFsmSpec = {
let cmpTreasureCollecter = Engine.QueryInterface(this.entity, IID_TreasureCollecter); let cmpTreasureCollecter = Engine.QueryInterface(this.entity, IID_TreasureCollecter);
if (!cmpTreasureCollecter || !cmpTreasureCollecter.CanCollect(this.order.data.target)) if (!cmpTreasureCollecter || !cmpTreasureCollecter.CanCollect(this.order.data.target))
{ {
this.FinishOrder(); this.SetNextState("FINDINGNEWTARGET");
return true; return true;
} }
if (this.CheckTargetRange(this.order.data.target, IID_TreasureCollecter)) if (this.CheckTargetRange(this.order.data.target, IID_TreasureCollecter))
@ -2889,7 +2898,7 @@ UnitAI.prototype.UnitFsmSpec = {
"enter": function() { "enter": function() {
if (!this.MoveToTargetRange(this.order.data.target, IID_TreasureCollecter)) if (!this.MoveToTargetRange(this.order.data.target, IID_TreasureCollecter))
{ {
this.FinishOrder(); this.SetNextState("FINDINGNEWTARGET");
return true; return true;
} }
return false; return false;
@ -2903,7 +2912,7 @@ UnitAI.prototype.UnitFsmSpec = {
if (this.CheckTargetRange(this.order.data.target, IID_TreasureCollecter)) if (this.CheckTargetRange(this.order.data.target, IID_TreasureCollecter))
this.SetNextState("COLLECTING"); this.SetNextState("COLLECTING");
else if (msg.likelyFailure) else if (msg.likelyFailure)
this.FinishOrder(); this.SetNextState("FINDINGNEWTARGET");
}, },
}, },
@ -2932,7 +2941,28 @@ UnitAI.prototype.UnitFsmSpec = {
}, },
"TargetInvalidated": function(msg) { "TargetInvalidated": function(msg) {
this.FinishOrder(); this.SetNextState("FINDINGNEWTARGET");
},
},
"FINDINGNEWTARGET": {
"enter": function() {
let oldData = this.order.data;
// Switch to the next order (if any).
if (this.FinishOrder())
return true;
// If autocontinue explicitly disabled (e.g. by AI)
// then do nothing automatically.
if (!oldData.autocontinue)
return false;
let nearbyTreasure = this.FindNearbyTreasure(this.TargetPosOrEntPos(oldData.target));
if (nearbyTreasure)
this.CollectTreasure(nearbyTreasure, oldData.autocontinue, true);
return true;
}, },
}, },
}, },
@ -4495,6 +4525,28 @@ UnitAI.prototype.FindNearbyFoundation = function(position)
return nearby.find(ent => !Engine.QueryInterface(ent, IID_Foundation).IsFinished()); return nearby.find(ent => !Engine.QueryInterface(ent, IID_Foundation).IsFinished());
}; };
/**
* Returns the entity ID of the nearest treasure.
* "Nearest" is nearest from @param position.
*/
UnitAI.prototype.FindNearbyTreasure = function(position)
{
if (!position)
return undefined;
let cmpTreasureCollecter = Engine.QueryInterface(this.entity, IID_TreasureCollecter);
if (!cmpTreasureCollecter)
return undefined;
let players = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetAllPlayers();
let range = 64; // TODO: what's a sensible number?
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
// Don't account for entity size, we need to match LOS visibility.
let nearby = cmpRangeManager.ExecuteQueryAroundPos(position, 0, range, players, IID_Treasure, false);
return nearby.find(ent => cmpTreasureCollecter.CanCollect(ent));
};
/** /**
* Play a sound appropriate to the current entity. * Play a sound appropriate to the current entity.
*/ */
@ -5683,9 +5735,27 @@ UnitAI.prototype.ReturnResource = function(target, queued)
/** /**
* Adds order to collect a treasure to queue, forced by the player. * Adds order to collect a treasure to queue, forced by the player.
*/ */
UnitAI.prototype.CollectTreasure = function(target, queued) UnitAI.prototype.CollectTreasure = function(target, autocontinue, queued)
{ {
this.AddOrder("CollectTreasure", { "target": target, "force": true }, queued); this.AddOrder("CollectTreasure", {
"target": target,
"autocontinue": autocontinue,
"force": true
}, queued);
};
/**
* Adds order to collect a treasure to queue, forced by the player.
*/
UnitAI.prototype.CollectTreasureNearPosition = function(posX, posZ, autocontinue, queued)
{
this.AddOrder("CollectTreasureNearPosition", {
"x": posX,
"z": posZ,
"target": target,
"autocontinue": autocontinue,
"force": false
}, queued);
}; };
UnitAI.prototype.CancelSetupTradeRoute = function(target) UnitAI.prototype.CancelSetupTradeRoute = function(target)

View File

@ -75,7 +75,14 @@ var g_Commands = {
"collect-treasure": function(player, cmd, data) "collect-treasure": function(player, cmd, data)
{ {
GetFormationUnitAIs(data.entities, player, cmd, data.formation).forEach(cmpUnitAI => { GetFormationUnitAIs(data.entities, player, cmd, data.formation).forEach(cmpUnitAI => {
cmpUnitAI.CollectTreasure(cmd.target, cmd.queued); cmpUnitAI.CollectTreasure(cmd.target, cmd.autocontinue, cmd.queued);
});
},
"collect-treasure-near-position": function(player, cmd, data)
{
GetFormationUnitAIs(data.entities, player, cmd, data.formation).forEach(cmpUnitAI => {
cmpUnitAI.CollectTreasureNearPosition(cmd.x, cmd.z, cmd.autocontinue, cmd.queued);
}); });
}, },

View File

@ -16,7 +16,14 @@ function GetRallyPointCommands(cmpRallyPoint, spawnedEnts)
{ {
let cmpPosition = Engine.QueryInterface(data[i].target, IID_Position); let cmpPosition = Engine.QueryInterface(data[i].target, IID_Position);
if (!cmpPosition || !cmpPosition.IsInWorld()) if (!cmpPosition || !cmpPosition.IsInWorld())
command = command == "gather" ? "gather-near-position" : "walk"; {
if (command == "gather")
command = "gather-near-position";
else if (command == "collect-treasure")
command = "collect-treasure-near-position";
else
command = "walk";
}
} }
switch (command) switch (command)
@ -103,6 +110,17 @@ function GetRallyPointCommands(cmpRallyPoint, spawnedEnts)
"entities": spawnedEnts, "entities": spawnedEnts,
"target": data[i].target, "target": data[i].target,
"queued": true, "queued": true,
"autocontinue": i == rallyPos.length - 1
});
break;
case "collect-treasure-near-position":
ret.push({
"type": "collect-treasure-near-position",
"entities": spawnedEnts,
"x": rallyPos[i].x,
"z": rallyPos[i].z,
"queued": true,
"autocontinue": i == rallyPos.length - 1
}); });
break; break;
default: default: