mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-29 13:22:48 +01:00
[7622] Added creatureAI with related database tables. Author: AlexDereka
*Note: three tables are renamed. --HG-- branch : trunk
This commit is contained in:
@@ -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 --
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user