Index: src/game/Spell.cpp =================================================================== --- src/game/Spell.cpp (revision 5445) +++ src/game/Spell.cpp (working copy) @@ -2668,6 +2668,17 @@ return SPELL_FAILED_NOT_READY; } + // Cannot be used in this stance/form + if (m_caster->GetTypeId()==TYPEID_PLAYER) + { + uint8 shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, ((Player*)m_caster)->m_form); + if (shapeError) + return shapeError; + } + + if (m_spellInfo->Attributes & 0x20000 && !(m_caster->HasStealthAura())) + return SPELL_FAILED_ONLY_STEALTHED; + // cancel autorepeat spells if cast start when moving // (not wand currently autorepeat cast delayed to moving stop anyway in spell update code) if( m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->isMoving() ) Index: src/game/SpellAuras.cpp =================================================================== --- src/game/SpellAuras.cpp (revision 5445) +++ src/game/SpellAuras.cpp (working copy) @@ -1681,6 +1681,10 @@ unit_target->m_form = 0; } + // adding/removing linked auras + // add/remove the shapeshift aura's boosts + HandleShapeshiftBoosts(apply); + if(player) player->InitDataForForm(); } Index: src/game/SpellMgr.cpp =================================================================== --- src/game/SpellMgr.cpp (revision 5445) +++ src/game/SpellMgr.cpp (working copy) @@ -23,6 +23,7 @@ #include "Database/DBCStores.h" #include "World.h" #include "Chat.h" +#include "Spell.h" SpellMgr::SpellMgr() { @@ -527,6 +528,44 @@ return false; } +uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form) +{ + uint32 stanceMask = (form ? 1 << (form - 1) : 0); + + if (stanceMask & spellInfo->StancesNot) + return SPELL_FAILED_NOT_SHAPESHIFT; + + if (stanceMask & spellInfo->Stances) + return 0; + + bool check1 = false; + if (form > 0) + { + SpellShapeshiftEntry const *shapeInfo = sSpellShapeshiftStore.LookupEntry(form); + if (!shapeInfo) + { + sLog.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form); + return 0; + } + check1 = !(shapeInfo->flags1 & 1); + } + + if(check1) + { + if (spellInfo->Attributes & 0x10000) + return SPELL_FAILED_NOT_SHAPESHIFT; + else if (spellInfo->Stances != 0) + return SPELL_FAILED_ONLY_SHAPESHIFT; + } + else + { + if(!(spellInfo->AttributesEx2 & 0x80000) && spellInfo->Stances != 0) + return SPELL_FAILED_ONLY_SHAPESHIFT; + } + + return 0; +} + void SpellMgr::LoadSpellTeleports() { mSpellTeleports.clear(); // need for reload case @@ -1588,3 +1627,4 @@ + Index: src/game/SpellMgr.h =================================================================== --- src/game/SpellMgr.h (revision 5445) +++ src/game/SpellMgr.h (working copy) @@ -133,6 +133,7 @@ bool CanUsedWhileStealthed(uint32 spellId); bool IsMechanicInvulnerabilityImmunityToSpell(SpellEntry const* spellInfo); +uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form); inline bool IsChanneledSpell(SpellEntry const* spellInfo) Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (revision 5445) +++ src/game/Unit.cpp (working copy) @@ -3645,11 +3645,6 @@ } } - // adding linked auras - // add the shapeshift aura's boosts - if(Aur->GetModifier()->m_auraname == SPELL_AURA_MOD_SHAPESHIFT) - Aur->HandleShapeshiftBoosts(true); - // add aura, register in lists and arrays Aur->_AddAura(); m_Auras.insert(AuraMap::value_type(spellEffectPair(Aur->GetId(), Aur->GetEffIndex()), Aur)); @@ -4011,10 +4006,6 @@ m_Auras.erase(i); ++m_removedAuras; // internal count used by unit update - // remove the shapeshift aura's boosts - if(Aur->GetModifier()->m_auraname == SPELL_AURA_MOD_SHAPESHIFT) - Aur->HandleShapeshiftBoosts(false); - Aur->_RemoveAura(); delete Aur; Index: src/shared/Database/DBCfmt.cpp =================================================================== --- src/shared/Database/DBCfmt.cpp (revision 5445) +++ src/shared/Database/DBCfmt.cpp (working copy) @@ -53,12 +53,13 @@ const char SkillLineAbilityfmt[]="xiniixxiixiixxi"; const char SpellCastTimefmt[]="nixx"; const char SpellDurationfmt[]="niii"; -const char SpellEntryfmt[]="niixiiiiiiixixiiiiixxiiiiiiiiiiiiiiiiiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiifffixiiissssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiixxfffxxxiii"; +const char SpellEntryfmt[]="niixiiiiiiixiiiiiiixxiiiiiiiiiiiiiiiiiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiifffixiiissssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiixxfffxxxiii"; const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; const char SpellItemEnchantmentfmt[]="niiiiiixxxiiissssssssssssssssxiiii"; const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; const char SpellRadiusfmt[]="nfxf"; const char SpellRangefmt[]="nffxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxx"; const char StableSlotPricesfmt[] = "ni"; const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxx"; const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiix"; Index: src/shared/Database/DBCStores.cpp =================================================================== --- src/shared/Database/DBCStores.cpp (revision 5445) +++ src/shared/Database/DBCStores.cpp (working copy) @@ -88,6 +88,7 @@ DBCStorage sSpellFocusObjectStore(SpellFocusObjectfmt); DBCStorage sSpellRadiusStore(SpellRadiusfmt); DBCStorage sSpellRangeStore(SpellRangefmt); +DBCStorage sSpellShapeshiftStore(SpellShapeshiftfmt); DBCStorage sStableSlotPricesStore(StableSlotPricesfmt); DBCStorage sTalentStore(TalentEntryfmt); TalentSpellCosts sTalentSpellCosts; @@ -171,7 +172,7 @@ { std::string tmpPath=""; - const uint32 DBCFilesCount = 50; + const uint32 DBCFilesCount = 51; barGoLink bar( DBCFilesCount ); @@ -255,6 +256,7 @@ LoadDBC(bar,bad_dbc_files,sSpellItemEnchantmentConditionStore,dataPath+"dbc/SpellItemEnchantmentCondition.dbc"); LoadDBC(bar,bad_dbc_files,sSpellRadiusStore, dataPath+"dbc/SpellRadius.dbc"); LoadDBC(bar,bad_dbc_files,sSpellRangeStore, dataPath+"dbc/SpellRange.dbc"); + LoadDBC(bar,bad_dbc_files,sSpellShapeshiftStore, dataPath+"dbc/SpellShapeshiftForm.dbc"); LoadDBC(bar,bad_dbc_files,sStableSlotPricesStore, dataPath+"dbc/StableSlotPrices.dbc"); LoadDBC(bar,bad_dbc_files,sTalentStore, dataPath+"dbc/Talent.dbc"); Index: src/shared/Database/DBCStores.h =================================================================== --- src/shared/Database/DBCStores.h (revision 5445) +++ src/shared/Database/DBCStores.h (working copy) @@ -144,6 +144,7 @@ extern SpellCategoryStore sSpellCategoryStore; extern DBCStorage sSpellRadiusStore; extern DBCStorage sSpellRangeStore; +extern DBCStorage sSpellShapeshiftStore; extern DBCStorage sSpellStore; extern DBCStorage sStableSlotPricesStore; extern DBCStorage sTalentStore; Index: src/shared/Database/DBCStructure.h =================================================================== --- src/shared/Database/DBCStructure.h (revision 5445) +++ src/shared/Database/DBCStructure.h (working copy) @@ -431,7 +431,7 @@ uint32 AttributesExEx; // 10 // 11 not used uint32 Stances; // 12 - // 13 not used + uint32 StancesNot; // 13 uint32 Targets; // 14 uint32 TargetCreatureType; // 15 uint32 RequiresSpellFocus; // 16 @@ -554,6 +554,30 @@ float maxRange; }; +struct SpellShapeshiftEntry +{ + uint32 ID; // 0 + //uint32 buttonPosition; // 1 unused + //char* Name[16]; // 2-17 unused + //uint32 NameFlags; // 18 unused + uint32 flags1; // 19 + //uint32 unk0; // 20 unused + //uint32 unk1; // 21 unused + //uint32 attackSpeed; // 22 unused + //uint32 modelID; // 23 unused + //uint32 unk2; // 24 unused + //uint32 unk3; // 25 unused + //uint32 unk4; // 26 unused + //uint32 unk5; // 27 unused + //uint32 unk6; // 28 unused + //uint32 unk7; // 29 unused + //uint32 unk8; // 30 unused + //uint32 unk9; // 31 unused + //uint32 unk10; // 32 unused + //uint32 unk11; // 33 unused + //uint32 unk12; // 34 unused +}; + struct SpellDurationEntry { uint32 ID;