1
0
forked from 0ad/0ad

Make selected stances and formations more obvious. Patch from leper, fixes #1190.

This was SVN commit r11386.
This commit is contained in:
Jonathan Waller 2012-03-21 16:45:02 +00:00
parent a957455647
commit 0d385f4112
16 changed files with 132 additions and 265 deletions

View File

@ -1,5 +0,0 @@
aggress,Aggress,
defend,Defend,
avoid,Avoid,
stand,Stand,
hold,Hold,

View File

@ -972,95 +972,6 @@
/>
</sprite>
<!--
==========================================
SESSION GUI - ICON SHEETS - STANCE
==========================================
-->
<sprite name="snIconSheetStance">
<image texture="session/icons/sheets/stance.dds"
cell_size="64 64"
size="0 0 100% 100%"
/>
</sprite>
<sprite name="snIconSheetStanceOver">
<effect add_color="42 42 42 0"/>
<image texture="session/icons/sheets/stance.dds"
cell_size="64 64"
size="0 0 100% 100%"
/>
</sprite>
<sprite name="snIconSheetStanceDisabled">
<effect grayscale=""/>
<image texture="session/icons/sheets/stance.dds"
cell_size="64 64"
size="0 0 100% 100%"
/>
</sprite>
<sprite name="snIconSheetStanceButton">
<image texture="session/icons/bkg/portrait.dds"
size="0 0 100% 100%"
/>
<image texture="session/icons/sheets/stance.dds"
cell_size="64 64"
size="0 0 100% 100%"
/>
</sprite>
<sprite name="snIconSheetStanceButtonOver">
<effect add_color="42 42 42 0"/>
<image texture="session/icons/bkg/portrait.dds"
size="0 0 100% 100%"
/>
<image texture="session/icons/sheets/stance.dds"
cell_size="64 64"
size="0 0 100% 100%"
/>
</sprite>
<sprite name="snIconSheetStanceButtonDisabled">
<effect grayscale=""/>
<image texture="session/icons/bkg/portrait.dds"
size="0 0 100% 100%"
/>
<image texture="session/icons/sheets/stance.dds"
cell_size="64 64"
size="0 0 100% 100%"
/>
</sprite>
<sprite name="snIconSheetStanceTabButton">
<image texture="session/icons/bkg/tab.dds"
size="0 0 100% 100%"
/>
<image texture="session/icons/sheets/stance.dds"
cell_size="64 64"
size="0 0 100% 100%"
/>
</sprite>
<sprite name="snIconSheetStanceTabButtonOver">
<image texture="session/icons/bkg/tab.dds"
size="0 0 100% 100%"
/>
<image
texture="session/icons/sheets/stance.dds"
cell_size="64 64"
size="0 0 100% 100%"
>
<effect add_color="42 42 42 0"/>
</image>
</sprite>
<sprite name="snIconSheetStanceTabButtonDisabled">
<effect grayscale=""/>
<image texture="session/icons/bkg/tab.dds"
size="0 0 100% 100%"
/>
<image texture="session/icons/sheets/stance.dds"
cell_size="64 64"
size="0 0 100% 100%"
/>
</sprite>
<!--
==========================================
SESSION GUI - ICON SHEETS - STATISTIC

View File

@ -593,10 +593,10 @@
<!-- Stats -->
<object size="8 36 50%-48 100%" name="statsArea" type="image">
<!-- Attack icon -->
<object hidden="true" size="0 0 48 48" type="image" name="attackIcon" sprite="snIconSheetStance" cell_id="1" tooltip_style="sessionToolTip"/>
<object hidden="true" size="0 0 48 48" type="image" name="attackIcon" sprite="stretched:session/icons/single/stance-aggressive.png" tooltip_style="sessionToolTip"/>
<!-- Armour icon "0 48 48 96"-->
<object size="0 0 48 48" type="image" name="armourIcon" sprite="snIconSheetStance" cell_id="3" tooltip_style="sessionToolTip"/>
<object size="0 0 48 48" type="image" name="armourIcon" sprite="stretched:session/icons/single/stance-defensive.png" tooltip_style="sessionToolTip"/>
<!-- Resource carrying icon/counter -->
<object size="0 40 48 88" type="image" name="resourceCarryingIcon" style="resourceIcon"/>

