Skip to content

Commit

Permalink
[9362] Make specs work at least for action bars
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
VladimirMangos committed Feb 12, 2010
1 parent 01a641e commit 12987be
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/game/MiscHandler.cpp
Expand Up @@ -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
{
Expand Down
69 changes: 56 additions & 13 deletions src/game/Player.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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();
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/game/Player.h
Expand Up @@ -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);

Expand Down
10 changes: 10 additions & 0 deletions src/game/SpellAuras.cpp
Expand Up @@ -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:
Expand Down
9 changes: 5 additions & 4 deletions src/game/SpellEffects.cpp
Expand Up @@ -7010,17 +7010,18 @@ 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);
}

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);
}
2 changes: 1 addition & 1 deletion 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__

6 comments on commit 12987be

@goldberg002
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AWESOME!!!

@KiriX
Copy link

@KiriX KiriX commented on 12987be Feb 12, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ну вот! Наконец-то какой-то заметный (и очень даже) шаг к реализации двойной специализации =)

@morphau
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks :)

@Wowka321
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! Thx =)

@tendonsie
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work !

@Ankso
Copy link

@Ankso Ankso commented on 12987be Feb 13, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OMG thanks

Please sign in to comment.