eluna-scripts-ornfelt/lua/WowEmulationScriptPack/patch/multitrainer_3.3.5.diff
2024-09-23 07:59:23 +02:00

206 lines
9.6 KiB
Diff

diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 8c3fcafaf83a..e68965571144 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -14233,7 +14233,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
break;
case GOSSIP_OPTION_TRAINER:
{
- Trainer::Trainer const* trainer = sObjectMgr->GetTrainer(creature->GetEntry());
+ Trainer::Trainer const* trainer = sObjectMgr->GetTrainer(itr->second.ActionMenuID ? itr->second.ActionMenuID : creature->GetEntry());
if (!trainer || !trainer->IsTrainerValidForPlayer(this))
{
TC_LOG_ERROR("sql.sql", "GOSSIP_OPTION_TRAINER:: Player %s %s requested wrong gossip menu: %u at Creature: %s (Entry: %u)",
@@ -14421,7 +14421,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men
GetSession()->SendStablePet(guid);
break;
case GOSSIP_OPTION_TRAINER:
- GetSession()->SendTrainerList(source->ToCreature());
+ GetSession()->SendTrainerList(source->ToCreature(), menuItemData->GossipActionMenuId);
break;
case GOSSIP_OPTION_LEARNDUALSPEC:
if (GetSpecsCount() == 1 && GetLevel() >= sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL))
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index dbc84d072250..2bdd4d946cc3 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -97,13 +97,13 @@ void WorldSession::HandleTrainerListOpcode(WorldPackets::NPC::Hello& packet)
SendTrainerList(npc);
}
-void WorldSession::SendTrainerList(Creature* npc)
+void WorldSession::SendTrainerList(Creature* npc, uint32 trainerEntry)
{
// remove fake death
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- Trainer::Trainer const* trainer = sObjectMgr->GetTrainer(npc->GetEntry());
+ Trainer::Trainer const* trainer = sObjectMgr->GetTrainer(trainerEntry ? trainerEntry : npc->GetEntry());
if (!trainer)
{
TC_LOG_DEBUG("network", "WorldSession: SendTrainerList - trainer spells not found for %s", npc->GetGUID().ToString().c_str());
@@ -116,6 +116,9 @@ void WorldSession::SendTrainerList(Creature* npc)
return;
}
+ SetCurrentTrainer(trainerEntry);
+ GetPlayer()->PlayerTalkClass->GetGossipMenu().SetSenderGUID(npc->GetGUID());
+
trainer->SendSpells(npc, _player, GetSessionDbLocaleIndex());
}
@@ -130,11 +133,14 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPackets::NPC::TrainerBuySpel
return;
}
+ if (packet.TrainerGUID != GetPlayer()->PlayerTalkClass->GetGossipMenu().GetSenderGUID())
+ return; // Cheating
+
// remove fake death
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- Trainer::Trainer const* trainer = sObjectMgr->GetTrainer(npc->GetEntry());
+ Trainer::Trainer const* trainer = sObjectMgr->GetTrainer(GetCurrentTrainer() ? GetCurrentTrainer() : npc->GetEntry());
if (!trainer)
return;
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 8c2f073fa674..986d7abdc86d 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -492,7 +492,7 @@ class TC_GAME_API WorldSession
void SendNameQueryOpcode(ObjectGuid guid);
- void SendTrainerList(Creature* npc);
+ void SendTrainerList(Creature* npc, uint32 trainer_entry = 0);
void SendListInventory(ObjectGuid guid);
void SendShowBank(ObjectGuid guid);
bool CanOpenMailBox(ObjectGuid guid);
@@ -568,6 +568,10 @@ class TC_GAME_API WorldSession
bool CanSpeak() const;
time_t m_muteTime;
+ // Multitrainer
+ uint32 GetCurrentTrainer() const { return m_current_trainer; }
+ void SetCurrentTrainer(uint32 entry) { m_current_trainer = entry; }
+
// Locales
LocaleConstant GetSessionDbcLocale() const { return m_sessionDbcLocale; }
LocaleConstant GetSessionDbLocaleIndex() const { return m_sessionDbLocaleIndex; }
@@ -1192,6 +1196,8 @@ class TC_GAME_API WorldSession
std::string _accountName;
uint8 m_expansion;
+ uint32 m_current_trainer;
+
// Warden
std::unique_ptr<Warden> _warden; // Remains NULL if Warden system is not enabled by config
diff --git a/src/server/scripts/Custom/multitrainer/MultitrainerExample.cpp b/src/server/scripts/Custom/multitrainer/MultitrainerExample.cpp
new file mode 100644
index 000000000000..c20ec57e8650
--- /dev/null
+++ b/src/server/scripts/Custom/multitrainer/MultitrainerExample.cpp
@@ -0,0 +1,42 @@
+#include "ScriptMgr.h"
+#include "Creature.h"
+#include "Player.h"
+#include "ScriptedGossip.h"
+#include "ScriptedCreature.h"
+#include "WorldSession.h"
+
+class MultivendorExample : public CreatureScript
+{
+public:
+ MultivendorExample() : CreatureScript("MultivendorExample") {}
+
+ struct MultivendorAI : public ScriptedAI
+ {
+ MultivendorAI(Creature* creature) : ScriptedAI(creature) {}
+
+ bool OnGossipHello(Player* player) override
+ {
+ AddGossipItemFor(player, GOSSIP_ICON_CHAT, "TrainerTest 33684", GOSSIP_SENDER_MAIN, 33684);
+ AddGossipItemFor(player, GOSSIP_ICON_CHAT, "TrainerTest 2704", GOSSIP_SENDER_MAIN, 2704);
+ SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, me);
+ return true;
+ }
+
+ bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
+ {
+ uint32 action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
+ player->GetSession()->SendTrainerList(me, action);
+ return true;
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new MultivendorAI(creature);
+ }
+};
+
+void AddSC_MultivendorExample()
+{
+ new MultivendorExample();
+}
diff --git a/src/server/scripts/Custom/multitrainer/MultitrainerExample.sql b/src/server/scripts/Custom/multitrainer/MultitrainerExample.sql
new file mode 100644
index 000000000000..8b94ebc32f0b
--- /dev/null
+++ b/src/server/scripts/Custom/multitrainer/MultitrainerExample.sql
@@ -0,0 +1,9 @@
+SET @ENTRY = (SELECT max(entry)+1 FROM creature_template);
+SET @MENU_ID = (SELECT max(menuid)+1 FROM gossip_menu_option);
+
+INSERT INTO `creature_template` (`entry`, `modelid1`, `name`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `baseattacktime`, `rangeattacktime`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `HoverHeight`, `RacialLeader`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`) VALUES
+(@ENTRY, 5080, "Rakka", "MultiTrainer", NULL, @MENU_ID, 10, 10, 0, 35, 17, 1, 1.14286, 1, 0, 0, 1500, 0, 1, 512, 2048, 8, 0, 7, 138412032, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 0, 0, 1, 0, 2, '');
+
+INSERT INTO `gossip_menu_option` (`menuid`, `optionid`, `optionicon`, `optiontext`, `optiontype`, `optionnpcflag`, `actionmenuid`, `actionpoiid`, `boxcoded`, `boxmoney`, `boxtext`) VALUES
+(@MENU_ID, 0, 3, 'TrainerTest 33684', 5, 16, 33684, 0, 0, 0, ''),
+(@MENU_ID, 1, 3, 'TrainerTest 2704', 5, 16, 2704, 0, 0, 0, '');
diff --git a/src/server/scripts/Custom/multitrainer/README.md b/src/server/scripts/Custom/multitrainer/README.md
new file mode 100644
index 000000000000..8d171d74a661
--- /dev/null
+++ b/src/server/scripts/Custom/multitrainer/README.md
@@ -0,0 +1,36 @@
+# Multitrainer [![Build Status](https://travis-ci.org/Rochet2/TrinityCore.svg?branch=multitrainer_3.3.5)](https://travis-ci.org/Rochet2/TrinityCore)
+
+#### About
+This patch was coded originally by [CyberMist2](https://github.com/CyberMist2).
+Multitrainer allows you to show multiple different trainer windows on an NPC.
+
+Source: http://rochet2.github.io/Multitrainer.html
+
+#### Installation
+
+Available as:
+- Direct merge: https://github.com/Rochet2/TrinityCore/tree/multitrainer_3.3.5
+- Diff: https://github.com/Rochet2/TrinityCore/compare/TrinityCore:3.3.5...multitrainer_3.3.5.diff
+- Diff in github view: https://github.com/Rochet2/TrinityCore/compare/TrinityCore:3.3.5...multitrainer_3.3.5
+
+Using direct merge:
+- open git bash to source location
+- do `git remote add rochet2 https://github.com/Rochet2/TrinityCore.git`
+- do `git pull rochet2 multitrainer_3.3.5`
+- use cmake and compile
+
+Using diff:
+- DO NOT COPY THE DIFF DIRECTLY! It causes apply to fail.
+- download the diff by __right clicking__ the link and select __Save link as__
+- place the downloaded `multitrainer_3.3.5.diff` to the source root folder
+- open git bash to source location
+- do `git apply multitrainer_3.3.5.diff`
+- use cmake and compile
+
+#### Usage
+The NPC is required to have `npcflag` set to `17`. The `trainer_type` can be `0`.
+In C++ you can pass the trainer entry to `SendTrainerList` function.
+In SQL in `world` database you can set the trainer entry to the `gossip_menu_option` table `ActionMenuID` column for an option that has `OptionType` set to `5`.
+
+#### Bugs and Contact
+Report issues and similar to https://rochet2.github.io/