From 5020fcd3f15ed2fedce47ddc8d58ce43cca5a339 Mon Sep 17 00:00:00 2001 From: Mordred Date: Wed, 15 Apr 2009 02:16:03 +0400 Subject: [PATCH 01/22] [7671] Wrong type casts not fixed in [7667]. Signed-off-by: VladimirMangos --- src/game/PetAI.cpp | 4 ++-- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index d308a6240..89c9073cd 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -63,7 +63,7 @@ void PetAI::MoveInLineOfSight(Unit *u) void PetAI::AttackStart(Unit *u) { - if( inCombat || !u || (m_creature->isPet() && ((Pet&)m_creature).getPetType() == MINI_PET) ) + if( inCombat || !u || (m_creature->isPet() && ((Pet*)m_creature)->getPetType() == MINI_PET) ) return; if(m_creature->Attack(u,true)) @@ -274,7 +274,7 @@ void PetAI::UpdateAI(const uint32 diff) m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id); if (m_creature->isPet()) - ((Pet&)m_creature).CheckLearning(spell->m_spellInfo->Id); + ((Pet*)m_creature)->CheckLearning(spell->m_spellInfo->Id); spell->prepare(&targets); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3bc5af93b..af44ab212 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 "7670" + #define REVISION_NR "7671" #endif // __REVISION_NR_H__ From 78dd259c38d66381e9e31921470c8ffdb41c6053 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 15 Apr 2009 06:06:42 +0400 Subject: [PATCH 02/22] [7672] Move ReceiveEmote from script API to AI API. This is also fix triggering ReceiveEmote for EventAI broken at it move to mangos sources. --- src/bindings/universal/ScriptMgr.cpp | 9 --------- src/bindings/universal/ScriptMgr.h | 3 +-- src/game/ChatHandler.cpp | 4 ++-- src/game/CreatureAI.h | 6 +++++- src/game/CreatureEventAI.cpp | 18 +++++++----------- src/game/CreatureEventAI.h | 2 +- src/game/ScriptCalls.cpp | 1 - src/game/ScriptCalls.h | 2 -- src/shared/revision_nr.h | 2 +- 9 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/bindings/universal/ScriptMgr.cpp b/src/bindings/universal/ScriptMgr.cpp index e607469b9..0694946b7 100644 --- a/src/bindings/universal/ScriptMgr.cpp +++ b/src/bindings/universal/ScriptMgr.cpp @@ -235,15 +235,6 @@ bool AreaTrigger ( Player *player, AreaTriggerEntry* atEntry ) return tmpscript->pAreaTrigger(player, atEntry); } -MANGOS_DLL_EXPORT -bool ReceiveEmote ( Player *player, Creature *_Creature, uint32 emote ) -{ - Script *tmpscript = m_scripts[_Creature->GetScriptId()]; - if(!tmpscript || !tmpscript->pReceiveEmote) return false; - - return tmpscript->pReceiveEmote(player,_Creature, emote); -} - MANGOS_DLL_EXPORT bool ItemUse( Player *player, Item* _Item, SpellCastTargets const& targets) { diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index 7bfaf2431..5cfb164db 100644 --- a/src/bindings/universal/ScriptMgr.h +++ b/src/bindings/universal/ScriptMgr.h @@ -41,7 +41,7 @@ struct Script pGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGossipSelectWithCode(NULL), pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), pChooseReward(NULL), pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), pGOQuestAccept(NULL), - pGOChooseReward(NULL), pReceiveEmote(NULL), pItemUse(NULL), pEffectDummyGameObj(NULL), pEffectDummyCreature(NULL), + pGOChooseReward(NULL), pItemUse(NULL), pEffectDummyGameObj(NULL), pEffectDummyCreature(NULL), pEffectDummyItem(NULL), GetAI(NULL) {} @@ -63,7 +63,6 @@ struct Script bool (*pItemQuestAccept )(Player *player, Item *_Item, Quest const*_Quest ); bool (*pGOQuestAccept )(Player *player, GameObject *_GO, Quest const*_Quest ); bool (*pGOChooseReward )(Player *player, GameObject *_GO, Quest const*_Quest, uint32 opt ); - bool (*pReceiveEmote )(Player *player, Creature *_Creature, uint32 emote ); bool (*pItemUse )(Player *player, Item* _Item, SpellCastTargets const& targets); bool (*pEffectDummyGameObj )(Unit*, uint32, uint32, GameObject* ); bool (*pEffectDummyCreature )(Unit*, uint32, uint32, Creature* ); diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp index f6774dc01..73f9c187e 100644 --- a/src/game/ChatHandler.cpp +++ b/src/game/ChatHandler.cpp @@ -587,8 +587,8 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data ) GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); //Send scripted event call - if (unit && unit->GetTypeId()==TYPEID_UNIT && Script) - Script->ReceiveEmote(GetPlayer(),(Creature*)unit,text_emote); + if (unit && unit->GetTypeId()==TYPEID_UNIT && ((Creature*)unit)->AI()) + ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(),text_emote); } void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data ) diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index 9b6e29f29..af2fb5e21 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -25,9 +25,10 @@ #include "Dynamic/ObjectRegistry.h" #include "Dynamic/FactoryHolder.h" +class WorldObject; class Unit; class Creature; -class WorldObject; +class Player; struct SpellEntry; #define TIME_INTERVAL_LOOK 5000 @@ -88,6 +89,9 @@ class MANGOS_DLL_SPEC CreatureAI // Called at waypoint reached or point movement finished virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {} + // Called at text emote receive from player + virtual void ReceiveEmote(Player* pPlayer, uint32 text_emote) {} + ///== Triggered Actions Requested ================== // Called when creature attack expected (if creature can and no have current victim) diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 408d80071..d67dc46a6 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -1629,19 +1629,17 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge return true; } -bool CreatureEventAI::ReceiveEmote(Player* pPlayer, Creature* pCreature, uint32 uiEmote) +void CreatureEventAI::ReceiveEmote(Player* pPlayer, uint32 text_emote) { - CreatureEventAI* pTmpCreature = (CreatureEventAI*)(pCreature->AI()); + if (bEmptyList) + return; - if (pTmpCreature->bEmptyList) - return true; - - for (std::list::iterator itr = pTmpCreature->CreatureEventAIList.begin(); itr != pTmpCreature->CreatureEventAIList.end(); ++itr) + for (std::list::iterator itr = CreatureEventAIList.begin(); itr != CreatureEventAIList.end(); ++itr) { if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE) { - if ((*itr).Event.event_param1 != uiEmote) - return true; + if ((*itr).Event.event_param1 != text_emote) + return; bool bProcess = false; @@ -1696,10 +1694,8 @@ bool CreatureEventAI::ReceiveEmote(Player* pPlayer, Creature* pCreature, uint32 if (bProcess) { sLog.outDebug("CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing"); - pTmpCreature->ProcessEvent(*itr, pPlayer); + ProcessEvent(*itr, pPlayer); } } } - - return true; } diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h index 06573ea58..eaf3bfc81 100644 --- a/src/game/CreatureEventAI.h +++ b/src/game/CreatureEventAI.h @@ -265,6 +265,7 @@ class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI void SpellHit(Unit* pUnit, const SpellEntry* pSpell); void UpdateAI(const uint32 diff); bool IsVisible(Unit *) const; + void ReceiveEmote(Player* pPlayer, uint32 text_emote); static int Permissible(const Creature *); bool ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker = NULL); @@ -277,7 +278,6 @@ class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI void DoZoneInCombat(Unit* pUnit); void DoMeleeAttackIfReady(); bool CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered); - bool ReceiveEmote(Player* pPlayer, Creature* pCreature, uint32 uiEmote); Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff); void DoFindFriendlyMissingBuff(std::list& _list, float range, uint32 spellid); diff --git a/src/game/ScriptCalls.cpp b/src/game/ScriptCalls.cpp index ec67773ec..adbdcb1f1 100644 --- a/src/game/ScriptCalls.cpp +++ b/src/game/ScriptCalls.cpp @@ -72,7 +72,6 @@ bool LoadScriptingModule(char const* libName) ||!(testScript->scriptAreaTrigger =(scriptCallAreaTrigger )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"AreaTrigger" )) ||!(testScript->ItemQuestAccept =(scriptCallItemQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemQuestAccept" )) ||!(testScript->GOQuestAccept =(scriptCallGOQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GOQuestAccept" )) - ||!(testScript->ReceiveEmote =(scriptCallReceiveEmote )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ReceiveEmote" )) ||!(testScript->ItemUse =(scriptCallItemUse )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemUse" )) ||!(testScript->EffectDummyGameObj =(scriptCallEffectDummyGameObj )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"EffectDummyGameObj" )) ||!(testScript->EffectDummyCreature =(scriptCallEffectDummyCreature )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"EffectDummyCreature" )) diff --git a/src/game/ScriptCalls.h b/src/game/ScriptCalls.h index 11aade7e7..4c8f46b69 100644 --- a/src/game/ScriptCalls.h +++ b/src/game/ScriptCalls.h @@ -54,7 +54,6 @@ typedef bool(MANGOS_IMPORT * scriptCallAreaTrigger)( Player *player, AreaTrigger typedef bool(MANGOS_IMPORT * scriptCallItemQuestAccept)(Player *player, Item *, Quest const*); typedef bool(MANGOS_IMPORT * scriptCallGOQuestAccept)(Player *player, GameObject *, Quest const*); typedef bool(MANGOS_IMPORT * scriptCallGOChooseReward)(Player *player, GameObject *, Quest const*, uint32 opt ); -typedef bool(MANGOS_IMPORT * scriptCallReceiveEmote) ( Player *player, Creature *_Creature, uint32 emote ); typedef bool(MANGOS_IMPORT * scriptCallItemUse) (Player *player, Item *_Item, SpellCastTargets const& targets); typedef bool(MANGOS_IMPORT * scriptCallEffectDummyGameObj) (Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget); typedef bool(MANGOS_IMPORT * scriptCallEffectDummyCreature) (Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget); @@ -83,7 +82,6 @@ typedef struct scriptCallAreaTrigger scriptAreaTrigger; scriptCallItemQuestAccept ItemQuestAccept; scriptCallGOQuestAccept GOQuestAccept; - scriptCallReceiveEmote ReceiveEmote; scriptCallItemUse ItemUse; scriptCallEffectDummyGameObj EffectDummyGameObj; scriptCallEffectDummyCreature EffectDummyCreature; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index af44ab212..0893222ee 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 "7671" + #define REVISION_NR "7672" #endif // __REVISION_NR_H__ From 3e4b31debb6e30e837c686a2d2a42679bfdb9acf Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 15 Apr 2009 11:46:24 +0400 Subject: [PATCH 03/22] [7673] Fixed pet spell cooldown values send in Player::PetSpellInitialize to client. --- src/game/Player.cpp | 14 ++++---------- src/shared/revision_nr.h | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 994783e83..684cdac66 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -16258,28 +16258,22 @@ void Player::PetSpellInitialize() for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr) { - time_t cooldown = 0; - - if(itr->second > curTime) - cooldown = (itr->second - curTime) * IN_MILISECONDS; + time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILISECONDS : 0; data << uint16(itr->first); // spellid data << uint16(0); // spell category? - data << uint32(itr->second); // cooldown + data << uint32(cooldown); // cooldown data << uint32(0); // category cooldown } for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureCategoryCooldowns.begin(); itr != pet->m_CreatureCategoryCooldowns.end(); ++itr) { - time_t cooldown = 0; - - if(itr->second > curTime) - cooldown = (itr->second - curTime) * IN_MILISECONDS; + time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILISECONDS : 0; data << uint16(itr->first); // spellid data << uint16(0); // spell category? data << uint32(0); // cooldown - data << uint32(itr->second); // category cooldown + data << uint32(cooldown); // category cooldown } GetSession()->SendPacket(&data); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0893222ee..b260e12c8 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 "7672" + #define REVISION_NR "7673" #endif // __REVISION_NR_H__ From 748ea8522a3f87c6030d3680bf2c1a229bd4c01b Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 16 Apr 2009 13:47:01 +0400 Subject: [PATCH 04/22] [7674] Fixed check of DB script string ids from `db_script_string` at loading. --- src/game/ObjectMgr.cpp | 13 ++++++++----- src/shared/revision_nr.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 90ef2211c..fb6f07182 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -7398,13 +7398,16 @@ void ObjectMgr::CheckScripts(ScriptMapMap const& scripts,std::set& ids) { for(ScriptMap::const_iterator itrM = itrMM->second.begin(); itrM != itrMM->second.end(); ++itrM) { - if(itrM->second.dataint) + switch(itrM->second.command) { - if(!GetMangosStringLocale (itrM->second.dataint)) - sLog.outErrorDb( "Table `db_script_string` has not existed string id %u", itrM->first); + case SCRIPT_COMMAND_TALK: + { + if(!GetMangosStringLocale (itrM->second.dataint)) + sLog.outErrorDb( "Table `db_script_string` not has string id %u used db script (ID: %s)", itrM->second.dataint, itrMM->first); - if(ids.count(itrM->second.dataint)) - ids.erase(itrM->second.dataint); + if(ids.count(itrM->second.dataint)) + ids.erase(itrM->second.dataint); + } } } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b260e12c8..ffd9eb987 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 "7673" + #define REVISION_NR "7674" #endif // __REVISION_NR_H__ From b576b2382d4d2abb8848364b8e6bdee57a0ee4c5 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 16 Apr 2009 18:28:25 +0400 Subject: [PATCH 05/22] [7675] Move spell targets in area selection code to function. --- src/game/Spell.cpp | 170 +++++++++------------------------------ src/game/Spell.h | 24 +++--- src/shared/revision_nr.h | 2 +- 3 files changed, 52 insertions(+), 144 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index d9c972297..6c3659c50 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1314,7 +1314,7 @@ struct TargetDistanceOrder : public std::binary_function &TagUnitMap) +void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) { float radius; if (m_spellInfo->EffectRadiusIndex[i]) @@ -1598,38 +1598,16 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) }break; case TARGET_ALL_ENEMY_IN_AREA: { - CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); + FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); + break; + } - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); - - TypeContainerVisitor world_object_notifier(notifier); - TypeContainerVisitor grid_object_notifier(notifier); - - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_object_notifier, *m_caster->GetMap()); - cell_lock->Visit(cell_lock, grid_object_notifier, *m_caster->GetMap()); - }break; case TARGET_ALL_ENEMY_IN_AREA_INSTANT: { // targets the ground, not the units in the area if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) { - CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); - - TypeContainerVisitor world_object_notifier(notifier); - TypeContainerVisitor grid_object_notifier(notifier); - - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_object_notifier, *m_caster->GetMap()); - cell_lock->Visit(cell_lock, grid_object_notifier, *m_caster->GetMap()); + FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); // exclude caster (this can be important if this not original caster) TagUnitMap.remove(m_caster); @@ -1778,37 +1756,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) m_targets.setDestination(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ()); }break; case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: - { - CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_SELF_CENTER,SPELL_TARGETS_FRIENDLY); - - TypeContainerVisitor world_object_notifier(notifier); - TypeContainerVisitor grid_object_notifier(notifier); - - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_object_notifier, *m_caster->GetMap()); - cell_lock->Visit(cell_lock, grid_object_notifier, *m_caster->GetMap()); - }break; + FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_SELF_CENTER,SPELL_TARGETS_FRIENDLY); + break; case TARGET_ALL_FRIENDLY_UNITS_IN_AREA: - { - CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_FRIENDLY); - - TypeContainerVisitor world_object_notifier(notifier); - TypeContainerVisitor grid_object_notifier(notifier); - - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_object_notifier, *m_caster->GetMap()); - cell_lock->Visit(cell_lock, grid_object_notifier, *m_caster->GetMap()); - }break; + FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_SELF_CENTER,SPELL_TARGETS_FRIENDLY); + break; // TARGET_SINGLE_PARTY means that the spells can only be casted on a party member and not on the caster (some seals, fire shield from imp, etc..) case TARGET_SINGLE_PARTY: { @@ -1871,21 +1823,10 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) }break; case TARGET_IN_FRONT_OF_CASTER: { - CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - bool inFront = m_spellInfo->SpellVisual[0] != 3879; - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE); - - TypeContainerVisitor world_object_notifier(notifier); - TypeContainerVisitor grid_object_notifier(notifier); - - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_object_notifier, *m_caster->GetMap()); - cell_lock->Visit(cell_lock, grid_object_notifier, *m_caster->GetMap()); - }break; + FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),radius,inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE); + break; + } case TARGET_DUELVSPLAYER: { Unit *target = m_targets.getUnitTarget(); @@ -1921,22 +1862,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) { // targets the ground, not the units in the area if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) - { - CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); - - TypeContainerVisitor world_object_notifier(notifier); - TypeContainerVisitor grid_object_notifier(notifier); - - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_object_notifier, *m_caster->GetMap()); - cell_lock->Visit(cell_lock, grid_object_notifier, *m_caster->GetMap()); - } - }break; + FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); + break; + } case TARGET_MINION: { if(m_spellInfo->Effect[i] != SPELL_EFFECT_DUEL) @@ -2038,24 +1966,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) unMaxTargets = EffectChainTarget; float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; - std::list tempUnitMap; + UnitList tempUnitMap; - { - CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, tempUnitMap, max_range, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY); - - TypeContainerVisitor world_object_notifier(notifier); - TypeContainerVisitor grid_object_notifier(notifier); - - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_object_notifier, *m_caster->GetMap()); - cell_lock->Visit(cell_lock, grid_object_notifier, *m_caster->GetMap()); - - } + FillAreaTargets(tempUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),max_range,PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY); if(m_caster != pUnitTarget && std::find(tempUnitMap.begin(),tempUnitMap.end(),m_caster) == tempUnitMap.end() ) tempUnitMap.push_front(m_caster); @@ -2108,20 +2021,10 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) TagUnitMap.push_back(currentTarget); m_targets.setDestination(currentTarget->GetPositionX(), currentTarget->GetPositionY(), currentTarget->GetPositionZ()); if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA_INSTANT) - { - CellPair p(MaNGOS::ComputeCellPair(currentTarget->GetPositionX(), currentTarget->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius,PUSH_TARGET_CENTER, SPELL_TARGETS_AOE_DAMAGE); - TypeContainerVisitor world_notifier(notifier); - TypeContainerVisitor grid_notifier(notifier); - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_notifier, *m_caster->GetMap()); - cell_lock->Visit(cell_lock, grid_notifier, *m_caster->GetMap()); - } + FillAreaTargets(TagUnitMap, currentTarget->GetPositionX(), currentTarget->GetPositionY(), radius, PUSH_TARGET_CENTER, SPELL_TARGETS_AOE_DAMAGE); } - }break; + break; + } case TARGET_AREAEFFECT_PARTY_AND_CLASS: { Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER @@ -2158,24 +2061,12 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) // if B==TARGET_TABLE_X_Y_Z_COORDINATES then A already fill all required targets if (m_spellInfo->EffectImplicitTargetB[i] && m_spellInfo->EffectImplicitTargetB[i]!=TARGET_TABLE_X_Y_Z_COORDINATES) { - CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - SpellTargets targetB = SPELL_TARGETS_AOE_DAMAGE; // Select friendly targets for positive effect if (IsPositiveEffect(m_spellInfo->Id, i)) targetB = SPELL_TARGETS_FRIENDLY; - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius,PUSH_DEST_CENTER, targetB); - - TypeContainerVisitor world_notifier(notifier); - TypeContainerVisitor grid_notifier(notifier); - - CellLock cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_notifier, *m_caster->GetMap()); - cell_lock->Visit(cell_lock, grid_notifier, *m_caster->GetMap()); + FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),radius, PUSH_DEST_CENTER, targetB); } } else @@ -2238,7 +2129,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) { // make sure one unit is always removed per iteration uint32 removed_utarget = 0; - for (std::list::iterator itr = TagUnitMap.begin(), next; itr != TagUnitMap.end(); itr = next) + for (UnitList::iterator itr = TagUnitMap.begin(), next; itr != TagUnitMap.end(); itr = next) { next = itr; ++next; @@ -2254,9 +2145,10 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) while (TagUnitMap.size() > unMaxTargets - removed_utarget) { uint32 poz = urand(0, TagUnitMap.size()-1); - for (std::list::iterator itr = TagUnitMap.begin(); itr != TagUnitMap.end(); ++itr, --poz) + for (UnitList::iterator itr = TagUnitMap.begin(); itr != TagUnitMap.end(); ++itr, --poz) { if (!*itr) continue; + if (!poz) { TagUnitMap.erase(itr); @@ -5731,3 +5623,17 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk return SPELL_CAST_OK; } + +void Spell::FillAreaTargets( UnitList& TagUnitMap, float x, float y, float radius, SpellNotifyPushType pushType, SpellTargets spellTargets ) +{ + CellPair p(MaNGOS::ComputeCellPair(x, y)); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, pushType, spellTargets); + TypeContainerVisitor world_notifier(notifier); + TypeContainerVisitor grid_notifier(notifier); + CellLock cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_notifier, *m_caster->GetMap()); + cell_lock->Visit(cell_lock, grid_notifier, *m_caster->GetMap()); +} diff --git a/src/game/Spell.h b/src/game/Spell.h index 468ce8884..f621c2d41 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -205,6 +205,15 @@ enum SpellState SPELL_STATE_DELAYED = 5 }; +enum SpellTargets +{ + SPELL_TARGETS_HOSTILE, + SPELL_TARGETS_NOT_FRIENDLY, + SPELL_TARGETS_NOT_HOSTILE, + SPELL_TARGETS_FRIENDLY, + SPELL_TARGETS_AOE_DAMAGE +}; + #define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL (1*IN_MILISECONDS) typedef std::multimap SpellTargetTimeMap; @@ -366,9 +375,11 @@ class Spell void DoCreateItem(uint32 i, uint32 itemtype); void WriteSpellGoTargets( WorldPacket * data ); void WriteAmmoToPacket( WorldPacket * data ); - void FillTargetMap(); - void SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap); + typedef std::list UnitList; + void FillTargetMap(); + void SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap); + void FillAreaTargets( UnitList& TagUnitMap, float x, float y, float radius, SpellNotifyPushType pushType, SpellTargets spellTargets ); Unit* SelectMagnetTarget(); bool CheckTarget( Unit* target, uint32 eff ); @@ -579,15 +590,6 @@ enum ReplenishType REPLENISH_RAGE = 22 }; -enum SpellTargets -{ - SPELL_TARGETS_HOSTILE, - SPELL_TARGETS_NOT_FRIENDLY, - SPELL_TARGETS_NOT_HOSTILE, - SPELL_TARGETS_FRIENDLY, - SPELL_TARGETS_AOE_DAMAGE -}; - namespace MaNGOS { struct MANGOS_DLL_DECL SpellNotifierPlayer diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ffd9eb987..51a7ed6ee 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 "7674" + #define REVISION_NR "7675" #endif // __REVISION_NR_H__ From 30d8be94cec0b0942943afa0ac6fece84d0ebd20 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 16 Apr 2009 18:50:31 +0400 Subject: [PATCH 06/22] [7676] Fixed typo in [7675] --- src/game/Spell.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 6c3659c50..de5b306bc 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1759,7 +1759,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_SELF_CENTER,SPELL_TARGETS_FRIENDLY); break; case TARGET_ALL_FRIENDLY_UNITS_IN_AREA: - FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_SELF_CENTER,SPELL_TARGETS_FRIENDLY); + FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_FRIENDLY); break; // TARGET_SINGLE_PARTY means that the spells can only be casted on a party member and not on the caster (some seals, fire shield from imp, etc..) case TARGET_SINGLE_PARTY: diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 51a7ed6ee..50b1ed5e7 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 "7675" + #define REVISION_NR "7676" #endif // __REVISION_NR_H__ From 650be82030112cb29256586a6df017fa17130d43 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 17 Apr 2009 11:21:58 +0400 Subject: [PATCH 07/22] [7677] Fixed crash at error report attempt at `db_script_string` loading. --- src/game/ObjectMgr.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index fb6f07182..27d770962 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -7403,7 +7403,7 @@ void ObjectMgr::CheckScripts(ScriptMapMap const& scripts,std::set& ids) case SCRIPT_COMMAND_TALK: { if(!GetMangosStringLocale (itrM->second.dataint)) - sLog.outErrorDb( "Table `db_script_string` not has string id %u used db script (ID: %s)", itrM->second.dataint, itrMM->first); + sLog.outErrorDb( "Table `db_script_string` not has string id %u used db script (ID: %u)", itrM->second.dataint, itrMM->first); if(ids.count(itrM->second.dataint)) ids.erase(itrM->second.dataint); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 50b1ed5e7..d6c06a4f5 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 "7676" + #define REVISION_NR "7677" #endif // __REVISION_NR_H__ From 09c32b54293ecb3458b8f953eca7952938513d0c Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 17 Apr 2009 13:36:29 +0400 Subject: [PATCH 08/22] [7678] Implement spell target mode 7 and cleanup target mode 17. --- src/game/SharedDefines.h | 1 + src/game/Spell.cpp | 39 ++++++++++++++++++++++++++------------- src/game/SpellAuras.cpp | 8 ++++---- src/game/SpellEffects.cpp | 1 + src/game/SpellMgr.h | 1 + src/shared/revision_nr.h | 2 +- 6 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 53a231ed2..99fc7f7e2 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -988,6 +988,7 @@ enum Targets TARGET_RANDOM_FRIEND_CHAIN_IN_AREA = 3, TARGET_PET = 5, TARGET_CHAIN_DAMAGE = 6, + TARGET_AREAEFFECT_INSTANT = 7, // targets around provided destination point TARGET_AREAEFFECT_CUSTOM = 8, TARGET_INNKEEPER_COORDINATES = 9, // uses in teleport to innkeeper spells TARGET_ALL_ENEMY_IN_AREA = 15, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index de5b306bc..768ab6b40 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -457,6 +457,11 @@ void Spell::FillTargetMap() case 0: SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); break; + case TARGET_AREAEFFECT_INSTANT: // use B case that not dependent from from A in fact + if((m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)==0) + m_targets.setDestination(m_caster->GetPositionX(),m_caster->GetPositionY(),m_caster->GetPositionZ()); + SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + break; case TARGET_BEHIND_VICTIM: // use B case that not dependent from from A in fact SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); break; @@ -482,8 +487,14 @@ void Spell::FillTargetMap() } break; case TARGET_TABLE_X_Y_Z_COORDINATES: - // Only if target A, for target B (used in teleports) dest select in effect - SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); + // All 17/7 pairs used for dest teleportation, A processed in effect code + if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_AREAEFFECT_INSTANT) + SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + else + { + SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); + SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + } break; default: switch(m_spellInfo->EffectImplicitTargetB[i]) @@ -1601,7 +1612,18 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); break; } + case TARGET_AREAEFFECT_INSTANT: + { + SpellTargets targetB = SPELL_TARGETS_AOE_DAMAGE; + // Select friendly targets for positive effect + if (IsPositiveEffect(m_spellInfo->Id, i)) + targetB = SPELL_TARGETS_FRIENDLY; + FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),radius, PUSH_DEST_CENTER, targetB); + + // exclude caster + TagUnitMap.remove(m_caster); + } case TARGET_ALL_ENEMY_IN_AREA_INSTANT: { // targets the ground, not the units in the area @@ -2057,17 +2079,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) { if (st->target_mapId == m_caster->GetMapId()) m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); - - // if B==TARGET_TABLE_X_Y_Z_COORDINATES then A already fill all required targets - if (m_spellInfo->EffectImplicitTargetB[i] && m_spellInfo->EffectImplicitTargetB[i]!=TARGET_TABLE_X_Y_Z_COORDINATES) - { - SpellTargets targetB = SPELL_TARGETS_AOE_DAMAGE; - // Select friendly targets for positive effect - if (IsPositiveEffect(m_spellInfo->Id, i)) - targetB = SPELL_TARGETS_FRIENDLY; - - FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),radius, PUSH_DEST_CENTER, targetB); - } + else + sLog.outError( "SPELL: wrong map (%u instead %u) target coordinates for spell ID %u", st->target_mapId, m_caster->GetMapId(), m_spellInfo->Id ); } else sLog.outError( "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id ); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 55a08c912..a02ea15a4 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -463,12 +463,12 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, { case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: m_areaAuraType = AREA_AURA_PARTY; - if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) + if (target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) m_modifier.m_auraname = SPELL_AURA_NONE; break; case SPELL_EFFECT_APPLY_AREA_AURA_RAID: m_areaAuraType = AREA_AURA_RAID; - if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) + if (target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) m_modifier.m_auraname = SPELL_AURA_NONE; break; case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: @@ -476,7 +476,7 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, break; case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: m_areaAuraType = AREA_AURA_ENEMY; - if(target == caster_ptr) + if (target == caster_ptr) m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self break; case SPELL_EFFECT_APPLY_AREA_AURA_PET: @@ -484,7 +484,7 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, break; case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: m_areaAuraType = AREA_AURA_OWNER; - if(target == caster_ptr) + if (target == caster_ptr) m_modifier.m_auraname = SPELL_AURA_NONE; break; default: diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 74ed51043..13d1f039f 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2097,6 +2097,7 @@ void Spell::EffectTeleportUnits(uint32 i) ((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0); return; } + case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES case TARGET_TABLE_X_Y_Z_COORDINATES: { SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id); diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index d026ccb36..ae0820ca3 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -181,6 +181,7 @@ inline bool IsAreaEffectTarget( Targets target ) { switch (target ) { + case TARGET_AREAEFFECT_INSTANT: case TARGET_AREAEFFECT_CUSTOM: case TARGET_ALL_ENEMY_IN_AREA: case TARGET_ALL_ENEMY_IN_AREA_INSTANT: diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index d6c06a4f5..700ecd909 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 "7677" + #define REVISION_NR "7678" #endif // __REVISION_NR_H__ From f926232efbf53f6e68f8e0b9c587416d6cb2dbcd Mon Sep 17 00:00:00 2001 From: NoFantasy Date: Fri, 17 Apr 2009 15:44:44 +0400 Subject: [PATCH 09/22] [7679] More checks for creature EventAI loading at server startup. Signed-off-by: VladimirMangos --- src/game/CreatureEventAI.cpp | 2 +- src/game/CreatureEventAI.h | 116 ++++++++------- src/game/CreatureEventAIMgr.cpp | 253 +++++++++++++++++++++++--------- src/shared/revision_nr.h | 2 +- 4 files changed, 241 insertions(+), 132 deletions(-) diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index d67dc46a6..dc7ad3fec 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -47,7 +47,7 @@ CreatureEventAI::CreatureEventAI(Creature *c ) : CreatureAI(c), InCombat(false) { //Debug check - #ifndef _DEBUG + #ifndef MANGOS_DEBUG if ((*i).event_flags & EFLAG_DEBUG_ONLY) continue; #endif diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h index eaf3bfc81..5cdbb140b 100644 --- a/src/game/CreatureEventAI.h +++ b/src/game/CreatureEventAI.h @@ -32,74 +32,74 @@ class WorldObject; #define MAX_ACTIONS 3 #define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available -enum Event_Types +enum EventAI_Type { - EVENT_T_TIMER = 0, //InitialMin, InitialMax, RepeatMin, RepeatMax - EVENT_T_TIMER_OOC = 1, //InitialMin, InitialMax, RepeatMin, RepeatMax - EVENT_T_HP = 2, //HPMax%, HPMin%, RepeatMin, RepeatMax - EVENT_T_MANA = 3, //ManaMax%,ManaMin% RepeatMin, RepeatMax - EVENT_T_AGGRO = 4, //NONE - EVENT_T_KILL = 5, //RepeatMin, RepeatMax - EVENT_T_DEATH = 6, //NONE - EVENT_T_EVADE = 7, //NONE - EVENT_T_SPELLHIT = 8, //SpellID, School, RepeatMin, RepeatMax - EVENT_T_RANGE = 9, //MinDist, MaxDist, RepeatMin, RepeatMax - EVENT_T_OOC_LOS = 10, //NoHostile, NoFriendly, RepeatMin, RepeatMax - EVENT_T_SPAWNED = 11, //NONE - EVENT_T_TARGET_HP = 12, //HPMax%, HPMin%, RepeatMin, RepeatMax - EVENT_T_TARGET_CASTING = 13, //RepeatMin, RepeatMax - EVENT_T_FRIENDLY_HP = 14, //HPDeficit, Radius, RepeatMin, RepeatMax - EVENT_T_FRIENDLY_IS_CC = 15, //DispelType, Radius, RepeatMin, RepeatMax - EVENT_T_FRIENDLY_MISSING_BUFF = 16, //SpellId, Radius, RepeatMin, RepeatMax - EVENT_T_SUMMONED_UNIT = 17, //CreatureId, RepeatMin, RepeatMax - EVENT_T_TARGET_MANA = 18, //ManaMax%, ManaMin%, RepeatMin, RepeatMax - EVENT_T_QUEST_ACCEPT = 19, //QuestID + EVENT_T_TIMER = 0, // InitialMin, InitialMax, RepeatMin, RepeatMax + EVENT_T_TIMER_OOC = 1, // InitialMin, InitialMax, RepeatMin, RepeatMax + EVENT_T_HP = 2, // HPMax%, HPMin%, RepeatMin, RepeatMax + EVENT_T_MANA = 3, // ManaMax%,ManaMin% RepeatMin, RepeatMax + EVENT_T_AGGRO = 4, // NONE + EVENT_T_KILL = 5, // RepeatMin, RepeatMax + EVENT_T_DEATH = 6, // NONE + EVENT_T_EVADE = 7, // NONE + EVENT_T_SPELLHIT = 8, // SpellID, School, RepeatMin, RepeatMax + EVENT_T_RANGE = 9, // MinDist, MaxDist, RepeatMin, RepeatMax + EVENT_T_OOC_LOS = 10, // NoHostile, NoFriendly, RepeatMin, RepeatMax + EVENT_T_SPAWNED = 11, // NONE + EVENT_T_TARGET_HP = 12, // HPMax%, HPMin%, RepeatMin, RepeatMax + EVENT_T_TARGET_CASTING = 13, // RepeatMin, RepeatMax + EVENT_T_FRIENDLY_HP = 14, // HPDeficit, Radius, RepeatMin, RepeatMax + EVENT_T_FRIENDLY_IS_CC = 15, // DispelType, Radius, RepeatMin, RepeatMax + EVENT_T_FRIENDLY_MISSING_BUFF = 16, // SpellId, Radius, RepeatMin, RepeatMax + EVENT_T_SUMMONED_UNIT = 17, // CreatureId, RepeatMin, RepeatMax + EVENT_T_TARGET_MANA = 18, // ManaMax%, ManaMin%, RepeatMin, RepeatMax + EVENT_T_QUEST_ACCEPT = 19, // QuestID EVENT_T_QUEST_COMPLETE = 20, // - EVENT_T_REACHED_HOME = 21, //NONE - EVENT_T_RECEIVE_EMOTE = 22, //EmoteId, Condition, CondValue1, CondValue2 + EVENT_T_REACHED_HOME = 21, // NONE + EVENT_T_RECEIVE_EMOTE = 22, // EmoteId, Condition, CondValue1, CondValue2 EVENT_T_END, }; -enum Action_Types +enum EventAI_ActionType { - ACTION_T_NONE = 0, //No action - ACTION_T_TEXT = 1, //-TextId1, optionally -TextId2, optionally -TextId3(if -TextId2 exist). If more than just -TextId1 is defined, randomize. Negative values. - ACTION_T_SET_FACTION = 2, //FactionId (or 0 for default) - ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3, //Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph) - ACTION_T_SOUND = 4, //SoundId - ACTION_T_EMOTE = 5, //EmoteId - ACTION_T_RANDOM_SAY = 6, //UNUSED - ACTION_T_RANDOM_YELL = 7, //UNUSED - ACTION_T_RANDOM_TEXTEMOTE = 8, //UNUSED + ACTION_T_NONE = 0, //*No action + ACTION_T_TEXT = 1, //*-TextId1, optionally -TextId2, optionally -TextId3(if -TextId2 exist). If more than just -TextId1 is defined, randomize. Negative values. + ACTION_T_SET_FACTION = 2, //*FactionId (or 0 for default) + ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3, //*Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph) + ACTION_T_SOUND = 4, //*SoundId + ACTION_T_EMOTE = 5, //*EmoteId + ACTION_T_RANDOM_SAY = 6, //*UNUSED + ACTION_T_RANDOM_YELL = 7, //*UNUSED + ACTION_T_RANDOM_TEXTEMOTE = 8, //*UNUSED ACTION_T_RANDOM_SOUND = 9, //SoundId1, SoundId2, SoundId3 (-1 in any field means no output if randomed that field) - ACTION_T_RANDOM_EMOTE = 10, //EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field) - ACTION_T_CAST = 11, //SpellId, Target, CastFlags - ACTION_T_SUMMON = 12, //CreatureID, Target, Duration in ms - ACTION_T_THREAT_SINGLE_PCT = 13, //Threat%, Target + ACTION_T_RANDOM_EMOTE = 10, //*EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field) + ACTION_T_CAST = 11, //*SpellId, Target, CastFlags + ACTION_T_SUMMON = 12, //*CreatureID, Target, Duration in ms + ACTION_T_THREAT_SINGLE_PCT = 13, //*Threat%, Target ACTION_T_THREAT_ALL_PCT = 14, //Threat% - ACTION_T_QUEST_EVENT = 15, //QuestID, Target - ACTION_T_CASTCREATUREGO = 16, //QuestID, SpellId, Target - ACTION_T_SET_UNIT_FIELD = 17, //Field_Number, Value, Target - ACTION_T_SET_UNIT_FLAG = 18, //Flags (may be more than one field OR'd together), Target - ACTION_T_REMOVE_UNIT_FLAG = 19, //Flags (may be more than one field OR'd together), Target + ACTION_T_QUEST_EVENT = 15, //*QuestID, Target + ACTION_T_CASTCREATUREGO = 16, //*QuestID, SpellId, Target + ACTION_T_SET_UNIT_FIELD = 17, //*Field_Number, Value, Target + ACTION_T_SET_UNIT_FLAG = 18, //*Flags (may be more than one field OR'd together), Target + ACTION_T_REMOVE_UNIT_FLAG = 19, //*Flags (may be more than one field OR'd together), Target ACTION_T_AUTO_ATTACK = 20, //AllowAttackState (0 = stop attack, anything else means continue attacking) ACTION_T_COMBAT_MOVEMENT = 21, //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking) - ACTION_T_SET_PHASE = 22, //Phase - ACTION_T_INC_PHASE = 23, //Value (may be negative to decrement phase, should not be 0) + ACTION_T_SET_PHASE = 22, //*Phase + ACTION_T_INC_PHASE = 23, //*Value (may be negative to decrement phase, should not be 0) ACTION_T_EVADE = 24, //No Params ACTION_T_FLEE = 25, //No Params - ACTION_T_QUEST_EVENT_ALL = 26, //QuestID - ACTION_T_CASTCREATUREGO_ALL = 27, //QuestId, SpellId - ACTION_T_REMOVEAURASFROMSPELL = 28, //Target, Spellid + ACTION_T_QUEST_EVENT_ALL = 26, //*QuestID + ACTION_T_CASTCREATUREGO_ALL = 27, //*QuestId, SpellId + ACTION_T_REMOVEAURASFROMSPELL = 28, //*Target, Spellid ACTION_T_RANGED_MOVEMENT = 29, //Distance, Angle ACTION_T_RANDOM_PHASE = 30, //PhaseId1, PhaseId2, PhaseId3 ACTION_T_RANDOM_PHASE_RANGE = 31, //PhaseMin, PhaseMax - ACTION_T_SUMMON_ID = 32, //CreatureId, Target, SpawnId - ACTION_T_KILLED_MONSTER = 33, //CreatureId, Target - ACTION_T_SET_INST_DATA = 34, //Field, Data - ACTION_T_SET_INST_DATA64 = 35, //Field, Target - ACTION_T_UPDATE_TEMPLATE = 36, //Entry, Team + ACTION_T_SUMMON_ID = 32, //*CreatureId, Target, SpawnId + ACTION_T_KILLED_MONSTER = 33, //*CreatureId, Target + ACTION_T_SET_INST_DATA = 34, //*Field, Data + ACTION_T_SET_INST_DATA64 = 35, //*Field, Target + ACTION_T_UPDATE_TEMPLATE = 36, //*Entry, Team ACTION_T_DIE = 37, //No Params ACTION_T_ZONE_COMBAT_PULSE = 38, //No Params @@ -152,7 +152,7 @@ enum EventFlags EFLAG_RESERVED_4 = 0x10, EFLAG_RESERVED_5 = 0x20, EFLAG_RESERVED_6 = 0x40, - EFLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build of SD2 only + EFLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build }; // String text additional data, used in (CreatureEventAI) @@ -172,10 +172,12 @@ struct CreatureEventAI_Event uint32 creature_id; - uint16 event_type; uint32 event_inverse_phase_mask; - uint8 event_chance; - uint8 event_flags; + + EventAI_Type event_type : 16; + uint8 event_chance : 8; + uint8 event_flags : 8; + union { uint32 event_param1; @@ -199,7 +201,7 @@ struct CreatureEventAI_Event struct _action { - uint16 type; + EventAI_ActionType type: 16; union { uint32 param1; diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp index 857f6c325..b0e6f1a67 100644 --- a/src/game/CreatureEventAIMgr.cpp +++ b/src/game/CreatureEventAIMgr.cpp @@ -171,38 +171,41 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() Field *fields = result->Fetch(); CreatureEventAI_Event temp; - - temp.event_id = fields[0].GetUInt32(); + temp.event_id = EventAI_Type(fields[0].GetUInt32()); uint32 i = temp.event_id; + temp.creature_id = fields[1].GetUInt32(); uint32 creature_id = temp.creature_id; - temp.event_type = fields[2].GetUInt16(); + + uint32 e_type = fields[2].GetUInt32(); + //Report any errors in event + if (e_type >= EVENT_T_END) + { + sLog.outErrorDb("CreatureEventAI: Event %u have wrong type (%u), skipping.", i,e_type); + continue; + } + temp.event_type = EventAI_Type(e_type); + temp.event_inverse_phase_mask = fields[3].GetUInt32(); temp.event_chance = fields[4].GetUInt8(); - temp.event_flags = fields[5].GetUInt8(); + temp.event_flags = fields[5].GetUInt8(); temp.event_param1 = fields[6].GetUInt32(); temp.event_param2 = fields[7].GetUInt32(); temp.event_param3 = fields[8].GetUInt32(); temp.event_param4 = fields[9].GetUInt32(); - CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(temp.creature_id); //Creature does not exist in database - if (!cInfo) + if (!sCreatureStorage.LookupEntry(temp.creature_id)) { - sLog.outErrorDb("CreatureEventAI: Event %u has script for non-existing creature.", i); + sLog.outErrorDb("CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, temp.creature_id); continue; } - //Report any errors in event - if (temp.event_type >= EVENT_T_END) - sLog.outErrorDb("CreatureEventAI: Event %u has incorrect event type. Maybe DB requires updated version of SD2.", i); - //No chance of this event occuring if (temp.event_chance == 0) sLog.outErrorDb("CreatureEventAI: Event %u has 0 percent chance. Event will never trigger!", i); - //Chance above 100, force it to be 100 - if (temp.event_chance > 100) + else if (temp.event_chance > 100) { sLog.outErrorDb("CreatureEventAI: Creature %u are using event %u with more than 100 percent chance. Adjusting to 100 percent.", temp.creature_id, i); temp.event_chance = 100; @@ -211,6 +214,18 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() //Individual event checks switch (temp.event_type) { + case EVENT_T_TIMER: + case EVENT_T_TIMER_OOC: + { + if (temp.event_param2 < temp.event_param1) + sLog.outErrorDb("CreatureEventAI: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i); + + if (temp.event_param4 < temp.event_param3) + sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + + break; + } + case EVENT_T_HP: case EVENT_T_MANA: case EVENT_T_TARGET_HP: @@ -226,14 +241,14 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() sLog.outErrorDb("CreatureEventAI: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i); temp.event_flags &= ~EFLAG_REPEATABLE; } + break; } - break; case EVENT_T_SPELLHIT: { if (temp.event_param1) { - SpellEntry const* pSpell = GetSpellStore()->LookupEntry(temp.event_param1); + SpellEntry const* pSpell = sSpellStore.LookupEntry(temp.event_param1); if (!pSpell) { sLog.outErrorDb("CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.event_param1, i); @@ -251,8 +266,8 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() if (temp.event_param4 < temp.event_param3) sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + break; } - break; case EVENT_T_RANGE: case EVENT_T_OOC_LOS: @@ -260,29 +275,28 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() case EVENT_T_FRIENDLY_IS_CC: case EVENT_T_FRIENDLY_MISSING_BUFF: { - if (temp.event_param4 < temp.event_param3) - sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); - } - break; - - case EVENT_T_TIMER: - case EVENT_T_TIMER_OOC: - { - if (temp.event_param2 < temp.event_param1) - sLog.outErrorDb("CreatureEventAI: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i); + //Disabled check for now. Check code related to events and adjust accordingly before enable. + //Events should have min/max or alternative set to a static value. + /*if (!temp.event_param3 && !temp.event_param4) + { + sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) without param3/param4 (RepeatMin/RepeatMax). Using minimum values.", temp.creature_id, i); + temp.event_param3 = 2500; + temp.event_param4 = 2500; + }*/ if (temp.event_param4 < temp.event_param3) sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + break; } - break; case EVENT_T_KILL: case EVENT_T_TARGET_CASTING: { if (temp.event_param2 < temp.event_param1) sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + + break; } - break; case EVENT_T_AGGRO: case EVENT_T_DEATH: @@ -295,13 +309,70 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() sLog.outErrorDb("CreatureEventAI: Creature %u has EFLAG_REPEATABLE set. Event can never be repeatable. Removing flag for event %u.", temp.creature_id, i); temp.event_flags &= ~EFLAG_REPEATABLE; } + + break; } - break; + + case EVENT_T_RECEIVE_EMOTE: + { + if (!sEmotesTextStore.LookupEntry(temp.event_param1)) + { + sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param1 (EmoteTextId: %u) are not valid.",temp.creature_id, i, temp.event_param1); + continue; + } + + if (temp.event_param2 == CONDITION_AD_COMMISSION_AURA || temp.event_param2 == CONDITION_NO_AURA) + { + sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not implemented for EventAI.",temp.creature_id, i, temp.event_param2); + continue; + } + + if (!PlayerCondition::IsValid(ConditionType(temp.event_param2), temp.event_param3, temp.event_param4)) + { + sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not valid.",temp.creature_id, i, temp.event_param2); + continue; + } + + if (!(temp.event_flags & EFLAG_REPEATABLE)) + { + sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: EFLAG_REPEATABLE not set. Event must always be repeatable. Flag applied.", temp.creature_id, i); + temp.event_flags |= EFLAG_REPEATABLE; + } + + break; + } + + case EVENT_T_SUMMONED_UNIT: + { + if (!sCreatureStorage.LookupEntry(temp.event_param1)) + sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with not existed creature template id (%u) in param1, skipped.", temp.creature_id, i, temp.event_param1); + + if (temp.event_param3 < temp.event_param2) + sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param3 < param2 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); + + break; + } + + case EVENT_T_QUEST_ACCEPT: + case EVENT_T_QUEST_COMPLETE: + sLog.outErrorDb("CreatureEventAI: Creature %u using not implemented event (%u) in event %u.", temp.creature_id, temp.event_id, i); + continue; + default: + sLog.outErrorDb("CreatureEventAI: Creature %u using not checked at load event (%u) in event %u. Need check code update?", temp.creature_id, temp.event_id, i); + break; } for (uint32 j = 0; j < MAX_ACTIONS; j++) { - temp.action[j].type = fields[10+(j*4)].GetUInt16(); + uint16 action_type = fields[10+(j*4)].GetUInt16(); + if (action_type >= ACTION_T_END) + { + sLog.outErrorDb("CreatureEventAI: Event %u Action %u has incorrect action type (%u), replace by ACTION_T_NONE.", i, j+1, action_type); + temp.action[j].type = ACTION_T_NONE; + continue; + } + + temp.action[j].type = EventAI_ActionType(action_type); temp.action[j].param1 = fields[11+(j*4)].GetUInt32(); temp.action[j].param2 = fields[12+(j*4)].GetUInt32(); temp.action[j].param3 = fields[13+(j*4)].GetUInt32(); @@ -309,6 +380,8 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() //Report any errors in actions switch (temp.action[j].type) { + case ACTION_T_NONE: + break; case ACTION_T_TEXT: { if (temp.action[j].param1_s < 0) @@ -332,10 +405,10 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() if (!temp.action[j].param1_s || !temp.action[j].param2_s) sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1); } + break; } - break; case ACTION_T_SET_FACTION: - if (temp.action[j].param1 !=0 && !GetFactionStore()->LookupEntry(temp.action[j].param1)) + if (temp.action[j].param1 !=0 && !sFactionStore.LookupEntry(temp.action[j].param1)) { sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant FactionId %u.", i, j+1, temp.action[j].param1); temp.action[j].param1 = 0; @@ -344,13 +417,13 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() case ACTION_T_MORPH_TO_ENTRY_OR_MODEL: if (temp.action[j].param1 !=0 || temp.action[j].param2 !=0) { - if (temp.action[j].param1 && !GetCreatureTemplateStore(temp.action[j].param1)) + if (temp.action[j].param1 && !sCreatureStorage.LookupEntry(temp.action[j].param1)) { sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, temp.action[j].param1); temp.action[j].param1 = 0; } - if (temp.action[j].param2 && !GetCreatureDisplayStore()->LookupEntry(temp.action[j].param2)) + if (temp.action[j].param2 && !sCreatureDisplayInfoStore.LookupEntry(temp.action[j].param2)) { sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, temp.action[j].param2); temp.action[j].param2 = 0; @@ -358,24 +431,38 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() } break; case ACTION_T_SOUND: - if (!GetSoundEntriesStore()->LookupEntry(temp.action[j].param1)) + if (!sSoundEntriesStore.LookupEntry(temp.action[j].param1)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, temp.action[j].param1); break; -/* case ACTION_T_RANDOM_SOUND: - { - if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param1)) + if (!sSoundEntriesStore.LookupEntry(temp.action[j].param1)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, temp.action[j].param1); - if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param2)) + if (temp.action[j].param2_s >= 0 && !sSoundEntriesStore.LookupEntry(temp.action[j].param2)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, temp.action[j].param2); - if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param3)) + if (temp.action[j].param3_s >= 0 && !sSoundEntriesStore.LookupEntry(temp.action[j].param3)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, temp.action[j].param3); - } - break; - */ + break; + case ACTION_T_EMOTE: + //TODO: load emotes and check it's store for existing + /* + if (!sEmotesStore.LookupEntry(temp.action[j].param1)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param1); + */ + break; + case ACTION_T_RANDOM_EMOTE: + //TODO: load emotes and check it's store for existing + /* + if (!sEmotesStore.LookupEntry(temp.action[j].param1)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param1); + if (temp.action[j].param2_s >= 0 && !sEmotesStore.LookupEntry(temp.action[j].param2)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param2); + if (temp.action[j].param3_s >= 0 && !sEmotesStore.LookupEntry(temp.action[j].param3)) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param3); + */ + break; case ACTION_T_CAST: { - const SpellEntry *spell = GetSpellStore()->LookupEntry(temp.action[j].param1); + const SpellEntry *spell = sSpellStore.LookupEntry(temp.action[j].param1); if (!spell) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param1); else @@ -384,26 +471,26 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() { //output as debug for now, also because there's no general rule all spells have RecoveryTime if (temp.event_param3 < spell->RecoveryTime) - debug_log("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1,temp.action[j].param1, spell->RecoveryTime, temp.event_param3); + sLog.outDebug("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1,temp.action[j].param1, spell->RecoveryTime, temp.event_param3); } } if (temp.action[j].param2 >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; } - break; case ACTION_T_REMOVEAURASFROMSPELL: { - if (!GetSpellStore()->LookupEntry(temp.action[j].param2)) + if (!sSpellStore.LookupEntry(temp.action[j].param2)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); if (temp.action[j].param1 >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; } - break; case ACTION_T_QUEST_EVENT: { - if (Quest const* qid = GetQuestTemplateStore(temp.action[j].param1)) + if (Quest const* qid = objmgr.GetQuestTemplate(temp.action[j].param1)) { if (!qid->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, temp.action[j].param1); @@ -413,45 +500,46 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() if (temp.action[j].param2 >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + + break; } - break; case ACTION_T_QUEST_EVENT_ALL: { - if (Quest const* qid = GetQuestTemplateStore(temp.action[j].param1)) + if (Quest const* qid = objmgr.GetQuestTemplate(temp.action[j].param1)) { if (!qid->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, temp.action[j].param1); } else sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1); + break; } - break; case ACTION_T_CASTCREATUREGO: { - if (!GetCreatureTemplateStore(temp.action[j].param1)) + if (!sCreatureStorage.LookupEntry(temp.action[j].param1)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1); - if (!GetSpellStore()->LookupEntry(temp.action[j].param2)) + if (!sSpellStore.LookupEntry(temp.action[j].param2)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); if (temp.action[j].param3 >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; } - break; case ACTION_T_CASTCREATUREGO_ALL: { - if (!GetQuestTemplateStore(temp.action[j].param1)) + if (!objmgr.GetQuestTemplate(temp.action[j].param1)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1); - if (!GetSpellStore()->LookupEntry(temp.action[j].param2)) + if (!sSpellStore.LookupEntry(temp.action[j].param2)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); + break; } - break; //2nd param target case ACTION_T_SUMMON_ID: { - if (!GetCreatureTemplateStore(temp.action[j].param1)) + if (!sCreatureStorage.LookupEntry(temp.action[j].param1)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1); if (m_CreatureEventAI_Summon_Map.find(temp.action[j].param3) == m_CreatureEventAI_Summon_Map.end()) @@ -459,34 +547,33 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() if (temp.action[j].param2 >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; } - break; case ACTION_T_KILLED_MONSTER: { - if (!GetCreatureTemplateStore(temp.action[j].param1)) + if (!sCreatureStorage.LookupEntry(temp.action[j].param1)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1); if (temp.action[j].param2 >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; } - break; case ACTION_T_SUMMON: { - if (!GetCreatureTemplateStore(temp.action[j].param1)) + if (!sCreatureStorage.LookupEntry(temp.action[j].param1)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1); if (temp.action[j].param2 >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + break; } - break; case ACTION_T_THREAT_SINGLE_PCT: case ACTION_T_SET_UNIT_FLAG: case ACTION_T_REMOVE_UNIT_FLAG: if (temp.action[j].param2 >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; - - //3rd param target + //3rd param target case ACTION_T_SET_UNIT_FIELD: if (temp.action[j].param1 < OBJECT_END || temp.action[j].param1 >= UNIT_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1); @@ -511,8 +598,9 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() if (temp.action[j].param2 > 4/*SPECIAL*/) sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1); + + break; } - break; case ACTION_T_SET_INST_DATA64: { if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC)) @@ -520,23 +608,42 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() if (temp.action[j].param2 >= TARGET_T_END) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); + + break; } - break; case ACTION_T_UPDATE_TEMPLATE: { - if (!GetCreatureTemplateStore(temp.action[j].param1)) + if (!sCreatureStorage.LookupEntry(temp.action[j].param1)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1); + break; } - break; + + case ACTION_T_THREAT_ALL_PCT: + if (abs(temp.action[j].param1_s) > 100) + sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, temp.action[j].param1); + break; + + case ACTION_T_EVADE: //No Params + case ACTION_T_FLEE: //No Params + case ACTION_T_DIE: //No Params + case ACTION_T_ZONE_COMBAT_PULSE: //No Params + case ACTION_T_AUTO_ATTACK: //AllowAttackState (0 = stop attack, anything else means continue attacking) + case ACTION_T_COMBAT_MOVEMENT: //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking) + case ACTION_T_RANGED_MOVEMENT: //Distance, Angle + break; + + case ACTION_T_RANDOM_PHASE: //PhaseId1, PhaseId2, PhaseId3 + case ACTION_T_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax + // check not implemented + break; + case ACTION_T_RANDOM_SAY: case ACTION_T_RANDOM_YELL: case ACTION_T_RANDOM_TEXTEMOTE: sLog.outErrorDb("CreatureEventAI: Event %u Action %u currently unused ACTION type. Did you forget to update database?", i, j+1); break; - default: - if (temp.action[j].type >= ACTION_T_END) - sLog.outErrorDb("CreatureEventAI: Event %u Action %u has incorrect action type. Maybe DB requires updated version of SD2.", i, j+1); + sLog.outErrorDb("CreatureEventAI: Event %u Action %u have currently not checked at load action type (%u). Need check code update?", i, j+1, temp.action[j].type); break; } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 700ecd909..c40e7edf6 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 "7678" + #define REVISION_NR "7679" #endif // __REVISION_NR_H__ From b4bc910d32b680cbbd357d009b2a3d34f06f7e20 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 17 Apr 2009 16:34:59 +0400 Subject: [PATCH 10/22] [7680] Fixed work spell effects with 17/0 spell target mode. Including many summon/teleport spells. --- src/game/Spell.cpp | 23 +++++++++++++++++------ src/shared/revision_nr.h | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 768ab6b40..f3140cb93 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -487,13 +487,24 @@ void Spell::FillTargetMap() } break; case TARGET_TABLE_X_Y_Z_COORDINATES: - // All 17/7 pairs used for dest teleportation, A processed in effect code - if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_AREAEFFECT_INSTANT) - SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); - else + switch(m_spellInfo->EffectImplicitTargetB[i]) { - SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); - SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + case 0: + SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); + + // need some target for proccesing + if(m_targets.getUnitTarget()) + tmpUnitMap.push_back(m_targets.getUnitTarget()); + else + tmpUnitMap.push_back(m_caster); + break; + case TARGET_AREAEFFECT_INSTANT: // All 17/7 pairs used for dest teleportation, A processed in effect code + SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + break; + default: + SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); + SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + break; } break; default: diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c40e7edf6..212aec81b 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 "7679" + #define REVISION_NR "7680" #endif // __REVISION_NR_H__ From 75d8c0b60405f278f9b46223ebefd80b7927c673 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 17 Apr 2009 17:01:47 +0400 Subject: [PATCH 11/22] [7681] Check guid type before lookup request for seldom GO-caster case. --- src/game/Spell.cpp | 4 ++-- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index f3140cb93..d8f6259ca 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1781,7 +1781,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) { // Check original caster is GO - set its coordinates as dst cast WorldObject *caster = NULL; - if (m_originalCasterGUID) + if (IS_GAMEOBJECT_GUID(m_originalCasterGUID)) caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID); if (!caster) caster = m_caster; @@ -5407,7 +5407,7 @@ bool Spell::CheckTarget( Unit* target, uint32 eff ) default: // normal case // Get GO cast coordinates if original caster -> GO WorldObject *caster = NULL; - if (m_originalCasterGUID) + if (IS_GAMEOBJECT_GUID(m_originalCasterGUID)) caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID); if (!caster) caster = m_caster; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 212aec81b..b6b59dd08 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 "7680" + #define REVISION_NR "7681" #endif // __REVISION_NR_H__ From 718185cf8e693b067ec5926deb769d4df813b603 Mon Sep 17 00:00:00 2001 From: Trazom Date: Fri, 17 Apr 2009 23:40:38 +0400 Subject: [PATCH 12/22] [7682] Implement support ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT Signed-off-by: VladimirMangos --- src/game/AchievementMgr.cpp | 11 ++++++++++- src/game/GameObject.cpp | 1 + src/shared/revision_nr.h | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 1b8338a62..1536cb7a9 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -943,6 +943,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if(miscvalue1 != achievementCriteria->use_gameobject.goEntry) continue; + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; + case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT: + if (!miscvalue1) + continue; + if (miscvalue1 != achievementCriteria->fish_in_gameobject.goEntry) + continue; + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: @@ -1031,7 +1039,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS: case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS: case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL: - case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT: case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE: case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL: case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE: @@ -1168,6 +1175,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve return progress->counter >= achievementCriteria->equip_item.count; case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper; + case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT: + return progress->counter >= achievementCriteria->fish_in_gameobject.lootCount; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: return progress->counter >= achievementCriteria->loot_money.goldInCopper; case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT: diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 5c931ab0d..4b2916de7 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -1027,6 +1027,7 @@ void GameObject::Use(Unit* user) if (ok) { player->SendLoot(ok->GetGUID(),LOOT_FISHINGHOLE); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT, ok->GetGOInfo()->id); SetLootState(GO_JUST_DEACTIVATED); } else diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b6b59dd08..a82dbb259 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 "7681" + #define REVISION_NR "7682" #endif // __REVISION_NR_H__ From 6c62fe750c37663f0eb4f547c214a42be92062ed Mon Sep 17 00:00:00 2001 From: Trazom Date: Sat, 18 Apr 2009 00:00:52 +0400 Subject: [PATCH 13/22] [7683] Fixed update ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST for daily quests. Signed-off-by: VladimirMangos --- src/game/AchievementMgr.cpp | 18 ++++++++++++++---- src/game/Player.cpp | 2 +- src/shared/revision_nr.h | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 1536cb7a9..0ba80dfd8 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -789,8 +789,18 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: - if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) - SetCriteriaProgress(achievementCriteria, 1); + // if miscvalues != 0, it contains the questID. + if (miscvalue1) + { + if (miscvalue1 == achievementCriteria->complete_quest.questID) + SetCriteriaProgress(achievementCriteria, 1); + } + else + { + // login case. + if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) + SetCriteriaProgress(achievementCriteria, 1); + } break; case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: @@ -1175,12 +1185,12 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve return progress->counter >= achievementCriteria->equip_item.count; case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper; - case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT: - return progress->counter >= achievementCriteria->fish_in_gameobject.lootCount; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: return progress->counter >= achievementCriteria->loot_money.goldInCopper; case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT: return progress->counter >= achievementCriteria->use_gameobject.useCount; + case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT: + return progress->counter >= achievementCriteria->fish_in_gameobject.lootCount; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 684cdac66..3c64dc334 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -12410,7 +12410,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver if (pQuest->GetZoneOrSort() > 0) GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, pQuest->GetZoneOrSort()); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, pQuest->GetQuestId()); uint32 zone = 0; uint32 area = 0; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a82dbb259..bf33dfca1 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 "7682" + #define REVISION_NR "7683" #endif // __REVISION_NR_H__ From e94c6755d087e91dcb6da56989cea4322ca9b3bc Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 18 Apr 2009 12:41:26 +0400 Subject: [PATCH 14/22] [7684] Resolve possible conflict in summon property enum type and enum names (currently commented) --- src/game/DBCEnums.h | 72 ++++++++++++++++++++-------------------- src/game/DBCStructure.h | 16 +++++---- src/game/Player.cpp | 2 +- src/shared/revision_nr.h | 2 +- 4 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h index ffad1a882..68f4bb1be 100644 --- a/src/game/DBCEnums.h +++ b/src/game/DBCEnums.h @@ -281,50 +281,50 @@ enum TotemCategoryType }; // SummonProperties.dbc, col 1 -/*enum SummonGroup +enum SummonPropGroup { - SUMMON_GROUP_UNKNOWN1 = 0, // 1160 spells in 3.0.3 - SUMMON_GROUP_UNKNOWN2 = 1, // 861 spells in 3.0.3 - SUMMON_GROUP_PETS = 2, // 52 spells in 3.0.3, pets mostly - SUMMON_GROUP_CONTROLLABLE = 3, // 13 spells in 3.0.3, mostly controllable - SUMMON_GROUP_UNKNOWN3 = 4 // 86 spells in 3.0.3, taxi/mounts + SUMMON_PROP_GROUP_UNKNOWN1 = 0, // 1160 spells in 3.0.3 + SUMMON_PROP_GROUP_UNKNOWN2 = 1, // 861 spells in 3.0.3 + SUMMON_PROP_GROUP_PETS = 2, // 52 spells in 3.0.3, pets mostly + SUMMON_PROP_GROUP_CONTROLLABLE = 3, // 13 spells in 3.0.3, mostly controllable + SUMMON_PROP_GROUP_UNKNOWN3 = 4 // 86 spells in 3.0.3, taxi/mounts }; // SummonProperties.dbc, col 3 -enum SummonType +enum SummonPropType { - SUMMON_TYPE_UNKNOWN = 0, // different summons, 1330 spells in 3.0.3 - SUMMON_TYPE_SUMMON = 1, // generic summons, 49 spells in 3.0.3 - SUMMON_TYPE_GUARDIAN = 2, // summon guardian, 393 spells in 3.0.3 - SUMMON_TYPE_ARMY = 3, // summon army, 5 spells in 3.0.3 - SUMMON_TYPE_TOTEM = 4, // summon totem, 169 spells in 3.0.3 - SUMMON_TYPE_CRITTER = 5, // critter/minipet, 195 spells in 3.0.3 - SUMMON_TYPE_DK = 6, // summon DRW/Ghoul, 2 spells in 3.0.3 - SUMMON_TYPE_BOMB = 7, // summon bot/bomb, 4 spells in 3.0.3 - SUMMON_TYPE_PHASING = 8, // something todo with DK prequest line, 2 spells in 3.0.3 - SUMMON_TYPE_SIEGE_VEH = 9, // summon different vehicles, 14 spells in 3.0.3 - SUMMON_TYPE_DRAKE_VEH = 10, // summon drake (vehicle), 3 spells - SUMMON_TYPE_LIGHTWELL = 11 // summon lightwell, 6 spells in 3.0.3 + SUMMON_PROP_TYPE_UNKNOWN = 0, // different summons, 1330 spells in 3.0.3 + SUMMON_PROP_TYPE_SUMMON = 1, // generic summons, 49 spells in 3.0.3 + SUMMON_PROP_TYPE_GUARDIAN = 2, // summon guardian, 393 spells in 3.0.3 + SUMMON_PROP_TYPE_ARMY = 3, // summon army, 5 spells in 3.0.3 + SUMMON_PROP_TYPE_TOTEM = 4, // summon totem, 169 spells in 3.0.3 + SUMMON_PROP_TYPE_CRITTER = 5, // critter/minipet, 195 spells in 3.0.3 + SUMMON_PROP_TYPE_DK = 6, // summon DRW/Ghoul, 2 spells in 3.0.3 + SUMMON_PROP_TYPE_BOMB = 7, // summon bot/bomb, 4 spells in 3.0.3 + SUMMON_PROP_TYPE_PHASING = 8, // something todo with DK prequest line, 2 spells in 3.0.3 + SUMMON_PROP_TYPE_SIEGE_VEH = 9, // summon different vehicles, 14 spells in 3.0.3 + SUMMON_PROP_TYPE_DRAKE_VEH = 10, // summon drake (vehicle), 3 spells + SUMMON_PROP_TYPE_LIGHTWELL = 11 // summon lightwell, 6 spells in 3.0.3 }; // SummonProperties.dbc, col 5 -enum SummonFlags +enum SummonPropFlags { - SUMMON_FLAG_NONE = 0x0000, // 1342 spells in 3.0.3 - SUMMON_FLAG_UNK1 = 0x0001, // 75 spells in 3.0.3, something unfriendly - SUMMON_FLAG_UNK2 = 0x0002, // 616 spells in 3.0.3, something friendly - SUMMON_FLAG_UNK3 = 0x0004, // 22 spells in 3.0.3, no idea... - SUMMON_FLAG_UNK4 = 0x0008, // 49 spells in 3.0.3, some mounts - SUMMON_FLAG_UNK5 = 0x0010, // 25 spells in 3.0.3, quest related? - SUMMON_FLAG_UNK6 = 0x0020, // 0 spells in 3.0.3, unused - SUMMON_FLAG_UNK7 = 0x0040, // 12 spells in 3.0.3, no idea - SUMMON_FLAG_UNK8 = 0x0080, // 4 spells in 3.0.3, no idea - SUMMON_FLAG_UNK9 = 0x0100, // 51 spells in 3.0.3, no idea, many quest related - SUMMON_FLAG_UNK10 = 0x0200, // 51 spells in 3.0.3, something defensive - SUMMON_FLAG_UNK11 = 0x0400, // 3 spells, requires something near? - SUMMON_FLAG_UNK12 = 0x0800, // 30 spells in 3.0.3, no idea - SUMMON_FLAG_UNK13 = 0x1000, // 8 spells in 3.0.3, siege vehicle - SUMMON_FLAG_UNK14 = 0x2000, // 2 spells in 3.0.3, escort? + SUMMON_PROP_FLAG_NONE = 0x0000, // 1342 spells in 3.0.3 + SUMMON_PROP_FLAG_UNK1 = 0x0001, // 75 spells in 3.0.3, something unfriendly + SUMMON_PROP_FLAG_UNK2 = 0x0002, // 616 spells in 3.0.3, something friendly + SUMMON_PROP_FLAG_UNK3 = 0x0004, // 22 spells in 3.0.3, no idea... + SUMMON_PROP_FLAG_UNK4 = 0x0008, // 49 spells in 3.0.3, some mounts + SUMMON_PROP_FLAG_UNK5 = 0x0010, // 25 spells in 3.0.3, quest related? + SUMMON_PROP_FLAG_UNK6 = 0x0020, // 0 spells in 3.0.3, unused + SUMMON_PROP_FLAG_UNK7 = 0x0040, // 12 spells in 3.0.3, no idea + SUMMON_PROP_FLAG_UNK8 = 0x0080, // 4 spells in 3.0.3, no idea + SUMMON_PROP_FLAG_UNK9 = 0x0100, // 51 spells in 3.0.3, no idea, many quest related + SUMMON_PROP_FLAG_UNK10 = 0x0200, // 51 spells in 3.0.3, something defensive + SUMMON_PROP_FLAG_UNK11 = 0x0400, // 3 spells, requires something near? + SUMMON_PROP_FLAG_UNK12 = 0x0800, // 30 spells in 3.0.3, no idea + SUMMON_PROP_FLAG_UNK13 = 0x1000, // 8 spells in 3.0.3, siege vehicle + SUMMON_PROP_FLAG_UNK14 = 0x2000, // 2 spells in 3.0.3, escort? }; -*/ + #endif diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index b119d5977..8af88562e 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1441,15 +1441,17 @@ struct StableSlotPricesEntry uint32 Price; }; -/*struct SummonPropertiesEntry +/* unused currently +struct SummonPropertiesEntry { uint32 Id; // 0 - uint32 Group; // 1, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount? - uint32 Unk2; // 2, 14 rows > 0 - uint32 Type; // 3, see enum - uint32 Slot; // 4, 0-6 - uint32 Flags; // 5 -};*/ + uint32 Group; // 1, enum SummonPropGroup, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount? + uint32 Unk2; // 2, 14 rows > 0 + uint32 Type; // 3, enum SummonPropType + uint32 Slot; // 4, 0-6 + uint32 Flags; // 5, enum SummonPropFlags +}; +*/ #define MAX_TALENT_RANK 5 #define MAX_PET_TALENT_RANK 3 // use in calculations, expected <= MAX_TALENT_RANK diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 3c64dc334..a1a3057ae 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -19428,7 +19428,7 @@ void Player::HandleFall(MovementInfo const& movementInfo) sLog.outDebug("zDiff = %f", z_diff); //Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored - // 14.57 can be calculated by resolving damageperc formular below to 0 + // 14.57 can be calculated by resolving damageperc formula below to 0 if (z_diff >= 14.57f && !isDead() && !isGameMaster() && !HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) && !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL) ) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index bf33dfca1..1cc24396e 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 "7683" + #define REVISION_NR "7684" #endif // __REVISION_NR_H__ From b3c4e3840959ffba55e0cd5ebfa215e2177a2200 Mon Sep 17 00:00:00 2001 From: NoFantasy Date: Sat, 18 Apr 2009 16:04:42 +0400 Subject: [PATCH 15/22] [7685] Load emotes.dbc and make emotes/emotetexts accessable from script DLL. Also some enum updates. Signed-off-by: VladimirMangos --- src/game/DBCStores.cpp | 8 ++++-- src/game/DBCStores.h | 3 ++ src/game/DBCStructure.h | 11 ++++++++ src/game/DBCfmt.h | 3 +- src/game/SharedDefines.h | 61 ++++++++++++++++++++++++++++++++++++---- src/shared/revision_nr.h | 2 +- 6 files changed, 78 insertions(+), 10 deletions(-) diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp index 1d5fbb78f..faad447d3 100644 --- a/src/game/DBCStores.cpp +++ b/src/game/DBCStores.cpp @@ -56,7 +56,8 @@ DBCStorage sCurrencyTypesStore(CurrencyTypesfmt); DBCStorage sDurabilityQualityStore(DurabilityQualityfmt); DBCStorage sDurabilityCostsStore(DurabilityCostsfmt); -DBCStorage sEmotesTextStore(EmoteEntryfmt); +DBCStorage sEmotesStore(EmotesEntryfmt); +DBCStorage sEmotesTextStore(EmotesTextEntryfmt); typedef std::map FactionTeamMap; static FactionTeamMap sFactionTeamMap; @@ -201,7 +202,7 @@ void LoadDBCStores(const std::string& dataPath) { std::string dbcPath = dataPath+"dbc/"; - const uint32 DBCFilesCount = 77; + const uint32 DBCFilesCount = 78; barGoLink bar( DBCFilesCount ); @@ -246,6 +247,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCurrencyTypesStore, dbcPath,"CurrencyTypes.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesStore, dbcPath,"Emotes.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesTextStore, dbcPath,"EmotesText.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionStore, dbcPath,"Faction.dbc"); for (uint32 i=0;i const* GetSpellRangeStore() MANGOS_DLL_SPEC DBCStorage const* GetFactionStore() { return &sFactionStore; } MANGOS_DLL_SPEC DBCStorage const* GetItemDisplayStore() { return &sItemStore; } MANGOS_DLL_SPEC DBCStorage const* GetCreatureDisplayStore() { return &sCreatureDisplayInfoStore; } +MANGOS_DLL_SPEC DBCStorage const* GetEmotesStore() { return &sEmotesStore; } +MANGOS_DLL_SPEC DBCStorage const* GetEmotesTextStore() { return &sEmotesTextStore; } diff --git a/src/game/DBCStores.h b/src/game/DBCStores.h index 95a2e4a4b..fc91325d0 100644 --- a/src/game/DBCStores.h +++ b/src/game/DBCStores.h @@ -80,6 +80,7 @@ extern DBCStorage sCreatureTypeStore; extern DBCStorage sCurrencyTypesStore; extern DBCStorage sDurabilityCostsStore; extern DBCStorage sDurabilityQualityStore; +extern DBCStorage sEmotesStore; extern DBCStorage sEmotesTextStore; extern DBCStorage sFactionStore; extern DBCStorage sFactionTemplateStore; @@ -155,4 +156,6 @@ MANGOS_DLL_SPEC DBCStorage const* GetSpellRangeStor MANGOS_DLL_SPEC DBCStorage const* GetFactionStore(); MANGOS_DLL_SPEC DBCStorage const* GetItemDisplayStore(); MANGOS_DLL_SPEC DBCStorage const* GetCreatureDisplayStore(); +MANGOS_DLL_SPEC DBCStorage const* GetEmotesStore(); +MANGOS_DLL_SPEC DBCStorage const* GetEmotesTextStore(); #endif diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 8af88562e..5c6c928a6 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -747,6 +747,17 @@ struct DurabilityQualityEntry float quality_mod; // 1 }; +struct EmotesEntry +{ + uint32 Id; // 0 + //char* Name; // 1, internal name + //uint32 AnimationId; // 2, ref to animationData + uint32 Flags; // 3, bitmask, may be unit_flags + uint32 EmoteType; // 4, Can be 0, 1 or 2 (determine how emote are shown) + uint32 UnitStandState; // 5, uncomfirmed, may be enum UnitStandStateType + //uint32 SoundId; // 6, ref to soundEntries +}; + struct EmotesTextEntry { uint32 Id; diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index 27ee3e1ad..2bb619ae7 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -42,7 +42,8 @@ const char CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx"; const char CurrencyTypesfmt[]="xnxi"; const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; const char DurabilityQualityfmt[]="nf"; -const char EmoteEntryfmt[]="nxixxxxxxxxxxxxxxxx"; +const char EmotesEntryfmt[]="nxxiiix"; +const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx"; const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiissssssssssssssssxxxxxxxxxxxxxxxxxx"; const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii"; const char GemPropertiesEntryfmt[]="nixxi"; diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 99fc7f7e2..3ce253b53 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -1334,7 +1334,7 @@ enum Emote EMOTE_ONESHOT_POINT = 25, EMOTE_STATE_STAND = 26, EMOTE_STATE_READYUNARMED = 27, - EMOTE_STATE_WORK = 28, + EMOTE_STATE_WORK_SHEATHED = 28, EMOTE_STATE_POINT = 29, EMOTE_STATE_NONE = 30, EMOTE_ONESHOT_WOUND = 33, @@ -1367,13 +1367,13 @@ enum Emote EMOTE_ONESHOT_SALUTE_NOSHEATH = 113, EMOTE_STATE_USESTANDING_NOSHEATHE = 133, EMOTE_ONESHOT_LAUGH_NOSHEATHE = 153, - EMOTE_STATE_WORK_NOSHEATHE = 173, + EMOTE_STATE_WORK = 173, EMOTE_STATE_SPELLPRECAST = 193, EMOTE_ONESHOT_READYRIFLE = 213, EMOTE_STATE_READYRIFLE = 214, - EMOTE_STATE_WORK_NOSHEATHE_MINING = 233, - EMOTE_STATE_WORK_NOSHEATHE_CHOPWOOD= 234, - EMOTE_zzOLDONESHOT_LIFTOFF = 253, + EMOTE_STATE_WORK_MINING = 233, + EMOTE_STATE_WORK_CHOPWOOD = 234, + EMOTE_STATE_APPLAUD = 253, EMOTE_ONESHOT_LIFTOFF = 254, EMOTE_ONESHOT_YES = 273, EMOTE_ONESHOT_NO = 274, @@ -1422,8 +1422,57 @@ enum Emote EMOTE_ONESHOT_CUSTOMSPELL09 = 410, EMOTE_ONESHOT_CUSTOMSPELL10 = 411, EMOTE_STATE_EXCLAIM = 412, + EMOTE_STATE_DANCE_CUSTOM = 413, EMOTE_STATE_SIT_CHAIR_MED = 415, - EMOTE_STATE_SPELLEFFECT_HOLD = 422 + EMOTE_STATE_CUSTOM_SPELL_01 = 416, + EMOTE_STATE_CUSTOM_SPELL_02 = 417, + EMOTE_STATE_EAT = 418, + EMOTE_STATE_CUSTOM_SPELL_04 = 419, + EMOTE_STATE_CUSTOM_SPELL_03 = 420, + EMOTE_STATE_CUSTOM_SPELL_05 = 421, + EMOTE_STATE_SPELLEFFECT_HOLD = 422, + EMOTE_STATE_EAT_NO_SHEATHE = 423, + EMOTE_STATE_MOUNT = 424, + EMOTE_STATE_READY2HL = 425, + EMOTE_STATE_SIT_CHAIR_HIGH = 426, + EMOTE_STATE_FALL = 427, + EMOTE_STATE_LOOT = 428, + EMOTE_STATE_SUBMERGED_NEW = 429, + EMOTE_ONESHOT_COWER = 430, + EMOTE_STATE_COWER = 431, + EMOTE_ONESHOT_USESTANDING = 432, + EMOTE_STATE_STEALTH_STAND = 433, + EMOTE_ONESHOT_OMNICAST_GHOUL = 434, + EMOTE_ONESHOT_ATTACKBOW = 435, + EMOTE_ONESHOT_ATTACKRIFLE = 436, + EMOTE_STATE_SWIM_IDLE = 437, + EMOTE_STATE_ATTACK_UNARMED = 438, + EMOTE_ONESHOT_SPELLCAST_W_SOUND = 439, + EMOTE_ONESHOT_DODGE = 440, + EMOTE_ONESHOT_PARRY1H = 441, + EMOTE_ONESHOT_PARRY2H = 442, + EMOTE_ONESHOT_PARRY2HL = 443, + EMOTE_STATE_FLYFALL = 444, + EMOTE_ONESHOT_FLYDEATH = 445, + EMOTE_STATE_FLY_FALL = 446, + EMOTE_ONESHOT_FLY_SIT_GROUND_DOWN = 447, + EMOTE_ONESHOT_FLY_SIT_GROUND_UP = 448, + EMOTE_ONESHOT_EMERGE = 449, + EMOTE_ONESHOT_DRAGONSPIT = 450, + EMOTE_STATE_SPECIALUNARMED = 451, + EMOTE_ONESHOT_FLYGRAB = 452, + EMOTE_STATE_FLYGRABCLOSED = 453, + EMOTE_ONESHOT_FLYGRABTHROWN = 454, + EMOTE_STATE_FLY_SIT_GROUND = 455, + EMOTE_STATE_WALKBACKWARDS = 456, + EMOTE_ONESHOT_FLYTALK = 457, + EMOTE_ONESHOT_FLYATTACK1H = 458, + EMOTE_STATE_CUSTOMSPELL08 = 459, + EMOTE_ONESHOT_FLY_DRAGONSPIT = 460, + EMOTE_STATE_SIT_CHAIR_LOW = 461, + EMOTE_ONE_SHOT_STUN = 462, + EMOTE_ONESHOT_SPELLCAST_OMNI = 463, + EMOTE_STATE_READYTHROWN = 464 }; enum Anim diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1cc24396e..606ac5ebf 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 "7684" + #define REVISION_NR "7685" #endif // __REVISION_NR_H__ From f97735f519078c539e6482ca27c5ad8aa854b324 Mon Sep 17 00:00:00 2001 From: Lightguard Date: Sun, 19 Apr 2009 00:38:30 +0400 Subject: [PATCH 16/22] [7686] Implement aura SPELL_AURA_ADD_CASTER_HIT_TRIGGER (111). Fixed bug with triggering SPELL_AURA_SPELL_MAGNET at non-magic casts (special weapon attacks). Signed-off-by: VladimirMangos --- src/game/Spell.cpp | 42 ++++++++++++---------------------------- src/game/Spell.h | 1 - src/game/SpellAuras.cpp | 4 ++-- src/game/Unit.cpp | 31 +++++++++++++++++++++++++++++ src/game/Unit.h | 1 + src/shared/revision_nr.h | 2 +- 6 files changed, 47 insertions(+), 34 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index d8f6259ca..67da066c3 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1542,9 +1542,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) { if (EffectChainTarget <= 1) { - Unit* pUnitTarget = SelectMagnetTarget(); - if(pUnitTarget) + if(Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), m_spellInfo)) + { + m_targets.setUnitTarget(pUnitTarget); TagUnitMap.push_back(pUnitTarget); + } } else { @@ -1871,9 +1873,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) } else { - Unit* pUnitTarget = SelectMagnetTarget(); - if(pUnitTarget) + if(Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), m_spellInfo)) + { + m_targets.setUnitTarget(pUnitTarget); TagUnitMap.push_back(pUnitTarget); + } } } }break; @@ -1905,9 +1909,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) }break; case TARGET_SINGLE_ENEMY: { - Unit* pUnitTarget = SelectMagnetTarget(); - if(pUnitTarget) + if(Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), m_spellInfo)) + { + m_targets.setUnitTarget(pUnitTarget); TagUnitMap.push_back(pUnitTarget); + } }break; case TARGET_AREAEFFECT_PARTY: { @@ -5419,30 +5425,6 @@ bool Spell::CheckTarget( Unit* target, uint32 eff ) return true; } -Unit* Spell::SelectMagnetTarget() -{ - Unit* target = m_targets.getUnitTarget(); - - if(target && target->HasAuraType(SPELL_AURA_SPELL_MAGNET) && !(m_spellInfo->Attributes & 0x10)) - { - Unit::AuraList const& magnetAuras = target->GetAurasByType(SPELL_AURA_SPELL_MAGNET); - for(Unit::AuraList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr) - { - if(Unit* magnet = (*itr)->GetCaster()) - { - if(magnet->IsWithinLOSInMap(m_caster)) - { - target = magnet; - m_targets.setUnitTarget(target); - break; - } - } - } - } - - return target; -} - bool Spell::IsNeedSendToClient() const { return m_spellInfo->SpellVisual[0] || m_spellInfo->SpellVisual[1] || IsChanneledSpell(m_spellInfo) || diff --git a/src/game/Spell.h b/src/game/Spell.h index f621c2d41..5fd7e8490 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -381,7 +381,6 @@ class Spell void SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap); void FillAreaTargets( UnitList& TagUnitMap, float x, float y, float radius, SpellNotifyPushType pushType, SpellTargets spellTargets ); - Unit* SelectMagnetTarget(); bool CheckTarget( Unit* target, uint32 eff ); bool CanAutoCast(Unit* target); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index a02ea15a4..5da2d285c 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -145,7 +145,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE &Aura::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::RegenerateAll &Aura::HandleAuraGhost, // 95 SPELL_AURA_GHOST - &Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Spell::SelectMagnetTarget + &Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Unit::SelectMagnetTarget &Aura::HandleManaShield, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist &Aura::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT &Aura::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER @@ -160,7 +160,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER &Aura::HandleAddTargetTrigger, //109 SPELL_AURA_ADD_TARGET_TRIGGER &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT - &Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER chance redirect attack to caster + &Aura::HandleNoImmediateEffect, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER implemented in Unit::SelectMagnetTarget &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index d2779c97e..a9b3605e2 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1961,6 +1961,9 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex return; } + // attack can be redirected to another target + pVictim = SelectMagnetTarget(pVictim); + CalcDamageInfo damageInfo; CalculateMeleeDamage(pVictim, 0, &damageInfo, attType); // Send log damage message to client @@ -7420,6 +7423,34 @@ void Unit::UnsummonAllTotems() } } +Unit* Unit::SelectMagnetTarget(Unit *victim, SpellEntry const *spellInfo) +{ + if(!victim) + return NULL; + + // Magic case + if(spellInfo && (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE || spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC)) + { + Unit::AuraList const& magnetAuras = victim->GetAurasByType(SPELL_AURA_SPELL_MAGNET); + for(Unit::AuraList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr) + if(Unit* magnet = (*itr)->GetCaster()) + if(magnet->IsWithinLOSInMap(this) && magnet->isAlive()) + return magnet; + } + // Melee && ranged case + else + { + AuraList const& hitTriggerAuras = victim->GetAurasByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER); + for(AuraList::const_iterator i = hitTriggerAuras.begin(); i != hitTriggerAuras.end(); ++i) + if(Unit* magnet = (*i)->GetCaster()) + if(magnet->isAlive() && magnet->IsWithinLOSInMap(this)) + if(roll_chance_i((*i)->GetModifier()->m_amount)) + return magnet; + } + + return victim; +} + void Unit::SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, bool critical) { // we guess size diff --git a/src/game/Unit.h b/src/game/Unit.h index e3ea874e7..69f01e527 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1339,6 +1339,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void ModifyAuraState(AuraState flag, bool apply); bool HasAuraState(AuraState flag) const { return HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); } void UnsummonAllTotems(); + Unit* SelectMagnetTarget(Unit *victim, SpellEntry const *spellInfo = NULL); int32 SpellBaseDamageBonus(SpellSchoolMask schoolMask); int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask); int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 606ac5ebf..2d2a4cb1c 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 "7685" + #define REVISION_NR "7686" #endif // __REVISION_NR_H__ From 82b0ff8b5d02798de5b95e31192488bc31eae160 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 19 Apr 2009 15:55:57 +0400 Subject: [PATCH 17/22] [7687] Batter player dumps protection from not proper use. * Prevent direct apply player dumps to DB * Check expected character DB structure (revision) before apply. --- src/game/PlayerDump.cpp | 46 +++++++++++++++++++++++++++++++++++++++- src/shared/revision_nr.h | 2 +- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/game/PlayerDump.cpp b/src/game/PlayerDump.cpp index 8f75e6427..e43da414c 100644 --- a/src/game/PlayerDump.cpp +++ b/src/game/PlayerDump.cpp @@ -330,6 +330,36 @@ void PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tabl std::string PlayerDumpWriter::GetDump(uint32 guid) { std::string dump; + + dump += "IMPORTANT NOTE: This sql queries not created for apply directly, use '.pdump load' command in console or client chat instead.\n"; + dump += "IMPORTANT NOTE: NOT APPLY ITS DIRECTLY to character DB or you will DAMAGE and CORRUPT character DB\n\n"; + + // revision check guard + QueryResult* result = CharacterDatabase.Query("SELECT * FROM character_db_version LIMIT 1"); + if(result) + { + QueryResult::FieldNames const& namesMap = result->GetFieldNames(); + std::string reqName; + for(QueryResult::FieldNames::const_iterator itr = namesMap.begin(); itr != namesMap.end(); ++itr) + { + if(itr->second.substr(0,9)=="required_") + { + reqName = itr->second; + break; + } + } + + if(!reqName.empty()) + { + // this will fail at wrong character DB version + dump += "UPDATE character_db_version SET "+reqName+" = 1 WHERE FALSE;\n\n"; + } + else + sLog.outError("Table 'character_db_version' not have revision guard field, revision guard query not added to pdump."); + } + else + sLog.outError("Character DB not have 'character_db_version' table, revision guard query not added to pdump."); + for(int i = 0; i < DUMP_TABLE_COUNT; i++) DumpTable(dump, guid, dumpTables[i].name, dumpTables[i].name, dumpTables[i].type); @@ -437,9 +467,23 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s std::string line; line.assign(buf); // skip empty strings - if(line.find_first_not_of(" \t\n\r\7")==std::string::npos) + size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); + if(nw_pos==std::string::npos) continue; + // skip NOTE + if(line.substr(nw_pos,15)=="IMPORTANT NOTE:") + continue; + + // add required_ check + if(line.substr(nw_pos,41)=="UPDATE character_db_version SET required_") + { + if(!CharacterDatabase.Execute(line.c_str())) + ROLLBACK(DUMP_FILE_BROKEN); + + continue; + } + // determine table name and load type std::string tn = gettablename(line); if(tn.empty()) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 2d2a4cb1c..9e80e057d 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 "7686" + #define REVISION_NR "7687" #endif // __REVISION_NR_H__ From f4adf83cd762218f9fbc37b7ab143855c6535a01 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 19 Apr 2009 22:31:58 +0400 Subject: [PATCH 18/22] [7688] Move Get*IfCanInteractWith to Player including renamed IsGameObjectOfTypeInRange. --- src/game/AuctionHouseHandler.cpp | 14 +++--- src/game/GuildHandler.cpp | 16 +++--- src/game/ItemHandler.cpp | 8 +-- src/game/Mail.cpp | 16 +++--- src/game/NPCHandler.cpp | 28 +++++------ src/game/ObjectAccessor.cpp | 46 ----------------- src/game/ObjectAccessor.h | 1 - src/game/ObjectMgr.cpp | 17 ------- src/game/ObjectMgr.h | 2 - src/game/PetitionsHandler.cpp | 4 +- src/game/Player.cpp | 84 +++++++++++++++++++++++++++++++- src/game/Player.h | 2 + src/game/QuestHandler.cpp | 2 +- src/game/SkillHandler.cpp | 2 +- src/game/TaxiHandler.cpp | 6 +-- src/shared/revision_nr.h | 2 +- 16 files changed, 134 insertions(+), 116 deletions(-) diff --git a/src/game/AuctionHouseHandler.cpp b/src/game/AuctionHouseHandler.cpp index f957a7b60..d37b1b731 100644 --- a/src/game/AuctionHouseHandler.cpp +++ b/src/game/AuctionHouseHandler.cpp @@ -38,7 +38,7 @@ void WorldSession::HandleAuctionHelloOpcode( WorldPacket & recv_data ) uint64 guid; //NPC guid recv_data >> guid; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); if (!unit) { sLog.outDebug( "WORLD: HandleAuctionHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -162,7 +162,7 @@ void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data ) if (!item || !bid || !etime) return; //check for cheaters - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, auctioneer,UNIT_NPC_FLAG_AUCTIONEER); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug( "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) ); @@ -286,7 +286,7 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) if (!auctionId || !price) return; //check for cheaters - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, auctioneer,UNIT_NPC_FLAG_AUCTIONEER); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug( "WORLD: HandleAuctionPlaceBid - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) ); @@ -412,7 +412,7 @@ void WorldSession::HandleAuctionRemoveItem( WorldPacket & recv_data ) recv_data >> auctionId; //sLog.outDebug( "Cancel AUCTION AuctionID: %u", auctionId); - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, auctioneer,UNIT_NPC_FLAG_AUCTIONEER); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug( "WORLD: HandleAuctionRemoveItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) ); @@ -497,7 +497,7 @@ void WorldSession::HandleAuctionListBidderItems( WorldPacket & recv_data ) outbiddedCount = 0; } - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug( "WORLD: HandleAuctionListBidderItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -546,7 +546,7 @@ void WorldSession::HandleAuctionListOwnerItems( WorldPacket & recv_data ) recv_data >> guid; recv_data >> listfrom; // not used in fact (this list not have page control in client) - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug( "WORLD: HandleAuctionListOwnerItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -593,7 +593,7 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory; recv_data >> quality >> usable; - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug( "WORLD: HandleAuctionListItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index 540ea9e96..934a77b70 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -782,7 +782,7 @@ void WorldSession::HandleGuildSaveEmblemOpcode(WorldPacket& recvPacket) recvPacket >> vendorGuid; - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorGuid,UNIT_NPC_FLAG_TABARDDESIGNER); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid,UNIT_NPC_FLAG_TABARDDESIGNER); if (!pCreature) { //"That's not an emblem vendor!" @@ -905,7 +905,7 @@ void WorldSession::HandleGuildBankQuery( WorldPacket & recv_data ) uint8 unk; recv_data >> GoGuid >> unk; - if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(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.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(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.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(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.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) return; uint32 GuildId = GetPlayer()->GetGuildId(); @@ -1107,7 +1107,7 @@ void WorldSession::HandleGuildBankDepositItem( WorldPacket & recv_data ) return; } - if (!objmgr.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(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.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(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.IsGameObjectOfTypeInRange(_player, GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) return; uint32 GuildId = GetPlayer()->GetGuildId(); diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index e5ce97b81..1c982fc1a 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -516,7 +516,7 @@ void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data ) if(!itemguid) return; - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); if (!pCreature) { sLog.outDebug( "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) ); @@ -621,7 +621,7 @@ void WorldSession::HandleBuybackItem(WorldPacket & recv_data) recv_data >> vendorguid >> slot; - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); if (!pCreature) { sLog.outDebug( "WORLD: HandleBuybackItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) ); @@ -708,7 +708,7 @@ void WorldSession::SendListInventory( uint64 vendorguid ) { sLog.outDebug( "WORLD: Sent SMSG_LIST_INVENTORY" ); - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, vendorguid,UNIT_NPC_FLAG_VENDOR); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); if (!pCreature) { sLog.outDebug( "WORLD: SendListInventory - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) ); @@ -835,7 +835,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket) recvPacket >> guid; // cheating protection - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_BANKER); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(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)) ); diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index b385043e4..d671aeb69 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -52,7 +52,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data ) recv_data >> mailbox; recv_data >> receiver; - if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; // recheck @@ -278,7 +278,7 @@ void WorldSession::HandleMarkAsRead(WorldPacket & recv_data ) uint32 mailId; recv_data >> mailbox; - if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; recv_data >> mailId; @@ -305,7 +305,7 @@ void WorldSession::HandleMailDelete(WorldPacket & recv_data ) recv_data >> mailbox; recv_data >> mailId; - if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; Player* pl = _player; @@ -324,7 +324,7 @@ void WorldSession::HandleReturnToSender(WorldPacket & recv_data ) uint32 mailId; recv_data >> mailbox; - if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; recv_data >> mailId; @@ -425,7 +425,7 @@ void WorldSession::HandleTakeItem(WorldPacket & recv_data ) uint32 itemId; recv_data >> mailbox; - if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; recv_data >> mailId; @@ -520,7 +520,7 @@ void WorldSession::HandleTakeMoney(WorldPacket & recv_data ) recv_data >> mailbox; recv_data >> mailId; - if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; Player *pl = _player; @@ -554,7 +554,7 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data ) uint64 mailbox; recv_data >> mailbox; - if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; Player* pl = _player; @@ -691,7 +691,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket & recv_data ) recv_data >> mailbox >> mailId; - if (!objmgr.IsGameObjectOfTypeInRange(_player, mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; Player *pl = _player; diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 18b27b562..ad63584b1 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -43,7 +43,7 @@ void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TABARDDESIGNER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_TABARDDESIGNER); if (!unit) { sLog.outDebug( "WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -74,7 +74,7 @@ void WorldSession::HandleBankerActivateOpcode( WorldPacket & recv_data ) recv_data >> guid; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_BANKER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_BANKER); if (!unit) { sLog.outDebug( "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -115,7 +115,7 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) { sLog.outDebug( "WORLD: SendTrainerList" ); - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_TRAINER); if (!unit) { sLog.outDebug( "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -200,7 +200,7 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) recv_data >> guid >> spellId; sLog.outDebug( "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u",uint32(GUID_LOPART(guid)), spellId ); - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_TRAINER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!unit) { sLog.outDebug( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -266,7 +266,7 @@ void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!unit) { sLog.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -324,7 +324,7 @@ void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data ) sLog.outBasic("string read: %s", code.c_str()); } - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!unit) { sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -357,7 +357,7 @@ void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data ) recv_data >> guid; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_SPIRITHEALER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_SPIRITHEALER); if (!unit) { sLog.outDebug( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -416,7 +416,7 @@ void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data ) if(!GetPlayer()->isAlive()) return; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID,UNIT_NPC_FLAG_INNKEEPER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID,UNIT_NPC_FLAG_INNKEEPER); if (!unit) { sLog.outDebug( "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); @@ -484,7 +484,7 @@ void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data ) recv_data >> npcGUID; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); if (!unit) { sLog.outDebug( "WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); @@ -563,7 +563,7 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data ) if(!GetPlayer()->isAlive()) return; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); if (!unit) { sLog.outDebug( "WORLD: HandleStablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); @@ -630,7 +630,7 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data ) recv_data >> npcGUID >> petnumber; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); if (!unit) { sLog.outDebug( "WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); @@ -689,7 +689,7 @@ void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data ) recv_data >> npcGUID; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); if (!unit) { sLog.outDebug( "WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); @@ -735,7 +735,7 @@ void WorldSession::HandleStableSwapPet( WorldPacket & recv_data ) recv_data >> npcGUID >> pet_number; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_STABLEMASTER); if (!unit) { sLog.outDebug( "WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); @@ -792,7 +792,7 @@ void WorldSession::HandleRepairItemOpcode( WorldPacket & recv_data ) recv_data >> npcGUID >> itemGUID >> guildBank; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_REPAIR); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_REPAIR); if (!unit) { sLog.outDebug( "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) ); diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 68807c6ba..17d7d59cb 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -46,52 +46,6 @@ INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ZThread::FastMutex); ObjectAccessor::ObjectAccessor() {} ObjectAccessor::~ObjectAccessor() {} -Creature* -ObjectAccessor::GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint32 npcflagmask) -{ - // unit checks - if (!guid) - return NULL; - - // exist - Creature *unit = GetCreature(player, guid); - if (!unit) - return NULL; - - // player check - if(!player.CanInteractWithNPCs(!unit->isSpiritService())) - return NULL; - - // appropriate npc type - if(npcflagmask && !unit->HasFlag( UNIT_NPC_FLAGS, npcflagmask )) - return NULL; - - // alive or spirit healer - if(!unit->isAlive() && (!unit->isSpiritService() || player.isAlive() )) - return NULL; - - // not allow interaction under control - if(unit->GetCharmerOrOwnerGUID()) - return NULL; - - // not enemy - if( unit->IsHostileTo(&player)) - return NULL; - - // not unfriendly - if(FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(unit->getFaction())) - if(factionTemplate->faction) - if(FactionEntry const* faction = sFactionStore.LookupEntry(factionTemplate->faction)) - if(faction->reputationListID >= 0 && player.GetReputationMgr().GetRank(faction) <= REP_UNFRIENDLY) - return NULL; - - // not too far - if(!unit->IsWithinDistInMap(&player,INTERACTION_DISTANCE)) - return NULL; - - return unit; -} - Creature* ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const &u, uint64 guid) { diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index 270a27e9b..a538dcf38 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -137,7 +137,6 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::SingletonGetGoType() == 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 06f437970..5468f1a17 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -417,8 +417,6 @@ class ObjectMgr return mGameObjectForQuestSet.find(entry) != mGameObjectForQuestSet.end(); } - bool IsGameObjectOfTypeInRange(Player *player, uint64 guid, GameobjectTypes type) const; - GossipText const* GetGossipText(uint32 Text_ID) const; WorldSafeLocsEntry const *GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team); diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index a3d50441f..0087253a1 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -80,7 +80,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str()); // prevent cheating - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guidNPC,UNIT_NPC_FLAG_PETITIONER); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC,UNIT_NPC_FLAG_PETITIONER); if (!pCreature) { sLog.outDebug("WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC)); @@ -904,7 +904,7 @@ void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data) void WorldSession::SendPetitionShowList(uint64 guid) { - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_PETITIONER); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_PETITIONER); if (!pCreature) { sLog.outDebug("WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a1a3057ae..c92c7cda5 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1951,6 +1951,88 @@ bool Player::CanInteractWithNPCs(bool alive) const return true; } +Creature* +Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask) +{ + // unit checks + if (!guid) + return NULL; + + if(!IsInWorld()) + return NULL; + + // exist + Creature *unit = ObjectAccessor::GetCreature(*this,guid); + if (!unit) + return NULL; + + // player check + if(!CanInteractWithNPCs(!unit->isSpiritService())) + return NULL; + + // appropriate npc type + if(npcflagmask && !unit->HasFlag( UNIT_NPC_FLAGS, npcflagmask )) + return NULL; + + // alive or spirit healer + if(!unit->isAlive() && (!unit->isSpiritService() || isAlive() )) + return NULL; + + // not allow interaction under control + if(unit->GetCharmerOrOwnerGUID()) + return NULL; + + // not enemy + if( unit->IsHostileTo(this)) + return NULL; + + // not unfriendly + if(FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(unit->getFaction())) + if(factionTemplate->faction) + if(FactionEntry const* faction = sFactionStore.LookupEntry(factionTemplate->faction)) + if(faction->reputationListID >= 0 && GetReputationMgr().GetRank(faction) <= REP_UNFRIENDLY) + return NULL; + + // not too far + if(!unit->IsWithinDistInMap(this,INTERACTION_DISTANCE)) + return NULL; + + return unit; +} + +GameObject* Player::GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const +{ + if(GameObject *go = ObjectAccessor::GetGameObject(*this,guid)) + { + if(go->GetGoType() == type) + { + float maxdist; + switch(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 + case GAMEOBJECT_TYPE_GUILD_BANK: + case GAMEOBJECT_TYPE_MAILBOX: + maxdist = 10.0f; + break; + case GAMEOBJECT_TYPE_FISHINGHOLE: + maxdist = 20.0f+CONTACT_DISTANCE; // max spell range + break; + default: + maxdist = INTERACTION_DISTANCE; + break; + } + + if (go->IsWithinDistInMap(this, maxdist)) + return go; + + 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(), GetName(), GetGUIDLow(), go->GetDistance(this)); + } + } + return NULL; +} + bool Player::IsUnderWater() const { return IsInWater() && @@ -16852,7 +16934,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint return false; } - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*this, vendorguid,UNIT_NPC_FLAG_VENDOR); + Creature *pCreature = GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); if (!pCreature) { sLog.outDebug( "WORLD: BuyItemFromVendor - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid)) ); diff --git a/src/game/Player.h b/src/game/Player.h index c3f4cdbee..d704b1b0e 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -879,7 +879,9 @@ class MANGOS_DLL_SPEC Player : public Unit void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0); void SendInstanceResetWarning(uint32 mapid, uint32 time); + Creature* GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask); bool CanInteractWithNPCs(bool alive = true) const; + GameObject* GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const; bool ToggleAFK(); bool ToggleDND(); diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 28787184a..bee8aa7eb 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -87,7 +87,7 @@ void WorldSession::HandleQuestgiverHelloOpcode( WorldPacket & recv_data ) sLog.outDebug ("WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u", GUID_LOPART(guid)); - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_NONE); + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_NONE); if (!pCreature) { sLog.outDebug ("WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp index 93826807e..a79bbf745 100644 --- a/src/game/SkillHandler.cpp +++ b/src/game/SkillHandler.cpp @@ -44,7 +44,7 @@ void WorldSession::HandleTalentWipeOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_TRAINER); if (!unit) { sLog.outDebug( "WORLD: HandleTalentWipeOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp index 166d833d0..4a035ce02 100644 --- a/src/game/TaxiHandler.cpp +++ b/src/game/TaxiHandler.cpp @@ -78,7 +78,7 @@ void WorldSession::HandleTaxiQueryAvailableNodes( WorldPacket & recv_data ) recv_data >> guid; // cheating checks - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_FLIGHTMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); if (!unit) { sLog.outDebug( "WORLD: HandleTaxiQueryAvailableNodes - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); @@ -165,7 +165,7 @@ void WorldSession::HandleActivateTaxiFarOpcode ( WorldPacket & recv_data ) recv_data >> guid >> _totalcost >> node_count; - Creature *npc = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_FLIGHTMASTER); + Creature *npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); if (!npc) { sLog.outDebug( "WORLD: HandleActivateTaxiFarOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid)) ); @@ -266,7 +266,7 @@ void WorldSession::HandleActivateTaxiOpcode( WorldPacket & recv_data ) recv_data >> guid >> nodes[0] >> nodes[1]; sLog.outDebug( "WORLD: Received CMSG_ACTIVATETAXI from %d to %d" ,nodes[0],nodes[1]); - Creature *npc = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_FLIGHTMASTER); + Creature *npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); if (!npc) { sLog.outDebug( "WORLD: HandleActivateTaxiOpcode - Unit (GUID: %u) not found or you can't interact with it.", uint32(GUID_LOPART(guid)) ); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 9e80e057d..10200dc94 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 "7687" + #define REVISION_NR "7688" #endif // __REVISION_NR_H__ From ee9ea143d1982b0a70acce7e03b7b29b8863e14d Mon Sep 17 00:00:00 2001 From: NoFantasy Date: Sun, 19 Apr 2009 23:02:17 +0400 Subject: [PATCH 19/22] [7689] Batter EventAI loading checks and fix one from possible crash cases. Signed-off-by: VladimirMangos --- src/game/CreatureEventAI.cpp | 9 +++++---- src/game/CreatureEventAIMgr.cpp | 28 ++++++++++++++++++---------- src/game/ObjectMgr.cpp | 10 ++++++++++ src/game/WaypointManager.cpp | 6 ++++++ src/shared/revision_nr.h | 2 +- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index dc7ad3fec..a63ca1136 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -910,10 +910,11 @@ void CreatureEventAI::ProcessAction(uint16 type, uint32 param1, uint32 param2, u else { //if not available, use pActionInvoker - Unit* pTarget = GetTargetByType(param2, pActionInvoker); - - if (Player* pPlayer = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself()) - pPlayer->RewardPlayerAndGroupAtEvent(param1, m_creature); + if (Unit* pTarget = GetTargetByType(param2, pActionInvoker)) + { + if (Player* pPlayer = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself()) + pPlayer->RewardPlayerAndGroupAtEvent(param1, m_creature); + } } } break; diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp index b0e6f1a67..5961e0995 100644 --- a/src/game/CreatureEventAIMgr.cpp +++ b/src/game/CreatureEventAIMgr.cpp @@ -25,6 +25,7 @@ #include "ProgressBar.h" #include "Policies/SingletonImp.h" #include "ObjectDefines.h" +#include "GridDefines.h" INSTANTIATE_SINGLETON_1(CreatureEventAIMgr); @@ -72,16 +73,22 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Texts() if (temp.SoundId) { - if (!GetSoundEntriesStore()->LookupEntry(temp.SoundId)) - sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has soundId %u but sound does not exist.",i,temp.SoundId); + if (!sSoundEntriesStore.LookupEntry(temp.SoundId)) + sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has Sound %u but sound does not exist.",i,temp.SoundId); } if (!GetLanguageDescByID(temp.Language)) sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` using Language %u but Language does not exist.",i,temp.Language); - if (temp.Type > CHAT_TYPE_BOSS_WHISPER) + if (temp.Type > CHAT_TYPE_ZONE_YELL) sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has Type %u but this Chat Type does not exist.",i,temp.Type); + if (temp.Emote) + { + if (!sEmotesStore.LookupEntry(temp.Emote)) + sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has Emote %u but emote does not exist.",i,temp.Emote); + } + m_CreatureEventAI_TextMap[i] = temp; ++count; } while (result->NextRow()); @@ -90,7 +97,8 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Texts() sLog.outString(); sLog.outString(">> Loaded %u additional CreatureEventAI Texts data.", count); - }else + } + else { barGoLink bar(1); bar.step(); @@ -128,6 +136,12 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Summons() temp.orientation = fields[4].GetFloat(); temp.SpawnTimeSecs = fields[5].GetUInt32(); + if(!MaNGOS::IsValidMapCoord(temp.position_x,temp.position_y,temp.position_z,temp.orientation)) + { + sLog.outErrorDb("CreatureEventAI: Summon id %u have wrong coordinates (%f,%f,%f,%f), skipping.", i,temp.position_x,temp.position_y,temp.position_z,temp.orientation); + continue; + } + //Add to map m_CreatureEventAI_Summon_Map[i] = temp; ++Count; @@ -443,22 +457,16 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, temp.action[j].param3); break; case ACTION_T_EMOTE: - //TODO: load emotes and check it's store for existing - /* if (!sEmotesStore.LookupEntry(temp.action[j].param1)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param1); - */ break; case ACTION_T_RANDOM_EMOTE: - //TODO: load emotes and check it's store for existing - /* if (!sEmotesStore.LookupEntry(temp.action[j].param1)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param1); if (temp.action[j].param2_s >= 0 && !sEmotesStore.LookupEntry(temp.action[j].param2)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param2); if (temp.action[j].param3_s >= 0 && !sEmotesStore.LookupEntry(temp.action[j].param3)) sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 (EmoteId: %u) are not valid.", i, j+1, temp.action[j].param3); - */ break; case ACTION_T_CAST: { diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 52a224945..d87ef4150 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3680,6 +3680,16 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename) break; } + case SCRIPT_COMMAND_EMOTE: + { + if(!sEmotesStore.LookupEntry(tmp.datalong)) + { + sLog.outErrorDb("Table `%s` has invalid emote id (datalong = %u) in SCRIPT_COMMAND_EMOTE for script id %u",tablename,tmp.datalong,tmp.id); + continue; + } + break; + } + case SCRIPT_COMMAND_TELEPORT_TO: { if(!sMapStore.LookupEntry(tmp.datalong)) diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp index 5cea9ed93..043d6fc91 100644 --- a/src/game/WaypointManager.cpp +++ b/src/game/WaypointManager.cpp @@ -141,6 +141,12 @@ void WaypointManager::Load() } } + if (be.emote) + { + if (!sEmotesStore.LookupEntry(be.emote)) + sLog.outErrorDb("Waypoint path %u (Point %u) are using emote %u, but emote does not exist.",id, point, be.emote); + } + // save memory by not storing empty behaviors if(!be.isEmpty()) { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 10200dc94..73e464fee 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 "7688" + #define REVISION_NR "7689" #endif // __REVISION_NR_H__ From fc0e1ecdf1738001913bb00f5ddba900879142b0 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 20 Apr 2009 18:53:08 +0400 Subject: [PATCH 20/22] [7690] Move GetCreature/GetGameobject to class Map. * This let get objects at map without reference to player or another object. * Simplify future implementation for per-map storage for like objects --- src/game/BattleGround.cpp | 4 +-- src/game/BattleGroundHandler.cpp | 10 +++---- src/game/Chat.cpp | 2 +- src/game/GameObject.cpp | 5 ---- src/game/GameObject.h | 1 - src/game/Level1.cpp | 2 +- src/game/Level2.cpp | 31 ++++++++++----------- src/game/LootHandler.cpp | 22 +++++++-------- src/game/Map.cpp | 42 ++++++++++++++++++++++++++++ src/game/Map.h | 4 +++ src/game/ObjectAccessor.cpp | 48 ++------------------------------ src/game/ObjectAccessor.h | 3 -- src/game/Player.cpp | 25 ++++++++--------- src/game/QuestHandler.cpp | 4 +-- src/game/Spell.cpp | 14 +++++----- src/game/SpellEffects.cpp | 6 ++-- src/game/SpellHandler.cpp | 6 ++-- src/game/TaxiHandler.cpp | 2 +- src/game/Unit.cpp | 12 ++++---- src/shared/revision_nr.h | 2 +- 20 files changed, 118 insertions(+), 127 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index f38d8ac09..96d145c35 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -266,9 +266,9 @@ void BattleGround::Update(uint32 diff) if (!plr) continue; - if (!sh) + if (!sh && plr->IsInWorld()) { - sh = ObjectAccessor::GetCreature(*plr, itr->first); + sh = plr->GetMap()->GetCreature(itr->first); // only for visual effect if (sh) sh->CastSpell(sh, SPELL_SPIRIT_HEAL, true); // Spirit Heal, effect 117 diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index e2df35847..06435bd34 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -40,7 +40,7 @@ void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data ) recv_data >> guid; sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_HELLO Message from: " I64FMT, guid); - Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; @@ -102,7 +102,7 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) if (_player->InBattleGround()) return; - Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; @@ -595,7 +595,7 @@ void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; @@ -618,7 +618,7 @@ void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; @@ -647,7 +647,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) recv_data >> guid >> arenaslot >> asGroup >> isRated; - Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 7a0bb8f4b..22f95529f 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -1315,7 +1315,7 @@ GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid Player* pl = m_session->GetPlayer(); - GameObject* obj = ObjectAccessor::GetGameObject(*pl, MAKE_NEW_GUID(lowguid, entry, HIGHGUID_GAMEOBJECT)); + GameObject* obj = pl->GetMap()->GetGameObject(MAKE_NEW_GUID(lowguid, entry, HIGHGUID_GAMEOBJECT)); if(!obj && objmgr.GetGOData(lowguid)) // guid is DB guid of object { diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 4b2916de7..7531c01b9 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -627,11 +627,6 @@ void GameObject::DeleteFromDB() WorldDatabase.PExecuteLog("DELETE FROM game_event_gameobject WHERE guid = '%u'", m_DBTableGuid); } -GameObject* GameObject::GetGameObject(WorldObject& object, uint64 guid) -{ - return ObjectAccessor::GetGameObject(object,guid); -} - GameObjectInfo const *GameObject::GetGOInfo() const { return m_goInfo; diff --git a/src/game/GameObject.h b/src/game/GameObject.h index 8fdea4d2f..f06dbe79e 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -427,7 +427,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject bool Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state); void Update(uint32 p_time); - static GameObject* GetGameObject(WorldObject& object, uint64 guid); GameObjectInfo const* GetGOInfo() const; bool IsTransport() const; diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index d98c0fe83..75a891abd 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -103,7 +103,7 @@ bool ChatHandler::HandleNpcWhisperCommand(const char* args) char* text = strtok(NULL, ""); uint64 guid = m_session->GetPlayer()->GetSelection(); - Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); + Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(guid); if(!pCreature || !receiver_str || !text) { diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 014122cba..79cd2c5da 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -506,7 +506,7 @@ bool ChatHandler::HandleGameObjectTargetCommand(const char* args) return false; } - GameObject* target = ObjectAccessor::GetGameObject(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT)); + GameObject* target = m_session->GetPlayer()->GetMap()->GetGameObject(MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT)); PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o); @@ -1338,7 +1338,7 @@ bool ChatHandler::HandleNpcDeleteCommand(const char* args) return false; if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid)) - unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); + unit = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT)); } else unit = getSelectedCreature(); @@ -2606,7 +2606,7 @@ bool ChatHandler::HandleWpAddCommand(const char* args) return false; } - target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT)); + target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT)); if(!target) { PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid); @@ -2640,7 +2640,7 @@ bool ChatHandler::HandleWpAddCommand(const char* args) return false; } - target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT)); + target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT)); if(!target || target->isPet()) { PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); @@ -2855,7 +2855,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args) return false; } - Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); + Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); if( !npcCreature ) { @@ -2934,13 +2934,13 @@ bool ChatHandler::HandleWpModifyCommand(const char* args) return false; } - Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); + Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); // wpCreature Creature* wpCreature = NULL; if( wpGuid != 0 ) { - wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); + wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); wpCreature->DeleteFromDB(); wpCreature->CleanupsBeforeDelete(); wpCreature->AddObjectToRemoveList(); @@ -2995,7 +2995,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args) return false; } - Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); + Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); // wpCreature Creature* wpCreature = NULL; @@ -3004,7 +3004,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args) // Respawn the owner of the waypoints if( wpGuid != 0 ) { - wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); + wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); wpCreature->DeleteFromDB(); wpCreature->CleanupsBeforeDelete(); wpCreature->AddObjectToRemoveList(); @@ -3067,7 +3067,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args) WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str); - Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); + Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT)); if(npcCreature) { npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); @@ -3167,7 +3167,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) return false; } - target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT)); + target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT)); if(!target) { @@ -3238,7 +3238,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) uint32 model2 = fields[11].GetUInt32(); // Get the creature for which we read the waypoint - Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT)); + Creature* wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT)); PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : ""), creGUID); PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime); @@ -3275,7 +3275,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) { Field *fields = result2->Fetch(); uint32 wpguid = fields[0].GetUInt32(); - Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); + Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); if(!pCreature) { @@ -3474,10 +3474,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) { Field *fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); - Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); - - //Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid); - + Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT)); if(!pCreature) { PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid); diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp index 254f1978f..6d3191a27 100644 --- a/src/game/LootHandler.cpp +++ b/src/game/LootHandler.cpp @@ -44,8 +44,7 @@ void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data ) if (IS_GAMEOBJECT_GUID(lguid)) { - GameObject *go = - ObjectAccessor::GetGameObject(*player, lguid); + GameObject *go = player->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || (go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) @@ -70,8 +69,7 @@ void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data ) } else { - Creature* pCreature = - ObjectAccessor::GetCreature(*player, lguid); + Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass()==CLASS_ROGUE && pCreature->lootForPickPocketed); @@ -163,7 +161,7 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ ) { case HIGHGUID_GAMEOBJECT: { - GameObject *pGameObject = ObjectAccessor::GetGameObject(*GetPlayer(), guid); + GameObject *pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) if( pGameObject && (pGameObject->GetOwnerGUID()==_player->GetGUID() || pGameObject->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) ) @@ -188,7 +186,7 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ ) } case HIGHGUID_UNIT: { - Creature* pCreature = ObjectAccessor::GetCreature(*GetPlayer(), guid); + Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass()==CLASS_ROGUE && pCreature->lootForPickPocketed); @@ -276,10 +274,12 @@ void WorldSession::DoLootRelease( uint64 lguid ) player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); + if(!player->IsInWorld()) + return; + if (IS_GAMEOBJECT_GUID(lguid)) { - GameObject *go = - ObjectAccessor::GetGameObject(*player, lguid); + GameObject *go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || (go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) @@ -401,7 +401,7 @@ void WorldSession::DoLootRelease( uint64 lguid ) } else { - Creature* pCreature = ObjectAccessor::GetCreature(*player, lguid); + Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass()==CLASS_ROGUE && pCreature->lootForPickPocketed); if ( !ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE) ) @@ -458,7 +458,7 @@ void WorldSession::HandleLootMasterGiveOpcode( WorldPacket & recv_data ) if(IS_CREATURE_GUID(GetPlayer()->GetLootGUID())) { - Creature *pCreature = ObjectAccessor::GetCreature(*GetPlayer(), lootguid); + Creature *pCreature = GetPlayer()->GetMap()->GetCreature(lootguid); if(!pCreature) return; @@ -466,7 +466,7 @@ void WorldSession::HandleLootMasterGiveOpcode( WorldPacket & recv_data ) } else if(IS_GAMEOBJECT_GUID(GetPlayer()->GetLootGUID())) { - GameObject *pGO = ObjectAccessor::GetGameObject(*GetPlayer(), lootguid); + GameObject *pGO = GetPlayer()->GetMap()->GetGameObject(lootguid); if(!pGO) return; diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 0db29f022..7de4dfa3f 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -2531,3 +2531,45 @@ void BattleGroundMap::UnloadAll(bool pForce) Map::UnloadAll(pForce); } + +Creature* +Map::GetCreature(uint64 guid) +{ + Creature * ret = ObjectAccessor::GetObjectInWorld(guid, (Creature*)NULL); + if(!ret) + return NULL; + + if(ret->GetMapId() != GetId()) + return NULL; + + if(ret->GetInstanceId() != GetInstanceId()) + return NULL; + + return ret; +} + +GameObject* +Map::GetGameObject(uint64 guid) +{ + GameObject * ret = ObjectAccessor::GetObjectInWorld(guid, (GameObject*)NULL); + if(!ret) + return NULL; + if(ret->GetMapId() != GetId()) + return NULL; + if(ret->GetInstanceId() != GetInstanceId()) + return NULL; + return ret; +} + +DynamicObject* +Map::GetDynamicObject(uint64 guid) +{ + DynamicObject * ret = ObjectAccessor::GetObjectInWorld(guid, (DynamicObject*)NULL); + if(!ret) + return NULL; + if(ret->GetMapId() != GetId()) + return NULL; + if(ret->GetInstanceId() != GetInstanceId()) + return NULL; + return ret; +} diff --git a/src/game/Map.h b/src/game/Map.h index 5388d3963..2b1f1c025 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -402,6 +402,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj void RemoveFromActive(T* obj) { RemoveFromActiveHelper(obj); } void RemoveFromActive(Creature* obj); + + Creature* GetCreature(uint64 guid); + GameObject* GetGameObject(uint64 guid); + DynamicObject* GetDynamicObject(uint64 guid); private: void LoadMapAndVMap(int gx, int gy); void LoadVMap(int gx, int gy); diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 17d7d59cb..da9dd61c4 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -55,23 +55,7 @@ ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const &u, uint64 guid) if(Creature *unit = GetVehicle(guid)) return unit; - return GetCreature(u, guid); -} - -Creature* -ObjectAccessor::GetCreature(WorldObject const &u, uint64 guid) -{ - Creature * ret = GetObjectInWorld(guid, (Creature*)NULL); - if(!ret) - return NULL; - - if(ret->GetMapId() != u.GetMapId()) - return NULL; - - if(ret->GetInstanceId() != u.GetInstanceId()) - return NULL; - - return ret; + return u.GetMap()->GetCreature(guid); } Unit* @@ -117,13 +101,13 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const &p, uint64 guid, u if(typemask & TYPEMASK_GAMEOBJECT) { - obj = GetGameObject(p,guid); + obj = p.GetMap()->GetGameObject(guid); if(obj) return obj; } if(typemask & TYPEMASK_DYNAMICOBJECT) { - obj = GetDynamicObject(p,guid); + obj = p.GetMap()->GetDynamicObject(guid); if(obj) return obj; } @@ -136,32 +120,6 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const &p, uint64 guid, u return NULL; } -GameObject* -ObjectAccessor::GetGameObject(WorldObject const &u, uint64 guid) -{ - GameObject * ret = GetObjectInWorld(guid, (GameObject*)NULL); - if(!ret) - return NULL; - if(ret->GetMapId() != u.GetMapId()) - return NULL; - if(ret->GetInstanceId() != u.GetInstanceId()) - return NULL; - return ret; -} - -DynamicObject* -ObjectAccessor::GetDynamicObject(WorldObject const &u, uint64 guid) -{ - DynamicObject * ret = GetObjectInWorld(guid, (DynamicObject*)NULL); - if(!ret) - return NULL; - if(ret->GetMapId() != u.GetMapId()) - return NULL; - if(ret->GetInstanceId() != u.GetInstanceId()) - return NULL; - return ret; -} - Player* ObjectAccessor::FindPlayer(uint64 guid) { diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index a538dcf38..f29dceb68 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -137,13 +137,10 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::SingletonGetGameObject(GetUInt64Value(PLAYER_DUEL_ARBITER)); if (obj) DuelComplete(DUEL_FLED); } @@ -1962,7 +1962,7 @@ Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask) return NULL; // exist - Creature *unit = ObjectAccessor::GetCreature(*this,guid); + Creature *unit = GetMap()->GetCreature(guid); if (!unit) return NULL; @@ -2002,7 +2002,7 @@ Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask) GameObject* Player::GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const { - if(GameObject *go = ObjectAccessor::GetGameObject(*this,guid)) + if(GameObject *go = GetMap()->GetGameObject(guid)) { if(go->GetGoType() == type) { @@ -6129,7 +6129,7 @@ void Player::CheckDuelDistance(time_t currTime) return; uint64 duelFlagGUID = GetUInt64Value(PLAYER_DUEL_ARBITER); - GameObject* obj = ObjectAccessor::GetGameObject(*this, duelFlagGUID); + GameObject* obj = GetMap()->GetGameObject(duelFlagGUID); if(!obj) return; @@ -6196,7 +6196,7 @@ void Player::DuelComplete(DuelCompleteType type) duel->opponent->GetSession()->SendPacket(&data);*/ //Remove Duel Flag object - GameObject* obj = ObjectAccessor::GetGameObject(*this, GetUInt64Value(PLAYER_DUEL_ARBITER)); + GameObject* obj = GetMap()->GetGameObject(GetUInt64Value(PLAYER_DUEL_ARBITER)); if(obj) duel->initiator->RemoveGameObject(obj,true); @@ -7101,8 +7101,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) if (IS_GAMEOBJECT_GUID(guid)) { sLog.outDebug(" IS_GAMEOBJECT_GUID(guid)"); - GameObject *go = - ObjectAccessor::GetGameObject(*this, guid); + GameObject *go = GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) // And permit out of range GO with no owner in case fishing hole @@ -7215,7 +7214,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) } else { - Creature *creature = ObjectAccessor::GetCreature(*this, guid); + Creature *creature = GetMap()->GetCreature(guid); // must be in range and creature must be alive for pickpocket and must be dead for another loot if (!creature || creature->isAlive()!=(loot_type == LOOT_PICKPOCKETING) || !creature->IsWithinDistInMap(this,INTERACTION_DISTANCE)) @@ -11835,7 +11834,7 @@ void Player::PrepareQuestMenu( uint64 guid ) Object *pObject; QuestRelations* pObjectQR; QuestRelations* pObjectQIR; - Creature *pCreature = ObjectAccessor::GetCreature(*this, guid); + Creature *pCreature = GetMap()->GetCreature(guid); if( pCreature ) { pObject = (Object*)pCreature; @@ -11844,7 +11843,7 @@ void Player::PrepareQuestMenu( uint64 guid ) } else { - GameObject *pGameObject = ObjectAccessor::GetGameObject(*this, guid); + GameObject *pGameObject = GetMap()->GetGameObject(guid); if( pGameObject ) { pObject = (Object*)pGameObject; @@ -11921,7 +11920,7 @@ void Player::SendPreparedQuest( uint64 guid ) qe._Delay = 0; qe._Emote = 0; std::string title = ""; - Creature *pCreature = ObjectAccessor::GetCreature(*this, guid); + Creature *pCreature = GetMap()->GetCreature(guid); if( pCreature ) { uint32 textid = pCreature->GetNpcTextId(); @@ -11985,7 +11984,7 @@ Quest const * Player::GetNextQuest( uint64 guid, Quest const *pQuest ) QuestRelations* pObjectQR; QuestRelations* pObjectQIR; - Creature *pCreature = ObjectAccessor::GetCreature(*this, guid); + Creature *pCreature = GetMap()->GetCreature(guid); if( pCreature ) { pObject = (Object*)pCreature; @@ -11994,7 +11993,7 @@ Quest const * Player::GetNextQuest( uint64 guid, Quest const *pQuest ) } else { - GameObject *pGameObject = ObjectAccessor::GetGameObject(*this, guid); + GameObject *pGameObject = GetMap()->GetGameObject(guid); if( pGameObject ) { pObject = (Object*)pGameObject; diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index bee8aa7eb..430d84c0f 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -611,7 +611,7 @@ void WorldSession::HandleQuestgiverStatusQueryMultipleOpcode(WorldPacket& /*recv if(IS_CREATURE_GUID(*itr)) { - Creature *questgiver = ObjectAccessor::GetCreature(*_player, *itr); + Creature *questgiver = GetPlayer()->GetMap()->GetCreature(*itr); if(!questgiver || questgiver->IsHostileTo(_player)) continue; if(!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) @@ -626,7 +626,7 @@ void WorldSession::HandleQuestgiverStatusQueryMultipleOpcode(WorldPacket& /*recv } else if(IS_GAMEOBJECT_GUID(*itr)) { - GameObject *questgiver = ObjectAccessor::GetGameObject(*_player, *itr); + GameObject *questgiver = GetPlayer()->GetMap()->GetGameObject(*itr); if(!questgiver) continue; if(questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 67da066c3..7f9b796d2 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -158,7 +158,7 @@ void SpellCastTargets::setCorpseTarget(Corpse* corpse) void SpellCastTargets::Update(Unit* caster) { - m_GOTarget = m_GOTargetGUID ? ObjectAccessor::GetGameObject(*caster,m_GOTargetGUID) : NULL; + m_GOTarget = m_GOTargetGUID ? caster->GetMap()->GetGameObject(m_GOTargetGUID) : NULL; m_unitTarget = m_unitTargetGUID ? ( m_unitTargetGUID==caster->GetGUID() ? caster : ObjectAccessor::GetUnit(*caster, m_unitTargetGUID) ) : NULL; @@ -956,7 +956,7 @@ void Spell::AddGOTarget(GameObject* pVictim, uint32 effIndex) void Spell::AddGOTarget(uint64 goGUID, uint32 effIndex) { - GameObject* go = ObjectAccessor::GetGameObject(*m_caster, goGUID); + GameObject* go = m_caster->GetMap()->GetGameObject(goGUID); if (go) AddGOTarget(go, effIndex); } @@ -1233,7 +1233,7 @@ void Spell::DoAllEffectOnTarget(GOTargetInfo *target) if(!effectMask) return; - GameObject* go = ObjectAccessor::GetGameObject(*m_caster, target->targetGUID); + GameObject* go = m_caster->GetMap()->GetGameObject(target->targetGUID); if(!go) return; @@ -1784,7 +1784,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) // Check original caster is GO - set its coordinates as dst cast WorldObject *caster = NULL; if (IS_GAMEOBJECT_GUID(m_originalCasterGUID)) - caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID); + caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID); if (!caster) caster = m_caster; // Set dest for targets @@ -2716,7 +2716,7 @@ void Spell::update(uint32 difftime) { GOTargetInfo* target = &*ihit; - GameObject* go = ObjectAccessor::GetGameObject(*m_caster, target->targetGUID); + GameObject* go = m_caster->GetMap()->GetGameObject(target->targetGUID); if(!go) continue; @@ -3266,7 +3266,7 @@ void Spell::SendChannelStart(uint32 duration) { if(itr->effectMask & (1<<0) ) { - target = ObjectAccessor::GetGameObject(*m_caster, itr->targetGUID); + target = m_caster->GetMap()->GetGameObject(itr->targetGUID); break; } } @@ -5414,7 +5414,7 @@ bool Spell::CheckTarget( Unit* target, uint32 eff ) // Get GO cast coordinates if original caster -> GO WorldObject *caster = NULL; if (IS_GAMEOBJECT_GUID(m_originalCasterGUID)) - caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID); + caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID); if (!caster) caster = m_caster; if(target!=m_caster && !target->IsWithinLOSInMap(caster)) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 13d1f039f..d4bb90154 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -5432,7 +5432,7 @@ void Spell::EffectSummonTotem(uint32 i) uint64 guid = m_caster->m_TotemSlot[slot]; if(guid != 0) { - Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid); + Creature *OldTotem = m_caster->GetMap()->GetCreature(guid); if(OldTotem && OldTotem->isTotem()) ((Totem*)OldTotem)->UnSummon(); } @@ -5632,7 +5632,7 @@ void Spell::EffectSummonObject(uint32 i) { GameObject* obj = NULL; if( m_caster ) - obj = ObjectAccessor::GetGameObject(*m_caster, guid); + obj = m_caster->GetMap()->GetGameObject(guid); if(obj) obj->Delete(); m_caster->m_ObjectSlot[slot] = 0; @@ -6114,7 +6114,7 @@ void Spell::EffectDestroyAllTotems(uint32 /*i*/) if(!m_caster->m_TotemSlot[slot]) continue; - Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]); + Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_TotemSlot[slot]); if(totem && totem->isTotem()) { uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL); diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index e01aaace5..2601497cb 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -230,7 +230,7 @@ void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data ) if(_player->m_mover != _player) return; - GameObject *obj = ObjectAccessor::GetGameObject(*_player, guid); + GameObject *obj = GetPlayer()->GetMap()->GetGameObject(guid); if(!obj) return; @@ -254,7 +254,7 @@ void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket) if(_player->m_mover != _player) return; - GameObject* go = ObjectAccessor::GetGameObject(*_player,guid); + GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid); if(!go) return; @@ -471,7 +471,7 @@ void WorldSession::HandleTotemDestroy( WorldPacket& recvPacket) if(!_player->m_TotemSlot[slotId]) return; - Creature* totem = ObjectAccessor::GetCreature(*_player,_player->m_TotemSlot[slotId]); + Creature* totem = GetPlayer()->GetMap()->GetCreature(_player->m_TotemSlot[slotId]); if(totem && totem->isTotem()) ((Totem*)totem)->UnSummon(); } diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp index 4a035ce02..4fedb5afc 100644 --- a/src/game/TaxiHandler.cpp +++ b/src/game/TaxiHandler.cpp @@ -46,7 +46,7 @@ void WorldSession::HandleTaxiNodeStatusQueryOpcode( WorldPacket & recv_data ) void WorldSession::SendTaxiStatus( uint64 guid ) { // cheating checks - Creature *unit = ObjectAccessor::GetCreature(*_player, guid); + Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) { sLog.outDebug( "WorldSession::SendTaxiStatus - Unit (GUID: %u) not found.", uint32(GUID_LOPART(guid)) ); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index a9b3605e2..7b38fdee4 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3984,7 +3984,7 @@ void Unit::RemoveDynObject(uint32 spellid) return; for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();) { - DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*i); + DynamicObject* dynObj = GetMap()->GetDynamicObject(*i); if(!dynObj) { i = m_dynObjGUIDs.erase(i); @@ -4003,7 +4003,7 @@ void Unit::RemoveAllDynObjects() { while(!m_dynObjGUIDs.empty()) { - DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*m_dynObjGUIDs.begin()); + DynamicObject* dynObj = GetMap()->GetDynamicObject(*m_dynObjGUIDs.begin()); if(dynObj) dynObj->Delete(); m_dynObjGUIDs.erase(m_dynObjGUIDs.begin()); @@ -4014,7 +4014,7 @@ DynamicObject * Unit::GetDynObject(uint32 spellId, uint32 effIndex) { for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();) { - DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*i); + DynamicObject* dynObj = GetMap()->GetDynamicObject(*i); if(!dynObj) { i = m_dynObjGUIDs.erase(i); @@ -4032,7 +4032,7 @@ DynamicObject * Unit::GetDynObject(uint32 spellId) { for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();) { - DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*i); + DynamicObject* dynObj = GetMap()->GetDynamicObject(*i); if(!dynObj) { i = m_dynObjGUIDs.erase(i); @@ -7259,7 +7259,7 @@ bool Unit::isAttackingPlayer() const { if(m_TotemSlot[i]) { - Creature *totem = ObjectAccessor::GetCreature(*this, m_TotemSlot[i]); + Creature *totem = GetMap()->GetCreature(m_TotemSlot[i]); if(totem && totem->isAttackingPlayer()) return true; } @@ -7417,7 +7417,7 @@ void Unit::UnsummonAllTotems() if(!m_TotemSlot[i]) continue; - Creature *OldTotem = ObjectAccessor::GetCreature(*this, m_TotemSlot[i]); + Creature *OldTotem = GetMap()->GetCreature(m_TotemSlot[i]); if (OldTotem && OldTotem->isTotem()) ((Totem*)OldTotem)->UnSummon(); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 73e464fee..8b313a2ef 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 "7689" + #define REVISION_NR "7690" #endif // __REVISION_NR_H__ From c4c093dac6416d39a6d4a6b2bc82eda8db1fdff7 Mon Sep 17 00:00:00 2001 From: AlexDereka Date: Mon, 20 Apr 2009 22:15:49 +0400 Subject: [PATCH 21/22] [7691] Added MySQL to PostgreSQL converter. Tested on PostgreSQL 8.3 and MySQL 5.0. For compile see README. --- contrib/mysql_to_pgsql/CMakeLists.txt | 21 ++ contrib/mysql_to_pgsql/README | 14 + contrib/mysql_to_pgsql/cmake/FindMySQL.cmake | 74 ++++ .../mysql_to_pgsql/cmake/FindPostgreSQL.cmake | 82 +++++ contrib/mysql_to_pgsql/src/defines.h | 173 +++++++++ contrib/mysql_to_pgsql/src/main.cpp | 339 ++++++++++++++++++ src/shared/revision_nr.h | 2 +- 7 files changed, 704 insertions(+), 1 deletion(-) create mode 100644 contrib/mysql_to_pgsql/CMakeLists.txt create mode 100644 contrib/mysql_to_pgsql/README create mode 100644 contrib/mysql_to_pgsql/cmake/FindMySQL.cmake create mode 100644 contrib/mysql_to_pgsql/cmake/FindPostgreSQL.cmake create mode 100644 contrib/mysql_to_pgsql/src/defines.h create mode 100644 contrib/mysql_to_pgsql/src/main.cpp diff --git a/contrib/mysql_to_pgsql/CMakeLists.txt b/contrib/mysql_to_pgsql/CMakeLists.txt new file mode 100644 index 000000000..490a023e4 --- /dev/null +++ b/contrib/mysql_to_pgsql/CMakeLists.txt @@ -0,0 +1,21 @@ +SET(CMAKE_VERBOSE_MAKEFILE ON) +cmake_minimum_required (VERSION 2.6) + +INCLUDE(cmake/FindMySQL.cmake) +INCLUDE(cmake/FindPostgreSQL.cmake) + +MESSAGE("-- Check PostgreSQL") +FIND_PGSQL() +ADD_DEFINITIONS(-DDO_POSTGRESQL) + +MESSAGE("-- Check MySQL") +FIND_MYSQL() +ADD_DEFINITIONS(-DDO_MYSQL) + +INCLUDE_DIRECTORIES(${MYSQL_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${PGSQL_INCLUDE_DIR}) + +ADD_EXECUTABLE (mysql2pgsql src/main.cpp) + +TARGET_LINK_LIBRARIES(mysql2pgsql ${PGSQL_LIBRARIES}) +TARGET_LINK_LIBRARIES(mysql2pgsql ${MYSQL_LIBRARIES}) diff --git a/contrib/mysql_to_pgsql/README b/contrib/mysql_to_pgsql/README new file mode 100644 index 000000000..bf7083fb6 --- /dev/null +++ b/contrib/mysql_to_pgsql/README @@ -0,0 +1,14 @@ +Using cmake on a Windows +------------------ + 1. install cmake (http://www.cmake.org/cmake/resources/software.html) + 2. cmake -i + 3. Project.sln + 4. {Debug/Release}/mysql2pgsql.exe + +Using cmake on a Unix/Linux +------------------ + 1. install cmake + 2. cmake -i + 3. make + 4. ./mysql2pgsql + diff --git a/contrib/mysql_to_pgsql/cmake/FindMySQL.cmake b/contrib/mysql_to_pgsql/cmake/FindMySQL.cmake new file mode 100644 index 000000000..e7d158de2 --- /dev/null +++ b/contrib/mysql_to_pgsql/cmake/FindMySQL.cmake @@ -0,0 +1,74 @@ +# - Find mysqlclient +# Find the native MySQL includes and library +# +# MYSQL_INCLUDE_DIR - where to find mysql.h, etc. +# MYSQL_LIBRARIES - List of libraries when using MySQL. +# MYSQL_FOUND - True if MySQL found. +MACRO(FIND_MYSQL) + +IF (MYSQL_INCLUDE_DIR) + # Already in cache, be silent + SET(MySQL_FIND_QUIETLY TRUE) +ENDIF (MYSQL_INCLUDE_DIR) + +FIND_PATH(MYSQL_INCLUDE_DIR mysql.h + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 6.0;Location]/include" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.1;Location]/include" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.0;Location]/include" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 4.1;Location]/include" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 4.0;Location]/include" + /usr/local/mysql/include + /usr/local/include/mysql + /usr/local/include + /usr/include/mysql + /usr/include + /usr/mysql/include +) + +IF(MSVC) + SET(MYSQL_NAMES libmysql) +ELSE(MSVC) + SET(MYSQL_NAMES mysqlclient mysqlclient_r) +ENDIF(MSVC) +SET(MYSQL_SEARCH_LIB_PATHS + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 6.0;Location]/lib/opt" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.1;Location]/lib/opt" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 5.0;Location]/lib/opt" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 4.1;Location]/lib/opt" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MySQL AB\\MySQL Server 4.0;Location]/lib/opt" + /usr/local/mysql/lib + /usr/local/lib/mysql + /usr/local/lib + /usr/lib/mysql + /usr/lib +) +FIND_LIBRARY(MYSQL_LIBRARY + NAMES ${MYSQL_NAMES} + PATHS ${MYSQL_SEARCH_LIB_PATHS} +) + +IF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) + SET(MYSQL_FOUND TRUE) + SET( MYSQL_LIBRARIES ${MYSQL_LIBRARY} ) +ELSE (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) + SET(MYSQL_FOUND FALSE) + SET( MYSQL_LIBRARIES ) +ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) + +IF (MYSQL_FOUND) + IF (NOT MySQL_FIND_QUIETLY) + MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARY}") + ENDIF (NOT MySQL_FIND_QUIETLY) +ELSE (MYSQL_FOUND) + IF (MySQL_FIND_REQUIRED) + MESSAGE(STATUS "Looked for MySQL libraries named ${MYSQL_NAMES}.") + MESSAGE(FATAL_ERROR "Could NOT find MySQL library") + ENDIF (MySQL_FIND_REQUIRED) +ENDIF (MYSQL_FOUND) + +MARK_AS_ADVANCED( + MYSQL_LIBRARY + MYSQL_INCLUDE_DIR +) + +ENDMACRO(FIND_MYSQL) \ No newline at end of file diff --git a/contrib/mysql_to_pgsql/cmake/FindPostgreSQL.cmake b/contrib/mysql_to_pgsql/cmake/FindPostgreSQL.cmake new file mode 100644 index 000000000..06a1adc9e --- /dev/null +++ b/contrib/mysql_to_pgsql/cmake/FindPostgreSQL.cmake @@ -0,0 +1,82 @@ +# - Find libpq +# Find the native PostgreSQL includes and library +# +# PGSQL_INCLUDE_DIR - where to find libpq-fe.h, etc. +# PGSQL_LIBRARIES - List of libraries when using PGSQL. +# PGSQL_FOUND - True if PGSQL found. + +MACRO(FIND_PGSQL) +IF (PGSQL_INCLUDE_DIR) + # Already in cache, be silent + SET(PostgreSQL_FIND_QUIETLY TRUE) +ENDIF (PGSQL_INCLUDE_DIR) + +# the registry settings checked are in order: +# - for pgInstaller 8.2.x postgresql version +# - for pgInstaller 8.3.x postgresql version +SET(PGSQL_WIN_BASE + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\PostgreSQL\\Installations\\{B823632F-3B72-4514-8861-B961CE263224};Base Directory]" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\PostgreSQL\\Installations\\{1F701DBD-1660-4108-B10A-FB435EA63BF0};Base Directory]") + +IF(PGSQL_WIN_BASE) + IF(MSVC) + SET(PGSQL_SEARCH_LIB_PATHS "${PGSQL_WIN_BASE}/lib/ms") + ELSE(MSVC) + SET(PGSQL_SEARCH_LIB_PATHS "${PGSQL_WIN_BASE}/lib") + ENDIF(MSVC) +ENDIF(PGSQL_WIN_BASE) + +FIND_PATH(PGSQL_INCLUDE_DIR libpq-fe.h + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\PostgreSQL\\Installations\\{1F701DBD-1660-4108-B10A-FB435EA63BF0};Base Directory]/include" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\PostgreSQL\\Installations\\{B823632F-3B72-4514-8861-B961CE263224};Base Directory]/include" + /usr/local/pgsql/include + /usr/local/postgresql/include + /usr/local/include/pgsql + /usr/local/include/postgresql + /usr/local/include + /usr/include/pgsql + /usr/include/postgresql + /usr/include + /usr/pgsql/include + /usr/postgresql/include +) + +SET(PGSQL_NAMES pq libpq) +SET(PGSQL_SEARCH_LIB_PATHS + ${PGSQL_SEARCH_LIB_PATHS} + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\PostgreSQL\\Installations\\{1F701DBD-1660-4108-B10A-FB435EA63BF0};Base Directory]/lib" + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\PostgreSQL\\Installations\\{B823632F-3B72-4514-8861-B961CE263224};Base Directory]/lib" + /usr/local/pgsql/lib + /usr/local/lib + /usr/lib +) +FIND_LIBRARY(PGSQL_LIBRARY + NAMES ${PGSQL_NAMES} + PATHS ${PGSQL_SEARCH_LIB_PATHS} +) + +IF (PGSQL_INCLUDE_DIR AND PGSQL_LIBRARY) + SET(PGSQL_FOUND TRUE) + SET( PGSQL_LIBRARIES ${PGSQL_LIBRARY} ) +ELSE (PGSQL_INCLUDE_DIR AND PGSQL_LIBRARY) + SET(PGSQL_FOUND FALSE) + SET( PGSQL_LIBRARIES ) +ENDIF (PGSQL_INCLUDE_DIR AND PGSQL_LIBRARY) + +IF (PGSQL_FOUND) + IF (NOT PostgreSQL_FIND_QUIETLY) + MESSAGE(STATUS "Found PostgreSQL: ${PGSQL_LIBRARY}") + ENDIF (NOT PostgreSQL_FIND_QUIETLY) +ELSE (PGSQL_FOUND) + IF (PostgreSQL_FIND_REQUIRED) + MESSAGE(STATUS "Looked for PostgreSQL libraries named ${PGSQL_NAMES}.") + MESSAGE(FATAL_ERROR "Could NOT find PostgreSQL library") + ENDIF (PostgreSQL_FIND_REQUIRED) +ENDIF (PGSQL_FOUND) + +MARK_AS_ADVANCED( + PGSQL_LIBRARY + PGSQL_INCLUDE_DIR +) +ENDMACRO(FIND_PGSQL) + diff --git a/contrib/mysql_to_pgsql/src/defines.h b/contrib/mysql_to_pgsql/src/defines.h new file mode 100644 index 000000000..662a7aab2 --- /dev/null +++ b/contrib/mysql_to_pgsql/src/defines.h @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _DEFINES_ +#define _DEFINES_ + +#ifdef WIN32 +#include +#pragma warning(disable:4996) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + + +#ifdef WIN32 +typedef unsigned __int64 uint64; +typedef unsigned int uint32; +#else +#include +#ifndef uint64_t +#include +#endif +typedef uint64_t uint64; +typedef unsigned int uint32; +#endif + +struct sField +{ + string name; // field name + string def; // field default data + string type; // field type + uint32 flags; // filed flags, see field flags; +}; +typedef vector T_Table; +typedef vector T_TableList; +typedef map< string, T_Table > TDataBase; + +static +void pg_notice(void *arg, const char *message) +{ + /// Do nothing + //printf("%s\n", message); +} + +inline +string ConvertNativeType(enum_field_types mysqlType, uint32 length) +{ + + switch (mysqlType) + { + case FIELD_TYPE_TIMESTAMP: + return "timestamp"; + case FIELD_TYPE_BIT: + return "bit(1)"; + case FIELD_TYPE_DATETIME: + return "date"; + case FIELD_TYPE_YEAR: + case FIELD_TYPE_BLOB: + case FIELD_TYPE_SET: + case FIELD_TYPE_NULL: + case FIELD_TYPE_ENUM: + return "text"; + case FIELD_TYPE_TINY: + case FIELD_TYPE_SHORT: + case FIELD_TYPE_INT24: + return "integer"; + case FIELD_TYPE_LONGLONG: + return "int8"; + case FIELD_TYPE_LONG: + return "bigint"; + case FIELD_TYPE_DECIMAL: + case FIELD_TYPE_FLOAT: + case FIELD_TYPE_DOUBLE: + return "float"; + case FIELD_TYPE_STRING: + { + string temp; + char str[10]; + temp = "char"; + if (length) + { + temp.append("("); + sprintf(str,"%d",length); + temp.append(str); + temp.append(")"); + } + return temp; + } + case FIELD_TYPE_VAR_STRING: + { + string temp; + char str[10]; + temp = "varchar"; + if (length) + { + temp.append("("); + sprintf(str,"%d",length); + temp.append(str); + temp.append(")"); + } + return temp; + } + default: + return "text"; + } + return "text"; +} + +inline +bool IsNeeedEscapeString(enum_field_types mysqlType) +{ + switch(mysqlType) + { + case FIELD_TYPE_VAR_STRING: + case FIELD_TYPE_STRING: + case FIELD_TYPE_TINY_BLOB: + case FIELD_TYPE_MEDIUM_BLOB: + case FIELD_TYPE_LONG_BLOB: + case FIELD_TYPE_BLOB: + return true; + default: + return false; + } + return false; +} + +inline +void PG_Exec_str(string sql, PGconn *mPGconn) +{ + PGresult *res = PQexec (mPGconn, sql.c_str()); + if (PQresultStatus(res) != PGRES_COMMAND_OK) + { + printf( "SQL: %s", sql.c_str() ); + printf( "SQL %s", PQerrorMessage(mPGconn) ); + } +} + +void PG_Escape_Str(string& str) +{ + if(str.empty()) + return; + char* buf = new char[str.size()*2+1]; + PQescapeString(buf,str.c_str(),str.size()); + str = buf; + delete[] buf; +} + +#endif + diff --git a/contrib/mysql_to_pgsql/src/main.cpp b/contrib/mysql_to_pgsql/src/main.cpp new file mode 100644 index 000000000..8ca6772de --- /dev/null +++ b/contrib/mysql_to_pgsql/src/main.cpp @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "defines.h" + +int main(int argc, char* argv[]) +{ + char sPGhost[26], sPGport[26], sPGdb[26], sPGuser[26], sPGpass[26]; + printf("Postgres connection settings\n Host>"); + scanf("%s",sPGhost); + printf(" Port>"); + scanf("%s",sPGport); + printf(" Base>"); + scanf("%s",sPGdb); + printf(" User>"); + scanf("%s",sPGuser); + printf(" Pass>"); + scanf("%s",sPGpass); + + /////////////////////////////// + ///////PGSQL Connect/////////// + /////////////////////////////// + PGconn *mPGconn=NULL; + mPGconn = PQsetdbLogin(sPGhost,sPGport, NULL, NULL, sPGdb, sPGuser, sPGpass); + + if (PQstatus(mPGconn) != CONNECTION_OK) + { + printf("Could not connect to Postgre database at [%s]: \n %s\n",sPGhost, PQerrorMessage(mPGconn)); + PQfinish(mPGconn); + return 1; + } + else + { + printf("Connected to Postgre database at [%s]\n", sPGhost); + printf(" PostgreSQL server ver: [%d]\n\n",PQserverVersion(mPGconn)); + } + + /// Set dummy notice processor + PQsetNoticeProcessor(mPGconn, pg_notice, mPGconn); + + /////////////////////////////// + ///////MySQL Connect/////////// + /////////////////////////////// + MYSQL *mysqlInit; + mysqlInit = mysql_init(NULL); + if (!mysqlInit) + { + printf( "Could not initialize Mysql connection\n" ); + return 1; + } + + char sMYhost[26], sMYdb[26], sMYuser[26], sMYpass[26]; + int iMYport; + printf("Mysql connection settings \n Host>"); + scanf("%s",sMYhost); + printf(" Port>"); + scanf("%d",&iMYport); + printf(" Base>"); + scanf("%s",sMYdb); + printf(" User>"); + scanf("%s",sMYuser); + printf(" Pass>"); + scanf("%s",sMYpass); + + mysql_options(mysqlInit,MYSQL_SET_CHARSET_NAME,"utf8"); + + MYSQL *mMysql; + mMysql = mysql_real_connect(mysqlInit, sMYhost, sMYuser, sMYpass, sMYdb, iMYport, NULL, 0); + + if (mMysql) + { + printf( "Connected to MySQL database at [%s] \n", sMYhost); + printf( " MySQL client library: [%s] \n", mysql_get_client_info()); + printf( " MySQL server ver: [%s] \n\n", mysql_get_server_info( mMysql)); + } + else + { + printf("Could not connect to MySQL database at [%s]:\n %s\n", sMYhost ,mysql_error(mysqlInit)); + mysql_close(mysqlInit); + return 1; + } + + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + MYSQL_RES *result = NULL; + MYSQL_ROW row; + MYSQL_FIELD *fields = NULL; + uint64 rowCount = 0; + uint32 fieldCount =0; + result = mysql_list_tables( mMysql , NULL ); + rowCount = mysql_num_rows(result); + + /***********************/ + /* get list of tables */ + /***********************/ + T_TableList mTableList; + mTableList.reserve((size_t)rowCount); + while( (row = mysql_fetch_row(result)) !=NULL ) + { + for (uint32 i = 0;i Date: Mon, 20 Apr 2009 22:44:25 +0400 Subject: [PATCH 22/22] [7692] Implement ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE and reimplement ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS. Also correctly set this criteria at login. --- src/game/AchievementMgr.cpp | 37 ++++++++++++++++++++++++++----------- src/game/DBCStructure.h | 2 +- src/game/Player.cpp | 16 +++++++++++----- src/shared/revision_nr.h | 2 +- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 0ba80dfd8..9bb894efc 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -965,14 +965,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui break; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: { - // spell always provide and at login spell learning. - if(!miscvalue1) - continue; - // rescan only when change possible - SkillLineAbilityMap::const_iterator skillIter0 = spellmgr.GetBeginSkillLineAbilityMap(miscvalue1); - if(skillIter0 == spellmgr.GetEndSkillLineAbilityMap(miscvalue1)) - continue; - if(skillIter0->second->skillId != achievementCriteria->learn_skilline_spell.skillLine) + if(miscvalue1 && miscvalue1 != achievementCriteria->learn_skillline_spell.skillLine) continue; uint32 spellCount = 0; @@ -984,7 +977,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first); ++skillIter) { - if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine) + if(skillIter->second->skillId == achievementCriteria->learn_skillline_spell.skillLine) spellCount++; } } @@ -1019,6 +1012,27 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; } + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE: + { + if(miscvalue1 && miscvalue1 != achievementCriteria->learn_skill_line.skillLine) + continue; + + uint32 spellCount = 0; + for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin(); + spellIter != GetPlayer()->GetSpellMap().end(); + ++spellIter) + { + for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first); + skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first); + ++skillIter) + { + if(skillIter->second->skillId == achievementCriteria->learn_skill_line.skillLine) + spellCount++; + } + } + SetCriteriaProgress(achievementCriteria, spellCount); + break; + } // std case: not exist in DBC, not triggered in code as result case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER: @@ -1069,7 +1083,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED: case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN: case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: - case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE: case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL: case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS: case ACHIEVEMENT_CRITERIA_TYPE_TOTAL: @@ -1192,7 +1205,9 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT: return progress->counter >= achievementCriteria->fish_in_gameobject.lootCount; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: - return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount; + return progress->counter >= achievementCriteria->learn_skillline_spell.spellCount; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE: + return progress->counter >= achievementCriteria->learn_skill_line.spellCount; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 5c6c928a6..af0e479cd 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -419,7 +419,7 @@ struct AchievementCriteriaEntry { uint32 skillLine; // 3 uint32 spellCount; // 4 - } learn_skilline_spell; + } learn_skillline_spell; // ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76 struct diff --git a/src/game/Player.cpp b/src/game/Player.cpp index db7041d01..74569e5db 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2891,6 +2891,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen SpellLearnSkillNode const* spellLearnSkill = spellmgr.GetSpellLearnSkill(spell_id); + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spell_id); + if(spellLearnSkill) { uint32 skill_value = GetPureSkillValue(spellLearnSkill->skill); @@ -2909,9 +2912,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen else { // not ranked skills - SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id); - SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spell_id); - for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) { SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->skillId); @@ -2958,10 +2958,16 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen } } - if(IsInWorld()) + if(!GetSession()->PlayerLoading()) { + // not ranked skills + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE,_spell_idx->second->skillId); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS,_spell_idx->second->skillId); + } + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL,spell_id); - GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS,spell_id); } // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 75073dfd7..85c93fa98 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 "7691" + #define REVISION_NR "7692" #endif // __REVISION_NR_H__