From 66f554f74debe7c10f33e3a2a5ce2f130eeeabdf Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 18 Apr 2009 17:21:29 +0400 Subject: [PATCH] Merge 'master' into 310 Please enter the commit message for your changes. Lines starting --- src/bindings/universal/ScriptMgr.cpp | 9 - src/bindings/universal/ScriptMgr.h | 3 +- src/game/AchievementMgr.cpp | 25 ++- src/game/ChatHandler.cpp | 4 +- src/game/CreatureAI.h | 6 +- src/game/CreatureEventAI.cpp | 20 +-- src/game/CreatureEventAI.h | 118 +++++++------ src/game/CreatureEventAIMgr.cpp | 253 +++++++++++++++++++-------- src/game/DBCEnums.h | 72 ++++---- src/game/DBCStores.cpp | 8 +- src/game/DBCStores.h | 3 + src/game/DBCStructure.h | 27 ++- src/game/DBCfmt.h | 3 +- src/game/GameObject.cpp | 1 + src/game/ObjectMgr.cpp | 13 +- src/game/PetAI.cpp | 4 +- src/game/Player.cpp | 18 +- src/game/ScriptCalls.cpp | 1 - src/game/ScriptCalls.h | 2 - src/game/SharedDefines.h | 62 ++++++- src/game/Spell.cpp | 220 ++++++++--------------- src/game/Spell.h | 24 +-- src/game/SpellAuras.cpp | 8 +- src/game/SpellEffects.cpp | 1 + src/game/SpellMgr.h | 1 + src/shared/revision_nr.h | 2 +- 26 files changed, 513 insertions(+), 395 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/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 1b8338a62..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: @@ -943,6 +953,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 +1049,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: @@ -1172,6 +1189,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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/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..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 @@ -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..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; @@ -265,6 +267,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 +280,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/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/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/DBCStores.cpp b/src/game/DBCStores.cpp index 7795a9198..d3ee63a08 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; @@ -198,7 +199,7 @@ void LoadDBCStores(const std::string& dataPath) { std::string dbcPath = dataPath+"dbc/"; - const uint32 DBCFilesCount = 77; + const uint32 DBCFilesCount = 78; barGoLink bar( DBCFilesCount ); @@ -243,6 +244,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 7b2fff347..1445a6a94 100644 --- a/src/game/DBCStores.h +++ b/src/game/DBCStores.h @@ -78,6 +78,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; @@ -153,4 +154,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 32f759003..22f05f330 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -749,6 +749,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; @@ -1446,15 +1457,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 FactionId; // 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 FactionId; // 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/DBCfmt.h b/src/game/DBCfmt.h index c4081bc67..0cd1ba0fc 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/GameObject.cpp b/src/game/GameObject.cpp index f7a5ad5c5..e5f3886d9 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -1024,6 +1024,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/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 697df7259..cf7242b00 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -7416,13 +7416,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: %u)", 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/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/game/Player.cpp b/src/game/Player.cpp index 2c79e46aa..a4a77ba4f 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -12371,7 +12371,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; @@ -16205,28 +16205,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 << uint32(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 << uint32(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); @@ -19378,7 +19372,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/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/game/SharedDefines.h b/src/game/SharedDefines.h index 919982f12..808873862 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -991,6 +991,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, @@ -1336,7 +1337,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, @@ -1369,13 +1370,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, @@ -1424,8 +1425,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/game/Spell.cpp b/src/game/Spell.cpp index bfaf411c0..5ddc41dbc 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,25 @@ 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); + switch(m_spellInfo->EffectImplicitTargetB[i]) + { + 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: switch(m_spellInfo->EffectImplicitTargetB[i]) @@ -1314,7 +1336,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 +1620,27 @@ 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; + } + 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; - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); + FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),radius, PUSH_DEST_CENTER, targetB); - 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; + // exclude caster + TagUnitMap.remove(m_caster); + } 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); @@ -1770,7 +1781,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &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; @@ -1778,37 +1789,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_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: { @@ -1871,21 +1856,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 +1895,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 +1999,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 +2054,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 @@ -2154,29 +2090,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &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) - { - 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()); - } + 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 ); @@ -2238,7 +2153,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 +2169,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); @@ -5490,7 +5406,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; @@ -5730,3 +5646,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/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index ea7b83aab..9ac627381 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -468,12 +468,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: @@ -481,7 +481,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: @@ -489,7 +489,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 5ce821823..bab3ffbaf 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2100,6 +2100,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 3bc5af93b..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 "7670" + #define REVISION_NR "7685" #endif // __REVISION_NR_H__