Added ai command setEquipment
[ryzomcore.git] / ryzom / server / src / ai_service / messages.cpp
blob6b1006b7020dae9dfb397487c0fa2b89d865f264
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2019 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 // include files
23 #include "stdpch.h"
25 #include "npc_description_msg.h"
26 #include "ai.h"
27 #include "ai_mgr_pet.h"
28 #include "ai_share/ai_actions.h"
29 #include "aids_interface.h"
30 #include "ai_player.h"
31 #include "ai_grp_pet.h"
32 #include "ai_bot_npc.h"
33 #include "ai_mgr_npc.h"
34 #include "ai_grp_npc.h"
35 #include "ai_bot_fauna.h"
36 #include "ai_mgr_fauna.h"
37 #include "ai_grp_fauna.h"
38 #include "ai_profile_fauna.h" // for CCorpseFaunaProfile
39 #include "dyn_mission.h"
40 #include "mirrors.h"
41 #include "commands.h"
44 #include "game_share/tick_event_handler.h"
45 #include "messages.h"
46 #include "server_share/msg_brick_service.h"
47 #include "server_share/msg_ai_service.h"
48 #include "server_share/effect_message.h"
49 // ai_share
50 #include "ai_share/ai_actions_dr.h"
53 #include "egs_interface.h"
56 #include "dyn_grp_inline.h"
58 using namespace NLMISC;
59 using namespace NLNET;
60 using namespace AITYPES;
62 //--------------------------------------------------------------------------
63 // CTransportClass message receivers
64 //--------------------------------------------------------------------------
66 class CCharacterBotChatBeginEndReceiver: public CCharacterBotChatBeginEnd
68 virtual void callback (const std::string &name, NLNET::TServiceId id)
70 // make sure bot chat start vector size is even
71 if (BotChatStart.size()&1)
73 nlwarning("CCharacterBotChatBeginEndReceiver::callback(): Invalid BotChatStart vector length");
74 return;
77 // make sure bot chat end vector size is even
78 if (BotChatEnd.size()&1)
80 nlwarning("CCharacterBotChatBeginEndReceiver::callback(): Invalid BotChatEnd vector length");
81 return;
84 // nlwarning("Cannot initiate Chat between Bot, will be correct in next AI integration");
86 // start new bot chats
88 for (uint i=0;i<BotChatStart.size();i+=2)
89 CAIS::instance().beginBotChat(BotChatStart[i+1],BotChatStart[i]);
92 // terminate ended bot chats
94 for (uint i=0;i<BotChatEnd.size();i+=2)
95 CAIS::instance().endBotChat(BotChatEnd[i+1],BotChatEnd[i]);
101 class CCharacterDynChatBeginEndReceiver: public CCharacterDynChatBeginEnd
103 virtual void callback (const std::string &name, NLNET::TServiceId id)
105 // report to the npcs
106 for ( uint i=0; i!=DynChatStart.size(); ++i )
107 CAIS::instance().beginDynChat( DynChatStart[i]);
108 for ( uint i=0; i!=DynChatEnd.size(); ++i )
109 CAIS::instance().endDynChat( DynChatEnd[i] );
115 //-------------------------------------------------------------------------
116 // callback for AIDS seviceUp() event
117 //--------------------------------------------------------------------------
119 static void cbAIDSServiceUp( const std::string &serviceName, uint16 serviceId, void *arg )
121 CMsgAIServiceUp(100.0f,100.0f).send(uint8(serviceId));
125 //-------------------------------------------------------------------------
126 // the callback table
127 //--------------------------------------------------------------------------
129 static void cbAddEntities( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
130 static void cbR2GoLive( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
131 static void cbR2StopLive( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
132 static void cbR2StartInstance( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
133 extern void cbR2NpcBotScriptById( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
134 extern void cbR2NpcGroupScriptByName( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
135 static void cbValidateSourceSpawn( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
136 static void cbValidateSimpleSourceSpawn( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
137 extern void cbOutpostCreateSquad( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
138 extern void cbOutpostSpawnSquad( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
139 extern void cbOutpostDespawnSquad( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
140 extern void cbOutpostDeleteSquad( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
141 extern void cbOutpostDespawnAllSquads( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
142 extern void cbOutpostSetOwner( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
143 extern void cbOutpostSetAttacker( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
144 extern void cbOutpostSetState( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
145 extern void cbOutpostEvent( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
146 extern void cbOutpostSetBuildingBotSheet( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
147 extern void cbEventCreateNpcGroup( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
148 extern void cbEventNpcGroupScript( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
149 extern void cbEventFaunaBotSetRadii( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
150 extern void cbEventFaunaBotResetRadii( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
151 extern void cbEventBotCanAggro( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
152 extern void cbEventBotSheet( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
153 extern void cbAskBotDespawnNotification( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
154 extern void cbSpawnEasterEgg( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
155 extern void cbDespawnEasterEgg( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId );
158 TUnifiedCallbackItem CbArray[] =
160 { "ADDED_ENTITIES", cbAddEntities, },
161 { "SRC_SPWN_VLD", cbValidateSourceSpawn },
162 { "S_SRC_SPWN_VLD", cbValidateSimpleSourceSpawn },
163 { "R2_GOLIVE", cbR2GoLive },
164 { "R2_STOPLIVE", cbR2StopLive },
165 { "R2_STARTINSTANCE", cbR2StartInstance },
166 { "R2_NPC_BOT_SCRIPT_BY_ID", cbR2NpcBotScriptById },
167 { "R2_NPC_GROUP_SCRIPT_BY_NAME", cbR2NpcGroupScriptByName },
168 { "OUTPOST_CREATE_SQUAD", cbOutpostCreateSquad },
169 { "OUTPOST_SPAWN_SQUAD", cbOutpostSpawnSquad },
170 { "OUTPOST_DESPAWN_SQUAD", cbOutpostDespawnSquad },
171 { "OUTPOST_DELETE_SQUAD", cbOutpostDeleteSquad },
172 { "OUTPOST_DESPAWN_ALL_SQUADS", cbOutpostDespawnAllSquads },
173 { "OUTPOST_OWNER", cbOutpostSetOwner },
174 { "OUTPOST_ATTACKER", cbOutpostSetAttacker },
175 { "OUTPOST_STATE", cbOutpostSetState },
176 { "OUTPOST_EVENT", cbOutpostEvent },
177 { "OUTPOST_SET_BUILDING_BOT_SHEET", cbOutpostSetBuildingBotSheet },
178 { "EVENT_CREATE_NPC_GROUP", cbEventCreateNpcGroup },
179 { "EVENT_NPC_GROUP_SCRIPT", cbEventNpcGroupScript },
180 { "EVENT_FAUNA_BOT_SET_RADII", cbEventFaunaBotSetRadii },
181 { "EVENT_FAUNA_BOT_RESET_RADII", cbEventFaunaBotResetRadii },
182 { "EVENT_BOT_CAN_AGGRO", cbEventBotCanAggro },
183 { "EVENT_BOT_SHEET", cbEventBotSheet },
184 { "ASK_BOT_DESPAWN_NOTIFICATION", cbAskBotDespawnNotification },
185 { "SPAWN_EASTER_EGG", cbSpawnEasterEgg },
186 { "DESPAWN_EASTER_EGG", cbDespawnEasterEgg },
191 void CMessages::release()
195 void CMessages::notifyBotDespawn(NLNET::TServiceId serviceId, uint32 botAlias, const NLMISC::CEntityId& botId)
197 CMessage msgout("BOT_DESPAWN_NOTIFICATION");
198 msgout.serial(botAlias);
199 msgout.serial(const_cast<NLMISC::CEntityId&>(botId));
200 CUnifiedNetwork::getInstance()->send(serviceId, msgout);
204 void CMessages::notifyBotDeath(NLNET::TServiceId serviceId, uint32 botAlias, const NLMISC::CEntityId& botId)
206 CMessage msgout("BOT_DEATH_NOTIFICATION");
207 msgout.serial(botAlias);
208 msgout.serial(const_cast<NLMISC::CEntityId&>(botId));
209 CUnifiedNetwork::getInstance()->send(serviceId, msgout);
212 void CMessages::notifyBotStopNpcControl(NLNET::TServiceId serviceId, uint32 botAlias, const NLMISC::CEntityId& botId)
214 CMessage msgout("BOT_STOPCCONTROL_NOTIFICATION");
215 msgout.serial(botAlias);
216 msgout.serial(const_cast<NLMISC::CEntityId&>(botId));
217 CUnifiedNetwork::getInstance()->send(serviceId, msgout);
220 //--------------------------------------------------------------------------
221 // Messages from the DSS
222 //--------------------------------------------------------------------------
224 #include "nel/ligo/primitive.h"
225 #include "nel/ligo/primitive_utils.h"
227 #include "ai_share/ai_share.h"
228 #include "ai_share/ai_actions.h"
230 #include "game_share/task_list.h"
236 // Load Scenarip phase 1 (remove old entities)
237 class CTaskRingGoLive1 : public CTask<uint32>
239 public:
240 CTaskRingGoLive1(uint32 aiInstance, bool isBase)
241 :_AiInstance(aiInstance), _IsBase(isBase){}
243 virtual void doOperation()
245 nldebug("Tick %u CTaskRingGoLive1 (Despawn) %u %u", getTime(), _AiInstance, _IsBase);
246 std::string actFilename = toString("r2.%04d.act.primitive", _AiInstance);
247 std::string baseFilename= toString("r2.%04d.base.primitive", _AiInstance);
249 ICommand::execute(toString("createDynamicAIInstance %d", _AiInstance), *InfoLog);
250 ICommand::execute(toString("unloadPrimitiveFile \"%s\"", actFilename.c_str()), *InfoLog);
252 if (_IsBase)
254 ICommand::execute(toString("unloadPrimitiveFile \"%s\"", baseFilename.c_str()), *InfoLog);
258 private:
259 uint32 _AiInstance;
260 bool _IsBase;
266 // Load Scenarip phase 2 (insert new entities)
267 class CTaskRingGoLive2 : public CTask<uint32>
270 public:
271 CTaskRingGoLive2(TSessionId sessionId, uint32 aiInstance, bool isBase)
272 :_SessionId(sessionId), _AiInstance(aiInstance), _IsBase(isBase){}
274 virtual void doOperation()
277 nldebug("Tick %u, CTaskRingGoLive2 (Spawn) session %u instance %u %u", getTime(), _SessionId.asInt(), _AiInstance, _IsBase);
278 CAIActions::IExecutor* executer;
279 executer = CAIActions::getExecuter();
281 ICommand::execute(toString("createDynamicAIInstance %d", _AiInstance), *InfoLog);
283 AI_SHARE::CAIActionsDataRecordPtr dataRec;
284 dataRec.init(&Pdr);
286 dataRec.applyToExecutor(*executer);
288 std::string cmd = toString("spawnManagers r2.%04d.%s", _SessionId.asInt(), _IsBase?"base":"act");
289 ICommand::execute(cmd, *InfoLog);
292 std::string cmd = toString("spawnManagers r2.%04d.%s", _SessionId.asInt(), _IsBase?"base.zone_trigger":"act.zone_trigger");
293 ICommand::execute(cmd, *InfoLog);
297 public:
298 CPersistentDataRecord Pdr;
300 private:
301 uint32 _AiInstance;
302 TSessionId _SessionId;
303 bool _IsBase;
310 static void cbR2GoLive( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId )
313 TSessionId sessionId;
314 uint32 aiInstance;
315 bool isBase;
316 uint32 size;
318 msgin.serial(sessionId);
319 msgin.serial(aiInstance);
320 msgin.serial(isBase);
321 msgin.serial(size);
322 if (size != 0)
324 // case where we want to start an instance but (at start of an edition session) but animation not started
326 uint32 tick = CTimeInterface::gameCycle();
327 CTaskRingGoLive1* task1 = new CTaskRingGoLive1( aiInstance, isBase);
328 CTaskRingGoLive2* task2 = new CTaskRingGoLive2( sessionId, aiInstance, isBase);
329 task2->Pdr.clear();
332 uint8* buffer = new uint8[size];
333 msgin.serialBuffer(buffer, size);
334 task2->Pdr.fromBuffer((const char*)buffer, size);
335 delete [] buffer;
338 CAIS::instance().addTickedTask(tick + 1,task1);
339 CAIS::instance().addTickedTask(tick + 2, task2);
344 if( isBase )
346 // ack to unblock DSS session queue
347 CMessage msgout("SESSION_ACK");
348 msgout.fastWrite( aiInstance );
349 CUnifiedNetwork::getInstance()->send("DSS",msgout);
350 nlinfo( "R2An: ack sent to DSS for anim session %u", aiInstance );
353 return;
359 class CTaskR2StopLive : public CTask<uint32>
362 public:
363 CTaskR2StopLive(uint32 aiInstance, bool isBase)
364 :_AiInstance(aiInstance), _IsBase(isBase){}
366 virtual void doOperation()
368 ICommand::execute(toString("createDynamicAIInstance %d", _AiInstance), *InfoLog);
371 // load a primitiv.binprim from DSS
372 //ICommand::execute(toString("despawnManagers %s", isBase?"base":"act"), *InfoLog);
373 ICommand::execute(toString("unloadPrimitiveFile \"r2.%04d.act.primitive\"", _AiInstance), *InfoLog);
375 //isBase == false <=> stop act
376 // isBase == true <=> stop Live
377 if (_IsBase)
379 ICommand::execute(toString("unloadPrimitiveFile \"r2.%04d.base.primitive\"", _AiInstance), *InfoLog);
380 CAIS::instance().destroyAIInstance(_AiInstance, true);
386 private:
387 uint32 _AiInstance;
388 bool _IsBase;
391 static void cbR2StopLive( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId )
394 bool isBase;
395 uint32 aiInstance;
396 msgin.serial(aiInstance);
397 msgin.serial(isBase);
399 uint32 tick = CTimeInterface::gameCycle();
400 CTask<uint32>* task1 = new CTaskR2StopLive( aiInstance, isBase);
401 CAIS::instance().addTickedTask(tick ,task1);
408 class CTaskR2StartInstance: public CTask<uint32>
411 public:
412 CTaskR2StartInstance(uint32 aiInstance)
413 :_AiInstance(aiInstance){}
415 virtual void doOperation()
417 // destroy the instance before exist
418 CAIS::instance().destroyAIInstance(_AiInstance, false);
419 ICommand::execute(toString("createDynamicAIInstance %d", _AiInstance), *InfoLog);
423 private:
424 uint32 _AiInstance;
427 static void cbR2StartInstance( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId )
429 uint32 aiInstance;
430 msgin.serial(aiInstance);
432 uint32 tick = CTimeInterface::gameCycle();
433 CTask<uint32>* task1 = new CTaskR2StartInstance( aiInstance);
434 CAIS::instance().addTickedTask(tick ,task1);
439 //--------------------------------------------------------------------------
440 // Messages from the GPMS
441 //--------------------------------------------------------------------------
444 static void cbAddEntities( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId )
446 // This is where we should deal with player record creation
450 //--------------------------------------------------------------------------
451 // Messages from the EGS
452 //--------------------------------------------------------------------------
453 void cbValidateSourceSpawn( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId )
455 H_AUTO(ValidateSourceSpawn);
457 // Read/write header
458 CMessage msgout( "SRC_SPWN_VLD_R" );
459 uint32 nbSources;
460 //CVector prospectingPos;
461 //msgin.fastRead( prospectingPos );
463 // Get world position of prospector
464 const RYAI_MAP_CRUNCH::CWorldMap& worldMap = CWorldContainer::getWorldMap();
465 //RYAI_MAP_CRUNCH::CWorldPosition prospectorWorldPos;
466 //CAIVector prospectingAiPos( (double)prospectingPos.x, (double)prospectingPos.y );
467 //bool isProspectingPosValid = worldMap.setWorldPosition( (double)prospectingPos.z, prospectorWorldPos, prospectingAiPos );
469 msgin.fastRead( nbSources );
470 msgout.fastWrite( nbSources );
472 for ( uint i=0; i!=nbSources; ++i )
474 // Read request
475 CVector2f pos2f;
476 TDataSetRow sourceDataSetRow;
477 msgin.serial( pos2f );
478 msgin.serial( sourceDataSetRow );
479 msgout.serial( sourceDataSetRow );
481 // Check position
482 RYAI_MAP_CRUNCH::CWorldPosition wPos;
483 CAIVector aiPos( (double)pos2f.x, (double)pos2f.y );
484 std::vector<RYAI_MAP_CRUNCH::CWorldPosition> wPosList;
486 bool canSpawnHere = worldMap.setWorldPosition( AITYPES::vp_auto, wPos, aiPos );
488 //worldMap.getWorldPositions( wPosList, aiPos );
489 //for ( std::vector<RYAI_MAP_CRUNCH::CWorldPosition>::const_iterator it=wPosList.begin(); it!=wPosList.end(); ++it )
491 // Discard if the position is in water or in interiors
492 if ( canSpawnHere && (wPos.getFlags() & (RYAI_MAP_CRUNCH::Water | RYAI_MAP_CRUNCH::Interior)) )
493 canSpawnHere = false;
494 //continue;
496 msgout.fastWrite( canSpawnHere );
498 // TODO: Browse the possible surfaces for the position (x,y), then keep only the one(s)
499 // for which a pathfinding from the prospector to the source limited to 5 surfaces succeeds
503 // Send reply
504 sendMessageViaMirror( serviceId, msgout ); // via mirror because receiver will access mirror
505 //nldebug( "Processed %u forage source pos validations", nbSources );
509 void cbValidateSimpleSourceSpawn( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId )
511 H_AUTO(ValidateSourceSpawn);
513 // Read/write header
514 CMessage msgout( "SRC_SPWN_VLD_R" );
516 // Read request
517 uint32 nbSources = 1;
518 msgout.fastWrite( nbSources );
519 CVector2f pos2f;
520 TDataSetRow sourceDataSetRow;
521 msgin.serial( pos2f );
522 msgin.serial( sourceDataSetRow );
523 msgout.serial( sourceDataSetRow );
525 // Check position
526 const RYAI_MAP_CRUNCH::CWorldMap& worldMap = CWorldContainer::getWorldMap();
527 RYAI_MAP_CRUNCH::CWorldPosition wPos;
528 CAIVector aiPos( (double)pos2f.x, (double)pos2f.y );
529 bool canSpawnHere = worldMap.setWorldPosition( AITYPES::vp_auto, wPos, aiPos );
531 // Discard if the position is in water or in interiors
532 if ( canSpawnHere && (wPos.getFlags() & (RYAI_MAP_CRUNCH::Water | RYAI_MAP_CRUNCH::Interior)) )
533 canSpawnHere = false;
535 msgout.fastWrite( canSpawnHere );
537 // Send reply
538 sendMessageViaMirror( serviceId, msgout ); // via mirror because receiver will access mirror
539 //nldebug( "Processed a simple forage source pos validation" );
544 //--------------------------------------------------------------------------
545 // CTransportClass callbacks
546 //--------------------------------------------------------------------------
548 void CMsgAIOpenMgrs::callback (const std::string &serviceName, uint8 sid)
550 if (Name.size()!=Type.size() || Name.size()!=MgrId.size())
552 nlwarning("Size missmatch in vectors in CMsgAIOpenMgrs message - message ignored");
553 return;
556 // iterate through the entries in the message opening new managers
557 for (uint i=0;i<Name.size();++i)
559 // look for a type that matches the type name given
560 EMgrType type=mgrType(Type[i].c_str());
562 if (type!=MgrTypeBadType)
564 // open the manger as requested
565 CAIS::newMgr(type,MgrId[i],Name[i],std::string());
567 else
569 // failed to identify type so give up
570 nlwarning("Failed to translate '%s' into a known type - request to open manager %04d (%s) ignored",
571 Type[i].c_str(),MgrId[i],Name[i].c_str());
572 std::string msgStr("Failed to open "+Name[i]+" due to bad type: '"+Type[i]+"'");
573 CMsgAIFeedback(msgStr).send("AIDS");
579 class CAITauntImp : public CAITauntMsg
581 public:
582 void callback (const std::string &name, NLNET::TServiceId id);
583 protected:
584 private:
587 class CAIPlayerRespawnMsgImp : public CAIPlayerRespawnMsg
589 public:
590 virtual void callback (const std::string &name, NLNET::TServiceId id);
593 class CAIAskForInfosOnEntityImp
594 :public CAIAskForInfosOnEntityMsg
596 public:
597 void callback (const std::string &name, NLNET::TServiceId id);
601 class CEnableAggroOnPlayerImp
602 :public CEnableAggroOnPlayerMsg
604 public:
605 void callback (const std::string &name, NLNET::TServiceId id);
608 class CSetBotHeadingImp : public CSetBotHeadingMsg
610 public:
611 void callback(const std::string &name, NLNET::TServiceId id);
614 class CChangeActionFlagMsgImp
615 :public CChangeActionFlagMsg
617 public:
618 void callback (const std::string &name, NLNET::TServiceId id);
621 class CChangeCreatureModeMsgImp
622 :public CChangeCreatureModeMsg
624 public:
625 void callback (const std::string &name, NLNET::TServiceId id);
628 //-------------------------------------------------------------------------
629 // singleton initialisation and release
630 //--------------------------------------------------------------------------
632 void CMessages::init()
634 // incoming from AIDS
635 TRANSPORT_CLASS_REGISTER( CMsgAICloseMgrs );
636 TRANSPORT_CLASS_REGISTER( CMsgAIBackupMgrs );
637 TRANSPORT_CLASS_REGISTER( CMsgAIUploadActions );
638 TRANSPORT_CLASS_REGISTER( CMsgAISpawnMgrs );
639 TRANSPORT_CLASS_REGISTER( CMsgAIDespawnMgrs );
641 // outgoing to AIDS
642 TRANSPORT_CLASS_REGISTER( CMsgAIServiceUp );
643 TRANSPORT_CLASS_REGISTER( CMsgAIManagerUp );
644 TRANSPORT_CLASS_REGISTER( CMsgAIFeedback );
646 // Classes used for comms with EGS (outgoing)
647 // TRANSPORT_CLASS_REGISTER( CNpcBotDescription );
648 TRANSPORT_CLASS_REGISTER( CCharacterBotChatBeginEndReceiver );
649 TRANSPORT_CLASS_REGISTER( CCharacterDynChatBeginEndReceiver );
650 TRANSPORT_CLASS_REGISTER( CFaunaBotDescription );
651 TRANSPORT_CLASS_REGISTER( CUserEventMsgImp );
652 TRANSPORT_CLASS_REGISTER( CSetEscortTeamIdImp );
653 TRANSPORT_CLASS_REGISTER( CCreatureDespawnImp );
654 TRANSPORT_CLASS_REGISTER( CDelHandledAIGroupImp );
655 TRANSPORT_CLASS_REGISTER( CAddHandledAIGroupImp );
656 TRANSPORT_CLASS_REGISTER( CHandledAIGroupSpawnedMsg );
657 TRANSPORT_CLASS_REGISTER( CHandledAIGroupDespawnedMsg );
658 TRANSPORT_CLASS_REGISTER( CGiveItemRequestMsg );
659 TRANSPORT_CLASS_REGISTER( CReceiveItemRequestMsg );
661 // Classes used for comms between AI and EGS
662 TRANSPORT_CLASS_REGISTER (CPetSpawnMsgImp);
663 TRANSPORT_CLASS_REGISTER (CPetSpawnConfirmationMsg);
665 TRANSPORT_CLASS_REGISTER (CPetCommandMsgImp);
666 TRANSPORT_CLASS_REGISTER (CPetCommandConfirmationMsg);
668 TRANSPORT_CLASS_REGISTER (CBSAIDeathReport);
669 TRANSPORT_CLASS_REGISTER (CCAisActionMsg);
671 TRANSPORT_CLASS_REGISTER (CEGSExecutePhraseMsg);
672 TRANSPORT_CLASS_REGISTER (CEGSExecuteAiActionMsg);
674 TRANSPORT_CLASS_REGISTER (CAddEffectsMessage);
675 TRANSPORT_CLASS_REGISTER (CRemoveEffectsMessage);
677 // TRANSPORT_CLASS_REGISTER (COutpostList);
678 // TRANSPORT_CLASS_REGISTER (COutpostDescription);
679 TRANSPORT_CLASS_REGISTER (CDutyDescription);
680 // TRANSPORT_CLASS_REGISTER (COutpostStateImp);
681 // TRANSPORT_CLASS_REGISTER (COutpostWarEnd);
683 TRANSPORT_CLASS_REGISTER (CAITauntImp);
685 TRANSPORT_CLASS_REGISTER (CAILostAggroMsg);
686 TRANSPORT_CLASS_REGISTER (CAIGainAggroMsg);
688 TRANSPORT_CLASS_REGISTER (CAINotifyDeathMsg);
690 TRANSPORT_CLASS_REGISTER (CAIPlayerRespawnMsgImp);
692 TRANSPORT_CLASS_REGISTER (CAIAskForInfosOnEntityImp);
693 TRANSPORT_CLASS_REGISTER (CAIInfosOnEntityMsg);
694 TRANSPORT_CLASS_REGISTER (CEnableAggroOnPlayerImp);
695 TRANSPORT_CLASS_REGISTER (CChangeActionFlagMsgImp);
697 TRANSPORT_CLASS_REGISTER (CPetSetOwnerImp);
699 TRANSPORT_CLASS_REGISTER (CSetBotHeadingImp);
701 // messages related to instance management
702 TRANSPORT_CLASS_REGISTER (CReportAICollisionAvailableMsg);
703 TRANSPORT_CLASS_REGISTER (CReportStaticAIInstanceMsg);
704 TRANSPORT_CLASS_REGISTER (CReportAIInstanceDespawnMsg);
705 TRANSPORT_CLASS_REGISTER (CWarnBadInstanceMsgImp);
706 TRANSPORT_CLASS_REGISTER (CCreatureSetUrlMsg);
707 TRANSPORT_CLASS_REGISTER (CChangeCreatureMaxHPMsg)
708 TRANSPORT_CLASS_REGISTER (CChangeCreatureHPMsg);
709 TRANSPORT_CLASS_REGISTER (CChangeCreatureModeMsgImp);
710 TRANSPORT_CLASS_REGISTER (CQueryEgs);
712 // setup the callback array
713 CUnifiedNetwork::getInstance()->addCallbackArray( CbArray, sizeof(CbArray)/sizeof(CbArray[0]) );
715 // hook up callback to service up of data service
716 // CUnifiedNetwork::getInstance()->setServiceUpCallback( std::string("AIDS"), cbAIDSServiceUp, 0);
721 //////////////////////////////////////////////////////////////////////////
722 // CallBack part
723 //////////////////////////////////////////////////////////////////////////
725 void CEnableAggroOnPlayerImp::callback (const std::string &name, NLNET::TServiceId id)
727 CAIEntityPhysical *phys=CAIS::instance().getEntityPhysical(EntityRowId);
728 if (!phys)
730 // When go from test to edition the ai instance is destroyed
731 if (!IsRingShard)
733 nlwarning("CEnableAggroOnPlayerImp::callback: unknow entity %s on this AIS !", EntityRowId.toString().c_str());
736 return;
739 switch(phys->getRyzomType())
741 case RYZOMID::player:
743 CBotPlayer *const bot=safe_cast<CBotPlayer*>(phys);
744 bot->setAggroable(EnableAggro);
745 if (!EnableAggro)
746 bot->forgotAggroForAggroer();
748 break;
749 default:
750 nlwarning("CEnableAggroOnPlayerImp::callback: non player entity ! %s(%u) on this AIS !", phys->getEntityId().toString().c_str(), EntityRowId.toString().c_str());
751 break;
757 void CAIAskForInfosOnEntityImp::callback (const std::string &name, NLNET::TServiceId id)
759 CAIInfosOnEntityMsg msg;
760 msg.AskerRowID=AskerRowID;
761 msg.EntityRowId=EntityRowId;
763 CArrayStringWriter stringWriter(msg.Infos);
765 CAIEntityPhysical *phys=CAIS::instance().getEntityPhysical(EntityRowId);
766 if (phys)
768 switch(phys->getRyzomType())
770 case RYZOMID::creature:
771 case RYZOMID::npc:
772 case RYZOMID::pack_animal:
774 const CBot *const bot=safe_cast<const CBot*>(&phys->getPersistent());
775 std::vector<std::string> strings = bot->getMultiLineInfoString();
776 msg.Infos.insert(msg.Infos.end(), strings.begin(), strings.end());
778 break;
779 default:
780 std::vector<std::string> strings = phys->getMultiLineInfoString();
781 msg.Infos.insert(msg.Infos.end(), strings.begin(), strings.end());
782 break;
785 else
787 nlwarning("CAIAskForInfosOnEntityImp::callback: entity %s is unknow on this AIS.", EntityRowId.toString().c_str());
788 stringWriter.append(toString("%s : unknow entity index %s", IService::getInstance()->getServiceShortName().c_str(), EntityRowId.toString().c_str()));
790 msg.send("EGS");
793 void CChangeActionFlagMsgImp::callback (const std::string &name, NLNET::TServiceId id)
795 const uint32 size = (uint32)Entities.size();
796 nlassert( size == ActionFlags.size() && size == Values.size());
798 for (uint32 i = 0 ; i < size ; ++i)
800 CAIEntityPhysical *const phys=CAIS::instance().getEntityPhysical(Entities[i]);
801 if (!phys)
802 continue;
804 if (Values[i])
805 phys->setActionFlags((RYZOMACTIONFLAGS::TActionFlag)ActionFlags[i]);
806 else
807 phys->removeActionFlags((RYZOMACTIONFLAGS::TActionFlag)ActionFlags[i]);
811 void CChangeCreatureModeMsgImp::callback (const std::string &name, NLNET::TServiceId id)
813 CAIEntityPhysical *phys=CAIS::instance().getEntityPhysical(CreatureId);
814 if (!phys)
815 return;
817 static_cast<CModEntityPhysical*>(phys)->setMode( MBEHAV::EMode(NewMode) );
821 ////----------------------------------------------------------------
822 //// EGS -> AIS ask infos on entity
823 ////----------------------------------------------------------------
824 //class CAIAskForInfosOnEntityMsg : public NLNET::CTransportClass
826 //public:
827 // TDataSetRow EntityRowId;
829 // virtual void description ()
830 // {
831 // className ("CAIAskForInfosOnEntityMsg");
832 // property ("EntityRowId", PropDataSetRow, TDataSetRow(), EntityRowId);
833 // }
834 // virtual void callback (const std::string &name, uint8 id) {}
835 //};
837 ////----------------------------------------------------------------
838 //// AIS -> EGS returns infos on entity as a vector of strings
839 ////----------------------------------------------------------------
840 //class CAIInfosOnEntityMsg : public NLNET::CTransportClass
842 //public:
843 // TDataSetRow EntityRowId;
844 // std::vector<std::string> Infos;
846 // virtual void description ()
847 // {
848 // className ("CAIInfosOnEntityMsg");
849 // property ("EntityRowId", PropDataSetRow, TDataSetRow(), EntityRowId);
850 // propertyCont ("Infos", PropString, Infos);
851 // }
852 // virtual void callback (const std::string &name, uint8 id) {}
853 //};
856 void CMsgAIUploadActions::callback(const std::string &serviceName, NLNET::TServiceId sid)
858 for(uint i=0;i<Data.size();)
860 uint argCount;
861 char action[9];
862 std::vector<CAIActions::CArg> args;
864 if (Data.size()-i<sizeof(char)+sizeof(uint64))
866 nlwarning("Unexpected end of input data in CMsgAIUploadActions message");
867 CAIDSInterface::warning("Unexpected end of input data in CMsgAIUploadActions()");
868 return;
870 argCount=Data[i]; i++;
871 uint k;
872 for (k=0;k<8;++i,++k)
873 action[k]=Data[i];
874 action[k]=0;
875 for (uint j=0;j<argCount;++j)
877 args.push_back(CAIActions::CArg::serialFromString(Data,i));
878 if (i<=Data.size())
879 continue;
881 nlwarning("Unexpected end of input data in CMsgAIUploadActions message");
882 CAIDSInterface::warning("Unexpected end of input data in CMsgAIUploadActions()");
883 return;
885 CAIActions::execute(action,args);
889 void CMsgAISpawnMgrs::callback(const std::string &serviceName, NLNET::TServiceId sid)
891 nlwarning("*** CMsgAISpawnMgrs message received from AIDS but not treated ***");
892 CMsgAIFeedback("*** CMsgAISpawnMgrs message received from AIDS but not treated ***").send("AIDS");
895 void CMsgAIDespawnMgrs::callback(const std::string &serviceName, NLNET::TServiceId sid)
897 nlwarning("*** CMsgAIDespawnMgrs message received from AIDS but not treated ***");
898 CMsgAIFeedback("*** CMsgAIDespawnMgrs message received from AIDS but not treated ***").send("AIDS");
901 void CMsgAICloseMgrs::callback (const std::string &serviceName, NLNET::TServiceId sid)
903 nlassert(false); // AIDataService.
904 // for (uint i=0;i<MgrId.size();++i)
905 // CAIS::instance().AIList()[0]->deleteMgr(MgrId[i]);
908 void CMsgAIBackupMgrs::callback (const std::string &serviceName, NLNET::TServiceId sid)
910 nlassert(false); // AIDataService.
912 nlwarning("*** Backup message received from AIDS but not treated ***");
913 CMsgAIFeedback("*** Backup message received from AIDS but not treated ***").send("AIDS");
917 //--------------------------------------------------------------------------
918 // CTransportClass stub callbacks for outgoing messages
919 //--------------------------------------------------------------------------
921 void CMsgAIServiceUp::callback (const std::string &serviceName, NLNET::TServiceId sid)
925 void CMsgAIManagerUp::callback (const std::string &serviceName, NLNET::TServiceId sid)
929 void CMsgAIFeedback::callback (const std::string &serviceName, NLNET::TServiceId sid)
934 void CBSAIDeathReport::callback(const std::string &name, NLNET::TServiceId id)
936 for (uint i=0; i<Bots.size(); ++i)
938 CAIEntityPhysical* phys=CAIS::instance().getEntityPhysical(Bots[i]);
939 if (!phys)
941 if (Zombies[i])
943 nldebug("CBSAIDeathReport::callback: ZombyUnKnown entity %s not handled here", Bots[i].toString().c_str());
945 // removed because of multi AIS
946 //nldebug("CBSAIDeathReport::callback: entity %s not handled here", Bots[i].toString().c_str());
947 continue;
950 #if !FINAL_VERSION
951 nlassert(phys->getRyzomType()!=RYZOMID::player);
952 #else
953 if (phys->getRyzomType()==RYZOMID::player)
955 if (Zombies[i])
957 nldebug("CBSAIDeathReport::callback: ZombyPlayer entity %s !!", Bots[i].toString().c_str());
959 continue;
961 #endif
962 static_cast<CModEntityPhysical*>(phys)->setMode(MBEHAV::DEATH);
963 if (Zombies[i])
965 if (dynamic_cast<CModEntityPhysical*>(phys)==NULL)
967 nldebug("CBSAIDeathReport::callback: ZombyCastError entity %s !!", Bots[i].toString().c_str());
969 else
971 nldebug("CBSAIDeathReport::callback: ZombyDEATHSet entity %s !!", Bots[i].toString().c_str());
976 switch(phys->getRyzomType())
978 case RYZOMID::npc:
980 const CSpawnBotNpc *const sb = static_cast<CSpawnBotNpc*>(phys);
981 CSpawnGroupNpc &spawnGrp = sb->spawnGrp();
982 const CMgrNpc &mgr = spawnGrp.getPersistent().mgr();
984 spawnGrp.addBotToDespawnAndRespawnTime (&(sb->getPersistent()), spawnGrp.getPersistent().despawnTime(), spawnGrp.getPersistent().respawnTime());
986 if (spawnGrp.getPersistent().getSquadLeader(false)==&sb->getPersistent())
987 spawnGrp.getPersistent().processStateEvent(mgr.EventSquadLeaderKilled);
990 CBotNpc* bot = NLMISC::safe_cast<CBotNpc*>(&(sb->getPersistent()));
991 spawnGrp.botHaveDied (bot);
992 bot->notifyBotDeath();
994 std::string eventBotKilled;
995 if (spawnGrp.getProfileParameter("event_bot_killed", eventBotKilled) && !eventBotKilled.empty())
997 nlinfo("NPC: TRIGGER EVENT BOT KILLED");
1000 spawnGrp.getPersistent().processStateEvent(mgr.EventBotKilled);
1002 std::string eventGroupKilled;
1003 if (!spawnGrp.isGroupAlive(0*1))
1005 if (spawnGrp.getProfileParameter("event_group_killed", eventGroupKilled) && !eventGroupKilled.empty())
1007 nlinfo("NPC: TRIGGER EVENT GROUP KILLED");
1009 spawnGrp.getPersistent().processStateEvent(mgr.EventGrpEliminated);
1012 if (!eventBotKilled.empty() || !eventGroupKilled.empty())
1014 CSpawnBot *const spBot = static_cast<CSpawnBot*>(phys);
1015 // make a vector of aggroable player
1016 CBotAggroOwner::TBotAggroList const& aggroList = spBot->getBotAggroList();
1017 //typedef std::map<TDataSetRow, TAggroEntryPtr> TBotAggroList;
1018 CBotAggroOwner::TBotAggroList::const_iterator aggroIt(aggroList.begin()), aggroEnd(aggroList.end());
1019 TDataSetRow foundRow = TDataSetRow();
1021 std::vector<TDataSetRow> playerAggroable;
1022 for (; aggroIt != aggroEnd; ++aggroIt)
1024 if (CMirrors::getEntityId(aggroIt->first).getType() != RYZOMID::player)
1025 continue;
1026 CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(aggroIt->first);
1027 if (!ep)
1028 continue;
1029 CBotPlayer const* const player = NLMISC::safe_cast<CBotPlayer const*>(ep);
1030 if (!player)
1031 continue;
1032 if (!player->isAggroable())
1033 continue;
1034 playerAggroable.push_back(aggroIt->first);
1037 NLNET::CMessage msgout("TRIGGER_WEBIG");
1038 if (!eventBotKilled.empty())
1039 msgout.serial(eventBotKilled);
1040 else
1041 msgout.serial(eventGroupKilled);
1043 uint32 nbPlayers = (uint32)playerAggroable.size();
1044 msgout.serial(nbPlayers);
1045 for (uint32 i = 0; i < nbPlayers; i++)
1047 msgout.serial(playerAggroable[i]);
1049 sendMessageViaMirror("EGS", msgout);
1052 break;
1053 case RYZOMID::creature:
1055 CSpawnBotFauna *const sb = static_cast<CSpawnBotFauna*>(phys);
1056 CSpawnGroupFauna &spawnGrp = sb->spawnGrp();
1057 CMgrFauna &mgr = spawnGrp.getPersistent().mgr();
1059 sb->setAIProfile(new CCorpseFaunaProfile(sb));
1061 const sint32 DespawnTime=spawnGrp.getPersistent().timer(CGrpFauna::CORPSE_TIME);
1062 const sint32 RespawnTime=spawnGrp.getPersistent().timer(CGrpFauna::RESPAWN_TIME);
1063 // set the _Bot to be despawn and gives the control to its group.
1064 // despawn the corpse after DespawnTime, and hence respawn after DespawnTime+RespawnTime since now.
1065 spawnGrp.addBotToDespawnAndRespawnTime(&sb->getPersistent(),(uint32) DespawnTime, (uint32) DespawnTime + (uint32) RespawnTime);
1068 spawnGrp.getPersistent().processStateEvent(mgr.EventBotKilled);
1069 if (spawnGrp.isGroupAlive())
1070 break;
1072 spawnGrp.getPersistent().processStateEvent(mgr.EventGrpEliminated);
1074 break;
1075 default:
1076 break;
1084 void CEGSExecutePhraseMsg::callback(const std::string &name, NLNET::TServiceId id)
1089 void CAITauntImp::callback (const std::string &name, NLNET::TServiceId id)
1091 CAIEntityPhysical *entity=CAIS::instance().getEntityPhysical(TargetRowId);
1093 if (!entity)
1094 return;
1096 CBotAggroOwner *aggroOwner=NULL;
1098 switch (entity->getRyzomType())
1100 case RYZOMID::creature:
1101 case RYZOMID::npc:
1102 aggroOwner=NLMISC::safe_cast<CSpawnBot*>(entity);
1103 break;
1104 default:
1105 break;
1108 if (!aggroOwner)
1109 return;
1111 aggroOwner->maximizeAggroFor(PlayerRowId);
1114 void CAIPlayerRespawnMsgImp::callback (const std::string &name, NLNET::TServiceId id)
1116 CAIEntityPhysical *entity=CAIS::instance().getEntityPhysical(PlayerRowId);
1117 if (!entity)
1118 return;
1120 CBotPlayer *player=NLMISC::safe_cast<CBotPlayer*>(entity);
1121 if (!player)
1122 return;
1124 player->forgotAggroForAggroer();
1129 void sAggroLost(TDataSetRow playerBot, TDataSetRow targetBot)
1131 CAIEntityPhysical *entity=CAIS::instance().getEntityPhysical(playerBot); // necessary ?
1132 if ( !entity
1133 || CMirrors::getEntityId(playerBot).getType()!=RYZOMID::player)
1134 return;
1136 CAILostAggroMsg msg(targetBot, playerBot);
1137 msg.send("EGS");
1139 CBotPlayer *player=NLMISC::safe_cast<CBotPlayer*>(entity);
1140 if (!player)
1141 return;
1142 player->removeAggroer(targetBot);
1146 void sAggroGain(TDataSetRow playerBot, TDataSetRow targetBot)
1148 CAIEntityPhysical *entity=CAIS::instance().getEntityPhysical(playerBot);
1149 if ( !entity
1150 || CMirrors::getEntityId(playerBot).getType()!=RYZOMID::player)
1151 return;
1153 CAIGainAggroMsg msg(targetBot, playerBot, false);
1154 msg.send("EGS");
1156 if (entity && entity->getRyzomType()==RYZOMID::player && (entity->getActionFlags() & RYZOMACTIONFLAGS::InWater))
1157 return;
1159 CAIEntityPhysical *botEntity = CAIEntityPhysicalLocator::getInstance()->getEntity(targetBot);
1160 CSpawnBotNpc* bot = dynamic_cast<CSpawnBotNpc*>(botEntity);
1161 if (bot && bot->getPersistent().getOwner()) {
1162 std::string groupName = bot->getPersistent().getOwner()->getName();
1163 if (groupName.substr(0, 6) == "group_") {
1164 if (groupName.find("_guardian_") != std::string::npos) {
1165 strFindReplace(groupName, "_guardian_", "_boss_");
1166 std::vector<CBot*> bots;
1167 /// try to find the bot name
1168 buildFilteredBotList(bots, groupName);
1169 if (!bots.empty())
1171 FOREACH(itBot, std::vector<CBot*>, bots)
1173 CBot* bot = *itBot;
1174 CSpawnBot *const sp = bot->getSpawnObj();
1175 if (sp && sp->isAlive())
1177 CAIGainAggroMsg msg(sp->dataSetRow(), playerBot, true);
1178 msg.send("EGS");
1187 CBotPlayer *player=NLMISC::safe_cast<CBotPlayer*>(entity);
1188 if (!player)
1189 return;
1190 player->addAggroer(targetBot);
1194 void CSetBotHeadingImp::callback(const std::string &serviceName, NLNET::TServiceId serviceId)
1196 CAIEntityPhysical *ep =CAIS::instance().getEntityPhysical(BotRowId);
1198 if (ep == NULL)
1200 nlwarning("CSetBotHeadingImp : invalid bot id : %s (%u)", TheDataset.getEntityId(BotRowId).toString().c_str(), BotRowId.getIndex());
1201 return;
1204 // ok, we have an entity physical, try to make it a npc
1205 CSpawnBotNpc *sb = dynamic_cast<CSpawnBotNpc*>(ep);
1207 if (sb == NULL)
1209 nlwarning("CSetBotHeadingImp : bot id %s (%u) is not an NPC !", TheDataset.getEntityId(BotRowId).toString().c_str(), BotRowId.getIndex());
1210 return;
1213 // set the theta
1214 sb->setTheta(CAngle(double(Heading)));
1218 void CWarnBadInstanceMsgImp::callback(const std::string &serviceName, NLNET::TServiceId serviceId)
1220 CAIS::instance().warnBadInstanceMsgImp(serviceName, serviceId, *this);
1223 #include "event_reaction_include.h"