aboutsummaryrefslogtreecommitdiff
path: root/src/bindings/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'src/bindings/scripts')
-rw-r--r--src/bindings/scripts/ScriptMgr.cpp649
-rw-r--r--src/bindings/scripts/include/sc_creature.cpp40
-rw-r--r--src/bindings/scripts/include/sc_creature.h3
-rw-r--r--src/bindings/scripts/scripts/creature/mob_event_ai.cpp1524
-rw-r--r--src/bindings/scripts/scripts/creature/mob_event_ai.h219
5 files changed, 4 insertions, 2431 deletions
diff --git a/src/bindings/scripts/ScriptMgr.cpp b/src/bindings/scripts/ScriptMgr.cpp
index 70974f9ea11..8b7b8af72c9 100644
--- a/src/bindings/scripts/ScriptMgr.cpp
+++ b/src/bindings/scripts/ScriptMgr.cpp
@@ -8,7 +8,6 @@
#include "DBCStores.h"
#include "ObjectMgr.h"
#include "ProgressBar.h"
-#include "scripts/creature/mob_event_ai.h"
#define _FULLVERSION "TrinityScript"
@@ -31,18 +30,6 @@ struct StringTextData
uint32 Emote;
};
-// Enums used by StringTextData::Type
-enum ChatType
-{
- CHAT_TYPE_SAY = 0,
- CHAT_TYPE_YELL = 1,
- CHAT_TYPE_TEXT_EMOTE = 2,
- CHAT_TYPE_BOSS_EMOTE = 3,
- CHAT_TYPE_WHISPER = 4,
- CHAT_TYPE_BOSS_WHISPER = 5,
- CHAT_TYPE_ZONE_YELL = 6
-};
-
#define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available
// Text Maps
@@ -51,14 +38,6 @@ UNORDERED_MAP<int32, StringTextData> TextMap;
// Waypoint lists
std::list<PointMovement> PointMovementList;
-//Event AI structure. Used exclusivly by mob_event_ai.cpp (60 bytes each)
-UNORDERED_MAP<uint32, std::vector<EventAI_Event> > EventAI_Event_Map;
-
-//Event AI summon structure. Used exclusivly by mob_event_ai.cpp.
-UNORDERED_MAP<uint32, EventAI_Summon> EventAI_Summon_Map;
-
-uint32 EAI_ErrorLevel;
-
void FillSpellSummary();
void LoadOverridenSQLData();
void LoadOverridenDBCData();
@@ -74,7 +53,6 @@ extern void AddSC_boss_taerar();
extern void AddSC_boss_ysondre();
// -- Creature --
-extern void AddSC_mob_event();
extern void AddSC_generic_creature();
// -- Custom --
@@ -916,613 +894,6 @@ void LoadDatabase()
outstring_log(">> Loaded 0 Script Waypoints. DB table `script_waypoint` is empty.");
}
- //Gather additional data for EventAI
- result = TScriptDB.PQuery("SELECT id, position_x, position_y, position_z, orientation, spawntimesecs FROM eventai_summons");
-
- //Drop Existing EventSummon Map
- EventAI_Summon_Map.clear();
-
- outstring_log("TSCR: Loading EventAI Summons...");
- if (result)
- {
- barGoLink bar(result->GetRowCount());
- uint32 Count = 0;
-
- do
- {
- bar.step();
- Field *fields = result->Fetch();
-
- EventAI_Summon temp;
-
- uint32 i = fields[0].GetUInt32();
- temp.position_x = fields[1].GetFloat();
- temp.position_y = fields[2].GetFloat();
- temp.position_z = fields[3].GetFloat();
- temp.orientation = fields[4].GetFloat();
- temp.SpawnTimeSecs = fields[5].GetUInt32();
-
- //Add to map
- EventAI_Summon_Map[i] = temp;
- ++Count;
- }while (result->NextRow());
-
- delete result;
-
- outstring_log("");
- outstring_log(">> Loaded %u EventAI summon definitions", Count);
- }else
- {
- barGoLink bar(1);
- bar.step();
- outstring_log("");
- outstring_log(">> Loaded 0 EventAI Summon definitions. DB table `eventai_summons` is empty.");
- }
-
- //Drop Existing EventAI List
- EventAI_Event_Map.clear();
- uint64 uiEAICreatureCount = 0;
-
- result = TScriptDB.PQuery("SELECT COUNT(creature_id) FROM eventai_scripts GROUP BY creature_id");
- if (result)
- {
- uiEAICreatureCount = result->GetRowCount();
- delete result;
- }
-
- outstring_log("SD2: Loading EventAI scripts for %u creature(s)...", uiEAICreatureCount);
-
- //Gather event data
- result = TScriptDB.PQuery("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, "
- "event_param1, event_param2, event_param3, event_param4, "
- "action1_type, action1_param1, action1_param2, action1_param3, "
- "action2_type, action2_param1, action2_param2, action2_param3, "
- "action3_type, action3_param1, action3_param2, action3_param3 "
- "FROM eventai_scripts");
-
- outstring_log("SD2: Loading EventAI scripts for %u creature(s)...", uiEAICreatureCount);
- if (result)
- {
- barGoLink bar(result->GetRowCount());
- uint32 Count = 0;
-
- do
- {
- bar.step();
- Field *fields = result->Fetch();
-
- EventAI_Event temp;
-
- temp.event_id = fields[0].GetUInt32();
- uint32 i = temp.event_id;
- temp.creature_id = fields[1].GetUInt32();
- uint32 creature_id = temp.creature_id;
- temp.event_type = fields[2].GetUInt16();
- temp.event_inverse_phase_mask = fields[3].GetUInt32();
- temp.event_chance = fields[4].GetUInt8();
- temp.event_flags = fields[5].GetUInt8();
- temp.event_param1 = fields[6].GetUInt32();
- temp.event_param2 = fields[7].GetUInt32();
- temp.event_param3 = fields[8].GetUInt32();
- temp.event_param4 = fields[9].GetUInt32();
-
- //Creature does not exist in database
- if (!GetCreatureTemplateStore(temp.creature_id))
- {
- error_db_log("TSCR: Event %u has script for non-existing creature.", i);
- continue;
- }
-
- //Report any errors in event
- if (temp.event_type >= EVENT_T_END)
- {
- error_db_log("TSCR: Event %u has incorrect event type. Maybe DB requires updated version of SD2.", i);
- continue;
- }
-
- //No chance of this event occuring
- if (temp.event_chance == 0)
- error_db_log("TSCR: Event %u has 0 percent chance. Event will never trigger!", i);
-
- //Chance above 100, force it to be 100
- if (temp.event_chance > 100)
- {
- error_db_log("TSCR: Creature %u are using event %u with more than 100 percent chance. Adjusting to 100 percent.", temp.creature_id, i);
- temp.event_chance = 100;
- }
-
- //Individual event checks
- switch (temp.event_type)
- {
- case EVENT_T_HP:
- case EVENT_T_MANA:
- case EVENT_T_TARGET_HP:
- {
- if (temp.event_param2 > 100)
- error_db_log("TSCR: Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i);
-
- if (temp.event_param1 <= temp.event_param2)
- error_db_log("TSCR: Creature %u are using percentage event(%u) with param1 <= param2 (MaxPercent <= MinPercent). Event will never trigger! ", temp.creature_id, i);
-
- if (temp.event_flags & EFLAG_REPEATABLE && !temp.event_param3 && !temp.event_param4)
- {
- error_db_log("TSCR: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i);
- temp.event_flags &= ~EFLAG_REPEATABLE;
- }
- }
- break;
-
- case EVENT_T_SPELLHIT:
- {
- if (temp.event_param1)
- {
- SpellEntry const* pSpell = GetSpellStore()->LookupEntry(temp.event_param1);
- if (!pSpell)
- {
- error_db_log("TSCR: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.event_param1, i);
- continue;
- }
-
- if (temp.event_param2_s != -1 && temp.event_param2 != pSpell->SchoolMask)
- error_db_log("TSCR: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.event_param1, i);
- }
-
- //TODO: fix this system with SPELL_SCHOOL_MASK. Current complicate things, using int32(-1) instead of just 0
- //SPELL_SCHOOL_MASK_NONE = 0 and does not exist, thus it can not ever trigger or be used in SpellHit()
- if (temp.event_param2_s != -1 && temp.event_param2_s > SPELL_SCHOOL_MASK_ALL)
- error_db_log("TSCR: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.event_param2, i);
-
- if (temp.event_param4 < temp.event_param3)
- error_db_log("TSCR: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- }
- break;
-
- case EVENT_T_OOC_LOS:
- {
- if (temp.event_param2 > VISIBLE_RANGE || temp.event_param2 <= 0)
- {
- error_db_log("SD2: Creature %u are using event(%u), but param2 (MaxAllowedRange=%u) are not within allowed range.", temp.creature_id, i, temp.event_param2);
- temp.event_param2 = VISIBLE_RANGE;
- }
-
- if (temp.event_param3 == 0 && temp.event_param4 == 0 && temp.event_flags & EFLAG_REPEATABLE)
- {
- error_db_log("SD2: Creature %u are using event(%u) with EFLAG_REPEATABLE, but param3(RepeatMin) and param4(RepeatMax) are 0. Repeatable disabled.", temp.creature_id, i);
- temp.event_flags &= ~EFLAG_REPEATABLE;
- }
-
- if (temp.event_param4 < temp.event_param3)
- error_db_log("SD2: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- }
- break;
-
- case EVENT_T_RANGE:
- case EVENT_T_FRIENDLY_HP:
- case EVENT_T_FRIENDLY_IS_CC:
- {
- if (temp.event_param4 < temp.event_param3)
- error_db_log("SD2: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- }
- break;
-
- case EVENT_T_FRIENDLY_MISSING_BUFF:
- {
- if (!GetSpellStore()->LookupEntry(temp.event_param1))
- {
- error_db_log("SD2: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.event_param1, i);
- continue;
- }
-
- if (temp.event_param4 < temp.event_param3)
- error_db_log("TSCR: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- }
- break;
-
- case EVENT_T_TIMER:
- case EVENT_T_TIMER_OOC:
- {
- if (temp.event_param2 < temp.event_param1)
- error_db_log("TSCR: 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)
- error_db_log("TSCR: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- }
- break;
-
- case EVENT_T_KILL:
- case EVENT_T_TARGET_CASTING:
- {
- if (temp.event_param2 < temp.event_param1)
- error_db_log("TSCR: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- }
- break;
-
- case EVENT_T_SUMMONED_UNIT:
- {
- if (!GetCreatureTemplateStore(temp.event_param1))
- {
- error_db_log("SD2: Creature %u has non-existant creature entry (%u) defined in event %u.", temp.creature_id, temp.event_param1, i);
- continue;
- }
- }
- break;
-
- case EVENT_T_AGGRO:
- case EVENT_T_DEATH:
- case EVENT_T_EVADE:
- case EVENT_T_SPAWNED:
- case EVENT_T_REACHED_HOME:
- {
- if (temp.event_flags & EFLAG_REPEATABLE)
- {
- error_db_log("TSCR: Creature %u has EFLAG_REPEATABLE set. Event can never be repeatable. Removing flag for event %u.", temp.creature_id, i);
- temp.event_flags &= ~EFLAG_REPEATABLE;
- }
- }
- break;
-
- case EVENT_T_RECEIVE_EMOTE:
- {
- //no good way to check for valid textEmote (enum TextEmotes)
-
- switch(temp.event_param2)
- {
- case CONDITION_AURA:
- if (!GetSpellStore()->LookupEntry(temp.event_param3))
- {
- error_db_log("SD2: Creature %u using event %u: param3 (CondValue1: %u) are not valid.",temp.creature_id, i, temp.event_param3);
- continue;
- }
- break;
- case CONDITION_TEAM:
- if (temp.event_param3 != HORDE || temp.event_param3 != ALLIANCE)
- {
- error_db_log("SD2: Creature %u using event %u: param3 (CondValue1: %u) are not valid.",temp.creature_id, i, temp.event_param3);
- continue;
- }
- break;
- case CONDITION_QUESTREWARDED:
- case CONDITION_QUESTTAKEN:
- if (!GetQuestTemplateStore(temp.event_param3))
- {
- error_db_log("SD2: Creature %u using event %u: param3 (CondValue1: %u) are not valid.",temp.creature_id, i, temp.event_param3);
- continue;
- }
- break;
- case CONDITION_ACTIVE_EVENT:
- if (temp.event_param3 !=
- (HOLIDAY_FIREWORKS_SPECTACULAR | HOLIDAY_FEAST_OF_WINTER_VEIL | HOLIDAY_NOBLEGARDEN |
- HOLIDAY_CHILDRENS_WEEK | HOLIDAY_CALL_TO_ARMS_AV | HOLIDAY_CALL_TO_ARMS_WG |
- HOLIDAY_CALL_TO_ARMS_AB | HOLIDAY_FISHING_EXTRAVAGANZA | HOLIDAY_HARVEST_FESTIVAL |
- HOLIDAY_HALLOWS_END | HOLIDAY_LUNAR_FESTIVAL | HOLIDAY_LOVE_IS_IN_THE_AIR |
- HOLIDAY_FIRE_FESTIVAL | HOLIDAY_CALL_TO_ARMS_ES | HOLIDAY_BREWFEST |
- HOLIDAY_DARKMOON_FAIRE_ELWYNN | HOLIDAY_DARKMOON_FAIRE_THUNDER | HOLIDAY_DARKMOON_FAIRE_SHATTRATH |
- HOLIDAY_CALL_TO_ARMS_SA | HOLIDAY_WOTLK_LAUNCH))
- {
- error_db_log("SD2: Creature %u using event %u: param3 (CondValue1: %u) are not valid.",temp.creature_id, i, temp.event_param3);
- continue;
- }
- break;
- case CONDITION_REPUTATION_RANK:
- if (!temp.event_param3)
- {
- error_db_log("SD2: Creature %u using event %u: param3 (CondValue1: %u) are missing.",temp.creature_id, i, temp.event_param3);
- continue;
- }
- if (temp.event_param4 > REP_EXALTED)
- {
- error_db_log("SD2: Creature %u using event %u: param4 (CondValue2: %u) are not valid.",temp.creature_id, i, temp.event_param4);
- continue;
- }
- break;
- case CONDITION_ITEM:
- case CONDITION_ITEM_EQUIPPED:
- case CONDITION_SKILL:
- if (!temp.event_param3)
- {
- error_db_log("SD2: Creature %u using event %u: param3 (CondValue1: %u) are missing.",temp.creature_id, i, temp.event_param3);
- continue;
- }
- if (!temp.event_param4)
- {
- error_db_log("SD2: Creature %u using event %u: param4 (CondValue2: %u) are missing.",temp.creature_id, i, temp.event_param4);
- continue;
- }
- break;
- case CONDITION_ZONEID:
- if (!temp.event_param3)
- {
- error_db_log("SD2: Creature %u using event %u: param3 (CondValue1: %u) are missing.",temp.creature_id, i, temp.event_param3);
- continue;
- }
- break;
- case CONDITION_NONE:
- break;
- default:
- {
- error_db_log("SD2: Creature %u using event %u: param2 (Condition: %u) are not valid/not implemented for script.",temp.creature_id, i, temp.event_param3);
- continue;
- }
- }
-
- if (!(temp.event_flags & EFLAG_REPEATABLE))
- {
- error_db_log("SD2: 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_QUEST_ACCEPT:
- case EVENT_T_QUEST_COMPLETE:
- {
- error_db_log("SD2: Creature %u using not implemented event (%u) in event %u.", temp.creature_id, temp.event_id, i);
- continue;
- }
- break;
- }
-
- for (uint32 j = 0; j < MAX_ACTIONS; j++)
- {
- temp.action[j].type = fields[10+(j*4)].GetUInt16();
- temp.action[j].param1 = fields[11+(j*4)].GetUInt32();
- temp.action[j].param2 = fields[12+(j*4)].GetUInt32();
- temp.action[j].param3 = fields[13+(j*4)].GetUInt32();
-
- //Report any errors in actions
- switch (temp.action[j].type)
- {
- case ACTION_T_TEXT:
- {
- if (temp.action[j].param1_s < 0)
- {
- if (TextMap.find(temp.action[j].param1_s) == TextMap.end())
- error_db_log("TSCR: Event %u Action %u param1 refrences non-existing entry in texts table.", i, j+1);
- }
- if (temp.action[j].param2_s < 0)
- {
- if (TextMap.find(temp.action[j].param2_s) == TextMap.end())
- error_db_log("TSCR: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1);
-
- if (!temp.action[j].param1_s)
- error_db_log("TSCR: Event %u Action %u has param2, but param1 is not set. Required for randomized text.", i, j+1);
- }
- if (temp.action[j].param3_s < 0)
- {
- if (TextMap.find(temp.action[j].param3_s) == TextMap.end())
- error_db_log("TSCR: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1);
-
- if (!temp.action[j].param1_s || !temp.action[j].param2_s)
- error_db_log("TSCR: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1);
- }
- }
- break;
- case ACTION_T_SET_FACTION:
- if (temp.action[j].param1 !=0 && !GetFactionStore()->LookupEntry(temp.action[j].param1))
- {
- error_db_log("TSCR: Event %u Action %u uses non-existant FactionId %u.", i, j+1, temp.action[j].param1);
- temp.action[j].param1 = 0;
- }
- break;
- case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
- if (temp.action[j].param1 !=0 || temp.action[j].param2 !=0)
- {
- if (temp.action[j].param1 && !GetCreatureTemplateStore(temp.action[j].param1))
- {
- error_db_log("TSCR: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, temp.action[j].param1);
- temp.action[j].param1 = 0;
- }
-
- if (temp.action[j].param2 && !GetCreatureDisplayStore()->LookupEntry(temp.action[j].param2))
- {
- error_db_log("TSCR: Event %u Action %u uses non-existant ModelId %u.", i, j+1, temp.action[j].param2);
- temp.action[j].param2 = 0;
- }
- }
- break;
- case ACTION_T_SOUND:
- if (!GetSoundEntriesStore()->LookupEntry(temp.action[j].param1))
- error_db_log("TSCR: Event %u Action %u uses non-existant SoundID %u.", i, j+1, temp.action[j].param1);
- break;
-
- /*case ACTION_T_RANDOM_SOUND:
- {
- if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param1))
- error_db_log("TSCR: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, temp.action[j].param1);
- if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param2))
- error_db_log("TSCR: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, temp.action[j].param2);
- if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param3))
- error_db_log("TSCR: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, temp.action[j].param3);
- }
- break;*/
-
- case ACTION_T_CAST:
- {
- const SpellEntry *spell = GetSpellStore()->LookupEntry(temp.action[j].param1);
- if (!spell)
- error_db_log("SD2: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param1);
- else
- {
- if (spell->RecoveryTime > 0 && temp.event_flags & EFLAG_REPEATABLE)
- {
- //output as debug for now, also because there's no general rule all spells have RecoveryTime
- if (temp.event_param3 < spell->RecoveryTime)
- debug_log("TSCR: 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)
- error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1);
- }
- break;
- case ACTION_T_REMOVEAURASFROMSPELL:
- {
- if (!GetSpellStore()->LookupEntry(temp.action[j].param2))
- error_db_log("TSCR: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
-
- if (temp.action[j].param1 >= TARGET_T_END)
- error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1);
- }
- break;
- case ACTION_T_QUEST_EVENT:
- {
- if (Quest const* qid = GetQuestTemplateStore(temp.action[j].param1))
- {
- if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
- error_db_log("TSCR: 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
- error_db_log("TSCR: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
-
- if (temp.action[j].param2 >= TARGET_T_END)
- error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1);
- }
- break;
- case ACTION_T_QUEST_EVENT_ALL:
- {
- if (Quest const* qid = GetQuestTemplateStore(temp.action[j].param1))
- {
- if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT))
- error_db_log("TSCR: 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
- error_db_log("TSCR: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
- }
- break;
- case ACTION_T_CASTCREATUREGO:
- {
- if (!GetCreatureTemplateStore(temp.action[j].param1))
- error_db_log("TSCR: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
-
- if (!GetSpellStore()->LookupEntry(temp.action[j].param2))
- error_db_log("TSCR: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
-
- if (temp.action[j].param3 >= TARGET_T_END)
- error_db_log("SD2: Event %u Action %u uses incorrect Target type", i, j+1);
- }
- break;
- case ACTION_T_CASTCREATUREGO_ALL:
- {
- if (!GetQuestTemplateStore(temp.action[j].param1))
- error_db_log("TSCR: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
-
- if (!GetSpellStore()->LookupEntry(temp.action[j].param2))
- error_db_log("TSCR: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
- }
- break;
-
- //2nd param target
- case ACTION_T_SUMMON_ID:
- {
- if (!GetCreatureTemplateStore(temp.action[j].param1))
- error_db_log("TSCR: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
-
- if (EventAI_Summon_Map.find(temp.action[j].param3) == EventAI_Summon_Map.end())
- error_db_log("TSCR: Event %u Action %u summons missing EventAI_Summon %u", i, j+1, temp.action[j].param3);
-
- if (temp.action[j].param2 >= TARGET_T_END)
- error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1);
- }
- break;
- case ACTION_T_KILLED_MONSTER:
- {
- if (!GetCreatureTemplateStore(temp.action[j].param1))
- error_db_log("TSCR: 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)
- error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1);
- }
- break;
- case ACTION_T_SUMMON:
- {
- if (!GetCreatureTemplateStore(temp.action[j].param1))
- error_db_log("TSCR: 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)
- error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1);
- }
- break;
- case ACTION_T_THREAT_SINGLE_PCT:
- case ACTION_T_SET_UNIT_FLAG:
- case ACTION_T_REMOVE_UNIT_FLAG:
- if (temp.action[j].param2 >= TARGET_T_END)
- error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
-
- //3rd param target
- case ACTION_T_SET_UNIT_FIELD:
- if (temp.action[j].param1 < OBJECT_END || temp.action[j].param1 >= UNIT_END)
- error_db_log("TSCR: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1);
- if (temp.action[j].param3 >= TARGET_T_END)
- error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
-
- case ACTION_T_SET_PHASE:
- if (temp.action[j].param1 > 31)
- error_db_log("TSCR: Event %u Action %u attempts to set phase > 31. Phase mask cannot be used past phase 31.", i, j+1);
- break;
-
- case ACTION_T_INC_PHASE:
- if (!temp.action[j].param1)
- error_db_log("SD2: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1);
- break;
-
- case ACTION_T_SET_INST_DATA:
- {
- if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC))
- error_db_log("TSCR: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1);
-
- if (temp.action[j].param2 > SPECIAL)
- error_db_log("TSCR: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1);
- }
- break;
- case ACTION_T_SET_INST_DATA64:
- {
- if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC))
- error_db_log("TSCR: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1);
-
- if (temp.action[j].param2 >= TARGET_T_END)
- error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1);
- }
- break;
- case ACTION_T_UPDATE_TEMPLATE:
- {
- if (!GetCreatureTemplateStore(temp.action[j].param1))
- error_db_log("TSCR: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
- }
- break;
- case ACTION_T_RANDOM_SAY:
- case ACTION_T_RANDOM_YELL:
- case ACTION_T_RANDOM_TEXTEMOTE:
- error_db_log("TSCR: Event %u Action %u currently unused ACTION type. Did you forget to update database?", i, j+1);
- break;
-
- default:
- if (temp.action[j].type >= ACTION_T_END)
- error_db_log("TSCR: Event %u Action %u has incorrect action type. Maybe DB requires updated version of SD2.", i, j+1);
- break;
- }
- }
-
- //Add to list
- EventAI_Event_Map[creature_id].push_back(temp);
-
- ++Count;
- } while (result->NextRow());
-
- delete result;
-
- outstring_log("");
- outstring_log(">> Loaded %u EventAI scripts", Count);
- }else
- {
- barGoLink bar(1);
- bar.step();
- outstring_log("");
- outstring_log(">> Loaded 0 EventAI scripts. DB table `eventai_scripts` is empty.");
- }
-
//Free database thread and resources
TScriptDB.HaltDelayThread();
@@ -1569,25 +940,6 @@ void ScriptsInit()
}
else outstring_log("TSCR: Using configuration file %s",_TRINITY_SCRIPT_CONFIG);
- EAI_ErrorLevel = TScriptConfig.GetIntDefault("EAIErrorLevel", 1);
-
- switch (EAI_ErrorLevel)
- {
- case 0:
- outstring_log("TSCR: EventAI Error Reporting level set to 0 (Startup Errors only)");
- break;
- case 1:
- outstring_log("TSCR: EventAI Error Reporting level set to 1 (Startup errors and Runtime event errors)");
- break;
- case 2:
- outstring_log("TSCR: EventAI Error Reporting level set to 2 (Startup errors, Runtime event errors, and Creation errors)");
- break;
- default:
- outstring_log("TSCR: Unknown EventAI Error Reporting level. Defaulting to 1 (Startup errors and Runtime event errors)");
- EAI_ErrorLevel = 1;
- break;
- }
-
outstring_log("");
//Load database (must be called after TScriptConfig.SetSource). In case it failed, no need to even try load.
@@ -1615,7 +967,6 @@ void ScriptsInit()
AddSC_boss_ysondre();
// -- Creature --
- AddSC_mob_event();
AddSC_generic_creature();
// -- Custom --
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp
index 59019348043..2c0ab471bda 100644
--- a/src/bindings/scripts/include/sc_creature.cpp
+++ b/src/bindings/scripts/include/sc_creature.cpp
@@ -519,11 +519,11 @@ bool ScriptedAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered)
return false;
//Silenced so we can't cast
- if (!Triggered && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
+ if (!Triggered && me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
return false;
//Check for power
- if (!Triggered && m_creature->GetPower((Powers)Spell->powerType) < Spell->manaCost)
+ if (!Triggered && me->GetPower((Powers)Spell->powerType) < Spell->manaCost)
return false;
SpellRangeEntry const *TempRange = NULL;
@@ -535,7 +535,8 @@ bool ScriptedAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered)
return false;
//Unit is out of range of this spell
- if (m_creature->GetDistance(Target) > m_creature->GetSpellMaxRangeForTarget(Target, TempRange) || m_creature->GetDistance(Target) < m_creature->GetSpellMinRangeForTarget(Target, TempRange))
+ if (me->GetDistance(Target) > me->GetSpellMaxRangeForTarget(Target, TempRange)
+ || me->GetDistance(Target) < me->GetSpellMinRangeForTarget(Target, TempRange))
return false;
return true;
@@ -636,39 +637,6 @@ void FillSpellSummary()
}
}
-void ScriptedAI::DoZoneInCombat(Unit* pUnit)
-{
- if (!pUnit)
- pUnit = m_creature;
-
- Map *map = pUnit->GetMap();
-
- if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
- {
- error_log("SD2: DoZoneInCombat call for map that isn't an instance (pUnit entry = %d)", pUnit->GetTypeId() == TYPEID_UNIT ? ((Creature*)pUnit)->GetEntry() : 0);
- return;
- }
-
- if (!pUnit->CanHaveThreatList() || pUnit->getThreatManager().isThreatListEmpty())
- {
- error_log("SD2: DoZoneInCombat called for creature that either cannot have threat list or has empty threat list (pUnit entry = %d)", pUnit->GetTypeId() == TYPEID_UNIT ? ((Creature*)pUnit)->GetEntry() : 0);
-
- return;
- }
-
- Map::PlayerList const &PlayerList = map->GetPlayers();
- for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
- {
- if (Player* i_pl = i->getSource())
- if (i_pl->isAlive())
- {
- pUnit->SetInCombatWith(i_pl);
- i_pl->SetInCombatWith(pUnit);
- pUnit->AddThreat(i_pl, 0.0f);
- }
- }
-}
-
void ScriptedAI::DoResetThreat()
{
if (!m_creature->CanHaveThreatList() || m_creature->getThreatManager().isThreatListEmpty())
diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h
index 5cb9b2c9f81..61a82bb6dd5 100644
--- a/src/bindings/scripts/include/sc_creature.h
+++ b/src/bindings/scripts/include/sc_creature.h
@@ -148,9 +148,6 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
//Plays a sound to all nearby players
void DoPlaySoundToSet(Unit* unit, uint32 sound);
- //Places the entire map into combat with creature
- void DoZoneInCombat(Unit* pUnit = 0);
-
//Drops all threat to 0%. Does not remove players from the threat list
void DoResetThreat();
diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp
index ed0e8d2a0a7..5f656a45da8 100644
--- a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp
+++ b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp
@@ -1,1525 +1 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* ScriptData
-SDName: Mob_Event_AI
-SD%Complete: 90
-SDComment: Database Event AI
-SDCategory: Creatures
-EndScriptData */
-
#include "precompiled.h"
-#include "mob_event_ai.h"
-#include "ObjectMgr.h"
-#include "GameEventMgr.h"
-
-#define EVENT_UPDATE_TIME 500
-#define SPELL_RUN_AWAY 8225
-
-struct EventHolder
-{
- EventHolder(EventAI_Event p) : Event(p), Time(0), Enabled(true){}
-
- EventAI_Event Event;
- uint32 Time;
- bool Enabled;
-};
-
-struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI
-{
- Mob_EventAI(Creature *c, std::list<EventHolder> pEventList) : ScriptedAI(c)
- {
- EventList = pEventList;
- bEmptyList = pEventList.empty();
- Phase = 0;
- CombatMovementEnabled = true;
- MeleeEnabled = true;
- AttackDistance = 0;
- AttackAngle = 0.0f;
-
- //Handle Spawned Events
- if (!bEmptyList)
- {
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_SPAWNED)
- ProcessEvent(*i);
- }
- }
- }
-
- ~Mob_EventAI()
- {
- EventList.clear();
- }
-
- //Variables used by EventAI for handling events
- std::list<EventHolder> EventList; //Holder for events (stores enabled, time, and eventid)
- uint32 EventUpdateTime; //Time between event updates
- uint32 EventDiff; //Time between the last event call
- bool bEmptyList;
-
- //Variables used by Events themselves
- uint8 Phase; //Current phase, max 32 phases
- bool CombatMovementEnabled; //If we allow targeted movment gen (movement twoards top threat)
- bool MeleeEnabled; //If we allow melee auto attack
- uint32 AttackDistance; //Distance to attack from
- float AttackAngle; //Angle of attack
- uint32 TimetoFleeLeft; //For fleeing
-
- bool ProcessEvent(EventHolder& pHolder, Unit* pActionInvoker = NULL)
- {
- if (!pHolder.Enabled || pHolder.Time)
- return false;
-
- //Check the inverse phase mask (event doesn't trigger if current phase bit is set in mask)
- if (pHolder.Event.event_inverse_phase_mask & (1 << Phase))
- return false;
-
- //Store random here so that all random actions match up
- uint32 rnd = rand();
-
- //Return if chance for event is not met
- if (pHolder.Event.event_chance <= rnd % 100)
- return false;
-
- union
- {
- uint32 param1;
- int32 param1_s;
- };
-
- union
- {
- uint32 param2;
- int32 param2_s;
- };
-
- union
- {
- uint32 param3;
- int32 param3_s;
- };
-
- union
- {
- uint32 param4;
- int32 param4_s;
- };
-
- param1 = pHolder.Event.event_param1;
- param2 = pHolder.Event.event_param2;
- param3 = pHolder.Event.event_param3;
- param4 = pHolder.Event.event_param4;
-
- //Check event conditions based on the event type, also reset events
- switch (pHolder.Event.event_type)
- {
- case EVENT_T_TIMER:
- {
- if (!InCombat)
- return false;
-
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_TIMER_OOC:
- {
- if (InCombat)
- return false;
-
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_HP:
- {
- if (!InCombat || !m_creature->GetMaxHealth())
- return false;
-
- uint32 perc = (m_creature->GetHealth()*100) / m_creature->GetMaxHealth();
-
- if (perc > param1 || perc < param2)
- return false;
-
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_MANA:
- {
- if (!InCombat || !m_creature->GetMaxPower(POWER_MANA))
- return false;
-
- uint32 perc = (m_creature->GetPower(POWER_MANA)*100) / m_creature->GetMaxPower(POWER_MANA);
-
- if (perc > param1 || perc < param2)
- return false;
-
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_AGGRO:
- {
- }
- break;
- case EVENT_T_KILL:
- {
- //Repeat Timers
- if (param1 == param2)
- {
- pHolder.Time = param1;
-
- }else if (param2 > param1)
- pHolder.Time = urand(param1, param2);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- case EVENT_T_DEATH:
- {
- }
- break;
- case EVENT_T_EVADE:
- {
- }
- break;
- case EVENT_T_SPELLHIT:
- {
- //Spell hit is special case, param1 and param2 handled within EventAI::SpellHit
-
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_RANGE:
- {
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_OOC_LOS:
- {
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_SPAWNED:
- {
- }
- break;
- case EVENT_T_TARGET_HP:
- {
- if (!InCombat || !m_creature->getVictim() || !m_creature->getVictim()->GetMaxHealth())
- return false;
-
- uint32 perc = (m_creature->getVictim()->GetHealth()*100) / m_creature->getVictim()->GetMaxHealth();
-
- if (perc > param1 || perc < param2)
- return false;
-
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_TARGET_CASTING:
- {
- if (!InCombat || !m_creature->getVictim() || !m_creature->getVictim()->IsNonMeleeSpellCasted(false, false, true))
- return false;
-
- //Repeat Timers
- if (param1 == param2)
- {
- pHolder.Time = param1;
-
- }else if (param2 > param1)
- pHolder.Time = urand(param1, param2);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_FRIENDLY_HP:
- {
- if (!InCombat)
- return false;
-
- Unit* pUnit = DoSelectLowestHpFriendly(param2, param1);
-
- if (!pUnit)
- return false;
-
- pActionInvoker = pUnit;
-
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_FRIENDLY_IS_CC:
- {
- if (!InCombat)
- return false;
-
- std::list<Creature*> pList = DoFindFriendlyCC(param2);
-
- //List is empty
- if (pList.empty())
- return false;
-
- //We don't really care about the whole list, just return first available
- pActionInvoker = *(pList.begin());
-
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_FRIENDLY_MISSING_BUFF:
- {
- std::list<Creature*> pList = DoFindFriendlyMissingBuff(param2, param1);
-
- //List is empty
- if (pList.empty())
- return false;
-
- //We don't really care about the whole list, just return first available
- pActionInvoker = *(pList.begin());
-
- //Repeat Timers
- if (param3 == param4)
- {
- pHolder.Time = param3;
-
- }else if (param4 > param3)
- pHolder.Time = urand(param3, param4);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_SUMMONED_UNIT:
- {
- //Prevent event from occuring on no unit or non creatures
- if (!pActionInvoker || pActionInvoker->GetTypeId()!=TYPEID_UNIT)
- return false;
-
- //Creature id doesn't match up
- if (param1 && ((Creature*)pActionInvoker)->GetEntry() != param1)
- return false;
-
- //Repeat Timers
- if (param2 == param3)
- {
- pHolder.Time = param2;
-
- }else if (param3 > param2)
- pHolder.Time = urand(param2, param3);
- else
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- pHolder.Enabled = false;
- }
- }
- break;
- case EVENT_T_REACHED_HOME:
- {
- }
- break;
- case EVENT_T_RECEIVE_EMOTE:
- {
- }
- break;
- default:
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature->GetEntry(), pHolder.Event.event_id, pHolder.Event.event_type);
- break;
- }
-
- //Disable non-repeatable events
- if (!(pHolder.Event.event_flags & EFLAG_REPEATABLE))
- pHolder.Enabled = false;
-
- //Process actions
- for (uint32 j = 0; j < MAX_ACTIONS; j++)
- ProcessAction(pHolder.Event.action[j].type, pHolder.Event.action[j].param1, pHolder.Event.action[j].param2, pHolder.Event.action[j].param3, rnd, pHolder.Event.event_id, pActionInvoker);
-
- return true;
- }
-
- inline uint32 GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3)
- {
- switch (rnd % 3)
- {
- case 0:
- return param1;
- break;
- case 1:
- return param2;
- break;
- case 2:
- return param3;
- break;
- }
- return 0;
- }
-
- inline Unit* GetTargetByType(uint32 Target, Unit* pActionInvoker)
- {
- switch (Target)
- {
- case TARGET_T_SELF:
- return m_creature;
- break;
- case TARGET_T_HOSTILE:
- return m_creature->getVictim();
- break;
- case TARGET_T_HOSTILE_SECOND_AGGRO:
- return SelectUnit(SELECT_TARGET_TOPAGGRO,1);
- break;
- case TARGET_T_HOSTILE_LAST_AGGRO:
- return SelectUnit(SELECT_TARGET_BOTTOMAGGRO,0);
- break;
- case TARGET_T_HOSTILE_RANDOM:
- return SelectUnit(SELECT_TARGET_RANDOM,0);
- break;
- case TARGET_T_HOSTILE_RANDOM_NOT_TOP:
- return SelectUnit(SELECT_TARGET_RANDOM,1);
- break;
- case TARGET_T_ACTION_INVOKER:
- return pActionInvoker;
- break;
- default:
- return NULL;
- break;
- };
- }
-
- void ProcessAction(uint16 type, uint32 param1, uint32 param2, uint32 param3, uint32 rnd, uint32 EventId, Unit* pActionInvoker)
- {
- switch (type)
- {
- case ACTION_T_TEXT:
- {
- if (!param1)
- return;
-
- uint32 temp = 0;
-
- if (param2 && param3)
- {
- switch( rand()%3 )
- {
- case 0: temp = param1; break;
- case 2: temp = param2; break;
- case 3: temp = param3; break;
- }
- }else if ( param2 && urand(0,1) )
- {
- temp = param2;
- }else
- {
- temp = param1;
- }
-
- if (temp)
- {
- Unit* target = NULL;
- Unit* owner = NULL;
-
- if (pActionInvoker)
- {
- if (pActionInvoker->GetTypeId() == TYPEID_PLAYER)
- target = pActionInvoker;
- else if (owner = pActionInvoker->GetOwner())
- {
- if (owner->GetTypeId() == TYPEID_PLAYER)
- target = owner;
- }
- }
- else if (target = m_creature->getVictim())
- {
- if (target->GetTypeId() != TYPEID_PLAYER)
- {
- if (owner = target->GetOwner())
- {
- if (owner->GetTypeId() == TYPEID_PLAYER)
- target = owner;
- }
- }
- }
-
- DoScriptText(temp, m_creature, target);
- }
- }
- break;
- case ACTION_T_SET_FACTION:
- {
- if (param1)
- m_creature->setFaction(param1);
- else
- {
- if (CreatureInfo const* ci = GetCreatureTemplateStore(m_creature->GetEntry()))
- {
- //if no id provided, assume reset and then use default
- if (m_creature->getFaction() != ci->faction_A)
- m_creature->setFaction(ci->faction_A);
- }
- }
- }
- break;
- case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
- {
- if (param1 || param2)
- {
- //set model based on entry from creature_template
- if (param1)
- {
- if (CreatureInfo const* ci = GetCreatureTemplateStore(param1))
- {
- //use default display
- if (ci->Modelid1)
- m_creature->SetDisplayId(ci->Modelid1);
- }
- }
- //if no param1, then use value from param2 (modelId)
- else
- m_creature->SetDisplayId(param2);
- }
- else
- m_creature->DeMorph();
- }
- break;
- case ACTION_T_SOUND:
- DoPlaySoundToSet(m_creature, param1);
- break;
- case ACTION_T_EMOTE:
- m_creature->HandleEmoteCommand(param1);
- break;
- case ACTION_T_RANDOM_SOUND:
- {
- uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
-
- if (temp != 0xffffffff)
- DoPlaySoundToSet(m_creature, temp);
- }
- break;
- case ACTION_T_RANDOM_EMOTE:
- {
- uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
-
- if (temp != 0xffffffff)
- m_creature->HandleEmoteCommand(temp);
- }
- break;
- case ACTION_T_CAST:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
- Unit* caster = m_creature;
-
- if (!target)
- return;
-
- //Cast is always triggered if target is forced to cast on self
- if (param3 & CAST_FORCE_TARGET_SELF)
- {
- param3 |= CAST_TRIGGERED;
- caster = target;
- }
-
- //Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
- bool canCast = !(caster->IsNonMeleeSpellCasted(false) && (param3 & CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS));
-
- // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
- if(param3 & CAST_AURA_NOT_PRESENT)
- {
- if(target->HasAura(param1))
- return;
- }
-
- if (canCast)
- {
- const SpellEntry* tSpell = GetSpellStore()->LookupEntry(param1);
-
- //Verify that spell exists
- if (tSpell)
- {
- //Check if cannot cast spell
- if (!(param3 & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) &&
- !CanCast(target, tSpell, (param3 & CAST_TRIGGERED)))
- {
- //Melee current victim if flag not set
- if (!(param3 & CAST_NO_MELEE_IF_OOM))
- {
- if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE)
- {
- AttackDistance = 0;
- AttackAngle = 0;
-
- m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle);
- }
- }
-
- }
- else
- {
- //Interrupt any previous spell
- if (caster->IsNonMeleeSpellCasted(false) && param3 & CAST_INTURRUPT_PREVIOUS)
- caster->InterruptNonMeleeSpells(false);
-
- caster->CastSpell(target, param1, (param3 & CAST_TRIGGERED));
- }
-
- }else if (EAI_ErrorLevel > 0)
- error_db_log("SD2: EventAI event %d creature %d attempt to cast spell that doesn't exist %d", EventId, m_creature->GetEntry(), param1);
- }
- }
- break;
- case ACTION_T_SUMMON:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
-
- Creature* pCreature = NULL;
-
- if (param3)
- pCreature = DoSpawnCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, param3);
- else pCreature = pCreature = DoSpawnCreature(param1, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
-
- if (!pCreature)
- {
- if (EAI_ErrorLevel > 0)
- error_db_log( "SD2: EventAI failed to spawn creature %u. Spawn event %d is on creature %d", param1, EventId, m_creature->GetEntry());
- }
- else if (param2 != TARGET_T_SELF && target)
- pCreature->AI()->AttackStart(target);
- }
- break;
- case ACTION_T_THREAT_SINGLE_PCT:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
-
- if (target)
- DoModifyThreatPercent(target, param1);
- }
- break;
- case ACTION_T_THREAT_ALL_PCT:
- {
- Unit* Temp = NULL;
-
- std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
- for (; i != m_creature->getThreatManager().getThreatList().end(); ++i)
- {
- Temp = Unit::GetUnit((*m_creature),(*i)->getUnitGuid());
- if (Temp)
- DoModifyThreatPercent(Temp, param1);
- }
- }
- break;
- case ACTION_T_QUEST_EVENT:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
-
- if (target && target->GetTypeId() == TYPEID_PLAYER)
- ((Player*)target)->AreaExploredOrEventHappens(param1);
- }
- break;
- case ACTION_T_CASTCREATUREGO:
- {
- Unit* target = GetTargetByType(param3, pActionInvoker);
-
- if (target && target->GetTypeId() == TYPEID_PLAYER)
- ((Player*)target)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2);
- }
- break;
- case ACTION_T_SET_UNIT_FIELD:
- {
- Unit* target = GetTargetByType(param3, pActionInvoker);
-
- if (param1 < OBJECT_END || param1 >= UNIT_END)
- return;
-
- if (target)
- target->SetUInt32Value(param1, param2);
- }
- break;
- case ACTION_T_SET_UNIT_FLAG:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
-
- if (target)
- target->SetFlag(UNIT_FIELD_FLAGS, param1);
- }
- break;
- case ACTION_T_REMOVE_UNIT_FLAG:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
-
- if (target)
- target->RemoveFlag(UNIT_FIELD_FLAGS, param1);
- }
- break;
- case ACTION_T_AUTO_ATTACK:
- {
- if (param1)
- MeleeEnabled = true;
- else MeleeEnabled = false;
- }
- break;
- case ACTION_T_COMBAT_MOVEMENT:
- {
- CombatMovementEnabled = param1;
-
- //Allow movement (create new targeted movement gen only if idle)
- if (CombatMovementEnabled)
- {
- m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle);
- }
- else
- {
- m_creature->GetMotionMaster()->MoveIdle();
- }
- }
- break;
- case ACTION_T_SET_PHASE:
- {
- Phase = param1;
- }
- break;
- case ACTION_T_INC_PHASE:
- {
- Phase += param1;
-
- if (Phase > 31)
- if (EAI_ErrorLevel > 0)
- error_db_log( "SD2: Event %d incremented Phase above 31. Phase mask cannot be used with phases past 31. CreatureEntry = %d", EventId, m_creature->GetEntry());
- }
- break;
- case ACTION_T_EVADE:
- {
- EnterEvadeMode();
- }
- break;
- case ACTION_T_FLEE:
- {
- if(m_creature->HasAuraType(SPELL_AURA_PREVENTS_FLEEING))
- break;
- TimetoFleeLeft = 8000;
- m_creature->DoFleeToGetAssistance();
- IsFleeing = true;
- }
- break;
- case ACTION_T_QUEST_EVENT_ALL:
- {
- Unit* Temp = NULL;
- if( pActionInvoker && pActionInvoker->GetTypeId() == TYPEID_PLAYER )
- {
- Temp = Unit::GetUnit((*m_creature),pActionInvoker->GetGUID());
- if( Temp )
- ((Player*)Temp)->GroupEventHappens(param1,m_creature);
- }
- }
- break;
- case ACTION_T_CASTCREATUREGO_ALL:
- {
- Unit* Temp = NULL;
-
- std::list<HostilReference*>::iterator i = m_creature->getThreatManager().getThreatList().begin();
- for (; i != m_creature->getThreatManager().getThreatList().end(); ++i)
- {
- Temp = Unit::GetUnit((*m_creature),(*i)->getUnitGuid());
- if (Temp && Temp->GetTypeId() == TYPEID_PLAYER)
- ((Player*)Temp)->CastedCreatureOrGO(param1, m_creature->GetGUID(), param2);
- }
- }
- break;
- case ACTION_T_REMOVEAURASFROMSPELL:
- {
- Unit* target = GetTargetByType(param1, pActionInvoker);
-
- if (target)
- target->RemoveAurasDueToSpell(param2);
- }
- break;
- case ACTION_T_RANGED_MOVEMENT:
- {
- AttackDistance = param1;
- AttackAngle = ((float)param2/180)*M_PI;
-
- if (CombatMovementEnabled)
- {
- m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), AttackDistance, AttackAngle);
- }
- }
- break;
- case ACTION_T_RANDOM_PHASE:
- {
- uint32 temp = GetRandActionParam(rnd, param1, param2, param3);
-
- Phase = temp;
- }
- break;
- case ACTION_T_RANDOM_PHASE_RANGE:
- {
- if (param2 > param1)
- {
- Phase = param1 + (rnd % (param2 - param1));
- }
- else if (EAI_ErrorLevel > 0)
- error_db_log( "SD2: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 <= Param1. Divide by Zero. Event = %d. CreatureEntry = %d", EventId, m_creature->GetEntry());
- }
- break;
- case ACTION_T_SUMMON_ID:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
-
- //Duration
- Creature* pCreature = NULL;
-
- UNORDERED_MAP<uint32, EventAI_Summon>::iterator i = EventAI_Summon_Map.find(param3);
-
- if (i == EventAI_Summon_Map.end())
- {
- if (EAI_ErrorLevel > 0)
- error_db_log( "SD2: EventAI failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", param1, param3, EventId, m_creature->GetEntry());
- return;
- }
-
- if ((*i).second.SpawnTimeSecs)
- pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs);
- else pCreature = m_creature->SummonCreature(param1, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0);
-
- if (!pCreature)
- {
- if (EAI_ErrorLevel > 0)
- error_db_log( "SD2: EventAI failed to spawn creature %u. EventId %d.Creature %d", param1, EventId, m_creature->GetEntry());
- }
- else if (param2 != TARGET_T_SELF && target)
- pCreature->AI()->AttackStart(target);
- }
- break;
- case ACTION_T_KILLED_MONSTER:
- {
- //first attempt player who tapped creature
- if (Player* pPlayer = m_creature->GetLootRecipient())
- pPlayer->RewardPlayerAndGroupAtEvent(param1,m_creature);
- else
- {
- //if not available, use pActionInvoker
- Unit* pTarget = GetTargetByType(param2, pActionInvoker);
-
- if (Player* pPlayer = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself())
- pPlayer->RewardPlayerAndGroupAtEvent(param1,m_creature);
- }
- }
- break;
- case ACTION_T_SET_INST_DATA:
- {
- ScriptedInstance* pInst = (ScriptedInstance*)m_creature->GetInstanceData();
- if (!pInst)
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Event %d attempt to set instance data without instance script. Creature %d", EventId, m_creature->GetEntry());
- return;
- }
-
- pInst->SetData(param1, param2);
- }
- break;
- case ACTION_T_SET_INST_DATA64:
- {
- Unit* target = GetTargetByType(param2, pActionInvoker);
-
- if (!target)
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Event %d attempt to set instance data64 but Target == NULL. Creature %d", EventId, m_creature->GetEntry());
- return;
- }
-
- ScriptedInstance* pInst = (ScriptedInstance*)m_creature->GetInstanceData();
-
- if (!pInst)
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Event %d attempt to set instance data64 without instance script. Creature %d", EventId, m_creature->GetEntry());
- return;
- }
-
- pInst->SetData64(param1, target->GetGUID());
- }
- break;
- case ACTION_T_UPDATE_TEMPLATE:
- {
- if (m_creature->GetEntry() == param1)
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", EventId, m_creature->GetEntry());
- return;
- }
-
- m_creature->UpdateEntry(param1, param2 ? HORDE : ALLIANCE);
- }
- break;
- case ACTION_T_DIE:
- {
- if (m_creature->isDead())
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Event %d ACTION_T_DIE on dead creature. Creature %d", EventId, m_creature->GetEntry());
- return;
- }
- m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
- }
- break;
- case ACTION_T_ZONE_COMBAT_PULSE:
- {
- if (!m_creature->isInCombat() || !m_creature->GetMap()->IsDungeon())
- {
- if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Event %d ACTION_T_ZONE_COMBAT_PULSE on creature out of combat or in non-dungeon map. Creature %d", EventId, m_creature->GetEntry());
- return;
- }
-
- DoZoneInCombat();
- }
- break;
-
- // TRINITY ONLY
- case ACTION_T_SET_ACTIVE:
- m_creature->setActive(param1 ? true : false);
- break;
- case ACTION_T_SET_AGGRESSIVE:
- m_creature->SetReactState(ReactStates(param1));
- break;
- case ACTION_T_ATTACK_START_PULSE:
- AttackStart(m_creature->SelectNearestTarget((float)param1));
- break;
- }
- }
-
- void JustRespawned()
- {
- InCombat = false;
- IsFleeing = false;
- Reset();
-
- if (bEmptyList)
- return;
-
- //Handle Spawned Events
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_SPAWNED)
- ProcessEvent(*i);
- }
- }
-
- void Reset()
- {
- EventUpdateTime = EVENT_UPDATE_TIME;
- EventDiff = 0;
-
- if (bEmptyList)
- return;
-
- //Reset all events to enabled
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- switch ((*i).Event.event_type)
- {
- //Reset all out of combat timers
- case EVENT_T_TIMER_OOC:
- {
- if ((*i).Event.event_param2 == (*i).Event.event_param1)
- {
- (*i).Time = (*i).Event.event_param1;
- (*i).Enabled = true;
- }
- else if ((*i).Event.event_param2 > (*i).Event.event_param1)
- {
- (*i).Time = urand((*i).Event.event_param1, (*i).Event.event_param2);
- (*i).Enabled = true;
- }
- else if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
- }
- break;
- //default:
- //TODO: enable below code line / verify this is correct to enable events previously disabled (ex. aggro yell), instead of enable this in void Aggro()
- //(*i).Enabled = true;
- //(*i).Time = 0;
- //break;
- }
- }
- }
-
- //when creature reach home after EnterEvadeMode
- void JustReachedHome()
- {
- m_creature->LoadCreaturesAddon();
-
- if (!bEmptyList)
- {
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_REACHED_HOME)
- ProcessEvent(*i);
- }
- }
-
- Reset();
- }
-
- void EnterEvadeMode()
- {
- m_creature->InterruptNonMeleeSpells(true);
- m_creature->RemoveAllAuras();
- m_creature->DeleteThreatList();
- m_creature->CombatStop();
-
- if (m_creature->isAlive())
- m_creature->GetMotionMaster()->MoveTargetedHome();
-
- m_creature->SetLootRecipient(NULL);
-
- InCombat = false;
-
- if (bEmptyList)
- return;
-
- //Handle Evade events
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_EVADE)
- ProcessEvent(*i);
- }
- }
-
- void JustDied(Unit* killer)
- {
- InCombat = false;
- IsFleeing = false;
- Reset();
-
- if (bEmptyList)
- return;
-
- //Handle Evade events
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_DEATH)
- ProcessEvent(*i, killer);
- }
- }
-
- void KilledUnit(Unit* victim)
- {
- if (bEmptyList || victim->GetTypeId() != TYPEID_PLAYER)
- return;
-
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_KILL)
- ProcessEvent(*i, victim);
- }
- }
-
- void JustSummoned(Creature* pUnit)
- {
- if (bEmptyList || !pUnit)
- return;
-
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_SUMMONED_UNIT)
- ProcessEvent(*i, pUnit);
- }
- }
-
- void Aggro(Unit *who)
- {
- //Check for on combat start events
- if (!bEmptyList)
- {
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- switch ((*i).Event.event_type)
- {
- case EVENT_T_AGGRO:
- (*i).Enabled = true;
- ProcessEvent(*i, who);
- break;
- //Reset all in combat timers
- case EVENT_T_TIMER:
- if ((*i).Event.event_param2 == (*i).Event.event_param1)
- {
- (*i).Time = (*i).Event.event_param1;
- (*i).Enabled = true;
- }
- else if ((*i).Event.event_param2 > (*i).Event.event_param1)
- {
- (*i).Time = urand((*i).Event.event_param1, (*i).Event.event_param2);
- (*i).Enabled = true;
- }
- else if (EAI_ErrorLevel > 0)
- error_db_log("SD2: Creature %u using Event %u (Type = %u) has InitialMax < InitialMin. Event disabled.", m_creature->GetEntry(), (*i).Event.event_id, (*i).Event.event_type);
- break;
- //All normal events need to be re-enabled and their time set to 0
- default:
- (*i).Enabled = true;
- (*i).Time = 0;
- break;
- }
- }
- }
-
- EventUpdateTime = EVENT_UPDATE_TIME;
- EventDiff = 0;
- }
-
- void AttackStart(Unit *who)
- {
- if (!who)
- return;
-
- if (m_creature->Attack(who, MeleeEnabled))
- {
- //Begin melee attack if we are within range
-
- if (!InCombat)
- {
- InCombat = true;
- Aggro(who);
- }
-
- if (CombatMovementEnabled)
- {
- m_creature->GetMotionMaster()->MoveChase(who, AttackDistance, AttackAngle);
- }
- else
- {
- m_creature->GetMotionMaster()->MoveIdle();
- }
- }
- }
-
- void MoveInLineOfSight(Unit *who)
- {
- if (!who || InCombat)
- return;
-
- //Check for OOC LOS Event
- if (!bEmptyList && !m_creature->getVictim())
- {
- for (std::list<EventHolder>::iterator itr = EventList.begin(); itr != EventList.end(); ++itr)
- {
- if ((*itr).Event.event_type == EVENT_T_OOC_LOS)
- {
- //can trigger if closer than fMaxAllowedRange
- float fMaxAllowedRange = (*itr).Event.event_param2;
-
- //if range is ok and we are actually in LOS
- if (m_creature->IsWithinDistInMap(who, fMaxAllowedRange) && m_creature->IsWithinLOSInMap(who))
- {
- //if friendly event&&who is not hostile OR hostile event&&who is hostile
- if (((*itr).Event.event_param1 && !m_creature->IsHostileTo(who)) ||
- ((!(*itr).Event.event_param1) && m_creature->IsHostileTo(who)))
- ProcessEvent(*itr, who);
- }
- }
- }
- }
-
- // do we need this?
- //if (m_creature->isCivilian() && m_creature->IsNeutralToAll())
- // return;
-
- if(m_creature->canStartAttack(who))
- AttackStart(who);
- }
-
- void SpellHit(Unit* pUnit, const SpellEntry* pSpell)
- {
- if (bEmptyList)
- return;
-
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_SPELLHIT)
- {
- //If spell id matches (or no spell id) & if spell school matches (or no spell school)
- if (!(*i).Event.event_param1 || pSpell->Id == (*i).Event.event_param1)
- {
- if ((*i).Event.event_param2_s == -1 || pSpell->SchoolMask == (*i).Event.event_param2)
- ProcessEvent(*i, pUnit);
- }
- }
- }
- }
-
- void UpdateAI(const uint32 diff)
- {
- //Check if we are in combat (also updates calls threat update code)
- bool Combat = InCombat ? UpdateVictim() : false;
-
- //Must return if creature isn't alive. Normally select hostil target and get victim prevent this
- if (!m_creature->isAlive())
- return;
-
- if (IsFleeing)
- {
- if(TimetoFleeLeft < diff)
- {
- m_creature->SetControlled(false, UNIT_STAT_FLEEING);
- m_creature->SetNoCallAssistance(false);
- m_creature->CallAssistance();
- if(m_creature->getVictim())
- m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
- IsFleeing = false;
- }
- else
- TimetoFleeLeft -= diff;
-
- return;
- }
-
- //Events are only updated once every EVENT_UPDATE_TIME ms to prevent lag with large amount of events
- if (!bEmptyList)
- {
- if (EventUpdateTime < diff)
- {
- EventDiff += diff;
-
- //Check for time based events
- for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i)
- {
- //Decrement Timers
- if ((*i).Time)
- {
- if ((*i).Time > EventDiff)
- {
- //Do not decrement timers if event cannot trigger in this phase
- if (!((*i).Event.event_inverse_phase_mask & (1 << Phase)))
- (*i).Time -= EventDiff;
-
- //Skip processing of events that have time remaining
- continue;
- }
- else (*i).Time = 0;
- }
-
- //Events that are updated every EVENT_UPDATE_TIME
- switch ((*i).Event.event_type)
- {
- case EVENT_T_TIMER_OOC:
- ProcessEvent(*i);
- break;
- case EVENT_T_TIMER:
- case EVENT_T_MANA:
- case EVENT_T_HP:
- case EVENT_T_TARGET_HP:
- case EVENT_T_TARGET_CASTING:
- case EVENT_T_FRIENDLY_HP:
- if (Combat)
- ProcessEvent(*i);
- break;
- case EVENT_T_RANGE:
- if (Combat)
- {
- if (m_creature->IsWithinDistInMap(m_creature->getVictim(),(float)(*i).Event.event_param2))
- {
- if (m_creature->GetDistance(m_creature->getVictim()) >= (float)(*i).Event.event_param1)
- ProcessEvent(*i);
- }
- }
- break;
- }
- }
-
- EventDiff = 0;
- EventUpdateTime = EVENT_UPDATE_TIME;
- }
- else
- {
- EventDiff += diff;
- EventUpdateTime -= diff;
- }
- }
-
- //Melee Auto-Attack
- if (Combat && MeleeEnabled)
- DoMeleeAttackIfReady();
-
- }
-};
-
-CreatureAI* GetAI_mob_eventai(Creature* pCreature)
-{
- //Select events by creature id
- std::list<EventHolder> EventList;
-
- //Find creature id in the Event map
- UNORDERED_MAP<uint32, std::vector<EventAI_Event> >::iterator CreatureEvents = EventAI_Event_Map.find(pCreature->GetEntry());
-
- if (CreatureEvents != EventAI_Event_Map.end())
- {
- std::vector<EventAI_Event>::iterator i;
-
- for (i = (*CreatureEvents).second.begin(); i != (*CreatureEvents).second.end(); ++i)
- {
- //Debug check
-#ifndef _DEBUG
- if ((*i).event_flags & EFLAG_DEBUG_ONLY)
- continue;
-#endif
- if (pCreature->GetMap()->IsDungeon())
- {
- if ((pCreature->GetMap()->IsHeroic() && (*i).event_flags & EFLAG_HEROIC) ||
- (!pCreature->GetMap()->IsHeroic() && (*i).event_flags & EFLAG_NORMAL))
- {
- //event flagged for instance mode
- EventList.push_back(EventHolder(*i));
- }
- continue;
- }
-
- EventList.push_back(EventHolder(*i));
- }
-
- //EventMap had events but they were not added because they must be for instance
- if (EventList.empty())
- {
- if (EAI_ErrorLevel > 1)
- error_db_log("SD2: CreatureId has events but no events added to list because of instance flags.", pCreature->GetEntry());
- }
- }
- else
- {
- if (EAI_ErrorLevel > 1)
- error_db_log("SD2: EventMap for Creature %u is empty but creature is using Mob_EventAI.", pCreature->GetEntry());
- }
-
- return new Mob_EventAI(pCreature, EventList);
-}
-
-bool ReceiveEmote_mob_eventai(Player* pPlayer, Creature* pCreature, uint32 uiEmote)
-{
- if(pCreature->isCharmed())
- return true;
-
- Mob_EventAI* pTmpCreature = (Mob_EventAI*)(pCreature->AI());
-
- if (pTmpCreature->bEmptyList)
- return true;
-
- for (std::list<EventHolder>::iterator itr = pTmpCreature->EventList.begin(); itr != pTmpCreature->EventList.end(); ++itr)
- {
- if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE)
- {
- if ((*itr).Event.event_param1 != uiEmote)
- return true;
-
- bool bProcess = false;
-
- switch((*itr).Event.event_param2)
- {
- //enum ConditionType
- case CONDITION_NONE: // 0 0
- bProcess = true;
- break;
- case CONDITION_AURA: // spell_id effindex
- if (pPlayer->HasAura((*itr).Event.event_param3,(*itr).Event.event_param4))
- bProcess = true;
- break;
- case CONDITION_ITEM: // item_id count
- if (pPlayer->HasItemCount((*itr).Event.event_param3,(*itr).Event.event_param4))
- bProcess = true;
- break;
- case CONDITION_ITEM_EQUIPPED: // item_id count
- if (pPlayer->HasItemOrGemWithIdEquipped((*itr).Event.event_param3,(*itr).Event.event_param4))
- bProcess = true;
- break;
- case CONDITION_ZONEID: // zone_id 0
- if (pPlayer->GetZoneId() == (*itr).Event.event_param3)
- bProcess = true;
- break;
- case CONDITION_REPUTATION_RANK: // faction_id min_rank
- if (pPlayer->GetReputationRank((*itr).Event.event_param3) >= (*itr).Event.event_param4)
- bProcess = true;
- break;
- case CONDITION_TEAM: // player_team 0, (469 - Alliance 67 - Horde)
- if (pPlayer->GetTeam() == (*itr).Event.event_param3)
- bProcess = true;
- break;
- case CONDITION_SKILL: // skill_id min skill_value
- if (pPlayer->HasSkill((*itr).Event.event_param3) && pPlayer->GetSkillValue((*itr).Event.event_param3) >= (*itr).Event.event_param4)
- bProcess = true;
- break;
- case CONDITION_QUESTREWARDED: // quest_id 0
- if (pPlayer->GetQuestRewardStatus((*itr).Event.event_param3))
- bProcess = true;
- break;
- case CONDITION_QUESTTAKEN: // quest_id 0, for condition true while quest active.
- if (pPlayer->GetQuestStatus((*itr).Event.event_param3) == QUEST_STATUS_INCOMPLETE)
- bProcess = true;
- break;
- case CONDITION_ACTIVE_EVENT: // event_id 0
- if (IsHolidayActive(HolidayIds((*itr).Event.event_param3)))
- bProcess = true;
- break;
- }
-
- if (bProcess)
- {
- debug_log("SD2: ReceiveEmote EventAI: Condition ok, processing");
- pTmpCreature->ProcessEvent(*itr, pPlayer);
- }
- }
- }
-
- return true;
-}
-
-void AddSC_mob_event()
-{
- Script *newscript;
- newscript = new Script;
- newscript->Name = "mob_eventai";
- newscript->GetAI = &GetAI_mob_eventai;
- newscript->pReceiveEmote = &ReceiveEmote_mob_eventai;
- newscript->RegisterSelf();
-}
-
diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.h b/src/bindings/scripts/scripts/creature/mob_event_ai.h
index 7c56b7932dc..f6c9b663ce0 100644
--- a/src/bindings/scripts/scripts/creature/mob_event_ai.h
+++ b/src/bindings/scripts/scripts/creature/mob_event_ai.h
@@ -1,223 +1,4 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
- * This program is free software licensed under GPL version 2
- * Please see the included DOCS/LICENSE.TXT for more information */
-
#ifndef SC_EVENTAI_H
#define SC_EVENTAI_H
-
-#define MAX_ACTIONS 3
-
-enum Event_Types
-{
- EVENT_T_TIMER = 0, //InitialMin, InitialMax, RepeatMin, RepeatMax
- EVENT_T_TIMER_OOC = 1, //InitialMin, InitialMax, RepeatMin, RepeatMax
- EVENT_T_HP = 2, //HPMax%, HPMin%, RepeatMin, RepeatMax
- EVENT_T_MANA = 3, //ManaMax%,ManaMin% RepeatMin, RepeatMax
- EVENT_T_AGGRO = 4, //NONE
- EVENT_T_KILL = 5, //RepeatMin, RepeatMax
- EVENT_T_DEATH = 6, //NONE
- EVENT_T_EVADE = 7, //NONE
- EVENT_T_SPELLHIT = 8, //SpellID, School, RepeatMin, RepeatMax
- EVENT_T_RANGE = 9, //MinDist, MaxDist, RepeatMin, RepeatMax
- EVENT_T_OOC_LOS = 10, //NoHostile, NoFriendly, RepeatMin, RepeatMax
- EVENT_T_SPAWNED = 11, //NONE
- EVENT_T_TARGET_HP = 12, //HPMax%, HPMin%, RepeatMin, RepeatMax
- EVENT_T_TARGET_CASTING = 13, //RepeatMin, RepeatMax
- EVENT_T_FRIENDLY_HP = 14, //HPDeficit, Radius, RepeatMin, RepeatMax
- EVENT_T_FRIENDLY_IS_CC = 15, //DispelType, Radius, RepeatMin, RepeatMax
- EVENT_T_FRIENDLY_MISSING_BUFF = 16, //SpellId, Radius, RepeatMin, RepeatMax
- EVENT_T_SUMMONED_UNIT = 17, //CreatureId, RepeatMin, RepeatMax
- EVENT_T_TARGET_MANA = 18, //ManaMax%, ManaMin%, RepeatMin, RepeatMax
- EVENT_T_QUEST_ACCEPT = 19, //QuestID
- EVENT_T_QUEST_COMPLETE = 20, //
- EVENT_T_REACHED_HOME = 21, //NONE
- EVENT_T_RECEIVE_EMOTE = 22, //EmoteId, Condition, CondValue1, CondValue2
-
- EVENT_T_END,
-};
-
-enum Action_Types
-{
- ACTION_T_NONE = 0, //No action
- ACTION_T_TEXT = 1, //-TextId1, optionally -TextId2, optionally -TextId3(if -TextId2 exist). If more than just -TextId1 is defined, randomize. Negative values.
- ACTION_T_SET_FACTION = 2, //FactionId (or 0 for default)
- ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3, //Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
- ACTION_T_SOUND = 4, //SoundId
- ACTION_T_EMOTE = 5, //EmoteId
- ACTION_T_RANDOM_SAY = 6, //UNUSED
- ACTION_T_RANDOM_YELL = 7, //UNUSED
- ACTION_T_RANDOM_TEXTEMOTE = 8, //UNUSED
- ACTION_T_RANDOM_SOUND = 9, //SoundId1, SoundId2, SoundId3 (-1 in any field means no output if randomed that field)
- ACTION_T_RANDOM_EMOTE = 10, //EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field)
- ACTION_T_CAST = 11, //SpellId, Target, CastFlags
- ACTION_T_SUMMON = 12, //CreatureID, Target, Duration in ms
- ACTION_T_THREAT_SINGLE_PCT = 13, //Threat%, Target
- ACTION_T_THREAT_ALL_PCT = 14, //Threat%
- ACTION_T_QUEST_EVENT = 15, //QuestID, Target
- ACTION_T_CASTCREATUREGO = 16, //QuestID, SpellId, Target
- ACTION_T_SET_UNIT_FIELD = 17, //Field_Number, Value, Target
- ACTION_T_SET_UNIT_FLAG = 18, //Flags (may be more than one field OR'd together), Target
- ACTION_T_REMOVE_UNIT_FLAG = 19, //Flags (may be more than one field OR'd together), Target
- ACTION_T_AUTO_ATTACK = 20, //AllowAttackState (0 = stop attack, anything else means continue attacking)
- ACTION_T_COMBAT_MOVEMENT = 21, //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
- ACTION_T_SET_PHASE = 22, //Phase
- ACTION_T_INC_PHASE = 23, //Value (may be negative to decrement phase, should not be 0)
- ACTION_T_EVADE = 24, //No Params
- ACTION_T_FLEE = 25, //No Params
- ACTION_T_QUEST_EVENT_ALL = 26, //QuestID
- ACTION_T_CASTCREATUREGO_ALL = 27, //QuestId, SpellId
- ACTION_T_REMOVEAURASFROMSPELL = 28, //Target, Spellid
- ACTION_T_RANGED_MOVEMENT = 29, //Distance, Angle
- ACTION_T_RANDOM_PHASE = 30, //PhaseId1, PhaseId2, PhaseId3
- ACTION_T_RANDOM_PHASE_RANGE = 31, //PhaseMin, PhaseMax
- ACTION_T_SUMMON_ID = 32, //CreatureId, Target, SpawnId
- ACTION_T_KILLED_MONSTER = 33, //CreatureId, Target
- ACTION_T_SET_INST_DATA = 34, //Field, Data
- ACTION_T_SET_INST_DATA64 = 35, //Field, Target
- ACTION_T_UPDATE_TEMPLATE = 36, //Entry, Team
- ACTION_T_DIE = 37, //No Params
- ACTION_T_ZONE_COMBAT_PULSE = 38, //No Params
-
- ACTION_T_SET_ACTIVE = 101, //Apply
- ACTION_T_SET_AGGRESSIVE = 102, //Apply
- ACTION_T_ATTACK_START_PULSE = 103, //Distance
-
- ACTION_T_END,
-};
-
-enum Target
-{
- //Self (m_creature)
- TARGET_T_SELF = 0, //Self cast
-
- //Hostile targets (if pet then returns pet owner)
- TARGET_T_HOSTILE, //Our current target (ie: highest aggro)
- TARGET_T_HOSTILE_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
- TARGET_T_HOSTILE_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
- TARGET_T_HOSTILE_RANDOM, //Just any random target on our threat list
- TARGET_T_HOSTILE_RANDOM_NOT_TOP, //Any random target except top threat
-
- //Invoker targets (if pet then returns pet owner)
- TARGET_T_ACTION_INVOKER, //Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF)
-
- //Hostile targets (including pets)
- TARGET_T_HOSTILE_WPET, //Current target (can be a pet)
- TARGET_T_HOSTILE_WPET_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
- TARGET_T_HOSTILE_WPET_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
- TARGET_T_HOSTILE_WPET_RANDOM, //Just any random target on our threat list
- TARGET_T_HOSTILE_WPET_RANDOM_NOT_TOP, //Any random target except top threat
-
- TARGET_T_ACTION_INVOKER_WPET,
-
- TARGET_T_END
-};
-
-enum CastFlags
-{
- CAST_INTURRUPT_PREVIOUS = 0x01, //Interrupt any spell casting
- CAST_TRIGGERED = 0x02, //Triggered (this makes spell cost zero mana and have no cast time)
- CAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range
- CAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range
- CAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself
- CAST_AURA_NOT_PRESENT = 0x20, //Only casts the spell if the target does not have an aura from the spell
-};
-
-enum EventFlags
-{
- EFLAG_REPEATABLE = 0x01, //Event repeats
- EFLAG_NORMAL = 0x02, //Event only occurs in Normal instance difficulty
- EFLAG_HEROIC = 0x04, //Event only occurs in Heroic instance difficulty
- EFLAG_RESERVED_3 = 0x08,
- EFLAG_RESERVED_4 = 0x10,
- EFLAG_RESERVED_5 = 0x20,
- EFLAG_RESERVED_6 = 0x40,
- EFLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build of SD2 only
-};
-
-struct EventAI_Event
-{
- uint32 event_id;
-
- uint32 creature_id;
-
- uint16 event_type;
- uint32 event_inverse_phase_mask;
- uint8 event_chance;
- uint8 event_flags;
- union
- {
- uint32 event_param1;
- int32 event_param1_s;
- };
- union
- {
- uint32 event_param2;
- int32 event_param2_s;
- };
- union
- {
- uint32 event_param3;
- int32 event_param3_s;
- };
- union
- {
- uint32 event_param4;
- int32 event_param4_s;
- };
-
- struct _action
- {
- uint16 type;
- union
- {
- uint32 param1;
- int32 param1_s;
- };
- union
- {
- uint32 param2;
- int32 param2_s;
- };
- union
- {
- uint32 param3;
- int32 param3_s;
- };
- }action[MAX_ACTIONS];
-};
-
-//Event_Map
-extern UNORDERED_MAP<uint32, std::vector<EventAI_Event> > EventAI_Event_Map;
-
-struct EventAI_Summon
-{
- uint32 id;
-
- float position_x;
- float position_y;
- float position_z;
- float orientation;
- uint32 SpawnTimeSecs;
-};
-
-//EventSummon_Map
-extern UNORDERED_MAP<uint32, EventAI_Summon> EventAI_Summon_Map;
-
-//EventAI Error handling
-extern uint32 EAI_ErrorLevel;
-/*
-
-struct EventAI_CreatureError
-{
- bool ListEmpty;
- bool NoInstance;
-};
-
-//Error prevention list
-extern UNORDERED_MAP<uint32, EventAI_CreatureError> EventAI_CreatureErrorPreventionList;
-
-//Defines
-#define EVENTAI_EMPTY_EVENTLIST "SD2: Eventlist for Creature %i is empty but creature is using Mob_EventAI. Preventing EventAI on this creature."
-*/
#endif