Merge branch 'master' into 310

This commit is contained in:
tomrus88 2009-04-14 15:54:43 +04:00
commit d6f6272f8c
41 changed files with 759 additions and 615 deletions

View file

@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`;
CREATE TABLE `db_version` (
`version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL,
`required_7643_02_mangos_mangos_string` bit(1) default NULL
`required_7662_02_mangos_spell_bonus_data` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@ -15786,6 +15786,16 @@ INSERT INTO spell_chain VALUES
(53199,48505,48505,2,0),
(53200,53199,48505,3,0),
(53201,53200,48505,4,0),
/*Starfall AOE*/
(50294,0,50294,1,0),
(53188,50294,50294,2,0),
(53189,53188,50294,3,0),
(53190,53189,50294,4,0),
/*Starfall Direct*/
(50288,0,50288,1,0),
(53191,50288,50288,2,0),
(53194,53191,50288,3,0),
(53195,53194,50288,4,0),
/*Starfire*/
(2912,0,2912,1,0),
(8949,2912,2912,2,0),
@ -17571,6 +17581,8 @@ INSERT INTO `spell_bonus_data` VALUES
('33763', '0', '0.09518', '0', 'Druid - Lifebloom'),
('774', '0', '0.37604', '0', 'Druid - Rejuvenation'),
('8936', '0.539', '0.188', '0', 'Druid - Regrowth'),
('50288', '0.05', '0', '0', 'Druid - Starfall'),
('50294', '0.012', '0', '0', 'Druid - Starfall AOE'),
('18562', '0', '0', '0', 'Druid - Swiftmend'),
('44203', '0.538', '0', '0', 'Druid - Tranquility Triggered'),
('48438', '0', '0.11505', '0', 'Druid - Wild Growth'),

View file

@ -0,0 +1,16 @@
ALTER TABLE db_version CHANGE COLUMN required_7643_02_mangos_mangos_string required_7662_01_mangos_spell_chain bit;
DELETE FROM `spell_chain` WHERE spell_id IN (50288, 53191, 53194, 53195);
INSERT INTO `spell_chain` VALUES
(50288, 0, 50288, 1, 0),
(53191, 50288, 50288, 2, 0),
(53194, 53191, 50288, 3, 0),
(53195, 53194, 50288, 4, 0);
DELETE FROM `spell_chain` WHERE spell_id IN (50294, 53188, 53189, 53190);
INSERT INTO `spell_chain` VALUES
(50294, 0, 50294, 1, 0),
(53188, 50294, 50294, 2, 0),
(53189, 53188, 50294, 3, 0),
(53190, 53189, 50294, 4, 0);

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_7662_01_mangos_spell_chain required_7662_02_mangos_spell_bonus_data bit;
DELETE FROM `spell_bonus_data` WHERE entry IN (50288, 50294);
INSERT INTO `spell_bonus_data` VALUES
(50288, 0.05, 0, 0, "Druid - Starfall"),
(50294, 0.012, 0, 0, "Druid - Starfall AOE");

View file

@ -171,6 +171,8 @@ pkgdata_DATA = \
7643_01_mangos_db_version.sql \
7643_02_mangos_mangos_string.sql \
7644_01_characters_character_pet.sql \
7662_01_mangos_spell_chain.sql \
7662_02_mangos_spell_bonus_data.sql \
README
## Additional files to include when running 'make dist'
@ -322,4 +324,6 @@ EXTRA_DIST = \
7643_01_mangos_db_version.sql \
7643_02_mangos_mangos_string.sql \
7644_01_characters_character_pet.sql \
7662_01_mangos_spell_chain.sql \
7662_02_mangos_spell_bonus_data.sql \
README

View file

@ -78,29 +78,15 @@ struct Script
#define VISIBLE_RANGE (50.0f)
// Read function descriptions in CreatureAI
struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI
{
ScriptedAI(Creature* creature) : m_creature(creature) {}
explicit ScriptedAI(Creature* creature) : CreatureAI(creature) {}
~ScriptedAI() {}
// Called if IsVisible(Unit *who) is true at each *who move
void MoveInLineOfSight(Unit *) {}
// Called at each attack of m_creature by any victim
void AttackStart(Unit *) {}
// Called at stopping attack by any attacker
void EnterEvadeMode();
// Called at any heal cast/item used (call non implemented)
void HealBy(Unit* /*healer*/, uint32 /*amount_healed*/) {}
// Called at any Damage to any victim (before damage apply)
void DamageDeal(Unit* /*done_to*/, uint32& /*damage*/) {}
// Called at any Damage from any attacker (before damage apply)
void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/) {}
// Is unit visible for MoveInLineOfSight
bool IsVisible(Unit* who) const
{
@ -110,20 +96,6 @@ struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI
// Called at World update tick
void UpdateAI(const uint32);
// Called when the creature is killed
void JustDied(Unit *){}
// Called when the creature kills a unit
void KilledUnit(Unit *){}
// Called when hit by a spell
void SpellHit(Unit *, const SpellEntry*){}
// Called when spell hits creature's target
void SpellHitTarget(Unit*, const SpellEntry*) {}
Creature* m_creature;
//= Some useful helpers =========================
// Start attack of victim and go to him

View file

@ -35,7 +35,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) : CreatureAI(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK)
{
}
@ -43,25 +43,25 @@ void
AggressorAI::MoveInLineOfSight(Unit *u)
{
// Ignore Z for flying creatures
if( !i_creature.canFly() && i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE )
if( !m_creature->canFly() && m_creature->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE )
return;
if( !i_creature.hasUnitState(UNIT_STAT_STUNNED) && u->isTargetableForAttack() &&
( i_creature.IsHostileTo( u ) /*|| u->getVictim() && i_creature.IsFriendlyTo( u->getVictim() )*/ ) &&
u->isInAccessablePlaceFor(&i_creature) )
if( !m_creature->hasUnitState(UNIT_STAT_STUNNED) && u->isTargetableForAttack() &&
( m_creature->IsHostileTo( u ) /*|| u->getVictim() && m_creature->IsFriendlyTo( u->getVictim() )*/ ) &&
u->isInAccessablePlaceFor(m_creature) )
{
float attackRadius = i_creature.GetAttackDistance(u);
if(i_creature.IsWithinDistInMap(u, attackRadius) && i_creature.IsWithinLOSInMap(u) )
float attackRadius = m_creature->GetAttackDistance(u);
if(m_creature->IsWithinDistInMap(u, attackRadius) && m_creature->IsWithinLOSInMap(u) )
{
if(!i_creature.getVictim())
if(!m_creature->getVictim())
{
AttackStart(u);
u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
}
else if(sMapStore.LookupEntry(i_creature.GetMapId())->IsDungeon())
else if(sMapStore.LookupEntry(m_creature->GetMapId())->IsDungeon())
{
u->SetInCombatWith(&i_creature);
i_creature.AddThreat(u, 0.0f);
u->SetInCombatWith(m_creature);
m_creature->AddThreat(u, 0.0f);
}
}
}
@ -69,70 +69,70 @@ AggressorAI::MoveInLineOfSight(Unit *u)
void AggressorAI::EnterEvadeMode()
{
if( !i_creature.isAlive() )
if( !m_creature->isAlive() )
{
DEBUG_LOG("Creature stopped attacking cuz his dead [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking cuz his dead [guid=%u]", m_creature->GetGUIDLow());
i_victimGuid = 0;
i_creature.CombatStop();
i_creature.DeleteThreatList();
m_creature->CombatStop();
m_creature->DeleteThreatList();
return;
}
Unit* victim = ObjectAccessor::GetUnit(i_creature, i_victimGuid );
Unit* victim = ObjectAccessor::GetUnit(*m_creature, i_victimGuid );
if( !victim )
{
DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", m_creature->GetGUIDLow());
}
else if( !victim->isAlive() )
{
DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", m_creature->GetGUIDLow());
}
else if( victim->HasStealthAura() )
{
DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", m_creature->GetGUIDLow());
}
else if( victim->isInFlight() )
{
DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", m_creature->GetGUIDLow());
}
else
{
DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", m_creature->GetGUIDLow());
//i_state = STATE_LOOK_AT_VICTIM;
//i_tracker.Reset(TIME_INTERVAL_LOOK);
}
if(!i_creature.isCharmed())
if(!m_creature->isCharmed())
{
i_creature.RemoveAllAuras();
m_creature->RemoveAllAuras();
// Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE )
i_creature.GetMotionMaster()->MoveTargetedHome();
if( m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE )
m_creature->GetMotionMaster()->MoveTargetedHome();
}
i_creature.DeleteThreatList();
m_creature->DeleteThreatList();
i_victimGuid = 0;
i_creature.CombatStop();
i_creature.SetLootRecipient(NULL);
m_creature->CombatStop();
m_creature->SetLootRecipient(NULL);
}
void
AggressorAI::UpdateAI(const uint32 /*diff*/)
{
// update i_victimGuid if i_creature.getVictim() !=0 and changed
if(!i_creature.SelectHostilTarget() || !i_creature.getVictim())
// update i_victimGuid if m_creature->getVictim() !=0 and changed
if(!m_creature->SelectHostilTarget() || !m_creature->getVictim())
return;
i_victimGuid = i_creature.getVictim()->GetGUID();
i_victimGuid = m_creature->getVictim()->GetGUID();
if( i_creature.isAttackReady() )
if( m_creature->isAttackReady() )
{
if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DISTANCE))
if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
i_creature.AttackerStateUpdate(i_creature.getVictim());
i_creature.resetAttackTimer();
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
}
}
}
@ -140,8 +140,8 @@ 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);
return m_creature->GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER)
&& pl->isVisibleForOrDetect(m_creature,true);
}
void
@ -150,15 +150,15 @@ AggressorAI::AttackStart(Unit *u)
if( !u )
return;
if(i_creature.Attack(u,true))
if(m_creature->Attack(u,true))
{
i_creature.SetInCombatWith(u);
u->SetInCombatWith(&i_creature);
m_creature->SetInCombatWith(u);
u->SetInCombatWith(m_creature);
i_creature.AddThreat(u, 0.0f);
// DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", i_creature.GetName(), u->GetGUIDLow());
m_creature->AddThreat(u, 0.0f);
// DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", m_creature->GetName(), u->GetGUIDLow());
i_victimGuid = u->GetGUID();
i_creature.GetMotionMaster()->MoveChase(u);
m_creature->GetMotionMaster()->MoveChase(u);
}
}

View file

@ -34,7 +34,7 @@ class MANGOS_DLL_DECL AggressorAI : public CreatureAI
public:
AggressorAI(Creature &c);
explicit AggressorAI(Creature *c);
void MoveInLineOfSight(Unit *);
void AttackStart(Unit *);
@ -45,7 +45,6 @@ class MANGOS_DLL_DECL AggressorAI : public CreatureAI
static int Permissible(const Creature *);
private:
Creature &i_creature;
uint64 i_victimGuid;
AggressorState i_state;
TimeTracker i_tracker;

View file

@ -109,7 +109,7 @@ Unit(), i_AI(NULL),
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
m_lootMoney(0), m_lootRecipient(0),
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isVehicle(false), m_isTotem(false),
m_gossipOptionLoaded(false), m_isPet(false), m_isVehicle(false), m_isTotem(false),
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false),
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
m_creatureInfo(NULL), m_isActiveObject(false)
@ -1993,12 +1993,17 @@ uint32 Creature::getLevelForTarget( Unit const* target ) const
return level;
}
std::string Creature::GetScriptName()
std::string Creature::GetAIName() const
{
return ObjectMgr::GetCreatureTemplate(GetEntry())->AIName;
}
std::string Creature::GetScriptName() const
{
return objmgr.GetScriptName(GetScriptId());
}
uint32 Creature::GetScriptId()
uint32 Creature::GetScriptId() const
{
return ObjectMgr::GetCreatureTemplate(GetEntry())->ScriptID;
}

View file

