diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 1fd3f3680..d5b294f21 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1492,7 +1492,7 @@ struct SpellShapeshiftEntry uint32 modelID_H; // 24 horde modelid (but only for one form) //uint32 unk3; // 25 unused always 0 //uint32 unk4; // 26 unused always 0 - //uint32 spell[8]; // 27-34 unused, spells which appear in the bar after shapeshifting + uint32 spellId[8]; // 27-34 spells which appear in the bar after shapeshifting }; struct SpellDurationEntry diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index d6a8d48f5..3fd24d802 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -91,7 +91,7 @@ const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; const char SpellRadiusfmt[]="nfxf"; const char SpellRangefmt[]="nffffxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char SpellRuneCostfmt[]="niiii"; -const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixiiixxxxxxxxxx"; +const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixiiixxiiiiiiii"; const char StableSlotPricesfmt[] = "ni"; const char SummonPropertiesfmt[] = "niiiii"; const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx"; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a010e9bc8..2d09f4f3b 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3188,7 +3188,7 @@ void Player::learnSpell(uint32 spell_id, bool dependent) GetSession()->SendPacket(&data); } -void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) +void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank, bool sendUpdate) { PlayerSpellMap::iterator itr = m_spells.find(spell_id); if (itr == m_spells.end()) @@ -3367,7 +3367,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) } // remove from spell book if not replaced by lesser rank - if(!prev_activate) + if (!prev_activate && sendUpdate) { WorldPacket data(SMSG_REMOVED_SPELL, 4); data << uint32(spell_id); @@ -21287,4 +21287,4 @@ void Player::SetHomebindToCurrentPos() // update sql homebind CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", m_homebindMapId, m_homebindZoneId, m_homebindX, m_homebindY, m_homebindZ, GetGUIDLow()); -} \ No newline at end of file +} diff --git a/src/game/Player.h b/src/game/Player.h index 64854f278..75e8e3163 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1555,7 +1555,7 @@ class MANGOS_DLL_SPEC Player : public Unit void SendInitialSpells(); bool addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled); void learnSpell(uint32 spell_id, bool dependent); - void removeSpell(uint32 spell_id, bool disabled = false, bool learn_low_rank = true); + void removeSpell(uint32 spell_id, bool disabled = false, bool learn_low_rank = true, bool sendUpdate = true); void resetSpells(); void learnDefaultSpells(); void learnQuestRewardedSpells(); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 500f529d5..350eb4030 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -5260,11 +5260,11 @@ SpellCastResult Spell::CheckItems() { uint32 itemid = m_CastItem->GetEntry(); if( !p_caster->HasItemCount(itemid, 1) ) - return SPELL_FAILED_ITEM_NOT_READY; + return SPELL_FAILED_ITEM_NOT_FOUND; ItemPrototype const *proto = m_CastItem->GetProto(); if(!proto) - return SPELL_FAILED_ITEM_NOT_READY; + return SPELL_FAILED_ITEM_NOT_FOUND; for (int i = 0; i < 5; ++i) if (proto->Spells[i].SpellCharges) @@ -5380,7 +5380,7 @@ SpellCastResult Spell::CheckItems() { ItemPrototype const *proto = m_CastItem->GetProto(); if(!proto) - return SPELL_FAILED_ITEM_NOT_READY; + return SPELL_FAILED_REAGENTS; for(int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s) { // CastItem will be used up and does not count as reagent @@ -5393,7 +5393,7 @@ SpellCastResult Spell::CheckItems() } } if( !p_caster->HasItemCount(itemid, itemcount) ) - return SPELL_FAILED_ITEM_NOT_READY; //0x54 + return SPELL_FAILED_REAGENTS; } } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 993753eb3..8ee935d0d 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2925,7 +2925,13 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue); SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(form); - if(ssEntry && ssEntry->modelID_A) + if (!ssEntry) + { + sLog.outError("Unknown shapeshift form %u in spell %u", form, GetId()); + return; + } + + if (ssEntry->modelID_A) { // i will asume that creatures will always take the defined model from the dbc // since no field in creature_templates describes wether an alliance or @@ -3112,6 +3118,14 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) m_target->m_ShapeShiftFormSpellId = GetId(); m_target->m_form = form; + + // a form can give the player a new castbar with some spells.. this is a clientside process.. + // serverside just needs to register the new spells so that player isn't kicked as cheater + if (m_target->GetTypeId() == TYPEID_PLAYER) + for (uint32 i = 0; i < 8; ++i) + if (ssEntry->spellId[i]) + ((Player*)m_target)->addSpell(ssEntry->spellId[i], true, false, false, false); + } else { @@ -3140,6 +3154,13 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) default: break; } + + // look at the comment in apply-part + if (m_target->GetTypeId() == TYPEID_PLAYER) + for (uint32 i = 0; i < 8; ++i) + if (ssEntry->spellId[i]) + ((Player*)m_target)->removeSpell(ssEntry->spellId[i], false, false, false); + } // adding/removing linked auras diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 00de098e1..89a4e1264 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 "9012" + #define REVISION_NR "9013" #endif // __REVISION_NR_H__