Merge 'master' into 310

Please enter the commit message for your changes. Lines starting
This commit is contained in:
tomrus88 2009-04-18 17:21:29 +04:00
parent 3423b5dbb2
commit 66f554f74d
26 changed files with 513 additions and 395 deletions

View file

@ -235,15 +235,6 @@ bool AreaTrigger ( Player *player, AreaTriggerEntry* atEntry )
return tmpscript->pAreaTrigger(player, 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 MANGOS_DLL_EXPORT
bool ItemUse( Player *player, Item* _Item, SpellCastTargets const& targets) bool ItemUse( Player *player, Item* _Item, SpellCastTargets const& targets)
{ {

View file

@ -41,7 +41,7 @@ struct Script
pGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGossipSelectWithCode(NULL), pGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGossipSelectWithCode(NULL),
pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), pChooseReward(NULL), pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), pChooseReward(NULL),
pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), pGOQuestAccept(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) pEffectDummyItem(NULL), GetAI(NULL)
{} {}
@ -63,7 +63,6 @@ struct Script
bool (*pItemQuestAccept )(Player *player, Item *_Item, Quest const*_Quest ); bool (*pItemQuestAccept )(Player *player, Item *_Item, Quest const*_Quest );
bool (*pGOQuestAccept )(Player *player, GameObject *_GO, Quest const*_Quest ); bool (*pGOQuestAccept )(Player *player, GameObject *_GO, Quest const*_Quest );
bool (*pGOChooseReward )(Player *player, GameObject *_GO, Quest const*_Quest, uint32 opt ); 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 (*pItemUse )(Player *player, Item* _Item, SpellCastTargets const& targets);
bool (*pEffectDummyGameObj )(Unit*, uint32, uint32, GameObject* ); bool (*pEffectDummyGameObj )(Unit*, uint32, uint32, GameObject* );
bool (*pEffectDummyCreature )(Unit*, uint32, uint32, Creature* ); bool (*pEffectDummyCreature )(Unit*, uint32, uint32, Creature* );

View file

@ -789,8 +789,18 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break; break;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) // if miscvalues != 0, it contains the questID.
SetCriteriaProgress(achievementCriteria, 1); 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; break;
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
@ -943,6 +953,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
if(miscvalue1 != achievementCriteria->use_gameobject.goEntry) if(miscvalue1 != achievementCriteria->use_gameobject.goEntry)
continue; 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); SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break; break;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: 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_MONEY_FROM_VENDORS:
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS: case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL: 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_EARNED_PVP_TITLE:
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL: case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE: case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
@ -1172,6 +1189,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
return progress->counter >= achievementCriteria->loot_money.goldInCopper; return progress->counter >= achievementCriteria->loot_money.goldInCopper;
case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT: case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
return progress->counter >= achievementCriteria->use_gameobject.useCount; 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: case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount; return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount;

View file

@ -587,8 +587,8 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);
//Send scripted event call //Send scripted event call
if (unit && unit->GetTypeId()==TYPEID_UNIT && Script) if (unit && unit->GetTypeId()==TYPEID_UNIT && ((Creature*)unit)->AI())
Script->ReceiveEmote(GetPlayer(),(Creature*)unit,text_emote); ((Creature*)unit)->AI()->ReceiveEmote(GetPlayer(),text_emote);
} }
void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data ) void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data )

View file

@ -25,9 +25,10 @@
#include "Dynamic/ObjectRegistry.h" #include "Dynamic/ObjectRegistry.h"
#include "Dynamic/FactoryHolder.h" #include "Dynamic/FactoryHolder.h"
class WorldObject;
class Unit; class Unit;
class Creature; class Creature;
class WorldObject; class Player;
struct SpellEntry; struct SpellEntry;
#define TIME_INTERVAL_LOOK 5000 #define TIME_INTERVAL_LOOK 5000
@ -88,6 +89,9 @@ class MANGOS_DLL_SPEC CreatureAI
// Called at waypoint reached or point movement finished // Called at waypoint reached or point movement finished
virtual void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) {} 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 ================== ///== Triggered Actions Requested ==================
// Called when creature attack expected (if creature can and no have current victim) // Called when creature attack expected (if creature can and no have current victim)

View file

@ -47,7 +47,7 @@ CreatureEventAI::CreatureEventAI(Creature *c ) : CreatureAI(c), InCombat(false)
{ {
//Debug check //Debug check
#ifndef _DEBUG #ifndef MANGOS_DEBUG
if ((*i).event_flags & EFLAG_DEBUG_ONLY) if ((*i).event_flags & EFLAG_DEBUG_ONLY)
continue; continue;
#endif #endif
@ -1629,19 +1629,17 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge
return true; 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) for (std::list<CreatureEventAIHolder>::iterator itr = CreatureEventAIList.begin(); itr != CreatureEventAIList.end(); ++itr)
return true;
for (std::list<CreatureEventAIHolder>::iterator itr = pTmpCreature->CreatureEventAIList.begin(); itr != pTmpCreature->CreatureEventAIList.end(); ++itr)
{ {
if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE) if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE)
{ {
if ((*itr).Event.event_param1 != uiEmote) if ((*itr).Event.event_param1 != text_emote)
return true; return;
bool bProcess = false; bool bProcess = false;
@ -1696,10 +1694,8 @@ bool CreatureEventAI::ReceiveEmote(Player* pPlayer, Creature* pCreature, uint32
if (bProcess) if (bProcess)
{ {
sLog.outDebug("CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing"); sLog.outDebug("CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing");
pTmpCreature->ProcessEvent(*itr, pPlayer); ProcessEvent(*itr, pPlayer);
} }
} }
} }
return true;
} }

View file

