From 12987be49b588558bbb2f8c5b2b813ec3224f8b3 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 12 Feb 2010 07:38:40 +0300 Subject: [PATCH] [9362] Make specs work at least for action bars * Propertly add/remove required for specs work spells at 63624/63651. * Copy current spec action bars to new spec at specs count increase, and delete action bars data at spec count decrease. * Avoid undexpected action button data test for not active spec at loading/copy, but test action buttons data at spec activation. * Reset active spec to default if active spec removed. * Remove talent reset at spec switch that useless at this moment. Also note that for future case this also can be not correct and batter unlearn/learn only talents that different in specs. After this changes specs must fully work in action bar part without unexpected another effects. --- src/game/MiscHandler.cpp | 2 +- src/game/Player.cpp | 69 +++++++++++++++++++++++++++++++-------- src/game/Player.h | 2 +- src/game/SpellAuras.cpp | 10 ++++++ src/game/SpellEffects.cpp | 9 ++--- src/shared/revision_nr.h | 2 +- 6 files changed, 74 insertions(+), 20 deletions(-) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 1e31bdfbd24..3a448df99e2 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -962,7 +962,7 @@ void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) if (!packetData) { sLog.outDetail( "MISC: Remove action from button %u", button ); - GetPlayer()->removeActionButton(button); + GetPlayer()->removeActionButton(GetPlayer()->GetActiveSpec(),button); } else { diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 02800e27d5e..635ee064879 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -5636,7 +5636,7 @@ void Player::SendInitialActionButtons() const WorldPacket data(SMSG_ACTION_BUTTONS, 1+(MAX_ACTION_BUTTONS*4)); data << uint8(1); // can be 0, 1, 2 (talent spec) ActionButtonList const& currentActionButtonList = m_actionButtons[m_activeSpec]; - for(int button = 0; button < MAX_ACTION_BUTTONS; ++button) + for(uint8 button = 0; button < MAX_ACTION_BUTTONS; ++button) { ActionButtonList::const_iterator itr = currentActionButtonList.find(button); if(itr != currentActionButtonList.end() && itr->second.uState != ACTIONBUTTON_DELETED) @@ -5706,8 +5706,8 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type, Pl ActionButton* Player::addActionButton(uint8 spec, uint8 button, uint32 action, uint8 type) { - - if (!IsActionButtonDataValid(button,action,type,this)) + // check action only for active spec (so not check at copy/load passive spec) + if (spec == GetActiveSpec() && !IsActionButtonDataValid(button,action,type,this)) return NULL; // it create new button (NEW state) if need or return existed @@ -5716,23 +5716,23 @@ ActionButton* Player::addActionButton(uint8 spec, uint8 button, uint32 action, u // set data and update to CHANGED if not NEW ab.SetActionAndType(action,ActionButtonType(type)); - sLog.outDetail( "Player '%u' Added Action '%u' (type %u) to Button '%u'", GetGUIDLow(), action, uint32(type), button ); + sLog.outDetail("Player '%u' Added Action '%u' (type %u) to Button '%u' for spec %u", GetGUIDLow(), action, uint32(type), button, spec); return &ab; } -void Player::removeActionButton(uint8 button) +void Player::removeActionButton(uint8 spec, uint8 button) { - ActionButtonList& currentActionButtonList = m_actionButtons[m_activeSpec]; + ActionButtonList& currentActionButtonList = m_actionButtons[spec]; ActionButtonList::iterator buttonItr = currentActionButtonList.find(button); - if (buttonItr==currentActionButtonList.end()) + if (buttonItr == currentActionButtonList.end() || buttonItr->second.uState == ACTIONBUTTON_DELETED) return; - if(buttonItr->second.uState==ACTIONBUTTON_NEW) + if (buttonItr->second.uState == ACTIONBUTTON_NEW) currentActionButtonList.erase(buttonItr); // new and not saved else buttonItr->second.uState = ACTIONBUTTON_DELETED; // saved, will deleted at next save - sLog.outDetail( "Action Button '%u' Removed from Player '%u'", button, GetGUIDLow() ); + sLog.outDetail("Action Button '%u' Removed from Player '%u' for spec %u", button, GetGUIDLow(), spec); } ActionButton const* Player::GetActionButton(uint8 button) @@ -21331,10 +21331,21 @@ void Player::ActivateSpec(uint8 specNum) if(GetActiveSpec() == specNum) return; - resetTalents(true); + if(specNum >= GetSpecsCount()) + return; + + // unlearn GetActiveSpec() talents (not learned in specNum); + // learn specNum talents SetActiveSpec(specNum); + // recheck action buttons (not checked at loading/spec copy) + ActionButtonList const& currentActionButtonList = m_actionButtons[m_activeSpec]; + for(ActionButtonList::const_iterator itr = currentActionButtonList.begin(); itr != currentActionButtonList.end(); ++itr) + if (itr->second.uState != ACTIONBUTTON_DELETED) + if (!IsActionButtonDataValid(itr->first,itr->second.GetAction(),itr->second.GetType(), this)) + removeActionButton(m_activeSpec,itr->first); + SendInitialActionButtons(); InitTalentForLevel(); @@ -21343,12 +21354,44 @@ void Player::ActivateSpec(uint8 specNum) void Player::UpdateSpecCount(uint8 count) { uint8 curCount = GetSpecsCount(); - if(curCount == count) + if (curCount == count) return; - if(count > curCount) + // maybe current spec data must be copied to 0 spec? + if (m_activeSpec >= count) + ActivateSpec(0); + + // copy spec data from new specs + if (count > curCount) + { + // copy action buttons from active spec (more easy in this case iterate first by button) + ActionButtonList const& currentActionButtonList = m_actionButtons[m_activeSpec]; + + for(ActionButtonList::const_iterator itr = currentActionButtonList.begin(); itr != currentActionButtonList.end(); ++itr) + { + if (itr->second.uState != ACTIONBUTTON_DELETED) + { + for(uint8 spec = curCount; spec < count; ++spec) + addActionButton(spec,itr->first,itr->second.GetAction(),itr->second.GetType()); + } + } + + // other data copy + // for(uint8 spec = curCount; spec < count; ++spec) + // ... + } + // delete spec data for removed specs + else if (count < curCount) { - //TODO: copy current action button set + // delete action buttons for removed spec + for(uint8 spec = count; spec < curCount; ++spec) + { + // delete action buttons for removed spec + for(uint8 button = 0; button < MAX_ACTION_BUTTONS; ++button) + removeActionButton(spec,button); + + // other data remove + } } SetSpecsCount(count); diff --git a/src/game/Player.h b/src/game/Player.h index eba64d79f5e..f15c72e0958 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1611,7 +1611,7 @@ class MANGOS_DLL_SPEC Player : public Unit static bool IsActionButtonDataValid(uint8 button, uint32 action, uint8 type, Player* player); ActionButton* addActionButton(uint8 spec, uint8 button, uint32 action, uint8 type); - void removeActionButton(uint8 button); + void removeActionButton(uint8 spec, uint8 button); void SendInitialActionButtons() const; ActionButton const* GetActionButton(uint8 button); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index e1141d4d7f7..24a1f75c4d9 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2314,6 +2314,16 @@ void Aura::HandleAuraDummy(bool apply, bool Real) // Reindeer Transformation m_target->CastSpell(m_target, 25860, true, NULL, this); return; + case 63624: // Learn a Second Talent Specialization + // Teach Learn Talent Specialization Switches, required for client triggered casts, allow after 30 sec delay + if (m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->learnSpell(63680, false); + return; + case 63651: // Revert to One Talent Specialization + // Teach Learn Talent Specialization Switches, remove + if (m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->removeSpell(63680); + return; } break; case SPELLFAMILY_WARRIOR: diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index b45c4b57e3b..3bde3ceef65 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -7010,7 +7010,7 @@ void Spell::EffectPlayMusic(uint32 i) void Spell::EffectSpecCount(uint32 /*eff_idx*/) { - if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; ((Player*)unitTarget)->UpdateSpecCount(damage); @@ -7018,9 +7018,10 @@ void Spell::EffectSpecCount(uint32 /*eff_idx*/) void Spell::EffectActivateSpec(uint32 /*eff_idx*/) { - if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - // damage = spec + 1 - ((Player*)unitTarget)->ActivateSpec(damage-1); + uint32 spec = damage-1; + + ((Player*)unitTarget)->ActivateSpec(spec); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 4743ecc0aba..7099b75ca26 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9361" + #define REVISION_NR "9362" #endif // __REVISION_NR_H__