From 0e1997f746911fef71624f8fe50800c75a9cdb3a Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 13 Apr 2009 01:03:16 +0400 Subject: [PATCH 01/15] [7657] Implement function for access to gameobject owned by unit and created by some spell. --- src/game/Unit.cpp | 15 ++++++++++++--- src/game/Unit.h | 11 ++++++++--- src/shared/revision_nr.h | 2 +- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 66b18d0c9..832d8dc7b 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -2916,7 +2916,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; @@ -4059,6 +4059,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); @@ -4109,7 +4118,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; @@ -4132,7 +4141,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); 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..a9dbed3fd 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 "7657" #endif // __REVISION_NR_H__ From edc51e20203ce537863a9cd9db04edd94e7b97d7 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Mon, 13 Apr 2009 02:21:44 +0400 Subject: [PATCH 02/15] Add name for WorldMapArea.dbc field Signed-off-by: DiSlord --- src/game/DBCStructure.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 1357d0060..b119d5977 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1624,6 +1624,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 From bd56140537a5a7d0d623b291f492c6f26239636d Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 13 Apr 2009 03:09:33 +0400 Subject: [PATCH 03/15] [7658] Drop dead code. --- src/game/Creature.cpp | 2 +- src/game/Creature.h | 2 -- src/shared/revision_nr.h | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 8cf34b10a..392f938f9 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) diff --git a/src/game/Creature.h b/src/game/Creature.h index 5ff1e30ec..1d785615c 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -546,7 +546,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 +664,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/shared/revision_nr.h b/src/shared/revision_nr.h index a9dbed3fd..3e9512b28 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 "7657" + #define REVISION_NR "7658" #endif // __REVISION_NR_H__ From a0ef77af5b24457a128dffbaa38e518b807c2ffc Mon Sep 17 00:00:00 2001 From: arrai Date: Mon, 13 Apr 2009 01:39:14 +0200 Subject: [PATCH 04/15] [7659] Added several security checks to prevent cheating using facked packets --- src/game/GuildHandler.cpp | 14 +++++++------- src/game/ItemHandler.cpp | 15 ++++++++++++++- src/game/Mail.cpp | 31 ++++++++++++++++++++++++++++--- src/game/ObjectMgr.cpp | 17 +++++++++++++++++ src/game/ObjectMgr.h | 8 +------- src/shared/revision_nr.h | 2 +- 6 files changed, 68 insertions(+), 19 deletions(-) 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 82ce5c546..e5ce97b81 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -825,10 +825,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/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 435e2a1ac..9c1d2fc2d 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -4154,6 +4154,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 89047f60f..06f437970 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/shared/revision_nr.h b/src/shared/revision_nr.h index 3e9512b28..87fbb229d 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 "7658" + #define REVISION_NR "7659" #endif // __REVISION_NR_H__ From cce772c08cdc1ea443a37c6abfaa8411c5dccfec Mon Sep 17 00:00:00 2001 From: Lightguard Date: Mon, 13 Apr 2009 04:13:17 +0400 Subject: [PATCH 05/15] [7660] Fixed problem with lost aura 40214 in some cases. Signed-off-by: VladimirMangos --- src/game/SpellMgr.cpp | 3 +++ src/shared/revision_nr.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 7fd3d1a8d..af34bcdaf 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 ) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 87fbb229d..c00ed7fd2 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 "7659" + #define REVISION_NR "7660" #endif // __REVISION_NR_H__ From f89c2052ea032d852807230035439f48a01cecc2 Mon Sep 17 00:00:00 2001 From: "False.Genesis" Date: Mon, 13 Apr 2009 05:54:34 +0400 Subject: [PATCH 06/15] [7661] Fixed problem with not remove health regeneration from polymorph. Signed-off-by: VladimirMangos Also fixed problem with remembering transform spell in case possible stacked negative and positive transforms. --- src/game/SpellAuras.cpp | 37 ++++++++++++++++++++----------------- src/shared/revision_nr.h | 2 +- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index c60809ec0..5cf940374 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2762,13 +2762,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: @@ -2828,7 +2828,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); @@ -2843,15 +2843,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) @@ -2861,20 +2864,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; @@ -2884,12 +2887,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) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c00ed7fd2..a23865a8a 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 "7660" + #define REVISION_NR "7661" #endif // __REVISION_NR_H__ From b143a300cb71c13abfcb25ab8737a6c859cf1cdb Mon Sep 17 00:00:00 2001 From: nos4r2zod Date: Mon, 13 Apr 2009 07:46:04 +0400 Subject: [PATCH 07/15] [7662] Spell power coefficients for talent 48505 and ranks. Signed-off-by: VladimirMangos --- sql/mangos.sql | 14 +++++++++++++- sql/updates/7662_01_mangos_spell_chain.sql | 16 ++++++++++++++++ sql/updates/7662_02_mangos_spell_bonus_data.sql | 6 ++++++ sql/updates/Makefile.am | 4 ++++ src/shared/revision_nr.h | 2 +- 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 sql/updates/7662_01_mangos_spell_chain.sql create mode 100644 sql/updates/7662_02_mangos_spell_bonus_data.sql 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/shared/revision_nr.h b/src/shared/revision_nr.h index a23865a8a..28e21e151 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 "7661" + #define REVISION_NR "7662" #endif // __REVISION_NR_H__ From 56350b32ed1cbfcdd08276cc0678f5b2a8f5a382 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 13 Apr 2009 10:39:37 +0400 Subject: [PATCH 08/15] [7663] Fixed crash at interrupting channeled spell. Cleanup spell interrupt code. --- src/game/SpellAuras.cpp | 16 ++-------------- src/game/SpellHandler.cpp | 14 ++++---------- src/game/Unit.cpp | 38 +++++++++++--------------------------- src/shared/revision_nr.h | 2 +- 4 files changed, 18 insertions(+), 52 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 5cf940374..4a32e4b28 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3726,20 +3726,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()) { 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/Unit.cpp b/src/game/Unit.cpp index 832d8dc7b..fca037f6d 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3043,7 +3043,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) @@ -3054,8 +3054,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; + } } } @@ -3086,36 +3091,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 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 28e21e151..5db1ec181 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 "7662" + #define REVISION_NR "7663" #endif // __REVISION_NR_H__ From 0aaf2665134dd609cfaa771195e25081b2e0a159 Mon Sep 17 00:00:00 2001 From: Lightguard Date: Mon, 13 Apr 2009 12:36:53 +0400 Subject: [PATCH 09/15] [7664] Implement work of rogue talent 58426. Signed-off-by: VladimirMangos Also fix problems with talent 58426 and 31223 work in case * fast stealth reapply after stealth lost * second stealth aura apply while another active. Signed-off-by: VladimirMangos --- src/game/SpellAuras.cpp | 65 ++++++++++++++++++++++++++-------------- src/game/SpellMgr.cpp | 4 +++ src/shared/revision_nr.h | 2 +- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 4a32e4b28..fba21e746 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3517,15 +3517,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); @@ -3541,23 +3563,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; } } } @@ -4181,11 +4198,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/SpellMgr.cpp b/src/game/SpellMgr.cpp index af34bcdaf..0b4647d98 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1374,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/shared/revision_nr.h b/src/shared/revision_nr.h index 5db1ec181..9c5780282 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 "7663" + #define REVISION_NR "7664" #endif // __REVISION_NR_H__ From 1ebf1a5ba40d9292a084910119d26441963bedb3 Mon Sep 17 00:00:00 2001 From: Splash Date: Tue, 14 Apr 2009 01:01:19 +0400 Subject: [PATCH 10/15] [7665] Include achievement data to pdumps. Signed-off-by: VladimirMangos --- src/game/PlayerDump.cpp | 42 +++++++++++++++++++++------------------- src/game/PlayerDump.h | 8 ++++---- src/shared/revision_nr.h | 2 +- 3 files changed, 27 insertions(+), 25 deletions(-) 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/shared/revision_nr.h b/src/shared/revision_nr.h index 9c5780282..947026152 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 "7664" + #define REVISION_NR "7665" #endif // __REVISION_NR_H__ From 721e005b84f9f55beedfed83c53b307ceb309e5d Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 14 Apr 2009 02:10:32 +0400 Subject: [PATCH 11/15] [7666] For heroic mode creature use AIName from normal mode version in same way as done for ScriptName. Also at creature templates loading check that AIName/ScriptName not set for heroic mode creature versions. --- src/game/Creature.cpp | 9 +++++++-- src/game/Creature.h | 5 +++-- src/game/CreatureAISelector.cpp | 4 +--- src/game/CreatureEventAI.cpp | 2 +- src/game/ObjectMgr.cpp | 12 ++++++++++++ src/shared/revision_nr.h | 2 +- 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 392f938f9..ca5fb4a13 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -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 1d785615c..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 ); diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp index 41013b97f..a3f4e517d 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 diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 00b32acfe..3d08eab88 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -32,7 +32,7 @@ int CreatureEventAI::Permissible(const Creature *creature) { - if( creature->GetCreatureInfo()->AIName == "EventAI" ) + if( creature->GetAIName() == "EventAI" ) return PERMIT_BASE_SPECIAL; return PERMIT_BASE_NO; } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 9c1d2fc2d..90ef2211c 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -528,6 +528,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); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 947026152..f6f1bce2b 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 "7665" + #define REVISION_NR "7666" #endif // __REVISION_NR_H__ From 69fb9736ccbc1deb8f266183f479670adae1d69e Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 14 Apr 2009 06:43:31 +0400 Subject: [PATCH 12/15] [7667] Add to CreatureAI field pointing to creature itself. Use it instead diff. fields in subclases. Also send pointer to AI constructors ans mark constructors as explicit. This changes allow move now some generic often used AI code to CreatureAI helper functions. --- src/bindings/universal/ScriptMgr.h | 4 +- src/game/AggressorAI.cpp | 86 ++++---- src/game/AggressorAI.h | 3 +- src/game/CreatureAI.h | 3 + src/game/CreatureAIImpl.h | 2 +- src/game/CreatureAISelector.cpp | 2 +- src/game/CreatureEventAI.cpp | 318 ++++++++++++++--------------- src/game/CreatureEventAI.h | 6 +- src/game/GuardAI.cpp | 84 ++++---- src/game/GuardAI.h | 3 +- src/game/NullCreatureAI.h | 4 +- src/game/PetAI.cpp | 142 ++++++------- src/game/PetAI.h | 3 +- src/game/ReactorAI.cpp | 56 ++--- src/game/ReactorAI.h | 3 +- src/game/TotemAI.cpp | 35 ++-- src/game/TotemAI.h | 5 +- src/shared/revision_nr.h | 2 +- 18 files changed, 379 insertions(+), 382 deletions(-) diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index 3b70e81ea..390296bfe 100644 --- a/src/bindings/universal/ScriptMgr.h +++ b/src/bindings/universal/ScriptMgr.h @@ -80,7 +80,7 @@ struct Script 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 @@ -122,8 +122,6 @@ struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI // 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/CreatureAI.h b/src/game/CreatureAI.h index 6d2a6a7f1..fbd2bc57a 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -36,6 +36,7 @@ struct SpellEntry; class MANGOS_DLL_SPEC CreatureAI { public: + explicit CreatureAI(Creature* creature) : m_creature(creature) {} virtual ~CreatureAI(); @@ -94,6 +95,8 @@ class MANGOS_DLL_SPEC CreatureAI // Called at waypoint reached or point movement finished virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {} + + 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 a3f4e517d..56ed5f300 100644 --- a/src/game/CreatureAISelector.cpp +++ b/src/game/CreatureAISelector.cpp @@ -82,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 3d08eab88..408d80071 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -37,9 +37,9 @@ int CreatureEventAI::Permissible(const Creature *creature) 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/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/NullCreatureAI.h b/src/game/NullCreatureAI.h index 661571b97..9683f01dc 100644 --- a/src/game/NullCreatureAI.h +++ b/src/game/NullCreatureAI.h @@ -25,9 +25,7 @@ class MANGOS_DLL_DECL NullCreatureAI : public CreatureAI { public: - NullCreatureAI(Creature &) {} - NullCreatureAI() {} - + explicit NullCreatureAI(Creature* c) : CreatureAI(c) {} ~NullCreatureAI(); void MoveInLineOfSight(Unit *) {} 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..60c5c5113 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -29,7 +29,7 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI { public: - PetAI(Creature &c); + explicit PetAI(Creature *c); void MoveInLineOfSight(Unit *); void AttackStart(Unit *); @@ -49,7 +49,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/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/TotemAI.cpp b/src/game/TotemAI.cpp index f10d75039..5b161ccbd 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); +} \ No newline at end of file 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/shared/revision_nr.h b/src/shared/revision_nr.h index f6f1bce2b..fe876d9ab 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 "7666" + #define REVISION_NR "7667" #endif // __REVISION_NR_H__ From d85e95295dcedb12893e7e02546a377d8a534d86 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 14 Apr 2009 07:21:04 +0400 Subject: [PATCH 13/15] [7668] Cleanup In CreatureAI function descriptions and AttackStart/AttackedBy use. * Use AI::AttackStart calls only in case explicit request creature attack from core or AI code "attack it if can". Like taunt, pet handler attack command. * Use AI::AttackedBy for reaction at hostile action "do something at hostile action" Like non-dot damage, swing, negative spell landing, or fade fear/etc. And provided by default call AttackStart if no current target. This fix some problems, like: * Civilian will react propertly at attack by another creature (not pet or player). * Will not cases (at least triggred by core) when attack target start run to attacker before any real hostile action apply. --- src/bindings/universal/ScriptMgr.h | 28 +-------------- src/game/CreatureAI.cpp | 7 ++++ src/game/CreatureAI.h | 48 +++++++++++++++---------- src/game/NullCreatureAI.h | 1 + src/game/PetAI.h | 1 - src/game/Spell.cpp | 2 +- src/game/SpellAuras.cpp | 4 +-- src/game/SpellEffects.cpp | 2 +- src/game/TotemAI.cpp | 2 +- src/game/Unit.cpp | 57 ++++++++++++++---------------- src/shared/revision_nr.h | 2 +- 11 files changed, 72 insertions(+), 82 deletions(-) diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index 390296bfe..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 { 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,18 +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*) {} - //= Some useful helpers ========================= // Start attack of victim and go to him 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 fbd2bc57a..9b6e29f29 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -40,14 +40,13 @@ class MANGOS_DLL_SPEC CreatureAI 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() {} @@ -59,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 *) {} @@ -84,11 +79,8 @@ 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() {} @@ -96,6 +88,26 @@ class MANGOS_DLL_SPEC CreatureAI // 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; }; diff --git a/src/game/NullCreatureAI.h b/src/game/NullCreatureAI.h index 9683f01dc..c56c968c1 100644 --- a/src/game/NullCreatureAI.h +++ b/src/game/NullCreatureAI.h @@ -30,6 +30,7 @@ class MANGOS_DLL_DECL NullCreatureAI : public CreatureAI void MoveInLineOfSight(Unit *) {} void AttackStart(Unit *) {} + void AttackedBy( Unit *) {} void EnterEvadeMode() {} bool IsVisible(Unit *) const { return false; } diff --git a/src/game/PetAI.h b/src/game/PetAI.h index 60c5c5113..02a412934 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -34,7 +34,6 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI void MoveInLineOfSight(Unit *); void AttackStart(Unit *); void EnterEvadeMode(); - void DamageTaken(Unit *done_by, uint32& /*damage*/) { AttackedBy(done_by); } void AttackedBy(Unit*); bool IsVisible(Unit *) const; void JustDied(Unit* /*who*/) { _stopAttack(); } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 3ec1f0088..d9c972297 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 fba21e746..55a08c912 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3116,7 +3116,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); } } } @@ -3269,7 +3269,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); } } } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 04d36d3fc..74ed51043 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3508,7 +3508,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/TotemAI.cpp b/src/game/TotemAI.cpp index 5b161ccbd..8b1f6bd3c 100644 --- a/src/game/TotemAI.cpp +++ b/src/game/TotemAI.cpp @@ -123,4 +123,4 @@ TotemAI::AttackStart(Unit *) Totem& TotemAI::getTotem() { return static_cast(*m_creature); -} \ No newline at end of file +} diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index fca037f6d..a063c5dc1 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -419,28 +419,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"); @@ -689,18 +683,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 @@ -1962,6 +1954,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; } @@ -1989,6 +1985,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 @@ -7165,9 +7165,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); @@ -10738,8 +10735,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/shared/revision_nr.h b/src/shared/revision_nr.h index fe876d9ab..54ec963b2 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 "7667" + #define REVISION_NR "7668" #endif // __REVISION_NR_H__ From 2289ee6b3075161fa1ef4bebbe5a8d490950e782 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 14 Apr 2009 13:57:06 +0400 Subject: [PATCH 14/15] [7669] Some lost commented code patch for currencies trading item move to empty slot. In fact it not change anything except GM item created trade: no currency items currently that not bind at picked up. --- src/game/Player.cpp | 2 -- src/shared/revision_nr.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 9f59951b9..994783e83 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -9311,7 +9311,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) @@ -9326,7 +9325,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/shared/revision_nr.h b/src/shared/revision_nr.h index 54ec963b2..efef0de50 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 "7668" + #define REVISION_NR "7669" #endif // __REVISION_NR_H__ From c62543fa522e17f224385f1bcf7b9e14d77fcbb5 Mon Sep 17 00:00:00 2001 From: Lightguard Date: Tue, 14 Apr 2009 14:35:35 +0400 Subject: [PATCH 15/15] [7670] Revert "Not apply/remove passive auras on aura state change (not need)" This reverts commit d5f6eefd1bb3c64797e54d19cc58ccc8c4cf8a4f. Some 3.0.x talents not work without this like 44441 Signed-off-by: VladimirMangos --- src/game/Unit.cpp | 46 +++++++++++++++++++++++++++++++++++++++- src/shared/revision_nr.h | 2 +- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index a063c5dc1..d2779c97e 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -7280,7 +7280,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 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index efef0de50..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 "7669" + #define REVISION_NR "7670" #endif // __REVISION_NR_H__