@ -532,8 +532,9 @@ class MANGOS_DLL_SPEC Creature : public Unit
CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; }
CreatureDataAddon const* GetCreatureAddon() const;
std::string GetScriptName();
uint32 GetScriptId();
std::string GetAIName() const;
std::string GetScriptName() const;
uint32 GetScriptId() const;
void prepareGossipMenu( Player *pPlayer, uint32 gossipid = 0 );
void sendPreparedGossip( Player* player );
@ -546,7 +547,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
GossipOption const* GetGossipOption( uint32 id ) const;
void addGossipOption(GossipOption const& gso) { m_goptions.push_back(gso); }
void setEmoteState(uint8 emote) { m_emoteState = emote; };
void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); }
void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); }
void TextEmote(int32 textId, uint64 TargetGuid, bool IsBossEmote = false) { MonsterTextEmote(textId,TargetGuid,IsBossEmote); }
@ -665,7 +665,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
bool m_gossipOptionLoaded;
GossipOptionList m_goptions;
uint8 m_emoteState;
bool m_isPet; // set only in Pet::Pet
bool m_isVehicle; // set only in Vehicle::Vehicle
bool m_isTotem; // set only in Totem::Totem

View file

@ -17,7 +17,14 @@
*/
#include "CreatureAI.h"
#include "Creature.h"
CreatureAI::~CreatureAI()
{
}
void CreatureAI::AttackedBy( Unit* attacker )
{
if(!m_creature->getVictim())
AttackStart(attacker);
}

View file

@ -36,17 +36,17 @@ struct SpellEntry;
class MANGOS_DLL_SPEC CreatureAI
{
public:
explicit CreatureAI(Creature* creature) : m_creature(creature) {}
virtual ~CreatureAI();
// Called if IsVisible(Unit *who) is true at each *who move
virtual void MoveInLineOfSight(Unit *) = 0;
///== Reactions At =================================
// Called at each attack of m_creature by any victim
virtual void AttackStart(Unit *) = 0;
// Called if IsVisible(Unit *who) is true at each *who move, reaction at visibility zone enter
virtual void MoveInLineOfSight(Unit *) {}
// Called at stopping attack by any attacker
virtual void EnterEvadeMode() = 0;
// Called for reaction at stopping attack at no attackers or targets
virtual void EnterEvadeMode() {}
// Called at reaching home after evade
virtual void JustReachedHome() {}
@ -58,13 +58,9 @@ class MANGOS_DLL_SPEC CreatureAI
virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {}
// Called at any Damage from any attacker (before damage apply)
virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) { AttackedBy(done_by); }
// Is unit visible for MoveInLineOfSight
virtual bool IsVisible(Unit *) const = 0;
// Called at World update tick
virtual void UpdateAI(const uint32 diff ) = 0;
// Note: it for recalculation damage or special reaction at damage
// for attack reaction use AttackedBy called for not DOT damage in Unit::DealDamage also
virtual void DamageTaken(Unit *done_by, uint32 & /*damage*/) {}
// Called when the creature is killed
virtual void JustDied(Unit *) {}
@ -83,17 +79,36 @@ class MANGOS_DLL_SPEC CreatureAI
// Called when spell hits creature's target
virtual void SpellHitTarget(Unit*, const SpellEntry*) {}
// 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 the creature is target of hostile action: swing, hostile spell landed, fear/etc)
virtual void AttackedBy(Unit* attacker);
// Called when creature is spawned or respawned (for reseting variables)
virtual void JustRespawned() {}
// Called at waypoint reached or point movement finished
virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {}
///== Triggered Actions Requested ==================
// Called when creature attack expected (if creature can and no have current victim)
// Note: for reaction at hostile action must be called AttackedBy function.
virtual void AttackStart(Unit *) {}
// Called at World update tick
virtual void UpdateAI(const uint32 diff ) {}
///== State checks =================================
// Is unit visible for MoveInLineOfSight
virtual bool IsVisible(Unit *) const { return false; }
// Called when victim entered water and creature can not enter water
virtual bool canReachByRangeAttack(Unit*) { return false; }
///== Fields =======================================
// Pointer to controlled by AI creature
Creature* const m_creature;
};
struct SelectableAI : public FactoryHolder<CreatureAI>, public Permissible<Creature>

View file

@ -25,6 +25,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

View file

@ -38,12 +38,10 @@ namespace FactorySelector
return scriptedAI;
CreatureAIRegistry &ai_registry(CreatureAIRepository::Instance());
assert( creature->GetCreatureInfo() != NULL );
CreatureInfo const *cinfo=creature->GetCreatureInfo();
const CreatureAICreator *ai_factory = NULL;
std::string ainame=cinfo->AIName;
std::string ainame=creature->GetAIName();
// select by NPC flags _first_ - otherwise EventAI might be choosen for pets/totems
// excplicit check for isControlled() and owner type to allow guardian, mini-pets and pets controlled by NPCs to be scripted by EventAI
@ -84,7 +82,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)

View file

