Core/SAI: Implemented new source type SMART_SCRIPT_TYPE_EVENT (3) (#28816)
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
DROP TABLE IF EXISTS `event_script_names`;
|
||||
CREATE TABLE `event_script_names` (
|
||||
`Id` int unsigned NOT NULL,
|
||||
`ScriptName` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1242,10 +1242,26 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class SmartEventTrigger : public EventScript
|
||||
{
|
||||
public:
|
||||
SmartEventTrigger() : EventScript("SmartEventTrigger") { }
|
||||
|
||||
void OnTrigger(WorldObject* object, WorldObject* invoker, uint32 eventId) override
|
||||
{
|
||||
TC_LOG_DEBUG("scripts.ai", "Event {} is using SmartEventTrigger script", eventId);
|
||||
SmartScript script;
|
||||
// Set invoker as BaseObject if there isn't target for GameEvents::Trigger
|
||||
script.OnInitialize(Coalesce<WorldObject>(object, invoker), nullptr, nullptr, nullptr, eventId);
|
||||
script.ProcessEventsFor(SMART_EVENT_SEND_EVENT_TRIGGER, invoker->ToUnit(), 0, 0, false, nullptr, invoker->ToGameObject());
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_SmartScripts()
|
||||
{
|
||||
new SmartTrigger();
|
||||
new SmartAreaTriggerEntityScript();
|
||||
new SmartScene();
|
||||
new SmartQuest();
|
||||
new SmartEventTrigger();
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ SmartScript::SmartScript()
|
||||
areaTrigger = nullptr;
|
||||
sceneTemplate = nullptr;
|
||||
quest = nullptr;
|
||||
event = 0;
|
||||
mEventPhase = 0;
|
||||
mPathId = 0;
|
||||
mTextTimer = 0;
|
||||
@@ -217,6 +218,7 @@ void SmartScript::ResetBaseObject()
|
||||
me = m;
|
||||
go = nullptr;
|
||||
areaTrigger = nullptr;
|
||||
player = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,6 +229,7 @@ void SmartScript::ResetBaseObject()
|
||||
me = nullptr;
|
||||
go = o;
|
||||
areaTrigger = nullptr;
|
||||
player = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3169,6 +3172,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
|
||||
case SMART_EVENT_FOLLOW_COMPLETED:
|
||||
case SMART_EVENT_ON_SPELLCLICK:
|
||||
case SMART_EVENT_ON_DESPAWN:
|
||||
case SMART_EVENT_SEND_EVENT_TRIGGER:
|
||||
ProcessAction(e, unit, var0, var1, bvar, spell, gob);
|
||||
break;
|
||||
case SMART_EVENT_GOSSIP_HELLO:
|
||||
@@ -3910,7 +3914,7 @@ void SmartScript::RetryLater(SmartScriptHolder& e, bool ignoreChanceRoll)
|
||||
e.runOnce = false;
|
||||
}
|
||||
|
||||
void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene, Quest const* quest)
|
||||
void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene, Quest const* quest, uint32 event)
|
||||
{
|
||||
if (e.empty())
|
||||
{
|
||||
@@ -3922,6 +3926,8 @@ void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEn
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript: EventMap for SceneId {} is empty but is using SmartScript.", scene->SceneId);
|
||||
if (quest)
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript: EventMap for Quest {} is empty but is using SmartScript.", quest->GetQuestId());
|
||||
if (event)
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript: EventMap for Event {} is empty but is using SmartScript.", event);
|
||||
return;
|
||||
}
|
||||
for (SmartScriptHolder& scriptholder : e)
|
||||
@@ -3969,43 +3975,49 @@ void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEn
|
||||
void SmartScript::GetScript()
|
||||
{
|
||||
SmartAIEventList e;
|
||||
if (me)
|
||||
|
||||
// We must use script type to avoid ambiguities
|
||||
switch (mScriptType)
|
||||
{
|
||||
e = sSmartScriptMgr->GetScript(-((int32)me->GetSpawnId()), mScriptType);
|
||||
if (e.empty())
|
||||
e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType);
|
||||
FillScript(std::move(e), me, nullptr, nullptr, nullptr);
|
||||
}
|
||||
else if (go)
|
||||
{
|
||||
e = sSmartScriptMgr->GetScript(-((int32)go->GetSpawnId()), mScriptType);
|
||||
if (e.empty())
|
||||
e = sSmartScriptMgr->GetScript((int32)go->GetEntry(), mScriptType);
|
||||
FillScript(std::move(e), go, nullptr, nullptr, nullptr);
|
||||
}
|
||||
else if (trigger)
|
||||
{
|
||||
e = sSmartScriptMgr->GetScript((int32)trigger->ID, mScriptType);
|
||||
FillScript(std::move(e), nullptr, trigger, nullptr, nullptr);
|
||||
}
|
||||
else if (areaTrigger)
|
||||
{
|
||||
e = sSmartScriptMgr->GetScript((int32)areaTrigger->GetEntry(), mScriptType);
|
||||
FillScript(std::move(e), areaTrigger, nullptr, nullptr, nullptr);
|
||||
}
|
||||
else if (sceneTemplate)
|
||||
{
|
||||
e = sSmartScriptMgr->GetScript(sceneTemplate->SceneId, mScriptType);
|
||||
FillScript(std::move(e), nullptr, nullptr, sceneTemplate, nullptr);
|
||||
}
|
||||
else if (quest)
|
||||
{
|
||||
e = sSmartScriptMgr->GetScript(quest->GetQuestId(), mScriptType);
|
||||
FillScript(std::move(e), nullptr, nullptr, nullptr, quest);
|
||||
case SMART_SCRIPT_TYPE_CREATURE:
|
||||
e = sSmartScriptMgr->GetScript(-((int32)me->GetSpawnId()), mScriptType);
|
||||
if (e.empty())
|
||||
e = sSmartScriptMgr->GetScript((int32)me->GetEntry(), mScriptType);
|
||||
FillScript(std::move(e), me, nullptr, nullptr, nullptr, 0);
|
||||
break;
|
||||
case SMART_SCRIPT_TYPE_GAMEOBJECT:
|
||||
e = sSmartScriptMgr->GetScript(-((int32)go->GetSpawnId()), mScriptType);
|
||||
if (e.empty())
|
||||
e = sSmartScriptMgr->GetScript((int32)go->GetEntry(), mScriptType);
|
||||
FillScript(std::move(e), go, nullptr, nullptr, nullptr, 0);
|
||||
break;
|
||||
case SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY:
|
||||
case SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY_SERVERSIDE:
|
||||
e = sSmartScriptMgr->GetScript((int32)areaTrigger->GetEntry(), mScriptType);
|
||||
FillScript(std::move(e), areaTrigger, nullptr, nullptr, nullptr, 0);
|
||||
break;
|
||||
case SMART_SCRIPT_TYPE_AREATRIGGER:
|
||||
e = sSmartScriptMgr->GetScript((int32)trigger->ID, mScriptType);
|
||||
FillScript(std::move(e), nullptr, trigger, nullptr, nullptr, 0);
|
||||
break;
|
||||
case SMART_SCRIPT_TYPE_SCENE:
|
||||
e = sSmartScriptMgr->GetScript(sceneTemplate->SceneId, mScriptType);
|
||||
FillScript(std::move(e), nullptr, nullptr, sceneTemplate, nullptr, 0);
|
||||
break;
|
||||
case SMART_SCRIPT_TYPE_QUEST:
|
||||
e = sSmartScriptMgr->GetScript(quest->GetQuestId(), mScriptType);
|
||||
FillScript(std::move(e), nullptr, nullptr, nullptr, quest, 0);
|
||||
break;
|
||||
case SMART_SCRIPT_TYPE_EVENT:
|
||||
e = sSmartScriptMgr->GetScript((int32)event, mScriptType);
|
||||
FillScript(std::move(e), nullptr, nullptr, nullptr, nullptr, event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SmartScript::OnInitialize(WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene, Quest const* qst)
|
||||
void SmartScript::OnInitialize(WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene, Quest const* qst, uint32 evnt)
|
||||
{
|
||||
if (at)
|
||||
{
|
||||
@@ -4049,6 +4061,32 @@ void SmartScript::OnInitialize(WorldObject* obj, AreaTriggerEntry const* at, Sce
|
||||
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript::OnInitialize: source is Quest with id {}, triggered by player {}", qst->GetQuestId(), player->GetGUID().ToString());
|
||||
}
|
||||
else if (evnt)
|
||||
{
|
||||
mScriptType = SMART_SCRIPT_TYPE_EVENT;
|
||||
event = evnt;
|
||||
|
||||
if (obj->IsPlayer())
|
||||
{
|
||||
player = obj->ToPlayer();
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript::OnInitialize: source is Event {}, triggered by player {}", event, player->GetGUID().ToString());
|
||||
}
|
||||
else if (obj->IsCreature())
|
||||
{
|
||||
me = obj->ToCreature();
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript::OnInitialize: source is Event {}, triggered by creature {}", event, me->GetEntry());
|
||||
}
|
||||
else if (obj->IsGameObject())
|
||||
{
|
||||
go = obj->ToGameObject();
|
||||
TC_LOG_DEBUG("scripts.ai", "SmartScript::OnInitialize: source is Event {}, triggered by gameobject {}", event, go->GetEntry());
|
||||
}
|
||||
else
|
||||
{
|
||||
TC_LOG_ERROR("misc", "SmartScript::OnInitialize: source is Event {}, missing trigger WorldObject", event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (obj) // Handle object based scripts
|
||||
{
|
||||
switch (obj->GetTypeId())
|
||||
|
||||
@@ -38,9 +38,9 @@ class TC_GAME_API SmartScript
|
||||
SmartScript();
|
||||
~SmartScript();
|
||||
|
||||
void OnInitialize(WorldObject* obj, AreaTriggerEntry const* at = nullptr, SceneTemplate const* scene = nullptr, Quest const* qst = nullptr);
|
||||
void OnInitialize(WorldObject* obj, AreaTriggerEntry const* at = nullptr, SceneTemplate const* scene = nullptr, Quest const* qst = nullptr, uint32 evnt = 0);
|
||||
void GetScript();
|
||||
void FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene, Quest const* quest);
|
||||
void FillScript(SmartAIEventList e, WorldObject* obj, AreaTriggerEntry const* at, SceneTemplate const* scene, Quest const* quest, uint32 event = 0);
|
||||
|
||||
void ProcessEventsFor(SMART_EVENT e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = "");
|
||||
void ProcessEvent(SmartScriptHolder& e, Unit* unit = nullptr, uint32 var0 = 0, uint32 var1 = 0, bool bvar = false, SpellInfo const* spell = nullptr, GameObject* gob = nullptr, std::string const& varString = "");
|
||||
@@ -122,6 +122,7 @@ class TC_GAME_API SmartScript
|
||||
AreaTrigger* areaTrigger;
|
||||
SceneTemplate const* sceneTemplate;
|
||||
Quest const* quest;
|
||||
uint32 event;
|
||||
SmartScriptType mScriptType;
|
||||
uint32 mEventPhase;
|
||||
|
||||
|
||||
@@ -137,6 +137,15 @@ void SmartAIMgr::LoadSmartAIFromDB()
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_SCRIPT_TYPE_EVENT:
|
||||
{
|
||||
if (!sObjectMgr->IsValidEvent((uint32)temp.entryOrGuid))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Event id ({}) does not exist, skipped loading.", uint32(temp.entryOrGuid));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SMART_SCRIPT_TYPE_QUEST:
|
||||
{
|
||||
if (!sObjectMgr->GetQuestTemplate((uint32)temp.entryOrGuid))
|
||||
@@ -451,6 +460,7 @@ SmartScriptHolder& SmartAIMgr::FindLinkedEvent(SmartAIEventList& list, uint32 li
|
||||
case SMART_EVENT_SCENE_TRIGGER:
|
||||
case SMART_EVENT_SCENE_CANCEL:
|
||||
case SMART_EVENT_SCENE_COMPLETE:
|
||||
case SMART_EVENT_SEND_EVENT_TRIGGER:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -804,6 +814,7 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
|
||||
case SMART_EVENT_ON_SPELL_FAILED: return sizeof(SmartEvent::spellCast);
|
||||
case SMART_EVENT_ON_SPELL_START: return sizeof(SmartEvent::spellCast);
|
||||
case SMART_EVENT_ON_DESPAWN: return NO_PARAMS;
|
||||
case SMART_EVENT_SEND_EVENT_TRIGGER: return NO_PARAMS;
|
||||
default:
|
||||
TC_LOG_WARN("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} is using an event with no unused params specified in SmartAIMgr::CheckUnusedEventParams(), please report this.",
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
|
||||
@@ -1442,6 +1453,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_EVENT_SCENE_CANCEL:
|
||||
case SMART_EVENT_SCENE_COMPLETE:
|
||||
case SMART_EVENT_SCENE_TRIGGER:
|
||||
case SMART_EVENT_SEND_EVENT_TRIGGER:
|
||||
break;
|
||||
// Unused
|
||||
case SMART_EVENT_TARGET_HEALTH_PCT:
|
||||
|
||||
@@ -186,8 +186,9 @@ enum SMART_EVENT
|
||||
SMART_EVENT_ON_SPELL_FAILED = 84, // SpellID, CooldownMin, CooldownMax
|
||||
SMART_EVENT_ON_SPELL_START = 85, // SpellID, CooldownMin, CooldownMax
|
||||
SMART_EVENT_ON_DESPAWN = 86, // NONE
|
||||
SMART_EVENT_SEND_EVENT_TRIGGER = 87, // NONE
|
||||
|
||||
SMART_EVENT_END = 87
|
||||
SMART_EVENT_END = 88
|
||||
};
|
||||
|
||||
struct SmartEvent
|
||||
@@ -1444,18 +1445,18 @@ struct SmartTarget
|
||||
|
||||
enum SmartScriptType
|
||||
{
|
||||
SMART_SCRIPT_TYPE_CREATURE = 0, //done
|
||||
SMART_SCRIPT_TYPE_GAMEOBJECT = 1, //done
|
||||
SMART_SCRIPT_TYPE_AREATRIGGER = 2, //done
|
||||
SMART_SCRIPT_TYPE_EVENT = 3, //
|
||||
SMART_SCRIPT_TYPE_GOSSIP = 4, //
|
||||
SMART_SCRIPT_TYPE_QUEST = 5, //done
|
||||
SMART_SCRIPT_TYPE_SPELL = 6, //
|
||||
SMART_SCRIPT_TYPE_TRANSPORT = 7, //
|
||||
SMART_SCRIPT_TYPE_INSTANCE = 8, //
|
||||
SMART_SCRIPT_TYPE_TIMED_ACTIONLIST = 9, //
|
||||
SMART_SCRIPT_TYPE_SCENE = 10, //done
|
||||
SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY = 11,
|
||||
SMART_SCRIPT_TYPE_CREATURE = 0,
|
||||
SMART_SCRIPT_TYPE_GAMEOBJECT = 1,
|
||||
SMART_SCRIPT_TYPE_AREATRIGGER = 2,
|
||||
SMART_SCRIPT_TYPE_EVENT = 3,
|
||||
SMART_SCRIPT_TYPE_GOSSIP = 4, // NYI
|
||||
SMART_SCRIPT_TYPE_QUEST = 5,
|
||||
SMART_SCRIPT_TYPE_SPELL = 6, // NYI
|
||||
SMART_SCRIPT_TYPE_TRANSPORT = 7, // NYI
|
||||
SMART_SCRIPT_TYPE_INSTANCE = 8, // NYI
|
||||
SMART_SCRIPT_TYPE_TIMED_ACTIONLIST = 9,
|
||||
SMART_SCRIPT_TYPE_SCENE = 10,
|
||||
SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY = 11,
|
||||
SMART_SCRIPT_TYPE_AREATRIGGER_ENTITY_SERVERSIDE = 12,
|
||||
SMART_SCRIPT_TYPE_MAX
|
||||
};
|
||||
@@ -1582,6 +1583,7 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
|
||||
{SMART_EVENT_ON_SPELL_FAILED, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
||||
{SMART_EVENT_ON_SPELL_START, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
||||
{SMART_EVENT_ON_DESPAWN, SMART_SCRIPT_TYPE_MASK_CREATURE },
|
||||
{SMART_EVENT_SEND_EVENT_TRIGGER, SMART_SCRIPT_TYPE_MASK_EVENT }
|
||||
};
|
||||
|
||||
enum SmartEventFlags
|
||||
|
||||
@@ -270,7 +270,7 @@ public:
|
||||
}
|
||||
}();
|
||||
if (eventId)
|
||||
GameEvents::Trigger(eventId, &_owner, nullptr);
|
||||
GameEvents::Trigger(eventId, &_owner, &_owner);
|
||||
|
||||
if (_autoCycleBetweenStopFrames)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "Map.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "Util.h"
|
||||
#include "ZoneScript.h"
|
||||
|
||||
@@ -37,7 +38,8 @@ void GameEvents::Trigger(uint32 gameEventId, WorldObject* source, WorldObject* t
|
||||
if (zoneScript)
|
||||
zoneScript->ProcessEvent(target, gameEventId, source);
|
||||
|
||||
Map* map = refForMapAndZoneScript->GetMap();
|
||||
sScriptMgr->OnEventTrigger(target, source, gameEventId);
|
||||
|
||||
if (GameObject* goTarget = Object::ToGameObject(target))
|
||||
if (GameObjectAI* goAI = goTarget->AI())
|
||||
goAI->EventInform(gameEventId);
|
||||
@@ -45,6 +47,7 @@ void GameEvents::Trigger(uint32 gameEventId, WorldObject* source, WorldObject* t
|
||||
if (Player* sourcePlayer = Object::ToPlayer(source))
|
||||
TriggerForPlayer(gameEventId, sourcePlayer);
|
||||
|
||||
Map* map = refForMapAndZoneScript->GetMap();
|
||||
TriggerForMap(gameEventId, map, source, target);
|
||||
}
|
||||
|
||||
|
||||
@@ -5832,24 +5832,24 @@ void ObjectMgr::LoadSpellScripts()
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadEventScripts()
|
||||
void ObjectMgr::LoadEventSet()
|
||||
{
|
||||
LoadScripts(SCRIPTS_EVENT);
|
||||
_eventStore.clear();
|
||||
|
||||
std::set<uint32> evt_scripts;
|
||||
// Load all possible script entries from gameobjects
|
||||
// Load all possible event ids from gameobjects
|
||||
for (auto const& gameObjectTemplatePair : _gameObjectTemplateStore)
|
||||
if (uint32 eventId = gameObjectTemplatePair.second.GetEventScriptId())
|
||||
evt_scripts.insert(eventId);
|
||||
_eventStore.insert(eventId);
|
||||
|
||||
// Load all possible script entries from spells
|
||||
// Load all possible event ids from spells
|
||||
for (SpellNameEntry const* spellNameEntry : sSpellNameStore)
|
||||
if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(spellNameEntry->ID, DIFFICULTY_NONE))
|
||||
for (SpellEffectInfo const& spellEffectInfo : spell->GetEffects())
|
||||
if (spellEffectInfo.IsEffect(SPELL_EFFECT_SEND_EVENT))
|
||||
if (spellEffectInfo.MiscValue)
|
||||
evt_scripts.insert(spellEffectInfo.MiscValue);
|
||||
_eventStore.insert(spellEffectInfo.MiscValue);
|
||||
|
||||
// Load all possible event ids from taxi path nodes
|
||||
for (size_t path_idx = 0; path_idx < sTaxiPathNodesByPath.size(); ++path_idx)
|
||||
{
|
||||
for (size_t node_idx = 0; node_idx < sTaxiPathNodesByPath[path_idx].size(); ++node_idx)
|
||||
@@ -5857,21 +5857,58 @@ void ObjectMgr::LoadEventScripts()
|
||||
TaxiPathNodeEntry const* node = sTaxiPathNodesByPath[path_idx][node_idx];
|
||||
|
||||
if (node->ArrivalEventID)
|
||||
evt_scripts.insert(node->ArrivalEventID);
|
||||
_eventStore.insert(node->ArrivalEventID);
|
||||
|
||||
if (node->DepartureEventID)
|
||||
evt_scripts.insert(node->DepartureEventID);
|
||||
_eventStore.insert(node->DepartureEventID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadEventScripts()
|
||||
{
|
||||
// Set of valid events referenced in several sources
|
||||
LoadEventSet();
|
||||
|
||||
// Deprecated
|
||||
LoadScripts(SCRIPTS_EVENT);
|
||||
|
||||
// Then check if all scripts are in above list of possible script entries
|
||||
for (ScriptMapMap::const_iterator itr = sEventScripts.begin(); itr != sEventScripts.end(); ++itr)
|
||||
{
|
||||
std::set<uint32>::const_iterator itr2 = evt_scripts.find(itr->first);
|
||||
if (itr2 == evt_scripts.end())
|
||||
TC_LOG_ERROR("sql.sql", "Table `event_scripts` has script (Id: {}) not referring to any gameobject_template type 10 data2 field, type 3 data6 field, type 13 data 2 field or any spell effect {}",
|
||||
if (!IsValidEvent(itr->first))
|
||||
TC_LOG_ERROR("sql.sql", "Table `event_scripts` has script (Id: {}) not referring to any gameobject_template (type 3 data6 field, type 7 data3 field, type 10 data2 field, type 13 data2 field, type 50 data7 field), any taxi path node or any spell effect {}",
|
||||
itr->first, SPELL_EFFECT_SEND_EVENT);
|
||||
}
|
||||
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
_eventScriptStore.clear(); // Reload case
|
||||
|
||||
QueryResult result = WorldDatabase.Query("SELECT Id, ScriptName FROM event_script_names");
|
||||
if (!result)
|
||||
{
|
||||
TC_LOG_INFO("server.loading", ">> Loaded 0 event scripts. DB table `event_script_names` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 eventId = fields[0].GetUInt32();
|
||||
std::string const scriptName = fields[1].GetString();
|
||||
|
||||
if (!IsValidEvent(eventId))
|
||||
{
|
||||
TC_LOG_ERROR("sql.sql", "Event (ID: {}) not referring to any gameobject_template (type 3 data6 field, type 7 data3 field, type 10 data2 field, type 13 data2 field, type 50 data7 field), any taxi path node or any spell effect {}",
|
||||
eventId, SPELL_EFFECT_SEND_EVENT);
|
||||
continue;
|
||||
}
|
||||
_eventScriptStore[eventId] = GetScriptId(scriptName);
|
||||
} while (result->NextRow());
|
||||
|
||||
TC_LOG_INFO("server.loading", ">> Loaded {} event scripts in {} ms", _eventScriptStore.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
//Load WP Scripts
|
||||
@@ -8982,6 +9019,14 @@ SpellScriptsBounds ObjectMgr::GetSpellScriptsBounds(uint32 spellId)
|
||||
return SpellScriptsBounds(_spellScriptsStore.equal_range(spellId));
|
||||
}
|
||||
|
||||
uint32 ObjectMgr::GetEventScriptId(uint32 eventId) const
|
||||
{
|
||||
EventScriptContainer::const_iterator i = _eventScriptStore.find(eventId);
|
||||
if (i != _eventScriptStore.end())
|
||||
return i->second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// this allows calculating base reputations to offline players, just by race and class
|
||||
int32 ObjectMgr::GetBaseReputationOf(FactionEntry const* factionEntry, uint8 race, uint8 playerClass) const
|
||||
{
|
||||
|
||||
@@ -1096,6 +1096,9 @@ class TC_GAME_API ObjectMgr
|
||||
|
||||
typedef std::unordered_map<uint64, AccessRequirement> AccessRequirementContainer;
|
||||
|
||||
typedef std::set<uint32> EventContainer;
|
||||
typedef std::unordered_map<uint32, uint32> EventScriptContainer;
|
||||
|
||||
typedef std::unordered_map<uint32, RepRewardRate > RepRewardRateContainer;
|
||||
typedef std::unordered_map<uint32, ReputationOnKillEntry> RepOnKillContainer;
|
||||
typedef std::unordered_map<uint32, RepSpilloverTemplate> RepSpilloverTemplateContainer;
|
||||
@@ -1218,6 +1221,11 @@ class TC_GAME_API ObjectMgr
|
||||
return _gameObjectForQuestStore.find(entry) != _gameObjectForQuestStore.end();
|
||||
}
|
||||
|
||||
bool IsValidEvent(uint32 eventId) const
|
||||
{
|
||||
return _eventStore.find(eventId) != _eventStore.end();
|
||||
}
|
||||
|
||||
NpcText const* GetNpcText(uint32 textID) const;
|
||||
QuestGreeting const* GetQuestGreeting(TypeID type, uint32 id) const;
|
||||
QuestGreetingLocale const* GetQuestGreetingLocale(TypeID type, uint32 id) const;
|
||||
@@ -1238,6 +1246,7 @@ class TC_GAME_API ObjectMgr
|
||||
AreaTriggerStruct const* GetMapEntranceTrigger(uint32 Map) const;
|
||||
|
||||
uint32 GetAreaTriggerScriptId(uint32 trigger_id) const;
|
||||
uint32 GetEventScriptId(uint32 eventId) const;
|
||||
SpellScriptsBounds GetSpellScriptsBounds(uint32 spellId);
|
||||
|
||||
RepRewardRate const* GetRepRewardRate(uint32 factionId) const
|
||||
@@ -1810,6 +1819,9 @@ class TC_GAME_API ObjectMgr
|
||||
DungeonEncounterContainer _dungeonEncounterStore;
|
||||
std::unordered_map<uint32, WorldSafeLocsEntry> _worldSafeLocs;
|
||||
|
||||
EventContainer _eventStore;
|
||||
EventScriptContainer _eventScriptStore;
|
||||
|
||||
RepRewardRateContainer _repRewardRateStore;
|
||||
RepOnKillContainer _repOnKillStore;
|
||||
RepSpilloverTemplateContainer _repSpilloverTemplateStore;
|
||||
@@ -1864,6 +1876,7 @@ class TC_GAME_API ObjectMgr
|
||||
std::unordered_map<uint32, std::vector<TerrainSwapInfo*>> _terrainSwapInfoByMap;
|
||||
|
||||
private:
|
||||
void LoadEventSet();
|
||||
void LoadScripts(ScriptsType type);
|
||||
void LoadQuestRelationsHelper(QuestRelations& map, QuestRelationsReverse* reverseMap, std::string const& table);
|
||||
QuestRelationResult GetQuestRelationsFrom(QuestRelations const& map, uint32 key, bool onlyActive) const { return { map.equal_range(key), onlyActive }; }
|
||||
|
||||
@@ -87,7 +87,7 @@ struct is_script_database_bound<AreaTriggerScript>
|
||||
|
||||
template<>
|
||||
struct is_script_database_bound<BattlefieldScript>
|
||||
: std::true_type { };
|
||||
: std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_script_database_bound<BattlegroundScript>
|
||||
@@ -137,6 +137,10 @@ template<>
|
||||
struct is_script_database_bound<WorldStateScript>
|
||||
: std::true_type { };
|
||||
|
||||
template<>
|
||||
struct is_script_database_bound<EventScript>
|
||||
: std::true_type { };
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_HOTSWAP_VISUAL_SPELL_EFFECT = 40162 // 59084
|
||||
@@ -2358,6 +2362,15 @@ void ScriptMgr::OnWorldStateValueChange(WorldStateTemplate const* worldStateTemp
|
||||
tmpscript->OnValueChange(worldStateTemplate->Id, oldValue, newValue, map);
|
||||
}
|
||||
|
||||
// Event
|
||||
void ScriptMgr::OnEventTrigger(WorldObject* object, WorldObject* invoker, uint32 eventId)
|
||||
{
|
||||
ASSERT(invoker);
|
||||
|
||||
GET_SCRIPT(EventScript, sObjectMgr->GetEventScriptId(eventId), tmpscript);
|
||||
tmpscript->OnTrigger(object, invoker, eventId);
|
||||
}
|
||||
|
||||
SpellScriptLoader::SpellScriptLoader(char const* name)
|
||||
: ScriptObject(name)
|
||||
{
|
||||
@@ -3209,6 +3222,18 @@ void WorldStateScript::OnValueChange(int32 /*worldStateId*/, int32 /*oldValue*/,
|
||||
{
|
||||
}
|
||||
|
||||
EventScript::EventScript(char const* name)
|
||||
: ScriptObject(name)
|
||||
{
|
||||
ScriptRegistry<EventScript>::Instance()->AddScript(this);
|
||||
}
|
||||
|
||||
EventScript::~EventScript() = default;
|
||||
|
||||
void EventScript::OnTrigger(WorldObject* /*object*/, WorldObject* /*invoker*/, uint32 /*eventId*/)
|
||||
{
|
||||
}
|
||||
|
||||
// Specialize for each script type class like so:
|
||||
template class TC_GAME_API ScriptRegistry<SpellScriptLoader>;
|
||||
template class TC_GAME_API ScriptRegistry<ServerScript>;
|
||||
@@ -3243,3 +3268,4 @@ template class TC_GAME_API ScriptRegistry<ConversationScript>;
|
||||
template class TC_GAME_API ScriptRegistry<SceneScript>;
|
||||
template class TC_GAME_API ScriptRegistry<QuestScript>;
|
||||
template class TC_GAME_API ScriptRegistry<WorldStateScript>;
|
||||
template class TC_GAME_API ScriptRegistry<EventScript>;
|
||||
|
||||
@@ -990,6 +990,20 @@ class TC_GAME_API WorldStateScript : public ScriptObject
|
||||
virtual void OnValueChange(int32 worldStateId, int32 oldValue, int32 newValue, Map const* map);
|
||||
};
|
||||
|
||||
class TC_GAME_API EventScript : public ScriptObject
|
||||
{
|
||||
protected:
|
||||
|
||||
explicit EventScript(char const* name);
|
||||
|
||||
public:
|
||||
|
||||
~EventScript();
|
||||
|
||||
// Called when a game event is triggered
|
||||
virtual void OnTrigger(WorldObject* object, WorldObject* invoker, uint32 eventId);
|
||||
};
|
||||
|
||||
// Manages registration, loading, and execution of scripts.
|
||||
class TC_GAME_API ScriptMgr
|
||||
{
|
||||
@@ -1296,6 +1310,10 @@ class TC_GAME_API ScriptMgr
|
||||
|
||||
void OnWorldStateValueChange(WorldStateTemplate const* worldStateTemplate, int32 oldValue, int32 newValue, Map const* map);
|
||||
|
||||
public: /* EventScript */
|
||||
|
||||
void OnEventTrigger(WorldObject* object, WorldObject* invoker, uint32 eventId);
|
||||
|
||||
private:
|
||||
uint32 _scriptCount;
|
||||
bool _scriptIdUpdated;
|
||||
|
||||
Reference in New Issue
Block a user