Changed: Target command to support keyword search.
--HG-- branch : develop
This commit is contained in:
parent
3a5bb966a8
commit
4a31913c60
4 changed files with 120 additions and 68 deletions
|
@ -78,17 +78,11 @@
|
||||||
|
|
||||||
<command name="self" action="self_target" params="" />
|
<command name="self" action="self_target" params="" />
|
||||||
|
|
||||||
<command name="target" action="target" params="entity=$" />
|
<command name="target" action="target" params="entity=+" ctrlchar="false" />
|
||||||
<command name="tar" action="target" params="entity=$" />
|
<command name="tar" action="target" params="entity=+" ctrlchar="false" />
|
||||||
|
|
||||||
<command name="target_quiet" action="target" params="entity=$|quiet=true" />
|
<command name="target_quiet" action="target" params="entity=+|quiet=true" ctrlchar="false" />
|
||||||
<command name="tarq" action="target" params="entity=$|quiet=true" />
|
<command name="tarq" action="target" params="entity=+|quiet=true" ctrlchar="false" />
|
||||||
|
|
||||||
<command name="target" action="target" params="entity=$|prefer_complete_match=$" />
|
|
||||||
<command name="tar" action="target" params="entity=$|prefer_complete_match=$" />
|
|
||||||
|
|
||||||
<command name="target_quiet" action="target" params="entity=$|prefer_complete_match=$|quiet=true" />
|
|
||||||
<command name="tarq" action="target" params="entity=$|prefer_complete_match=$|quiet=true" />
|
|
||||||
|
|
||||||
<command name="target" action="no_target" params="" />
|
<command name="target" action="no_target" params="" />
|
||||||
<command name="tar" action="no_target" params="" />
|
<command name="tar" action="no_target" params="" />
|
||||||
|
|
|
@ -2334,7 +2334,63 @@ CEntityCL *CEntityManager::getEntityByName (uint32 stringId) const
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
|
CEntityCL *CEntityManager::getEntityByKeywords (const std::vector<ucstring> &keywords, bool onlySelectable) const
|
||||||
|
{
|
||||||
|
if (keywords.empty()) return NULL;
|
||||||
|
|
||||||
|
std::vector<ucstring> lcKeywords;
|
||||||
|
lcKeywords.resize(keywords.size());
|
||||||
|
for(uint k = 0; k < keywords.size(); k++)
|
||||||
|
{
|
||||||
|
lcKeywords[k] = toLower(keywords[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NLMISC::CVectorD &userPosD = UserEntity->pos();
|
||||||
|
const uint count = (uint)_Entities.size();
|
||||||
|
uint selectedEntityId = 0;
|
||||||
|
float selectedEntityDist = FLT_MAX;
|
||||||
|
for(uint i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
if (!_Entities[i]) continue;
|
||||||
|
|
||||||
|
if (onlySelectable && !_Entities[i]->properties().selectable()) continue;
|
||||||
|
|
||||||
|
ucstring lcName;
|
||||||
|
lcName = toLower(_Entities[i]->getDisplayName());
|
||||||
|
if (lcName.empty()) continue;
|
||||||
|
|
||||||
|
bool match = true;
|
||||||
|
for (uint k = 0; k < lcKeywords.size(); ++k)
|
||||||
|
{
|
||||||
|
if (lcName.find(lcKeywords[k]) == ucstring::npos)
|
||||||
|
{
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match)
|
||||||
|
{
|
||||||
|
const NLMISC::CVectorD &targetPosD = _Entities[i]->pos();
|
||||||
|
|
||||||
|
float deltaX = (float) targetPosD.x - (float) userPosD.x;
|
||||||
|
float deltaY = (float) targetPosD.y - (float) userPosD.y;
|
||||||
|
float dist = (float)sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||||
|
if (dist < selectedEntityDist)
|
||||||
|
{
|
||||||
|
selectedEntityDist = dist;
|
||||||
|
selectedEntityId = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedEntityDist != FLT_MAX)
|
||||||
|
return _Entities[selectedEntityId];
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------
|
||||||
CEntityCL *CEntityManager::getEntityByName (const ucstring &name, bool caseSensitive, bool complete) const
|
CEntityCL *CEntityManager::getEntityByName (const ucstring &name, bool caseSensitive, bool complete) const
|
||||||
{
|
{
|
||||||
ucstring source = name;
|
ucstring source = name;
|
||||||
|
|
|
@ -302,6 +302,12 @@ public:
|
||||||
* \param complete : if true, the name must match the full name of the entity.
|
* \param complete : if true, the name must match the full name of the entity.
|
||||||
*/
|
*/
|
||||||
CEntityCL *getEntityByName (const ucstring &name, bool caseSensitive, bool complete) const;
|
CEntityCL *getEntityByName (const ucstring &name, bool caseSensitive, bool complete) const;
|
||||||
|
/**
|
||||||
|
* Case insensitive match against entity name. All listed keywords must match.
|
||||||
|
* \param keywords to match
|
||||||
|
* \param onlySelectable : if true, match only entity that can be selected
|
||||||
|
*/
|
||||||
|
CEntityCL *getEntityByKeywords (const std::vector<ucstring> &keywords, bool onlySelectable) const;
|
||||||
CEntityCL *getEntityBySheetName (const std::string &sheet) const;
|
CEntityCL *getEntityBySheetName (const std::string &sheet) const;
|
||||||
/// Get an entity by dataset index. Returns NULL if the entity is not found.
|
/// Get an entity by dataset index. Returns NULL if the entity is not found.
|
||||||
CEntityCL *getEntityByCompressedIndex(TDataSetIndex compressedIndex) const;
|
CEntityCL *getEntityByCompressedIndex(TDataSetIndex compressedIndex) const;
|
||||||
|
|
|
@ -2416,70 +2416,66 @@ class CAHTarget : public IActionHandler
|
||||||
{
|
{
|
||||||
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
|
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
|
||||||
{
|
{
|
||||||
// Get the entity name to target
|
|
||||||
ucstring entityName;
|
ucstring entityName;
|
||||||
entityName.fromUtf8 (getParam (Params, "entity"));
|
entityName.fromUtf8(getParam(Params, "entity"));
|
||||||
bool preferCompleteMatch = (getParam (Params, "prefer_complete_match") != "0");
|
if (entityName.empty()) return;
|
||||||
|
|
||||||
|
string completeMatch = getParam(Params, "prefer_complete_match");
|
||||||
bool quiet = (getParam (Params, "quiet") == "true");
|
bool quiet = (getParam (Params, "quiet") == "true");
|
||||||
|
|
||||||
if (!entityName.empty())
|
vector<ucstring> keywords;
|
||||||
|
NLMISC::splitUCString(entityName, ucstring(" "), keywords);
|
||||||
|
if (!keywords.empty() && keywords[0].size() > 0 && keywords[0][0] == (ucchar)'"')
|
||||||
{
|
{
|
||||||
CEntityCL *entity = NULL;
|
// entity name is in quotes, do old style match with 'starts with' filter
|
||||||
if (preferCompleteMatch)
|
// search for optional second parameter from old command for prefer_complete_match param
|
||||||
{
|
keywords.clear();
|
||||||
// Try to get the entity with complete match first
|
|
||||||
entity = EntitiesMngr.getEntityByName (entityName, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity == NULL)
|
|
||||||
{
|
|
||||||
// Get the entity with a partial match
|
|
||||||
entity = EntitiesMngr.getEntityByName (entityName, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity == NULL)
|
ucstring::size_type lastOf = entityName.rfind(ucstring("\""));
|
||||||
{
|
if (lastOf == 0)
|
||||||
//Get the entity with a sheetName
|
lastOf = ucstring::npos;
|
||||||
entity = EntitiesMngr.getEntityBySheetName(entityName.toUtf8());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity)
|
|
||||||
{
|
|
||||||
CCharacterCL *character = dynamic_cast<CCharacterCL*>(entity);
|
|
||||||
if (character != NULL)
|
|
||||||
{
|
|
||||||
if(character->isSelectableBySpace())
|
|
||||||
{
|
|
||||||
nldebug("isSelectableBySpace");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nldebug("is not isSelectableBySpace");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(entity->properties().selectable())
|
|
||||||
{
|
|
||||||
nldebug("is prop selectable");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// to avoid campfire selection exploit #316
|
|
||||||
nldebug("is not prop selectable");
|
|
||||||
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
|
||||||
if(!quiet)
|
|
||||||
pIM->displaySystemInfo(CI18N::get("uiTargetErrorCmd"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select the entity
|
// override the value only when there is no 'prefer_complete_match' parameter set
|
||||||
UserEntity->selection(entity->slot());
|
if (completeMatch.empty() && lastOf < entityName.size())
|
||||||
}
|
completeMatch = trim(entityName.substr(lastOf+1).toUtf8());
|
||||||
else
|
|
||||||
{
|
entityName = entityName.substr(1, lastOf-1);
|
||||||
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
}
|
||||||
if(!quiet)
|
|
||||||
pIM->displaySystemInfo(CI18N::get("uiTargetErrorCmd"));
|
// late check because only possible if doing 'starts-with' search
|
||||||
}
|
bool preferCompleteMatch = (completeMatch != "0");
|
||||||
|
|
||||||
|
CEntityCL *entity = NULL;
|
||||||
|
if (preferCompleteMatch)
|
||||||
|
{
|
||||||
|
// Try to get the entity with complete match first
|
||||||
|
entity = EntitiesMngr.getEntityByName (entityName, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity == NULL && !keywords.empty())
|
||||||
|
{
|
||||||
|
entity = EntitiesMngr.getEntityByKeywords(keywords, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity == NULL)
|
||||||
|
{
|
||||||
|
// Get the entity with a partial match using 'starts with' search
|
||||||
|
entity = EntitiesMngr.getEntityByName(entityName, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity == NULL)
|
||||||
|
{
|
||||||
|
//Get the entity with a sheetName
|
||||||
|
entity = EntitiesMngr.getEntityBySheetName(entityName.toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity && entity->properties().selectable() && !entity->getDisplayName().empty())
|
||||||
|
{
|
||||||
|
UserEntity->selection(entity->slot());
|
||||||
|
}
|
||||||
|
else if (!quiet)
|
||||||
|
{
|
||||||
|
CInterfaceManager::getInstance()->displaySystemInfo(CI18N::get("uiTargetErrorCmd"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue