[10465] Implement SPELL_EFFECT_REDIRECT_THREAT

Note: all spells with effect expect additional code for redirection reset.
Until code adding redirection work longer that expected.

Signed-off-by: VladimirMangos <vladimir@getmangos.com>

Patch partly rewrited with move new data into HostileRefManager
and added redirection to threatAssist. Also bug fixed with
redirection threat to unit not in hostile list yet.
This commit is contained in:
ascent 2010-09-11 00:03:27 +04:00 committed by VladimirMangos
parent f441216aa0
commit 88cc2d440f
7 changed files with 85 additions and 9 deletions

View file

@ -21,6 +21,12 @@
#include "Unit.h" #include "Unit.h"
#include "DBCStructure.h" #include "DBCStructure.h"
#include "SpellMgr.h" #include "SpellMgr.h"
#include "Map.h"
HostileRefManager::HostileRefManager( Unit *pOwner ) : iOwner(pOwner), m_redirectionMod(0.0f)
{
}
HostileRefManager::~HostileRefManager() HostileRefManager::~HostileRefManager()
{ {
@ -34,17 +40,34 @@ HostileRefManager::~HostileRefManager()
void HostileRefManager::threatAssist(Unit *pVictim, float pThreat, SpellEntry const *pThreatSpell, bool pSingleTarget) void HostileRefManager::threatAssist(Unit *pVictim, float pThreat, SpellEntry const *pThreatSpell, bool pSingleTarget)
{ {
HostileReference* ref; float redirectedMod = pVictim->getHostileRefManager().GetThreatRedirectionMod();
Unit* redirectedTarget = redirectedMod ? pVictim->getHostileRefManager().GetThreatRedirectionTarget() : NULL;
uint32 size = pSingleTarget ? 1 : getSize(); // if pSingleTarget do not devide threat uint32 size = pSingleTarget ? 1 : getSize(); // if pSingleTarget do not devide threat
ref = getFirst(); HostileReference* ref = getFirst();
while(ref != NULL) while(ref != NULL)
{ {
float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, false, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell); float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, false, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell);
if(pVictim == getOwner())
if (threat > 0.0f)
{
if (redirectedTarget && redirectedTarget != ref->getTarget() && redirectedTarget->isAlive())
{
float redirectedThreat = threat * redirectedMod;
threat -= redirectedThreat;
if(redirectedTarget == getOwner()) // It is faster to modify the threat durectly if possible
ref->addThreat(float (threat) / size);
else
ref->getSource()->addThreat(redirectedTarget, redirectedThreat);
}
}
if (pVictim == getOwner())
ref->addThreat(float (threat) / size); // It is faster to modify the threat durectly if possible ref->addThreat(float (threat) / size); // It is faster to modify the threat durectly if possible
else else
ref->getSource()->addThreat(pVictim, float (threat) / size); ref->getSource()->addThreat(pVictim, float (threat) / size);
ref = ref->next(); ref = ref->next();
} }
} }
@ -162,4 +185,10 @@ void HostileRefManager::setOnlineOfflineState(Unit *pCreature,bool pIsOnline)
} }
} }
Unit* HostileRefManager::GetThreatRedirectionTarget() const
{
return !m_redirectionTargetGuid.IsEmpty() ? iOwner->GetMap()->GetUnit(m_redirectionTargetGuid) : NULL;
}
//================================================= //=================================================

View file

@ -20,6 +20,7 @@
#define _HOSTILEREFMANAGER #define _HOSTILEREFMANAGER
#include "Common.h" #include "Common.h"
#include "ObjectGuid.h"
#include "Utilities/LinkedReference/RefManager.h" #include "Utilities/LinkedReference/RefManager.h"
class Unit; class Unit;
@ -31,10 +32,8 @@ struct SpellEntry;
class HostileRefManager : public RefManager<Unit, ThreatManager> class HostileRefManager : public RefManager<Unit, ThreatManager>
{ {
private:
Unit *iOwner;
public: public:
explicit HostileRefManager(Unit *pOwner) { iOwner = pOwner; } explicit HostileRefManager(Unit *pOwner);
~HostileRefManager(); ~HostileRefManager();
Unit* getOwner() { return iOwner; } Unit* getOwner() { return iOwner; }
@ -64,6 +63,22 @@ class HostileRefManager : public RefManager<Unit, ThreatManager>
// delete one reference, defined by Unit // delete one reference, defined by Unit
void deleteReference(Unit *pCreature); void deleteReference(Unit *pCreature);
// redirection threat data
void SetThreatRedirection(ObjectGuid guid, uint32 pct)
{
m_redirectionTargetGuid = guid;
m_redirectionMod = pct/100.0f;
}
float GetThreatRedirectionMod() const { return m_redirectionMod; }
Unit* GetThreatRedirectionTarget() const;
private:
Unit* iOwner; // owner of manager variable, back ref. to it, always exist
float m_redirectionMod;
ObjectGuid m_redirectionTargetGuid;
}; };
//================================================= //=================================================
#endif #endif

