*Update to Mangos 7083.

--HG--
branch : trunk
This commit is contained in:
megamage
2009-01-14 00:35:13 -06:00
parent 78e92e9023
commit 83e7f653fe
16 changed files with 698 additions and 147 deletions
+4
View File
@@ -372,6 +372,10 @@ struct TrainerSpell
uint32 reqskill;
uint32 reqskillvalue;
uint32 reqlevel;
uint32 learned_spell;
// helpers
bool IsCastable() const { return learned_spell != spell; }
};
typedef std::vector<TrainerSpell*> TrainerSpellList;
+22 -16
View File
@@ -166,17 +166,17 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle )
{
TrainerSpell const* tSpell = *itr;
if(!_player->IsSpellFitByClassAndRace(tSpell->spell))
if(!_player->IsSpellFitByClassAndRace(tSpell->learned_spell))
continue;
++count;
bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell);
bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->learned_spell);
SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell);
SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->learned_spell);
uint32 req_spell = spellmgr.GetSpellRequired(tSpell->spell);
data << uint32(tSpell->spell);
data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case)
data << uint8(_player->GetTrainerSpellState(tSpell));
data << uint32(floor(tSpell->spellcost * fDiscountMod));
@@ -241,21 +241,27 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
if(_player->GetMoney() < nSpellCost )
return;
WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer
data << uint64(guid) << uint32(0xB3);
SendPacket(&data);
data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player
data << uint64(_player->GetGUID()) << uint32(0x016A);
SendPacket(&data);
_player->ModifyMoney( -int32(nSpellCost) );
// learn explicitly to prevent lost money at lags, learning spell will be only show spell animation
_player->learnSpell(trainer_spell->spell);
// learn explicitly or cast explicitly
if(trainer_spell->IsCastable ())
//FIXME: prof. spell entry in trainer list not marked gray until list re-open.
unit->CastSpell(_player,trainer_spell->spell,true);
else
{
WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer
data << uint64(guid) << uint32(0xB3);
SendPacket(&data);
data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
data << uint64(guid) << uint32(spellId);
data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player
data << uint64(_player->GetGUID()) << uint32(0x016A);
SendPacket(&data);
_player->learnSpell(spellId);
}
WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12);
data << uint64(guid) << uint32(trainer_spell->spell);
SendPacket(&data);
}
+31
View File
@@ -1693,6 +1693,24 @@ void ObjectMgr::LoadItemPrototypes()
if(dbcitem)
{
if(proto->Class != dbcitem->Class || proto->SubClass != dbcitem->SubClass)
{
sLog.outErrorDb("Item (Entry: %u) not correct (Class: %u, Sub: %u) pair, must be (Class: %u, Sub: %u) (still using DB value).",i,proto->Class,proto->SubClass,dbcitem->Class,dbcitem->SubClass);
// It safe let use Class/Subclass from DB
}
if(proto->Unk0 != dbcitem->Unk0)
{
sLog.outErrorDb("Item (Entry: %u) not correct %u Unk0, must be %u (still using DB value).",i,proto->Unk0,dbcitem->Unk0);
// It safe let use Unk0 from DB
}
if(proto->Material != dbcitem->Material)
{
sLog.outErrorDb("Item (Entry: %u) not correct %u material, must be %u (still using DB value).",i,proto->Material,dbcitem->Material);
// It safe let use Material from DB
}
if(proto->InventoryType != dbcitem->InventoryType)
{
sLog.outErrorDb("Item (Entry: %u) not correct %u inventory type, must be %u (still using DB value).",i,proto->InventoryType,dbcitem->InventoryType);
@@ -7267,6 +7285,19 @@ void ObjectMgr::LoadTrainerSpell()
if(!pTrainerSpell->reqlevel)
pTrainerSpell->reqlevel = spellinfo->spellLevel;
// calculate learned spell for profession case when stored cast-spell
pTrainerSpell->learned_spell = spell;
for(int i = 0; i <3; ++i)
{
if(spellinfo->Effect[i]!=SPELL_EFFECT_LEARN_SPELL)
continue;
if(SpellMgr::IsProfessionOrRidingSpell(spellinfo->EffectTriggerSpell[i]))
{
pTrainerSpell->learned_spell = spellinfo->EffectTriggerSpell[i];
break;
}
}
TrainerSpellData& data = m_mCacheTrainerSpellMap[entry];
+14 -9
View File
@@ -3566,22 +3566,22 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell
if (!trainer_spell)
return TRAINER_SPELL_RED;
if (!trainer_spell->spell)
if (!trainer_spell->learned_spell)
return TRAINER_SPELL_RED;
// known spell
if(HasSpell(trainer_spell->spell))
if(HasSpell(trainer_spell->learned_spell))
return TRAINER_SPELL_GRAY;
// check race/class requirement
if(!IsSpellFitByClassAndRace(trainer_spell->spell))
if(!IsSpellFitByClassAndRace(trainer_spell->learned_spell))
return TRAINER_SPELL_RED;
// check level requirement
if(getLevel() < trainer_spell->reqlevel)
return TRAINER_SPELL_RED;
if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->spell))
if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->learned_spell))
{
// check prev.rank requirement
if(spell_chain->prev && !HasSpell(spell_chain->prev))
@@ -3600,7 +3600,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell
return TRAINER_SPELL_RED;
// exist, already checked at loading
SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->spell);
SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->learned_spell);
// secondary prof. or not prof. spell
uint32 skill = spell->EffectMiscValue[1];
@@ -5049,7 +5049,7 @@ void Player::UpdateSkillsToMaxSkillsForLevel()
if (GetUInt32Value(PLAYER_SKILL_INDEX(i)))
{
uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
if( IsProfessionSkill(pskill) || pskill == SKILL_RIDING )
if( IsProfessionOrRidingSkill(pskill))
continue;
uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i));
@@ -18756,18 +18756,23 @@ bool Player::IsSpellFitByClassAndRace( uint32 spell_id ) const
SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id);
SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spell_id);
if(lower==upper)
return true;
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
{
// skip wrong race skills
if( _spell_idx->second->racemask && (_spell_idx->second->racemask & racemask) == 0)
return false;
continue;
// skip wrong class skills
if( _spell_idx->second->classmask && (_spell_idx->second->classmask & classmask) == 0)
return false;
continue;
return true;
}
return true;
return false;
}
bool Player::HasQuestForGO(int32 GOId)
+75 -80
View File
@@ -869,30 +869,6 @@ void Spell::EffectDummy(uint32 i)
}
return;
}
case 14185: // Preparation Rogue
{
if(m_caster->GetTypeId()!=TYPEID_PLAYER)
return;
//immediately finishes the cooldown on certain Rogue abilities
const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
uint32 classspell = itr->first;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL))
{
((Player*)m_caster)->RemoveSpellCooldown(classspell);
WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
data << uint32(classspell);
data << uint64(m_caster->GetGUID());
((Player*)m_caster)->GetSession()->SendPacket(&data);
}
}
return;
}
case 15998: // Capture Worg Pup
case 29435: // Capture Female Kaliri Hatchling
{
@@ -969,7 +945,7 @@ void Spell::EffectDummy(uint32 i)
return;
}
case 23074: // Arc. Dragonling
case 23074: // Arcanite Dragonling
if (!m_CastItem) return;
m_caster->CastSpell(m_caster,19804,true,m_CastItem);
return;
@@ -1378,7 +1354,13 @@ void Spell::EffectDummy(uint32 i)
if(!unitTarget)
return;
int32 basePoints0 = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]);
uint32 rage = m_caster->GetPower(POWER_RAGE);
// Glyph of Execution bonus
if (Aura *aura = m_caster->GetDummyAura(58367))
rage+=aura->GetModifier()->m_amount;
int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
m_caster->SetPower(POWER_RAGE,0);
return;
@@ -1514,11 +1496,6 @@ void Spell::EffectDummy(uint32 i)
case SPELLFAMILY_ROGUE:
switch(m_spellInfo->Id )
{
case 31231: // Cheat Death
{
m_caster->CastSpell(m_caster,45182,true);
return;
}
case 5938: // Shiv
{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
@@ -1554,6 +1531,35 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(unitTarget, 5940, true);
return;
}
case 14185: // Preparation Rogue
{
if(m_caster->GetTypeId()!=TYPEID_PLAYER)
return;
//immediately finishes the cooldown on certain Rogue abilities
const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
uint32 classspell = itr->first;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x0000024000000860LL))
{
((Player*)m_caster)->RemoveSpellCooldown(classspell);
WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
data << uint32(classspell);
data << uint64(m_caster->GetGUID());
((Player*)m_caster)->GetSession()->SendPacket(&data);
}
}
return;
}
case 31231: // Cheat Death
{
m_caster->CastSpell(m_caster,45182,true);
return;
}
}
break;
case SPELLFAMILY_HUNTER:
@@ -2841,7 +2847,7 @@ void Spell::EffectEnergisePct(uint32 i)
uint32 gain = damage * maxPower / 100;
unitTarget->ModifyPower(power, gain);
m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power);
}
void Spell::SendLoot(uint64 guid, LootType loottype)
@@ -5141,57 +5147,46 @@ void Spell::EffectScriptEffect(uint32 effIndex)
}
else if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
{
switch(m_spellInfo->SpellFamilyFlags)
// Judgement
if (m_spellInfo->SpellFamilyFlags & 0x0000000000800000LL)
{
// Judgement
case 0x800000:
{
uint32 spellId2 = 0;
// all seals have aura dummy
Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
{
SpellEntry const *spellInfo = (*itr)->GetSpellProto();
// search seal (all seals have judgement's aura dummy spell id in 2 effect
if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 )
continue;
// must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1;
if(spellId2 <= 1)
continue;
// found, remove seal
m_caster->RemoveAurasDueToSpell((*itr)->GetId());
// Sanctified Judgement
Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i)
{
if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL)
{
int32 chance = (*i)->GetModifier()->m_amount;
if ( roll_chance_i(chance) )
{
int32 mana = spellInfo->manaCost;
if ( Player* modOwner = m_caster->GetSpellModOwner() )
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana);
mana = int32(mana* 0.8f);
m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i);
}
break;
}
}
break;
}
m_caster->CastSpell(unitTarget,spellId2,true);
if(!unitTarget || !unitTarget->isAlive())
return;
uint32 spellId1 = 0;
uint32 spellId2 = 0;
// Judgement self add switch
switch (m_spellInfo->Id)
{
case 41467: break; // Judgement
case 53407: spellId1 = 20184; break; // Judgement of Justice
case 20271: // Judgement of Light
case 57774: spellId1 = 20185; break; // Judgement of Light
case 53408: spellId1 = 20186; break; // Judgement of Wisdom
default:
return;
}
// all seals have aura dummy in 2 effect
Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
{
SpellEntry const *spellInfo = (*itr)->GetSpellProto();
// search seal (all seals have judgement's aura dummy spell id in 2 effect
if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo))
continue;
spellId2 = (*itr)->GetModifier()->m_amount;
SpellEntry const *judge = sSpellStore.LookupEntry(spellId2);
if (!judge)
continue;
// found, remove seal
m_caster->RemoveAurasDueToSpell(spellInfo->Id);
break;
}
if (spellId1)
m_caster->CastSpell(unitTarget, spellId1, true);
if (spellId2)
m_caster->CastSpell(unitTarget, spellId2, true);
return;
}
}
+4 -3
View File
@@ -1225,7 +1225,7 @@ bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
{
if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH)
return false;
if(IsProfessionSpell(spellInfo->Id))
if(IsProfessionOrRidingSpell(spellInfo->Id))
return false;
// All stance spells. if any better way, change it.
@@ -1327,7 +1327,8 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool
return true;
}
bool SpellMgr::IsProfessionSpell(uint32 spellId)
bool SpellMgr::IsProfessionOrRidingSpell(uint32 spellId)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
if(!spellInfo)
@@ -1338,7 +1339,7 @@ bool SpellMgr::IsProfessionSpell(uint32 spellId)
uint32 skill = spellInfo->EffectMiscValue[1];
return IsProfessionSkill(skill);
return IsProfessionOrRidingSkill(skill);
}
bool SpellMgr::IsPrimaryProfessionSpell(uint32 spellId)
+6
View File
@@ -757,6 +757,11 @@ typedef std::vector<uint32> SpellCustomAttribute;
typedef std::map<int32, std::vector<int32> > SpellLinkedMap;
inline bool IsProfessionOrRidingSkill(uint32 skill)
{
return IsProfessionSkill(skill) || skill == SKILL_RIDING;
}
class SpellMgr
{
// Constructors
@@ -935,6 +940,7 @@ class SpellMgr
return false;
}
static bool IsProfessionOrRidingSpell(uint32 spellId);
static bool IsProfessionSpell(uint32 spellId);
static bool IsPrimaryProfessionSpell(uint32 spellId);
bool IsPrimaryProfessionFirstRankSpell(uint32 spellId) const;
+79 -31
View File
@@ -1285,17 +1285,6 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
return;
}
// update at damage Judgement aura duration that applied by attacker at victim
if(damageInfo->damage && spellProto->Id == 35395)
{
AuraMap& vAuras = pVictim->GetAuras();
for(AuraMap::iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr)
{
SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID()))
(*itr).second->RefreshAura();
}
}
// Call default DealDamage
CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, MELEE_HIT_NORMAL);
DealDamage(pVictim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss);
@@ -4882,6 +4871,30 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
target = this;
break;
}
// Divine purpose
case 31871:
case 31872:
{
// Roll chane
if (!roll_chance_i(triggeredByAura->GetModifier()->m_amount))
return false;
// Remove any stun effect on target
AuraMap& Auras = pVictim->GetAuras();
for(AuraMap::iterator iter = Auras.begin(); iter != Auras.end();)
{
SpellEntry const *spell = iter->second->GetSpellProto();
if( spell->Mechanic == MECHANIC_STUN ||
spell->EffectMechanic[iter->second->GetEffIndex()] == MECHANIC_STUN)
{
pVictim->RemoveAurasDueToSpell(spell->Id);
iter = Auras.begin();
}
else
++iter;
}
return true;
}
}
break;
}
@@ -5384,29 +5397,30 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
basepoints0 = GetAttackTime(BASE_ATTACK) * int32(ap*0.022f + 0.044f * holy) / 1000;
break;
}
// Seal of Blood do damage trigger
if(dummySpell->SpellFamilyFlags & 0x0000040000000000LL)
{
switch(triggeredByAura->GetEffIndex())
{
case 0:
triggered_spell_id = 31893;
break;
case 1:
{
// damage
damage += CalculateDamage(BASE_ATTACK, false) * 35 / 100; // add spell damage from prev effect (35%)
basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100;
target = this;
triggered_spell_id = 32221;
break;
}
}
}
switch(dummySpell->Id)
{
// Judgement of Light
case 20185:
{
// Get judgement caster
Unit *caster = triggeredByAura->GetCaster();
if (!caster)
return false;
float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
int32 holy = caster->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) +
caster->SpellBaseDamageBonusForVictim(SPELL_SCHOOL_MASK_HOLY, this);
basepoints0 = int32(ap*0.10f + 0.10f*holy);
pVictim->CastCustomSpell(pVictim, 20267, &basepoints0, 0, 0, true, 0, triggeredByAura);
return true;
}
// Judgement of Wisdom
case 20186:
{
if (pVictim->getPowerType() == POWER_MANA)
pVictim->CastSpell(pVictim, 20268, true, 0, triggeredByAura);
return true;
}
// Holy Power (Redemption Armor set)
case 28789:
{
@@ -5461,6 +5475,40 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 31786;
break;
}
// Seal of Blood do damage trigger
case 31892:
{
if (triggeredByAura->GetEffIndex() == 0) // 0 effect - is proc on enemy
triggered_spell_id = 31893;
else if (triggeredByAura->GetEffIndex() == 1) // 1 effect - is proc on self
{
// add spell damage from prev effect (27%)
damage += CalculateDamage(BASE_ATTACK, false) * 27 / 100;
basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100;
target = this;
triggered_spell_id = 32221;
}
else
return true;
break;
}
// Seal of the Martyr do damage trigger
case 53720:
{
if (triggeredByAura->GetEffIndex() == 0) // 0 effect - is proc on enemy
triggered_spell_id = 53719;
else if (triggeredByAura->GetEffIndex() == 1) // 1 effect - is proc on self
{
// add spell damage from prev effect (27%)
damage += CalculateDamage(BASE_ATTACK, false) * 27 / 100;
basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100;
target = this;
triggered_spell_id = 53718;
}
else
return true;
break;
}
// Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
case 40470:
{
+4 -4
View File
@@ -815,10 +815,10 @@ struct GtRegenMPPerSptEntry
struct ItemEntry
{
uint32 ID;
//uint32 Class;
//uint32 SubClass;
//uint32 Unk0;
//uint32 Material;
uint32 Class;
uint32 SubClass;
uint32 Unk0;
uint32 Material;
uint32 DisplayId;
uint32 InventoryType;
uint32 Sheath;
+1 -1
View File
@@ -53,7 +53,7 @@ const char GtOCTRegenHPfmt[]="f";
//const char GtOCTRegenMPfmt[]="f";
const char GtRegenHPPerSptfmt[]="f";
const char GtRegenMPPerSptfmt[]="f";
const char Itemfmt[]="nxxxxiii";
const char Itemfmt[]="niiiiiii";
//const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx";
//const char ItemCondExtCostsEntryfmt[]="xiii";
const char ItemExtendedCostEntryfmt[]="niiiiiiiiiiiiix";
+1 -1
View File
@@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "7076"
#define REVISION_NR "7083"
#endif // __REVISION_NR_H__