#include #include "Log.h" #include "Config.h" #include "ScriptMgr.h" #include "Unit.h" #include "Player.h" #include "Pet.h" #include "Map.h" #include "Group.h" #include "InstanceScript.h" #include "Chat.h" #include #include bool SoloCraftEnable = 1; bool SoloCraftAnnounceModule = 1; bool SoloCraftDebuffEnable = 1; bool SolocraftXPBalEnabled = 1; bool SolocraftXPEnabled = 1; bool SolocraftNoXPFlag = 0; float SoloCraftSpellMult = 1.0; float SoloCraftStatsMult = 100.0; float SoloCraftXPMod = 1.0; uint32 SolocraftLevelDiff = 1; uint32 SolocraftDungeonLevel = 1; std::unordered_map classes; std::unordered_map dungeons; std::unordered_map diff_Multiplier; std::unordered_map diff_Multiplier_Heroics; float D5 = 1.0; float D10 = 1.0; float D25 = 1.0; float D40 = 1.0; float D649H10 = 1.0; float D649H25 = 1.0; class SolocraftConfig : public WorldScript { public: SolocraftConfig() : WorldScript("SolocraftConfig") {} void OnBeforeConfigLoad(bool reload) override { if (!reload) { // Load Configuration Settings SetInitialWorldSettings(); } } // Load Configuration Settings void SetInitialWorldSettings() { SoloCraftEnable = sConfigMgr->GetOption("Solocraft.Enable", 1); SoloCraftAnnounceModule = sConfigMgr->GetOption("Solocraft.Announce", 1); //Balancing SoloCraftDebuffEnable = sConfigMgr->GetOption("SoloCraft.Debuff.Enable", 1); SoloCraftSpellMult = sConfigMgr->GetOption("SoloCraft.Spellpower.Mult", 2.5); SoloCraftStatsMult = sConfigMgr->GetOption("SoloCraft.Stats.Mult", 100.0); classes = { {1, sConfigMgr->GetOption("SoloCraft.WARRIOR", 100) }, {2, sConfigMgr->GetOption("SoloCraft.PALADIN", 100) }, {3, sConfigMgr->GetOption("SoloCraft.HUNTER", 100) }, {4, sConfigMgr->GetOption("SoloCraft.ROGUE", 100) }, {5, sConfigMgr->GetOption("SoloCraft.PRIEST", 100) }, {6, sConfigMgr->GetOption("SoloCraft.DEATH_KNIGHT", 100) }, {7, sConfigMgr->GetOption("SoloCraft.SHAMAN", 100) }, {8, sConfigMgr->GetOption("SoloCraft.MAGE", 100) }, {9, sConfigMgr->GetOption("SoloCraft.WARLOCK", 100) }, {11, sConfigMgr->GetOption("SoloCraft.DRUID", 100) }, }; //XP Enabled SolocraftXPEnabled = sConfigMgr->GetOption("Solocraft.XP.Enabled", 1); //XP Balancing SolocraftXPBalEnabled = sConfigMgr->GetOption("Solocraft.XPBal.Enabled", 1); //Level Thresholds SolocraftLevelDiff = sConfigMgr->GetOption("Solocraft.Max.Level.Diff", 10); //Catch All Dungeon Level Threshold SolocraftDungeonLevel = sConfigMgr->GetOption("Solocraft.Dungeon.Level", 80); // Dungeon Base Level dungeons = { // Wow Classic {33, sConfigMgr->GetOption("Solocraft.ShadowfangKeep.Level", 15) }, {34, sConfigMgr->GetOption("Solocraft.Stockades.Level", 22) }, {36, sConfigMgr->GetOption("Solocraft.Deadmines.Level", 18) }, {43, sConfigMgr->GetOption("Solocraft.WailingCaverns.Level", 17) }, {47, sConfigMgr->GetOption("Solocraft.RazorfenKraulInstance.Level", 30) }, {48, sConfigMgr->GetOption("Solocraft.Blackfathom.Level", 20) }, {70, sConfigMgr->GetOption("Solocraft.Uldaman.Level", 40) }, {90, sConfigMgr->GetOption("Solocraft.GnomeragonInstance.Level", 24) }, {109, sConfigMgr->GetOption("Solocraft.SunkenTemple.Level", 50) }, {129, sConfigMgr->GetOption("Solocraft.RazorfenDowns.Level", 40) }, {189, sConfigMgr->GetOption("Solocraft.MonasteryInstances.Level", 35) }, // Scarlet Monastery {209, sConfigMgr->GetOption("Solocraft.TanarisInstance.Level", 44) }, // Zul'Farrak {229, sConfigMgr->GetOption("Solocraft.BlackRockSpire.Level", 55) }, {230, sConfigMgr->GetOption("Solocraft.BlackrockDepths.Level", 50) }, {249, sConfigMgr->GetOption("Solocraft.OnyxiaLairInstance.Level", 60) }, {289, sConfigMgr->GetOption("Solocraft.SchoolofNecromancy.Level", 55) }, // Scholomance {309, sConfigMgr->GetOption("Solocraft.Zul'gurub.Level", 60) }, {329, sConfigMgr->GetOption("Solocraft.Stratholme.Level", 55) }, {349, sConfigMgr->GetOption("Solocraft.Mauradon.Level", 48) }, {389, sConfigMgr->GetOption("Solocraft.OrgrimmarInstance.Level", 15) }, // Ragefire Chasm {409, sConfigMgr->GetOption("Solocraft.MoltenCore.Level", 60) }, {429, sConfigMgr->GetOption("Solocraft.DireMaul.Level", 48) }, {469, sConfigMgr->GetOption("Solocraft.BlackwingLair.Level", 40) }, {509, sConfigMgr->GetOption("Solocraft.AhnQiraj.Level", 60) }, // Ruins of Ahn'Qiraj {531, sConfigMgr->GetOption("Solocraft.AhnQirajTemple.Level", 60) }, // BC Instances {269, sConfigMgr->GetOption("Solocraft.CavernsOfTime.Level", 68) }, // The Black Morass {532, sConfigMgr->GetOption("Solocraft.Karazahn.Level", 68) }, {534, sConfigMgr->GetOption("Solocraft.HyjalPast.Level", 70) }, // The Battle for Mount Hyjal - Hyjal Summit {540, sConfigMgr->GetOption("Solocraft.HellfireMilitary.Level", 68) }, // The Shattered Halls {542, sConfigMgr->GetOption("Solocraft.HellfireDemon.Level", 68) }, // The Blood Furnace {543, sConfigMgr->GetOption("Solocraft.HellfireRampart.Level", 68) }, {544, sConfigMgr->GetOption("Solocraft.HellfireRaid.Level", 68) }, // Magtheridon's Lair {545, sConfigMgr->GetOption("Solocraft.CoilfangPumping.Level", 68) }, // The Steamvault {546, sConfigMgr->GetOption("Solocraft.CoilfangMarsh.Level", 68) }, // The Underbog {547, sConfigMgr->GetOption("Solocraft.CoilfangDraenei.Level", 68) }, // The Slavepens {548, sConfigMgr->GetOption("Solocraft.CoilfangRaid.Level", 70) }, // Serpentshrine Cavern {550, sConfigMgr->GetOption("Solocraft.TempestKeepRaid.Level", 70) }, // The Eye {552, sConfigMgr->GetOption("Solocraft.TempestKeepArcane.Level", 68) }, // The Arcatraz {553, sConfigMgr->GetOption("Solocraft.TempestKeepAtrium.Level", 68) }, // The Botanica {554, sConfigMgr->GetOption("Solocraft.TempestKeepFactory.Level", 68) }, // The Mechanar {555, sConfigMgr->GetOption("Solocraft.AuchindounShadow.Level", 68) }, // Shadow Labyrinth {556, sConfigMgr->GetOption("Solocraft.AuchindounDemon.Level", 68) }, // Sethekk Halls {557, sConfigMgr->GetOption("Solocraft.AuchindounEthereal.Level", 68) }, // Mana-Tombs {558, sConfigMgr->GetOption("Solocraft.AuchindounDraenei.Level", 68) }, // Auchenai Crypts {560, sConfigMgr->GetOption("Solocraft.HillsbradPast.Level", 68) }, // Old Hillsbrad Foothills {564, sConfigMgr->GetOption("Solocraft.BlackTemple.Level", 70) }, {565, sConfigMgr->GetOption("Solocraft.GruulsLair.Level", 70) }, {568, sConfigMgr->GetOption("Solocraft.ZulAman.Level", 68) }, {580, sConfigMgr->GetOption("Solocraft.SunwellPlateau.Level", 70) }, {585, sConfigMgr->GetOption("Solocraft.Sunwell5ManFix.Level", 68) }, // Magister's Terrace // WOTLK Instances {533, sConfigMgr->GetOption("Solocraft.StratholmeRaid.Level", 78) }, // Naxxramas {574, sConfigMgr->GetOption("Solocraft.Valgarde70.Level", 78) }, // Utgarde Keep {575, sConfigMgr->GetOption("Solocraft.UtgardePinnacle.Level", 78) }, {576, sConfigMgr->GetOption("Solocraft.Nexus70.Level", 78) }, // The Nexus {578, sConfigMgr->GetOption("Solocraft.Nexus80.Level", 78) }, // The Occulus {595, sConfigMgr->GetOption("Solocraft.StratholmeCOT.Level", 78) }, // The Culling of Stratholme {599, sConfigMgr->GetOption("Solocraft.Ulduar70.Level", 78) }, // Halls of Stone {600, sConfigMgr->GetOption("Solocraft.DrakTheronKeep.Level", 78) }, // Drak'Tharon Keep {601, sConfigMgr->GetOption("Solocraft.Azjol_Uppercity.Level", 78) }, // Azjol-Nerub {602, sConfigMgr->GetOption("Solocraft.Ulduar80.Level", 78) }, // Halls of Lighting {603, sConfigMgr->GetOption("Solocraft.UlduarRaid.Level", 80) }, // Ulduar {604, sConfigMgr->GetOption("Solocraft.GunDrak.Level", 78) }, {608, sConfigMgr->GetOption("Solocraft.DalaranPrison.Level", 78) }, // Violet Hold {615, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsBlack.Level", 80) }, // The Obsidian Sanctum {616, sConfigMgr->GetOption("Solocraft.NexusRaid.Level", 80) }, // The Eye of Eternity {619, sConfigMgr->GetOption("Solocraft.Azjol_LowerCity.Level", 78) }, // Ahn'kahet: The Old Kingdom {631, sConfigMgr->GetOption("Solocraft.IcecrownCitadel.Level", 80) }, // Icecrown Citadel {632, sConfigMgr->GetOption("Solocraft.IcecrownCitadel5Man.Level", 78) }, // The Forge of Souls {649, sConfigMgr->GetOption("Solocraft.ArgentTournamentRaid.Level", 80) }, // Trial of the Crusader {650, sConfigMgr->GetOption("Solocraft.ArgentTournamentDungeon.Level", 80) }, // Trial of the Champion {658, sConfigMgr->GetOption("Solocraft.QuarryOfTears.Level", 78) }, // Pit of Saron {668, sConfigMgr->GetOption("Solocraft.HallsOfReflection.Level", 78) }, // Halls of Reflection {724, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsRed.Level", 80) }, // The Ruby Sanctum }; // Dungeon Difficulty | Catch alls D5 = sConfigMgr->GetOption("Solocraft.Dungeon", 5.0); D10 = sConfigMgr->GetOption("Solocraft.Heroic", 10.0); D25 = sConfigMgr->GetOption("Solocraft.Raid25", 25.0); D40 = sConfigMgr->GetOption("Solocraft.Raid40", 40.0); diff_Multiplier = { // WOW Classic Instances {33, sConfigMgr->GetOption("Solocraft.ShadowfangKeep", 5.0) }, {34, sConfigMgr->GetOption("Solocraft.Stockades", 5.0) }, {36, sConfigMgr->GetOption("Solocraft.Deadmines", 5.0) }, {43, sConfigMgr->GetOption("Solocraft.WailingCaverns", 5.0) }, {47, sConfigMgr->GetOption("Solocraft.RazorfenKraulInstance", 5.0) }, {48, sConfigMgr->GetOption("Solocraft.Blackfathom", 5.0) }, {70, sConfigMgr->GetOption("Solocraft.Uldaman", 5.0) }, {90, sConfigMgr->GetOption("Solocraft.GnomeragonInstance", 5.0) }, {109, sConfigMgr->GetOption("Solocraft.SunkenTemple", 5.0) }, {129, sConfigMgr->GetOption("Solocraft.RazorfenDowns", 5.0) }, {189, sConfigMgr->GetOption("Solocraft.MonasteryInstances", 5.0) }, // Scarlet {209, sConfigMgr->GetOption("Solocraft.TanarisInstance", 5.0) }, // Zul'Farrak {229, sConfigMgr->GetOption("Solocraft.BlackRockSpire", 10.0) }, {230, sConfigMgr->GetOption("Solocraft.BlackrockDepths", 5.0) }, {249, sConfigMgr->GetOption("Solocraft.OnyxiaLairInstance", 40.0) }, {289, sConfigMgr->GetOption("Solocraft.SchoolofNecromancy", 5.0) }, // Scholo {309, sConfigMgr->GetOption("Solocraft.Zul'gurub", 20.0) }, {329, sConfigMgr->GetOption("Solocraft.Stratholme", 5.0) }, {349, sConfigMgr->GetOption("Solocraft.Mauradon", 5.0) }, {389, sConfigMgr->GetOption("Solocraft.OrgrimmarInstance", 5.0) }, // Ragefire {409, sConfigMgr->GetOption("Solocraft.MoltenCore", 40.0) }, {429, sConfigMgr->GetOption("Solocraft.DireMaul", 5.0) }, {469, sConfigMgr->GetOption("Solocraft.BlackwingLair", 40.0) }, {509, sConfigMgr->GetOption("Solocraft.AhnQiraj", 20.0) }, {531, sConfigMgr->GetOption("Solocraft.AhnQirajTemple", 40.0) }, // BC Instances {269, sConfigMgr->GetOption("Solocraft.CavernsOfTime", 5.0) }, // Black Morass {532, sConfigMgr->GetOption("Solocraft.Karazahn", 10.0) }, {534, sConfigMgr->GetOption("Solocraft.HyjalPast", 25.0) }, // Mount Hyjal {540, sConfigMgr->GetOption("Solocraft.HellfireMilitary", 5.0) }, // The Shattered Halls {542, sConfigMgr->GetOption("Solocraft.HellfireDemon", 5.0) }, // The Blood Furnace {543, sConfigMgr->GetOption("Solocraft.HellfireRampart", 5.0) }, {544, sConfigMgr->GetOption("Solocraft.HellfireRaid", 25.0) }, // Magtheridon's Lair {545, sConfigMgr->GetOption("Solocraft.CoilfangPumping", 5.0) }, // The Steamvault {546, sConfigMgr->GetOption("Solocraft.CoilfangMarsh", 5.0) }, // The Underbog {547, sConfigMgr->GetOption("Solocraft.CoilfangDraenei", 5.0) }, // The Slavepens {548, sConfigMgr->GetOption("Solocraft.CoilfangRaid", 25.0) }, // Serpentshrine Cavern {550, sConfigMgr->GetOption("Solocraft.TempestKeepRaid", 25.0) }, // The Eye {552, sConfigMgr->GetOption("Solocraft.TempestKeepArcane", 5.0) }, // The Arcatraz {553, sConfigMgr->GetOption("Solocraft.TempestKeepAtrium", 5.0) }, // The Botanica {554, sConfigMgr->GetOption("Solocraft.TempestKeepFactory", 5.0) }, // The Mechanar {555, sConfigMgr->GetOption("Solocraft.AuchindounShadow", 5.0) }, // Shadow Labyrinth {556, sConfigMgr->GetOption("Solocraft.AuchindounDemon", 5.0) }, // Sethekk Halls {557, sConfigMgr->GetOption("Solocraft.AuchindounEthereal", 5.0) }, // Mana-Tombs {558, sConfigMgr->GetOption("Solocraft.AuchindounDraenei", 5.0) }, // Auchenai Crypts {560, sConfigMgr->GetOption("Solocraft.HillsbradPast", 5.0) }, // Old Hillsbrad Foothills {564, sConfigMgr->GetOption("Solocraft.BlackTemple", 25.0) }, {565, sConfigMgr->GetOption("Solocraft.GruulsLair", 25.0) }, {568, sConfigMgr->GetOption("Solocraft.ZulAman", 5.0) }, {580, sConfigMgr->GetOption("Solocraft.SunwellPlateau", 25.0) }, {585, sConfigMgr->GetOption("Solocraft.Sunwell5ManFix", 5.0) }, // Magister's Terrace // WOTLK Instances {533, sConfigMgr->GetOption("Solocraft.StratholmeRaid", 10.0) }, // Nax 10 {574, sConfigMgr->GetOption("Solocraft.Valgarde70", 5.0) }, // Utgarde Keep {575, sConfigMgr->GetOption("Solocraft.UtgardePinnacle", 5.0) }, {576, sConfigMgr->GetOption("Solocraft.Nexus70", 5.0) }, // The Nexus {578, sConfigMgr->GetOption("Solocraft.Nexus80", 5.0) }, // The Occulus {595, sConfigMgr->GetOption("Solocraft.StratholmeCOT", 5.0) }, // The Culling of Stratholme {599, sConfigMgr->GetOption("Solocraft.Ulduar70", 5.0) }, // Halls of Stone {600, sConfigMgr->GetOption("Solocraft.DrakTheronKeep", 5.0) }, // Drak'Tharon Keep {601, sConfigMgr->GetOption("Solocraft.Azjol_Uppercity", 5.0) }, // Azjol-Nerub {602, sConfigMgr->GetOption("Solocraft.Ulduar80", 5.0) }, // Halls of Lighting {603, sConfigMgr->GetOption("Solocraft.UlduarRaid", 10.0) }, // Ulduar 10 {604, sConfigMgr->GetOption("Solocraft.GunDrak", 5.0) }, {608, sConfigMgr->GetOption("Solocraft.DalaranPrison", 5.0) }, // Violet Hold {615, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsBlack", 10.0) }, // The Obsidian Sanctum 10 {616, sConfigMgr->GetOption("Solocraft.NexusRaid", 10.0) }, // The Eye of Eternity 10 {619, sConfigMgr->GetOption("Solocraft.Azjol_LowerCity", 5.0) }, // Ahn'kahet: The Old Kingdom {631, sConfigMgr->GetOption("Solocraft.IcecrownCitadel", 10.0) }, // Icecrown Citadel 10 {632, sConfigMgr->GetOption("Solocraft.IcecrownCitadel5Man", 5.0) }, // The Forge of Souls {649, sConfigMgr->GetOption("Solocraft.ArgentTournamentRaid", 10.0) }, // Trial of the Crusader 10 {650, sConfigMgr->GetOption("Solocraft.ArgentTournamentDungeon", 5.0) }, // Trial of the Champion {658, sConfigMgr->GetOption("Solocraft.QuarryOfTears", 5.0) }, // Pit of Saron {668, sConfigMgr->GetOption("Solocraft.HallsOfReflection", 5.0) }, // Halls of Reflection {724, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsRed", 10.0) }, // The Ruby Sanctum 10 }; // Heroics diff_Multiplier_Heroics = { // BC Instances Heroics {269, sConfigMgr->GetOption("Solocraft.CavernsOfTimeH", 5.0) }, // Black Morass H {540, sConfigMgr->GetOption("Solocraft.HellfireMilitaryH", 5.0) }, // The Shattered Halls H {542, sConfigMgr->GetOption("Solocraft.HellfireDemonH", 5.0) }, // The Blood Furnace H {543, sConfigMgr->GetOption("Solocraft.HellfireRampartH", 5.0) }, // Heroic {545, sConfigMgr->GetOption("Solocraft.CoilfangPumpingH", 5.0) }, // The Steamvault {546, sConfigMgr->GetOption("Solocraft.CoilfangMarshH", 5.0) }, // The Underbog {547, sConfigMgr->GetOption("Solocraft.CoilfangDraeneiH", 5.0) }, // The Slavepens H {552, sConfigMgr->GetOption("Solocraft.TempestKeepArcaneH", 5.0) }, // The Arcatraz H {553, sConfigMgr->GetOption("Solocraft.TempestKeepAtriumH", 5.0) }, // The Botanica H {554, sConfigMgr->GetOption("Solocraft.TempestKeepFactoryH", 5.0) }, // The Mechanar H {555, sConfigMgr->GetOption("Solocraft.AuchindounShadowH", 5.0) }, // Shadow Labyrinth H {556, sConfigMgr->GetOption("Solocraft.AuchindounDemonH", 5.0) }, // Sethekk Halls H {557, sConfigMgr->GetOption("Solocraft.AuchindounEtherealH", 5.0) }, // Mana-Tombs H {558, sConfigMgr->GetOption("Solocraft.AuchindounDraeneiH", 5.0) }, // Auchenai Crypts H {560, sConfigMgr->GetOption("Solocraft.HillsbradPastH", 5.0) }, // Old Hillsbrad Foothills H {568, sConfigMgr->GetOption("Solocraft.ZulAmanH", 5.0) }, // Zul'Aman H {585, sConfigMgr->GetOption("Solocraft.Sunwell5ManFixH", 5.0) }, // Magister's Terrace H // WOTLK Instances Heroics {533, sConfigMgr->GetOption("Solocraft.StratholmeRaidH", 25.0) }, // Naxxramas 25 {574, sConfigMgr->GetOption("Solocraft.Valgarde70H", 5.0) }, // Utgarde Keep H {575, sConfigMgr->GetOption("Solocraft.UtgardePinnacleH", 5.0) }, // Utgarde Pinnacle H {576, sConfigMgr->GetOption("Solocraft.Nexus70H", 5.0) }, // The Nexus H {578, sConfigMgr->GetOption("Solocraft.Nexus80H", 5.0) }, // The Occulus H {595, sConfigMgr->GetOption("Solocraft.StratholmeCOTH", 5.0) }, // The Culling of Stratholme H {599, sConfigMgr->GetOption("Solocraft.Ulduar70H", 5.0) }, // Halls of Stone H {600, sConfigMgr->GetOption("Solocraft.DrakTheronKeepH", 5.0) }, // Drak'Tharon Keep H {601, sConfigMgr->GetOption("Solocraft.Azjol_UppercityH", 5.0) }, // Azjol-Nerub H {602, sConfigMgr->GetOption("Solocraft.Ulduar80H", 5.0) }, // Halls of Lighting H {603, sConfigMgr->GetOption("Solocraft.UlduarRaidH", 25.0) }, // Ulduar 25 {604, sConfigMgr->GetOption("Solocraft.GunDrakH", 5.0) }, // Gundrak H {608, sConfigMgr->GetOption("Solocraft.DalaranPrisonH", 5.0) }, // Violet Hold H {615, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsBlackH", 25.0) }, // The Obsidian Sanctum 25 {616, sConfigMgr->GetOption("Solocraft.NexusRaidH", 25.0) }, // The Eye of Eternity 25 {619, sConfigMgr->GetOption("Solocraft.Azjol_LowerCityH", 5.0) }, // Ahn'kahet: The Old Kingdom H {631, sConfigMgr->GetOption("Solocraft.IcecrownCitadelH", 25.0) }, // Icecrown Citadel 25 {632, sConfigMgr->GetOption("Solocraft.IcecrownCitadel5ManH", 5.0) }, // The Forge of Souls {649, sConfigMgr->GetOption("Solocraft.ArgentTournamentRaidH", 25.0) }, // Trial of the Crusader 25 {650, sConfigMgr->GetOption("Solocraft.ArgentTournamentDungeonH", 5.0) }, // Trial of the Champion H {658, sConfigMgr->GetOption("Solocraft.QuarryOfTearsH", 5.0) }, // Pit of Saron H {668, sConfigMgr->GetOption("Solocraft.HallsOfReflectionH", 5.0) }, // Halls of Reflection H {724, sConfigMgr->GetOption("Solocraft.ChamberOfAspectsRedH", 25.0) }, // The Ruby Sanctum 25 }; //Unique Raids beyond the heroic and normal versions of themselves D649H10 = sConfigMgr->GetOption("Solocraft.ArgentTournamentRaidH10", 10.0); //Trial of the Crusader 10 Heroic D649H25 = sConfigMgr->GetOption("Solocraft.ArgentTournamentRaidH25", 25.0); //Trial of the Crusader 25 Heroic } }; class SolocraftAnnounce : public PlayerScript { public: SolocraftAnnounce() : PlayerScript("SolocraftAnnounce") {} void OnLogin(Player* player) override { if (SoloCraftEnable && SoloCraftAnnounceModule) { ChatHandler(player->GetSession()).SendSysMessage("This server is running the |cff4CFF00SoloCraft |rmodule."); } } void OnLogout(Player* player) override { QueryResult result = CharacterDatabase.Query("SELECT `GUID` FROM `custom_solocraft_character_stats` WHERE `GUID`={}", player->GetGUID().GetCounter()); if (result) { //Remove database entry as the player has logged out CharacterDatabase.Execute("DELETE FROM `custom_solocraft_character_stats` WHERE `GUID`={}", player->GetGUID().GetCounter()); } } void OnGiveXP(Player* /*player*/, uint32& amount, Unit* /*victim*/, uint8 /*xpSource*/) override { if (SolocraftXPBalEnabled) { // Decrease Experience based on number of players and difficulty of instance (0 to 100%) amount = uint32(amount * SoloCraftXPMod); } } }; class SolocraftPlayerInstanceHandler : public PlayerScript { public: SolocraftPlayerInstanceHandler() : PlayerScript("SolocraftPlayerInstanceHandler") {} void OnMapChanged(Player* player) override { if (sConfigMgr->GetOption("Solocraft.Enable", true)) { Map* map = player->GetMap(); float difficulty = CalculateDifficulty(map); uint32 dunLevel = CalculateDungeonLevel(map); uint32 numInGroup = GetNumInGroup(player); uint32 classBalance = GetClassBalance(player); ApplyBuffs(player, map, difficulty, dunLevel, numInGroup, classBalance); } } // Set the instance difficulty float CalculateDifficulty(Map* map) { if (map) { if (map->Is25ManRaid()) { if (map->IsHeroic() && map->GetId() == 649) { return D649H25; } else if (diff_Multiplier_Heroics.find(map->GetId()) == diff_Multiplier_Heroics.end()) { return D25; } else return diff_Multiplier_Heroics[map->GetId()]; } if (map->IsHeroic()) { if (map->GetId() == 649) { return D649H10; } else if (diff_Multiplier_Heroics.find(map->GetId()) == diff_Multiplier_Heroics.end()) { return D10; } else return diff_Multiplier_Heroics[map->GetId()]; } if (diff_Multiplier.find(map->GetId()) == diff_Multiplier.end()) { if (map->IsDungeon()) { return D5; } else if (map->IsRaid()) { return D40; } } else return diff_Multiplier[map->GetId()]; } return 0; } // Set the Dungeon Level uint32 CalculateDungeonLevel(Map* map) { if (dungeons.find(map->GetId()) == dungeons.end()) { return SolocraftDungeonLevel; } else { return dungeons[map->GetId()]; } } // Get the group's size uint32 GetNumInGroup(Player* player) { uint32 numInGroup = 1; Group* group = player->GetGroup(); if (group) { Group::MemberSlotList const& groupMembers = group->GetMemberSlots(); numInGroup = groupMembers.size(); } return numInGroup; } // Get the Player's class balance debuff uint32 GetClassBalance(Player* player) { uint32 classBalance = 100; if (classes.find(player->getClass()) == classes.end()) { return classBalance; } else if (classes[player->getClass()] >= 0 && classes[player->getClass()] <= 100) { return classes[player->getClass()]; } else return classBalance; } // Get the current group members GUIDS and return the total sum of the difficulty offset by all group members currently in the dungeon float GetGroupDifficulty(Player* player) { float GroupDifficulty = 0.0; Group* group = player->GetGroup(); if (group) { Group::MemberSlotList const& groupMembers = group->GetMemberSlots(); for (Group::member_citerator itr = groupMembers.begin(); itr != groupMembers.end(); ++itr) { if (itr->guid != player->GetGUID()) { QueryResult result = CharacterDatabase.Query("SELECT `GUID`, `Difficulty`, `GroupSize` FROM `custom_solocraft_character_stats` WHERE `GUID`={}", itr->guid.GetCounter()); if (result) { if ((*result)[1].Get() > 0) { GroupDifficulty = GroupDifficulty + (*result)[1].Get(); } } } } } return GroupDifficulty; } // Resets buffers void ClearBuffs(Player* player) { //Database query to get offset from the last instance player exited QueryResult result = CharacterDatabase.Query("SELECT `GUID`, `Difficulty`, `GroupSize`, `SpellPower`, `Stats` FROM `custom_solocraft_character_stats` WHERE `GUID`={}", player->GetGUID().GetCounter()); uint32 SpellPowerBonus = 0; if (result) { float difficulty = (*result)[1].Get(); SpellPowerBonus = (*result)[3].Get(); float StatsMultPct = (*result)[4].Get(); SoloCraftXPMod = 1.0; for (uint32 i = STAT_STRENGTH; i < MAX_STATS; ++i) { player->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, difficulty * StatsMultPct, false); } if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN) && !SolocraftNoXPFlag) { player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); } SolocraftNoXPFlag = 0; CharacterDatabase.Execute("DELETE FROM custom_solocraft_character_stats WHERE GUID = {}", player->GetGUID().GetCounter()); } if (player->getPowerType() == POWER_MANA || player->getClass() == CLASS_DRUID) { player->ApplySpellPowerBonus(SpellPowerBonus, false); } } // Apply the player buffs void ApplyBuffs(Player* player, Map* map, float difficulty, int dunLevel, int numInGroup, int classBalance) { // Check whether to buff the player or check to debuff back to normal if (difficulty != 0) { std::ostringstream ss; int SpellPowerBonus = 0; // Check for an existing No XP Gain flag - other mod compatibility if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN)) { SolocraftNoXPFlag = 1; } // If a player is too high level for dungeon don't buff but if in a group will count towards the group offset balancing. if (player->getLevel() <= dunLevel + SolocraftLevelDiff) { // Get Current members total difficulty offset and if it exceeds the difficulty offset of the dungeon then debuff new group members coming in until all members leave and re-enter. This happens when a player already inside dungeon invite others to the group but the player already has the full difficulty offset. float GroupDifficulty = GetGroupDifficulty(player); // Check to either debuff or buff player entering dungeon. Debuff must be enabled in Config if (GroupDifficulty >= difficulty && SoloCraftDebuffEnable == 1) { // Current dungeon offset exceeded - Debuff player modified by ClassBalance Adjustment difficulty = (-abs(difficulty)) + ((((float)classBalance / 100) * difficulty) / numInGroup); // Float variables suck difficulty = roundf(difficulty * 100) / 100; // Disable player XP gain if debuff applied if (!player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN) && SolocraftXPBalEnabled) { player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); } } else { // Current Dungeon offset not exceeded - Buff player // Group difficulty and ClassBalance Adjustment difficulty = (((float)classBalance / 100) * difficulty) / numInGroup; // Float variables suck - two decimal rounding difficulty = roundf(difficulty * 100) / 100; // Set XP Modifier SoloCraftXPMod = (1.04 / difficulty) - 0.02; SoloCraftXPMod = roundf(SoloCraftXPMod * 100) / 100; // Check for negative XP modifier - Disable XP Gain if (SoloCraftXPMod < 0) { SoloCraftXPMod = 0; if (!player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN) && SolocraftXPBalEnabled) { player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); } } // Check XP modifier for over max limit and adjust if (SoloCraftXPMod > 1) { SoloCraftXPMod = 1.0; } } // Check Database for a current dungeon entry QueryResult result = CharacterDatabase.Query("SELECT `GUID`, `Difficulty`, `GroupSize`, `SpellPower`, `Stats` FROM `custom_solocraft_character_stats` WHERE `GUID`={}", player->GetGUID().GetCounter()); // Modify Player Stats // STATS defined/enum in SharedDefines.h for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) { // Check for Dungeon to Dungeon Transfer and remove old buff if (result) { player->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, (*result)[1].Get() * (*result)[4].Get(), false); } // Buff the player // Unitmods enum UNIT_MOD_STAT_START defined in Unit.h line 391 player->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, difficulty * SoloCraftStatsMult, true); } // Set player health // Defined in Unit.h line 1524 player->SetFullHealth(); if (player->IsExistPet()) { // Set Pet Health player->CastSpell(player, 6962, true); } // Spellcaster Stat modify if (player->getPowerType() == POWER_MANA || player->getClass() == CLASS_DRUID) { // Buff the player's mana player->SetPower(POWER_MANA, player->GetMaxPower(POWER_MANA)); // Check for Dungeon to Dungeon Transfer and remove old Spellpower buff if (result) { // remove spellpower bonus player->ApplySpellPowerBonus((*result)[3].Get() * (*result)[4].Get(), false); } // Buff Spellpower // Debuffed characters do not get spellpower if (difficulty > 0) { SpellPowerBonus = static_cast((player->getLevel() * SoloCraftSpellMult) * difficulty); player->ApplySpellPowerBonus(SpellPowerBonus, true); } } // XP Gain Disabled if (!SolocraftXPEnabled) { SoloCraftXPMod = 0; if (!player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN)) { player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); } } // Announcements if (difficulty > 0) { // Announce to player - Buff if (!SolocraftXPEnabled) { ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - Difficulty Offset: %0.2f. Spellpower Bonus: %i. Class Balance Weight: %i. XP Gain: |cffFF0000Disabled"; ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), difficulty, SpellPowerBonus, classBalance); } else { if (!SolocraftXPBalEnabled) { ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - Difficulty Offset: %0.2f. Spellpower Bonus: %i. Class Balance Weight: %i. XP Balancing: |cffFF0000Disabled"; ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), difficulty, SpellPowerBonus, classBalance); } else { ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - Difficulty Offset: %0.2f. Spellpower Bonus: %i. Class Balance Weight: %i. XP Balancing: |cff4CFF00Enabled"; ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), difficulty, SpellPowerBonus, classBalance); } } } else { // Announce to player - Debuff if (!SolocraftXPBalEnabled && SolocraftXPEnabled) { ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - |cffFF0000BE ADVISED - You have been debuffed by offset: %0.2f with a Class Balance Weight: %i. |cffFF8000 A group member already inside has the dungeon's full buff offset. No Spellpower buff will be applied to spell casters. ALL group members must exit the dungeon and re-enter to receive a balanced offset."; ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), difficulty, classBalance); } else { ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - |cffFF0000BE ADVISED - You have been debuffed by offset: %0.2f with a Class Balance Weight: %i and no XP will be awarded. |cffFF8000 A group member already inside has the dungeon's full buff offset. No Spellpower buff will be applied to spell casters. ALL group members must exit the dungeon and re-enter to receive a balanced offset."; ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), difficulty, classBalance); } } // Save Player Dungeon Offsets to Database CharacterDatabase.Execute("REPLACE INTO custom_solocraft_character_stats (GUID, Difficulty, GroupSize, SpellPower, Stats) VALUES ({}, {}, {}, {}, {})", player->GetGUID().GetCounter(), difficulty, numInGroup, SpellPowerBonus, SoloCraftStatsMult); } else { // Announce to player - Over Max Level Threshold ss << "|cffFF0000[SoloCraft] |cffFF8000" << player->GetName() << " entered %s - |cffFF0000You have not been buffed. |cffFF8000 Your level is higher than the max level (%i) threshold for this dungeon."; ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str(), map->GetMapName(), dunLevel + SolocraftLevelDiff); ClearBuffs(player); // Check to revert player back to normal } } else { ClearBuffs(player); // Check to revert player back to normal - Moving this here fixed logout and login while in instance buff and debuff issues } } private: std::map _unitDifficulty; }; void AddSolocraftScripts() { new SolocraftConfig(); new SolocraftAnnounce(); new SolocraftPlayerInstanceHandler(); }