From 4c3f353b2d72991a7907e461f660e0c4d8662f76 Mon Sep 17 00:00:00 2001 From: Pappons Date: Mon, 1 Jul 2024 12:01:46 +0000 Subject: [PATCH 1/2] Fix: Updated the SQL script to use the create_template_model table Feature: Switched hard-coded spell ids to use spell chains so it picks a more level appropriate spell Feature: Added Thorns to the spell list --- conf/npc_buffer.conf.dist | 15 +++- data/sql/db-world/npc_buffer_00.sql | 9 +- src/npc_buffer.cpp | 132 ++++++++++++---------------- 3 files changed, 75 insertions(+), 81 deletions(-) diff --git a/conf/npc_buffer.conf.dist b/conf/npc_buffer.conf.dist index 14a31f9..345e31d 100644 --- a/conf/npc_buffer.conf.dist +++ b/conf/npc_buffer.conf.dist @@ -44,10 +44,18 @@ Buff.CureRes = 1 Buff.ByLevel = 1 +# +# Buff.MaxLevel +# Description: The highest character level at which buffs are scaled. +# Characters at this level or higher receive the maximum +# strength of buffs. +# + +Buff.MaxLevel = 80 + # # Buff.Spells # Description: Buff Defaults (Leave blank to disable a buff) -# This function is not active if Buff.ByLevel = 1 # # 1. Prayer of Fortitude (48162) # 2. Greater Blessing of Kings (43223) @@ -55,12 +63,13 @@ Buff.ByLevel = 1 # 4. Prayer of Spirit (48074) # 5. Prayer of Shadow Protection (48170) # 6. Arcane Intellect (42995) +# 7. Thorns (53307) # # Fun Stuff # 48612 (Dalron the Controller) # -Buff.Spells = "48162;43223;48469;48074;48170;42995;" +Buff.Spells = "48162;43223;48469;48074;48170;42995;53307;" # # Buff.MessageTimer @@ -90,7 +99,6 @@ BF.P1 = "Come get buffed, taste my stuff, the elven females can't get enuff!" BF.P2 = "She never shook the stars from the swirling cosmos, but she loved good tauren and rode good kodos." BF.P3 = "Mr. Grubbs is the toughest grub around. No doubt about it." BF.P4 = "Those trolls sure now how to dance! I hear they like to party in the mountains of Darkshore." - # # Buff.NumWhispers # Description: How many whispers does the NPC have? @@ -117,6 +125,7 @@ BF.W8 = "Indeed.. %s. The dwarves keep many secrets about that which lies beyond BF.W9 = "A little bit of this.. a dab of that.. ahh.. there we go %s." BF.W10 = "No %s, I never did hear if they found the children that disappeared from Nagrand and Zangarmarsh." + # # Buff.EmoteSpell # Description: The spell cast to get the player's attention diff --git a/data/sql/db-world/npc_buffer_00.sql b/data/sql/db-world/npc_buffer_00.sql index 4fb20ac..b123c54 100644 --- a/data/sql/db-world/npc_buffer_00.sql +++ b/data/sql/db-world/npc_buffer_00.sql @@ -22,8 +22,11 @@ SET -- NPC DELETE FROM `creature_template` WHERE `entry`=@Entry; -INSERT INTO `creature_template` (`entry`, `modelid1`, `name`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `unit_class`, `unit_flags`, `type`, `type_flags`, `RegenHealth`, `flags_extra`, `AiName`, `ScriptName`) VALUES -(@Entry, @Model, @Name, @Title, @Icon, @GossipMenu, @MinLevel, @MaxLevel, @Faction, @NPCFlag, 1, 1.14286, @Scale, @Rank, 1, 2, @Type, @TypeFlags, 1, @FlagsExtra, @AIName, @Script); +INSERT INTO `creature_template` (`entry`, `name`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `unit_class`, `unit_flags`, `type`, `type_flags`, `RegenHealth`, `flags_extra`, `AiName`, `ScriptName`) VALUES +(@Entry, @Name, @Title, @Icon, @GossipMenu, @MinLevel, @MaxLevel, @Faction, @NPCFlag, 1, 1.14286, @Scale, @Rank, 1, 2, @Type, @TypeFlags, 1, @FlagsExtra, @AIName, @Script); + +-- NPC MODEL +INSERT INTO `creature_template_model` (`CreatureID`, `Idx`, `CreatureDisplayID`, `DisplayScale`, `Probability`) VALUES (@Entry, 0, @Model, 1, 1); -- NPC EQUIPPED -- War Axe(14824), Torch @@ -31,7 +34,7 @@ DELETE FROM `creature_equip_template` WHERE `CreatureID`=@Entry AND `ID`=1; INSERT INTO `creature_equip_template` VALUES (@Entry, 1, 1906, 0, 0, 18019); --- creatture_template_movement +-- creature_template_movement DELETE FROM `creature_template_movement` WHERE `CreatureId`=@Entry; INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES (@Entry, 1, 1, 0, 0, 0, 0, NULL); diff --git a/src/npc_buffer.cpp b/src/npc_buffer.cpp index 15aa30a..5cd14c2 100644 --- a/src/npc_buffer.cpp +++ b/src/npc_buffer.cpp @@ -30,6 +30,7 @@ the player using configurable emote options. ### Version ------------------------------------------------------------------------------------------------------------------ +- v2024.07.01 - Fix database script to use creature_template_model table. Updated spell list/scaling code. Added Thorns to spell list - v2019.04.17 - Fix Cure Resurrection Sickness, works now! Courtesy of Poszer and Milestorme - v2019.04.15 - Ported to AzerothCore by gtao725 (https://github.com/gtao725/) - v2019.02.13 - Added phrases/emotes, config options, updated AI @@ -69,6 +70,7 @@ This code and content is released under the [GNU AGPL v3](https://github.com/aze #include "Player.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" +#include "Log.h" static bool BFEnableModule; static bool BFAnnounceModule; @@ -79,6 +81,7 @@ static uint32 BuffNumWhispers; static uint32 BuffMessageTimer; static uint32 BuffEmoteSpell; static uint32 BuffEmoteCommand; +static uint32 MaxLevel = 80; class BufferConfig : public WorldScript { @@ -97,6 +100,8 @@ class BufferConfig : public WorldScript BuffEmoteSpell = sConfigMgr->GetOption("Buff.EmoteSpell", 44940); BuffEmoteCommand = sConfigMgr->GetOption("Buff.EmoteCommand", 3); + MaxLevel = sConfigMgr->GetOption("Buff.MaxLevel", 80); + // Enforce Min/Max Time if (BuffMessageTimer != 0) { @@ -128,6 +133,52 @@ class buff_npc : public CreatureScript public: buff_npc() : CreatureScript("buff_npc") {} + /** Get the most level-appropriate spell from the chain, + * based on character level compared to max level (MaxLevel) */ + static uint GetSpellForLevel(uint32 spell_id, Player *player) + { + uint32 level = player->getLevel(); + + // if the character is level max level or higher, return the last spell in the chain + if (level >= MaxLevel) + { + return sSpellMgr->GetLastSpellInChain(spell_id); + } + + uint32 first_spell = sSpellMgr->GetFirstSpellInChain(spell_id); + uint32 next_spell = first_spell; + uint32 number_of_spells_in_chain = 0; + for (; next_spell; next_spell = sSpellMgr->GetNextSpellInChain(next_spell)) + { + number_of_spells_in_chain++; + } + + // if the chain is empty, return the first spell + if (number_of_spells_in_chain == 0) + { + LOG_WARN("module.buffernpc", "Unable to find a spell chain for spell with id {}", spell_id); + return first_spell; + } + + // if the chain has only one spell, return that spell + if (number_of_spells_in_chain == 1) + { + return first_spell; + } + + // if the chain has more than one spell, calculate the level-appropriate spell + uint32 spell_index = (level * number_of_spells_in_chain) / MaxLevel; + uint32 spell = first_spell; + LOG_DEBUG("module.buffernpc", "{}, level {}, gets spell {} of {} from spell {}", player->GetName(), level, (spell_index+1), number_of_spells_in_chain, spell_id); + for (uint32 i = 0; i < spell_index; i++) + { + // traverse to the level-appropriate spell + spell = sSpellMgr->GetNextSpellInChain(spell); + } + + return spell; + } + static bool replace(std::string &str, const std::string &from, const std::string &to) { size_t start_pos = str.find(from); @@ -184,7 +235,7 @@ class buff_npc : public CreatureScript // Who are we dealing with? std::string CreatureWhisper = "Init"; std::string PlayerName = player->GetName(); - uint32 PlayerLevel = player->getLevel(); + std::vector vecBuffChainSizes = {}; // Store Buff IDs std::vector vecBuffs = {}; @@ -206,80 +257,12 @@ class buff_npc : public CreatureScript // Are we buffing based on level if (BuffByLevel == true) { - // Apply (10-19, 20-29, ..., 70-79, 80) - if (PlayerLevel < 10) - { - // Dish out the buffs - player->CastSpell(player, 21562, true); // Prayer of Fortitude (Rank 1) - player->CastSpell(player, 1126, true); // Mark of the Wild (Rank 1) - player->CastSpell(player, 27683, true); // Prayer of Shadow Protection (Rank 1) - } // 1-9 - else if (PlayerLevel >= 10 && PlayerLevel < 20) - { - player->CastSpell(player, 21562, true); // Prayer of Fortitude (Rank 1) - player->CastSpell(player, 1126, true); // Mark of the Wild (Rank 1) - player->CastSpell(player, 27683, true); // Prayer of Shadow Protection (Rank 1) - } // 10-19 - else if (PlayerLevel >= 20 && PlayerLevel < 30) - { - player->CastSpell(player, 21562, true); // Prayer of Fortitude (Rank 1) - player->CastSpell(player, 1126, true); // Mark of the Wild (Rank 1) - player->CastSpell(player, 27683, true); // Prayer of Shadow Protection (Rank 1) - player->CastSpell(player, 13326, true); // Arcane Intellect (Rank 1) - } // 20-29 - else if (PlayerLevel >= 30 && PlayerLevel < 40) - { - player->CastSpell(player, 21562, true); // Prayer of Fortitude (Rank 1) - player->CastSpell(player, 25898, true); // Greater Blessing of Kings (Rank 1) - player->CastSpell(player, 1126, true); // Mark of the Wild (Rank 1) - player->CastSpell(player, 27681, true); // Prayer of Spirit (Rank 1) - player->CastSpell(player, 27683, true); // Prayer of Shadow Protection (Rank 1) - player->CastSpell(player, 13326, true); // Arcane Intellect (Rank 1) - } // 30-39 - else if (PlayerLevel >= 40 && PlayerLevel < 50) - { - player->CastSpell(player, 21562, true); // Prayer of Fortitude (Rank 1) - player->CastSpell(player, vecBuffs[2], true); // Mark of the Wild(48469) - player->CastSpell(player, 27681, true); // Prayer of Spirit (Rank 1) - player->CastSpell(player, vecBuffs[4], true); // Prayer of Shadow Protection(48170) - player->CastSpell(player, 13326, true); // Arcane Intellect (Rank 1) - } // 40-49 - else if (PlayerLevel >= 50 && PlayerLevel < 60) - { - player->CastSpell(player, vecBuffs[0], true); // Prayer of Fortitude(48162) - player->CastSpell(player, vecBuffs[1], true); // Greater Blessing of Kings(43223) - player->CastSpell(player, vecBuffs[2], true); // Mark of the Wild(48469) - player->CastSpell(player, vecBuffs[3], true); // Prayer of Spirit(48074) - player->CastSpell(player, vecBuffs[4], true); // Prayer of Shadow Protection(48170) - player->CastSpell(player, vecBuffs[5], true); // Arcane Intellect(42995) - } // 50-59 - else if (PlayerLevel >= 60 && PlayerLevel < 70) - { - player->CastSpell(player, vecBuffs[0], true); // Prayer of Fortitude(48162) - player->CastSpell(player, vecBuffs[1], true); // Greater Blessing of Kings(43223) - player->CastSpell(player, vecBuffs[2], true); // Mark of the Wild(48469) - player->CastSpell(player, vecBuffs[3], true); // Prayer of Spirit(48074) - player->CastSpell(player, vecBuffs[4], true); // Prayer of Shadow Protection(48170) - player->CastSpell(player, vecBuffs[5], true); // Arcane Intellect(42995) - } // 60-69 - else if (PlayerLevel >= 70 && PlayerLevel < 80) - { - player->CastSpell(player, vecBuffs[0], true); // Prayer of Fortitude(48162) - player->CastSpell(player, vecBuffs[1], true); // Greater Blessing of Kings(43223) - player->CastSpell(player, vecBuffs[2], true); // Mark of the Wild(48469) - player->CastSpell(player, vecBuffs[3], true); // Prayer of Spirit(48074) - player->CastSpell(player, vecBuffs[4], true); // Prayer of Shadow Protection(48170) - player->CastSpell(player, vecBuffs[5], true); // Arcane Intellect(42995) - } // 70-79 - else + for (std::vector::const_iterator itr = vecBuffs.begin(); itr != vecBuffs.end(); itr++) { - player->CastSpell(player, vecBuffs[0], true); // Prayer of Fortitude (48162) - player->CastSpell(player, vecBuffs[1], true); // Greater Blessing of Kings (43223) - player->CastSpell(player, vecBuffs[2], true); // Mark of the Wild (48469) - player->CastSpell(player, vecBuffs[3], true); // Prayer of Spirit (48074) - player->CastSpell(player, vecBuffs[4], true); // Prayer of Shadow Protection (48170) - player->CastSpell(player, vecBuffs[5], true); // Arcane Intellect (42995) - } // LEVEL 80 + uint32 spell_id = *itr; // get the spell id from the list of spells + uint32 spell = GetSpellForLevel(spell_id, player); // get the level-appropriate spell + player->CastSpell(player, spell, true); // cast the buff + } } else { @@ -292,7 +275,6 @@ class buff_npc : public CreatureScript // Choose and speak a random phrase to the player // Phrases are stored in the config file - if (BuffNumWhispers > 0) { creature->Whisper(PickWhisper(PlayerName).c_str(), LANG_UNIVERSAL, player); From f34c1de05bf0d8b05d724fc6789738e5c8eb7f05 Mon Sep 17 00:00:00 2001 From: Pappons Date: Mon, 1 Jul 2024 18:39:43 +0000 Subject: [PATCH 2/2] Removed unused variable --- src/npc_buffer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/npc_buffer.cpp b/src/npc_buffer.cpp index 5cd14c2..9357188 100644 --- a/src/npc_buffer.cpp +++ b/src/npc_buffer.cpp @@ -134,7 +134,8 @@ class buff_npc : public CreatureScript buff_npc() : CreatureScript("buff_npc") {} /** Get the most level-appropriate spell from the chain, - * based on character level compared to max level (MaxLevel) */ + * based on character level compared to max level (MaxLevel) + * */ static uint GetSpellForLevel(uint32 spell_id, Player *player) { uint32 level = player->getLevel(); @@ -235,7 +236,6 @@ class buff_npc : public CreatureScript // Who are we dealing with? std::string CreatureWhisper = "Init"; std::string PlayerName = player->GetName(); - std::vector vecBuffChainSizes = {}; // Store Buff IDs std::vector vecBuffs = {};