From 9baebb1b5d6d36ceb828a5808f3498069090b36c Mon Sep 17 00:00:00 2001 From: Shocker Date: Tue, 14 Jun 2016 13:28:53 +0300 Subject: Core/Spells: Implement SPELL_AURA_PROC_ON_POWER_AMOUNT_2 --- src/server/game/Entities/Unit/Unit.cpp | 2 ++ src/server/game/Spells/Auras/SpellAuraDefines.h | 2 +- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 84494f5eff0..8035b3411b7 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -11657,6 +11657,7 @@ bool InitTriggerAuraData() isAlwaysTriggeredAura[i] = false; } isTriggerAura[SPELL_AURA_PROC_ON_POWER_AMOUNT] = true; + isTriggerAura[SPELL_AURA_PROC_ON_POWER_AMOUNT_2] = true; isTriggerAura[SPELL_AURA_DUMMY] = true; isTriggerAura[SPELL_AURA_MOD_CONFUSE] = true; isTriggerAura[SPELL_AURA_MOD_THREAT] = true; @@ -11981,6 +11982,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u break; } case SPELL_AURA_PROC_ON_POWER_AMOUNT: + case SPELL_AURA_PROC_ON_POWER_AMOUNT_2: { triggeredByAura->HandleProcTriggerSpellOnPowerAmountAuraProc(aurApp, eventInfo); takeCharges = true; diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 9eb6ad5c864..4dfc7f7ac34 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -453,7 +453,7 @@ enum AuraType SPELL_AURA_393 = 393, SPELL_AURA_SHOW_CONFIRMATION_PROMPT = 394, SPELL_AURA_AREA_TRIGGER = 395, // NYI - SPELL_AURA_396 = 396, + SPELL_AURA_PROC_ON_POWER_AMOUNT_2 = 396, // missing MicValueB handling, probably OnAmountReach ascending/descending or spell/stack add/remove SPELL_AURA_397 = 397, SPELL_AURA_398 = 398, SPELL_AURA_399 = 399, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index db1767fa8d4..e8fc7a68952 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -455,7 +455,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //393 &AuraEffect::HandleShowConfirmationPrompt, //394 SPELL_AURA_SHOW_CONFIRMATION_PROMPT &AuraEffect::HandleNULL, //395 SPELL_AURA_AREA_TRIGGER - &AuraEffect::HandleNULL, //396 + &AuraEffect::HandleNoImmediateEffect, //396 SPELL_AURA_PROC_ON_POWER_AMOUNT_2 implemented in Unit::HandleAuraProcOnPowerAmount &AuraEffect::HandleNULL, //397 &AuraEffect::HandleNULL, //398 &AuraEffect::HandleNULL, //399 @@ -1236,6 +1236,7 @@ void AuraEffect::HandleProc(AuraApplication* aurApp, ProcEventInfo& eventInfo) HandleRaidProcFromChargeWithValueAuraProc(aurApp, eventInfo); break; case SPELL_AURA_PROC_ON_POWER_AMOUNT: + case SPELL_AURA_PROC_ON_POWER_AMOUNT_2: HandleProcTriggerSpellOnPowerAmountAuraProc(aurApp, eventInfo); break; default: -- cgit v1.2.3 From 96e5d9cd68dc78b8a6c5833cc7eb5c32122ac83e Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 14 Jun 2016 19:01:30 +0200 Subject: Core/Auras: Defined new aura type 468 SPELL_AURA_TRIGGER_SPELL_ON_HEALTH_BELOW_PCT --- src/server/game/Spells/Auras/SpellAuraDefines.h | 6 +++--- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 4dfc7f7ac34..69e7ee53f68 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -523,9 +523,9 @@ enum AuraType SPELL_AURA_CONVER_CRIT_RATING_PCT_TO_PARRY_RATING = 463, // NYI SPELL_AURA_464 = 464, SPELL_AURA_465 = 465, - SPELL_AURA_MOD_BONUS_ARMOR_PCT = 466, // Affects bonus armor gain from all sources except base stats - SPELL_AURA_MOD_STAT_BONUS_PCT = 467, // Affects stat gain from all sources except base stats - SPELL_AURA_468 = 468, + SPELL_AURA_MOD_BONUS_ARMOR_PCT = 466, // Affects bonus armor gain from all sources except base stats + SPELL_AURA_MOD_STAT_BONUS_PCT = 467, // Affects stat gain from all sources except base stats + SPELL_AURA_TRIGGER_SPELL_ON_HEALTH_BELOW_PCT = 468, // Triggers spell when health falls below specified percent value (once, not every time damage is taken below threshold) SPELL_AURA_SHOW_CONFIRMATION_PROMPT_WITH_DIFFICULTY = 469, SPELL_AURA_470 = 470, SPELL_AURA_MOD_VERSATILITY = 471, // NYI diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index e8fc7a68952..772fac2673d 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -527,7 +527,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //465 &AuraEffect::HandleNULL, //466 SPELL_AURA_MOD_BONUS_ARMOR_PCT &AuraEffect::HandleModStatBonusPercent, //467 SPELL_AURA_MOD_STAT_BONUS_PCT - &AuraEffect::HandleNULL, //468 + &AuraEffect::HandleNULL, //468 SPELL_AURA_TRIGGER_SPELL_ON_HEALTH_BELOW_PCT &AuraEffect::HandleShowConfirmationPrompt, //469 SPELL_AURA_SHOW_CONFIRMATION_PROMPT_WITH_DIFFICULTY &AuraEffect::HandleNULL, //470 &AuraEffect::HandleNULL, //471 SPELL_AURA_MOD_VERSATILITY -- cgit v1.2.3 From 5da217877be7f22db3bfc8ee06ca1ffad172d281 Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 15 Jun 2016 16:20:43 +0200 Subject: Core/Spells: Automatically generate spell rank info from SkillLineAbility * This fixes weird spellbook/talent/glyph/profession ui behavior when knowing multiple spells to remove talent or glyph, or multiple spells to open profession ui --- sql/updates/world/6.x/2016_06_15_06_world.sql | 1 + src/server/game/Entities/Player/Player.cpp | 10 +- src/server/game/Spells/SpellInfo.cpp | 39 ------- src/server/game/Spells/SpellInfo.h | 2 - src/server/game/Spells/SpellMgr.cpp | 145 ++++++++++---------------- 5 files changed, 59 insertions(+), 138 deletions(-) create mode 100644 sql/updates/world/6.x/2016_06_15_06_world.sql (limited to 'src') diff --git a/sql/updates/world/6.x/2016_06_15_06_world.sql b/sql/updates/world/6.x/2016_06_15_06_world.sql new file mode 100644 index 00000000000..6d63a4ca441 --- /dev/null +++ b/sql/updates/world/6.x/2016_06_15_06_world.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `spell_ranks`; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 1dd3f63097a..e3d114e367c 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2905,7 +2905,6 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent bool dependent_set = false; bool disabled_case = false; - bool superceded_old = false; PlayerSpellMap::iterator itr = m_spells.find(spellId); @@ -2916,7 +2915,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent { uint32 next_active_spell_id = 0; // fix activate state for non-stackable low rank (and find next spell for !active case) - if (!spellInfo->IsStackableWithRanks() && spellInfo->IsRanked()) + if (spellInfo->IsRanked()) { if (uint32 next = sSpellMgr->GetNextSpellInChain(spellId)) { @@ -3029,7 +3028,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent newspell->disabled = disabled; // replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible - if (newspell->active && !newspell->disabled && !spellInfo->IsStackableWithRanks() && spellInfo->IsRanked() != 0) + if (newspell->active && !newspell->disabled && spellInfo->IsRanked()) { for (PlayerSpellMap::iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2) { @@ -3053,7 +3052,6 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent itr2->second->active = false; if (itr2->second->state != PLAYERSPELL_NEW) itr2->second->state = PLAYERSPELL_CHANGED; - superceded_old = true; // new spell replace old in action bars and spell book. } else { @@ -3173,7 +3171,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent } // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell - return active && !disabled && !superceded_old; + return active && !disabled; } void Player::AddTemporarySpell(uint32 spellId) @@ -3379,7 +3377,7 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) { // if ranked non-stackable spell: need activate lesser rank and update dendence state /// No need to check for spellInfo != NULL here because if cur_active is true, then that means that the spell was already in m_spells, and only valid spells can be pushed there. - if (cur_active && !spellInfo->IsStackableWithRanks() && spellInfo->IsRanked()) + if (cur_active && spellInfo->IsRanked()) { // need manually update dependence state (learn spell ignore like attempts) PlayerSpellMap::iterator prev_itr = m_spells.find(prev_id); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index e7ac181e69f..25a5c874a58 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1257,22 +1257,6 @@ bool SpellInfo::IsQuestTame() const return effect0 && effect1 && effect0->Effect == SPELL_EFFECT_THREAT && effect1->Effect == SPELL_EFFECT_APPLY_AURA && effect1->ApplyAuraName == SPELL_AURA_DUMMY; } -bool SpellInfo::IsProfessionOrRiding(uint32 difficulty) const -{ - SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); - for (SpellEffectInfo const* effect : effects) - { - if ((effect && effect->Effect == SPELL_EFFECT_SKILL)) - { - uint32 skill = effect->MiscValue; - - if (IsProfessionOrRidingSkill(skill)) - return true; - } - } - return false; -} - bool SpellInfo::IsProfession(uint32 difficulty) const { SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); @@ -1310,23 +1294,6 @@ bool SpellInfo::IsPrimaryProfessionFirstRank(uint32 difficulty) const return IsPrimaryProfession(difficulty) && GetRank() == 1; } -bool SpellInfo::IsAbilityLearnedWithProfession() const -{ - SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(Id); - - for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx) - { - SkillLineAbilityEntry const* pAbility = _spell_idx->second; - if (!pAbility || pAbility->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) - continue; - - if (pAbility->MinSkillLineRank > 0) - return true; - } - - return false; -} - bool SpellInfo::IsAbilityOfSkillType(uint32 skillType) const { SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(Id); @@ -1425,12 +1392,6 @@ bool SpellInfo::IsStackableWithRanks() const if (IsPassive()) return false; - if (IsProfessionOrRiding()) - return false; - - if (IsAbilityLearnedWithProfession()) - return false; - // All stance spells. if any better way, change it. SpellEffectInfoVector effects = GetEffectsForDifficulty(DIFFICULTY_NONE); for (SpellEffectInfo const* effect : effects) diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 4faf98a0791..3ca96b3c0e9 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -481,11 +481,9 @@ public: bool IsExplicitDiscovery() const; bool IsLootCrafting() const; bool IsQuestTame() const; - bool IsProfessionOrRiding(uint32 difficulty = DIFFICULTY_NONE) const; bool IsProfession(uint32 difficulty = DIFFICULTY_NONE) const; bool IsPrimaryProfession(uint32 difficulty = DIFFICULTY_NONE) const; bool IsPrimaryProfessionFirstRank(uint32 difficulty = DIFFICULTY_NONE) const; - bool IsAbilityLearnedWithProfession() const; bool IsAbilityOfSkillType(uint32 skillType) const; bool IsAffectingArea(uint32 difficulty) const; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index beeb1109dce..e99c4bd661f 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1261,113 +1261,76 @@ void SpellMgr::LoadSpellRanks() { uint32 oldMSTime = getMSTime(); - // 0 1 2 - QueryResult result = WorldDatabase.Query("SELECT first_spell_id, spell_id, rank from spell_ranks ORDER BY first_spell_id, rank"); - - if (!result) + std::map chains; + std::set hasPrev; + for (SkillLineAbilityEntry const* skillAbility : sSkillLineAbilityStore) { - TC_LOG_INFO("server.loading", ">> Loaded 0 spell rank records. DB table `spell_ranks` is empty."); - return; - } + if (!skillAbility->SupercedesSpell) + continue; - uint32 count = 0; - bool finished = false; + if (!GetSpellInfo(skillAbility->SupercedesSpell) || !GetSpellInfo(skillAbility->SpellID)) + continue; - do - { - // spellid, rank - std::list < std::pair < int32, int32 > > rankChain; - int32 currentSpell = -1; - int32 lastSpell = -1; + chains[skillAbility->SupercedesSpell] = skillAbility->SpellID; + hasPrev.insert(skillAbility->SpellID); + } - // fill one chain - while (currentSpell == lastSpell && !finished) - { - Field* fields = result->Fetch(); + // each key in chains that isn't present in hasPrev is a first rank + for (auto itr = chains.begin(); itr != chains.end(); ++itr) + { + if (hasPrev.count(itr->first)) + continue; - currentSpell = fields[0].GetUInt32(); - if (lastSpell == -1) - lastSpell = currentSpell; - uint32 spell_id = fields[1].GetUInt32(); - uint32 rank = fields[2].GetUInt8(); + SpellInfo const* first = GetSpellInfo(itr->first); + SpellInfo const* next = GetSpellInfo(itr->second); - // don't drop the row if we're moving to the next rank - if (currentSpell == lastSpell) - { - rankChain.push_back(std::make_pair(spell_id, rank)); - if (!result->NextRow()) - finished = true; - } - else - break; - } - // check if chain is made with valid first spell - SpellInfo const* first = GetSpellInfo(lastSpell); - if (!first) - { - TC_LOG_ERROR("sql.sql", "The spell rank identifier(first_spell_id) %u listed in `spell_ranks` does not exist!", lastSpell); + if (!first || next) continue; - } - // check if chain is long enough - if (rankChain.size() < 2) - { - TC_LOG_ERROR("sql.sql", "There is only 1 spell rank for identifier(first_spell_id) %u in `spell_ranks`, entry is not needed!", lastSpell); - continue; - } - int32 curRank = 0; - bool valid = true; - // check spells in chain - for (std::list >::iterator itr = rankChain.begin(); itr!= rankChain.end(); ++itr) + + mSpellChains[itr->first].first = first; + mSpellChains[itr->first].prev = nullptr; + mSpellChains[itr->first].next = next; + mSpellChains[itr->first].last = next; + mSpellChains[itr->first].rank = 1; + mSpellInfoMap[itr->first]->ChainEntry = &mSpellChains[itr->first]; + + mSpellChains[itr->second].first = first; + mSpellChains[itr->second].prev = first; + mSpellChains[itr->second].next = nullptr; + mSpellChains[itr->second].last = next; + mSpellChains[itr->second].rank = 2; + mSpellInfoMap[itr->second]->ChainEntry = &mSpellChains[itr->second]; + + uint8 rank = 3; + auto nextItr = chains.find(itr->second); + while (nextItr != chains.end()) { - SpellInfo const* spell = GetSpellInfo(itr->first); - if (!spell) - { - TC_LOG_ERROR("sql.sql", "The spell %u (rank %u) listed in `spell_ranks` for chain %u does not exist!", itr->first, itr->second, lastSpell); - valid = false; - break; - } - ++curRank; - if (itr->second != curRank) - { - TC_LOG_ERROR("sql.sql", "The spell %u (rank %u) listed in `spell_ranks` for chain %u does not have a proper rank value (should be %u)!", itr->first, itr->second, lastSpell, curRank); - valid = false; + SpellInfo const* prev = GetSpellInfo(nextItr->first); // already checked in previous iteration (or above, in case this is the first one) + SpellInfo const* last = GetSpellInfo(nextItr->second); + if (!last) break; - } - } - if (!valid) - continue; - int32 prevRank = 0; - // insert the chain - std::list >::iterator itr = rankChain.begin(); - do - { - ++count; - int32 addedSpell = itr->first; - if (mSpellInfoMap[addedSpell]->ChainEntry) - TC_LOG_ERROR("sql.sql", "The spell %u (rank: %u, first: %u) listed in `spell_ranks` already has ChainEntry from dbc.", addedSpell, itr->second, lastSpell); + mSpellChains[nextItr->first].next = last; - mSpellChains[addedSpell].first = GetSpellInfo(lastSpell); - mSpellChains[addedSpell].last = GetSpellInfo(rankChain.back().first); - mSpellChains[addedSpell].rank = itr->second; - mSpellChains[addedSpell].prev = GetSpellInfo(prevRank); - mSpellInfoMap[addedSpell]->ChainEntry = &mSpellChains[addedSpell]; - prevRank = addedSpell; - ++itr; + mSpellChains[nextItr->second].first = first; + mSpellChains[nextItr->second].prev = prev; + mSpellChains[nextItr->second].next = nullptr; + mSpellChains[nextItr->second].last = last; + mSpellChains[nextItr->second].rank = rank++; + mSpellInfoMap[nextItr->second]->ChainEntry = &mSpellChains[nextItr->second]; - if (itr == rankChain.end()) + // fill 'last' + do { - mSpellChains[addedSpell].next = NULL; - break; - } - else - mSpellChains[addedSpell].next = GetSpellInfo(itr->first); + mSpellChains[prev->Id].last = last; + prev = mSpellChains[prev->Id].prev; + } while (prev); + + nextItr = chains.find(nextItr->second); } - while (true); } - while (!finished); - TC_LOG_INFO("server.loading", ">> Loaded %u spell rank records in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded %u spell rank records in %u ms", uint32(mSpellChains.size()), GetMSTimeDiffToNow(oldMSTime)); } void SpellMgr::LoadSpellRequired() -- cgit v1.2.3 From afa0bac669ac787e6bd35273c967a58b3e4e2196 Mon Sep 17 00:00:00 2001 From: Naios Date: Wed, 15 Jun 2016 19:58:21 +0200 Subject: Core/Common: Add the linkage type to the version string * Add platform strings for intel and apple * Remove usage of underscore uppercase identifiers because those are reserved for the compiler. * Requested by Aokromes --- src/common/GitRevision.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp index 2b4537db448..1f4c28cd310 100644 --- a/src/common/GitRevision.cpp +++ b/src/common/GitRevision.cpp @@ -46,19 +46,30 @@ char const* GitRevision::GetHotfixesDatabase() return _HOTFIXES_DATABASE; } -#define _PACKAGENAME "TrinityCore" - -char const* GitRevision::GetFullVersion() -{ #if PLATFORM == PLATFORM_WINDOWS -# ifdef _WIN64 - return _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Win64, " _BUILD_DIRECTIVE ")"; -# else - return _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Win32, " _BUILD_DIRECTIVE ")"; -# endif +# ifdef _WIN64 +# define TRINITY_PLATFORM_STR "Win64" +# else +# define TRINITY_PLATFORM_STR "Win32" +# endif +#elif PLATFORM == PLATFORM_APPLE +# define TRINITY_PLATFORM_STR "MacOSX" +#elif PLATFORM == PLATFORM_INTEL +# define TRINITY_PLATFORM_STR "Intel" +#else // PLATFORM_UNIX +# define TRINITY_PLATFORM_STR "Unix" +#endif + +#ifndef TRINITY_API_USE_DYNAMIC_LINKING +# define TRINITY_LINKAGE_TYPE_STR "Static" #else - return _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Unix, " _BUILD_DIRECTIVE ")"; +# define TRINITY_LINKAGE_TYPE_STR "Dynamic" #endif + +char const* GitRevision::GetFullVersion() +{ + return "TrinityCore rev. " VER_PRODUCTVERSION_STR + " (" TRINITY_PLATFORM_STR ", " _BUILD_DIRECTIVE ", " TRINITY_LINKAGE_TYPE_STR ")"; } char const* GitRevision::GetCompanyNameStr() -- cgit v1.2.3 From be0ce1c4d32b3b29c11db771ddf2024c3da29cce Mon Sep 17 00:00:00 2001 From: Aokromes Date: Thu, 16 Jun 2016 15:49:27 +0200 Subject: Scripts/Ulduar: Remove removed achievement Closes #17387 --- .../Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 33afada15fd..3a7d8547cc9 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -1366,17 +1366,6 @@ class spell_algalon_supermassive_fail : public SpellScriptLoader } }; -class achievement_he_feeds_on_your_tears : public AchievementCriteriaScript -{ - public: - achievement_he_feeds_on_your_tears() : AchievementCriteriaScript("achievement_he_feeds_on_your_tears") { } - - bool OnCheck(Player* /*source*/, Unit* target) override - { - return !target->GetAI()->GetData(DATA_HAS_FED_ON_TEARS); - } -}; - void AddSC_boss_algalon_the_observer() { new boss_algalon_the_observer(); @@ -1393,5 +1382,4 @@ void AddSC_boss_algalon_the_observer() new spell_algalon_cosmic_smash(); new spell_algalon_cosmic_smash_damage(); new spell_algalon_supermassive_fail(); - new achievement_he_feeds_on_your_tears(); } -- cgit v1.2.3 From cfc40f2cccee891dba364a9cefb3ab0057a7d7fc Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 16 Jun 2016 17:47:10 +0200 Subject: Core/Auras: Defined more aura types --- src/server/game/Spells/Auras/SpellAuraDefines.h | 6 +++--- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 69e7ee53f68..70a08d05d5f 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -515,9 +515,9 @@ enum AuraType SPELL_AURA_455 = 455, SPELL_AURA_CHARGE_RECOVERY_AFFECTED_BY_HASTE = 456, SPELL_AURA_CHARGE_RECOVERY_AFFECTED_BY_HASTE_REGEN = 457, - SPELL_AURA_IGNORE_DUAL_WIELD_HIT_PENALTY = 458, // NYI - SPELL_AURA_459 = 459, - SPELL_AURA_460 = 460, + SPELL_AURA_IGNORE_DUAL_WIELD_HIT_PENALTY = 458, // NYI + SPELL_AURA_IGNORE_MOVEMENT_FORCES = 459, // NYI + SPELL_AURA_RESET_COOLDOWNS_ON_DUEL_START = 460, // NYI SPELL_AURA_461 = 461, SPELL_AURA_462 = 462, SPELL_AURA_CONVER_CRIT_RATING_PCT_TO_PARRY_RATING = 463, // NYI diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 772fac2673d..34bd7e66ac2 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -518,8 +518,8 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNoImmediateEffect, //456 SPELL_AURA_CHARGE_RECOVERY_AFFECTED_BY_HASTE implemented in SpellHistory::GetChargeRecoveryTime &AuraEffect::HandleNoImmediateEffect, //457 SPELL_AURA_CHARGE_RECOVERY_AFFECTED_BY_HASTE_REGEN implemented in SpellHistory::GetChargeRecoveryTime &AuraEffect::HandleNULL, //458 SPELL_AURA_IGNORE_DUAL_WIELD_HIT_PENALTY - &AuraEffect::HandleNULL, //459 - &AuraEffect::HandleNULL, //460 + &AuraEffect::HandleNULL, //459 SPELL_AURA_IGNORE_MOVEMENT_FORCES + &AuraEffect::HandleNULL, //460 SPELL_AURA_RESET_COOLDOWNS_ON_DUEL_START &AuraEffect::HandleNULL, //461 &AuraEffect::HandleNULL, //462 &AuraEffect::HandleNULL, //463 SPELL_AURA_CRIT_RATING_AFFECTS_PARRY used by Riposte -- cgit v1.2.3 From 5fdeb0667532b1ca76f4fa097ecef782eafbbeb7 Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 17 Jun 2016 18:33:54 +0200 Subject: Core/Quests: Fixed loading quest objective progress Closes #17297 --- src/server/game/Entities/Player/Player.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index e3d114e367c..1aab9f001ed 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -17777,7 +17777,6 @@ void Player::_LoadQuestStatus(PreparedQueryResult result) void Player::_LoadQuestStatusObjectives(PreparedQueryResult result) { - uint16 slot = 0; //// 0 1 2 //QueryResult* result = CharacterDatabase.PQuery("SELECT quest, objective, data WHERE guid = '%u'", GetGUIDLow()); @@ -17790,8 +17789,9 @@ void Player::_LoadQuestStatusObjectives(PreparedQueryResult result) uint32 questID = fields[0].GetUInt32(); + uint16 slot = FindQuestSlot(questID); auto itr = m_QuestStatus.find(questID); - if (itr != m_QuestStatus.end()) + if (itr != m_QuestStatus.end() && slot < MAX_QUEST_LOG_SIZE) { QuestStatusData& questStatusData = itr->second; uint8 objectiveIndex = fields[1].GetUInt8(); -- cgit v1.2.3 From 65eb88c8a5ef4f0d07c41b1177b2418903095028 Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 17 Jun 2016 21:17:07 +0200 Subject: Core/Spells: Fixed monk spell Provoke Initial PR submitted by @Infamous-devel Closes #17384 --- sql/updates/world/6.x/2016_06_17_01_world.sql | 3 ++ src/server/scripts/Spells/spell_monk.cpp | 74 ++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 sql/updates/world/6.x/2016_06_17_01_world.sql (limited to 'src') diff --git a/sql/updates/world/6.x/2016_06_17_01_world.sql b/sql/updates/world/6.x/2016_06_17_01_world.sql new file mode 100644 index 00000000000..e5bc16000ce --- /dev/null +++ b/sql/updates/world/6.x/2016_06_17_01_world.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_monk_provoke'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(115546,'spell_monk_provoke'); diff --git a/src/server/scripts/Spells/spell_monk.cpp b/src/server/scripts/Spells/spell_monk.cpp index 904089bc451..e87a76c3e9f 100644 --- a/src/server/scripts/Spells/spell_monk.cpp +++ b/src/server/scripts/Spells/spell_monk.cpp @@ -28,12 +28,13 @@ enum MonkSpells { - SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHANNEL = 117952, - SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHI_PROC = 123333, - SPELL_MONK_STANCE_OF_THE_SPIRITED_CRANE = 154436, - - SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK = 117962, - SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK_CD = 117953, + SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHANNEL = 117952, + SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHI_PROC = 123333, + SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK = 117962, + SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK_CD = 117953, + SPELL_MONK_PROVOKE_SINGLE_TARGET = 116189, + SPELL_MONK_PROVOKE_AOE = 118635, + SPELL_MONK_STANCE_OF_THE_SPIRITED_CRANE = 154436, }; // 117952 - Crackling Jade Lightning @@ -125,8 +126,69 @@ public: } }; +// 115546 - Provoke +class spell_monk_provoke : public SpellScriptLoader +{ +public: + spell_monk_provoke() : SpellScriptLoader("spell_monk_provoke") { } + + class spell_monk_provoke_SpellScript : public SpellScript + { + PrepareSpellScript(spell_monk_provoke_SpellScript); + + static uint32 const BlackOxStatusEntry = 61146; + + bool Validate(SpellInfo const* spellInfo) override + { + if (!(spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT_MASK)) // ensure GetExplTargetUnit() will return something meaningful during CheckCast + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_MONK_PROVOKE_SINGLE_TARGET)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_MONK_PROVOKE_AOE)) + return false; + return true; + } + + SpellCastResult CheckExplicitTarget() + { + if (GetExplTargetUnit()->GetEntry() != BlackOxStatusEntry) + { + SpellInfo const* singleTarget = sSpellMgr->AssertSpellInfo(SPELL_MONK_PROVOKE_SINGLE_TARGET); + SpellCastResult singleTargetExplicitResult = singleTarget->CheckExplicitTarget(GetCaster(), GetExplTargetUnit()); + if (singleTargetExplicitResult != SPELL_CAST_OK) + return singleTargetExplicitResult; + } + else if (GetExplTargetUnit()->GetOwnerGUID() != GetCaster()->GetGUID()) + return SPELL_FAILED_BAD_TARGETS; + + return SPELL_CAST_OK; + } + + void HandleDummy(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + if (GetHitUnit()->GetEntry() != BlackOxStatusEntry) + GetCaster()->CastSpell(GetHitUnit(), SPELL_MONK_PROVOKE_SINGLE_TARGET, true); + else + GetCaster()->CastSpell(GetHitUnit(), SPELL_MONK_PROVOKE_AOE, true); + } + + void Register() override + { + OnCheckCast += SpellCheckCastFn(spell_monk_provoke_SpellScript::CheckExplicitTarget); + OnEffectHitTarget += SpellEffectFn(spell_monk_provoke_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_monk_provoke_SpellScript(); + } +}; + void AddSC_monk_spell_scripts() { new spell_monk_crackling_jade_lightning(); new spell_monk_crackling_jade_lightning_knockback_proc_aura(); + new spell_monk_provoke(); } -- cgit v1.2.3 From 11ed9b0b63115812892903abba82a2d1684d69b9 Mon Sep 17 00:00:00 2001 From: P-Kito Date: Fri, 17 Jun 2016 21:26:51 +0200 Subject: Game/Unit: Update shapeshift forms enum to match SpellShapeshiftForm.dbc (#17407) --- src/server/game/Battlegrounds/Battleground.cpp | 2 +- src/server/game/Entities/Player/Player.cpp | 4 +- src/server/game/Entities/Unit/StatSystem.cpp | 4 +- src/server/game/Entities/Unit/Unit.cpp | 28 ++--- src/server/game/Entities/Unit/Unit.h | 65 +++++------ src/server/game/Spells/Auras/SpellAuraEffects.cpp | 129 +++++++++++----------- src/server/game/Spells/SpellMgr.cpp | 2 +- src/server/scripts/Spells/spell_druid.cpp | 8 +- 8 files changed, 121 insertions(+), 121 deletions(-) (limited to 'src') diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index e96286692d2..8b5622331a8 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -1870,7 +1870,7 @@ uint32 Battleground::GetAlivePlayersCountByTeam(uint32 Team) const if (itr->second.Team == Team) { Player* player = ObjectAccessor::FindPlayer(itr->first); - if (player && player->IsAlive() && !player->HasByteFlag(UNIT_FIELD_BYTES_2, 3, FORM_SPIRITOFREDEMPTION)) + if (player && player->IsAlive() && !player->HasByteFlag(UNIT_FIELD_BYTES_2, 3, FORM_SPIRIT_OF_REDEMPTION)) ++count; } } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 1aab9f001ed..d26ebcc9170 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -20888,13 +20888,13 @@ void Player::InitDataForForm(bool reapplyMods) switch (form) { case FORM_GHOUL: - case FORM_CAT: + case FORM_CAT_FORM: { if (getPowerType() != POWER_ENERGY) setPowerType(POWER_ENERGY); break; } - case FORM_BEAR: + case FORM_BEAR_FORM: { if (getPowerType() != POWER_RAGE) setPowerType(POWER_RAGE); diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 4fa79a91eee..397a4b993db 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -417,12 +417,12 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo if (Item* weapon = GetWeaponForAttack(BASE_ATTACK, true)) weaponSpeed = weapon->GetTemplate()->GetDelay() / 1000; - if (GetShapeshiftForm() == FORM_CAT) + if (GetShapeshiftForm() == FORM_CAT_FORM) { weaponMinDamage = weaponMinDamage / weaponSpeed; weaponMaxDamage = weaponMaxDamage / weaponSpeed; } - else if (GetShapeshiftForm() == FORM_BEAR) + else if (GetShapeshiftForm() == FORM_BEAR_FORM) { weaponMinDamage = weaponMinDamage / weaponSpeed + weaponMinDamage / 2.5; weaponMaxDamage = weaponMinDamage / weaponSpeed + weaponMaxDamage / 2.5; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 8035b3411b7..87bdcf3692a 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -6254,10 +6254,10 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg switch (GetShapeshiftForm()) { case FORM_NONE: trigger_spell_id = 37344; break; - case FORM_CAT: trigger_spell_id = 37341; break; - case FORM_BEAR: trigger_spell_id = 37340; break; - case FORM_TREE: trigger_spell_id = 37342; break; - case FORM_MOONKIN: trigger_spell_id = 37343; break; + case FORM_CAT_FORM: trigger_spell_id = 37341; break; + case FORM_BEAR_FORM: trigger_spell_id = 37340; break; + case FORM_TREE_OF_LIFE: trigger_spell_id = 37342; break; + case FORM_MOONKIN_FORM: trigger_spell_id = 37343; break; default: return false; } @@ -6268,8 +6268,8 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg { switch (GetShapeshiftForm()) { - case FORM_CAT: trigger_spell_id = 67355; break; - case FORM_BEAR: trigger_spell_id = 67354; break; + case FORM_CAT_FORM: trigger_spell_id = 67355; break; + case FORM_BEAR_FORM: trigger_spell_id = 67354; break; default: return false; } @@ -10732,7 +10732,7 @@ void Unit::SetShapeshiftForm(ShapeshiftForm form) bool Unit::IsInFeralForm() const { ShapeshiftForm form = GetShapeshiftForm(); - return form == FORM_CAT || form == FORM_BEAR; + return form == FORM_CAT_FORM || form == FORM_BEAR_FORM; } bool Unit::IsInDisallowedMountForm() const @@ -13183,7 +13183,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) // restore for use at real death victim->SetUInt32Value(PLAYER_SELF_RES_SPELL, ressSpellId); - // FORM_SPIRITOFREDEMPTION and related auras + // FORM_SPIRIT_OF_REDEMPTION and related auras victim->CastSpell(victim, 27827, true, NULL, aurEff); spiritOfRedemption = true; break; @@ -14271,7 +14271,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const { switch (form) { - case FORM_CAT: + case FORM_CAT_FORM: // Based on Hair color if (getRace() == RACE_NIGHTELF) { @@ -14419,7 +14419,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const return 892; else return 8571; - case FORM_BEAR: + case FORM_BEAR_FORM: // Based on Hair color if (getRace() == RACE_NIGHTELF) { @@ -14567,17 +14567,17 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const return 2281; else return 2289; - case FORM_FLIGHT: + case FORM_FLIGHT_FORM: if (Player::TeamForRace(getRace()) == ALLIANCE) return 20857; return 20872; - case FORM_FLIGHT_EPIC: + case FORM_FLIGHT_FORM_EPIC: if (Player::TeamForRace(getRace()) == ALLIANCE) return (getRace() == RACE_WORGEN ? 37729 : 21243); if (getRace() == RACE_TROLL) return 37730; return 21244; - case FORM_MOONKIN: + case FORM_MOONKIN_FORM: switch (getRace()) { case RACE_NIGHTELF: @@ -14592,7 +14592,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const break; } break; - case FORM_GHOSTWOLF: + case FORM_GHOST_WOLF: if (HasAura(58135)) //! Glyph of Arctic Wolf return 27312; default: diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 05149a4cd0a..48e7cb86fcf 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -260,37 +260,40 @@ enum UnitBytes1_Flags // high byte (3 from 0..3) of UNIT_FIELD_BYTES_2 enum ShapeshiftForm { - FORM_NONE = 0x00, - FORM_CAT = 0x01, - FORM_TREE = 0x02, - FORM_TRAVEL = 0x03, - FORM_AQUA = 0x04, - FORM_BEAR = 0x05, - FORM_AMBIENT = 0x06, - FORM_GHOUL = 0x07, - FORM_DIREBEAR = 0x08, // Removed in 4.0.1 - FORM_STEVES_GHOUL = 0x09, - FORM_THARONJA_SKELETON = 0x0A, - FORM_TEST_OF_STRENGTH = 0x0B, - FORM_BLB_PLAYER = 0x0C, - FORM_SHADOW_DANCE = 0x0D, - FORM_CREATUREBEAR = 0x0E, - FORM_CREATURECAT = 0x0F, - FORM_GHOSTWOLF = 0x10, - FORM_BATTLESTANCE = 0x11, - FORM_DEFENSIVESTANCE = 0x12, - FORM_BERSERKERSTANCE = 0x13, - FORM_TEST = 0x14, - FORM_ZOMBIE = 0x15, - FORM_METAMORPHOSIS = 0x16, - FORM_UNDEAD = 0x19, - FORM_MASTER_ANGLER = 0x1A, - FORM_FLIGHT_EPIC = 0x1B, - FORM_SHADOW = 0x1C, - FORM_FLIGHT = 0x1D, - FORM_STEALTH = 0x1E, - FORM_MOONKIN = 0x1F, - FORM_SPIRITOFREDEMPTION = 0x20 + FORM_NONE = 0, + FORM_CAT_FORM = 1, + FORM_TREE_OF_LIFE = 2, + FORM_TRAVEL_FORM = 3, + FORM_AQUATIC_FORM = 4, + FORM_BEAR_FORM = 5, + FORM_AMBIENT = 6, + FORM_GHOUL = 7, + FORM_DIRE_BEAR_FORM = 8, + FORM_CRANE_STANCE = 9, + FORM_THARONJA_SKELETON = 10, + FORM_DARKMOON_TEST_OF_STRENGTH = 11, + FORM_BLB_PLAYER = 12, + FORM_SHADOW_DANCE = 13, + FORM_CREATURE_BEAR = 14, + FORM_CREATURE_CAT = 15, + FORM_GHOST_WOLF = 16, + FORM_BATTLE_STANCE = 17, + FORM_DEFENSIVE_STANCE = 18, + FORM_BERSERKER_STANCE = 19, + FORM_SERPENT_STANCE = 20, + FORM_ZOMBIE = 21, + FORM_METAMORPHOSIS = 22, + FORM_OX_STANCE = 23, + FORM_TIGER_STANCE = 24, + FORM_UNDEAD = 25, + FORM_FRENZY = 26, + FORM_FLIGHT_FORM_EPIC = 27, + FORM_SHADOWFORM = 28, + FORM_FLIGHT_FORM = 29, + FORM_STEALTH = 30, + FORM_MOONKIN_FORM = 31, + FORM_SPIRIT_OF_REDEMPTION = 32, + FORM_GLADIATOR_STANCE = 33 }; // low byte (0 from 0..3) of UNIT_FIELD_BYTES_2 diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 34bd7e66ac2..f205ac03e01 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1275,40 +1275,40 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const switch (GetMiscValue()) { - case FORM_CAT: + case FORM_CAT_FORM: spellId = 3025; break; - case FORM_TREE: + case FORM_TREE_OF_LIFE: spellId = 34123; break; - case FORM_TRAVEL: + case FORM_TRAVEL_FORM: spellId = 5419; break; - case FORM_AQUA: + case FORM_AQUATIC_FORM: spellId = 5421; break; - case FORM_BEAR: + case FORM_BEAR_FORM: spellId = 1178; spellId2 = 21178; break; - case FORM_BATTLESTANCE: + case FORM_BATTLE_STANCE: spellId = 21156; break; - case FORM_DEFENSIVESTANCE: + case FORM_DEFENSIVE_STANCE: spellId = 7376; break; - case FORM_BERSERKERSTANCE: + case FORM_BERSERKER_STANCE: spellId = 7381; break; - case FORM_MOONKIN: + case FORM_MOONKIN_FORM: spellId = 24905; spellId2 = 24907; break; - case FORM_FLIGHT: + case FORM_FLIGHT_FORM: spellId = 33948; spellId2 = 34764; break; - case FORM_FLIGHT_EPIC: + case FORM_FLIGHT_FORM_EPIC: spellId = 40122; spellId2 = 40121; break; @@ -1316,21 +1316,19 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const spellId = 54817; spellId2 = 54879; break; - case FORM_SPIRITOFREDEMPTION: + case FORM_SPIRIT_OF_REDEMPTION: spellId = 27792; spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation. break; - case FORM_SHADOW: + case FORM_SHADOWFORM: spellId = 49868; break; - case FORM_GHOSTWOLF: + case FORM_GHOST_WOLF: spellId = 67116; break; case FORM_GHOUL: case FORM_AMBIENT: case FORM_STEALTH: - case FORM_CREATURECAT: - case FORM_CREATUREBEAR: break; default: break; @@ -1395,7 +1393,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const switch (GetMiscValue()) { - case FORM_CAT: + case FORM_CAT_FORM: // Savage Roar if (target->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_DRUID, flag128(0, 0x10000000, 0))) target->CastSpell(target, 62071, true); @@ -1421,7 +1419,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const target->CastCustomSpell(target, 48420, &bp, NULL, NULL, true); } break; - case FORM_BEAR: + case FORM_BEAR_FORM: // Master Shapeshifter - Bear if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_HEALING_DONE_PERCENT, SPELLFAMILY_GENERIC, 2851, EFFECT_0)) { @@ -1429,7 +1427,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const target->CastCustomSpell(target, 48418, &bp, NULL, NULL, true); } break; - case FORM_MOONKIN: + case FORM_MOONKIN_FORM: // Master Shapeshifter - Moonkin if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_HEALING_DONE_PERCENT, SPELLFAMILY_GENERIC, 2851, EFFECT_0)) { @@ -1784,44 +1782,43 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo switch (form) { - case FORM_CAT: // 0x01 - case FORM_GHOUL: // 0x07 + case FORM_CAT_FORM: + case FORM_GHOUL: + case FORM_TIGER_STANCE: + case FORM_OX_STANCE: PowerType = POWER_ENERGY; break; - case FORM_BEAR: // 0x05 + case FORM_BEAR_FORM: - case FORM_BATTLESTANCE: // 0x11 - case FORM_DEFENSIVESTANCE: // 0x12 - case FORM_BERSERKERSTANCE: // 0x13 + case FORM_BATTLE_STANCE: + case FORM_DEFENSIVE_STANCE: + case FORM_BERSERKER_STANCE: PowerType = POWER_RAGE; break; - case FORM_TREE: // 0x02 - case FORM_TRAVEL: // 0x03 - case FORM_AQUA: // 0x04 - case FORM_AMBIENT: // 0x06 - - case FORM_STEVES_GHOUL: // 0x09 - case FORM_THARONJA_SKELETON: // 0x0A - case FORM_TEST_OF_STRENGTH: // 0x0B - case FORM_BLB_PLAYER: // 0x0C - case FORM_SHADOW_DANCE: // 0x0D - case FORM_CREATUREBEAR: // 0x0E - case FORM_CREATURECAT: // 0x0F - case FORM_GHOSTWOLF: // 0x10 - - case FORM_TEST: // 0x14 - case FORM_ZOMBIE: // 0x15 - case FORM_METAMORPHOSIS: // 0x16 - case FORM_UNDEAD: // 0x19 - case FORM_MASTER_ANGLER: // 0x1A - case FORM_FLIGHT_EPIC: // 0x1B - case FORM_SHADOW: // 0x1C - case FORM_FLIGHT: // 0x1D - case FORM_STEALTH: // 0x1E - case FORM_MOONKIN: // 0x1F - case FORM_SPIRITOFREDEMPTION: // 0x20 + case FORM_TREE_OF_LIFE: + case FORM_TRAVEL_FORM: + case FORM_AQUATIC_FORM: + case FORM_AMBIENT: + + case FORM_THARONJA_SKELETON: + case FORM_DARKMOON_TEST_OF_STRENGTH: + case FORM_BLB_PLAYER: + case FORM_SHADOW_DANCE: + case FORM_CRANE_STANCE: + case FORM_GHOST_WOLF: + + case FORM_SERPENT_STANCE: + case FORM_ZOMBIE: + case FORM_METAMORPHOSIS: + case FORM_UNDEAD: + case FORM_FLIGHT_FORM_EPIC: + case FORM_SHADOWFORM: + case FORM_FLIGHT_FORM: + case FORM_STEALTH: + case FORM_MOONKIN_FORM: + case FORM_SPIRIT_OF_REDEMPTION: break; default: TC_LOG_ERROR("spells", "Auras: Unknown Shapeshift Type: %u", GetMiscValue()); @@ -1834,14 +1831,14 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo // remove polymorph before changing display id to keep new display id switch (form) { - case FORM_CAT: - case FORM_TREE: - case FORM_TRAVEL: - case FORM_AQUA: - case FORM_BEAR: - case FORM_FLIGHT_EPIC: - case FORM_FLIGHT: - case FORM_MOONKIN: + case FORM_CAT_FORM: + case FORM_TREE_OF_LIFE: + case FORM_TRAVEL_FORM: + case FORM_AQUATIC_FORM: + case FORM_BEAR_FORM: + case FORM_FLIGHT_FORM_EPIC: + case FORM_FLIGHT_FORM: + case FORM_MOONKIN_FORM: { // remove movement affects target->RemoveMovementImpairingAuras(); @@ -1869,14 +1866,14 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo if (target->getPowerType() != PowerType) target->setPowerType(PowerType); - if (form == FORM_CAT || form == FORM_BEAR) + if (form == FORM_CAT_FORM || form == FORM_BEAR_FORM) { // get furor proc chance int32 FurorChance = 0; if (AuraEffect const* dummy = target->GetDummyAuraEffect(SPELLFAMILY_DRUID, 238, 0)) FurorChance = std::max(dummy->GetAmount(), 0); - if (form == FORM_CAT) + if (form == FORM_CAT_FORM) { int32 basePoints = std::min(oldPower, FurorChance); target->SetPower(POWER_ENERGY, 0); @@ -1919,19 +1916,19 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo switch (form) { // Nordrassil Harness - bonus - case FORM_BEAR: - case FORM_CAT: + case FORM_BEAR_FORM: + case FORM_CAT_FORM: if (AuraEffect* dummy = target->GetAuraEffect(37315, 0)) target->CastSpell(target, 37316, true, NULL, dummy); break; // Nordrassil Regalia - bonus - case FORM_MOONKIN: + case FORM_MOONKIN_FORM: if (AuraEffect* dummy = target->GetAuraEffect(37324, 0)) target->CastSpell(target, 37325, true, NULL, dummy); break; - case FORM_BATTLESTANCE: - case FORM_DEFENSIVESTANCE: - case FORM_BERSERKERSTANCE: + case FORM_BATTLE_STANCE: + case FORM_DEFENSIVE_STANCE: + case FORM_BERSERKER_STANCE: { int32 Rage_val = 0; // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index e99c4bd661f..4e9a6363e8d 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3385,7 +3385,7 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CAST | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_JUMP; break; case 5420: // Tree of Life (Passive) - spellInfo->Stances = UI64LIT(1) << (FORM_TREE - 1); + spellInfo->Stances = UI64LIT(1) << (FORM_TREE_OF_LIFE - 1); break; case 49376: // Feral Charge (Cat Form) spellInfo->AttributesEx3 &= ~SPELL_ATTR3_CANT_TRIGGER_PROC; diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 4488561589f..d82e9920df2 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -74,7 +74,7 @@ class spell_dru_dash : public SpellScriptLoader void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) { // do not set speed if not in cat form - if (GetUnitOwner()->GetShapeshiftForm() != FORM_CAT) + if (GetUnitOwner()->GetShapeshiftForm() != FORM_CAT_FORM) amount = 0; } @@ -767,7 +767,7 @@ class spell_dru_savage_roar : public SpellScriptLoader SpellCastResult CheckCast() { Unit* caster = GetCaster(); - if (caster->GetShapeshiftForm() != FORM_CAT) + if (caster->GetShapeshiftForm() != FORM_CAT_FORM) return SPELL_FAILED_ONLY_SHAPESHIFT; return SPELL_CAST_OK; @@ -889,7 +889,7 @@ class spell_dru_stampede : public SpellScriptLoader void HandleEffectCatProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) { PreventDefaultAction(); - if (GetTarget()->GetShapeshiftForm() != FORM_CAT || eventInfo.GetDamageInfo()->GetSpellInfo()->Id != SPELL_DRUID_FERAL_CHARGE_CAT) + if (GetTarget()->GetShapeshiftForm() != FORM_CAT_FORM || eventInfo.GetDamageInfo()->GetSpellInfo()->Id != SPELL_DRUID_FERAL_CHARGE_CAT) return; GetTarget()->CastSpell(GetTarget(), sSpellMgr->GetSpellWithRank(SPELL_DRUID_STAMPEDE_CAT_RANK_1, GetSpellInfo()->GetRank()), true, NULL, aurEff); @@ -899,7 +899,7 @@ class spell_dru_stampede : public SpellScriptLoader void HandleEffectBearProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) { PreventDefaultAction(); - if (GetTarget()->GetShapeshiftForm() != FORM_BEAR || eventInfo.GetDamageInfo()->GetSpellInfo()->Id != SPELL_DRUID_FERAL_CHARGE_BEAR) + if (GetTarget()->GetShapeshiftForm() != FORM_BEAR_FORM || eventInfo.GetDamageInfo()->GetSpellInfo()->Id != SPELL_DRUID_FERAL_CHARGE_BEAR) return; GetTarget()->CastSpell(GetTarget(), sSpellMgr->GetSpellWithRank(SPELL_DRUID_STAMPEDE_BAER_RANK_1, GetSpellInfo()->GetRank()), true, NULL, aurEff); -- cgit v1.2.3 From f6637439f484dacc9c8deb3c4dd07832146ff6f6 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 18 Jun 2016 16:23:55 +0200 Subject: Core/Items: Updated max durability calculation --- src/server/game/Globals/ObjectMgr.cpp | 54 +++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 96936a82d08..9cae9926477 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2325,26 +2325,26 @@ uint32 FillMaxDurability(uint32 itemClass, uint32 itemSubClass, uint32 inventory static float const qualityMultipliers[MAX_ITEM_QUALITY] = { - 1.0f, 1.0f, 1.0f, 1.17f, 1.37f, 1.68f, 0.0f, 0.0f + 0.92f, 0.92f, 0.92f, 1.11f, 1.32f, 1.61f, 0.0f, 0.0f }; static float const armorMultipliers[MAX_INVTYPE] = { 0.00f, // INVTYPE_NON_EQUIP - 0.59f, // INVTYPE_HEAD + 0.60f, // INVTYPE_HEAD 0.00f, // INVTYPE_NECK - 0.59f, // INVTYPE_SHOULDERS + 0.60f, // INVTYPE_SHOULDERS 0.00f, // INVTYPE_BODY 1.00f, // INVTYPE_CHEST - 0.35f, // INVTYPE_WAIST - 0.75f, // INVTYPE_LEGS - 0.49f, // INVTYPE_FEET - 0.35f, // INVTYPE_WRISTS - 0.35f, // INVTYPE_HANDS + 0.33f, // INVTYPE_WAIST + 0.72f, // INVTYPE_LEGS + 0.48f, // INVTYPE_FEET + 0.33f, // INVTYPE_WRISTS + 0.33f, // INVTYPE_HANDS 0.00f, // INVTYPE_FINGER 0.00f, // INVTYPE_TRINKET 0.00f, // INVTYPE_WEAPON - 1.00f, // INVTYPE_SHIELD + 0.72f, // INVTYPE_SHIELD 0.00f, // INVTYPE_RANGED 0.00f, // INVTYPE_CLOAK 0.00f, // INVTYPE_2HWEAPON @@ -2363,27 +2363,27 @@ uint32 FillMaxDurability(uint32 itemClass, uint32 itemSubClass, uint32 inventory static float const weaponMultipliers[MAX_ITEM_SUBCLASS_WEAPON] = { - 0.89f, // ITEM_SUBCLASS_WEAPON_AXE - 1.03f, // ITEM_SUBCLASS_WEAPON_AXE2 - 0.77f, // ITEM_SUBCLASS_WEAPON_BOW - 0.77f, // ITEM_SUBCLASS_WEAPON_GUN - 0.89f, // ITEM_SUBCLASS_WEAPON_MACE - 1.03f, // ITEM_SUBCLASS_WEAPON_MACE2 - 1.03f, // ITEM_SUBCLASS_WEAPON_POLEARM - 0.89f, // ITEM_SUBCLASS_WEAPON_SWORD - 1.03f, // ITEM_SUBCLASS_WEAPON_SWORD2 + 0.91f, // ITEM_SUBCLASS_WEAPON_AXE + 1.00f, // ITEM_SUBCLASS_WEAPON_AXE2 + 1.00f, // ITEM_SUBCLASS_WEAPON_BOW + 1.00f, // ITEM_SUBCLASS_WEAPON_GUN + 0.91f, // ITEM_SUBCLASS_WEAPON_MACE + 1.00f, // ITEM_SUBCLASS_WEAPON_MACE2 + 1.00f, // ITEM_SUBCLASS_WEAPON_POLEARM + 0.91f, // ITEM_SUBCLASS_WEAPON_SWORD + 1.00f, // ITEM_SUBCLASS_WEAPON_SWORD2 0.00f, // ITEM_SUBCLASS_WEAPON_Obsolete - 1.03f, // ITEM_SUBCLASS_WEAPON_STAFF + 1.00f, // ITEM_SUBCLASS_WEAPON_STAFF 0.00f, // ITEM_SUBCLASS_WEAPON_EXOTIC 0.00f, // ITEM_SUBCLASS_WEAPON_EXOTIC2 - 0.64f, // ITEM_SUBCLASS_WEAPON_FIST_WEAPON + 0.66f, // ITEM_SUBCLASS_WEAPON_FIST_WEAPON 0.00f, // ITEM_SUBCLASS_WEAPON_MISCELLANEOUS - 0.64f, // ITEM_SUBCLASS_WEAPON_DAGGER - 0.64f, // ITEM_SUBCLASS_WEAPON_THROWN + 0.66f, // ITEM_SUBCLASS_WEAPON_DAGGER + 0.00f, // ITEM_SUBCLASS_WEAPON_THROWN 0.00f, // ITEM_SUBCLASS_WEAPON_SPEAR - 0.77f, // ITEM_SUBCLASS_WEAPON_CROSSBOW - 0.64f, // ITEM_SUBCLASS_WEAPON_WAND - 0.64f, // ITEM_SUBCLASS_WEAPON_FISHING_POLE + 1.00f, // ITEM_SUBCLASS_WEAPON_CROSSBOW + 0.66f, // ITEM_SUBCLASS_WEAPON_WAND + 0.66f, // ITEM_SUBCLASS_WEAPON_FISHING_POLE }; float levelPenalty = 1.0f; @@ -2395,10 +2395,10 @@ uint32 FillMaxDurability(uint32 itemClass, uint32 itemSubClass, uint32 inventory if (inventoryType > INVTYPE_ROBE) return 0; - return 5 * uint32(23.0f * qualityMultipliers[quality] * armorMultipliers[inventoryType] * levelPenalty + 0.5f); + return 5 * uint32(round(25.0f * qualityMultipliers[quality] * armorMultipliers[inventoryType] * levelPenalty)); } - return 5 * uint32(17.0f * qualityMultipliers[quality] * weaponMultipliers[itemSubClass] * levelPenalty + 0.5f); + return 5 * uint32(round(18.0f * qualityMultipliers[quality] * weaponMultipliers[itemSubClass] * levelPenalty)); }; void FillDisenchantFields(uint32* disenchantID, uint32* requiredDisenchantSkill, ItemTemplate const& itemTemplate) -- cgit v1.2.3 From 78b31e963795f62700e06b1d5266172772394327 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 19 Jun 2016 11:25:47 +0200 Subject: Tools/Patcher: Fixed client crashes happening on macs Closes #16872 --- src/tools/connection_patcher/Patches/Common.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/connection_patcher/Patches/Common.hpp b/src/tools/connection_patcher/Patches/Common.hpp index 22e22beedcd..58215a42419 100644 --- a/src/tools/connection_patcher/Patches/Common.hpp +++ b/src/tools/connection_patcher/Patches/Common.hpp @@ -66,7 +66,7 @@ R"({ "SigningCertificates": [ { "RawData": "-----BEGIN CERTIFICATE-----MIIF5DCCA8ygAwIBAgIJAIgLslwk40XzMA0GCSqGSIb3DQEBCwUAMH8xCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtUcmluaXR5Q29yZTEqMCgGA1UECwwhVHJpbml0eUNvcmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MS4wLAYDVQQDDCVUcmluaXR5Q29yZSBCYXR0bGUubmV0IEF1cm9yYSBSb290IENBMB4XDTE2MDIyODEyNDkwOFoXDTM2MDIyMzEyNDkwOFowfzELMAkGA1UEBhMCVVMxFDASBgNVBAoMC1RyaW5pdHlDb3JlMSowKAYDVQQLDCFUcmluaXR5Q29yZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxLjAsBgNVBAMMJVRyaW5pdHlDb3JlIEJhdHRsZS5uZXQgQXVyb3JhIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGrYWvS0mVParJd96E4z/qjCvW6eR0buQ++VNEqVgeG14k4V41wkEzakB4nr2oGH10z9J/aqLlWnxaOl+yJ7BaomUAAOgJaCyqAJ8HaEU+7BbDO4MZXmtw1A3YcHsBkVx5wGm3tcH5IEXfVhvNZDqwAmYIcm7gKFgnds6RFJmRxF4WznWiRr2MQkSOr/kc2eQ2VUg5afTlTxZva/mXEVpShinvbhaMSgFBW+QahCwBJVQaLhEn+Wc6YNuHFmZ/i716xGb3cuYu89TF46iKQ/9Bm8yEFGg8QA28IZQ1sXgVpzJI9eowFtqAwhl65ipjGw4xH33of+WcwJQNjF7HXymRqk0WAa2jtXOEiShI3XDloblX7vKbAe9RFpfVIqT8UfKSOJGQDVzvl4wSihINshO7YgIqp97MGnWtnlWCDb2mcSj8JjnzRjG2kZZCNR/2lgfCG/1VF+QLh/3vD2+N5YkJZqBK1JTFFx+p66lVQWfdh2MXPlGjat343HZGm0YR7nRjngO2j3YtTojdJxRfLgztQv94jMtWPHE38ysUK7mS6KKqYXqyB19IOHL2QB8fjmON1hCd0wDW42ZB23ywNkASw6uJDR02xXN2wiynIIb3cz6zouXd60wC7utMTveq8+rhFFgmFDdI2o9gwWQPA/43OYIlAdKVg2NRhXb/6bzFkwIDAQABo2MwYTAdBgNVHQ4EFgQUEt6gxhfmHEc7rBOqHJEfNkzGv3MwHwYDVR0jBBgwFoAUEt6gxhfmHEc7rBOqHJEfNkzGv3MwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAFzCJkcDCPVMal+Thlip26LPkszZ4zWTsNsbUYmSe7h0kmMWt4x3mmZITfwb/eysYCnHThBVTjXj9VWBGfbECZ/xdyXC2ur+qp0Mm7xH2Wuswf7yfPC+USNO6+/tFS282FO/nM0quaKVknOC8ioCoASsBICB9lwRoYRKNBwRn3pkJplHepGahaJez4eedujO3dzxDdD32zy2/AfdeFXTxhWY8PTjMBKC2zpUQD7Kdvl+D8SfIsq73b8a9XmhdNX7qTc6MjecCD7WHAP2rrK7epjTaVJp4+PYlw7qfix/NT1fNkq2Mb2E77h2eToUG1mjs/mvG/4WfVCfMaBHOKaw6fyZULf366Jbx02r8K05P5ouvS1Z0De1mZJuUEUYhTRSs2POIdrmVrn9R83Y4l7TKNPJelq2uyEc4r+/fRrerIlT4HVlLPTC3SdW8ytYSUZXx+1NfJfQimieveIyIaTOV3SfC4EfeXtPtUpcVJvmFXqVbnXOO7bQU63bfFuuVSeU6OXWjoFRVkdHNYTGUGb5xg4hgWqlLWvWg0WPgLLabMbetrP6c5/Qhml/l07nJHeLoVxlFuwsL8HGeu0JWqnmwamp4/mmblRC9UfyrIQeDS8gsx8q/t2zdzT4bBph0nqYkZSyiIoQzlMrYdrWxeJm3sReR0G3FluL+03TGJypGfhr-----END CERTIFICATE-----" } ] -};inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature)"; +}NGISerting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature_inserting_dummy_signature)"; } }; } -- cgit v1.2.3 From 688635ff9280ebece98d74ded5ed1f3c618718c0 Mon Sep 17 00:00:00 2001 From: Shauren Date: Mon, 20 Jun 2016 17:04:12 +0200 Subject: Core/Players: Fixed learning riding --- src/server/game/Entities/Player/Player.cpp | 16 ++++++++++++---- src/server/game/Server/Packets/SpellPackets.cpp | 14 ++++++++++++++ src/server/game/Server/Packets/SpellPackets.h | 11 +++++++++++ src/server/game/Server/Protocol/Opcodes.cpp | 2 +- src/server/game/Spells/SpellMgr.cpp | 13 ++++--------- 5 files changed, 42 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index d26ebcc9170..c28d2884a01 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2905,6 +2905,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent bool dependent_set = false; bool disabled_case = false; + bool superceded_old = false; PlayerSpellMap::iterator itr = m_spells.find(spellId); @@ -3052,6 +3053,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent itr2->second->active = false; if (itr2->second->state != PLAYERSPELL_NEW) itr2->second->state = PLAYERSPELL_CHANGED; + superceded_old = true; // new spell replace old in action bars and spell book. } else { @@ -3171,7 +3173,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent } // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell - return active && !disabled; + return active && !disabled && !superceded_old; } void Player::AddTemporarySpell(uint32 spellId) @@ -22646,6 +22648,11 @@ void Player::LearnQuestRewardedSpells() void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue) { + // bad hack to work around data being suited only for the client - AcquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN for riding + // client uses it to show riding in spellbook as trainable + if (skillId == SKILL_RIDING) + return; + uint32 raceMask = getRaceMask(); uint32 classMask = getClassMask(); for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) @@ -26059,9 +26066,10 @@ void Player::SendUpdatePhasing() void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell) const { - WorldPacket data(SMSG_SUPERCEDED_SPELLS, 8); - data << uint32(newSpell) << uint32(oldSpell); - GetSession()->SendPacket(&data); + WorldPackets::Spells::SupercededSpells supercededSpells; + supercededSpells.SpellID.push_back(newSpell); + supercededSpells.Superceded.push_back(oldSpell); + GetSession()->SendPacket(supercededSpells.Write()); } uint32 Player::CalculateTalentsTiers() const diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp index aa78cae6deb..c319be3811d 100644 --- a/src/server/game/Server/Packets/SpellPackets.cpp +++ b/src/server/game/Server/Packets/SpellPackets.cpp @@ -428,6 +428,20 @@ WorldPacket const* WorldPackets::Spells::LearnedSpells::Write() return &_worldPacket; } +WorldPacket const* WorldPackets::Spells::SupercededSpells::Write() +{ + _worldPacket << uint32(SpellID.size()); + _worldPacket << uint32(Superceded.size()); + + if (!SpellID.empty()) + _worldPacket.append(SpellID.data(), SpellID.size()); + + if (!Superceded.empty()) + _worldPacket.append(Superceded.data(), Superceded.size()); + + return &_worldPacket; +} + WorldPacket const* WorldPackets::Spells::SpellFailure::Write() { _worldPacket << CasterUnit; diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h index b1cb39251de..016fbb89895 100644 --- a/src/server/game/Server/Packets/SpellPackets.h +++ b/src/server/game/Server/Packets/SpellPackets.h @@ -392,6 +392,17 @@ namespace WorldPackets bool SuppressMessaging = false; }; + class SupercededSpells final : public ServerPacket + { + public: + SupercededSpells() : ServerPacket(SMSG_SUPERCEDED_SPELLS, 4 + 4 + 4 + 4) { } + + WorldPacket const* Write() override; + + std::vector SpellID; + std::vector Superceded; + }; + class SpellFailure final : public ServerPacket { public: diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index a2e4bfe6321..a284d874191 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -1638,7 +1638,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUMMON_CANCEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUMMON_RAID_MEMBER_VALIDATE_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUMMON_REQUEST, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUPERCEDED_SPELLS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUPERCEDED_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUPPRESS_NPC_GREETINGS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_COMMS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 4e9a6363e8d..b2a7a32eab7 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1281,11 +1281,8 @@ void SpellMgr::LoadSpellRanks() if (hasPrev.count(itr->first)) continue; - SpellInfo const* first = GetSpellInfo(itr->first); - SpellInfo const* next = GetSpellInfo(itr->second); - - if (!first || next) - continue; + SpellInfo const* first = AssertSpellInfo(itr->first); + SpellInfo const* next = AssertSpellInfo(itr->second); mSpellChains[itr->first].first = first; mSpellChains[itr->first].prev = nullptr; @@ -1305,10 +1302,8 @@ void SpellMgr::LoadSpellRanks() auto nextItr = chains.find(itr->second); while (nextItr != chains.end()) { - SpellInfo const* prev = GetSpellInfo(nextItr->first); // already checked in previous iteration (or above, in case this is the first one) - SpellInfo const* last = GetSpellInfo(nextItr->second); - if (!last) - break; + SpellInfo const* prev = AssertSpellInfo(nextItr->first); // already checked in previous iteration (or above, in case this is the first one) + SpellInfo const* last = AssertSpellInfo(nextItr->second); mSpellChains[nextItr->first].next = last; -- cgit v1.2.3 From ed00534e7c311530e5fbb1ffb567d9459ff4c1f0 Mon Sep 17 00:00:00 2001 From: frozen4 Date: Tue, 21 Jun 2016 20:33:51 +0200 Subject: Core/Items: Implemented item upgrades Closes #17432 --- .../hotfixes/6.x/2016_06_21_00_hotfixes.sql | 27 ++++++++++ .../Database/Implementation/HotfixDatabase.cpp | 11 +++- .../Database/Implementation/HotfixDatabase.h | 8 ++- src/server/game/DataStores/DB2Stores.cpp | 17 ++++++ src/server/game/DataStores/DB2Stores.h | 4 ++ src/server/game/DataStores/DB2Structure.h | 18 +++++++ src/server/game/DataStores/DB2fmt.h | 2 + src/server/game/Entities/Player/Player.cpp | 3 ++ src/server/game/Handlers/ItemHandler.cpp | 62 ++++++++++++++++++++++ src/server/game/Server/Packets/ItemPackets.cpp | 17 ++++++ src/server/game/Server/Packets/ItemPackets.h | 24 +++++++++ src/server/game/Server/Protocol/Opcodes.cpp | 3 +- src/server/game/Server/Protocol/Opcodes.h | 1 + src/server/game/Server/WorldSession.h | 2 + 14 files changed, 194 insertions(+), 5 deletions(-) create mode 100644 sql/updates/hotfixes/6.x/2016_06_21_00_hotfixes.sql (limited to 'src') diff --git a/sql/updates/hotfixes/6.x/2016_06_21_00_hotfixes.sql b/sql/updates/hotfixes/6.x/2016_06_21_00_hotfixes.sql new file mode 100644 index 00000000000..e2ca7d2ce65 --- /dev/null +++ b/sql/updates/hotfixes/6.x/2016_06_21_00_hotfixes.sql @@ -0,0 +1,27 @@ +-- +-- Table structure for table `item_upgrade` +-- +DROP TABLE IF EXISTS `item_upgrade`; +CREATE TABLE `item_upgrade` ( + `ID` int(10) unsigned NOT NULL DEFAULT '0', + `ItemUpgradePathID` int(10) unsigned NOT NULL DEFAULT '0', + `ItemLevelBonus` int(10) unsigned NOT NULL DEFAULT '0', + `PrevItemUpgradeID` int(10) unsigned NOT NULL DEFAULT '0', + `CurrencyID` int(10) unsigned NOT NULL DEFAULT '0', + `CurrencyCost` int(10) unsigned NOT NULL DEFAULT '0', + `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `ruleset_item_upgrade` +-- +DROP TABLE IF EXISTS `ruleset_item_upgrade`; +CREATE TABLE `ruleset_item_upgrade` ( + `ID` int(10) unsigned NOT NULL DEFAULT '0', + `RulesetID` int(10) unsigned NOT NULL DEFAULT '0', + `ItemUpgradeID` int(10) unsigned NOT NULL DEFAULT '0', + `ItemID` int(10) unsigned NOT NULL DEFAULT '0', + `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp index 6749300000b..c6b03dbf385 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.cpp +++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp @@ -15,8 +15,8 @@ * with this program. If not, see . */ - // DO NOT EDIT! - // Autogenerated from DB2Structure.h +// DO NOT EDIT! +// Autogenerated from DB2Structure.h #include "HotfixDatabase.h" @@ -300,6 +300,10 @@ void HotfixDatabaseConnection::DoPrepareStatements() // ItemToBattlePetSpecies.db2 PrepareStatement(HOTFIX_SEL_ITEM_TO_BATTLE_PET_SPECIES, "SELECT ID, BattlePetSpeciesID FROM item_to_battle_pet_species ORDER BY ID DESC", CONNECTION_SYNCH); + // ItemUpgrade.db2 + PrepareStatement(HOTFIX_SEL_ITEM_UPGRADE, "SELECT ID, ItemUpgradePathID, ItemLevelBonus, PrevItemUpgradeID, CurrencyID, CurrencyCost" + " FROM item_upgrade ORDER BY ID DESC", CONNECTION_SYNCH); + // ItemXBonusTree.db2 PrepareStatement(HOTFIX_SEL_ITEM_X_BONUS_TREE, "SELECT ID, ItemID, BonusTreeID FROM item_x_bonus_tree ORDER BY ID DESC", CONNECTION_SYNCH); @@ -383,6 +387,9 @@ void HotfixDatabaseConnection::DoPrepareStatements() // QuestXp.db2 PrepareStatement(HOTFIX_SEL_QUEST_XP, "SELECT ID, Exp1, Exp2, Exp3, Exp4, Exp5, Exp6, Exp7, Exp8, Exp9, Exp10 FROM quest_xp ORDER BY ID DESC", CONNECTION_SYNCH); + // RulesetItemUpgrade.db2 + PrepareStatement(HOTFIX_SEL_RULESET_ITEM_UPGRADE, "SELECT ID, RulesetID, ItemUpgradeID, ItemID FROM ruleset_item_upgrade ORDER BY ID DESC", CONNECTION_SYNCH); + // ScalingStatDistribution.db2 PrepareStatement(HOTFIX_SEL_SCALING_STAT_DISTRIBUTION, "SELECT ID, MinLevel, MaxLevel, ItemLevelCurveID FROM scaling_stat_distribution" " ORDER BY ID DESC", CONNECTION_SYNCH); diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h index 999c9316dad..cb45187e275 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.h +++ b/src/server/database/Database/Implementation/HotfixDatabase.h @@ -15,8 +15,8 @@ * with this program. If not, see . */ - // DO NOT EDIT! - // Autogenerated from DB2Structure.h +// DO NOT EDIT! +// Autogenerated from DB2Structure.h #ifndef _HOTFIXDATABASE_H #define _HOTFIXDATABASE_H @@ -174,6 +174,8 @@ enum HotfixDatabaseStatements HOTFIX_SEL_ITEM_TO_BATTLE_PET_SPECIES, + HOTFIX_SEL_ITEM_UPGRADE, + HOTFIX_SEL_ITEM_X_BONUS_TREE, HOTFIX_SEL_KEY_CHAIN, @@ -217,6 +219,8 @@ enum HotfixDatabaseStatements HOTFIX_SEL_QUEST_XP, + HOTFIX_SEL_RULESET_ITEM_UPGRADE, + HOTFIX_SEL_SCALING_STAT_DISTRIBUTION, HOTFIX_SEL_SOUND_ENTRIES, diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 2fd9c22b080..f706e52330d 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -83,6 +83,7 @@ DB2Storage sItemSparseStore("Item-sparse.db DB2Storage sItemSpecStore("ItemSpec.db2", ItemSpecFormat, HOTFIX_SEL_ITEM_SPEC); DB2Storage sItemSpecOverrideStore("ItemSpecOverride.db2", ItemSpecOverrideFormat, HOTFIX_SEL_ITEM_SPEC_OVERRIDE); DB2Storage sItemToBattlePetSpeciesStore("ItemToBattlePetSpecies.db2", ItemToBattlePetSpeciesFormat, HOTFIX_SEL_ITEM_TO_BATTLE_PET_SPECIES); +DB2Storage sItemUpgradeStore("ItemUpgrade.db2", ItemUpgradeEntryFormat, HOTFIX_SEL_ITEM_UPGRADE); DB2Storage sItemXBonusTreeStore("ItemXBonusTree.db2", ItemXBonusTreeFormat, HOTFIX_SEL_ITEM_X_BONUS_TREE); DB2Storage sKeyChainStore("KeyChain.db2", KeyChainFormat, HOTFIX_SEL_KEY_CHAIN); DB2Storage sMailTemplateStore("MailTemplate.db2", MailTemplateFormat, HOTFIX_SEL_MAIL_TEMPLATE); @@ -102,6 +103,7 @@ DB2Storage sQuestPackageItemStore("QuestPac DB2Storage sQuestSortStore("QuestSort.db2", QuestSortFormat, HOTFIX_SEL_QUEST_SORT); DB2Storage sQuestV2Store("QuestV2.db2", QuestV2Format, HOTFIX_SEL_QUEST_V2); DB2Storage sQuestXPStore("QuestXP.db2", QuestXPFormat, HOTFIX_SEL_QUEST_XP); +DB2Storage sRulesetItemUpgradeStore("RulesetItemUpgrade.db2", RulesetItemUpgradeEntryFormat, HOTFIX_SEL_RULESET_ITEM_UPGRADE); DB2Storage sScalingStatDistributionStore("ScalingStatDistribution.db2", ScalingStatDistributionFormat, HOTFIX_SEL_SCALING_STAT_DISTRIBUTION); DB2Storage sSoundEntriesStore("SoundEntries.db2", SoundEntriesFormat, HOTFIX_SEL_SOUND_ENTRIES); DB2Storage sSpecializationSpellsStore("SpecializationSpells.db2", SpecializationSpellsFormat, HOTFIX_SEL_SPECIALIZATION_SPELLS); @@ -265,6 +267,7 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) LOAD_DB2(sItemSpecStore); LOAD_DB2(sItemStore); LOAD_DB2(sItemToBattlePetSpeciesStore); + LOAD_DB2(sItemUpgradeStore); LOAD_DB2(sItemXBonusTreeStore); LOAD_DB2(sKeyChainStore); LOAD_DB2(sMailTemplateStore); @@ -284,6 +287,7 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) LOAD_DB2(sQuestSortStore); LOAD_DB2(sQuestV2Store); LOAD_DB2(sQuestXPStore); + LOAD_DB2(sRulesetItemUpgradeStore); LOAD_DB2(sScalingStatDistributionStore); LOAD_DB2(sSoundEntriesStore); LOAD_DB2(sSpecializationSpellsStore); @@ -424,6 +428,10 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) for (QuestPackageItemEntry const* questPackageItem : sQuestPackageItemStore) _questPackages[questPackageItem->QuestPackageID].push_back(questPackageItem); + for (RulesetItemUpgradeEntry const* rulesetItemUpgrade : sRulesetItemUpgradeStore) + if (rulesetItemUpgrade->RulesetID == 1) // xref to Cfg_Regions.db2, RulesetID column. 1 is the value for EU region we send hardcoded in SMSG_INITIAL_SETUP, possible other value for RulesetID is 2 in korean region + _rulesetItemUpgrade[rulesetItemUpgrade->ItemID] = rulesetItemUpgrade->ItemUpgradeID; + for (SpecializationSpellsEntry const* specSpells : sSpecializationSpellsStore) _specializationSpellsBySpec[specSpells->SpecID].push_back(specSpells); @@ -809,6 +817,15 @@ std::set DB2Manager::GetPhasesForGroup(uint32 group) const return std::set(); } +uint32 DB2Manager::GetRulesetItemUpgrade(uint32 itemId) const +{ + auto itr = _rulesetItemUpgrade.find(itemId); + if (itr != _rulesetItemUpgrade.end()) + return itr->second; + + return 0; +} + std::vector const* DB2Manager::GetSpecializationSpells(uint32 specId) const { auto itr = _specializationSpellsBySpec.find(specId); diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index b42d1dd8bab..b7201f7d47d 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -76,6 +76,7 @@ TC_GAME_API extern DB2Storage sItemSparseS TC_GAME_API extern DB2Storage sItemSpecStore; TC_GAME_API extern DB2Storage sItemSpecOverrideStore; TC_GAME_API extern DB2Storage sItemToBattlePetSpeciesStore; +TC_GAME_API extern DB2Storage sItemUpgradeStore; TC_GAME_API extern DB2Storage sMailTemplateStore; TC_GAME_API extern DB2Storage sModifierTreeStore; TC_GAME_API extern DB2Storage sMountCapabilityStore; @@ -158,6 +159,7 @@ public: typedef std::array, TOTAL_LOCALES + 1> NameValidationRegexContainer; typedef std::unordered_map> PhaseGroupContainer; typedef std::unordered_map> QuestPackageItemContainer; + typedef std::unordered_map RulesetItemUpgradeContainer; typedef std::unordered_map> SpecializationSpellsContainer; typedef std::unordered_map> SpellPowerContainer; typedef std::unordered_map>> SpellPowerDifficultyContainer; @@ -192,6 +194,7 @@ public: std::vector const* GetQuestPackageItems(uint32 questPackageID) const; uint32 GetQuestUniqueBitFlag(uint32 questId); std::set GetPhasesForGroup(uint32 group) const; + uint32 GetRulesetItemUpgrade(uint32 itemId) const; std::vector const* GetSpecializationSpells(uint32 specId) const; std::vector GetSpellPowers(uint32 spellId, Difficulty difficulty = DIFFICULTY_NONE, bool* hasDifficultyPowers = nullptr) const; std::vector GetSpellProcsPerMinuteMods(uint32 spellprocsPerMinuteId) const; @@ -217,6 +220,7 @@ private: NameGenContainer _nameGenData; NameValidationRegexContainer _nameValidators; PhaseGroupContainer _phasesByGroup; + RulesetItemUpgradeContainer _rulesetItemUpgrade; QuestPackageItemContainer _questPackages; SpecializationSpellsContainer _specializationSpellsBySpec; SpellPowerContainer _spellPowers; diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index daebcf7375f..685b186f92d 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -879,6 +879,16 @@ struct ItemToBattlePetSpeciesEntry uint32 BattlePetSpeciesID; // 1 }; +struct ItemUpgradeEntry +{ + uint32 ID; // 0 + uint32 ItemUpgradePathID; // 1 + uint32 ItemLevelBonus; // 2 + uint32 PrevItemUpgradeID; // 3 + uint32 CurrencyID; // 4 + uint32 CurrencyCost; // 5 +}; + struct ItemXBonusTreeEntry { uint32 ID; // 0 @@ -1103,6 +1113,14 @@ struct QuestXPEntry uint32 Exp[10]; // 1 }; +struct RulesetItemUpgradeEntry +{ + uint32 ID; // 0 + uint32 RulesetID; // 1 + uint32 ItemUpgradeID; // 2 + uint32 ItemID; // 3 +}; + struct ScalingStatDistributionEntry { uint32 ID; // 0 diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h index 2a64a2d4eb5..ea5ef297b3c 100644 --- a/src/server/game/DataStores/DB2fmt.h +++ b/src/server/game/DataStores/DB2fmt.h @@ -77,6 +77,7 @@ char const ItemSparseFormat[] = "niiiiffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii char const ItemSpecFormat[] = "niiiiii"; char const ItemSpecOverrideFormat[] = "nii"; char const ItemToBattlePetSpeciesFormat[] = "ni"; +char const ItemUpgradeEntryFormat[] = "niiiii"; char const ItemXBonusTreeFormat[] = "nii"; char const KeyChainFormat[] = "nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; char const MailTemplateFormat[] = "ns"; @@ -96,6 +97,7 @@ char const QuestPackageItemfmt[] = "niiii"; char const QuestSortFormat[] = "ns"; char const QuestV2Format[] = "ni"; char const QuestXPFormat[] = "niiiiiiiiii"; +char const RulesetItemUpgradeEntryFormat[] = "niii"; char const ScalingStatDistributionFormat[] = "niii"; char const SoundEntriesFormat[] = "nisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiififfiifffffii"; char const SpecializationSpellsFormat[] = "niiiis"; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c28d2884a01..50b0a3dd69f 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -11038,6 +11038,9 @@ Item* Player::StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool updat if (randomPropertyId) item->SetItemRandomProperties(randomPropertyId); + if (uint32 upgradeID = sDB2Manager.GetRulesetItemUpgrade(itemId)) + item->SetModifier(ITEM_MODIFIER_UPGRADE_ID, upgradeID); + for (int32 bonusListID : bonusListIDs) item->AddBonuses(bonusListID); diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index 8c7f8190e09..6eab4072491 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -1292,3 +1292,65 @@ void WorldSession::HandleUseCritterItem(WorldPackets::Item::UseCritterItem& useC GetBattlePetMgr()->AddPet(battlePetSpecies->ID, battlePetSpecies->CreatureID, BattlePetMgr::RollPetBreed(battlePetSpecies->ID), BattlePetMgr::GetDefaultPetQuality(battlePetSpecies->ID)); _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); } + +void WorldSession::HandleUpgradeItem(WorldPackets::Item::UpgradeItem& upgradeItem) +{ + WorldPackets::Item::ItemUpgradeResult itemUpgradeResult; + if (!_player->GetNPCIfCanInteractWith(upgradeItem.ItemMaster, UNIT_NPC_FLAG_ITEM_UPGRADE_MASTER)) + { + TC_LOG_DEBUG("network", "WORLD: HandleUpgradeItems - %s not found or player can't interact with it.", upgradeItem.ItemMaster.ToString().c_str()); + itemUpgradeResult.Success = false; + SendPacket(itemUpgradeResult.Write()); + return; + } + + Item* item = _player->GetItemByGuid(upgradeItem.ItemGUID); + if (!item) + { + TC_LOG_DEBUG("network", "WORLD: HandleUpgradeItems: Item %s not found!", upgradeItem.ItemGUID.ToString().c_str()); + itemUpgradeResult.Success = false; + SendPacket(itemUpgradeResult.Write()); + return; + } + + ItemUpgradeEntry const* itemUpgradeEntry = sItemUpgradeStore.LookupEntry(upgradeItem.UpgradeID); + if (!itemUpgradeEntry) + { + TC_LOG_DEBUG("network", "WORLD: HandleUpgradeItems - ItemUpgradeEntry (%u) not found.", upgradeItem.UpgradeID); + itemUpgradeResult.Success = false; + SendPacket(itemUpgradeResult.Write()); + return; + } + + // Check if player has enough currency + if (!_player->HasCurrency(itemUpgradeEntry->CurrencyID, itemUpgradeEntry->CurrencyCost)) + { + TC_LOG_DEBUG("network", "WORLD: HandleUpgradeItems - Player has not enougth currency (ID: %u, Cost: %u) not found.", itemUpgradeEntry->CurrencyID, itemUpgradeEntry->CurrencyCost); + itemUpgradeResult.Success = false; + SendPacket(itemUpgradeResult.Write()); + return; + } + + uint32 currentUpgradeId = item->GetModifier(ITEM_MODIFIER_UPGRADE_ID); + if (currentUpgradeId != itemUpgradeEntry->PrevItemUpgradeID) + { + TC_LOG_DEBUG("network", "WORLD: HandleUpgradeItems - ItemUpgradeEntry (%u) is not related to this ItemUpgradePath (%u).", itemUpgradeEntry->ID, currentUpgradeId); + itemUpgradeResult.Success = false; + SendPacket(itemUpgradeResult.Write()); + return; + } + + itemUpgradeResult.Success = true; + SendPacket(itemUpgradeResult.Write()); + + if (item->IsEquipped()) + _player->_ApplyItemBonuses(item, item->GetSlot(), false); + + item->SetModifier(ITEM_MODIFIER_UPGRADE_ID, itemUpgradeEntry->ID); + + if (item->IsEquipped()) + _player->_ApplyItemBonuses(item, item->GetSlot(), true); + + item->SetState(ITEM_CHANGED, _player); + _player->ModifyCurrency(itemUpgradeEntry->CurrencyID, -int32(itemUpgradeEntry->CurrencyCost)); +} diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp index e627d80fdea..8ac3e947135 100644 --- a/src/server/game/Server/Packets/ItemPackets.cpp +++ b/src/server/game/Server/Packets/ItemPackets.cpp @@ -529,6 +529,15 @@ void WorldPackets::Item::UseCritterItem::Read() _worldPacket >> ItemGuid; } +void WorldPackets::Item::UpgradeItem::Read() +{ + _worldPacket >> ItemMaster; + _worldPacket >> ItemGUID; + _worldPacket >> UpgradeID; + _worldPacket >> ContainerSlot; + _worldPacket >> Slot; +} + void WorldPackets::Item::SocketGems::Read() { _worldPacket >> ItemGuid; @@ -544,3 +553,11 @@ WorldPacket const* WorldPackets::Item::SocketGemsResult::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::Item::ItemUpgradeResult::Write() +{ + _worldPacket.WriteBit(Success); + _worldPacket.FlushBits(); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/ItemPackets.h b/src/server/game/Server/Packets/ItemPackets.h index 833d1bd9261..ad821682f9c 100644 --- a/src/server/game/Server/Packets/ItemPackets.h +++ b/src/server/game/Server/Packets/ItemPackets.h @@ -502,6 +502,30 @@ namespace WorldPackets ObjectGuid ItemGuid; }; + class UpgradeItem final : public ClientPacket + { + public: + UpgradeItem(WorldPacket&& packet) : ClientPacket(CMSG_UPGRADE_ITEM, std::move(packet)) { } + + void Read() override; + + ObjectGuid ItemMaster; + ObjectGuid ItemGUID; + int32 ContainerSlot = 0; + int32 UpgradeID = 0; + int32 Slot = 0; + }; + + class ItemUpgradeResult final : public ServerPacket + { + public: + ItemUpgradeResult() : ServerPacket(SMSG_ITEM_UPGRADE_RESULT, 1) { } + + WorldPacket const* Write() override; + + bool Success = false; + }; + class SocketGems final : public ClientPacket { public: diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index a284d874191..fc1501b6894 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -774,7 +774,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_UPDATE_WOW_TOKEN_AUCTIONABLE_LIST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Token::UpdateListedAuctionableTokens, &WorldSession::HandleUpdateListedAuctionableTokens); DEFINE_HANDLER(CMSG_UPDATE_WOW_TOKEN_COUNT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_UPGRADE_GARRISON, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_UPGRADE_ITEM, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_UPGRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::UpgradeItem, &WorldSession::HandleUpgradeItem); DEFINE_HANDLER(CMSG_USED_FOLLOW, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_USE_CRITTER_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::UseCritterItem, &WorldSession::HandleUseCritterItem); DEFINE_HANDLER(CMSG_USE_EQUIPMENT_SET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::EquipmentSet::UseEquipmentSet, &WorldSession::HandleUseEquipmentSet); @@ -1228,6 +1228,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_PURCHASE_REFUND_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_PUSH_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_TIME_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_UPGRADE_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_KICK_REASON, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARNED_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARN_TALENT_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 37f8500fe84..5e428ec9a4d 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -1644,6 +1644,7 @@ enum OpcodeServer : uint32 // Opcodes that are not generated automatically SMSG_ACCOUNT_HEIRLOOM_UPDATE = 0x254B, // no client handler + SMSG_ITEM_UPGRADE_RESULT = 0x25DB, // no client handler SMSG_COMPRESSED_PACKET = 0x2FCF, SMSG_MULTIPLE_PACKETS = 0x2FCE, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 26e8329ee9c..0e2ecee911f 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -371,6 +371,7 @@ namespace WorldPackets class CancelTempEnchantment; class TransmogrifyItems; class UseCritterItem; + class UpgradeItem; class SocketGems; struct ItemInstance; } @@ -1426,6 +1427,7 @@ class TC_GAME_API WorldSession void HandleBuybackItem(WorldPackets::Item::BuyBackItem& packet); void HandleWrapItem(WorldPackets::Item::WrapItem& packet); void HandleUseCritterItem(WorldPackets::Item::UseCritterItem& packet); + void HandleUpgradeItem(WorldPackets::Item::UpgradeItem& packet); void HandleAttackSwingOpcode(WorldPackets::Combat::AttackSwing& packet); void HandleAttackStopOpcode(WorldPackets::Combat::AttackStop& packet); -- cgit v1.2.3 From f6cac4df5b2765ac0bf710da36dc28c83cd119ed Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 21 Jun 2016 20:41:30 +0200 Subject: Core/Items: Item upgrade followup * Fixed Item::SetModifier to broadcast value updates * Generate base item upgrade when looting * Generate base item upgrade when loading from db and db2 data changed --- .../Database/Implementation/CharacterDatabase.cpp | 2 +- src/server/game/Entities/Item/Item.cpp | 28 +++++++++++++++++++++- src/server/game/Loot/LootMgr.cpp | 1 + src/server/game/Loot/LootMgr.h | 3 ++- src/server/game/Server/Packets/ItemPackets.cpp | 6 ++++- 5 files changed, 36 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 67aa54c5679..65e228a7c48 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -161,7 +161,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_REP_INVENTORY_ITEM, "REPLACE INTO character_inventory (guid, bag, slot, item) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_REP_ITEM_INSTANCE, "REPLACE INTO item_instance (itemEntry, owner_guid, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, transmogrification, upgradeId, enchantIllusion, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, bonusListIDs, guid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_ITEM_INSTANCE, "UPDATE item_instance SET itemEntry = ?, owner_guid = ?, creatorGuid = ?, giftCreatorGuid = ?, count = ?, duration = ?, charges = ?, flags = ?, enchantments = ?, randomPropertyId = ?, durability = ?, playedTime = ?, text = ?, transmogrification = ?, upgradeId = ?, enchantIllusion = ?, battlePetSpeciesId = ?, battlePetBreedData = ?, battlePetLevel = ?, battlePetDisplayId = ?, bonusListIDs = ? WHERE guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_UPD_ITEM_INSTANCE_ON_LOAD, "UPDATE item_instance SET duration = ?, flags = ?, durability = ? WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_UPD_ITEM_INSTANCE_ON_LOAD, "UPDATE item_instance SET duration = ?, flags = ?, durability = ?, upgradeId = ? WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_ITEM_INSTANCE, "DELETE FROM item_instance WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_ITEM_INSTANCE_BY_OWNER, "DELETE FROM item_instance WHERE owner_guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_GIFT_OWNER, "UPDATE character_gifts SET guid = ? WHERE item_guid = ?", CONNECTION_ASYNC); diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 20f1772ef00..a3193bd3de3 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -486,7 +486,23 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie SetModifier(ITEM_MODIFIER_TRANSMOG_APPEARANCE_MOD, (transmogEntry >> 24) & 0xFF); SetModifier(ITEM_MODIFIER_TRANSMOG_ITEM_ID, transmogEntry & 0xFFFFFF); } - SetModifier(ITEM_MODIFIER_UPGRADE_ID, fields[14].GetUInt32()); + + uint32 upgradeId = fields[14].GetUInt32(); + ItemUpgradeEntry const* rulesetUpgrade = sItemUpgradeStore.LookupEntry(sDB2Manager.GetRulesetItemUpgrade(entry)); + ItemUpgradeEntry const* upgrade = sItemUpgradeStore.LookupEntry(upgradeId); + if (!rulesetUpgrade || !upgrade || rulesetUpgrade->ItemUpgradePathID != upgrade->ItemUpgradePathID) + { + upgradeId = 0; + need_save = true; + } + + if (rulesetUpgrade && !upgradeId) + { + upgradeId = rulesetUpgrade->ID; + need_save = true; + } + + SetModifier(ITEM_MODIFIER_UPGRADE_ID, upgradeId); SetModifier(ITEM_MODIFIER_ENCHANT_ILLUSION, fields[15].GetUInt32()); SetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID, fields[16].GetUInt32()); SetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA, fields[17].GetUInt32()); @@ -506,6 +522,7 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie stmt->setUInt32(0, GetUInt32Value(ITEM_FIELD_DURATION)); stmt->setUInt32(1, GetUInt32Value(ITEM_FIELD_FLAGS)); stmt->setUInt32(2, GetUInt32Value(ITEM_FIELD_DURABILITY)); + stmt->setUInt32(3, GetModifier(ITEM_MODIFIER_UPGRADE_ID)); stmt->setUInt64(3, guid); CharacterDatabase.Execute(stmt); } @@ -1848,6 +1865,9 @@ uint32 Item::GetItemLevel(Player const* owner) const if (uint32 heirloomIlvl = sDB2Manager.GetHeirloomItemLevel(ssd->ItemLevelCurveID, owner->getLevel())) itemLevel = heirloomIlvl; + if (ItemUpgradeEntry const* upgrade = sItemUpgradeStore.LookupEntry(GetModifier(ITEM_MODIFIER_UPGRADE_ID))) + itemLevel += upgrade->ItemLevelBonus; + return std::min(std::max(itemLevel + _bonusData.ItemLevel, uint32(MIN_ITEM_LEVEL)), uint32(MAX_ITEM_LEVEL)); } @@ -1877,6 +1897,12 @@ uint32 Item::GetDisplayId() const void Item::SetModifier(ItemModifier modifier, uint32 value) { + if (_modifiers[modifier] != value) + { + _dynamicChangesMask.SetBit(ITEM_DYNAMIC_FIELD_MODIFIERS); + AddToObjectUpdateIfNeeded(); + } + _modifiers[modifier] = value; ApplyModFlag(ITEM_FIELD_MODIFIERS_MASK, 1 << modifier, value != 0); } diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index a7e11e81970..3aabe686f58 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -366,6 +366,7 @@ LootItem::LootItem(LootStoreItem const& li) randomSuffix = GenerateEnchSuffixFactor(itemid); randomPropertyId = Item::GenerateItemRandomPropertyId(itemid); + upgradeId = sDB2Manager.GetRulesetItemUpgrade(itemid); count = 0; is_looted = 0; is_blocked = 0; diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index 006edab70a6..f7c1085eaad 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -159,6 +159,7 @@ struct TC_GAME_API LootItem uint32 itemid; uint32 randomSuffix; int32 randomPropertyId; + int32 upgradeId; std::vector BonusListIDs; ConditionContainer conditions; // additional loot condition GuidSet allowedGUIDs; @@ -177,7 +178,7 @@ struct TC_GAME_API LootItem explicit LootItem(LootStoreItem const& li); // Empty constructor for creating an empty LootItem to be filled in with DB data - LootItem() : itemid(0), randomSuffix(0), randomPropertyId(0), count(0), is_looted(false), is_blocked(false), + LootItem() : itemid(0), randomSuffix(0), randomPropertyId(0), upgradeId(0), count(0), is_looted(false), is_blocked(false), freeforall(false), is_underthreshold(false), is_counted(false), needs_quest(false), follow_loot_rules(false), canSave(true){ }; diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp index 8ac3e947135..94a9f1d24c0 100644 --- a/src/server/game/Server/Packets/ItemPackets.cpp +++ b/src/server/game/Server/Packets/ItemPackets.cpp @@ -280,7 +280,11 @@ void WorldPackets::Item::ItemInstance::Initialize(::LootItem const& lootItem) ItemBonus->Context = 0; /// @todo } - /// no Modifications + if (lootItem.upgradeId) + { + Modifications = boost::in_place(); + Modifications->Insert(ITEM_MODIFIER_UPGRADE_ID, lootItem.upgradeId); + } } void WorldPackets::Item::ItemInstance::Initialize(::VoidStorageItem const* voidItem) -- cgit v1.2.3 From 9a2d8eac99a0600387201bd40efc6b6e30dbfd03 Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 21 Jun 2016 20:45:34 +0200 Subject: Prepared statement parameter fix, screw manual indexing --- src/server/game/Entities/Item/Item.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index a3193bd3de3..47e711c33cd 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -518,12 +518,13 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie if (need_save) // normal item changed state set not work at loading { + uint8 index = 0; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ITEM_INSTANCE_ON_LOAD); - stmt->setUInt32(0, GetUInt32Value(ITEM_FIELD_DURATION)); - stmt->setUInt32(1, GetUInt32Value(ITEM_FIELD_FLAGS)); - stmt->setUInt32(2, GetUInt32Value(ITEM_FIELD_DURABILITY)); - stmt->setUInt32(3, GetModifier(ITEM_MODIFIER_UPGRADE_ID)); - stmt->setUInt64(3, guid); + stmt->setUInt32(index++, GetUInt32Value(ITEM_FIELD_DURATION)); + stmt->setUInt32(index++, GetUInt32Value(ITEM_FIELD_FLAGS)); + stmt->setUInt32(index++, GetUInt32Value(ITEM_FIELD_DURABILITY)); + stmt->setUInt32(index++, GetModifier(ITEM_MODIFIER_UPGRADE_ID)); + stmt->setUInt64(index++, guid); CharacterDatabase.Execute(stmt); } -- cgit v1.2.3 From 63c2804beb138510a5db153c6a9de31cefd4b273 Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 22 Jun 2016 22:04:42 +0200 Subject: Core/DataStores: Fixed typo in field name --- src/server/game/DataStores/DBCStructure.h | 2 +- src/server/game/Entities/Player/Player.cpp | 6 +++--- src/server/game/Spells/SpellMgr.cpp | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index 5eed5ca0b6d..f9968a7378c 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -977,7 +977,7 @@ struct SkillLineAbilityEntry uint32 ClassMask; // 4 uint32 MinSkillLineRank; // 7 uint32 SupercedesSpell; // 8 - uint32 AquireMethod; // 9 + uint32 AcquireMethod; // 9 uint32 TrivialSkillLineRankHigh; // 10 uint32 TrivialSkillLineRankLow; // 11 uint32 NumSkillUps; // 12 diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 50b0a3dd69f..c78b7011295 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3137,7 +3137,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent continue; // Runeforging special case - if ((_spell_idx->second->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->ID)) || ((pSkill->ID == SKILL_RUNEFORGING_2) && _spell_idx->second->TrivialSkillLineRankHigh == 0)) + if ((_spell_idx->second->AcquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->ID)) || ((pSkill->ID == SKILL_RUNEFORGING_2) && _spell_idx->second->TrivialSkillLineRankHigh == 0)) if (SkillRaceClassInfoEntry const* rcInfo = GetSkillRaceClassInfo(pSkill->ID, getRace(), getClass())) LearnDefaultSkill(rcInfo); } @@ -22668,7 +22668,7 @@ void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue) if (!spellInfo) continue; - if (ability->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE && ability->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) + if (ability->AcquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE && ability->AcquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; // Check race if set @@ -22684,7 +22684,7 @@ void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue) continue; // need unlearn spell - if (skillValue < ability->MinSkillLineRank && ability->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) + if (skillValue < ability->MinSkillLineRank && ability->AcquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) RemoveSpell(ability->SpellID); // need learn else if (!IsInWorld()) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index b2a7a32eab7..d001705bc79 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1409,8 +1409,8 @@ void SpellMgr::LoadSpellLearnSkills() if (effect && effect->Effect == SPELL_EFFECT_SKILL) { SpellLearnSkillNode dbc_node; - dbc_node.skill = effect->MiscValue; - dbc_node.step = effect->CalcValue(); + dbc_node.skill = uint16(effect->MiscValue); + dbc_node.step = uint16(effect->CalcValue()); if (dbc_node.skill != SKILL_RIDING) dbc_node.value = 1; else @@ -1636,7 +1636,7 @@ void SpellMgr::LoadSpellTargetPositions() // target facing is in degrees for 6484 & 9268... (blizz sucks) if (effect->PositionFacing > 2 * M_PI) - st.target_Orientation = effect->PositionFacing * M_PI / 180; + st.target_Orientation = effect->PositionFacing * float(M_PI) / 180; else st.target_Orientation = effect->PositionFacing; @@ -2334,7 +2334,7 @@ void SpellMgr::LoadPetLevelupSpellMap() if (skillLine->SkillLine != creatureFamily->SkillLine[j]) continue; - if (skillLine->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) + if (skillLine->AcquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; SpellInfo const* spell = GetSpellInfo(skillLine->SpellID); @@ -3452,7 +3452,7 @@ void SpellMgr::LoadPetFamilySpellsStore() if (skillLine->SkillLine != cFamily->SkillLine[0] && skillLine->SkillLine != cFamily->SkillLine[1]) continue; - if (skillLine->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) + if (skillLine->AcquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; sPetFamilySpellsStore[i].insert(spellInfo->ID); -- cgit v1.2.3 From b4c83443e7901d08ae51b565aa966d40dd9f7637 Mon Sep 17 00:00:00 2001 From: Nelidon Date: Thu, 23 Jun 2016 18:04:54 +0200 Subject: Core/Battlenet: Allow player to switch realm (#17441) --- src/server/game/Handlers/BattlenetHandler.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/server/game/Handlers/BattlenetHandler.cpp b/src/server/game/Handlers/BattlenetHandler.cpp index 1f968c3b423..2324ae51959 100644 --- a/src/server/game/Handlers/BattlenetHandler.cpp +++ b/src/server/game/Handlers/BattlenetHandler.cpp @@ -31,6 +31,7 @@ void WorldSession::HandleBattlenetRequestRealmListTicket(WorldPackets::Battlenet WorldPackets::Battlenet::RealmListTicket realmListTicket; realmListTicket.Token = requestRealmListTicket.Token; + realmListTicket.Allow = true; realmListTicket.Ticket << "WorldserverRealmListTicket"; SendPacket(realmListTicket.Write()); -- cgit v1.2.3 From c5bad429e2ca0d58660922157655cbaec857e53e Mon Sep 17 00:00:00 2001 From: Kito Date: Sat, 18 Jun 2016 20:34:45 +0200 Subject: Scripts/Monk: Surging Mist * When glyphed and in stance will cast AOE ally selection heal * Else, cast normal heal on Explicit target --- sql/updates/world/6.x/2016_06_23_02_world.sql | 3 ++ src/server/scripts/Spells/spell_monk.cpp | 48 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 sql/updates/world/6.x/2016_06_23_02_world.sql (limited to 'src') diff --git a/sql/updates/world/6.x/2016_06_23_02_world.sql b/sql/updates/world/6.x/2016_06_23_02_world.sql new file mode 100644 index 00000000000..43f2c02dcf2 --- /dev/null +++ b/sql/updates/world/6.x/2016_06_23_02_world.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_monk_surging_mist'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(116694,'spell_monk_surging_mist'); diff --git a/src/server/scripts/Spells/spell_monk.cpp b/src/server/scripts/Spells/spell_monk.cpp index e87a76c3e9f..93ba174b1b6 100644 --- a/src/server/scripts/Spells/spell_monk.cpp +++ b/src/server/scripts/Spells/spell_monk.cpp @@ -32,9 +32,12 @@ enum MonkSpells SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHI_PROC = 123333, SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK = 117962, SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK_CD = 117953, + SPELL_MONK_GLYPH_OF_SURGING_MIST = 120483, SPELL_MONK_PROVOKE_SINGLE_TARGET = 116189, SPELL_MONK_PROVOKE_AOE = 118635, SPELL_MONK_STANCE_OF_THE_SPIRITED_CRANE = 154436, + SPELL_MONK_SURGING_MIST_HEAL = 116995, + SPELL_MONK_SURGING_MIST_HEAL_GLYPHED = 123273, }; // 117952 - Crackling Jade Lightning @@ -186,9 +189,54 @@ public: } }; +// 116694 - Surging Mist +class spell_monk_surging_mist : public SpellScriptLoader +{ + public: + spell_monk_surging_mist() : SpellScriptLoader("spell_monk_surging_mist") { } + + class spell_monk_surging_mist_SpellScript : public SpellScript + { + PrepareSpellScript(spell_monk_surging_mist_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_MONK_SURGING_MIST_HEAL)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_MONK_SURGING_MIST_HEAL_GLYPHED)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_MONK_GLYPH_OF_SURGING_MIST)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + Unit* caster = GetCaster(); + Unit* target = GetHitUnit(); + if (caster->GetShapeshiftForm() == FORM_CRANE_STANCE && caster->HasAura(SPELL_MONK_GLYPH_OF_SURGING_MIST)) + caster->CastSpell(target, SPELL_MONK_SURGING_MIST_HEAL_GLYPHED, true); + else + caster->CastSpell(target, SPELL_MONK_SURGING_MIST_HEAL, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_monk_surging_mist_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_monk_surging_mist_SpellScript(); + } +}; + void AddSC_monk_spell_scripts() { new spell_monk_crackling_jade_lightning(); new spell_monk_crackling_jade_lightning_knockback_proc_aura(); new spell_monk_provoke(); + new spell_monk_surging_mist(); } -- cgit v1.2.3 From 73aababbd4e4ecab5783d1ab179b47bab133a490 Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 23 Jun 2016 22:19:52 +0200 Subject: Core/Spells: Fixed handling spell interrupts - PreventionType dbc field is a bitmask --- src/server/game/Entities/Creature/Creature.cpp | 8 ++++---- src/server/game/Miscellaneous/SharedDefines.h | 7 +++---- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 4 ++-- src/server/game/Spells/Spell.cpp | 8 ++++---- src/server/game/Spells/SpellEffects.cpp | 2 +- src/server/game/Spells/SpellHistory.cpp | 4 ++-- 6 files changed, 16 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 979390baaeb..7b8467f83bf 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1898,9 +1898,9 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim) float dist = GetDistance(victim); if (dist > range || dist < minrange) continue; - if (spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + if (spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) continue; - if (spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) + if (spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) continue; return spellInfo; } @@ -1948,9 +1948,9 @@ SpellInfo const* Creature::reachWithSpellCure(Unit* victim) // continue; if (dist > range || dist < minrange) continue; - if (spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + if (spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) continue; - if (spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) + if (spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) continue; return spellInfo; } diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 4a69eadb6b1..ce4be425140 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -2054,10 +2054,9 @@ enum SpellDmgClass enum SpellPreventionType { - SPELL_PREVENTION_TYPE_NONE = 0, - SPELL_PREVENTION_TYPE_SILENCE = 1, - SPELL_PREVENTION_TYPE_PACIFY = 2, - SPELL_PREVENTION_TYPE_UNK = 3 // Only a few spells have this, but most of the should be interruptable. + SPELL_PREVENTION_TYPE_SILENCE = 1, + SPELL_PREVENTION_TYPE_PACIFY = 2, + SPELL_PREVENTION_TYPE_NO_ACTIONS = 4 }; enum GameobjectTypes : uint8 // (6.0.3.19103) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index f205ac03e01..350ba8af206 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2424,10 +2424,10 @@ void AuraEffect::HandleAuraModSilence(AuraApplication const* aurApp, uint8 mode, target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); // call functions which may have additional effects after chainging state of unit - // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE + // Stop cast only spells vs PreventionType & SPELL_PREVENTION_TYPE_SILENCE for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) if (Spell* spell = target->GetCurrentSpell(CurrentSpellTypes(i))) - if (spell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + if (spell->m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE) // Stop spells on prepare or casting state target->InterruptSpell(CurrentSpellTypes(i), false); } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 31bcfc39980..b77cac83e34 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5765,9 +5765,9 @@ SpellCastResult Spell::CheckCasterAuras() const prevented_reason = SPELL_FAILED_CONFUSED; else if (unitflag & UNIT_FLAG_FLEEING && !m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED)) prevented_reason = SPELL_FAILED_FLEEING; - else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE) prevented_reason = SPELL_FAILED_SILENCED; - else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY) + else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY) prevented_reason = SPELL_FAILED_PACIFIED; // Attr must make flag drop spell totally immune from all effects @@ -5814,9 +5814,9 @@ SpellCastResult Spell::CheckCasterAuras() const case SPELL_AURA_MOD_SILENCE: case SPELL_AURA_MOD_PACIFY: case SPELL_AURA_MOD_PACIFY_SILENCE: - if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY) + if (m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY) return SPELL_FAILED_PACIFIED; - else if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + else if (m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE) return SPELL_FAILED_SILENCED; break; default: break; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index d9930ce890a..9f457e5672a 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3127,7 +3127,7 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex) // check if we can interrupt spell if ((spell->getState() == SPELL_STATE_CASTING || (spell->getState() == SPELL_STATE_PREPARING && spell->GetCastTime() > 0.0f)) - && (curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE || curSpellInfo->PreventionType == SPELL_PREVENTION_TYPE_UNK) + && (curSpellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE) && ((i == CURRENT_GENERIC_SPELL && curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT) || (i == CURRENT_CHANNELED_SPELL && curSpellInfo->ChannelInterruptFlags & CHANNEL_INTERRUPT_FLAG_INTERRUPT))) { diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp index fe56eb3c01b..df9d50dad06 100644 --- a/src/server/game/Spells/SpellHistory.cpp +++ b/src/server/game/Spells/SpellHistory.cpp @@ -261,7 +261,7 @@ void SpellHistory::HandleCooldowns(SpellInfo const* spellInfo, uint32 itemID, Sp bool SpellHistory::IsReady(SpellInfo const* spellInfo, uint32 itemId /*= 0*/, bool ignoreCategoryCooldown /*= false*/) const { - if (spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + if (spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE) if (IsSchoolLocked(spellInfo->GetSchoolMask())) return false; @@ -683,7 +683,7 @@ void SpellHistory::LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTim if (spellInfo->IsCooldownStartedOnEvent()) continue; - if (spellInfo->PreventionType != SPELL_PREVENTION_TYPE_SILENCE) + if (!(spellInfo->PreventionType & SPELL_PREVENTION_TYPE_SILENCE)) continue; if ((schoolMask & spellInfo->GetSchoolMask()) && GetRemainingCooldown(spellInfo) < lockoutTime) -- cgit v1.2.3 From 420b9045e43d6e7ea139414bfd31167d1b1770df Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 24 Jun 2016 16:00:39 +0200 Subject: Core/Auras: Fixed SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT to affect ranged attack power as well --- src/server/game/Entities/Unit/StatSystem.cpp | 29 ++++++++++++++++------- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 1 + 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 397a4b993db..6ca1045f63a 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -164,7 +164,10 @@ void Player::ApplySpellPowerBonus(int32 amount, bool apply) ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, amount, apply); if (HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT)) + { UpdateAttackPowerAndDamage(); + UpdateAttackPowerAndDamage(true); + } } void Player::UpdateSpellDamageAndHealingBonus() @@ -178,7 +181,10 @@ void Player::UpdateSpellDamageAndHealingBonus() SetStatInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, SpellBaseDamageBonusDone(SpellSchoolMask(1 << i))); if (HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT)) + { UpdateAttackPowerAndDamage(); + UpdateAttackPowerAndDamage(true); + } } bool Player::UpdateAllStats() @@ -314,19 +320,24 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) index = UNIT_FIELD_RANGED_ATTACK_POWER; index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS; index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; - val2 = (level + std::max(GetStat(STAT_AGILITY), 0.0f)) * entry->RangedAttackPowerPerAgility; } - else if (!HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT)) + + if (!HasAuraType(SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT)) { - float strengthValue = std::max(GetStat(STAT_STRENGTH) * entry->AttackPowerPerStrength, 0.0f); - float agilityValue = std::max(GetStat(STAT_AGILITY) * entry->AttackPowerPerAgility, 0.0f); + if (!ranged) + { + float strengthValue = std::max(GetStat(STAT_STRENGTH) * entry->AttackPowerPerStrength, 0.0f); + float agilityValue = std::max(GetStat(STAT_AGILITY) * entry->AttackPowerPerAgility, 0.0f); - SpellShapeshiftFormEntry const* form = sSpellShapeshiftFormStore.LookupEntry(GetShapeshiftForm()); - // Directly taken from client, SHAPESHIFT_FLAG_AP_FROM_STRENGTH ? - if (form && form->Flags & 0x20) - agilityValue += std::max(GetStat(STAT_AGILITY) * entry->AttackPowerPerStrength, 0.0f); + SpellShapeshiftFormEntry const* form = sSpellShapeshiftFormStore.LookupEntry(GetShapeshiftForm()); + // Directly taken from client, SHAPESHIFT_FLAG_AP_FROM_STRENGTH ? + if (form && form->Flags & 0x20) + agilityValue += std::max(GetStat(STAT_AGILITY) * entry->AttackPowerPerStrength, 0.0f); - val2 = strengthValue + agilityValue; + val2 = strengthValue + agilityValue; + } + else + val2 = (level + std::max(GetStat(STAT_AGILITY), 0.0f)) * entry->RangedAttackPowerPerAgility; } else { diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 350ba8af206..4ae91981448 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -3996,6 +3996,7 @@ void AuraEffect::HandleOverrideAttackPowerBySpellPower(AuraApplication const* au target->ApplyModSignedFloatValue(PLAYER_FIELD_OVERRIDE_AP_BY_SPELL_POWER_PERCENT, float(m_amount), apply); target->UpdateAttackPowerAndDamage(); + target->UpdateAttackPowerAndDamage(true); } /********************************/ -- cgit v1.2.3 From 55d5cd37df8f3415b71dac1e50ecc970873d6deb Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 25 Jun 2016 10:50:28 +0200 Subject: Core/Auras: Implemented aura 321 SPELL_AURA_MOD_NO_ACTIONS --- src/server/game/Entities/Unit/Unit.h | 3 ++- src/server/game/Spells/Auras/SpellAuraDefines.h | 2 +- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 31 ++++++++++++++++++++++- src/server/game/Spells/Auras/SpellAuraEffects.h | 1 + src/server/game/Spells/Spell.cpp | 4 ++- 5 files changed, 37 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 48e7cb86fcf..5cbe29996dc 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -729,7 +729,8 @@ enum UnitFlags2 UNIT_FLAG2_DISABLE_TURN = 0x00008000, UNIT_FLAG2_UNK2 = 0x00010000, UNIT_FLAG2_PLAY_DEATH_ANIM = 0x00020000, // Plays special death animation upon death - UNIT_FLAG2_ALLOW_CHEAT_SPELLS = 0x00040000 // Allows casting spells with AttributesEx7 & SPELL_ATTR7_IS_CHEAT_SPELL + UNIT_FLAG2_ALLOW_CHEAT_SPELLS = 0x00040000, // Allows casting spells with AttributesEx7 & SPELL_ATTR7_IS_CHEAT_SPELL + UNIT_FLAG2_NO_ACTIONS = 0x00800000 }; /// Non Player Character flags diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 70a08d05d5f..ae34e06fe37 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -378,7 +378,7 @@ enum AuraType SPELL_AURA_MASTERY = 318, SPELL_AURA_MOD_MELEE_HASTE_3 = 319, SPELL_AURA_MOD_RANGED_HASTE_2 = 320, - SPELL_AURA_321 = 321, + SPELL_AURA_MOD_NO_ACTIONS = 321, SPELL_AURA_INTERFERE_TARGETTING = 322, // NYI SPELL_AURA_323 = 323, // Not used in 4.3.4 SPELL_AURA_324 = 324, // spell critical chance (probably by school mask) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 4ae91981448..9e46b2d1d35 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -380,7 +380,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleMastery, //318 SPELL_AURA_MASTERY &AuraEffect::HandleModMeleeSpeedPct, //319 SPELL_AURA_MOD_MELEE_HASTE_3 &AuraEffect::HandleAuraModRangedHaste, //320 SPELL_AURA_MOD_RANGED_HASTE_2 - &AuraEffect::HandleNULL, //321 SPELL_AURA_321 + &AuraEffect::HandleAuraModNoActions, //321 SPELL_AURA_MOD_NO_ACTIONS &AuraEffect::HandleNULL, //322 SPELL_AURA_INTERFERE_TARGETTING &AuraEffect::HandleUnused, //323 unused (4.3.4) &AuraEffect::HandleNULL, //324 SPELL_AURA_324 @@ -2509,6 +2509,35 @@ void AuraEffect::HandleAuraAllowOnlyAbility(AuraApplication const* aurApp, uint8 } } +void AuraEffect::HandleAuraModNoActions(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit* target = aurApp->GetTarget(); + + if (apply) + { + target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_NO_ACTIONS); + + // call functions which may have additional effects after chainging state of unit + // Stop cast only spells vs PreventionType & SPELL_PREVENTION_TYPE_SILENCE + for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) + if (Spell* spell = target->GetCurrentSpell(CurrentSpellTypes(i))) + if (spell->m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_NO_ACTIONS) + // Stop spells on prepare or casting state + target->InterruptSpell(CurrentSpellTypes(i), false); + } + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if (target->HasAuraType(SPELL_AURA_MOD_NO_ACTIONS)) + return; + + target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_NO_ACTIONS); + } +} + /****************************/ /*** TRACKING ***/ /****************************/ diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 7d1df37eb42..a046a675eb4 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -167,6 +167,7 @@ class TC_GAME_API AuraEffect void HandleAuraModPacify(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModPacifyAndSilence(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraAllowOnlyAbility(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleAuraModNoActions(AuraApplication const* aurApp, uint8 mode, bool apply) const; // tracking void HandleAuraTrackResources(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraTrackCreatures(AuraApplication const* aurApp, uint8 mode, bool apply) const; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index b77cac83e34..bc34002a33b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5749,7 +5749,7 @@ SpellCastResult Spell::CheckCasterAuras() const Unit::AuraEffectList const& stunAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_STUN); for (Unit::AuraEffectList::const_iterator i = stunAuras.begin(); i != stunAuras.end(); ++i) { - if ((*i)->GetSpellInfo()->GetAllEffectsMechanicMask() && !((*i)->GetSpellInfo()->GetAllEffectsMechanicMask() & (1<GetSpellInfo()->GetAllEffectsMechanicMask() && !((*i)->GetSpellInfo()->GetAllEffectsMechanicMask() & (1 << MECHANIC_STUN))) { foundNotStun = true; break; @@ -5769,6 +5769,8 @@ SpellCastResult Spell::CheckCasterAuras() const prevented_reason = SPELL_FAILED_SILENCED; else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY) prevented_reason = SPELL_FAILED_PACIFIED; + else if (m_caster->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_NO_ACTIONS) && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_NO_ACTIONS) + prevented_reason = SPELL_FAILED_NO_ACTIONS; // Attr must make flag drop spell totally immune from all effects if (prevented_reason != SPELL_CAST_OK) -- cgit v1.2.3 From 9ae700c809f1b02aa33131ef6ec4914bde522027 Mon Sep 17 00:00:00 2001 From: Shocker Date: Sun, 26 Jun 2016 14:51:37 +0300 Subject: Core/Reputation: Player::SetReputation() / Player::GetReputation() should work with signed values --- src/server/game/Entities/Player/Player.cpp | 4 ++-- src/server/game/Entities/Player/Player.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c78b7011295..aedb283e368 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -25367,11 +25367,11 @@ void Player::SendTimeSync() GetName().c_str(), GetGUID().ToString().c_str()); } -void Player::SetReputation(uint32 factionentry, uint32 value) +void Player::SetReputation(uint32 factionentry, int32 value) { GetReputationMgr().SetReputation(sFactionStore.LookupEntry(factionentry), value); } -uint32 Player::GetReputation(uint32 factionentry) const +int32 Player::GetReputation(uint32 factionentry) const { return GetReputationMgr().GetReputation(sFactionStore.LookupEntry(factionentry)); } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 3c630c42fda..20739ed4148 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1749,8 +1749,8 @@ class TC_GAME_API Player : public Unit, public GridObject void RemoveSpecializationSpells(); void SendSpellCategoryCooldowns() const; - void SetReputation(uint32 factionentry, uint32 value); - uint32 GetReputation(uint32 factionentry) const; + void SetReputation(uint32 factionentry, int32 value); + int32 GetReputation(uint32 factionentry) const; std::string GetGuildName() const; // Loot Spec -- cgit v1.2.3 From a515b73738c0cb21239711b166ac7a84801149b1 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 26 Jun 2016 19:52:41 +0200 Subject: Core/Spells: Fixed Glyph of Surging Mist --- sql/updates/world/6.x/2016_06_26_00_world.sql | 3 + src/server/scripts/Spells/spell_monk.cpp | 86 +++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 sql/updates/world/6.x/2016_06_26_00_world.sql (limited to 'src') diff --git a/sql/updates/world/6.x/2016_06_26_00_world.sql b/sql/updates/world/6.x/2016_06_26_00_world.sql new file mode 100644 index 00000000000..ead8bc25478 --- /dev/null +++ b/sql/updates/world/6.x/2016_06_26_00_world.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_monk_surging_mist_glyphed'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(123273,'spell_monk_surging_mist_glyphed'); diff --git a/src/server/scripts/Spells/spell_monk.cpp b/src/server/scripts/Spells/spell_monk.cpp index 93ba174b1b6..fd91db9216f 100644 --- a/src/server/scripts/Spells/spell_monk.cpp +++ b/src/server/scripts/Spells/spell_monk.cpp @@ -32,12 +32,11 @@ enum MonkSpells SPELL_MONK_CRACKLING_JADE_LIGHTNING_CHI_PROC = 123333, SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK = 117962, SPELL_MONK_CRACKLING_JADE_LIGHTNING_KNOCKBACK_CD = 117953, - SPELL_MONK_GLYPH_OF_SURGING_MIST = 120483, SPELL_MONK_PROVOKE_SINGLE_TARGET = 116189, SPELL_MONK_PROVOKE_AOE = 118635, + SPELL_MONK_SOOTHING_MIST = 115175, SPELL_MONK_STANCE_OF_THE_SPIRITED_CRANE = 154436, SPELL_MONK_SURGING_MIST_HEAL = 116995, - SPELL_MONK_SURGING_MIST_HEAL_GLYPHED = 123273, }; // 117952 - Crackling Jade Lightning @@ -203,26 +202,26 @@ class spell_monk_surging_mist : public SpellScriptLoader { if (!sSpellMgr->GetSpellInfo(SPELL_MONK_SURGING_MIST_HEAL)) return false; - if (!sSpellMgr->GetSpellInfo(SPELL_MONK_SURGING_MIST_HEAL_GLYPHED)) - return false; - if (!sSpellMgr->GetSpellInfo(SPELL_MONK_GLYPH_OF_SURGING_MIST)) - return false; return true; } + void SelectTarget(WorldObject*& target) + { + Unit* caster = GetCaster(); + if (caster->GetUInt32Value(UNIT_CHANNEL_SPELL) == SPELL_MONK_SOOTHING_MIST) + if (Unit* soothingMistTarget = ObjectAccessor::GetUnit(*caster, caster->GetChannelObjectGuid())) + target = soothingMistTarget; + } + void HandleDummy(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - Unit* caster = GetCaster(); - Unit* target = GetHitUnit(); - if (caster->GetShapeshiftForm() == FORM_CRANE_STANCE && caster->HasAura(SPELL_MONK_GLYPH_OF_SURGING_MIST)) - caster->CastSpell(target, SPELL_MONK_SURGING_MIST_HEAL_GLYPHED, true); - else - caster->CastSpell(target, SPELL_MONK_SURGING_MIST_HEAL, true); + GetCaster()->CastSpell(GetHitUnit(), SPELL_MONK_SURGING_MIST_HEAL, true); } void Register() override { + OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_monk_surging_mist_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_TARGET_ALLY); OnEffectHitTarget += SpellEffectFn(spell_monk_surging_mist_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; @@ -233,10 +232,73 @@ class spell_monk_surging_mist : public SpellScriptLoader } }; +// 123273 - Surging Mist (Glyphed) +class spell_monk_surging_mist_glyphed : public SpellScriptLoader +{ +public: + spell_monk_surging_mist_glyphed() : SpellScriptLoader("spell_monk_surging_mist_glyphed") { } + + class spell_monk_surging_mist_glyphed_SpellScript : public SpellScript + { + PrepareSpellScript(spell_monk_surging_mist_glyphed_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_MONK_SURGING_MIST_HEAL)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_MONK_SOOTHING_MIST)) + return false; + return true; + } + + void SelectTarget(std::list& targets) + { + Unit* caster = GetCaster(); + if (caster->GetUInt32Value(UNIT_CHANNEL_SPELL) == SPELL_MONK_SOOTHING_MIST) + { + targets.clear(); + if (Unit* soothingMistTarget = ObjectAccessor::GetUnit(*caster, caster->GetChannelObjectGuid())) + targets.push_back(soothingMistTarget); + } + else + { + targets.remove_if([caster](WorldObject* target) + { + return target->GetTypeId() != TYPEID_UNIT || !target->ToUnit()->IsInRaidWith(caster); + }); + targets.sort(Trinity::HealthPctOrderPred()); + if (!targets.empty()) + targets.resize(1); + } + + if (targets.empty()) + targets.push_back(caster); + } + + void HandleDummy(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetCaster()->CastSpell(GetHitUnit(), SPELL_MONK_SURGING_MIST_HEAL, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_monk_surging_mist_glyphed_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnEffectHitTarget += SpellEffectFn(spell_monk_surging_mist_glyphed_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_monk_surging_mist_glyphed_SpellScript(); + } +}; + void AddSC_monk_spell_scripts() { new spell_monk_crackling_jade_lightning(); new spell_monk_crackling_jade_lightning_knockback_proc_aura(); new spell_monk_provoke(); new spell_monk_surging_mist(); + new spell_monk_surging_mist_glyphed(); } -- cgit v1.2.3 From 68473ccba24560da3db65467dc24b07882cfa057 Mon Sep 17 00:00:00 2001 From: Shauren Date: Mon, 27 Jun 2016 17:19:05 +0200 Subject: Core/PacketIO: Marked CMSG_GUILD_NEWS_UPDATE_STICKY as thread unsafe --- src/server/game/Server/Protocol/Opcodes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index fc1501b6894..ac2041d981a 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -399,7 +399,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_GUILD_INVITE_BY_NAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildInviteByName, &WorldSession::HandleGuildInviteByName); DEFINE_HANDLER(CMSG_GUILD_LEAVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildLeave, &WorldSession::HandleGuildLeave); DEFINE_HANDLER(CMSG_GUILD_MEMBER_SEND_SOR_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_GUILD_NEWS_UPDATE_STICKY, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Guild::GuildNewsUpdateSticky, &WorldSession::HandleGuildNewsUpdateSticky); + DEFINE_HANDLER(CMSG_GUILD_NEWS_UPDATE_STICKY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildNewsUpdateSticky, &WorldSession::HandleGuildNewsUpdateSticky); DEFINE_HANDLER(CMSG_GUILD_OFFICER_REMOVE_MEMBER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildOfficerRemoveMember, &WorldSession::HandleGuildOfficerRemoveMember); DEFINE_HANDLER(CMSG_GUILD_PERMISSIONS_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildPermissionsQuery, &WorldSession::HandleGuildPermissionsQuery); DEFINE_HANDLER(CMSG_GUILD_PROMOTE_MEMBER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Guild::GuildPromoteMember, &WorldSession::HandleGuildPromoteMember); -- cgit v1.2.3 From b3d814ee50b265c140d65b6f92ce42482ce1f39b Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 28 Jun 2016 17:38:19 +0200 Subject: Core/Spells: Fixed spell effect on caster not being processed instantly for spells that have travel time and hit both caster and another unit --- src/server/game/Spells/Spell.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index bc34002a33b..34261f4f0e2 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -6824,8 +6824,8 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time) return true; // spell is deletable, finish event } // event will be re-added automatically at the end of routine) - } break; - + break; + } case SPELL_STATE_DELAYED: { // first, check, if we have just started @@ -6875,17 +6875,21 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time) { // delaying had just started, record the moment m_Spell->SetDelayStart(e_time); + // handle effects on caster if the spell has travel time but also affects the caster in some way + uint64 n_offset = m_Spell->handle_delayed(0); + ASSERT(n_offset == m_Spell->GetDelayMoment()); // re-plan the event for the delay moment m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + m_Spell->GetDelayMoment(), false); return false; // event not complete } - } break; - + break; + } default: { // all other states // event will be re-added automatically at the end of routine) - } break; + break; + } } // spell processing not complete, plan event on the next update interval -- cgit v1.2.3 From 7ed1c47f6b336cc7953373de60e964ba0a076b36 Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 29 Jun 2016 19:49:23 +0200 Subject: Core/Auras: Implemented SPELL_AURA_OVERRIDE_SPELL_VISUAL --- .../game/Entities/AreaTrigger/AreaTrigger.cpp | 18 +++++--- src/server/game/Entities/AreaTrigger/AreaTrigger.h | 3 +- .../game/Entities/DynamicObject/DynamicObject.cpp | 11 +++-- .../game/Entities/DynamicObject/DynamicObject.h | 3 +- src/server/game/Entities/Unit/Unit.cpp | 18 ++++++++ src/server/game/Entities/Unit/Unit.h | 1 + src/server/game/Spells/Auras/SpellAuraEffects.cpp | 2 +- src/server/game/Spells/Auras/SpellAuras.cpp | 4 +- src/server/game/Spells/Auras/SpellAuras.h | 3 +- src/server/game/Spells/Spell.cpp | 6 +-- src/server/game/Spells/SpellEffects.cpp | 10 ++--- src/server/game/Spells/SpellInfo.cpp | 41 ++++++++++++------ src/server/game/Spells/SpellInfo.h | 4 +- src/server/game/Spells/SpellMgr.cpp | 48 +++++++++++----------- 14 files changed, 111 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp index 68ee386be3f..568c0e39469 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp @@ -15,13 +15,14 @@ * with this program. If not, see . */ -#include "Unit.h" -#include "SpellInfo.h" +#include "AreaTrigger.h" +#include "DB2Stores.h" #include "Log.h" +#include "SpellInfo.h" +#include "Unit.h" #include "UpdateData.h" -#include "AreaTrigger.h" -AreaTrigger::AreaTrigger() : WorldObject(false), _duration(0) +AreaTrigger::AreaTrigger() : WorldObject(false), _duration(0), _spellXSpellVisualId(0) { m_objectType |= TYPEMASK_AREATRIGGER; m_objectTypeId = TYPEID_AREATRIGGER; @@ -56,8 +57,9 @@ void AreaTrigger::RemoveFromWorld() } } -bool AreaTrigger::CreateAreaTrigger(ObjectGuid::LowType guidlow, uint32 triggerEntry, Unit* caster, SpellInfo const* spell, Position const& pos) +bool AreaTrigger::CreateAreaTrigger(ObjectGuid::LowType guidlow, uint32 triggerEntry, Unit* caster, SpellInfo const* spell, Position const& pos, uint32 spellXSpellVisualId) { + _spellXSpellVisualId = spellXSpellVisualId; SetMap(caster->GetMap()); Relocate(pos); if (!IsPositionValid()) @@ -69,13 +71,17 @@ bool AreaTrigger::CreateAreaTrigger(ObjectGuid::LowType guidlow, uint32 triggerE Object::_Create(ObjectGuid::Create(GetMapId(), triggerEntry, guidlow)); SetPhaseMask(caster->GetPhaseMask(), false); + uint32 spellVisual = 0; + if (SpellXSpellVisualEntry const* visual = sSpellXSpellVisualStore.LookupEntry(spellXSpellVisualId)) + spellVisual = visual->SpellVisualID[0]; + SetEntry(triggerEntry); SetDuration(spell->GetDuration()); SetObjectScale(1); SetGuidValue(AREATRIGGER_CASTER, caster->GetGUID()); SetUInt32Value(AREATRIGGER_SPELLID, spell->Id); - SetUInt32Value(AREATRIGGER_SPELLVISUALID, spell->GetSpellVisual(GetMap()->GetDifficultyID())); + SetUInt32Value(AREATRIGGER_SPELLVISUALID, spellVisual); SetUInt32Value(AREATRIGGER_DURATION, spell->GetDuration()); CopyPhaseFrom(caster); diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.h b/src/server/game/Entities/AreaTrigger/AreaTrigger.h index e3caa6d2e95..1b3e6f02a3e 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.h +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.h @@ -32,7 +32,7 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObjectGetMap()); Relocate(pos); if (!IsPositionValid()) @@ -93,10 +94,14 @@ bool DynamicObject::CreateDynamicObject(ObjectGuid::LowType guidlow, Unit* caste WorldObject::_Create(ObjectGuid::Create(GetMapId(), spell->Id, guidlow)); SetPhaseMask(caster->GetPhaseMask(), false); + uint32 spellVisual = 0; + if (SpellXSpellVisualEntry const* visual = sSpellXSpellVisualStore.LookupEntry(spellXSpellVisualId)) + spellVisual = visual->SpellVisualID[0]; + SetEntry(spell->Id); SetObjectScale(1.0f); SetGuidValue(DYNAMICOBJECT_CASTER, caster->GetGUID()); - SetUInt32Value(DYNAMICOBJECT_BYTES, spell->GetSpellVisual(GetMap()->GetDifficultyID()) | (type << 28)); + SetUInt32Value(DYNAMICOBJECT_BYTES, spellVisual | (type << 28)); SetUInt32Value(DYNAMICOBJECT_SPELLID, spell->Id); SetFloatValue(DYNAMICOBJECT_RADIUS, radius); SetUInt32Value(DYNAMICOBJECT_CASTTIME, getMSTime()); diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h index 09426a3c044..4d1cdefdd48 100644 --- a/src/server/game/Entities/DynamicObject/DynamicObject.h +++ b/src/server/game/Entities/DynamicObject/DynamicObject.h @@ -41,7 +41,7 @@ class TC_GAME_API DynamicObject : public WorldObject, public GridObjectGetMiscValue() == spellInfo->Id) + { + if (SpellInfo const* visualSpell = sSpellMgr->GetSpellInfo(effect->GetMiscValueB())) + { + spellInfo = visualSpell; + break; + } + } + } + + return spellInfo->GetSpellXSpellVisualId(this); +} + struct CombatLogSender { WorldObject const* i_source; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 5cbe29996dc..2ee0ea8873a 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1931,6 +1931,7 @@ class TC_GAME_API Unit : public WorldObject Spell* FindCurrentSpellBySpellId(uint32 spell_id) const; int32 GetCurrentSpellCastTime(uint32 spell_id) const; virtual SpellInfo const* GetCastSpellInfo(SpellInfo const* spellInfo) const; + uint32 GetCastSpellXSpellVisualId(SpellInfo const* spellInfo) const; SpellHistory* GetSpellHistory() { return _spellHistory; } SpellHistory const* GetSpellHistory() const { return _spellHistory; } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 9e46b2d1d35..136aea7a811 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -462,7 +462,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleAuraModSkill, //400 SPELL_AURA_MOD_SKILL_2 &AuraEffect::HandleNULL, //401 &AuraEffect::HandleNULL, //402 - &AuraEffect::HandleNULL, //403 + &AuraEffect::HandleNoImmediateEffect, //403 SPELL_AURA_OVERRIDE_SPELL_VISUAL implemented in Unit::GetCastSpellXSpellVisualId &AuraEffect::HandleOverrideAttackPowerBySpellPower, //404 SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT &AuraEffect::HandleNULL, //405 SPELL_AURA_MOD_RATING_PCT &AuraEffect::HandleNULL, //406 diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index e7c932e8a3b..b337e4aca58 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -202,7 +202,7 @@ void AuraApplication::BuildUpdatePacket(WorldPackets::Spells::AuraInfo& auraInfo WorldPackets::Spells::AuraDataInfo auraData; auraData.SpellID = aura->GetId(); - auraData.SpellXSpellVisualID = aura->GetSpellInfo()->GetSpellXSpellVisualId(_target->GetMap()->GetDifficultyID()); + auraData.SpellXSpellVisualID = aura->GetSpellXSpellVisualId(); auraData.Flags = GetFlags(); if (aura->GetMaxDuration() > 0 && !(aura->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_HIDE_DURATION)) auraData.Flags |= AFLAG_DURATION; @@ -365,7 +365,7 @@ Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* own Aura::Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel) : m_spellInfo(spellproto), m_casterGuid(!casterGUID.IsEmpty() ? casterGUID : caster->GetGUID()), -m_castItemGuid(castItem ? castItem->GetGUID() : ObjectGuid::Empty), m_castItemLevel(castItemLevel), +m_castItemGuid(castItem ? castItem->GetGUID() : ObjectGuid::Empty), m_castItemLevel(castItemLevel), m_spellXSpellVisualId(caster ? caster->GetCastSpellXSpellVisualId(spellproto) : spellproto->GetSpellXSpellVisualId()), m_applyTime(time(NULL)), m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0), m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1), m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr), diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 27e2333bd97..33b4f41c34d 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -133,6 +133,7 @@ class TC_GAME_API Aura ObjectGuid GetCastItemGUID() const { return m_castItemGuid; } int32 GetCastItemLevel() const { return m_castItemLevel; } ObjectGuid GetCasterGUID() const { return m_casterGuid; } + uint32 GetSpellXSpellVisualId() const { return m_spellXSpellVisualId; } Unit* GetCaster() const; WorldObject* GetOwner() const { return m_owner; } Unit* GetUnitOwner() const { ASSERT(GetType() == UNIT_AURA_TYPE); return (Unit*)m_owner; } @@ -300,6 +301,7 @@ class TC_GAME_API Aura ObjectGuid const m_casterGuid; ObjectGuid const m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted int32 m_castItemLevel; + uint32 const m_spellXSpellVisualId; time_t const m_applyTime; WorldObject* const m_owner; @@ -313,7 +315,6 @@ class TC_GAME_API Aura uint8 m_procCharges; // Aura charges (0 for infinite) uint8 m_stackAmount; // Aura stack amount - //AuraEffect* m_effects[3]; ApplicationMap m_applications; bool m_isRemoved; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 34261f4f0e2..a09d97b8e68 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -591,7 +591,7 @@ m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)), focusObject = NULL; m_cast_count = 0; memset(m_misc.Raw.Data, 0, sizeof(m_misc.Raw.Data)); - m_SpellVisual = m_spellInfo->GetSpellXSpellVisualId(caster->GetMap()->GetDifficultyID()); + m_SpellVisual = caster->GetCastSpellXSpellVisualId(m_spellInfo); m_preCastSpell = 0; m_triggeredByAuraSpell = NULL; m_spellAura = NULL; @@ -4355,7 +4355,7 @@ void Spell::SendChannelStart(uint32 duration) m_caster->SetChannelObjectGuid(channelTarget); m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, m_spellInfo->Id); - m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL_X_SPELL_VISUAL, m_spellInfo->GetSpellXSpellVisualId(m_caster->GetMap()->GetDifficultyID())); + m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL_X_SPELL_VISUAL, m_SpellVisual); } void Spell::SendResurrectRequest(Player* target) @@ -6763,7 +6763,7 @@ bool Spell::IsAutoActionResetSpell() const bool Spell::IsNeedSendToClient() const { - return m_spellInfo->GetSpellXSpellVisualId(m_caster->GetMap()->GetDifficultyID()) || m_spellInfo->IsChanneled() || + return m_SpellVisual || m_spellInfo->IsChanneled() || (m_spellInfo->HasAttribute(SPELL_ATTR8_AURA_SEND_AMOUNT)) || m_spellInfo->Speed > 0.0f || (!m_triggeredByAuraSpell && !IsTriggered()); } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 9f457e5672a..193cdeb2c8f 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1542,7 +1542,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex) if (!caster->IsInWorld()) return; DynamicObject* dynObj = new DynamicObject(false); - if (!dynObj->CreateDynamicObject(caster->GetMap()->GenerateLowGuid(), caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL)) + if (!dynObj->CreateDynamicObject(caster->GetMap()->GenerateLowGuid(), caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_AREA_SPELL, m_SpellVisual)) { delete dynObj; return; @@ -2383,7 +2383,7 @@ void Spell::EffectAddFarsight(SpellEffIndex /*effIndex*/) return; DynamicObject* dynObj = new DynamicObject(true); - if (!dynObj->CreateDynamicObject(m_caster->GetMap()->GenerateLowGuid(), m_caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS)) + if (!dynObj->CreateDynamicObject(m_caster->GetMap()->GenerateLowGuid(), m_caster, m_spellInfo, *destTarget, radius, DYNAMIC_OBJECT_FARSIGHT_FOCUS, m_SpellVisual)) { delete dynObj; return; @@ -2642,10 +2642,10 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex) else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN) duration = 3600; // 30 mins // other cases with this SpellVisual already selected - else if (m_spellInfo->GetSpellVisual(DIFFICULTY_NONE) == 215) + else if (m_spellInfo->GetSpellVisual() == 215) duration = 1800; // 30 mins // some fishing pole bonuses except Glow Worm which lasts full hour - else if (m_spellInfo->GetSpellVisual(DIFFICULTY_NONE) == 563 && m_spellInfo->Id != 64401) + else if (m_spellInfo->GetSpellVisual() == 563 && m_spellInfo->Id != 64401) duration = 600; // 10 mins else if (m_spellInfo->Id == 29702) duration = 300; // 5 mins @@ -5693,7 +5693,7 @@ void Spell::EffectCreateAreaTrigger(SpellEffIndex /*effIndex*/) uint32 triggerEntry = effectInfo->MiscValue; AreaTrigger * areaTrigger = new AreaTrigger; - if (!areaTrigger->CreateAreaTrigger(GetCaster()->GetMap()->GenerateLowGuid(), triggerEntry, GetCaster(), GetSpellInfo(), pos)) + if (!areaTrigger->CreateAreaTrigger(GetCaster()->GetMap()->GenerateLowGuid(), triggerEntry, GetCaster(), GetSpellInfo(), pos, m_SpellVisual)) delete areaTrigger; } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 25a5c874a58..f38cf40dd96 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1039,6 +1039,9 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntryMap const& ef ActiveIconID = _misc ? _misc->ActiveIconID : 0; _visuals = std::move(visuals); + // sort all visuals so that the ones without a condition requirement are last on the list + for (auto& visualPair : _visuals) + std::sort(visualPair.second.begin(), visualPair.second.end(), [](SpellXSpellVisualEntry const* first, SpellXSpellVisualEntry const* second) { return first->PlayerConditionID > second->PlayerConditionID; }); // SpellScalingEntry SpellScalingEntry const* _scaling = GetSpellScaling(); @@ -2935,32 +2938,46 @@ bool SpellInfo::IsHighRankOf(SpellInfo const* spellInfo) const return false; } -uint32 SpellInfo::GetSpellXSpellVisualId(Difficulty difficulty) const +uint32 SpellInfo::GetSpellXSpellVisualId(Unit const* caster /*= nullptr*/) const { - DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty); - while (difficultyEntry) + if (caster) { - auto itr = _visuals.find(difficulty); - if (itr != _visuals.end()) - for (SpellXSpellVisualEntry const* visual : itr->second) - if (!visual->PlayerConditionID) - return visual->ID; + Difficulty difficulty = caster->GetMap()->GetDifficultyID(); + DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty); + while (difficultyEntry) + { + auto itr = _visuals.find(difficulty); + if (itr != _visuals.end()) + { + for (SpellXSpellVisualEntry const* visual : itr->second) + { + PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(visual->PlayerConditionID); + if (!playerCondition || (caster->GetTypeId() == TYPEID_PLAYER && sConditionMgr->IsPlayerMeetingCondition(caster->ToPlayer(), playerCondition))) + return visual->ID; + } + } - difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID); + difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID); + } } auto itr = _visuals.find(DIFFICULTY_NONE); if (itr != _visuals.end()) + { for (SpellXSpellVisualEntry const* visual : itr->second) - if (!visual->PlayerConditionID) + { + PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(visual->PlayerConditionID); + if (!playerCondition || (caster && caster->GetTypeId() == TYPEID_PLAYER && sConditionMgr->IsPlayerMeetingCondition(caster->ToPlayer(), playerCondition))) return visual->ID; + } + } return 0; } -uint32 SpellInfo::GetSpellVisual(Difficulty difficulty, Player* /*forPlayer*/ /*= nullptr*/) const +uint32 SpellInfo::GetSpellVisual(Unit const* caster /*= nullptr*/) const { - if (SpellXSpellVisualEntry const* visual = sSpellXSpellVisualStore.LookupEntry(GetSpellXSpellVisualId(difficulty))) + if (SpellXSpellVisualEntry const* visual = sSpellXSpellVisualStore.LookupEntry(GetSpellXSpellVisualId(caster))) { //if (visual->SpellVisualID[1] && forPlayer->GetViolenceLevel() operator 2) // return visual->SpellVisualID[1]; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 3ca96b3c0e9..f749539f51f 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -573,8 +573,8 @@ public: bool IsDifferentRankOf(SpellInfo const* spellInfo) const; bool IsHighRankOf(SpellInfo const* spellInfo) const; - uint32 GetSpellXSpellVisualId(Difficulty difficulty) const; - uint32 GetSpellVisual(Difficulty difficulty, Player* forPlayer = nullptr) const; + uint32 GetSpellXSpellVisualId(Unit const* caster = nullptr) const; + uint32 GetSpellVisual(Unit const* caster = nullptr) const; // loading helpers void _InitializeExplicitTargetMask(); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index d001705bc79..6768eb10b46 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -69,24 +69,24 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) case SPELLFAMILY_GENERIC: { // Entrapment -- 135373 - if (spellproto->SpellIconID == 20 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39588) + if (spellproto->SpellIconID == 20 && spellproto->GetSpellVisual() == 39588) return DIMINISHING_ROOT; // Intimidation -- 24394 - if (spellproto->SpellIconID == 166 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 2816) + if (spellproto->SpellIconID == 166 && spellproto->GetSpellVisual() == 2816) return DIMINISHING_STUN; // Pulverize (Primal Earth Elemental) -- 118345 - if (spellproto->SpellIconID == 4507 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39877) + if (spellproto->SpellIconID == 4507 && spellproto->GetSpellVisual() == 39877) return DIMINISHING_STUN; // Static Charge (Capacitor Totem) -- 118905 - if (spellproto->SpellIconID == 54 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 24442) + if (spellproto->SpellIconID == 54 && spellproto->GetSpellVisual() == 24442) return DIMINISHING_STUN; // Remorseless Winter -- 115001 - if (spellproto->SpellIconID == 5744 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 23514) + if (spellproto->SpellIconID == 5744 && spellproto->GetSpellVisual() == 23514) return DIMINISHING_STUN; // Gorefiend's Grasp -- 108199 - if (spellproto->SpellIconID == 5743 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 28937) + if (spellproto->SpellIconID == 5743 && spellproto->GetSpellVisual() == 28937) return DIMINISHING_AOE_KNOCKBACK; break; } @@ -151,7 +151,7 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) if (spellproto->SpellFamilyFlags[1] & 0x8000000) return DIMINISHING_INCAPACITATE; // Blood Horror -- 137143, no flags (17986) - if (spellproto->SpellIconID == 6447 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 26758) + if (spellproto->SpellIconID == 6447 && spellproto->GetSpellVisual() == 26758) return DIMINISHING_INCAPACITATE; // Fear -- 118699 @@ -195,11 +195,11 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) if (spellproto->SpellFamilyFlags[0] & 0x2000) return DIMINISHING_STUN; // Rake -- 163505 -- no flags on the stun, 20490 - if (spellproto->SpellIconID == 494 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38283) + if (spellproto->SpellIconID == 494 && spellproto->GetSpellVisual() == 38283) return DIMINISHING_STUN; // Incapacitating Roar -- 99, no flags on the stun, 14 - if (spellproto->SpellIconID == 960 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38528) + if (spellproto->SpellIconID == 960 && spellproto->GetSpellVisual() == 38528) return DIMINISHING_INCAPACITATE; // Cyclone -- 33786 @@ -221,7 +221,7 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) if (spellproto->SpellFamilyFlags[0] & 0x200) return DIMINISHING_ROOT; // Mass Entanglement -- 102359, no flags on the root, 13535 - if (spellproto->SpellIconID == 5782 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38269) + if (spellproto->SpellIconID == 5782 && spellproto->GetSpellVisual() == 38269) return DIMINISHING_ROOT; // Faerie Fire -- 770, 20 seconds in PvP (6.0) @@ -260,14 +260,14 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) // return DIMINISHING_AOE_KNOCKBACK; // Charge (Tenacity pet) -- 53148, no flags (5526) - if (spellproto->SpellIconID == 1559 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39480) + if (spellproto->SpellIconID == 1559 && spellproto->GetSpellVisual() == 39480) return DIMINISHING_ROOT; // Narrow Escape -- 136634, no flags (17964) if (spellproto->SpellIconID == 3342 && spellproto->SchoolMask == 8) return DIMINISHING_ROOT; // Binding Shot -- 117526, no flags (15581) - if (spellproto->SpellIconID == 4612 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 6859) + if (spellproto->SpellIconID == 4612 && spellproto->GetSpellVisual() == 6859) return DIMINISHING_STUN; // Freezing Trap -- 3355 @@ -314,7 +314,7 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) if (spellproto->SpellFamilyFlags[2] & 0x4000) return DIMINISHING_ROOT; // Frost Shock (with Frozen Power) -- 63685, no flags (6918) - if (spellproto->SpellIconID == 193 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39876) + if (spellproto->SpellIconID == 193 && spellproto->GetSpellVisual() == 39876) return DIMINISHING_ROOT; break; } @@ -325,31 +325,31 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) return DIMINISHING_SILENCE; // Chains of Ice (with Chilblains) -- 96294, no flags (13020) - if (spellproto->SpellIconID == 180 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 20135) + if (spellproto->SpellIconID == 180 && spellproto->GetSpellVisual() == 20135) return DIMINISHING_ROOT; // Asphyxiate -- 108194 if (spellproto->SpellFamilyFlags[2] & 0x100000) return DIMINISHING_STUN; // Gnaw (Ghoul) -- 91800, no flags (12511) - if (spellproto->SpellIconID == 3010 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38760) + if (spellproto->SpellIconID == 3010 && spellproto->GetSpellVisual() == 38760) return DIMINISHING_STUN; // Monstrous Blow (Ghoul w/ Dark Transformation active) -- 91797, no flags (12510) - if (spellproto->SpellIconID == 15 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38761) + if (spellproto->SpellIconID == 15 && spellproto->GetSpellVisual() == 38761) return DIMINISHING_STUN; break; } case SPELLFAMILY_PRIEST: { // Glyph of Mind Blast -- 87194, no flags (10092) - if (spellproto->SpellIconID == 2114 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 38927) + if (spellproto->SpellIconID == 2114 && spellproto->GetSpellVisual() == 38927) return DIMINISHING_ROOT; // Void Tendrils -- 114404, no flags (15067) - if (spellproto->SpellIconID == 5816 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 25199) + if (spellproto->SpellIconID == 5816 && spellproto->GetSpellVisual() == 25199) return DIMINISHING_ROOT; // Dominate Mind -- 605 - if (spellproto->SpellFamilyFlags[0] & 0x20000 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39068) + if (spellproto->SpellFamilyFlags[0] & 0x20000 && spellproto->GetSpellVisual() == 39068) return DIMINISHING_INCAPACITATE; // Holy Word: Chastise -- 88625 if (spellproto->SpellFamilyFlags[2] & 0x20) @@ -370,7 +370,7 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) case SPELLFAMILY_MONK: { // Disable -- 116706, no flags (15483) - if (spellproto->SpellIconID == 23 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39984) + if (spellproto->SpellIconID == 23 && spellproto->GetSpellVisual() == 39984) return DIMINISHING_ROOT; // Charging Ox Wave -- 119392 @@ -384,13 +384,13 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) return DIMINISHING_STUN; // Glyph of Breath of Fire -- 123393, no flags (16504) - if (spellproto->SpellIconID == 15 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 25408) + if (spellproto->SpellIconID == 15 && spellproto->GetSpellVisual() == 25408) return DIMINISHING_INCAPACITATE; // Paralysis -- 115078 if (spellproto->SpellFamilyFlags[2] & 0x800000) return DIMINISHING_INCAPACITATE; // Ring of Peace -- 137460, no flags (18006) - if (spellproto->SpellIconID == 7195 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 39999) + if (spellproto->SpellIconID == 7195 && spellproto->GetSpellVisual() == 39999) return DIMINISHING_INCAPACITATE; break; } @@ -444,7 +444,7 @@ int32 GetDiminishingReturnsLimitDuration(SpellInfo const* spellproto) case SPELLFAMILY_HUNTER: { // Binding Shot - 3 seconds in PvP (6.0) - if (spellproto->SpellIconID == 4612 && spellproto->GetSpellVisual(DIFFICULTY_NONE) == 6859) + if (spellproto->SpellIconID == 4612 && spellproto->GetSpellVisual() == 6859) return 3 * IN_MILLISECONDS; // Wyvern Sting - 6 seconds in PvP (6.0) if (spellproto->SpellFamilyFlags[1] & 0x1000) @@ -2835,7 +2835,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes() if (!spellInfo->_IsPositiveEffect(EFFECT_2, false)) spellInfo->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF2; - if (spellInfo->GetSpellVisual(DIFFICULTY_NONE) == 3879) + if (spellInfo->GetSpellVisual() == 3879) spellInfo->AttributesCu |= SPELL_ATTR0_CU_CONE_BACK; if (talentSpells.count(spellInfo->Id)) -- cgit v1.2.3 From 1b1478ba86addad3e4aecbacd625a1dbcc18e48c Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 30 Jun 2016 17:20:13 +0200 Subject: Core/Auras: Implemented spell aura 402 - SPELL_AURA_MOD_POWER_DISPLAY Closes #17468 --- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Spells/Auras/SpellAuraDefines.h | 2 +- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 24 ++++++++++++++++++++++- src/server/game/Spells/Auras/SpellAuraEffects.h | 1 + 4 files changed, 26 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 9b95fe9b5a4..f65449dbf74 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -16123,7 +16123,7 @@ uint32 Unit::GetCastSpellXSpellVisualId(SpellInfo const* spellInfo) const Unit::AuraEffectList const& visualOverrides = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_SPELL_VISUAL); for (AuraEffect const* effect : visualOverrides) { - if (effect->GetMiscValue() == spellInfo->Id) + if (uint32(effect->GetMiscValue()) == spellInfo->Id) { if (SpellInfo const* visualSpell = sSpellMgr->GetSpellInfo(effect->GetMiscValueB())) { diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index ae34e06fe37..b063788f76f 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -459,7 +459,7 @@ enum AuraType SPELL_AURA_399 = 399, SPELL_AURA_MOD_SKILL_2 = 400, SPELL_AURA_401 = 401, - SPELL_AURA_402 = 402, + SPELL_AURA_MOD_POWER_DISPLAY = 402, SPELL_AURA_OVERRIDE_SPELL_VISUAL = 403, SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT = 404, SPELL_AURA_MOD_RATING_PCT = 405, // NYI diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 136aea7a811..cab3dc8f6e6 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -461,7 +461,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //399 &AuraEffect::HandleAuraModSkill, //400 SPELL_AURA_MOD_SKILL_2 &AuraEffect::HandleNULL, //401 - &AuraEffect::HandleNULL, //402 + &AuraEffect::HandleModPowerDisplay, //402 SPELL_AURA_MOD_POWER_DISPLAY &AuraEffect::HandleNoImmediateEffect, //403 SPELL_AURA_OVERRIDE_SPELL_VISUAL implemented in Unit::GetCastSpellXSpellVisualId &AuraEffect::HandleOverrideAttackPowerBySpellPower, //404 SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT &AuraEffect::HandleNULL, //405 SPELL_AURA_MOD_RATING_PCT @@ -4196,6 +4196,28 @@ void AuraEffect::HandleAuraModIncreaseBaseManaPercent(AuraApplication const* aur aurApp->GetTarget()->HandleStatModifier(UNIT_MOD_MANA, BASE_PCT, float(GetAmount()), apply); } +void AuraEffect::HandleModPowerDisplay(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + PowerDisplayEntry const* powerDisplay = sPowerDisplayStore.LookupEntry(GetMiscValue()); + if (!powerDisplay) + return; + + Unit* target = aurApp->GetTarget(); + if (target->GetPowerIndex(powerDisplay->PowerType) == MAX_POWERS) + return; + + if (apply) + { + target->RemoveAurasByType(GetAuraType(), ObjectGuid::Empty, GetBase()); + target->SetUInt32Value(UNIT_FIELD_OVERRIDE_DISPLAY_POWER_ID, powerDisplay->ID); + } + else + target->SetUInt32Value(UNIT_FIELD_OVERRIDE_DISPLAY_POWER_ID, 0); +} + /********************************/ /*** FIGHT ***/ /********************************/ diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index a046a675eb4..73766bbcf1a 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -248,6 +248,7 @@ class TC_GAME_API AuraEffect void HandleAuraModIncreaseHealthPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraIncreaseBaseHealthPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModIncreaseBaseManaPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleModPowerDisplay(AuraApplication const* aurApp, uint8 mode, bool apply) const; // fight void HandleAuraModParryPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModDodgePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const; -- cgit v1.2.3 From ef396877ae68e6f71638b1da961a295131feb8da Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 1 Jul 2016 20:26:49 +0200 Subject: Core/Spells: Fixed spell range check Closes #17060 (cherry picked from commit e6a52d4aae9e8facc46c3b05e0560d540a928d73) --- src/server/game/Entities/Item/ItemTemplate.h | 1 + src/server/game/Entities/Unit/Unit.cpp | 8 +- src/server/game/Entities/Unit/Unit.h | 1 - src/server/game/Spells/Spell.cpp | 92 ++++++++++++++-------- .../EasternKingdoms/Karazhan/boss_moroes.cpp | 2 +- 5 files changed, 64 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h index d69f1c88845..76c129d325a 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -680,6 +680,7 @@ struct TC_GAME_API ItemTemplate uint32 GetScalingStatDistribution() const { return ExtendedData->ScalingStatDistribution; } uint32 GetDamageType() const { return ExtendedData->DamageType; } uint32 GetDelay() const { return ExtendedData->Delay; } + float GetRangedModRange() const { return ExtendedData->RangedModRange; } ItemBondingType GetBonding() const { return ItemBondingType(ExtendedData->Bonding); } char const* GetName(LocaleConstant locale) const; uint32 GetPageText() const { return ExtendedData->PageText; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f65449dbf74..c408d4390cd 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -484,12 +484,6 @@ void Unit::resetAttackTimer(WeaponAttackType type) m_attackTimer[type] = uint32(GetAttackTime(type) * m_modAttackSpeedPct[type]); } -float Unit::GetMeleeReach() const -{ - float reach = m_floatValues[UNIT_FIELD_COMBATREACH]; - return reach > MIN_MELEE_REACH ? reach : MIN_MELEE_REACH; -} - bool Unit::IsWithinCombatRange(const Unit* obj, float dist2compare) const { if (!obj || !IsInMap(obj) || !IsInPhase(obj)) @@ -516,7 +510,7 @@ bool Unit::IsWithinMeleeRange(const Unit* obj, float dist) const float dz = GetPositionZMinusOffset() - obj->GetPositionZMinusOffset(); float distsq = dx*dx + dy*dy + dz*dz; - float sizefactor = GetMeleeReach() + obj->GetMeleeReach(); + float sizefactor = GetCombatReach() + obj->GetCombatReach() + 4.0f / 3.0f; float maxdist = dist + sizefactor; return distsq < maxdist * maxdist; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 2ee0ea8873a..962d9549f2c 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1365,7 +1365,6 @@ class TC_GAME_API Unit : public WorldObject bool CanDualWield() const { return m_canDualWield; } virtual void SetCanDualWield(bool value) { m_canDualWield = value; } float GetCombatReach() const { return m_floatValues[UNIT_FIELD_COMBATREACH]; } - float GetMeleeReach() const; bool IsWithinCombatRange(const Unit* obj, float dist2compare) const; bool IsWithinMeleeRange(const Unit* obj, float dist = MELEE_RANGE) const; void GetRandomContactPoint(const Unit* target, float &x, float &y, float &z, float distance2dMin, float distance2dMax) const; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index a09d97b8e68..2b59926fa33 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5924,43 +5924,73 @@ SpellCastResult Spell::CheckRange(bool strict) if (!strict && m_casttime == 0) return SPELL_CAST_OK; - uint32 range_type = 0; + Unit* target = m_targets.GetUnitTarget(); + float minRange = 0.0f; + float maxRange = 0.0f; + float rangeMod = 0.0f; + if (strict && IsNextMeleeSwingSpell()) + maxRange = 100.0f; + else if (m_spellInfo->RangeEntry) + { + if (m_spellInfo->RangeEntry->Flags & SPELL_RANGE_MELEE) + { + rangeMod = m_caster->GetCombatReach() + 4.0f / 3.0f; + if (target) + rangeMod += target->GetCombatReach(); + else + rangeMod += m_caster->GetCombatReach(); - if (m_spellInfo->RangeEntry) - { - // check needed by 68766 51693 - both spells are cast on enemies and have 0 max range - // these are triggered by other spells - possibly we should omit range check in that case? - if (m_spellInfo->RangeEntry->ID == 1) - return SPELL_CAST_OK; + rangeMod = std::max(rangeMod, NOMINAL_MELEE_RANGE); + } + else + { + float meleeRange = 0.0f; + if (m_spellInfo->RangeEntry->Flags & SPELL_RANGE_RANGED) + { + meleeRange = m_caster->GetCombatReach() + 4.0f / 3.0f; + if (target) + meleeRange += target->GetCombatReach(); + else + meleeRange += m_caster->GetCombatReach(); + + meleeRange = std::max(meleeRange, NOMINAL_MELEE_RANGE); + } + + minRange = m_caster->GetSpellMinRangeForTarget(target, m_spellInfo) + meleeRange; + maxRange = m_caster->GetSpellMaxRangeForTarget(target, m_spellInfo); - range_type = m_spellInfo->RangeEntry->Flags; + if (target || m_targets.GetCorpseTarget()) + { + rangeMod = m_caster->GetCombatReach(); + if (target) + rangeMod += target->GetCombatReach(); + + if (minRange > 0.0f && !(m_spellInfo->RangeEntry->Flags & SPELL_RANGE_RANGED)) + minRange += rangeMod; + } + } + + if (target && m_caster->isMoving() && target->isMoving() && !m_caster->IsWalking() && !target->IsWalking() && + (m_spellInfo->RangeEntry->Flags & SPELL_RANGE_MELEE || target->GetTypeId() == TYPEID_PLAYER)) + rangeMod += 5.0f / 3.0f; } - Unit* target = m_targets.GetUnitTarget(); - float max_range = m_caster->GetSpellMaxRangeForTarget(target, m_spellInfo); - float min_range = m_caster->GetSpellMinRangeForTarget(target, m_spellInfo); + if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) && m_caster->GetTypeId() == TYPEID_PLAYER) + if (Item* ranged = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK, true)) + maxRange *= ranged->GetTemplate()->GetRangedModRange() * 0.01f; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range, this); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, maxRange, this); + + maxRange += rangeMod; if (target && target != m_caster) { - if (range_type == SPELL_RANGE_MELEE) - { - // Because of lag, we can not check too strictly here. - if (!m_caster->IsWithinMeleeRange(target, max_range)) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; - } - else if (!m_caster->IsWithinCombatRange(target, max_range)) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; //0x5A; + if (!m_caster->IsInDist(target, maxRange)) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; - if (range_type == SPELL_RANGE_RANGED) - { - if (m_caster->IsWithinMeleeRange(target)) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_TOO_CLOSE : SPELL_FAILED_DONT_REPORT; - } - else if (min_range && m_caster->IsWithinCombatRange(target, min_range)) // skip this check if min_range = 0 - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_TOO_CLOSE : SPELL_FAILED_DONT_REPORT; + if (minRange > 0.0f && m_caster->IsInDist(target, minRange)) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; if (m_caster->GetTypeId() == TYPEID_PLAYER && (m_spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT) && !m_caster->HasInArc(static_cast(M_PI), target)) @@ -5969,10 +5999,10 @@ SpellCastResult Spell::CheckRange(bool strict) if (m_targets.HasDst() && !m_targets.HasTraj()) { - if (!m_caster->IsWithinDist3d(m_targets.GetDstPos(), max_range)) - return SPELL_FAILED_OUT_OF_RANGE; - if (min_range && m_caster->IsWithinDist3d(m_targets.GetDstPos(), min_range)) - return SPELL_FAILED_TOO_CLOSE; + if (!m_caster->IsInDist(m_targets.GetDstPos(), maxRange)) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; + if (minRange > 0.0f && m_caster->IsInDist(m_targets.GetDstPos(), minRange)) + return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; } return SPELL_CAST_OK; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp index b87c836c2a4..84ee5cd97db 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp @@ -298,7 +298,7 @@ public: if (Blind_Timer <= diff) { std::list targets; - SelectTargetList(targets, 5, SELECT_TARGET_RANDOM, me->GetMeleeReach()*5, true); + SelectTargetList(targets, 5, SELECT_TARGET_RANDOM, me->GetCombatReach()*5, true); for (std::list::const_iterator i = targets.begin(); i != targets.end(); ++i) if (!me->IsWithinMeleeRange(*i)) { -- cgit v1.2.3 From 54881d22969c0c10f098ce697878b22bae8076a9 Mon Sep 17 00:00:00 2001 From: Aokromes Date: Sat, 2 Jul 2016 13:20:18 +0200 Subject: Update worldserver.conf.dist --- src/server/worldserver/worldserver.conf.dist | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 2bf6b42d703..ad225ac77d5 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -99,6 +99,12 @@ LogsDir = "" # "127.0.0.1;3306;trinity;trinity;world" - (WorldDatabaseInfo) # "127.0.0.1;3306;trinity;trinity;characters" - (CharacterDatabaseInfo) # "127.0.0.1;3306;trinity;trinity;hotfixes" - (HotfixDatabaseInfo) +# +# Don't change hostname unless you are hosting mysql on a different machine, if you need help +# with configuration allowing to connect from diferent machine than the one running server +# search for TCE00016 on forum. +# Don't open port on firewall to external connections (it belongs to mysql, not to wow server). +# The username you choice must have permisions to create/alter/rename tables. LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth" WorldDatabaseInfo = "127.0.0.1;3306;trinity;trinity;world" -- cgit v1.2.3 From e76f5bd93e0699e4d6f10d5037592df007bbcb9f Mon Sep 17 00:00:00 2001 From: Aokromes Date: Sat, 2 Jul 2016 14:18:18 +0200 Subject: Update worldserver.conf.dist --- src/server/worldserver/worldserver.conf.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index ad225ac77d5..eeb2be26a23 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -104,7 +104,7 @@ LogsDir = "" # with configuration allowing to connect from diferent machine than the one running server # search for TCE00016 on forum. # Don't open port on firewall to external connections (it belongs to mysql, not to wow server). -# The username you choice must have permisions to create/alter/rename tables. +# The username you choose must have permisions to create/alter/rename tables. LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth" WorldDatabaseInfo = "127.0.0.1;3306;trinity;trinity;world" -- cgit v1.2.3 From 77f980035a43a9156c22130042d1fb6597139ee0 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 2 Jul 2016 22:44:03 +0200 Subject: Core/Items: Implemented scaling item enchants with player level --- src/server/game/Entities/Player/Player.cpp | 43 +++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index aedb283e368..b60dce4f668 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7914,11 +7914,10 @@ void Player::_ApplyAllLevelScaleItemMods(bool apply) { if (m_items[i]) { - if (m_items[i]->IsBroken() || !CanUseAttackType(Player::GetAttackBySlot(i, m_items[i]->GetTemplate()->GetInventoryType()))) + if (!CanUseAttackType(Player::GetAttackBySlot(i, m_items[i]->GetTemplate()->GetInventoryType()))) continue; - _ApplyItemBonuses(m_items[i], i, apply); - ApplyItemEquipSpell(m_items[i], apply); + _ApplyItemMods(m_items[i], i, apply); } } } @@ -12833,6 +12832,25 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool } break; case ITEM_ENCHANTMENT_TYPE_RESISTANCE: + if (pEnchant->ScalingClass) + { + int32 scalingClass = pEnchant->ScalingClass; + if ((GetUInt32Value(UNIT_FIELD_MIN_ITEM_LEVEL) || GetUInt32Value(UNIT_FIELD_MAXITEMLEVEL)) && pEnchant->ScalingClassRestricted) + scalingClass = pEnchant->ScalingClassRestricted; + + uint8 minLevel = pEnchant->Flags & 0x20 ? 1 : 60; + uint8 scalingLevel = getLevel(); + uint8 maxLevel = uint8(pEnchant->MaxLevel ? pEnchant->MaxLevel : sGtSpellScalingStore.GetTableRowCount()); + + if (minLevel > getLevel()) + scalingLevel = minLevel; + else if (maxLevel < getLevel()) + scalingLevel = maxLevel; + + if (GtSpellScalingEntry const* spellScaling = sGtSpellScalingStore.EvaluateTable(scalingLevel - 1, MAX_CLASSES - 1 - scalingClass)) + enchant_amount = uint32(pEnchant->EffectScalingPoints[s] * spellScaling->value); + } + if (!enchant_amount) { ItemRandomSuffixEntry const* item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); @@ -12853,6 +12871,25 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool break; case ITEM_ENCHANTMENT_TYPE_STAT: { + if (pEnchant->ScalingClass) + { + int32 scalingClass = pEnchant->ScalingClass; + if ((GetUInt32Value(UNIT_FIELD_MIN_ITEM_LEVEL) || GetUInt32Value(UNIT_FIELD_MAXITEMLEVEL)) && pEnchant->ScalingClassRestricted) + scalingClass = pEnchant->ScalingClassRestricted; + + uint8 minLevel = pEnchant->Flags & 0x20 ? 1 : 60; + uint8 scalingLevel = getLevel(); + uint8 maxLevel = uint8(pEnchant->MaxLevel ? pEnchant->MaxLevel : sGtSpellScalingStore.GetTableRowCount()); + + if (minLevel > getLevel()) + scalingLevel = minLevel; + else if (maxLevel < getLevel()) + scalingLevel = maxLevel; + + if (GtSpellScalingEntry const* spellScaling = sGtSpellScalingStore.EvaluateTable(scalingLevel - 1, (MAX_CLASSES - 1 /*ChrClasses->MaxIndex*/) - scalingClass - 1)) + enchant_amount = uint32(pEnchant->EffectScalingPoints[s] * spellScaling->value); + } + if (!enchant_amount) { ItemRandomSuffixEntry const* item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); -- cgit v1.2.3 From 9645f868ed42f2ba88c96d4106c547c480cd462b Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 3 Jul 2016 22:35:14 +0200 Subject: Core/Auras: Defined more aura types --- src/server/game/Spells/Auras/SpellAuraDefines.h | 8 ++++---- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index b063788f76f..34023c16d1b 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -519,10 +519,10 @@ enum AuraType SPELL_AURA_IGNORE_MOVEMENT_FORCES = 459, // NYI SPELL_AURA_RESET_COOLDOWNS_ON_DUEL_START = 460, // NYI SPELL_AURA_461 = 461, - SPELL_AURA_462 = 462, - SPELL_AURA_CONVER_CRIT_RATING_PCT_TO_PARRY_RATING = 463, // NYI - SPELL_AURA_464 = 464, - SPELL_AURA_465 = 465, + SPELL_AURA_MOD_HEALING_AND_ABSORB_FROM_CASTER = 462, // NYI + SPELL_AURA_CONVERT_CRIT_RATING_PCT_TO_PARRY_RATING = 463, // NYI + SPELL_AURA_MOD_ATTACK_POWER_OF_BONUS_ARMOR = 464, // NYI + SPELL_AURA_MOD_BONUS_ARMOR = 465, // NYI SPELL_AURA_MOD_BONUS_ARMOR_PCT = 466, // Affects bonus armor gain from all sources except base stats SPELL_AURA_MOD_STAT_BONUS_PCT = 467, // Affects stat gain from all sources except base stats SPELL_AURA_TRIGGER_SPELL_ON_HEALTH_BELOW_PCT = 468, // Triggers spell when health falls below specified percent value (once, not every time damage is taken below threshold) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index cab3dc8f6e6..72a002f39d5 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -521,10 +521,10 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //459 SPELL_AURA_IGNORE_MOVEMENT_FORCES &AuraEffect::HandleNULL, //460 SPELL_AURA_RESET_COOLDOWNS_ON_DUEL_START &AuraEffect::HandleNULL, //461 - &AuraEffect::HandleNULL, //462 - &AuraEffect::HandleNULL, //463 SPELL_AURA_CRIT_RATING_AFFECTS_PARRY used by Riposte - &AuraEffect::HandleNULL, //464 - &AuraEffect::HandleNULL, //465 + &AuraEffect::HandleNULL, //462 SPELL_AURA_MOD_HEALING_AND_ABSORB_FROM_CASTER + &AuraEffect::HandleNULL, //463 SPELL_AURA_CONVERT_CRIT_RATING_PCT_TO_PARRY_RATING used by Riposte + &AuraEffect::HandleNULL, //464 SPELL_AURA_MOD_ATTACK_POWER_OF_BONUS_ARMOR + &AuraEffect::HandleNULL, //465 SPELL_AURA_MOD_BONUS_ARMOR &AuraEffect::HandleNULL, //466 SPELL_AURA_MOD_BONUS_ARMOR_PCT &AuraEffect::HandleModStatBonusPercent, //467 SPELL_AURA_MOD_STAT_BONUS_PCT &AuraEffect::HandleNULL, //468 SPELL_AURA_TRIGGER_SPELL_ON_HEALTH_BELOW_PCT -- cgit v1.2.3 From d0d76abc9dc79f3bcf66445c917258c064a1f70a Mon Sep 17 00:00:00 2001 From: Shauren Date: Mon, 4 Jul 2016 22:52:07 +0200 Subject: Core/Achievements: Implemented all criteria tree operators --- src/server/game/Achievements/AchievementMgr.cpp | 2 +- src/server/game/Achievements/CriteriaHandler.cpp | 85 ++++++++++++++++++------ src/server/game/Achievements/CriteriaHandler.h | 2 +- src/server/game/DataStores/DBCEnums.h | 21 +++++- 4 files changed, 84 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 642c21e3ff1..0a8f9d95871 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -85,7 +85,7 @@ bool AchievementMgr::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTre return false; } - return true; + return CriteriaHandler::CanUpdateCriteriaTree(criteria, tree, referencePlayer); } bool AchievementMgr::CanCompleteCriteriaTree(CriteriaTree const* tree) diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp index e8e418001ad..8f2dfcda625 100644 --- a/src/server/game/Achievements/CriteriaHandler.cpp +++ b/src/server/game/Achievements/CriteriaHandler.cpp @@ -936,37 +936,80 @@ bool CriteriaHandler::IsCompletedCriteriaTree(CriteriaTree const* tree) return false; uint64 requiredCount = tree->Entry->Amount; - uint64 completedCount = 0; - uint32 op = tree->Entry->Operator; - bool hasAll = true; - - // Check criteria we depend on first - for (CriteriaTree const* node : tree->Children) + switch (tree->Entry->Operator) { - if (IsCompletedCriteriaTree(node)) - ++completedCount; - else - hasAll = false; + case CRITERIA_TREE_OPERATOR_SINGLE: + return tree->Criteria && IsCompletedCriteria(tree->Criteria, requiredCount); + case CRITERIA_TREE_OPERATOR_SINGLE_NOT_COMPLETED: + return !tree->Criteria || !IsCompletedCriteria(tree->Criteria, requiredCount); + case CRITERIA_TREE_OPERATOR_ALL: + for (CriteriaTree const* node : tree->Children) + if (!IsCompletedCriteriaTree(node)) + return false; + return true; + case CRITERIA_TREE_OPERAROR_SUM_CHILDREN: + { + uint64 progress = 0; + CriteriaMgr::WalkCriteriaTree(tree, [this, &progress](CriteriaTree const* criteriaTree) + { + if (criteriaTree->Criteria) + if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(criteriaTree->Criteria)) + progress += criteriaProgress->Counter; + }); + return progress >= requiredCount; + } + case CRITERIA_TREE_OPERATOR_MAX_CHILD: + { + uint64 progress = 0; + CriteriaMgr::WalkCriteriaTree(tree, [this, &progress](CriteriaTree const* criteriaTree) + { + if (criteriaTree->Criteria) + if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(criteriaTree->Criteria)) + if (criteriaProgress->Counter > progress) + progress = criteriaProgress->Counter; + }); + return progress >= requiredCount; + } + case CRITERIA_TREE_OPERATOR_COUNT_DIRECT_CHILDREN: + { + uint64 progress = 0; + for (CriteriaTree const* node : tree->Children) + if (node->Criteria) + if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(node->Criteria)) + if (criteriaProgress->Counter >= 1) + if (++progress >= requiredCount) + return true; - if (op & CRITERIA_TREE_OPERATOR_ANY && completedCount >= requiredCount) + return false; + } + case CRITERIA_TREE_OPERATOR_ANY: { - if (!tree->Criteria) - return true; + uint64 progress = 0; + for (CriteriaTree const* node : tree->Children) + if (IsCompletedCriteriaTree(node)) + if (++progress >= requiredCount) + return true; - break; + return false; } + default: + break; } - if (op & CRITERIA_TREE_OPERATOR_ANY && completedCount < requiredCount) - return false; + return false; +} - if (op & CRITERIA_TREE_OPERATOR_ALL && !hasAll) +bool CriteriaHandler::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const +{ + if ((tree->Entry->Flags & CRITERIA_TREE_FLAG_HORDE_ONLY && referencePlayer->GetTeam() != HORDE) || + (tree->Entry->Flags & CRITERIA_TREE_FLAG_ALLIANCE_ONLY && referencePlayer->GetTeam() != ALLIANCE)) + { + TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteriaTree: (Id: %u Type %s CriteriaTree %u) Wrong faction", + criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), tree->Entry->ID); return false; + } - if (!tree->Criteria) - return true; - - return IsCompletedCriteria(tree->Criteria, requiredCount); + return true; } bool CriteriaHandler::CanCompleteCriteriaTree(CriteriaTree const* /*tree*/) diff --git a/src/server/game/Achievements/CriteriaHandler.h b/src/server/game/Achievements/CriteriaHandler.h index 03a4f30136e..91bedbab44f 100644 --- a/src/server/game/Achievements/CriteriaHandler.h +++ b/src/server/game/Achievements/CriteriaHandler.h @@ -273,7 +273,7 @@ protected: virtual void SendCriteriaProgressRemoved(uint32 criteriaId) = 0; bool IsCompletedCriteriaTree(CriteriaTree const* tree); - virtual bool CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const = 0; + virtual bool CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const; virtual bool CanCompleteCriteriaTree(CriteriaTree const* tree); virtual void CompletedCriteriaTree(CriteriaTree const* tree, Player* referencePlayer) = 0; virtual void AfterCriteriaTreeUpdate(CriteriaTree const* /*tree*/, Player* /*referencePlayer*/) { } diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 710e92ca712..3501dbc55c9 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -407,10 +407,25 @@ enum CriteriaTypes #define CRITERIA_TYPE_TOTAL 190 -enum CriteriaTreeOperator +enum CriteriaTreeFlags : uint16 { - CRITERIA_TREE_OPERATOR_ALL = 4, - CRITERIA_TREE_OPERATOR_ANY = 8 + CRITERIA_TREE_FLAG_PROGRESS_BAR = 0x0001, + CRITERIA_TREE_FLAG_PROGRESS_IS_DATE = 0x0004, + CRITERIA_TREE_FLAG_SHOW_CURRENCY_ICON = 0x0008, + CRITERIA_TREE_FLAG_ALLIANCE_ONLY = 0x0200, + CRITERIA_TREE_FLAG_HORDE_ONLY = 0x0400, + CRITERIA_TREE_FLAG_SHOW_REQUIRED_COUNT = 0x0800 +}; + +enum CriteriaTreeOperator : uint8 +{ + CRITERIA_TREE_OPERATOR_SINGLE = 0, + CRITERIA_TREE_OPERATOR_SINGLE_NOT_COMPLETED = 1, + CRITERIA_TREE_OPERATOR_ALL = 4, + CRITERIA_TREE_OPERAROR_SUM_CHILDREN = 5, + CRITERIA_TREE_OPERATOR_MAX_CHILD = 6, + CRITERIA_TREE_OPERATOR_COUNT_DIRECT_CHILDREN = 7, + CRITERIA_TREE_OPERATOR_ANY = 8 }; enum Difficulty : uint8 -- cgit v1.2.3 From c0df97276815f6bdf10b3df938e242bec13d2a8b Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 5 Jul 2016 00:02:04 +0200 Subject: Core/Spells: Fixed crash with DEST targets added in b3d814ee50b265c140d65b6f92ce42482ce1f39b --- src/server/game/Spells/Spell.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 2b59926fa33..1068e406e78 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -6906,8 +6906,11 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time) // delaying had just started, record the moment m_Spell->SetDelayStart(e_time); // handle effects on caster if the spell has travel time but also affects the caster in some way - uint64 n_offset = m_Spell->handle_delayed(0); - ASSERT(n_offset == m_Spell->GetDelayMoment()); + if (!m_Spell->m_targets.HasDst()) + { + uint64 n_offset = m_Spell->handle_delayed(0); + ASSERT(n_offset == m_Spell->GetDelayMoment()); + } // re-plan the event for the delay moment m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + m_Spell->GetDelayMoment(), false); return false; // event not complete -- cgit v1.2.3 From 1a891f3a5edf173adcd304aa4bfc6828b63fb507 Mon Sep 17 00:00:00 2001 From: Naios Date: Sat, 2 Jul 2016 18:38:24 +0200 Subject: Core/Scripting: Don't force event cancellation when swapping creatures. * EventProcessor::KillAllEvents(force = false) should only be used by the EventProcessor. (cherry picked from commit d68316fcd2fc71343edfbd387249b75bd6e8a90f) --- src/server/game/Scripting/ScriptMgr.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 5d3297b009d..476b87f2440 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -368,7 +368,9 @@ class CreatureGameObjectScriptRegistrySwapHooks // Hook which is called before a creature is swapped static void UnloadStage1(Creature* creature) { - creature->m_Events.KillAllEvents(true); + // Remove deletable events only, + // otherwise it causes crashes with non-deletable spell events. + creature->m_Events.KillAllEvents(false); if (creature->IsCharmed()) creature->RemoveCharmedBy(nullptr); -- cgit v1.2.3 From 80fe552894a42b0be45fcc0fa0d55a7551e0149f Mon Sep 17 00:00:00 2001 From: Naios Date: Sun, 3 Jul 2016 00:06:49 +0200 Subject: Core/EventProcessor: Wait for non deletable events to get deletable. * Immediate deletion caused issues with the SpellEvent, so we delete it at one of the next update ticks now. * Only affects the unforced cancellation of events. * Ref #16675 (cherry picked from commit 1ad73212dca0cf8a829d15ffdbcc4cd611e64d4e) --- src/common/Utilities/EventProcessor.cpp | 51 +++++++++++++++++++--------- src/common/Utilities/EventProcessor.h | 36 ++++++++++++++------ src/server/game/Entities/Vehicle/Vehicle.cpp | 10 +++--- src/server/game/Spells/Auras/SpellAuras.cpp | 2 +- 4 files changed, 67 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/common/Utilities/EventProcessor.cpp b/src/common/Utilities/EventProcessor.cpp index be74d58b790..195deeb054b 100644 --- a/src/common/Utilities/EventProcessor.cpp +++ b/src/common/Utilities/EventProcessor.cpp @@ -17,11 +17,20 @@ */ #include "EventProcessor.h" +#include "Errors.h" -EventProcessor::EventProcessor() +void BasicEvent::ScheduleAbort() { - m_time = 0; - m_aborting = false; + ASSERT(IsRunning() + && "Tried to scheduled the abortion of an event twice!"); + m_abortState = AbortState::STATE_ABORT_SCHEDULED; +} + +void BasicEvent::SetAborted() +{ + ASSERT(!IsAborted() + && "Tried to abort an already aborted event!"); + m_abortState = AbortState::STATE_ABORTED; } EventProcessor::~EventProcessor() @@ -39,37 +48,47 @@ void EventProcessor::Update(uint32 p_time) while (((i = m_events.begin()) != m_events.end()) && i->first <= m_time) { // get and remove event from queue - BasicEvent* Event = i->second; + BasicEvent* event = i->second; m_events.erase(i); - if (!Event->to_Abort) + if (event->IsRunning()) { - if (Event->Execute(m_time, p_time)) + if (event->Execute(m_time, p_time)) { // completely destroy event if it is not re-added - delete Event; + delete event; } + continue; + } + + if (event->IsAbortScheduled()) + { + event->Abort(m_time); + // Mark the event as aborted + event->SetAborted(); } - else + + if (event->IsDeletable()) { - Event->Abort(m_time); - delete Event; + delete event; + continue; } + + // Reschedule non deletable events to be checked at + // the next update tick + AddEvent(event, CalculateTime(1), false); } } void EventProcessor::KillAllEvents(bool force) { - // prevent event insertions - m_aborting = true; - // first, abort all existing events for (EventList::iterator i = m_events.begin(); i != m_events.end();) { EventList::iterator i_old = i; ++i; - i_old->second->to_Abort = true; + i_old->second->SetAborted(); i_old->second->Abort(m_time); if (force || i_old->second->IsDeletable()) { @@ -87,7 +106,8 @@ void EventProcessor::KillAllEvents(bool force) void EventProcessor::AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime) { - if (set_addtime) Event->m_addTime = m_time; + if (set_addtime) + Event->m_addTime = m_time; Event->m_execTime = e_time; m_events.insert(std::pair(e_time, Event)); } @@ -96,4 +116,3 @@ uint64 EventProcessor::CalculateTime(uint64 t_offset) const { return(m_time + t_offset); } - diff --git a/src/common/Utilities/EventProcessor.h b/src/common/Utilities/EventProcessor.h index e10558e6a21..57f3065f323 100644 --- a/src/common/Utilities/EventProcessor.h +++ b/src/common/Utilities/EventProcessor.h @@ -20,20 +20,27 @@ #define __EVENTPROCESSOR_H #include "Define.h" - #include +class EventProcessor; + // Note. All times are in milliseconds here. class TC_COMMON_API BasicEvent { + friend class EventProcessor; + + enum class AbortState : uint8 + { + STATE_RUNNING, + STATE_ABORT_SCHEDULED, + STATE_ABORTED + }; + public: BasicEvent() - { - to_Abort = false; - m_addTime = 0; - m_execTime = 0; - } + : m_abortState(AbortState::STATE_RUNNING), m_addTime(0), m_execTime(0) { } + virtual ~BasicEvent() { } // override destructor to perform some actions on event removal // this method executes when the event is triggered @@ -45,8 +52,16 @@ class TC_COMMON_API BasicEvent virtual void Abort(uint64 /*e_time*/) { } // this method executes when the event is aborted - bool to_Abort; // set by externals when the event is aborted, aborted events don't execute - // and get Abort call when deleted + // Aborts the event at the next update tick + void ScheduleAbort(); + + private: + void SetAborted(); + bool IsRunning() const { return (m_abortState == AbortState::STATE_RUNNING); } + bool IsAbortScheduled() const { return (m_abortState == AbortState::STATE_ABORT_SCHEDULED); } + bool IsAborted() const { return (m_abortState == AbortState::STATE_ABORTED); } + + AbortState m_abortState; // set by externals when the event is aborted, aborted events don't execute // these can be used for time offset control uint64 m_addTime; // time when the event was added to queue, filled by event handler @@ -58,16 +73,17 @@ typedef std::multimap EventList; class TC_COMMON_API EventProcessor { public: - EventProcessor(); + EventProcessor() : m_time(0) { } ~EventProcessor(); void Update(uint32 p_time); void KillAllEvents(bool force); void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true); uint64 CalculateTime(uint64 t_offset) const; + protected: uint64 m_time; EventList m_events; - bool m_aborting; }; + #endif diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index cd7e038508c..9705eeaed72 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -232,7 +232,7 @@ void Vehicle::RemoveAllPassengers() while (!_pendingJoinEvents.empty()) { VehicleJoinEvent* e = _pendingJoinEvents.front(); - e->to_Abort = true; + e->ScheduleAbort(); e->Target = eventVehicle; _pendingJoinEvents.pop_front(); } @@ -421,7 +421,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) if (seat == Seats.end()) // no available seat { - e->to_Abort = true; + e->ScheduleAbort(); return false; } @@ -433,7 +433,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) seat = Seats.find(seatId); if (seat == Seats.end()) { - e->to_Abort = true; + e->ScheduleAbort(); return false; } @@ -691,7 +691,7 @@ void Vehicle::RemovePendingEventsForSeat(int8 seatId) { if ((*itr)->Seat->first == seatId) { - (*itr)->to_Abort = true; + (*itr)->ScheduleAbort(); _pendingJoinEvents.erase(itr++); } else @@ -716,7 +716,7 @@ void Vehicle::RemovePendingEventsForPassenger(Unit* passenger) { if ((*itr)->Passenger == passenger) { - (*itr)->to_Abort = true; + (*itr)->ScheduleAbort(); _pendingJoinEvents.erase(itr++); } else diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index b337e4aca58..bcef1da2b69 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -524,7 +524,7 @@ void Aura::_Remove(AuraRemoveMode removeMode) if (m_dropEvent) { - m_dropEvent->to_Abort = true; + m_dropEvent->ScheduleAbort(); m_dropEvent = nullptr; } } -- cgit v1.2.3 From a2ac2b3cc7a0711cf4a5d43e8c9f96b841677103 Mon Sep 17 00:00:00 2001 From: Naios Date: Sun, 3 Jul 2016 20:52:50 +0200 Subject: Core/EventProcessor: Check whether an event was aborted before aborting it. * Fixes an assertion introduced in commit 1ad73212dca0cf. * Use itr = std::unordered_map<...>::erase for updating the iterator. (cherry picked from commit d9755c637c39e600f145f5ecb7ff0ccf3724b1ad) --- src/common/Utilities/EventProcessor.cpp | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/common/Utilities/EventProcessor.cpp b/src/common/Utilities/EventProcessor.cpp index 195deeb054b..2341d0a0872 100644 --- a/src/common/Utilities/EventProcessor.cpp +++ b/src/common/Utilities/EventProcessor.cpp @@ -82,24 +82,31 @@ void EventProcessor::Update(uint32 p_time) void EventProcessor::KillAllEvents(bool force) { - // first, abort all existing events - for (EventList::iterator i = m_events.begin(); i != m_events.end();) + for (auto itr = m_events.begin(); itr != m_events.end();) { - EventList::iterator i_old = i; - ++i; - - i_old->second->SetAborted(); - i_old->second->Abort(m_time); - if (force || i_old->second->IsDeletable()) + // Abort events which weren't aborted already + if (!itr->second->IsAborted()) { - delete i_old->second; + itr->second->SetAborted(); + itr->second->Abort(m_time); + } - if (!force) // need per-element cleanup - m_events.erase (i_old); + // Skip non-deletable events when we are + // not forcing the event cancellation. + if (!force && !itr->second->IsDeletable()) + { + ++itr; + continue; } + + delete itr->second; + + if (force) + ++itr; // Clear the whole container when forcing + else + itr = m_events.erase(itr); } - // fast clear event list (in force case) if (force) m_events.clear(); } -- cgit v1.2.3 From 7ab514532164cfac50abc4f45cbefc6a39b21b6a Mon Sep 17 00:00:00 2001 From: DDuarte Date: Tue, 5 Jul 2016 11:21:50 +0100 Subject: Scripts/Commands: Remove unused argument of .cometome command (cherry picked from commit 1100fe60572b186eee98b6b7cbdccf5a2d67b7e1) # Conflicts: # sql/updates/world/3.3.5/2016_07_05_01_world.sql --- sql/updates/world/3.3.5/2016_07_05_02_world.sql | 1 + src/server/scripts/Commands/cs_misc.cpp | 10 +--------- 2 files changed, 2 insertions(+), 9 deletions(-) create mode 100644 sql/updates/world/3.3.5/2016_07_05_02_world.sql (limited to 'src') diff --git a/sql/updates/world/3.3.5/2016_07_05_02_world.sql b/sql/updates/world/3.3.5/2016_07_05_02_world.sql new file mode 100644 index 00000000000..2921c19b0c1 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_07_05_02_world.sql @@ -0,0 +1 @@ +UPDATE `command` SET `help` = 'Syntax: .cometome\nMake selected creature come to your current location (new position not saved to DB).' WHERE `command`.`name` = 'cometome'; diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 7ad80352995..31af42d0010 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -2183,17 +2183,9 @@ public: } return true; } - /* - ComeToMe command REQUIRED for 3rd party scripting library to have access to PointMovementGenerator - Without this function 3rd party scripting library will get linking errors (unresolved external) - when attempting to use the PointMovementGenerator - */ + static bool HandleComeToMeCommand(ChatHandler* handler, char const* args) { - char const* newFlagStr = strtok((char*)args, " "); - if (!newFlagStr) - return false; - Creature* caster = handler->getSelectedCreature(); if (!caster) { -- cgit v1.2.3 From b9ec8ae3282e55ede70e289106db07d5dc70532c Mon Sep 17 00:00:00 2001 From: DDuarte Date: Tue, 5 Jul 2016 11:55:29 +0100 Subject: Scripts/Commands: Fix build warning (cherry picked from commit 42028a18421f672a3292733cac73840c4e766089) --- src/server/scripts/Commands/cs_misc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 31af42d0010..5d1e26c0ee5 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -2184,7 +2184,7 @@ public: return true; } - static bool HandleComeToMeCommand(ChatHandler* handler, char const* args) + static bool HandleComeToMeCommand(ChatHandler* handler, char const* /*args*/) { Creature* caster = handler->getSelectedCreature(); if (!caster) -- cgit v1.2.3 From b63346a25e2b7942bc618e91aa2b3d1690d6687a Mon Sep 17 00:00:00 2001 From: Shauren Date: Tue, 5 Jul 2016 16:59:37 +0200 Subject: Core/Spells: Fixed spell dest range check failing on 0 distance max range requirement even if standing directly on top of destination (cherry picked from commit ba63361d7c20bf93a7089c517cd707c005949f62) --- src/server/game/Spells/Spell.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 1068e406e78..175b921b164 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5984,12 +5984,15 @@ SpellCastResult Spell::CheckRange(bool strict) maxRange += rangeMod; + minRange *= minRange; + maxRange *= maxRange; + if (target && target != m_caster) { - if (!m_caster->IsInDist(target, maxRange)) + if (m_caster->GetExactDistSq(target) > maxRange) return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; - if (minRange > 0.0f && m_caster->IsInDist(target, minRange)) + if (minRange > 0.0f && m_caster->GetExactDistSq(target) < minRange) return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; if (m_caster->GetTypeId() == TYPEID_PLAYER && @@ -5999,9 +6002,9 @@ SpellCastResult Spell::CheckRange(bool strict) if (m_targets.HasDst() && !m_targets.HasTraj()) { - if (!m_caster->IsInDist(m_targets.GetDstPos(), maxRange)) + if (m_caster->GetExactDistSq(m_targets.GetDstPos()) > maxRange) return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; - if (minRange > 0.0f && m_caster->IsInDist(m_targets.GetDstPos(), minRange)) + if (minRange > 0.0f && m_caster->GetExactDistSq(m_targets.GetDstPos()) < minRange) return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; } -- cgit v1.2.3 From 48f0f47dd2c83eeb4bceff53fdb7c94bc0ce5190 Mon Sep 17 00:00:00 2001 From: Ulduar Date: Tue, 5 Jul 2016 23:27:59 +0600 Subject: [6.x] Scripts/Spells: K'ure & Decimatus, SAI + spell scripts * Core/DB Add SAI for Decimatus. Add Decimatus SAI and Dark Siphon spell condition target. * Decimatus spell script for 169869. Decimatus Transformation Sickness. * Replace caster on target. Compiling fine! And then you never know what comes into head Blizzard. * Add three spell scripts. Add support spell scripts for 189549, 189512 and 189491. --- sql/updates/world/6.x/2016_06_11_00_world.sql | 33 ++++++ src/server/scripts/Spells/spell_generic.cpp | 162 ++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 sql/updates/world/6.x/2016_06_11_00_world.sql (limited to 'src') diff --git a/sql/updates/world/6.x/2016_06_11_00_world.sql b/sql/updates/world/6.x/2016_06_11_00_world.sql new file mode 100644 index 00000000000..e81a39afd96 --- /dev/null +++ b/sql/updates/world/6.x/2016_06_11_00_world.sql @@ -0,0 +1,33 @@ +-- Dark Siphon +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceGroup`=0 AND `SourceEntry`=165059; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,165059,0,0,31,0,3,81556 ,0,0,"","Dark Siphon – Cast only on K'ure."); + +-- Decimatus SAI +SET @ENTRY := 81989; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,11,0,100,0,0,0,0,0,11,169869,34,0,0,0,0,1,0,0,0,0,0,0,0,"Decimatus - On Respawn - Cast Transformation Sickness on Self (Need Core Handler for Spell)"), +(@ENTRY,0,1,0,0,0,100,0,9000,11000,9000,11000,11,174011,0,0,0,0,0,5,0,0,0,0,0,0,0,"Decimatus - In Combat - Cast Neutralize - Need Core Handler."), +(@ENTRY,0,2,0,0,0,100,0,27000,27000,27000,27000,11,174016,1,0,0,0,0,1,0,0,0,0,0,0,0,"Decimatus - In Combat - Cast Decimate."); + +-- spell_gen_decimatus_transformation_sickness + DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_gen_decimatus_transformation_sickness'; + INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES + (169869,'spell_gen_decimatus_transformation_sickness'); + +-- spell_gen_azgalor_rain_of_fire_hellfire_citadel + DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_gen_azgalor_rain_of_fire_hellfire_citadel'; + INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES + (189549,'spell_gen_azgalor_rain_of_fire_hellfire_citadel'); + +-- spell_gen_mark_of_kazrogal_hellfire + DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_gen_mark_of_kazrogal_hellfire'; + INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES + (189512,'spell_gen_mark_of_kazrogal_hellfire'); + +-- spell_gen_anetheron_summon_towering_infernal + DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_gen_anetheron_summon_towering_infernal'; + INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES + (189491,'spell_gen_anetheron_summon_towering_infernal'); diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index cf9ff3ef28b..f0ebfb23427 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -4228,6 +4228,164 @@ class spell_gen_clear_debuffs : public SpellScriptLoader } }; +// 169869 - Transformation Sickness +class spell_gen_decimatus_transformation_sickness : public SpellScriptLoader +{ +public: + spell_gen_decimatus_transformation_sickness() : SpellScriptLoader("spell_gen_decimatus_transformation_sickness") { } + + class spell_gen_decimatus_transformation_sickness_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_decimatus_transformation_sickness_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + target->SetHealth(target->CountPctFromMaxHealth(10)); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_decimatus_transformation_sickness_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gen_decimatus_transformation_sickness_SpellScript(); + } +}; + +// 189491 - Summon Towering Infernal. +class spell_gen_anetheron_summon_towering_infernal : public SpellScriptLoader +{ + public: + spell_gen_anetheron_summon_towering_infernal() : SpellScriptLoader("spell_gen_anetheron_summon_towering_infernal") { } + + class spell_gen_anetheron_summon_towering_infernal_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_anetheron_summon_towering_infernal_SpellScript); + + void HandleDummy(SpellEffIndex /* effIndex */) + { + GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_anetheron_summon_towering_infernal_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gen_anetheron_summon_towering_infernal_SpellScript(); + } +}; + +enum KazrogalHellfireMark +{ + SPELL_MARK_OF_KAZROGAL_HELLFIRE = 189512, + SPELL_MARK_OF_KAZROGAL_DAMAGE_HELLFIRE = 189515 +}; + +class MarkTargetHellfireFilter +{ + public: + bool operator()(WorldObject* target) const + { + if (Unit* unit = target->ToUnit()) + return unit->getPowerType() != POWER_MANA; + return false; + } +}; + +class spell_gen_mark_of_kazrogal_hellfire : public SpellScriptLoader +{ + public: + spell_gen_mark_of_kazrogal_hellfire() : SpellScriptLoader("spell_gen_mark_of_kazrogal_hellfire") { } + + class spell_gen_mark_of_kazrogal_hellfire_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_mark_of_kazrogal_hellfire_SpellScript); + + void FilterTargets(std::list& targets) + { + targets.remove_if(MarkTargetHellfireFilter()); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gen_mark_of_kazrogal_hellfire_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + class spell_gen_mark_of_kazrogal_hellfire_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_mark_of_kazrogal_hellfire_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_MARK_OF_KAZROGAL_DAMAGE_HELLFIRE)) + return false; + return true; + } + + void OnPeriodic(AuraEffect const* aurEff) + { + Unit* target = GetTarget(); + + if (target->GetPower(POWER_MANA) == 0) + { + target->CastSpell(target, SPELL_MARK_OF_KAZROGAL_DAMAGE_HELLFIRE, true, NULL, aurEff); + // Remove aura + SetDuration(0); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_mark_of_kazrogal_hellfire_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_POWER_BURN); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gen_mark_of_kazrogal_hellfire_SpellScript(); + } + + AuraScript* GetAuraScript() const override + { + return new spell_gen_mark_of_kazrogal_hellfire_AuraScript(); + } +}; + +class spell_gen_azgalor_rain_of_fire_hellfire_citadel : public SpellScriptLoader +{ + public: + spell_gen_azgalor_rain_of_fire_hellfire_citadel() : SpellScriptLoader("spell_gen_azgalor_rain_of_fire_hellfire_citadel") { } + + class spell_gen_azgalor_rain_of_fire_hellfire_citadel_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_azgalor_rain_of_fire_hellfire_citadel_SpellScript); + + void HandleDummy(SpellEffIndex /* effIndex */) + { + GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_azgalor_rain_of_fire_hellfire_citadel_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gen_azgalor_rain_of_fire_hellfire_citadel_SpellScript(); + } +}; + void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); @@ -4318,4 +4476,8 @@ void AddSC_generic_spell_scripts() new spell_gen_mixology_bonus(); new spell_gen_landmine_knockback_achievement(); new spell_gen_clear_debuffs(); + new spell_gen_decimatus_transformation_sickness(); + new spell_gen_anetheron_summon_towering_infernal(); + new spell_gen_mark_of_kazrogal_hellfire(); + new spell_gen_azgalor_rain_of_fire_hellfire_citadel(); } -- cgit v1.2.3