From 437513b1f6bc467227763ced04f1f184bb8c04e8 Mon Sep 17 00:00:00 2001 From: Saiska Date: Fri, 29 May 2026 12:46:35 +0200 Subject: [PATCH] Add event chatter for zone/killed-by-creature/reputation/resurrect/combat 6 new opt-in events; per-event Player/BotEventChance. split selected by isSourceBot; defaults 0; existing Died untouched. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 2 +- conf/mod_ollama_chat.conf.dist | 31 +++++++++++ src/mod-ollama-chat_config.cpp | 42 +++++++++++++++ src/mod-ollama-chat_config.h | 22 ++++++++ src/mod-ollama-chat_events.cpp | 99 ++++++++++++++++++++++++++++++++++ src/mod-ollama-chat_events.h | 38 +++++++++++++ src/mod-ollama-chat_main.cpp | 5 ++ 7 files changed, 238 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ac8014cc..8b92b4ac5 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Reload the module’s config and personality packs in-game or from the server console, without restarting. - **Event-Based Chatter:** - Player bots now comment on key in-game events such as quest completion, rare loot, deaths, PvP kills, leveling up, duels, learning spells, and achievements. Remarks are context-aware, immersive, and personality-driven, making the world feel much more alive. + Player bots now comment on key in-game events such as quest completion, rare loot, deaths, PvP kills, leveling up, duels, learning spells, and achievements. Remarks are context-aware, immersive, and personality-driven, making the world feel much more alive. Additional opt-in events include entering zones, being slain by creatures, reputation rank-ups, resurrecting, and entering or leaving combat. Each of these new events supports separate player-vs-bot trigger chances (`PlayerEventChance.` / `BotEventChance.`) and defaults to off (0) to avoid spam. - **Party-Only Bot Responses:** When enabled, bots will only respond to real player messages and events when they are in the same non-raid party. This helps reduce chat spam while maintaining full bot-to-bot communication within parties for immersive group interactions. diff --git a/conf/mod_ollama_chat.conf.dist b/conf/mod_ollama_chat.conf.dist index b6000322e..ee5b20520 100644 --- a/conf/mod_ollama_chat.conf.dist +++ b/conf/mod_ollama_chat.conf.dist @@ -640,6 +640,37 @@ OllamaChat.EventTypeAchievement_Chance = 75 OllamaChat.EventTypeUsedObject = used object OllamaChat.EventTypeUsedObject_Chance = 10 +# -------------------------------------------- +# ADDITIONAL EVENT HOOKS — all default 0 (off / opt-in) +# Each event has a type string (the prompt label) and split chances: +# PlayerEventChance. = chance (0-100) when the actor is a real player +# BotEventChance. = chance (0-100) when the actor is a bot +# -------------------------------------------- + +OllamaChat.EventTypeEnteredZone = entered zone +OllamaChat.PlayerEventChance.EnteredZone = 0 +OllamaChat.BotEventChance.EnteredZone = 0 + +OllamaChat.EventTypeKilledByCreature = killed by creature +OllamaChat.PlayerEventChance.KilledByCreature = 0 +OllamaChat.BotEventChance.KilledByCreature = 0 + +OllamaChat.EventTypeReputationRank = reputation rank +OllamaChat.PlayerEventChance.ReputationRank = 0 +OllamaChat.BotEventChance.ReputationRank = 0 + +OllamaChat.EventTypeResurrected = resurrected +OllamaChat.PlayerEventChance.Resurrected = 0 +OllamaChat.BotEventChance.Resurrected = 0 + +OllamaChat.EventTypeEnteredCombat = entered combat +OllamaChat.PlayerEventChance.EnteredCombat = 0 +OllamaChat.BotEventChance.EnteredCombat = 0 + +OllamaChat.EventTypeLeftCombat = left combat +OllamaChat.PlayerEventChance.LeftCombat = 0 +OllamaChat.BotEventChance.LeftCombat = 0 + # OllamaChat.EventCooldownTime # Description: The cooldown time (in seconds) for bots to respond to an event. # Default: 10 diff --git a/src/mod-ollama-chat_config.cpp b/src/mod-ollama-chat_config.cpp index 8bc1b1da3..9d368c91e 100644 --- a/src/mod-ollama-chat_config.cpp +++ b/src/mod-ollama-chat_config.cpp @@ -216,6 +216,27 @@ std::string g_GuildEventTypeGuildDemotion = ""; std::string g_GuildEventTypeGuildLogin = ""; std::string g_GuildEventTypeGuildAchievement = ""; +// additional event-chatter hook type strings and chances +std::string g_EventTypeEnteredZone; +std::string g_EventTypeKilledByCreature; +std::string g_EventTypeReputationRank; +std::string g_EventTypeResurrected; +std::string g_EventTypeEnteredCombat; +std::string g_EventTypeLeftCombat; + +uint32_t g_PlayerEventChance_EnteredZone = 0; +uint32_t g_BotEventChance_EnteredZone = 0; +uint32_t g_PlayerEventChance_KilledByCreature = 0; +uint32_t g_BotEventChance_KilledByCreature = 0; +uint32_t g_PlayerEventChance_ReputationRank = 0; +uint32_t g_BotEventChance_ReputationRank = 0; +uint32_t g_PlayerEventChance_Resurrected = 0; +uint32_t g_BotEventChance_Resurrected = 0; +uint32_t g_PlayerEventChance_EnteredCombat = 0; +uint32_t g_BotEventChance_EnteredCombat = 0; +uint32_t g_PlayerEventChance_LeftCombat = 0; +uint32_t g_BotEventChance_LeftCombat = 0; + // -------------------------------------------- // Event Chatter Templates // -------------------------------------------- @@ -513,6 +534,27 @@ void LoadOllamaChatConfig() g_EventTypeAchievement = sConfigMgr->GetOption("OllamaChat.EventTypeAchievement", ""); g_EventTypeUsedObject = sConfigMgr->GetOption("OllamaChat.EventTypeUsedObject", ""); + // additional event-chatter hook type strings + g_EventTypeEnteredZone = sConfigMgr->GetOption("OllamaChat.EventTypeEnteredZone", "entered zone"); + g_EventTypeKilledByCreature = sConfigMgr->GetOption("OllamaChat.EventTypeKilledByCreature", "killed by creature"); + g_EventTypeReputationRank = sConfigMgr->GetOption("OllamaChat.EventTypeReputationRank", "reputation rank"); + g_EventTypeResurrected = sConfigMgr->GetOption("OllamaChat.EventTypeResurrected", "resurrected"); + g_EventTypeEnteredCombat = sConfigMgr->GetOption("OllamaChat.EventTypeEnteredCombat", "entered combat"); + g_EventTypeLeftCombat = sConfigMgr->GetOption("OllamaChat.EventTypeLeftCombat", "left combat"); + + // per-event player/bot chances (default 0 = off) + g_PlayerEventChance_EnteredZone = sConfigMgr->GetOption("OllamaChat.PlayerEventChance.EnteredZone", 0); + g_BotEventChance_EnteredZone = sConfigMgr->GetOption("OllamaChat.BotEventChance.EnteredZone", 0); + g_PlayerEventChance_KilledByCreature = sConfigMgr->GetOption("OllamaChat.PlayerEventChance.KilledByCreature", 0); + g_BotEventChance_KilledByCreature = sConfigMgr->GetOption("OllamaChat.BotEventChance.KilledByCreature", 0); + g_PlayerEventChance_ReputationRank = sConfigMgr->GetOption("OllamaChat.PlayerEventChance.ReputationRank", 0); + g_BotEventChance_ReputationRank = sConfigMgr->GetOption("OllamaChat.BotEventChance.ReputationRank", 0); + g_PlayerEventChance_Resurrected = sConfigMgr->GetOption("OllamaChat.PlayerEventChance.Resurrected", 0); + g_BotEventChance_Resurrected = sConfigMgr->GetOption("OllamaChat.BotEventChance.Resurrected", 0); + g_PlayerEventChance_EnteredCombat = sConfigMgr->GetOption("OllamaChat.PlayerEventChance.EnteredCombat", 0); + g_BotEventChance_EnteredCombat = sConfigMgr->GetOption("OllamaChat.BotEventChance.EnteredCombat", 0); + g_PlayerEventChance_LeftCombat = sConfigMgr->GetOption("OllamaChat.PlayerEventChance.LeftCombat", 0); + g_BotEventChance_LeftCombat = sConfigMgr->GetOption("OllamaChat.BotEventChance.LeftCombat", 0); // Load extra blacklist commands from config (comma-separated list) std::string extraBlacklist = sConfigMgr->GetOption("OllamaChat.BlacklistCommands", ""); diff --git a/src/mod-ollama-chat_config.h b/src/mod-ollama-chat_config.h index 37e66e26e..966012dbe 100644 --- a/src/mod-ollama-chat_config.h +++ b/src/mod-ollama-chat_config.h @@ -187,6 +187,28 @@ extern std::string g_GuildEventTypeGuildDemotion; extern std::string g_GuildEventTypeGuildLogin; extern std::string g_GuildEventTypeGuildAchievement; +// additional event-chatter hook type strings +extern std::string g_EventTypeEnteredZone; +extern std::string g_EventTypeKilledByCreature; +extern std::string g_EventTypeReputationRank; +extern std::string g_EventTypeResurrected; +extern std::string g_EventTypeEnteredCombat; +extern std::string g_EventTypeLeftCombat; + +// per-event player/bot chances (0-100); all default 0 (opt-in) +extern uint32_t g_PlayerEventChance_EnteredZone; +extern uint32_t g_BotEventChance_EnteredZone; +extern uint32_t g_PlayerEventChance_KilledByCreature; +extern uint32_t g_BotEventChance_KilledByCreature; +extern uint32_t g_PlayerEventChance_ReputationRank; +extern uint32_t g_BotEventChance_ReputationRank; +extern uint32_t g_PlayerEventChance_Resurrected; +extern uint32_t g_BotEventChance_Resurrected; +extern uint32_t g_PlayerEventChance_EnteredCombat; +extern uint32_t g_BotEventChance_EnteredCombat; +extern uint32_t g_PlayerEventChance_LeftCombat; +extern uint32_t g_BotEventChance_LeftCombat; + // Chance variables for normal events extern int g_EventTypeDefeated_Chance; extern int g_EventTypeDefeatedPlayer_Chance; diff --git a/src/mod-ollama-chat_events.cpp b/src/mod-ollama-chat_events.cpp index a1eb690d7..32574a1a1 100644 --- a/src/mod-ollama-chat_events.cpp +++ b/src/mod-ollama-chat_events.cpp @@ -16,6 +16,10 @@ #include "SpellMgr.h" #include "AchievementMgr.h" #include "GameObject.h" +#include "Creature.h" +#include "DBCStores.h" +#include "World.h" +#include "SharedDefines.h" #include #include #include @@ -198,6 +202,30 @@ void OllamaBotEventChatter::DispatchGameEvent(Player* source, std::string type, } else if (type == g_EventTypeUsedObject) { eventChance = g_EventTypeUsedObject_Chance; } + else if (type == g_EventTypeEnteredZone) + { + eventChance = isSourceBot ? g_BotEventChance_EnteredZone : g_PlayerEventChance_EnteredZone; + } + else if (type == g_EventTypeKilledByCreature) + { + eventChance = isSourceBot ? g_BotEventChance_KilledByCreature : g_PlayerEventChance_KilledByCreature; + } + else if (type == g_EventTypeReputationRank) + { + eventChance = isSourceBot ? g_BotEventChance_ReputationRank : g_PlayerEventChance_ReputationRank; + } + else if (type == g_EventTypeResurrected) + { + eventChance = isSourceBot ? g_BotEventChance_Resurrected : g_PlayerEventChance_Resurrected; + } + else if (type == g_EventTypeEnteredCombat) + { + eventChance = isSourceBot ? g_BotEventChance_EnteredCombat : g_PlayerEventChance_EnteredCombat; + } + else if (type == g_EventTypeLeftCombat) + { + eventChance = isSourceBot ? g_BotEventChance_LeftCombat : g_PlayerEventChance_LeftCombat; + } // Add chance checks for all GuildEventType entries if (type == g_GuildEventTypeEpicGear) { @@ -663,6 +691,77 @@ void ChatOnGameObjectUse::OnGameObjectUse(Player* player, GameObject* go) eventChatter.DispatchGameEvent(player, g_EventTypeUsedObject, go->GetGOInfo()->name); } +// additional event-chatter hooks + +ChatOnZone::ChatOnZone() : PlayerScript("ChatOnZone") {} + +void ChatOnZone::OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 /*newArea*/) +{ + if (!player) + return; + std::string zoneName; + if (AreaTableEntry const* zone = sAreaTableStore.LookupEntry(newZone)) + { + zoneName = zone->area_name[sWorld->GetDefaultDbcLocale()]; + if (zoneName.empty()) + zoneName = zone->area_name[LOCALE_enUS]; + } + eventChatter.DispatchGameEvent(player, g_EventTypeEnteredZone, zoneName); +} + +ChatOnKilledByCreature::ChatOnKilledByCreature() : PlayerScript("ChatOnKilledByCreature") {} + +void ChatOnKilledByCreature::OnPlayerKilledByCreature(Creature* killer, Player* killed) +{ + if (!killer || !killed) + return; + eventChatter.DispatchGameEvent(killed, g_EventTypeKilledByCreature, killer->GetName()); +} + +ChatOnReputationRank::ChatOnReputationRank() : PlayerScript("ChatOnReputationRank") {} + +void ChatOnReputationRank::OnPlayerReputationRankChange(Player* player, uint32 factionID, + ReputationRank /*newRank*/, + ReputationRank /*oldRank*/, bool increased) +{ + if (!player || !increased) // only celebrate rank-ups, not losses + return; + std::string factionName; + if (FactionEntry const* faction = sFactionStore.LookupEntry(factionID)) + { + factionName = faction->name[sWorld->GetDefaultDbcLocale()]; + if (factionName.empty()) + factionName = faction->name[LOCALE_enUS]; + } + eventChatter.DispatchGameEvent(player, g_EventTypeReputationRank, factionName); +} + +ChatOnResurrect::ChatOnResurrect() : PlayerScript("ChatOnResurrect") {} + +void ChatOnResurrect::OnPlayerResurrect(Player* player, float /*restorePercent*/, bool& /*applySickness*/) +{ + if (!player) + return; + eventChatter.DispatchGameEvent(player, g_EventTypeResurrected, ""); +} + +ChatOnCombat::ChatOnCombat() : PlayerScript("ChatOnCombat") {} + +void ChatOnCombat::OnPlayerEnterCombat(Player* player, Unit* enemy) +{ + if (!player) + return; + std::string enemyName = enemy ? enemy->GetName() : ""; + eventChatter.DispatchGameEvent(player, g_EventTypeEnteredCombat, enemyName); +} + +void ChatOnCombat::OnPlayerLeaveCombat(Player* player) +{ + if (!player) + return; + eventChatter.DispatchGameEvent(player, g_EventTypeLeftCombat, ""); +} + ChatOnGuildMemberChange::ChatOnGuildMemberChange() : PlayerScript("ChatOnGuildMemberChange") {} void ChatOnGuildMemberChange::OnGuildMemberJoin(Player* player, Guild* /*guild*/) diff --git a/src/mod-ollama-chat_events.h b/src/mod-ollama-chat_events.h index 3387db3dc..6eefcb1b2 100644 --- a/src/mod-ollama-chat_events.h +++ b/src/mod-ollama-chat_events.h @@ -81,6 +81,44 @@ class ChatOnGameObjectUse : public PlayerScript void OnGameObjectUse(Player* player, GameObject* go); }; +// additional event-chatter hooks +class ChatOnZone : public PlayerScript +{ +public: + ChatOnZone(); + void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea) override; +}; + +class ChatOnKilledByCreature : public PlayerScript +{ +public: + ChatOnKilledByCreature(); + void OnPlayerKilledByCreature(Creature* killer, Player* killed) override; +}; + +class ChatOnReputationRank : public PlayerScript +{ +public: + ChatOnReputationRank(); + void OnPlayerReputationRankChange(Player* player, uint32 factionID, ReputationRank /*newRank*/, + ReputationRank /*oldRank*/, bool increased) override; +}; + +class ChatOnResurrect : public PlayerScript +{ +public: + ChatOnResurrect(); + void OnPlayerResurrect(Player* player, float restorePercent, bool& applySickness) override; +}; + +class ChatOnCombat : public PlayerScript +{ +public: + ChatOnCombat(); + void OnPlayerEnterCombat(Player* player, Unit* enemy) override; + void OnPlayerLeaveCombat(Player* player) override; +}; + class ChatOnGuildMemberChange : public PlayerScript { public: diff --git a/src/mod-ollama-chat_main.cpp b/src/mod-ollama-chat_main.cpp index 9c1a14197..b56b2ebd0 100644 --- a/src/mod-ollama-chat_main.cpp +++ b/src/mod-ollama-chat_main.cpp @@ -23,5 +23,10 @@ void Addmod_ollama_chatScripts() new ChatOnLevelUp(); new ChatOnAchievement(); new ChatOnGameObjectUse(); + new ChatOnZone(); + new ChatOnKilledByCreature(); + new ChatOnReputationRank(); + new ChatOnResurrect(); + new ChatOnCombat(); new OllamaChatConfigCommand(); }