diff options
| author | megamage <none@none> | 2009-01-29 19:33:39 -0600 |
|---|---|---|
| committer | megamage <none@none> | 2009-01-29 19:33:39 -0600 |
| commit | 25ab1fa4adfe1e9be1f8bfb6701f6a0d48887770 (patch) | |
| tree | 7a7f598ef74d053a5dc3c5caa81d147c8c57c97c /src | |
| parent | 7663c741c748344270d85638a493a65eb6c3c93e (diff) | |
*Update to Mangos 7200.
--HG--
branch : trunk
Diffstat (limited to 'src')
| -rw-r--r-- | src/game/Chat.cpp | 1 | ||||
| -rw-r--r-- | src/game/Chat.h | 1 | ||||
| -rw-r--r-- | src/game/Level3.cpp | 9 | ||||
| -rw-r--r-- | src/game/ObjectAccessor.cpp | 6 | ||||
| -rw-r--r-- | src/game/SharedDefines.h | 4 | ||||
| -rw-r--r-- | src/game/Spell.cpp | 13 | ||||
| -rw-r--r-- | src/game/SpellAuraDefines.h | 6 | ||||
| -rw-r--r-- | src/game/SpellAuras.cpp | 104 | ||||
| -rw-r--r-- | src/game/SpellAuras.h | 2 | ||||
| -rw-r--r-- | src/game/SpellEffects.cpp | 32 | ||||
| -rw-r--r-- | src/game/SpellMgr.cpp | 46 | ||||
| -rw-r--r-- | src/game/SpellMgr.h | 27 | ||||
| -rw-r--r-- | src/game/Unit.cpp | 503 | ||||
| -rw-r--r-- | src/game/Unit.h | 4 | ||||
| -rw-r--r-- | src/game/World.cpp | 3 | ||||
| -rw-r--r-- | src/shared/revision_nr.h | 2 |
16 files changed, 391 insertions, 372 deletions
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 42fe369e1d4..785b2380914 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -310,6 +310,7 @@ ChatCommand * ChatHandler::getCommandTable() { "spell_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSpellCommand, "", NULL }, { "spell_pet_auras", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL }, { "spell_proc_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL }, + { "spell_bonus_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellBonusesCommand, "", NULL }, { "spell_script_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL }, { "spell_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL }, { "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 483f3c97863..8faea36e9fc 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -264,6 +264,7 @@ class ChatHandler bool HandleReloadSpellElixirCommand(const char* args); bool HandleReloadSpellLearnSpellCommand(const char* args); bool HandleReloadSpellProcEventCommand(const char* args); + bool HandleReloadSpellBonusesCommand(const char* args); bool HandleReloadSpellScriptTargetCommand(const char* args); bool HandleReloadSpellScriptsCommand(const char* args); bool HandleReloadSpellTargetPositionCommand(const char* args); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index fde30daebd2..88be4f6f2d5 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -513,6 +513,7 @@ bool ChatHandler::HandleReloadAllSpellCommand(const char*) HandleReloadSpellElixirCommand("a"); HandleReloadSpellLearnSpellCommand("a"); HandleReloadSpellProcEventCommand("a"); + HandleReloadSpellBonusesCommand("a"); HandleReloadSpellScriptTargetCommand("a"); HandleReloadSpellTargetPositionCommand("a"); HandleReloadSpellThreatsCommand("a"); @@ -837,6 +838,14 @@ bool ChatHandler::HandleReloadSpellProcEventCommand(const char*) return true; } +bool ChatHandler::HandleReloadSpellBonusesCommand(const char*) +{ + sLog.outString( "Re-Loading Spell Bonus Data..." ); + spellmgr.LoadSpellBonusess(); + SendGlobalSysMessage("DB table `spell_bonus_data` (spell damage/healing coefficients) reloaded."); + return true; +} + bool ChatHandler::HandleReloadSpellScriptTargetCommand(const char*) { sLog.outString( "Re-Loading SpellsScriptTarget..." ); diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 1891dc0396d..3fe28a4bfb0 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -176,7 +176,7 @@ ObjectAccessor::GetCorpse(WorldObject const &u, uint64 guid) if(!ret) return NULL; if(ret->GetMapId() != u.GetMapId()) - ret = NULL; + return NULL; if(ret->GetInstanceId() != u.GetInstanceId()) return NULL; return ret; @@ -226,7 +226,7 @@ ObjectAccessor::GetGameObject(WorldObject const &u, uint64 guid) if(!ret) return NULL; if(ret->GetMapId() != u.GetMapId()) - ret = NULL; + return NULL; if(ret->GetInstanceId() != u.GetInstanceId()) return NULL; return ret; @@ -239,7 +239,7 @@ ObjectAccessor::GetDynamicObject(WorldObject const &u, uint64 guid) if(!ret) return NULL; if(ret->GetMapId() != u.GetMapId()) - ret = NULL; + return NULL; if(ret->GetInstanceId() != u.GetInstanceId()) return NULL; return ret; diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 720c4898a70..51f6f1488fe 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -285,7 +285,7 @@ enum SpellCategory #define SPELL_ATTR_EX2_UNK0 0x00000001 // 0 #define SPELL_ATTR_EX2_UNK1 0x00000002 // 1 -#define SPELL_ATTR_EX2_UNK2 0x00000004 // 2 boss spells? +#define SPELL_ATTR_EX2_CANT_REFLECTED 0x00000004 // 2 ? used for detect can or not spell reflected #define SPELL_ATTR_EX2_UNK3 0x00000008 // 3 #define SPELL_ATTR_EX2_UNK4 0x00000010 // 4 #define SPELL_ATTR_EX2_AUTOREPEAT_FLAG 0x00000020 // 5 @@ -711,7 +711,7 @@ enum AuraState AURA_STATE_IMMOLATE = 14, // T | AURA_STATE_SWIFTMEND = 15, // T | AURA_STATE_DEADLY_POISON = 16, // T | - //AURA_STATE_UNKNOWN17 = 17, // C | + AURA_STATE_ENRAGE = 17, // C | //AURA_STATE_UNKNOWN18 = 18, // C t| //AURA_STATE_UNKNOWN19 = 19, // | not used //AURA_STATE_UNKNOWN20 = 20, // c | only (45317 Suicide) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index e7e009bafab..cf6245d9624 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -378,7 +378,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi // determine reflection m_canReflect = false; - if(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && (m_spellInfo->AttributesEx2 & 0x4)==0) + if(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_CANT_REFLECTED)) { for(int j=0;j<3;j++) { @@ -4469,15 +4469,16 @@ uint8 Spell::CheckCasterAuras() const //Check whether the cast should be prevented by any state you might have. uint8 prevented_reason = 0; // Have to check if there is a stun aura. Otherwise will have problems with ghost aura apply while logging out - if(!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED) && m_caster->HasAuraType(SPELL_AURA_MOD_STUN)) + uint32 unitflag = m_caster->GetUInt32Value(UNIT_FIELD_FLAGS); // Get unit state + if(unitflag & UNIT_FLAG_STUNNED && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED)) prevented_reason = SPELL_FAILED_STUNNED; - else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED) && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED)) + else if(unitflag & UNIT_FLAG_CONFUSED && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED)) prevented_reason = SPELL_FAILED_CONFUSED; - else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING) && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED)) + else if(unitflag & UNIT_FLAG_FLEEING && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED)) prevented_reason = SPELL_FAILED_FLEEING; - else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE) + else if(unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE) prevented_reason = SPELL_FAILED_SILENCED; - else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY) + else if(unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY) prevented_reason = SPELL_FAILED_PACIFIED; // Attr must make flag drop spell totally immune from all effects diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index fec7a295ac8..81339b038b5 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -90,9 +90,9 @@ enum AuraType SPELL_AURA_PROC_TRIGGER_DAMAGE = 43, SPELL_AURA_TRACK_CREATURES = 44, SPELL_AURA_TRACK_RESOURCES = 45, - SPELL_AURA_MOD_PARRY_SKILL = 46, + SPELL_AURA_46 = 46, // Ignore all Gear test spells SPELL_AURA_MOD_PARRY_PERCENT = 47, - SPELL_AURA_MOD_DODGE_SKILL = 48, + SPELL_AURA_48 = 48, // One periodic spell SPELL_AURA_MOD_DODGE_PERCENT = 49, SPELL_AURA_MOD_CRITICAL_HEALING_BONUS = 50, SPELL_AURA_MOD_BLOCK_PERCENT = 51, @@ -109,7 +109,7 @@ enum AuraType SPELL_AURA_PERIODIC_HEALTH_FUNNEL = 62, SPELL_AURA_PERIODIC_MANA_FUNNEL = 63, SPELL_AURA_PERIODIC_MANA_LEECH = 64, - SPELL_AURA_MOD_CASTING_SPEED = 65, + SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK = 65, SPELL_AURA_FEIGN_DEATH = 66, SPELL_AURA_MOD_DISARM = 67, SPELL_AURA_MOD_STALKED = 68, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 718b07a2012..47bee213e21 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -100,9 +100,9 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor &Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES &Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES - &Aura::HandleUnused, // 46 SPELL_AURA_MOD_PARRY_SKILL obsolete? + &Aura::HandleUnused, // 46 SPELL_AURA_46 &Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT - &Aura::HandleUnused, // 48 SPELL_AURA_MOD_DODGE_SKILL obsolete? + &Aura::HandleUnused, // 48 SPELL_AURA_48 &Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT &Aura::HandleNoImmediateEffect, // 50 SPELL_AURA_MOD_CRITICAL_HEALING_BONUS &Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT @@ -119,7 +119,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandlePeriodicHealthFunnel, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL &Aura::HandleUnused, // 63 SPELL_AURA_PERIODIC_MANA_FUNNEL obsolete? &Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH - &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED + &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK &Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH &Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM &Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED @@ -440,8 +440,10 @@ m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false) if(modOwner) modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges); - m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances && - !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000)); + m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && + m_spellProto->Stances && + !(m_spellProto->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && + !(m_spellProto->Attributes & SPELL_ATTR_NOT_SHAPESHIFT)); } Aura::~Aura() @@ -858,6 +860,10 @@ void Aura::_AddAura() // Deadly poison aura state if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags & 0x10000) m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON, true); + + // Enrage aura state + if(m_spellProto->Dispel == DISPEL_ENRAGE) + m_target->ModifyAuraState(AURA_STATE_ENRAGE, true); } } } @@ -927,6 +933,10 @@ void Aura::_RemoveAura() //***************************************************** // Update target aura state flag (at last aura remove) //***************************************************** + // Enrage aura state + if(m_spellProto->Dispel == DISPEL_ENRAGE) + m_target->ModifyAuraState(AURA_STATE_ENRAGE, false); + uint32 removeState = 0; switch(m_spellProto->SpellFamilyName) { @@ -1975,7 +1985,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { // prevent double apply bonuses if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) - m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target); + m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE); return; } } @@ -2173,7 +2183,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if ( caster ) // prevent double apply bonuses if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) - m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target); + m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE); } else { @@ -2847,6 +2857,9 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real) //talent will remove the caster's aura->interrupt channel->remove victim aura if(victim->GetHealth() > 0) return; + // Item amount + if (m_modifier.m_amount <= 0) + return; SpellEntry const *spellInfo = GetSpellProto(); if(spellInfo->EffectItemType[m_effIndex] == 0) @@ -2857,16 +2870,22 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real) (victim->getLevel() <= Trinity::XP::GetGrayLevel(caster->getLevel()) || victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) ) return; + //Adding items + uint32 noSpaceForCount = 0; + uint32 count = m_modifier.m_amount; + ItemPosCountVec dest; - uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 ); + uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], count, &noSpaceForCount); if( msg != EQUIP_ERR_OK ) { + count-=noSpaceForCount; ((Player*)caster)->SendEquipError( msg, NULL, NULL ); - return; + if (count==0) + return; } Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true); - ((Player*)caster)->SendNewItem(newitem, 1, true, false); + ((Player*)caster)->SendNewItem(newitem, count, true, false); } } @@ -3694,9 +3713,8 @@ void Aura::HandleModMechanicImmunity(bool apply, bool Real) next = iter; ++next; SpellEntry const *spell = iter->second->GetSpellProto(); - if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability - && !iter->second->IsPositive() // only remove negative spells - && spell->Id != GetId()) + if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) && // spells unaffected by invulnerability + spell->Id != GetId()) { //check for mechanic mask if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic) @@ -4122,29 +4140,6 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) } break; } - case SPELLFAMILY_PALADIN: - { - // Consecration - if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) - { - // ($m1+0.04*$SPH+0.04*$AP) - float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 holy = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) + - caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target); - m_modifier.m_amount += int32(0.04f*holy + 0.04f*ap); - return; - } - // Seal of Vengeance 0.013*$SPH+0.025*$AP per tick (also can stack) - if(m_spellProto->SpellFamilyFlags & 0x0000080000000000LL) - { - float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 holy = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) + - caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target); - m_modifier.m_amount += int32((0.013f*holy + 0.025f*ap) * GetStackAmount()); - return; - } - break; - } default: break; } @@ -5086,7 +5081,7 @@ void Aura::HandleShapeshiftBoosts(bool apply) if(itr->second->state == PLAYERSPELL_REMOVED) continue; if(itr->first==spellId || itr->first==spellId2) continue; SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue; + if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7)))) continue; if (spellInfo->Stances & (1<<form)) m_target->CastSpell(m_target, itr->first, true, NULL, this); } @@ -5487,13 +5482,12 @@ void Aura::PeriodicTick() CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; - - uint32 pdamage; + //uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + uint32 pdamage = GetModifier()->m_amount > 0 ? GetModifier()->m_amount : 0; if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE) { - pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),amount,DOT); + pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount()); // Calculate armor mitigation if it is a physical spell // But not for bleed mechanic spells @@ -5505,8 +5499,6 @@ void Aura::PeriodicTick() pdamage = pdamageReductedArmor; } - //pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); - // Curse of Agony damage-per-tick calculation if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544) { @@ -5527,8 +5519,6 @@ void Aura::PeriodicTick() if (m_target->GetTypeId()==TYPEID_PLAYER) pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - pdamage *= GetStackAmount(); - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", @@ -5583,8 +5573,9 @@ void Aura::PeriodicTick() uint32 resist=0; CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); - uint32 pdamage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; - pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); + //uint32 pdamage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + uint32 pdamage = GetModifier()->m_amount > 0 ? GetModifier()->m_amount : 0; + pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount()); //Calculate armor mitigation if it is a physical spell if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL) @@ -5594,15 +5585,11 @@ void Aura::PeriodicTick() pdamage = pdamageReductedArmor; } - //pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); - //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit // Reduce dot damage from resilience for players if (m_target->GetTypeId()==TYPEID_PLAYER) pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - pdamage *= GetStackAmount(); - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); if(m_target->GetHealth() < pdamage) @@ -5640,7 +5627,7 @@ void Aura::PeriodicTick() if(Player *modOwner = pCaster->GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); - uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster); + uint32 heal = pCaster->SpellHealingBonus(pCaster, spellProto, uint32(new_damage * multiplier), DOT, GetStackAmount()); int32 gain = pCaster->ModifyHealth(heal); pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto); @@ -5660,18 +5647,13 @@ void Aura::PeriodicTick() return; // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; - - uint32 pdamage; + //uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + uint32 pdamage = GetModifier()->m_amount > 0 ? GetModifier()->m_amount : 0; if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH) - pdamage = uint32(m_target->GetMaxHealth() * amount/100); + pdamage = uint32(m_target->GetMaxHealth() * pdamage * GetStackAmount() / 100); else - pdamage = pCaster->SpellHealingBonus(GetSpellProto(), amount, DOT, m_target); - - pdamage *= GetStackAmount(); - - //pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target); + pdamage = pCaster->SpellHealingBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount()); sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 8d9f32f4fc2..3822d2abf86 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -274,7 +274,7 @@ class TRINITY_DLL_SPEC Aura void SendAuraUpdate(bool remove); int8 GetStackAmount() {return m_stackAmount;} - int32 GetModifierValuePerStack() {return m_modifier.m_amount / m_stackAmount;} + //int32 GetModifierValuePerStack() {return m_modifier.m_amount / m_stackAmount;} void SetStackAmount(uint8 num); bool modStackAmount(int32 num); // return true if last charge dropped void RefreshAura(); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 107265d9432..114458db6b9 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -623,7 +623,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) if(stacks) damage += damage * stacks * 10 /100; } - // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) + // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL) { float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); @@ -631,15 +631,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); damage += int32(ap * 0.07f) + int32(holy * 7 / 100); } - // Exorcism ($m1+0.15*$SPH+0.15*$AP) - else if(m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL) - { - float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + - m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); - damage += int32(ap * 0.15f) + int32(holy * 15 / 100); - } - // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) + // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix else if(m_spellInfo->SpellFamilyFlags & 0x0000008000000000LL) { float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); @@ -647,14 +639,6 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); damage += int32(ap * 0.15f) + int32(holy * 15 / 100); } - // Holy Wrath ($m1+0.07*$SPH+0.07*$AP) - else if(m_spellInfo->SpellFamilyFlags & 0x0020000000000000LL) - { - float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + - m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); - damage += int32(ap * 0.15f) + int32(holy * 15 / 100); - } break; } } @@ -2484,12 +2468,12 @@ void Spell::SpellDamageHeal(uint32 /*i*/) idx++; } - int32 tickheal = targetAura->GetModifierValuePerStack(); + int32 tickheal = targetAura->GetModifier()->m_amount; if(Unit* auraCaster = targetAura->GetCaster()) - tickheal = auraCaster->SpellHealingBonus(targetAura->GetSpellProto(), tickheal, DOT, unitTarget); + tickheal = auraCaster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), tickheal, DOT); //int32 tickheal = targetAura->GetSpellProto()->EffectBasePoints[idx] + 1; //It is said that talent bonus should not be included - //int32 tickheal = targetAura->GetModifier()->m_amount; + int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx]; addhealth += tickheal * tickcount; unitTarget->RemoveAurasDueToCasterSpell(targetAura->GetId(), targetAura->GetCasterGUID()); @@ -2498,7 +2482,7 @@ void Spell::SpellDamageHeal(uint32 /*i*/) //addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget); } else - addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget); + addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL); m_damage -= addhealth; } @@ -2539,7 +2523,7 @@ void Spell::EffectHealMechanical( uint32 /*i*/ ) if (!caster) return; - uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget); + uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL); caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false); unitTarget->ModifyHealth( int32(damage) ); } @@ -2570,7 +2554,7 @@ void Spell::EffectHealthLeech(uint32 i) if(m_caster->isAlive()) { - new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster); + new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL); m_caster->ModifyHealth(new_damage); diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index baf40d24350..e73285d0f22 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1041,7 +1041,7 @@ void SpellMgr::LoadSpellProcEvents() bar.step(); - uint16 entry = fields[0].GetUInt16(); + uint32 entry = fields[0].GetUInt32(); const SpellEntry *spell = sSpellStore.LookupEntry(entry); if (!spell) @@ -1085,6 +1085,50 @@ void SpellMgr::LoadSpellProcEvents() sLog.outString( ">> Loaded %u extra spell proc event conditions", count ); } +void SpellMgr::LoadSpellBonusess() +{ + mSpellBonusMap.clear(); // need for reload case + uint32 count = 0; + // 0 1 2 3 + QueryResult *result = WorldDatabase.Query("SELECT entry, direct_bonus, dot_bonus, ap_bonus FROM spell_bonus_data"); + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + sLog.outString(); + sLog.outString( ">> Loaded %u spell bonus data", count); + return; + } + + barGoLink bar( result->GetRowCount() ); + do + { + Field *fields = result->Fetch(); + bar.step(); + uint32 entry = fields[0].GetUInt32(); + + const SpellEntry *spell = sSpellStore.LookupEntry(entry); + if (!spell) + { + sLog.outErrorDb("Spell %u listed in `spell_bonus_data` does not exist", entry); + continue; + } + + SpellBonusEntry sbe; + + sbe.direct_damage = fields[1].GetFloat(); + sbe.dot_damage = fields[2].GetFloat(); + sbe.ap_bonus = fields[3].GetFloat(); + + mSpellBonusMap[entry] = sbe; + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u extra spell bonus data", count); +} + bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active) { // No extra req need diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 77ee39e2249..eb9ce0637dc 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -605,7 +605,15 @@ struct SpellProcEventEntry uint32 cooldown; // hidden cooldown used for some spell proc events, applied to _triggered_spell_ }; +struct SpellBonusEntry +{ + float direct_damage; + float dot_damage; + float ap_bonus; +}; + typedef UNORDERED_MAP<uint32, SpellProcEventEntry> SpellProcEventMap; +typedef UNORDERED_MAP<uint32, SpellBonusEntry> SpellBonusMap; #define ELIXIR_BATTLE_MASK 0x1 #define ELIXIR_GUARDIAN_MASK 0x2 @@ -830,6 +838,23 @@ class SpellMgr static bool IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active); + // Spell bonus data + SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const + { + // Lookup data + SpellBonusMap::const_iterator itr = mSpellBonusMap.find(spellId); + if( itr != mSpellBonusMap.end( ) ) + return &itr->second; + // Not found, try lookup for 1 spell rank if exist + if (uint32 rank_1 = GetFirstSpellInChain(spellId)) + { + SpellBonusMap::const_iterator itr = mSpellBonusMap.find(rank_1); + if( itr != mSpellBonusMap.end( ) ) + return &itr->second; + } + return NULL; + } + // Spell target coordinates SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id) const { @@ -1041,6 +1066,7 @@ class SpellMgr void LoadSpellAffects(); void LoadSpellElixirs(); void LoadSpellProcEvents(); + void LoadSpellBonusess(); void LoadSpellTargetPositions(); void LoadSpellThreats(); void LoadSkillLineAbilityMap(); @@ -1060,6 +1086,7 @@ class SpellMgr SpellAffectMap mSpellAffectMap; SpellElixirMap mSpellElixirs; SpellProcEventMap mSpellProcEventMap; + SpellBonusMap mSpellBonusMap; SkillLineAbilityMap mSkillLineAbilityMap; SpellPetAuraMap mSpellPetAuraMap; SpellCustomAttribute mSpellCustomAttr; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 7b5b9f09511..43f9916f302 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1755,6 +1755,9 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe // Get unit state (need for some absorb check) uint32 unitflag = pVictim->GetUInt32Value(UNIT_FIELD_FLAGS); + // Reflect damage spells (not cast any damage spell in aura lookup) + uint32 reflectSpell = 0; + int32 reflectDamage = 0; // Need remove expired auras after bool existExpired = false; // absorb without mana cost @@ -1810,12 +1813,11 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe // Reflective Shield (Lady Malande boss) if (spellProto->Id == 41475) { - int32 reflectDamage = 0; if(RemainingDamage < currentAbsorb) reflectDamage = RemainingDamage / 2; else reflectDamage = currentAbsorb / 2; - pVictim->CastCustomSpell(this, 33619, &reflectDamage, NULL, NULL, true, NULL, *i); + reflectSpell = 33619; break; } if (spellProto->Id == 39228 || // Argussian Compass @@ -1884,14 +1886,10 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe reflectDamage = (*k)->GetModifier()->m_amount * currentAbsorb/100; else reflectDamage = (*k)->GetModifier()->m_amount * RemainingDamage/100; + reflectSpell = 33619; } break; default: break; } - if (reflectDamage) - { - pVictim->CastCustomSpell(this, 33619, &reflectDamage, NULL, NULL, true, NULL, *i); - break; - } } break; } @@ -1982,6 +1980,9 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe ++i; } } + // Cast back reflect damage spell + if (reflectSpell) + pVictim->CastCustomSpell(this, reflectSpell, &reflectDamage, NULL, NULL, true); // absorb by mana cost AuraList const& vManaShield = pVictim->GetAurasByType(SPELL_AURA_MANA_SHIELD); @@ -4675,7 +4676,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu if(!target) return false; - basepoints0 = int32(damage * 2.5f); // manaregen triggered_spell_id = 34650; break; } @@ -5980,6 +5980,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case 10432: spell = 26363; break; case 25469: spell = 26371; break; case 25472: spell = 26372; break; + case 49280: spell = 49278; break; + case 49281: spell = 49279; break; default: return false; } @@ -6535,6 +6537,10 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB trigger_spell_id = 26371; break; case 25472: // Rank 9 trigger_spell_id = 26372; break; + case 49280: // Rank 10 + trigger_spell_id = 49278; break; + case 49281: // Rank 11 + trigger_spell_id = 49279; break; default: sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield", auraSpellInfo->Id); return false; @@ -7402,51 +7408,7 @@ void Unit::RemoveAllAttackers() void Unit::ModifyAuraState(AuraState flag, bool apply) { - if (apply) - { - if (!HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1))) - { - SetFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); - if(GetTypeId() == TYPEID_PLAYER) - { - const PlayerSpellMap& sp_list = ((Player*)this)->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) - { - if(itr->second->state == PLAYERSPELL_REMOVED) continue; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - if (!spellInfo || !IsPassiveSpell(itr->first)) continue; - if (spellInfo->CasterAuraState == flag) - CastSpell(this, itr->first, true, NULL); - } - } - } - } - else - { - if (HasFlag(UNIT_FIELD_AURASTATE,1<<(flag-1))) - { - RemoveFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); - Unit::AuraMap& tAuras = GetAuras(); - for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();) - { - SpellEntry const* spellProto = (*itr).second->GetSpellProto(); - if (spellProto->CasterAuraState == flag) - { - // exceptions (applied at state but not removed at state change) - // Rampage - if(spellProto->SpellIconID==2006 && spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && spellProto->SpellFamilyFlags==0x100000) - { - ++itr; - continue; - } - - RemoveAura(itr); - } - else - ++itr; - } - } - } + ApplyModFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1), apply); } Unit *Unit::GetOwner() const @@ -7596,7 +7558,7 @@ void Unit::SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, Po SendMessageToSet(&data, true); } -uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype) +uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) { if(!spellProto || !pVictim || damagetype==DIRECT_DAMAGE ) return pdamage; @@ -7611,8 +7573,8 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 // Taken/Done total percent damage auras float DoneTotalMod = 1.0f; float TakenTotalMod = 1.0f; - uint32 DoneTotal = 0; - uint32 TakenTotal = 0; + int32 DoneTotal = 0; + int32 TakenTotal = 0; // ..done // Pet damage @@ -7799,107 +7761,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 } } - // ..taken - AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); - for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) - if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) ) - TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; - - // .. taken pct: dummy auras - AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); - for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) - { - switch((*i)->GetSpellProto()->SpellIconID) - { - //Cheat Death - case 2109: - if( ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) ) - { - if(pVictim->GetTypeId() != TYPEID_PLAYER) - continue; - float mod = -((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2*4; - if (mod < (*i)->GetModifier()->m_amount) - mod = (*i)->GetModifier()->m_amount; - TakenTotalMod *= (mod+100.0f)/100.0f; - } - break; - } - } - - // From caster spells - AuraList const& mOwnerTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER); - for(AuraList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i) - if( (*i)->GetCasterGUID() == GetGUID() && (*i)->isAffectedOnSpell(spellProto)) - TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; - - // Mod damage from spell mechanic - uint32 mechanicMask = GetAllSpellMechanicMask(spellProto); - if (mechanicMask) - { - AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); - for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i) - if(mechanicMask & uint32(1<<((*i)->GetModifier()->m_miscvalue))) - TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; - } - - // Damage Done from spell damage bonus - uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); - - // Taken/Done fixed damage bonus auras - int32 DoneAdvertisedBenefit = SpellBaseDamageBonus(GetSpellSchoolMask(spellProto)); - int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); - - // Pets just add their bonus damage to their spell damage - // note that their spell damage is just gain of their own auras - if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) - DoneAdvertisedBenefit += ((Pet*)this)->GetBonusDamage(); - - // Damage over Time spells bonus calculation - float DotFactor = 1.0f; - if(damagetype == DOT) - { - int32 DotDuration = GetSpellDuration(spellProto); - // 200% limit - if(DotDuration > 0) - { - if(DotDuration > 30000) DotDuration = 30000; - if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; - int x = 0; - for(int j = 0; j < 3; j++) - { - if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) - { - x = j; - break; - } - } - int DotTicks = 6; - if(spellProto->EffectAmplitude[x] != 0) - DotTicks = DotDuration / spellProto->EffectAmplitude[x]; - if(DotTicks) - { - DoneAdvertisedBenefit /= DotTicks; - TakenAdvertisedBenefit /= DotTicks; - } - } - } - // Distribute Damage over multiple effects, reduce by AoE - CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - - // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing - for(int j = 0; j < 3; ++j) - { - if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || - spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) - { - CastingTime /= 2; - break; - } - } - - switch(spellProto->SpellFamilyName) + /*switch(spellProto->SpellFamilyName) { case SPELLFAMILY_GENERIC: // Siphon Essence - 0% @@ -8090,51 +7952,143 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 { CastingTime = 500; } - break; - case SPELLFAMILY_DRUID: - // Hurricane triggered spell - if((spellProto->SpellFamilyFlags & 0x400000LL) && spellProto->SpellIconID == 220) - { - CastingTime = 500; - } - break; - case SPELLFAMILY_WARRIOR: - case SPELLFAMILY_HUNTER: - case SPELLFAMILY_ROGUE: - CastingTime = 0; - break; - default: - break; + break;*/ + + // Custom scripted damage + // Ice Lance + if (spellProto->SpellFamilyName == SPELLFAMILY_MAGE && spellProto->SpellIconID == 186) + { + if (pVictim->isFrozen()) + DoneTotalMod *= 3.0f; } - float LvlPenalty = CalculateLevelPenalty(spellProto); + // ..taken + AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) + if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) ) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; - // Spellmod SpellDamage - //float SpellModSpellDamage = 100.0f; - float CoefficientPtc = DotFactor * 100.0f; - if(spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL) - CoefficientPtc *= ((float)CastingTime/3500.0f); + // .. taken pct: dummy auras + if (pVictim->GetTypeId() == TYPEID_PLAYER) + { + //Cheat Death + if (Aura *dummy = pVictim->GetDummyAura(45182)) + { + float mod = -((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2*4; + if (mod < dummy->GetModifier()->m_amount) + mod = dummy->GetModifier()->m_amount; + TakenTotalMod *= (mod+100.0f)/100.0f; + } + } - if(Player* modOwner = GetSpellModOwner()) - //modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,SpellModSpellDamage); - modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,CoefficientPtc); + // From caster spells + AuraList const& mOwnerTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER); + for(AuraList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i) + if( (*i)->GetCasterGUID() == GetGUID() && (*i)->isAffectedOnSpell(spellProto)) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; - //SpellModSpellDamage /= 100.0f; - CoefficientPtc /= 100.0f; + // Mod damage from spell mechanic + uint32 mechanicMask = GetAllSpellMechanicMask(spellProto); + if (mechanicMask) + { + AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); + for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i) + if(mechanicMask & uint32(1<<((*i)->GetModifier()->m_miscvalue))) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + } - //float DoneActualBenefit = DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * SpellModSpellDamage * LvlPenalty; - - float DoneActualBenefit = DoneAdvertisedBenefit * CoefficientPtc * LvlPenalty; - float TakenActualBenefit = TakenAdvertisedBenefit * DotFactor * LvlPenalty; - if(spellProto->SpellFamilyName && spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL) - TakenActualBenefit *= ((float)CastingTime / 3500.0f); + // Taken/Done fixed damage bonus auras + int32 DoneAdvertisedBenefit = SpellBaseDamageBonus(GetSpellSchoolMask(spellProto)); + int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); + // Pets just add their bonus damage to their spell damage + // note that their spell damage is just gain of their own auras + if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) + DoneAdvertisedBenefit += ((Pet*)this)->GetBonusDamage(); - float tmpDamage = (float(pdamage)+DoneActualBenefit + DoneTotal)*DoneTotalMod; + // Check for table values + float coeff; + SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id); + if (bonus) + { + if (damagetype == DOT) + coeff = bonus->dot_damage; + else + coeff = bonus->direct_damage; + if (bonus->ap_bonus) + DoneTotal+=bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack; + } + // Default calculation + else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit) + { + // Damage Done from spell damage bonus + uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); + // Damage over Time spells bonus calculation + float DotFactor = 1.0f; + if(damagetype == DOT) + { + int32 DotDuration = GetSpellDuration(spellProto); + // 200% limit + if(DotDuration > 0) + { + if(DotDuration > 30000) DotDuration = 30000; + if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; + int x = 0; + for(int j = 0; j < 3; j++) + { + if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) + { + x = j; + break; + } + } + int DotTicks = 6; + if(spellProto->EffectAmplitude[x] != 0) + DotTicks = DotDuration / spellProto->EffectAmplitude[x]; + if(DotTicks) + { + DoneAdvertisedBenefit /= DotTicks; + TakenAdvertisedBenefit /= DotTicks; + } + } + } + // Distribute Damage over multiple effects, reduce by AoE + CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); + + // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing + for(int j = 0; j < 3; ++j) + { + if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || + spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) + { + CastingTime /= 2; + break; + } + } + if(spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL) + coeff = (CastingTime / 3500.0f) * DotFactor; + else + coeff = DotFactor; + } + + float coeff2 = CalculateLevelPenalty(spellProto) * stack; + if(spellProto->SpellFamilyName) //TODO: fix this + TakenTotal+= TakenAdvertisedBenefit * coeff * coeff2; + if(Player* modOwner = GetSpellModOwner()) + { + coeff *= 100.0f; + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_SPELL_BONUS_DAMAGE, coeff); + coeff /= 100.0f; + } + DoneTotal += DoneAdvertisedBenefit * coeff * coeff2; + + float tmpDamage = (pdamage + DoneTotal) * DoneTotalMod; // apply spellmod to Done damage (flat and pct) if(Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage); - tmpDamage = (tmpDamage + TakenActualBenefit + TakenTotal)*TakenTotalMod; + tmpDamage = (tmpDamage + TakenTotal) * TakenTotalMod; return tmpDamage > 0 ? uint32(tmpDamage) : 0; } @@ -8361,15 +8315,18 @@ uint32 Unit::SpellCriticalHealingBonus(SpellEntry const *spellProto, uint32 dama return damage; } -uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim) +uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack) { + // No heal amount for this class spells + if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE) + return healamount; + // For totems get healing bonus from owner (statue isn't totem in fact) if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE) if(Unit* owner = GetOwner()) - return owner->SpellHealingBonus(spellProto, healamount, damagetype, pVictim); - - // Healing Done + return owner->SpellHealingBonus(pVictim, spellProto, healamount, damagetype, stack); + // TODO: to be deleted // These Spells are doing fixed amount of healing (TODO found less hack-like check) if (spellProto->Id == 15290 || spellProto->Id == 39373 || spellProto->Id == 33778 || spellProto->Id == 379 || @@ -8378,11 +8335,12 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, spellProto->Id == 34299) return healamount; + // Healing Done // Taken/Done total percent damage auras float DoneTotalMod = 1.0f; float TakenTotalMod = 1.0f; - uint32 DoneTotal = 0; - uint32 TakenTotal = 0; + int32 DoneTotal = 0; + int32 TakenTotal = 0; // Healing done percent AuraList const& mHealingDonePct = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT); @@ -8470,58 +8428,7 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, } } - int32 DoneAdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto)); - int32 TakenAdvertisedBenefit = SpellBaseHealingBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); - if (DoneAdvertisedBenefit != 0 && TakenAdvertisedBenefit!=0) - { - // Healing over Time spells - float DotFactor = 1.0f; - if(damagetype == DOT) - { - int32 DotDuration = GetSpellDuration(spellProto); - if(DotDuration > 0) - { - // 200% limit - if(DotDuration > 30000) DotDuration = 30000; - if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; - int x = 0; - for(int j = 0; j < 3; j++) - { - if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_HEAL || - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) - { - x = j; - break; - } - } - int DotTicks = 6; - if(spellProto->EffectAmplitude[x] != 0) - DotTicks = DotDuration / spellProto->EffectAmplitude[x]; - if(DotTicks) - { - DoneAdvertisedBenefit /= DotTicks; - TakenAdvertisedBenefit /= DotTicks; - } - } - } - uint32 CastingTime = GetSpellCastTime(spellProto); - - // distribute healing to all effects, reduce AoE damage - CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - - // 0% bonus for damage and healing spells for leech spells from healing bonus - for(int j = 0; j < 3; ++j) - { - if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || - spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) - { - CastingTime = 0; - break; - } - } - - // Exception + /*// Exception switch (spellProto->SpellFamilyName) { case SPELLFAMILY_GENERIC: @@ -8576,24 +8483,84 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, case SPELLFAMILY_HUNTER: CastingTime = 0; break; - } - - float LvlPenalty = CalculateLevelPenalty(spellProto); - - // Spellmod SpellDamage - //float SpellModSpellDamage = 100.0f; - float CoefficientPtc = ((float)CastingTime/3500.0f)*DotFactor*100.0f; + }*/ - if(Player* modOwner = GetSpellModOwner()) - //modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,SpellModSpellDamage); - modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,CoefficientPtc); + // Taken/Done fixed damage bonus auras + int32 DoneAdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto)); + int32 TakenAdvertisedBenefit = SpellBaseHealingBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); - //SpellModSpellDamage /= 100.0f; - CoefficientPtc /= 100.0f; + // Check for table values + SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id); + float coeff; + if (bonus) + { + if (damagetype == DOT) + coeff = bonus->dot_damage; + else + coeff = bonus->direct_damage; + if (bonus->ap_bonus) + DoneTotal+=bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack; + } + // Default calculation + else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit) + { + // Damage Done from spell damage bonus + uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); + // Damage over Time spells bonus calculation + float DotFactor = 1.0f; + if(damagetype == DOT) + { + int32 DotDuration = GetSpellDuration(spellProto); + // 200% limit + if(DotDuration > 0) + { + if(DotDuration > 30000) DotDuration = 30000; + if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; + int x = 0; + for(int j = 0; j < 3; j++) + { + if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) + { + x = j; + break; + } + } + int DotTicks = 6; + if(spellProto->EffectAmplitude[x] != 0) + DotTicks = DotDuration / spellProto->EffectAmplitude[x]; + if(DotTicks) + { + DoneAdvertisedBenefit /= DotTicks; + TakenAdvertisedBenefit /= DotTicks; + } + } + } + // Distribute Damage over multiple effects, reduce by AoE + CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); + // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing + for(int j = 0; j < 3; ++j) + { + if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || + spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) + { + CastingTime /= 2; + break; + } + } + coeff = (CastingTime / 3500.0f) * DotFactor; + } - DoneTotal += (float)DoneAdvertisedBenefit * CoefficientPtc * LvlPenalty; - TakenTotal += (float)TakenAdvertisedBenefit * CoefficientPtc * LvlPenalty; + float coeff2 = CalculateLevelPenalty(spellProto) * 1.88f * stack; + TakenTotal+= TakenAdvertisedBenefit * coeff * coeff2; + if(Player* modOwner = GetSpellModOwner()) + { + coeff *= 100.0f; + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_SPELL_BONUS_DAMAGE, coeff); + coeff /= 100.0f; } + DoneTotal += DoneAdvertisedBenefit * coeff * coeff2; // use float as more appropriate for negative values and percent applying float heal = (healamount + DoneTotal)*DoneTotalMod; @@ -8609,7 +8576,7 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, Unit::AuraList const& auraDummy = pVictim->GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr!=auraDummy.end(); ++itr) if((*itr)->GetId() == 29203) - TakenTotalMod *= (*itr)->GetModifier()->m_amount; + TakenTotalMod *= ((*itr)->GetModifier()->m_amount+100.0f) / 100.0f; } // Healing taken percent @@ -8859,8 +8826,8 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN); // Done/Taken total percent damage auras - float DoneTotalMod = 1; - float TakenTotalMod = 1; + float DoneTotalMod = 1.0f; + float TakenTotalMod = 1.0f; // ..done // SPELL_AURA_MOD_DAMAGE_PERCENT_DONE included in weapon damage @@ -10754,7 +10721,7 @@ bool InitTriggerAuraData() isTriggerAura[SPELL_AURA_DAMAGE_IMMUNITY] = true; isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL] = true; isTriggerAura[SPELL_AURA_PROC_TRIGGER_DAMAGE] = true; - isTriggerAura[SPELL_AURA_MOD_CASTING_SPEED] = true; + isTriggerAura[SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK] = true; isTriggerAura[SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT] = true; isTriggerAura[SPELL_AURA_MOD_POWER_COST_SCHOOL] = true; isTriggerAura[SPELL_AURA_REFLECT_SPELLS_SCHOOL] = true; @@ -10998,7 +10965,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag continue; break; } - case SPELL_AURA_MOD_CASTING_SPEED: + case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK: // Skip melee hits or instant cast spells if (procSpell == NULL || GetSpellCastTime(procSpell) == 0) continue; diff --git a/src/game/Unit.h b/src/game/Unit.h index 990e1fe020b..cbb61eb3c32 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1351,8 +1351,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask); int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim); int32 SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim); - uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 damage, DamageEffectType damagetype); - uint32 SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim); + uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 damage, DamageEffectType damagetype, uint32 stack = 1); + uint32 SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1); bool isSpellBlocked(Unit *pVictim, SpellEntry const *spellProto, WeaponAttackType attackType = BASE_ATTACK); bool isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK); uint32 SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim); diff --git a/src/game/World.cpp b/src/game/World.cpp index 7170ab290e0..397a01ddd51 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1161,6 +1161,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Spell Proc Event conditions..." ); spellmgr.LoadSpellProcEvents(); + sLog.outString( "Loading Spell Bonus Data..." ); + spellmgr.LoadSpellBonusess(); + sLog.outString( "Loading Aggro Spells Definitions..."); spellmgr.LoadSpellThreats(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3784904ebf4..d542e8dd61d 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 "7195" + #define REVISION_NR "7200" #endif // __REVISION_NR_H__ |
