diff options
-rw-r--r-- | src/bindings/scripts/ScriptMgr.cpp | 48 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/creature/mob_event_ai.cpp | 204 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/creature/mob_event_ai.h | 2 |
3 files changed, 133 insertions, 121 deletions
diff --git a/src/bindings/scripts/ScriptMgr.cpp b/src/bindings/scripts/ScriptMgr.cpp index b3389c3676c..b63d27055d4 100644 --- a/src/bindings/scripts/ScriptMgr.cpp +++ b/src/bindings/scripts/ScriptMgr.cpp @@ -51,7 +51,7 @@ UNORDERED_MAP<int32, StringTextData> TextMap; std::list<PointMovement> PointMovementList; //Event AI structure. Used exclusivly by mob_event_ai.cpp (60 bytes each) -std::list<EventAI_Event> EventAI_Event_List; +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; @@ -853,7 +853,7 @@ void LoadDatabase() outstring_log(""); outstring_log(">> Loaded 0 additional Custom Texts data. DB table `custom_texts` is empty."); } - + // Drop Existing Waypoint list PointMovementList.clear(); uint64 uiCreatureCount = 0; @@ -959,7 +959,7 @@ void LoadDatabase() } //Drop Existing EventAI List - EventAI_Event_List.clear(); + EventAI_Event_Map.clear(); uint64 uiEAICreatureCount = 0; result = TScriptDB.PQuery("SELECT COUNT(creature_id) FROM eventai_scripts GROUP BY creature_id"); @@ -995,6 +995,7 @@ void LoadDatabase() 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(); @@ -1074,26 +1075,27 @@ void LoadDatabase() 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_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; - 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: { @@ -1101,6 +1103,7 @@ void LoadDatabase() 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)) @@ -1146,6 +1149,7 @@ void LoadDatabase() 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) @@ -1232,7 +1236,7 @@ void LoadDatabase() } break; case CONDITION_NONE: - break; + 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); @@ -1256,7 +1260,6 @@ void LoadDatabase() continue; } break; - } for (uint32 j = 0; j < MAX_ACTIONS; j++) @@ -1502,7 +1505,8 @@ void LoadDatabase() } //Add to list - EventAI_Event_List.push_back(temp); + EventAI_Event_Map[creature_id].push_back(temp); + ++Count; } while (result->NextRow()); diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp index af5f47634e0..cd296910d2c 100644 --- a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp +++ b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp @@ -43,6 +43,7 @@ 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; @@ -50,13 +51,12 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI AttackAngle = 0.0f; //Handle Spawned Events - for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) + if (!bEmptyList) { - switch ((*i).Event.event_type) + for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) { - case EVENT_T_SPAWNED: + if ((*i).Event.event_type == EVENT_T_SPAWNED) ProcessEvent(*i); - break; } } @@ -72,6 +72,7 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI 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 @@ -551,8 +552,7 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI }else if ( param2 && urand(0,1) ) { temp = param2; - } - else + }else { temp = param1; } @@ -1032,15 +1032,14 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI IsFleeing = false; Reset(); + if (bEmptyList) + return; + //Handle Spawned Events for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) { - switch ((*i).Event.event_type) - { - case EVENT_T_SPAWNED: + if ((*i).Event.event_type == EVENT_T_SPAWNED) ProcessEvent(*i); - break; - } } } @@ -1049,6 +1048,9 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI 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) { @@ -1061,11 +1063,13 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI { (*i).Time = (*i).Event.event_param1; (*i).Enabled = true; - }else if ((*i).Event.event_param2 > (*i).Event.event_param1) + } + 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) + } + 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; @@ -1083,10 +1087,13 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI { m_creature->LoadCreaturesAddon(); - for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) + if (!bEmptyList) { - if ((*i).Event.event_type == EVENT_T_REACHED_HOME) - ProcessEvent(*i); + for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) + { + if ((*i).Event.event_type == EVENT_T_REACHED_HOME) + ProcessEvent(*i); + } } Reset(); @@ -1106,6 +1113,9 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI InCombat = false; + if (bEmptyList) + return; + //Handle Evade events for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) { @@ -1120,83 +1130,75 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI IsFleeing = false; Reset(); + if (bEmptyList) + return; + //Handle Evade events for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) { - switch ((*i).Event.event_type) - { - //Evade - case EVENT_T_DEATH: - ProcessEvent(*i, killer); - break; - } + if ((*i).Event.event_type == EVENT_T_DEATH) + ProcessEvent(*i, killer); } } void KilledUnit(Unit* victim) { - if (victim->GetTypeId() != TYPEID_PLAYER) + if (bEmptyList || victim->GetTypeId() != TYPEID_PLAYER) return; for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) { - switch ((*i).Event.event_type) - { - //Kill - case EVENT_T_KILL: - ProcessEvent(*i, victim); - break; - } + if ((*i).Event.event_type == EVENT_T_KILL) + ProcessEvent(*i, victim); } - } void JustSummoned(Creature* pUnit) { - if (!pUnit) + if (bEmptyList || !pUnit) return; for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) { - switch ((*i).Event.event_type) - { - //Summoned - case EVENT_T_SUMMONED_UNIT: - ProcessEvent(*i, pUnit); - break; - } + if ((*i).Event.event_type == EVENT_T_SUMMONED_UNIT) + ProcessEvent(*i, pUnit); } } void Aggro(Unit *who) { //Check for on combat start events - for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) + if (!bEmptyList) { - switch ((*i).Event.event_type) + 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 + //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) + } + 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) + } + 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 + //All normal events need to be re-enabled and their time set to 0 default: (*i).Enabled = true; (*i).Time = 0; break; + } } } @@ -1236,14 +1238,14 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI return; //Check for OOC LOS Event - if (!m_creature->getVictim()) + 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; + 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)) @@ -1252,7 +1254,6 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI if (((*itr).Event.event_param1 && !m_creature->IsHostileTo(who)) || ((!(*itr).Event.event_param1) && m_creature->IsHostileTo(who))) ProcessEvent(*itr, who); - } } } @@ -1268,19 +1269,19 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI void SpellHit(Unit* pUnit, const SpellEntry* pSpell) { + if (bEmptyList) + return; + for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) { - switch ((*i).Event.event_type) + if ((*i).Event.event_type == EVENT_T_SPELLHIT) { - //Spell hit - case 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); - } - break; + //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); + } } } } @@ -1312,31 +1313,33 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI } //Events are only updated once every EVENT_UPDATE_TIME ms to prevent lag with large amount of events - if (EventUpdateTime < diff) + if (!bEmptyList) { - EventDiff += diff; - - //Check for time based events - for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) + if (EventUpdateTime < diff) { - //Decrement Timers - if ((*i).Time) + EventDiff += diff; + + //Check for time based events + for (std::list<EventHolder>::iterator i = EventList.begin(); i != EventList.end(); ++i) { - if ((*i).Time > EventDiff) + //Decrement Timers + if ((*i).Time) { - //Do not decrement timers if event cannot trigger in this phase - if (!((*i).Event.event_inverse_phase_mask & (1 << Phase))) - (*i).Time -= EventDiff; + 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; + //Skip processing of events that have time remaining + continue; + } + else (*i).Time = 0; } - else (*i).Time = 0; - } - //Events that are updated every EVENT_UPDATE_TIME - switch ((*i).Event.event_type) - { + //Events that are updated every EVENT_UPDATE_TIME + switch ((*i).Event.event_type) + { case EVENT_T_TIMER_OOC: ProcessEvent(*i); break; @@ -1359,16 +1362,17 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI } } break; + } } - } - EventDiff = 0; - EventUpdateTime = EVENT_UPDATE_TIME; - } - else - { - EventDiff += diff; - EventUpdateTime -= diff; + EventDiff = 0; + EventUpdateTime = EVENT_UPDATE_TIME; + } + else + { + EventDiff += diff; + EventUpdateTime -= diff; + } } //Melee Auto-Attack @@ -1382,15 +1386,17 @@ CreatureAI* GetAI_mob_eventai(Creature* pCreature) { //Select events by creature id std::list<EventHolder> EventList; - uint32 ID = pCreature->GetEntry(); - std::list<EventAI_Event>::iterator i; + //Find creature id in the Event map + UNORDERED_MAP<uint32, std::vector<EventAI_Event> >::iterator CreatureEvents = EventAI_Event_Map.find(pCreature->GetEntry()); - for (i = EventAI_Event_List.begin(); i != EventAI_Event_List.end(); ++i) + if (CreatureEvents != EventAI_Event_Map.end()) { - if ((*i).creature_id == ID) + std::vector<EventAI_Event>::iterator i; + + for (i = (*CreatureEvents).second.begin(); i != (*CreatureEvents).second.end(); ++i) { -//Debug check + //Debug check #ifndef _DEBUG if ((*i).event_flags & EFLAG_DEBUG_ONLY) continue; @@ -1403,21 +1409,23 @@ CreatureAI* GetAI_mob_eventai(Creature* pCreature) //event flagged for instance mode EventList.push_back(EventHolder(*i)); } - continue; } EventList.push_back(EventHolder(*i)); } - } - //EventAI is pointless to use without events and may cause crashes - if (EventList.empty()) + //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: Eventlist for Creature %u is empty but creature is using Mob_EventAI (missing instance mode flags?). Preventing EventAI on this creature.", pCreature->GetEntry()); - - return NULL; + error_db_log("SD2: EventMap for Creature %u is empty but creature is using Mob_EventAI.", pCreature->GetEntry()); } return new Mob_EventAI(pCreature, EventList); @@ -1427,7 +1435,7 @@ bool ReceiveEmote_mob_eventai(Player* pPlayer, Creature* pCreature, uint32 uiEmo { Mob_EventAI* pTmpCreature = (Mob_EventAI*)(pCreature->AI()); - if (pTmpCreature->EventList.empty()) + if (pTmpCreature->bEmptyList) return true; for (std::list<EventHolder>::iterator itr = pTmpCreature->EventList.begin(); itr != pTmpCreature->EventList.end(); ++itr) diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.h b/src/bindings/scripts/scripts/creature/mob_event_ai.h index 8793e143a87..7c56b7932dc 100644 --- a/src/bindings/scripts/scripts/creature/mob_event_ai.h +++ b/src/bindings/scripts/scripts/creature/mob_event_ai.h @@ -187,7 +187,7 @@ struct EventAI_Event }; //Event_Map -extern std::list<EventAI_Event> EventAI_Event_List; +extern UNORDERED_MAP<uint32, std::vector<EventAI_Event> > EventAI_Event_Map; struct EventAI_Summon { |