diff --git a/sql/mangos.sql b/sql/mangos.sql index 7caf7af32..8324b65ab 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -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'), diff --git a/sql/updates/7662_01_mangos_spell_chain.sql b/sql/updates/7662_01_mangos_spell_chain.sql new file mode 100644 index 000000000..6547b1259 --- /dev/null +++ b/sql/updates/7662_01_mangos_spell_chain.sql @@ -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); + diff --git a/sql/updates/7662_02_mangos_spell_bonus_data.sql b/sql/updates/7662_02_mangos_spell_bonus_data.sql new file mode 100644 index 000000000..8aa04924f --- /dev/null +++ b/sql/updates/7662_02_mangos_spell_bonus_data.sql @@ -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"); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 2879cb0a8..61a74bd1b 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -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 diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index 3b70e81ea..7bfaf2431 100644 --- a/src/bindings/universal/ScriptMgr.h +++ b/src/bindings/universal/ScriptMgr.h @@ -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 diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp index c792d0261..37346269c 100644 --- a/src/game/AggressorAI.cpp +++ b/src/game/AggressorAI.cpp @@ -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); } } diff --git a/src/game/AggressorAI.h b/src/game/AggressorAI.h index c67bed34d..8a0c3b43b 100644 --- a/src/game/AggressorAI.h +++ b/src/game/AggressorAI.h @@ -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; diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 8cf34b10a..ca5fb4a13 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -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; } diff --git a/src/game/Creature.h b/src/game/Creature.h index 5ff1e30ec..4536aaf45 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -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 diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index b4f916f34..784ea7d35 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -17,7 +17,14 @@ */ #include "CreatureAI.h" +#include "Creature.h" CreatureAI::~CreatureAI() { } + +void CreatureAI::AttackedBy( Unit* attacker ) +{ + if(!m_creature->getVictim()) + AttackStart(attacker); +} diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index 6d2a6a7f1..9b6e29f29 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -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, public Permissible diff --git a/src/game/CreatureAIImpl.h b/src/game/CreatureAIImpl.h index 70dd02167..9f21c32fd 100644 --- a/src/game/CreatureAIImpl.h +++ b/src/game/CreatureAIImpl.h @@ -25,6 +25,6 @@ inline CreatureAI* CreatureAIFactory::Create(void *data) const { Creature* creature = reinterpret_cast(data); - return (new REAL_AI(*creature)); + return (new REAL_AI(creature)); } #endif diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp index 41013b97f..56ed5f300 100644 --- a/src/game/CreatureAISelector.cpp +++ b/src/game/CreatureAISelector.cpp @@ -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) diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 00b32acfe..408d80071 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -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::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::iterator i = m_creature.getThreatManager().getThreatList().begin(); - for (; i != m_creature.getThreatManager().getThreatList().end(); ++i) + std::list::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::iterator i = m_creature.getThreatManager().getThreatList().begin(); - for (; i != m_creature.getThreatManager().getThreatList().end(); ++i) + std::list::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::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& m_threatlist = m_creature.getThreatManager().getThreatList(); + std::list& m_threatlist = m_creature->getThreatManager().getThreatList(); std::list::iterator i = m_threatlist.begin(); std::list::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 searcher(&m_creature, pUnit, u_check); + MaNGOS::MostHPMissingInRange u_check(m_creature, range, MinHPDiff); + MaNGOS::UnitLastSearcher 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, GridTypeMapContainer > grid_unit_searcher(searcher); CellLock 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& _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 searcher(&m_creature, _list, u_check); + MaNGOS::FriendlyCCedInRange u_check(m_creature, range); + MaNGOS::CreatureListSearcher searcher(m_creature, _list, u_check); TypeContainerVisitor, GridTypeMapContainer > grid_creature_searcher(searcher); CellLock 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& _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 searcher(&m_creature, _list, u_check); + MaNGOS::FriendlyMissingBuffInRange u_check(m_creature, range, spellid); + MaNGOS::CreatureListSearcher searcher(m_creature, _list, u_check); TypeContainerVisitor, GridTypeMapContainer > grid_creature_searcher(searcher); CellLock 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; diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h index c595f3233..06573ea58 100644 --- a/src/game/CreatureEventAI.h +++ b/src/game/CreatureEventAI.h @@ -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& _list, float range, uint32 spellid); void DoFindFriendlyCC(std::list& _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 CreatureEventAIList; uint32 EventUpdateTime; //Time between event updates diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index b2568a2d9..32f759003 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -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 diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp index 255930f5b..b65e918cc 100644 --- a/src/game/GuardAI.cpp +++ b/src/game/GuardAI.cpp @@ -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); } diff --git a/src/game/GuardAI.h b/src/game/GuardAI.h index 365e3af75..20690201d 100644 --- a/src/game/GuardAI.h +++ b/src/game/GuardAI.h @@ -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; diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index f9bde8849..540ea9e96 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -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(); diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index fedbf8da0..f78f77dfe 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -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 diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 78043d900..b385043e4 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -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); diff --git a/src/game/NullCreatureAI.h b/src/game/NullCreatureAI.h index 661571b97..c56c968c1 100644 --- a/src/game/NullCreatureAI.h +++ b/src/game/NullCreatureAI.h @@ -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; } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index cdf6a56e7..697df7259 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -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); diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 88dc20c59..adf68a5c6 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -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; diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 4d2734c5a..d308a6240 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -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(i_pet.getVictim(), spell)); + m_targetSpellStore.push_back(std::make_pair(m_creature->getVictim(), spell)); continue; } else @@ -231,7 +231,7 @@ void PetAI::UpdateAI(const uint32 diff) bool spellUsed = false; for(std::set::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); } diff --git a/src/game/PetAI.h b/src/game/PetAI.h index 00edf864e..02a412934 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -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 m_AllySet; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a6b2dfe55..c6c883277 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -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++) { diff --git a/src/game/PlayerDump.cpp b/src/game/PlayerDump.cpp index 7712ec0f5..8f75e6427 100644 --- a/src/game/PlayerDump.cpp +++ b/src/game/PlayerDump.cpp @@ -24,7 +24,7 @@ #include "ObjectMgr.h" // Character Dump tables -#define DUMP_TABLE_COUNT 19 +#define DUMP_TABLE_COUNT 21 struct DumpTable { @@ -34,25 +34,27 @@ struct DumpTable static DumpTable dumpTables[DUMP_TABLE_COUNT] = { - { "characters", DTT_CHARACTER }, - { "character_queststatus", DTT_CHAR_TABLE }, - { "character_reputation", DTT_CHAR_TABLE }, - { "character_spell", DTT_CHAR_TABLE }, - { "character_spell_cooldown", DTT_CHAR_TABLE }, - { "character_action", DTT_CHAR_TABLE }, - { "character_aura", DTT_CHAR_TABLE }, - { "character_homebind", DTT_CHAR_TABLE }, - { "character_ticket", DTT_CHAR_TABLE }, - { "character_inventory", DTT_INVENTORY }, - { "mail", DTT_MAIL }, - { "mail_items", DTT_MAIL_ITEM }, - { "item_instance", DTT_ITEM }, - { "character_gifts", DTT_ITEM_GIFT }, - { "item_text", DTT_ITEM_TEXT }, - { "character_pet", DTT_PET }, - { "pet_aura", DTT_PET_TABLE }, - { "pet_spell", DTT_PET_TABLE }, - { "pet_spell_cooldown", DTT_PET_TABLE }, + { "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 }, + { "character_spell_cooldown", DTT_CHAR_TABLE }, + { "character_action", DTT_CHAR_TABLE }, + { "character_aura", DTT_CHAR_TABLE }, + { "character_homebind", DTT_CHAR_TABLE }, + { "character_ticket", DTT_CHAR_TABLE }, + { "character_inventory", DTT_INVENTORY }, + { "mail", DTT_MAIL }, + { "mail_items", DTT_MAIL_ITEM }, + { "item_instance", DTT_ITEM }, + { "character_gifts", DTT_ITEM_GIFT }, + { "item_text", DTT_ITEM_TEXT }, + { "character_pet", DTT_PET }, + { "pet_aura", DTT_PET_TABLE }, + { "pet_spell", DTT_PET_TABLE }, + { "pet_spell_cooldown", DTT_PET_TABLE }, }; // Low level functions diff --git a/src/game/PlayerDump.h b/src/game/PlayerDump.h index d3258bb95..90fd2ac0e 100644 --- a/src/game/PlayerDump.h +++ b/src/game/PlayerDump.h @@ -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 diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp index 91fa808ed..d12284f1c 100644 --- a/src/game/ReactorAI.cpp +++ b/src/game/ReactorAI.cpp @@ -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(); } diff --git a/src/game/ReactorAI.h b/src/game/ReactorAI.h index b0ebacc26..679e28360 100644 --- a/src/game/ReactorAI.h +++ b/src/game/ReactorAI.h @@ -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 diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index e5024a717..bfaf411c0 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -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); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index f1575e414..ea7b83aab 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -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 { + // ApplyModifier(true) will reapply it if need + m_target->setTransForm(0); + 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()) - { - m_target->SetDisplayId(m_target->GetNativeDisplayId()); - m_target->setTransForm(0); - } - else + 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 - Unit::AuraList const& mDummyAuras = pTarget->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) - { - if ((*i)->GetSpellProto()->SpellIconID == 2114) - { - if (apply) + // 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) { - int32 bp = (*i)->GetModifier()->m_amount; - pTarget->CastCustomSpell(pTarget,31665,&bp,NULL,NULL,true); + // Master of Subtlety + if ((*i)->GetSpellProto()->SpellIconID == 2114) + pTarget->CastSpell(pTarget,31666,true); + // Overkill + else if ((*i)->GetId() == 58426 && GetSpellProto()->SpellFamilyFlags & 0x0000000000400000LL) + pTarget->CastSpell(m_target, 58428, true); } - else - pTarget->CastSpell(pTarget,31666,true); - break; } } } @@ -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; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 66ca8a356..5ce821823 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -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); } } } diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 6c6cd79d0..e01aaace5 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -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; } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 7fd3d1a8d..0b4647d98 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -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; diff --git a/src/game/TotemAI.cpp b/src/game/TotemAI.cpp index f10d75039..8b1f6bd3c 100644 --- a/src/game/TotemAI.cpp +++ b/src/game/TotemAI.cpp @@ -36,7 +36,7 @@ TotemAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -TotemAI::TotemAI(Creature &c) : i_totem(static_cast(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 checker(&i_totem,victim, u_check); + MaNGOS::NearestAttackableUnitInObjectRangeCheck u_check(m_creature, m_creature, max_range); + MaNGOS::UnitLastSearcher checker(m_creature,victim, u_check); TypeContainerVisitor, GridTypeMapContainer > grid_object_checker(checker); TypeContainerVisitor, WorldTypeMapContainer > world_object_checker(checker); CellLock 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(*m_creature); +} diff --git a/src/game/TotemAI.h b/src/game/TotemAI.h index c0759b075..bd2c2ad3d 100644 --- a/src/game/TotemAI.h +++ b/src/game/TotemAI.h @@ -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 diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index c37c65817..7ec8c0bab 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -420,28 +420,22 @@ 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->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER) { - // no xp,health if type 8 /critters/ - if ( pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER) - { - pVictim->setDeathState(JUST_DIED); - pVictim->SetHealth(0); + pVictim->setDeathState(JUST_DIED); + pVictim->SetHealth(0); - // allow loot only if has loot_id in creature_template - CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo(); - if(cInfo && cInfo->lootid) - pVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + // allow loot only if has loot_id in creature_template + CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo(); + if(cInfo && cInfo->lootid) + pVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - // some critters required for quests - if(GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID()); + // some critters required for quests + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID()); - return damage; - } - - if(!pVictim->isInCombat() && ((Creature*)pVictim)->AI()) - ((Creature*)pVictim)->AI()->AttackStart(this); + return damage; } DEBUG_LOG("DealDamageStart"); @@ -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::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,8 +3055,13 @@ void Unit::InterruptSpell(uint32 spellType, bool withDelayed) if (m_currentSpells[spellType]->getState() != SPELL_STATE_FINISHED) m_currentSpells[spellType]->cancel(); - m_currentSpells[spellType]->SetReferencedFromCurrent(false); - m_currentSpells[spellType] = NULL; + + // 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; + } } } @@ -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::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::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); } } diff --git a/src/game/Unit.h b/src/game/Unit.h index 19f54195c..e3ea874e7 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -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 DynObjectGUIDs; DynObjectGUIDs m_dynObjGUIDs; - std::list m_gameObj; + typedef std::list GameObjectList; + GameObjectList m_gameObj; bool m_isSorted; uint32 m_transform; uint32 m_removedAuras; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a17c844ea..3bc5af93b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7656" + #define REVISION_NR "7670" #endif // __REVISION_NR_H__