1
0
forked from 0ad/0ad

Show gatherers next to resource icons.

And total gatherers next to the population icon.

Closes #643
Patch by: @mammadori
Differential Revision: D3155
Earlier revisions reviewed by: @Angen, @wraitii
Comments by: @Nescio, @s0600204, @Stan
This was SVN commit r24357.
This commit is contained in:
Freagarach 2020-12-10 08:13:46 +00:00
parent 8accbce1d7
commit 1e0a6f66f0
11 changed files with 112 additions and 5 deletions

View File

@ -151,6 +151,7 @@
{ "nick": "m0l0t0ph", "name": "Christoph Gielisch" },
{ "nick": "madmax", "name": "Abhijit Nandy" },
{ "nick": "madpilot", "name": "Guido Falsi" },
{ "nick": "mammadori", "name": "Marco Amadori" },
{ "nick": "markcho" },
{ "nick": "MarkT", "name": "Mark Thompson" },
{ "nick": "Markus" },

View File

@ -116,6 +116,14 @@
text_valign="center"
/>
<style name="gathererCounts"
textcolor="white"
font="sans-stroke-12"
ghost="true"
text_align="right"
text_valign="bottom"
/>
<style name="StatsTextLeft"
font="sans-stroke-12"
textcolor="white"

View File

@ -37,7 +37,8 @@ class CounterManager
resCode,
Engine.GetGUIObjectByName("resource" + id),
Engine.GetGUIObjectByName("resource" + id + "_icon"),
Engine.GetGUIObjectByName("resource" + id + "_count")));
Engine.GetGUIObjectByName("resource" + id + "_count"),
Engine.GetGUIObjectByName("resource" + id + "_stats")));
}
init()

View File

