[10299] Add new script call ProcessEventId

Let script library know when some event is about to start. Event id's may be found in several sources, such as spells, GO's and transport/taxi paths.
Database scripts may be prevented by returning true from script side whenever needed. If false, DB script will run like normal.
New database table event_id_scripts will need a ScriptName for the event id, in same way as for example areatrigger_scripts.

Signed-off-by: NoFantasy <nofantasy@nf.no>
This commit is contained in:
NoFantasy 2010-07-31 17:51:49 +02:00
parent 28d1ac66c3
commit 2ad9cd34b2
16 changed files with 180 additions and 11 deletions

View file

@ -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`
--

View file

@ -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';

View file

@ -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

View file

@ -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)
{

View file

@ -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 );

View file

@ -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;
}

View file

@ -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<uint32> evt_scripts;
// Load all possible event entries from gameobjects
for(uint32 i = 1; i < sGOStorage.MaxEntry; ++i)
if (GameObjectInfo const * goInfo = sGOStorage.LookupEntry<GameObjectInfo>(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<uint32>::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

View file

@ -476,6 +476,7 @@ class ObjectMgr
typedef UNORDERED_MAP<uint32, AreaTrigger> AreaTriggerMap;
typedef UNORDERED_MAP<uint32, uint32> AreaTriggerScriptMap;
typedef UNORDERED_MAP<uint32, uint32> EventIdScriptMap;
typedef UNORDERED_MAP<uint32, RepRewardRate > RepRewardRateMap;
typedef UNORDERED_MAP<uint32, ReputationOnKillEntry> 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<int32>::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);

View file

@ -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" ))

View file

@ -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;

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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 <cassert>
@ -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);
}
}

View file

@ -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();

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10298"
#define REVISION_NR "10299"
#endif // __REVISION_NR_H__

View file

@ -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__