@ -32,74 +32,74 @@ class WorldObject;
#define MAX_ACTIONS 3 #define MAX_ACTIONS 3
#define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available #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 = 0, // InitialMin, InitialMax, RepeatMin, RepeatMax
EVENT_T_TIMER_OOC = 1, //InitialMin, InitialMax, RepeatMin, RepeatMax EVENT_T_TIMER_OOC = 1, // InitialMin, InitialMax, RepeatMin, RepeatMax
EVENT_T_HP = 2, //HPMax%, HPMin%, RepeatMin, RepeatMax EVENT_T_HP = 2, // HPMax%, HPMin%, RepeatMin, RepeatMax
EVENT_T_MANA = 3, //ManaMax%,ManaMin% RepeatMin, RepeatMax EVENT_T_MANA = 3, // ManaMax%,ManaMin% RepeatMin, RepeatMax
EVENT_T_AGGRO = 4, //NONE EVENT_T_AGGRO = 4, // NONE
EVENT_T_KILL = 5, //RepeatMin, RepeatMax EVENT_T_KILL = 5, // RepeatMin, RepeatMax
EVENT_T_DEATH = 6, //NONE EVENT_T_DEATH = 6, // NONE
EVENT_T_EVADE = 7, //NONE EVENT_T_EVADE = 7, // NONE
EVENT_T_SPELLHIT = 8, //SpellID, School, RepeatMin, RepeatMax EVENT_T_SPELLHIT = 8, // SpellID, School, RepeatMin, RepeatMax
EVENT_T_RANGE = 9, //MinDist, MaxDist, RepeatMin, RepeatMax EVENT_T_RANGE = 9, // MinDist, MaxDist, RepeatMin, RepeatMax
EVENT_T_OOC_LOS = 10, //NoHostile, NoFriendly, RepeatMin, RepeatMax EVENT_T_OOC_LOS = 10, // NoHostile, NoFriendly, RepeatMin, RepeatMax
EVENT_T_SPAWNED = 11, //NONE EVENT_T_SPAWNED = 11, // NONE
EVENT_T_TARGET_HP = 12, //HPMax%, HPMin%, RepeatMin, RepeatMax EVENT_T_TARGET_HP = 12, // HPMax%, HPMin%, RepeatMin, RepeatMax
EVENT_T_TARGET_CASTING = 13, //RepeatMin, RepeatMax EVENT_T_TARGET_CASTING = 13, // RepeatMin, RepeatMax
EVENT_T_FRIENDLY_HP = 14, //HPDeficit, Radius, RepeatMin, RepeatMax EVENT_T_FRIENDLY_HP = 14, // HPDeficit, Radius, RepeatMin, RepeatMax
EVENT_T_FRIENDLY_IS_CC = 15, //DispelType, 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_FRIENDLY_MISSING_BUFF = 16, // SpellId, Radius, RepeatMin, RepeatMax
EVENT_T_SUMMONED_UNIT = 17, //CreatureId, RepeatMin, RepeatMax EVENT_T_SUMMONED_UNIT = 17, // CreatureId, RepeatMin, RepeatMax
EVENT_T_TARGET_MANA = 18, //ManaMax%, ManaMin%, RepeatMin, RepeatMax EVENT_T_TARGET_MANA = 18, // ManaMax%, ManaMin%, RepeatMin, RepeatMax
EVENT_T_QUEST_ACCEPT = 19, //QuestID EVENT_T_QUEST_ACCEPT = 19, // QuestID
EVENT_T_QUEST_COMPLETE = 20, // EVENT_T_QUEST_COMPLETE = 20, //
EVENT_T_REACHED_HOME = 21, //NONE EVENT_T_REACHED_HOME = 21, // NONE
EVENT_T_RECEIVE_EMOTE = 22, //EmoteId, Condition, CondValue1, CondValue2 EVENT_T_RECEIVE_EMOTE = 22, // EmoteId, Condition, CondValue1, CondValue2
EVENT_T_END, EVENT_T_END,
}; };
enum Action_Types enum EventAI_ActionType
{ {
ACTION_T_NONE = 0, //No action 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_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_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_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_SOUND = 4, //*SoundId
ACTION_T_EMOTE = 5, //EmoteId ACTION_T_EMOTE = 5, //*EmoteId
ACTION_T_RANDOM_SAY = 6, //UNUSED ACTION_T_RANDOM_SAY = 6, //*UNUSED
ACTION_T_RANDOM_YELL = 7, //UNUSED ACTION_T_RANDOM_YELL = 7, //*UNUSED
ACTION_T_RANDOM_TEXTEMOTE = 8, //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_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_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_CAST = 11, //*SpellId, Target, CastFlags
ACTION_T_SUMMON = 12, //CreatureID, Target, Duration in ms ACTION_T_SUMMON = 12, //*CreatureID, Target, Duration in ms
ACTION_T_THREAT_SINGLE_PCT = 13, //Threat%, Target ACTION_T_THREAT_SINGLE_PCT = 13, //*Threat%, Target
ACTION_T_THREAT_ALL_PCT = 14, //Threat% ACTION_T_THREAT_ALL_PCT = 14, //Threat%
ACTION_T_QUEST_EVENT = 15, //QuestID, Target ACTION_T_QUEST_EVENT = 15, //*QuestID, Target
ACTION_T_CASTCREATUREGO = 16, //QuestID, SpellId, Target ACTION_T_CASTCREATUREGO = 16, //*QuestID, SpellId, Target
ACTION_T_SET_UNIT_FIELD = 17, //Field_Number, Value, 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_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_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_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_COMBAT_MOVEMENT = 21, //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
ACTION_T_SET_PHASE = 22, //Phase ACTION_T_SET_PHASE = 22, //*Phase
ACTION_T_INC_PHASE = 23, //Value (may be negative to decrement phase, should not be 0) ACTION_T_INC_PHASE = 23, //*Value (may be negative to decrement phase, should not be 0)
ACTION_T_EVADE = 24, //No Params ACTION_T_EVADE = 24, //No Params
ACTION_T_FLEE = 25, //No Params ACTION_T_FLEE = 25, //No Params
ACTION_T_QUEST_EVENT_ALL = 26, //QuestID ACTION_T_QUEST_EVENT_ALL = 26, //*QuestID
ACTION_T_CASTCREATUREGO_ALL = 27, //QuestId, SpellId ACTION_T_CASTCREATUREGO_ALL = 27, //*QuestId, SpellId
ACTION_T_REMOVEAURASFROMSPELL = 28, //Target, Spellid ACTION_T_REMOVEAURASFROMSPELL = 28, //*Target, Spellid
ACTION_T_RANGED_MOVEMENT = 29, //Distance, Angle ACTION_T_RANGED_MOVEMENT = 29, //Distance, Angle
ACTION_T_RANDOM_PHASE = 30, //PhaseId1, PhaseId2, PhaseId3 ACTION_T_RANDOM_PHASE = 30, //PhaseId1, PhaseId2, PhaseId3
ACTION_T_RANDOM_PHASE_RANGE = 31, //PhaseMin, PhaseMax ACTION_T_RANDOM_PHASE_RANGE = 31, //PhaseMin, PhaseMax
ACTION_T_SUMMON_ID = 32, //CreatureId, Target, SpawnId ACTION_T_SUMMON_ID = 32, //*CreatureId, Target, SpawnId
ACTION_T_KILLED_MONSTER = 33, //CreatureId, Target ACTION_T_KILLED_MONSTER = 33, //*CreatureId, Target
ACTION_T_SET_INST_DATA = 34, //Field, Data ACTION_T_SET_INST_DATA = 34, //*Field, Data
ACTION_T_SET_INST_DATA64 = 35, //Field, Target ACTION_T_SET_INST_DATA64 = 35, //*Field, Target
ACTION_T_UPDATE_TEMPLATE = 36, //Entry, Team ACTION_T_UPDATE_TEMPLATE = 36, //*Entry, Team
ACTION_T_DIE = 37, //No Params ACTION_T_DIE = 37, //No Params
ACTION_T_ZONE_COMBAT_PULSE = 38, //No Params ACTION_T_ZONE_COMBAT_PULSE = 38, //No Params
@ -152,7 +152,7 @@ enum EventFlags
EFLAG_RESERVED_4 = 0x10, EFLAG_RESERVED_4 = 0x10,
EFLAG_RESERVED_5 = 0x20, EFLAG_RESERVED_5 = 0x20,
EFLAG_RESERVED_6 = 0x40, 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) // String text additional data, used in (CreatureEventAI)
@ -172,10 +172,12 @@ struct CreatureEventAI_Event
uint32 creature_id; uint32 creature_id;
uint16 event_type;
uint32 event_inverse_phase_mask; 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 union
{ {
uint32 event_param1; uint32 event_param1;
@ -199,7 +201,7 @@ struct CreatureEventAI_Event
struct _action struct _action
{ {
uint16 type; EventAI_ActionType type: 16;
union union
{ {
uint32 param1; uint32 param1;
@ -265,6 +267,7 @@ class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI
void SpellHit(Unit* pUnit, const SpellEntry* pSpell); void SpellHit(Unit* pUnit, const SpellEntry* pSpell);
void UpdateAI(const uint32 diff); void UpdateAI(const uint32 diff);
bool IsVisible(Unit *) const; bool IsVisible(Unit *) const;
void ReceiveEmote(Player* pPlayer, uint32 text_emote);
static int Permissible(const Creature *); static int Permissible(const Creature *);
bool ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker = NULL); bool ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker = NULL);
@ -277,7 +280,6 @@ class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI
void DoZoneInCombat(Unit* pUnit); void DoZoneInCombat(Unit* pUnit);
void DoMeleeAttackIfReady(); void DoMeleeAttackIfReady();
bool CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered); bool CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered);
bool ReceiveEmote(Player* pPlayer, Creature* pCreature, uint32 uiEmote);
Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff); Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff);
void DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid); void DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid);

View file

@ -171,38 +171,41 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
Field *fields = result->Fetch(); Field *fields = result->Fetch();
CreatureEventAI_Event temp; CreatureEventAI_Event temp;
temp.event_id = EventAI_Type(fields[0].GetUInt32());
temp.event_id = fields[0].GetUInt32();
uint32 i = temp.event_id; uint32 i = temp.event_id;
temp.creature_id = fields[1].GetUInt32(); temp.creature_id = fields[1].GetUInt32();
uint32 creature_id = temp.creature_id; 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_inverse_phase_mask = fields[3].GetUInt32();
temp.event_chance = fields[4].GetUInt8(); 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_param1 = fields[6].GetUInt32();
temp.event_param2 = fields[7].GetUInt32(); temp.event_param2 = fields[7].GetUInt32();
temp.event_param3 = fields[8].GetUInt32(); temp.event_param3 = fields[8].GetUInt32();
temp.event_param4 = fields[9].GetUInt32(); temp.event_param4 = fields[9].GetUInt32();
CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(temp.creature_id);
//Creature does not exist in database //Creature does not exist in database
if (!cInfo) if (!sCreatureStorage.LookupEntry<CreatureInfo>(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; 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 //No chance of this event occuring
if (temp.event_chance == 0) if (temp.event_chance == 0)
sLog.outErrorDb("CreatureEventAI: Event %u has 0 percent chance. Event will never trigger!", i); sLog.outErrorDb("CreatureEventAI: Event %u has 0 percent chance. Event will never trigger!", i);
//Chance above 100, force it to be 100 //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); 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; temp.event_chance = 100;
@ -211,6 +214,18 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
//Individual event checks //Individual event checks
switch (temp.event_type) 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_HP:
case EVENT_T_MANA: case EVENT_T_MANA:
case EVENT_T_TARGET_HP: 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); 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; temp.event_flags &= ~EFLAG_REPEATABLE;
} }
break;
} }
break;
case EVENT_T_SPELLHIT: case EVENT_T_SPELLHIT:
{ {
if (temp.event_param1) if (temp.event_param1)
{ {
SpellEntry const* pSpell = GetSpellStore()->LookupEntry(temp.event_param1); SpellEntry const* pSpell = sSpellStore.LookupEntry(temp.event_param1);
if (!pSpell) if (!pSpell)
{ {
sLog.outErrorDb("CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.event_param1, i); 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) 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); 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_RANGE:
case EVENT_T_OOC_LOS: case EVENT_T_OOC_LOS:
@ -260,29 +275,28 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
case EVENT_T_FRIENDLY_IS_CC: case EVENT_T_FRIENDLY_IS_CC:
case EVENT_T_FRIENDLY_MISSING_BUFF: case EVENT_T_FRIENDLY_MISSING_BUFF:
{ {
if (temp.event_param4 < temp.event_param3) //Disabled check for now. Check code related to events and adjust accordingly before enable.
sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); //Events should have min/max or alternative set to a static value.
} /*if (!temp.event_param3 && !temp.event_param4)
break; {
sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) without param3/param4 (RepeatMin/RepeatMax). Using minimum values.", temp.creature_id, i);
case EVENT_T_TIMER: temp.event_param3 = 2500;
case EVENT_T_TIMER_OOC: temp.event_param4 = 2500;
{ }*/
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) 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); 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_KILL:
case EVENT_T_TARGET_CASTING: case EVENT_T_TARGET_CASTING:
{ {
if (temp.event_param2 < temp.event_param1) 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); 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_AGGRO:
case EVENT_T_DEATH: 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); 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; 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<CreatureInfo>(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++) 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].param1 = fields[11+(j*4)].GetUInt32();
temp.action[j].param2 = fields[12+(j*4)].GetUInt32(); temp.action[j].param2 = fields[12+(j*4)].GetUInt32();
temp.action[j].param3 = fields[13+(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 //Report any errors in actions
switch (temp.action[j].type) switch (temp.action[j].type)
{ {
case ACTION_T_NONE:
break;
case ACTION_T_TEXT: case ACTION_T_TEXT:
{ {
if (temp.action[j].param1_s < 0) 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) 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); 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: 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); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant FactionId %u.", i, j+1, temp.action[j].param1);
temp.action[j].param1 = 0; temp.action[j].param1 = 0;
@ -344,13 +417,13 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
case ACTION_T_MORPH_TO_ENTRY_OR_MODEL: case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
if (temp.action[j].param1 !=0 || temp.action[j].param2 !=0) 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<CreatureInfo>(temp.action[j].param1))
{ {
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, 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; 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); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, temp.action[j].param2);
temp.action[j].param2 = 0; temp.action[j].param2 = 0;
@ -358,24 +431,38 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
} }
break; break;
case ACTION_T_SOUND: 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); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, temp.action[j].param1);
break; break;
/*
case ACTION_T_RANDOM_SOUND: case ACTION_T_RANDOM_SOUND:
{ if (!sSoundEntriesStore.LookupEntry(temp.action[j].param1))
if(!GetSoundEntriesStore()->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); 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); 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); 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: case ACTION_T_CAST:
{ {
const SpellEntry *spell = GetSpellStore()->LookupEntry(temp.action[j].param1); const SpellEntry *spell = sSpellStore.LookupEntry(temp.action[j].param1);
if (!spell) if (!spell)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param1); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param1);
else 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 //output as debug for now, also because there's no general rule all spells have RecoveryTime
if (temp.event_param3 < spell->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) if (temp.action[j].param2 >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
} }
break;
case ACTION_T_REMOVEAURASFROMSPELL: 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); 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) if (temp.action[j].param1 >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
} }
break;
case ACTION_T_QUEST_EVENT: 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)) 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); 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) if (temp.action[j].param2 >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
} }
break;
case ACTION_T_QUEST_EVENT_ALL: 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)) 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); 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 else
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1); 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: case ACTION_T_CASTCREATUREGO:
{ {
if (!GetCreatureTemplateStore(temp.action[j].param1)) if (!sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, 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); 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) if (temp.action[j].param3 >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
} }
break;
case ACTION_T_CASTCREATUREGO_ALL: 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); 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); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
break;
} }
break;
//2nd param target //2nd param target
case ACTION_T_SUMMON_ID: case ACTION_T_SUMMON_ID:
{ {
if (!GetCreatureTemplateStore(temp.action[j].param1)) if (!sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, 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()) 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) if (temp.action[j].param2 >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
} }
break;
case ACTION_T_KILLED_MONSTER: case ACTION_T_KILLED_MONSTER:
{ {
if (!GetCreatureTemplateStore(temp.action[j].param1)) if (!sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, 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) if (temp.action[j].param2 >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
} }
break;
case ACTION_T_SUMMON: case ACTION_T_SUMMON:
{ {
if (!GetCreatureTemplateStore(temp.action[j].param1)) if (!sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, 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) if (temp.action[j].param2 >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); 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_THREAT_SINGLE_PCT:
case ACTION_T_SET_UNIT_FLAG: case ACTION_T_SET_UNIT_FLAG:
case ACTION_T_REMOVE_UNIT_FLAG: case ACTION_T_REMOVE_UNIT_FLAG:
if (temp.action[j].param2 >= TARGET_T_END) if (temp.action[j].param2 >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break; break;
//3rd param target
//3rd param target
case ACTION_T_SET_UNIT_FIELD: case ACTION_T_SET_UNIT_FIELD:
if (temp.action[j].param1 < OBJECT_END || temp.action[j].param1 >= UNIT_END) 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); 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*/) 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); 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: case ACTION_T_SET_INST_DATA64:
{ {
if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC)) 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) if (temp.action[j].param2 >= TARGET_T_END)
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
break;
} }
break;
case ACTION_T_UPDATE_TEMPLATE: case ACTION_T_UPDATE_TEMPLATE:
{ {
if (!GetCreatureTemplateStore(temp.action[j].param1)) if (!sCreatureStorage.LookupEntry<CreatureInfo>(temp.action[j].param1))
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, 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_SAY:
case ACTION_T_RANDOM_YELL: case ACTION_T_RANDOM_YELL:
case ACTION_T_RANDOM_TEXTEMOTE: 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); sLog.outErrorDb("CreatureEventAI: Event %u Action %u currently unused ACTION type. Did you forget to update database?", i, j+1);
break; break;
default: default:
if (temp.action[j].type >= ACTION_T_END) 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);
sLog.outErrorDb("CreatureEventAI: Event %u Action %u has incorrect action type. Maybe DB requires updated version of SD2.", i, j+1);
break; break;
} }
} }

View file

@ -281,50 +281,50 @@ enum TotemCategoryType
}; };
// SummonProperties.dbc, col 1 // SummonProperties.dbc, col 1
/*enum SummonGroup enum SummonPropGroup
{ {
SUMMON_GROUP_UNKNOWN1 = 0, // 1160 spells in 3.0.3 SUMMON_PROP_GROUP_UNKNOWN1 = 0, // 1160 spells in 3.0.3
SUMMON_GROUP_UNKNOWN2 = 1, // 861 spells in 3.0.3 SUMMON_PROP_GROUP_UNKNOWN2 = 1, // 861 spells in 3.0.3
SUMMON_GROUP_PETS = 2, // 52 spells in 3.0.3, pets mostly SUMMON_PROP_GROUP_PETS = 2, // 52 spells in 3.0.3, pets mostly
SUMMON_GROUP_CONTROLLABLE = 3, // 13 spells in 3.0.3, mostly controllable SUMMON_PROP_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_UNKNOWN3 = 4 // 86 spells in 3.0.3, taxi/mounts
}; };
// SummonProperties.dbc, col 3 // SummonProperties.dbc, col 3
enum SummonType enum SummonPropType
{ {
SUMMON_TYPE_UNKNOWN = 0, // different summons, 1330 spells in 3.0.3 SUMMON_PROP_TYPE_UNKNOWN = 0, // different summons, 1330 spells in 3.0.3
SUMMON_TYPE_SUMMON = 1, // generic summons, 49 spells in 3.0.3 SUMMON_PROP_TYPE_SUMMON = 1, // generic summons, 49 spells in 3.0.3
SUMMON_TYPE_GUARDIAN = 2, // summon guardian, 393 spells in 3.0.3 SUMMON_PROP_TYPE_GUARDIAN = 2, // summon guardian, 393 spells in 3.0.3
SUMMON_TYPE_ARMY = 3, // summon army, 5 spells in 3.0.3 SUMMON_PROP_TYPE_ARMY = 3, // summon army, 5 spells in 3.0.3
SUMMON_TYPE_TOTEM = 4, // summon totem, 169 spells in 3.0.3 SUMMON_PROP_TYPE_TOTEM = 4, // summon totem, 169 spells in 3.0.3
SUMMON_TYPE_CRITTER = 5, // critter/minipet, 195 spells in 3.0.3 SUMMON_PROP_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_PROP_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_PROP_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_PROP_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_PROP_TYPE_SIEGE_VEH = 9, // summon different vehicles, 14 spells in 3.0.3
SUMMON_TYPE_DRAKE_VEH = 10, // summon drake (vehicle), 3 spells SUMMON_PROP_TYPE_DRAKE_VEH = 10, // summon drake (vehicle), 3 spells
SUMMON_TYPE_LIGHTWELL = 11 // summon lightwell, 6 spells in 3.0.3 SUMMON_PROP_TYPE_LIGHTWELL = 11 // summon lightwell, 6 spells in 3.0.3
}; };
// SummonProperties.dbc, col 5 // SummonProperties.dbc, col 5
enum SummonFlags enum SummonPropFlags
{ {
SUMMON_FLAG_NONE = 0x0000, // 1342 spells in 3.0.3 SUMMON_PROP_FLAG_NONE = 0x0000, // 1342 spells in 3.0.3
SUMMON_FLAG_UNK1 = 0x0001, // 75 spells in 3.0.3, something unfriendly SUMMON_PROP_FLAG_UNK1 = 0x0001, // 75 spells in 3.0.3, something unfriendly
SUMMON_FLAG_UNK2 = 0x0002, // 616 spells in 3.0.3, something friendly SUMMON_PROP_FLAG_UNK2 = 0x0002, // 616 spells in 3.0.3, something friendly
SUMMON_FLAG_UNK3 = 0x0004, // 22 spells in 3.0.3, no idea... SUMMON_PROP_FLAG_UNK3 = 0x0004, // 22 spells in 3.0.3, no idea...
SUMMON_FLAG_UNK4 = 0x0008, // 49 spells in 3.0.3, some mounts SUMMON_PROP_FLAG_UNK4 = 0x0008, // 49 spells in 3.0.3, some mounts
SUMMON_FLAG_UNK5 = 0x0010, // 25 spells in 3.0.3, quest related? SUMMON_PROP_FLAG_UNK5 = 0x0010, // 25 spells in 3.0.3, quest related?
SUMMON_FLAG_UNK6 = 0x0020, // 0 spells in 3.0.3, unused SUMMON_PROP_FLAG_UNK6 = 0x0020, // 0 spells in 3.0.3, unused
SUMMON_FLAG_UNK7 = 0x0040, // 12 spells in 3.0.3, no idea SUMMON_PROP_FLAG_UNK7 = 0x0040, // 12 spells in 3.0.3, no idea
SUMMON_FLAG_UNK8 = 0x0080, // 4 spells in 3.0.3, no idea SUMMON_PROP_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_PROP_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_PROP_FLAG_UNK10 = 0x0200, // 51 spells in 3.0.3, something defensive
SUMMON_FLAG_UNK11 = 0x0400, // 3 spells, requires something near? SUMMON_PROP_FLAG_UNK11 = 0x0400, // 3 spells, requires something near?
SUMMON_FLAG_UNK12 = 0x0800, // 30 spells in 3.0.3, no idea SUMMON_PROP_FLAG_UNK12 = 0x0800, // 30 spells in 3.0.3, no idea
SUMMON_FLAG_UNK13 = 0x1000, // 8 spells in 3.0.3, siege vehicle SUMMON_PROP_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_UNK14 = 0x2000, // 2 spells in 3.0.3, escort?
}; };
*/
#endif #endif

View file

@ -56,7 +56,8 @@ DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore(CurrencyTypesfmt);
DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore(DurabilityQualityfmt); DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore(DurabilityQualityfmt);
DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt); DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt);
DBCStorage <EmotesTextEntry> sEmotesTextStore(EmoteEntryfmt); DBCStorage <EmotesEntry> sEmotesStore(EmotesEntryfmt);
DBCStorage <EmotesTextEntry> sEmotesTextStore(EmotesTextEntryfmt);
typedef std::map<uint32,SimpleFactionsList> FactionTeamMap; typedef std::map<uint32,SimpleFactionsList> FactionTeamMap;
static FactionTeamMap sFactionTeamMap; static FactionTeamMap sFactionTeamMap;
@ -198,7 +199,7 @@ void LoadDBCStores(const std::string& dataPath)
{ {
std::string dbcPath = dataPath+"dbc/"; std::string dbcPath = dataPath+"dbc/";
const uint32 DBCFilesCount = 77; const uint32 DBCFilesCount = 78;
barGoLink bar( DBCFilesCount ); 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,sCurrencyTypesStore, dbcPath,"CurrencyTypes.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.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,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,sEmotesTextStore, dbcPath,"EmotesText.dbc");
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionStore, dbcPath,"Faction.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionStore, dbcPath,"Faction.dbc");
for (uint32 i=0;i<sFactionStore.GetNumRows(); ++i) for (uint32 i=0;i<sFactionStore.GetNumRows(); ++i)
@ -667,3 +669,5 @@ MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStore()
MANGOS_DLL_SPEC DBCStorage <FactionEntry> const* GetFactionStore() { return &sFactionStore; } MANGOS_DLL_SPEC DBCStorage <FactionEntry> const* GetFactionStore() { return &sFactionStore; }
MANGOS_DLL_SPEC DBCStorage <ItemEntry> const* GetItemDisplayStore() { return &sItemStore; } MANGOS_DLL_SPEC DBCStorage <ItemEntry> const* GetItemDisplayStore() { return &sItemStore; }
MANGOS_DLL_SPEC DBCStorage <CreatureDisplayInfoEntry> const* GetCreatureDisplayStore() { return &sCreatureDisplayInfoStore; } MANGOS_DLL_SPEC DBCStorage <CreatureDisplayInfoEntry> const* GetCreatureDisplayStore() { return &sCreatureDisplayInfoStore; }
MANGOS_DLL_SPEC DBCStorage <EmotesEntry> const* GetEmotesStore() { return &sEmotesStore; }
MANGOS_DLL_SPEC DBCStorage <EmotesTextEntry> const* GetEmotesTextStore() { return &sEmotesTextStore; }

View file

@ -78,6 +78,7 @@ extern DBCStorage <CreatureTypeEntry> sCreatureTypeStore;
extern DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore; extern DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore;
extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore; extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore;
extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore; extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore;
extern DBCStorage <EmotesEntry> sEmotesStore;
extern DBCStorage <EmotesTextEntry> sEmotesTextStore; extern DBCStorage <EmotesTextEntry> sEmotesTextStore;
extern DBCStorage <FactionEntry> sFactionStore; extern DBCStorage <FactionEntry> sFactionStore;
extern DBCStorage <FactionTemplateEntry> sFactionTemplateStore; extern DBCStorage <FactionTemplateEntry> sFactionTemplateStore;
@ -153,4 +154,6 @@ MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStor
MANGOS_DLL_SPEC DBCStorage <FactionEntry> const* GetFactionStore(); MANGOS_DLL_SPEC DBCStorage <FactionEntry> const* GetFactionStore();
MANGOS_DLL_SPEC DBCStorage <ItemEntry> const* GetItemDisplayStore(); MANGOS_DLL_SPEC DBCStorage <ItemEntry> const* GetItemDisplayStore();
MANGOS_DLL_SPEC DBCStorage <CreatureDisplayInfoEntry> const* GetCreatureDisplayStore(); MANGOS_DLL_SPEC DBCStorage <CreatureDisplayInfoEntry> const* GetCreatureDisplayStore();
MANGOS_DLL_SPEC DBCStorage <EmotesEntry> const* GetEmotesStore();
MANGOS_DLL_SPEC DBCStorage <EmotesTextEntry> const* GetEmotesTextStore();
#endif #endif

View file

@ -749,6 +749,17 @@ struct DurabilityQualityEntry
float quality_mod; // 1 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 struct EmotesTextEntry
{ {
uint32 Id; uint32 Id;
@ -1446,15 +1457,17 @@ struct StableSlotPricesEntry
uint32 Price; uint32 Price;
}; };
/*struct SummonPropertiesEntry /* unused currently
struct SummonPropertiesEntry
{ {
uint32 Id; // 0 uint32 Id; // 0
uint32 Group; // 1, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount? 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 FactionId; // 2, 14 rows > 0
uint32 Type; // 3, see enum uint32 Type; // 3, enum SummonPropType
uint32 Slot; // 4, 0-6 uint32 Slot; // 4, 0-6
uint32 Flags; // 5 uint32 Flags; // 5, enum SummonPropFlags
};*/ };
*/
#define MAX_TALENT_RANK 5 #define MAX_TALENT_RANK 5
#define MAX_PET_TALENT_RANK 3 // use in calculations, expected <= MAX_TALENT_RANK #define MAX_PET_TALENT_RANK 3 // use in calculations, expected <= MAX_TALENT_RANK

View file

@ -42,7 +42,8 @@ const char CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx";
const char CurrencyTypesfmt[]="xnxi"; const char CurrencyTypesfmt[]="xnxi";
const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
const char DurabilityQualityfmt[]="nf"; const char DurabilityQualityfmt[]="nf";
const char EmoteEntryfmt[]="nxixxxxxxxxxxxxxxxx"; const char EmotesEntryfmt[]="nxxiiix";
const char EmotesTextEntryfmt[]="nxixxxxxxxxxxxxxxxx";
const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiissssssssssssssssxxxxxxxxxxxxxxxxxx"; const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiissssssssssssssssxxxxxxxxxxxxxxxxxx";
const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii"; const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
const char GemPropertiesEntryfmt[]="nixxi"; const char GemPropertiesEntryfmt[]="nixxi";

View file

@ -1024,6 +1024,7 @@ void GameObject::Use(Unit* user)
if (ok) if (ok)
{ {
player->SendLoot(ok->GetGUID(),LOOT_FISHINGHOLE); player->SendLoot(ok->GetGUID(),LOOT_FISHINGHOLE);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT, ok->GetGOInfo()->id);
SetLootState(GO_JUST_DEACTIVATED); SetLootState(GO_JUST_DEACTIVATED);
} }
else else

View file

@ -7416,13 +7416,16 @@ void ObjectMgr::CheckScripts(ScriptMapMap const& scripts,std::set<int32>& ids)
{ {
for(ScriptMap::const_iterator itrM = itrMM->second.begin(); itrM != itrMM->second.end(); ++itrM) 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)) case SCRIPT_COMMAND_TALK:
sLog.outErrorDb( "Table `db_script_string` has not existed string id %u", itrM->first); {
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)) if(ids.count(itrM->second.dataint))
ids.erase(itrM->second.dataint); ids.erase(itrM->second.dataint);
}
} }
} }
} }

View file

@ -63,7 +63,7 @@ void PetAI::MoveInLineOfSight(Unit *u)
void PetAI::AttackStart(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; return;
if(m_creature->Attack(u,true)) if(m_creature->Attack(u,true))
@ -274,7 +274,7 @@ void PetAI::UpdateAI(const uint32 diff)
m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id); m_creature->AddCreatureSpellCooldown(spell->m_spellInfo->Id);
if (m_creature->isPet()) if (m_creature->isPet())
((Pet&)m_creature).CheckLearning(spell->m_spellInfo->Id); ((Pet*)m_creature)->CheckLearning(spell->m_spellInfo->Id);
spell->prepare(&targets); spell->prepare(&targets);
} }

View file

@ -12371,7 +12371,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
if (pQuest->GetZoneOrSort() > 0) if (pQuest->GetZoneOrSort() > 0)
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, pQuest->GetZoneOrSort()); 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_COUNT);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, pQuest->GetQuestId());
uint32 zone = 0; uint32 zone = 0;
uint32 area = 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) for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr)
{ {
time_t cooldown = 0; time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILISECONDS : 0;
if(itr->second > curTime)
cooldown = (itr->second - curTime) * IN_MILISECONDS;
data << uint32(itr->first); // spellid data << uint32(itr->first); // spellid
data << uint16(0); // spell category? data << uint16(0); // spell category?
data << uint32(itr->second); // cooldown data << uint32(cooldown); // cooldown
data << uint32(0); // category cooldown data << uint32(0); // category cooldown
} }
for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureCategoryCooldowns.begin(); itr != pet->m_CreatureCategoryCooldowns.end(); ++itr) for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureCategoryCooldowns.begin(); itr != pet->m_CreatureCategoryCooldowns.end(); ++itr)
{ {
time_t cooldown = 0; time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILISECONDS : 0;
if(itr->second > curTime)
cooldown = (itr->second - curTime) * IN_MILISECONDS;
data << uint32(itr->first); // spellid data << uint32(itr->first); // spellid
data << uint16(0); // spell category? data << uint16(0); // spell category?
data << uint32(0); // cooldown data << uint32(0); // cooldown
data << uint32(itr->second); // category cooldown data << uint32(cooldown); // category cooldown
} }
GetSession()->SendPacket(&data); GetSession()->SendPacket(&data);
@ -19378,7 +19372,7 @@ void Player::HandleFall(MovementInfo const& movementInfo)
sLog.outDebug("zDiff = %f", z_diff); sLog.outDebug("zDiff = %f", z_diff);
//Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored //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() && if (z_diff >= 14.57f && !isDead() && !isGameMaster() &&
!HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) && !HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) &&
!HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL) ) !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL) )

View file

@ -72,7 +72,6 @@ bool LoadScriptingModule(char const* libName)
||!(testScript->scriptAreaTrigger =(scriptCallAreaTrigger )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"AreaTrigger" )) ||!(testScript->scriptAreaTrigger =(scriptCallAreaTrigger )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"AreaTrigger" ))
||!(testScript->ItemQuestAccept =(scriptCallItemQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemQuestAccept" )) ||!(testScript->ItemQuestAccept =(scriptCallItemQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemQuestAccept" ))
||!(testScript->GOQuestAccept =(scriptCallGOQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GOQuestAccept" )) ||!(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->ItemUse =(scriptCallItemUse )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemUse" ))
||!(testScript->EffectDummyGameObj =(scriptCallEffectDummyGameObj )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"EffectDummyGameObj" )) ||!(testScript->EffectDummyGameObj =(scriptCallEffectDummyGameObj )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"EffectDummyGameObj" ))
||!(testScript->EffectDummyCreature =(scriptCallEffectDummyCreature )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"EffectDummyCreature" )) ||!(testScript->EffectDummyCreature =(scriptCallEffectDummyCreature )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"EffectDummyCreature" ))

View file

@ -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 * scriptCallItemQuestAccept)(Player *player, Item *, Quest const*);
typedef bool(MANGOS_IMPORT * scriptCallGOQuestAccept)(Player *player, GameObject *, 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 * 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 * 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 * scriptCallEffectDummyGameObj) (Unit *caster, uint32 spellId, uint32 effIndex, GameObject *gameObjTarget);
typedef bool(MANGOS_IMPORT * scriptCallEffectDummyCreature) (Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget); typedef bool(MANGOS_IMPORT * scriptCallEffectDummyCreature) (Unit *caster, uint32 spellId, uint32 effIndex, Creature *crTarget);
@ -83,7 +82,6 @@ typedef struct
scriptCallAreaTrigger scriptAreaTrigger; scriptCallAreaTrigger scriptAreaTrigger;
scriptCallItemQuestAccept ItemQuestAccept; scriptCallItemQuestAccept ItemQuestAccept;
scriptCallGOQuestAccept GOQuestAccept; scriptCallGOQuestAccept GOQuestAccept;
scriptCallReceiveEmote ReceiveEmote;
scriptCallItemUse ItemUse; scriptCallItemUse ItemUse;
scriptCallEffectDummyGameObj EffectDummyGameObj; scriptCallEffectDummyGameObj EffectDummyGameObj;
scriptCallEffectDummyCreature EffectDummyCreature; scriptCallEffectDummyCreature EffectDummyCreature;

View file