@ -4,7 +4,7 @@
*/
class CounterPopulation
{
constructor(resCode, panel, icon, count)
constructor(resCode, panel, icon, count, stats)
{
this.resCode = resCode;
this.panel = panel;
@ -13,18 +13,25 @@ class CounterPopulation
this.count.onTick = this.onTick.bind(this);
this.isTrainingBlocked = false;
this.color = this.DefaultPopulationColor;
this.stats = stats;
}
rebuild(playerState, getAllyStatTooltip)
{
this.count.caption = sprintf(translate(this.CounterCaption), playerState);
let total = 0;
for (let resCode of g_ResourceData.GetCodes())
total += playerState.resourceGatherers[resCode];
// Do not show zeroes.
this.stats.caption = total || "";
this.isTrainingBlocked = playerState.trainingBlocked;
this.panel.tooltip =
setStringTags(translate(this.PopulationTooltip), CounterManager.ResourceTitleTags) + "\n" +
sprintf(translate(this.MaximumPopulationTooltip), { "popCap": playerState.popMax }) +
getAllyStatTooltip(this.getTooltipData.bind(this));
getAllyStatTooltip(this.getTooltipData.bind(this)) + "\n" +
(total > 0 ? sprintf(translate("Current gatherers: %(amount)s"), { "amount" : total }) : "");
}
getTooltipData(playerState, playername)

View File

@ -3,18 +3,23 @@
*/
class CounterResource
{
constructor(resCode, panel, icon, count)
constructor(resCode, panel, icon, count, stats)
{
this.resCode = resCode;
this.panel = panel;
this.icon = icon;
this.count = count;
this.stats = stats;
}
rebuild(playerState, getAllyStatTooltip)
{
this.count.caption = Math.floor(playerState.resourceCounts[this.resCode]);
// Do not show zeroes.
let gatherers = playerState.resourceGatherers[this.resCode];
this.stats.caption = gatherers || "";
// TODO: Set the tooltip only if hovered?
let description = g_ResourceData.GetResource(this.resCode).description;
if (description)
@ -23,7 +28,8 @@ class CounterResource
this.panel.tooltip =
setStringTags(resourceNameFirstWord(this.resCode), CounterManager.ResourceTitleTags) +
description +
getAllyStatTooltip(this.getTooltipData.bind(this));
getAllyStatTooltip(this.getTooltipData.bind(this)) + "\n" +
(gatherers > 0 ? sprintf(translate("Gatherers: %(amount)s"), { "amount" : gatherers }) : "");
}
getTooltipData(playerState, playername)

View File

@ -6,6 +6,7 @@
<object name="resource[n]" size="0 0 89 100%" type="button" style="resourceCounter" tooltip_style="sessionToolTipBold">
<object size="0 -2 40 38" type="image" name="resource[n]_icon" ghost="true"/>
<object size="34 0 100%-2 100%-2" type="text" style="resourceText" name="resource[n]_count"/>
<object size="0 0 32 32" type="text" style="gathererCounts" name="resource[n]_stats"/>
</object>
</repeat>
</object>

View File

@ -101,6 +101,7 @@ GuiInterface.prototype.GetSimulationState = function()
"popMax": cmpPlayer.GetMaxPopulation(),
"panelEntities": cmpPlayer.GetPanelEntities(),
"resourceCounts": cmpPlayer.GetResourceCounts(),
"resourceGatherers": cmpPlayer.GetResourceGatherers(),
"trainingBlocked": cmpPlayer.IsTrainingBlocked(),
"state": cmpPlayer.GetState(),
"team": cmpPlayer.GetTeam(),

View File

@ -54,6 +54,7 @@ Player.prototype.Init = function()
this.maxPop = 300; // Maximum population.
this.trainingBlocked = false; // Indicates whether any training queue is currently blocked.
this.resourceCount = {};
this.resourceGatherers = {};
this.tradingGoods = []; // Goods for next trade-route and its probabilities * 100.
this.team = -1; // Team number of the player, players on the same team will always have ally diplomatic status. Also this is useful for team emblems, scoring, etc.
this.teamsLocked = false;
@ -83,6 +84,7 @@ Player.prototype.Init = function()
{
this.resourceCount[res] = 300;
this.resourceNames[res] = Resources.GetResource(res).name;
this.resourceGatherers[res] = 0;
}
// Trading goods probability in steps of 5.
let resTradeCodes = Resources.GetTradableCodes();
@ -262,6 +264,27 @@ Player.prototype.GetResourceCounts = function()
return this.resourceCount;
};
Player.prototype.GetResourceGatherers = function()
{
return this.resourceGatherers;
};
/**
* @param {string} type - The generic type of resource to add the gatherer for.
*/
Player.prototype.AddResourceGatherer = function(type)
{
++this.resourceGatherers[type];
};
/**
* @param {string} type - The generic type of resource to remove the gatherer from.
*/
Player.prototype.RemoveResourceGatherer = function(type)
{
--this.resourceGatherers[type];
};
/**
* Add resource of specified type to player.
* @param {string} type - Generic type of resource.

View File

@ -334,6 +334,41 @@ ResourceGatherer.prototype.DropResources = function()
Engine.PostMessage(this.entity, MT_ResourceCarryingChanged, { "to": this.GetCarryingStatus() });
};
/**
* @param {string} type - A generic resource type.
*/
ResourceGatherer.prototype.AddToPlayerCounter = function(type)
{
// We need to be removed from the player counter first.
if (this.lastGathered)
return;
let cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
if (cmpPlayer)
cmpPlayer.AddResourceGatherer(type);
this.lastGathered = type;
};
/**
* @param {number} playerid - Optionally a player ID.
*/
ResourceGatherer.prototype.RemoveFromPlayerCounter = function(playerid)
{
if (!this.lastGathered)
return;
let cmpPlayer = playerid != undefined ?
QueryPlayerIDInterface(playerid) :
QueryOwnerInterface(this.entity, IID_Player);
if (cmpPlayer)
cmpPlayer.RemoveResourceGatherer(this.lastGathered);
delete this.lastGathered;
};
// Since we cache gather rates, we need to make sure we update them when tech changes.
// and when our owner change because owners can had different techs.
ResourceGatherer.prototype.OnValueModification = function(msg)
@ -347,7 +382,11 @@ ResourceGatherer.prototype.OnValueModification = function(msg)
ResourceGatherer.prototype.OnOwnershipChanged = function(msg)
{
if (msg.to == INVALID_PLAYER)
{
this.RemoveFromPlayerCounter(msg.from);
return;
}
this.RecalculateGatherRatesAndCapacities();
};

View File

@ -2221,6 +2221,9 @@ UnitAI.prototype.UnitFsmSpec = {
return true;
}
this.SetAnimationVariant("approach_" + this.order.data.type.specific);
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
if (cmpResourceGatherer)
cmpResourceGatherer.AddToPlayerCounter(this.order.data.type.generic);
return false;
},
@ -2242,6 +2245,11 @@ UnitAI.prototype.UnitFsmSpec = {
let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply);
if (cmpSupply)
cmpSupply.RemoveGatherer(this.entity);
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
if (cmpResourceGatherer)
cmpResourceGatherer.RemoveFromPlayerCounter();
delete this.gatheringTarget;
},
},
@ -2323,6 +2331,7 @@ UnitAI.prototype.UnitFsmSpec = {
this.SetDefaultAnimationVariant();
this.FaceTowardsTarget(this.order.data.target);
this.SelectAnimation("gather_" + this.order.data.type.specific);
cmpResourceGatherer.AddToPlayerCounter(this.order.data.type.generic);
}
return false;
},
@ -2335,6 +2344,11 @@ UnitAI.prototype.UnitFsmSpec = {
let cmpSupply = Engine.QueryInterface(this.gatheringTarget, IID_ResourceSupply);
if (cmpSupply)
cmpSupply.RemoveGatherer(this.entity);
let cmpResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
if (cmpResourceGatherer)
cmpResourceGatherer.RemoveFromPlayerCounter();
delete this.gatheringTarget;
this.ResetAnimation();

View File

@ -100,6 +100,7 @@ AddMock(100, IID_Player, {
"GetPopulationLimit": function() { return 20; },
"GetMaxPopulation": function() { return 200; },
"GetResourceCounts": function() { return { "food": 100 }; },
"GetResourceGatherers": function() { return { "food": 1 }; },
"GetPanelEntities": function() { return []; },
"IsTrainingBlocked": function() { return false; },
"GetState": function() { return "active"; },
@ -186,6 +187,7 @@ AddMock(101, IID_Player, {
"GetPopulationLimit": function() { return 30; },
"GetMaxPopulation": function() { return 300; },
"GetResourceCounts": function() { return { "food": 200 }; },
"GetResourceGatherers": function() { return { "food": 3 }; },
"GetPanelEntities": function() { return []; },
"IsTrainingBlocked": function() { return false; },
"GetState": function() { return "active"; },
@ -278,6 +280,7 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
"popMax": 200,
"panelEntities": [],
"resourceCounts": { "food": 100 },
"resourceGatherers": { "food": 1 },
"trainingBlocked": false,
"state": "active",
"team": -1,
@ -327,6 +330,7 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
"popMax": 300,
"panelEntities": [],
"resourceCounts": { "food": 200 },
"resourceGatherers": { "food": 3 },
"trainingBlocked": false,
"state": "active",
"team": -1,
@ -386,6 +390,7 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
"popMax": 200,
"panelEntities": [],
"resourceCounts": { "food": 100 },
"resourceGatherers": { "food": 1 },
"trainingBlocked": false,
"state": "active",
"team": -1,
@ -458,6 +463,7 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
"popMax": 300,
"panelEntities": [],
"resourceCounts": { "food": 200 },
"resourceGatherers": { "food": 3 },
"trainingBlocked": false,
"state": "active",
"team": -1,