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="target" action="target" params="entity=$" />
|
||||
<command name="tar" action="target" params="entity=$" />
|
||||
<command name="target" action="target" params="entity=+" ctrlchar="false" />
|
||||
<command name="tar" action="target" params="entity=+" ctrlchar="false" />
|
||||
|
||||
<command name="target_quiet" action="target" params="entity=$|quiet=true" />
|
||||
<command name="tarq" action="target" params="entity=$|quiet=true" />
|
||||
|
||||
<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_quiet" action="target" params="entity=+|quiet=true" ctrlchar="false" />
|
||||
<command name="tarq" action="target" params="entity=+|quiet=true" ctrlchar="false" />
|
||||
|
||||
<command name="target" 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
|
||||
{
|
||||
ucstring source = name;
|
||||
|
|
|
@ -302,6 +302,12 @@ public:
|
|||
* \param complete : if true, the name must match the full name of the entity.
|
||||
*/
|
||||
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;
|
||||
/// Get an entity by dataset index. Returns NULL if the entity is not found.
|
||||
CEntityCL *getEntityByCompressedIndex(TDataSetIndex compressedIndex) const;
|
||||
|
|
|
@ -2416,14 +2416,35 @@ class CAHTarget : public IActionHandler
|
|||
{
|
||||
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
|
||||
{
|
||||
// Get the entity name to target
|
||||
ucstring entityName;
|
||||
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");
|
||||
|
||||
if (!entityName.empty())
|
||||
vector<ucstring> keywords;
|
||||
NLMISC::splitUCString(entityName, ucstring(" "), keywords);
|
||||
if (!keywords.empty() && keywords[0].size() > 0 && keywords[0][0] == (ucchar)'"')
|
||||
{
|
||||
// entity name is in quotes, do old style match with 'starts with' filter
|
||||
// search for optional second parameter from old command for prefer_complete_match param
|
||||
keywords.clear();
|
||||
|
||||
ucstring::size_type lastOf = entityName.rfind(ucstring("\""));
|
||||
if (lastOf == 0)
|
||||
lastOf = ucstring::npos;
|
||||
|
||||
// override the value only when there is no 'prefer_complete_match' parameter set
|
||||
if (completeMatch.empty() && lastOf < entityName.size())
|
||||
completeMatch = trim(entityName.substr(lastOf+1).toUtf8());
|
||||
|
||||
entityName = entityName.substr(1, lastOf-1);
|
||||
}
|
||||
|
||||
// late check because only possible if doing 'starts-with' search
|
||||
bool preferCompleteMatch = (completeMatch != "0");
|
||||
|
||||
CEntityCL *entity = NULL;
|
||||
if (preferCompleteMatch)
|
||||
{
|
||||
|
@ -2431,9 +2452,14 @@ class CAHTarget : public IActionHandler
|
|||
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
|
||||
// Get the entity with a partial match using 'starts with' search
|
||||
entity = EntitiesMngr.getEntityByName(entityName, false, false);
|
||||
}
|
||||
|
||||
|
@ -2443,43 +2469,13 @@ class CAHTarget : public IActionHandler
|
|||
entity = EntitiesMngr.getEntityBySheetName(entityName.toUtf8());
|
||||
}
|
||||
|
||||
if (entity)
|
||||
if (entity && entity->properties().selectable() && !entity->getDisplayName().empty())
|
||||
{
|
||||
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
|
||||
UserEntity->selection(entity->slot());
|
||||
}
|
||||
else
|
||||
else if (!quiet)
|
||||
{
|
||||
CInterfaceManager *pIM= CInterfaceManager::getInstance();
|
||||
if(!quiet)
|
||||
pIM->displaySystemInfo(CI18N::get("uiTargetErrorCmd"));
|
||||
}
|
||||
CInterfaceManager::getInstance()->displaySystemInfo(CI18N::get("uiTargetErrorCmd"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue