diff --git a/sql/mangos.sql b/sql/mangos.sql index f53bb268e..397bbb73d 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_10289_02_mangos_creature_model_info` bit(1) default NULL + `required_10299_01_mangos_event_id_scripts` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -1417,6 +1417,26 @@ LOCK TABLES `creature_ai_texts` WRITE; /*!40000 ALTER TABLE `creature_ai_texts` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `event_id_scripts` +-- + +DROP TABLE IF EXISTS `event_id_scripts`; +CREATE TABLE `event_id_scripts` ( + `id` mediumint(8) NOT NULL, + `ScriptName` char(64) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Script library scripted events'; + +-- +-- Dumping data for table `event_id_scripts` +-- + +LOCK TABLES `event_id_scripts` WRITE; +/*!40000 ALTER TABLE `event_id_scripts` DISABLE KEYS */; +/*!40000 ALTER TABLE `event_id_scripts` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `event_scripts` -- diff --git a/sql/updates/10299_01_mangos_event_id_scripts.sql b/sql/updates/10299_01_mangos_event_id_scripts.sql new file mode 100644 index 000000000..b0a1b3c25 --- /dev/null +++ b/sql/updates/10299_01_mangos_event_id_scripts.sql @@ -0,0 +1,8 @@ +ALTER TABLE db_version CHANGE COLUMN required_10289_02_mangos_creature_model_info required_10299_01_mangos_event_id_scripts bit; + +DROP TABLE IF EXISTS `event_id_scripts`; +CREATE TABLE `event_id_scripts` ( + `id` mediumint(8) NOT NULL, + `ScriptName` char(64) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Script library scripted events'; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 99f96313b..3789ec946 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -60,6 +60,7 @@ pkgdata_DATA = \ 10286_01_mangos_creature_addon.sql \ 10289_01_mangos_creature_template.sql \ 10289_02_mangos_creature_model_info.sql \ + 10299_01_mangos_event_id_scripts.sql \ README ## Additional files to include when running 'make dist' @@ -100,4 +101,5 @@ EXTRA_DIST = \ 10286_01_mangos_creature_addon.sql \ 10289_01_mangos_creature_template.sql \ 10289_02_mangos_creature_model_info.sql \ + 10299_01_mangos_event_id_scripts.sql \ README diff --git a/src/bindings/universal/ScriptMgr.cpp b/src/bindings/universal/ScriptMgr.cpp index d5994a59f..0d1c5f535 100644 --- a/src/bindings/universal/ScriptMgr.cpp +++ b/src/bindings/universal/ScriptMgr.cpp @@ -288,6 +288,17 @@ bool AreaTrigger ( Player *player, AreaTriggerEntry* atEntry ) return tmpscript->pAreaTrigger(player, atEntry); } +MANGOS_DLL_EXPORT +bool ProcessEventId(uint32 eventId, Object* source, Object* target, bool data) +{ + Script *tmpscript = m_scripts[GetEventIdScriptId(eventId)]; + if (!tmpscript || !tmpscript->pProcessEventId) + return false; + + // data normally false, true for taxi event id where it's a departure + return tmpscript->pProcessEventId(eventId, source, target, data); +} + MANGOS_DLL_EXPORT bool ItemUse( Player *player, Item* _Item, SpellCastTargets const& targets) { diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index e5e27f216..cc3cdd816 100644 --- a/src/bindings/universal/ScriptMgr.h +++ b/src/bindings/universal/ScriptMgr.h @@ -42,7 +42,7 @@ struct Script pGossipHello(NULL), pGOGossipHello(NULL), pQuestAccept(NULL), pGossipSelect(NULL), pGOGossipSelect(NULL), pGossipSelectWithCode(NULL), pGOGossipSelectWithCode(NULL), pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL), pChooseReward(NULL), - pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), pGOQuestAccept(NULL), + pItemHello(NULL), pGOHello(NULL), pProcessEventId(NULL), pAreaTrigger(NULL), pItemQuestAccept(NULL), pGOQuestAccept(NULL), pGOChooseReward(NULL), pItemUse(NULL), pEffectDummyGameObj(NULL), pEffectDummyCreature(NULL), pEffectDummyItem(NULL), pEffectAuraDummy(NULL), GetAI(NULL) {} @@ -65,6 +65,7 @@ struct Script bool (*pItemHello )(Player *player, Item *_Item, Quest const*_Quest ); bool (*pGOHello )(Player *player, GameObject *_GO ); bool (*pAreaTrigger )(Player *player, AreaTriggerEntry* at); + bool (*pProcessEventId )(uint32 eventId, Object* source, Object* target, bool data); bool (*pItemQuestAccept )(Player *player, Item *_Item, Quest const*_Quest ); bool (*pGOQuestAccept )(Player *player, GameObject *_GO, Quest const*_Quest ); bool (*pGOChooseReward )(Player *player, GameObject *_GO, Quest const*_Quest, uint32 opt ); diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 461f5305a..654035d7a 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -912,7 +912,9 @@ void GameObject::Use(Unit* user) if (GetGOInfo()->chest.eventId) { DEBUG_LOG("Chest ScriptStart id %u for GO %u", GetGOInfo()->chest.eventId, GetDBTableGUIDLow()); - GetMap()->ScriptsStart(sEventScripts, GetGOInfo()->chest.eventId, user, this); + + if (!Script->ProcessEventId(GetGOInfo()->chest.eventId, user, this, false)) + GetMap()->ScriptsStart(sEventScripts, GetGOInfo()->chest.eventId, user, this); } // triggering linked GO @@ -1016,7 +1018,9 @@ void GameObject::Use(Unit* user) if (info->goober.eventId) { DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Goober ScriptStart id %u for GO entry %u (GUID %u).", info->goober.eventId, GetEntry(), GetDBTableGUIDLow()); - GetMap()->ScriptsStart(sEventScripts, info->goober.eventId, player, this); + + if (!Script->ProcessEventId(info->goober.eventId, player, this, false)) + GetMap()->ScriptsStart(sEventScripts, info->goober.eventId, player, this); } // possible quest objective for active quests @@ -1077,7 +1081,10 @@ void GameObject::Use(Unit* user) player->SendCinematicStart(info->camera.cinematicId); if (info->camera.eventID) - GetMap()->ScriptsStart(sEventScripts, info->camera.eventID, player, this); + { + if (!Script->ProcessEventId(info->camera.eventID, player, this, false)) + GetMap()->ScriptsStart(sEventScripts, info->camera.eventID, player, this); + } return; } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index d40f86e47..14747ba81 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -5242,6 +5242,90 @@ void ObjectMgr::LoadAreaTriggerScripts() sLog.outString( ">> Loaded %u areatrigger scripts", count ); } +void ObjectMgr::LoadEventIdScripts() +{ + mEventIdScripts.clear(); // need for reload case + QueryResult *result = WorldDatabase.Query("SELECT id, ScriptName FROM event_id_scripts"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u event id scripts", count ); + return; + } + + barGoLink bar( (int)result->GetRowCount() ); + + // TODO: remove duplicate code below, same way to collect event id's used in LoadEventScripts() + std::set evt_scripts; + + // Load all possible event entries from gameobjects + for(uint32 i = 1; i < sGOStorage.MaxEntry; ++i) + if (GameObjectInfo const * goInfo = sGOStorage.LookupEntry(i)) + if (uint32 eventId = goInfo->GetEventScriptId()) + evt_scripts.insert(eventId); + + // Load all possible event entries from spells + for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) + { + SpellEntry const * spell = sSpellStore.LookupEntry(i); + if (spell) + { + for(int j = 0; j < MAX_EFFECT_INDEX; ++j) + { + if( spell->Effect[j] == SPELL_EFFECT_SEND_EVENT ) + { + if (spell->EffectMiscValue[j]) + evt_scripts.insert(spell->EffectMiscValue[j]); + } + } + } + } + + // Load all possible event entries 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) + { + TaxiPathNodeEntry const& node = sTaxiPathNodesByPath[path_idx][node_idx]; + + if (node.arrivalEventID) + evt_scripts.insert(node.arrivalEventID); + + if (node.departureEventID) + evt_scripts.insert(node.departureEventID); + } + } + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 eventId = fields[0].GetUInt32(); + const char *scriptName = fields[1].GetString(); + + std::set::const_iterator itr = evt_scripts.find(eventId); + if (itr == evt_scripts.end()) + sLog.outErrorDb("Table `event_id_scripts` has id %u not referring to any gameobject_template type 10 data2 field, type 3 data6 field, type 13 data 2 field or any spell effect %u or path taxi node data", + eventId, SPELL_EFFECT_SEND_EVENT); + + mEventIdScripts[eventId] = GetScriptId(scriptName); + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u event id scripts", count ); +} + uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid, uint32 team ) { bool found = false; @@ -7624,6 +7708,15 @@ uint32 ObjectMgr::GetAreaTriggerScriptId(uint32 trigger_id) return 0; } +uint32 ObjectMgr::GetEventIdScriptId(uint32 eventId) +{ + EventIdScriptMap::const_iterator i = mEventIdScripts.find(eventId); + if (i!= mEventIdScripts.end()) + return i->second; + + return 0; +} + // Checks if player meets the condition bool PlayerCondition::Meets(Player const * player) const { @@ -8768,6 +8861,8 @@ void ObjectMgr::LoadScriptNames() "UNION " "SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' " "UNION " + "SELECT DISTINCT(ScriptName) FROM event_id_scripts WHERE ScriptName <> '' " + "UNION " "SELECT DISTINCT(script) FROM instance_template WHERE script <> ''"); if( !result ) @@ -8887,6 +8982,11 @@ uint32 GetAreaTriggerScriptId(uint32 trigger_id) return sObjectMgr.GetAreaTriggerScriptId(trigger_id); } +uint32 GetEventIdScriptId(uint32 eventId) +{ + return sObjectMgr.GetEventIdScriptId(eventId); +} + bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value, int32 end_value) { // MAX_DB_SCRIPT_STRING_ID is max allowed negative value for scripts (scrpts can use only more deep negative values diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 83bf5427c..027fa3387 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -476,6 +476,7 @@ class ObjectMgr typedef UNORDERED_MAP AreaTriggerMap; typedef UNORDERED_MAP AreaTriggerScriptMap; + typedef UNORDERED_MAP EventIdScriptMap; typedef UNORDERED_MAP RepRewardRateMap; typedef UNORDERED_MAP RepOnKillMap; @@ -611,6 +612,7 @@ class ObjectMgr AreaTrigger const* GetMapEntranceTrigger(uint32 Map) const; uint32 GetAreaTriggerScriptId(uint32 trigger_id); + uint32 GetEventIdScriptId(uint32 eventId); RepRewardRate const* GetRepRewardRate(uint32 factionId) const { @@ -712,6 +714,7 @@ class ObjectMgr void LoadAreaTriggerTeleports(); void LoadQuestAreaTriggers(); void LoadAreaTriggerScripts(); + void LoadEventIdScripts(); void LoadTavernAreaTriggers(); void LoadGameObjectForQuests(); @@ -1047,7 +1050,9 @@ class ObjectMgr GameObjectForQuestSet mGameObjectForQuestSet; GossipTextMap mGossipText; AreaTriggerMap mAreaTriggers; - AreaTriggerScriptMap mAreaTriggerScripts; + + AreaTriggerScriptMap mAreaTriggerScripts; + EventIdScriptMap mEventIdScripts; RepRewardRateMap m_RepRewardRateMap; RepOnKillMap mRepOnKill; @@ -1140,6 +1145,7 @@ class ObjectMgr // scripting access functions MANGOS_DLL_SPEC bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value = MAX_CREATURE_AI_TEXT_STRING_ID, int32 end_value = std::numeric_limits::min()); MANGOS_DLL_SPEC uint32 GetAreaTriggerScriptId(uint32 trigger_id); +MANGOS_DLL_SPEC uint32 GetEventIdScriptId(uint32 event_id); MANGOS_DLL_SPEC uint32 GetScriptId(const char *name); MANGOS_DLL_SPEC ObjectMgr::ScriptNameMap& GetScriptNames(); MANGOS_DLL_SPEC CreatureInfo const* GetCreatureTemplateStore(uint32 entry); diff --git a/src/game/ScriptCalls.cpp b/src/game/ScriptCalls.cpp index c5f77ddde..35f9b664b 100644 --- a/src/game/ScriptCalls.cpp +++ b/src/game/ScriptCalls.cpp @@ -73,6 +73,7 @@ bool LoadScriptingModule(char const* libName) ||!(testScript->ItemHello =(scriptCallItemHello )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemHello" )) ||!(testScript->GOHello =(scriptCallGOHello )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GOHello" )) ||!(testScript->scriptAreaTrigger =(scriptCallAreaTrigger )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"AreaTrigger" )) + ||!(testScript->ProcessEventId =(scriptCallProcessEventId )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ProcessEventId" )) ||!(testScript->ItemQuestAccept =(scriptCallItemQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemQuestAccept" )) ||!(testScript->GOQuestAccept =(scriptCallGOQuestAccept )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"GOQuestAccept" )) ||!(testScript->ItemUse =(scriptCallItemUse )MANGOS_GET_PROC_ADDR(testScript->hScriptsLib,"ItemUse" )) diff --git a/src/game/ScriptCalls.h b/src/game/ScriptCalls.h index 7747c917f..5b7977403 100644 --- a/src/game/ScriptCalls.h +++ b/src/game/ScriptCalls.h @@ -55,6 +55,7 @@ typedef bool(MANGOS_IMPORT * scriptCallChooseReward)( Player *player, Creature * typedef bool(MANGOS_IMPORT * scriptCallItemHello)( Player *player, Item *, Quest const*); typedef bool(MANGOS_IMPORT * scriptCallGOHello)( Player *player, GameObject * ); typedef bool(MANGOS_IMPORT * scriptCallAreaTrigger)( Player *player, AreaTriggerEntry const* ); +typedef bool(MANGOS_IMPORT * scriptCallProcessEventId)(uint32 eventId, Object* source, Object* target, bool data); typedef bool(MANGOS_IMPORT * scriptCallItemQuestAccept)(Player *player, Item *, Quest const*); typedef bool(MANGOS_IMPORT * scriptCallGOQuestAccept)(Player *player, GameObject *, Quest const*); typedef bool(MANGOS_IMPORT * scriptCallGOChooseReward)(Player *player, GameObject *, Quest const*, uint32 opt ); @@ -88,6 +89,7 @@ typedef struct scriptCallItemHello ItemHello; scriptCallGOHello GOHello; scriptCallAreaTrigger scriptAreaTrigger; + scriptCallProcessEventId ProcessEventId; scriptCallItemQuestAccept ItemQuestAccept; scriptCallGOQuestAccept GOQuestAccept; scriptCallItemUse ItemUse; diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 15dc8e5cd..4d4b1bd08 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3096,7 +3096,9 @@ void Spell::EffectSendEvent(SpellEffectIndex effectIndex) we do not handle a flag dropping or clicking on flag in battleground by sendevent system */ DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[effectIndex], m_spellInfo->Id); - m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[effectIndex], m_caster, focusObject); + + if (!Script->ProcessEventId(m_spellInfo->EffectMiscValue[effectIndex], m_caster, focusObject, false)) + m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[effectIndex], m_caster, focusObject); } void Spell::EffectPowerBurn(SpellEffectIndex eff_idx) diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index f8fd16e81..cef0579b0 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -27,6 +27,7 @@ #include "WorldPacket.h" #include "DBCStores.h" #include "ProgressBar.h" +#include "ScriptCalls.h" void MapManager::LoadTransports() { @@ -566,6 +567,8 @@ void Transport::DoEventIfAny(WayPointMap::value_type const& node, bool departure if (uint32 eventid = departure ? node.second.departureEventID : node.second.arrivalEventID) { DEBUG_FILTER_LOG(LOG_FILTER_TRANSPORT_MOVES, "Taxi %s event %u of node %u of %s (%s) path", departure ? "departure" : "arrival", eventid, node.first, GetName(), GetObjectGuid().GetString().c_str()); - GetMap()->ScriptsStart(sEventScripts, eventid, this, this); + + if (!Script->ProcessEventId(eventid, this, this, departure)) + GetMap()->ScriptsStart(sEventScripts, eventid, this, this); } } diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp index f62184f97..502708f18 100644 --- a/src/game/WaypointMovementGenerator.cpp +++ b/src/game/WaypointMovementGenerator.cpp @@ -39,6 +39,7 @@ alter table creature_movement add `wpguid` int(11) default '0'; #include "CreatureAI.h" #include "WaypointManager.h" #include "WorldPacket.h" +#include "ScriptCalls.h" #include @@ -412,7 +413,9 @@ void FlightPathMovementGenerator::DoEventIfAny(Player& player, TaxiPathNodeEntry if (uint32 eventid = departure ? node.departureEventID : node.arrivalEventID) { DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.index, node.path, player.GetName()); - player.GetMap()->ScriptsStart(sEventScripts, eventid, &player, &player); + + if (!Script->ProcessEventId(eventid, &player, &player, departure)) + player.GetMap()->ScriptsStart(sEventScripts, eventid, &player, &player); } } diff --git a/src/game/World.cpp b/src/game/World.cpp index 2ff58a000..28393bdfd 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1087,6 +1087,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading AreaTrigger script names..." ); sObjectMgr.LoadAreaTriggerScripts(); + sLog.outString( "Loading event id script names..." ); + sObjectMgr.LoadEventIdScripts(); + sLog.outString( "Loading Graveyard-zone links..."); sObjectMgr.LoadGraveyardZones(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 958a8e02a..f1a5be3ef 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10298" + #define REVISION_NR "10299" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 067b46cd5..6e3de8355 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_10254_01_characters_auctionhouse" - #define REVISION_DB_MANGOS "required_10289_02_mangos_creature_model_info" + #define REVISION_DB_MANGOS "required_10299_01_mangos_event_id_scripts" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version" #endif // __REVISION_SQL_H__