// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#include "stdpch.h"
#include "continent.h"
#include "continent_inline.h"
#include "ai_mgr.h"
#include "ai_grp.h"
#include "ai_bot.h"
#include "ai_entity_matrix.h"
#include "ai_player.h"
#include "ai_mgr_fauna.h"
#include "ai_grp_fauna.h"
#include "ai_grp_npc.h"
#include "ai_grp_pet.h"
#include "ai_bot_npc.h"
#include "mirrors.h"
#include "server_share/mission_messages.h"
#include "game_share/fame.h"
#include "server_share/used_continent.h"
#include "ai_outpost.h"
#include "script_compiler.h"
#include "ais_actions.h"
#include "fx_entity_manager.h"
#include "ai_script_data_manager.h"
#include "commands.h"
#include "ais_user_models.h"
extern bool GrpHistoryRecordLog;
extern NLLIGO::CLigoConfig LigoConfig;
using namespace NLMISC;
using namespace NLNET;
using namespace std;
using namespace AITYPES;
using namespace AICOMP;
using namespace AIVM;
//////////////////////////////////////////////////////////////////////////////
// New set of commands //
//////////////////////////////////////////////////////////////////////////////
//- Generic commands ---------------------------------------------------------
RYAI_TEMPLATED_COMMAND(listInstances, "display the list of ai instances", "[]", CAIInstance, buildInstanceList, displayList)
RYAI_TEMPLATED_COMMAND(listContinents, "display the list of continents", "[]", CContinent, buildContinentList, displayList)
RYAI_TEMPLATED_COMMAND(listRegions, "display the list of regions", "[]", CRegion, buildRegionList, displayList)
RYAI_TEMPLATED_COMMAND(listCellZones, "display the list of cell zones", "[]", CCellZone, buildCellZoneList, displayList)
RYAI_TEMPLATED_COMMAND(listFamilyBehaviours, "display the list of family behaviours", "[]", CFamilyBehavior, buildFamilyBehaviorList, displayList)
RYAI_TEMPLATED_COMMAND(listOutposts, "display the list of outposts", "[]", COutpost, buildOutpostList, displayList)
RYAI_TEMPLATED_COMMAND(listManagers, "display the list of managers", "[]", CManager, buildManagerList, displayList)
RYAI_TEMPLATED_COMMAND(listGroups, "display the list of groups", "[]", CGroup, buildGroupList, displayList)
RYAI_TEMPLATED_COMMAND(listBots, "display the list of bots", "[]", CBot, buildBotList, displayList)
RYAI_TEMPLATED_COMMAND(listPlayers, "display the list of players", "[]", CBotPlayer, buildPlayerList, displayList)
RYAI_TEMPLATED_COMMAND(listFaunaPlaces, "display the list of fauna places", "[]", CAIPlace, buildFaunaPlaceList, displayList)
RYAI_TEMPLATED_COMMAND(enableFaunaPlace, "enable a fauna place", "[]", CAIPlace, buildFaunaPlaceList, spawnList)
RYAI_TEMPLATED_COMMAND(disableFaunaPlace, "disable a fauna place", "[]", CAIPlace, buildFaunaPlaceList, despawnList)
RYAI_TEMPLATED_COMMAND(displayInstances, "display extensively the list of ai instances", "[]", CAIInstance, buildInstanceList, displayListEx)
RYAI_TEMPLATED_COMMAND(displayContinents, "display extensively the list of continents", "[]", CContinent, buildContinentList, displayListEx)
RYAI_TEMPLATED_COMMAND(displayRegions, "display extensively the list of regions", "[]", CRegion, buildRegionList, displayListEx)
RYAI_TEMPLATED_COMMAND(displayCellZones, "display extensively the list of cell zones", "[]", CCellZone, buildCellZoneList, displayListEx)
RYAI_TEMPLATED_COMMAND(displayFamilyBehaviours, "display extensively the list of family behaviours", "[]", CFamilyBehavior, buildFamilyBehaviorList, displayListEx)
//RYAI_TEMPLATED_COMMAND(displayOutposts, "display extensively the list of outposts", "[]", COutpost, buildOutpostList, displayListEx)
RYAI_TEMPLATED_COMMAND(displayManagers, "display extensively the list of managers", "[]", CManager, buildManagerList, displayListEx)
RYAI_TEMPLATED_COMMAND(displayGroups, "display extensively the list of groups", "[]", CGroup, buildGroupList, displayListEx)
RYAI_TEMPLATED_COMMAND(displayBots, "display extensively the list of bots", "[]", CBot, buildBotList, displayListEx)
RYAI_TEMPLATED_COMMAND(displayPlayers, "display extensively the list of players", "[]", CBotPlayer, buildPlayerList, displayListEx)
RYAI_TEMPLATED_COMMAND(spawnInstances, "spawns the ai instances", "[]", CAIInstance, buildInstanceList, spawnList)
//RYAI_TEMPLATED_COMMAND(spawnContinents, "spawns the continents", "[]", CContinent, buildContinentList, spawnList)
//RYAI_TEMPLATED_COMMAND(spawnRegions, "spawns the regions", "[]", CRegion, buildRegionList, spawnList)
//RYAI_TEMPLATED_COMMAND(spawnCellZones, "spawns the cell zones", "[]", CCellZone, buildCellZoneList, spawnList)
//RYAI_TEMPLATED_COMMAND(spawnFamilyBehaviours, "spawns the family behaviours", "[]", CFamilyBehavior, buildFamilyBehaviorList, spawnList)
//RYAI_TEMPLATED_COMMAND(spawnOutposts, "spawns the outposts", "[]", COutpost, buildOutpostList, spawnList)
RYAI_TEMPLATED_COMMAND(spawnManagers, "spawns the managers", "[]", CManager, buildManagerList, spawnList)
RYAI_TEMPLATED_COMMAND(spawnGroups, "spawns the groups", "[]", CGroup, buildGroupList, spawnList)
//RYAI_TEMPLATED_COMMAND(spawnBots, "spawns the bots", "[]", CBot, buildBotList, spawnList)
//RYAI_TEMPLATED_COMMAND(spawnPlayers, "spawns the players", "[]", CBotPlayer, buildPlayerList, spawnList)
RYAI_TEMPLATED_COMMAND(despawnInstances, "despawns the ai instances", "[]", CAIInstance, buildInstanceList, despawnList)
//RYAI_TEMPLATED_COMMAND(despawnContinents, "despawns the continents", "[]", CContinent, buildContinentList, despawnList)
//RYAI_TEMPLATED_COMMAND(despawnRegions, "despawns the regions", "[]", CRegion, buildRegionList, despawnList)
//RYAI_TEMPLATED_COMMAND(despawnCellZones, "despawns the cell zones", "[]", CCellZone, buildCellZoneList, despawnList)
//RYAI_TEMPLATED_COMMAND(despawnFamilyBehaviours, "despawns the family behaviours", "[]", CFamilyBehavior, buildFamilyBehaviorList, despawnList)
//RYAI_TEMPLATED_COMMAND(despawnOutposts, "despawns the outposts", "[]", COutpost, buildOutpostList, despawnList)
RYAI_TEMPLATED_COMMAND(despawnManagers, "despawns the managers", "[]", CManager, buildManagerList, despawnList)
RYAI_TEMPLATED_COMMAND(despawnGroups, "despawns the groups", "[]", CGroup, buildGroupList, despawnList)
//RYAI_TEMPLATED_COMMAND(despawnBots, "despawns the bots", "[]", CBot, buildBotList, despawnList)
//RYAI_TEMPLATED_COMMAND(despawnPlayers, "despawns the players", "[]", CBotPlayer, buildPlayerList, despawnList)
//- Special commands ---------------------------------------------------------
NLMISC_COMMAND(search, "search all the data tree for a name part","")
{
if (args.size() != 1)
return false;
{
log.displayNL("- Search results in instances ------------------------------------------------");
std::deque container;
buildInstanceList(container);
displayList(log, container, args[0]);
}
{
log.displayNL("- Search results in continents -----------------------------------------------");
std::deque container;
buildContinentList(container);
displayList(log, container, args[0]);
}
{
log.displayNL("- Search results in regions --------------------------------------------------");
std::deque container;
buildRegionList(container);
displayList(log, container, args[0]);
}
{
log.displayNL("- Search results in cell zones -----------------------------------------------");
std::deque container;
buildCellZoneList(container);
displayList(log, container, args[0]);
}
{
log.displayNL("- Search results in family behaviors -----------------------------------------");
std::deque container;
buildFamilyBehaviorList(container);
displayList(log, container, args[0]);
}
{
log.displayNL("- Search results in outposts -------------------------------------------------");
std::deque container;
buildOutpostList(container);
displayList(log, container, args[0]);
}
{
log.displayNL("- Search results in managers -------------------------------------------------");
std::deque container;
buildManagerList(container);
displayList(log, container, args[0]);
}
{
log.displayNL("- Search results in groups ---------------------------------------------------");
std::deque container;
buildGroupList(container);
displayList(log, container, args[0]);
}
{
log.displayNL("- Search results in bots -----------------------------------------------------");
std::deque container;
buildBotList(container);
displayList(log, container, args[0]);
}
{
log.displayNL("- Search results in players --------------------------------------------------");
std::deque container;
buildPlayerList(container);
displayList(log, container, args[0]);
}
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(eventCreateNpcGroup, "create an event npc group", " [ [ [ []]]]")
{
if (args.size()<5)
return false;
CLogStringWriter stringWriter(&log);
CAIInstance* aiInstance = NULL;
{
uint32 aiInstanceId = NLMISC::atoui(args[0].c_str());
if (aiInstanceId>=CAIS::instance().aiinstances().size())
{
stringWriter.append("Invalid AI Instance Number");
return true;
}
aiInstance = CAIS::instance().aiinstances()[aiInstanceId];
if (!aiInstance)
{
stringWriter.append("AI Instance do not exists");
return true;
}
}
uint32 nbBots = NLMISC::atoui(args[1].c_str());
if (nbBots<=0)
{
stringWriter.append("invalid bot count");
return true;
}
NLMISC::CSheetId sheetId(args[2]);
if (sheetId==NLMISC::CSheetId::Unknown)
sheetId = args[2] + ".creature";
if (sheetId==NLMISC::CSheetId::Unknown)
{
stringWriter.append("invalid sheet id");
return true;
}
double x, y;
NLMISC::fromString(args[3], x);
NLMISC::fromString(args[4], y);
double dispersionRadius = 10.;
if (args.size()>5)
{
dispersionRadius = atof(args[5].c_str());
if (dispersionRadius<0.)
{
stringWriter.append("invalid dispersion radius");
return true;
}
}
bool spawnBots = true;
if (args.size()>6)
{
NLMISC::fromString(args[6], spawnBots);
}
double orientation = 6.666;
if (args.size()>7 && args[7] != "random")
{
NLMISC::fromString(args[7], orientation);
orientation = orientation / 360.0 * (NLMISC::Pi * 2.0);
}
std::string botsName;
if (args.size()>8) botsName = args[8];
aiInstance->eventCreateNpcGroup(nbBots, sheetId, CAIVector(x, y), dispersionRadius, spawnBots, orientation, botsName, "");
return true;
}
//----------------------------------------------------------------------------
NLMISC_COMMAND(listFxEntities, "", "[]")
{
if (args.size()>0)
displayList(log, CFxEntityManager::getInstance()->getEntities(), args[0]);
else
displayList(log, CFxEntityManager::getInstance()->getEntities());
return true;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Old set of commands //
//////////////////////////////////////////////////////////////////////////////
// Dump the road/zone connectivity
NLMISC_COMMAND(dumpRoadCon, "dump road/cell connectivity graph"," []")
{
if (args.size() > 2)
return false;
uint instanceIndex = 0;
if (args.size() == 2)
NLMISC::fromString(args[1], instanceIndex);
if (instanceIndex >= CAIS::instance().AIList().size())
{
log.displayNL("ai index %u is out of range ! (only %u ai instance)",
instanceIndex,
CAIS::instance().AIList().size());
return false;
}
CAIInstance *aii = CAIS::instance().AIList()[instanceIndex];
for (uint i=0; icontinents().size(); ++i)
{
CContinent *cont = aii->continents()[i];
if (!cont)
continue;
if ( args.empty()
|| cont->getName()==args[0])
{
log.displayRawNL("Dumping connection in '%s' (@ %p):",
cont->getName().c_str(),
cont);
CAliasCont ®ions = cont->regions();
for (uint i=0; i &cellZones = region->cellZones();
for (uint i=0; icells().size(); ++j)
{
CCell *cell = czone->cells()[j];
if (!cell) continue;
set >::iterator first(cell->_NeighbourCells.begin()), last(cell->_NeighbourCells.end());
for (; first != last; ++first)
{
nldebug("Link '%s' => '%s'", cell->getName().c_str(), (*first)->getName().c_str());
}
}
}
for (uint i=0; icells().size(); ++j)
{
CCell *cell = czone->cells()[j];
if (!cell) continue;
// bound the point into the cell
for (uint k=0; knpcZoneCount(); ++k)
{
CNpcZone *nz = cell->npcZone(k);
if (!nz)
continue;
for (uint l=0; lroads().size(); ++l)
{
nldebug("NpcZone '%s' host road '%s'", nz->getAliasTreeOwner().getName().c_str(), nz->roads()[l]->getName().c_str());
}
}
CAliasCont &roads = cell->roads();
for (uint i=0; igetName().c_str(),
road->startZone().isNULL() ? "none" : road->startZone()->getAliasTreeOwner().getName().c_str(),
road->startExternal() ? "(external)" : "",
road->endZone().isNULL() ? "none" : road->endZone()->getAliasTreeOwner().getName().c_str(),
road->endExternal() ? "(external)" : "");
}
}
}
}
}
}
return true;
}
bool dumpContinentImp(uint instanceIndex, const std::string &continentName, NLMISC::CLog &log);
// Dump the structure of a dynamic continent
NLMISC_COMMAND(dumpContinent, "dump the structure of a continent"," []")
{
if (args.size() > 2 || args.size() < 1)
return false;
uint instanceIndex = 0;
if (args.size() == 2)
NLMISC::fromString(args[1], instanceIndex);
if (instanceIndex >= CAIS::instance().AIList().size())
{
log.displayNL("ai index %u is out of range ! (only %u ai instance)",
instanceIndex,
CAIS::instance().AIList().size());
return false;
}
return dumpContinentImp(instanceIndex, args[0], log);
}
bool dumpContinentImp(uint instanceIndex, const std::string &continentName, NLMISC::CLog &log)
{
CAIInstance *aii = CAIS::instance().AIList()[instanceIndex];
for (uint i=0; icontinents().size(); ++i)
{
CContinent *cont = aii->continents()[i];
if (!cont) continue;
if (cont->getName()==continentName)
{
log.displayRawNL("Dumping continent '%s' (@ %p):",
cont->getName().c_str(),
cont);
for (uint j=0; jregions().size(); ++j)
{
CRegion *region = cont->regions()[j];
if (!region)
{
log.displayNL(" +- %u null entry", j);
continue;
}
log.displayNL(" +- Region '%s'%s @ %p",
region->getName().c_str(),
region->getAliasString().c_str(),
static_cast(region));
for (uint k=0; kcellZones().size(); ++k)
{
CCellZone *cz = region->cellZones()[k];
if (!cz)
{
log.displayNL(" | +- %u null entry", k);
continue;
}
log.displayNL(" | +- CellZone '%s'%s @ %p",
cz->getName().c_str(),
cz->getAliasString().c_str(),
static_cast(cz));
for (uint l=0; lcells().size(); ++l)
{
CCell *cell = cz->cells()[l];
if (!cell)
{
log.displayNL(" | | +- %u null entry", l);
continue;
}
log.displayNL(" | | +- Cell '%s'%s @ %p",
cell->getName().c_str(),
cell->getAliasString().c_str(),
static_cast(cell));
for (uint m=0; mnpcZoneCount(); ++m)
{
CNpcZone *nz = cell->npcZone(m);
if (!nz)
{
log.displayNL(" | | | +- %u null entry", m);
continue;
}
// log.displayNL(" | | | +- NpcZone '%s' (alias A:%u @ %p)", nz->getName().c_str(), nz->getAlias(), static_cast(nz));
log.displayNL(" | | | +- NpcZone '%s'%s",
nz->getAliasTreeOwner().getName().c_str(),
nz->getAliasTreeOwner().getAliasString().c_str());
}
for (uint k=0; kroads().size(); ++k)
{
CRoad *road = cell->roads()[k];
if (!road)
{
log.displayNL(" | | +- %u null entry", k);
continue;
}
log.displayNL(" | | +- Road '%s'%s @ %p",
road->getName().c_str(),
road->getAliasString().c_str(),
static_cast(road));
}
for (uint m=0; mfaunaZones().size(); ++m)
{
CFaunaZone *fz = cell->faunaZones()[m];
if (!fz)
{
log.displayNL(" | | | +- %u null entry", m);
continue;
}
log.displayNL(" | | | +- FaunaZone '%s'%s @ %p",
fz->getName().c_str(),
fz->getAliasString().c_str(),
static_cast(fz));
}
}
}
}
// no more to do
return true;
}
}
log.displayNL("Can't find continent '%s' in ai instance %u",
continentName.c_str(),
instanceIndex);
return true;
}
// Load a collision map
NLMISC_COMMAND(loadContinent, "load a continent collision map","")
{
if (args.size() != 1)
return false;
CWorldContainer::loadContinent(args[0]);
return true;
}
CAIInstance *currentInstance = NULL;
NLMISC_COMMAND(createDynamicAIInstance, "Create a new dynamic AIInstance","")
{
if (args.size() != 1)
return false;
// find an unused continent id
uint32 in;
NLMISC::fromString(args[0], in);
if( !CAIS::instance().getAIInstance(in) )
{
std::string name= NLMISC::toString("ring_%d",in);
const int index = CAIS::instance().createAIInstance(name, in);
nlinfo("AIInstance %u created for continent '%s' (Instance Index : %u)", in, name.c_str(), index);
}
// activate the current AIInstance
currentInstance = CAIS::instance().getAIInstance(in); //CAIS::instance().getAIInstance(continentInstanceId);
CWorkPtr::aiInstance(currentInstance);
return true;
}
NLMISC_COMMAND(createStaticAIInstance, "Create a new static AIInstance for a given continent.","")
{
if (args.size() != 1)
return false;
CUsedContinent &uc = CUsedContinent::instance();
const uint32 in = uc.getInstanceForContinent(args[0]);
if (in == std::numeric_limits::max())
{
nlwarning("The continent '%s' is unknow or not active. Can't create instance, FATAL", args[0].c_str());
nlassert(in != ~0);
// nlassertex(in != ~0, ("The continent '%s' is unknow or not active. Can't create instance, FATAL", args[0].c_str()));
}
if (!CAIS::instance().getAIInstance(in))
{
const int index = CAIS::instance().createAIInstance(args[0], in);
nlinfo("AIInstance %u created for continent '%s' (Instance Index : %u)",
in, args[0].c_str(), index);
}
// activate the current AIInstance
currentInstance = CAIS::instance().getAIInstance(in); //CAIS::instance().getAIInstance(continentInstanceId);
return true;
}
NLMISC_COMMAND(autoConfig, "Automaticaly load collision map, create AIInstance and load the primitives","")
{
if (!args.empty())
return false;
CUsedContinent &uc = CUsedContinent::instance();
log.displayNL("AIS Auto config with %u continents...", uc.getContinents().size());
for (uint i=0; i] [family-] [value-] [detailled]")
{
std::string family;
std::string cellZoneName;
uint32 value=~0;
bool detailled=false;
CLogStringWriter stringWriter(&log);
{
for (uint32 i=0;icontinents().size(); ++j)
{
CContinent *cont = aii->continents()[j];
if (!cont)
continue;
for (uint k=0; kregions().size(); ++k)
{
CRegion *r = cont->regions()[k];
if (!r)
continue;
for (uint l=0; lcellZones().size(); ++l)
{
CCellZone *cz = r->cellZones()[l];
if (!cz)
continue;
if ( !cellZoneName.empty()
&& cz->getAliasFullName()!=cellZoneName)
continue;
if (value==~0)
stringWriter.append("");
for (uint m=0; m_Families.size(); ++m)
{
CFamilyBehavior *fb = cz->_Families[m];
if (!fb)
// TODO
// || ( !family.empty()
// && familyFilter!=fb->getFamily().getFamilyName()))
{
continue;
}
if (value==~0) // not for affectation.
{
fb->displayLogOld (stringWriter, detailled);
}
else
{
fb->setEffectiveLevel (value);
}
}
}
}
}
}
return true;
}
class CDoOnFamily
{
public:
CDoOnFamily()
{}
virtual ~CDoOnFamily()
{}
virtual void doOnFamily (CFamilyBehavior *fb) const = 0;
virtual void doOnCellZone (CCellZone *cz) const = 0;
protected:
private:
};
bool doOnFamily (const std::vector &args, CDoOnFamily *fam)
{
std::string family;
std::string cellZoneName;
for (uint32 i=0;i, CAIS::instance().AIList())
{
FOREACH(contIt, CCont, (*aiiIt)->continents())
{
FOREACH(rIt, CCont, (*contIt)->regions())
{
FOREACH(czIt, CCont, (*rIt)->cellZones())
{
if ( !cellZoneName.empty()
&& czIt->getAliasFullName()!=cellZoneName)
continue;
fam->doOnCellZone(*czIt);
FOREACH(fb, CCont, czIt->_Families)
{
if ( !family.empty()
&& familyFilter!=fb->getName())
continue;
fam->doOnFamily(*fb);
}
}
}
}
}
return true;
}
class CDoOnFamilyCommand
:public CDoOnFamily
{
public:
CDoOnFamilyCommand (const std::vector &args, NLMISC::CLog &log)
:_stringWriter(&log)
{
_index=~0;
_value=-1;
_detailled=false;
for (uint32 i=0;idisplayLogOld (_stringWriter, _detailled);
return;
}
if (_index==~0) // all indexs ?
{
for (uint32 nrjIndex=0;nrjIndex<4;nrjIndex++)
fb->setModifier (_value, nrjIndex);
return;
}
fb->setModifier (_value, (uint32)_index);
}
virtual void doOnCellZone(CCellZone *cz) const
{
if (_value==-1)
_stringWriter.append("");
}
protected:
private:
uint32 _index;
float _value;
bool _detailled;
mutable CLogStringWriter _stringWriter;
};
NLMISC_COMMAND(energyscalemodifier, "set or get the energy scale (affects group number).","[cellZone-] [family-] [index-] [value-] [detailled]")
{
CDoOnFamilyCommand command(args, log);
return doOnFamily (args, &command);
}
NLMISC_COMMAND(energyScaleModifier2, "set or get the energy scale (affects group number).","[--cellZone=] [--family=] [--index=] [--value=] [--detailled]")
{
std::string cellZoneName;
std::string familyName;
int index = -1;
float value = -1.f;
bool detailed = false;
for (size_t i=0; i widths(10, 0);
CFamilyBehavior::checkLogHeadersWidths(widths, index, detailed);
FOREACH(itInstance, CCont, CAIS::instance().AIList())
{
FOREACH(itContinent, CCont, itInstance->continents())
{
FOREACH(itRegion, CCont, itContinent->regions())
{
FOREACH(itCellZone, CCont, itRegion->cellZones())
{
CCellZone* cellZone = *itCellZone;
if (!cellZone || !cellZoneName.empty() && cellZone->getName()!=cellZoneName)
continue;
FOREACH(itFamilyBehavior, CCont, cellZone->familyBehaviors())
{
CFamilyBehavior* familyBehavior = *itFamilyBehavior;
if (!familyBehavior || !familyName.empty() && familyBehavior->getName()!=familyName)
continue;
familyBehavior->checkLogWidths(widths, index, detailed);
}
}
}
}
}
CLogStringWriter stringWriter(&log);
CFamilyBehavior::displayLogLine(stringWriter, index, detailed, widths);
CFamilyBehavior::displayLogHeaders(stringWriter, index, detailed, widths);
CFamilyBehavior::displayLogLine(stringWriter, index, detailed, widths);
FOREACH(itInstance, CCont, CAIS::instance().AIList())
{
FOREACH(itContinent, CCont, itInstance->continents())
{
FOREACH(itRegion, CCont, itContinent->regions())
{
FOREACH(itCellZone, CCont, itRegion->cellZones())
{
CCellZone* cellZone = *itCellZone;
if (!cellZone || !cellZoneName.empty() && cellZone->getName()!=cellZoneName)
continue;
FOREACH(itFamilyBehavior, CCont, cellZone->familyBehaviors())
{
CFamilyBehavior* familyBehavior = *itFamilyBehavior;
if (!familyBehavior || !familyName.empty() && familyBehavior->getName()!=familyName)
continue;
familyBehavior->displayLog(stringWriter, index, detailed, widths);
}
}
}
}
}
CFamilyBehavior::displayLogLine(stringWriter, index, detailed, widths);
}
else
{
// Change value
}
return true;
}
NLMISC_COMMAND(globalEnergy, "set or get the effective energy for a family.","[ []]")
{
if (args.size() > 2)
return false;
string family;
CLogStringWriter stringWriter(&log);
if (args.size() > 0)
{
family=args[0];
}
uint32 value;
if (args.size() == 2)
{
float v = float(atof(args[1].c_str()));
clamp(v,0,1);
stringWriter.append("Setting effective energy level for '"+family+"' to "+toString(v));
value = uint32(v * ENERGY_SCALE);
}
for (uint i=0; icontinents().size(); ++j)
{
CContinent *cont = aii->continents()[j];
if (!cont)
continue;
for (uint k=0; kregions().size(); ++k)
{
CRegion *r = cont->regions()[k];
if (!r)
continue;
for (uint l=0; lcellZones().size(); ++l)
{
CCellZone *cz = r->cellZones()[l];
if (!cz)
continue;
stringWriter.append("");
for (uint m=0; m_Families.size(); ++m)
{
CFamilyBehavior *fb = cz->_Families[m];
if (!fb)
continue;
if (args.size() ==0
|| ( args.size() == 1
&& family == fb->getName())
)
{
fb->displayLogOld (stringWriter, args.size()==1);
continue;
}
if ( args.size() == 2
&& family == fb->getName())
{
fb->setEffectiveLevel(value);
}
}
}
}
}
}
return true;
}
//-------------------------------------------------------------------------
// memory report
// NLMISC_COMMAND(statMemory, "generate a memory usage statistic file","")
// {
// if (args.size() != 1)
// return false;
//
// CLogStringWriter stringWriter(&log);
//
// if (args[0] == "begin")
// {
// stringWriter.append("Writing begin memory state in 'memory_report_begin.csv'...");
// NLMEMORY::StatisticsReport("memory_report_begin.csv", false);
// stringWriter.append("Memory stat Done.");
// }
// else if (args[0] == "end")
// {
// stringWriter.append("Writing end memory state report in 'memory_report_end.csv'...");
// NLMEMORY::StatisticsReport("memory_report_end.csv", false);
// stringWriter.append("Memory stat Done.");
// }
// else
// return false;
//
// return true;
// }
//-------------------------------------------------------------------------
// set a group variable
NLMISC_COMMAND(setGroupVar,"display the logic var of the group in the given AI Instance"," ")
{
if (args.size()!=4)
return false;
CGroup *grp = NULL;
CLogStringWriter stringWriter(&log);
CAIInstance *aiInstance=NULL;
{
uint32 aiInstanceId = NLMISC::atoui(args[0].c_str());
if (aiInstanceId>CAIS::instance().AIList().size())
{
stringWriter.append("Invalid AI Instance Number");
return false;
}
aiInstance=CAIS::instance().AIList()[aiInstanceId];
if (!aiInstance)
{
stringWriter.append("AI Instance do not exists");
return false;
}
}
// first, try to find the group by alias
uint32 alias = NLMISC::atoui(args[1].c_str());
if (alias != 0)
{
grp = aiInstance->findGroup(alias);
}
if (grp == NULL)
{
/// try to find the group bt name
std::vector grps;
aiInstance->findGroup(grps, args[1]);
if (grps.size() > 1)
{
std::string s;
for (uint i=0; ialiasTreeOwner()->getAliasString().c_str());
}
stringWriter.append("More than one group have name '"+args[1]+"', listing alias :");
stringWriter.append(s);
return false;
}
else if (grps.empty())
{
stringWriter.append("No group correspond to name '"+args[1]+"'");
return false;
}
else
{
grp = grps.front();
}
}
// retreive the varID.
// uint32 varId = NLMISC::atoui(args[2].c_str());
NLMISC::TStringId varId=CStringMapper::map(args[2]); // NLMISC::atoui(args[2].c_str());
float value = float(atof(args[3].c_str()));
CStateInstance *stateInstance=grp->getPersistentStateInstance();
stringWriter.append(grp->aliasTreeOwner()->getName()+":"+toString(*varId)+" = "+toString(value)+" (old value : "+ toString(stateInstance->getLogicVar(varId))+" )");
stateInstance->setLogicVar(varId, value);
return true;
}
//-------------------------------------------------------------------------
// display group variable
NLMISC_COMMAND(displayGroupVar,"display the logic var of the group in the given AI Instance"," ")
{
if (args.size()!=2)
return false;
CLogStringWriter stringWriter(&log);
CAIInstance *aiInstance=NULL;
{
uint32 aiInstanceId = NLMISC::atoui(args[0].c_str());
if (aiInstanceId>CAIS::instance().AIList().size())
{
stringWriter.append("Invalid AI Instance Number");
return false;
}
aiInstance=CAIS::instance().AIList()[aiInstanceId];
if (!aiInstance)
{
stringWriter.append("AI Instance do not exists");
return false;
}
}
CGroup *grp = NULL;
// first, try to find the group by alias
uint32 alias = NLMISC::atoui(args[1].c_str());
if (alias != 0)
{
grp = aiInstance->findGroup(alias);
}
if (grp == NULL)
{
/// try to find the group bt name
std::vector grps;
aiInstance->findGroup(grps, args[1]);
if (grps.size() > 1)
{
std::string s;
for (uint i=0; ialiasTreeOwner()->getAliasString().c_str());
}
stringWriter.append("More than one group have name '"+args[1]+"', listing alias :");
stringWriter.append(s);
return false;
}
else if (grps.empty())
{
stringWriter.append("No group correspond to name '"+args[1]+"'");
return false;
}
else
{
grp = grps.front();
}
}
stringWriter.append("Logic var of group '"+grp->aliasTreeOwner()->getName()+"'");
// parser les variables pour outputer le contenu ..
{
const CStateInstance *stateInstance=grp->getPersistentStateInstance();
{
string str;
stateInstance->logicVarsToString(str);
stringWriter.append(str);
}
}
return true;
}
//-------------------------------------------------------------------------
// display the player teams data
NLMISC_COMMAND(displayPlayerTeams,"display all the player teams"," [<-no_detail>]")
{
bool noDetail = false;
if (args.size()>1)
return false;
if ( !args.empty()
&& args[args.size()-1]=="-no_detail")
noDetail = true;
CCont::iterator it=CAIS::instance().AIList().begin(), itEnd=CAIS::instance().AIList().end();
CLogStringWriter stringWriter(&log);
while (it!=itEnd)
{
std::vector teamIds;
CAIInstance *aiInstance=*it;
aiInstance->getPlayerMgr()->getTeamIds(teamIds);
if (teamIds.empty())
{
continue;
}
std::vector::iterator first(teamIds.begin()), last(teamIds.end());
for (; first != last; ++first)
{
int id = *first;
{
stringWriter.append("Player Team "+toString(id)+" :");
if (!noDetail)
{
const std::set &team = aiInstance->getPlayerMgr()->getPlayerTeam(uint16(id));
std::set::const_iterator first(team.begin()), last(team.end());
for (; first != last; ++first)
{
stringWriter.append(" Row "+toString((*first).getIndex())+" : "+CMirrors::DataSet->getEntityId(*first).toString());
}
}
}
}
++it;
}
return true;
}
//-------------------------------------------------------------------------
// set the escrot team ID for a group
NLMISC_COMMAND(setEscortId,"set the escort team id for a group in the given aIInstance"," |")
{
if (args.size()!=3)
return false;
CLogStringWriter stringWriter(&log);
CAIInstance *aiInstance=NULL;
{
uint32 aiInstanceId = NLMISC::atoui(args[0].c_str());
if (aiInstanceId>CAIS::instance().AIList().size())
{
stringWriter.append("Invalid AI Instance Number");
return false;
}
aiInstance=CAIS::instance().AIList()[aiInstanceId];
if (!aiInstance)
{
stringWriter.append("AI Instance do not exists");
return false;
}
}
CGroup *grp = NULL;
// first, try to find the group by alias
uint32 alias = NLMISC::atoui(args[2].c_str());
if (alias != 0)
{
grp = aiInstance->findGroup(alias);
}
if (grp == NULL)
{
/// try to find the group bt name
std::vector grps;
aiInstance->findGroup(grps, args[2]);
if (grps.size() > 1)
{
std::string s;
for (uint i=0; ialiasTreeOwner()->getAliasString().c_str());
}
stringWriter.append("More than one group have name '"+args[2]+"', listing alias :");
stringWriter.append(s);
return false;
}
else if (grps.empty())
{
stringWriter.append("No group correspond to name"+args[2]);
return false;
}
else
{
grp = grps.front();
}
}
uint16 teamId = uint16(NLMISC::atoui(args[1].c_str()));
stringWriter.append("Setting escort teamId "
+toString(teamId)
+" on group '"
+args[2]
+"'"
+grp->aliasTreeOwner()->getAliasString().c_str());
grp->setEscortTeamId(teamId);
return true;
}
//-------------------------------------------------------------------------
// buffered commands facility
typedef vector TCommand;
typedef vector TCommandList;
static vector bufferedRetStrings;
void clearBufferedRetStrings()
{
bufferedRetStrings.clear();
}
TCommandList setEventCommands;
TCommandList scriptCommands;
TCommandList scriptCommands2;
TCommandList scriptCommandsBotById;
TCommandList scriptCommandsGroupByName;
TCommandList loadScriptCommands;
bool execSetEvent( CStringWriter& stringWriter, TCommand const& args);
bool execScript( CStringWriter& stringWriter, TCommand const& args);
bool execScript2( CStringWriter& stringWriter, TCommand const& args);
bool execScriptBotById( CStringWriter& stringWriter, TCommand const& args);
bool execScriptGroupByName( CStringWriter& stringWriter, TCommand const& args);
bool execLoadScript(CStringWriter& stringWriter, TCommand const& args);
void execBufferedCommands()
{
vector retStrings;
CArrayStringWriter sw(retStrings);
FOREACHC(it, TCommandList, setEventCommands)
{
execSetEvent(sw, *it);
}
setEventCommands.clear();
FOREACHC(it, TCommandList, scriptCommands)
{
execScript(sw, *it);
}
scriptCommands.clear();
FOREACHC(it, TCommandList, scriptCommands2)
{
execScript2(sw, *it);
}
scriptCommands2.clear();
FOREACHC(it, TCommandList, scriptCommandsBotById)
{
execScriptBotById(sw, *it);
}
scriptCommandsBotById.clear();
FOREACHC(it, TCommandList, scriptCommandsGroupByName)
{
execScriptGroupByName(sw, *it);
}
scriptCommandsGroupByName.clear();
FOREACHC(it, TCommandList, loadScriptCommands)
{
execLoadScript(sw, *it);
}
loadScriptCommands.clear();
// Show ret commands
FOREACHC(strIt, vector, retStrings)
nlwarning(strIt->c_str());
bufferedRetStrings.insert(bufferedRetStrings.end(), retStrings.begin(), retStrings.end());
}
//-------------------------------------------------------------------------
// set a user event on a group
bool execSetEvent(CStringWriter &stringWriter, const vector &args)
{
// Temporize setEvent commands.
if ( args.size() != 3
&& !( args.size() == 4
&& args[1] == "-no_detail"))
return false;
CAIInstance *aiInstance=NULL;
{
const uint32 aiInstanceId = NLMISC::atoui(args[0].c_str());
if (aiInstanceId>CAIS::instance().AIList().size())
{
stringWriter.append("Invalid AI Instance Number");
return false;
}
aiInstance=CAIS::instance().AIList()[aiInstanceId];
if (!aiInstance)
{
stringWriter.append("AI Instance do not exists");
return false;
}
}
bool noDetail = false;
if (args.size() == 4)
noDetail = true;
uint32 eventId = NLMISC::atoui(args[1].c_str());
NLMISC::clamp(eventId, 0u, 9u);
CGroup *grp = NULL;
// first, try to find the group by alias
uint32 alias = NLMISC::atoui(args[2].c_str());
if (alias != 0)
{
grp = aiInstance->findGroup(alias);
if (!grp)
return false;
stringWriter.append("Setting event "+toString(eventId)+" on groups '"+grp->aliasTreeOwner()->getName()+"' ("+toString(grp->getChildIndex())+")");
grp->setEvent(eventId);
return true;
}
std::vector grps;
if (!grp)
{
/// try to find the group bot name
aiInstance->findGroup(grps, args[2]);
if (grps.size() > 1)
{
if (noDetail)
{
std::string s;
for (uint i=0; ialiasTreeOwner()->getAliasString().c_str());
}
stringWriter.append("More than one group have name '"+args[2]+"', listing alias :");
stringWriter.append(s);
return false;
}
}
else if (grps.empty())
{
stringWriter.append("No group correspond to name "+ args[2]);
return false;
}
}
stringWriter.append("Setting event "+toString(eventId)+" on groups '"+args[2]+"'");
for (uint i=0; isetEvent(eventId);
return true;
}
NLMISC_COMMAND(setEvent,"set an event for a group in the given aIInstance [buffered]"," [<-no_detail>] |")
{
clearBufferedRetStrings();
setEventCommands.push_back(args);
return true;
}
//-------------------------------------------------------------------------
// executes a script on groups matching a specified filter (1st arg)
bool execScript(CStringWriter& stringWriter, TCommand const& args)
{
if (args.size()<1)
return false;
string const& groupName = args[0];
typedef vector TGroupContainer;
TGroupContainer grps;
{
/// try to find the group bot name
buildFilteredGroupList(grps, groupName);
if (grps.empty())
{
stringWriter.append("No group correspond to name "+ groupName);
return false;
}
}
stringWriter.append("do script on groups '"+groupName+"'");
if (args.size()>1)
{
vector codeLines;
for (size_t i=1; i codePtr = CCompiler::getInstance().compileCode(codeLines, "script Command");
FOREACHC(itGrp, TGroupContainer, grps)
{
CGroup* grp = *itGrp;
if (grp->getPersistentStateInstance())
grp->getPersistentStateInstance()->interpretCode(NULL, codePtr);
}
}
else
{
FOREACHC(itGrp, TGroupContainer, grps)
{
CGroup* grp = *itGrp;
if (grp->getPersistentStateInstance())
{
stringWriter.append("Group: "+grp->getFullName());
grp->getPersistentStateInstance()->dumpVarsAndFunctions(stringWriter);
}
}
}
return true;
}
//-------------------------------------------------------------------------
// executes a script on groups containing a bot matching a specified filter (1st arg)
bool execScript2(CStringWriter& stringWriter, TCommand const& args)
{
if (args.size()<1)
return false;
string const& botName = args[0];
typedef set TGroupContainer;
TGroupContainer grps;
{
vector bots;
/// try to find the bot name
buildFilteredBotList(bots, botName);
if (bots.empty())
{
stringWriter.append("No bot correspond to name "+ botName);
return false;
}
else
{
FOREACH(itBot, vector, bots)
{
CBot* bot = *itBot;
CGroup* group = bot->getOwner();
// if (group->getOwner()==_EventNpcManager) // This would restrict the command to event groups
grps.insert(group);
}
}
}
stringWriter.append("do script on groups containing bot '"+botName+"'");
if (args.size()>1)
{
vector codeLines;
for (size_t i=1; i codePtr = CCompiler::getInstance().compileCode(codeLines, "script2 Command");
FOREACHC(itGrp, TGroupContainer, grps)
{
CGroup* grp = *itGrp;
if (grp->getPersistentStateInstance())
grp->getPersistentStateInstance()->interpretCode(NULL, codePtr);
}
}
else
{
FOREACHC(itGrp, TGroupContainer, grps)
{
CGroup* grp = *itGrp;
if (grp->getPersistentStateInstance())
{
stringWriter.append("Group: "+grp->getFullName());
grp->getPersistentStateInstance()->dumpVarsAndFunctions(stringWriter);
}
}
}
return true;
}
//-------------------------------------------------------------------------
// executes a script on groups containing a bot given its entity id
bool execScriptBotById(CStringWriter& stringWriter, TCommand const& args)
{
if (args.size()<2)
return false;
NLMISC::CEntityId botId = NLMISC::CEntityId(args[0]);
if (botId==NLMISC::CEntityId::Unknown)
return false;
CAIEntityPhysical* entity = CAIEntityPhysicalLocator::getInstance()->getEntity(botId);
CSpawnBotNpc* bot = dynamic_cast(entity);
if (!bot)
return false;
if (!bot->getPersistent().getOwner())
return false;
if (!bot->getPersistent().getOwner()->getPersistentStateInstance())
return false;
vector codeLines;
for (size_t i=1; i codePtr = CCompiler::getInstance().compileCode(codeLines, "script2 Command");
bot->getPersistent().getOwner()->getPersistentStateInstance()->interpretCode(NULL, codePtr);
return true;
}
//-------------------------------------------------------------------------
// executes a script on groups containing a bot given its entity id
bool execScriptGroupByName(CStringWriter& stringWriter, TCommand const& args)
{
if (args.size()<2)
return false;
string const& groupName = args[0];
// NLMISC::CEntityId botId = NLMISC::CEntityId(args[0]);
// if (botId==NLMISC::CEntityId::Unknown)
// return false;
CGroupNpc* group = dynamic_cast(CAliasTreeOwnerLocator::getInstance()->getEntity(groupName));
if (!group)
return false;
if (!group->getPersistentStateInstance())
return false;
vector codeLines;
for (size_t i=1; i codePtr = CCompiler::getInstance().compileCode(codeLines, "script2 Command");
group->getPersistentStateInstance()->interpretCode(NULL, codePtr);
return true;
}
NLMISC_COMMAND(getDatasetId,"get datasetid of bots with name matchiong the given filter", "")
{
if (args.size()!=1)
return false;
string const& botName = args[0];
string DatasetIds;
vector bots;
/// try to find the bot name
buildFilteredBotList(bots, botName);
if (bots.empty())
{
log.displayNL("ERR: No bot correspond to name %s", botName.c_str());
return false;
}
else
{
FOREACH(itBot, vector, bots)
{
CBot* bot = *itBot;
CSpawnBot* spawnBot = bot->getSpawnObj();
if (spawnBot!=NULL)
DatasetIds += spawnBot->dataSetRow().toString()+"|";
}
}
log.displayNL("%s", DatasetIds.c_str());
return true;
}
NLMISC_COMMAND(script,"execute a script for groups matching the given filter [buffered]"," ")
{
clearBufferedRetStrings();
scriptCommands.push_back(args);
return true;
}
NLMISC_COMMAND(script2,"execute a script for groups containing a bot matching the given filter [buffered]"," ")
{
clearBufferedRetStrings();
scriptCommands2.push_back(args);
return true;
}
static std::string scriptHex_decode(std::string str)
{
std::string output;
for (size_t i=0; i<(str.length()-1); i+=2)
{
char c1 = str[i], c2 = str[i+1];
char buffer[3] = { c1, c2, '\0' };
char c = (char)strtol(buffer, NULL, 16);
output.push_back(c);
}
return output;
}
NLMISC_COMMAND(scriptHex,"execute a hex-encoded script for a group in the given aIInstance [buffered]"," ")
{
vector _args = args;
_args[1] = scriptHex_decode(_args[1]);
clearBufferedRetStrings();
scriptCommands.push_back(_args);
return true;
}
static const char* hexEncoderTcl =
"proc copy_encoded {} {"
" # Get the args from the text fields"
" set group [ .group.name get 1.0 end ]"
" set script [ .script get 1.0 end ]"
" # Initiate the AIS command"
" set output [concat \"scriptHex\" ${group}]"
" append output \" \""
" # Convert the script itself into an hex string (-1 to remove trailing newline)"
" for {set i 0} {$i < [string length $script]-1} {incr i} {"
" # Get the character"
" set c [string index $script $i]"
" # Get its ascii value"
" scan $c %c n"
" # Print it as 2 hex digits"
" append output [format %02x $n]"
" }"
" # Replace the clipboard with the AIS command"
" clipboard clear"
" clipboard append $output"
"}"
""
"frame .group"
"pack .group -anchor w -fill x"
"label .group.label -text \"Group:\""
"pack .group.label -side left"
"text .group.name -height 1 -width 70"
"pack .group.name -fill x"
"text .script"
"pack .script -fill both -expand 1"
"button .button -text \"Copy encoded!\""
"pack .button -side bottom"
""
"bind .button {"
" copy_encoded"
"}"
"";
NLMISC_COMMAND(hexEncoder,"prints a script that can be used to encode a text for use with scriptHex","")
{
if (args.size()!=1)
return false;
if (args[0]=="tcl")
{
log.displayNL("%s", hexEncoderTcl);
}
else
{
log.displayNL("Invalid language name! Valid languages are: tcl");
}
return true;
}
//-------------------------------------------------------------------------
// set a user event on a group
bool execLoadScript(CStringWriter& stringWriter, vector const& args)
{
if (args.size()!=3)
return false;
CAIInstance* aiInstance = NULL;
{
uint32 const aiInstanceId = NLMISC::atoui(args[0].c_str());
if (aiInstanceId>CAIS::instance().AIList().size())
{
stringWriter.append("Invalid AI Instance Number");
return false;
}
aiInstance=CAIS::instance().AIList()[aiInstanceId];
if (!aiInstance)
{
stringWriter.append("AI Instance do not exists");
return false;
}
}
bool noDetail = false;
string const& groupName = args[1];
std::vector grps;
{
/// try to find the group bot name
aiInstance->findGroup(grps, groupName);
if (grps.size() > 1)
{
if (noDetail)
{
std::string s;
for (uint i=0; ialiasTreeOwner()->getAliasString().c_str());
}
stringWriter.append("More than one group have name '"+groupName+"', listing alias :");
stringWriter.append(s);
return false;
}
}
else if (grps.empty())
{
stringWriter.append("No group correspond to name "+ groupName);
return false;
}
}
stringWriter.append("do script on groups '"+groupName+"'");
try
{
NLMISC::CIFile file(NLMISC::CPath::lookup(args[2]));
vector lines;
while (!file.eof())
{
const size_t bufferSize = 4*1024;
char buffer[bufferSize];
file.getline(buffer, bufferSize);
lines.push_back(buffer);
}
// Compile the buffer
CSmartPtr codePtr=CCompiler::getInstance().compileCode(lines, "script Command");
// Interpret the code for each group
FOREACHC(itGrp, vector, grps)
(*itGrp)->getPersistentStateInstance()->interpretCode(NULL, codePtr);
}
catch (const EPathNotFound &)
{
nlwarning("Path not found while loading AIS script %s", args[2].c_str());
return false;
}
return true;
}
NLMISC_COMMAND(loadScript, "execute a script from a file for a group in the given aIInstance [buffered]", " ")
{
clearBufferedRetStrings();
loadScriptCommands.push_back(args);
return true;
}
NLMISC_COMMAND(getInfo,"display returned values of buffered commands","")
{
CLogStringWriter stringWriter(&log);
FOREACHC(strIt, vector, bufferedRetStrings)
{
stringWriter.append(*strIt);
}
return true;
}
//-------------------------------------------------------------------------
// DISPLAYING Managers, Groups and Bots
static void displayNode(const CAIAliasDescriptionNode *node,uint indent=0)
{
nlinfo("%*s- %s %-12s - %s",
indent,
"",
node->getAliasString().c_str(),
getName(node->getType()),
node->fullName().c_str());
for (uint i=0;igetChildCount();++i)
displayNode(node->getChild(i),indent+2);
}
NLMISC_COMMAND(displayNodeTreeMgr,"display node tree for given manager(s)","[...]")
{
if(args.size()<1)
return false;
for (uint i=0;igetAliasTreeOwner()->getAliasNode());
continue;
}
nlwarning("Failed to find mgr: %s",args[i].c_str());
}
return true;
}
NLMISC_COMMAND(displayTarget,"display bot target status for given bot(s) or player(s)","[...]")
{
if(args.size() <1)
return false;
CLogStringWriter stringWriter(&log);
for (uint i=0;i can't find entity: %s", args[i].c_str());
continue;
}
CAIEntityPhysical *phys=EntityPtr->getTarget();
if (!phys)
{
log.displayNL("=> bot %s have no target", args[i].c_str());
continue;
}
bool found=false;
switch (phys->getRyzomType())
{
case RYZOMID::npc:
case RYZOMID::creature:
case RYZOMID::pack_animal:
break;
case RYZOMID::player:
log.displayNL("=> target is a player");
break;
default:
{
CSpawnBot* spawnBot=dynamic_cast(phys);
if (spawnBot)
{
vector strings = spawnBot->getPersistent().getMultiLineInfoString();
FOREACHC(itString, vector, strings)
log.displayNL("%s", itString->c_str());
found=true;
}
}
break;
}
if (!found)
{
log.displayNL("=> can't display information for the target of: %s", args[i].c_str());
}
}
return true;
}
NLMISC_COMMAND(displayVision3x3,"display 3x3 cell vision centred on a given coordinate in the given aIInstance"," ")
{
if(args.size()!=3)
return false;
CAIInstance *aiInstance=NULL;
{
uint32 aiInstanceId = NLMISC::atoui(args[0].c_str());
if (aiInstanceId>CAIS::instance().AIList().size())
{
log.displayNL("Invalid AI Instance Number");
return false;
}
aiInstance=CAIS::instance().AIList()[aiInstanceId];
if (!aiInstance)
{
log.displayNL("AI Instance do not exists");
return false;
}
}
double dx, dy;
NLMISC::fromString(args[1], dx);
NLMISC::fromString(args[2], dy);
CAICoord x, y;
x = dx;
y = dy;
log.displayNL("3x3 Vision around (%.3f,%.3f)", x.asDouble(), y.asDouble());
uint32 botCount=0;
uint32 plrCount=0;
CAIVector position(x,y);
{
CAIEntityMatrix::CEntityIteratorRandom it;
for (it=aiInstance->playerMatrix().beginEntities(CAIS::instance().matrixIterator3x3(),position);!it.end();++it)
{
++plrCount;
// log.displayNL("=> PLR: %s (%s)", (*it).id().toString().c_str(), (*it).pos().toString().c_str());
if ((*it).isSpawned())
log.displayNL("=> (messageToChange)PLR: %d (%s)", (*it).getSpawnObj()->dataSetRow().getIndex(), (*it).getSpawnObj()->pos().toString().c_str());
}
}
{
CAIEntityMatrix::CEntityIteratorRandom it;
for (it=aiInstance->botMatrix().beginEntities(CAIS::instance().matrixIterator3x3(),position);!it.end();++it)
{
CPersistentOfPhysical &persRef=(*it);
if (!persRef.isSpawned())
continue;
++botCount;
CBot* botPtr=NLMISC::safe_cast(&persRef);
if (botPtr->getAliasTreeOwner())
log.displayNL("=> BOT: %s (%s)", botPtr->getAliasTreeOwner()->getName().c_str(), persRef.getSpawnObj()->pos().toString().c_str());
else
log.displayNL("=> BOT: unknown (%s)", persRef.getSpawnObj()->pos().toString().c_str());
// log.displayNL("=> BOT: %s (%s)", (*it).id().toString().c_str(), (*it).pos().toString().c_str());
}
}
log.displayNL("Entites found: %d bots, %d players, total: %d", botCount, plrCount, botCount+plrCount);
return true;
}
NLMISC_COMMAND(displayVisionRadius,"display roughly 'radius' cell vision centred on a given coordinate in the given aIInstance"," [=100]")
{
if ( args.size()!=3
&& args.size()!=4 )
return false;
CAIInstance *aiInstance=NULL;
{
uint32 aiInstanceId = NLMISC::atoui(args[0].c_str());
if (aiInstanceId>CAIS::instance().AIList().size())
{
log.displayNL("Invalid AI Instance Number");
return false;
}
aiInstance=CAIS::instance().AIList()[aiInstanceId];
if (!aiInstance)
{
log.displayNL("AI Instance do not exists");
return false;
}
}
uint32 dist=100;
CAICoord x, y;
x=atof(args[1].c_str());
y=atof(args[2].c_str());
if (args.size()==4)
NLMISC::fromString(args[3], dist);
log.displayNL("%dm Vision around (%.3f,%.3f)", dist, x.asDouble(), y.asDouble());
uint32 botCount=0;
uint32 plrCount=0;
const CAIEntityMatrixIteratorTblLinear *tbl=CAIS::instance().bestLinearMatrixIteratorTbl(dist);
CAIEntityMatrix::CEntityIteratorLinear it;
CAIVector position(x,y);
for (it=aiInstance->playerMatrix().beginEntities(tbl,position);!it.end();++it)
{
++plrCount;
const CPersistentOfPhysical& entityPtr = (*it);
const CBotPlayer* const playerPtr=dynamic_cast(&entityPtr);
if (!playerPtr)
continue;
// have to implement players.
#ifdef NL_DEBUG
nlwarning("Not Implemented");
#endif
// log.displayNL("=> PLR: %s (%s)", (*it).id().toString().c_str(), (*it).pos().toString().c_str());
// log.displayNL("=> PLR: %s (%s)", (*it).id().toString().c_str(), (*it).pos().toString().c_str());
}
for (it=aiInstance->botMatrix().beginEntities(tbl,position);!it.end();++it)
{
if ((*it).isSpawned())
{
++botCount;
// log.displayNL("=> BOT: %s (%s)", (*it).id().toString().c_str(), (*it).pos().toString().c_str());
log.displayNL("=> (messageToChange)BOT: %d (%s)", (*it).getSpawnObj()->dataSetRow().getIndex(), (*it).getSpawnObj()->pos().toString().c_str());
}
}
log.displayNL("Entites found: %d bots, %d players, total: %d", botCount, plrCount, botCount+plrCount);
return true;
}
NLMISC_COMMAND(countEntitesInVisionMatrix,"scan the vision matrix for entities in the given aiInstance","")
{
if (args.size()!=1)
return false;
CAIInstance *aiInstance=NULL;
{
uint32 aiInstanceId = NLMISC::atoui(args[0].c_str());
if (aiInstanceId>CAIS::instance().AIList().size())
{
log.displayNL("Invalid AI Instance Number");
return false;
}
aiInstance=CAIS::instance().AIList()[aiInstanceId];
if (!aiInstance)
{
log.displayNL("AI Instance do not exists");
return false;
}
}
// build an iterator table for our scan
CAIEntityMatrixIteratorTblRandom tbl;
tbl.push_back(0,0);
for (int i=0;i<256;++i)
{
for (int j=0;j<255;++j)
tbl.push_back(1,0);
if (i<255)
tbl.push_back(-255,1);
}
// some variables
CAIEntityMatrix::CCellTblIteratorRandom it;
uint32 botCount=0;
uint32 plrCount=0;
CAIVector position(0,0);
// count entities in bot matrix
for (it=aiInstance->botMatrix().beginCells(&tbl,position);!it.end();++it)
{
for (CEntityListLink *listLink=(*it)->next();listLink!=*it;listLink=listLink->next())
++botCount;
}
// count entities in player matrix
for (it=aiInstance->playerMatrix().beginCells(&tbl,position);!it.end();++it)
{
for (CEntityListLink *listLink=(*it)->next();listLink!=*it;listLink=listLink->next())
++plrCount;
}
// display the results
log.displayNL("Entites found: %d bots, %d players, total: %d", botCount, plrCount, botCount+plrCount);
return true;
}
//-------------------------------------------------------------------------
// DISPLAYING Places
NLMISC_COMMAND(displayPlaces,"display the list of places for specified manager","[]")
{
if(args.size() !=1)
return false;
// manager specified so lookup manager by name
CMgrFauna* mgrFaunaPtr = dynamic_cast(CAIS::instance().tryToGetManager(args[0].c_str()));
if (mgrFaunaPtr==NULL)
return false;
CLogStringWriter stringWriter(&log);
CCont::iterator it = mgrFaunaPtr->groups().begin();
CCont::iterator itEnd = mgrFaunaPtr->groups().end();
while (it!=itEnd)
{
NLMISC::safe_cast(*it)->displayPlaces(stringWriter);
++it;
}
return true;
}
//-------------------------------------------------------------------------
// WATCHES FOR TRACKING MGR, GRP & BOT OBJECTS
static std::string WATCH0,WATCH1,WATCH2,WATCH3,WATCH4,
WATCH5,WATCH6,WATCH7,WATCH8,WATCH9;
static std::string *watchStrings[]=
{
&WATCH0,&WATCH1,&WATCH2,&WATCH3,&WATCH4,
&WATCH5,&WATCH6,&WATCH7,&WATCH8,&WATCH9
};
static CAIEntity* watchEntity[sizeof(watchStrings)/sizeof(watchStrings[0])];
static uint watchIdx[sizeof(watchStrings)/sizeof(watchStrings[0])];
NLMISC_VARIABLE(string, WATCH0, "watch string 0");
NLMISC_VARIABLE(string, WATCH1, "watch string 1");
NLMISC_VARIABLE(string, WATCH2, "watch string 2");
NLMISC_VARIABLE(string, WATCH3, "watch string 3");
NLMISC_VARIABLE(string, WATCH4, "watch string 4");
NLMISC_VARIABLE(string, WATCH5, "watch string 5");
NLMISC_VARIABLE(string, WATCH6, "watch string 6");
NLMISC_VARIABLE(string, WATCH7, "watch string 7");
NLMISC_VARIABLE(string, WATCH8, "watch string 8");
NLMISC_VARIABLE(string, WATCH9, "watch string 9");
//
bool FAUNA_GRAPH_USES_DEBUG_TIME = false;
NLMISC_VARIABLE(bool, FAUNA_GRAPH_USES_DEBUG_TIME, "force fauna graph to use local time (for debug)");
// global routine called by the service main update()
void UpdateWatches()
{
// if (!CAIS::initialised())
// return;
for (uint i=0;igetOneLineInfoString();
else
*watchStrings[i] = string("");
}
}
void removeFromWatch(CAIEntity *entity)
{
for (uint i=0;i []")
{
if (args.size()!=2 && args.size()!=3)
return false;
uint idx;
NLMISC::fromString(args[0], idx);
if ( toString(idx)!=args[0]
|| idx>=sizeof(watchStrings)/sizeof(watchStrings[0]))
return false;
CAIEntity* CAIEntityPtr = CAIS::instance().tryToGetAIEntity(args[1].c_str());
if (!CAIEntityPtr)
return true;
watchEntity[idx]=CAIEntityPtr;
if (args.size()==3)
NLMISC::fromString(args[2], watchIdx[idx]);
else
watchIdx[idx]=0;
return true;
}
static bool setBotRecordHistory(std::vector args,bool onOff)
{
if (args.size()==0)
{
CAIInstance* instancePtr = CAIS::instance().AIList().getNextValidChild();
while (instancePtr!=NULL)
{
CManager* mgrPtr = instancePtr->managers().getNextValidChild();
while (mgrPtr!=NULL)
{
CGroup* grpPtr=mgrPtr->getNextValidGroupChild();
while (grpPtr!=NULL)
{
grpPtr->getDebugHistory()->setRecording(onOff);
CBot* botPtr = grpPtr->getNextValidBotChild();
while (botPtr!=NULL)
{
botPtr->getDebugHistory()->setRecording(onOff);
botPtr=grpPtr->getNextValidBotChild(botPtr);
}
grpPtr=mgrPtr->getNextValidGroupChild(grpPtr);
}
mgrPtr=instancePtr->managers().getNextValidChild(mgrPtr);
}
instancePtr=CAIS::instance().AIList().getNextValidChild(instancePtr);
}
}
else
{
CAIInstance* instancePtr = CAIS::instance().AIList().getNextValidChild();
while (instancePtr!=NULL)
{
CManager* mgrPtr = instancePtr->managers().getNextValidChild();
while (mgrPtr!=NULL)
{
CGroup* grpPtr=mgrPtr->getNextValidGroupChild();
while (grpPtr!=NULL)
{
if (onOff)
grpPtr->getDebugHistory()->setRecording(onOff);
CBot* botPtr = grpPtr->getNextValidBotChild();
while (botPtr!=NULL)
{
for (uint i=0;igetAliasTreeOwner()->getName(),args[i])==0)
{
botPtr->getDebugHistory()->setRecording(onOff);
}
botPtr=grpPtr->getNextValidBotChild(botPtr);
}
grpPtr=mgrPtr->getNextValidGroupChild(grpPtr);
}
mgrPtr=instancePtr->managers().getNextValidChild(mgrPtr);
}
instancePtr=CAIS::instance().AIList().getNextValidChild(instancePtr);
}
}
return true;
}
NLMISC_COMMAND(botHistoryRecordBegin,"setup history recording for all or named entities","[ [...]]")
{
return setBotRecordHistory(args,true);
}
NLMISC_COMMAND(botHistoryRecordEnd,"setup history recording for all or named entities","[ [...]]")
{
return setBotRecordHistory(args,false);
}
NLMISC_COMMAND(botViewHistory,"view recorded history for named entity","")
{
if (args.size()==0)
return false;
CAIInstance* instancePtr = CAIS::instance().AIList().getNextValidChild();
while (instancePtr!=NULL)
{
CManager* mgrPtr = instancePtr->managers().getNextValidChild();
while (mgrPtr!=NULL)
{
CGroup* grpPtr=mgrPtr->getNextValidGroupChild();
while (grpPtr!=NULL)
{
CBot* botPtr = grpPtr->getNextValidBotChild();
while (botPtr!=NULL)
{
for (uint i=0;igetAliasTreeOwner()->getName(),args[i])==0)
{
botPtr->getDebugHistory()->writeAsInfo();
break; // don't need to write info more than one time.
}
}
botPtr=grpPtr->getNextValidBotChild(botPtr);
}
grpPtr=mgrPtr->getNextValidGroupChild(grpPtr);
}
mgrPtr=instancePtr->managers().getNextValidChild(mgrPtr);
}
instancePtr=CAIS::instance().AIList().getNextValidChild(instancePtr);
}
return true;
}
NLMISC_COMMAND(grpHistoryRecordLog,"toggle grp history recorder 'nlinfo' logging","")
{
GrpHistoryRecordLog=!GrpHistoryRecordLog;
nlinfo("GrpHistoryRecordLog: %s",GrpHistoryRecordLog?"ON":"OFF");
return true;
}
//-------------------------------------------------------------------------
// DISPLAYING VISION OF FAUNA GROUPS
NLMISC_COMMAND(displayFaunaGrpVision,"display the vision of a fauna group","")
{
return false;
}
//-------------------------------------------------------------------------
// MANIPULATING STATE OF FAUNA GROUPS
NLMISC_COMMAND(advanceGrpState,"advance the group to the next state in its cycle","")
{
if(args.size() !=1)
return false;
CGrpFauna *grp=dynamic_cast(CAIS::instance().tryToGetGroup(args[0].c_str()));
if (!grp)
{
log.displayNL("Failed to identify group: %s",args[0].c_str());
return true;
}
if (!grp->isSpawned())
{
log.displayNL("Group not spawned: %s",args[0].c_str());
}
else
{
grp->getSpawnObj()->resetTimer();
}
return true;
}
NLMISC_COMMAND(setGrpTimers,"set the timer values for a given group"," ")
{
if(args.size()!=3)
return false;
CGrpFauna *grp=dynamic_cast(CAIS::instance().tryToGetGroup(args[0].c_str()));
if (!grp)
{
log.displayNL("Failed to identify group: %s",args[0].c_str());
return true;
}
uint32 eatTime, restTime;
NLMISC::fromString(args[1], eatTime);
NLMISC::fromString(args[2], restTime);
if (eatTime<1 || restTime<1)
{
log.displayNL("Invalid time parameters");
return true;
}
grp->setTimer(CGrpFauna::EAT_TIME, eatTime*10);
grp->setTimer(CGrpFauna::REST_TIME, restTime*10);
return true;
}
//-------------------------------------------------------------------------
// RUNNING THE AI UPDATE FOR TESTING OFFLINE
void cbTick();
extern uint ForceTicks;
NLMISC_COMMAND(updateAI,"call CAIS::update() (simulate a tick off-line)","[tick]")
{
if(args.size() >1)
return false;
// if there's an argument make sure its a positive integer
if (args.size()==1)
{
uint tick;
NLMISC::fromString(args[0], tick);
if ((tick < 1) || (toString(tick)!=args[0]))
return false;
ForceTicks = tick;
return true;
}
cbTick();
return true;
}
NLMISC_COMMAND(addPetsToPlayer,"Add some pets specified with a sheet to the specified player.","