@ -32,14 +32,14 @@
int CreatureEventAI::Permissible(const Creature *creature)
{
if( creature->GetCreatureInfo()->AIName == "EventAI" )
if( creature->GetAIName() == "EventAI" )
return PERMIT_BASE_SPECIAL;
return PERMIT_BASE_NO;
}
CreatureEventAI::CreatureEventAI(Creature &c ) : m_creature(c), InCombat(false)
CreatureEventAI::CreatureEventAI(Creature *c ) : CreatureAI(c), InCombat(false)
{
CreatureEventAI_Event_Map::iterator CreatureEvents = CreatureEAI_Mgr.GetCreatureEventAIMap().find(m_creature.GetEntry());
CreatureEventAI_Event_Map::iterator CreatureEvents = CreatureEAI_Mgr.GetCreatureEventAIMap().find(m_creature->GetEntry());
if (CreatureEvents != CreatureEAI_Mgr.GetCreatureEventAIMap().end())
{
std::vector<CreatureEventAI_Event>::iterator i;
@ -51,10 +51,10 @@ CreatureEventAI::CreatureEventAI(Creature &c ) : m_creature(c), InCombat(false)
if ((*i).event_flags & EFLAG_DEBUG_ONLY)
continue;
#endif
if( m_creature.GetMap()->IsDungeon() )
if (m_creature->GetMap()->IsDungeon())
{
if( (m_creature.GetMap()->IsHeroic() && (*i).event_flags & EFLAG_HEROIC) ||
(!m_creature.GetMap()->IsHeroic() && (*i).event_flags & EFLAG_NORMAL))
if( (m_creature->GetMap()->IsHeroic() && (*i).event_flags & EFLAG_HEROIC) ||
(!m_creature->GetMap()->IsHeroic() && (*i).event_flags & EFLAG_NORMAL))
{
//event flagged for instance mode
CreatureEventAIList.push_back(CreatureEventAIHolder(*i));
@ -65,10 +65,10 @@ CreatureEventAI::CreatureEventAI(Creature &c ) : m_creature(c), InCombat(false)
}
//EventMap had events but they were not added because they must be for instance
if (CreatureEventAIList.empty())
sLog.outError("CreatureEventAI: CreatureId has events but no events added to list because of instance flags.", m_creature.GetEntry());
sLog.outError("CreatureEventAI: CreatureId has events but no events added to list because of instance flags.", m_creature->GetEntry());
}
else
sLog.outError("CreatureEventAI: EventMap for Creature %u is empty but creature is using CreatureEventAI.", m_creature.GetEntry());
sLog.outError("CreatureEventAI: EventMap for Creature %u is empty but creature is using CreatureEventAI.", m_creature->GetEntry());
bEmptyList = CreatureEventAIList.empty();
Phase = 0;
@ -151,7 +151,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -171,17 +171,17 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
break;
case EVENT_T_HP:
{
if (!InCombat || !m_creature.GetMaxHealth())
if (!InCombat || !m_creature->GetMaxHealth())
return false;
uint32 perc = (m_creature.GetHealth()*100) / m_creature.GetMaxHealth();
uint32 perc = (m_creature->GetHealth()*100) / m_creature->GetMaxHealth();
if (perc > param1 || perc < param2)
return false;
@ -196,17 +196,17 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
break;
case EVENT_T_MANA:
{
if (!InCombat || !m_creature.GetMaxPower(POWER_MANA))
if (!InCombat || !m_creature->GetMaxPower(POWER_MANA))
return false;
uint32 perc = (m_creature.GetPower(POWER_MANA)*100) / m_creature.GetMaxPower(POWER_MANA);
uint32 perc = (m_creature->GetPower(POWER_MANA)*100) / m_creature->GetMaxPower(POWER_MANA);
if (perc > param1 || perc < param2)
return false;
@ -221,7 +221,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -242,7 +242,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -268,7 +268,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -285,7 +285,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -302,7 +302,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -313,10 +313,10 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
break;
case EVENT_T_TARGET_HP:
{
if (!InCombat || !m_creature.getVictim() || !m_creature.getVictim()->GetMaxHealth())
if (!InCombat || !m_creature->getVictim() || !m_creature->getVictim()->GetMaxHealth())
return false;
uint32 perc = (m_creature.getVictim()->GetHealth()*100) / m_creature.getVictim()->GetMaxHealth();
uint32 perc = (m_creature->getVictim()->GetHealth()*100) / m_creature->getVictim()->GetMaxHealth();
if (perc > param1 || perc < param2)
return false;
@ -331,14 +331,14 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
break;
case EVENT_T_TARGET_CASTING:
{
if (!InCombat || !m_creature.getVictim() || !m_creature.getVictim()->IsNonMeleeSpellCasted(false, false, true))
if (!InCombat || !m_creature->getVictim() || !m_creature->getVictim()->IsNonMeleeSpellCasted(false, false, true))
return false;
//Repeat Timers
@ -351,7 +351,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -378,7 +378,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -407,7 +407,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
pHolder.Time = urand(param3, param4);
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -434,7 +434,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -459,7 +459,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
else
{
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
pHolder.Enabled = false;
}
}
@ -474,7 +474,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
break;
default:
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature.GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
break;
}
@ -531,7 +531,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
target = owner;
}
}
else if (target = m_creature.getVictim())
else if (target = m_creature->getVictim())
{
if (target->GetTypeId() != TYPEID_PLAYER)
{
@ -543,21 +543,21 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
}
}
DoScriptText(temp, &m_creature, target);
DoScriptText(temp, m_creature, target);
}
}
break;
case ACTION_T_SET_FACTION:
{
if (param1)
m_creature.setFaction(param1);
m_creature->setFaction(param1);
else
{
if (CreatureInfo const* ci = GetCreatureTemplateStore(m_creature.GetEntry()))
if (CreatureInfo const* ci = GetCreatureTemplateStore(m_creature->GetEntry()))
{
//if no id provided, assume reset and then use default
if (m_creature.getFaction() != ci->faction_A)
m_creature.setFaction(ci->faction_A);
if (m_creature->getFaction() != ci->faction_A)
m_creature->setFaction(ci->faction_A);
}
}
}
@ -573,29 +573,29 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
{
//use default display
if (ci->DisplayID_A)
m_creature.SetDisplayId(ci->DisplayID_A);
m_creature->SetDisplayId(ci->DisplayID_A);
}
}
//if no param1, then use value from param2 (modelId)
else
m_creature.SetDisplayId(param2);
m_creature->SetDisplayId(param2);
}
else
m_creature.DeMorph();
m_creature->DeMorph();
}
break;
case ACTION_T_SOUND:
m_creature.PlayDirectSound(param1);
m_creature->PlayDirectSound(param1);
break;
case ACTION_T_EMOTE:
m_creature.HandleEmoteCommand(param1);
m_creature->HandleEmoteCommand(param1);
break;
case ACTION_T_RANDOM_SOUND:
{
uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
if (temp != uint32(0xffffffff))
m_creature.PlayDirectSound( temp );
m_creature->PlayDirectSound( temp );
}
break;
case ACTION_T_RANDOM_EMOTE:
@ -603,13 +603,13 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
if (temp != uint32(0xffffffff))
m_creature.HandleEmoteCommand(temp);
m_creature->HandleEmoteCommand(temp);
}
break;
case ACTION_T_CAST:
{
Unit* target = GetTargetByType(param2, pActionInvoker);
Unit* caster = &m_creature;
Unit* caster = m_creature;
if (!target)
return;
@ -646,13 +646,13 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
//Melee current victim if flag not set
if (!(param3 & CAST_NO_MELEE_IF_OOM))
{
if (m_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
{
AttackDistance = 0;
AttackAngle = 0;
m_creature.GetMotionMaster()->Clear(false);
m_creature.GetMotionMaster()->MoveChase(m_creature.getVictim(), AttackDistance, AttackAngle);
m_creature->GetMotionMaster()->Clear(false);
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle);
}
}
@ -667,7 +667,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
}
}else
sLog.outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature.GetEntry(), param1);
sLog.outErrorDb("CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature->GetEntry(), param1);
}
}
break;
@ -678,14 +678,14 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
Creature* pCreature = NULL;
if (param3)
pCreature = m_creature.SummonCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, param3);
pCreature = m_creature->SummonCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, param3);
else
pCreature = m_creature.SummonCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
pCreature = m_creature->SummonCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
if (!pCreature)
{
sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", param1, EventId, m_creature.GetEntry());
sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Spawn event %d is on creature %d", param1, EventId, m_creature->GetEntry());
}
else if (param2 != TARGET_T_SELF && target)
pCreature->AI()->AttackStart(target);
@ -696,19 +696,19 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
Unit* target = GetTargetByType(param2, pActionInvoker);
if (target)
m_creature.getThreatManager().modifyThreatPercent(target, param1);
m_creature->getThreatManager().modifyThreatPercent(target, param1);
}
break;
case ACTION_T_THREAT_ALL_PCT:
{
Unit* Temp = NULL;
std::list<HostilReference*>::iterator i = m_creature.getThreatManager().getThreatList().begin();
for (; i != m_creature.getThreatManager().getThreatList().end(); ++i)
std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
for (; i != m_creature->getThreatManager().getThreatList().end(); ++i)
{
Temp = Unit::GetUnit(m_creature,(*i)->getUnitGuid());
Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid());
if (Temp)
m_creature.getThreatManager().modifyThreatPercent(Temp, param1);
m_creature->getThreatManager().modifyThreatPercent(Temp, param1);
}
}
break;
@ -725,7 +725,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
Unit* target = GetTargetByType(param3, pActionInvoker);
if (target && target->GetTypeId() == TYPEID_PLAYER)
((Player*)target)->CastedCreatureOrGO(param1, m_creature.GetGUID(), param2);
((Player*)target)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2);
}
break;
case ACTION_T_SET_UNIT_FIELD:
@ -769,18 +769,18 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
//Allow movement (create new targeted movement gen only if idle)
if (CombatMovementEnabled)
{
if (m_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE)
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE)
{
m_creature.GetMotionMaster()->Clear(false);
m_creature.GetMotionMaster()->MoveChase(m_creature.getVictim(), AttackDistance, AttackAngle);
m_creature->GetMotionMaster()->Clear(false);
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle);
}
}
else
if (m_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
{
m_creature.GetMotionMaster()->Clear(false);
m_creature.GetMotionMaster()->MoveIdle();
m_creature.StopMoving();
m_creature->GetMotionMaster()->Clear(false);
m_creature->GetMotionMaster()->MoveIdle();
m_creature->StopMoving();
}
}
break;
@ -795,7 +795,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
if (Phase > 31)
sLog.outErrorDb( "CreatureEventAI: Event %d incremented Phase above 31. Phase mask cannot be used with phases past 31. CreatureEntry = %d", EventId, m_creature.GetEntry());
sLog.outErrorDb( "CreatureEventAI: Event %d incremented Phase above 31. Phase mask cannot be used with phases past 31. CreatureEntry = %d", EventId, m_creature->GetEntry());
}
break;
case ACTION_T_EVADE:
@ -806,7 +806,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
case ACTION_T_FLEE:
{
//TODO: Replace with Flee movement generator
m_creature.CastSpell(&m_creature, SPELL_RUN_AWAY, true);
m_creature->CastSpell(m_creature, SPELL_RUN_AWAY, true);
}
break;
case ACTION_T_QUEST_EVENT_ALL:
@ -814,9 +814,9 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
Unit* Temp = NULL;
if( pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER )
{
Temp = Unit::GetUnit(m_creature,pActionInvoker->GetGUID());
Temp = Unit::GetUnit(*m_creature,pActionInvoker->GetGUID());
if( Temp )
((Player*)Temp)->GroupEventHappens(param1,&m_creature);
((Player*)Temp)->GroupEventHappens(param1,m_creature);
}
}
break;
@ -824,12 +824,12 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
{
Unit* Temp = NULL;
std::list<HostilReference*>::iterator i = m_creature.getThreatManager().getThreatList().begin();
for (; i != m_creature.getThreatManager().getThreatList().end(); ++i)
std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
for (; i != m_creature->getThreatManager().getThreatList().end(); ++i)
{
Temp = Unit::GetUnit(m_creature,(*i)->getUnitGuid());
Temp = Unit::GetUnit(*m_creature,(*i)->getUnitGuid());
if (Temp && Temp->GetTypeId() == TYPEID_PLAYER)
((Player*)Temp)->CastedCreatureOrGO(param1, m_creature.GetGUID(), param2);
((Player*)Temp)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2);
}
}
break;
@ -848,11 +848,11 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
if (CombatMovementEnabled)
{
if (m_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
{
//Drop current movement gen
m_creature.GetMotionMaster()->Clear(false);
m_creature.GetMotionMaster()->MoveChase(m_creature.getVictim(), AttackDistance, AttackAngle);
m_creature->GetMotionMaster()->Clear(false);
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle);
}
}
}
@ -871,7 +871,7 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
Phase = param1 + (rnd % (param2 - param1));
}
else
sLog.outErrorDb( "CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 <= Param1. Divide by Zero. Event = %d. CreatureEntry = %d", EventId, m_creature.GetEntry());
sLog.outErrorDb( "CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 <= Param1. Divide by Zero. Event = %d. CreatureEntry = %d", EventId, m_creature->GetEntry());
}
break;
case ACTION_T_SUMMON_ID:
@ -885,18 +885,18 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
if (i == CreatureEAI_Mgr.GetCreatureEventAISummonMap().end())
{
sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", param1, param3, EventId, m_creature.GetEntry());
sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", param1, param3, EventId, m_creature->GetEntry());
return;
}
if ((*i).second.SpawnTimeSecs)
pCreature = m_creature.SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs);
else pCreature = m_creature.SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs);
else pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
if (!pCreature)
{
sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", param1, EventId, m_creature.GetEntry());
sLog.outErrorDb( "CreatureEventAI: failed to spawn creature %u. EventId %d.Creature %d", param1, EventId, m_creature->GetEntry());
}
else if (param2 != TARGET_T_SELF && target)
pCreature->AI()->AttackStart(target);
@ -905,24 +905,24 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
case ACTION_T_KILLED_MONSTER:
{
//first attempt player who tapped creature
if (Player* pPlayer = m_creature.GetLootRecipient())
pPlayer->RewardPlayerAndGroupAtEvent(param1, &m_creature);
if (Player* pPlayer = m_creature->GetLootRecipient())
pPlayer->RewardPlayerAndGroupAtEvent(param1, m_creature);
else
{
//if not available, use pActionInvoker
Unit* pTarget = GetTargetByType(param2, pActionInvoker);
if (Player* pPlayer = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself())
pPlayer->RewardPlayerAndGroupAtEvent(param1, &m_creature);
pPlayer->RewardPlayerAndGroupAtEvent(param1, m_creature);
}
}
break;
case ACTION_T_SET_INST_DATA:
{
InstanceData* pInst = (InstanceData*)m_creature.GetInstanceData();
InstanceData* pInst = (InstanceData*)m_creature->GetInstanceData();
if (!pInst)
{
sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", EventId, m_creature.GetEntry());
sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", EventId, m_creature->GetEntry());
return;
}
@ -934,14 +934,14 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
Unit* target = GetTargetByType(param2, pActionInvoker);
if (!target)
{
sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, m_creature.GetEntry());
sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, m_creature->GetEntry());
return;
}
InstanceData* pInst = (InstanceData*)m_creature.GetInstanceData();
InstanceData* pInst = (InstanceData*)m_creature->GetInstanceData();
if (!pInst)
{
sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", EventId, m_creature.GetEntry());
sLog.outErrorDb("CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", EventId, m_creature->GetEntry());
return;
}
@ -950,37 +950,37 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u
break;
case ACTION_T_UPDATE_TEMPLATE:
{
if (m_creature.GetEntry() == param1)
if (m_creature->GetEntry() == param1)
{
sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", EventId, m_creature.GetEntry());
sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", EventId, m_creature->GetEntry());
return;
}
m_creature.UpdateEntry(param1, param2 ? HORDE : ALLIANCE);
m_creature->UpdateEntry(param1, param2 ? HORDE : ALLIANCE);
}
break;
case ACTION_T_DIE:
{
if (m_creature.isDead())
if (m_creature->isDead())
{
sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", EventId, m_creature.GetEntry());
sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", EventId, m_creature->GetEntry());
return;
}
m_creature.DealDamage(&m_creature, m_creature.GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
}
break;
case ACTION_T_ZONE_COMBAT_PULSE:
{
if (!m_creature.isInCombat() || !m_creature.GetMap()->IsDungeon())
if (!m_creature->isInCombat() || !m_creature->GetMap()->IsDungeon())
{
sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_ZONE_COMBAT_PULSE on creature out of combat or in non-dungeon map. Creature %d", EventId, m_creature.GetEntry());
sLog.outErrorDb("CreatureEventAI: Event %d ACTION_T_ZONE_COMBAT_PULSE on creature out of combat or in non-dungeon map. Creature %d", EventId, m_creature->GetEntry());
return;
}
DoZoneInCombat(&m_creature);
DoZoneInCombat(m_creature);
}
break;
}
@ -1029,7 +1029,7 @@ void CreatureEventAI::Reset()
(*i).Enabled = true;
}
else
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature.GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
}
break;
//default:
@ -1043,7 +1043,7 @@ void CreatureEventAI::Reset()
void CreatureEventAI::JustReachedHome()
{
m_creature.LoadCreaturesAddon();
m_creature->LoadCreaturesAddon();
if (!bEmptyList)
{
@ -1059,15 +1059,15 @@ void CreatureEventAI::JustReachedHome()
void CreatureEventAI::EnterEvadeMode()
{
m_creature.InterruptNonMeleeSpells(true);
m_creature.RemoveAllAuras();
m_creature.DeleteThreatList();
m_creature.CombatStop();
m_creature->InterruptNonMeleeSpells(true);
m_creature->RemoveAllAuras();
m_creature->DeleteThreatList();
m_creature->CombatStop();
if (m_creature.isAlive())
m_creature.GetMotionMaster()->MoveTargetedHome();
if (m_creature->isAlive())
m_creature->GetMotionMaster()->MoveTargetedHome();
m_creature.SetLootRecipient(NULL);
m_creature->SetLootRecipient(NULL);
InCombat = false;
@ -1148,7 +1148,7 @@ void CreatureEventAI::Aggro(Unit *who)
(*i).Enabled = true;
}
else
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature.GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
sLog.outErrorDb("CreatureEventAI: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
break;
//All normal events need to be re-enabled and their time set to 0
default:
@ -1168,11 +1168,11 @@ void CreatureEventAI::AttackStart(Unit *who)
if (!who)
return;
if (m_creature.Attack(who, MeleeEnabled))
if (m_creature->Attack(who, MeleeEnabled))
{
m_creature.AddThreat(who, 0.0f);
m_creature.SetInCombatWith(who);
who->SetInCombatWith(&m_creature);
m_creature->AddThreat(who, 0.0f);
m_creature->SetInCombatWith(who);
who->SetInCombatWith(m_creature);
if (!InCombat)
{
@ -1182,12 +1182,12 @@ void CreatureEventAI::AttackStart(Unit *who)
if (CombatMovementEnabled)
{
m_creature.GetMotionMaster()->MoveChase(who, AttackDistance, AttackAngle);
m_creature->GetMotionMaster()->MoveChase(who, AttackDistance, AttackAngle);
}
else
{
m_creature.GetMotionMaster()->MoveIdle();
m_creature.StopMoving();
m_creature->GetMotionMaster()->MoveIdle();
m_creature->StopMoving();
}
}
}
@ -1198,7 +1198,7 @@ void CreatureEventAI::MoveInLineOfSight(Unit *who)
return;
//Check for OOC LOS Event
if (!bEmptyList && !m_creature.getVictim())
if (!bEmptyList && !m_creature->getVictim())
{
for (std::list<CreatureEventAIHolder>::iterator itr = CreatureEventAIList.begin(); itr != CreatureEventAIList.end(); ++itr)
{
@ -1208,38 +1208,38 @@ void CreatureEventAI::MoveInLineOfSight(Unit *who)
float fMaxAllowedRange = (*itr).Event.event_param2;
//if range is ok and we are actually in LOS
if (m_creature.IsWithinDistInMap(who, fMaxAllowedRange) && m_creature.IsWithinLOSInMap(who))
if (m_creature->IsWithinDistInMap(who, fMaxAllowedRange) && m_creature->IsWithinLOSInMap(who))
{
//if friendly event&&who is not hostile OR hostile event&&who is hostile
if (((*itr).Event.event_param1 && !m_creature.IsHostileTo(who)) ||
((!(*itr).Event.event_param1) && m_creature.IsHostileTo(who)))
if (((*itr).Event.event_param1 && !m_creature->IsHostileTo(who)) ||
((!(*itr).Event.event_param1) && m_creature->IsHostileTo(who)))
ProcessEvent(*itr, who);
}
}
}
}
if (m_creature.isCivilian() && m_creature.IsNeutralToAll())
if (m_creature->isCivilian() && m_creature->IsNeutralToAll())
return;
if (!m_creature.hasUnitState(UNIT_STAT_STUNNED) && who->isTargetableForAttack() &&
m_creature.IsHostileTo(who) && who->isInAccessablePlaceFor(&m_creature))
if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && who->isTargetableForAttack() &&
m_creature->IsHostileTo(who) && who->isInAccessablePlaceFor(m_creature))
{
if (!m_creature.canFly() && m_creature.GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
if (!m_creature->canFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
return;
float attackRadius = m_creature.GetAttackDistance(who);
if (m_creature.IsWithinDistInMap(who, attackRadius) && m_creature.IsWithinLOSInMap(who))
float attackRadius = m_creature->GetAttackDistance(who);
if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who))
{
if (!m_creature.getVictim())
if (!m_creature->getVictim())
{
AttackStart(who);
who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
}
else if (m_creature.GetMap()->IsDungeon())
else if (m_creature->GetMap()->IsDungeon())
{
who->SetInCombatWith(&m_creature);
m_creature.AddThreat(who, 0.0f);
who->SetInCombatWith(m_creature);
m_creature->AddThreat(who, 0.0f);
}
}
}
@ -1268,10 +1268,10 @@ void CreatureEventAI::SpellHit(Unit* pUnit, const SpellEntry* pSpell)
void CreatureEventAI::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() && m_creature->getVictim()) : false;
//Must return if creature isn't alive. Normally select hostil target and get victim prevent this
if (!m_creature.isAlive())
if (!m_creature->isAlive())
return;
if (!bEmptyList)
@ -1317,9 +1317,9 @@ void CreatureEventAI::UpdateAI(const uint32 diff)
case EVENT_T_RANGE:
if (Combat)
{
if (m_creature.IsWithinDistInMap(m_creature.getVictim(),(float)(*i).Event.event_param2))
if (m_creature->IsWithinDistInMap(m_creature->getVictim(),(float)(*i).Event.event_param2))
{
if (m_creature.GetDistance(m_creature.getVictim()) >= (float)(*i).Event.event_param1)
if (m_creature->GetDistance(m_creature->getVictim()) >= (float)(*i).Event.event_param1)
ProcessEvent(*i);
}
}
@ -1344,14 +1344,14 @@ void CreatureEventAI::UpdateAI(const uint32 diff)
bool CreatureEventAI::IsVisible(Unit *pl) const
{
return m_creature.GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER)
&& pl->isVisibleForOrDetect(&m_creature,true);
return m_creature->GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER)
&& pl->isVisibleForOrDetect(m_creature,true);
}
inline Unit* CreatureEventAI::SelectUnit(AttackingTarget target, uint32 position)
{
//ThreatList m_threatlist;
std::list<HostilReference*>& m_threatlist = m_creature.getThreatManager().getThreatList();
std::list<HostilReference*>& m_threatlist = m_creature->getThreatManager().getThreatList();
std::list<HostilReference*>::iterator i = m_threatlist.begin();
std::list<HostilReference*>::reverse_iterator r = m_threatlist.rbegin();
@ -1363,17 +1363,17 @@ inline Unit* CreatureEventAI::SelectUnit(AttackingTarget target, uint32 position
case ATTACKING_TARGET_RANDOM:
{
advance ( i , position + (rand() % (m_threatlist.size() - position ) ));
return Unit::GetUnit(m_creature,(*i)->getUnitGuid());
return Unit::GetUnit(*m_creature,(*i)->getUnitGuid());
}
case ATTACKING_TARGET_TOPAGGRO:
{
advance ( i , position);
return Unit::GetUnit(m_creature,(*i)->getUnitGuid());
return Unit::GetUnit(*m_creature,(*i)->getUnitGuid());
}
case ATTACKING_TARGET_BOTTOMAGGRO:
{
advance ( r , position);
return Unit::GetUnit(m_creature,(*r)->getUnitGuid());
return Unit::GetUnit(*m_creature,(*r)->getUnitGuid());
}
}
return NULL;
@ -1401,10 +1401,10 @@ inline Unit* CreatureEventAI::GetTargetByType(uint32 Target, Unit* pActionInvoke
switch (Target)
{
case TARGET_T_SELF:
return &m_creature;
return m_creature;
break;
case TARGET_T_HOSTILE:
return m_creature.getVictim();
return m_creature->getVictim();
break;
case TARGET_T_HOSTILE_SECOND_AGGRO:
return SelectUnit(ATTACKING_TARGET_TOPAGGRO,1);
@ -1429,15 +1429,15 @@ inline Unit* CreatureEventAI::GetTargetByType(uint32 Target, Unit* pActionInvoke
Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff)
{
CellPair p(MaNGOS::ComputeCellPair(m_creature.GetPositionX(), m_creature.GetPositionY()));
CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
Unit* pUnit = NULL;
MaNGOS::MostHPMissingInRange u_check(&m_creature, range, MinHPDiff);
MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange> searcher(&m_creature, pUnit, u_check);
MaNGOS::MostHPMissingInRange u_check(m_creature, range, MinHPDiff);
MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange> searcher(m_creature, pUnit, u_check);
/*
typedef TYPELIST_4(GameObject, Creature*except pets*, DynamicObject, Corpse*Bones*) AllGridObjectTypes;
@ -1446,40 +1446,40 @@ Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff)
TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_creature.GetMap());
cell_lock->Visit(cell_lock, grid_unit_searcher, *m_creature->GetMap());
return pUnit;
}
void CreatureEventAI::DoFindFriendlyCC(std::list<Creature*>& _list, float range)
{
CellPair p(MaNGOS::ComputeCellPair(m_creature.GetPositionX(), m_creature.GetPositionY()));
CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
MaNGOS::FriendlyCCedInRange u_check(&m_creature, range);
MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange> searcher(&m_creature, _list, u_check);
MaNGOS::FriendlyCCedInRange u_check(m_creature, range);
MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange> searcher(m_creature, _list, u_check);
TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature.GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap());
}
void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid)
{
CellPair p(MaNGOS::ComputeCellPair(m_creature.GetPositionX(), m_creature.GetPositionY()));
CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
MaNGOS::FriendlyMissingBuffInRange u_check(&m_creature, range, spellid);
MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange> searcher(&m_creature, _list, u_check);
MaNGOS::FriendlyMissingBuffInRange u_check(m_creature, range, spellid);
MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange> searcher(m_creature, _list, u_check);
TypeContainerVisitor<MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature.GetMap());
cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap());
}
//*********************************
@ -1562,7 +1562,7 @@ void CreatureEventAI::DoScriptText(int32 textEntry, WorldObject* pSource, Unit*
void CreatureEventAI::DoZoneInCombat(Unit* pUnit)
{
if (!pUnit)
pUnit = &m_creature;
pUnit = m_creature;
Map *map = pUnit->GetMap();
@ -1589,13 +1589,13 @@ void CreatureEventAI::DoZoneInCombat(Unit* pUnit)
void CreatureEventAI::DoMeleeAttackIfReady()
{
//Make sure our attack is ready before checking distance
if (m_creature.isAttackReady())
if (m_creature->isAttackReady())
{
//If we are within range melee the target
if (m_creature.IsWithinDistInMap(m_creature.getVictim(), ATTACK_DISTANCE))
if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
m_creature.AttackerStateUpdate(m_creature.getVictim());
m_creature.resetAttackTimer();
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
}
}
}
@ -1607,11 +1607,11 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge
return false;
//Silenced so we can't cast
if (!Triggered && m_creature.HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
if (!Triggered && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
return false;
//Check for power
if (!Triggered && m_creature.GetPower((Powers)Spell->powerType) < Spell->manaCost)
if (!Triggered && m_creature->GetPower((Powers)Spell->powerType) < Spell->manaCost)
return false;
SpellRangeEntry const *TempRange = NULL;
@ -1623,7 +1623,7 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge
return false;
//Unit is out of range of this spell
if (m_creature.GetDistance(Target) > TempRange->maxRange || m_creature.GetDistance(Target) < TempRange->minRange)
if (m_creature->GetDistance(Target) > TempRange->maxRange || m_creature->GetDistance(Target) < TempRange->minRange)
return false;
return true;

View file

@ -247,7 +247,7 @@ class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI
{
public:
CreatureEventAI(Creature &c);
explicit CreatureEventAI(Creature *c);
~CreatureEventAI()
{
CreatureEventAIList.clear();
@ -283,12 +283,8 @@ class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI
void DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid);
void DoFindFriendlyCC(std::list<Creature*>& _list, float range);
//Pointer to creature we are manipulating
Creature& m_creature;
//Bool for if we are in combat or not
bool InCombat;
//Holder for events (stores enabled, time, and eventid)
std::list<CreatureEventAIHolder> CreatureEventAIList;
uint32 EventUpdateTime; //Time between event updates

View file

@ -1633,6 +1633,7 @@ struct WorldMapAreaEntry
float x1; // 6
float x2; // 7
int32 virtual_map_id; // 8 -1 (map_id have correct map) other: virtual map where zone show (map_id - where zone in fact internally)
// int32 dungeonMap_id; // 9 pointer to DungeonMap.dbc (owerride x1,x2,y1,y2 coordinates)
};
struct WorldSafeLocsEntry

View file

@ -31,22 +31,22 @@ 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_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK)
{
}
void GuardAI::MoveInLineOfSight(Unit *u)
{
// Ignore Z for flying creatures
if ( !i_creature.canFly() && i_creature.GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE )
if (!m_creature->canFly() && m_creature->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE)
return;
if( !i_creature.getVictim() && u->isTargetableForAttack() &&
( u->IsHostileToPlayers() || i_creature.IsHostileTo(u) /*|| u->getVictim() && i_creature.IsFriendlyTo(u->getVictim())*/ ) &&
u->isInAccessablePlaceFor(&i_creature))
if (!m_creature->getVictim() && u->isTargetableForAttack() &&
( u->IsHostileToPlayers() || m_creature->IsHostileTo(u) /*|| u->getVictim() && m_creature->IsFriendlyTo(u->getVictim())*/ ) &&
u->isInAccessablePlaceFor(m_creature))
{
float attackRadius = i_creature.GetAttackDistance(u);
if(i_creature.IsWithinDistInMap(u,attackRadius))
float attackRadius = m_creature->GetAttackDistance(u);
if (m_creature->IsWithinDistInMap(u,attackRadius))
{
//Need add code to let guard support player
AttackStart(u);
@ -57,76 +57,76 @@ void GuardAI::MoveInLineOfSight(Unit *u)
void GuardAI::EnterEvadeMode()
{
if( !i_creature.isAlive() )
if (!m_creature->isAlive())
{
DEBUG_LOG("Creature stopped attacking because he's dead [guid=%u]", i_creature.GetGUIDLow());
i_creature.StopMoving();
i_creature.GetMotionMaster()->MoveIdle();
DEBUG_LOG("Creature stopped attacking because he's dead [guid=%u]", m_creature->GetGUIDLow());
m_creature->StopMoving();
m_creature->GetMotionMaster()->MoveIdle();
i_state = STATE_NORMAL;
i_victimGuid = 0;
i_creature.CombatStop();
i_creature.DeleteThreatList();
m_creature->CombatStop();
m_creature->DeleteThreatList();
return;
}
Unit* victim = ObjectAccessor::GetUnit(i_creature, i_victimGuid );
Unit* victim = ObjectAccessor::GetUnit(*m_creature, i_victimGuid );
if( !victim )
if (!victim)
{
DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", m_creature->GetGUIDLow());
}
else if( !victim ->isAlive() )
else if (!victim->isAlive())
{
DEBUG_LOG("Creature stopped attacking because victim is dead [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking because victim is dead [guid=%u]", m_creature->GetGUIDLow());
}
else if( victim ->HasStealthAura() )
else if (victim->HasStealthAura())
{
DEBUG_LOG("Creature stopped attacking because victim is using stealth [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking because victim is using stealth [guid=%u]", m_creature->GetGUIDLow());
}
else if( victim ->isInFlight() )
else if (victim->isInFlight())
{
DEBUG_LOG("Creature stopped attacking because victim is flying away [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking because victim is flying away [guid=%u]", m_creature->GetGUIDLow());
}
else
{
DEBUG_LOG("Creature stopped attacking because victim outran him [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking because victim outran him [guid=%u]", m_creature->GetGUIDLow());
}
i_creature.RemoveAllAuras();
i_creature.DeleteThreatList();
m_creature->RemoveAllAuras();
m_creature->DeleteThreatList();
i_victimGuid = 0;
i_creature.CombatStop();
m_creature->CombatStop();
i_state = STATE_NORMAL;
// Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE )
i_creature.GetMotionMaster()->MoveTargetedHome();
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
m_creature->GetMotionMaster()->MoveTargetedHome();
}
void GuardAI::UpdateAI(const uint32 /*diff*/)
{
// update i_victimGuid if i_creature.getVictim() !=0 and changed
if(!i_creature.SelectHostilTarget() || !i_creature.getVictim())
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
return;
i_victimGuid = i_creature.getVictim()->GetGUID();
i_victimGuid = m_creature->getVictim()->GetGUID();
if( i_creature.isAttackReady() )
if (m_creature->isAttackReady())
{
if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DISTANCE))
if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
i_creature.AttackerStateUpdate(i_creature.getVictim());
i_creature.resetAttackTimer();
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
}
}
}
bool GuardAI::IsVisible(Unit *pl) const
{
return i_creature.GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_GUARDER)
&& pl->isVisibleForOrDetect(&i_creature,true);
return m_creature->GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_GUARDER)
&& pl->isVisibleForOrDetect(m_creature,true);
}
void GuardAI::AttackStart(Unit *u)
@ -135,19 +135,19 @@ void GuardAI::AttackStart(Unit *u)
return;
// DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", i_creature.GetName(), u->GetGUIDLow());
if(i_creature.Attack(u,true))
if(m_creature->Attack(u,true))
{
i_creature.SetInCombatWith(u);
u->SetInCombatWith(&i_creature);
m_creature->SetInCombatWith(u);
u->SetInCombatWith(m_creature);
i_creature.AddThreat(u, 0.0f);
m_creature->AddThreat(u, 0.0f);
i_victimGuid = u->GetGUID();
i_creature.GetMotionMaster()->MoveChase(u);
m_creature->GetMotionMaster()->MoveChase(u);
}
}
void GuardAI::JustDied(Unit *killer)
{
if(Player* pkiller = killer->GetCharmerOrOwnerPlayerOrPlayerItself())
i_creature.SendZoneUnderAttackMessage(pkiller);
m_creature->SendZoneUnderAttackMessage(pkiller);
}

View file

@ -34,7 +34,7 @@ class MANGOS_DLL_DECL GuardAI : public CreatureAI
public:
GuardAI(Creature &c);
explicit GuardAI(Creature *c);
void MoveInLineOfSight(Unit *);
void AttackStart(Unit *);
@ -46,7 +46,6 @@ class MANGOS_DLL_DECL GuardAI : public CreatureAI
static int Permissible(const Creature *);
private:
Creature &i_creature;
uint64 i_victimGuid;
GuardState i_state;
TimeTracker i_tracker;

View file

@ -905,7 +905,7 @@ void WorldSession::HandleGuildBankQuery( WorldPacket & recv_data )
uint8 unk;
recv_data >> GoGuid >> unk;
if (!objmgr.IsGuildVaultGameObject(_player, GoGuid))
if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
return;
if (uint32 GuildId = GetPlayer()->GetGuildId())
@ -929,7 +929,7 @@ void WorldSession::HandleGuildBankTabColon( WorldPacket & recv_data )
uint8 TabId,unk1;
recv_data >> GoGuid >> TabId >> unk1;
if (!objmgr.IsGuildVaultGameObject(_player, GoGuid))
if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
return;
uint32 GuildId = GetPlayer()->GetGuildId();
@ -958,7 +958,7 @@ void WorldSession::HandleGuildBankDeposit( WorldPacket & recv_data )
if (!money)
return;
if (!objmgr.IsGuildVaultGameObject(_player, GoGuid))
if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
return;
uint32 GuildId = GetPlayer()->GetGuildId();
@ -1006,7 +1006,7 @@ void WorldSession::HandleGuildBankWithdraw( WorldPacket & recv_data )
if (!money)
return;
if (!objmgr.IsGuildVaultGameObject(_player, GoGuid))
if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
return;
uint32 GuildId = GetPlayer()->GetGuildId();
@ -1107,7 +1107,7 @@ void WorldSession::HandleGuildBankDepositItem( WorldPacket & recv_data )
return;
}
if (!objmgr.IsGuildVaultGameObject(_player, GoGuid))
if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
return;
uint32 GuildId = GetPlayer()->GetGuildId();
@ -1562,7 +1562,7 @@ void WorldSession::HandleGuildBankBuyTab( WorldPacket & recv_data )
recv_data >> GoGuid;
recv_data >> TabId;
if (!objmgr.IsGuildVaultGameObject(_player, GoGuid))
if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
return;
uint32 GuildId = GetPlayer()->GetGuildId();
@ -1619,7 +1619,7 @@ void WorldSession::HandleGuildBankModifyTab( WorldPacket & recv_data )
if(IconIndex.empty())
return;
if (!objmgr.IsGuildVaultGameObject(_player, GoGuid))
if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
return;
uint32 GuildId = GetPlayer()->GetGuildId();

View file

@ -826,10 +826,23 @@ void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data )
_player->StoreItem( dest, pItem, true );
}
void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& /*recvPacket*/)
void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket)
{
CHECK_PACKET_SIZE(recvPacket, 8);
sLog.outDebug("WORLD: CMSG_BUY_BANK_SLOT");
uint64 guid;
recvPacket >> guid;
// cheating protection
Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_BANKER);
if(!pCreature)
{
sLog.outDebug( "WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
return;
}
uint32 slot = _player->GetByteValue(PLAYER_BYTES_2, 2);
// next slot

View file

@ -52,6 +52,9 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
recv_data >> mailbox;
recv_data >> receiver;
if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
// recheck
CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+1+1+4+4+1+4+4+8+1);
@ -274,6 +277,10 @@ void WorldSession::HandleMarkAsRead(WorldPacket & recv_data )
uint64 mailbox;
uint32 mailId;
recv_data >> mailbox;
if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
recv_data >> mailId;
Player *pl = _player;
Mail *m = pl->GetMail(mailId);
@ -297,6 +304,10 @@ void WorldSession::HandleMailDelete(WorldPacket & recv_data )
uint32 mailId;
recv_data >> mailbox;
recv_data >> mailId;
if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
Player* pl = _player;
pl->m_mailsUpdated = true;
Mail *m = pl->GetMail(mailId);
@ -312,6 +323,10 @@ void WorldSession::HandleReturnToSender(WorldPacket & recv_data )
uint64 mailbox;
uint32 mailId;
recv_data >> mailbox;
if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
recv_data >> mailId;
Player *pl = _player;
Mail *m = pl->GetMail(mailId);
@ -409,6 +424,10 @@ void WorldSession::HandleTakeItem(WorldPacket & recv_data )
uint32 mailId;
uint32 itemId;
recv_data >> mailbox;
if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
recv_data >> mailId;
recv_data >> itemId; // item guid low?
Player* pl = _player;
@ -500,6 +519,10 @@ void WorldSession::HandleTakeMoney(WorldPacket & recv_data )
uint32 mailId;
recv_data >> mailbox;
recv_data >> mailId;
if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
Player *pl = _player;
Mail* m = pl->GetMail(mailId);
@ -531,9 +554,8 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data )
uint64 mailbox;
recv_data >> mailbox;
//GameObject* obj = ObjectAccessor::GetGameObject(_player, mailbox);
//if(!obj || !obj->IsMailBox())
// return;
if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
Player* pl = _player;
@ -669,6 +691,9 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data )
recv_data >> mailbox >> mailId;
if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX))
return;
Player *pl = _player;
Mail* m = pl->GetMail(mailId);

View file

@ -25,13 +25,12 @@ class MANGOS_DLL_DECL NullCreatureAI : public CreatureAI
{
public:
NullCreatureAI(Creature &) {}
NullCreatureAI() {}
explicit NullCreatureAI(Creature* c) : CreatureAI(c) {}
~NullCreatureAI();
void MoveInLineOfSight(Unit *) {}
void AttackStart(Unit *) {}
void AttackedBy( Unit *) {}
void EnterEvadeMode() {}
bool IsVisible(Unit *) const { return false; }

View file

@ -529,6 +529,18 @@ void ObjectMgr::LoadCreatureTemplates()
continue;
}
if(heroicInfo->AIName && *heroicInfo->AIName)
{
sLog.outErrorDb("Heroic mode creature (Entry: %u) has `AIName`, but in any case will used normal mode creature (Entry: %u) AIName.",cInfo->HeroicEntry,i);
continue;
}
if(heroicInfo->ScriptID)
{
sLog.outErrorDb("Heroic mode creature (Entry: %u) has `ScriptName`, but in any case will used normal mode creature (Entry: %u) ScriptName.",cInfo->HeroicEntry,i);
continue;
}
hasHeroicEntries.insert(i);
heroicEntries.insert(cInfo->HeroicEntry);
}
@ -4155,6 +4167,23 @@ void ObjectMgr::LoadInstanceTemplate()
sLog.outString();
}
bool ObjectMgr::IsGameObjectOfTypeInRange(Player *player, uint64 guid, GameobjectTypes type) const
{
if(GameObject *go = ObjectAccessor::GetGameObject(*player, guid))
{
if(go->GetGoType() == type)
{
// TODO: find out how the client calculates the maximal usage distance to spellless working
// gameobjects like guildbanks and mailboxes - 10.0 is a just an abitrary choosen number
if (go->IsWithinDistInMap(player, 10.0f))
return true;
sLog.outError("IsGameObjectOfTypeInRange: GameObject '%s' [GUID: %u] is too far away from player %s [GUID: %u] to be used by him (distance=%f, maximal 10 is allowed)", go->GetGOInfo()->name,
go->GetGUIDLow(), player->GetName(), player->GetGUIDLow(), go->GetDistance(player));
}
}
return false;
}
GossipText const *ObjectMgr::GetGossipText(uint32 Text_ID) const
{
GossipTextMap::const_iterator itr = mGossipText.find(Text_ID);

View file

@ -417,13 +417,7 @@ class ObjectMgr
return mGameObjectForQuestSet.find(entry) != mGameObjectForQuestSet.end();
}
bool IsGuildVaultGameObject(Player *player, uint64 guid) const
{
if(GameObject *go = ObjectAccessor::GetGameObject(*player, guid))
if(go->GetGoType() == GAMEOBJECT_TYPE_GUILD_BANK)
return true;
return false;
}
bool IsGameObjectOfTypeInRange(Player *player, uint64 guid, GameobjectTypes type) const;
GossipText const* GetGossipText(uint32 Text_ID) const;

View file

@ -36,7 +36,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_tracker(TIME_INTERVAL_LOOK), inCombat(false)
{
m_AllySet.clear();
UpdateAllies();
@ -44,15 +44,15 @@ PetAI::PetAI(Creature &c) : i_pet(c), i_tracker(TIME_INTERVAL_LOOK), inCombat(fa
void PetAI::MoveInLineOfSight(Unit *u)
{
if( !i_pet.getVictim() && i_pet.GetCharmInfo() &&
i_pet.GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) &&
u->isTargetableForAttack() && i_pet.IsHostileTo( u ) &&
u->isInAccessablePlaceFor(&i_pet))
if( !m_creature->getVictim() && m_creature->GetCharmInfo() &&
m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) &&
u->isTargetableForAttack() && m_creature->IsHostileTo( u ) &&
u->isInAccessablePlaceFor(m_creature))
{
float attackRadius = i_pet.GetAttackDistance(u);
if(i_pet.IsWithinDistInMap(u, attackRadius) && i_pet.GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE)
float attackRadius = m_creature->GetAttackDistance(u);
if(m_creature->IsWithinDistInMap(u, attackRadius) && m_creature->GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE)
{
if(i_pet.IsWithinLOSInMap(u))
if(m_creature->IsWithinLOSInMap(u))
{
AttackStart(u);
u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
@ -63,17 +63,17 @@ void PetAI::MoveInLineOfSight(Unit *u)
void PetAI::AttackStart(Unit *u)
{
if( inCombat || !u || (i_pet.isPet() && ((Pet&)i_pet).getPetType() == MINI_PET) )
if( inCombat || !u || (m_creature->isPet() && ((Pet&)m_creature).getPetType() == MINI_PET) )
return;
if(i_pet.Attack(u,true))
if(m_creature->Attack(u,true))
{
i_pet.clearUnitState(UNIT_STAT_FOLLOW);
m_creature->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
// hope it doesn't start to leak memory without this :-/
//i_pet->Clear();
i_pet.GetMotionMaster()->MoveChase(u);
m_creature->GetMotionMaster()->MoveChase(u);
inCombat = true;
}
}
@ -90,48 +90,48 @@ bool PetAI::IsVisible(Unit *pl) const
bool PetAI::_needToStop() const
{
// This is needed for charmed creatures, as once their target was reset other effects can trigger threat
if(i_pet.isCharmed() && i_pet.getVictim() == i_pet.GetCharmer())
if(m_creature->isCharmed() && m_creature->getVictim() == m_creature->GetCharmer())
return true;
return !i_pet.getVictim()->isTargetableForAttack();
return !m_creature->getVictim()->isTargetableForAttack();
}
void PetAI::_stopAttack()
{
inCombat = false;
if( !i_pet.isAlive() )
if( !m_creature->isAlive() )
{
DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", i_pet.GetGUIDLow());
i_pet.StopMoving();
i_pet.GetMotionMaster()->Clear();
i_pet.GetMotionMaster()->MoveIdle();
i_pet.CombatStop();
i_pet.getHostilRefManager().deleteReferences();
DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", m_creature->GetGUIDLow());
m_creature->StopMoving();
m_creature->GetMotionMaster()->Clear();
m_creature->GetMotionMaster()->MoveIdle();
m_creature->CombatStop();
m_creature->getHostilRefManager().deleteReferences();
return;
}
Unit* owner = i_pet.GetCharmerOrOwner();
Unit* owner = m_creature->GetCharmerOrOwner();
if(owner && i_pet.GetCharmInfo() && i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
if(owner && m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
{
i_pet.GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
}
else
{
i_pet.clearUnitState(UNIT_STAT_FOLLOW);
i_pet.GetMotionMaster()->Clear();
i_pet.GetMotionMaster()->MoveIdle();
m_creature->clearUnitState(UNIT_STAT_FOLLOW);
m_creature->GetMotionMaster()->Clear();
m_creature->GetMotionMaster()->MoveIdle();
}
i_pet.AttackStop();
m_creature->AttackStop();
}
void PetAI::UpdateAI(const uint32 diff)
{
if (!i_pet.isAlive())
if (!m_creature->isAlive())
return;
Unit* owner = i_pet.GetCharmerOrOwner();
Unit* owner = m_creature->GetCharmerOrOwner();
if(m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
@ -139,67 +139,67 @@ void PetAI::UpdateAI(const uint32 diff)
else
m_updateAlliesTimer -= diff;
if (inCombat && !i_pet.getVictim())
if (inCombat && !m_creature->getVictim())
_stopAttack();
// i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
if( i_pet.getVictim() )
if (m_creature->getVictim())
{
if( _needToStop() )
if (_needToStop())
{
DEBUG_LOG("Pet AI stoped attacking [guid=%u]", i_pet.GetGUIDLow());
DEBUG_LOG("Pet AI stoped attacking [guid=%u]", m_creature->GetGUIDLow());
_stopAttack();
return;
}
else if( i_pet.IsStopped() || i_pet.IsWithinDistInMap(i_pet.getVictim(), ATTACK_DISTANCE))
else if (m_creature->IsStopped() || m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
// required to be stopped cases
if ( i_pet.IsStopped() && i_pet.IsNonMeleeSpellCasted(false) )
if (m_creature->IsStopped() && m_creature->IsNonMeleeSpellCasted(false))
{
if( i_pet.hasUnitState(UNIT_STAT_FOLLOW) )
i_pet.InterruptNonMeleeSpells(false);
if (m_creature->hasUnitState(UNIT_STAT_FOLLOW))
m_creature->InterruptNonMeleeSpells(false);
else
return;
}
// not required to be stopped case
else if( i_pet.isAttackReady() && i_pet.canReachWithAttack(i_pet.getVictim()) )
else if (m_creature->isAttackReady() && m_creature->canReachWithAttack(m_creature->getVictim()))
{
i_pet.AttackerStateUpdate(i_pet.getVictim());
m_creature->AttackerStateUpdate(m_creature->getVictim());
i_pet.resetAttackTimer();
m_creature->resetAttackTimer();
if ( !i_pet.getVictim() )
if (!m_creature->getVictim())
return;
//if pet misses its target, it will also be the first in threat list
i_pet.getVictim()->AddThreat(&i_pet,0.0f);
m_creature->getVictim()->AddThreat(m_creature,0.0f);
if( _needToStop() )
_stopAttack();
}
}
}
else if(owner && i_pet.GetCharmInfo())
else if (owner && m_creature->GetCharmInfo())
{
if(owner->isInCombat() && !(i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) || i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY)))
if (owner->isInCombat() && !(m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) || m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY)))
{
AttackStart(owner->getAttackerForHelper());
}
else if(i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
else if(m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
{
if (!i_pet.hasUnitState(UNIT_STAT_FOLLOW) )
if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW) )
{
i_pet.GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE);
}
}
}
if (i_pet.GetGlobalCooldown() == 0 && !i_pet.IsNonMeleeSpellCasted(false))
if (m_creature->GetGlobalCooldown() == 0 && !m_creature->IsNonMeleeSpellCasted(false))
{
//Autocast
for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++)
for (uint8 i = 0; i < m_creature->GetPetAutoSpellSize(); i++)
{
uint32 spellID = i_pet.GetPetAutoSpellOnPos(i);
uint32 spellID = m_creature->GetPetAutoSpellOnPos(i);
if (!spellID)
continue;
@ -219,11 +219,11 @@ void PetAI::UpdateAI(const uint32 diff)
continue;
}
Spell *spell = new Spell(&i_pet, spellInfo, false, 0);
Spell *spell = new Spell(m_creature, spellInfo, false, 0);
if(inCombat && !i_pet.hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(i_pet.getVictim()))
if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim()))
{
m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(i_pet.getVictim(), spell));
m_targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(m_creature->getVictim(), spell));
continue;
}
else
@ -231,7 +231,7 @@ void PetAI::UpdateAI(const uint32 diff)
bool spellUsed = false;
for(std::set<uint64>::iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
{
Unit* Target = ObjectAccessor::GetUnit(i_pet,*tar);
Unit* Target = ObjectAccessor::GetUnit(*m_creature,*tar);
//only buff targets that are in combat, unless the spell can only be cast while out of combat
if(!Target)
@ -250,7 +250,7 @@ void PetAI::UpdateAI(const uint32 diff)
}
//found units to cast on to
if(!m_targetSpellStore.empty())
if (!m_targetSpellStore.empty())
{
uint32 index = urand(0, m_targetSpellStore.size() - 1);
@ -262,19 +262,19 @@ void PetAI::UpdateAI(const uint32 diff)
SpellCastTargets targets;
targets.setUnitTarget( target );
if( !i_pet.HasInArc(M_PI, target) )
if (!m_creature->HasInArc(M_PI, target))
{
i_pet.SetInFront(target);
if( target->GetTypeId() == TYPEID_PLAYER )
i_pet.SendUpdateToPlayer( (Player*)target );
m_creature->SetInFront(target);
if (target->GetTypeId() == TYPEID_PLAYER)
m_creature->SendUpdateToPlayer((Player*)target);
if(owner && owner->GetTypeId() == TYPEID_PLAYER)
i_pet.SendUpdateToPlayer( (Player*)owner );
if (owner && owner->GetTypeId() == TYPEID_PLAYER)
m_creature->SendUpdateToPlayer( (Player*)owner );
}
i_pet.AddCreatureSpellCooldown(spell->m_spellInfo->Id);
if(i_pet.isPet())
((Pet*)&i_pet)->CheckLearning(spell->m_spellInfo->Id);
m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id);
if (m_creature->isPet())
((Pet&)m_creature).CheckLearning(spell->m_spellInfo->Id);
spell->prepare(&targets);
}
@ -289,13 +289,13 @@ 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);
return m_creature->GetDistance(u) < sWorld.getConfig(CONFIG_SIGHT_GUARDER)
&& u->isVisibleForOrDetect(m_creature,true);
}
void PetAI::UpdateAllies()
{
Unit* owner = i_pet.GetCharmerOrOwner();
Unit* owner = m_creature->GetCharmerOrOwner();
Group *pGroup = NULL;
m_updateAlliesTimer = 10*IN_MILISECONDS; //update friendly targets every 10 seconds, lesser checks increase performance
@ -313,7 +313,7 @@ void PetAI::UpdateAllies()
return;
m_AllySet.clear();
m_AllySet.insert(i_pet.GetGUID());
m_AllySet.insert(m_creature->GetGUID());
if(pGroup) //add group
{
for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
@ -335,7 +335,7 @@ void PetAI::UpdateAllies()
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.canReachWithAttack(attacker)))
if(!m_creature->getVictim() && m_creature->GetCharmInfo() && !m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) &&
(!m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY) || m_creature->canReachWithAttack(attacker)))
AttackStart(attacker);
}

View file

@ -29,12 +29,11 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI
{
public:
PetAI(Creature &c);
explicit 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(); }
@ -49,7 +48,6 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI
void UpdateAllies();
Creature &i_pet;
bool inCombat;
TimeTracker i_tracker;
std::set<uint64> m_AllySet;

View file

