// 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."," ") { if ( args.size() !=3 ) return false; #ifdef NL_DEBUG nlstopex(("Not Implemented")); #endif return true; } //------------------------------------------------------------------------- // DISPLAYING FIGHT SHEET. NLMISC_COMMAND(displayFightSheet,"display the sheet","") { if (args.size() !=1) { log.displayNL("One argument needed"); return false; } AISHEETS::ICreatureCPtr sheet = AISHEETS::CSheets::getInstance()->lookup(CSheetId(args[0])); if (!sheet) { log.displayNL("Unknown sheet %s", args[0].c_str()); return true; } if (sheet->SheetId()==NLMISC::CSheetId::Unknown) { std::string creatureString=args[0]+std::string(".creature"); sheet = /*const_cast(*/AISHEETS::CSheets::getInstance()->lookup(CSheetId(creatureString))/*)*/; } if (sheet->SheetId()==NLMISC::CSheetId::Unknown) { log.displayNL("Failed to identify sheet: %s",args[0].c_str()); return false; } log.displayNL("all these values are used to compute a score for a possible new target"); log.displayNL("beware the fact that in this version we used 'level' to represent relative force, it may be changed, so don't take too much time tuning courage"); log.displayNL("- DistModulator [0 n]: %f value=1/(1+distance*DistModulator)", sheet->DistModulator()); log.displayNL("value means the distance sensitivity of the bot, equals to zero means the bot never mind the distance"); log.displayNL("- TargetModulator [0 n]: %f value=1/(1+nbTarget*TargetModulator)", sheet->TargetModulator()); log.displayNL("value means the number of attacker sensitivity of the bot, equals to zero means the bot never mind the number of attackers on the target"); log.displayNL("- ScoreModulator [0 1]: %f score>ScoreModulator", sheet->ScoreModulator()); log.displayNL("value means the minimum value (threshold) needed for the bot to attack, 0 means always, 1 never (also impossible)"); log.displayNL("- FearModulator [0 1]: %f score>FearModulator", sheet->FearModulator()); log.displayNL("value means the minimum value (threshold) needed for the bot to flee, 0 means always, 1 never (also impossible)"); log.displayNL("- LifeLevelModulator [0 1]: %f value=LifeLevelModulator*lifeCoef+(1.f-LifeLevelModulator)*levelCoef", sheet->LifeLevelModulator()); log.displayNL("value means the ratio between the life and level ratio, 1 means life is only take in count, 0 means level only take in count"); log.displayNL("- CourageModulator [-n +n]: %f", sheet->CourageModulator()); log.displayNL("value used to make a bot courageous or feared, -n the bot is feared, +n its courageous"); log.displayNL("- GroupCohesionModulator [0 1]: %f", sheet->GroupCohesionModulator()); log.displayNL("value used to make bots of a group aware of each other, 0 each bot is individual, 1 they fight in group"); log.displayNL("- GroupDispersion [0 1]: %f", sheet->GroupDispersion()); log.displayNL("value used to make bots of a group far or not of each other, 0 each all bots are at the same place, 1 they go everywere in the place"); return true; } // all these values are used to compute a score for a possible new target // beware the fact that in this version we used 'level' to represent relative force, it may be changed, so don't take too much time tuning courage // // - DistModulator [0 n]: value=1/(1+distance*DistModulator) // value means the distance sensitivity of the bot, equals to zero means the bot never mind the distance // // - TargetModulator [0 n]: value=1/(1+nbTarget*TargetModulator) // value means the number of attacker sensitivity of the bot, equals to zero means the bot never mind the number of attackers on the target // // - ScoreModulator [0 1]: score>ScoreModulator // value means the minimum value (threshold) needed for the bot to attack, 0 means always, 1 never (also impossible) // // - FearModulator [0 1]: score>FearModulator // value means the minimum value (threshold) needed for the bot to flee, 0 means always, 1 never (also impossible) // // - LifeLevelModulator [0 1]: value=LifeLevelModulator*lifeCoef+(1.f-LifeLevelModulator)*levelCoef // value means the ratio between the life and level ratio, 1 means life is only take in count, 0 means level only take in count // // - CourageModulator [-n +n]: // value used to make a bot courageous or feared, -n the bot is feared, +n its courageous // // - GroupCohesionModulator [0 1]: // value used to make bots of a group aware of each other, 0 each bot is individual, 1 they fight in group /* NLMISC_COMMAND(setFightSheet,"change a value in the fight sheet"," (use name without 'modulator', ex: 'Dist')") { if (args.size() !=3) { log.displayNL("three argument needed"); return false; } AISHEETS::ICreature *sheet=const_cast(AISHEETS::CSheets::getInstance()->lookup(CSheetId(args[0]))); if (sheet->SheetId==NLMISC::CSheetId::Unknown) { std::string creatureString=args[0]+std::string(".creature"); sheet=const_cast(AISHEETS::CSheets::getInstance()->lookup(CSheetId(creatureString))); } if (sheet->SheetId==NLMISC::CSheetId::Unknown) { log.displayNL("Failed to identify sheet: %s",args[0].c_str()); return false; } float value = float(atof(args[2].c_str())); if (NLMISC::nlstricmp(args[1].c_str(), "dist")==0) { if (value<0) { log.displayNL("Failed, out of bounds, values accepted are [0 +n]"); return false; } sheet->DistModulator=value; log.displayNL("Done, DistModulator=%f", value); return true; } if (NLMISC::nlstricmp(args[1].c_str(), "target")==0) { if (value<0) { log.displayNL("Failed, out of bounds, values accepted are [0 +n]"); return false; } sheet->TargetModulator=value; log.displayNL("Done, TargetModulator=%f", value); return true; } if (NLMISC::nlstricmp(args[1].c_str(), "score")==0) { if (value<0 || value>1) { log.displayNL("Failed, out of bounds, values accepted are [0 +1]"); return false; } sheet->ScoreModulator=value; log.displayNL("Done, ScoreModulator=%f", value); return true; } if (NLMISC::nlstricmp(args[1].c_str(), "fear")==0) { if (value<0 || value>1) { log.displayNL("Failed, out of bounds, values accepted are [0 +1]"); return false; } sheet->FearModulator=value; log.displayNL("Done, FearModulator=%f", value); return true; } if (NLMISC::nlstricmp(args[1].c_str(), "LifeLevel")==0) { if (value<0 || value>1) { log.displayNL("Failed, out of bounds, values accepted are [0 +1]"); return false; } sheet->LifeLevelModulator=value; log.displayNL("Done, LifeLevelModulator=%f", value); return true; } if (NLMISC::nlstricmp(args[1].c_str(), "Courage")==0) { sheet->CourageModulator=value; log.displayNL("Done, CourageModulator=%f", value); return true; } if (NLMISC::nlstricmp(args[1].c_str(), "GroupCohesion")==0) { if (value<0 || value>1) { log.displayNL("Failed, out of bounds, values accepted are [0 +1]"); return false; } sheet->GroupCohesionModulator=value; log.displayNL("Done, GroupCohesionModulator=%f", value); return true; } if (NLMISC::nlstricmp(args[1].c_str(), "GroupDispersion")==0) { if (value<0 || value>1) { log.displayNL("Failed, out of bounds, values accepted are [0 +1]"); return false; } sheet->GroupDispersion=value; log.displayNL("Done, GroupDispersion=%f", value); return true; } log.displayNL("Failed to identify %s", args[1].c_str()); return false; } */ static void botSetPosition(CBot* bot, std::vector const& args, std::string const& botid, float x, float y, uint z, NLMISC::CLog& log) { CSpawnBot* spawnBot = bot->getSpawnObj(); if (spawnBot!=NULL) { std::string botname = bot->getAliasTreeOwner()->getName(); NLMISC::CEntityId eid = spawnBot->getEntityId(); std::string eidstr = eid.toString(); if (botid=="*" || (botname!="")&&(botname.find(botid)!=std::string::npos) || eidstr.find(botid)!=std::string::npos) { CAIPosMirror p = spawnBot->pos(); if (args.size()>0) { if (args.size()==3) z = p.h(); spawnBot->setPos(CAIPos(x, y, z, p.theta())); } p = spawnBot->pos(); if (botname!="") log.displayNL("Bot position for %s %s is %f;%f;%d", eidstr.c_str(), botname.c_str(), p.x().asDouble(), p.y().asDouble(), p.h()); else log.displayNL("Bot position for %s is %f;%f;%d", eidstr.c_str(), p.x().asDouble(), p.y().asDouble(), p.h()); } } } static void botSetPosition(CGroup* grp, std::vector const& args, std::string const& botid, float x, float y, uint z, NLMISC::CLog& log) { FOREACH (itBot, CCont, grp->bots()) { botSetPosition(*itBot, args, botid, x, y, z, log); } } static void botSetPosition(CManager* mgr, std::vector const& args, std::string const& botid, float x, float y, uint z, NLMISC::CLog& log) { FOREACH (itGroup, CCont, mgr->groups()) { botSetPosition(*itGroup, args, botid, x, y, z, log); } } NLMISC_COMMAND(botSetPosition,"set the position of one or several bots"," [ []]") { if (args.size()!=1 && args.size()!=3 && args.size()!=4) return false; std::string botid = args[0]; float x = 0.f; float y = 0.f; uint z = 0; if (args.size()>1) { x = (float)atof(args[1].c_str()); y = (float)atof(args[2].c_str()); if (args.size()==4) NLMISC::fromString(args[3], z); } // For each bot FOREACH (itInstance, CCont, CAIS::instance().AIList()) { FOREACH (itManager, CCont, itInstance->managers()) { botSetPosition(*itManager, args, botid, x, y, z, log); } FOREACH (itCont, CCont, itInstance->continents()) { FOREACH (itRegion, CCont, itCont->regions()) { FOREACH (itCellZone, CCont, itRegion->cellZones()) { FOREACH (itFamilyBehavior, CCont, itCellZone->familyBehaviors()) { botSetPosition(itFamilyBehavior->mgrNpc(), args, botid, x, y, z, log); botSetPosition(itFamilyBehavior->mgrFauna(), args, botid, x, y, z, log); } } } } } return true; } NLMISC_COMMAND(helpAboutId, "display a short explanation about id used in ai commands", "") { log.displayNL("AI Identifier are a string composed as follow :"); log.displayNL(" [AIS_:]{[][:mgr_idx][:grp_idx][:bot_idx] | dyn_[:][:][:][:fauna|:npc]}"); log.displayNL(" e.g. : - AIS_138:1:2:3:4 for a 'static' bot"); log.displayNL(" - AIS_138:dyn_0:2:3:4:npc for a 'dynmaic' npc manager"); log.displayNL("The initial 'AIS_:' is optional."); log.displayNL("Most of the commands that need an AI id support 'multi selection' by specifying only part of the id."); return true; } NLMISC_COMMAND(despawnEntity, "despawn an entity.","[entityId]") { if (args.size()!=1) return false; const std::string &entityStr=args[0]; const CEntityId entity(entityStr.c_str()); const TDataSetRow dataSetRow=TheDataset.getDataSetRow(entity); CAIEntityPhysical *const phys=CAIS::instance().getEntityPhysical(dataSetRow); if (!phys) { return true;} switch(phys->getRyzomType()) { case RYZOMID::creature: case RYZOMID::npc: { CSpawnBot *const bot=safe_cast(phys); if (!bot) break; bot->getPersistent().getGroup().bots().removeChildByIndex(bot->getPersistent().getChildIndex()); } break; case RYZOMID::pack_animal: { CSpawnBotPet *const pet=safe_cast(phys); if (!pet) break; pet->getPersistent().setDespawn(); } break; default: break; } return true; } /* Unload a primitive file * Unreference all the managers and the regions that are registered for this file. */ NLMISC_COMMAND(unloadPrimitiveFile,"unload a primitive file","") { if (args.size()!=1) return false; // Get the string ID const NLMISC::TStringId stringId=NLMISC::CStringMapper::map(CFile::getFilenameWithoutExtension(CFile::getFilename(args[0]))); uint managerUnreferenced = 0; uint continentUnreferenced = 0; // Parse AI instance CAIInstance *aiInstance = CWorkPtr::aiInstance(); if (aiInstance) { // Parse managers uint i; for (i=0; imanagers().size(); i++) { CSmartPtr manager=aiInstance->managers()[i]; if (manager) { // Remove this manager if (manager->isRegisteredForFile (stringId)) { aiInstance->managers().removeChildByIndex (i); managerUnreferenced++; // Check the pointer is not referenced anymore nlassert (manager->getRefCount() == 1); } } } // Parse continents for (i=0; icontinents().size(); i++) { CContinent *continent=aiInstance->continents()[i]; if (continent) { // Parse regions uint j; for (j=0; jregions().size(); j++) { CSmartPtr region=continent->regions()[j]; if (region) { // Remove this region if (region->isRegisteredForFile (stringId)) { continent->regions().removeChildByIndex (j); continentUnreferenced++; // Check the pointer is not referenced anymore nlassert (region->getRefCount() == 1); } } } } } aiInstance=CAIS::instance().AIList().getNextValidChild(aiInstance); uint32 primAlias = LigoConfig.getFileStaticAliasMapping(CFile::getFilename(args[0])); nldebug(" Sending alias '%u' to AIS for custom data range deletion", primAlias); CAIUserModelManager::getInstance()->deleteCustomDataByPrimAlias(primAlias); log.displayNL("unloadPrimitiveFile %s : %d manager removed, %d region removed", args[0].c_str(), managerUnreferenced, continentUnreferenced); } else log.displayNL("unloadPrimitiveFile failed : no active ai instance"); return true; } ////////////////////////////////////////////////////////////////////////////// // Bug simulation // ////////////////////////////////////////////////////////////////////////////// static bool bugSimulationInited = false; static bool bugSimulationTextInited = false; static int const bugSimulationCount = 10; static bool simulateBugs[bugSimulationCount]; static char const* simulateBugTexts[bugSimulationCount]; inline static void initBugSimulations() { if (!bugSimulationInited) { bugSimulationInited = true; for (int i=0; i=0 && bugId=0 && bugId []") { if (args.size()>=1) { if (args[0] == "list") { if (args.size()==1) { initBugSimulations(); initBugSimulationTexts(); log.displayNL("Bug simulations"); log.displayNL("Id|Description |State"); for (int i=0; i=0 && i=0 && i") { if (!args.empty()) return false; const CRyzomTime &rt = CTimeInterface::getRyzomTime(); displayTime(rt, log); return true; } NLMISC_COMMAND(localTime, "Display current local time (debug time).", "<>") { if (!args.empty()) return false; const CRyzomTime &rt = CTimeInterface::getRyzomDebugTime(); displayTime(rt, log); return true; } struct CRyzomDate { float Time; uint Day; uint Year; }; static void getRyzomDebugDate(CRyzomDate &rd) { const CRyzomTime &rt = CTimeInterface::getRyzomDebugTime(); rd.Time = rt.getRyzomTime(); rd.Day = rt.getRyzomDayOfYear(); rd.Year = rt.getRyzomYear(); } static void setRyzomDebugDate(CRyzomDate &rd) { CRyzomTime &rt = CTimeInterface::getRyzomDebugTime(); rt.updateRyzomClock((uint32) (rd.Time * RYZOM_HOURS_IN_TICKS) + (rd.Day + rd.Year * RYZOM_YEAR_IN_DAY) * RYZOM_DAY_IN_TICKS); } NLMISC_COMMAND(setDebugHour, "set the current debug hour", "") { if (args.size() != 1) return false; int hour; if (sscanf(args[0].c_str(), "%d", &hour) != 1) return false; CRyzomDate rd; getRyzomDebugDate(rd); rd.Time = fmodf(rd.Time, 1.f) + (float) hour; setRyzomDebugDate(rd); return true; } NLMISC_COMMAND(setDebugDayOfYear, "set the current debug day of year (first day has index 1)", "") { if (args.size() != 1) return false; int day; if (sscanf(args[0].c_str(), "%d", &day) != 1) return false; CRyzomDate rd; getRyzomDebugDate(rd); rd.Day = day - 1; // for the user, days start at '1' setRyzomDebugDate(rd); return true; } // // setPersistentVar setname:varName value // NLMISC_COMMAND(setPersistentVar, "sets an AI script persistent var", " []") { if (args.size() == 2) { std::string varName = args[0].c_str(); std::string value = args[1].c_str(); CAIScriptDataManager::getInstance()->setVar(varName, value); log.displayNL("Var '%s' set to '%s'", varName.c_str(), value.c_str()); return true; } return false; } // // listPersistentVar // NLMISC_COMMAND(listPersistentVar, "display all persistent vars", "") { if (!args.empty()) return false; const CPersistentVariables &persistentVar = CAIScriptDataManager::getInstance()->getPersistentVariables(); const TVariableSets &variableSet = persistentVar.getVariableSet(); for (TVariableSets::const_iterator i = variableSet.begin(); i != variableSet.end(); ++i) { log.displayNL("#Set: '%s'#", i->first.c_str()); for (TVariables::const_iterator j = i->second.Variables.begin(); j != i->second.Variables.end(); ++j) { log.displayNL("Name: '%s' -- Value: '%s'", j->first.c_str(), j->second.c_str()); } } return true; } // // getPersistentVar setname:varname // NLMISC_COMMAND(getPersistentVarAsString, "get a persistent ai var", "") { if (args.size() == 1) { std::string varName = args[0]; std::string value = CAIScriptDataManager::getInstance()->getVar_s(varName); log.displayNL("Variable '%s' has value '%s'", varName.c_str(), value.c_str() ); return true; } return false; } // // getPersistentVar setname:varname // NLMISC_COMMAND(getPersistentVarAsFloat, "get a persistent ai var", "") { if (args.size() == 1) { std::string varName = args[0]; float value = CAIScriptDataManager::getInstance()->getVar_f(varName); nlinfo("Variable '%s' has value '%f'", varName.c_str(), value ); return true; } return false; } NLMISC_COMMAND(deletePersistentVar, "deletes an AI script persistent var", "") { if (args.size() == 1) { std::string varName = args[0].c_str(); CAIScriptDataManager::getInstance()->deleteVar(varName); log.displayNL("Var '%s' deleted", varName.c_str()); return true; } return false; } //----------------------------------------------------------------------------