@ -991,6 +991,7 @@ enum Targets
TARGET_RANDOM_FRIEND_CHAIN_IN_AREA = 3, TARGET_RANDOM_FRIEND_CHAIN_IN_AREA = 3,
TARGET_PET = 5, TARGET_PET = 5,
TARGET_CHAIN_DAMAGE = 6, TARGET_CHAIN_DAMAGE = 6,
TARGET_AREAEFFECT_INSTANT = 7, // targets around provided destination point
TARGET_AREAEFFECT_CUSTOM = 8, TARGET_AREAEFFECT_CUSTOM = 8,
TARGET_INNKEEPER_COORDINATES = 9, // uses in teleport to innkeeper spells TARGET_INNKEEPER_COORDINATES = 9, // uses in teleport to innkeeper spells
TARGET_ALL_ENEMY_IN_AREA = 15, TARGET_ALL_ENEMY_IN_AREA = 15,
@ -1336,7 +1337,7 @@ enum Emote
EMOTE_ONESHOT_POINT = 25, EMOTE_ONESHOT_POINT = 25,
EMOTE_STATE_STAND = 26, EMOTE_STATE_STAND = 26,
EMOTE_STATE_READYUNARMED = 27, EMOTE_STATE_READYUNARMED = 27,
EMOTE_STATE_WORK = 28, EMOTE_STATE_WORK_SHEATHED = 28,
EMOTE_STATE_POINT = 29, EMOTE_STATE_POINT = 29,
EMOTE_STATE_NONE = 30, EMOTE_STATE_NONE = 30,
EMOTE_ONESHOT_WOUND = 33, EMOTE_ONESHOT_WOUND = 33,
@ -1369,13 +1370,13 @@ enum Emote
EMOTE_ONESHOT_SALUTE_NOSHEATH = 113, EMOTE_ONESHOT_SALUTE_NOSHEATH = 113,
EMOTE_STATE_USESTANDING_NOSHEATHE = 133, EMOTE_STATE_USESTANDING_NOSHEATHE = 133,
EMOTE_ONESHOT_LAUGH_NOSHEATHE = 153, EMOTE_ONESHOT_LAUGH_NOSHEATHE = 153,
EMOTE_STATE_WORK_NOSHEATHE = 173, EMOTE_STATE_WORK = 173,
EMOTE_STATE_SPELLPRECAST = 193, EMOTE_STATE_SPELLPRECAST = 193,
EMOTE_ONESHOT_READYRIFLE = 213, EMOTE_ONESHOT_READYRIFLE = 213,
EMOTE_STATE_READYRIFLE = 214, EMOTE_STATE_READYRIFLE = 214,
EMOTE_STATE_WORK_NOSHEATHE_MINING = 233, EMOTE_STATE_WORK_MINING = 233,
EMOTE_STATE_WORK_NOSHEATHE_CHOPWOOD= 234, EMOTE_STATE_WORK_CHOPWOOD = 234,
EMOTE_zzOLDONESHOT_LIFTOFF = 253, EMOTE_STATE_APPLAUD = 253,
EMOTE_ONESHOT_LIFTOFF = 254, EMOTE_ONESHOT_LIFTOFF = 254,
EMOTE_ONESHOT_YES = 273, EMOTE_ONESHOT_YES = 273,
EMOTE_ONESHOT_NO = 274, EMOTE_ONESHOT_NO = 274,
@ -1424,8 +1425,57 @@ enum Emote
EMOTE_ONESHOT_CUSTOMSPELL09 = 410, EMOTE_ONESHOT_CUSTOMSPELL09 = 410,
EMOTE_ONESHOT_CUSTOMSPELL10 = 411, EMOTE_ONESHOT_CUSTOMSPELL10 = 411,
EMOTE_STATE_EXCLAIM = 412, EMOTE_STATE_EXCLAIM = 412,
EMOTE_STATE_DANCE_CUSTOM = 413,
EMOTE_STATE_SIT_CHAIR_MED = 415, 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 enum Anim

View file

