From 763a793cc050389cfae0d8c85f5366a1a36fe0fd Mon Sep 17 00:00:00 2001 From: Stoabrogga Date: Fri, 13 Feb 2026 10:36:03 +0100 Subject: [PATCH 01/10] Improvements --- conf/morphsummon.conf.dist | 8 ++ .../db-characters/base/morphsummon_ddl.sql | 4 +- data/sql/db-world/base/morphsummon.sql | 7 +- src/morphsummon.cpp | 117 ++++++++++++------ 4 files changed, 89 insertions(+), 47 deletions(-) diff --git a/conf/morphsummon.conf.dist b/conf/morphsummon.conf.dist index 5338265..ae4666f 100644 --- a/conf/morphsummon.conf.dist +++ b/conf/morphsummon.conf.dist @@ -4,10 +4,18 @@ # mod-morphsummon configuration ##################################### +# Enable or disable the module + +MorphSummon.Enabled = 1 + # Announce the module when the player logs in? MorphSummon.Announce = 0 +# Allow new name for demons and ghouls + +MorphSummon.NewNameEnabled = 1 + # Model IDs for the summoned permanent creatures MorphSummon.Warlock.Imp = "Imp Black,4449,Imp Jade,7552,Imp Red,10811,Outland Imp Red,16888,Outland Imp Purple,16889,Outland Imp Yellow,16890,Outland Imp White,16891" diff --git a/data/sql/db-characters/base/morphsummon_ddl.sql b/data/sql/db-characters/base/morphsummon_ddl.sql index be43ea5..2ed536b 100644 --- a/data/sql/db-characters/base/morphsummon_ddl.sql +++ b/data/sql/db-characters/base/morphsummon_ddl.sql @@ -1,5 +1,5 @@ CREATE TABLE IF NOT EXISTS `mod_morphsummon_felguard_weapon` ( - `PlayerGUIDLow` int(10) unsigned NOT NULL, - `FelguardItemID` int(10) unsigned NOT NULL COMMENT 'Item ID for Felguard virtual item slot 0', + `PlayerGUIDLow` int unsigned NOT NULL, + `FelguardItemID` int unsigned NOT NULL COMMENT 'Item ID for Felguard virtual item slot 0', PRIMARY KEY (`PlayerGUIDLow`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='mod-morphsummon; used for custom Felguard weapons'; diff --git a/data/sql/db-world/base/morphsummon.sql b/data/sql/db-world/base/morphsummon.sql index eebd3e2..0eadc3c 100644 --- a/data/sql/db-world/base/morphsummon.sql +++ b/data/sql/db-world/base/morphsummon.sql @@ -12,7 +12,7 @@ SET @MENU_CHOICE := @MENU_HELLO + 2; DELETE FROM `creature_template` WHERE `entry` = @ENTRY; INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `name`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `DamageModifier`, `BaseAttackTime`, `RangeAttackTime`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `HoverHeight`, `HealthModifier`, `ManaModifier`, `ArmorModifier`, `RacialLeader`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES -(@ENTRY, 0, 0, 0, 0, 0, @NAME, @SUBNAME, NULL, 0, 80, 80, 2, 35, 0, 1, 1.14286, 1, 0, 0, 1, 2000, 2000, 8, 0, 2048, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 0, 0, 1, 0, 2, @SCRIPTNAME, 0); +(@ENTRY, 0, 0, 0, 0, 0, @NAME, @SUBNAME, NULL, 0, 80, 80, 2, 35, 1, 1, 1.14286, 1, 0, 0, 1, 2000, 2000, 8, 0, 2048, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 0, 0, 1, 0, 2, @SCRIPTNAME, 0); DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (@ENTRY); INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES @@ -28,12 +28,11 @@ DELETE FROM `gossip_menu_option` WHERE `MenuID` IN (@MENU_HELLO, @MENU_SORRY, @M INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES (@MENU_HELLO, 0, 0, 'Choose polymorph', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), (@MENU_HELLO, 1, 0, 'Choose Felguard weapon', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), +(@MENU_HELLO, 2, 0, 'Generate new name', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), (@MENU_SORRY, 0, 0, 'Ah, nevermind.', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), (@MENU_CHOICE, 0, 0, 'Back..', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), (@MENU_CHOICE, 1, 4, 'Next..', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), (@MENU_CHOICE, 2, 4, 'Previous..', 0, 0, 0, 0, 0, 0, 0, '', 0, 0); DELETE FROM `creature_template_model` where `CreatureID` = @ENTRY; -INSERT INTO `creature_template_model` (`CreatureID`, `Idx`, `CreatureDisplayID`, `DisplayScale`, `Probability`, `VerifiedBuild`) VALUES (@ENTRY, 0, @MODELID, 1, 1, 12340); - -UPDATE `creature_template` SET `npcflag`=`npcflag`|1 WHERE `entry`=@ENTRY; +INSERT INTO `creature_template_model` (`CreatureID`, `Idx`, `CreatureDisplayID`, `DisplayScale`, `Probability`, `VerifiedBuild`) VALUES (@ENTRY, 0, @MODELID, 1, 1, 0); diff --git a/src/morphsummon.cpp b/src/morphsummon.cpp index 5d3a92a..71ee475 100644 --- a/src/morphsummon.cpp +++ b/src/morphsummon.cpp @@ -11,6 +11,7 @@ #include "ScriptMgr.h" #include "SpellAuras.h" #include "Unit.h" +#include "GameTime.h" std::map warlock_imp; std::map warlock_voidwalker; @@ -24,7 +25,9 @@ std::list randomVisualEffectSpells; std::list randomMainHandEquip; uint32 minTimeVisualEffect; uint32 maxTimeVisualEffect; +bool morphSummonEnabled; bool morphSummonAnnounce; +bool morphSummonNewNameEnabled; enum MorphSummonGossip { @@ -40,6 +43,7 @@ enum MorphSummonGossip MORPH_PAGE_MAX = 901, MORPH_MAIN_MENU = 50, MORPH_CLOSE_MENU = 60, + MORPH_NEW_NAME = 70, MORPH_GOSSIP_TEXT_HELLO = 601072, MORPH_GOSSIP_TEXT_SORRY = 601073, MORPH_GOSSIP_TEXT_CHOICE = 601074, @@ -48,6 +52,7 @@ enum MorphSummonGossip MORPH_GOSSIP_MENU_CHOICE = 61074, MORPH_GOSSIP_OPTION_POLYMORPH = 0, MORPH_GOSSIP_OPTION_FELGUARD_WEAPON = 1, + MORPH_GOSSIP_OPTION_NEW_NAME = 2, MORPH_GOSSIP_OPTION_SORRY = 0, MORPH_GOSSIP_OPTION_CHOICE_BACK = 0, MORPH_GOSSIP_OPTION_CHOICE_NEXT = 1, @@ -62,7 +67,7 @@ enum MorphSummonSpells SUMMON_FELHUNTER = 691, SUMMON_FELGUARD = 30146, RAISE_DEAD = 52150, - SUMMON_WATER_ELEMENTAL = 70907 + SUMMON_WATER_ELEMENTAL = 70908 }; enum MorphEffectSpells @@ -86,27 +91,18 @@ class MorphSummonPlayerScript : public PlayerScript void OnPlayerLogin(Player* player) override { - if (morphSummonAnnounce) + if (morphSummonEnabled && morphSummonAnnounce) ChatHandler(player->GetSession()).SendSysMessage("This server is running the |cff4CFF00MorphSummon |rmodule."); } void OnPlayerAfterGuardianInitStatsForLevel(Player* player, Guardian* guardian) override { - if (Pet* pet = guardian->ToPet()) + if (Pet* pet = guardian->ToPet(); pet && pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_FELGUARD) { - if (pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_WATER_ELEMENTAL) + if (QueryResult result = CharacterDatabase.Query("SELECT `FelguardItemID` FROM `mod_morphsummon_felguard_weapon` WHERE `PlayerGUIDLow`={}", player->GetGUID().GetCounter())) { - // The size of the water elemental model is not automatically scaled, so needs to be done here - CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(pet->GetNativeDisplayId()); - pet->SetObjectScale(0.85f / displayInfo->scale); - } - else if (pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_FELGUARD) - { - if (QueryResult result = CharacterDatabase.Query("SELECT `FelguardItemID` FROM `mod_morphsummon_felguard_weapon` WHERE `PlayerGUIDLow`={}", player->GetGUID().GetCounter())) - { - Field* fields = result->Fetch(); - pet->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, fields[0].Get()); - } + Field* fields = result->Fetch(); + pet->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, fields[0].Get()); } } } @@ -119,11 +115,17 @@ class MorphSummonCreatureScript : public CreatureScript bool OnGossipHello(Player* player, Creature* creature) override { + if (!morphSummonEnabled) + return true; + return CreateMainMenu(player, creature); } bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) override { + if (!morphSummonEnabled) + return true; + ClearGossipMenuFor(player); if (action == MORPH_MAIN_MENU) @@ -135,6 +137,12 @@ class MorphSummonCreatureScript : public CreatureScript return true; } + if (morphSummonNewNameEnabled && action == MORPH_NEW_NAME) + { + GenerateNewName(player); + return CreateMainMenu(player, creature); + } + if (action >= MORPH_PAGE_START_WARLOCK_IMP && action < MORPH_PAGE_START_WARLOCK_VOIDWALKER) AddGossip(player, action, warlock_imp, MORPH_PAGE_START_WARLOCK_IMP); else if (action >= MORPH_PAGE_START_WARLOCK_VOIDWALKER && action < MORPH_PAGE_START_WARLOCK_SUCCUBUS) @@ -222,16 +230,23 @@ class MorphSummonCreatureScript : public CreatureScript private: bool CreateMainMenu(Player* player, Creature* creature) { - bool sorry = false; + bool sorry = true; + bool showNewName = true; // Mage Pet (minion) - if (player->getClass() == CLASS_MAGE) { + if (player->getClass() == CLASS_MAGE) + { + showNewName = false; + if (Minion* minion = player->GetFirstMinion()) { if (minion->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_WATER_ELEMENTAL) { if (!mage_water_elemental.empty()) + { + sorry = false; AddGossipItemFor(player, MORPH_GOSSIP_MENU_HELLO, MORPH_GOSSIP_OPTION_POLYMORPH, GOSSIP_SENDER_MAIN, MORPH_PAGE_START_MAGE_WATER_ELEMENTAL); + } } } } @@ -243,53 +258,56 @@ class MorphSummonCreatureScript : public CreatureScript { case SUMMON_IMP: if (!warlock_imp.empty()) + { + sorry = false; AddGossipItemFor(player, MORPH_GOSSIP_MENU_HELLO, MORPH_GOSSIP_OPTION_POLYMORPH, GOSSIP_SENDER_MAIN, MORPH_PAGE_START_WARLOCK_IMP); - else - sorry = true; + } break; case SUMMON_VOIDWALKER: if (!warlock_voidwalker.empty()) + { + sorry = false; AddGossipItemFor(player, MORPH_GOSSIP_MENU_HELLO, MORPH_GOSSIP_OPTION_POLYMORPH, GOSSIP_SENDER_MAIN, MORPH_PAGE_START_WARLOCK_VOIDWALKER); - else - sorry = true; + } break; case SUMMON_SUCCUBUS: if (!warlock_succubus.empty()) + { + sorry = false; AddGossipItemFor(player, MORPH_GOSSIP_MENU_HELLO, MORPH_GOSSIP_OPTION_POLYMORPH, GOSSIP_SENDER_MAIN, MORPH_PAGE_START_WARLOCK_SUCCUBUS); - else - sorry = true; + } break; case SUMMON_FELHUNTER: if (!warlock_felhunter.empty()) + { + sorry = false; AddGossipItemFor(player, MORPH_GOSSIP_MENU_HELLO, MORPH_GOSSIP_OPTION_POLYMORPH, GOSSIP_SENDER_MAIN, MORPH_PAGE_START_WARLOCK_FELHUNTER); - else - sorry = true; + } break; case SUMMON_FELGUARD: if (!warlock_felguard.empty()) { + sorry = false; AddGossipItemFor(player, MORPH_GOSSIP_MENU_HELLO, MORPH_GOSSIP_OPTION_POLYMORPH, GOSSIP_SENDER_MAIN, MORPH_PAGE_START_WARLOCK_FELGUARD); if (!felguard_weapon.empty()) AddGossipItemFor(player, MORPH_GOSSIP_MENU_HELLO, MORPH_GOSSIP_OPTION_FELGUARD_WEAPON, GOSSIP_SENDER_MAIN, MORPH_PAGE_START_FELGUARD_WEAPON); } else if (!felguard_weapon.empty()) + { + sorry = false; AddGossipItemFor(player, MORPH_GOSSIP_MENU_HELLO, MORPH_GOSSIP_OPTION_FELGUARD_WEAPON, GOSSIP_SENDER_MAIN, MORPH_PAGE_START_FELGUARD_WEAPON); - else - sorry = true; + } break; case RAISE_DEAD: if (!death_knight_ghoul.empty()) + { + sorry = false; AddGossipItemFor(player, MORPH_GOSSIP_MENU_HELLO, MORPH_GOSSIP_OPTION_POLYMORPH, GOSSIP_SENDER_MAIN, MORPH_PAGE_START_DEATH_KNIGHT_GHOUL); - else - sorry = true; + } break; - default: - sorry = true; } } - else - sorry = true; } if (sorry) @@ -298,7 +316,12 @@ class MorphSummonCreatureScript : public CreatureScript SendGossipMenuFor(player, MORPH_GOSSIP_TEXT_SORRY, creature->GetGUID()); } else + { + if (showNewName && morphSummonNewNameEnabled) + AddGossipItemFor(player, MORPH_GOSSIP_MENU_HELLO, MORPH_GOSSIP_OPTION_NEW_NAME, GOSSIP_SENDER_MAIN, MORPH_NEW_NAME); + SendGossipMenuFor(player, MORPH_GOSSIP_TEXT_HELLO, creature->GetGUID()); + } return true; } @@ -350,13 +373,6 @@ class MorphSummonCreatureScript : public CreatureScript petOrMinion->SetDisplayId(morphId); petOrMinion->SetNativeDisplayId(morphId); - if (petOrMinion->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_WATER_ELEMENTAL) - { - // The size of the water elemental model is not automatically scaled, so needs to be done here - CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(petOrMinion->GetNativeDisplayId()); - petOrMinion->SetObjectScale(0.85f / displayInfo->scale); - } - if (Aura *aura = petOrMinion->AddAura(SUBMERGE, pet)) aura->SetDuration(2000); petOrMinion->CastSpell(pet, SHADOW_SUMMON_VISUAL, true); @@ -372,6 +388,23 @@ class MorphSummonCreatureScript : public CreatureScript AddGossip(player, sender, modelMap, startPage); } } + + void GenerateNewName(Player* player) + { + if (Pet* pet = player->GetPet()) + { + std::string new_name = sObjectMgr->GeneratePetName(pet->GetEntry()); + + if (!new_name.empty()) + { + pet->SetName(new_name); + pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(GameTime::GetGameTime().count())); + + if (player->GetGroup()) + player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); + } + } + } }; class MorphSummonWorldScript : public WorldScript @@ -383,7 +416,9 @@ class MorphSummonWorldScript : public WorldScript void OnBeforeConfigLoad(bool /*reload*/) override { - morphSummonAnnounce = sConfigMgr->GetOption("MorphSummon.Announce", true); + morphSummonEnabled = sConfigMgr->GetOption("MorphSummon.Enabled", true); + morphSummonAnnounce = sConfigMgr->GetOption("MorphSummon.Announce", false); + morphSummonNewNameEnabled = sConfigMgr->GetOption("MorphSummon.NewNameEnabled", true); randomVisualEffectSpells.clear(); std::stringstream stringStream; From 344f1bd171a209fcc686a1bb2e559f7dd1db5c2a Mon Sep 17 00:00:00 2001 From: Stoabrogga Date: Sun, 15 Feb 2026 10:26:22 +0100 Subject: [PATCH 02/10] Reset display IDs if module is disabled --- src/morphsummon.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/src/morphsummon.cpp b/src/morphsummon.cpp index 71ee475..0b56d36 100644 --- a/src/morphsummon.cpp +++ b/src/morphsummon.cpp @@ -23,6 +23,7 @@ std::map death_knight_ghoul; std::map mage_water_elemental; std::list randomVisualEffectSpells; std::list randomMainHandEquip; +std::set defaultGhoulDisplayIds; uint32 minTimeVisualEffect; uint32 maxTimeVisualEffect; bool morphSummonEnabled; @@ -70,6 +71,21 @@ enum MorphSummonSpells SUMMON_WATER_ELEMENTAL = 70908 }; +enum MorphSummonDefaultIds +{ + DISPLAY_ID_IMP = 4449, + DISPLAY_ID_VOIDWALKER = 1132, + DISPLAY_ID_SUCCUBUS = 4162, + DISPLAY_ID_FELHUNTER = 850, + DISPLAY_ID_FELGUARD = 14255, + DISPLAY_ID_GHOUL1 = 24992, + DISPLAY_ID_GHOUL2 = 24993, + DISPLAY_ID_GHOUL3 = 24994, + DISPLAY_ID_GHOUL4 = 24995, + DISPLAY_ID_WATER_ELEMENTAL = 525, + ITEM_ID_FELGUARD_WEAPON = 22199 +}; + enum MorphEffectSpells { SUBMERGE = 53421, @@ -97,12 +113,75 @@ class MorphSummonPlayerScript : public PlayerScript void OnPlayerAfterGuardianInitStatsForLevel(Player* player, Guardian* guardian) override { - if (Pet* pet = guardian->ToPet(); pet && pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_FELGUARD) + if (Pet* pet = guardian->ToPet()) { - if (QueryResult result = CharacterDatabase.Query("SELECT `FelguardItemID` FROM `mod_morphsummon_felguard_weapon` WHERE `PlayerGUIDLow`={}", player->GetGUID().GetCounter())) + if (!morphSummonEnabled) { - Field* fields = result->Fetch(); - pet->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, fields[0].Get()); + switch (pet->GetUInt32Value(UNIT_CREATED_BY_SPELL)) + { + case SUMMON_IMP: + if (pet->GetDisplayId() != DISPLAY_ID_IMP) + { + pet->SetDisplayId(DISPLAY_ID_IMP); + pet->SetNativeDisplayId(DISPLAY_ID_IMP); + } + break; + case SUMMON_VOIDWALKER: + if (pet->GetDisplayId() != DISPLAY_ID_VOIDWALKER) + { + pet->SetDisplayId(DISPLAY_ID_VOIDWALKER); + pet->SetNativeDisplayId(DISPLAY_ID_VOIDWALKER); + } + break; + case SUMMON_SUCCUBUS: + if (pet->GetDisplayId() != DISPLAY_ID_SUCCUBUS) + { + pet->SetDisplayId(DISPLAY_ID_SUCCUBUS); + pet->SetNativeDisplayId(DISPLAY_ID_SUCCUBUS); + } + break; + case SUMMON_FELHUNTER: + if (pet->GetDisplayId() != DISPLAY_ID_FELHUNTER) + { + pet->SetDisplayId(DISPLAY_ID_FELHUNTER); + pet->SetNativeDisplayId(DISPLAY_ID_FELHUNTER); + } + break; + case SUMMON_FELGUARD: + if (pet->GetDisplayId() != DISPLAY_ID_FELGUARD) + { + pet->SetDisplayId(DISPLAY_ID_FELGUARD); + pet->SetNativeDisplayId(DISPLAY_ID_FELGUARD); + pet->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, ITEM_ID_FELGUARD_WEAPON); + } + break; + case RAISE_DEAD: + if (!defaultGhoulDisplayIds.contains(pet->GetDisplayId())) + { + uint32 ghoulDisplayId = Acore::Containers::SelectRandomContainerElement(defaultGhoulDisplayIds); + pet->SetDisplayId(ghoulDisplayId); + pet->SetNativeDisplayId(ghoulDisplayId); + } + break; + case SUMMON_WATER_ELEMENTAL: + if (pet->GetDisplayId() != DISPLAY_ID_WATER_ELEMENTAL) + { + pet->SetDisplayId(DISPLAY_ID_WATER_ELEMENTAL); + pet->SetNativeDisplayId(DISPLAY_ID_WATER_ELEMENTAL); + } + break; + } + } + else + { + if (Pet* pet = guardian->ToPet(); pet && pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_FELGUARD) + { + if (QueryResult result = CharacterDatabase.Query("SELECT `FelguardItemID` FROM `mod_morphsummon_felguard_weapon` WHERE `PlayerGUIDLow`={}", player->GetGUID().GetCounter())) + { + Field* fields = result->Fetch(); + pet->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, fields[0].Get()); + } + } } } } @@ -420,6 +499,14 @@ class MorphSummonWorldScript : public WorldScript morphSummonAnnounce = sConfigMgr->GetOption("MorphSummon.Announce", false); morphSummonNewNameEnabled = sConfigMgr->GetOption("MorphSummon.NewNameEnabled", true); + if (defaultGhoulDisplayIds.empty()) + { + defaultGhoulDisplayIds.emplace(DISPLAY_ID_GHOUL1); + defaultGhoulDisplayIds.emplace(DISPLAY_ID_GHOUL2); + defaultGhoulDisplayIds.emplace(DISPLAY_ID_GHOUL3); + defaultGhoulDisplayIds.emplace(DISPLAY_ID_GHOUL4); + } + randomVisualEffectSpells.clear(); std::stringstream stringStream; std::string delimitedValue; From fae091cecd8cc533f1bc09b836736a0b0bbe5967 Mon Sep 17 00:00:00 2001 From: Stoabrogga Date: Sun, 15 Feb 2026 10:39:16 +0100 Subject: [PATCH 03/10] Bugfix reset Felguard weapon --- src/morphsummon.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/morphsummon.cpp b/src/morphsummon.cpp index 0b56d36..3dd1b95 100644 --- a/src/morphsummon.cpp +++ b/src/morphsummon.cpp @@ -152,6 +152,10 @@ class MorphSummonPlayerScript : public PlayerScript { pet->SetDisplayId(DISPLAY_ID_FELGUARD); pet->SetNativeDisplayId(DISPLAY_ID_FELGUARD); + } + + if (pet->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID) != ITEM_ID_FELGUARD_WEAPON) + { pet->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, ITEM_ID_FELGUARD_WEAPON); } break; From 93e46c4f53571f5f89afb1cf2906b336fc742f5e Mon Sep 17 00:00:00 2001 From: Stoabrogga Date: Mon, 16 Feb 2026 13:53:05 +0100 Subject: [PATCH 04/10] Remove obsolete pet-pointer --- src/morphsummon.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/morphsummon.cpp b/src/morphsummon.cpp index 3dd1b95..a1b099d 100644 --- a/src/morphsummon.cpp +++ b/src/morphsummon.cpp @@ -176,15 +176,12 @@ class MorphSummonPlayerScript : public PlayerScript break; } } - else + else if (pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_FELGUARD) { - if (Pet* pet = guardian->ToPet(); pet && pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_FELGUARD) + if (QueryResult result = CharacterDatabase.Query("SELECT `FelguardItemID` FROM `mod_morphsummon_felguard_weapon` WHERE `PlayerGUIDLow`={}", player->GetGUID().GetCounter())) { - if (QueryResult result = CharacterDatabase.Query("SELECT `FelguardItemID` FROM `mod_morphsummon_felguard_weapon` WHERE `PlayerGUIDLow`={}", player->GetGUID().GetCounter())) - { - Field* fields = result->Fetch(); - pet->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, fields[0].Get()); - } + Field* fields = result->Fetch(); + pet->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, fields[0].Get()); } } } From 1f13024c42ff18d7163417444d8bc084f0f09dfd Mon Sep 17 00:00:00 2001 From: Stoabrogga Date: Mon, 16 Feb 2026 22:18:45 +0100 Subject: [PATCH 05/10] Review feedback --- src/morphsummon.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/morphsummon.cpp b/src/morphsummon.cpp index a1b099d..17b044d 100644 --- a/src/morphsummon.cpp +++ b/src/morphsummon.cpp @@ -4,6 +4,7 @@ #include "Chat.h" #include "Config.h" +#include "GameTime.h" #include "Pet.h" #include "Player.h" #include "ScriptedCreature.h" @@ -11,7 +12,6 @@ #include "ScriptMgr.h" #include "SpellAuras.h" #include "Unit.h" -#include "GameTime.h" std::map warlock_imp; std::map warlock_voidwalker; @@ -155,9 +155,7 @@ class MorphSummonPlayerScript : public PlayerScript } if (pet->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID) != ITEM_ID_FELGUARD_WEAPON) - { pet->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, ITEM_ID_FELGUARD_WEAPON); - } break; case RAISE_DEAD: if (!defaultGhoulDisplayIds.contains(pet->GetDisplayId())) From ce2439633a3edc1511945652ea364338e6754b7f Mon Sep 17 00:00:00 2001 From: Stoabrogga Date: Tue, 17 Feb 2026 17:56:46 +0100 Subject: [PATCH 06/10] Adjust scaling for water elementals --- src/morphsummon.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/morphsummon.cpp b/src/morphsummon.cpp index 17b044d..e86c955 100644 --- a/src/morphsummon.cpp +++ b/src/morphsummon.cpp @@ -174,6 +174,12 @@ class MorphSummonPlayerScript : public PlayerScript break; } } + else if (pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_WATER_ELEMENTAL) + { + // The size of the water elemental model is not automatically scaled, so needs to be done here + CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(pet->GetNativeDisplayId()); + pet->SetObjectScale(0.85f / displayInfo->scale); + } else if (pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_FELGUARD) { if (QueryResult result = CharacterDatabase.Query("SELECT `FelguardItemID` FROM `mod_morphsummon_felguard_weapon` WHERE `PlayerGUIDLow`={}", player->GetGUID().GetCounter())) @@ -186,6 +192,24 @@ class MorphSummonPlayerScript : public PlayerScript } }; +class MorphSummonUnitScript : public UnitScript +{ +public: + MorphSummonUnitScript() : UnitScript("MorphSummonUnitScript", { + UNITHOOK_ON_AURA_REMOVE + }) {} + + void OnAuraRemove(Unit* unit, AuraApplication* /*aurApp*/, AuraRemoveMode /*mode*/) override + { + if (Pet* pet = unit->ToPet(); pet && pet->GetOwner() && pet->GetOwner()->IsPlayer() && pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_WATER_ELEMENTAL) + { + // The size of the water elemental model is not automatically scaled, so needs to be done here after auras are removed + CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(pet->GetNativeDisplayId()); + pet->SetObjectScale(0.85f / displayInfo->scale); + } + } +}; + class MorphSummonCreatureScript : public CreatureScript { public: @@ -578,5 +602,6 @@ void AddMorphSummonScripts() { new MorphSummonWorldScript(); new MorphSummonPlayerScript(); + new MorphSummonUnitScript(); new MorphSummonCreatureScript(); } From 5cc097bf7a127d9c0fe245878ebde27c5ce12900 Mon Sep 17 00:00:00 2001 From: Stoabrogga Date: Tue, 17 Feb 2026 18:05:08 +0100 Subject: [PATCH 07/10] Remove braces --- src/morphsummon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/morphsummon.cpp b/src/morphsummon.cpp index e86c955..7d07427 100644 --- a/src/morphsummon.cpp +++ b/src/morphsummon.cpp @@ -195,9 +195,9 @@ class MorphSummonPlayerScript : public PlayerScript class MorphSummonUnitScript : public UnitScript { public: - MorphSummonUnitScript() : UnitScript("MorphSummonUnitScript", { + MorphSummonUnitScript() : UnitScript("MorphSummonUnitScript", UNITHOOK_ON_AURA_REMOVE - }) {} + ) {} void OnAuraRemove(Unit* unit, AuraApplication* /*aurApp*/, AuraRemoveMode /*mode*/) override { From b6094cd140812a9528ebb6c5884d9386f3b124b4 Mon Sep 17 00:00:00 2001 From: Stoabrogga Date: Wed, 18 Feb 2026 12:43:54 +0100 Subject: [PATCH 08/10] Bugfix MorphSummonUnitScript --- src/morphsummon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/morphsummon.cpp b/src/morphsummon.cpp index 7d07427..19df455 100644 --- a/src/morphsummon.cpp +++ b/src/morphsummon.cpp @@ -195,9 +195,9 @@ class MorphSummonPlayerScript : public PlayerScript class MorphSummonUnitScript : public UnitScript { public: - MorphSummonUnitScript() : UnitScript("MorphSummonUnitScript", + MorphSummonUnitScript() : UnitScript("MorphSummonUnitScript", true, { UNITHOOK_ON_AURA_REMOVE - ) {} + }) {} void OnAuraRemove(Unit* unit, AuraApplication* /*aurApp*/, AuraRemoveMode /*mode*/) override { From 427bdc8f4b62dc8e147d0a0b4ddfb4f6f884c8d5 Mon Sep 17 00:00:00 2001 From: Stoabrogga Date: Wed, 18 Feb 2026 13:26:36 +0100 Subject: [PATCH 09/10] Review feedback --- data/sql/db-world/base/morphsummon.sql | 2 +- src/morphsummon.cpp | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/data/sql/db-world/base/morphsummon.sql b/data/sql/db-world/base/morphsummon.sql index 0eadc3c..e064fce 100644 --- a/data/sql/db-world/base/morphsummon.sql +++ b/data/sql/db-world/base/morphsummon.sql @@ -29,7 +29,7 @@ INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionTex (@MENU_HELLO, 0, 0, 'Choose polymorph', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), (@MENU_HELLO, 1, 0, 'Choose Felguard weapon', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), (@MENU_HELLO, 2, 0, 'Generate new name', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), -(@MENU_SORRY, 0, 0, 'Ah, nevermind.', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), +(@MENU_SORRY, 0, 0, 'Ah, nevermind.', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), (@MENU_CHOICE, 0, 0, 'Back..', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), (@MENU_CHOICE, 1, 4, 'Next..', 0, 0, 0, 0, 0, 0, 0, '', 0, 0), (@MENU_CHOICE, 2, 4, 'Previous..', 0, 0, 0, 0, 0, 0, 0, '', 0, 0); diff --git a/src/morphsummon.cpp b/src/morphsummon.cpp index 19df455..a638c2a 100644 --- a/src/morphsummon.cpp +++ b/src/morphsummon.cpp @@ -177,8 +177,8 @@ class MorphSummonPlayerScript : public PlayerScript else if (pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_WATER_ELEMENTAL) { // The size of the water elemental model is not automatically scaled, so needs to be done here - CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(pet->GetNativeDisplayId()); - pet->SetObjectScale(0.85f / displayInfo->scale); + if (CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(pet->GetNativeDisplayId())) + pet->SetObjectScale(0.85f / displayInfo->scale); } else if (pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_FELGUARD) { @@ -201,11 +201,14 @@ class MorphSummonUnitScript : public UnitScript void OnAuraRemove(Unit* unit, AuraApplication* /*aurApp*/, AuraRemoveMode /*mode*/) override { + if (!morphSummonEnabled) + return; + if (Pet* pet = unit->ToPet(); pet && pet->GetOwner() && pet->GetOwner()->IsPlayer() && pet->GetUInt32Value(UNIT_CREATED_BY_SPELL) == SUMMON_WATER_ELEMENTAL) { // The size of the water elemental model is not automatically scaled, so needs to be done here after auras are removed - CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(pet->GetNativeDisplayId()); - pet->SetObjectScale(0.85f / displayInfo->scale); + if (CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(pet->GetNativeDisplayId())) + pet->SetObjectScale(0.85f / displayInfo->scale); } } }; From 1b7bedffd88b231043a5bae4adcb668b675b05e9 Mon Sep 17 00:00:00 2001 From: Stoabrogga Date: Fri, 20 Feb 2026 17:15:41 +0100 Subject: [PATCH 10/10] Change default for "MorphSummon.NewNameEnabled" to 0 Downward compatibility. If people upgrade to the new version they probably don't want any new gossip options suddenly appearing. --- conf/morphsummon.conf.dist | 2 +- src/morphsummon.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/morphsummon.conf.dist b/conf/morphsummon.conf.dist index ae4666f..4ed2d68 100644 --- a/conf/morphsummon.conf.dist +++ b/conf/morphsummon.conf.dist @@ -14,7 +14,7 @@ MorphSummon.Announce = 0 # Allow new name for demons and ghouls -MorphSummon.NewNameEnabled = 1 +MorphSummon.NewNameEnabled = 0 # Model IDs for the summoned permanent creatures diff --git a/src/morphsummon.cpp b/src/morphsummon.cpp index a638c2a..c65acd8 100644 --- a/src/morphsummon.cpp +++ b/src/morphsummon.cpp @@ -523,7 +523,7 @@ class MorphSummonWorldScript : public WorldScript { morphSummonEnabled = sConfigMgr->GetOption("MorphSummon.Enabled", true); morphSummonAnnounce = sConfigMgr->GetOption("MorphSummon.Announce", false); - morphSummonNewNameEnabled = sConfigMgr->GetOption("MorphSummon.NewNameEnabled", true); + morphSummonNewNameEnabled = sConfigMgr->GetOption("MorphSummon.NewNameEnabled", false); if (defaultGhoulDisplayIds.empty()) {