Adjusts unit selection behavior to account for ranks. Triple-click now selects units regardless of their rank.
Adds modifier hotkey to select units offscreen. Fixes #826. This was SVN commit r9443.
This commit is contained in:
parent
f423e269e2
commit
26de01cdd1
@ -134,6 +134,7 @@ hotkey.console.paste = "Ctrl+V" ; Paste clipboard to console
|
||||
hotkey.selection.add = Shift ; Add units to selection
|
||||
hotkey.selection.remove = Ctrl ; Remove units from selection
|
||||
hotkey.selection.idle = Period ; Select next idle unit
|
||||
hotkey.selection.offscreen = Alt ; Include offscreen units in selection
|
||||
hotkey.selection.group.select.0 = 0
|
||||
hotkey.selection.group.save.0 = "Ctrl+0"
|
||||
hotkey.selection.group.add.0 = "Shift+0"
|
||||
|
@ -726,7 +726,9 @@ function handleInputAfterGui(ev)
|
||||
return true;
|
||||
}
|
||||
|
||||
var onScreenOnly;
|
||||
var showOffscreen = Engine.HotkeyIsPressed("selection.offscreen");
|
||||
var matchRank;
|
||||
var templateToMatch;
|
||||
var selectedEntity = ents[0];
|
||||
var now = new Date();
|
||||
|
||||
@ -738,20 +740,20 @@ function handleInputAfterGui(ev)
|
||||
if (!doubleClicked)
|
||||
{
|
||||
// If double click hasn't already occurred, this is a double click.
|
||||
// Select only similar on-screen units
|
||||
onScreenOnly = true;
|
||||
// Select units matching exact rank
|
||||
templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).template;
|
||||
matchRank = true;
|
||||
doubleClicked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Double click has already occurred, so this is a triple click.
|
||||
// Select all similar units whether they are on-screen or not
|
||||
onScreenOnly = false;
|
||||
// Select all similar units regardless of rank
|
||||
templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).identity.selectionGroupName;
|
||||
matchRank = false;
|
||||
}
|
||||
|
||||
var templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).template;
|
||||
|
||||
ents = Engine.PickSimilarFriendlyEntities(templateToMatch, onScreenOnly);
|
||||
ents = Engine.PickSimilarFriendlyEntities(templateToMatch, showOffscreen, matchRank);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -119,7 +119,8 @@ GuiInterface.prototype.GetEntityState = function(player, ent)
|
||||
{
|
||||
ret.identity = {
|
||||
"rank": cmpIdentity.GetRank(),
|
||||
"classes": cmpIdentity.GetClassesList()
|
||||
"classes": cmpIdentity.GetClassesList(),
|
||||
"selectionGroupName": cmpIdentity.GetSelectionGroupName()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -139,4 +139,9 @@ Identity.prototype.HasClass = function(name)
|
||||
return this.GetClassesList().indexOf(name) != -1;
|
||||
};
|
||||
|
||||
Identity.prototype.GetSelectionGroupName = function()
|
||||
{
|
||||
return (this.template.SelectionGroupName || "");
|
||||
}
|
||||
|
||||
Engine.RegisterComponentType(IID_Identity, "Identity", Identity);
|
||||
|
@ -1 +0,0 @@
|
||||
Engine.RegisterInterface("Identity");
|
@ -2,6 +2,7 @@
|
||||
<Entity parent="template_unit_cavalry_melee_spearman">
|
||||
<Identity>
|
||||
<Civ>iber</Civ>
|
||||
<SelectionGroupName>units/iber_cavalry_spearman_b</SelectionGroupName>
|
||||
<SpecificName>Epones</SpecificName>
|
||||
<Icon>units/iber_cavalry_spearman.png</Icon>
|
||||
<History>Armed like the light infantry, Iberian cavalry were often pursued as mercenaries, especially by the Carthaginians. Mounted on excellent horses and wielding high-grade swords they were capable of taking on heavy or light cavalry. As with all Iberians armor was scarce, but they wore the ubiquitous sinew caps made famous by the peoples of the peninsula.</History>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<Entity parent="template_unit_infantry_ranged_javelinist">
|
||||
<Identity>
|
||||
<Civ>iber</Civ>
|
||||
<SelectionGroupName>units/iber_infantry_javelinist_b</SelectionGroupName>
|
||||
<SpecificName>Caetrati Lusitano</SpecificName>
|
||||
<History>Iberians, especially the Lusitanians, were good at ranged combat and ambushing enemy columns. They throw heavy iron javelins and sometimes even add burning pitch to them, making them good as a cheap siege weapon.</History>
|
||||
<Icon>units/cart_cavalry_javelinist.png</Icon>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<Entity parent="template_unit_infantry_ranged_slinger">
|
||||
<Identity>
|
||||
<Civ>iber</Civ>
|
||||
<SelectionGroupName>units/iber_infantry_slinger_b</SelectionGroupName>
|
||||
<SpecificName>Karsken</SpecificName>
|
||||
<Icon>units/iber_infantry_slinger.png</Icon>
|
||||
<History>Iberian slingers were the undisputed masters of the weapon and extracted a high toll of the enemy. Going into combat scantily clad at best, the slinger carried three slings tied around his waist, each of a different length allowing him to attack opponents from all ranges. Unlike other cultures, the Iberian slingers threw rocks instead of specially made lead shot.</History>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<Entity parent="template_unit_infantry_melee_spearman">
|
||||
<Identity>
|
||||
<Civ>iber</Civ>
|
||||
<SelectionGroupName>units/iber_infantry_spearman_b</SelectionGroupName>
|
||||
<SpecificName>Scutari</SpecificName>
|
||||
<Icon>units/iber_infantry_spearman.png</Icon>
|
||||
<History>A long-bladed spear was a chief melee weapon of the Iberian infantry, often used after the javelins had been thrown. Typically carried by infantry known as scutarii for their long oval body shields, the spearmen would close in formation to attack their opponents. Usually lightly armored, they were quick and had a ferocious reputation.</History>
|
||||
|
@ -2,6 +2,7 @@
|
||||
<Entity parent="template_unit_infantry_melee_swordsman">
|
||||
<Identity>
|
||||
<Civ>iber</Civ>
|
||||
<SelectionGroupName>units/iber_infantry_swordsman_b</SelectionGroupName>
|
||||
<SpecificName>Caetrati</SpecificName>
|
||||
<Icon>units/iber_infantry_swordsman.png</Icon>
|
||||
<History>The Iberians were master sword-smiths and the falcata was their greatest creation. Wielded by superb swordsmen equipped with light armor and a buckler known as a caetra, they caused untold carnage. Thanks to this Iberian infantry were fast and agile unlike many of their opponents and could bite hard when they attacked. Their skill with sword and buckler were legendary, allowing them to go toe-to-toe with heavy infantry.</History>
|
||||
|
@ -133,9 +133,9 @@ std::vector<entity_id_t> PickFriendlyEntitiesInRect(void* UNUSED(cbdata), int x0
|
||||
return EntitySelection::PickEntitiesInRect(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), x0, y0, x1, y1, player);
|
||||
}
|
||||
|
||||
std::vector<entity_id_t> PickSimilarFriendlyEntities(void* UNUSED(cbdata), std::string templateName, bool onScreenOnly)
|
||||
std::vector<entity_id_t> PickSimilarFriendlyEntities(void* UNUSED(cbdata), std::string templateName, bool includeOffScreen, bool matchRank)
|
||||
{
|
||||
return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, g_Game->GetPlayerID(), onScreenOnly);
|
||||
return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, g_Game->GetPlayerID(), includeOffScreen, matchRank);
|
||||
}
|
||||
|
||||
CFixedVector3D GetTerrainAtPoint(void* UNUSED(cbdata), int x, int y)
|
||||
@ -465,7 +465,7 @@ void GuiScriptingInit(ScriptInterface& scriptInterface)
|
||||
// Entity picking
|
||||
scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, &PickEntitiesAtPoint>("PickEntitiesAtPoint");
|
||||
scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, int, int, int, int, &PickFriendlyEntitiesInRect>("PickFriendlyEntitiesInRect");
|
||||
scriptInterface.RegisterFunction<std::vector<entity_id_t>, std::string, bool, &PickSimilarFriendlyEntities>("PickSimilarFriendlyEntities");
|
||||
scriptInterface.RegisterFunction<std::vector<entity_id_t>, std::string, bool, bool, &PickSimilarFriendlyEntities>("PickSimilarFriendlyEntities");
|
||||
scriptInterface.RegisterFunction<CFixedVector3D, int, int, &GetTerrainAtPoint>("GetTerrainAtPoint");
|
||||
|
||||
// Network / game setup functions
|
||||
|
@ -76,6 +76,9 @@ COMPONENT(Footprint)
|
||||
INTERFACE(GuiInterface)
|
||||
COMPONENT(GuiInterfaceScripted)
|
||||
|
||||
INTERFACE(Identity)
|
||||
COMPONENT(IdentityScripted)
|
||||
|
||||
INTERFACE(Minimap)
|
||||
COMPONENT(Minimap)
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "graphics/Camera.h"
|
||||
#include "simulation2/Simulation2.h"
|
||||
#include "simulation2/components/ICmpIdentity.h"
|
||||
#include "simulation2/components/ICmpOwnership.h"
|
||||
#include "simulation2/components/ICmpRangeManager.h"
|
||||
#include "simulation2/components/ICmpTemplateManager.h"
|
||||
@ -132,17 +133,38 @@ std::vector<entity_id_t> EntitySelection::PickEntitiesInRect(CSimulation2& simul
|
||||
return hitEnts;
|
||||
}
|
||||
|
||||
std::vector<entity_id_t> EntitySelection::PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, const std::string& templateName, int owner, bool onScreenOnly)
|
||||
std::vector<entity_id_t> EntitySelection::PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, const std::string& templateName, int owner, bool includeOffScreen, bool matchRank)
|
||||
{
|
||||
CmpPtr<ICmpTemplateManager> cmpTemplateManager(simulation, SYSTEM_ENTITY);
|
||||
CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY);
|
||||
|
||||
std::vector<entity_id_t> hitEnts;
|
||||
|
||||
std::vector<entity_id_t> entities = cmpTemplateManager->GetEntitiesUsingTemplate(templateName);
|
||||
for (std::vector<entity_id_t>::iterator it = entities.begin(); it != entities.end(); ++it)
|
||||
{
|
||||
entity_id_t ent = *it;
|
||||
const CSimulation2::InterfaceListUnordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable);
|
||||
for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it)
|
||||
{
|
||||
entity_id_t ent = it->first;
|
||||
|
||||
CmpPtr<ICmpIdentity> cmpIdentity(simulation.GetSimContext(), ent);
|
||||
|
||||
std::string groupName;
|
||||
if (!cmpIdentity.null())
|
||||
{
|
||||
groupName = cmpIdentity->GetSelectionGroupName();
|
||||
}
|
||||
|
||||
if (!matchRank && !groupName.empty())
|
||||
{
|
||||
// There's a selection group so match that
|
||||
if (groupName.compare(templateName) != 0)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fall back to exact template name matching
|
||||
if (cmpTemplateManager->GetCurrentTemplateName(ent).compare(templateName) != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld)
|
||||
// In this case, the checking is done to avoid selecting garrisoned units
|
||||
@ -154,7 +176,8 @@ std::vector<entity_id_t> EntitySelection::PickSimilarEntities(CSimulation2& simu
|
||||
if (cmpOwnership.null() || cmpOwnership->GetOwner() != owner)
|
||||
continue;
|
||||
|
||||
if (onScreenOnly)
|
||||
// Ignore off screen entities
|
||||
if (!includeOffScreen)
|
||||
{
|
||||
// Find the current interpolated model position.
|
||||
CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent);
|
||||
|
@ -49,10 +49,12 @@ std::vector<entity_id_t> PickEntitiesInRect(CSimulation2& simulation, const CCam
|
||||
|
||||
/**
|
||||
* Finds all entities with the given entity template name, that belong to player @p owner.
|
||||
* If @p onScreenOnly then only entities visible on the screen will be selected,
|
||||
* else all entities visible in the world will be selected.
|
||||
* If @p includeOffScreen then all entities visible in the world will be selected,
|
||||
* else only entities visible on the screen will be selected.
|
||||
* If @p matchRank then only entities that exactly match @p templateName will be selected,
|
||||
* else entities with matching SelectionGroupName will be selected.
|
||||
*/
|
||||
std::vector<entity_id_t> PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, const std::string& templateName, int owner, bool onScreenOnly);
|
||||
std::vector<entity_id_t> PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, const std::string& templateName, int owner, bool includeOffScreen, bool matchRank);
|
||||
|
||||
} // namespace
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user