aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Scripting
diff options
context:
space:
mode:
authorModoX <moardox@gmail.com>2024-12-28 23:25:10 +0100
committerGitHub <noreply@github.com>2024-12-28 23:25:10 +0100
commit309ba22a15e5e0b4321b99f7157ccb18e0adc8dd (patch)
treef40e4b0b27df733b348144b3813b932f8aeb3268 /src/server/game/Scripting
parentd8bcf5fcb655d9931f7c74883ca19c0428e2a8ae (diff)
Core/AI: Implemented conversation ai (#30538)
Diffstat (limited to 'src/server/game/Scripting')
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp118
-rw-r--r--src/server/game/Scripting/ScriptMgr.h29
2 files changed, 80 insertions, 67 deletions
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index e69b64a73fa..99f25980a0d 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -21,6 +21,7 @@
#include "AreaTriggerAI.h"
#include "ChatCommand.h"
#include "Conversation.h"
+#include "ConversationAI.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "CreatureAIImpl.h"
@@ -382,7 +383,7 @@ public:
/// This hook is responsible for swapping Creature, GameObject and AreaTrigger AI's
template<typename ObjectType, typename ScriptType, typename Base>
-class CreatureGameObjectAreaTriggerScriptRegistrySwapHooks
+class CreatureGameObjectAreaTriggerConversationScriptRegistrySwapHooks
: public ScriptRegistrySwapHookBase
{
template<typename W>
@@ -484,6 +485,24 @@ class CreatureGameObjectAreaTriggerScriptRegistrySwapHooks
"The AI should be null here!");
}
+ // Hook which is called before a conversation is swapped
+ static void UnloadResetScript(Conversation* conversation)
+ {
+ // Remove deletable events only,
+ // otherwise it causes crashes with non-deletable spell events.
+ conversation->m_Events.KillAllEvents(false);
+
+ conversation->AI()->OnRemove();
+ }
+
+ static void UnloadDestroyScript(Conversation* conversation)
+ {
+ conversation->AI_Destroy();
+
+ ASSERT(!conversation->AI(),
+ "The AI should be null here!");
+ }
+
// Hook which is called after a creature was swapped
static void LoadInitializeScript(Creature* creature)
{
@@ -543,6 +562,20 @@ class CreatureGameObjectAreaTriggerScriptRegistrySwapHooks
at->AI()->OnCreate(nullptr);
}
+ // Hook which is called after a conversation was swapped
+ static void LoadInitializeScript(Conversation* conversation)
+ {
+ ASSERT(!conversation->AI(),
+ "The AI should be null here!");
+
+ conversation->AI_Initialize();
+ }
+
+ static void LoadResetScript(Conversation* conversation)
+ {
+ conversation->AI()->OnCreate(nullptr);
+ }
+
static Creature* GetEntityFromMap(std::common_type<Creature>, Map* map, ObjectGuid const& guid)
{
return map->GetCreature(guid);
@@ -558,6 +591,11 @@ class CreatureGameObjectAreaTriggerScriptRegistrySwapHooks
return map->GetAreaTrigger(guid);
}
+ static Conversation* GetEntityFromMap(std::common_type<Conversation>, Map* map, ObjectGuid const& guid)
+ {
+ return map->GetConversation(guid);
+ }
+
static auto VisitObjectsToSwapOnMap(std::unordered_set<uint32> const& idsToRemove)
{
return [&idsToRemove](Map* map, auto&& visitor)
@@ -731,24 +769,32 @@ private:
// This hook is responsible for swapping CreatureAI's
template<typename Base>
class ScriptRegistrySwapHooks<CreatureScript, Base>
- : public CreatureGameObjectAreaTriggerScriptRegistrySwapHooks<
+ : public CreatureGameObjectAreaTriggerConversationScriptRegistrySwapHooks<
Creature, CreatureScript, Base
> { };
// This hook is responsible for swapping GameObjectAI's
template<typename Base>
class ScriptRegistrySwapHooks<GameObjectScript, Base>
- : public CreatureGameObjectAreaTriggerScriptRegistrySwapHooks<
+ : public CreatureGameObjectAreaTriggerConversationScriptRegistrySwapHooks<
GameObject, GameObjectScript, Base
> { };
// This hook is responsible for swapping AreaTriggerAI's
template<typename Base>
class ScriptRegistrySwapHooks<AreaTriggerEntityScript, Base>
- : public CreatureGameObjectAreaTriggerScriptRegistrySwapHooks<
+ : public CreatureGameObjectAreaTriggerConversationScriptRegistrySwapHooks<
AreaTrigger, AreaTriggerEntityScript, Base
> { };
+// This hook is responsible for swapping ConversationAI's
+template<typename Base>
+class ScriptRegistrySwapHooks<ConversationScript, Base>
+ : public CreatureGameObjectAreaTriggerConversationScriptRegistrySwapHooks<
+ Conversation, ConversationScript, Base
+ > {
+};
+
/// This hook is responsible for swapping BattlefieldScripts
template<typename Base>
class ScriptRegistrySwapHooks<BattlefieldScript, Base>
@@ -955,7 +1001,7 @@ class SpecializedScriptRegistry<ScriptType, true>
friend class ScriptRegistrySwapHooks;
template<typename, typename, typename>
- friend class CreatureGameObjectAreaTriggerScriptRegistrySwapHooks;
+ friend class CreatureGameObjectAreaTriggerConversationScriptRegistrySwapHooks;
public:
SpecializedScriptRegistry() { }
@@ -1752,6 +1798,19 @@ bool ScriptMgr::OnAreaTrigger(Player* player, AreaTriggerEntry const* trigger, b
return entered ? tmpscript->OnTrigger(player, trigger) : tmpscript->OnExit(player, trigger);
}
+bool ScriptMgr::CanCreateConversationAI(uint32 scriptId) const
+{
+ return !!ScriptRegistry<ConversationScript>::Instance()->GetScriptById(scriptId);
+}
+
+ConversationAI* ScriptMgr::GetConversationAI(Conversation* conversation)
+{
+ ASSERT(conversation);
+
+ GET_SCRIPT_RET(ConversationScript, conversation->GetScriptId(), tmpscript, nullptr);
+ return tmpscript->GetAI(conversation);
+}
+
Battlefield* ScriptMgr::CreateBattlefield(uint32 scriptId, Map* map)
{
GET_SCRIPT_RET(BattlefieldScript, scriptId, tmpscript, nullptr);
@@ -2279,40 +2338,6 @@ void ScriptMgr::ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& dama
FOREACH_SCRIPT(UnitScript)->ModifySpellDamageTaken(target, attacker, damage, spellInfo);
}
-// Conversation
-void ScriptMgr::OnConversationCreate(Conversation* conversation, Unit* creator)
-{
- ASSERT(conversation);
-
- GET_SCRIPT(ConversationScript, conversation->GetScriptId(), tmpscript);
- tmpscript->OnConversationCreate(conversation, creator);
-}
-
-void ScriptMgr::OnConversationStart(Conversation* conversation)
-{
- ASSERT(conversation);
-
- GET_SCRIPT(ConversationScript, conversation->GetScriptId(), tmpscript);
- tmpscript->OnConversationStart(conversation);
-}
-
-void ScriptMgr::OnConversationLineStarted(Conversation* conversation, uint32 lineId, Player* sender)
-{
- ASSERT(conversation);
- ASSERT(sender);
-
- GET_SCRIPT(ConversationScript, conversation->GetScriptId(), tmpscript);
- tmpscript->OnConversationLineStarted(conversation, lineId, sender);
-}
-
-void ScriptMgr::OnConversationUpdate(Conversation* conversation, uint32 diff)
-{
- ASSERT(conversation);
-
- GET_SCRIPT(ConversationScript, conversation->GetScriptId(), tmpscript);
- tmpscript->OnConversationUpdate(conversation, diff);
-}
-
// Scene
void ScriptMgr::OnSceneStart(Player* player, uint32 sceneInstanceID, SceneTemplate const* sceneTemplate)
{
@@ -3172,20 +3197,9 @@ ConversationScript::ConversationScript(char const* name)
ConversationScript::~ConversationScript() = default;
-void ConversationScript::OnConversationCreate(Conversation* /*conversation*/, Unit* /*creator*/)
-{
-}
-
-void ConversationScript::OnConversationStart(Conversation* /*conversation*/ )
-{
-}
-
-void ConversationScript::OnConversationLineStarted(Conversation* /*conversation*/, uint32 /*lineId*/, Player* /*sender*/)
-{
-}
-
-void ConversationScript::OnConversationUpdate(Conversation* /*conversation*/, uint32 /*diff*/)
+ConversationAI* ConversationScript::GetAI(Conversation* /*conversation*/) const
{
+ return nullptr;
}
SceneScript::SceneScript(char const* name)
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index 31a5842a383..d7746b01e04 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -38,6 +38,7 @@ class BattlegroundMap;
class BattlegroundScript;
class Channel;
class Conversation;
+class ConversationAI;
class Creature;
class CreatureAI;
class DynamicObject;
@@ -911,17 +912,8 @@ class TC_GAME_API ConversationScript : public ScriptObject
~ConversationScript();
- // Called when Conversation is created but not added to Map yet.
- virtual void OnConversationCreate(Conversation* conversation, Unit* creator);
-
- // Called when Conversation is started
- virtual void OnConversationStart(Conversation* conversation);
-
- // Called when player sends CMSG_CONVERSATION_LINE_STARTED with valid conversation guid
- virtual void OnConversationLineStarted(Conversation* conversation, uint32 lineId, Player* sender);
-
- // Called for each update tick
- virtual void OnConversationUpdate(Conversation* conversation, uint32 diff);
+ // Called when a ConversationAI object is needed for the conversation.
+ virtual ConversationAI* GetAI(Conversation* conversation) const;
};
class TC_GAME_API SceneScript : public ScriptObject
@@ -1279,10 +1271,8 @@ class TC_GAME_API ScriptMgr
public: /* ConversationScript */
- void OnConversationCreate(Conversation* conversation, Unit* creator);
- void OnConversationStart(Conversation* conversation);
- void OnConversationLineStarted(Conversation* conversation, uint32 lineId, Player* sender);
- void OnConversationUpdate(Conversation* conversation, uint32 diff);
+ bool CanCreateConversationAI(uint32 scriptId) const;
+ ConversationAI* GetConversationAI(Conversation* conversation);
public: /* SceneScript */
@@ -1405,6 +1395,15 @@ class GenericAreaTriggerEntityScript : public AreaTriggerEntityScript
};
#define RegisterAreaTriggerAI(ai_name) new GenericAreaTriggerEntityScript<ai_name>(#ai_name)
+template <class AI>
+class GenericConversationScript : public ConversationScript
+{
+public:
+ GenericConversationScript(char const* name) : ConversationScript(name) {}
+ ConversationAI* GetAI(Conversation* conversation) const override { return new AI(conversation); }
+};
+#define RegisterConversationAI(ai_name) new GenericConversationScript<ai_name>(#ai_name)
+
template<class Script>
class GenericBattlegroundMapScript : public BattlegroundMapScript
{