View File

@ -17,33 +17,6 @@
/>
</sprite>
<!-- ================================ ================================ -->
<!-- Unit Command Icons -->
<!-- ================================ ================================ -->
<sprite name="formation">
<image
texture="session/icons/sheets/formation_select.png"
cell_size="64 64"
size="0 0 100% 100%"
/>
</sprite>
<sprite name="formation_disabled">
<image
texture="session/icons/sheets/formation_nonselect.png"
cell_size="64 64"
size="0 0 100% 100%"
/>
</sprite>
<sprite name="commands">
<image
texture="session/icons/sheets/commands.png"
cell_size="32 32"
size="0 0 100% 100%"
/>
</sprite>
<!-- ================================ ================================ -->
<!-- Menu -->
<!-- ================================ ================================ -->

View File

@ -304,24 +304,47 @@ function setupUnitPanel(guiName, usedPanels, unitEntState, items, callback)
// Get icon image
if (guiName == "Formation")
{
icon.cell_id = getFormationCellId(item);
var formationOk = Engine.GuiInterfaceCall("CanMoveEntsIntoFormation", {
"ents": g_Selection.toList(),
"formationName": item
});
icon.enabled = formationOk;
button.enabled = formationOk;
if (!icon.enabled)
{
icon.sprite = "formation_disabled";
button.tooltip += " (disabled)";
}
else
{
icon.sprite = "formation";
}
}
if (!formationOk)
{
icon.sprite = "stretched:session/icons/formations/formation-"+item.replace(/\s+/,'').toLowerCase()+".png";
// 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.";
}
}
else
{
var formationSelected = Engine.GuiInterfaceCall("IsFormationSelected", {
"ents": g_Selection.toList(),
"formationName": item
});
if (formationSelected)
icon.sprite = "stretched:session/icons/formations/formation-"+item.replace(/\s+/,'').toLowerCase()+"-selected.png";
else
icon.sprite = "stretched:session/icons/formations/formation-"+item.replace(/\s+/,'').toLowerCase()+"-available.png";
}
}
else if (guiName == "Stance")
{
var stanceSelected = Engine.GuiInterfaceCall("IsStanceSelected", {
@ -329,16 +352,13 @@ function setupUnitPanel(guiName, usedPanels, unitEntState, items, callback)
"stance": item
});
icon.cell_id = i;
if (stanceSelected)
icon.sprite = "snIconSheetStanceButton";
icon.sprite = "stretched:session/icons/single/stance-"+item+"-select.png";
else
icon.sprite = "snIconSheetStanceButtonDisabled";
icon.sprite = "stretched:session/icons/single/stance-"+item+".png";
}
else if (guiName == "Command")
{
//icon.cell_id = i;
//icon.cell_id = getCommandCellId(item);
icon.sprite = "stretched:session/icons/single/" + item.icon;
}
@ -520,7 +540,7 @@ function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, s
// TODO: probably should load the stance list from a data file,
// and/or vary depending on what units are selected
var stances = ["violent", "aggressive", "passive", "defensive", "stand"];
var stances = ["violent", "aggressive", "passive", "defensive", "standground"];
if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && !entState.garrisonHolder && stances.length)
{
setupUnitPanel("Stance", usedPanels, entState, stances,

View File

@ -121,41 +121,6 @@ function damageTypesToText(dmg)
return dmgArray.join("[font=\"serif-12\"], [/font]");
}
function getFormationCellId(formationName)
{
switch (formationName)
{
case "Loose":
return 0;
case "Box":
return 1;
case "Column Closed":
return 2;
case "Line Closed":
return 3;
case "Column Open":
return 4;
case "Line Open":
return 5;
case "Flank":
return 6;
case "Skirmish":
return 7;
case "Wedge":
return 8;
case "Testudo":
return 9;
case "Phalanx":
return 10;
case "Syntagma":
return 11;
case "Formation12":
return 12;
default:
return -1;
}
}
function getEntityFormationsList(entState)
{
var civ = g_Players[entState.player].civ;
@ -167,7 +132,7 @@ function getCivFormations(civ)
{
// TODO: this should come from the civ JSON files instead
var civFormations = ["Loose", "Box", "Column Closed", "Line Closed", "Column Open", "Line Open", "Flank", "Skirmish", "Wedge", "Formation12"];
var civFormations = ["Scatter", "Box", "Column Closed", "Line Closed", "Column Open", "Line Open", "Flank", "Skirmish", "Wedge", "Battle Line"];
if (civ == "hele")
{
civFormations.push("Phalanx");

View File

@ -271,7 +271,7 @@ Formation.prototype.ComputeFormationOffsets = function(active, columnar)
cols = 6;
shape = "opensquare";
}
else if (this.formationName == "Loose")
else if (this.formationName == "Scatter")
{
var width = Math.sqrt(count) * separation * 5;
@ -418,7 +418,7 @@ Formation.prototype.ComputeFormationOffsets = function(active, columnar)
var cols = Math.ceil(Math.sqrt(count));
shape = "square";
}
else if (this.formationName == "Formation12")
else if (this.formationName == "Battle Line")
{
if (count <= 5)
cols = count;

View File

@ -362,11 +362,32 @@ GuiInterface.prototype.GetNextNotification = function()
return "";
};
GuiInterface.prototype.GetFormationRequirements = function(player, data)
{
return GetFormationRequirements(data.formationName);
};
GuiInterface.prototype.CanMoveEntsIntoFormation = function(player, data)
{
return CanMoveEntsIntoFormation(data.ents, data.formationName);
};
GuiInterface.prototype.IsFormationSelected = function(player, data)
{
for each (var ent in data.ents)
{
var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
if (cmpUnitAI)
{
// GetLastFormationName is named in a strange way as it (also) is
// the value of the current formation (see Formation.js LoadFormation)
if (cmpUnitAI.GetLastFormationName() == data.formationName)
return true;
}
}
return false;
};
GuiInterface.prototype.IsStanceSelected = function(player, data)
{
for each (var ent in data.ents)
@ -783,7 +804,9 @@ var exposedFunctions = {
"GetTemplateData": 1,
"GetNextNotification": 1,
"GetFormationRequirements": 1,
"CanMoveEntsIntoFormation": 1,
"IsFormationSelected": 1,
"IsStanceSelected": 1,
"SetSelectionHighlight": 1,

View File

@ -57,7 +57,7 @@ Identity.prototype.Schema =
"</element>" +
"</optional>" +
"<optional>" +
"<element name='Formations' a:help='Optional list of space-separated formations this unit is allowed to use. Choices include: Loose, Box, ColumnClosed, LineClosed, ColumnOpen, LineOpen, Flank, Skirmish, Wedge, Testudo, Phalanx, Syntagma, Formation12'>" +
"<element name='Formations' a:help='Optional list of space-separated formations this unit is allowed to use. Choices include: Scatter, Box, ColumnClosed, LineClosed, ColumnOpen, LineOpen, Flank, Skirmish, Wedge, Testudo, Phalanx, Syntagma, BattleLine'>" +
"<attribute name='datatype'>" +
"<value>tokens</value>" +
"</attribute>" +

View File

@ -9,7 +9,7 @@ UnitAI.prototype.Schema =
"<value>aggressive</value>" +
"<value>defensive</value>" +
"<value>passive</value>" +
"<value>stand</value>" +
"<value>standground</value>" +
"</choice>" +
"</element>" +
"<element name='FormationController'>" +
@ -98,7 +98,7 @@ var g_Stances = {
respondStandGround: false,
respondHoldGround: false,
},
"stand": {
"standground": {
targetVisibleEnemies: true,
targetAttackers: true,
respondFlee: false,
@ -2543,7 +2543,7 @@ UnitAI.prototype.SwitchToStance = function(stance)
this.SetStance(stance);
// Stop moving if switching to stand ground
// TODO: Also stop existing orders in a sensible way
if (stance == "stand")
if (stance == "standground")
this.StopMoving();
// Reset the range query, since the range depends on stance

View File

@ -592,92 +592,83 @@ function GetFormationUnitAIs(ents)
}
else
{
cmpFormation.LoadFormation("Loose");
cmpFormation.LoadFormation("Scatter");
}
}
return nonformedUnitAIs.concat(Engine.QueryInterface(formationEnt, IID_UnitAI));
}
function GetFormationRequirements(formationName)
{
var countRequired = 1;
var classesRequired;
switch(formationName)
{
case "Scatter":
case "Column Closed":
case "Line Closed":
case "Column Open":
case "Line Open":
case "Battle Line":
break;
case "Box":
countRequired = 4;
break;
case "Flank":
countRequired = 8;
break;
case "Skirmish":
classesRequired = ["Ranged"];
break;
case "Wedge":
countRequired = 3;
classesRequired = ["Cavalry"];
break;
case "Phalanx":
countRequired = 10;
classesRequired = ["Melee", "Infantry"];
break;
case "Syntagma":
countRequired = 9;
classesRequired = ["Melee", "Infantry"]; // TODO: pike only
break;
case "Testudo":
countRequired = 9;
classesRequired = ["Melee", "Infantry"];
break;
default:
// We encountered a unknown formation -> warn the user
warn("Commands.js: GetFormationRequirements: unknown formation: " + formationName);
return false;
}
return { "count": countRequired, "classesRequired": classesRequired };
}
function CanMoveEntsIntoFormation(ents, formationName)
{
var count = ents.length;
var classesRequired;
// TODO: should check the player's civ is allowed to use this formation
if (formationName == "Loose")
{
return true;
}
else if (formationName == "Box")
{
if (count < 4)
return false;
}
else if (formationName == "Column Closed")
{
}
else if (formationName == "Line Closed")
{
}
else if (formationName == "Column Open")
{
}
else if (formationName == "Line Open")
{
}
else if (formationName == "Flank")
{
if (count < 8)
return false;
}
else if (formationName == "Skirmish")
{
classesRequired = ["Ranged"];
}
else if (formationName == "Wedge")
{
if (count < 3)
return false;
classesRequired = ["Cavalry"];
}
else if (formationName == "Formation12")
{
}
else if (formationName == "Phalanx")
{
if (count < 10)
return false;
classesRequired = ["Melee", "Infantry"];
}
else if (formationName == "Syntagma")
{
if (count < 9)
return false;
classesRequired = ["Melee", "Infantry"]; // TODO: pike only
}
else if (formationName == "Testudo")
{
if (count < 9)
return false;
classesRequired = ["Melee", "Infantry"];
}
else
{
var requirements = GetFormationRequirements(formationName);
if (!requirements)
return false;
if (count < requirements.count)
return false;
}
var looseOnlyUnits = true;
var scatterOnlyUnits = true;
for each (var ent in ents)
{
var cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
if (cmpIdentity)
{
var classes = cmpIdentity.GetClassesList();
if (looseOnlyUnits && (classes.indexOf("Worker") == -1 || classes.indexOf("Support") == -1))
looseOnlyUnits = false;
for each (var classRequired in classesRequired)
if (scatterOnlyUnits && (classes.indexOf("Worker") == -1 || classes.indexOf("Support") == -1))
scatterOnlyUnits = false;
for each (var classRequired in requirements.classesRequired)
{
if (classes.indexOf(classRequired) == -1)
{
@ -687,7 +678,7 @@ function CanMoveEntsIntoFormation(ents, formationName)
}
}
if (looseOnlyUnits)
if (scatterOnlyUnits)
return false;
return true;
@ -711,5 +702,6 @@ function FilterEntityList(entities, player, controlAll)
return entities.filter(function(ent) { return CanControlUnit(ent, player, controlAll);} );
}
Engine.RegisterGlobal("GetFormationRequirements", GetFormationRequirements);
Engine.RegisterGlobal("CanMoveEntsIntoFormation", CanMoveEntsIntoFormation);
Engine.RegisterGlobal("ProcessCommand", ProcessCommand);

View File

@ -37,7 +37,7 @@
<GenericName>Unit</GenericName>
<Classes datatype="tokens">Unit ConquestCritical</Classes>
<Formations datatype="tokens">
Loose
Scatter
Box
ColumnClosed
LineClosed
@ -49,7 +49,7 @@
Testudo
Phalanx
Syntagma
Formation12
BattleLine
</Formations>
</Identity>
<Looter/>