*Merge.
--HG-- branch : trunk
This commit is contained in:
@@ -38,29 +38,10 @@ 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) : CreatureAI(c), i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AggressorAI::MoveInLineOfSight(Unit *u)
|
||||
{
|
||||
if(!i_creature.getVictim() && i_creature.canStartAttack(u))
|
||||
AttackStart(u);
|
||||
|
||||
/*
|
||||
if(!i_creature.getVictim())
|
||||
{
|
||||
AttackStart(u);
|
||||
}
|
||||
else if(sMapStore.LookupEntry(i_creature.GetMapId())->IsDungeon())
|
||||
{
|
||||
u->SetInCombatWith(&i_creature);
|
||||
i_creature.AddThreat(u, 0.0f);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void AggressorAI::EnterEvadeMode()
|
||||
{
|
||||
if( !i_creature.isAlive() )
|
||||
@@ -118,7 +99,7 @@ void
|
||||
AggressorAI::UpdateAI(const uint32 /*diff*/)
|
||||
{
|
||||
// update i_victimGuid if i_creature.getVictim() !=0 and changed
|
||||
if(!i_creature.SelectHostilTarget() || !i_creature.getVictim())
|
||||
if(!UpdateVictim())
|
||||
return;
|
||||
|
||||
i_victimGuid = i_creature.getVictim()->GetGUID();
|
||||
@@ -132,29 +113,3 @@ AggressorAI::UpdateAI(const uint32 /*diff*/)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AggressorAI::IsVisible(Unit *pl) const
|
||||
{
|
||||
return i_creature.GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER)
|
||||
&& pl->isVisibleForOrDetect(&i_creature,true);
|
||||
}
|
||||
|
||||
void
|
||||
AggressorAI::AttackStart(Unit *u)
|
||||
{
|
||||
if( !u )
|
||||
return;
|
||||
|
||||
if(i_creature.Attack(u,true))
|
||||
{
|
||||
i_creature.SetInCombatWith(u);
|
||||
u->SetInCombatWith(&i_creature);
|
||||
|
||||
i_creature.AddThreat(u, 0.0f);
|
||||
// DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", i_creature.GetName(), u->GetGUIDLow());
|
||||
i_victimGuid = u->GetGUID();
|
||||
|
||||
i_creature.GetMotionMaster()->MoveChase(u);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,7 @@ class TRINITY_DLL_DECL AggressorAI : public CreatureAI
|
||||
|
||||
AggressorAI(Creature *c);
|
||||
|
||||
void MoveInLineOfSight(Unit *);
|
||||
void AttackStart(Unit *);
|
||||
void EnterEvadeMode();
|
||||
bool IsVisible(Unit *) const;
|
||||
|
||||
void UpdateAI(const uint32);
|
||||
static int Permissible(const Creature *);
|
||||
|
||||
+1
-1
@@ -637,7 +637,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
|
||||
bool IsFormationLeader() {return (GetDBTableGUIDLow() && GetDBTableGUIDLow() == m_formationID);}
|
||||
uint32 GetFormationID(){return m_formationID;}
|
||||
|
||||
Unit *SelectHostilTarget();
|
||||
Unit *SelectVictim();
|
||||
protected:
|
||||
bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL);
|
||||
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
|
||||
|
||||
+26
-11
@@ -20,17 +20,39 @@
|
||||
|
||||
#include "CreatureAI.h"
|
||||
#include "Creature.h"
|
||||
#include "Player.h"
|
||||
#include "Pet.h"
|
||||
#include "SpellAuras.h"
|
||||
|
||||
CreatureAI::~CreatureAI()
|
||||
void UnitAI::AttackStart(Unit *victim)
|
||||
{
|
||||
if(!victim)
|
||||
return;
|
||||
|
||||
if(me->Attack(victim, true))
|
||||
{
|
||||
//DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", me->GetName(), victim->GetGUIDLow());
|
||||
me->GetMotionMaster()->MoveChase(victim);
|
||||
}
|
||||
}
|
||||
|
||||
void CreatureAI::MoveInLineOfSight(Unit *who)
|
||||
{
|
||||
if(!me->getVictim() && me->canStartAttack(who))
|
||||
AttackStart(who);
|
||||
}
|
||||
|
||||
bool CreatureAI::UpdateVictim()
|
||||
{
|
||||
if(!me->isInCombat())
|
||||
return false;
|
||||
if(Unit *victim = me->SelectVictim())
|
||||
AttackStart(victim);
|
||||
return me->getVictim();
|
||||
}
|
||||
|
||||
void CreatureAI::EnterEvadeMode()
|
||||
{
|
||||
if(!me) return;
|
||||
|
||||
me->RemoveAllAuras();
|
||||
me->DeleteThreatList();
|
||||
me->CombatStop();
|
||||
@@ -62,12 +84,5 @@ void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/)
|
||||
|
||||
Unit *target = me->getVictim();
|
||||
if(!target || !charmer->canAttack(target))
|
||||
{
|
||||
target = charmer->SelectNearestTarget();
|
||||
if(!target)
|
||||
return;
|
||||
|
||||
me->GetMotionMaster()->MoveChase(target);
|
||||
me->Attack(target, true);
|
||||
}
|
||||
AttackStart(charmer->SelectNearestTarget());
|
||||
}
|
||||
|
||||
+19
-17
@@ -29,6 +29,7 @@
|
||||
|
||||
class Unit;
|
||||
class Creature;
|
||||
class Player;
|
||||
struct SpellEntry;
|
||||
|
||||
#define TIME_INTERVAL_LOOK 5000
|
||||
@@ -71,34 +72,41 @@ enum SelectAggroTarget
|
||||
|
||||
class TRINITY_DLL_SPEC UnitAI
|
||||
{
|
||||
public:
|
||||
UnitAI(Unit *u) : me(u) {}
|
||||
virtual void UpdateAI(const uint32 diff) = 0;
|
||||
protected:
|
||||
Unit *me;
|
||||
public:
|
||||
UnitAI(Unit *u) : me(u) {}
|
||||
virtual void AttackStart(Unit *);
|
||||
virtual void UpdateAI(const uint32 diff) = 0;
|
||||
};
|
||||
|
||||
class TRINITY_DLL_SPEC SimpleCharmedAI : public UnitAI
|
||||
class TRINITY_DLL_SPEC PlayerAI : public UnitAI
|
||||
{
|
||||
protected:
|
||||
Player *me;
|
||||
public:
|
||||
PlayerAI(Player *p) : UnitAI((Unit*)p), me(p) {}
|
||||
};
|
||||
|
||||
class TRINITY_DLL_SPEC SimpleCharmedAI : public PlayerAI
|
||||
{
|
||||
public:
|
||||
virtual void UpdateAI(const uint32 diff);
|
||||
void UpdateAI(const uint32 diff);
|
||||
};
|
||||
|
||||
class TRINITY_DLL_SPEC CreatureAI : public UnitAI
|
||||
{
|
||||
protected:
|
||||
Creature *me;
|
||||
|
||||
bool UpdateVictim();
|
||||
public:
|
||||
CreatureAI() : UnitAI(NULL), me(NULL) {}
|
||||
CreatureAI(Creature *c) : UnitAI((Unit*)c), me(c) {}
|
||||
|
||||
virtual ~CreatureAI();
|
||||
virtual ~CreatureAI() {}
|
||||
|
||||
// Called if IsVisible(Unit *who) is true at each *who move
|
||||
virtual void MoveInLineOfSight(Unit *) = 0;
|
||||
|
||||
// Called at each attack of m_creature by any victim
|
||||
virtual void AttackStart(Unit *) = 0;
|
||||
virtual void MoveInLineOfSight(Unit *);
|
||||
|
||||
// Called at stopping attack by any attacker
|
||||
virtual void EnterEvadeMode();
|
||||
@@ -106,12 +114,6 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI
|
||||
// Called at any Damage from any attacker (before damage apply)
|
||||
virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) {}
|
||||
|
||||
// Is unit visible for MoveInLineOfSight
|
||||
virtual bool IsVisible(Unit *) const = 0;
|
||||
|
||||
// Called at World update tick
|
||||
virtual void UpdateAI(const uint32 diff ) = 0;
|
||||
|
||||
// Called when the creature is killed
|
||||
virtual void JustDied(Unit *) {}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ DestinationHolder<TRAVELLER>::StartTravel(TRAVELLER &traveller, bool sendMove)
|
||||
|
||||
float speed;
|
||||
if(traveller.GetTraveller().hasUnitState(UNIT_STAT_CHARGING))
|
||||
speed = 0.025f; // assume it is 25 yard per second
|
||||
speed = SPEED_CHARGE * 0.001f;
|
||||
else
|
||||
speed = traveller.Speed() * 0.001f; // speed is in seconds so convert from second to millisecond
|
||||
i_totalTravelTime = static_cast<uint32>(dist/speed);
|
||||
|
||||
+2
-19
@@ -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) : CreatureAI(c), i_creature(*c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ void GuardAI::EnterEvadeMode()
|
||||
void GuardAI::UpdateAI(const uint32 /*diff*/)
|
||||
{
|
||||
// update i_victimGuid if i_creature.getVictim() !=0 and changed
|
||||
if(!i_creature.SelectHostilTarget() || !i_creature.getVictim())
|
||||
if(!UpdateVictim())
|
||||
return;
|
||||
|
||||
i_victimGuid = i_creature.getVictim()->GetGUID();
|
||||
@@ -131,23 +131,6 @@ bool GuardAI::IsVisible(Unit *pl) const
|
||||
&& pl->isVisibleForOrDetect(&i_creature,true);
|
||||
}
|
||||
|
||||
void GuardAI::AttackStart(Unit *u)
|
||||
{
|
||||
if( !u )
|
||||
return;
|
||||
|
||||
// DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", i_creature.GetName(), u->GetGUIDLow());
|
||||
if(i_creature.Attack(u,true))
|
||||
{
|
||||
i_creature.SetInCombatWith(u);
|
||||
u->SetInCombatWith(&i_creature);
|
||||
|
||||
i_creature.AddThreat(u, 0.0f);
|
||||
i_victimGuid = u->GetGUID();
|
||||
i_creature.GetMotionMaster()->MoveChase(u);
|
||||
}
|
||||
}
|
||||
|
||||
void GuardAI::JustDied(Unit *killer)
|
||||
{
|
||||
if(Player* pkiller = killer->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
|
||||
@@ -39,7 +39,6 @@ class TRINITY_DLL_DECL GuardAI : public CreatureAI
|
||||
GuardAI(Creature *c);
|
||||
|
||||
void MoveInLineOfSight(Unit *);
|
||||
void AttackStart(Unit *);
|
||||
void EnterEvadeMode();
|
||||
void JustDied(Unit *);
|
||||
bool IsVisible(Unit *) const;
|
||||
|
||||
@@ -32,8 +32,6 @@ class TRINITY_DLL_DECL PassiveAI : public CreatureAI
|
||||
void MoveInLineOfSight(Unit *) {}
|
||||
void AttackStart(Unit *) {}
|
||||
|
||||
bool IsVisible(Unit *) const { return false; }
|
||||
|
||||
void UpdateAI(const uint32);
|
||||
static int Permissible(const Creature *) { return PERMIT_BASE_IDLE; }
|
||||
};
|
||||
@@ -43,6 +41,7 @@ class TRINITY_DLL_DECL NullCreatureAI : public PassiveAI
|
||||
public:
|
||||
NullCreatureAI(Creature *c) : PassiveAI(c) {}
|
||||
|
||||
void UpdateAI(const uint32) {}
|
||||
void EnterEvadeMode() {}
|
||||
};
|
||||
|
||||
|
||||
@@ -25,18 +25,18 @@
|
||||
|
||||
#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) : NullCreatureAI(c)
|
||||
{
|
||||
sLog.outDebug("OutdoorPvP objective AI assigned to creature guid %u", i_creature.GetGUIDLow());
|
||||
i_creature.SetReactState(REACT_AGGRESSIVE);
|
||||
sLog.outDebug("OutdoorPvP objective AI assigned to creature guid %u", me->GetGUIDLow());
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
void OutdoorPvPObjectiveAI::MoveInLineOfSight(Unit *u)
|
||||
{
|
||||
// IsVisible only passes for players in range, so no need to check again
|
||||
// leaving/entering distance will be checked based on go range data
|
||||
if((u->GetTypeId() == TYPEID_PLAYER) && i_creature.IsWithinDistInMap(u, MAX_OUTDOOR_PVP_DISTANCE))
|
||||
sOutdoorPvPMgr.HandleCaptureCreaturePlayerMoveInLos(((Player*)u),&i_creature);
|
||||
if((u->GetTypeId() == TYPEID_PLAYER) && me->IsWithinDistInMap(u, MAX_OUTDOOR_PVP_DISTANCE))
|
||||
sOutdoorPvPMgr.HandleCaptureCreaturePlayerMoveInLos(((Player*)u), me);
|
||||
}
|
||||
|
||||
int OutdoorPvPObjectiveAI::Permissible(const Creature * c)
|
||||
@@ -45,22 +45,3 @@ int OutdoorPvPObjectiveAI::Permissible(const Creature * c)
|
||||
return PERMIT_BASE_NO;
|
||||
}
|
||||
|
||||
bool OutdoorPvPObjectiveAI::IsVisible(Unit *pl) const
|
||||
{
|
||||
return (pl->GetTypeId() == TYPEID_PLAYER) && (i_creature.GetDistance(pl) < MAX_OUTDOOR_PVP_DISTANCE);
|
||||
}
|
||||
|
||||
void OutdoorPvPObjectiveAI::AttackStart(Unit *)
|
||||
{
|
||||
//EnterEvadeMode();
|
||||
}
|
||||
|
||||
void OutdoorPvPObjectiveAI::EnterEvadeMode()
|
||||
{
|
||||
// i_creature.DeleteThreatList();
|
||||
// i_creature.CombatStop();
|
||||
}
|
||||
|
||||
void OutdoorPvPObjectiveAI::UpdateAI(const uint32 diff)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -19,25 +19,17 @@
|
||||
#ifndef TRINITY_OUTDOORPVPOBJECTIVEAI_H
|
||||
#define TRINITY_OUTDOORPVPOBJECTIVEAI_H
|
||||
|
||||
#include "CreatureAI.h"
|
||||
#include "NullCreatureAI.h"
|
||||
|
||||
class Creature;
|
||||
|
||||
class TRINITY_DLL_DECL OutdoorPvPObjectiveAI : public CreatureAI
|
||||
class TRINITY_DLL_DECL OutdoorPvPObjectiveAI : public NullCreatureAI
|
||||
{
|
||||
public:
|
||||
|
||||
OutdoorPvPObjectiveAI(Creature *c);
|
||||
|
||||
void MoveInLineOfSight(Unit *);
|
||||
bool IsVisible(Unit *) const;
|
||||
void AttackStart(Unit *);
|
||||
void EnterEvadeMode();
|
||||
void UpdateAI(const uint32 diff);
|
||||
|
||||
static int Permissible(const Creature *);
|
||||
|
||||
private:
|
||||
Creature &i_creature;
|
||||
};
|
||||
#endif
|
||||
|
||||
+1
-15
@@ -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) : CreatureAI(c), i_pet(*c), i_tracker(TIME_INTERVAL_LOOK), inCombat(false)
|
||||
{
|
||||
m_AllySet.clear();
|
||||
UpdateAllies();
|
||||
@@ -73,8 +73,6 @@ void PetAI::AttackStart(Unit *u)
|
||||
|
||||
if(i_pet.Attack(u,true))
|
||||
{
|
||||
i_pet.SetInCombatWith(u);
|
||||
|
||||
i_pet.clearUnitState(UNIT_STAT_FOLLOW);
|
||||
// TMGs call CreatureRelocation which via MoveInLineOfSight can call this function
|
||||
// thus with the following clear the original TMG gets invalidated and crash, doh
|
||||
@@ -89,11 +87,6 @@ void PetAI::EnterEvadeMode()
|
||||
{
|
||||
}
|
||||
|
||||
bool PetAI::IsVisible(Unit *pl) const
|
||||
{
|
||||
return _isVisible(pl);
|
||||
}
|
||||
|
||||
bool PetAI::_needToStop() const
|
||||
{
|
||||
// This is needed for charmed creatures, as once their target was reset other effects can trigger threat
|
||||
@@ -293,13 +286,6 @@ void PetAI::UpdateAI(const uint32 diff)
|
||||
}
|
||||
}
|
||||
|
||||
bool PetAI::_isVisible(Unit *u) const
|
||||
{
|
||||
//return false; //( ((Creature*)&i_pet)->GetDistanceSq(u) * 1.0<= sWorld.getConfig(CONFIG_SIGHT_GUARDER) && !u->m_stealth && u->isAlive());
|
||||
return i_pet.GetDistance(u) < sWorld.getConfig(CONFIG_SIGHT_GUARDER)
|
||||
&& u->isVisibleForOrDetect(&i_pet,true);
|
||||
}
|
||||
|
||||
void PetAI::UpdateAllies()
|
||||
{
|
||||
Unit* owner = i_pet.GetCharmerOrOwner();
|
||||
|
||||
@@ -36,7 +36,6 @@ class TRINITY_DLL_DECL PetAI : public CreatureAI
|
||||
void MoveInLineOfSight(Unit *);
|
||||
void AttackStart(Unit *);
|
||||
void EnterEvadeMode();
|
||||
bool IsVisible(Unit *) const;
|
||||
void JustDied(Unit* who) { _stopAttack(); }
|
||||
|
||||
void UpdateAI(const uint32);
|
||||
|
||||
@@ -107,12 +107,6 @@ void PossessedAI::UpdateAI(const uint32 diff)
|
||||
}
|
||||
}
|
||||
|
||||
bool PossessedAI::_isVisible(Unit *u) const
|
||||
{
|
||||
return i_pet.GetDistance(u) < sWorld.getConfig(CONFIG_SIGHT_MONSTER)
|
||||
&& u->isVisibleForOrDetect(&i_pet,true);
|
||||
}
|
||||
|
||||
void PossessedAI::JustDied(Unit *u)
|
||||
{
|
||||
// We died while possessed, disable our loot
|
||||
|
||||
@@ -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) : CreatureAI(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);
|
||||
bool IsVisible(Unit * u) const { return _isVisible(u); }
|
||||
|
||||
void UpdateAI(const uint32);
|
||||
// Never permit this to be used, it must always be initialized with Creature::InitPossessedAI()
|
||||
|
||||
+1
-19
@@ -41,24 +41,6 @@ ReactorAI::MoveInLineOfSight(Unit *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ReactorAI::AttackStart(Unit *p)
|
||||
{
|
||||
if(!p)
|
||||
return;
|
||||
|
||||
if(i_creature.Attack(p,true))
|
||||
{
|
||||
DEBUG_LOG("Tag unit GUID: %u (TypeId: %u) as a victim", p->GetGUIDLow(), p->GetTypeId());
|
||||
i_creature.SetInCombatWith(p);
|
||||
p->SetInCombatWith(&i_creature);
|
||||
|
||||
i_creature.AddThreat(p, 0.0f);
|
||||
i_victimGuid = p->GetGUID();
|
||||
i_creature.GetMotionMaster()->MoveChase(p);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ReactorAI::IsVisible(Unit *) const
|
||||
{
|
||||
@@ -69,7 +51,7 @@ void
|
||||
ReactorAI::UpdateAI(const uint32 /*time_diff*/)
|
||||
{
|
||||
// update i_victimGuid if i_creature.getVictim() !=0 and changed
|
||||
if(!i_creature.SelectHostilTarget() || !i_creature.getVictim())
|
||||
if(!UpdateVictim())
|
||||
return;
|
||||
|
||||
i_victimGuid = i_creature.getVictim()->GetGUID();
|
||||
|
||||
@@ -29,10 +29,9 @@ class TRINITY_DLL_DECL ReactorAI : public CreatureAI
|
||||
{
|
||||
public:
|
||||
|
||||
ReactorAI(Creature *c) : i_creature(*c), i_victimGuid(0) {}
|
||||
ReactorAI(Creature *c) : CreatureAI(c), i_creature(*c), i_victimGuid(0) {}
|
||||
|
||||
void MoveInLineOfSight(Unit *);
|
||||
void AttackStart(Unit *);
|
||||
void EnterEvadeMode();
|
||||
bool IsVisible(Unit *) const;
|
||||
|
||||
|
||||
+27
-8
@@ -290,13 +290,14 @@ void SpellCastTargets::write ( WorldPacket * data )
|
||||
*data << m_strTarget;
|
||||
}
|
||||
|
||||
Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID, Spell** triggeringContainer )
|
||||
Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID, Spell** triggeringContainer, bool skipCheck )
|
||||
{
|
||||
ASSERT( Caster != NULL && info != NULL );
|
||||
ASSERT( info == sSpellStore.LookupEntry( info->Id ) && "`info` must be pointer to sSpellStore element");
|
||||
|
||||
m_spellInfo = info;
|
||||
m_customAttr = spellmgr.GetSpellCustomAttr(m_spellInfo->Id);
|
||||
m_skipCheck = skipCheck;
|
||||
m_caster = Caster;
|
||||
m_selfContainer = NULL;
|
||||
m_triggeringContainer = triggeringContainer;
|
||||
@@ -442,7 +443,7 @@ void Spell::FillTargetMap()
|
||||
{
|
||||
if(effectTargetType == SPELL_REQUIRE_CASTER)
|
||||
AddUnitTarget(m_caster, i);
|
||||
if(effectTargetType == SPELL_REQUIRE_DEST)
|
||||
/*else if(effectTargetType == SPELL_REQUIRE_DEST)
|
||||
{
|
||||
if(m_targets.HasDest() && m_spellInfo->speed > 0.0f)
|
||||
{
|
||||
@@ -450,7 +451,7 @@ void Spell::FillTargetMap()
|
||||
if (dist < 5.0f) dist = 5.0f;
|
||||
m_delayMoment = (uint64) floor(dist / m_spellInfo->speed * 1000.0f);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
else if(effectTargetType == SPELL_REQUIRE_ITEM)
|
||||
{
|
||||
if(m_targets.getItemTarget())
|
||||
@@ -633,6 +634,16 @@ void Spell::FillTargetMap()
|
||||
for(std::list<Unit*>::iterator iunit= tmpUnitMap.begin();iunit != tmpUnitMap.end();++iunit)
|
||||
AddUnitTarget((*iunit), i);
|
||||
}
|
||||
|
||||
if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
|
||||
{
|
||||
if(m_spellInfo->speed > 0.0f && m_targets.HasDest())
|
||||
{
|
||||
float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ);
|
||||
if (dist < 5.0f) dist = 5.0f;
|
||||
m_delayMoment = (uint64) floor(dist / m_spellInfo->speed * 1000.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::prepareDataForTriggerSystem()
|
||||
@@ -763,7 +774,11 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
|
||||
|
||||
// Calculate hit result
|
||||
if(m_originalCaster)
|
||||
{
|
||||
target.missCondition = m_originalCaster->SpellHitResult(pVictim, m_spellInfo, m_canReflect);
|
||||
if(m_skipCheck && target.missCondition != SPELL_MISS_IMMUNE)
|
||||
target.missCondition = SPELL_MISS_NONE;
|
||||
}
|
||||
else
|
||||
target.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE;
|
||||
|
||||
@@ -923,7 +938,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
|
||||
if (target->reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him
|
||||
DoSpellHitOnUnit(m_caster, mask);
|
||||
}
|
||||
else //TODO: This is a hack. need fix
|
||||
/*else //TODO: This is a hack. need fix
|
||||
{
|
||||
uint32 tempMask = 0;
|
||||
for(uint32 i = 0; i < 3; ++i)
|
||||
@@ -932,7 +947,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
|
||||
tempMask |= 1<<i;
|
||||
if(tempMask &= mask)
|
||||
DoSpellHitOnUnit(unit, tempMask);
|
||||
}
|
||||
}*/
|
||||
|
||||
// All calculated do it!
|
||||
// Do healing and triggers
|
||||
@@ -2206,6 +2221,8 @@ void Spell::cast(bool skipCheck)
|
||||
// Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells
|
||||
if (m_spellInfo->speed > 0.0f && !IsChanneledSpell(m_spellInfo))
|
||||
{
|
||||
if(m_customAttr & SPELL_ATTR_CU_CHARGE)
|
||||
EffectCharge(0);
|
||||
|
||||
// Remove used for cast item if need (it can be already NULL after TakeReagents call
|
||||
// in case delayed spell remove item at cast delay start
|
||||
@@ -2288,12 +2305,14 @@ uint64 Spell::handle_delayed(uint64 t_offset)
|
||||
m_immediateHandled = true;
|
||||
}
|
||||
|
||||
bool single_missile = (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION);
|
||||
|
||||
// now recheck units targeting correctness (need before any effects apply to prevent adding immunity at first effect not allow apply second spell effect and similar cases)
|
||||
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end();++ihit)
|
||||
{
|
||||
if (ihit->processed == false)
|
||||
{
|
||||
if ( ihit->timeDelay <= t_offset )
|
||||
if ( single_missile || ihit->timeDelay <= t_offset )
|
||||
DoAllEffectOnTarget(&(*ihit));
|
||||
else if( next_time == 0 || ihit->timeDelay < next_time )
|
||||
next_time = ihit->timeDelay;
|
||||
@@ -2305,7 +2324,7 @@ uint64 Spell::handle_delayed(uint64 t_offset)
|
||||
{
|
||||
if (ighit->processed == false)
|
||||
{
|
||||
if ( ighit->timeDelay <= t_offset )
|
||||
if ( single_missile || ighit->timeDelay <= t_offset )
|
||||
DoAllEffectOnTarget(&(*ighit));
|
||||
else if( next_time == 0 || ighit->timeDelay < next_time )
|
||||
next_time = ighit->timeDelay;
|
||||
@@ -3486,7 +3505,7 @@ void Spell::TriggerSpell()
|
||||
{
|
||||
for(TriggerSpells::iterator si=m_TriggerSpells.begin(); si!=m_TriggerSpells.end(); ++si)
|
||||
{
|
||||
Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID, m_selfContainer);
|
||||
Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID, m_selfContainer, true);
|
||||
spell->prepare(&m_targets); // use original spell original targets
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -351,7 +351,7 @@ class Spell
|
||||
void EffectActivateRune(uint32 i);
|
||||
void EffectTitanGrip(uint32 i);
|
||||
|
||||
Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL );
|
||||
Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL, bool skipCheck = false );
|
||||
~Spell();
|
||||
|
||||
void prepare(SpellCastTargets const* targets, Aura* triggeredByAura = NULL);
|
||||
@@ -611,6 +611,7 @@ class Spell
|
||||
SpellEntry const* m_triggeredByAuraSpell;
|
||||
|
||||
uint32 m_customAttr;
|
||||
bool m_skipCheck;
|
||||
};
|
||||
|
||||
namespace Trinity
|
||||
|
||||
@@ -160,7 +160,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
|
||||
&Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
|
||||
&Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT
|
||||
&Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING
|
||||
&Spell::EffectCharge, // 96 SPELL_EFFECT_CHARGE
|
||||
&Spell::EffectUnused, // 96 SPELL_EFFECT_CHARGE
|
||||
&Spell::EffectUnused, // 97 SPELL_EFFECT_97
|
||||
&Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK
|
||||
&Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT
|
||||
@@ -655,6 +655,9 @@ void Spell::EffectDummy(uint32 i)
|
||||
if(!unitTarget && !gameObjTarget && !itemTarget)
|
||||
return;
|
||||
|
||||
uint32 spell_id = 0;
|
||||
int32 bp = 0;
|
||||
|
||||
// selection by spell family
|
||||
switch(m_spellInfo->SpellFamilyName)
|
||||
{
|
||||
@@ -1306,9 +1309,9 @@ void Spell::EffectDummy(uint32 i)
|
||||
if (Aura *aura = m_caster->GetDummyAura(58367))
|
||||
rage+=aura->GetModifier()->m_amount;
|
||||
|
||||
int32 basePoints0 = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
|
||||
spell_id = 20647;
|
||||
int32 bp = damage+int32(rage * m_spellInfo->DmgMultiplier[i] +
|
||||
m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
|
||||
m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
|
||||
m_caster->SetPower(POWER_RAGE,0);
|
||||
return;
|
||||
}
|
||||
@@ -1807,6 +1810,24 @@ void Spell::EffectDummy(uint32 i)
|
||||
break;
|
||||
}
|
||||
|
||||
//spells triggered by dummy effect should not miss
|
||||
if(spell_id)
|
||||
{
|
||||
SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
|
||||
|
||||
if(!spellInfo)
|
||||
{
|
||||
sLog.outError("EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id);
|
||||
return;
|
||||
}
|
||||
|
||||
Spell* spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID, NULL, true);
|
||||
if(bp) spell->m_currentBasePoints[0] = bp;
|
||||
SpellCastTargets targets;
|
||||
targets.setUnitTarget(unitTarget);
|
||||
spell->prepare(&targets);
|
||||
}
|
||||
|
||||
// pet auras
|
||||
if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
|
||||
{
|
||||
@@ -6006,16 +6027,20 @@ void Spell::EffectSkinning(uint32 /*i*/)
|
||||
|
||||
void Spell::EffectCharge(uint32 /*i*/)
|
||||
{
|
||||
if(!unitTarget || !m_caster)
|
||||
if(!m_caster)
|
||||
return;
|
||||
|
||||
Unit *target = m_targets.getUnitTarget();
|
||||
if(!target)
|
||||
return;
|
||||
|
||||
float x, y, z;
|
||||
unitTarget->GetContactPoint(m_caster, x, y, z);
|
||||
target->GetContactPoint(m_caster, x, y, z);
|
||||
m_caster->GetMotionMaster()->MoveCharge(x, y, z);
|
||||
|
||||
// not all charge effects used in negative spells
|
||||
if ( !IsPositiveSpell(m_spellInfo->Id) && m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
m_caster->Attack(unitTarget,true);
|
||||
m_caster->Attack(target, true);
|
||||
}
|
||||
|
||||
void Spell::EffectSummonCritter(uint32 i)
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "Chat.h"
|
||||
#include "Spell.h"
|
||||
|
||||
bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS];
|
||||
|
||||
SpellMgr::SpellMgr()
|
||||
{
|
||||
for(int i = 0; i < TOTAL_SPELL_EFFECTS; ++i)
|
||||
@@ -2170,6 +2172,15 @@ void SpellMgr::LoadSpellCustomAttr()
|
||||
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
|
||||
case SPELL_EFFECT_HEAL:
|
||||
mSpellCustomAttr[i] |= SPELL_ATTR_CU_DIRECT_DAMAGE;
|
||||
break;
|
||||
case SPELL_EFFECT_CHARGE:
|
||||
if(!spellInfo->speed)
|
||||
spellInfo->speed = SPEED_CHARGE;
|
||||
mSpellCustomAttr[i] |= SPELL_ATTR_CU_CHARGE;
|
||||
case SPELL_EFFECT_TRIGGER_SPELL:
|
||||
if(spellInfo->Targets & (TARGET_FLAG_SOURCE_LOCATION|TARGET_FLAG_DEST_LOCATION))
|
||||
spellInfo->Effect[j] = SPELL_EFFECT_TRIGGER_MISSILE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -396,7 +396,7 @@ bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId);
|
||||
|
||||
uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id);
|
||||
|
||||
static bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS];
|
||||
extern bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS];
|
||||
|
||||
inline bool IsAreaOfEffectSpell(SpellEntry const *spellInfo)
|
||||
{
|
||||
@@ -773,6 +773,7 @@ inline bool IsProfessionSkill(uint32 skill)
|
||||
#define SPELL_ATTR_CU_AURA_CC 0x00000040
|
||||
#define SPELL_ATTR_CU_AURA_SPELL 0x00000080
|
||||
#define SPELL_ATTR_CU_DIRECT_DAMAGE 0x00000100
|
||||
#define SPELL_ATTR_CU_CHARGE 0x00000200
|
||||
|
||||
typedef std::vector<uint32> SpellCustomAttribute;
|
||||
|
||||
|
||||
@@ -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) : CreatureAI(c), i_totem(static_cast<Totem&>(*c)), i_victimGuid(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+14
-21
@@ -7296,6 +7296,12 @@ bool Unit::Attack(Unit *victim, bool meleeAttack)
|
||||
((WorldObject*)this)->SendMessageToSet(&data, true);
|
||||
|
||||
((Creature*)this)->CallAssistance();
|
||||
|
||||
// should not let player enter combat by right clicking target
|
||||
SetInCombatWith(victim);
|
||||
if(victim->GetTypeId() == TYPEID_PLAYER)
|
||||
victim->SetInCombatWith(this);
|
||||
AddThreat(victim, 0.0f);
|
||||
}
|
||||
|
||||
// delay offhand weapon attack to next attack time
|
||||
@@ -9735,7 +9741,7 @@ void Unit::TauntFadeOut(Unit *taunter)
|
||||
|
||||
//======================================================================
|
||||
|
||||
Unit* Creature::SelectHostilTarget()
|
||||
Unit* Creature::SelectVictim()
|
||||
{
|
||||
//function provides main threat functionality
|
||||
//next-victim-selection algorithm and evade mode are called
|
||||
@@ -9746,13 +9752,8 @@ Unit* Creature::SelectHostilTarget()
|
||||
//otherwise enterevademode every update
|
||||
|
||||
|
||||
if (!this->isAlive())
|
||||
return false;
|
||||
//This function only useful once AI has been initialized
|
||||
if (!AI())
|
||||
return NULL;
|
||||
Unit* target = NULL;
|
||||
|
||||
Unit* target = NULL;
|
||||
// First checking if we have some taunt on us
|
||||
const AuraList& tauntAuras = GetAurasByType(SPELL_AURA_MOD_TAUNT);
|
||||
if ( !tauntAuras.empty() )
|
||||
@@ -9792,18 +9793,15 @@ Unit* Creature::SelectHostilTarget()
|
||||
{
|
||||
if(!hasUnitState(UNIT_STAT_STUNNED))
|
||||
SetInFront(target);
|
||||
AI()->AttackStart(target);
|
||||
return getVictim();
|
||||
return target;
|
||||
}
|
||||
|
||||
// no target but something prevent go to evade mode
|
||||
if( !isInCombat() /*|| HasAuraType(SPELL_AURA_MOD_TAUNT)*/ )
|
||||
return NULL;
|
||||
|
||||
// last case when creature don't must go to evade mode:
|
||||
// it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
|
||||
// for example at owner command to pet attack some far away creature
|
||||
// Note: creature not have targeted movement generator but have attacker in this case
|
||||
if(m_attackers.size())
|
||||
return NULL;
|
||||
/*if( GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE )
|
||||
{
|
||||
for(AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr)
|
||||
@@ -9816,14 +9814,9 @@ Unit* Creature::SelectHostilTarget()
|
||||
// search nearby enemy before enter evade mode
|
||||
if(HasReactState(REACT_AGGRESSIVE))
|
||||
{
|
||||
if(target = SelectNearestTarget())
|
||||
{
|
||||
if(!IsOutOfThreatArea(target))
|
||||
{
|
||||
AI()->AttackStart(target);
|
||||
return getVictim();
|
||||
}
|
||||
}
|
||||
target = SelectNearestTarget();
|
||||
if(target && !IsOutOfThreatArea(target))
|
||||
return target;
|
||||
}
|
||||
|
||||
if(m_invisibilityMask)
|
||||
|
||||
+2
-1
@@ -406,6 +406,8 @@ enum UnitMoveType
|
||||
#define MAX_MOVE_TYPE 9
|
||||
|
||||
extern float baseMoveSpeed[MAX_MOVE_TYPE];
|
||||
// assume it is 25 yard per 0.6 second
|
||||
#define SPEED_CHARGE 42.0f
|
||||
|
||||
enum WeaponAttackType
|
||||
{
|
||||
@@ -1275,7 +1277,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
|
||||
void AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL);
|
||||
float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL);
|
||||
void DeleteThreatList();
|
||||
//bool SelectHostilTarget();
|
||||
void TauntApply(Unit* pVictim);
|
||||
void TauntFadeOut(Unit *taunter);
|
||||
ThreatManager& getThreatManager() { return m_ThreatManager; }
|
||||
|
||||
Reference in New Issue
Block a user