@ -9289,7 +9289,6 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const
if (b_found) continue;
/* until proper implementation
if(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS)
{
for(uint32 t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t)
@ -9304,7 +9303,6 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const
}
if (b_found) continue;
*/
for(int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; t++)
{

View file

@ -24,7 +24,7 @@
#include "ObjectMgr.h"
// Character Dump tables
#define DUMP_TABLE_COUNT 19
#define DUMP_TABLE_COUNT 21
struct DumpTable
{
@ -35,6 +35,8 @@ struct DumpTable
static DumpTable dumpTables[DUMP_TABLE_COUNT] =
{
{ "characters", DTT_CHARACTER },
{ "character_achievement", DTT_CHAR_TABLE },
{ "character_achievement_progress", DTT_CHAR_TABLE },
{ "character_queststatus", DTT_CHAR_TABLE },
{ "character_reputation", DTT_CHAR_TABLE },
{ "character_spell", DTT_CHAR_TABLE },

View file

@ -27,10 +27,10 @@ enum DumpTableType
{
DTT_CHARACTER, // // characters
DTT_CHAR_TABLE, // // character_action, character_aura, character_homebind,
// character_queststatus, character_reputation,
// character_spell, character_spell_cooldown, character_ticket,
// character_tutorial
DTT_CHAR_TABLE, // // character_achievement, character_achievement_progress,
// character_action, character_aura, character_homebind,
// character_queststatus, character_reputation, character_spell,
// character_spell_cooldown, character_ticket, character_tutorial
DTT_INVENTORY, // -> item guids collection // character_inventory

View file

@ -45,15 +45,15 @@ ReactorAI::AttackStart(Unit *p)
if(!p)
return;
if(i_creature.Attack(p,true))
if(m_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);
m_creature->SetInCombatWith(p);
p->SetInCombatWith(m_creature);
i_creature.AddThreat(p, 0.0f);
m_creature->AddThreat(p, 0.0f);
i_victimGuid = p->GetGUID();
i_creature.GetMotionMaster()->MoveChase(p);
m_creature->GetMotionMaster()->MoveChase(p);
}
}
@ -67,17 +67,17 @@ 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(!m_creature->SelectHostilTarget() || !m_creature->getVictim())
return;
i_victimGuid = i_creature.getVictim()->GetGUID();
i_victimGuid = m_creature->getVictim()->GetGUID();
if( i_creature.isAttackReady() )
if( m_creature->isAttackReady() )
{
if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DISTANCE))
if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
{
i_creature.AttackerStateUpdate(i_creature.getVictim());
i_creature.resetAttackTimer();
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
}
}
}
@ -85,43 +85,43 @@ ReactorAI::UpdateAI(const uint32 /*time_diff*/)
void
ReactorAI::EnterEvadeMode()
{
if( !i_creature.isAlive() )
if( !m_creature->isAlive() )
{
DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", i_creature.GetGUIDLow());
i_creature.GetMotionMaster()->MovementExpired();
i_creature.GetMotionMaster()->MoveIdle();
DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", m_creature->GetGUIDLow());
m_creature->GetMotionMaster()->MovementExpired();
m_creature->GetMotionMaster()->MoveIdle();
i_victimGuid = 0;
i_creature.CombatStop();
i_creature.DeleteThreatList();
m_creature->CombatStop();
m_creature->DeleteThreatList();
return;
}
Unit* victim = ObjectAccessor::GetUnit(i_creature, i_victimGuid );
Unit* victim = ObjectAccessor::GetUnit(*m_creature, i_victimGuid );
if( !victim )
{
DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", m_creature->GetGUIDLow());
}
else if( victim->HasStealthAura() )
{
DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", m_creature->GetGUIDLow());
}
else if( victim->isInFlight() )
{
DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", m_creature->GetGUIDLow());
}
else
{
DEBUG_LOG("Creature stopped attacking due to target %s [guid=%u]", victim->isAlive() ? "out run him" : "is dead", i_creature.GetGUIDLow());
DEBUG_LOG("Creature stopped attacking due to target %s [guid=%u]", victim->isAlive() ? "out run him" : "is dead", m_creature->GetGUIDLow());
}
i_creature.RemoveAllAuras();
i_creature.DeleteThreatList();
m_creature->RemoveAllAuras();
m_creature->DeleteThreatList();
i_victimGuid = 0;
i_creature.CombatStop();
i_creature.SetLootRecipient(NULL);
m_creature->CombatStop();
m_creature->SetLootRecipient(NULL);
// Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE )
i_creature.GetMotionMaster()->MoveTargetedHome();
if( m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE )
m_creature->GetMotionMaster()->MoveTargetedHome();
}

View file

@ -27,7 +27,7 @@ class MANGOS_DLL_DECL ReactorAI : public CreatureAI
{
public:
ReactorAI(Creature &c) : i_creature(c), i_victimGuid(0) {}
explicit ReactorAI(Creature *c) : CreatureAI(c), i_victimGuid(0) {}
void MoveInLineOfSight(Unit *);
void AttackStart(Unit *);
@ -38,7 +38,6 @@ class MANGOS_DLL_DECL ReactorAI : public CreatureAI
static int Permissible(const Creature *);
private:
Creature &i_creature;
uint64 i_victimGuid;
};
#endif

View file

@ -1140,7 +1140,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
unit->SetStandState(UNIT_STAND_STATE_STAND);
if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI())
((Creature*)unit)->AI()->AttackStart(m_caster);
((Creature*)unit)->AI()->AttackedBy(m_caster);
unit->SetInCombatWith(m_caster);
m_caster->SetInCombatWith(unit);

View file

@ -2767,13 +2767,13 @@ void Aura::HandleAuraTransform(bool apply, bool Real)
if (apply)
{
// special case (spell specific functionality)
if(m_modifier.m_miscvalue==0)
if (m_modifier.m_miscvalue==0)
{
// player applied only
if(m_target->GetTypeId()!=TYPEID_PLAYER)
if (m_target->GetTypeId()!=TYPEID_PLAYER)
return;
switch(GetId())
switch (GetId())
{
// Orb of Deception
case 16739:
@ -2833,7 +2833,7 @@ void Aura::HandleAuraTransform(bool apply, bool Real)
else
{
CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
if(!ci)
if (!ci)
{
//pig pink ^_^
m_target->SetDisplayId(16358);
@ -2848,15 +2848,18 @@ void Aura::HandleAuraTransform(bool apply, bool Real)
if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty())
m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
}
m_target->setTransForm(GetId());
}
// update active transform spell only not set or not overwriting negative by positive case
if (!m_target->getTransForm() || !IsPositiveSpell(GetId()) || IsPositiveSpell(m_target->getTransForm()))
m_target->setTransForm(GetId());
// polymorph case
if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
{
// for players, start regeneration after 1s (in polymorph fast regeneration case)
// only if caster is Player (after patch 2.4.2)
if(IS_PLAYER_GUID(GetCasterGUID()) )
if (IS_PLAYER_GUID(GetCasterGUID()) )
((Player*)m_target)->setRegenTimer(1*IN_MILISECONDS);
//dismount polymorphed target (after patch 2.4.2)
@ -2866,20 +2869,20 @@ void Aura::HandleAuraTransform(bool apply, bool Real)
}
else
{
Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
if(otherTransforms.empty())
{
m_target->SetDisplayId(m_target->GetNativeDisplayId());
// ApplyModifier(true) will reapply it if need
m_target->setTransForm(0);
}
else
m_target->SetDisplayId(m_target->GetNativeDisplayId());
// re-aplly some from still active with preference negative cases
Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
if (!otherTransforms.empty())
{
// look for other transform auras
Aura* handledAura = *otherTransforms.begin();
for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i)
{
// negative auras are preferred
if(!IsPositiveSpell((*i)->GetSpellProto()->Id))
if (!IsPositiveSpell((*i)->GetSpellProto()->Id))
{
handledAura = *i;
break;
@ -2889,12 +2892,12 @@ void Aura::HandleAuraTransform(bool apply, bool Real)
}
// Dragonmaw Illusion (restore mount model)
if(GetId()==42016 && m_target->GetMountID()==16314)
if (GetId()==42016 && m_target->GetMountID()==16314)
{
if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
if (!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
{
uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue;
if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
if (CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
{
uint32 team = 0;
if (m_target->GetTypeId()==TYPEID_PLAYER)
@ -3118,7 +3121,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
((Creature*)m_target)->AIM_Initialize();
if (((Creature*)m_target)->AI())
((Creature*)m_target)->AI()->AttackStart(caster);
((Creature*)m_target)->AI()->AttackedBy(caster);
}
}
}
@ -3271,7 +3274,7 @@ void Aura::HandleModCharm(bool apply, bool Real)
{
((Creature*)m_target)->AIM_Initialize();
if (((Creature*)m_target)->AI())
((Creature*)m_target)->AI()->AttackStart(caster);
((Creature*)m_target)->AI()->AttackedBy(caster);
}
}
}
@ -3519,15 +3522,37 @@ void Aura::HandleModStealth(bool apply, bool Real)
pTarget->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
pTarget->SetVisibility(VISIBILITY_GROUP_STEALTH);
}
// apply full stealth period bonuses only at first stealth aura in stack
if(pTarget->GetAurasByType(SPELL_AURA_MOD_STEALTH).size()<=1)
{
Unit::AuraList const& mDummyAuras = pTarget->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
{
// Master of Subtlety
if ((*i)->GetSpellProto()->SpellIconID == 2114)
{
pTarget->RemoveAurasDueToSpell(31666);
int32 bp = (*i)->GetModifier()->m_amount;
pTarget->CastCustomSpell(pTarget,31665,&bp,NULL,NULL,true);
}
// Overkill
else if ((*i)->GetId() == 58426 && GetSpellProto()->SpellFamilyFlags & 0x0000000000400000LL)
{
pTarget->RemoveAurasDueToSpell(58428);
pTarget->CastSpell(m_target, 58427, true);
}
}
}
}
}
else
{
// only at real aura remove
if (Real)
// only at real aura remove of _last_ SPELL_AURA_MOD_STEALTH
if (Real && !pTarget->HasAuraType(SPELL_AURA_MOD_STEALTH))
{
// if last SPELL_AURA_MOD_STEALTH and no GM invisibility
if (!pTarget->HasAuraType(SPELL_AURA_MOD_STEALTH) && pTarget->GetVisibility()!=VISIBILITY_OFF)
// if no GM invisibility
if(pTarget->GetVisibility()!=VISIBILITY_OFF)
{
pTarget->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP);
@ -3543,23 +3568,18 @@ void Aura::HandleModStealth(bool apply, bool Real)
else
pTarget->SetVisibility(VISIBILITY_ON);
}
}
}
// Master of Subtlety
// apply delayed talent bonus remover at last stealth aura remove
Unit::AuraList const& mDummyAuras = pTarget->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
{
// Master of Subtlety
if ((*i)->GetSpellProto()->SpellIconID == 2114)
{
if (apply)
{
int32 bp = (*i)->GetModifier()->m_amount;
pTarget->CastCustomSpell(pTarget,31665,&bp,NULL,NULL,true);
}
else
pTarget->CastSpell(pTarget,31666,true);
break;
// Overkill
else if ((*i)->GetId() == 58426 && GetSpellProto()->SpellFamilyFlags & 0x0000000000400000LL)
pTarget->CastSpell(m_target, 58428, true);
}
}
}
}
@ -3728,20 +3748,8 @@ void Aura::HandleAuraModSilence(bool apply, bool Real)
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
// Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++)
{
Spell* currentSpell = m_target->m_currentSpells[i];
if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
{
uint32 state = currentSpell->getState();
// Stop spells on prepare or casting state
if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
{
currentSpell->cancel();
currentSpell->SetReferencedFromCurrent(false);
m_target->m_currentSpells[i] = NULL;
}
}
}
if (m_target->m_currentSpells[i] && m_target->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
m_target->InterruptSpell(i,false); // Stop spells on prepare or casting state
switch (GetId())
{
@ -4195,11 +4203,15 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
{
case SPELLFAMILY_ROGUE:
{
// Master of Subtlety
if (spell->Id==31666 && !apply)
if(!apply)
{
m_target->RemoveAurasDueToSpell(31665);
break;
switch(spell->Id)
{
// Master of Subtlety
case 31666: m_target->RemoveAurasDueToSpell(31665); break;
// Overkill
case 58428: m_target->RemoveAurasDueToSpell(58427); break;
}
}
break;
}

View file

@ -3511,7 +3511,7 @@ void Spell::EffectPickPocket(uint32 /*i*/)
// Reveal action + get attack
m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
if (((Creature*)unitTarget)->AI())
((Creature*)unitTarget)->AI()->AttackStart(m_caster);
((Creature*)unitTarget)->AI()->AttackedBy(m_caster);
}
}
}

View file

@ -372,17 +372,11 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
return;
// channeled spell case (it currently casted then)
if(IsChanneledSpell(spellInfo))
if (IsChanneledSpell(spellInfo))
{
if(Spell* spell = _player->m_currentSpells[CURRENT_CHANNELED_SPELL])
{
if(spell->m_spellInfo->Id==spellId)
{
spell->cancel();
spell->SetReferencedFromCurrent(false);
_player->m_currentSpells[CURRENT_CHANNELED_SPELL] = NULL;
}
}
if (_player->m_currentSpells[CURRENT_CHANNELED_SPELL] &&
_player->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id==spellId)
_player->InterruptSpell(CURRENT_CHANNELED_SPELL);
return;
}

View file

@ -1228,6 +1228,9 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
break;
}
}
// Dragonmaw Illusion, Blood Elf Illusion, Human Illusion, Illidari Agent Illusion, Scarlet Crusade Disguise
if(spellInfo_1->SpellIconID == 1691 && spellInfo_2->SpellIconID == 1691)
return false;
break;
case SPELLFAMILY_MAGE:
if( spellInfo_2->SpellFamilyName == SPELLFAMILY_MAGE )
@ -1371,6 +1374,10 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
return false;
}
//Overkill
if( spellInfo_1->SpellIconID == 2285 && spellInfo_2->SpellIconID == 2285 )
return false;
// Garrote -> Garrote-Silence (multi-family check)
if( spellInfo_1->SpellIconID == 498 && spellInfo_2->SpellIconID == 498 && spellInfo_2->SpellVisual[0] == 0 )
return false;

