1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2019 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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/>.
25 #include "npc_description_msg.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"
44 #include "game_share/tick_event_handler.h"
46 #include "server_share/msg_brick_service.h"
47 #include "server_share/msg_ai_service.h"
48 #include "server_share/effect_message.h"
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");
77 // make sure bot chat end vector size is even
78 if (BotChatEnd
.size()&1)
80 nlwarning("CCharacterBotChatBeginEndReceiver::callback(): Invalid BotChatEnd vector length");
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
>
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
);
254 ICommand::execute(toString("unloadPrimitiveFile \"%s\"", baseFilename
.c_str()), *InfoLog
);
266 // Load Scenarip phase 2 (insert new entities)
267 class CTaskRingGoLive2
: public CTask
<uint32
>
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
;
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
);
298 CPersistentDataRecord Pdr
;
302 TSessionId _SessionId
;
310 static void cbR2GoLive( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
313 TSessionId sessionId
;
318 msgin
.serial(sessionId
);
319 msgin
.serial(aiInstance
);
320 msgin
.serial(isBase
);
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
);
332 uint8
* buffer
= new uint8
[size
];
333 msgin
.serialBuffer(buffer
, size
);
334 task2
->Pdr
.fromBuffer((const char*)buffer
, size
);
338 CAIS::instance().addTickedTask(tick
+ 1,task1
);
339 CAIS::instance().addTickedTask(tick
+ 2, task2
);
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
);
359 class CTaskR2StopLive
: public CTask
<uint32
>
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
379 ICommand::execute(toString("unloadPrimitiveFile \"r2.%04d.base.primitive\"", _AiInstance
), *InfoLog
);
380 CAIS::instance().destroyAIInstance(_AiInstance
, true);
391 static void cbR2StopLive( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
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
>
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
);
427 static void cbR2StartInstance( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
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
);
458 CMessage
msgout( "SRC_SPWN_VLD_R" );
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
)
476 TDataSetRow sourceDataSetRow
;
477 msgin
.serial( pos2f
);
478 msgin
.serial( sourceDataSetRow
);
479 msgout
.serial( sourceDataSetRow
);
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;
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
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
);
514 CMessage
msgout( "SRC_SPWN_VLD_R" );
517 uint32 nbSources
= 1;
518 msgout
.fastWrite( nbSources
);
520 TDataSetRow sourceDataSetRow
;
521 msgin
.serial( pos2f
);
522 msgin
.serial( sourceDataSetRow
);
523 msgout
.serial( sourceDataSetRow
);
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
);
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");
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());
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
582 void callback (const std::string
&name
, NLNET::TServiceId id
);
587 class CAIPlayerRespawnMsgImp
: public CAIPlayerRespawnMsg
590 virtual void callback (const std::string
&name
, NLNET::TServiceId id
);
593 class CAIAskForInfosOnEntityImp
594 :public CAIAskForInfosOnEntityMsg
597 void callback (const std::string
&name
, NLNET::TServiceId id
);
601 class CEnableAggroOnPlayerImp
602 :public CEnableAggroOnPlayerMsg
605 void callback (const std::string
&name
, NLNET::TServiceId id
);
608 class CSetBotHeadingImp
: public CSetBotHeadingMsg
611 void callback(const std::string
&name
, NLNET::TServiceId id
);
614 class CChangeActionFlagMsgImp
615 :public CChangeActionFlagMsg
618 void callback (const std::string
&name
, NLNET::TServiceId id
);
621 class CChangeCreatureModeMsgImp
622 :public CChangeCreatureModeMsg
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
);
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 //////////////////////////////////////////////////////////////////////////
723 //////////////////////////////////////////////////////////////////////////
725 void CEnableAggroOnPlayerImp::callback (const std::string
&name
, NLNET::TServiceId id
)
727 CAIEntityPhysical
*phys
=CAIS::instance().getEntityPhysical(EntityRowId
);
730 // When go from test to edition the ai instance is destroyed
733 nlwarning("CEnableAggroOnPlayerImp::callback: unknow entity %s on this AIS !", EntityRowId
.toString().c_str());
739 switch(phys
->getRyzomType())
741 case RYZOMID::player
:
743 CBotPlayer
*const bot
=safe_cast
<CBotPlayer
*>(phys
);
744 bot
->setAggroable(EnableAggro
);
746 bot
->forgotAggroForAggroer();
750 nlwarning("CEnableAggroOnPlayerImp::callback: non player entity ! %s(%u) on this AIS !", phys
->getEntityId().toString().c_str(), EntityRowId
.toString().c_str());
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
);
768 switch(phys
->getRyzomType())
770 case RYZOMID::creature
:
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());
780 std::vector
<std::string
> strings
= phys
->getMultiLineInfoString();
781 msg
.Infos
.insert(msg
.Infos
.end(), strings
.begin(), strings
.end());
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()));
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
]);
805 phys
->setActionFlags((RYZOMACTIONFLAGS::TActionFlag
)ActionFlags
[i
]);
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
);
817 static_cast<CModEntityPhysical
*>(phys
)->setMode( MBEHAV::EMode(NewMode
) );
821 ////----------------------------------------------------------------
822 //// EGS -> AIS ask infos on entity
823 ////----------------------------------------------------------------
824 //class CAIAskForInfosOnEntityMsg : public NLNET::CTransportClass
827 // TDataSetRow EntityRowId;
829 // virtual void description ()
831 // className ("CAIAskForInfosOnEntityMsg");
832 // property ("EntityRowId", PropDataSetRow, TDataSetRow(), EntityRowId);
834 // virtual void callback (const std::string &name, uint8 id) {}
837 ////----------------------------------------------------------------
838 //// AIS -> EGS returns infos on entity as a vector of strings
839 ////----------------------------------------------------------------
840 //class CAIInfosOnEntityMsg : public NLNET::CTransportClass
843 // TDataSetRow EntityRowId;
844 // std::vector<std::string> Infos;
846 // virtual void description ()
848 // className ("CAIInfosOnEntityMsg");
849 // property ("EntityRowId", PropDataSetRow, TDataSetRow(), EntityRowId);
850 // propertyCont ("Infos", PropString, Infos);
852 // virtual void callback (const std::string &name, uint8 id) {}
856 void CMsgAIUploadActions::callback(const std::string
&serviceName
, NLNET::TServiceId sid
)
858 for(uint i
=0;i
<Data
.size();)
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()");
870 argCount
=Data
[i
]; i
++;
872 for (k
=0;k
<8;++i
,++k
)
875 for (uint j
=0;j
<argCount
;++j
)
877 args
.push_back(CAIActions::CArg::serialFromString(Data
,i
));
881 nlwarning("Unexpected end of input data in CMsgAIUploadActions message");
882 CAIDSInterface::warning("Unexpected end of input data in CMsgAIUploadActions()");
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
]);
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());
951 nlassert(phys
->getRyzomType()!=RYZOMID::player
);
953 if (phys
->getRyzomType()==RYZOMID::player
)
957 nldebug("CBSAIDeathReport::callback: ZombyPlayer entity %s !!", Bots
[i
].toString().c_str());
962 static_cast<CModEntityPhysical
*>(phys
)->setMode(MBEHAV::DEATH
);
965 if (dynamic_cast<CModEntityPhysical
*>(phys
)==NULL
)
967 nldebug("CBSAIDeathReport::callback: ZombyCastError entity %s !!", Bots
[i
].toString().c_str());
971 nldebug("CBSAIDeathReport::callback: ZombyDEATHSet entity %s !!", Bots
[i
].toString().c_str());
976 switch(phys
->getRyzomType())
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
)
1026 CAIEntityPhysical
* ep
= CAIS::instance().getEntityPhysical(aggroIt
->first
);
1029 CBotPlayer
const* const player
= NLMISC::safe_cast
<CBotPlayer
const*>(ep
);
1032 if (!player
->isAggroable())
1034 playerAggroable
.push_back(aggroIt
->first
);
1037 NLNET::CMessage
msgout("TRIGGER_WEBIG");
1038 if (!eventBotKilled
.empty())
1039 msgout
.serial(eventBotKilled
);
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
);
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())
1072 spawnGrp
.getPersistent().processStateEvent(mgr
.EventGrpEliminated
);
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
);
1096 CBotAggroOwner
*aggroOwner
=NULL
;
1098 switch (entity
->getRyzomType())
1100 case RYZOMID::creature
:
1102 aggroOwner
=NLMISC::safe_cast
<CSpawnBot
*>(entity
);
1111 aggroOwner
->maximizeAggroFor(PlayerRowId
);
1114 void CAIPlayerRespawnMsgImp::callback (const std::string
&name
, NLNET::TServiceId id
)
1116 CAIEntityPhysical
*entity
=CAIS::instance().getEntityPhysical(PlayerRowId
);
1120 CBotPlayer
*player
=NLMISC::safe_cast
<CBotPlayer
*>(entity
);
1124 player
->forgotAggroForAggroer();
1129 void sAggroLost(TDataSetRow playerBot
, TDataSetRow targetBot
)
1131 CAIEntityPhysical
*entity
=CAIS::instance().getEntityPhysical(playerBot
); // necessary ?
1133 || CMirrors::getEntityId(playerBot
).getType()!=RYZOMID::player
)
1136 CAILostAggroMsg
msg(targetBot
, playerBot
);
1139 CBotPlayer
*player
=NLMISC::safe_cast
<CBotPlayer
*>(entity
);
1142 player
->removeAggroer(targetBot
);
1146 void sAggroGain(TDataSetRow playerBot
, TDataSetRow targetBot
)
1148 CAIEntityPhysical
*entity
=CAIS::instance().getEntityPhysical(playerBot
);
1150 || CMirrors::getEntityId(playerBot
).getType()!=RYZOMID::player
)
1153 CAIGainAggroMsg
msg(targetBot
, playerBot
, false);
1156 if (entity
&& entity
->getRyzomType()==RYZOMID::player
&& (entity
->getActionFlags() & RYZOMACTIONFLAGS::InWater
))
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
);
1171 FOREACH(itBot
, std::vector
<CBot
*>, bots
)
1174 CSpawnBot
*const sp
= bot
->getSpawnObj();
1175 if (sp
&& sp
->isAlive())
1177 CAIGainAggroMsg
msg(sp
->dataSetRow(), playerBot
, true);
1187 CBotPlayer
*player
=NLMISC::safe_cast
<CBotPlayer
*>(entity
);
1190 player
->addAggroer(targetBot
);
1194 void CSetBotHeadingImp::callback(const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1196 CAIEntityPhysical
*ep
=CAIS::instance().getEntityPhysical(BotRowId
);
1200 nlwarning("CSetBotHeadingImp : invalid bot id : %s (%u)", TheDataset
.getEntityId(BotRowId
).toString().c_str(), BotRowId
.getIndex());
1204 // ok, we have an entity physical, try to make it a npc
1205 CSpawnBotNpc
*sb
= dynamic_cast<CSpawnBotNpc
*>(ep
);
1209 nlwarning("CSetBotHeadingImp : bot id %s (%u) is not an NPC !", TheDataset
.getEntityId(BotRowId
).toString().c_str(), BotRowId
.getIndex());
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"