1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "continent.h"
21 #include "continent_inline.h"
25 #include "ai_entity_matrix.h"
26 #include "ai_player.h"
27 #include "ai_mgr_fauna.h"
28 #include "ai_grp_fauna.h"
29 #include "ai_grp_npc.h"
30 #include "ai_grp_pet.h"
31 #include "ai_bot_npc.h"
33 #include "server_share/mission_messages.h"
34 #include "game_share/fame.h"
35 #include "server_share/used_continent.h"
36 #include "ai_outpost.h"
37 #include "script_compiler.h"
38 #include "ais_actions.h"
39 #include "fx_entity_manager.h"
40 #include "ai_script_data_manager.h"
43 #include "ais_user_models.h"
45 extern bool GrpHistoryRecordLog
;
46 extern NLLIGO::CLigoConfig LigoConfig
;
48 using namespace NLMISC
;
49 using namespace NLNET
;
51 using namespace AITYPES
;
52 using namespace AICOMP
;
55 //////////////////////////////////////////////////////////////////////////////
56 // New set of commands //
57 //////////////////////////////////////////////////////////////////////////////
59 //- Generic commands ---------------------------------------------------------
61 RYAI_TEMPLATED_COMMAND(listInstances
, "display the list of ai instances", "[<filter>]", CAIInstance
, buildInstanceList
, displayList
)
62 RYAI_TEMPLATED_COMMAND(listContinents
, "display the list of continents", "[<filter>]", CContinent
, buildContinentList
, displayList
)
63 RYAI_TEMPLATED_COMMAND(listRegions
, "display the list of regions", "[<filter>]", CRegion
, buildRegionList
, displayList
)
64 RYAI_TEMPLATED_COMMAND(listCellZones
, "display the list of cell zones", "[<filter>]", CCellZone
, buildCellZoneList
, displayList
)
65 RYAI_TEMPLATED_COMMAND(listFamilyBehaviours
, "display the list of family behaviours", "[<filter>]", CFamilyBehavior
, buildFamilyBehaviorList
, displayList
)
66 RYAI_TEMPLATED_COMMAND(listOutposts
, "display the list of outposts", "[<filter>]", COutpost
, buildOutpostList
, displayList
)
67 RYAI_TEMPLATED_COMMAND(listManagers
, "display the list of managers", "[<filter>]", CManager
, buildManagerList
, displayList
)
68 RYAI_TEMPLATED_COMMAND(listNpcManagers
, "display the list of managers", "[<filter>]", CManager
, buildNpcManagerList
, displayList
)
69 RYAI_TEMPLATED_COMMAND(listGroups
, "display the list of groups", "[<filter>]", CGroup
, buildGroupList
, displayList
)
70 RYAI_TEMPLATED_COMMAND(listBots
, "display the list of bots", "[<filter>]", CBot
, buildBotList
, displayList
)
71 RYAI_TEMPLATED_COMMAND(listPlayers
, "display the list of players", "[<filter>]", CBotPlayer
, buildPlayerList
, displayList
)
72 RYAI_TEMPLATED_COMMAND(listFaunaPlaces
, "display the list of fauna places", "[<filter>]", CAIPlace
, buildFaunaPlaceList
, displayList
)
74 RYAI_TEMPLATED_COMMAND(enableFaunaPlace
, "enable a fauna place", "[<filter>]", CAIPlace
, buildFaunaPlaceList
, spawnList
)
75 RYAI_TEMPLATED_COMMAND(disableFaunaPlace
, "disable a fauna place", "[<filter>]", CAIPlace
, buildFaunaPlaceList
, despawnList
)
79 RYAI_TEMPLATED_COMMAND(displayInstances
, "display extensively the list of ai instances", "[<filter>]", CAIInstance
, buildInstanceList
, displayListEx
)
80 RYAI_TEMPLATED_COMMAND(displayContinents
, "display extensively the list of continents", "[<filter>]", CContinent
, buildContinentList
, displayListEx
)
81 RYAI_TEMPLATED_COMMAND(displayRegions
, "display extensively the list of regions", "[<filter>]", CRegion
, buildRegionList
, displayListEx
)
82 RYAI_TEMPLATED_COMMAND(displayCellZones
, "display extensively the list of cell zones", "[<filter>]", CCellZone
, buildCellZoneList
, displayListEx
)
83 RYAI_TEMPLATED_COMMAND(displayFamilyBehaviours
, "display extensively the list of family behaviours", "[<filter>]", CFamilyBehavior
, buildFamilyBehaviorList
, displayListEx
)
84 //RYAI_TEMPLATED_COMMAND(displayOutposts, "display extensively the list of outposts", "[<filter>]", COutpost, buildOutpostList, displayListEx)
85 RYAI_TEMPLATED_COMMAND(displayManagers
, "display extensively the list of managers", "[<filter>]", CManager
, buildManagerList
, displayListEx
)
86 RYAI_TEMPLATED_COMMAND(displayGroups
, "display extensively the list of groups", "[<filter>]", CGroup
, buildGroupList
, displayListEx
)
87 RYAI_TEMPLATED_COMMAND(displayBots
, "display extensively the list of bots", "[<filter>]", CBot
, buildBotList
, displayListEx
)
88 RYAI_TEMPLATED_COMMAND(displayPlayers
, "display extensively the list of players", "[<filter>]", CBotPlayer
, buildPlayerList
, displayListEx
)
90 RYAI_TEMPLATED_COMMAND(spawnInstances
, "spawns the ai instances", "[<filter>]", CAIInstance
, buildInstanceList
, spawnList
)
91 //RYAI_TEMPLATED_COMMAND(spawnContinents, "spawns the continents", "[<filter>]", CContinent, buildContinentList, spawnList)
92 //RYAI_TEMPLATED_COMMAND(spawnRegions, "spawns the regions", "[<filter>]", CRegion, buildRegionList, spawnList)
93 //RYAI_TEMPLATED_COMMAND(spawnCellZones, "spawns the cell zones", "[<filter>]", CCellZone, buildCellZoneList, spawnList)
94 //RYAI_TEMPLATED_COMMAND(spawnFamilyBehaviours, "spawns the family behaviours", "[<filter>]", CFamilyBehavior, buildFamilyBehaviorList, spawnList)
95 //RYAI_TEMPLATED_COMMAND(spawnOutposts, "spawns the outposts", "[<filter>]", COutpost, buildOutpostList, spawnList)
96 RYAI_TEMPLATED_COMMAND(spawnManagers
, "spawns the managers", "[<filter>]", CManager
, buildManagerList
, spawnList
)
97 RYAI_TEMPLATED_COMMAND(spawnGroups
, "spawns the groups", "[<filter>]", CGroup
, buildGroupList
, spawnList
)
98 //RYAI_TEMPLATED_COMMAND(spawnBots, "spawns the bots", "[<filter>]", CBot, buildBotList, spawnList)
99 //RYAI_TEMPLATED_COMMAND(spawnPlayers, "spawns the players", "[<filter>]", CBotPlayer, buildPlayerList, spawnList)
101 RYAI_TEMPLATED_COMMAND(despawnInstances
, "despawns the ai instances", "[<filter>]", CAIInstance
, buildInstanceList
, despawnList
)
102 //RYAI_TEMPLATED_COMMAND(despawnContinents, "despawns the continents", "[<filter>]", CContinent, buildContinentList, despawnList)
103 //RYAI_TEMPLATED_COMMAND(despawnRegions, "despawns the regions", "[<filter>]", CRegion, buildRegionList, despawnList)
104 //RYAI_TEMPLATED_COMMAND(despawnCellZones, "despawns the cell zones", "[<filter>]", CCellZone, buildCellZoneList, despawnList)
105 //RYAI_TEMPLATED_COMMAND(despawnFamilyBehaviours, "despawns the family behaviours", "[<filter>]", CFamilyBehavior, buildFamilyBehaviorList, despawnList)
106 //RYAI_TEMPLATED_COMMAND(despawnOutposts, "despawns the outposts", "[<filter>]", COutpost, buildOutpostList, despawnList)
107 RYAI_TEMPLATED_COMMAND(despawnManagers
, "despawns the managers", "[<filter>]", CManager
, buildManagerList
, despawnList
)
108 RYAI_TEMPLATED_COMMAND(despawnGroups
, "despawns the groups", "[<filter>]", CGroup
, buildGroupList
, despawnList
)
109 //RYAI_TEMPLATED_COMMAND(despawnBots, "despawns the bots", "[<filter>]", CBot, buildBotList, despawnList)
110 //RYAI_TEMPLATED_COMMAND(despawnPlayers, "despawns the players", "[<filter>]", CBotPlayer, buildPlayerList, despawnList)
112 //- Special commands ---------------------------------------------------------
114 NLMISC_COMMAND(search
, "search all the data tree for a name part","<name_part>")
116 if (args
.size() != 1)
120 log
.displayNL("- Search results in instances ------------------------------------------------");
121 std::deque
<CAIInstance
*> container
;
122 buildInstanceList(container
);
123 displayList(log
, container
, args
[0]);
127 log
.displayNL("- Search results in continents -----------------------------------------------");
128 std::deque
<CContinent
*> container
;
129 buildContinentList(container
);
130 displayList(log
, container
, args
[0]);
134 log
.displayNL("- Search results in regions --------------------------------------------------");
135 std::deque
<CRegion
*> container
;
136 buildRegionList(container
);
137 displayList(log
, container
, args
[0]);
141 log
.displayNL("- Search results in cell zones -----------------------------------------------");
142 std::deque
<CCellZone
*> container
;
143 buildCellZoneList(container
);
144 displayList(log
, container
, args
[0]);
148 log
.displayNL("- Search results in family behaviors -----------------------------------------");
149 std::deque
<CFamilyBehavior
*> container
;
150 buildFamilyBehaviorList(container
);
151 displayList(log
, container
, args
[0]);
155 log
.displayNL("- Search results in outposts -------------------------------------------------");
156 std::deque
<COutpost
*> container
;
157 buildOutpostList(container
);
158 displayList(log
, container
, args
[0]);
162 log
.displayNL("- Search results in managers -------------------------------------------------");
163 std::deque
<CManager
*> container
;
164 buildManagerList(container
);
165 displayList(log
, container
, args
[0]);
169 log
.displayNL("- Search results in groups ---------------------------------------------------");
170 std::deque
<CGroup
*> container
;
171 buildGroupList(container
);
172 displayList(log
, container
, args
[0]);
176 log
.displayNL("- Search results in bots -----------------------------------------------------");
177 std::deque
<CBot
*> container
;
178 buildBotList(container
);
179 displayList(log
, container
, args
[0]);
183 log
.displayNL("- Search results in players --------------------------------------------------");
184 std::deque
<CBotPlayer
*> container
;
185 buildPlayerList(container
);
186 displayList(log
, container
, args
[0]);
192 //----------------------------------------------------------------------------
194 NLMISC_COMMAND(eventCreateNpcGroup
, "create an event npc group", "<aiInstanceId> <nbBots> <sheet> <x> <y> [<dispersionRadius=10m> [<spawnBots=true> [<orientation=random|-360..360> [<name>]]]]")
199 CLogStringWriter
stringWriter(&log
);
201 CAIInstance
* aiInstance
= NULL
;
203 uint32 aiInstanceId
= NLMISC::atoui(args
[0].c_str());
204 if (aiInstanceId
>=CAIS::instance().aiinstances().size())
206 stringWriter
.append("Invalid AI Instance Number");
209 aiInstance
= CAIS::instance().aiinstances()[aiInstanceId
];
212 stringWriter
.append("AI Instance do not exists");
217 uint32 nbBots
= NLMISC::atoui(args
[1].c_str());
220 stringWriter
.append("invalid bot count");
224 NLMISC::CSheetId
sheetId(args
[2]);
225 if (sheetId
==NLMISC::CSheetId::Unknown
)
226 sheetId
= args
[2] + ".creature";
227 if (sheetId
==NLMISC::CSheetId::Unknown
)
229 stringWriter
.append("invalid sheet id");
234 NLMISC::fromString(args
[3], x
);
235 NLMISC::fromString(args
[4], y
);
237 double dispersionRadius
= 10.;
240 dispersionRadius
= atof(args
[5].c_str());
241 if (dispersionRadius
<0.)
243 stringWriter
.append("invalid dispersion radius");
248 bool spawnBots
= true;
251 NLMISC::fromString(args
[6], spawnBots
);
254 double orientation
= 6.666;
255 if (args
.size()>7 && args
[7] != "random")
257 NLMISC::fromString(args
[7], orientation
);
258 orientation
= orientation
/ 360.0 * (NLMISC::Pi
* 2.0);
261 std::string botsName
;
262 if (args
.size()>8) botsName
= args
[8];
264 aiInstance
->eventCreateNpcGroup(nbBots
, sheetId
, CAIVector(x
, y
), dispersionRadius
, spawnBots
, orientation
, botsName
, "");
269 //----------------------------------------------------------------------------
271 NLMISC_COMMAND(listFxEntities
, "", "[<filter>]")
274 displayList(log
, CFxEntityManager::getInstance()->getEntities(), args
[0]);
276 displayList(log
, CFxEntityManager::getInstance()->getEntities());
280 //////////////////////////////////////////////////////////////////////////////
282 //////////////////////////////////////////////////////////////////////////////
283 // Old set of commands //
284 //////////////////////////////////////////////////////////////////////////////
286 // Dump the road/zone connectivity
287 NLMISC_COMMAND(dumpRoadCon
, "dump road/cell connectivity graph","<continentName> [<ai instance number = 0>]")
292 uint instanceIndex
= 0;
294 if (args
.size() == 2)
295 NLMISC::fromString(args
[1], instanceIndex
);
297 if (instanceIndex
>= CAIS::instance().AIList().size())
299 log
.displayNL("ai index %u is out of range ! (only %u ai instance)",
301 CAIS::instance().AIList().size());
305 CAIInstance
*aii
= CAIS::instance().AIList()[instanceIndex
];
307 for (uint i
=0; i
<aii
->continents().size(); ++i
)
309 CContinent
*cont
= aii
->continents()[i
];
314 || cont
->getName()==args
[0])
316 log
.displayRawNL("Dumping connection in '%s' (@ %p):",
317 cont
->getName().c_str(),
320 CAliasCont
<CRegion
> ®ions
= cont
->regions();
322 for (uint i
=0; i
<regions
.size(); ++i
)
324 CRegion
*region
= regions
[i
];
328 CAliasCont
<CCellZone
> &cellZones
= region
->cellZones();
330 for (uint i
=0; i
<cellZones
.size(); ++i
)
332 CCellZone
*czone
= cellZones
[i
];
333 if (!czone
) continue;
334 for (uint j
=0; j
<czone
->cells().size(); ++j
)
336 CCell
*cell
= czone
->cells()[j
];
339 set
<NLMISC::CDbgPtr
<CCell
> >::iterator
first(cell
->_NeighbourCells
.begin()), last(cell
->_NeighbourCells
.end());
340 for (; first
!= last
; ++first
)
342 nldebug("Link '%s' => '%s'", cell
->getName().c_str(), (*first
)->getName().c_str());
348 for (uint i
=0; i
<cellZones
.size(); ++i
)
350 CCellZone
*czone
= cellZones
[i
];
351 if (!czone
) continue;
352 for (uint j
=0; j
<czone
->cells().size(); ++j
)
354 CCell
*cell
= czone
->cells()[j
];
356 // bound the point into the cell
357 for (uint k
=0; k
<cell
->npcZoneCount(); ++k
)
359 CNpcZone
*nz
= cell
->npcZone(k
);
363 for (uint l
=0; l
<nz
->roads().size(); ++l
)
365 nldebug("NpcZone '%s' host road '%s'", nz
->getAliasTreeOwner().getName().c_str(), nz
->roads()[l
]->getName().c_str());
370 CAliasCont
<CRoad
> &roads
= cell
->roads();
371 for (uint i
=0; i
<roads
.size(); ++i
)
373 CRoad
*road
= roads
[i
];
376 // clear existing link;
377 nldebug("Road '%s' link from '%s' %s to '%s' %s", road
->getName().c_str(),
378 road
->startZone().isNULL() ? "none" : road
->startZone()->getAliasTreeOwner().getName().c_str(),
379 road
->startExternal() ? "(external)" : "",
380 road
->endZone().isNULL() ? "none" : road
->endZone()->getAliasTreeOwner().getName().c_str(),
381 road
->endExternal() ? "(external)" : "");
394 bool dumpContinentImp(uint instanceIndex
, const std::string
&continentName
, NLMISC::CLog
&log
);
395 // Dump the structure of a dynamic continent
396 NLMISC_COMMAND(dumpContinent
, "dump the structure of a continent","<continentName> [<ai instance number = 0>]")
398 if (args
.size() > 2 || args
.size() < 1)
401 uint instanceIndex
= 0;
403 if (args
.size() == 2)
404 NLMISC::fromString(args
[1], instanceIndex
);
406 if (instanceIndex
>= CAIS::instance().AIList().size())
408 log
.displayNL("ai index %u is out of range ! (only %u ai instance)",
410 CAIS::instance().AIList().size());
414 return dumpContinentImp(instanceIndex
, args
[0], log
);
417 bool dumpContinentImp(uint instanceIndex
, const std::string
&continentName
, NLMISC::CLog
&log
)
419 CAIInstance
*aii
= CAIS::instance().AIList()[instanceIndex
];
421 for (uint i
=0; i
<aii
->continents().size(); ++i
)
423 CContinent
*cont
= aii
->continents()[i
];
426 if (cont
->getName()==continentName
)
428 log
.displayRawNL("Dumping continent '%s' (@ %p):",
429 cont
->getName().c_str(),
432 for (uint j
=0; j
<cont
->regions().size(); ++j
)
434 CRegion
*region
= cont
->regions()[j
];
437 log
.displayNL(" +- %u null entry", j
);
441 log
.displayNL(" +- Region '%s'%s @ %p",
442 region
->getName().c_str(),
443 region
->getAliasString().c_str(),
444 static_cast<CAliasTreeOwner
*>(region
));
446 for (uint k
=0; k
<region
->cellZones().size(); ++k
)
448 CCellZone
*cz
= region
->cellZones()[k
];
451 log
.displayNL(" | +- %u null entry", k
);
455 log
.displayNL(" | +- CellZone '%s'%s @ %p",
456 cz
->getName().c_str(),
457 cz
->getAliasString().c_str(),
458 static_cast<CAliasTreeOwner
*>(cz
));
460 for (uint l
=0; l
<cz
->cells().size(); ++l
)
462 CCell
*cell
= cz
->cells()[l
];
465 log
.displayNL(" | | +- %u null entry", l
);
469 log
.displayNL(" | | +- Cell '%s'%s @ %p",
470 cell
->getName().c_str(),
471 cell
->getAliasString().c_str(),
472 static_cast<CAliasTreeOwner
*>(cell
));
474 for (uint m
=0; m
<cell
->npcZoneCount(); ++m
)
476 CNpcZone
*nz
= cell
->npcZone(m
);
479 log
.displayNL(" | | | +- %u null entry", m
);
483 // log.displayNL(" | | | +- NpcZone '%s' (alias A:%u @ %p)", nz->getName().c_str(), nz->getAlias(), static_cast<CAliasTreeOwner*>(nz));
484 log
.displayNL(" | | | +- NpcZone '%s'%s",
485 nz
->getAliasTreeOwner().getName().c_str(),
486 nz
->getAliasTreeOwner().getAliasString().c_str());
490 for (uint k
=0; k
<cell
->roads().size(); ++k
)
492 CRoad
*road
= cell
->roads()[k
];
495 log
.displayNL(" | | +- %u null entry", k
);
499 log
.displayNL(" | | +- Road '%s'%s @ %p",
500 road
->getName().c_str(),
501 road
->getAliasString().c_str(),
502 static_cast<CAliasTreeOwner
*>(road
));
505 for (uint m
=0; m
<cell
->faunaZones().size(); ++m
)
507 CFaunaZone
*fz
= cell
->faunaZones()[m
];
510 log
.displayNL(" | | | +- %u null entry", m
);
514 log
.displayNL(" | | | +- FaunaZone '%s'%s @ %p",
515 fz
->getName().c_str(),
516 fz
->getAliasString().c_str(),
517 static_cast<CAliasTreeOwner
*>(fz
));
528 log
.displayNL("Can't find continent '%s' in ai instance %u",
529 continentName
.c_str(),
537 // Load a collision map
538 NLMISC_COMMAND(loadContinent
, "load a continent collision map","<landName>")
540 if (args
.size() != 1)
543 CWorldContainer::loadContinent(args
[0]);
549 CAIInstance
*currentInstance
= NULL
;
551 NLMISC_COMMAND(createDynamicAIInstance
, "Create a new dynamic AIInstance","")
553 if (args
.size() != 1)
556 // find an unused continent id
558 NLMISC::fromString(args
[0], in
);
559 if( !CAIS::instance().getAIInstance(in
) )
561 std::string name
= NLMISC::toString("ring_%d",in
);
562 const int index
= CAIS::instance().createAIInstance(name
, in
);
564 nlinfo("AIInstance %u created for continent '%s' (Instance Index : %u)", in
, name
.c_str(), index
);
568 // activate the current AIInstance
569 currentInstance
= CAIS::instance().getAIInstance(in
); //CAIS::instance().getAIInstance(continentInstanceId);
570 CWorkPtr::aiInstance(currentInstance
);
574 NLMISC_COMMAND(createStaticAIInstance
, "Create a new static AIInstance for a given continent.","<continentName>")
576 if (args
.size() != 1)
579 CUsedContinent
&uc
= CUsedContinent::instance();
581 const uint32 in
= uc
.getInstanceForContinent(args
[0]);
582 if (in
== std::numeric_limits
<uint32
>::max())
584 nlwarning("The continent '%s' is unknow or not active. Can't create instance, FATAL", args
[0].c_str());
586 // nlassertex(in != ~0, ("The continent '%s' is unknow or not active. Can't create instance, FATAL", args[0].c_str()));
589 if (!CAIS::instance().getAIInstance(in
))
591 const int index
= CAIS::instance().createAIInstance(args
[0], in
);
592 nlinfo("AIInstance %u created for continent '%s' (Instance Index : %u)",
593 in
, args
[0].c_str(), index
);
596 // activate the current AIInstance
597 currentInstance
= CAIS::instance().getAIInstance(in
); //CAIS::instance().getAIInstance(continentInstanceId);
601 NLMISC_COMMAND(autoConfig
, "Automaticaly load collision map, create AIInstance and load the primitives","")
606 CUsedContinent
&uc
= CUsedContinent::instance();
608 log
.displayNL("AIS Auto config with %u continents...", uc
.getContinents().size());
609 for (uint i
=0; i
<uc
.getContinents().size(); ++i
)
611 const CUsedContinent::TContinentInfo
&ci
= uc
.getContinents()[i
];
613 // translate logical continent name
614 const string
&phyName
= uc
.getPhysicalContinentName(ci
.ContinentName
);
616 // load the collision map
617 ICommand::execute(toString("loadContinent %s", phyName
.c_str()), log
);
618 // create the AI Instance
619 ICommand::execute(toString("createStaticAIInstance %s", ci
.ContinentName
.c_str()), log
);
620 // load the active maps
621 ICommand::execute(toString("loadMapsFromCommon %s_all", ci
.ContinentName
.c_str()), log
);
627 bool getParameter(const std::string
&srcStr
, const std::string
&keyWord
, std::string
&returnStr
)
629 if (srcStr
.find(keyWord
)!=std::string::npos
)
631 returnStr
=srcStr
.substr(keyWord
.size(),std::string::npos
);
634 returnStr
=std::string();
638 //-------------------------------------------------------------------------
639 // set/get the energy value for a family (global version)
640 NLMISC_COMMAND(energy
, "set or get the effective energy (affects group type).","[cellZone-<cellZoneName>] [family-<familyName>] [value-<value>] [detailled]")
643 std::string cellZoneName
;
645 bool detailled
=false;
647 CLogStringWriter
stringWriter(&log
);
650 for (uint32 i
=0;i
<args
.size();i
++)
652 const std::string
&str
=args
[i
];
655 if (getParameter(str
,"cellZone-",res
))
660 if (getParameter(str
,"family-",res
))
665 if (getParameter(str
,"value-",res
))
667 float v
=float(atof(res
.c_str()));
669 value
=uint32(v
* ENERGY_SCALE
);
672 if (getParameter(str
,"detailled",res
))
679 const CStringFilter
familyFilter(family
);
681 for (uint i
=0; i
<CAIS::instance().AIList().size(); ++i
)
683 CAIInstance
*aii
= CAIS::instance().AIList()[i
];
687 for (uint j
=0; j
<aii
->continents().size(); ++j
)
689 CContinent
*cont
= aii
->continents()[j
];
693 for (uint k
=0; k
<cont
->regions().size(); ++k
)
695 CRegion
*r
= cont
->regions()[k
];
699 for (uint l
=0; l
<r
->cellZones().size(); ++l
)
701 CCellZone
*cz
= r
->cellZones()[l
];
705 if ( !cellZoneName
.empty()
706 && cz
->getAliasFullName()!=cellZoneName
)
710 stringWriter
.append("");
712 for (uint m
=0; m
<cz
->_Families
.size(); ++m
)
714 CFamilyBehavior
*fb
= cz
->_Families
[m
];
718 // || ( !family.empty()
719 // && familyFilter!=fb->getFamily().getFamilyName()))
724 if (value
==~0) // not for affectation.
726 fb
->displayLogOld (stringWriter
, detailled
);
730 fb
->setEffectiveLevel (value
);
746 virtual ~CDoOnFamily()
748 virtual void doOnFamily (CFamilyBehavior
*fb
) const = 0;
749 virtual void doOnCellZone (CCellZone
*cz
) const = 0;
755 bool doOnFamily (const std::vector
<std::string
> &args
, CDoOnFamily
*fam
)
758 std::string cellZoneName
;
760 for (uint32 i
=0;i
<args
.size();i
++)
762 const std::string
&str
=args
[i
];
765 if (getParameter(str
,"cellZone-",res
))
768 if (getParameter(str
,"family-",res
))
772 const CStringFilter
familyFilter(family
);
774 FOREACH(aiiIt
, CCont
<CAIInstance
>, CAIS::instance().AIList())
776 FOREACH(contIt
, CCont
<CContinent
>, (*aiiIt
)->continents())
778 FOREACH(rIt
, CCont
<CRegion
>, (*contIt
)->regions())
780 FOREACH(czIt
, CCont
<CCellZone
>, (*rIt
)->cellZones())
782 if ( !cellZoneName
.empty()
783 && czIt
->getAliasFullName()!=cellZoneName
)
786 fam
->doOnCellZone(*czIt
);
788 FOREACH(fb
, CCont
<CFamilyBehavior
>, czIt
->_Families
)
791 && familyFilter
!=fb
->getName())
794 fam
->doOnFamily(*fb
);
804 class CDoOnFamilyCommand
808 CDoOnFamilyCommand (const std::vector
<std::string
> &args
, NLMISC::CLog
&log
)
814 for (uint32 i
=0;i
<args
.size();i
++)
816 const std::string
&str
=args
[i
];
818 if (getParameter(str
,"index-",res
))
819 NLMISC::fromString(res
, _index
);
820 if (getParameter(str
,"value-",res
))
821 _value
=float(atof(res
.c_str()));
822 _detailled
|=getParameter(str
,"detailled",res
);
826 void doOnFamily(CFamilyBehavior
*fb
) const
828 if (_value
==-1) // not for affectation.
830 fb
->displayLogOld (_stringWriter
, _detailled
);
833 if (_index
==~0) // all indexs ?
835 for (uint32 nrjIndex
=0;nrjIndex
<4;nrjIndex
++)
836 fb
->setModifier (_value
, nrjIndex
);
839 fb
->setModifier (_value
, (uint32
)_index
);
842 virtual void doOnCellZone(CCellZone
*cz
) const
845 _stringWriter
.append("");
852 mutable CLogStringWriter _stringWriter
;
856 NLMISC_COMMAND(energyscalemodifier
, "set or get the energy scale (affects group number).","[cellZone-<cellZoneName>] [family-<familyName>] [index-<index>] [value-<value>] [detailled]")
858 CDoOnFamilyCommand
command(args
, log
);
859 return doOnFamily (args
, &command
);
862 NLMISC_COMMAND(energyScaleModifier2
, "set or get the energy scale (affects group number).","[--cellZone=<cellZoneName>] [--family=<familyName>] [--index=<index>] [--value=<value>] [--detailled]")
864 std::string cellZoneName
;
865 std::string familyName
;
868 bool detailed
= false;
869 for (size_t i
=0; i
<args
.size(); ++i
)
871 std::string
const& str
= args
[i
];
873 if (getParameter(str
, "--cellZone=", res
))
875 if (getParameter(str
, "--family=", res
))
877 if (getParameter(str
, "--index=", res
))
878 fromString(res
, index
);
879 if (getParameter(str
, "--value=", res
))
880 fromString(res
, value
);
881 if (str
== "--detailed")
887 std::vector
<size_t> widths(10, 0);
888 CFamilyBehavior::checkLogHeadersWidths(widths
, index
, detailed
);
889 FOREACH(itInstance
, CCont
<CAIInstance
>, CAIS::instance().AIList())
891 FOREACH(itContinent
, CCont
<CContinent
>, itInstance
->continents())
893 FOREACH(itRegion
, CCont
<CRegion
>, itContinent
->regions())
895 FOREACH(itCellZone
, CCont
<CCellZone
>, itRegion
->cellZones())
897 CCellZone
* cellZone
= *itCellZone
;
898 if (!cellZone
|| !cellZoneName
.empty() && cellZone
->getName()!=cellZoneName
)
900 FOREACH(itFamilyBehavior
, CCont
<CFamilyBehavior
>, cellZone
->familyBehaviors())
902 CFamilyBehavior
* familyBehavior
= *itFamilyBehavior
;
903 if (!familyBehavior
|| !familyName
.empty() && familyBehavior
->getName()!=familyName
)
905 familyBehavior
->checkLogWidths(widths
, index
, detailed
);
911 CLogStringWriter
stringWriter(&log
);
912 CFamilyBehavior::displayLogLine(stringWriter
, index
, detailed
, widths
);
913 CFamilyBehavior::displayLogHeaders(stringWriter
, index
, detailed
, widths
);
914 CFamilyBehavior::displayLogLine(stringWriter
, index
, detailed
, widths
);
915 FOREACH(itInstance
, CCont
<CAIInstance
>, CAIS::instance().AIList())
917 FOREACH(itContinent
, CCont
<CContinent
>, itInstance
->continents())
919 FOREACH(itRegion
, CCont
<CRegion
>, itContinent
->regions())
921 FOREACH(itCellZone
, CCont
<CCellZone
>, itRegion
->cellZones())
923 CCellZone
* cellZone
= *itCellZone
;
924 if (!cellZone
|| !cellZoneName
.empty() && cellZone
->getName()!=cellZoneName
)
926 FOREACH(itFamilyBehavior
, CCont
<CFamilyBehavior
>, cellZone
->familyBehaviors())
928 CFamilyBehavior
* familyBehavior
= *itFamilyBehavior
;
929 if (!familyBehavior
|| !familyName
.empty() && familyBehavior
->getName()!=familyName
)
931 familyBehavior
->displayLog(stringWriter
, index
, detailed
, widths
);
937 CFamilyBehavior::displayLogLine(stringWriter
, index
, detailed
, widths
);
948 NLMISC_COMMAND(globalEnergy
, "set or get the effective energy for a family.","[<familyName> [<value>]]")
955 CLogStringWriter
stringWriter(&log
);
963 if (args
.size() == 2)
965 float v
= float(atof(args
[1].c_str()));
967 stringWriter
.append("Setting effective energy level for '"+family
+"' to "+toString(v
));
968 value
= uint32(v
* ENERGY_SCALE
);
971 for (uint i
=0; i
<CAIS::instance().AIList().size(); ++i
)
973 CAIInstance
*aii
= CAIS::instance().AIList()[i
];
977 for (uint j
=0; j
<aii
->continents().size(); ++j
)
979 CContinent
*cont
= aii
->continents()[j
];
983 for (uint k
=0; k
<cont
->regions().size(); ++k
)
985 CRegion
*r
= cont
->regions()[k
];
989 for (uint l
=0; l
<r
->cellZones().size(); ++l
)
991 CCellZone
*cz
= r
->cellZones()[l
];
995 stringWriter
.append("");
997 for (uint m
=0; m
<cz
->_Families
.size(); ++m
)
999 CFamilyBehavior
*fb
= cz
->_Families
[m
];
1004 || ( args
.size() == 1
1005 && family
== fb
->getName())
1008 fb
->displayLogOld (stringWriter
, args
.size()==1);
1012 if ( args
.size() == 2
1013 && family
== fb
->getName())
1015 fb
->setEffectiveLevel(value
);
1025 //-------------------------------------------------------------------------
1027 // NLMISC_COMMAND(statMemory, "generate a memory usage statistic file","<begin|end>")
1029 // if (args.size() != 1)
1032 // CLogStringWriter stringWriter(&log);
1034 // if (args[0] == "begin")
1036 // stringWriter.append("Writing begin memory state in 'memory_report_begin.csv'...");
1037 // NLMEMORY::StatisticsReport("memory_report_begin.csv", false);
1038 // stringWriter.append("Memory stat Done.");
1040 // else if (args[0] == "end")
1042 // stringWriter.append("Writing end memory state report in 'memory_report_end.csv'...");
1043 // NLMEMORY::StatisticsReport("memory_report_end.csv", false);
1044 // stringWriter.append("Memory stat Done.");
1052 //-------------------------------------------------------------------------
1053 // set a group variable
1055 NLMISC_COMMAND(setGroupVar
,"display the logic var of the group in the given AI Instance","<aiInstanceId> <group_name|group_alias> <varId> <value>")
1062 CLogStringWriter
stringWriter(&log
);
1064 CAIInstance
*aiInstance
=NULL
;
1066 uint32 aiInstanceId
= NLMISC::atoui(args
[0].c_str());
1067 if (aiInstanceId
>CAIS::instance().AIList().size())
1069 stringWriter
.append("Invalid AI Instance Number");
1072 aiInstance
=CAIS::instance().AIList()[aiInstanceId
];
1075 stringWriter
.append("AI Instance do not exists");
1081 // first, try to find the group by alias
1082 uint32 alias
= NLMISC::atoui(args
[1].c_str());
1085 grp
= aiInstance
->findGroup(alias
);
1090 /// try to find the group bt name
1091 std::vector
<CGroup
*> grps
;
1092 aiInstance
->findGroup(grps
, args
[1]);
1093 if (grps
.size() > 1)
1096 for (uint i
=0; i
<grps
.size(); ++i
)
1098 s
+= NLMISC::toString("%s ", grps
[i
]->aliasTreeOwner()->getAliasString().c_str());
1100 stringWriter
.append("More than one group have name '"+args
[1]+"', listing alias :");
1101 stringWriter
.append(s
);
1105 else if (grps
.empty())
1107 stringWriter
.append("No group correspond to name '"+args
[1]+"'");
1116 // retreive the varID.
1117 // uint32 varId = NLMISC::atoui(args[2].c_str());
1118 NLMISC::TStringId varId
=CStringMapper::map(args
[2]); // NLMISC::atoui(args[2].c_str());
1119 float value
= float(atof(args
[3].c_str()));
1122 CStateInstance
*stateInstance
=grp
->getPersistentStateInstance();
1123 stringWriter
.append(grp
->aliasTreeOwner()->getName()+":"+toString(*varId
)+" = "+toString(value
)+" (old value : "+ toString(stateInstance
->getLogicVar(varId
))+" )");
1124 stateInstance
->setLogicVar(varId
, value
);
1129 //-------------------------------------------------------------------------
1130 // display group variable
1132 NLMISC_COMMAND(displayGroupVar
,"display the logic var of the group in the given AI Instance","<aIInstanceId> <group_name|group_alias>")
1137 CLogStringWriter
stringWriter(&log
);
1139 CAIInstance
*aiInstance
=NULL
;
1141 uint32 aiInstanceId
= NLMISC::atoui(args
[0].c_str());
1142 if (aiInstanceId
>CAIS::instance().AIList().size())
1144 stringWriter
.append("Invalid AI Instance Number");
1147 aiInstance
=CAIS::instance().AIList()[aiInstanceId
];
1150 stringWriter
.append("AI Instance do not exists");
1158 // first, try to find the group by alias
1159 uint32 alias
= NLMISC::atoui(args
[1].c_str());
1162 grp
= aiInstance
->findGroup(alias
);
1167 /// try to find the group bt name
1168 std::vector
<CGroup
*> grps
;
1169 aiInstance
->findGroup(grps
, args
[1]);
1170 if (grps
.size() > 1)
1173 for (uint i
=0; i
<grps
.size(); ++i
)
1175 s
+= NLMISC::toString("%s ", grps
[i
]->aliasTreeOwner()->getAliasString().c_str());
1177 stringWriter
.append("More than one group have name '"+args
[1]+"', listing alias :");
1178 stringWriter
.append(s
);
1181 else if (grps
.empty())
1183 stringWriter
.append("No group correspond to name '"+args
[1]+"'");
1192 stringWriter
.append("Logic var of group '"+grp
->aliasTreeOwner()->getName()+"'");
1195 // parser les variables pour outputer le contenu ..
1198 const CStateInstance
*stateInstance
=grp
->getPersistentStateInstance();
1201 stateInstance
->logicVarsToString(str
);
1202 stringWriter
.append(str
);
1211 //-------------------------------------------------------------------------
1212 // display the player teams data
1214 NLMISC_COMMAND(displayPlayerTeams
,"display all the player teams"," [<-no_detail>]")
1216 bool noDetail
= false;
1221 && args
[args
.size()-1]=="-no_detail")
1224 CCont
<CAIInstance
>::iterator it
=CAIS::instance().AIList().begin(), itEnd
=CAIS::instance().AIList().end();
1226 CLogStringWriter
stringWriter(&log
);
1230 std::vector
<uint16
> teamIds
;
1231 CAIInstance
*aiInstance
=*it
;
1232 aiInstance
->getPlayerMgr()->getTeamIds(teamIds
);
1234 if (teamIds
.empty())
1239 std::vector
<uint16
>::iterator
first(teamIds
.begin()), last(teamIds
.end());
1240 for (; first
!= last
; ++first
)
1244 stringWriter
.append("Player Team "+toString(id
)+" :");
1248 const std::set
<TDataSetRow
> &team
= aiInstance
->getPlayerMgr()->getPlayerTeam(uint16(id
));
1249 std::set
<TDataSetRow
>::const_iterator
first(team
.begin()), last(team
.end());
1250 for (; first
!= last
; ++first
)
1252 stringWriter
.append(" Row "+toString((*first
).getIndex())+" : "+CMirrors::DataSet
->getEntityId(*first
).toString());
1262 //-------------------------------------------------------------------------
1263 // set the escrot team ID for a group
1265 NLMISC_COMMAND(setEscortId
,"set the escort team id for a group in the given aIInstance","<aIInstanceId> <teamId> <groupAlias>|<groupName>")
1270 CLogStringWriter
stringWriter(&log
);
1272 CAIInstance
*aiInstance
=NULL
;
1274 uint32 aiInstanceId
= NLMISC::atoui(args
[0].c_str());
1275 if (aiInstanceId
>CAIS::instance().AIList().size())
1277 stringWriter
.append("Invalid AI Instance Number");
1280 aiInstance
=CAIS::instance().AIList()[aiInstanceId
];
1283 stringWriter
.append("AI Instance do not exists");
1290 // first, try to find the group by alias
1291 uint32 alias
= NLMISC::atoui(args
[2].c_str());
1294 grp
= aiInstance
->findGroup(alias
);
1299 /// try to find the group bt name
1300 std::vector
<CGroup
*> grps
;
1301 aiInstance
->findGroup(grps
, args
[2]);
1302 if (grps
.size() > 1)
1305 for (uint i
=0; i
<grps
.size(); ++i
)
1307 s
+= NLMISC::toString("%s ", grps
[i
]->aliasTreeOwner()->getAliasString().c_str());
1309 stringWriter
.append("More than one group have name '"+args
[2]+"', listing alias :");
1310 stringWriter
.append(s
);
1313 else if (grps
.empty())
1315 stringWriter
.append("No group correspond to name"+args
[2]);
1324 uint16 teamId
= uint16(NLMISC::atoui(args
[1].c_str()));
1325 stringWriter
.append("Setting escort teamId "
1330 +grp
->aliasTreeOwner()->getAliasString().c_str());
1331 grp
->setEscortTeamId(teamId
);
1337 //-------------------------------------------------------------------------
1338 // buffered commands facility
1339 typedef vector
<string
> TCommand
;
1340 typedef vector
<TCommand
> TCommandList
;
1341 static vector
<string
> bufferedRetStrings
;
1342 void clearBufferedRetStrings()
1344 bufferedRetStrings
.clear();
1347 TCommandList setEventCommands
;
1348 TCommandList scriptCommands
;
1349 TCommandList scriptCommands2
;
1350 TCommandList scriptCommandsBotById
;
1351 TCommandList scriptCommandsGroupByName
;
1352 TCommandList loadScriptCommands
;
1354 bool execSetEvent( CStringWriter
& stringWriter
, TCommand
const& args
);
1355 bool execScript( CStringWriter
& stringWriter
, TCommand
const& args
);
1356 bool execScript2( CStringWriter
& stringWriter
, TCommand
const& args
);
1357 bool execScriptBotById( CStringWriter
& stringWriter
, TCommand
const& args
);
1358 bool execScriptGroupByName( CStringWriter
& stringWriter
, TCommand
const& args
);
1359 bool execLoadScript(CStringWriter
& stringWriter
, TCommand
const& args
);
1361 void execBufferedCommands()
1363 vector
<string
> retStrings
;
1364 CArrayStringWriter
sw(retStrings
);
1366 FOREACHC(it
, TCommandList
, setEventCommands
)
1368 execSetEvent(sw
, *it
);
1370 setEventCommands
.clear();
1371 FOREACHC(it
, TCommandList
, scriptCommands
)
1373 execScript(sw
, *it
);
1375 scriptCommands
.clear();
1376 FOREACHC(it
, TCommandList
, scriptCommands2
)
1378 execScript2(sw
, *it
);
1380 scriptCommands2
.clear();
1381 FOREACHC(it
, TCommandList
, scriptCommandsBotById
)
1383 execScriptBotById(sw
, *it
);
1385 scriptCommandsBotById
.clear();
1386 FOREACHC(it
, TCommandList
, scriptCommandsGroupByName
)
1388 execScriptGroupByName(sw
, *it
);
1390 scriptCommandsGroupByName
.clear();
1391 FOREACHC(it
, TCommandList
, loadScriptCommands
)
1393 execLoadScript(sw
, *it
);
1395 loadScriptCommands
.clear();
1397 // Show ret commands
1398 FOREACHC(strIt
, vector
<string
>, retStrings
)
1399 nlwarning(strIt
->c_str());
1400 bufferedRetStrings
.insert(bufferedRetStrings
.end(), retStrings
.begin(), retStrings
.end());
1404 //-------------------------------------------------------------------------
1405 // set a user event on a group
1406 bool execSetEvent(CStringWriter
&stringWriter
, const vector
<string
> &args
)
1408 // Temporize setEvent commands.
1409 if ( args
.size() != 3
1410 && !( args
.size() == 4
1411 && args
[1] == "-no_detail"))
1414 CAIInstance
*aiInstance
=NULL
;
1416 const uint32 aiInstanceId
= NLMISC::atoui(args
[0].c_str());
1417 if (aiInstanceId
>CAIS::instance().AIList().size())
1419 stringWriter
.append("Invalid AI Instance Number");
1422 aiInstance
=CAIS::instance().AIList()[aiInstanceId
];
1425 stringWriter
.append("AI Instance do not exists");
1431 bool noDetail
= false;
1433 if (args
.size() == 4)
1436 uint32 eventId
= NLMISC::atoui(args
[1].c_str());
1437 NLMISC::clamp(eventId
, 0u, 9u);
1441 // first, try to find the group by alias
1442 uint32 alias
= NLMISC::atoui(args
[2].c_str());
1445 grp
= aiInstance
->findGroup(alias
);
1450 stringWriter
.append("Setting event "+toString(eventId
)+" on groups '"+grp
->aliasTreeOwner()->getName()+"' ("+toString(grp
->getChildIndex())+")");
1451 grp
->setEvent(eventId
);
1455 std::vector
<CGroup
*> grps
;
1458 /// try to find the group bot name
1459 aiInstance
->findGroup(grps
, args
[2]);
1460 if (grps
.size() > 1)
1465 for (uint i
=0; i
<grps
.size(); ++i
)
1467 s
+= NLMISC::toString("%s ", grps
[i
]->aliasTreeOwner()->getAliasString().c_str());
1469 stringWriter
.append("More than one group have name '"+args
[2]+"', listing alias :");
1470 stringWriter
.append(s
);
1474 else if (grps
.empty())
1476 stringWriter
.append("No group correspond to name "+ args
[2]);
1481 stringWriter
.append("Setting event "+toString(eventId
)+" on groups '"+args
[2]+"'");
1483 for (uint i
=0; i
<grps
.size(); ++i
)
1484 grps
[i
]->setEvent(eventId
);
1489 NLMISC_COMMAND(setEvent
,"set an event for a group in the given aIInstance [buffered]","<aIInstanceId> [<-no_detail>] <eventId> <groupAlias>|<groupName>")
1491 clearBufferedRetStrings();
1492 setEventCommands
.push_back(args
);
1496 //-------------------------------------------------------------------------
1497 // executes a script on groups matching a specified filter (1st arg)
1498 bool execScript(CStringWriter
& stringWriter
, TCommand
const& args
)
1503 string
const& groupName
= args
[0];
1504 typedef vector
<CGroup
*> TGroupContainer
;
1505 TGroupContainer grps
;
1507 /// try to find the group bot name
1508 buildFilteredGroupList(grps
, groupName
);
1511 stringWriter
.append("No group correspond to name "+ groupName
);
1516 stringWriter
.append("do script on groups '"+groupName
+"'");
1520 vector
<string
> codeLines
;
1521 for (size_t i
=1; i
<args
.size(); ++i
)
1522 codeLines
.push_back(args
[i
]);
1524 CSmartPtr
<const CByteCode
> codePtr
= CCompiler::getInstance().compileCode(codeLines
, "script Command");
1526 FOREACHC(itGrp
, TGroupContainer
, grps
)
1528 CGroup
* grp
= *itGrp
;
1529 if (grp
->getPersistentStateInstance())
1530 grp
->getPersistentStateInstance()->interpretCode(NULL
, codePtr
);
1535 FOREACHC(itGrp
, TGroupContainer
, grps
)
1537 CGroup
* grp
= *itGrp
;
1538 if (grp
->getPersistentStateInstance())
1540 stringWriter
.append("Group: "+grp
->getFullName());
1541 grp
->getPersistentStateInstance()->dumpVarsAndFunctions(stringWriter
);
1548 //-------------------------------------------------------------------------
1549 // executes a script on groups containing a bot matching a specified filter (1st arg)
1550 bool execScript2(CStringWriter
& stringWriter
, TCommand
const& args
)
1555 string
const& botName
= args
[0];
1556 typedef set
<CGroup
*> TGroupContainer
;
1557 TGroupContainer grps
;
1560 /// try to find the bot name
1561 buildFilteredBotList(bots
, botName
);
1564 stringWriter
.append("No bot correspond to name "+ botName
);
1569 FOREACH(itBot
, vector
<CBot
*>, bots
)
1572 CGroup
* group
= bot
->getOwner();
1573 // if (group->getOwner()==_EventNpcManager) // This would restrict the command to event groups
1579 stringWriter
.append("do script on groups containing bot '"+botName
+"'");
1583 vector
<string
> codeLines
;
1584 for (size_t i
=1; i
<args
.size(); ++i
)
1585 codeLines
.push_back(args
[i
]);
1587 CSmartPtr
<const CByteCode
> codePtr
= CCompiler::getInstance().compileCode(codeLines
, "script2 Command");
1589 FOREACHC(itGrp
, TGroupContainer
, grps
)
1591 CGroup
* grp
= *itGrp
;
1592 if (grp
->getPersistentStateInstance())
1593 grp
->getPersistentStateInstance()->interpretCode(NULL
, codePtr
);
1598 FOREACHC(itGrp
, TGroupContainer
, grps
)
1600 CGroup
* grp
= *itGrp
;
1601 if (grp
->getPersistentStateInstance())
1603 stringWriter
.append("Group: "+grp
->getFullName());
1604 grp
->getPersistentStateInstance()->dumpVarsAndFunctions(stringWriter
);
1611 //-------------------------------------------------------------------------
1612 // executes a script on groups containing a bot given its entity id
1613 bool execScriptBotById(CStringWriter
& stringWriter
, TCommand
const& args
)
1618 NLMISC::CEntityId botId
= NLMISC::CEntityId(args
[0]);
1619 if (botId
==NLMISC::CEntityId::Unknown
)
1621 CAIEntityPhysical
* entity
= CAIEntityPhysicalLocator::getInstance()->getEntity(botId
);
1622 CSpawnBotNpc
* bot
= dynamic_cast<CSpawnBotNpc
*>(entity
);
1625 if (!bot
->getPersistent().getOwner())
1627 if (!bot
->getPersistent().getOwner()->getPersistentStateInstance())
1630 vector
<string
> codeLines
;
1631 for (size_t i
=1; i
<args
.size(); ++i
)
1632 codeLines
.push_back(args
[i
]);
1634 CSmartPtr
<const CByteCode
> codePtr
= CCompiler::getInstance().compileCode(codeLines
, "script2 Command");
1636 bot
->getPersistent().getOwner()->getPersistentStateInstance()->interpretCode(NULL
, codePtr
);
1641 //-------------------------------------------------------------------------
1642 // executes a script on groups containing a bot given its entity id
1643 bool execScriptGroupByName(CStringWriter
& stringWriter
, TCommand
const& args
)
1648 string
const& groupName
= args
[0];
1649 // NLMISC::CEntityId botId = NLMISC::CEntityId(args[0]);
1650 // if (botId==NLMISC::CEntityId::Unknown)
1652 CGroupNpc
* group
= dynamic_cast<CGroupNpc
*>(CAliasTreeOwnerLocator::getInstance()->getEntity(groupName
));
1655 if (!group
->getPersistentStateInstance())
1658 vector
<string
> codeLines
;
1659 for (size_t i
=1; i
<args
.size(); ++i
)
1660 codeLines
.push_back(args
[i
]);
1662 CSmartPtr
<const CByteCode
> codePtr
= CCompiler::getInstance().compileCode(codeLines
, "script2 Command");
1664 group
->getPersistentStateInstance()->interpretCode(NULL
, codePtr
);
1669 NLMISC_COMMAND(getDatasetId
,"get datasetid of bots with name matchiong the given filter", "<groupFilter>")
1674 string
const& botName
= args
[0];
1678 /// try to find the bot name
1679 buildFilteredBotList(bots
, botName
);
1682 log
.displayNL("ERR: No bot correspond to name %s", botName
.c_str());
1687 FOREACH(itBot
, vector
<CBot
*>, bots
)
1690 CSpawnBot
* spawnBot
= bot
->getSpawnObj();
1692 DatasetIds
+= spawnBot
->dataSetRow().toString()+"|";
1696 log
.displayNL("%s", DatasetIds
.c_str());
1700 NLMISC_COMMAND(script
,"execute a script for groups matching the given filter [buffered]","<groupFilter> <code>")
1702 clearBufferedRetStrings();
1703 scriptCommands
.push_back(args
);
1707 NLMISC_COMMAND(script2
,"execute a script for groups containing a bot matching the given filter [buffered]","<groupFilter> <code>")
1709 clearBufferedRetStrings();
1710 scriptCommands2
.push_back(args
);
1714 NLMISC_COMMAND(scriptHex
,"execute a hex-encoded script for a group in the given aIInstance [buffered]","<groupName> <hexcode>")
1716 vector
<string
> _args
= args
;
1717 _args
[1] = scriptHex_decode(_args
[1]);
1718 clearBufferedRetStrings();
1719 scriptCommands
.push_back(_args
);
1723 static const char* hexEncoderTcl
=
1724 "proc copy_encoded {} {"
1725 " # Get the args from the text fields"
1726 " set group [ .group.name get 1.0 end ]"
1727 " set script [ .script get 1.0 end ]"
1728 " # Initiate the AIS command"
1729 " set output [concat \"scriptHex\" ${group}]"
1730 " append output \" \""
1731 " # Convert the script itself into an hex string (-1 to remove trailing newline)"
1732 " for {set i 0} {$i < [string length $script]-1} {incr i} {"
1733 " # Get the character"
1734 " set c [string index $script $i]"
1735 " # Get its ascii value"
1737 " # Print it as 2 hex digits"
1738 " append output [format %02x $n]"
1740 " # Replace the clipboard with the AIS command"
1742 " clipboard append $output"
1746 "pack .group -anchor w -fill x"
1747 "label .group.label -text \"Group:\""
1748 "pack .group.label -side left"
1749 "text .group.name -height 1 -width 70"
1750 "pack .group.name -fill x"
1752 "pack .script -fill both -expand 1"
1753 "button .button -text \"Copy encoded!\""
1754 "pack .button -side bottom"
1756 "bind .button <ButtonPress-1> {"
1761 NLMISC_COMMAND(hexEncoder
,"prints a script that can be used to encode a text for use with scriptHex","<language>")
1768 log
.displayNL("%s", hexEncoderTcl
);
1772 log
.displayNL("Invalid language name! Valid languages are: tcl");
1777 //-------------------------------------------------------------------------
1778 // set a user event on a group
1779 bool execLoadScript(CStringWriter
& stringWriter
, vector
<string
> const& args
)
1784 CAIInstance
* aiInstance
= NULL
;
1786 uint32
const aiInstanceId
= NLMISC::atoui(args
[0].c_str());
1787 if (aiInstanceId
>CAIS::instance().AIList().size())
1789 stringWriter
.append("Invalid AI Instance Number");
1792 aiInstance
=CAIS::instance().AIList()[aiInstanceId
];
1795 stringWriter
.append("AI Instance do not exists");
1800 bool noDetail
= false;
1802 string
const& groupName
= args
[1];
1803 std::vector
<CGroup
*> grps
;
1805 /// try to find the group bot name
1806 aiInstance
->findGroup(grps
, groupName
);
1807 if (grps
.size() > 1)
1812 for (uint i
=0; i
<grps
.size(); ++i
)
1814 s
+= NLMISC::toString("%s ", grps
[i
]->aliasTreeOwner()->getAliasString().c_str());
1816 stringWriter
.append("More than one group have name '"+groupName
+"', listing alias :");
1817 stringWriter
.append(s
);
1821 else if (grps
.empty())
1823 stringWriter
.append("No group correspond to name "+ groupName
);
1828 stringWriter
.append("do script on groups '"+groupName
+"'");
1832 NLMISC::CIFile
file(NLMISC::CPath::lookup(args
[2]));
1834 vector
<string
> lines
;
1837 const size_t bufferSize
= 4*1024;
1838 char buffer
[bufferSize
];
1839 file
.getline(buffer
, bufferSize
);
1840 lines
.push_back(buffer
);
1842 // Compile the buffer
1843 CSmartPtr
<const CByteCode
> codePtr
=CCompiler::getInstance().compileCode(lines
, "script Command");
1845 // Interpret the code for each group
1846 FOREACHC(itGrp
, vector
<CGroup
*>, grps
)
1847 (*itGrp
)->getPersistentStateInstance()->interpretCode(NULL
, codePtr
);
1849 catch (const EPathNotFound
&)
1851 nlwarning("Path not found while loading AIS script %s", args
[2].c_str());
1857 NLMISC_COMMAND(loadScript
, "execute a script from a file for a group in the given aIInstance [buffered]", "<aIInstanceId> <groupName> <filename>")
1859 clearBufferedRetStrings();
1860 loadScriptCommands
.push_back(args
);
1864 NLMISC_COMMAND(getInfo
,"display returned values of buffered commands","")
1866 CLogStringWriter
stringWriter(&log
);
1868 FOREACHC(strIt
, vector
<string
>, bufferedRetStrings
)
1870 stringWriter
.append(*strIt
);
1877 //-------------------------------------------------------------------------
1878 // DISPLAYING Managers, Groups and Bots
1880 static void displayNode(const CAIAliasDescriptionNode
*node
,uint indent
=0)
1882 nlinfo("%*s- %s %-12s - %s",
1885 node
->getAliasString().c_str(),
1886 getName(node
->getType()),
1887 node
->fullName().c_str());
1888 for (uint i
=0;i
<node
->getChildCount();++i
)
1889 displayNode(node
->getChild(i
),indent
+2);
1892 NLMISC_COMMAND(displayNodeTreeMgr
,"display node tree for given manager(s)","<manager id>[...]")
1897 for (uint i
=0;i
<args
.size();++i
)
1899 CManager
* ManagerPtr
= CAIS::instance().tryToGetManager(args
[i
].c_str());
1902 nlinfo("Manager: %d",i
);
1903 displayNode(ManagerPtr
->getAliasTreeOwner()->getAliasNode());
1906 nlwarning("Failed to find mgr: %s",args
[i
].c_str());
1912 NLMISC_COMMAND(displayTarget
,"display bot target status for given bot(s) or player(s)","<bot id>[...]")
1917 CLogStringWriter
stringWriter(&log
);
1919 for (uint i
=0;i
<args
.size();++i
)
1921 CAIEntityPhysical
* EntityPtr
= CAIS::instance().tryToGetEntityPhysical(args
[i
].c_str());
1924 // log.displayNL("=> can't find entity: %s", args[i].c_str());
1928 CAIEntityPhysical
*phys
=EntityPtr
->getTarget();
1932 log
.displayNL("=> bot %s have no target", args
[i
].c_str());
1938 switch (phys
->getRyzomType())
1941 case RYZOMID::creature
:
1942 case RYZOMID::pack_animal
:
1944 case RYZOMID::player
:
1945 log
.displayNL("=> target is a player");
1949 CSpawnBot
* spawnBot
=dynamic_cast<CSpawnBot
*>(phys
);
1952 vector
<string
> strings
= spawnBot
->getPersistent().getMultiLineInfoString();
1953 FOREACHC(itString
, vector
<string
>, strings
)
1954 log
.displayNL("%s", itString
->c_str());
1964 log
.displayNL("=> can't display information for the target of: %s", args
[i
].c_str());
1971 NLMISC_COMMAND(displayVision3x3
,"display 3x3 cell vision centred on a given coordinate in the given aIInstance","<aiInstance> <x><y>")
1976 CAIInstance
*aiInstance
=NULL
;
1978 uint32 aiInstanceId
= NLMISC::atoui(args
[0].c_str());
1979 if (aiInstanceId
>CAIS::instance().AIList().size())
1981 log
.displayNL("Invalid AI Instance Number");
1984 aiInstance
=CAIS::instance().AIList()[aiInstanceId
];
1987 log
.displayNL("AI Instance do not exists");
1993 NLMISC::fromString(args
[1], dx
);
1994 NLMISC::fromString(args
[2], dy
);
1999 log
.displayNL("3x3 Vision around (%.3f,%.3f)", x
.asDouble(), y
.asDouble());
2004 CAIVector
position(x
,y
);
2007 CAIEntityMatrix
<CPersistentOfPhysical
>::CEntityIteratorRandom it
;
2008 for (it
=aiInstance
->playerMatrix().beginEntities(CAIS::instance().matrixIterator3x3(),position
);!it
.end();++it
)
2011 // log.displayNL("=> PLR: %s (%s)", (*it).id().toString().c_str(), (*it).pos().toString().c_str());
2012 if ((*it
).isSpawned())
2013 log
.displayNL("=> (messageToChange)PLR: %d (%s)", (*it
).getSpawnObj()->dataSetRow().getIndex(), (*it
).getSpawnObj()->pos().toString().c_str());
2018 CAIEntityMatrix
<CPersistentOfPhysical
>::CEntityIteratorRandom it
;
2019 for (it
=aiInstance
->botMatrix().beginEntities(CAIS::instance().matrixIterator3x3(),position
);!it
.end();++it
)
2021 CPersistentOfPhysical
&persRef
=(*it
);
2022 if (!persRef
.isSpawned())
2026 CBot
* botPtr
=NLMISC::safe_cast
<CBot
*>(&persRef
);
2028 if (botPtr
->getAliasTreeOwner())
2029 log
.displayNL("=> BOT: %s (%s)", botPtr
->getAliasTreeOwner()->getName().c_str(), persRef
.getSpawnObj()->pos().toString().c_str());
2031 log
.displayNL("=> BOT: unknown (%s)", persRef
.getSpawnObj()->pos().toString().c_str());
2033 // log.displayNL("=> BOT: %s (%s)", (*it).id().toString().c_str(), (*it).pos().toString().c_str());
2037 log
.displayNL("Entites found: %d bots, %d players, total: %d", botCount
, plrCount
, botCount
+plrCount
);
2042 NLMISC_COMMAND(displayVisionRadius
,"display roughly 'radius' cell vision centred on a given coordinate in the given aIInstance","<aIInstance> <x><y>[<radius>=100]")
2048 CAIInstance
*aiInstance
=NULL
;
2050 uint32 aiInstanceId
= NLMISC::atoui(args
[0].c_str());
2051 if (aiInstanceId
>CAIS::instance().AIList().size())
2053 log
.displayNL("Invalid AI Instance Number");
2056 aiInstance
=CAIS::instance().AIList()[aiInstanceId
];
2059 log
.displayNL("AI Instance do not exists");
2066 x
=atof(args
[1].c_str());
2067 y
=atof(args
[2].c_str());
2069 NLMISC::fromString(args
[3], dist
);
2070 log
.displayNL("%dm Vision around (%.3f,%.3f)", dist
, x
.asDouble(), y
.asDouble());
2075 const CAIEntityMatrixIteratorTblLinear
*tbl
=CAIS::instance().bestLinearMatrixIteratorTbl(dist
);
2077 CAIEntityMatrix
<CPersistentOfPhysical
>::CEntityIteratorLinear it
;
2079 CAIVector
position(x
,y
);
2080 for (it
=aiInstance
->playerMatrix().beginEntities(tbl
,position
);!it
.end();++it
)
2083 const CPersistentOfPhysical
& entityPtr
= (*it
);
2084 const CBotPlayer
* const playerPtr
=dynamic_cast<const CBotPlayer
* const>(&entityPtr
);
2088 // have to implement players.
2090 nlwarning("Not Implemented");
2092 // log.displayNL("=> PLR: %s (%s)", (*it).id().toString().c_str(), (*it).pos().toString().c_str());
2093 // log.displayNL("=> PLR: %s (%s)", (*it).id().toString().c_str(), (*it).pos().toString().c_str());
2096 for (it
=aiInstance
->botMatrix().beginEntities(tbl
,position
);!it
.end();++it
)
2098 if ((*it
).isSpawned())
2101 // log.displayNL("=> BOT: %s (%s)", (*it).id().toString().c_str(), (*it).pos().toString().c_str());
2102 log
.displayNL("=> (messageToChange)BOT: %d (%s)", (*it
).getSpawnObj()->dataSetRow().getIndex(), (*it
).getSpawnObj()->pos().toString().c_str());
2106 log
.displayNL("Entites found: %d bots, %d players, total: %d", botCount
, plrCount
, botCount
+plrCount
);
2113 NLMISC_COMMAND(countEntitesInVisionMatrix
,"scan the vision matrix for entities in the given aiInstance","<aiInstance>")
2118 CAIInstance
*aiInstance
=NULL
;
2120 uint32 aiInstanceId
= NLMISC::atoui(args
[0].c_str());
2121 if (aiInstanceId
>CAIS::instance().AIList().size())
2123 log
.displayNL("Invalid AI Instance Number");
2126 aiInstance
=CAIS::instance().AIList()[aiInstanceId
];
2129 log
.displayNL("AI Instance do not exists");
2134 // build an iterator table for our scan
2135 CAIEntityMatrixIteratorTblRandom tbl
;
2137 for (int i
=0;i
<256;++i
)
2139 for (int j
=0;j
<255;++j
)
2142 tbl
.push_back(-255,1);
2146 CAIEntityMatrix
<CPersistentOfPhysical
>::CCellTblIteratorRandom it
;
2150 CAIVector
position(0,0);
2151 // count entities in bot matrix
2152 for (it
=aiInstance
->botMatrix().beginCells(&tbl
,position
);!it
.end();++it
)
2154 for (CEntityListLink
<CPersistentOfPhysical
> *listLink
=(*it
)->next();listLink
!=*it
;listLink
=listLink
->next())
2158 // count entities in player matrix
2159 for (it
=aiInstance
->playerMatrix().beginCells(&tbl
,position
);!it
.end();++it
)
2161 for (CEntityListLink
<CPersistentOfPhysical
> *listLink
=(*it
)->next();listLink
!=*it
;listLink
=listLink
->next())
2165 // display the results
2166 log
.displayNL("Entites found: %d bots, %d players, total: %d", botCount
, plrCount
, botCount
+plrCount
);
2172 //-------------------------------------------------------------------------
2173 // DISPLAYING Places
2175 NLMISC_COMMAND(displayPlaces
,"display the list of places for specified manager","[<manager id>]")
2180 // manager specified so lookup manager by name
2181 CMgrFauna
* mgrFaunaPtr
= dynamic_cast<CMgrFauna
*>(CAIS::instance().tryToGetManager(args
[0].c_str()));
2182 if (mgrFaunaPtr
==NULL
)
2185 CLogStringWriter
stringWriter(&log
);
2187 CCont
<CGroup
>::iterator it
= mgrFaunaPtr
->groups().begin();
2188 CCont
<CGroup
>::iterator itEnd
= mgrFaunaPtr
->groups().end();
2191 NLMISC::safe_cast
<CGrpFauna
*>(*it
)->displayPlaces(stringWriter
);
2198 //-------------------------------------------------------------------------
2199 // WATCHES FOR TRACKING MGR, GRP & BOT OBJECTS
2201 static std::string WATCH0
,WATCH1
,WATCH2
,WATCH3
,WATCH4
,
2202 WATCH5
,WATCH6
,WATCH7
,WATCH8
,WATCH9
;
2203 static std::string
*watchStrings
[]=
2205 &WATCH0
,&WATCH1
,&WATCH2
,&WATCH3
,&WATCH4
,
2206 &WATCH5
,&WATCH6
,&WATCH7
,&WATCH8
,&WATCH9
2209 static CAIEntity
* watchEntity
[sizeof(watchStrings
)/sizeof(watchStrings
[0])];
2210 static uint watchIdx
[sizeof(watchStrings
)/sizeof(watchStrings
[0])];
2212 NLMISC_VARIABLE(string
, WATCH0
, "watch string 0");
2213 NLMISC_VARIABLE(string
, WATCH1
, "watch string 1");
2214 NLMISC_VARIABLE(string
, WATCH2
, "watch string 2");
2215 NLMISC_VARIABLE(string
, WATCH3
, "watch string 3");
2216 NLMISC_VARIABLE(string
, WATCH4
, "watch string 4");
2217 NLMISC_VARIABLE(string
, WATCH5
, "watch string 5");
2218 NLMISC_VARIABLE(string
, WATCH6
, "watch string 6");
2219 NLMISC_VARIABLE(string
, WATCH7
, "watch string 7");
2220 NLMISC_VARIABLE(string
, WATCH8
, "watch string 8");
2221 NLMISC_VARIABLE(string
, WATCH9
, "watch string 9");
2224 bool FAUNA_GRAPH_USES_DEBUG_TIME
= false;
2225 NLMISC_VARIABLE(bool, FAUNA_GRAPH_USES_DEBUG_TIME
, "force fauna graph to use local time (for debug)");
2227 // global routine called by the service main update()
2229 void UpdateWatches()
2231 // if (!CAIS::initialised())
2234 for (uint i
=0;i
<sizeof(watchStrings
)/sizeof(watchStrings
[0]);++i
)
2237 *watchStrings
[i
] = watchEntity
[i
]->getOneLineInfoString();
2239 *watchStrings
[i
] = string("<NULL ENTITY>");
2244 void removeFromWatch(CAIEntity
*entity
)
2246 for (uint i
=0;i
<sizeof(watchStrings
)/sizeof(watchStrings
[0]);++i
)
2248 if (watchEntity
[i
]==entity
)
2249 watchEntity
[i
]=NULL
;
2255 NLMISC_COMMAND(setWatch
,"setup one of the watch variables","<watch id> <mgr, grp or bot id> [<index>]")
2257 if (args
.size()!=2 && args
.size()!=3)
2261 NLMISC::fromString(args
[0], idx
);
2262 if ( toString(idx
)!=args
[0]
2263 || idx
>=sizeof(watchStrings
)/sizeof(watchStrings
[0]))
2266 CAIEntity
* CAIEntityPtr
= CAIS::instance().tryToGetAIEntity(args
[1].c_str());
2271 watchEntity
[idx
]=CAIEntityPtr
;
2274 NLMISC::fromString(args
[2], watchIdx
[idx
]);
2280 static bool setBotRecordHistory(std::vector
<std::string
> args
,bool onOff
)
2284 CAIInstance
* instancePtr
= CAIS::instance().AIList().getNextValidChild();
2285 while (instancePtr
!=NULL
)
2287 CManager
* mgrPtr
= instancePtr
->managers().getNextValidChild();
2288 while (mgrPtr
!=NULL
)
2290 CGroup
* grpPtr
=mgrPtr
->getNextValidGroupChild();
2291 while (grpPtr
!=NULL
)
2293 grpPtr
->getDebugHistory()->setRecording(onOff
);
2295 CBot
* botPtr
= grpPtr
->getNextValidBotChild();
2296 while (botPtr
!=NULL
)
2298 botPtr
->getDebugHistory()->setRecording(onOff
);
2300 botPtr
=grpPtr
->getNextValidBotChild(botPtr
);
2302 grpPtr
=mgrPtr
->getNextValidGroupChild(grpPtr
);
2304 mgrPtr
=instancePtr
->managers().getNextValidChild(mgrPtr
);
2306 instancePtr
=CAIS::instance().AIList().getNextValidChild(instancePtr
);
2311 CAIInstance
* instancePtr
= CAIS::instance().AIList().getNextValidChild();
2312 while (instancePtr
!=NULL
)
2314 CManager
* mgrPtr
= instancePtr
->managers().getNextValidChild();
2315 while (mgrPtr
!=NULL
)
2317 CGroup
* grpPtr
=mgrPtr
->getNextValidGroupChild();
2318 while (grpPtr
!=NULL
)
2321 grpPtr
->getDebugHistory()->setRecording(onOff
);
2323 CBot
* botPtr
= grpPtr
->getNextValidBotChild();
2324 while (botPtr
!=NULL
)
2326 for (uint i
=0;i
<args
.size();++i
)
2327 if (NLMISC::nlstricmp(botPtr
->getAliasTreeOwner()->getName(),args
[i
])==0)
2329 botPtr
->getDebugHistory()->setRecording(onOff
);
2331 botPtr
=grpPtr
->getNextValidBotChild(botPtr
);
2333 grpPtr
=mgrPtr
->getNextValidGroupChild(grpPtr
);
2335 mgrPtr
=instancePtr
->managers().getNextValidChild(mgrPtr
);
2337 instancePtr
=CAIS::instance().AIList().getNextValidChild(instancePtr
);
2343 NLMISC_COMMAND(botHistoryRecordBegin
,"setup history recording for all or named entities","[<bot name> [...]]")
2345 return setBotRecordHistory(args
,true);
2348 NLMISC_COMMAND(botHistoryRecordEnd
,"setup history recording for all or named entities","[<bot name> [...]]")
2350 return setBotRecordHistory(args
,false);
2353 NLMISC_COMMAND(botViewHistory
,"view recorded history for named entity","<bot name>")
2358 CAIInstance
* instancePtr
= CAIS::instance().AIList().getNextValidChild();
2359 while (instancePtr
!=NULL
)
2361 CManager
* mgrPtr
= instancePtr
->managers().getNextValidChild();
2362 while (mgrPtr
!=NULL
)
2364 CGroup
* grpPtr
=mgrPtr
->getNextValidGroupChild();
2365 while (grpPtr
!=NULL
)
2367 CBot
* botPtr
= grpPtr
->getNextValidBotChild();
2368 while (botPtr
!=NULL
)
2370 for (uint i
=0;i
<args
.size();++i
)
2372 if (NLMISC::nlstricmp(botPtr
->getAliasTreeOwner()->getName(),args
[i
])==0)
2374 botPtr
->getDebugHistory()->writeAsInfo();
2375 break; // don't need to write info more than one time.
2379 botPtr
=grpPtr
->getNextValidBotChild(botPtr
);
2381 grpPtr
=mgrPtr
->getNextValidGroupChild(grpPtr
);
2383 mgrPtr
=instancePtr
->managers().getNextValidChild(mgrPtr
);
2385 instancePtr
=CAIS::instance().AIList().getNextValidChild(instancePtr
);
2391 NLMISC_COMMAND(grpHistoryRecordLog
,"toggle grp history recorder 'nlinfo' logging","")
2393 GrpHistoryRecordLog
=!GrpHistoryRecordLog
;
2395 nlinfo("GrpHistoryRecordLog: %s",GrpHistoryRecordLog
?"ON":"OFF");
2400 //-------------------------------------------------------------------------
2401 // DISPLAYING VISION OF FAUNA GROUPS
2403 NLMISC_COMMAND(displayFaunaGrpVision
,"display the vision of a fauna group","<grp id>")
2408 //-------------------------------------------------------------------------
2409 // MANIPULATING STATE OF FAUNA GROUPS
2411 NLMISC_COMMAND(advanceGrpState
,"advance the group to the next state in its cycle","<grp id>")
2416 CGrpFauna
*grp
=dynamic_cast<CGrpFauna
*>(CAIS::instance().tryToGetGroup(args
[0].c_str()));
2419 log
.displayNL("Failed to identify group: %s",args
[0].c_str());
2422 if (!grp
->isSpawned())
2424 log
.displayNL("Group not spawned: %s",args
[0].c_str());
2428 grp
->getSpawnObj()->resetTimer();
2433 NLMISC_COMMAND(setGrpTimers
,"set the timer values for a given group","<grp id> <eat time> <rest time>")
2438 CGrpFauna
*grp
=dynamic_cast<CGrpFauna
*>(CAIS::instance().tryToGetGroup(args
[0].c_str()));
2441 log
.displayNL("Failed to identify group: %s",args
[0].c_str());
2445 uint32 eatTime
, restTime
;
2446 NLMISC::fromString(args
[1], eatTime
);
2447 NLMISC::fromString(args
[2], restTime
);
2449 if (eatTime
<1 || restTime
<1)
2451 log
.displayNL("Invalid time parameters");
2455 grp
->setTimer(CGrpFauna::EAT_TIME
, eatTime
*10);
2456 grp
->setTimer(CGrpFauna::REST_TIME
, restTime
*10);
2460 //-------------------------------------------------------------------------
2461 // RUNNING THE AI UPDATE FOR TESTING OFFLINE
2464 extern uint ForceTicks
;
2466 NLMISC_COMMAND(updateAI
,"call CAIS::update() (simulate a tick off-line)","[tick]")
2471 // if there's an argument make sure its a positive integer
2475 NLMISC::fromString(args
[0], tick
);
2476 if ((tick
< 1) || (toString(tick
)!=args
[0]))
2490 NLMISC_COMMAND(addPetsToPlayer
,"Add some pets specified with a sheet to the specified player.","<player id> <nb pets> <pet_sheet>")
2492 if ( args
.size() !=3 )
2496 nlstopex(("Not Implemented"));
2501 //-------------------------------------------------------------------------
2502 // DISPLAYING FIGHT SHEET.
2504 NLMISC_COMMAND(displayFightSheet
,"display the sheet","<sheet name>")
2506 if (args
.size() !=1)
2508 log
.displayNL("One argument needed");
2512 AISHEETS::ICreatureCPtr sheet
= AISHEETS::CSheets::getInstance()->lookup(CSheetId(args
[0]));
2515 log
.displayNL("Unknown sheet %s", args
[0].c_str());
2518 if (sheet
->SheetId()==NLMISC::CSheetId::Unknown
)
2520 std::string creatureString
=args
[0]+std::string(".creature");
2521 sheet
= /*const_cast<AISHEETS::ICreature*>(*/AISHEETS::CSheets::getInstance()->lookup(CSheetId(creatureString
))/*)*/;
2524 if (sheet
->SheetId()==NLMISC::CSheetId::Unknown
)
2526 log
.displayNL("Failed to identify sheet: %s",args
[0].c_str());
2530 log
.displayNL("all these values are used to compute a score for a possible new target");
2531 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");
2533 log
.displayNL("- DistModulator [0 n]: %f value=1/(1+distance*DistModulator)", sheet
->DistModulator());
2534 log
.displayNL("value means the distance sensitivity of the bot, equals to zero means the bot never mind the distance");
2536 log
.displayNL("- TargetModulator [0 n]: %f value=1/(1+nbTarget*TargetModulator)", sheet
->TargetModulator());
2537 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");
2539 log
.displayNL("- ScoreModulator [0 1]: %f score>ScoreModulator", sheet
->ScoreModulator());
2540 log
.displayNL("value means the minimum value (threshold) needed for the bot to attack, 0 means always, 1 never (also impossible)");
2542 log
.displayNL("- FearModulator [0 1]: %f score>FearModulator", sheet
->FearModulator());
2543 log
.displayNL("value means the minimum value (threshold) needed for the bot to flee, 0 means always, 1 never (also impossible)");
2545 log
.displayNL("- LifeLevelModulator [0 1]: %f value=LifeLevelModulator*lifeCoef+(1.f-LifeLevelModulator)*levelCoef", sheet
->LifeLevelModulator());
2546 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");
2548 log
.displayNL("- CourageModulator [-n +n]: %f", sheet
->CourageModulator());
2549 log
.displayNL("value used to make a bot courageous or feared, -n the bot is feared, +n its courageous");
2551 log
.displayNL("- GroupCohesionModulator [0 1]: %f", sheet
->GroupCohesionModulator());
2552 log
.displayNL("value used to make bots of a group aware of each other, 0 each bot is individual, 1 they fight in group");
2554 log
.displayNL("- GroupDispersion [0 1]: %f", sheet
->GroupDispersion());
2555 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");
2562 // all these values are used to compute a score for a possible new target
2563 // 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
2565 // - DistModulator [0 n]: value=1/(1+distance*DistModulator)
2566 // value means the distance sensitivity of the bot, equals to zero means the bot never mind the distance
2568 // - TargetModulator [0 n]: value=1/(1+nbTarget*TargetModulator)
2569 // 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
2571 // - ScoreModulator [0 1]: score>ScoreModulator
2572 // value means the minimum value (threshold) needed for the bot to attack, 0 means always, 1 never (also impossible)
2574 // - FearModulator [0 1]: score>FearModulator
2575 // value means the minimum value (threshold) needed for the bot to flee, 0 means always, 1 never (also impossible)
2577 // - LifeLevelModulator [0 1]: value=LifeLevelModulator*lifeCoef+(1.f-LifeLevelModulator)*levelCoef
2578 // 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
2580 // - CourageModulator [-n +n]:
2581 // value used to make a bot courageous or feared, -n the bot is feared, +n its courageous
2583 // - GroupCohesionModulator [0 1]:
2584 // value used to make bots of a group aware of each other, 0 each bot is individual, 1 they fight in group
2586 NLMISC_COMMAND(setFightSheet,"change a value in the fight sheet","<sheet name> <value name> <value> (use name without 'modulator', ex: 'Dist')")
2588 if (args.size() !=3)
2590 log.displayNL("three argument needed");
2594 AISHEETS::ICreature *sheet=const_cast<AISHEETS::CCreature*>(AISHEETS::CSheets::getInstance()->lookup(CSheetId(args[0])));
2595 if (sheet->SheetId==NLMISC::CSheetId::Unknown)
2597 std::string creatureString=args[0]+std::string(".creature");
2598 sheet=const_cast<AISHEETS::ICreature*>(AISHEETS::CSheets::getInstance()->lookup(CSheetId(creatureString)));
2601 if (sheet->SheetId==NLMISC::CSheetId::Unknown)
2603 log.displayNL("Failed to identify sheet: %s",args[0].c_str());
2607 float value = float(atof(args[2].c_str()));
2609 if (NLMISC::nlstricmp(args[1].c_str(), "dist")==0)
2613 log.displayNL("Failed, out of bounds, values accepted are [0 +n]");
2616 sheet->DistModulator=value;
2617 log.displayNL("Done, DistModulator=%f", value);
2621 if (NLMISC::nlstricmp(args[1].c_str(), "target")==0)
2625 log.displayNL("Failed, out of bounds, values accepted are [0 +n]");
2628 sheet->TargetModulator=value;
2629 log.displayNL("Done, TargetModulator=%f", value);
2633 if (NLMISC::nlstricmp(args[1].c_str(), "score")==0)
2635 if (value<0 || value>1)
2637 log.displayNL("Failed, out of bounds, values accepted are [0 +1]");
2640 sheet->ScoreModulator=value;
2641 log.displayNL("Done, ScoreModulator=%f", value);
2645 if (NLMISC::nlstricmp(args[1].c_str(), "fear")==0)
2647 if (value<0 || value>1)
2649 log.displayNL("Failed, out of bounds, values accepted are [0 +1]");
2652 sheet->FearModulator=value;
2653 log.displayNL("Done, FearModulator=%f", value);
2657 if (NLMISC::nlstricmp(args[1].c_str(), "LifeLevel")==0)
2659 if (value<0 || value>1)
2661 log.displayNL("Failed, out of bounds, values accepted are [0 +1]");
2664 sheet->LifeLevelModulator=value;
2665 log.displayNL("Done, LifeLevelModulator=%f", value);
2669 if (NLMISC::nlstricmp(args[1].c_str(), "Courage")==0)
2671 sheet->CourageModulator=value;
2672 log.displayNL("Done, CourageModulator=%f", value);
2676 if (NLMISC::nlstricmp(args[1].c_str(), "GroupCohesion")==0)
2678 if (value<0 || value>1)
2680 log.displayNL("Failed, out of bounds, values accepted are [0 +1]");
2683 sheet->GroupCohesionModulator=value;
2684 log.displayNL("Done, GroupCohesionModulator=%f", value);
2688 if (NLMISC::nlstricmp(args[1].c_str(), "GroupDispersion")==0)
2690 if (value<0 || value>1)
2692 log.displayNL("Failed, out of bounds, values accepted are [0 +1]");
2695 sheet->GroupDispersion=value;
2696 log.displayNL("Done, GroupDispersion=%f", value);
2700 log.displayNL("Failed to identify %s", args[1].c_str());
2704 static void botSetPosition(CBot
* bot
, std::vector
<std::string
> const& args
, std::string
const& botid
, float x
, float y
, uint z
, NLMISC::CLog
& log
)
2706 CSpawnBot
* spawnBot
= bot
->getSpawnObj();
2709 std::string botname
= bot
->getAliasTreeOwner()->getName();
2710 NLMISC::CEntityId eid
= spawnBot
->getEntityId();
2711 std::string eidstr
= eid
.toString();
2712 if (botid
=="*" || (botname
!="")&&(botname
.find(botid
)!=std::string::npos
) || eidstr
.find(botid
)!=std::string::npos
)
2714 CAIPosMirror p
= spawnBot
->pos();
2719 spawnBot
->setPos(CAIPos(x
, y
, z
, p
.theta()));
2721 p
= spawnBot
->pos();
2723 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());
2725 log
.displayNL("Bot position for %s is %f;%f;%d", eidstr
.c_str(), p
.x().asDouble(), p
.y().asDouble(), p
.h());
2730 static void botSetPosition(CGroup
* grp
, std::vector
<std::string
> const& args
, std::string
const& botid
, float x
, float y
, uint z
, NLMISC::CLog
& log
)
2732 FOREACH (itBot
, CCont
<CBot
>, grp
->bots())
2734 botSetPosition(*itBot
, args
, botid
, x
, y
, z
, log
);
2738 static void botSetPosition(CManager
* mgr
, std::vector
<std::string
> const& args
, std::string
const& botid
, float x
, float y
, uint z
, NLMISC::CLog
& log
)
2740 FOREACH (itGroup
, CCont
<CGroup
>, mgr
->groups())
2742 botSetPosition(*itGroup
, args
, botid
, x
, y
, z
, log
);
2746 NLMISC_COMMAND(botSetPosition
,"set the position of one or several bots","<eid> [<x> <y> [<z>]]")
2748 if (args
.size()!=1 && args
.size()!=3 && args
.size()!=4)
2751 std::string botid
= args
[0];
2757 x
= (float)atof(args
[1].c_str());
2758 y
= (float)atof(args
[2].c_str());
2760 NLMISC::fromString(args
[3], z
);
2764 FOREACH (itInstance
, CCont
<CAIInstance
>, CAIS::instance().AIList())
2766 FOREACH (itManager
, CCont
<CManager
>, itInstance
->managers())
2768 botSetPosition(*itManager
, args
, botid
, x
, y
, z
, log
);
2770 FOREACH (itCont
, CCont
<CContinent
>, itInstance
->continents())
2772 FOREACH (itRegion
, CCont
<CRegion
>, itCont
->regions())
2774 FOREACH (itCellZone
, CCont
<CCellZone
>, itRegion
->cellZones())
2776 FOREACH (itFamilyBehavior
, CCont
<CFamilyBehavior
>, itCellZone
->familyBehaviors())
2778 botSetPosition(itFamilyBehavior
->mgrNpc(), args
, botid
, x
, y
, z
, log
);
2779 botSetPosition(itFamilyBehavior
->mgrFauna(), args
, botid
, x
, y
, z
, log
);
2788 NLMISC_COMMAND(helpAboutId
, "display a short explanation about id used in ai commands", "")
2790 log
.displayNL("AI Identifier are a string composed as follow :");
2791 log
.displayNL(" [AIS_<serice_id>:]{[<instance_idx>][:mgr_idx][:grp_idx][:bot_idx] | dyn_<cont_idx>[:<region_idx>][:<cellzone_idx>][:<family_idx>][:fauna|:npc]}");
2792 log
.displayNL(" e.g. : - AIS_138:1:2:3:4 for a 'static' bot");
2793 log
.displayNL(" - AIS_138:dyn_0:2:3:4:npc for a 'dynmaic' npc manager");
2794 log
.displayNL("The initial 'AIS_<serivce_id>:' is optional.");
2795 log
.displayNL("Most of the commands that need an AI id support 'multi selection' by specifying only part of the id.");
2799 NLMISC_COMMAND(despawnEntity
, "despawn an entity.","[entityId]")
2804 const std::string
&entityStr
=args
[0];
2805 const CEntityId
entity(entityStr
.c_str());
2807 const TDataSetRow dataSetRow
=TheDataset
.getDataSetRow(entity
);
2809 CAIEntityPhysical
*const phys
=CAIS::instance().getEntityPhysical(dataSetRow
);
2811 if (!phys
) { return true;}
2813 switch(phys
->getRyzomType())
2815 case RYZOMID::creature
:
2818 CSpawnBot
*const bot
=safe_cast
<CSpawnBot
*>(phys
);
2822 bot
->getPersistent().getGroup().bots().removeChildByIndex(bot
->getPersistent().getChildIndex());
2825 case RYZOMID::pack_animal
:
2827 CSpawnBotPet
*const pet
=safe_cast
<CSpawnBotPet
*>(phys
);
2831 pet
->getPersistent().setDespawn();
2841 /* Unload a primitive file
2842 * Unreference all the managers and the regions that are registered for this file.
2844 NLMISC_COMMAND(unloadPrimitiveFile
,"unload a primitive file","<file name>")
2849 // Get the string ID
2850 const NLMISC::TStringId stringId
=NLMISC::CStringMapper::map(CFile::getFilenameWithoutExtension(CFile::getFilename(args
[0])));
2852 uint managerUnreferenced
= 0;
2853 uint continentUnreferenced
= 0;
2855 // Parse AI instance
2856 CAIInstance
*aiInstance
= CWorkPtr::aiInstance();
2861 for (i
=0; i
<aiInstance
->managers().size(); i
++)
2863 CSmartPtr
<CManager
> manager
=aiInstance
->managers()[i
];
2866 // Remove this manager
2867 if (manager
->isRegisteredForFile (stringId
))
2869 aiInstance
->managers().removeChildByIndex (i
);
2870 managerUnreferenced
++;
2872 // Check the pointer is not referenced anymore
2873 nlassert (manager
->getRefCount() == 1);
2879 for (i
=0; i
<aiInstance
->continents().size(); i
++)
2881 CContinent
*continent
=aiInstance
->continents()[i
];
2886 for (j
=0; j
<continent
->regions().size(); j
++)
2888 CSmartPtr
<CRegion
> region
=continent
->regions()[j
];
2891 // Remove this region
2892 if (region
->isRegisteredForFile (stringId
))
2894 continent
->regions().removeChildByIndex (j
);
2895 continentUnreferenced
++;
2897 // Check the pointer is not referenced anymore
2898 nlassert (region
->getRefCount() == 1);
2904 aiInstance
=CAIS::instance().AIList().getNextValidChild(aiInstance
);
2905 uint32 primAlias
= LigoConfig
.getFileStaticAliasMapping(CFile::getFilename(args
[0]));
2906 nldebug("<unloadPrimitiveFile> Sending alias '%u' to AIS for custom data range deletion", primAlias
);
2907 CAIUserModelManager::getInstance()->deleteCustomDataByPrimAlias(primAlias
);
2908 log
.displayNL("unloadPrimitiveFile %s : %d manager removed, %d region removed", args
[0].c_str(), managerUnreferenced
, continentUnreferenced
);
2911 log
.displayNL("unloadPrimitiveFile failed : no active ai instance");
2916 //////////////////////////////////////////////////////////////////////////////
2917 // Bug simulation //
2918 //////////////////////////////////////////////////////////////////////////////
2920 static bool bugSimulationInited
= false;
2921 static bool bugSimulationTextInited
= false;
2922 static int const bugSimulationCount
= 10;
2923 static bool simulateBugs
[bugSimulationCount
];
2924 static char const* simulateBugTexts
[bugSimulationCount
];
2927 static void initBugSimulations()
2929 if (!bugSimulationInited
)
2931 bugSimulationInited
= true;
2932 for (int i
=0; i
<bugSimulationCount
; ++i
)
2934 simulateBugs
[i
] = false;
2940 static void initBugSimulationTexts()
2942 if (!bugSimulationTextInited
)
2944 bugSimulationTextInited
= true;
2945 for (int i
=0; i
<bugSimulationCount
; ++i
)
2946 simulateBugTexts
[i
] = "[No bug with this id] ";
2948 simulateBugTexts
[0] = "Bots didn't use range weapons ";
2949 simulateBugTexts
[1] = "Assign. a string var in another group ";
2950 simulateBugTexts
[2] = "Destination reach detection was delayed ";
2951 simulateBugTexts
[3] = "Npc grp behav. wasn't updtd often enough ";
2952 simulateBugTexts
[4] = "User event only worked in AI instance 0 ";
2953 simulateBugTexts
[5] = "Mektoubs following in Water ";
2954 simulateBugTexts
[6] = "When looted, fauna respawned immediately ";
2955 simulateBugTexts
[7] = "Added a member init. in normal profile ";
2956 simulateBugTexts
[8] = "Repulsion vector calc. was misordered ";
2961 static char const* simulateBugText(int bugId
)
2963 initBugSimulations();
2964 if (bugId
>=0 && bugId
<bugSimulationCount
)
2965 return simulateBugTexts
[bugId
];
2970 /// Past this declaration where needed
2971 extern bool simulateBug(int bugId
);
2973 bool simulateBug(int bugId
)
2975 initBugSimulations();
2976 if (bugId
>=0 && bugId
<bugSimulationCount
)
2977 return simulateBugs
[bugId
];
2982 NLMISC_COMMAND(simulateBug
, "simulate an old AIS bug; command is one of 'list', 'enable', 'disable'; enable and disable take as command_arg the id of the bug to simulate","<command> [<command_arg>]")
2987 if (args
[0] == "list")
2991 initBugSimulations();
2992 initBugSimulationTexts();
2993 log
.displayNL("Bug simulations");
2994 log
.displayNL("Id|Description |State");
2995 for (int i
=0; i
<bugSimulationCount
; ++i
)
2997 log
.displayNL("%02d|%s|%s", i
, simulateBugText(i
), simulateBugs
[i
]?"on":"off");
3002 else if (args
[0] == "enable")
3006 initBugSimulations();
3009 for (int i
=0; i
<bugSimulationCount
; ++i
)
3010 simulateBugs
[i
] = true;
3015 NLMISC::fromString(args
[1], i
);
3016 if (i
>=0 && i
<bugSimulationCount
)
3017 simulateBugs
[i
] = true;
3019 log
.displayNL("No bug simulation with id %02d", i
);
3024 else if (args
[0] == "disable")
3028 initBugSimulations();
3031 for (sint i
=0; i
<bugSimulationCount
; ++i
)
3032 simulateBugs
[i
] = false;
3037 NLMISC::fromString(args
[1], i
);
3038 if (i
>=0 && i
<bugSimulationCount
)
3039 simulateBugs
[i
] = false;
3041 log
.displayNL("No bug simulation with id %02d", i
);
3051 static void displayTime(const CRyzomTime
&rt
, NLMISC::CLog
&log
)
3054 result
= NLMISC::toString("hh:mm = %d:%d; ", (int) floorf(rt
.getRyzomTime()) , (int) floorf(60.f
* fmodf(rt
.getRyzomTime(), 1.f
)));
3055 log
.displayNL(result
.c_str());
3056 uint32 month
= rt
.getRyzomMonth();
3057 MONTH::EMonth monthInCycle
= rt
.getRyzomMonthInCurrentCycle();
3058 std::string monthName
= MONTH::toString((MONTH::EMonth
) monthInCycle
);
3059 uint32 dayOfMonth
= rt
.getRyzomDayOfMonth();
3060 std::string dayName
= WEEKDAY::toString((WEEKDAY::EWeekDay
) rt
.getRyzomDayOfWeek());
3061 result
= NLMISC::toString("mm:dd:yy = %d:%d:%d (%s:%s)",
3063 (int) (dayOfMonth
+ 1),
3064 (int) rt
.getRyzomYear(),
3067 log
.displayNL(result
.c_str());
3068 log
.displayNL("day of year = %d/%d", (int) (rt
.getRyzomDayOfYear() + 1), (int) RYZOM_YEAR_IN_DAY
);
3069 log
.displayNL("season = %d/4 (%s)", (int) rt
.getRyzomSeason() + 1, EGSPD::CSeason::toString(rt
.getRyzomSeason()).c_str());
3072 NLMISC_COMMAND(time
, "Display current time.", "<>")
3074 if (!args
.empty()) return false;
3075 const CRyzomTime
&rt
= CTimeInterface::getRyzomTime();
3076 displayTime(rt
, log
);
3080 NLMISC_COMMAND(localTime
, "Display current local time (debug time).", "<>")
3082 if (!args
.empty()) return false;
3083 const CRyzomTime
&rt
= CTimeInterface::getRyzomDebugTime();
3084 displayTime(rt
, log
);
3096 static void getRyzomDebugDate(CRyzomDate
&rd
)
3098 const CRyzomTime
&rt
= CTimeInterface::getRyzomDebugTime();
3099 rd
.Time
= rt
.getRyzomTime();
3100 rd
.Day
= rt
.getRyzomDayOfYear();
3101 rd
.Year
= rt
.getRyzomYear();
3104 static void setRyzomDebugDate(CRyzomDate
&rd
)
3106 CRyzomTime
&rt
= CTimeInterface::getRyzomDebugTime();
3107 rt
.updateRyzomClock((uint32
) (rd
.Time
* RYZOM_HOURS_IN_TICKS
) + (rd
.Day
+ rd
.Year
* RYZOM_YEAR_IN_DAY
) * RYZOM_DAY_IN_TICKS
);
3110 NLMISC_COMMAND(setDebugHour
, "set the current debug hour", "<hour>")
3112 if (args
.size() != 1) return false;
3114 if (!fromString(args
[0], hour
)) return false;
3116 getRyzomDebugDate(rd
);
3117 rd
.Time
= fmodf(rd
.Time
, 1.f
) + (float) hour
;
3118 setRyzomDebugDate(rd
);
3122 NLMISC_COMMAND(setDebugDayOfYear
, "set the current debug day of year (first day has index 1)", "<day>")
3124 if (args
.size() != 1) return false;
3126 if (!fromString(args
[0], day
)) return false;
3128 getRyzomDebugDate(rd
);
3129 rd
.Day
= day
- 1; // for the user, days start at '1'
3130 setRyzomDebugDate(rd
);
3135 // setPersistentVar setname:varName value
3137 NLMISC_COMMAND(setPersistentVar
, "sets an AI script persistent var", "<command> [<command_arg>]")
3139 if (args
.size() == 2)
3141 std::string varName
= args
[0].c_str();
3142 std::string value
= args
[1].c_str();
3144 CAIScriptDataManager::getInstance()->setVar(varName
, value
);
3146 log
.displayNL("Var '%s' set to '%s'", varName
.c_str(), value
.c_str());
3154 // listPersistentVar
3156 NLMISC_COMMAND(listPersistentVar
, "display all persistent vars", "")
3158 if (!args
.empty()) return false;
3160 const CPersistentVariables
&persistentVar
= CAIScriptDataManager::getInstance()->getPersistentVariables();
3162 const TVariableSets
&variableSet
= persistentVar
.getVariableSet();
3164 for (TVariableSets::const_iterator i
= variableSet
.begin(); i
!= variableSet
.end(); ++i
)
3166 log
.displayNL("#Set: '%s'#", i
->first
.c_str());
3167 for (TVariables::const_iterator j
= i
->second
.Variables
.begin(); j
!= i
->second
.Variables
.end(); ++j
)
3169 log
.displayNL("Name: '%s' -- Value: '%s'", j
->first
.c_str(), j
->second
.c_str());
3178 // getPersistentVar setname:varname
3180 NLMISC_COMMAND(getPersistentVarAsString
, "get a persistent ai var", "")
3182 if (args
.size() == 1)
3184 std::string varName
= args
[0];
3186 std::string value
= CAIScriptDataManager::getInstance()->getVar_s(varName
);
3187 log
.displayNL("Variable '%s' has value '%s'", varName
.c_str(), value
.c_str() );
3195 // getPersistentVar setname:varname
3197 NLMISC_COMMAND(getPersistentVarAsFloat
, "get a persistent ai var", "")
3199 if (args
.size() == 1)
3201 std::string varName
= args
[0];
3203 float value
= CAIScriptDataManager::getInstance()->getVar_f(varName
);
3204 nlinfo("Variable '%s' has value '%f'", varName
.c_str(), value
);
3211 NLMISC_COMMAND(deletePersistentVar
, "deletes an AI script persistent var", "")
3213 if (args
.size() == 1)
3215 std::string varName
= args
[0].c_str();
3217 CAIScriptDataManager::getInstance()->deleteVar(varName
);
3219 log
.displayNL("Var '%s' deleted", varName
.c_str());
3227 //----------------------------------------------------------------------------