0ad/binaries/data/mods/public/gui/session/unit_commands.js
2014-06-18 15:27:28 +00:00

294 lines
8.8 KiB
JavaScript

// The number of currently visible buttons (used to optimise showing/hiding)
var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Training": 0, "Research": 0, "Barter": 0, "Construction": 0, "Command": 0, "Stance": 0, "Gate": 0, "Pack": 0};
/**
* Set the position of a panel object according to the index,
* from left to right, from top to bottom.
* Will wrap around to subsequent rows if the index
* is larger than rowLength.
*/
function setPanelObjectPosition(object, index, rowLength, vMargin = 1, hMargin = 1)
{
var size = object.size;
// horizontal position
var oWidth = size.right - size.left;
var hIndex = index % rowLength;
size.left = hIndex * (oWidth + vMargin);
size.right = size.left + oWidth;
// vertical position
var oHeight = size.bottom - size.top;
var vIndex = Math.floor(index / rowLength);
size.top = vIndex * (oHeight + hMargin);
size.bottom = size.top + oHeight;
object.size = size;
}
/**
* Helper function for updateUnitCommands; sets up "unit panels"
* (i.e. panels with rows of icons) for the currently selected unit.
*
* @param guiName Short identifier string of this panel. See g_SelectionPanels.
* @param unitEntState Entity state of the (first) selected unit.
* @param payerState Player state
*/
function setupUnitPanel(guiName, unitEntState, playerState)
{
if (!g_SelectionPanels[guiName])
{
error("unknown guiName used '" + guiName + "'");
return;
}
var selection = g_Selection.toList();
var items = g_SelectionPanels[guiName].getItems(unitEntState, selection);
if (!items || !items.length)
return;
var numberOfItems = items.length;
var garrisonGroups = new EntityGroups();
// Determine how many buttons there should be
var maxNumberOfItems = g_SelectionPanels[guiName].getMaxNumberOfItems()
if (maxNumberOfItems < numberOfItems)
numberOfItems = maxNumberOfItems;
if (g_SelectionPanels[guiName].rowLength)
var rowLength = g_SelectionPanels[guiName].rowLength;
else
var rowLength = 8;
if (g_SelectionPanels[guiName].resizePanel)
g_SelectionPanels[guiName].resizePanel(numberOfItems, rowLength);
// Make buttons
for (var i = 0; i < numberOfItems; i++)
{
var item = items[i];
// If a tech has been researched it leaves an empty slot
if (!item)
{
if (g_SelectionPanels[guiName].hideItem)
g_SelectionPanels[guiName].hideItem(i, rowLength);
continue;
}
// STANDARD DATA
// add standard data
var data = {
"i": i,
"item": item,
"selection": selection,
"playerState": playerState,
"unitEntState": unitEntState,
"rowLength": rowLength,
"numberOfItems": numberOfItems,
};
// add standard gui objects to the data
// depending on the actual XML, some of this may be undefined
data.button = Engine.GetGUIObjectByName("unit"+guiName+"Button["+i+"]");
data.affordableMask = Engine.GetGUIObjectByName("unit"+guiName+"Unaffordable["+i+"]");
data.icon = Engine.GetGUIObjectByName("unit"+guiName+"Icon["+i+"]");
data.guiSelection = Engine.GetGUIObjectByName("unit"+guiName+"Selection["+i+"]");
data.countDisplay = Engine.GetGUIObjectByName("unit"+guiName+"Count["+i+"]");
// DEFAULTS
if (data.button)
{
data.button.hidden = false;
data.button.enabled = true;
data.button.tooltip = "";
data.button.caption = "";
}
if (data.affordableMask)
data.affordableMask.hidden = true; // actually used for the red "lack of resource" overlay, and darkening if unavailable. Sort of a hack.
// GENERAL DATA
// add general data, and a chance to abort on faulty data
if (g_SelectionPanels[guiName].addData)
{
var success = g_SelectionPanels[guiName].addData(data);
if (!success)
continue; // ignore faulty data
}
// SET CONTENT
// run all content setters
for (var f in g_SelectionPanels[guiName])
{
if (f.match(/^set/))
g_SelectionPanels[guiName][f](data);
}
// Special case: position
if (!g_SelectionPanels[guiName].setPosition)
setPanelObjectPosition(data.button, i, rowLength);
// TODO: we should require all entities to have icons, so this case never occurs
if (data.icon && !data.icon.sprite)
data.icon.sprite = "bkFillBlack";
}
// Hide any buttons we're no longer using
for (var i = numberOfItems; i < g_unitPanelButtons[guiName]; ++i)
if (g_SelectionPanels[guiName].hideItem)
g_SelectionPanels[guiName].hideItem(i, rowLength);
else
Engine.GetGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true;
// remember the number of items
g_unitPanelButtons[guiName] = numberOfItems;
g_SelectionPanels[guiName].used = true;
}
function resourcesToAlphaMask(neededResources)
{
var totalCost = 0;
for each (var resource in neededResources)
totalCost += resource;
var alpha = 50 + Math.round(totalCost/10);
alpha = alpha > 125 ? 125 : alpha;
return "colour: 255 0 0 " + (alpha);
}
/**
* Updates the selection panels where buttons are supposed to
* depend on the context.
* Runs in the main session loop via updateSelectionDetails().
* Delegates to setupUnitPanel to set up individual subpanels,
* appropriately activated depending on the selected unit's state.
*
* @param entState Entity state of the (first) selected unit.
* @param supplementalDetailsPanel Reference to the
* "supplementalSelectionDetails" GUI Object
* @param commandsPanel Reference to the "commandsPanel" GUI Object
* @param selection Array of currently selected entity IDs.
*/
function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection)
{
for each (var panel in g_SelectionPanels)
panel.used = false;
// If the selection is friendly units, add the command panels
var player = Engine.GetPlayerID();
// Get player state to check some constraints
// e.g. presence of a hero or build limits
var simState = GetSimState();
var playerState = simState.players[player];
if (entState.player == player || g_DevSettings.controlAll)
{
for (var guiName of g_PanelsOrder)
{
if (
g_SelectionPanels[guiName].conflictsWith &&
g_SelectionPanels[guiName].conflictsWith.some(function (p) { return g_SelectionPanels[p].used; })
)
continue;
setupUnitPanel(guiName, entState, playerState);
}
supplementalDetailsPanel.hidden = false;
commandsPanel.hidden = false;
}
else if (playerState.isMutualAlly[entState.player]) // owned by allied player
{
// TODO if there's a second panel needed for a different player
// we should consider adding the players list to g_SelectionPanels
setupUnitPanel("Garrison", entState, playerState);
if (g_SelectionPanels["Garrison"].used)
supplementalDetailsPanel.hidden = false;
else
supplementalDetailsPanel.hidden = true;
commandsPanel.hidden = true;
}
else // owned by another player
{
supplementalDetailsPanel.hidden = true;
commandsPanel.hidden = true;
}
// Hides / unhides Unit Panels (panels should be grouped by type, not by order, but we will leave that for another time)
for (var panelName in g_SelectionPanels)
Engine.GetGUIObjectByName("unit" + panelName + "Panel").hidden = !g_SelectionPanels[panelName].used;
}
// Force hide commands panels
function hideUnitCommands()
{
for (var panelName in g_SelectionPanels)
Engine.GetGUIObjectByName("unit" + panelName + "Panel").hidden = true;
}
// Get all of the available entities which can be trained by the selected entities
function getAllTrainableEntities(selection)
{
var trainableEnts = [];
var state;
// Get all buildable and trainable entities
for (var i in selection)
{
if ((state = GetEntityState(selection[i])) && state.production && state.production.entities.length)
trainableEnts = trainableEnts.concat(state.production.entities);
}
// Remove duplicates
removeDupes(trainableEnts);
return trainableEnts;
}
function getAllTrainableEntitiesFromSelection()
{
if (!g_allTrainableEntities)
g_allTrainableEntities = getAllTrainableEntities(g_Selection.toList());
return g_allTrainableEntities;
}
// Get all of the available entities which can be built by the selected entities
function getAllBuildableEntities(selection)
{
var buildableEnts = [];
var state;
// Get all buildable entities
for (var i in selection)
{
if ((state = GetEntityState(selection[i])) && state.buildEntities && state.buildEntities.length)
buildableEnts = buildableEnts.concat(state.buildEntities);
}
// Remove duplicates
removeDupes(buildableEnts);
return buildableEnts;
}
function getAllBuildableEntitiesFromSelection()
{
if (!g_allBuildableEntities)
g_allBuildableEntities = getAllBuildableEntities(g_Selection.toList());
return g_allBuildableEntities;
}
function getNumberOfRightPanelButtons()
{
var sum = 0;
if (g_SelectionPanels["Construction"].used)
sum += g_unitPanelButtons["Construction"];
if (g_SelectionPanels["Training"].used)
sum += g_unitPanelButtons["Training"];
if (g_SelectionPanels["Pack"].used)
sum += g_unitPanelButtons["Pack"];
if (g_SelectionPanels["Gate"].used)
sum += g_unitPanelButtons["Gate"];
return sum;
}