View file

@ -304,6 +304,7 @@ class Spell
void EffectCharge(SpellEffectIndex eff_idx); void EffectCharge(SpellEffectIndex eff_idx);
void EffectCharge2(SpellEffectIndex eff_idx); void EffectCharge2(SpellEffectIndex eff_idx);
void EffectProspecting(SpellEffectIndex eff_idx); void EffectProspecting(SpellEffectIndex eff_idx);
void EffectRedirectThreat(SpellEffectIndex eff_idx);
void EffectMilling(SpellEffectIndex eff_idx); void EffectMilling(SpellEffectIndex eff_idx);
void EffectRenamePet(SpellEffectIndex eff_idx); void EffectRenamePet(SpellEffectIndex eff_idx);
void EffectSendTaxi(SpellEffectIndex eff_idx); void EffectSendTaxi(SpellEffectIndex eff_idx);

View file

@ -190,7 +190,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell &Spell::EffectProspecting, //127 SPELL_EFFECT_PROSPECTING Prospecting spell
&Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
&Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
&Spell::EffectNULL, //130 SPELL_EFFECT_REDIRECT_THREAT &Spell::EffectRedirectThreat, //130 SPELL_EFFECT_REDIRECT_THREAT
&Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
&Spell::EffectPlayMusic, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc) &Spell::EffectPlayMusic, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
&Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
@ -8051,6 +8051,12 @@ void Spell::EffectRestoreItemCharges( SpellEffectIndex eff_idx )
item->RestoreCharges(); item->RestoreCharges();
} }
void Spell::EffectRedirectThreat(SpellEffectIndex eff_idx)
{
if (unitTarget)
m_caster->getHostileRefManager().SetThreatRedirection(unitTarget->GetObjectGuid(), uint32(damage));
}
void Spell::EffectTeachTaxiNode( SpellEffectIndex eff_idx ) void Spell::EffectTeachTaxiNode( SpellEffectIndex eff_idx )
{ {
if (unitTarget->GetTypeId() != TYPEID_PLAYER) if (unitTarget->GetTypeId() != TYPEID_PLAYER)

View file

@ -392,6 +392,27 @@ void ThreatManager::addThreat(Unit* pVictim, float pThreat, bool crit, SpellScho
float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, crit, schoolMask, pThreatSpell); float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, crit, schoolMask, pThreatSpell);
if (threat > 0.0f)
{
if (float redirectedMod = pVictim->getHostileRefManager().GetThreatRedirectionMod())
{
if (Unit* redirectedTarget = pVictim->getHostileRefManager().GetThreatRedirectionTarget())
{
if (redirectedTarget != getOwner() && redirectedTarget->isAlive())
{
float redirectedThreat = threat * redirectedMod;
threat -= redirectedThreat;
addThreatDirectly(redirectedTarget, redirectedThreat);
}
}
}
}
addThreatDirectly(pVictim, threat);
}
void ThreatManager::addThreatDirectly(Unit* pVictim, float threat)
{
HostileReference* ref = iThreatContainer.addThreat(pVictim, threat); HostileReference* ref = iThreatContainer.addThreat(pVictim, threat);
// Ref is online // Ref is online
if (ref) if (ref)

View file

@ -183,6 +183,10 @@ class MANGOS_DLL_SPEC ThreatManager
void addThreat(Unit* pVictim, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell); void addThreat(Unit* pVictim, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell);
void addThreat(Unit* pVictim, float threat) { addThreat(pVictim,threat,false,SPELL_SCHOOL_MASK_NONE,NULL); } void addThreat(Unit* pVictim, float threat) { addThreat(pVictim,threat,false,SPELL_SCHOOL_MASK_NONE,NULL); }
// add threat as raw value (ignore redirections and expection all mods applied already to it
void addThreatDirectly(Unit* pVictim, float threat);
void modifyThreatPercent(Unit *pVictim, int32 pPercent); void modifyThreatPercent(Unit *pVictim, int32 pPercent);
float getThreat(Unit *pVictim, bool pAlsoSearchOfflineList = false); float getThreat(Unit *pVictim, bool pAlsoSearchOfflineList = false);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "10464" #define REVISION_NR "10465"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__