View file

@ -36,7 +36,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_victimGuid(0)
{
}
@ -47,20 +47,20 @@ TotemAI::MoveInLineOfSight(Unit *)
void TotemAI::EnterEvadeMode()
{
i_totem.CombatStop();
m_creature->CombatStop();
}
void
TotemAI::UpdateAI(const uint32 /*diff*/)
{
if (i_totem.GetTotemType() != TOTEM_ACTIVE)
if (getTotem().GetTotemType() != TOTEM_ACTIVE)
return;
if (!i_totem.isAlive() || i_totem.IsNonMeleeSpellCasted(false))
if (!m_creature->isAlive() || m_creature->IsNonMeleeSpellCasted(false))
return;
// Search spell
SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_totem.GetSpell());
SpellEntry const *spellInfo = sSpellStore.LookupEntry(getTotem().GetSpell());
if (!spellInfo)
return;
@ -71,28 +71,28 @@ TotemAI::UpdateAI(const uint32 /*diff*/)
// SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems
// pointer to appropriate target if found any
Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(i_totem, i_victimGuid) : NULL;
Unit* victim = i_victimGuid ? ObjectAccessor::GetUnit(*m_creature, i_victimGuid) : NULL;
// Search victim if no, not attackable, or out of range, or friendly (possible in case duel end)
if( !victim ||
!victim->isTargetableForAttack() || !i_totem.IsWithinDistInMap(victim, max_range) ||
i_totem.IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(&i_totem,false) )
!victim->isTargetableForAttack() || !m_creature->IsWithinDistInMap(victim, max_range) ||
m_creature->IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(m_creature,false) )
{
CellPair p(MaNGOS::ComputeCellPair(i_totem.GetPositionX(),i_totem.GetPositionY()));
CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(),m_creature->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
victim = NULL;
MaNGOS::NearestAttackableUnitInObjectRangeCheck u_check(&i_totem, &i_totem, max_range);
MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck> checker(&i_totem,victim, u_check);
MaNGOS::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, max_range);
MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck> checker(m_creature,victim, u_check);
TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
TypeContainerVisitor<MaNGOS::UnitLastSearcher<MaNGOS::NearestAttackableUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_object_checker, *i_totem.GetMap());
cell_lock->Visit(cell_lock, world_object_checker, *i_totem.GetMap());
cell_lock->Visit(cell_lock, grid_object_checker, *m_creature->GetMap());
cell_lock->Visit(cell_lock, world_object_checker, *m_creature->GetMap());
}
// If have target
@ -102,8 +102,8 @@ TotemAI::UpdateAI(const uint32 /*diff*/)
i_victimGuid = victim->GetGUID();
// attack
i_totem.SetInFront(victim); // client change orientation by self
i_totem.CastSpell(victim, i_totem.GetSpell(), false);
m_creature->SetInFront(victim); // client change orientation by self
m_creature->CastSpell(victim, getTotem().GetSpell(), false);
}
else
i_victimGuid = 0;
@ -119,3 +119,8 @@ void
TotemAI::AttackStart(Unit *)
{
}
Totem& TotemAI::getTotem()
{
return static_cast<Totem&>(*m_creature);
}

View file

@ -29,7 +29,7 @@ class MANGOS_DLL_DECL TotemAI : public CreatureAI
{
public:
TotemAI(Creature &c);
explicit TotemAI(Creature *c);
void MoveInLineOfSight(Unit *);
void AttackStart(Unit *);
@ -38,9 +38,10 @@ class MANGOS_DLL_DECL TotemAI : public CreatureAI
void UpdateAI(const uint32);
static int Permissible(const Creature *);
protected:
Totem& getTotem();
private:
Totem &i_totem;
uint64 i_victimGuid;
};
#endif

View file

@ -420,10 +420,8 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if (!spellProto || !(spellProto->Mechanic == MECHANIC_ROOT || IsAuraAddedBySpell(SPELL_AURA_MOD_ROOT, spellProto->Id)))
pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_ROOT, damage);
if(pVictim->GetTypeId() != TYPEID_PLAYER)
{
// no xp,health if type 8 /critters/
if ( pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER)
if(pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER)
{
pVictim->setDeathState(JUST_DIED);
pVictim->SetHealth(0);
@ -440,10 +438,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
return damage;
}
if(!pVictim->isInCombat() && ((Creature*)pVictim)->AI())
((Creature*)pVictim)->AI()->AttackStart(this);
}
DEBUG_LOG("DealDamageStart");
uint32 health = pVictim->GetHealth();
@ -690,18 +684,16 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if(damagetype != DOT)
{
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
if(!getVictim())
{
// if not have main target then attack state with target (including AI call)
//start melee attacks only after melee hit
Attack(pVictim,(damagetype == DIRECT_DAMAGE));
}
// if damage pVictim call AI reaction
if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI())
((Creature*)pVictim)->AI()->AttackedBy(this);
}
// polymorphed and other negative transformed cases
@ -1963,6 +1955,10 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex
}
}
// if damage pVictim call AI reaction
if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI())
((Creature*)pVictim)->AI()->AttackedBy(this);
return;
}
@ -1990,6 +1986,10 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex
--m_extraAttacks;
}
}
// if damage pVictim call AI reaction
if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI())
((Creature*)pVictim)->AI()->AttackedBy(this);
}
MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackType attType) const
@ -2917,7 +2917,7 @@ void Unit::_UpdateSpells( uint32 time )
if(!m_gameObj.empty())
{
std::list<GameObject*>::iterator ite1, dnext1;
GameObjectList::iterator ite1, dnext1;
for (ite1 = m_gameObj.begin(); ite1 != m_gameObj.end(); ite1 = dnext1)
{
dnext1 = ite1;
@ -3044,7 +3044,7 @@ void Unit::InterruptSpell(uint32 spellType, bool withDelayed)
{
assert(spellType < CURRENT_MAX_SPELL);
if(m_currentSpells[spellType] && (withDelayed || m_currentSpells[spellType]->getState() != SPELL_STATE_DELAYED) )
if (m_currentSpells[spellType] && (withDelayed || m_currentSpells[spellType]->getState() != SPELL_STATE_DELAYED) )
{
// send autorepeat cancel message for autorepeat spells
if (spellType == CURRENT_AUTOREPEAT_SPELL)
@ -3055,9 +3055,14 @@ void Unit::InterruptSpell(uint32 spellType, bool withDelayed)
if (m_currentSpells[spellType]->getState() != SPELL_STATE_FINISHED)
m_currentSpells[spellType]->cancel();
// cancel can interrupt spell already (caster cancel ->target aura remove -> caster iterrupt)
if (m_currentSpells[spellType])
{
m_currentSpells[spellType]->SetReferencedFromCurrent(false);
m_currentSpells[spellType] = NULL;
}
}
}
bool Unit::IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled, bool skipAutorepeat) const
@ -3087,36 +3092,15 @@ void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id)
{
// generic spells are interrupted if they are not finished or delayed
if (m_currentSpells[CURRENT_GENERIC_SPELL] && (!spell_id || m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id==spell_id))
{
if ( (m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_FINISHED) &&
(withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED) )
m_currentSpells[CURRENT_GENERIC_SPELL]->cancel();
m_currentSpells[CURRENT_GENERIC_SPELL]->SetReferencedFromCurrent(false);
m_currentSpells[CURRENT_GENERIC_SPELL] = NULL;
}
InterruptSpell(CURRENT_GENERIC_SPELL,withDelayed);
// autorepeat spells are interrupted if they are not finished or delayed
if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && (!spell_id || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id==spell_id))
{
// send disable autorepeat packet in any case
if(GetTypeId()==TYPEID_PLAYER)
((Player*)this)->SendAutoRepeatCancel();
if ( (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->getState() != SPELL_STATE_FINISHED) &&
(withDelayed || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->getState() != SPELL_STATE_DELAYED) )
m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->cancel();
m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->SetReferencedFromCurrent(false);
m_currentSpells[CURRENT_AUTOREPEAT_SPELL] = NULL;
}
InterruptSpell(CURRENT_AUTOREPEAT_SPELL,withDelayed);
// channeled spells are interrupted if they are not finished, even if they are delayed
if (m_currentSpells[CURRENT_CHANNELED_SPELL] && (!spell_id || m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id==spell_id))
{
if (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED)
m_currentSpells[CURRENT_CHANNELED_SPELL]->cancel();
m_currentSpells[CURRENT_CHANNELED_SPELL]->SetReferencedFromCurrent(false);
m_currentSpells[CURRENT_CHANNELED_SPELL] = NULL;
}
InterruptSpell(CURRENT_CHANNELED_SPELL,true);
}
Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const
@ -4060,6 +4044,15 @@ DynamicObject * Unit::GetDynObject(uint32 spellId)
return NULL;
}
GameObject* Unit::GetGameObject(uint32 spellId) const
{
for (GameObjectList::const_iterator i = m_gameObj.begin(); i != m_gameObj.end();)
if ((*i)->GetSpellId() == spellId)
return *i;
return NULL;
}
void Unit::AddGameObject(GameObject* gameObj)
{
assert(gameObj && gameObj->GetOwnerGUID()==0);
@ -4110,7 +4103,7 @@ void Unit::RemoveGameObject(uint32 spellid, bool del)
{
if(m_gameObj.empty())
return;
std::list<GameObject*>::iterator i, next;
GameObjectList::iterator i, next;
for (i = m_gameObj.begin(); i != m_gameObj.end(); i = next)
{
next = i;
@ -4133,7 +4126,7 @@ void Unit::RemoveGameObject(uint32 spellid, bool del)
void Unit::RemoveAllGameObjects()
{
// remove references to unit
for(std::list<GameObject*>::iterator i = m_gameObj.begin(); i != m_gameObj.end();)
for(GameObjectList::iterator i = m_gameObj.begin(); i != m_gameObj.end();)
{
(*i)->SetOwnerGUID(0);
(*i)->SetRespawnTime(0);
@ -7173,9 +7166,6 @@ 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(GetTypeId()==TYPEID_UNIT)
{
WorldPacket data(SMSG_AI_REACTION, 12);
@ -7291,7 +7281,51 @@ void Unit::RemoveAllAttackers()
void Unit::ModifyAuraState(AuraState flag, bool apply)
{
ApplyModFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1), 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;
}
}
}
}
Unit *Unit::GetOwner() const
@ -10746,8 +10780,8 @@ void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID)
// attack caster if can
Unit* caster = ObjectAccessor::GetObjectInWorld(casterGUID, (Unit*)NULL);
if(caster && caster != getVictim() && ((Creature*)this)->AI())
((Creature*)this)->AI()->AttackStart(caster);
if(caster && ((Creature*)this)->AI())
((Creature*)this)->AI()->AttackedBy(caster);
}
}

View file

@ -1320,16 +1320,20 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); }
void setTransForm(uint32 spellid) { m_transform = spellid;}
uint32 getTransForm() const { return m_transform;}
DynamicObject* GetDynObject(uint32 spellId, uint32 effIndex);
DynamicObject* GetDynObject(uint32 spellId);
void AddDynObject(DynamicObject* dynObj);
void RemoveDynObject(uint32 spellid);
void RemoveDynObjectWithGUID(uint64 guid) { m_dynObjGUIDs.remove(guid); }
void RemoveAllDynObjects();
GameObject* GetGameObject(uint32 spellId) const;
void AddGameObject(GameObject* gameObj);
void RemoveGameObject(GameObject* gameObj, bool del);
void RemoveGameObject(uint32 spellid, bool del);
void RemoveAllGameObjects();
DynamicObject *GetDynObject(uint32 spellId, uint32 effIndex);
DynamicObject *GetDynObject(uint32 spellId);
uint32 CalculateDamage(WeaponAttackType attType, bool normalized);
float GetAPMultiplier(WeaponAttackType attType, bool normalized);
void ModifyAuraState(AuraState flag, bool apply);
@ -1455,7 +1459,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
typedef std::list<uint64> DynObjectGUIDs;
DynObjectGUIDs m_dynObjGUIDs;
std::list<GameObject*> m_gameObj;
typedef std::list<GameObject*> GameObjectList;
GameObjectList m_gameObj;
bool m_isSorted;
uint32 m_transform;
uint32 m_removedAuras;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "7656"
#define REVISION_NR "7670"
#endif // __REVISION_NR_H__