2010-07-31 23:46:25 +02:00
|
|
|
// Panel types
|
|
|
|
const SELECTION = "Selection";
|
|
|
|
const QUEUE = "Queue";
|
2010-09-28 16:19:13 +02:00
|
|
|
const GARRISON = "Garrison";
|
|
|
|
const FORMATION = "Formation";
|
2010-07-31 23:46:25 +02:00
|
|
|
const TRAINING = "Training";
|
2012-04-20 19:21:04 +02:00
|
|
|
const RESEARCH = "Research";
|
2010-07-31 23:46:25 +02:00
|
|
|
const CONSTRUCTION = "Construction";
|
2012-07-16 06:12:48 +02:00
|
|
|
const TRADING = "Trading";
|
2010-08-01 07:09:30 +02:00
|
|
|
const COMMAND = "Command";
|
2011-06-18 00:13:39 +02:00
|
|
|
const STANCE = "Stance";
|
2012-07-08 18:25:33 +02:00
|
|
|
const GATE = "Gate";
|
2010-07-31 23:46:25 +02:00
|
|
|
|
2010-10-04 00:42:15 +02:00
|
|
|
// Constants
|
|
|
|
const COMMANDS_PANEL_WIDTH = 228;
|
|
|
|
const UNIT_PANEL_BASE = -52; // QUEUE: The offset above the main panel (will often be negative)
|
|
|
|
const UNIT_PANEL_HEIGHT = 44; // QUEUE: The height needed for a row of buttons
|
2010-07-19 23:23:12 +02:00
|
|
|
|
2012-03-08 21:42:28 +01:00
|
|
|
// Trading constants
|
|
|
|
const TRADING_RESOURCES = ["food", "wood", "stone", "metal"];
|
|
|
|
|
2011-11-24 16:43:32 +01:00
|
|
|
// Barter constants
|
|
|
|
const BARTER_RESOURCE_AMOUNT_TO_SELL = 100;
|
|
|
|
const BARTER_BUNCH_MULTIPLIER = 5;
|
|
|
|
const BARTER_RESOURCES = ["food", "wood", "stone", "metal"];
|
|
|
|
const BARTER_ACTIONS = ["Sell", "Buy"];
|
|
|
|
|
2012-07-17 01:49:19 +02:00
|
|
|
// Gate constants
|
|
|
|
const GATE_ACTIONS = ["Lock", "Unlock"];
|
|
|
|
|
2010-07-01 22:31:47 +02:00
|
|
|
// The number of currently visible buttons (used to optimise showing/hiding)
|
2012-07-08 18:25:33 +02:00
|
|
|
var g_unitPanelButtons = {"Selection": 0, "Queue": 0, "Formation": 0, "Garrison": 0, "Training": 0, "Research": 0, "Barter": 0, "Trading": 0, "Construction": 0, "Command": 0, "Stance": 0, "Gate": 0};
|
2010-07-01 22:31:47 +02:00
|
|
|
|
|
|
|
// Unit panels are panels with row(s) of buttons
|
2012-07-08 18:25:33 +02:00
|
|
|
var g_unitPanels = ["Selection", "Queue", "Formation", "Garrison", "Training", "Barter", "Trading", "Construction", "Research", "Stance", "Command", "Gate"];
|
2011-11-24 16:43:32 +01:00
|
|
|
|
|
|
|
// Indexes of resources to sell and buy on barter panel
|
|
|
|
var g_barterSell = 0;
|
2010-07-01 22:31:47 +02:00
|
|
|
|
2010-09-25 17:22:41 +02:00
|
|
|
// Lay out a row of centered buttons (does not work inside a loop like the other function)
|
|
|
|
function layoutButtonRowCentered(rowNumber, guiName, startIndex, endIndex, width)
|
|
|
|
{
|
|
|
|
var buttonSideLength = getGUIObjectByName("unit"+guiName+"Button[0]").size.bottom;
|
|
|
|
var buttonSpacer = buttonSideLength+1;
|
|
|
|
var colNumber = 0;
|
|
|
|
|
|
|
|
// Collect buttons
|
|
|
|
var buttons = [];
|
|
|
|
var icons = [];
|
|
|
|
|
|
|
|
for (var i = startIndex; i < endIndex; i++)
|
|
|
|
{
|
|
|
|
var button = getGUIObjectByName("unit"+guiName+"Button["+i+"]");
|
|
|
|
var icon = getGUIObjectByName("unit"+guiName+"Icon["+i+"]");
|
|
|
|
|
|
|
|
if (button)
|
|
|
|
{
|
|
|
|
buttons.push(button);
|
|
|
|
icons.push(icon);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Location of middle button
|
|
|
|
var middleIndex = Math.ceil(buttons.length/2);
|
|
|
|
|
|
|
|
// Determine whether even or odd number of buttons
|
|
|
|
var center = (buttons.length/2 == Math.ceil(buttons.length/2))? Math.ceil(width/2) : Math.ceil(width/2+buttonSpacer/2);
|
|
|
|
|
|
|
|
// Left Side
|
|
|
|
for (var i = middleIndex-1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if (buttons[i])
|
|
|
|
{
|
|
|
|
var icon = icons[i];
|
|
|
|
var size = buttons[i].size;
|
|
|
|
size.left = center - buttonSpacer*colNumber - buttonSideLength;
|
|
|
|
size.right = center - buttonSpacer*colNumber;
|
|
|
|
size.top = buttonSpacer*rowNumber;
|
|
|
|
size.bottom = buttonSpacer*rowNumber + buttonSideLength;
|
|
|
|
buttons[i].size = size;
|
|
|
|
colNumber++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Right Side
|
|
|
|
center += 1; // add spacing to center buttons
|
|
|
|
colNumber = 0; // reset to 0
|
|
|
|
|
|
|
|
for (var i = middleIndex; i < buttons.length; i++)
|
|
|
|
{
|
|
|
|
if (buttons[i])
|
|
|
|
{
|
|
|
|
var icon = icons[i];
|
|
|
|
var size = buttons[i].size;
|
|
|
|
size.left = center + buttonSpacer*colNumber;
|
|
|
|
size.right = center + buttonSpacer*colNumber + buttonSideLength;
|
|
|
|
size.top = buttonSpacer*rowNumber;
|
|
|
|
size.bottom = buttonSpacer*rowNumber + buttonSideLength;
|
|
|
|
buttons[i].size = size;
|
|
|
|
colNumber++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-03 18:51:20 +02:00
|
|
|
// Lay out button rows
|
2012-04-25 19:02:41 +02:00
|
|
|
function layoutButtonRow(rowNumber, guiName, buttonSideWidth, buttonSpacer, startIndex, endIndex)
|
|
|
|
{
|
|
|
|
layoutRow("Button", rowNumber, guiName, buttonSideWidth, buttonSpacer, buttonSideWidth, buttonSpacer, startIndex, endIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lay out rows
|
|
|
|
function layoutRow(objectName, rowNumber, guiName, objectSideWidth, objectSpacerWidth, objectSideHeight, objectSpacerHeight, startIndex, endIndex)
|
2010-07-03 18:51:20 +02:00
|
|
|
{
|
2010-07-06 01:04:38 +02:00
|
|
|
var colNumber = 0;
|
2010-07-03 18:51:20 +02:00
|
|
|
|
2010-07-20 01:01:58 +02:00
|
|
|
for (var i = startIndex; i < endIndex; i++)
|
2010-07-03 18:51:20 +02:00
|
|
|
{
|
2012-04-25 19:02:41 +02:00
|
|
|
var button = getGUIObjectByName("unit"+guiName+objectName+"["+i+"]");
|
2010-09-25 17:22:41 +02:00
|
|
|
|
|
|
|
if (button)
|
|
|
|
{
|
|
|
|
var size = button.size;
|
2011-09-06 20:15:27 +02:00
|
|
|
|
2012-04-25 19:02:41 +02:00
|
|
|
size.left = objectSpacerWidth*colNumber;
|
|
|
|
size.right = objectSpacerWidth*colNumber + objectSideWidth;
|
|
|
|
size.top = objectSpacerHeight*rowNumber;
|
|
|
|
size.bottom = objectSpacerHeight*rowNumber + objectSideHeight;
|
2011-09-06 20:15:27 +02:00
|
|
|
|
2010-09-25 17:22:41 +02:00
|
|
|
button.size = size;
|
|
|
|
colNumber++;
|
|
|
|
}
|
2010-07-03 18:51:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-25 19:58:16 +02:00
|
|
|
// Set the visibility of the object
|
|
|
|
function setOverlay(object, value)
|
|
|
|
{
|
|
|
|
object.hidden = !value;
|
|
|
|
}
|
|
|
|
|
2012-05-05 21:22:22 +02:00
|
|
|
/**
|
|
|
|
* 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 constants defined at the top of this file.
|
|
|
|
* @param usedPanels Output object; usedPanels[guiName] will be set to 1 to indicate that this panel was used during this
|
2012-07-17 01:49:19 +02:00
|
|
|
* run of updateUnitCommands and should not be hidden. TODO: why is this done this way instead of having
|
|
|
|
* updateUnitCommands keep track of this?
|
2012-05-05 21:22:22 +02:00
|
|
|
* @param unitEntState Entity state of the (first) selected unit.
|
|
|
|
* @param items Panel-specific data to construct the icons with.
|
|
|
|
* @param callback Callback function to argument to execute when an item's icon gets clicked. Takes a single 'item' argument.
|
|
|
|
*/
|
2010-07-31 23:46:25 +02:00
|
|
|
function setupUnitPanel(guiName, usedPanels, unitEntState, items, callback)
|
2010-07-01 22:31:47 +02:00
|
|
|
{
|
|
|
|
usedPanels[guiName] = 1;
|
2012-03-08 21:42:28 +01:00
|
|
|
|
2010-07-31 23:46:25 +02:00
|
|
|
var numberOfItems = items.length;
|
2010-10-02 00:18:03 +02:00
|
|
|
var selection = g_Selection.toList();
|
2010-10-24 00:43:15 +02:00
|
|
|
var garrisonGroups = new EntityGroups();
|
2010-07-31 23:46:25 +02:00
|
|
|
|
2011-09-06 20:15:27 +02:00
|
|
|
// Determine how many buttons there should be
|
|
|
|
switch (guiName)
|
2010-07-01 22:31:47 +02:00
|
|
|
{
|
2010-08-03 03:54:16 +02:00
|
|
|
case SELECTION:
|
2011-09-06 20:15:27 +02:00
|
|
|
if (numberOfItems > 16)
|
2012-07-17 01:49:19 +02:00
|
|
|
numberOfItems = 16;
|
2010-07-31 23:46:25 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case QUEUE:
|
2011-09-06 20:15:27 +02:00
|
|
|
if (numberOfItems > 16)
|
|
|
|
numberOfItems = 16;
|
2010-09-28 16:19:13 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GARRISON:
|
2011-09-06 20:15:27 +02:00
|
|
|
if (numberOfItems > 16)
|
|
|
|
numberOfItems = 16;
|
2010-09-28 16:19:13 +02:00
|
|
|
break;
|
|
|
|
|
2011-06-18 00:13:39 +02:00
|
|
|
case STANCE:
|
2011-09-06 20:15:27 +02:00
|
|
|
if (numberOfItems > 5)
|
2012-07-17 01:49:19 +02:00
|
|
|
numberOfItems = 5;
|
2012-04-15 18:27:44 +02:00
|
|
|
break;
|
2012-04-15 05:44:57 +02:00
|
|
|
|
2010-09-28 16:19:13 +02:00
|
|
|
case FORMATION:
|
2011-09-06 20:15:27 +02:00
|
|
|
if (numberOfItems > 16)
|
2012-07-17 01:49:19 +02:00
|
|
|
numberOfItems = 16;
|
2010-07-31 23:46:25 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TRAINING:
|
2011-09-06 20:15:27 +02:00
|
|
|
if (numberOfItems > 24)
|
2012-07-17 01:49:19 +02:00
|
|
|
numberOfItems = 24;
|
2010-07-31 23:46:25 +02:00
|
|
|
break;
|
2012-04-25 19:02:41 +02:00
|
|
|
|
2012-04-20 19:21:04 +02:00
|
|
|
case RESEARCH:
|
2012-04-25 19:02:41 +02:00
|
|
|
if (numberOfItems > 8)
|
2012-07-17 01:49:19 +02:00
|
|
|
numberOfItems = 8;
|
2012-04-20 19:21:04 +02:00
|
|
|
break;
|
2010-08-17 15:37:46 +02:00
|
|
|
|
2010-07-31 23:46:25 +02:00
|
|
|
case CONSTRUCTION:
|
2011-09-06 20:15:27 +02:00
|
|
|
if (numberOfItems > 24)
|
2012-07-17 01:49:19 +02:00
|
|
|
numberOfItems = 24;
|
2010-07-31 23:46:25 +02:00
|
|
|
break;
|
2010-08-17 15:37:46 +02:00
|
|
|
|
2010-08-01 07:09:30 +02:00
|
|
|
case COMMAND:
|
2011-09-06 20:15:27 +02:00
|
|
|
if (numberOfItems > 6)
|
|
|
|
numberOfItems = 6;
|
2010-08-01 07:09:30 +02:00
|
|
|
break;
|
2010-07-31 23:46:25 +02:00
|
|
|
|
2012-07-08 18:25:33 +02:00
|
|
|
case GATE:
|
2012-07-19 23:46:35 +02:00
|
|
|
if(numberOfItems > 8)
|
|
|
|
numberOfItems = 8;
|
2012-07-08 18:25:33 +02:00
|
|
|
break;
|
|
|
|
|
2010-07-31 23:46:25 +02:00
|
|
|
default:
|
|
|
|
break;
|
2011-09-06 20:15:27 +02:00
|
|
|
}
|
|
|
|
|
2012-08-16 03:15:04 +02:00
|
|
|
switch (guiName)
|
|
|
|
{
|
|
|
|
case GARRISON:
|
|
|
|
case COMMAND:
|
|
|
|
// Common code for garrison and 'unload all' button counts.
|
|
|
|
for (var i = 0; i < selection.length; ++i)
|
|
|
|
{
|
|
|
|
var state = GetEntityState(selection[i]);
|
|
|
|
if (state.garrisonHolder)
|
|
|
|
garrisonGroups.add(state.garrisonHolder.entities)
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-04-25 19:02:41 +02:00
|
|
|
var rowLength = 8;
|
|
|
|
if (guiName == SELECTION)
|
|
|
|
rowLength = 4;
|
|
|
|
else if (guiName == FORMATION || guiName == GARRISON || guiName == COMMAND)
|
|
|
|
rowLength = 4;
|
|
|
|
|
2011-09-06 20:15:27 +02:00
|
|
|
// Make buttons
|
|
|
|
var i;
|
|
|
|
for (i = 0; i < numberOfItems; i++)
|
|
|
|
{
|
|
|
|
var item = items[i];
|
2012-04-20 19:21:04 +02:00
|
|
|
|
|
|
|
// If a tech has been researched it leaves an empty slot
|
|
|
|
if (guiName == RESEARCH && !item)
|
|
|
|
{
|
|
|
|
getGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true;
|
2012-04-25 19:02:41 +02:00
|
|
|
// We also remove the paired tech and the pair symbol
|
|
|
|
getGUIObjectByName("unit"+guiName+"Button["+(i+rowLength)+"]").hidden = true;
|
|
|
|
getGUIObjectByName("unit"+guiName+"Pair["+i+"]").hidden = true;
|
2012-04-20 19:21:04 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the entity type and load the template for that type if necessary
|
|
|
|
var entType;
|
2011-09-06 20:15:27 +02:00
|
|
|
var template;
|
2012-04-25 19:02:41 +02:00
|
|
|
var entType1;
|
|
|
|
var template1;
|
2012-04-20 19:21:04 +02:00
|
|
|
switch (guiName)
|
2011-09-06 20:15:27 +02:00
|
|
|
{
|
2012-04-20 19:21:04 +02:00
|
|
|
case QUEUE:
|
|
|
|
// The queue can hold both technologies and units so we need to use the correct code for
|
|
|
|
// loading the templates
|
|
|
|
if (item.unitTemplate)
|
|
|
|
{
|
|
|
|
entType = item.unitTemplate;
|
|
|
|
template = GetTemplateData(entType);
|
|
|
|
}
|
|
|
|
else if (item.technologyTemplate)
|
|
|
|
{
|
|
|
|
entType = item.technologyTemplate;
|
|
|
|
template = GetTechnologyData(entType);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!template)
|
2012-07-17 01:49:19 +02:00
|
|
|
continue; // ignore attempts to use invalid templates (an error should have been
|
|
|
|
// reported already)
|
2012-04-20 19:21:04 +02:00
|
|
|
break;
|
|
|
|
case RESEARCH:
|
2012-04-25 19:02:41 +02:00
|
|
|
if (item.pair)
|
|
|
|
{
|
2012-04-26 19:43:33 +02:00
|
|
|
entType1 = item.top;
|
2012-04-25 19:02:41 +02:00
|
|
|
template1 = GetTechnologyData(entType1);
|
|
|
|
if (!template1)
|
2012-07-17 01:49:19 +02:00
|
|
|
continue; // ignore attempts to use invalid templates (an error should have been
|
|
|
|
// reported already)
|
2012-04-25 19:02:41 +02:00
|
|
|
|
2012-04-26 19:43:33 +02:00
|
|
|
entType = item.bottom;
|
2012-04-25 19:02:41 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
entType = item;
|
|
|
|
}
|
2012-04-20 19:21:04 +02:00
|
|
|
template = GetTechnologyData(entType);
|
|
|
|
if (!template)
|
2012-07-17 01:49:19 +02:00
|
|
|
continue; // ignore attempts to use invalid templates (an error should have been
|
|
|
|
// reported already)
|
2012-04-25 19:02:41 +02:00
|
|
|
|
2012-04-20 19:21:04 +02:00
|
|
|
break;
|
|
|
|
case SELECTION:
|
|
|
|
case GARRISON:
|
|
|
|
case TRAINING:
|
|
|
|
case CONSTRUCTION:
|
|
|
|
entType = item;
|
|
|
|
template = GetTemplateData(entType);
|
|
|
|
if (!template)
|
2012-07-17 01:49:19 +02:00
|
|
|
continue; // ignore attempts to use invalid templates (an error should have been
|
|
|
|
// reported already)
|
2012-04-20 19:21:04 +02:00
|
|
|
break;
|
2011-09-06 20:15:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (guiName)
|
|
|
|
{
|
|
|
|
case SELECTION:
|
2012-08-27 09:07:33 +02:00
|
|
|
var name = getEntityNames(template);
|
2011-09-06 20:15:27 +02:00
|
|
|
var tooltip = name;
|
|
|
|
var count = g_Selection.groups.getCount(item);
|
|
|
|
getGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = (count > 1 ? count : "");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QUEUE:
|
2012-08-27 09:07:33 +02:00
|
|
|
var tooltip = getEntityNames(template);
|
2011-09-06 20:15:27 +02:00
|
|
|
var progress = Math.round(item.progress*100) + "%";
|
|
|
|
getGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = (item.count > 1 ? item.count : "");
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
{
|
|
|
|
getGUIObjectByName("queueProgress").caption = (item.progress ? progress : "");
|
|
|
|
var size = getGUIObjectByName("unit"+guiName+"ProgressSlider["+i+"]").size;
|
2012-07-31 05:37:04 +02:00
|
|
|
|
|
|
|
// Buttons are assumed to be square, so left/right offsets can be used for top/bottom.
|
|
|
|
size.top = size.left + Math.round(item.progress * (size.right - size.left));
|
2011-09-06 20:15:27 +02:00
|
|
|
getGUIObjectByName("unit"+guiName+"ProgressSlider["+i+"]").size = size;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GARRISON:
|
2012-08-27 09:07:33 +02:00
|
|
|
var name = getEntityNames(template);
|
2012-08-26 21:58:25 +02:00
|
|
|
var tooltip = "Unload " + name + "\nSingle-click to unload 1. Shift-click to unload all of this type.";
|
2011-09-06 20:15:27 +02:00
|
|
|
var count = garrisonGroups.getCount(item);
|
|
|
|
getGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = (count > 1 ? count : "");
|
|
|
|
break;
|
|
|
|
|
2012-07-17 01:49:19 +02:00
|
|
|
case GATE:
|
|
|
|
var tooltip = item.tooltip;
|
|
|
|
if (item.template)
|
2012-08-13 18:47:10 +02:00
|
|
|
{
|
|
|
|
var template = GetTemplateData(item.template);
|
|
|
|
tooltip += "\n" + getEntityCostTooltip(template);
|
|
|
|
|
|
|
|
var affordableMask = getGUIObjectByName("unitGateUnaffordable["+i+"]");
|
|
|
|
affordableMask.hidden = true;
|
|
|
|
|
|
|
|
var neededResources = Engine.GuiInterfaceCall("GetNeededResources", template.cost);
|
|
|
|
if (neededResources)
|
|
|
|
{
|
|
|
|
affordableMask.hidden = false;
|
|
|
|
tooltip += getNeededResourcesTooltip(neededResources);
|
|
|
|
}
|
|
|
|
}
|
2012-07-17 01:49:19 +02:00
|
|
|
break;
|
|
|
|
|
2011-09-06 20:15:27 +02:00
|
|
|
case STANCE:
|
|
|
|
case FORMATION:
|
|
|
|
var tooltip = toTitleCase(item);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TRAINING:
|
2012-08-27 09:07:33 +02:00
|
|
|
var tooltip = getEntityNamesFormatted(template);
|
2011-11-12 23:23:08 +01:00
|
|
|
|
2011-09-06 20:15:27 +02:00
|
|
|
if (template.tooltip)
|
|
|
|
tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]";
|
|
|
|
|
2012-04-20 19:21:04 +02:00
|
|
|
var [batchSize, batchIncrement] = getTrainingBatchStatus(unitEntState.id, entType);
|
2011-11-12 23:23:08 +01:00
|
|
|
var trainNum = batchSize ? batchSize+batchIncrement : batchIncrement;
|
|
|
|
|
2012-05-05 21:22:22 +02:00
|
|
|
tooltip += "\n" + getEntityCostTooltip(template);
|
2011-09-06 20:15:27 +02:00
|
|
|
|
2011-11-12 23:23:08 +01:00
|
|
|
if (template.health)
|
|
|
|
tooltip += "\n[font=\"serif-bold-13\"]Health:[/font] " + template.health;
|
|
|
|
if (template.armour)
|
|
|
|
tooltip += "\n[font=\"serif-bold-13\"]Armour:[/font] " + damageTypesToText(template.armour);
|
|
|
|
if (template.attack)
|
|
|
|
tooltip += "\n" + getEntityAttack(template);
|
|
|
|
if (template.speed)
|
|
|
|
tooltip += "\n" + getEntitySpeed(template);
|
|
|
|
|
|
|
|
tooltip += "\n\n[font=\"serif-bold-13\"]Shift-click[/font][font=\"serif-13\"] to train " + trainNum + ".[/font]";
|
|
|
|
|
2011-09-06 20:15:27 +02:00
|
|
|
break;
|
2012-04-20 19:21:04 +02:00
|
|
|
|
|
|
|
case RESEARCH:
|
2012-08-27 09:07:33 +02:00
|
|
|
var tooltip = getEntityNamesFormatted(template);
|
2012-04-20 19:21:04 +02:00
|
|
|
if (template.tooltip)
|
|
|
|
tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]";
|
|
|
|
|
2012-05-05 21:22:22 +02:00
|
|
|
tooltip += "\n" + getEntityCostTooltip(template);
|
2012-04-25 19:02:41 +02:00
|
|
|
|
|
|
|
if (item.pair)
|
|
|
|
{
|
2012-08-27 09:07:33 +02:00
|
|
|
var tooltip1 = getEntityNamesFormatted(template1);
|
2012-04-25 19:02:41 +02:00
|
|
|
if (template1.tooltip)
|
|
|
|
tooltip1 += "\n[font=\"serif-13\"]" + template1.tooltip + "[/font]";
|
|
|
|
|
2012-05-05 21:22:22 +02:00
|
|
|
tooltip1 += "\n" + getEntityCostTooltip(template1);
|
2012-04-25 19:02:41 +02:00
|
|
|
}
|
2012-04-20 19:21:04 +02:00
|
|
|
break;
|
2011-09-06 20:15:27 +02:00
|
|
|
|
|
|
|
case CONSTRUCTION:
|
2012-08-27 09:07:33 +02:00
|
|
|
var tooltip = getEntityNamesFormatted(template);
|
2011-09-06 20:15:27 +02:00
|
|
|
if (template.tooltip)
|
2011-11-12 23:23:08 +01:00
|
|
|
tooltip += "\n[font=\"serif-13\"]" + template.tooltip + "[/font]";
|
2011-09-06 20:15:27 +02:00
|
|
|
|
2012-05-05 21:22:22 +02:00
|
|
|
tooltip += "\n" + getEntityCostTooltip(template); // see utility_functions.js
|
|
|
|
tooltip += getPopulationBonusTooltip(template); // see utility_functions.js
|
2011-11-12 23:23:08 +01:00
|
|
|
|
|
|
|
if (template.health)
|
|
|
|
tooltip += "\n[font=\"serif-bold-13\"]Health:[/font] " + template.health;
|
|
|
|
|
2011-09-06 20:15:27 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case COMMAND:
|
2011-12-10 08:07:04 +01:00
|
|
|
// here, "item" is an object with properties .name (command name), .tooltip and .icon (relative to session/icons/single)
|
|
|
|
if (item.name == "unload-all")
|
2011-09-06 20:15:27 +02:00
|
|
|
{
|
2012-08-16 03:15:04 +02:00
|
|
|
var count = garrisonGroups.getTotalCount();
|
2011-09-06 20:15:27 +02:00
|
|
|
getGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = (count > 0 ? count : "");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
getGUIObjectByName("unit"+guiName+"Count["+i+"]").caption = "";
|
|
|
|
}
|
|
|
|
|
2011-12-10 08:07:04 +01:00
|
|
|
tooltip = (item.tooltip ? item.tooltip : toTitleCase(item.name));
|
2011-09-06 20:15:27 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2010-07-01 22:31:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Button
|
|
|
|
var button = getGUIObjectByName("unit"+guiName+"Button["+i+"]");
|
2012-04-25 19:02:41 +02:00
|
|
|
var button1 = getGUIObjectByName("unit"+guiName+"Button["+(i+rowLength)+"]");
|
2012-08-13 18:47:10 +02:00
|
|
|
var affordableMask = getGUIObjectByName("unit"+guiName+"Unaffordable["+i+"]");
|
|
|
|
var affordableMask1 = getGUIObjectByName("unit"+guiName+"Unaffordable["+(i+rowLength)+"]");
|
2010-07-01 22:31:47 +02:00
|
|
|
var icon = getGUIObjectByName("unit"+guiName+"Icon["+i+"]");
|
2012-04-09 20:58:03 +02:00
|
|
|
var selection = getGUIObjectByName("unit"+guiName+"Selection["+i+"]");
|
2012-04-25 19:02:41 +02:00
|
|
|
var pair = getGUIObjectByName("unit"+guiName+"Pair["+i+"]");
|
2010-07-01 22:31:47 +02:00
|
|
|
button.hidden = false;
|
|
|
|
button.tooltip = tooltip;
|
|
|
|
|
2011-09-06 20:15:27 +02:00
|
|
|
// Button Function (need nested functions to get the closure right)
|
2012-07-30 01:08:15 +02:00
|
|
|
// Items can have a callback element that overrides the normal caller-supplied callback function.
|
|
|
|
button.onpress = (function(e){ return function() { e.callback ? e.callback(e) : callback(e) } })(item);
|
2010-07-01 22:31:47 +02:00
|
|
|
|
2012-05-01 20:56:47 +02:00
|
|
|
if (guiName == RESEARCH)
|
2012-04-25 19:02:41 +02:00
|
|
|
{
|
2012-05-01 20:56:47 +02:00
|
|
|
if (item.pair)
|
|
|
|
{
|
|
|
|
button.onpress = (function(e){ return function() { callback(e) } })(item.bottom);
|
|
|
|
|
|
|
|
var icon1 = getGUIObjectByName("unit"+guiName+"Icon["+(i+rowLength)+"]");
|
|
|
|
button1.hidden = false;
|
|
|
|
button1.tooltip = tooltip1;
|
|
|
|
button1.onpress = (function(e){ return function() { callback(e) } })(item.top);
|
|
|
|
|
|
|
|
// We add a red overlay to the paired button (we reuse the selection for that)
|
|
|
|
button1.onmouseenter = (function(e){ return function() { setOverlay(e, true) } })(selection);
|
|
|
|
button1.onmouseleave = (function(e){ return function() { setOverlay(e, false) } })(selection);
|
|
|
|
|
|
|
|
var selection1 = getGUIObjectByName("unit"+guiName+"Selection["+(i+rowLength)+"]");;
|
|
|
|
button.onmouseenter = (function(e){ return function() { setOverlay(e, true) } })(selection1);
|
|
|
|
button.onmouseleave = (function(e){ return function() { setOverlay(e, false) } })(selection1);
|
|
|
|
|
|
|
|
pair.hidden = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Hide the overlay
|
|
|
|
selection.hidden = true;
|
|
|
|
}
|
2012-04-25 19:02:41 +02:00
|
|
|
}
|
|
|
|
|
2010-08-01 18:25:24 +02:00
|
|
|
// Get icon image
|
2012-04-21 19:26:06 +02:00
|
|
|
if (guiName == FORMATION)
|
2010-09-28 16:19:13 +02:00
|
|
|
{
|
2011-05-01 22:40:53 +02:00
|
|
|
var formationOk = Engine.GuiInterfaceCall("CanMoveEntsIntoFormation", {
|
|
|
|
"ents": g_Selection.toList(),
|
|
|
|
"formationName": item
|
|
|
|
});
|
|
|
|
|
2012-04-09 20:58:03 +02:00
|
|
|
var grayscale = "";
|
2011-05-01 22:40:53 +02:00
|
|
|
button.enabled = formationOk;
|
2012-03-21 17:45:02 +01:00
|
|
|
if (!formationOk)
|
|
|
|
{
|
2012-04-09 20:58:03 +02:00
|
|
|
grayscale = "grayscale:";
|
2012-03-21 17:45:02 +01:00
|
|
|
|
|
|
|
// Display a meaningful tooltip why the formation is disabled
|
|
|
|
var requirements = Engine.GuiInterfaceCall("GetFormationRequirements", {
|
|
|
|
"formationName": item
|
|
|
|
});
|
|
|
|
|
|
|
|
button.tooltip += " (disabled)";
|
|
|
|
if (requirements.count > 1)
|
|
|
|
button.tooltip += "\n" + requirements.count + " units required";
|
|
|
|
if (requirements.classesRequired)
|
|
|
|
{
|
|
|
|
button.tooltip += "\nOnly units of type";
|
|
|
|
for each (var classRequired in requirements.classesRequired)
|
|
|
|
{
|
|
|
|
button.tooltip += " " + classRequired;
|
|
|
|
}
|
|
|
|
button.tooltip += " allowed.";
|
|
|
|
}
|
|
|
|
}
|
2012-04-09 20:58:03 +02:00
|
|
|
|
|
|
|
var formationSelected = Engine.GuiInterfaceCall("IsFormationSelected", {
|
|
|
|
"ents": g_Selection.toList(),
|
|
|
|
"formationName": item
|
|
|
|
});
|
|
|
|
|
|
|
|
selection.hidden = !formationSelected;
|
|
|
|
icon.sprite = "stretched:"+grayscale+"session/icons/formations/"+item.replace(/\s+/,'').toLowerCase()+".png";
|
|
|
|
|
2012-03-21 17:45:02 +01:00
|
|
|
}
|
2012-04-21 19:26:06 +02:00
|
|
|
else if (guiName == STANCE)
|
2011-06-18 00:13:39 +02:00
|
|
|
{
|
2011-06-24 14:35:15 +02:00
|
|
|
var stanceSelected = Engine.GuiInterfaceCall("IsStanceSelected", {
|
2011-06-18 00:13:39 +02:00
|
|
|
"ents": g_Selection.toList(),
|
|
|
|
"stance": item
|
|
|
|
});
|
|
|
|
|
2012-04-09 20:58:03 +02:00
|
|
|
selection.hidden = !stanceSelected;
|
|
|
|
icon.sprite = "stretched:session/icons/stances/"+item+".png";
|
2011-06-18 00:13:39 +02:00
|
|
|
}
|
2012-04-21 19:26:06 +02:00
|
|
|
else if (guiName == COMMAND)
|
2010-08-01 07:09:30 +02:00
|
|
|
{
|
2012-04-10 01:13:45 +02:00
|
|
|
icon.sprite = "stretched:session/icons/" + item.icon;
|
2010-08-01 07:09:30 +02:00
|
|
|
}
|
2012-07-08 18:25:33 +02:00
|
|
|
else if (guiName == GATE)
|
|
|
|
{
|
2012-07-16 03:52:18 +02:00
|
|
|
var gateIcon;
|
2012-07-17 01:49:19 +02:00
|
|
|
// If already a gate, show locking actions
|
2012-07-30 01:08:15 +02:00
|
|
|
if (item.gate)
|
2012-07-17 01:49:19 +02:00
|
|
|
{
|
2012-07-30 01:08:15 +02:00
|
|
|
gateIcon = "icons/lock_" + GATE_ACTIONS[item.locked ? 0 : 1].toLowerCase() + "ed.png";
|
|
|
|
selection.hidden = item.gate.locked === undefined ? false : item.gate.locked != item.locked;
|
2012-07-17 01:49:19 +02:00
|
|
|
}
|
|
|
|
// otherwise show gate upgrade icon
|
2012-07-16 03:52:18 +02:00
|
|
|
else
|
2012-07-17 01:49:19 +02:00
|
|
|
{
|
2012-07-19 23:46:35 +02:00
|
|
|
template = GetTemplateData(item.template);
|
|
|
|
gateIcon = template.icon ? "portraits/" + template.icon : "icons/gate_closed.png";
|
2012-07-17 01:49:19 +02:00
|
|
|
selection.hidden = true;
|
|
|
|
}
|
2012-07-16 03:52:18 +02:00
|
|
|
|
2012-07-19 23:46:35 +02:00
|
|
|
icon.sprite = "stretched:session/" + gateIcon;
|
2012-07-08 18:25:33 +02:00
|
|
|
}
|
2010-10-23 01:27:42 +02:00
|
|
|
else if (template.icon)
|
|
|
|
{
|
2012-04-20 19:21:04 +02:00
|
|
|
var grayscale = "";
|
|
|
|
button.enabled = true;
|
|
|
|
|
2012-07-08 22:12:36 +02:00
|
|
|
if (guiName != SELECTION && template.requiredTechnology && !Engine.GuiInterfaceCall("IsTechnologyResearched", template.requiredTechnology))
|
2012-04-20 19:21:04 +02:00
|
|
|
{
|
|
|
|
button.enabled = false;
|
2012-08-27 09:07:33 +02:00
|
|
|
var techName = getEntityNames(GetTechnologyData(template.requiredTechnology));
|
2012-04-20 19:21:04 +02:00
|
|
|
button.tooltip += "\nRequires " + techName;
|
|
|
|
grayscale = "grayscale:";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (guiName == RESEARCH && !Engine.GuiInterfaceCall("CheckTechnologyRequirements", entType))
|
|
|
|
{
|
|
|
|
button.enabled = false;
|
|
|
|
button.tooltip += "\n" + GetTechnologyData(entType).requirementsTooltip;
|
|
|
|
grayscale = "grayscale:";
|
|
|
|
}
|
|
|
|
|
|
|
|
icon.sprite = "stretched:" + grayscale + "session/portraits/" + template.icon;
|
2012-04-25 19:02:41 +02:00
|
|
|
|
|
|
|
if (guiName == RESEARCH)
|
|
|
|
{
|
2012-08-13 18:47:10 +02:00
|
|
|
// Check resource requirements for first button
|
|
|
|
affordableMask.hidden = true;
|
|
|
|
var neededResources = Engine.GuiInterfaceCall("GetNeededResources", template.cost);
|
|
|
|
if (neededResources)
|
|
|
|
{
|
|
|
|
if (button.enabled !== false)
|
|
|
|
{
|
|
|
|
button.enabled = false;
|
|
|
|
affordableMask.hidden = false;
|
|
|
|
}
|
|
|
|
button.tooltip += getNeededResourcesTooltip(neededResources);
|
|
|
|
}
|
|
|
|
|
2012-04-25 19:02:41 +02:00
|
|
|
if (item.pair)
|
|
|
|
{
|
|
|
|
grayscale = "";
|
|
|
|
button1.enabled = true;
|
2012-08-13 18:47:10 +02:00
|
|
|
|
|
|
|
if (!Engine.GuiInterfaceCall("CheckTechnologyRequirements", entType1))
|
2012-04-25 19:02:41 +02:00
|
|
|
{
|
|
|
|
button1.enabled = false;
|
|
|
|
button1.tooltip += "\n" + GetTechnologyData(entType1).requirementsTooltip;
|
|
|
|
grayscale = "grayscale:";
|
|
|
|
}
|
|
|
|
icon1.sprite = "stretched:" + grayscale + "session/portraits/" +template1.icon;
|
2012-08-13 18:47:10 +02:00
|
|
|
|
|
|
|
// Check resource requirements for second button
|
|
|
|
affordableMask1.hidden = true;
|
|
|
|
neededResources = Engine.GuiInterfaceCall("GetNeededResources", template.cost);
|
|
|
|
if (neededResources)
|
|
|
|
{
|
|
|
|
if (button1.enabled !== false)
|
|
|
|
{
|
|
|
|
button1.enabled = false;
|
|
|
|
affordableMask1.hidden = false;
|
|
|
|
}
|
|
|
|
button1.tooltip += getNeededResourcesTooltip(neededResources);
|
|
|
|
}
|
2012-04-25 19:02:41 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pair.hidden = true;
|
|
|
|
button1.hidden = true;
|
2012-08-13 18:47:10 +02:00
|
|
|
affordableMask1.hidden = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (guiName == CONSTRUCTION || guiName == TRAINING)
|
|
|
|
{
|
|
|
|
affordableMask.hidden = true;
|
|
|
|
var totalCosts = {};
|
|
|
|
var trainNum = 1;
|
|
|
|
if (Engine.HotkeyIsPressed("session.batchtrain") && guiName == TRAINING)
|
|
|
|
{
|
|
|
|
var [batchSize, batchIncrement] = getTrainingBatchStatus(unitEntState.id, entType);
|
|
|
|
trainNum = batchSize + batchIncrement;
|
2012-04-25 19:02:41 +02:00
|
|
|
}
|
2012-08-13 18:47:10 +02:00
|
|
|
|
|
|
|
// Walls have no cost defined.
|
|
|
|
if (template.cost !== undefined)
|
|
|
|
for (var r in template.cost)
|
|
|
|
totalCosts[r] = Math.floor(template.cost[r] * trainNum);
|
|
|
|
|
|
|
|
var neededResources = Engine.GuiInterfaceCall("GetNeededResources", totalCosts);
|
|
|
|
if (neededResources)
|
|
|
|
{
|
|
|
|
var totalCost = 0;
|
|
|
|
if (button.enabled !== false)
|
|
|
|
{
|
|
|
|
for each (var resource in neededResources)
|
|
|
|
totalCost += resource;
|
|
|
|
|
|
|
|
button.enabled = false;
|
|
|
|
affordableMask.hidden = false;
|
|
|
|
var alpha = 75 + totalCost/6;
|
|
|
|
alpha = alpha > 150 ? 150 : alpha;
|
|
|
|
affordableMask.sprite = "colour: 255 0 0 " + (alpha);
|
|
|
|
}
|
|
|
|
button.tooltip += getNeededResourcesTooltip(neededResources);
|
|
|
|
}
|
2012-04-25 19:02:41 +02:00
|
|
|
}
|
2010-10-23 01:27:42 +02:00
|
|
|
}
|
2010-07-01 22:31:47 +02:00
|
|
|
else
|
2010-08-01 07:09:30 +02:00
|
|
|
{
|
2010-10-23 01:27:42 +02:00
|
|
|
// TODO: we should require all entities to have icons, so this case never occurs
|
|
|
|
icon.sprite = "bkFillBlack";
|
2010-08-01 07:09:30 +02:00
|
|
|
}
|
2010-07-01 22:31:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Position the visible buttons (TODO: if there's lots, maybe they should be squeezed together to fit)
|
|
|
|
var numButtons = i;
|
2010-09-28 16:19:13 +02:00
|
|
|
|
2010-08-01 02:33:20 +02:00
|
|
|
var numRows = Math.ceil(numButtons / rowLength);
|
2012-04-25 19:02:41 +02:00
|
|
|
|
2010-07-19 23:23:12 +02:00
|
|
|
var buttonSideLength = getGUIObjectByName("unit"+guiName+"Button[0]").size.bottom;
|
2010-07-07 15:28:37 +02:00
|
|
|
|
2012-04-26 19:43:33 +02:00
|
|
|
// We sort pairs upside down, so get the size from the topmost button.
|
|
|
|
if (guiName == RESEARCH)
|
|
|
|
buttonSideLength = getGUIObjectByName("unit"+guiName+"Button["+(rowLength*numRows)+"]").size.bottom;
|
|
|
|
|
|
|
|
var buttonSpacer = buttonSideLength+1;
|
|
|
|
|
2010-07-19 23:23:12 +02:00
|
|
|
// Layout buttons
|
2012-04-21 19:26:06 +02:00
|
|
|
if (guiName == COMMAND)
|
2010-09-25 17:22:41 +02:00
|
|
|
{
|
2010-10-04 00:42:15 +02:00
|
|
|
layoutButtonRowCentered(0, guiName, 0, numButtons, COMMANDS_PANEL_WIDTH);
|
2010-09-25 17:22:41 +02:00
|
|
|
}
|
2012-04-26 19:43:33 +02:00
|
|
|
else if (guiName == RESEARCH)
|
|
|
|
{
|
|
|
|
// We support pairs so we need to add a row
|
|
|
|
numRows++;
|
|
|
|
// Layout rows from bottom to top
|
|
|
|
for (var i = 0, j = numRows; i < numRows; i++, j--)
|
|
|
|
{
|
|
|
|
layoutButtonRow(i, guiName, buttonSideLength, buttonSpacer, rowLength*(j-1), rowLength*j);
|
|
|
|
}
|
|
|
|
}
|
2010-09-25 17:22:41 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
for (var i = 0; i < numRows; i++)
|
|
|
|
layoutButtonRow(i, guiName, buttonSideLength, buttonSpacer, rowLength*i, rowLength*(i+1) );
|
|
|
|
}
|
2012-04-25 19:02:41 +02:00
|
|
|
|
|
|
|
// Layout pair icons
|
|
|
|
if (guiName == RESEARCH)
|
|
|
|
{
|
|
|
|
var pairSize = getGUIObjectByName("unit"+guiName+"Pair[0]").size;
|
|
|
|
var pairSideWidth = pairSize.right;
|
|
|
|
var pairSideHeight = pairSize.bottom;
|
|
|
|
var pairSpacerHeight = pairSideHeight + 1;
|
|
|
|
var pairSpacerWidth = pairSideWidth + 1;
|
|
|
|
|
|
|
|
layoutRow("Pair", 0, guiName, pairSideWidth, pairSpacerWidth, pairSideHeight, pairSpacerHeight, 0, rowLength);
|
|
|
|
}
|
2011-09-06 20:15:27 +02:00
|
|
|
|
2010-10-04 00:42:15 +02:00
|
|
|
// Resize Queue panel if needed
|
2012-04-21 19:26:06 +02:00
|
|
|
if (guiName == QUEUE) // or garrison
|
2010-10-04 00:42:15 +02:00
|
|
|
{
|
|
|
|
var panel = getGUIObjectByName("unitQueuePanel");
|
|
|
|
var size = panel.size;
|
|
|
|
size.top = (UNIT_PANEL_BASE - ((numRows-1)*UNIT_PANEL_HEIGHT));
|
|
|
|
panel.size = size;
|
|
|
|
}
|
2010-07-19 23:23:12 +02:00
|
|
|
|
2010-07-01 22:31:47 +02:00
|
|
|
// Hide any buttons we're no longer using
|
|
|
|
for (i = numButtons; i < g_unitPanelButtons[guiName]; ++i)
|
|
|
|
getGUIObjectByName("unit"+guiName+"Button["+i+"]").hidden = true;
|
|
|
|
|
2012-04-25 19:02:41 +02:00
|
|
|
// Hide unused pair buttons and symbols
|
|
|
|
if (guiName == RESEARCH)
|
|
|
|
{
|
|
|
|
for (i = numButtons; i < g_unitPanelButtons[guiName]; ++i)
|
|
|
|
{
|
|
|
|
getGUIObjectByName("unit"+guiName+"Button["+(i+rowLength)+"]").hidden = true;
|
|
|
|
getGUIObjectByName("unit"+guiName+"Pair["+i+"]").hidden = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-01 22:31:47 +02:00
|
|
|
g_unitPanelButtons[guiName] = numButtons;
|
|
|
|
}
|
|
|
|
|
2012-03-08 21:42:28 +01:00
|
|
|
// Sets up "unit trading panel" - special case for setupUnitPanel
|
2012-07-16 06:12:48 +02:00
|
|
|
function setupUnitTradingPanel(usedPanels, unitEntState, selection)
|
2012-03-08 21:42:28 +01:00
|
|
|
{
|
2012-07-16 06:12:48 +02:00
|
|
|
usedPanels[TRADING] = 1;
|
|
|
|
|
2012-03-08 21:42:28 +01:00
|
|
|
for (var i = 0; i < TRADING_RESOURCES.length; i++)
|
|
|
|
{
|
|
|
|
var resource = TRADING_RESOURCES[i];
|
|
|
|
var button = getGUIObjectByName("unitTradingButton["+i+"]");
|
|
|
|
button.size = (i * 46) + " 0 " + ((i + 1) * 46) + " 46";
|
2012-04-06 17:07:04 +02:00
|
|
|
var selectTradingPreferredGoodsData = { "entities": selection, "preferredGoods": resource };
|
2012-03-08 21:42:28 +01:00
|
|
|
button.onpress = (function(e){ return function() { selectTradingPreferredGoods(e); } })(selectTradingPreferredGoodsData);
|
|
|
|
button.enabled = true;
|
|
|
|
button.tooltip = "Set " + resource + " as trading goods";
|
|
|
|
var icon = getGUIObjectByName("unitTradingIcon["+i+"]");
|
|
|
|
var preferredGoods = unitEntState.trader.preferredGoods;
|
2012-04-09 20:58:03 +02:00
|
|
|
var selected = getGUIObjectByName("unitTradingSelection["+i+"]");
|
|
|
|
selected.hidden = !(resource == preferredGoods);
|
2012-04-09 00:56:11 +02:00
|
|
|
var grayscale = (resource != preferredGoods) ? "grayscale:" : "";
|
2012-04-09 20:58:03 +02:00
|
|
|
icon.sprite = "stretched:"+grayscale+"session/icons/resources/" + resource + ".png";
|
2012-03-08 21:42:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-24 16:43:32 +01:00
|
|
|
// Sets up "unit barter panel" - special case for setupUnitPanel
|
|
|
|
function setupUnitBarterPanel(unitEntState)
|
|
|
|
{
|
|
|
|
// Amount of player's resource to exchange
|
|
|
|
var amountToSell = BARTER_RESOURCE_AMOUNT_TO_SELL;
|
|
|
|
if (Engine.HotkeyIsPressed("session.massbarter"))
|
|
|
|
amountToSell *= BARTER_BUNCH_MULTIPLIER;
|
|
|
|
// One pass for each resource
|
|
|
|
for (var i = 0; i < BARTER_RESOURCES.length; i++)
|
|
|
|
{
|
|
|
|
var resource = BARTER_RESOURCES[i];
|
|
|
|
// One pass for 'sell' row and another for 'buy'
|
|
|
|
for (var j = 0; j < 2; j++)
|
|
|
|
{
|
|
|
|
var action = BARTER_ACTIONS[j];
|
|
|
|
|
2012-04-09 20:58:03 +02:00
|
|
|
if (j == 0)
|
|
|
|
{
|
|
|
|
// Display the selection overlay
|
|
|
|
var selection = getGUIObjectByName("unitBarter" + action + "Selection["+i+"]");
|
|
|
|
selection.hidden = !(i == g_barterSell);
|
|
|
|
}
|
|
|
|
|
2012-04-09 00:56:11 +02:00
|
|
|
// We gray out the not selected icons in 'sell' row
|
|
|
|
var grayscale = (j == 0 && i != g_barterSell) ? "grayscale:" : "";
|
2011-11-24 16:43:32 +01:00
|
|
|
var icon = getGUIObjectByName("unitBarter" + action + "Icon["+i+"]");
|
|
|
|
|
|
|
|
var button = getGUIObjectByName("unitBarter" + action + "Button["+i+"]");
|
|
|
|
button.size = (i * 46) + " 0 " + ((i + 1) * 46) + " 46";
|
|
|
|
var amountToBuy;
|
2012-04-15 18:27:44 +02:00
|
|
|
// We don't display a button in 'buy' row if the same resource is selected in 'sell' row
|
2011-11-24 16:43:32 +01:00
|
|
|
if (j == 1 && i == g_barterSell)
|
|
|
|
{
|
2012-04-15 05:44:57 +02:00
|
|
|
button.hidden = true;
|
2011-11-24 16:43:32 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-04-15 05:44:57 +02:00
|
|
|
button.hidden = false;
|
2011-11-24 16:43:32 +01:00
|
|
|
button.tooltip = action + " " + resource;
|
2012-04-09 20:58:03 +02:00
|
|
|
icon.sprite = "stretched:"+grayscale+"session/icons/resources/" + resource + ".png";
|
2011-11-24 16:43:32 +01:00
|
|
|
var sellPrice = unitEntState.barterMarket.prices["sell"][BARTER_RESOURCES[g_barterSell]];
|
|
|
|
var buyPrice = unitEntState.barterMarket.prices["buy"][resource];
|
|
|
|
amountToBuy = "+" + Math.round(sellPrice / buyPrice * amountToSell);
|
|
|
|
}
|
2012-08-13 18:47:10 +02:00
|
|
|
|
2011-11-24 16:43:32 +01:00
|
|
|
var amount;
|
|
|
|
if (j == 0)
|
|
|
|
{
|
2012-04-08 09:27:56 +02:00
|
|
|
button.onpress = (function(i){ return function() { g_barterSell = i; } })(i);
|
2012-08-13 18:47:10 +02:00
|
|
|
if (i == g_barterSell)
|
|
|
|
{
|
|
|
|
amount = "-" + amountToSell;
|
|
|
|
|
|
|
|
var neededRes = {};
|
|
|
|
neededRes[resource] = amountToSell;
|
|
|
|
var neededResources = Engine.GuiInterfaceCall("GetNeededResources", neededRes);
|
|
|
|
var hidden = neededResources ? false : true;
|
|
|
|
for (var ii = 0; ii < BARTER_RESOURCES.length; ii++)
|
|
|
|
{
|
|
|
|
var affordableMask = getGUIObjectByName("unitBarterBuyUnaffordable["+ii+"]");
|
|
|
|
affordableMask.hidden = hidden;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
amount = "";
|
|
|
|
}
|
2011-11-24 16:43:32 +01:00
|
|
|
else
|
|
|
|
{
|
2012-04-08 09:27:56 +02:00
|
|
|
var exchangeResourcesParameters = { "sell": BARTER_RESOURCES[g_barterSell], "buy": BARTER_RESOURCES[i], "amount": amountToSell };
|
|
|
|
button.onpress = (function(exchangeResourcesParameters){ return function() { exchangeResources(exchangeResourcesParameters); } })(exchangeResourcesParameters);
|
2011-11-24 16:43:32 +01:00
|
|
|
amount = amountToBuy;
|
|
|
|
}
|
|
|
|
getGUIObjectByName("unitBarter" + action + "Amount["+i+"]").caption = amount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-05 21:22:22 +02:00
|
|
|
/**
|
|
|
|
* Updates the right hand side "Unit Commands" panel. 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
|
2012-06-11 03:07:41 +02:00
|
|
|
* @param commandsPanel Reference to the "commandsPanel" GUI Object
|
2012-05-05 21:22:22 +02:00
|
|
|
* @param selection Array of currently selected entity IDs.
|
|
|
|
*/
|
2010-09-28 16:19:13 +02:00
|
|
|
function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection)
|
2010-07-01 22:31:47 +02:00
|
|
|
{
|
|
|
|
// Panels that are active
|
|
|
|
var usedPanels = {};
|
|
|
|
|
|
|
|
// If the selection is friendly units, add the command panels
|
|
|
|
var player = Engine.GetPlayerID();
|
|
|
|
if (entState.player == player || g_DevSettings.controlAll)
|
|
|
|
{
|
2010-09-28 16:19:13 +02:00
|
|
|
if (selection.length > 1)
|
2012-04-21 19:26:06 +02:00
|
|
|
setupUnitPanel(SELECTION, usedPanels, entState, g_Selection.groups.getTemplateNames(),
|
2010-09-28 16:19:13 +02:00
|
|
|
function (entType) { changePrimarySelectionGroup(entType); } );
|
|
|
|
|
2010-09-28 20:31:40 +02:00
|
|
|
var commands = getEntityCommandsList(entState);
|
|
|
|
if (commands.length)
|
2012-04-21 19:26:06 +02:00
|
|
|
setupUnitPanel(COMMAND, usedPanels, entState, commands,
|
2011-12-10 08:07:04 +01:00
|
|
|
function (item) { performCommand(entState.id, item.name); } );
|
2010-09-28 16:19:13 +02:00
|
|
|
|
2010-10-24 00:43:15 +02:00
|
|
|
if (entState.garrisonHolder)
|
|
|
|
{
|
|
|
|
var groups = new EntityGroups();
|
2012-08-16 03:15:04 +02:00
|
|
|
for (var i in selection)
|
|
|
|
{
|
|
|
|
state = GetEntityState(selection[i]);
|
|
|
|
if (state.garrisonHolder)
|
|
|
|
groups.add(state.garrisonHolder.entities)
|
|
|
|
}
|
|
|
|
|
2012-04-21 19:26:06 +02:00
|
|
|
setupUnitPanel(GARRISON, usedPanels, entState, groups.getTemplateNames(),
|
2012-08-16 03:15:04 +02:00
|
|
|
function (item) { unloadTemplate(item); } );
|
2010-10-24 00:43:15 +02:00
|
|
|
}
|
2010-10-13 23:40:56 +02:00
|
|
|
|
2012-05-04 01:32:10 +02:00
|
|
|
var formations = Engine.GuiInterfaceCall("GetAvailableFormations");
|
2012-03-18 22:16:30 +01:00
|
|
|
if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && !entState.garrisonHolder && formations.length)
|
2011-06-24 14:35:15 +02:00
|
|
|
{
|
2012-04-21 19:26:06 +02:00
|
|
|
setupUnitPanel(FORMATION, usedPanels, entState, formations,
|
2010-09-28 16:19:13 +02:00
|
|
|
function (item) { performFormation(entState.id, item); } );
|
2011-06-24 14:35:15 +02:00
|
|
|
}
|
2010-10-13 23:40:56 +02:00
|
|
|
|
2011-06-24 14:35:15 +02:00
|
|
|
// TODO: probably should load the stance list from a data file,
|
|
|
|
// and/or vary depending on what units are selected
|
2012-03-21 17:45:02 +01:00
|
|
|
var stances = ["violent", "aggressive", "passive", "defensive", "standground"];
|
2012-03-18 22:16:30 +01:00
|
|
|
if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && !entState.garrisonHolder && stances.length)
|
2011-06-24 14:35:15 +02:00
|
|
|
{
|
2012-04-21 19:26:06 +02:00
|
|
|
setupUnitPanel(STANCE, usedPanels, entState, stances,
|
2011-06-18 00:13:39 +02:00
|
|
|
function (item) { performStance(entState.id, item); } );
|
2011-06-24 14:35:15 +02:00
|
|
|
}
|
2011-06-18 00:13:39 +02:00
|
|
|
|
2011-11-24 16:43:32 +01:00
|
|
|
getGUIObjectByName("unitBarterPanel").hidden = !entState.barterMarket;
|
|
|
|
if (entState.barterMarket)
|
|
|
|
{
|
|
|
|
usedPanels["Barter"] = 1;
|
|
|
|
setupUnitBarterPanel(entState);
|
|
|
|
}
|
|
|
|
|
2012-04-21 22:10:11 +02:00
|
|
|
var buildableEnts = [];
|
|
|
|
var trainableEnts = [];
|
|
|
|
var state;
|
|
|
|
// Get all buildable and trainable entities
|
|
|
|
for (var i in selection)
|
2010-09-28 20:31:40 +02:00
|
|
|
{
|
2012-04-21 22:10:11 +02:00
|
|
|
if ((state = GetEntityState(selection[i])) && state.buildEntities && state.buildEntities.length)
|
|
|
|
buildableEnts = buildableEnts.concat(state.buildEntities);
|
|
|
|
if ((state = GetEntityState(selection[i])) && state.production && state.production.entities.length)
|
|
|
|
trainableEnts = trainableEnts.concat(state.production.entities);
|
2010-09-28 20:31:40 +02:00
|
|
|
}
|
2012-04-20 19:21:04 +02:00
|
|
|
|
2012-04-21 22:10:11 +02:00
|
|
|
// Remove duplicates
|
|
|
|
removeDupes(buildableEnts);
|
|
|
|
removeDupes(trainableEnts);
|
|
|
|
|
2012-07-19 23:46:35 +02:00
|
|
|
// Whether the GUI's right panel has been filled.
|
|
|
|
var rightUsed = true;
|
|
|
|
|
2012-07-16 06:12:48 +02:00
|
|
|
// The first selected entity's type has priority.
|
|
|
|
if (entState.buildEntities)
|
2012-04-21 22:10:11 +02:00
|
|
|
setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement);
|
2012-07-16 06:12:48 +02:00
|
|
|
else if (entState.production && entState.production.entities)
|
2012-04-21 22:10:11 +02:00
|
|
|
setupUnitPanel(TRAINING, usedPanels, entState, trainableEnts,
|
2012-04-21 02:21:01 +02:00
|
|
|
function (trainEntType) { addTrainingToQueue(selection, trainEntType); } );
|
2012-07-16 06:12:48 +02:00
|
|
|
else if (entState.trader)
|
|
|
|
setupUnitTradingPanel(usedPanels, entState, selection);
|
2012-07-30 01:08:15 +02:00
|
|
|
else if (!entState.foundation && entState.gate || hasClass(entState, "LongWall"))
|
2012-07-19 23:46:35 +02:00
|
|
|
{
|
|
|
|
// Allow long wall pieces to be converted to gates
|
|
|
|
var longWallTypes = {};
|
2012-07-30 01:08:15 +02:00
|
|
|
var walls = [];
|
|
|
|
var gates = [];
|
2012-07-19 23:46:35 +02:00
|
|
|
for (var i in selection)
|
|
|
|
{
|
2012-07-30 01:08:15 +02:00
|
|
|
state = GetEntityState(selection[i]);
|
|
|
|
if (hasClass(state, "LongWall") && !state.gate && !longWallTypes[state.template])
|
2012-07-19 23:46:35 +02:00
|
|
|
{
|
|
|
|
var gateTemplate = getWallGateTemplate(state.id);
|
|
|
|
if (gateTemplate)
|
|
|
|
{
|
|
|
|
var wallName = GetTemplateData(state.template).name.generic;
|
|
|
|
var gateName = GetTemplateData(gateTemplate).name.generic;
|
|
|
|
|
2012-07-30 01:08:15 +02:00
|
|
|
walls.push({
|
2012-07-19 23:46:35 +02:00
|
|
|
"tooltip": "Convert " + wallName + " to " + gateName,
|
2012-07-30 01:08:15 +02:00
|
|
|
"template": gateTemplate,
|
|
|
|
"callback": function (item) { transformWallToGate(item.template); }
|
2012-07-19 23:46:35 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// We only need one entity per type.
|
|
|
|
longWallTypes[state.template] = true;
|
|
|
|
}
|
2012-07-30 01:08:15 +02:00
|
|
|
else if (state.gate && !gates.length)
|
|
|
|
for (var j = 0; j < GATE_ACTIONS.length; ++j)
|
|
|
|
gates.push({
|
|
|
|
"gate": state.gate,
|
|
|
|
"tooltip": GATE_ACTIONS[j] + " gate",
|
|
|
|
"locked": j == 0,
|
|
|
|
"callback": function (item) { lockGate(item.locked); }
|
|
|
|
});
|
|
|
|
// Show both 'locked' and 'unlocked' as active if the selected gates have both lock states.
|
|
|
|
else if (state.gate && state.gate.locked != gates[0].gate.locked)
|
|
|
|
for (var j = 0; j < gates.length; ++j)
|
|
|
|
delete gates[j].gate.locked;
|
2012-07-19 23:46:35 +02:00
|
|
|
}
|
|
|
|
|
2012-07-30 01:08:15 +02:00
|
|
|
// Place wall conversion options after gate lock/unlock icons.
|
|
|
|
var items = gates.concat(walls);
|
2012-07-19 23:46:35 +02:00
|
|
|
if (items.length)
|
2012-07-30 01:08:15 +02:00
|
|
|
setupUnitPanel(GATE, usedPanels, entState, items);
|
2012-07-19 23:46:35 +02:00
|
|
|
else
|
|
|
|
rightUsed = false;
|
|
|
|
}
|
2012-07-16 06:12:48 +02:00
|
|
|
else
|
2012-07-19 23:46:35 +02:00
|
|
|
rightUsed = false;
|
|
|
|
|
|
|
|
if (!rightUsed)
|
2010-09-28 20:31:40 +02:00
|
|
|
{
|
2012-07-16 06:12:48 +02:00
|
|
|
// The right pane is empty. Fill the pane with a sane type.
|
|
|
|
// Prefer buildables for units and trainables for structures.
|
|
|
|
if (buildableEnts.length && (hasClass(entState, "Unit") || !trainableEnts.length))
|
|
|
|
setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement);
|
|
|
|
else if (trainableEnts.length)
|
|
|
|
setupUnitPanel(TRAINING, usedPanels, entState, trainableEnts,
|
|
|
|
function (trainEntType) { addTrainingToQueue(selection, trainEntType); } );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show technologies if the active panel has at most one row of icons.
|
|
|
|
if (entState.production && entState.production.technologies.length)
|
|
|
|
{
|
|
|
|
var activepane = usedPanels[CONSTRUCTION] ? buildableEnts.length : trainableEnts.length;
|
|
|
|
if (selection.length == 1 || activepane <= 8)
|
|
|
|
setupUnitPanel(RESEARCH, usedPanels, entState, entState.production.technologies,
|
|
|
|
function (researchType) { addResearchToQueue(entState.id, researchType); } );
|
2010-09-28 20:31:40 +02:00
|
|
|
}
|
2010-07-01 22:31:47 +02:00
|
|
|
|
2012-04-20 19:21:04 +02:00
|
|
|
if (entState.production && entState.production.queue.length)
|
2012-04-21 19:26:06 +02:00
|
|
|
setupUnitPanel(QUEUE, usedPanels, entState, entState.production.queue,
|
2012-04-20 19:21:04 +02:00
|
|
|
function (item) { removeFromProductionQueue(entState.id, item.id); } );
|
2012-06-11 03:07:41 +02:00
|
|
|
|
|
|
|
supplementalDetailsPanel.hidden = false;
|
|
|
|
commandsPanel.hidden = false;
|
|
|
|
}
|
|
|
|
else // owned by another player
|
|
|
|
{
|
2012-07-17 01:49:19 +02:00
|
|
|
supplementalDetailsPanel.hidden = true;
|
|
|
|
commandsPanel.hidden = true;
|
2010-07-01 22:31:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Hides / unhides Unit Panels (panels should be grouped by type, not by order, but we will leave that for another time)
|
|
|
|
var offset = 0;
|
|
|
|
for each (var panelName in g_unitPanels)
|
|
|
|
{
|
|
|
|
var panel = getGUIObjectByName("unit" + panelName + "Panel");
|
|
|
|
if (usedPanels[panelName])
|
|
|
|
panel.hidden = false;
|
|
|
|
else
|
|
|
|
panel.hidden = true;
|
|
|
|
}
|
|
|
|
}
|
2010-10-25 01:40:09 +02:00
|
|
|
|
|
|
|
// Force hide commands panels
|
|
|
|
function hideUnitCommands()
|
|
|
|
{
|
|
|
|
for each (var panelName in g_unitPanels)
|
|
|
|
getGUIObjectByName("unit" + panelName + "Panel").hidden = true;
|
2011-05-01 22:40:53 +02:00
|
|
|
}
|