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/>.
23 #include "child_container.h"
25 #include "ai_entity_matrix.h"
26 #include "ai_player.h"
27 #include "ai_mgr_pet.h"
29 #include "ai_mgr_fauna.h"
30 #include "ai_mgr_npc.h"
31 #include "ai_bot_npc.h"
32 #include "ai_grp_npc.h"
33 #include "ai_grp_pet.h"
35 #include "ai_script_data_manager.h"
37 #include "ais_user_models.h"
38 #include "continent.h"
39 #include "client_message.h"
40 #include "ai_outpost.h"
42 #include "nel/georges/u_form_loader.h"
43 #include "nel/georges/u_form_elm.h"
44 #include "nel/georges/u_form.h"
45 #include "nel/georges/u_form_dfn.h"
47 #include "game_share/emote_list_parser.h"
48 #include "game_share/backup_service_interface.h"
50 #include "ai_variables.h"
51 #include "server_share/r2_variables.h"
53 using namespace NLMISC
;
54 using namespace NLNET
;
56 using namespace NLGEORGES
;
58 //--------------------------------------------------------------------------
60 //--------------------------------------------------------------------------
63 CAIS
*CAIS::_Instance
= NULL
;
65 CRandom
CAIS::_random
;
67 const std::string
disengageString("DISENGAGE");
68 const std::string
egsString("EGS");
71 const uint32 Default_MaxPlayers
=5000;
72 const uint32 Default_MaxBotsPet
=Default_MaxPlayers
*4;
73 const uint32 Default_MaxBotsFauna
=40000;
74 const uint32 Default_MaxBotsNpc
=20000;
75 const uint32 Default_MaxBotsFx
=200;
77 CAIS
&CAIS::instance()
79 if (_Instance
== NULL
)
81 _Instance
= new CAIS();
91 : _PetBotCounter(TotalMaxPet
),
92 _FaunaBotCounter(TotalMaxFauna
),
93 _NpcBotCounter(TotalMaxNpc
)
95 // _initialised=false;
96 _TotalBotsSpawned
= 0;
97 _ClientCreatureDebug
=false;
100 void setMaxPetCallBack(IVariable
&var
)
102 uint32 newMax
=NLMISC::safe_cast
<CVariable
<uint32
>*>(&var
)->get();
103 if (CAIS::instanceCreated())
104 CAIS::instance()._PetBotCounter
.setMax(newMax
);
106 void setMaxFaunaCallBack(IVariable
&var
)
108 uint32 newMax
=NLMISC::safe_cast
<CVariable
<uint32
>*>(&var
)->get();
109 if (CAIS::instanceCreated())
110 CAIS::instance()._FaunaBotCounter
.setMax(newMax
);
112 void setMaxNpcCallBack(IVariable
&var
)
114 uint32 newMax
=NLMISC::safe_cast
<CVariable
<uint32
>*>(&var
)->get();
115 if (CAIS::instanceCreated())
116 CAIS::instance()._NpcBotCounter
.setMax(newMax
);
119 CVariable
<uint32
> TotalMaxPlayer("ai", "NbPlayersLimit", "Security absolute limit to the number of Player", Default_MaxPlayers
, 0, true );
120 CVariable
<uint32
> TotalMaxPet("ai", "NbPetLimit", "Security absolute limit to the number of Pets", Default_MaxBotsPet
, 0, true, setMaxPetCallBack
);
121 CVariable
<uint32
> TotalMaxFauna("ai", "NbFaunaLimit", "Security absolute limit to the number of Faunas", Default_MaxBotsFauna
, 0, true, setMaxFaunaCallBack
);
122 CVariable
<uint32
> TotalMaxNpc("ai", "NbNpcLimit", "Security absolute limit to the number of Npcs", Default_MaxBotsNpc
, 0, true, setMaxNpcCallBack
);
123 CVariable
<uint32
> TotalMaxFx("ai", "NbFxLimit", "Security absolute limit to the number of Fx", Default_MaxBotsFx
, 0, true );
125 CVariable
<string
> BotRepopFx("ai", "BotRepopFx", "Fx sheet to use when changing the sheet of a bot", string(), 0, true );
127 //--------------------------------------------------------------------------
128 // DATA TABLES FOR ENTITY MATRIX
129 //--------------------------------------------------------------------------
131 // a series of tables giving the minimum iterator table forms for entity matrix iterators for all sizes up to 127m
132 static uint32 EntityMatrixTbl0
[] = { 3, 3, 3};
133 static uint32 EntityMatrixTbl16
[] = { 3, 5, 5, 5, 3};
134 static uint32 EntityMatrixTbl23
[] = { 5, 5, 5, 5, 5};
135 static uint32 EntityMatrixTbl32
[] = { 3, 5, 7, 7, 7, 5, 3};
136 static uint32 EntityMatrixTbl36
[] = { 5, 7, 7, 7, 7, 7, 5};
137 static uint32 EntityMatrixTbl46
[] = { 7, 7, 7, 7, 7, 7, 7};
138 static uint32 EntityMatrixTbl48
[] = { 3, 7, 7, 9, 9, 9, 7, 7, 3};
139 static uint32 EntityMatrixTbl51
[] = { 5, 7, 9, 9, 9, 9, 9, 7, 5};
140 static uint32 EntityMatrixTbl58
[] = { 7, 9, 9, 9, 9, 9, 9, 9, 7};
141 static uint32 EntityMatrixTbl64
[] = { 3, 7, 9, 9, 11, 11, 11, 9, 9, 7, 3};
142 static uint32 EntityMatrixTbl66
[] = { 5, 7, 9, 11, 11, 11, 11, 11, 9, 7, 5};
143 static uint32 EntityMatrixTbl68
[] = { 5, 9, 9, 11, 11, 11, 11, 11, 9, 9, 5};
144 static uint32 EntityMatrixTbl72
[] = { 7, 9, 11, 11, 11, 11, 11, 11, 11, 9, 7};
145 static uint32 EntityMatrixTbl80
[] = { 3, 9, 11, 11, 11, 13, 13, 13, 11, 11, 11, 9, 3};
146 static uint32 EntityMatrixTbl82
[] = { 5, 9, 11, 11, 13, 13, 13, 13, 13, 11, 11, 9, 5};
147 static uint32 EntityMatrixTbl87
[] = { 7, 9, 11, 13, 13, 13, 13, 13, 13, 13, 11, 9, 7};
148 static uint32 EntityMatrixTbl91
[] = { 7, 11, 11, 13, 13, 13, 13, 13, 13, 13, 11, 11, 7};
149 static uint32 EntityMatrixTbl94
[] = { 9, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 9};
150 static uint32 EntityMatrixTbl96
[] = { 3, 9, 11, 13, 13, 13, 15, 15, 15, 13, 13, 13, 11, 9, 3};
151 static uint32 EntityMatrixTbl98
[] = { 5, 9, 11, 13, 13, 15, 15, 15, 15, 15, 13, 13, 11, 9, 5};
152 static uint32 EntityMatrixTbl102
[] = { 7, 9, 11, 13, 15, 15, 15, 15, 15, 15, 15, 13, 11, 9, 7};
153 static uint32 EntityMatrixTbl103
[] = { 7, 11, 13, 13, 15, 15, 15, 15, 15, 15, 15, 13, 13, 11, 7};
154 static uint32 EntityMatrixTbl108
[] = { 9, 11, 13, 15, 15, 15, 15, 15, 15, 15, 15, 15, 13, 11, 9};
155 static uint32 EntityMatrixTbl112
[] = { 3, 9, 11, 13, 15, 15, 15, 17, 17, 17, 15, 15, 15, 13, 11, 9, 3};
156 static uint32 EntityMatrixTbl114
[] = { 5, 9, 13, 13, 15, 15, 17, 17, 17, 17, 17, 15, 15, 13, 13, 9, 5};
157 static uint32 EntityMatrixTbl116
[] = { 5, 11, 13, 15, 15, 15, 17, 17, 17, 17, 17, 15, 15, 15, 13, 11, 5};
158 static uint32 EntityMatrixTbl117
[] = { 7, 11, 13, 15, 15, 17, 17, 17, 17, 17, 17, 17, 15, 15, 13, 11, 7};
159 static uint32 EntityMatrixTbl122
[] = { 9, 11, 13, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 15, 13, 11, 9};
160 static uint32 EntityMatrixTbl125
[] = { 9, 13, 15, 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 15, 15, 13, 9};
162 // a few larger special case matrices
163 static uint32 EntityMatrixTblUpTo150
[] = { 7, 11, 15, 17, 17, 19, 19, 21, 21, 21, 21, 21, 21, 21, 19, 19, 17, 17, 15, 11, 7};
164 static uint32 EntityMatrixTblUpTo200
[] = { 9, 13, 17, 19, 21, 23, 23, 25, 25, 27, 27, 27, 27, 27, 27, 27, 27, 27, 25, 25, 23, 23, 21, 19, 17, 13, 9};
165 static uint32 EntityMatrixTblUpTo250
[] = {11, 15, 19, 23, 25, 27, 27, 29, 29, 31, 31, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 31, 31, 29, 29, 27, 27, 25, 23, 19, 15, 11};
167 static void initLinearMatrixIteratorTables(std::vector
<CAIEntityMatrixIteratorTblLinear
*> &vect
)
169 // initialise the vector with the first table
170 vect
.push_back(new CAIEntityMatrixIteratorTblLinear(&(EntityMatrixTbl0
[0]),3));
172 // local macro undefined at end of function
175 while (vect.size()<d) \
176 vect.push_back(vect[vect.size()-1]); \
177 vect.push_back(new CAIEntityMatrixIteratorTblLinear(EntityMatrixTbl##d,sizeof(EntityMatrixTbl##d)/sizeof(EntityMatrixTbl##d[0]))); \
180 // setup the tables ...
181 ADD_TBL(16) ADD_TBL(23)
182 ADD_TBL(32) ADD_TBL(36) ADD_TBL(46)
183 ADD_TBL(48) ADD_TBL(51) ADD_TBL(58)
184 ADD_TBL(64) ADD_TBL(66) ADD_TBL(68) ADD_TBL(72)
185 ADD_TBL(80) ADD_TBL(82) ADD_TBL(87) ADD_TBL(91) ADD_TBL(94)
186 ADD_TBL(96) ADD_TBL(98) ADD_TBL(102) ADD_TBL(103) ADD_TBL(108)
187 ADD_TBL(112) ADD_TBL(114) ADD_TBL(116) ADD_TBL(117) ADD_TBL(122) ADD_TBL(125)
192 bool CAIS::markTagForDelete(const std::string
&filename
)
194 const TStringId fileId
= CStringMapper::map(filename
);
195 for (CCont
<CAIInstance
>::iterator it
=_AIInstances
.begin(), itEnd
=_AIInstances
.end(); it
!=itEnd
;++it
)
197 // first: tag the dynamic regions in the continents
198 for_each(it
->continents().begin(), it
->continents().end(),
199 bind2nd(mem_fun(&CContinent::markTagForDelete
), fileId
));
201 for_each(it
->managers().begin(),it
->managers().end(),
202 CAliasTreeRoot::CMarkTagForDelete(fileId
));
207 void CAIS::deleteTaggedAlias(const std::string
&filename
)
209 const TStringId fileId
= CStringMapper::map(filename
);
210 FOREACH(it
, CCont
<CAIInstance
>, _AIInstances
)
212 // first: tag the dynamic regions in the continents
213 for_each(it
->continents().begin(), it
->continents().end(),
214 bind2nd(mem_fun(&CContinent::deleteTaggedAlias
),fileId
));
216 for_each(it
->managers().begin(),it
->managers().end(),
217 CAliasTreeRoot::CDeleteTagged
<CManager
>(it
->managers()));
223 uint32
CAIS::getEmotNumber(const std::string
&name
)
225 std::map
<std::string
, uint32
>::iterator
it(_EmotNames
.find(name
));
226 if (it
==_EmotNames
.end())
227 return std::numeric_limits
<uint32
>::max();
233 bool CAIS::advanceUserTimer (uint32 nbTicks
)
235 // for each manager, look for a timer event
236 for_each(AIList().begin(), AIList().end(), bind2nd(mem_fun(&CAIInstance::advanceUserTimer
),nbTicks
) );
242 // initialise the singleton
247 // _initialised=true;
248 nlinfo("---------- Initialising AI Singleton ----------");
250 // setup the random number generator
251 _random
.srand( (sint32
)NLMISC::CTime::getLocalTime() );
253 // allocate RAM for the players
255 // setup the standard iterator tables for scanning the entity matrices
256 _matrixIterator2x2
.push_back(-1,-1); _matrixIterator2x2
.push_back(1,0);
257 _matrixIterator2x2
.push_back(-1, 1); _matrixIterator2x2
.push_back(1,0);
259 _matrixIterator3x3
.push_back(-1,-1); _matrixIterator3x3
.push_back(1,0); _matrixIterator3x3
.push_back(1,0);
260 _matrixIterator3x3
.push_back(-2, 1); _matrixIterator3x3
.push_back(1,0); _matrixIterator3x3
.push_back(1,0);
261 _matrixIterator3x3
.push_back(-2, 1); _matrixIterator3x3
.push_back(1,0); _matrixIterator3x3
.push_back(1,0);
263 // setup the set of linear iterator tables for generating visions of given distances
264 initLinearMatrixIteratorTables(_matrixIteratorsByDistance
);
266 EMOTE_LIST_PARSER::initEmoteList(_EmotNames
);
268 // init the client message callbacks
269 CAIClientMessages::init();
273 uint32
CAIS::createAIInstance(const std::string
&continentName
, uint32 instanceNumber
)
275 // first, check that an instance with this number is not already running
277 for (CCont
<CAIInstance
>::iterator it
=_AIInstances
.begin(), itEnd
=_AIInstances
.end();it
!=itEnd
;++it
)
279 if (it
->getInstanceNumber()!=instanceNumber
)
282 nlwarning("CAIS::createAIInstance: instance number %u is already in use, can't create new instance.", instanceNumber
);
283 return std::numeric_limits
<uint32
>::max();
286 CAIInstance
*aii
= _AIInstances
.addChild(new CAIInstance(this));
288 // ok, set the continent name and instance number
289 aii
->initInstance(continentName
, instanceNumber
);
291 return aii
->getChildIndex();
294 void CAIS::destroyAIInstance(uint32 instanceNumber
, bool displayWarningIfInstanceNotExist
)
296 // this method is not fully tested for a Ryzom shard
297 // but it should work as expected for a Ring shard
298 nlassert(IsRingShard
.get());
300 CRefPtr
<CAIInstance
> aii
= getAIInstance(instanceNumber
);
303 if (displayWarningIfInstanceNotExist
)
305 nlwarning("AI instance %u does not exist but it was asked to delete here", instanceNumber
);
310 _AIInstances
.removeChildByIndex(aii
->getChildIndex());
311 nlassert(aii
== NULL
);
314 if (EGSHasMirrorReady
)
316 CReportAIInstanceDespawnMsg msg
;
317 msg
.InstanceNumbers
.push_back(instanceNumber
);
323 // release the singleton before program exit
324 void CAIS::release ()
326 // force an update to save the persistent var if needed
327 updatePersistentVariables();
329 // erase all ai instance.
332 CAIUserModelManager::getInstance()->destroyInstance();
333 // release the client message callbacks
334 CAIClientMessages::release();
337 // free up the vision matrix iterator tables
338 if (!_matrixIteratorsByDistance
.empty())
340 for (uint i
=0;i
<_matrixIteratorsByDistance
.size();)
342 // erase the iterator table
343 delete _matrixIteratorsByDistance
[i
];
344 // run i forwards past repeated refs to the iterator tbl that we just deleted
345 for (++i
;i
<_matrixIteratorsByDistance
.size() && _matrixIteratorsByDistance
[i
]==_matrixIteratorsByDistance
[i
-1];++i
) {}
347 _matrixIteratorsByDistance
.clear();
353 void CAIS::serviceEvent (const CServiceEvent
&info
)
355 if (info
.getEventType() == CServiceEvent::SERVICE_UP
&& info
.getServiceName() == "EGS")
357 // send the list of available collision data
358 CReportAICollisionAvailableMsg msg
;
359 msg
.ContinentsCollision
= CWorldContainer::getContinentList();
360 msg
.send(info
.getServiceId());
363 // event on all ai instance
365 // for_each(_AIInstances.begin(), _AIInstances.end(), bind2nd(mem_fun1(&CAIInstance::serviceEvent), info));
366 // don't compile coz we need to pass an object and not a reference (info). have to build an object that represents the reference.
368 FOREACH(it
, CCont
<CAIInstance
>, _AIInstances
)
369 it
->serviceEvent (info
);
373 //--------------------------------------------------------------------------
375 //--------------------------------------------------------------------------
377 // the update routine called once per tick
378 // this is the routine that calls the managers' updates
379 extern void execBufferedCommands();
380 extern void execNamedEntityChanges();
384 if (!EGSHasMirrorReady
)
390 // Init stat counters
391 AISStat::countersBegin();
393 // Execute buffered Task
394 uint32 tick
= CTimeInterface::gameCycle();
395 _TickedTaskList
.execute(tick
);
397 // Execute buffered functions that need to be executed in the correct context
398 execBufferedCommands();
401 execNamedEntityChanges();
403 // Update AI instances
404 FOREACH(it
, CCont
<CAIInstance
>, CAIS::instance().AIList())
405 (*it
)->CAIInstance::update();
407 // Send systematic messages to EGS
408 if (EGSHasMirrorReady
)
410 // send the fauna description message to EGS then clear the content.
411 if (!_FaunaDescriptionList
.Bots
.empty())
413 nlassert(_FaunaDescriptionList
.Bots
.size() == _FaunaDescriptionList
.GrpAlias
.size());
414 _FaunaDescriptionList
.send("EGS");
415 _FaunaDescriptionList
.Bots
.clear();
416 _FaunaDescriptionList
.GrpAlias
.clear();
418 // send agglomerated hp changes
419 if (!_CreatureChangeHPList
.Entities
.empty())
421 nlassert(_CreatureChangeHPList
.Entities
.size()==_CreatureChangeHPList
.DeltaHp
.size());
422 _CreatureChangeHPList
.send("EGS");
423 _CreatureChangeHPList
.Entities
.clear();
424 _CreatureChangeHPList
.DeltaHp
.clear();
426 if (!_CreatureChangeMaxHPList
.Entities
.empty())
428 nlassert(_CreatureChangeMaxHPList
.Entities
.size()==_CreatureChangeMaxHPList
.MaxHp
.size());
429 nlassert(_CreatureChangeMaxHPList
.Entities
.size()==_CreatureChangeMaxHPList
.SetFull
.size());
430 _CreatureChangeMaxHPList
.send("EGS");
431 _CreatureChangeMaxHPList
.Entities
.clear();
432 _CreatureChangeMaxHPList
.MaxHp
.clear();
433 _CreatureChangeMaxHPList
.SetFull
.clear();
438 // update persistent variables every 1024 tick if AI script data manager is flagged
439 if ((tick
& 0x3FF) == 0)
441 updatePersistentVariables();
444 //TODO: UserModelManager must send UserModels to EGS if not done yet
445 //CAIUserModelManager::getInstance()->sendUserModels();
446 // Terminate counters and store stats in an accessible place
447 AISStat::countersEnd();
450 // provoke a general 'save to backup' across the whole service
453 nlinfo("*** save() NOT IMPLEMENTED YET ***");
457 //--------------------------------------------------------------------------
458 // management of iterator tables for vision matrices
459 //--------------------------------------------------------------------------
461 const CAIEntityMatrixIteratorTblLinear
* CAIS::bestLinearMatrixIteratorTbl(uint32 distInMeters
)
464 nlassert(!_matrixIteratorsByDistance
.empty());
467 if (distInMeters
>= _matrixIteratorsByDistance
.size())
469 //nlwarning("Try to access to a Vision Matrix to far %u the farest is only %u", distInMeters, _matrixIteratorsByDistance.size());
470 return _matrixIteratorsByDistance
.back();
473 return _matrixIteratorsByDistance
[distInMeters
];
476 int getInt64FromStr (const char* str
)
478 if(str
[0] == '0' && (str
[1] == 'x' || str
[1] == 'X'))
479 return (int) atoiInt64(str
+2,16);
480 return (int) atoiInt64(str
,10);
483 // all these dynamics casts can be throwned away ..
484 CAIInstance
* CAIS::tryToGetAIInstance(const char* str
)
486 return dynamic_cast<CAIInstance
*> (tryToGetEntity(str
,CAIS::AI_INSTANCE
));
489 CContinent
*CAIS::tryToGetContinent (const char *str
)
491 return dynamic_cast<CContinent
*> (tryToGetEntity(str
,CAIS::AI_CONTINENT
));
494 CRegion
*CAIS::tryToGetRegion (const char *str
)
496 return dynamic_cast<CRegion
*> (tryToGetEntity(str
,CAIS::AI_REGION
));
499 CCellZone
*CAIS::tryToGetCellZone (const char *str
)
501 return dynamic_cast<CCellZone
*> (tryToGetEntity(str
,CAIS::AI_CELL_ZONE
));
504 CFamilyBehavior
*CAIS::tryToGetFamilyBehavior (const char *str
)
506 return dynamic_cast<CFamilyBehavior
*> (tryToGetEntity(str
,CAIS::AI_FAMILY_BEHAVIOR
));
510 CManager
* CAIS::tryToGetManager(const char* str
)
512 return dynamic_cast<CManager
*> (tryToGetEntity(str
,CAIS::AI_MANAGER
));
515 CGroup
* CAIS::tryToGetGroup(const char* str
)
517 return dynamic_cast<CGroup
*> (tryToGetEntity(str
,CAIS::AI_GROUP
));
520 CBot
* CAIS::tryToGetBot(const char* str
)
522 return dynamic_cast<CBot
*> (tryToGetEntity(str
,CAIS::AI_BOT
));
525 CAIEntity
* CAIS::tryToGetAIEntity(const char* str
)
527 return dynamic_cast<CAIEntity
*> (tryToGetEntity(str
));
530 CAIEntityPhysical
* CAIS::tryToGetEntityPhysical(const char* str
)
533 entityId
.fromString(str
);
534 return CAIS::getEntityPhysical(CMirrors::DataSet
->getDataSetRow(entityId
));
537 CAIEntity
* CAIS::tryToGetEntity(const char* str
, TSearchType searchType
)
539 CAIInstance
*aii
= NULL
;
540 CManager
*mgr
= NULL
;
545 vector
<string
> parts
;
546 explode(string(str
), string(":"), parts
, false);
548 if (parts
.empty() || parts
[0].empty())
551 // skip AIS number if any
552 if (parts
[0].substr(0, 4) == "AIS_")
553 parts
.erase(parts
.begin());
556 if (parts
.empty() || parts
[0].empty()) return NULL
;
559 uint32 index
= atoui(parts
[0].c_str());
560 if (index
>= CAIS::instance().AIList().size())
561 goto tryWithEntityId
;
562 aii
= CAIS::AIList()[index
];
564 goto tryWithEntityId
;
565 if (searchType
==CAIS::AI_INSTANCE
566 || (searchType
== CAIS::AI_UNDEFINED
&& parts
.size() == 1))
569 parts
.erase(parts
.begin());
572 if (parts
.empty() || parts
[0].empty()) return NULL
;
574 // branch on static or dynamic system
576 if (parts
[0].find("dyn_") == 0)
581 index
= atoui(parts
[0].substr(4).c_str());
582 if (index
>= aii
->continents().size())
584 CContinent
*continent
= aii
->continents()[index
];
585 if (searchType
==CAIS::AI_CONTINENT
586 || (searchType
== CAIS::AI_UNDEFINED
&& parts
.size() == 1))
589 parts
.erase(parts
.begin());
592 if (parts
.empty() || parts
[0].empty()) return NULL
;
595 index
= atoui(parts
[0].c_str());
596 if (index
>= continent
->regions().size())
598 CRegion
*region
= continent
->regions()[index
];
599 if (searchType
==CAIS::AI_REGION
600 || (searchType
== CAIS::AI_UNDEFINED
&& parts
.size() == 1))
603 parts
.erase(parts
.begin());
606 if (parts
.empty() || parts
[0].empty()) return NULL
;
609 index
= atoui(parts
[0].c_str());
610 if (index
>= region
->cellZones().size())
612 CCellZone
*cz
= region
->cellZones()[index
];
613 if (searchType
==CAIS::AI_CELL_ZONE
614 || (searchType
== CAIS::AI_UNDEFINED
&& parts
.size() == 1))
617 parts
.erase(parts
.begin());
620 if (parts
.empty() || parts
[0].empty()) return NULL
;
622 // family behavior index
623 index
= atoui(parts
[0].c_str());
624 if (index
>= cz
->familyBehaviors().size())
626 CFamilyBehavior
*fb
= cz
->familyBehaviors()[index
];
627 if (searchType
==CAIS::AI_FAMILY_BEHAVIOR
628 || (searchType
== CAIS::AI_UNDEFINED
&& parts
.size() == 1))
631 parts
.erase(parts
.begin());
634 if (parts
.empty() || parts
[0].empty())
638 if (parts
[0] == "npc")
640 else if (parts
[0] == "fauna")
641 mgr
= fb
->mgrFauna();
646 if (searchType
==CAIS::AI_MANAGER
647 || (searchType
== CAIS::AI_UNDEFINED
&& parts
.size() == 1)
651 parts
.erase(parts
.begin());
654 if (parts
.empty() || parts
[0].empty()) return NULL
;
661 index
= atoui(parts
[0].c_str());
662 if (index
>= aii
->managers().size())
664 mgr
= aii
->managers()[index
];
665 if (searchType
==CAIS::AI_MANAGER
666 || (searchType
== CAIS::AI_UNDEFINED
&& parts
.size() == 1)
670 parts
.erase(parts
.begin());
674 if (parts
.empty() || parts
[0].empty()) return NULL
;
678 index
= atoui(parts
[0].c_str());
679 if (index
>= mgr
->groups().size())
681 grp
= mgr
->groups()[index
];
682 if (searchType
==CAIS::AI_GROUP
683 || (searchType
== CAIS::AI_UNDEFINED
&& parts
.size() == 1))
686 parts
.erase(parts
.begin());
689 if (parts
.empty() || parts
[0].empty()) return NULL
;
692 index
= atoui(parts
[0].c_str());
693 if (index
>= grp
->bots().size())
695 bot
= grp
->bots()[index
];
696 if (searchType
==CAIS::AI_BOT
697 || (searchType
== CAIS::AI_UNDEFINED
&& parts
.size() == 1))
706 entityId
.fromString(str
);
708 if (entityId
.isUnknownId())
711 CCont
<CAIInstance
>::iterator instanceIt
=CAIS::instance().AIList().begin(), instanceItEnd
=CAIS::instance().AIList().end();
713 while (instanceIt
!=instanceItEnd
)
715 CAIInstance
*instancePtr
=*instanceIt
;
717 CCont
<CManager
>::iterator it
=instancePtr
->managers().begin(), itEnd
=instancePtr
->managers().end();
721 CManager
*mgrPtr
= *it
;
723 CGroup
*grpPtr
= mgrPtr
->getNextValidGroupChild ();
726 CBot
*botPtr
= grpPtr
->getNextValidBotChild();
729 if ( botPtr
->isSpawned()
730 && botPtr
->getSpawnObj()->getEntityId() == entityId
)
731 return dynamic_cast<CAIEntity
*> (botPtr
);
732 botPtr
= grpPtr
->getNextValidBotChild (botPtr
);
734 grpPtr
=mgrPtr
->getNextValidGroupChild (grpPtr
);
748 //--------------------------------------------------------------------------
749 // manageing the set of maps
750 //--------------------------------------------------------------------------
752 CAIEntityPhysical
*CAIS::getEntityPhysical(const TDataSetRow
& row
)
754 CHashMap
<int,NLMISC::CDbgPtr
<CAIEntityPhysical
> >::iterator
it(_CAIEntityByDataSetRow
.find(row
.getIndex()));
756 if (it
!=_CAIEntityByDataSetRow
.end())
760 // the code below generates an error .. :( hu !
764 //-------------------------------------------------------------------
765 // Interface to bot chat - callbacks called when bots start or
766 // stop chatting with player(s)
767 //-------------------------------------------------------------------
769 void CAIS::beginBotChat(const TDataSetRow
&bot
,const TDataSetRow
&player
)
772 /// Is this still true?
773 nlwarning("Chat can't work now as bot are now splitted in persistent and spawnable part. Have to rework on this part.");
776 // get a pointer to the bot
777 CSpawnBotNpc
* botNpc
=dynamic_cast<CSpawnBotNpc
*>(CAIS::getEntityPhysical(bot
));
780 // nlwarning("CAIS::beginBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
784 // get a pointer to the player
785 CBotPlayer
* plrPtr
= dynamic_cast<CBotPlayer
*>(CAIS::getEntityPhysical(player
));
788 // nlwarning("CAIS::beginBotChat(): Bot chat message identifies an unknown player!!!");
792 // have the bot register the chat
793 botNpc
->beginBotChat(plrPtr
);
796 void CAIS::endBotChat(const TDataSetRow
&bot
, const TDataSetRow
&player
)
798 // get a pointer to the bot
799 CSpawnBotNpc
* botNpc
=dynamic_cast<CSpawnBotNpc
*>(CAIS::getEntityPhysical(bot
));
802 // nlwarning("CAIS::endBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
806 // get a pointer to the player
807 CBotPlayer
* plrPtr
= dynamic_cast<CBotPlayer
*>(CAIS::getEntityPhysical(player
));
810 // nlwarning("CAIS::endBotChat(): Bot chat message identifies an unknown player!!!");
814 // have the bot register the chat end
815 botNpc
->endBotChat(plrPtr
);
818 void CAIS::beginDynChat(const TDataSetRow
&bot
)
820 // get a pointer to the bot
821 CSpawnBotNpc
* botNpc
=dynamic_cast<CSpawnBotNpc
*>(CAIS::getEntityPhysical(bot
));
824 // nlwarning("CAIS::beginBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
828 // have the bot register the chat
829 botNpc
->beginDynChat();
830 nldebug( "DYNCHT: E%u: %u dyn chats", bot
.getIndex(), botNpc
->getNbActiveDynChats() );
833 void CAIS::endDynChat(const TDataSetRow
&bot
)
835 // get a pointer to the bot
836 CSpawnBotNpc
* botNpc
=dynamic_cast<CSpawnBotNpc
*>(CAIS::getEntityPhysical(bot
));
839 // nlwarning("CAIS::endBotChat(): Bot chat message identifies an entity that isn't an NPC!!!");
843 // have the bot register the chat end
844 botNpc
->endDynChat();
845 nldebug( "DYNCHT: E%u: %u dyn chats", bot
.getIndex(), botNpc
->getNbActiveDynChats() );
849 void CAIPlaceXYR::display(CStringWriter
&stringWriter
) const
851 stringWriter
.append("XYR: ("+_pos
.x().toString()
854 +" "+toString(_pos
.h())
860 // nlinfo("XYR: (%s,%s,%d) x %f :%s",_pos.x().toString().c_str(),_pos.y().toString().c_str(),_pos.h(),_radius,getName().c_str());
864 void CAIS::warnBadInstanceMsgImp(const std::string
&serviceName
, TServiceId serviceId
, CWarnBadInstanceMsgImp
&msg
)
866 // EGS says that an instance is spoofing an instance number or using a bad static instance number/continent name association.
867 // we must despawn/delete the aiinstance
869 FOREACH(it
, CCont
<CAIInstance
>, _AIInstances
)
871 if ((*it
)->getInstanceNumber()!=msg
.InstanceNumber
)
874 // ok, we found the bad guy !
875 nlwarning("CAIS::warnBadInstanceMsgImp: despawning AIInstance %u, instance number %u, continent '%s'",
876 (*it
)->getChildIndex(), msg
.InstanceNumber
, (*it
)->getContinentName().c_str());
877 _AIInstances
.removeChildByIndex((*it
)->getChildIndex());
882 nlwarning("CAIS::warnBadInstanceMsgImp: can't find AIInstance with instance number %u ! Can't despawn it", msg
.InstanceNumber
);
885 void CAIS::updatePersistentVariables()
887 if (CAIScriptDataManager::getInstance()->needsPersistentVarUpdate() == true)
889 // sending data to bs
890 CPersistentDataRecord
pdr("AiTokenFamily");
892 CAIScriptDataManager::getInstance()->getPersistentVariables().store(pdr
);
894 uint32 bufSize
= pdr
.totalDataSize();
896 buffer
.resize(bufSize
);
897 pdr
.toBuffer(&buffer
[0],bufSize
);
899 CBackupMsgSaveFile
msg( CAIScriptDataManager::getInstance()->makePdrFileName(), CBackupMsgSaveFile::SaveFile
, Bsi
);
900 msg
.DataMsg
.serialBuffer((uint8
*)&buffer
[0], bufSize
);
903 CAIScriptDataManager::getInstance()->clearDirtyFlag();
907 CAIInstance
*CAIS::getAIInstance(uint32 instanceNumber
)
909 FOREACH(it
, CCont
<CAIInstance
>, _AIInstances
)
911 if ((*it
)->getInstanceNumber()==instanceNumber
)