forked from 0ad/0ad
Show the selection panels to observers / in replays, fixes #3731.
This allows observers to see the training queue, researched techs, unit stance, constructable buildings, garrisoned units, market prices etc. for all players without changing the perspective. All buttons are disabled if the user isn't allowed to control the affected player. Notice updateUnitCommands() fills out the panel differently in case of selecting an allied building. Extends the GUIInterface methods "GetNeededResources", "CheckTechnologyRequirements" and "IsTechnologyResearched" to optionally take a different player-argument. This was SVN commit r17617.
This commit is contained in:
parent
9b922ebadd
commit
6b710f35b0
@ -685,7 +685,7 @@ function handleInputBeforeGui(ev, hoveredObject)
|
||||
if (result && result.cost)
|
||||
{
|
||||
placementSupport.tooltipMessage = getEntityCostTooltip(result);
|
||||
var neededResources = Engine.GuiInterfaceCall("GetNeededResources", result.cost);
|
||||
var neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost": result.cost });
|
||||
if (neededResources)
|
||||
placementSupport.tooltipMessage += getNeededResourcesTooltip(neededResources);
|
||||
}
|
||||
@ -1081,7 +1081,7 @@ function handleInputAfterGui(ev)
|
||||
else
|
||||
{
|
||||
// cancel if not enough resources
|
||||
if (placementSupport.template && Engine.GuiInterfaceCall("GetNeededResources", GetTemplateData(placementSupport.template).cost))
|
||||
if (placementSupport.template && Engine.GuiInterfaceCall("GetNeededResources", { "cost": GetTemplateData(placementSupport.template).cost }))
|
||||
{
|
||||
placementSupport.Reset();
|
||||
inputState = INPUT_NORMAL;
|
||||
@ -1414,8 +1414,8 @@ function addTrainingToQueue(selection, trainEntType, playerState)
|
||||
else if (limits.canBeAddedCount == undefined ||
|
||||
limits.canBeAddedCount > batchTrainingCount * appropriateBuildings.length)
|
||||
{
|
||||
if (Engine.GuiInterfaceCall("GetNeededResources", multiplyEntityCosts(
|
||||
template, batchTrainingCount + batchIncrementSize)))
|
||||
if (Engine.GuiInterfaceCall("GetNeededResources", { "cost":
|
||||
multiplyEntityCosts(template, batchTrainingCount + batchIncrementSize) }))
|
||||
return;
|
||||
|
||||
batchTrainingCount += batchIncrementSize;
|
||||
@ -1432,8 +1432,8 @@ function addTrainingToQueue(selection, trainEntType, playerState)
|
||||
}
|
||||
|
||||
// Don't start a new batch if decrementing or unable to afford it.
|
||||
if (decrement || Engine.GuiInterfaceCall("GetNeededResources",
|
||||
multiplyEntityCosts(template, batchIncrementSize)))
|
||||
if (decrement || Engine.GuiInterfaceCall("GetNeededResources", { "cost":
|
||||
multiplyEntityCosts(template, batchIncrementSize) }))
|
||||
return;
|
||||
|
||||
inputState = INPUT_BATCHTRAINING;
|
||||
|
@ -418,15 +418,6 @@ function updateSelectionDetails()
|
||||
// Show basic details.
|
||||
detailsPanel.hidden = false;
|
||||
|
||||
if (g_IsObserver)
|
||||
{
|
||||
// Observers don't need these displayed.
|
||||
supplementalDetailsPanel.hidden = true;
|
||||
commandsPanel.hidden = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fill out commands panel for specific unit selected (or first unit of primary group)
|
||||
updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection);
|
||||
}
|
||||
// Fill out commands panel for specific unit selected (or first unit of primary group)
|
||||
updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection);
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ g_SelectionPanels.Alert = {
|
||||
data.button.hidden = !data.unitEntState.alertRaiser.hasRaisedAlert;
|
||||
data.icon.sprite = "stretched:session/icons/bell_level0.png";
|
||||
}
|
||||
data.button.enabled = !data.button.hidden;
|
||||
data.button.enabled = !data.button.hidden && controlsPlayer(data.unitEntState.player);
|
||||
},
|
||||
};
|
||||
|
||||
@ -158,16 +158,24 @@ g_SelectionPanels.Barter = {
|
||||
// do we have enough of this resource to sell?
|
||||
var neededRes = {};
|
||||
neededRes[data.item] = data.amountToSell;
|
||||
var canSellCurrent = Engine.GuiInterfaceCall("GetNeededResources", neededRes) != undefined ? "color:255 0 0 80:" : "";
|
||||
var canSellCurrent = Engine.GuiInterfaceCall("GetNeededResources", {
|
||||
"cost": neededRes,
|
||||
"player": data.unitEntState.player
|
||||
}) ? "color:255 0 0 80:" : "";
|
||||
|
||||
// Let's see if we have enough resources to barter.
|
||||
neededRes = {};
|
||||
neededRes[g_barterSell] = data.amountToSell;
|
||||
var canBuyAny = Engine.GuiInterfaceCall("GetNeededResources", neededRes) != undefined ? "color:255 0 0 80:" : "";
|
||||
var canBuyAny = Engine.GuiInterfaceCall("GetNeededResources", {
|
||||
"cost": neededRes,
|
||||
"player": data.unitEntState.player
|
||||
}) ? "color:255 0 0 80:" : "";
|
||||
|
||||
data.icon.Sell.sprite = canSellCurrent + "stretched:"+grayscale+"session/icons/resources/" + data.item + ".png";
|
||||
data.icon.Buy.sprite = canBuyAny + "stretched:"+grayscale+"session/icons/resources/" + data.item + ".png";
|
||||
|
||||
data.button.Buy.hidden = data.isSelected;
|
||||
data.button.Buy.enabled = controlsPlayer(data.unitEntState.player);
|
||||
data.button.Sell.hidden = false;
|
||||
data.selectionIcon.hidden = !data.isSelected;
|
||||
},
|
||||
@ -212,6 +220,7 @@ g_SelectionPanels.Command = {
|
||||
"setGraphics": function(data)
|
||||
{
|
||||
data.icon.sprite = "stretched:session/icons/" + data.item.icon;
|
||||
data.button.enabled = controlsPlayer(data.unitEntState.player);
|
||||
},
|
||||
"setPosition": function(data)
|
||||
{
|
||||
@ -262,6 +271,7 @@ g_SelectionPanels.AllyCommand = {
|
||||
"setGraphics": function(data)
|
||||
{
|
||||
data.icon.sprite = "stretched:session/icons/" + data.item.icon;
|
||||
data.button.enabled = data.item.count > 0;
|
||||
},
|
||||
"setPosition": function(data)
|
||||
{
|
||||
@ -293,12 +303,18 @@ g_SelectionPanels.Construction = {
|
||||
data.template = GetTemplateData(data.entType);
|
||||
if (!data.template) // abort if no template
|
||||
return false;
|
||||
data.technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", data.template.requiredTechnology);
|
||||
|
||||
data.technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", {
|
||||
"tech": data.template.requiredTechnology,
|
||||
"player": data.unitEntState.player
|
||||
});
|
||||
|
||||
if (data.template.cost)
|
||||
{
|
||||
var totalCost = multiplyEntityCosts(data.template, 1);
|
||||
data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", totalCost);
|
||||
}
|
||||
data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", {
|
||||
"cost": multiplyEntityCosts(data.template, 1),
|
||||
"player": data.unitEntState.player
|
||||
});
|
||||
|
||||
data.limits = getEntityLimitAndCount(data.playerState, data.entType);
|
||||
return true;
|
||||
},
|
||||
@ -342,6 +358,8 @@ g_SelectionPanels.Construction = {
|
||||
data.button.enabled = false;
|
||||
modifier += resourcesToAlphaMask(data.neededResources) +":";
|
||||
}
|
||||
else
|
||||
data.button.enabled = controlsPlayer(data.unitEntState.player);
|
||||
|
||||
if (data.template.icon)
|
||||
data.icon.sprite = modifier + "stretched:session/portraits/" + data.template.icon;
|
||||
@ -394,7 +412,7 @@ g_SelectionPanels.Formation = {
|
||||
},
|
||||
"setGraphics": function(data)
|
||||
{
|
||||
data.button.enabled = data.formationOk;
|
||||
data.button.enabled = data.formationOk && controlsPlayer(data.unitEntState.player);
|
||||
var grayscale = data.formationOk ? "" : "grayscale:";
|
||||
data.guiSelection.hidden = !data.formationSelected;
|
||||
data.icon.sprite = "stretched:"+grayscale+"session/icons/"+data.formationInfo.icon;
|
||||
@ -452,15 +470,12 @@ g_SelectionPanels.Garrison = {
|
||||
var entplayer = GetEntityState(ents[0]).player;
|
||||
data.button.sprite = "color:" + rgbToGuiColor(g_Players[entplayer].color) +":";
|
||||
|
||||
var player = Engine.GetPlayerID();
|
||||
if(player != data.unitEntState.player && !g_DevSettings.controlAll)
|
||||
if (!controlsPlayer(data.unitEntState.player) && !controlsPlayer(entplayer))
|
||||
{
|
||||
if (entplayer != player)
|
||||
{
|
||||
data.button.enabled = false;
|
||||
grayscale = "grayscale:";
|
||||
}
|
||||
data.button.enabled = false;
|
||||
grayscale = "grayscale:";
|
||||
}
|
||||
|
||||
data.icon.sprite = "stretched:" + grayscale + "session/portraits/" + data.template.icon;
|
||||
},
|
||||
};
|
||||
@ -545,8 +560,9 @@ g_SelectionPanels.Gate = {
|
||||
|
||||
tooltip += "\n" + getEntityCostTooltip(data.template, data.wallCount);
|
||||
|
||||
data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost":
|
||||
multiplyEntityCosts(data.template, data.wallCount) });
|
||||
|
||||
data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", multiplyEntityCosts(data.template, data.wallCount));
|
||||
if (data.neededResources)
|
||||
tooltip += getNeededResourcesTooltip(data.neededResources);
|
||||
}
|
||||
@ -554,6 +570,7 @@ g_SelectionPanels.Gate = {
|
||||
},
|
||||
"setGraphics": function(data)
|
||||
{
|
||||
data.button.enabled = controlsPlayer(data.unitEntState.player);
|
||||
var gateIcon;
|
||||
if (data.item.gate)
|
||||
{
|
||||
@ -640,6 +657,8 @@ g_SelectionPanels.Pack = {
|
||||
data.icon.sprite = "stretched:session/icons/unpack.png";
|
||||
else
|
||||
data.icon.sprite = "stretched:session/icons/pack.png";
|
||||
|
||||
data.button.enabled = controlsPlayer(data.unitEntState.player);
|
||||
},
|
||||
"setPosition": function(data)
|
||||
{
|
||||
@ -720,6 +739,8 @@ g_SelectionPanels.Queue = {
|
||||
{
|
||||
if (data.template.icon)
|
||||
data.icon.sprite = "stretched:session/portraits/" + data.template.icon;
|
||||
|
||||
data.button.enabled = controlsPlayer(data.unitEntState.player);
|
||||
},
|
||||
};
|
||||
|
||||
@ -779,11 +800,17 @@ g_SelectionPanels.Research = {
|
||||
});
|
||||
|
||||
data.neededResources = data.template.map(function(t) {
|
||||
return Engine.GuiInterfaceCall("GetNeededResources", t.cost);
|
||||
return Engine.GuiInterfaceCall("GetNeededResources", {
|
||||
"cost": t.cost,
|
||||
"player": data.unitEntState.player
|
||||
});
|
||||
});
|
||||
|
||||
data.requirementsPassed = data.entType.map(function(e) {
|
||||
return Engine.GuiInterfaceCall("CheckTechnologyRequirements",e);
|
||||
return Engine.GuiInterfaceCall("CheckTechnologyRequirements", {
|
||||
"tech": e,
|
||||
"player": data.unitEntState.player
|
||||
});
|
||||
});
|
||||
|
||||
data.pair = Engine.GetGUIObjectByName("unitResearchPair["+data.i+"]");
|
||||
@ -806,7 +833,7 @@ g_SelectionPanels.Research = {
|
||||
tooltip += "\n" + template.requirementsTooltip;
|
||||
if (template.classRequirements)
|
||||
{
|
||||
var player = Engine.GetPlayerID();
|
||||
var player = data.unitEntState.player;
|
||||
var current = GetSimState().players[player].classCounts[template.classRequirements.class] || 0;
|
||||
var remaining = template.classRequirements.number - current;
|
||||
tooltip += " " + sprintf(translatePlural("Remaining: %(number)s to build.", "Remaining: %(number)s to build.", remaining), { number: remaining});
|
||||
@ -862,7 +889,7 @@ g_SelectionPanels.Research = {
|
||||
modifier += resourcesToAlphaMask(data.neededResources[i]) + ":";
|
||||
}
|
||||
else
|
||||
button.enabled = true;
|
||||
button.enabled = controlsPlayer(data.unitEntState.player);
|
||||
|
||||
if (data.template[i].icon)
|
||||
data.icon[i].sprite = modifier + "stretched:session/portraits/" + data.template[i].icon;
|
||||
@ -970,6 +997,8 @@ g_SelectionPanels.Selection = {
|
||||
{
|
||||
if (data.template.icon)
|
||||
data.icon.sprite = "stretched:session/portraits/" + data.template.icon;
|
||||
|
||||
data.button.enabled = controlsPlayer(data.unitEntState.player);
|
||||
},
|
||||
};
|
||||
|
||||
@ -1005,6 +1034,7 @@ g_SelectionPanels.Stance = {
|
||||
{
|
||||
data.guiSelection.hidden = !data.stanceSelected;
|
||||
data.icon.sprite = "stretched:session/icons/stances/"+data.item+".png";
|
||||
data.button.enabled = controlsPlayer(data.unitEntState.player);
|
||||
},
|
||||
};
|
||||
|
||||
@ -1024,7 +1054,11 @@ g_SelectionPanels.Training = {
|
||||
data.template = GetTemplateData(data.entType);
|
||||
if (!data.template)
|
||||
return false;
|
||||
data.technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", data.template.requiredTechnology);
|
||||
|
||||
data.technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", {
|
||||
"tech": data.template.requiredTechnology,
|
||||
"player": data.unitEntState.player
|
||||
});
|
||||
|
||||
var [buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch] =
|
||||
getTrainingBatchStatus(data.playerState, data.unitEntState.id, data.entType, data.selection);
|
||||
@ -1038,7 +1072,10 @@ g_SelectionPanels.Training = {
|
||||
if (data.template.cost)
|
||||
{
|
||||
var totalCosts = multiplyEntityCosts(data.template, data.trainNum);
|
||||
data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", totalCosts);
|
||||
data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", {
|
||||
"cost": totalCosts,
|
||||
"player": data.unitEntState.player
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -248,6 +248,14 @@ function selectViewPlayer(playerID)
|
||||
openTrade();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current user can issue commands for that player.
|
||||
*/
|
||||
function controlsPlayer(playerID)
|
||||
{
|
||||
return Engine.GetPlayerID() == playerID || g_DevSettings.controlAll;
|
||||
}
|
||||
|
||||
function updateTopPanel()
|
||||
{
|
||||
let playerID = Engine.GetPlayerID();
|
||||
|
@ -168,7 +168,7 @@ function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, s
|
||||
var simState = GetSimState();
|
||||
var playerState = simState.players[player];
|
||||
|
||||
if (entState.player == player || g_DevSettings.controlAll)
|
||||
if (controlsPlayer(entState.player) || player == -1)
|
||||
{
|
||||
for (var guiName of g_PanelsOrder)
|
||||
{
|
||||
@ -178,7 +178,7 @@ function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, s
|
||||
)
|
||||
continue;
|
||||
|
||||
setupUnitPanel(guiName, entState, playerState);
|
||||
setupUnitPanel(guiName, entState, simState.players[entState.player]);
|
||||
}
|
||||
|
||||
supplementalDetailsPanel.hidden = false;
|
||||
|
@ -589,28 +589,28 @@ GuiInterface.prototype.GetTechnologyData = function(player, name)
|
||||
return GetTechnologyDataHelper(template, cmpPlayer.GetCiv());
|
||||
};
|
||||
|
||||
GuiInterface.prototype.IsTechnologyResearched = function(player, tech)
|
||||
GuiInterface.prototype.IsTechnologyResearched = function(player, data)
|
||||
{
|
||||
if (!tech)
|
||||
if (!data.tech)
|
||||
return true;
|
||||
|
||||
let cmpTechnologyManager = QueryPlayerIDInterface(player, IID_TechnologyManager);
|
||||
let cmpTechnologyManager = QueryPlayerIDInterface(data.player || player, IID_TechnologyManager);
|
||||
|
||||
if (!cmpTechnologyManager)
|
||||
return false;
|
||||
|
||||
return cmpTechnologyManager.IsTechnologyResearched(tech);
|
||||
return cmpTechnologyManager.IsTechnologyResearched(data.tech);
|
||||
};
|
||||
|
||||
// Checks whether the requirements for this technology have been met
|
||||
GuiInterface.prototype.CheckTechnologyRequirements = function(player, tech)
|
||||
GuiInterface.prototype.CheckTechnologyRequirements = function(player, data)
|
||||
{
|
||||
let cmpTechnologyManager = QueryPlayerIDInterface(player, IID_TechnologyManager);
|
||||
let cmpTechnologyManager = QueryPlayerIDInterface(data.player || player, IID_TechnologyManager);
|
||||
|
||||
if (!cmpTechnologyManager)
|
||||
return false;
|
||||
|
||||
return cmpTechnologyManager.CanResearch(tech);
|
||||
return cmpTechnologyManager.CanResearch(data.tech);
|
||||
};
|
||||
|
||||
// Returns technologies that are being actively researched, along with
|
||||
@ -652,9 +652,9 @@ GuiInterface.prototype.GetIncomingAttacks = function(player)
|
||||
};
|
||||
|
||||
// Used to show a red square over GUI elements you can't yet afford.
|
||||
GuiInterface.prototype.GetNeededResources = function(player, amounts)
|
||||
GuiInterface.prototype.GetNeededResources = function(player, data)
|
||||
{
|
||||
return QueryPlayerIDInterface(player).GetNeededResources(amounts);
|
||||
return QueryPlayerIDInterface(data.player || player).GetNeededResources(data.cost);
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user