@ -457,6 +457,11 @@ void Spell::FillTargetMap()
case 0: case 0:
SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap);
break; 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 case TARGET_BEHIND_VICTIM: // use B case that not dependent from from A in fact
SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap);
break; break;
@ -482,8 +487,25 @@ void Spell::FillTargetMap()
} }
break; break;
case TARGET_TABLE_X_Y_Z_COORDINATES: case TARGET_TABLE_X_Y_Z_COORDINATES:
// Only if target A, for target B (used in teleports) dest select in effect switch(m_spellInfo->EffectImplicitTargetB[i])
SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[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; break;
default: default:
switch(m_spellInfo->EffectImplicitTargetB[i]) switch(m_spellInfo->EffectImplicitTargetB[i])
@ -1314,7 +1336,7 @@ struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit,
} }
}; };
void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap)
{ {
float radius; float radius;
if (m_spellInfo->EffectRadiusIndex[i]) if (m_spellInfo->EffectRadiusIndex[i])
@ -1598,38 +1620,27 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
}break; }break;
case TARGET_ALL_ENEMY_IN_AREA: case TARGET_ALL_ENEMY_IN_AREA:
{ {
CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE);
Cell cell(p); break;
cell.data.Part.reserved = ALL_DISTRICT; }
cell.SetNoCreate(); 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<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier); // exclude caster
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier); TagUnitMap.remove(m_caster);
}
CellLock<GridReadGuard> 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: case TARGET_ALL_ENEMY_IN_AREA_INSTANT:
{ {
// targets the ground, not the units in the area // targets the ground, not the units in the area
if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA)
{ {
CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE);
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<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> 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());
// exclude caster (this can be important if this not original caster) // exclude caster (this can be important if this not original caster)
TagUnitMap.remove(m_caster); TagUnitMap.remove(m_caster);
@ -1770,7 +1781,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
{ {
// Check original caster is GO - set its coordinates as dst cast // Check original caster is GO - set its coordinates as dst cast
WorldObject *caster = NULL; WorldObject *caster = NULL;
if (m_originalCasterGUID) if (IS_GAMEOBJECT_GUID(m_originalCasterGUID))
caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID); caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID);
if (!caster) if (!caster)
caster = m_caster; caster = m_caster;
@ -1778,37 +1789,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
m_targets.setDestination(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ()); m_targets.setDestination(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ());
}break; }break;
case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER:
{ FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_SELF_CENTER,SPELL_TARGETS_FRIENDLY);
CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); break;
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_SELF_CENTER,SPELL_TARGETS_FRIENDLY);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> 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_FRIENDLY_UNITS_IN_AREA: case TARGET_ALL_FRIENDLY_UNITS_IN_AREA:
{ FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_FRIENDLY);
CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); break;
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_FRIENDLY);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> 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;
// 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..) // 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: case TARGET_SINGLE_PARTY:
{ {
@ -1871,21 +1856,10 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
}break; }break;
case TARGET_IN_FRONT_OF_CASTER: 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; bool inFront = m_spellInfo->SpellVisual[0] != 3879;
MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE); FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),radius,inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE);
break;
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier); }
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> 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_DUELVSPLAYER: case TARGET_DUELVSPLAYER:
{ {
Unit *target = m_targets.getUnitTarget(); Unit *target = m_targets.getUnitTarget();
@ -1921,22 +1895,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
{ {
// targets the ground, not the units in the area // targets the ground, not the units in the area
if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA)
{ FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE);
CellPair p(MaNGOS::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); break;
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<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> 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_MINION: case TARGET_MINION:
{ {
if(m_spellInfo->Effect[i] != SPELL_EFFECT_DUEL) if(m_spellInfo->Effect[i] != SPELL_EFFECT_DUEL)
@ -2038,24 +1999,9 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
unMaxTargets = EffectChainTarget; unMaxTargets = EffectChainTarget;
float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS;
std::list<Unit *> tempUnitMap; UnitList tempUnitMap;
{ FillAreaTargets(tempUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),max_range,PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY);
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<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
CellLock<GridReadGuard> 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());
}
if(m_caster != pUnitTarget && std::find(tempUnitMap.begin(),tempUnitMap.end(),m_caster) == tempUnitMap.end() ) if(m_caster != pUnitTarget && std::find(tempUnitMap.begin(),tempUnitMap.end(),m_caster) == tempUnitMap.end() )
tempUnitMap.push_front(m_caster); tempUnitMap.push_front(m_caster);
@ -2108,20 +2054,10 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
TagUnitMap.push_back(currentTarget); TagUnitMap.push_back(currentTarget);
m_targets.setDestination(currentTarget->GetPositionX(), currentTarget->GetPositionY(), currentTarget->GetPositionZ()); m_targets.setDestination(currentTarget->GetPositionX(), currentTarget->GetPositionY(), currentTarget->GetPositionZ());
if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA_INSTANT) if(m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA_INSTANT)
{ FillAreaTargets(TagUnitMap, currentTarget->GetPositionX(), currentTarget->GetPositionY(), radius, PUSH_TARGET_CENTER, SPELL_TARGETS_AOE_DAMAGE);
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<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_notifier(notifier);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_notifier, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_notifier, *m_caster->GetMap());
}
} }
}break; break;
}
case TARGET_AREAEFFECT_PARTY_AND_CLASS: case TARGET_AREAEFFECT_PARTY_AND_CLASS:
{ {
Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER
@ -2154,29 +2090,8 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
{ {
if (st->target_mapId == m_caster->GetMapId()) if (st->target_mapId == m_caster->GetMapId())
m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); m_targets.setDestination(st->target_X, st->target_Y, st->target_Z);
else
// if B==TARGET_TABLE_X_Y_Z_COORDINATES then A already fill all required targets sLog.outError( "SPELL: wrong map (%u instead %u) target coordinates for spell ID %u", st->target_mapId, m_caster->GetMapId(), m_spellInfo->Id );
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<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_notifier(notifier);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_notifier(notifier);
CellLock<GridReadGuard> 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 else
sLog.outError( "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id ); 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<Unit*> &TagUnitMap)
{ {
// make sure one unit is always removed per iteration // make sure one unit is always removed per iteration
uint32 removed_utarget = 0; uint32 removed_utarget = 0;
for (std::list<Unit*>::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 = itr;
++next; ++next;
@ -2254,9 +2169,10 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
while (TagUnitMap.size() > unMaxTargets - removed_utarget) while (TagUnitMap.size() > unMaxTargets - removed_utarget)
{ {
uint32 poz = urand(0, TagUnitMap.size()-1); uint32 poz = urand(0, TagUnitMap.size()-1);
for (std::list<Unit*>::iterator itr = TagUnitMap.begin(); itr != TagUnitMap.end(); ++itr, --poz) for (UnitList::iterator itr = TagUnitMap.begin(); itr != TagUnitMap.end(); ++itr, --poz)
{ {
if (!*itr) continue; if (!*itr) continue;
if (!poz) if (!poz)
{ {
TagUnitMap.erase(itr); TagUnitMap.erase(itr);
@ -5490,7 +5406,7 @@ bool Spell::CheckTarget( Unit* target, uint32 eff )
default: // normal case default: // normal case
// Get GO cast coordinates if original caster -> GO // Get GO cast coordinates if original caster -> GO
WorldObject *caster = NULL; WorldObject *caster = NULL;
if (m_originalCasterGUID) if (IS_GAMEOBJECT_GUID(m_originalCasterGUID))
caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID); caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID);
if (!caster) if (!caster)
caster = m_caster; caster = m_caster;
@ -5730,3 +5646,17 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk
return SPELL_CAST_OK; 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<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_notifier(notifier);
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_notifier(notifier);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_notifier, *m_caster->GetMap());
cell_lock->Visit(cell_lock, grid_notifier, *m_caster->GetMap());
}

View file

@ -205,6 +205,15 @@ enum SpellState
SPELL_STATE_DELAYED = 5 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) #define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL (1*IN_MILISECONDS)
typedef std::multimap<uint64, uint64> SpellTargetTimeMap; typedef std::multimap<uint64, uint64> SpellTargetTimeMap;
@ -366,9 +375,11 @@ class Spell
void DoCreateItem(uint32 i, uint32 itemtype); void DoCreateItem(uint32 i, uint32 itemtype);
void WriteSpellGoTargets( WorldPacket * data ); void WriteSpellGoTargets( WorldPacket * data );
void WriteAmmoToPacket( WorldPacket * data ); void WriteAmmoToPacket( WorldPacket * data );
void FillTargetMap();
void SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap); typedef std::list<Unit*> 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(); Unit* SelectMagnetTarget();
bool CheckTarget( Unit* target, uint32 eff ); bool CheckTarget( Unit* target, uint32 eff );
@ -579,15 +590,6 @@ enum ReplenishType
REPLENISH_RAGE = 22 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 namespace MaNGOS
{ {
struct MANGOS_DLL_DECL SpellNotifierPlayer struct MANGOS_DLL_DECL SpellNotifierPlayer

View file

@ -468,12 +468,12 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target,
{ {
case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
m_areaAuraType = 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; m_modifier.m_auraname = SPELL_AURA_NONE;
break; break;
case SPELL_EFFECT_APPLY_AREA_AURA_RAID: case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
m_areaAuraType = 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; m_modifier.m_auraname = SPELL_AURA_NONE;
break; break;
case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
@ -481,7 +481,7 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target,
break; break;
case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
m_areaAuraType = 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 m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self
break; break;
case SPELL_EFFECT_APPLY_AREA_AURA_PET: case SPELL_EFFECT_APPLY_AREA_AURA_PET:
@ -489,7 +489,7 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target,
break; break;
case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
m_areaAuraType = AREA_AURA_OWNER; m_areaAuraType = AREA_AURA_OWNER;
if(target == caster_ptr) if (target == caster_ptr)
m_modifier.m_auraname = SPELL_AURA_NONE; m_modifier.m_auraname = SPELL_AURA_NONE;
break; break;
default: default:

View file

@ -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); ((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; return;
} }
case TARGET_AREAEFFECT_INSTANT: // in all cases first TARGET_TABLE_X_Y_Z_COORDINATES
case TARGET_TABLE_X_Y_Z_COORDINATES: case TARGET_TABLE_X_Y_Z_COORDINATES:
{ {
SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id); SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);

View file

@ -181,6 +181,7 @@ inline bool IsAreaEffectTarget( Targets target )
{ {
switch (target ) switch (target )
{ {
case TARGET_AREAEFFECT_INSTANT:
case TARGET_AREAEFFECT_CUSTOM: case TARGET_AREAEFFECT_CUSTOM:
case TARGET_ALL_ENEMY_IN_AREA: case TARGET_ALL_ENEMY_IN_AREA:
case TARGET_ALL_ENEMY_IN_AREA_INSTANT: case TARGET_ALL_ENEMY_IN_AREA_INSTANT:

View file

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