diff options
Diffstat (limited to 'src')
45 files changed, 602 insertions, 488 deletions
diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp index eee4269e12c..6b46b7aecde 100644 --- a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp +++ b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp @@ -1225,7 +1225,7 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI void UpdateAI(const uint32 diff) { //Check if we are in combat (also updates calls threat update code) - bool Combat = InCombat ? (m_creature->SelectHostilTarget() && m_creature->getVictim()) : false; + bool Combat = InCombat ? m_creature->SelectHostilTarget() : false; //Must return if creature isn't alive. Normally select hostil target and get victim prevent this if (!m_creature->isAlive()) @@ -1233,11 +1233,9 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI if (IsFleeing) { - if(TimetoFleeLeft < diff - || m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE - && m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != FLEEING_MOTION_TYPE) + if(TimetoFleeLeft < diff) { - m_creature->GetMotionMaster()->Clear(false); + m_creature->SetControlled(false, UNIT_STAT_FLEEING); m_creature->SetNoCallAssistance(false); m_creature->CallAssistance(); if(m_creature->getVictim()) diff --git a/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp b/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp index c6ef71f25e5..6a11c455f67 100644 --- a/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp +++ b/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp @@ -149,7 +149,6 @@ struct TRINITY_DLL_DECL npc_dashel_stonefistAI : public ScriptedAI //m_creature->CombatStop(); EnterEvadeMode(); } - AttackedBy(done_by); } void Aggro(Unit *who) {} diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_laj.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_laj.cpp index 87fe0f92641..c7e138e0918 100644 --- a/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_laj.cpp +++ b/src/bindings/scripts/scripts/zone/tempest_keep/botanica/boss_laj.cpp @@ -144,6 +144,12 @@ struct TRINITY_DLL_DECL boss_lajAI : public ScriptedAI { } + void JustSummoned(Creature *summon) + { + if(summon && m_creature->getVictim()) + summon->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM, 0)); + } + void UpdateAI(const uint32 diff) { if( !m_creature->SelectHostilTarget() || !m_creature->getVictim() ) diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp index 1e29cd1df30..99e39618f53 100644 --- a/src/game/AggressorAI.cpp +++ b/src/game/AggressorAI.cpp @@ -38,7 +38,7 @@ AggressorAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -AggressorAI::AggressorAI(Creature &c) : i_creature(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) +AggressorAI::AggressorAI(Creature *c) : i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) { } diff --git a/src/game/AggressorAI.h b/src/game/AggressorAI.h index 51c123237f8..f6e2a649c8a 100644 --- a/src/game/AggressorAI.h +++ b/src/game/AggressorAI.h @@ -36,7 +36,7 @@ class TRINITY_DLL_DECL AggressorAI : public CreatureAI public: - AggressorAI(Creature &c); + AggressorAI(Creature *c); void MoveInLineOfSight(Unit *); void AttackStart(Unit *); 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/Creature.cpp b/src/game/Creature.cpp index 7ce5de97297..a4e683fb9d1 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -336,6 +336,8 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) SetUInt32Value(UNIT_FIELD_FLAGS,GetCreatureInfo()->unit_flags); SetUInt32Value(UNIT_DYNAMIC_FLAGS,GetCreatureInfo()->dynamicflags); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + SetMeleeDamageSchool(SpellSchools(GetCreatureInfo()->dmgschool)); SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(GetCreatureInfo()->armor)); SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(GetCreatureInfo()->resistance1)); @@ -375,6 +377,12 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) else SetReactState(REACT_AGGRESSIVE); + if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_TAUNT) + { + ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); + } + return true; } @@ -482,7 +490,7 @@ void Creature::Update(uint32 diff) if(!isAlive()) break; - if(!IsInEvadeMode()) + if(!IsInEvadeMode() && m_AI_enabled) { // do not allow the AI to be changed during update m_AI_locked = true; @@ -599,6 +607,7 @@ bool Creature::AIM_Initialize(CreatureAI* ai) i_AI = ai ? ai : FactorySelector::selectAI(this); if (oldAI) delete oldAI; + m_AI_enabled = true; return true; } @@ -607,10 +616,13 @@ void Creature::InitPossessedAI() if (!isPossessed()) return; if (!i_AI_possessed) - i_AI_possessed = new PossessedAI(*this); + i_AI_possessed = new PossessedAI(this); // Signal the old AI that it's been disabled i_AI->OnPossess(true); + + if(!(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_CHARM_AI)) + m_AI_enabled = false; } void Creature::DisablePossessedAI() @@ -621,6 +633,8 @@ void Creature::DisablePossessedAI() // Signal the old AI that it's been re-enabled i_AI->OnPossess(false); + + m_AI_enabled = true; } bool Creature::Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data) @@ -1855,22 +1869,12 @@ void Creature::DoFleeToGetAssistance(float radius) // Optional parameter return; Creature* pCreature = NULL; - - CellPair p(Trinity::ComputeCellPair(GetPositionX(), GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - Trinity::NearestAssistCreatureInCreatureRangeCheck u_check(this,getVictim(),radius); Trinity::CreatureLastSearcher<Trinity::NearestAssistCreatureInCreatureRangeCheck> searcher(pCreature, u_check); - - TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestAssistCreatureInCreatureRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher); - - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, grid_creature_searcher, *(GetMap())); + VisitNearbyGridObject(radius, searcher); if(!pCreature) - GetMotionMaster()->MoveFleeing(getVictim()); + SetControlled(true, UNIT_STAT_FLEEING); else GetMotionMaster()->MovePoint(0,pCreature->GetPositionX(),pCreature->GetPositionY(),pCreature->GetPositionZ()); } diff --git a/src/game/Creature.h b/src/game/Creature.h index 6ba3c9178e3..59475e27618 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -132,6 +132,8 @@ enum CreatureFlagsExtra CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP CREATURE_FLAG_EXTRA_TRIGGER = 0x00000080, // trigger creature CREATURE_FLAG_EXTRA_WORLDEVENT = 0x00004000, // custom flag for world event creatures (left room for merging) + CREATURE_FLAG_EXTRA_CHARM_AI = 0x00008000, // use ai when charmed + CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00010000, // cannot be taunted }; // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform @@ -676,6 +678,7 @@ class TRINITY_DLL_SPEC Creature : public Unit bool m_AlreadyCallAssistance; bool m_regenHealth; bool m_AI_locked; + bool m_AI_enabled; bool m_isDeadByDefault; SpellSchoolMask m_meleeDamageSchoolMask; diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index 71046e2f154..66c9d5af0b0 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -27,37 +27,47 @@ CreatureAI::~CreatureAI() { } -SimpleCharmedAI::SimpleCharmedAI(Unit &u) : me(u) +void CreatureAI::EnterEvadeMode() { + if(!me) return; + + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(); + me->LoadCreaturesAddon(); + me->SetLootRecipient(NULL); + + if(me->isAlive()) + me->GetMotionMaster()->MoveTargetedHome(); } void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/) { - Creature *charmer = (Creature*)me.GetCharmer(); + Creature *charmer = (Creature*)me->GetCharmer(); //kill self if charm aura has infinite duration if(charmer->IsInEvadeMode()) { - Unit::AuraList const& auras = me.GetAurasByType(SPELL_AURA_MOD_CHARM); + Unit::AuraList const& auras = me->GetAurasByType(SPELL_AURA_MOD_CHARM); for(Unit::AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->IsPermanent()) { - charmer->Kill(&me); + charmer->Kill(me); return; } } if(!charmer->isInCombat()) - me.GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - Unit *target = me.getVictim(); + Unit *target = me->getVictim(); if(!target || !charmer->canAttack(target)) { target = charmer->SelectNearestTarget(); if(!target) return; - me.GetMotionMaster()->MoveChase(target); - me.Attack(target, true); + me->GetMotionMaster()->MoveChase(target); + me->Attack(target, true); } } diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index b5fda95ef85..72e911cceaf 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -72,21 +72,25 @@ enum SelectAggroTarget class TRINITY_DLL_SPEC UnitAI { public: + UnitAI(Unit *u) : me(u) {} virtual void UpdateAI(const uint32 diff) = 0; + protected: + Unit *me; }; -class TRINITY_DLL_SPEC SimpleCharmedAI +class TRINITY_DLL_SPEC SimpleCharmedAI : public UnitAI { public: - SimpleCharmedAI(Unit &u); virtual void UpdateAI(const uint32 diff); - private: - Unit &me; }; class TRINITY_DLL_SPEC CreatureAI : public UnitAI { + protected: + Creature *me; public: + CreatureAI() : UnitAI(NULL), me(NULL) {} + CreatureAI(Creature *c) : UnitAI((Unit*)c), me(c) {} virtual ~CreatureAI(); @@ -97,10 +101,10 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI virtual void AttackStart(Unit *) = 0; // Called at stopping attack by any attacker - virtual void EnterEvadeMode() = 0; + virtual void EnterEvadeMode(); // Called at any Damage from any attacker (before damage apply) - virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) { AttackedBy(done_by); } + virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) {} // Is unit visible for MoveInLineOfSight virtual bool IsVisible(Unit *) const = 0; @@ -128,9 +132,6 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI // Called when vitim entered water and creature can not enter water virtual bool canReachByRangeAttack(Unit*) { return false; } - // Called when the creature is attacked - virtual void AttackedBy(Unit * /*attacker*/) {} - // Called when creature is spawned or respawned (for reseting variables) virtual void JustRespawned() {} diff --git a/src/game/CreatureAIImpl.h b/src/game/CreatureAIImpl.h index 76ba93a3cb5..2122adeb61c 100644 --- a/src/game/CreatureAIImpl.h +++ b/src/game/CreatureAIImpl.h @@ -27,6 +27,6 @@ inline CreatureAI* CreatureAIFactory<REAL_AI>::Create(void *data) const { Creature* creature = reinterpret_cast<Creature *>(data); - return (new REAL_AI(*creature)); + return (new REAL_AI(creature)); } #endif diff --git a/src/game/CreatureAIRegistry.cpp b/src/game/CreatureAIRegistry.cpp index a4ee030c34e..12b4aa97d0d 100644 --- a/src/game/CreatureAIRegistry.cpp +++ b/src/game/CreatureAIRegistry.cpp @@ -41,6 +41,8 @@ namespace AIRegistry (new CreatureAIFactory<NullCreatureAI>("NullCreatureAI"))->RegisterSelf(); (new CreatureAIFactory<AggressorAI>("AggressorAI"))->RegisterSelf(); (new CreatureAIFactory<ReactorAI>("ReactorAI"))->RegisterSelf(); + (new CreatureAIFactory<PassiveAI>("PassiveAI"))->RegisterSelf(); + (new CreatureAIFactory<CritterAI>("CritterAI"))->RegisterSelf(); (new CreatureAIFactory<GuardAI>("GuardAI"))->RegisterSelf(); (new CreatureAIFactory<PetAI>("PetAI"))->RegisterSelf(); (new CreatureAIFactory<TotemAI>("TotemAI"))->RegisterSelf(); diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp index 9927ff34df3..9e53fe0f641 100644 --- a/src/game/CreatureAISelector.cpp +++ b/src/game/CreatureAISelector.cpp @@ -65,6 +65,8 @@ namespace FactorySelector ai_factory = ai_registry.GetRegistryItem("TotemAI"); else if(creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER) ai_factory = ai_registry.GetRegistryItem("NullCreatureAI"); + else if(creature->GetCreatureType() == CREATURE_TYPE_CRITTER) + ai_factory = ai_registry.GetRegistryItem("CritterAI"); } // select by permit check @@ -91,7 +93,7 @@ namespace FactorySelector ainame = (ai_factory == NULL) ? "NullCreatureAI" : ai_factory->key(); DEBUG_LOG("Creature %u used AI is %s.", creature->GetGUIDLow(), ainame.c_str() ); - return ( ai_factory == NULL ? new NullCreatureAI : ai_factory->Create(creature) ); + return ( ai_factory == NULL ? new NullCreatureAI(creature) : ai_factory->Create(creature) ); } MovementGenerator* selectMovementGenerator(Creature *creature) diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp index 806b4a1a112..e5a7ce87092 100644 --- a/src/game/GuardAI.cpp +++ b/src/game/GuardAI.cpp @@ -33,7 +33,7 @@ int GuardAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -GuardAI::GuardAI(Creature &c) : i_creature(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) +GuardAI::GuardAI(Creature *c) : i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) { } diff --git a/src/game/GuardAI.h b/src/game/GuardAI.h index 07a638ea17a..16e0c6e8bd6 100644 --- a/src/game/GuardAI.h +++ b/src/game/GuardAI.h @@ -36,7 +36,7 @@ class TRINITY_DLL_DECL GuardAI : public CreatureAI public: - GuardAI(Creature &c); + GuardAI(Creature *c); void MoveInLineOfSight(Unit *); void AttackStart(Unit *); 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/NullCreatureAI.cpp b/src/game/NullCreatureAI.cpp index 4c1cb592967..164aa2f7974 100644 --- a/src/game/NullCreatureAI.cpp +++ b/src/game/NullCreatureAI.cpp @@ -19,7 +19,23 @@ */ #include "NullCreatureAI.h" +#include "Creature.h" -NullCreatureAI::~NullCreatureAI() +void PassiveAI::UpdateAI(const uint32) { + if(me->isInCombat() && me->getAttackers().empty()) + EnterEvadeMode(); +} + +void CritterAI::DamageTaken(Unit *done_by, uint32 &) +{ + if(!me->hasUnitState(UNIT_STAT_FLEEING)) + me->SetControlled(true, UNIT_STAT_FLEEING); +} + +void CritterAI::EnterEvadeMode() +{ + if(me->hasUnitState(UNIT_STAT_FLEEING)) + me->SetControlled(false, UNIT_STAT_FLEEING); + CreatureAI::EnterEvadeMode(); } diff --git a/src/game/NullCreatureAI.h b/src/game/NullCreatureAI.h index 3a93805fae2..821b42f7e76 100644 --- a/src/game/NullCreatureAI.h +++ b/src/game/NullCreatureAI.h @@ -23,22 +23,36 @@ #include "CreatureAI.h" -class TRINITY_DLL_DECL NullCreatureAI : public CreatureAI +class TRINITY_DLL_DECL PassiveAI : public CreatureAI { public: - - NullCreatureAI(Creature &) {} - NullCreatureAI() {} - - ~NullCreatureAI(); + PassiveAI(Creature *c) : CreatureAI(c) {} + ~PassiveAI() {} void MoveInLineOfSight(Unit *) {} void AttackStart(Unit *) {} - void EnterEvadeMode() {} bool IsVisible(Unit *) const { return false; } - void UpdateAI(const uint32) {} + void UpdateAI(const uint32); static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; } }; + +class TRINITY_DLL_DECL NullCreatureAI : public PassiveAI +{ + public: + NullCreatureAI(Creature *c) : PassiveAI(c) {} + + void EnterEvadeMode() {} +}; + +class TRINITY_DLL_DECL CritterAI : public PassiveAI +{ + public: + CritterAI(Creature *c) : PassiveAI(c) {} + + void DamageTaken(Unit *done_by, uint32 & /*damage*/); + void EnterEvadeMode(); +}; + #endif diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 5c46ba93a5a..caaadd1851f 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1187,6 +1187,14 @@ float WorldObject::GetDistance(const float x, const float y, const float z) cons return ( dist > 0 ? dist : 0); } +float WorldObject::GetDistanceSq(const float &x, const float &y, const float &z) const +{ + float dx = GetPositionX() - x; + float dy = GetPositionY() - y; + float dz = GetPositionZ() - z; + return dx*dx + dy*dy + dz*dz; +} + float WorldObject::GetDistance2d(const WorldObject* obj) const { float dx = GetPositionX() - obj->GetPositionX(); diff --git a/src/game/Object.h b/src/game/Object.h index 7db10b1d78d..0399f7313be 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -437,6 +437,7 @@ class TRINITY_DLL_SPEC WorldObject : public Object float GetDistance( const WorldObject* obj ) const; float GetDistance(const float x, const float y, const float z) const; + float GetDistanceSq(const float &x, const float &y, const float &z) const; float GetDistance2d(const WorldObject* obj) const; float GetDistance2d(const float x, const float y) const; float GetDistanceZ(const WorldObject* obj) const; 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/OutdoorPvPObjectiveAI.cpp b/src/game/OutdoorPvPObjectiveAI.cpp index e27c583eb25..a99afbfbe5a 100644 --- a/src/game/OutdoorPvPObjectiveAI.cpp +++ b/src/game/OutdoorPvPObjectiveAI.cpp @@ -25,10 +25,10 @@ #define MAX_OUTDOOR_PVP_DISTANCE 200 // the max value in capture point type go data0 is 100 currently, so use twice that much to handle leaving as well -OutdoorPvPObjectiveAI::OutdoorPvPObjectiveAI(Creature &c) : i_creature(c) +OutdoorPvPObjectiveAI::OutdoorPvPObjectiveAI(Creature *c) : i_creature(*c) { - sLog.outDebug("OutdoorPvP objective AI assigned to creature guid %u", c.GetGUIDLow()); - c.SetReactState(REACT_AGGRESSIVE); + sLog.outDebug("OutdoorPvP objective AI assigned to creature guid %u", i_creature.GetGUIDLow()); + i_creature.SetReactState(REACT_AGGRESSIVE); } void OutdoorPvPObjectiveAI::MoveInLineOfSight(Unit *u) diff --git a/src/game/OutdoorPvPObjectiveAI.h b/src/game/OutdoorPvPObjectiveAI.h index 19302a31305..2da9086dbd3 100644 --- a/src/game/OutdoorPvPObjectiveAI.h +++ b/src/game/OutdoorPvPObjectiveAI.h @@ -27,7 +27,7 @@ class TRINITY_DLL_DECL OutdoorPvPObjectiveAI : public CreatureAI { public: - OutdoorPvPObjectiveAI(Creature &c); + OutdoorPvPObjectiveAI(Creature *c); void MoveInLineOfSight(Unit *); bool IsVisible(Unit *) const; diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 1d4fbfba8e2..0a93bea158d 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -38,7 +38,7 @@ int PetAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -PetAI::PetAI(Creature &c) : i_pet(c), i_tracker(TIME_INTERVAL_LOOK), inCombat(false) +PetAI::PetAI(Creature *c) : i_pet(*c), i_tracker(TIME_INTERVAL_LOOK), inCombat(false) { m_AllySet.clear(); UpdateAllies(); @@ -339,10 +339,10 @@ void PetAI::UpdateAllies() m_AllySet.insert(owner->GetGUID()); } -void PetAI::AttackedBy(Unit *attacker) +/*void PetAI::AttackedBy(Unit *attacker) { //when attacked, fight back in case 1)no victim already AND 2)not set to passive AND 3)not set to stay, unless can it can reach attacker with melee attack anyway if(!i_pet.getVictim() && i_pet.GetCharmInfo() && !i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) && (!i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY) || i_pet.IsWithinMeleeRange(attacker))) AttackStart(attacker); -} +}*/ diff --git a/src/game/PetAI.h b/src/game/PetAI.h index 33118dabdcb..8583404b669 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -31,13 +31,11 @@ class TRINITY_DLL_DECL PetAI : public CreatureAI { public: - PetAI(Creature &c); + PetAI(Creature *c); void MoveInLineOfSight(Unit *); void AttackStart(Unit *); void EnterEvadeMode(); - void DamageTaken(Unit *done_by, uint32& /*damage*/) { AttackedBy(done_by); } - void AttackedBy(Unit*); bool IsVisible(Unit *) const; void JustDied(Unit* who) { _stopAttack(); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 8e7c4762270..7bf2deff3e8 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -19453,20 +19453,24 @@ void Player::UpdateZoneDependentAuras( uint32 newZone ) } // Some spells applied at enter into zone (with subzones) - // Human Illusion - // NOTE: these are removed by RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP); - if ( newZone == 2367 ) // Old Hillsbrad Foothills - { - uint32 spellid = 0; - // all horde races - if( GetTeam() == HORDE ) - spellid = getGender() == GENDER_FEMALE ? 35481 : 35480; - // and some alliance races - else if( getRace() == RACE_NIGHTELF || getRace() == RACE_DRAENEI ) - spellid = getGender() == GENDER_FEMALE ? 35483 : 35482; - - if(spellid && !HasAura(spellid,0) ) - CastSpell(this,spellid,true); + switch(newZone) + { + case 2367: // Old Hillsbrad Foothills + { + // Human Illusion + // NOTE: these are removed by RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP); + uint32 spellid = 0; + // all horde races + if( GetTeam() == HORDE ) + spellid = getGender() == GENDER_FEMALE ? 35481 : 35480; + // and some alliance races + else if( getRace() == RACE_NIGHTELF || getRace() == RACE_DRAENEI ) + spellid = getGender() == GENDER_FEMALE ? 35483 : 35482; + + if(spellid && !HasAura(spellid,0) ) + CastSpell(this,spellid,true); + break; + } } } @@ -20185,11 +20189,11 @@ bool Player::IsAllowUseFlyMountsHere() const { case 0: case 1: - if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_AZEROTH)) + //if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_AZEROTH)) return false; break; case 530: - if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_OUTLAND)) + //if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_OUTLAND)) return false; break; case 571: @@ -20197,7 +20201,7 @@ bool Player::IsAllowUseFlyMountsHere() const return false; break; default: - if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_OTHERS)) + //if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_OTHERS)) return false; break; } diff --git a/src/game/PossessedAI.h b/src/game/PossessedAI.h index c33da2c3595..16c3172b6bf 100644 --- a/src/game/PossessedAI.h +++ b/src/game/PossessedAI.h @@ -28,7 +28,7 @@ class Creature; class TRINITY_DLL_DECL PossessedAI : public CreatureAI { public: - PossessedAI(Creature &c) : i_pet(c), i_victimGuid(0) {} + PossessedAI(Creature *c) : i_pet(*c), i_victimGuid(0) {} // Possessed creatures shouldn't aggro by themselves void MoveInLineOfSight(Unit *) {} @@ -36,7 +36,6 @@ class TRINITY_DLL_DECL PossessedAI : public CreatureAI void EnterEvadeMode() {} void JustDied(Unit*); void KilledUnit(Unit* victim); - void AttackedBy(Unit*) {} bool IsVisible(Unit * u) const { return _isVisible(u); } void UpdateAI(const uint32); diff --git a/src/game/ReactorAI.h b/src/game/ReactorAI.h index c71c48d0985..b2bfa3501c2 100644 --- a/src/game/ReactorAI.h +++ b/src/game/ReactorAI.h @@ -29,7 +29,7 @@ class TRINITY_DLL_DECL ReactorAI : public CreatureAI { public: - ReactorAI(Creature &c) : i_creature(c), i_victimGuid(0) {} + ReactorAI(Creature *c) : i_creature(*c), i_victimGuid(0) {} void MoveInLineOfSight(Unit *); void AttackStart(Unit *); 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..852c7943612 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++) { @@ -1323,7 +1323,7 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const uint32 &type, SpellTargets TargetType, uint32 entry) { - float x, y; + float x, y, z; if(type == PUSH_DEST_CENTER) { if(!m_targets.HasDest()) @@ -1333,11 +1333,7 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const u } x = m_targets.m_destX; y = m_targets.m_destY; - } - else if(type == PUSH_SELF_CENTER) - { - x = m_caster->GetPositionX(); - y = m_caster->GetPositionY(); + z = m_targets.m_destZ; } else if(type == PUSH_TARGET_CENTER) { @@ -1349,9 +1345,16 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const u } x = target->GetPositionX(); y = target->GetPositionY(); + z = target->GetPositionZ(); + } + else + { + x = m_caster->GetPositionX(); + y = m_caster->GetPositionY(); + z = m_caster->GetPositionZ(); } - Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, type, TargetType, entry); + Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, type, TargetType, entry, x, y, z); if((m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY) || TargetType == SPELL_TARGETS_ENTRY && !entry) m_caster->GetMap()->VisitWorld(x, y, radius, notifier); @@ -4469,15 +4472,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/Spell.h b/src/game/Spell.h index 2aa6051a654..c5e3841c0f1 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -106,7 +106,6 @@ enum SpellNotifyPushType PUSH_IN_FRONT, PUSH_IN_BACK, PUSH_IN_LINE, - PUSH_SELF_CENTER, PUSH_DEST_CENTER, PUSH_TARGET_CENTER, }; @@ -621,14 +620,16 @@ namespace Trinity std::list<Unit*> *i_data; Spell &i_spell; const uint32& i_push_type; - float i_radius; + float i_radius, i_radiusSq; SpellTargets i_TargetType; Unit* i_caster; uint32 i_entry; + float i_x, i_y, i_z; SpellNotifierCreatureAndPlayer(Spell &spell, std::list<Unit*> &data, float radius, const uint32 &type, - SpellTargets TargetType = SPELL_TARGETS_ENEMY, uint32 entry = 0) - : i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType), i_entry(entry) + SpellTargets TargetType = SPELL_TARGETS_ENEMY, uint32 entry = 0, float x = 0, float y = 0, float z = 0) + : i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_radiusSq(radius*radius) + , i_TargetType(TargetType), i_entry(entry), i_x(x), i_y(y), i_z(z) { i_caster = spell.GetCaster(); } @@ -693,12 +694,8 @@ namespace Trinity if(i_caster->isInLine((Unit*)(itr->getSource()), i_radius )) i_data->push_back(itr->getSource()); break; - case PUSH_SELF_CENTER: - if(i_caster->IsWithinDistInMap((Unit*)(itr->getSource()), i_radius)) - i_data->push_back(itr->getSource()); - break; - case PUSH_DEST_CENTER: - if((itr->getSource()->GetDistance(i_spell.m_targets.m_destX, i_spell.m_targets.m_destY, i_spell.m_targets.m_destZ) < i_radius )) + default: + if((itr->getSource()->GetDistanceSq(i_x, i_y, i_z) < i_radiusSq)) i_data->push_back(itr->getSource()); break; } diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index eb23306b5b1..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, @@ -305,7 +305,7 @@ enum AuraType SPELL_AURA_258 = 258, SPELL_AURA_259 = 259, SPELL_AURA_SCREEN_EFFECT = 260, - SPELL_AURA_261 = 261, + SPELL_AURA_PHASE = 261, SPELL_AURA_262 = 262, SPELL_AURA_ALLOW_ONLY_ABILITY = 263, SPELL_AURA_264 = 264, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 8af4f59124f..fdb8fe316f5 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 @@ -315,9 +315,9 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL &Aura::HandleNULL, //259 corrupt healing over time spell &Aura::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code - &Aura::HandleNULL, //261 out of phase? + &Aura::HandlePhase, //261 SPELL_AURA_PHASE undetactable invisibility? implemented in Unit::isVisibleForOrDetect &Aura::HandleNULL, //262 - &Aura::HandleNULL, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilites set in SpellClassMask + &Aura::HandleNULL, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask &Aura::HandleNULL, //264 unused &Aura::HandleNULL, //265 unused &Aura::HandleNULL, //266 unused @@ -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) { @@ -5520,15 +5512,13 @@ void Aura::PeriodicTick() } } else - pdamage = uint32(m_target->GetMaxHealth()*amount/100); + pdamage = uint32(m_target->GetMaxHealth()*pdamage/100); //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); 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()); @@ -6547,3 +6529,24 @@ void Aura::HandleModCharm(bool apply, bool Real) else m_target->RemoveCharmedOrPossessedBy(caster); } + +void Aura::HandlePhase(bool apply, bool Real) +{ + // no-phase is also phase state so same code for apply and remove + + // phase auras normaly not expected at BG but anyway better check + if(Real && m_target->GetTypeId()==TYPEID_PLAYER) + { + // drop flag at invisible in bg + if(((Player*)m_target)->InBattleGround()) + if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) + bg->EventPlayerDroppedFlag((Player*)m_target); + } + + // apply/remove only if not in GM invisibility + if(m_target->GetVisibility()!=VISIBILITY_OFF) + { + // just need triggering visibility update base at aura presence + m_target->SetVisibility(m_target->GetVisibility()); + } +} diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 4cbb531ea6d..3822d2abf86 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -211,6 +211,7 @@ class TRINITY_DLL_SPEC Aura void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real); void HandleNoReagentUseAura(bool Apply, bool Real); void HandleModAttackerSpellHitChance(bool apply, bool Real); + void HandlePhase(bool Apply, bool Real); virtual ~Aura(); @@ -273,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 0e7fe1380f0..3172a47ca38 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -503,6 +503,7 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex) case 37675: // Chaos Blast case 41519: // Mark of Stormrage case 34877: // Custodian of Time + case 34700: return false; } @@ -1041,7 +1042,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 +1086,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 @@ -2587,6 +2632,10 @@ uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,u case 51721: // Dominion Over Acherus case 54055: // Dominion Over Acherus return area_id == 4281 || area_id == 4342 ? 0 : SPELL_FAILED_INCORRECT_AREA; + case 51852: // The Eye of Acherus + { + return map_id == 609 ? 0 : SPELL_FAILED_REQUIRES_AREA; + } case 54119: // Mist of the Kvaldir return area_id == 4028 || area_id == 4029 || area_id == 4106 || area_id == 4031 ? 0 : SPELL_FAILED_INCORRECT_AREA; } 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/TotemAI.cpp b/src/game/TotemAI.cpp index 7b99a8f0358..72a43cfc97b 100644 --- a/src/game/TotemAI.cpp +++ b/src/game/TotemAI.cpp @@ -40,7 +40,7 @@ TotemAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -TotemAI::TotemAI(Creature &c) : i_totem(static_cast<Totem&>(c)), i_victimGuid(0) +TotemAI::TotemAI(Creature *c) : i_totem(static_cast<Totem&>(*c)), i_victimGuid(0) { } diff --git a/src/game/TotemAI.h b/src/game/TotemAI.h index 1b4f96e6067..8ce40e60c81 100644 --- a/src/game/TotemAI.h +++ b/src/game/TotemAI.h @@ -31,7 +31,7 @@ class TRINITY_DLL_DECL TotemAI : public CreatureAI { public: - TotemAI(Creature &c); + TotemAI(Creature *c); void MoveInLineOfSight(Unit *); void AttackStart(Unit *); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 7b5b9f09511..f47eb78bbf7 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -580,9 +580,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa // no xp,health if type 8 /critters/ if ( pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER) { - // critters run away when hit - pVictim->GetMotionMaster()->MoveFleeing(this); - // allow loot only if has loot_id in creature_template if(damage >= pVictim->GetHealth()) { @@ -841,13 +838,13 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if(damagetype != DOT) { - if(getVictim()) - { + if(!getVictim()) + /*{ // if have target and damage pVictim just call AI reaction if(pVictim != getVictim() && pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI()) ((Creature*)pVictim)->AI()->AttackedBy(this); } - else + else*/ { // if not have main target then attack state with target (including AI call) //start melee attacks only after melee hit @@ -1755,6 +1752,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 +1810,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 +1883,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 +1977,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 +4673,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 +5977,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 +6534,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; @@ -7282,8 +7285,8 @@ bool Unit::Attack(Unit *victim, bool meleeAttack) m_attacking = victim; m_attacking->_addAttacker(this); - if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->AI()) - ((Creature*)m_attacking)->AI()->AttackedBy(this); + //if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->AI()) + // ((Creature*)m_attacking)->AI()->AttackedBy(this); if(GetTypeId()==TYPEID_UNIT) { @@ -7402,51 +7405,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 +7555,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 +7570,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 +7758,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 +7949,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 +8312,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 +8332,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 +8425,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 +8480,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 +8573,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 +8823,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 @@ -9777,6 +9741,10 @@ Unit* Creature::SelectHostilTarget() //next-victim-selection algorithm and evade mode are called //threat list sorting etc. + //This should not be called by unit who does not have a threatlist + //or who does not have threat (totem/pet/critter) + //otherwise enterevademode every update + if (!this->isAlive()) return false; @@ -9841,7 +9809,7 @@ Unit* Creature::SelectHostilTarget() for(AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr) { if( (*itr)->IsInMap(this) && canAttack(*itr) && (*itr)->isInAccessiblePlaceFor((Creature*)this) ) - return false; + return NULL; } }*/ @@ -10754,7 +10722,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 +10966,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; @@ -12133,6 +12101,8 @@ void Unit::SetFeared(bool apply) Unit::AuraList const& fearAuras = GetAurasByType(SPELL_AURA_MOD_FEAR); if(!fearAuras.empty()) caster = ObjectAccessor::GetUnit(*this, fearAuras.front()->GetCasterGUID()); + if(!caster) + caster = getAttackerForHelper(); GetMotionMaster()->MoveFleeing(caster); // caster==NULL processed in MoveFleeing } else 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.h b/src/shared/revision.h index 1d590b1e7c0..e60dcfdb657 100644 --- a/src/shared/revision.h +++ b/src/shared/revision.h @@ -1,7 +1,7 @@ #ifndef __REVISION_H__ #define __REVISION_H__ - #define _REVISION "1091" - #define _HASH "88c4b2b6b9a2" + #define _REVISION "1116" + #define _HASH "81edc7393bc6" #define _REVISION_DATE "*" #define _REVISION_TIME "*" #endif // __REVISION_H__ diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index f2e3c0e71e0..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 "7194" + #define REVISION_NR "7200" #endif // __REVISION_NR_H__ |
