diff --git a/sql/world/base/cs_individualProgression.sql b/sql/world/base/cs_individualProgression.sql new file mode 100644 index 0000000..ea2ab30 --- /dev/null +++ b/sql/world/base/cs_individualProgression.sql @@ -0,0 +1,3 @@ +DELETE FROM `command` WHERE `name` IN ('individualProgression set'); +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('individualProgression set', 2, 'Syntax: .individualProgression set $player $progressionLevel\nSets the player to the given progression level.'); diff --git a/src/IndividualProgression.cpp b/src/IndividualProgression.cpp index 862642e..dc0292c 100644 --- a/src/IndividualProgression.cpp +++ b/src/IndividualProgression.cpp @@ -4,10 +4,172 @@ #include "IndividualProgression.h" -static float vanillaPowerAdjustment, vanillaHealthAdjustment, tbcPowerAdjustment, tbcHealthAdjustment, vanillaHealingAdjustment, tbcHealingAdjustment, previousGearTuning; -static bool enabled, questXpFix, hunterPetLevelFix, requirePreAQQuests, enforceGroupRules, fishingFix, simpleConfigOverride, questMoneyAtLevelCap; -static int progressionLimit, startingProgression; -static questXpMapType questXpMap; +IndividualProgression* IndividualProgression::instance() +{ + static IndividualProgression instance; + return &instance; +} + + +bool IndividualProgression::hasPassedProgression(Player* player, ProgressionState state) const +{ + if (progressionLimit && state >= progressionLimit) + return false; + return player->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= state; +} + +bool IndividualProgression::isBeforeProgression(Player* player, ProgressionState state) const +{ + return player->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value < state; +} + +void IndividualProgression::UpdateProgressionState(Player* player, ProgressionState newState) const +{ + if (progressionLimit && newState >= progressionLimit) + return; + uint8 currentState = player->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value; + if (newState > currentState) + { + player->UpdatePlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE, newState); + } +} + +void IndividualProgression::CheckAdjustments(Player* player) const +{ + if (!enabled) + { + return; + } + if (!hasPassedProgression(player, PROGRESSION_NAXX40)) + { + AdjustVanillaStats(player); + } + else if (!hasPassedProgression(player, PROGRESSION_TBC_TIER_5)) + { + AdjustTBCStats(player); + } + else + { + AdjustWotLKStats(player); + } + if (player->getClass() == CLASS_HUNTER) + { + // Remove the 15% built-in ranged haste that was added to hunters in WotLK + // This lets us add haste spells back to quivers + player->RemoveAura(RANGED_HASTE_SPELL); + player->CastSpell(player, RANGED_HASTE_SPELL, false); + } + if (player->getClass() == CLASS_DEATH_KNIGHT) + { + // Apply a custom aura to fix Rune Tap if healing rate is modified + float computedHealingAdjustment; + if (!hasPassedProgression(player, PROGRESSION_NAXX40)) + { + float adjustmentAmount = 1.0f - vanillaHealingAdjustment; + float applyPercent = ((player->getLevel() - 10.0f) / 50.0f); + computedHealingAdjustment = player->getLevel() > 10 ? 1.0f - applyPercent * adjustmentAmount : 1.0f; + } + // Player is in TBC content - give TBC health adjustment + else if (!hasPassedProgression(player, PROGRESSION_TBC_TIER_5)) + { + computedHealingAdjustment = tbcHealingAdjustment; + } + else { + computedHealingAdjustment = 1.0; + } + if (computedHealingAdjustment < 1.0) + { + auto bp0 = int(((1.0f/computedHealingAdjustment) * 100.0f) - 101.0f); + int32 bp1 = 0; // Don't change the cooldown + player->RemoveAura(RUNE_TAP_FIX_SPELL); + player->CastCustomSpell(player, RUNE_TAP_FIX_SPELL, &bp0, &bp1, nullptr, false); + } + } + +} + +void IndividualProgression::ApplyGearStatsTuning(Player* player, float& computedAdjustment, ItemTemplate const* item) const +{ + if (item->Quality != ITEM_QUALITY_EPIC) // Non-endgame gear is okay + return; + if ((hasPassedProgression(player, PROGRESSION_NAXX40) && (item->RequiredLevel <= 60)) || + hasPassedProgression(player, PROGRESSION_TBC_TIER_5) && (item->RequiredLevel <=70)) + { + computedAdjustment -= (100.0f * previousGearTuning); + } +} + +void IndividualProgression::ApplyGearHealthTuning(Player* player, float& computedAdjustment, ItemTemplate const* item) const +{ + if (item->Quality != ITEM_QUALITY_EPIC) // Non-endgame gear is okay + return; + if ((hasPassedProgression(player, PROGRESSION_NAXX40) && (item->RequiredLevel <= 60)) || + hasPassedProgression(player, PROGRESSION_TBC_TIER_5) && (item->RequiredLevel <=70)) + { + computedAdjustment += previousGearTuning; + } +} + +void IndividualProgression::AdjustVanillaStats(Player* player) const +{ + float adjustmentValue = -100.0f * (1.0f - vanillaPowerAdjustment); + float adjustmentApplyPercent = (player->getLevel() - 10.0f) / 50.0f; + float computedAdjustment = player->getLevel() > 10 ? (adjustmentValue * adjustmentApplyPercent) : 0; + + float adjustmentHealingValue = -100.0f * (1.0f - vanillaHealingAdjustment); + float adjustmentHealingApplyPercent = (player->getLevel() - 10.0f) / 50.0f; + float computedHealingAdjustment = player->getLevel() > 10 ? (adjustmentHealingValue * adjustmentHealingApplyPercent) : 0; + + AdjustStats(player, computedAdjustment, computedHealingAdjustment); +} + +void IndividualProgression::AdjustTBCStats(Player* player) const +{ + float adjustmentValue = -100.0f * (1.0f - tbcPowerAdjustment); + float adjustmentApplyPercent = 1; + float computedAdjustment = player->getLevel() > 10 ? (adjustmentValue * adjustmentApplyPercent) : 0; + + float adjustmentHealingValue = -100.0f * (1.0f - tbcHealingAdjustment); + float adjustmentHealingApplyPercent = 1; + float computedHealingAdjustment = player->getLevel() > 10 ? (adjustmentHealingValue * adjustmentHealingApplyPercent) : 0; + + for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i) + { + if (Item *item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + { + ApplyGearStatsTuning(player, computedAdjustment, item->GetTemplate()); + ApplyGearStatsTuning(player, computedHealingAdjustment, item->GetTemplate()); + } + } + AdjustStats(player, computedAdjustment, computedHealingAdjustment); +} + +void IndividualProgression::AdjustWotLKStats(Player* player) const +{ + float computedAdjustment = 0; + for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i) + { + if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + ApplyGearStatsTuning(player, computedAdjustment, item->GetTemplate()); + } + AdjustStats(player, computedAdjustment, computedAdjustment); +} + +void IndividualProgression::AdjustStats(Player* player, float computedAdjustment, float computedHealingAdjustment) +{ + int32 bp0 = 0; // This would be the damage taken adjustment value, but we are already adjusting health + auto bp1 = static_cast(computedAdjustment); + auto bp1Healing = static_cast(computedHealingAdjustment); + + player->RemoveAura(DAMAGE_DONE_TAKEN_SPELL); + player->CastCustomSpell(player, DAMAGE_DONE_TAKEN_SPELL, &bp0, &bp1, nullptr, false); + + player->RemoveAura(ABSORB_SPELL); + player->CastCustomSpell(player, ABSORB_SPELL, &bp1, nullptr, nullptr, false); + + player->RemoveAura(HEALING_DONE_SPELL); + player->CastCustomSpell(player, HEALING_DONE_SPELL, &bp1Healing, nullptr, nullptr, false); +} class gobject_ipp_wotlk : public GameObjectScript { @@ -16,16 +178,16 @@ public: struct gobject_ipp_wotlkAI: GameObjectAI { - gobject_ipp_wotlkAI(GameObject* object) : GameObjectAI(object) { }; + explicit gobject_ipp_wotlkAI(GameObject* object) : GameObjectAI(object) { }; bool CanBeSeen(Player const* player) override { - if (player->IsGameMaster() || !enabled) + if (player->IsGameMaster() || !sIndividualProgression->enabled) { return true; } Player* target = ObjectAccessor::FindConnectedPlayer(player->GetGUID()); - return target->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= PROGRESSION_TBC_TIER_5; + return sIndividualProgression->hasPassedProgression(target, PROGRESSION_TBC_TIER_5); } }; @@ -42,16 +204,16 @@ public: struct gobject_ipp_tbcAI: GameObjectAI { - gobject_ipp_tbcAI(GameObject* object) : GameObjectAI(object) { }; + explicit gobject_ipp_tbcAI(GameObject* object) : GameObjectAI(object) { }; bool CanBeSeen(Player const* player) override { - if (player->IsGameMaster() || !enabled) + if (player->IsGameMaster() || !sIndividualProgression->enabled) { return true; } Player* target = ObjectAccessor::FindConnectedPlayer(player->GetGUID()); - return target->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= PROGRESSION_NAXX40; + return sIndividualProgression->hasPassedProgression(target, PROGRESSION_NAXX40); } }; @@ -68,16 +230,16 @@ public: struct npc_ipp_tbcAI: ScriptedAI { - npc_ipp_tbcAI(Creature* creature) : ScriptedAI(creature) { }; + explicit npc_ipp_tbcAI(Creature* creature) : ScriptedAI(creature) { }; bool CanBeSeen(Player const* player) override { - if (player->IsGameMaster() || !enabled) + if (player->IsGameMaster() || !sIndividualProgression->enabled) { return true; } Player* target = ObjectAccessor::FindConnectedPlayer(player->GetGUID()); - return target->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= PROGRESSION_NAXX40; + return sIndividualProgression->hasPassedProgression(target, PROGRESSION_NAXX40); } }; @@ -94,16 +256,16 @@ public: struct npc_ipp_tbc_t4AI: ScriptedAI { - npc_ipp_tbc_t4AI(Creature* creature) : ScriptedAI(creature) { }; + explicit npc_ipp_tbc_t4AI(Creature* creature) : ScriptedAI(creature) { }; bool CanBeSeen(Player const* player) override { - if (player->IsGameMaster() || !enabled) + if (player->IsGameMaster() || !sIndividualProgression->enabled) { return true; } Player* target = ObjectAccessor::FindConnectedPlayer(player->GetGUID()); - return target->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= PROGRESSION_TBC_TIER_3; + return sIndividualProgression->hasPassedProgression(target, PROGRESSION_TBC_TIER_3); } }; @@ -120,16 +282,16 @@ public: struct npc_ipp_tbc_pre_t4AI: ScriptedAI { - npc_ipp_tbc_pre_t4AI(Creature* creature) : ScriptedAI(creature) { }; + explicit npc_ipp_tbc_pre_t4AI(Creature* creature) : ScriptedAI(creature) { }; bool CanBeSeen(Player const* player) override { - if (player->IsGameMaster() || !enabled) + if (player->IsGameMaster() || !sIndividualProgression->enabled) { return true; } Player* target = ObjectAccessor::FindConnectedPlayer(player->GetGUID()); - return target->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value < PROGRESSION_TBC_TIER_3; + return sIndividualProgression->isBeforeProgression(target,PROGRESSION_TBC_TIER_3); } }; @@ -146,16 +308,16 @@ public: struct npc_ipp_wotlkAI: ScriptedAI { - npc_ipp_wotlkAI(Creature* creature) : ScriptedAI(creature) { }; + explicit npc_ipp_wotlkAI(Creature* creature) : ScriptedAI(creature) { }; bool CanBeSeen(Player const* player) override { - if (player->IsGameMaster() || !enabled) + if (player->IsGameMaster() || !sIndividualProgression->enabled) { return true; } Player* target = ObjectAccessor::FindConnectedPlayer(player->GetGUID()); - return target->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= PROGRESSION_TBC_TIER_5; + return sIndividualProgression->hasPassedProgression(target, PROGRESSION_TBC_TIER_5); } }; @@ -172,16 +334,16 @@ public: struct npc_ipp_aqAI: ScriptedAI { - npc_ipp_aqAI(Creature* creature) : ScriptedAI(creature) { }; + explicit npc_ipp_aqAI(Creature* creature) : ScriptedAI(creature) { }; bool CanBeSeen(Player const* player) override { - if (player->IsGameMaster() || !enabled) + if (player->IsGameMaster() || !sIndividualProgression->enabled) { return true; } Player* target = ObjectAccessor::FindConnectedPlayer(player->GetGUID()); - return target->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= PROGRESSION_BLACKWING_LAIR; + return sIndividualProgression->hasPassedProgression(target, PROGRESSION_BLACKWING_LAIR); } }; @@ -198,16 +360,16 @@ public: struct npc_ipp_naxx40AI: ScriptedAI { - npc_ipp_naxx40AI(Creature* creature) : ScriptedAI(creature) { }; + explicit npc_ipp_naxx40AI(Creature* creature) : ScriptedAI(creature) { }; bool CanBeSeen(Player const* player) override { - if (player->IsGameMaster() || !enabled) + if (player->IsGameMaster() || !sIndividualProgression->enabled) { return true; } Player* target = ObjectAccessor::FindConnectedPlayer(player->GetGUID()); - return target->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= PROGRESSION_AQ; + return sIndividualProgression->hasPassedProgression(target, PROGRESSION_AQ); } }; @@ -221,30 +383,30 @@ public: class IndividualPlayerProgression_WorldScript : public WorldScript { private: - void LoadConfig() + static void LoadConfig() { - enabled = sConfigMgr->GetOption("IndividualProgression.Enable", true); - vanillaPowerAdjustment = sConfigMgr->GetOption("IndividualProgression.VanillaPowerAdjustment", 1); - vanillaHealingAdjustment = sConfigMgr->GetOption("IndividualProgression.VanillaHealingAdjustment", 1); - vanillaHealthAdjustment = sConfigMgr->GetOption("IndividualProgression.VanillaHealthAdjustment", 1); - tbcPowerAdjustment = sConfigMgr->GetOption("IndividualProgression.TBCPowerAdjustment", 1); - tbcHealingAdjustment = sConfigMgr->GetOption("IndividualProgression.TBCHealingAdjustment", 1); - tbcHealthAdjustment = sConfigMgr->GetOption("IndividualProgression.TBCHealthAdjustment", 1); - questXpFix = sConfigMgr->GetOption("IndividualProgression.QuestXPFix", true); - hunterPetLevelFix = sConfigMgr->GetOption("IndividualProgression.HunterPetLevelFix", true); - requirePreAQQuests = sConfigMgr->GetOption("IndividualProgression.RequirePreAQQuests", true); - enforceGroupRules = sConfigMgr->GetOption("IndividualProgression.EnforceGroupRules", true); - fishingFix = sConfigMgr->GetOption("IndividualProgression.FishingFix", true); - simpleConfigOverride = sConfigMgr->GetOption("IndividualProgression.SimpleConfigOverride", true); - previousGearTuning = sConfigMgr->GetOption("IndividualProgression.PreviousGearTuning", 0.03); - progressionLimit = sConfigMgr->GetOption("IndividualProgression.ProgressionLimit", 0); - startingProgression = sConfigMgr->GetOption("IndividualProgression.StartingProgression", 0); - questMoneyAtLevelCap = sConfigMgr->GetOption("IndividualProgression.QuestMoneyAtLevelCap", true); + sIndividualProgression->enabled = sConfigMgr->GetOption("IndividualProgression.Enable", true); + sIndividualProgression->vanillaPowerAdjustment = sConfigMgr->GetOption("IndividualProgression.VanillaPowerAdjustment", 1); + sIndividualProgression->vanillaHealingAdjustment = sConfigMgr->GetOption("IndividualProgression.VanillaHealingAdjustment", 1); + sIndividualProgression->vanillaHealthAdjustment = sConfigMgr->GetOption("IndividualProgression.VanillaHealthAdjustment", 1); + sIndividualProgression->tbcPowerAdjustment = sConfigMgr->GetOption("IndividualProgression.TBCPowerAdjustment", 1); + sIndividualProgression->tbcHealingAdjustment = sConfigMgr->GetOption("IndividualProgression.TBCHealingAdjustment", 1); + sIndividualProgression->tbcHealthAdjustment = sConfigMgr->GetOption("IndividualProgression.TBCHealthAdjustment", 1); + sIndividualProgression->questXpFix = sConfigMgr->GetOption("IndividualProgression.QuestXPFix", true); + sIndividualProgression->hunterPetLevelFix = sConfigMgr->GetOption("IndividualProgression.HunterPetLevelFix", true); + sIndividualProgression->requirePreAQQuests = sConfigMgr->GetOption("IndividualProgression.RequirePreAQQuests", true); + sIndividualProgression->enforceGroupRules = sConfigMgr->GetOption("IndividualProgression.EnforceGroupRules", true); + sIndividualProgression->fishingFix = sConfigMgr->GetOption("IndividualProgression.FishingFix", true); + sIndividualProgression->simpleConfigOverride = sConfigMgr->GetOption("IndividualProgression.SimpleConfigOverride", true); + sIndividualProgression->previousGearTuning = sConfigMgr->GetOption("IndividualProgression.PreviousGearTuning", 0.03); + sIndividualProgression->progressionLimit = sConfigMgr->GetOption("IndividualProgression.ProgressionLimit", 0); + sIndividualProgression->startingProgression = sConfigMgr->GetOption("IndividualProgression.StartingProgression", 0); + sIndividualProgression->questMoneyAtLevelCap = sConfigMgr->GetOption("IndividualProgression.QuestMoneyAtLevelCap", true); } - void LoadXpValues() + static void LoadXpValues() { - if (enabled && questXpFix) + if (sIndividualProgression->enabled && sIndividualProgression->questXpFix) { LOG_INFO("module", "Loading Quest XP cache...."); uint32 questXpAmount = 0; @@ -255,7 +417,7 @@ private: { uint32 questId = (*result)[0].Get(); uint32 xpValue = (*result)[1].Get(); - questXpMap.insert({questId, xpValue}); + sIndividualProgression->questXpMap.insert({questId, xpValue}); questXpAmount++; } while (result->NextRow()); } @@ -274,7 +436,7 @@ public: void OnAfterConfigLoad(bool /*reload*/) override { - if (simpleConfigOverride) + if (sIndividualProgression->simpleConfigOverride) { sWorld->setIntConfig(CONFIG_WATER_BREATH_TIMER, 60000); // sWorld->setBoolConfig(CONFIG_OBJECT_QUEST_MARKERS, false); Waiting for PR merge: https://github.com/azerothcore/azerothcore-wotlk/pull/13013 @@ -287,16 +449,9 @@ public: class IndividualPlayerProgression_PetScript : public PetScript { private: - bool hasPassedProgression(Player* player, ProgressionState state) + static void CheckAdjustments(Pet* pet) { - if (progressionLimit && state >= progressionLimit) - return false; - return player->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= state; - } - - void CheckAdjustments(Pet* pet) - { - if (!enabled) + if (!sIndividualProgression->enabled) { return; } @@ -304,42 +459,42 @@ private: { return; } - if (!hasPassedProgression(pet->GetOwner(), PROGRESSION_NAXX40)) + if (!sIndividualProgression->hasPassedProgression(pet->GetOwner(), PROGRESSION_NAXX40)) { AdjustVanillaStats(pet); } - else if (!hasPassedProgression(pet->GetOwner(), PROGRESSION_TBC_TIER_5)) + else if (!sIndividualProgression->hasPassedProgression(pet->GetOwner(), PROGRESSION_TBC_TIER_5)) { AdjustTBCStats(pet); } } - void AdjustVanillaStats(Pet* pet) + static void AdjustVanillaStats(Pet* pet) { - float adjustmentValue = -100.0 * (1.0 - vanillaPowerAdjustment); - float adjustmentApplyPercent = (pet->getLevel() - 10.0) / 50.0; + float adjustmentValue = -100.0f * (1.0f - sIndividualProgression->vanillaPowerAdjustment); + float adjustmentApplyPercent = (pet->getLevel() - 10.0f) / 50.0f; float computedAdjustment = pet->getLevel() > 10 ? (adjustmentValue * adjustmentApplyPercent) : 0; - float hpAdjustmentValue = -100.0 * (1.0 - vanillaHealthAdjustment); + float hpAdjustmentValue = -100.0f * (1.0f - sIndividualProgression->vanillaHealthAdjustment); float hpAdjustment = pet->getLevel() > 10 ? (hpAdjustmentValue * adjustmentApplyPercent) : 0; AdjustStats(pet, computedAdjustment, hpAdjustment); } - void AdjustTBCStats(Pet* pet) + static void AdjustTBCStats(Pet* pet) { - float adjustmentValue = -100.0 * (1.0 - tbcPowerAdjustment); + float adjustmentValue = -100.0f * (1.0f - sIndividualProgression->tbcPowerAdjustment); float adjustmentApplyPercent = 1; float computedAdjustment = pet->getLevel() > 10 ? (adjustmentValue * adjustmentApplyPercent) : 0; - float hpAdjustmentValue = -100.0 * (1.0 - tbcHealthAdjustment); + float hpAdjustmentValue = -100.0f * (1.0f - sIndividualProgression->tbcHealthAdjustment); float hpAdjustment = pet->getLevel() > 10 ? (hpAdjustmentValue * adjustmentApplyPercent) : 0; AdjustStats(pet, computedAdjustment, hpAdjustment); } - void AdjustStats(Pet* pet, float computedAdjustment, float hpAdjustment) + static void AdjustStats(Pet* pet, float computedAdjustment, float hpAdjustment) { int32 bp0 = 0; // This would be the damage taken adjustment value, but we are already adjusting health - int32 bp1 = static_cast(computedAdjustment); - int32 bp2 = static_cast(hpAdjustment); + auto bp1 = static_cast(computedAdjustment); + auto bp2 = static_cast(hpAdjustment); pet->RemoveAura(DAMAGE_DONE_TAKEN_SPELL); pet->CastCustomSpell(pet, DAMAGE_DONE_TAKEN_SPELL, &bp0, &bp1, nullptr, false); @@ -365,210 +520,54 @@ public: // Add player scripts class IndividualPlayerProgression : public PlayerScript { -private: - static bool hasPassedProgression(Player* player, ProgressionState state) - { - if (progressionLimit && state >= progressionLimit) - return false; - return player->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= state; - } - static void UpdateProgressionState(Player* player, ProgressionState newState) - { - if (progressionLimit && newState >= progressionLimit) - return; - uint8 currentState = player->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value; - if (newState > currentState) - { - player->UpdatePlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE, newState); - } - } - - void CheckAdjustments(Player* player) - { - if (!enabled) - { - return; - } - if (!hasPassedProgression(player, PROGRESSION_NAXX40)) - { - AdjustVanillaStats(player); - } - else if (!hasPassedProgression(player, PROGRESSION_TBC_TIER_5)) - { - AdjustTBCStats(player); - } - else - { - AdjustWotLKStats(player); - } - if (player->getClass() == CLASS_HUNTER) - { - // Remove the 15% built-in ranged haste that was added to hunters in WotLK - // This lets us add haste spells back to quivers - player->RemoveAura(RANGED_HASTE_SPELL); - player->CastSpell(player, RANGED_HASTE_SPELL, false); - } - if (player->getClass() == CLASS_DEATH_KNIGHT) - { - // Apply a custom aura to fix Rune Tap if healing rate is modified - float computedHealingAdjustment; - if (!hasPassedProgression(player, PROGRESSION_NAXX40)) - { - float adjustmentAmount = 1.0 - vanillaHealingAdjustment; - float applyPercent = ((player->getLevel() - 10.0) / 50.0); - computedHealingAdjustment = player->getLevel() > 10 ? 1.0 - applyPercent * adjustmentAmount : 1.0; - } - // Player is in TBC content - give TBC health adjustment - else if (!hasPassedProgression(player, PROGRESSION_TBC_TIER_5)) - { - computedHealingAdjustment = tbcHealingAdjustment; - } - else { - computedHealingAdjustment = 1.0; - } - if (computedHealingAdjustment < 1.0) - { - int32 bp0 = int(((1.0f/computedHealingAdjustment) * 100.0) - 101.0); - int32 bp1 = 0; // Don't change the cooldown - player->RemoveAura(RUNE_TAP_FIX_SPELL); - player->CastCustomSpell(player, RUNE_TAP_FIX_SPELL, &bp0, &bp1, nullptr, false); - } - } - - } - - void ApplyGearStatsTuning(Player* player, float& computedAdjustment, ItemTemplate const* item) - { - if (item->Quality != ITEM_QUALITY_EPIC) // Non-endgame gear is okay - return; - if ((hasPassedProgression(player, PROGRESSION_NAXX40) && (item->RequiredLevel <= 60)) || - hasPassedProgression(player, PROGRESSION_TBC_TIER_5) && (item->RequiredLevel <=70)) - { - computedAdjustment -= (100.0 * previousGearTuning); - } - } - - void ApplyGearHealthTuning(Player* player, float& computedAdjustment, ItemTemplate const* item) - { - if (item->Quality != ITEM_QUALITY_EPIC) // Non-endgame gear is okay - return; - if ((hasPassedProgression(player, PROGRESSION_NAXX40) && (item->RequiredLevel <= 60)) || - hasPassedProgression(player, PROGRESSION_TBC_TIER_5) && (item->RequiredLevel <=70)) - { - computedAdjustment += previousGearTuning; - } - } - - void AdjustVanillaStats(Player* player) - { - float adjustmentValue = -100.0 * (1.0 - vanillaPowerAdjustment); - float adjustmentApplyPercent = (player->getLevel() - 10.0) / 50.0; - float computedAdjustment = player->getLevel() > 10 ? (adjustmentValue * adjustmentApplyPercent) : 0; - - float adjustmentHealingValue = -100.0 * (1.0 - vanillaHealingAdjustment); - float adjustmentHealingApplyPercent = (player->getLevel() - 10.0) / 50.0; - float computedHealingAdjustment = player->getLevel() > 10 ? (adjustmentHealingValue * adjustmentHealingApplyPercent) : 0; - - AdjustStats(player, computedAdjustment, computedHealingAdjustment); - } - - void AdjustTBCStats(Player* player) - { - float adjustmentValue = -100.0 * (1.0 - tbcPowerAdjustment); - float adjustmentApplyPercent = 1; - float computedAdjustment = player->getLevel() > 10 ? (adjustmentValue * adjustmentApplyPercent) : 0; - - float adjustmentHealingValue = -100.0 * (1.0 - tbcHealingAdjustment); - float adjustmentHealingApplyPercent = 1; - float computedHealingAdjustment = player->getLevel() > 10 ? (adjustmentHealingValue * adjustmentHealingApplyPercent) : 0; - - for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i) - { - if (Item *item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) - { - ApplyGearStatsTuning(player, computedAdjustment, item->GetTemplate()); - ApplyGearStatsTuning(player, computedHealingAdjustment, item->GetTemplate()); - } - } - AdjustStats(player, computedAdjustment, computedHealingAdjustment); - } - - void AdjustWotLKStats(Player* player) - { - float computedAdjustment = 0; - for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i) - { - if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) - ApplyGearStatsTuning(player, computedAdjustment, item->GetTemplate()); - } - AdjustStats(player, computedAdjustment, computedAdjustment); - } - - void AdjustStats(Player* player, float computedAdjustment, float computedHealingAdjustment) - { - int32 bp0 = 0; // This would be the damage taken adjustment value, but we are already adjusting health - int32 bp1 = static_cast(computedAdjustment); - int32 bp1Healing = static_cast(computedHealingAdjustment); - - player->RemoveAura(DAMAGE_DONE_TAKEN_SPELL); - player->CastCustomSpell(player, DAMAGE_DONE_TAKEN_SPELL, &bp0, &bp1, nullptr, false); - - player->RemoveAura(ABSORB_SPELL); - player->CastCustomSpell(player, ABSORB_SPELL, &bp1, nullptr, nullptr, false); - - player->RemoveAura(HEALING_DONE_SPELL); - player->CastCustomSpell(player, HEALING_DONE_SPELL, &bp1Healing, nullptr, nullptr, false); - } - - public: IndividualPlayerProgression() : PlayerScript("IndividualProgression") { } void OnLogin(Player* player) override { - if (startingProgression && !hasPassedProgression(player, static_cast(startingProgression))) + if (sIndividualProgression->startingProgression && !sIndividualProgression->hasPassedProgression(player, static_cast(sIndividualProgression->startingProgression))) { - UpdateProgressionState(player, static_cast(startingProgression)); + sIndividualProgression->UpdateProgressionState(player, static_cast(sIndividualProgression->startingProgression)); } - CheckAdjustments(player); + sIndividualProgression->CheckAdjustments(player); } void OnMapChanged(Player* player) override { - CheckAdjustments(player); + sIndividualProgression->CheckAdjustments(player); } void OnLevelChanged(Player* player, uint8 /*oldLevel*/) override { - CheckAdjustments(player); + sIndividualProgression->CheckAdjustments(player); } void OnEquip(Player* player, Item* /*it*/, uint8 /*bag*/, uint8 /*slot*/, bool /*update*/) override { - CheckAdjustments(player); + sIndividualProgression->CheckAdjustments(player); } void OnPlayerResurrect(Player* player, float /*restore_percent*/, bool /*applySickness*/) override { - CheckAdjustments(player); + sIndividualProgression->CheckAdjustments(player); } bool ShouldBeRewardedWithMoneyInsteadOfExp(Player* player) override { - if (!questMoneyAtLevelCap) + if (!sIndividualProgression->questMoneyAtLevelCap) { return false; } // Player is still in Vanilla content - give money at 60 level cap - return ((!hasPassedProgression(player, PROGRESSION_NAXX40) && player->getLevel() == 60) || + return ((!sIndividualProgression->hasPassedProgression(player, PROGRESSION_NAXX40) && player->getLevel() == 60) || // Player is in TBC content - give money at 70 level cap - (!hasPassedProgression(player, PROGRESSION_TBC_TIER_5) && player->getLevel() == 70)); + (!sIndividualProgression->hasPassedProgression(player, PROGRESSION_TBC_TIER_5) && player->getLevel() == 70)); } void OnAfterUpdateMaxHealth(Player* player, float& value) override { // TODO: This should be adjust to use an aura like damage adjustment. This is more robust to update when changing equipment, etc. - if (!enabled) + if (!sIndividualProgression->enabled) { return; } @@ -576,20 +575,20 @@ public: for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i) { if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) - ApplyGearHealthTuning(player, gearAdjustment, item->GetTemplate()); + sIndividualProgression->ApplyGearHealthTuning(player, gearAdjustment, item->GetTemplate()); } // Player is still in Vanilla content - give Vanilla health adjustment - if (!hasPassedProgression(player, PROGRESSION_NAXX40)) + if (!sIndividualProgression->hasPassedProgression(player, PROGRESSION_NAXX40)) { - float adjustmentAmount = 1.0 - vanillaHealthAdjustment; - float applyPercent = ((player->getLevel() - 10.0) / 50.0); - float computedAdjustment = player->getLevel() > 10 ? 1.0 - applyPercent * adjustmentAmount : 1.0; + float adjustmentAmount = 1.0f - sIndividualProgression->vanillaHealthAdjustment; + float applyPercent = ((player->getLevel() - 10.0f) / 50.0f); + float computedAdjustment = player->getLevel() > 10 ? 1.0f - applyPercent * adjustmentAmount : 1.0f; value *= computedAdjustment; } // Player is in TBC content - give TBC health adjustment - else if (!hasPassedProgression(player, PROGRESSION_TBC_TIER_5)) + else if (!sIndividualProgression->hasPassedProgression(player, PROGRESSION_TBC_TIER_5)) { - value *= (tbcHealthAdjustment - gearAdjustment); + value *= (sIndividualProgression->tbcHealthAdjustment - gearAdjustment); } // Player is in WotLK content - only need to check gear adjustment else @@ -600,13 +599,13 @@ public: void OnQuestComputeXP(Player* player, Quest const* quest, uint32& xpValue) override { - if (!enabled || !questXpFix) + if (!sIndividualProgression->enabled || !sIndividualProgression->questXpFix) { return; } - if (questXpMap.count(quest->GetQuestId())) + if (sIndividualProgression->questXpMap.count(quest->GetQuestId())) { - uint32 vanillaXpValue = questXpMap[quest->GetQuestId()]; + uint32 vanillaXpValue = sIndividualProgression->questXpMap[quest->GetQuestId()]; if (player) { vanillaXpValue *= player->GetQuestRate(); @@ -622,17 +621,17 @@ public: void OnGiveXP(Player* player, uint32& amount, Unit* /*victim*/) override { - if (!enabled) + if (!sIndividualProgression->enabled) { return; } // Player is still in Vanilla content - do not give XP past level 60 - if (!hasPassedProgression(player, PROGRESSION_NAXX40) && player->getLevel() >= 60) + if (!sIndividualProgression->hasPassedProgression(player, PROGRESSION_NAXX40) && player->getLevel() >= 60) { amount = 0; } // Player is in TBC content - do not give XP past level 70 - else if (!hasPassedProgression(player, PROGRESSION_TBC_TIER_5) && player->getLevel() >= 70) + else if (!sIndividualProgression->hasPassedProgression(player, PROGRESSION_TBC_TIER_5) && player->getLevel() >= 70) { amount = 0; } @@ -640,19 +639,19 @@ public: bool OnBeforeTeleport(Player* player, uint32 mapid, float x, float y, float z, float /*orientation*/, uint32 /*options*/, Unit* /*target*/) override { - if (!enabled || player->IsGameMaster()) + if (!sIndividualProgression->enabled || player->IsGameMaster()) { return true; } - if (mapid == MAP_ZUL_GURUB && !hasPassedProgression(player, PROGRESSION_BLACKWING_LAIR)) + if (mapid == MAP_ZUL_GURUB && !sIndividualProgression->hasPassedProgression(player, PROGRESSION_BLACKWING_LAIR)) { return false; } - if (mapid == MAP_AQ_40 && !hasPassedProgression(player, PROGRESSION_PRE_AQ)) + if (mapid == MAP_AQ_40 && !sIndividualProgression->hasPassedProgression(player, PROGRESSION_PRE_AQ)) { return false; } - if (mapid == MAP_AQ_20 && !hasPassedProgression(player, PROGRESSION_PRE_AQ)) + if (mapid == MAP_AQ_20 && !sIndividualProgression->hasPassedProgression(player, PROGRESSION_PRE_AQ)) { return false; } @@ -660,36 +659,36 @@ public: { Map const* map = sMapMgr->FindMap(mapid, 0); uint32 zoneId = map->GetZoneId(0, x, y, z); - if (!hasPassedProgression(player, PROGRESSION_NAXX40)) + if (!sIndividualProgression->hasPassedProgression(player, PROGRESSION_NAXX40)) { // The player may be in the Azuremyst area which is on the outlands map - check the area ID return (zoneId == ZONE_AZUREMYST || zoneId == ZONE_BLOODMYST || zoneId == ZONE_GHOSTLANDS || zoneId == ZONE_EVERSONG || zoneId == ZONE_EXODAR || zoneId == ZONE_SILVERMOON); } - if (!hasPassedProgression(player, PROGRESSION_TBC_TIER_4) && zoneId == ZONE_QUELDANAS) + if (!sIndividualProgression->hasPassedProgression(player, PROGRESSION_TBC_TIER_4) && zoneId == ZONE_QUELDANAS) { return false; } } - if (mapid == MAP_ZUL_AMAN && !hasPassedProgression(player, PROGRESSION_TBC_TIER_3)) + if (mapid == MAP_ZUL_AMAN && !sIndividualProgression->hasPassedProgression(player, PROGRESSION_TBC_TIER_3)) { return false; } - if (mapid == MAP_NORTHREND && !hasPassedProgression(player, PROGRESSION_TBC_TIER_5)) + if (mapid == MAP_NORTHREND && !sIndividualProgression->hasPassedProgression(player, PROGRESSION_TBC_TIER_5)) { return false; } - if (mapid == MAP_ULDUAR && !hasPassedProgression(player, PROGRESSION_WOTLK_TIER_1)) + if (mapid == MAP_ULDUAR && !sIndividualProgression->hasPassedProgression(player, PROGRESSION_WOTLK_TIER_1)) { return false; } - if ((mapid == MAP_TRIAL_OF_THE_CHAMPION || mapid == MAP_TRIAL_OF_THE_CRUSADER) && !hasPassedProgression(player, PROGRESSION_WOTLK_TIER_2)){ + if ((mapid == MAP_TRIAL_OF_THE_CHAMPION || mapid == MAP_TRIAL_OF_THE_CRUSADER) && !sIndividualProgression->hasPassedProgression(player, PROGRESSION_WOTLK_TIER_2)){ return false; } - if ((mapid == MAP_ICC || mapid == MAP_FORGE_OF_SOULS) && !hasPassedProgression(player, PROGRESSION_WOTLK_TIER_3)) + if ((mapid == MAP_ICC || mapid == MAP_FORGE_OF_SOULS) && !sIndividualProgression->hasPassedProgression(player, PROGRESSION_WOTLK_TIER_3)) { return false; } - if (mapid == MAP_RUBY_SANTCUM && !hasPassedProgression(player, PROGRESSION_WOTLK_TIER_4)) + if (mapid == MAP_RUBY_SANTCUM && !sIndividualProgression->hasPassedProgression(player, PROGRESSION_WOTLK_TIER_4)) { return false; } @@ -698,21 +697,21 @@ public: void OnPlayerCompleteQuest(Player* player, Quest const* quest) override { - if (!enabled) + if (!sIndividualProgression->enabled) { return; } switch (quest->GetQuestId()) { case MIGHT_OF_KALIMDOR: - UpdateProgressionState(player, PROGRESSION_PRE_AQ); + sIndividualProgression->UpdateProgressionState(player, PROGRESSION_PRE_AQ); break; } } bool CanGroupInvite(Player* player, std::string& membername) override { - if (!enabled || !enforceGroupRules) + if (!sIndividualProgression->enabled || !sIndividualProgression->enforceGroupRules) { return true; } @@ -724,7 +723,7 @@ public: bool CanGroupAccept(Player* player, Group* group) override { - if (!enabled || !enforceGroupRules) + if (!sIndividualProgression->enabled || !sIndividualProgression->enforceGroupRules) { return true; } @@ -738,7 +737,7 @@ public: void OnCreatureKill(Player* killer, Creature* killed) override { - if (!enabled) + if (!sIndividualProgression->enabled) { return; } @@ -746,56 +745,56 @@ public: switch (killed->GetEntry()) { case RAGNAROS: - UpdateProgressionState(killer, PROGRESSION_MOLTEN_CORE); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_MOLTEN_CORE); break; case ONYXIA: - UpdateProgressionState(killer, PROGRESSION_ONYXIA); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_ONYXIA); break; case NEFARIAN: - if (requirePreAQQuests) + if (sIndividualProgression->requirePreAQQuests) { - UpdateProgressionState(killer, PROGRESSION_BLACKWING_LAIR); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_BLACKWING_LAIR); } else { - UpdateProgressionState(killer, PROGRESSION_PRE_AQ); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_PRE_AQ); } break; case CTHUN: - UpdateProgressionState(killer, PROGRESSION_AQ); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_AQ); break; case KELTHUZAD_40: - UpdateProgressionState(killer, PROGRESSION_NAXX40); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_NAXX40); break; case MALCHEZAAR: - UpdateProgressionState(killer, PROGRESSION_TBC_TIER_1); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_TBC_TIER_1); break; case KAELTHAS: - UpdateProgressionState(killer, PROGRESSION_TBC_TIER_2); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_TBC_TIER_2); break; case ILLIDAN: - UpdateProgressionState(killer, PROGRESSION_TBC_TIER_3); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_TBC_TIER_3); break; case ZULJIN: - UpdateProgressionState(killer, PROGRESSION_TBC_TIER_4); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_TBC_TIER_4); break; case KILJAEDEN: - UpdateProgressionState(killer, PROGRESSION_TBC_TIER_5); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_TBC_TIER_5); break; case KELTHUZAD: - UpdateProgressionState(killer, PROGRESSION_WOTLK_TIER_1); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_WOTLK_TIER_1); break; case YOGGSARON: - UpdateProgressionState(killer, PROGRESSION_WOTLK_TIER_2); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_WOTLK_TIER_2); break; case ANUBARAK: - UpdateProgressionState(killer, PROGRESSION_WOTLK_TIER_3); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_WOTLK_TIER_3); break; case LICH_KING: - UpdateProgressionState(killer, PROGRESSION_WOTLK_TIER_4); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_WOTLK_TIER_4); break; case HALION: - UpdateProgressionState(killer, PROGRESSION_WOTLK_TIER_5); + sIndividualProgression->UpdateProgressionState(killer, PROGRESSION_WOTLK_TIER_5); break; } } diff --git a/src/IndividualProgression.h b/src/IndividualProgression.h index b52638e..22d015d 100644 --- a/src/IndividualProgression.h +++ b/src/IndividualProgression.h @@ -108,5 +108,28 @@ enum ProgressionState : uint8 PROGRESSION_WOTLK_TIER_5 = 16 // Ruby Sanctum }; +class IndividualProgression +{ +public: + static IndividualProgression* instance(); + + questXpMapType questXpMap; + float vanillaPowerAdjustment, vanillaHealthAdjustment, tbcPowerAdjustment, tbcHealthAdjustment, vanillaHealingAdjustment, tbcHealingAdjustment, previousGearTuning; + bool enabled, questXpFix, hunterPetLevelFix, requirePreAQQuests, enforceGroupRules, fishingFix, simpleConfigOverride, questMoneyAtLevelCap; + int progressionLimit, startingProgression; + + bool hasPassedProgression(Player* player, ProgressionState state) const; + bool isBeforeProgression(Player* player, ProgressionState state) const; + void UpdateProgressionState(Player* player, ProgressionState newState) const; + void CheckAdjustments(Player* player) const; + void ApplyGearStatsTuning(Player* player, float& computedAdjustment, ItemTemplate const* item) const; + void ApplyGearHealthTuning(Player* player, float& computedAdjustment, ItemTemplate const* item) const; + void AdjustVanillaStats(Player* player) const; + void AdjustTBCStats(Player* player) const; + void AdjustWotLKStats(Player* player) const; + static void AdjustStats(Player* player, float computedAdjustment, float computedHealingAdjustment); +}; + +#define sIndividualProgression IndividualProgression::instance() #endif //AZEROTHCORE_INDIVIDUALPROGRESSION_H diff --git a/src/cs_individualProgression.cpp b/src/cs_individualProgression.cpp new file mode 100644 index 0000000..5aa54b6 --- /dev/null +++ b/src/cs_individualProgression.cpp @@ -0,0 +1,51 @@ +#include "Chat.h" +#include "Player.h" +#include "ScriptMgr.h" +#include "Tokenize.h" +#include "IndividualProgression.h" + +using namespace Acore::ChatCommands; + +class individualProgression_commandscript : public CommandScript +{ +public: + individualProgression_commandscript() : CommandScript("individualProgression_commandscript") { } + + ChatCommandTable GetCommands() const override + { + static ChatCommandTable individualProgressionTable = + { + { "set", HandleSetIndividualProgressionCommand, SEC_GAMEMASTER, Console::Yes }, + }; + + static ChatCommandTable commandTable = + { + { "individualProgression", individualProgressionTable }, + }; + + return commandTable; + } + + static bool HandleSetIndividualProgressionCommand(ChatHandler* handler, Optional player, uint32 progressionLevel) + { + if (progressionLevel > PROGRESSION_WOTLK_TIER_5) + { + handler->SendSysMessage("Invalid progression level."); + return false; + } + Player* target = player->GetConnectedPlayer(); + if (target) + { + sIndividualProgression->UpdateProgressionState(target, static_cast(progressionLevel)); + handler->SendSysMessage("Progression state updated successfully"); + } + return true; + } + + +}; + +void AddSC_individualProgression_commandscript() +{ + new individualProgression_commandscript(); +} diff --git a/src/vanillaScripts/cot_scripts.cpp b/src/vanillaScripts/cot_scripts.cpp index b671a62..f0e85be 100644 --- a/src/vanillaScripts/cot_scripts.cpp +++ b/src/vanillaScripts/cot_scripts.cpp @@ -27,7 +27,7 @@ public: return true; } Player* target = ObjectAccessor::FindConnectedPlayer(player->GetGUID()); - return target->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value < PROGRESSION_NAXX40; + return sIndividualProgression->isBeforeProgression(target, PROGRESSION_NAXX40); } }; diff --git a/src/wotlkScripts/IppWotlkModdedScripts.cpp b/src/wotlkScripts/IppWotlkModdedScripts.cpp index c73696a..8366c12 100644 --- a/src/wotlkScripts/IppWotlkModdedScripts.cpp +++ b/src/wotlkScripts/IppWotlkModdedScripts.cpp @@ -107,7 +107,7 @@ public: return true; } Player* target = ObjectAccessor::FindConnectedPlayer(player->GetGUID()); - return target->GetPlayerSetting("mod-individual-progression", SETTING_PROGRESSION_STATE).value >= PROGRESSION_TBC_TIER_5; + return sIndividualProgression->hasPassedProgression(target, PROGRESSION_TBC_TIER_5); } EventMap events;