[8252] Move DB scripting code from global World to Map. Author: Ambal
This one more step to pre-map events proccesing and parallel in future.
[8256] Restore DB script loading broken after [8252]. Author: VladimirMangos
Also propetly decrease scheduled DB script actions at map unloading.
Some code style restore.
--HG--
branch : trunk
This commit is contained in:
+33
-21
@@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`;
|
||||
CREATE TABLE `db_version` (
|
||||
`version` varchar(120) default NULL,
|
||||
`creature_ai_version` varchar(120) default NULL,
|
||||
`required_8251_03_mangos_spell_proc_event` bit(1) default NULL
|
||||
`required_8254_01_mangos_spell_proc_event` bit(1) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
|
||||
|
||||
--
|
||||
@@ -15654,7 +15654,7 @@ INSERT INTO spell_chain VALUES
|
||||
(27219,11700,689,7,0),
|
||||
(27220,27219,689,8,0),
|
||||
(47857,27220,689,9,0),
|
||||
/*DrainSoul*/
|
||||
/*Drain Soul*/
|
||||
(1120,0,1120,1,0),
|
||||
(8288,1120,1120,2,0),
|
||||
(8289,8288,1120,3,0),
|
||||
@@ -15670,14 +15670,20 @@ INSERT INTO spell_chain VALUES
|
||||
(59161,48181,48181,2,0),
|
||||
(59163,59161,48181,3,0),
|
||||
(59164,59163,48181,4,0),
|
||||
/*HowlofTerror*/
|
||||
/*Howl of Terror*/
|
||||
(5484,0,5484,1,0),
|
||||
(17928,5484,5484,2,0),
|
||||
/*SeedofCorruption*/
|
||||
/*Seed of Corruption*/
|
||||
(27243,0,27243,1,0),
|
||||
(47835,27243,27243,2,0),
|
||||
(47836,47835,27243,3,0),
|
||||
/*UnstableAffliction*/
|
||||
/* Shadow embrace */
|
||||
(32385,0,32385,1,0),
|
||||
(32387,32385,32385,2,0),
|
||||
(32392,32387,32385,3,0),
|
||||
(32393,32392,32385,4,0),
|
||||
(32394,32393,32385,5,0),
|
||||
/*Unstable Affliction*/
|
||||
(30108,0,30108,1,0),
|
||||
(30404,30108,30108,2,0),
|
||||
(30405,30404,30108,3,0),
|
||||
@@ -15776,6 +15782,12 @@ INSERT INTO spell_chain VALUES
|
||||
(26372,26371,26364,9,0),
|
||||
(49278,26372,26364,10,0),
|
||||
(49279,49278,26364,11,0),
|
||||
/*Maelstrom Weapon*/
|
||||
(51528,0,51528,1,0),
|
||||
(51529,51528,51528,2,0),
|
||||
(51530,51529,51528,3,0),
|
||||
(51531,51530,51528,4,0),
|
||||
(51532,51531,51528,5,0),
|
||||
/*Nature Resistance Totem*/
|
||||
(10595,0,10595,1,0),
|
||||
(10600,10595,10595,2,0),
|
||||
@@ -17233,7 +17245,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(12999, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4.000000, 0.000000, 0),
|
||||
(13000, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 6.000000, 0.000000, 0),
|
||||
(13001, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 8.000000, 0.000000, 0),
|
||||
(13002, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 10.000000, 0.000000, 0),
|
||||
(13002, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,10.000000, 0.000000, 0),
|
||||
(13045, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(13046, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(13047, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
@@ -17327,8 +17339,8 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(20131, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
(20132, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
(20164, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5.000000, 0.000000, 0),
|
||||
(20165, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20.000000, 0.000000, 0),
|
||||
(20166, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20.000000, 0.000000, 0),
|
||||
(20165, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,20.000000, 0.000000, 0),
|
||||
(20166, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,15.000000, 0.000000, 0),
|
||||
(20182, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
(20210, 0x00000000, 10, 0xC0000000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(20212, 0x00000000, 10, 0xC0000000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
@@ -17366,7 +17378,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(24353, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(24389, 0x00000000, 3, 0x00C00017, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(24658, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00014110, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(24905, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 15.000000, 0.000000, 0),
|
||||
(24905, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002,15.000000, 0.000000, 0),
|
||||
(24932, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 6),
|
||||
(25050, 0x00000004, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(25669, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1.000000, 0.000000, 0),
|
||||
@@ -17462,7 +17474,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(31570, 0x00000000, 3, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31785, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00008800, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31794, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0),
|
||||
(31801, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20.000000, 0.000000, 0),
|
||||
(31801, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,20.000000, 0.000000, 0),
|
||||
(31833, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31835, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31836, 0x00000000, 10, 0x80000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
@@ -17472,11 +17484,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(31877, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31878, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000008, 0x00004110, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(31904, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
(32385, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32387, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32392, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32393, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32394, 0x00000000, 5, 0x00000402, 0x00000011, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32385, 0x00000000, 5, 0x00000001, 0x00040000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32409, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(32587, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
(32642, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0.000000, 0.000000, 0),
|
||||
@@ -17752,6 +17760,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(51483, 0x00000001, 11, 0x20000000, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(51485, 0x00000001, 11, 0x20000000, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(51486, 0x00000001, 11, 0x20000000, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(51528, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,12.500000, 0.000000, 0),
|
||||
(51556, 0x00000000, 11, 0x000000C0, 0x00000000, 0x00000010, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(51557, 0x00000000, 11, 0x000000C0, 0x00000000, 0x00000010, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(51558, 0x00000000, 11, 0x000000C0, 0x00000000, 0x00000010, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
@@ -17781,12 +17790,12 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(51698, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 1),
|
||||
(51700, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 1),
|
||||
(51701, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 1),
|
||||
(51940, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(51989, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(52004, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(52005, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(52007, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(52008, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 20.000000, 0),
|
||||
(51940, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(51989, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(52004, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(52005, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(52007, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(52008, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000,20.000000, 0),
|
||||
(52020, 0x00000000, 7, 0x00008000, 0x00100000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(52127, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 3),
|
||||
(52420, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 30),
|
||||
@@ -17857,6 +17866,7 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(55677, 0x00000000, 6, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(55680, 0x00000000, 6, 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(55689, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
(55747, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(55768, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(55776, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(56218, 0x00000000, 5, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
@@ -17904,6 +17914,8 @@ INSERT INTO `spell_proc_event` VALUES
|
||||
(60132, 0x00000000, 15, 0x00000000, 0x08020000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(60170, 0x00000000, 5, 0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(60172, 0x00000000, 5, 0x00040000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0),
|
||||
(60436, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(60442, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(60493, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
|
||||
(60503, 0x00000000, 4, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
|
||||
(60537, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
|
||||
|
||||
@@ -949,7 +949,7 @@ void GameObject::Use(Unit* user)
|
||||
UseDoorOrButton();
|
||||
|
||||
// activate script
|
||||
sWorld.ScriptsStart(sGameObjectScripts, GetDBTableGUIDLow(), spellCaster, this);
|
||||
GetMap()->ScriptsStart(sGameObjectScripts, GetDBTableGUIDLow(), spellCaster, this);
|
||||
return;
|
||||
|
||||
case GAMEOBJECT_TYPE_QUESTGIVER: //2
|
||||
@@ -1045,7 +1045,7 @@ void GameObject::Use(Unit* user)
|
||||
player->CastedCreatureOrGO(info->id, GetGUID(), 0);
|
||||
|
||||
if (info->goober.eventId)
|
||||
sWorld.ScriptsStart(sEventScripts, info->goober.eventId, player, this);
|
||||
GetMap()->ScriptsStart(sEventScripts, info->goober.eventId, player, this);
|
||||
}
|
||||
|
||||
// cast this spell later if provided
|
||||
@@ -1068,7 +1068,7 @@ void GameObject::Use(Unit* user)
|
||||
player->SendCinematicStart(info->camera.cinematicId);
|
||||
|
||||
if (info->camera.eventID)
|
||||
sWorld.ScriptsStart(sEventScripts, info->camera.eventID, player, this);
|
||||
GetMap()->ScriptsStart(sEventScripts, info->camera.eventID, player, this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
+856
-9
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "MapManager.h"
|
||||
#include "Player.h"
|
||||
#include "Vehicle.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "Log.h"
|
||||
#include "GridStates.h"
|
||||
@@ -36,6 +37,7 @@
|
||||
#include "Group.h"
|
||||
#include "MapRefManager.h"
|
||||
#include "Vehicle.h"
|
||||
#include "WaypointManager.h"
|
||||
|
||||
#include "MapInstanced.h"
|
||||
#include "InstanceSaveMgr.h"
|
||||
@@ -46,9 +48,20 @@
|
||||
|
||||
GridState* si_GridStates[MAX_GRID_STATE];
|
||||
|
||||
struct ScriptAction
|
||||
{
|
||||
uint64 sourceGUID;
|
||||
uint64 targetGUID;
|
||||
uint64 ownerGUID; // owner of source if source is item
|
||||
ScriptInfo const* script; // pointer to static script data
|
||||
};
|
||||
|
||||
Map::~Map()
|
||||
{
|
||||
UnloadAll();
|
||||
|
||||
if(!m_scriptSchedule.empty())
|
||||
sWorld.DecreaseScheduledScriptCount(m_scriptSchedule.size());
|
||||
}
|
||||
|
||||
bool Map::ExistMap(uint32 mapid,int gx,int gy)
|
||||
@@ -780,17 +793,21 @@ void Map::Update(const uint32 &t_diff)
|
||||
|
||||
// Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load !
|
||||
// This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended
|
||||
if (IsBattleGroundOrArena())
|
||||
return;
|
||||
|
||||
for (GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end(); )
|
||||
if (!IsBattleGroundOrArena())
|
||||
{
|
||||
NGridType *grid = i->getSource();
|
||||
GridInfo *info = i->getSource()->getGridInfoRef();
|
||||
++i; // The update might delete the map and we need the next map before the iterator gets invalid
|
||||
assert(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE);
|
||||
si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, grid->getX(), grid->getY(), t_diff);
|
||||
for (GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end(); )
|
||||
{
|
||||
NGridType *grid = i->getSource();
|
||||
GridInfo *info = i->getSource()->getGridInfoRef();
|
||||
++i; // The update might delete the map and we need the next map before the iterator gets invalid
|
||||
assert(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE);
|
||||
si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, grid->getX(), grid->getY(), t_diff);
|
||||
}
|
||||
}
|
||||
|
||||
///- Process necessary scripts
|
||||
if (!m_scriptSchedule.empty())
|
||||
ScriptsProcess();
|
||||
}
|
||||
|
||||
void Map::Remove(Player *player, bool remove)
|
||||
@@ -2745,6 +2762,836 @@ void BattleGroundMap::UnloadAll()
|
||||
Map::UnloadAll();
|
||||
}
|
||||
|
||||
/// Put scripts in the execution queue
|
||||
void Map::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target)
|
||||
{
|
||||
///- Find the script map
|
||||
ScriptMapMap::const_iterator s = scripts.find(id);
|
||||
if (s == scripts.end())
|
||||
return;
|
||||
|
||||
// prepare static data
|
||||
uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; //some script commands doesn't have source
|
||||
uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
|
||||
uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
|
||||
|
||||
///- Schedule script execution for all scripts in the script map
|
||||
ScriptMap const *s2 = &(s->second);
|
||||
bool immedScript = false;
|
||||
for (ScriptMap::const_iterator iter = s2->begin(); iter != s2->end(); ++iter)
|
||||
{
|
||||
ScriptAction sa;
|
||||
sa.sourceGUID = sourceGUID;
|
||||
sa.targetGUID = targetGUID;
|
||||
sa.ownerGUID = ownerGUID;
|
||||
|
||||
sa.script = &iter->second;
|
||||
m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(time_t(sWorld.GetGameTime() + iter->first), sa));
|
||||
if (iter->first == 0)
|
||||
immedScript = true;
|
||||
|
||||
sWorld.IncreaseScheduledScriptsCount();
|
||||
}
|
||||
///- If one of the effects should be immediate, launch the script execution
|
||||
if (/*start &&*/ immedScript)
|
||||
ScriptsProcess();
|
||||
}
|
||||
|
||||
void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target)
|
||||
{
|
||||
// NOTE: script record _must_ exist until command executed
|
||||
|
||||
// prepare static data
|
||||
uint64 sourceGUID = source ? source->GetGUID() : (uint64)0;
|
||||
uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
|
||||
uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
|
||||
|
||||
ScriptAction sa;
|
||||
sa.sourceGUID = sourceGUID;
|
||||
sa.targetGUID = targetGUID;
|
||||
sa.ownerGUID = ownerGUID;
|
||||
|
||||
sa.script = &script;
|
||||
m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(time_t(sWorld.GetGameTime() + delay), sa));
|
||||
|
||||
sWorld.IncreaseScheduledScriptsCount();
|
||||
|
||||
///- If effects should be immediate, launch the script execution
|
||||
if(delay == 0)
|
||||
ScriptsProcess();
|
||||
}
|
||||
|
||||
/// Process queued scripts
|
||||
void Map::ScriptsProcess()
|
||||
{
|
||||
if (m_scriptSchedule.empty())
|
||||
return;
|
||||
|
||||
///- Process overdue queued scripts
|
||||
std::multimap<time_t, ScriptAction>::iterator iter = m_scriptSchedule.begin();
|
||||
// ok as multimap is a *sorted* associative container
|
||||
while (!m_scriptSchedule.empty() && (iter->first <= sWorld.GetGameTime()))
|
||||
{
|
||||
ScriptAction const& step = iter->second;
|
||||
|
||||
Object* source = NULL;
|
||||
|
||||
if(step.sourceGUID)
|
||||
{
|
||||
switch(GUID_HIPART(step.sourceGUID))
|
||||
{
|
||||
case HIGHGUID_ITEM:
|
||||
// case HIGHGUID_CONTAINER: ==HIGHGUID_ITEM
|
||||
{
|
||||
Player* player = HashMapHolder<Player>::Find(step.ownerGUID);
|
||||
if(player)
|
||||
source = player->GetItemByGuid(step.sourceGUID);
|
||||
break;
|
||||
}
|
||||
case HIGHGUID_UNIT:
|
||||
source = HashMapHolder<Creature>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_PET:
|
||||
source = HashMapHolder<Pet>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_VEHICLE:
|
||||
source = HashMapHolder<Vehicle>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_PLAYER:
|
||||
source = HashMapHolder<Player>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_GAMEOBJECT:
|
||||
source = HashMapHolder<GameObject>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_CORPSE:
|
||||
source = HashMapHolder<Corpse>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_MO_TRANSPORT:
|
||||
for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
|
||||
{
|
||||
if((*iter)->GetGUID() == step.sourceGUID)
|
||||
{
|
||||
source = reinterpret_cast<Object*>(*iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.sourceGUID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if(source && !source->IsInWorld()) source = NULL;
|
||||
|
||||
Object* target = NULL;
|
||||
|
||||
if(step.targetGUID)
|
||||
{
|
||||
switch(GUID_HIPART(step.targetGUID))
|
||||
{
|
||||
case HIGHGUID_UNIT:
|
||||
target = HashMapHolder<Creature>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_PET:
|
||||
target = HashMapHolder<Pet>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_VEHICLE:
|
||||
target = HashMapHolder<Vehicle>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_PLAYER: // empty GUID case also
|
||||
target = HashMapHolder<Player>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_GAMEOBJECT:
|
||||
target = HashMapHolder<GameObject>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_CORPSE:
|
||||
target = HashMapHolder<Corpse>::Find(step.targetGUID);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.targetGUID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if(target && !target->IsInWorld()) target = NULL;
|
||||
|
||||
switch (step.script->command)
|
||||
{
|
||||
case SCRIPT_COMMAND_TALK:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong > 3)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK invalid chat type (%u), skipping.",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
uint64 unit_target = target ? target->GetGUID() : 0;
|
||||
|
||||
//datalong 0=normal say, 1=whisper, 2=yell, 3=emote text
|
||||
switch(step.script->datalong)
|
||||
{
|
||||
case 0: // Say
|
||||
((Creature *)source)->Say(step.script->dataint, LANG_UNIVERSAL, unit_target);
|
||||
break;
|
||||
case 1: // Whisper
|
||||
if(!unit_target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK attempt to whisper (%u) NULL, skipping.",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
((Creature *)source)->Whisper(step.script->dataint,unit_target);
|
||||
break;
|
||||
case 2: // Yell
|
||||
((Creature *)source)->Yell(step.script->dataint, LANG_UNIVERSAL, unit_target);
|
||||
break;
|
||||
case 3: // Emote text
|
||||
((Creature *)source)->TextEmote(step.script->dataint, unit_target);
|
||||
break;
|
||||
default:
|
||||
break; // must be already checked at load
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_EMOTE:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_EMOTE call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_EMOTE call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
((Creature *)source)->HandleEmoteCommand(step.script->datalong);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FIELD_SET:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FIELD_SET call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FIELD_SET call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->SetUInt32Value(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
case SCRIPT_COMMAND_MOVE_TO:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_MOVE_TO call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_MOVE_TO call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
((Creature*)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->datalong2 );
|
||||
((Creature*)source)->GetMap()->CreatureRelocation(((Creature*)source), step.script->x, step.script->y, step.script->z, 0);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FLAG_SET:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_SET call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_SET call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->SetFlag(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FLAG_REMOVE:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->RemoveFlag(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
|
||||
case SCRIPT_COMMAND_TELEPORT_TO:
|
||||
{
|
||||
// accept player in any one from target/source arg
|
||||
if (!target && !source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for NULL object.");
|
||||
break;
|
||||
}
|
||||
|
||||
// must be only Player
|
||||
if((!target || target->GetTypeId() != TYPEID_PLAYER) && (!source || source->GetTypeId() != TYPEID_PLAYER))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0);
|
||||
break;
|
||||
}
|
||||
|
||||
Player* pSource = target && target->GetTypeId() == TYPEID_PLAYER ? (Player*)target : (Player*)source;
|
||||
|
||||
pSource->TeleportTo(step.script->datalong, step.script->x, step.script->y, step.script->z, step.script->o);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE:
|
||||
{
|
||||
if(!step.script->datalong) // creature not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL world object.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* summoner = dynamic_cast<WorldObject*>(source);
|
||||
|
||||
if(!summoner)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
float x = step.script->x;
|
||||
float y = step.script->y;
|
||||
float z = step.script->z;
|
||||
float o = step.script->o;
|
||||
|
||||
Creature* pCreature = summoner->SummonCreature(step.script->datalong, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,step.script->datalong2);
|
||||
if (!pCreature)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON failed for creature (entry: %u).",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT:
|
||||
{
|
||||
if(!step.script->datalong) // gameobject not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL gameobject.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL world object.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* summoner = dynamic_cast<WorldObject*>(source);
|
||||
|
||||
if(!summoner)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
GameObject *go = NULL;
|
||||
int32 time_to_despawn = step.script->datalong2<5 ? 5 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(MaNGOS::ComputeCellPair(summoner->GetPositionX(), summoner->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(summoner, go,go_check);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *summoner->GetMap());
|
||||
|
||||
if ( !go )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
if( go->GetGoType()==GAMEOBJECT_TYPE_FISHINGNODE ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_DOOR ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_BUTTON ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_TRAP )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT can not be used with gameobject of type %u (guid: %u).", uint32(go->GetGoType()), step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
if( go->isSpawned() )
|
||||
break; //gameobject already spawned
|
||||
|
||||
go->SetLootState(GO_READY);
|
||||
go->SetRespawnTime(time_to_despawn); //despawn object in ? seconds
|
||||
|
||||
go->GetMap()->Add(go);
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_OPEN_DOOR:
|
||||
{
|
||||
if(!step.script->datalong) // door not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL door.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *door = NULL;
|
||||
int32 time_to_close = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *caster->GetMap());
|
||||
|
||||
if (!door)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for non-door(GoType: %u).", door->GetGoType());
|
||||
break;
|
||||
}
|
||||
|
||||
if (door->GetGoState() != GO_STATE_READY)
|
||||
break; //door already open
|
||||
|
||||
door->UseDoorOrButton(time_to_close);
|
||||
|
||||
if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON)
|
||||
((GameObject*)target)->UseDoorOrButton(time_to_close);
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_CLOSE_DOOR:
|
||||
{
|
||||
if(!step.script->datalong) // guid for door not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL door.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *door = NULL;
|
||||
int32 time_to_open = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *caster->GetMap());
|
||||
|
||||
if ( !door )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
if ( door->GetGoType() != GAMEOBJECT_TYPE_DOOR )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for non-door(GoType: %u).", door->GetGoType());
|
||||
break;
|
||||
}
|
||||
|
||||
if( door->GetGoState() == GO_STATE_READY )
|
||||
break; //door already closed
|
||||
|
||||
door->UseDoorOrButton(time_to_open);
|
||||
|
||||
if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON)
|
||||
((GameObject*)target)->UseDoorOrButton(time_to_open);
|
||||
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_QUEST_EXPLORED:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL source.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL target.");
|
||||
break;
|
||||
}
|
||||
|
||||
// when script called for item spell casting then target == (unit or GO) and source is player
|
||||
WorldObject* worldObject;
|
||||
Player* player;
|
||||
|
||||
if(target->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
if(source->GetTypeId()!=TYPEID_UNIT && source->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
worldObject = (WorldObject*)source;
|
||||
player = (Player*)target;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(target->GetTypeId()!=TYPEID_UNIT && target->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_PLAYER)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-player(TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
worldObject = (WorldObject*)target;
|
||||
player = (Player*)source;
|
||||
}
|
||||
|
||||
// quest id and flags checked at script loading
|
||||
if( (worldObject->GetTypeId()!=TYPEID_UNIT || ((Unit*)worldObject)->isAlive()) &&
|
||||
(step.script->datalong2==0 || worldObject->IsWithinDistInMap(player,float(step.script->datalong2))) )
|
||||
player->AreaExploredOrEventHappens(step.script->datalong);
|
||||
else
|
||||
player->FailQuest(step.script->datalong);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_ACTIVATE_OBJECT:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT must have source caster.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT source caster isn't unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for NULL gameobject.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(target->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for non-gameobject (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *go = (GameObject*)target;
|
||||
|
||||
go->Use(caster);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_REMOVE_AURA:
|
||||
{
|
||||
Object* cmdTarget = step.script->datalong2 ? source : target;
|
||||
|
||||
if(!cmdTarget)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_REMOVE_AURA call for NULL %s.",step.script->datalong2 ? "source" : "target");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdTarget->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_REMOVE_AURA %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 ? "source" : "target",cmdTarget->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
((Unit*)cmdTarget)->RemoveAurasDueToSpell(step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_CAST_SPELL:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL must have source caster.");
|
||||
break;
|
||||
}
|
||||
|
||||
Object* cmdTarget = step.script->datalong2 & 0x01 ? source : target;
|
||||
|
||||
if(!cmdTarget)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x01 ? "source" : "target");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdTarget->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x01 ? "source" : "target",cmdTarget->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* spellTarget = (Unit*)cmdTarget;
|
||||
|
||||
Object* cmdSource = step.script->datalong2 & 0x02 ? target : source;
|
||||
|
||||
if(!cmdSource)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x02 ? "target" : "source");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdSource->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x02 ? "target" : "source", cmdSource->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* spellSource = (Unit*)cmdSource;
|
||||
|
||||
//TODO: when GO cast implemented, code below must be updated accordingly to also allow GO spell cast
|
||||
spellSource->CastSpell(spellTarget,step.script->datalong,false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_LOAD_PATH:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE is tried to apply to NON-existing unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE source mover isn't unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!WaypointMgr.GetPath(step.script->datalong))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE source mover has an invallid path, skipping.", step.script->datalong2);
|
||||
break;
|
||||
}
|
||||
|
||||
dynamic_cast<Unit*>(source)->GetMotionMaster()->MovePath(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_CALLSCRIPT_TO_UNIT:
|
||||
{
|
||||
if(!step.script->datalong || !step.script->datalong2)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CALLSCRIPT calls invallid db_script_id or lowguid not present: skipping.");
|
||||
break;
|
||||
}
|
||||
//our target
|
||||
Creature* target = NULL;
|
||||
|
||||
if(source) //using grid searcher
|
||||
{
|
||||
CellPair p(Trinity::ComputeCellPair(((Unit*)source)->GetPositionX(), ((Unit*)source)->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
//sLog.outDebug("Attempting to find Creature: Db GUID: %i", step.script->datalong);
|
||||
Trinity::CreatureWithDbGUIDCheck target_check(((Unit*)source), step.script->datalong);
|
||||
Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(((Unit*)source), target, target_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, unit_checker, *(((Unit*)source)->GetMap()));
|
||||
}
|
||||
else //check hashmap holders
|
||||
{
|
||||
if(CreatureData const* data = objmgr.GetCreatureData(step.script->datalong))
|
||||
target = ObjectAccessor::GetObjectInWorld<Creature>(data->mapid, data->posX, data->posY, MAKE_NEW_GUID(step.script->datalong, data->id, HIGHGUID_UNIT), target);
|
||||
}
|
||||
//sLog.outDebug("attempting to pass target...");
|
||||
if(!target)
|
||||
break;
|
||||
//sLog.outDebug("target passed");
|
||||
//Lets choose our ScriptMap map
|
||||
ScriptMapMap *datamap = NULL;
|
||||
switch(step.script->dataint)
|
||||
{
|
||||
case 1://QUEST END SCRIPTMAP
|
||||
datamap = &sQuestEndScripts;
|
||||
break;
|
||||
case 2://QUEST START SCRIPTMAP
|
||||
datamap = &sQuestStartScripts;
|
||||
break;
|
||||
case 3://SPELLS SCRIPTMAP
|
||||
datamap = &sSpellScripts;
|
||||
break;
|
||||
case 4://GAMEOBJECTS SCRIPTMAP
|
||||
datamap = &sGameObjectScripts;
|
||||
break;
|
||||
case 5://EVENTS SCRIPTMAP
|
||||
datamap = &sEventScripts;
|
||||
break;
|
||||
case 6://WAYPOINTS SCRIPTMAP
|
||||
datamap = &sWaypointScripts;
|
||||
break;
|
||||
default:
|
||||
sLog.outError("SCRIPT_COMMAND_CALLSCRIPT ERROR: no scriptmap present... ignoring");
|
||||
break;
|
||||
}
|
||||
//if no scriptmap present...
|
||||
if(!datamap)
|
||||
break;
|
||||
|
||||
uint32 script_id = step.script->datalong2;
|
||||
//insert script into schedule but do not start it
|
||||
ScriptsStart(*datamap, script_id, target, NULL/*, false*/);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_KILL:
|
||||
{
|
||||
if(!source || ((Creature*)source)->isDead())
|
||||
break;
|
||||
|
||||
((Creature*)source)->DealDamage(((Creature*)source), ((Creature*)source)->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
|
||||
switch(step.script->dataint)
|
||||
{
|
||||
case 0: break; //return false not remove corpse
|
||||
case 1: ((Creature*)source)->RemoveCorpse(); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_PLAY_SOUND:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* pSource = dynamic_cast<WorldObject*>(source);
|
||||
if(!pSource)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for non-world object (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
// bitmask: 0/1=anyone/target, 0/2=with distance dependent
|
||||
Player* pTarget = NULL;
|
||||
if(step.script->datalong2 & 1)
|
||||
{
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for NULL target.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(target->GetTypeId()!=TYPEID_PLAYER)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for non-player (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
pTarget = (Player*)target;
|
||||
}
|
||||
|
||||
// bitmask: 0/1=anyone/target, 0/2=with distance dependent
|
||||
if(step.script->datalong2 & 2)
|
||||
pSource->PlayDistanceSound(step.script->datalong,pTarget);
|
||||
else
|
||||
pSource->PlayDirectSound(step.script->datalong,pTarget);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog.outError("Unknown script command %u called.",step.script->command);
|
||||
break;
|
||||
}
|
||||
|
||||
m_scriptSchedule.erase(iter);
|
||||
sWorld.DecreaseScheduledScriptCount();
|
||||
|
||||
iter = m_scriptSchedule.begin();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Creature*
|
||||
Map::GetCreature(uint64 guid)
|
||||
{
|
||||
|
||||
@@ -43,9 +43,12 @@ class WorldPacket;
|
||||
class InstanceData;
|
||||
class Group;
|
||||
class InstanceSave;
|
||||
class Object;
|
||||
class WorldObject;
|
||||
class TempSummon;
|
||||
class CreatureGroup;
|
||||
struct ScriptInfo;
|
||||
struct ScriptAction;
|
||||
|
||||
|
||||
typedef ACE_RW_Thread_Mutex GridRWLock;
|
||||
@@ -398,6 +401,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
|
||||
typedef MapRefManager PlayerList;
|
||||
PlayerList const& GetPlayers() const { return m_mapRefManager; }
|
||||
|
||||
//per-map script storage
|
||||
void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target);
|
||||
void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
|
||||
|
||||
// must called with AddToWorld
|
||||
template<class T>
|
||||
void AddToActive(T* obj) { AddToActiveHelper(obj); }
|
||||
@@ -467,6 +474,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
|
||||
void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); }
|
||||
|
||||
void setNGrid(NGridType* grid, uint32 x, uint32 y);
|
||||
void ScriptsProcess();
|
||||
|
||||
void UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff);
|
||||
protected:
|
||||
@@ -508,6 +516,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
|
||||
std::vector<Unit*> i_unitsToNotify;
|
||||
std::set<WorldObject *> i_objectsToRemove;
|
||||
std::map<WorldObject*, bool> i_objectsToSwitch;
|
||||
std::multimap<time_t, ScriptAction> m_scriptSchedule;
|
||||
|
||||
// Type specific code for add/remove to/from grid
|
||||
template<class T>
|
||||
|
||||
+2
-2
@@ -12882,7 +12882,7 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver )
|
||||
|
||||
//starting initial quest script
|
||||
if(questGiver && pQuest->GetQuestStartScript()!=0)
|
||||
sWorld.ScriptsStart(sQuestStartScripts, pQuest->GetQuestStartScript(), questGiver, this);
|
||||
GetMap()->ScriptsStart(sQuestStartScripts, pQuest->GetQuestStartScript(), questGiver, this);
|
||||
|
||||
// Some spells applied at quest activation
|
||||
SpellAreaForQuestMapBounds saBounds = spellmgr.GetSpellAreaForQuestMapBounds(quest_id,true);
|
||||
@@ -14142,7 +14142,7 @@ void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGive
|
||||
GetSession()->SendPacket( &data );
|
||||
|
||||
if (pQuest->GetQuestCompleteScript() != 0)
|
||||
sWorld.ScriptsStart(sQuestEndScripts, pQuest->GetQuestCompleteScript(), questGiver, this);
|
||||
GetMap()->ScriptsStart(sQuestEndScripts, pQuest->GetQuestCompleteScript(), questGiver, this);
|
||||
}
|
||||
|
||||
void Player::SendQuestFailed( uint32 quest_id )
|
||||
|
||||
@@ -2483,7 +2483,7 @@ void Spell::EffectSendEvent(uint32 EffectIndex)
|
||||
we do not handle a flag dropping or clicking on flag in battleground by sendevent system
|
||||
*/
|
||||
sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
|
||||
sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
|
||||
m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
|
||||
}
|
||||
|
||||
void Spell::EffectPowerBurn(uint32 i)
|
||||
@@ -2999,7 +2999,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype)
|
||||
case GAMEOBJECT_TYPE_DOOR:
|
||||
case GAMEOBJECT_TYPE_BUTTON:
|
||||
gameObjTarget->UseDoorOrButton();
|
||||
sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
|
||||
player->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
|
||||
return;
|
||||
|
||||
case GAMEOBJECT_TYPE_QUESTGIVER:
|
||||
@@ -3019,7 +3019,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype)
|
||||
if (gameObjTarget->GetGOInfo()->goober.eventId)
|
||||
{
|
||||
sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
|
||||
sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
|
||||
player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
|
||||
gameObjTarget->EventInform(gameObjTarget->GetGOInfo()->goober.eventId);
|
||||
}
|
||||
|
||||
@@ -3030,7 +3030,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype)
|
||||
return;
|
||||
|
||||
Script->GOHello(player, gameObjTarget);
|
||||
sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
|
||||
gameObjTarget->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
|
||||
|
||||
gameObjTarget->AddUniqueUse(player);
|
||||
gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
|
||||
@@ -3052,7 +3052,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype)
|
||||
if (gameObjTarget->GetGOInfo()->chest.eventId)
|
||||
{
|
||||
sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
|
||||
sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
|
||||
player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
|
||||
}
|
||||
|
||||
// triggering linked GO
|
||||
@@ -5501,7 +5501,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
|
||||
|
||||
// normal DB scripted effect
|
||||
sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
|
||||
sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
|
||||
m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
|
||||
}
|
||||
|
||||
void Spell::EffectSanctuary(uint32 /*i*/)
|
||||
@@ -5703,7 +5703,7 @@ void Spell::EffectActivateObject(uint32 effect_idx)
|
||||
|
||||
int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
|
||||
|
||||
sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
|
||||
gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
|
||||
}
|
||||
|
||||
void Spell::EffectApplyGlyph(uint32 i)
|
||||
|
||||
@@ -487,7 +487,7 @@ void Transport::CheckForEvent(uint32 entry, uint32 wp_id)
|
||||
{
|
||||
uint32 key = entry*100+wp_id;
|
||||
if(objmgr.TransportEventMap.find(key) != objmgr.TransportEventMap.end())
|
||||
sWorld.ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL);
|
||||
GetMap()->ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL);
|
||||
}
|
||||
|
||||
void Transport::Update(uint32 /*p_time*/)
|
||||
|
||||
@@ -198,7 +198,7 @@ WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 &diff)
|
||||
|
||||
//note: disable "start" for mtmap
|
||||
if(node->event_id && rand()%100 < node->event_chance)
|
||||
sWorld.ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL, false);
|
||||
unit.GetMap()->ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL/*, false*/);
|
||||
|
||||
MovementInform(unit);
|
||||
unit.UpdateWaypointID(i_currentNode);
|
||||
|
||||
+1
-842
@@ -63,7 +63,6 @@
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "CellImpl.h"
|
||||
#include "InstanceSaveMgr.h"
|
||||
#include "WaypointManager.h"
|
||||
#include "Util.h"
|
||||
#include "Language.h"
|
||||
#include "CreatureGroups.h"
|
||||
@@ -83,14 +82,6 @@ float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE;
|
||||
float World::m_VisibleUnitGreyDistance = 0;
|
||||
float World::m_VisibleObjectGreyDistance = 0;
|
||||
|
||||
struct ScriptAction
|
||||
{
|
||||
uint64 sourceGUID;
|
||||
uint64 targetGUID;
|
||||
uint64 ownerGUID; // owner of source if source is item
|
||||
ScriptInfo const* script; // pointer to static script data
|
||||
};
|
||||
|
||||
/// World constructor
|
||||
World::World()
|
||||
{
|
||||
@@ -106,6 +97,7 @@ World::World()
|
||||
m_MaxPlayerCount = 0;
|
||||
m_resultQueue = NULL;
|
||||
m_NextDailyQuestReset = 0;
|
||||
m_scheduledScripts = 0;
|
||||
|
||||
m_defaultDbcLocale = LOCALE_enUS;
|
||||
m_availableDbcLocaleMask = 0;
|
||||
@@ -1796,14 +1788,6 @@ void World::Update(uint32 diff)
|
||||
MapManager::Instance().DoDelayedMovesAndRemoves();
|
||||
}*/
|
||||
|
||||
///- Process necessary scripts
|
||||
if (!m_scriptSchedule.empty())
|
||||
{
|
||||
RecordTimeDiff(NULL);
|
||||
ScriptsProcess();
|
||||
RecordTimeDiff("UpdateScriptsProcess");
|
||||
}
|
||||
|
||||
sBattleGroundMgr.Update(diff);
|
||||
RecordTimeDiff("UpdateBattleGroundMgr");
|
||||
|
||||
@@ -1848,831 +1832,6 @@ void World::ForceGameEventUpdate()
|
||||
m_timers[WUPDATE_EVENTS].Reset();
|
||||
}
|
||||
|
||||
/// Put scripts in the execution queue
|
||||
void World::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target, bool start)
|
||||
{
|
||||
///- Find the script map
|
||||
ScriptMapMap::const_iterator s = scripts.find(id);
|
||||
if (s == scripts.end())
|
||||
return;
|
||||
|
||||
// prepare static data
|
||||
uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; //some script commands doesn't have source
|
||||
uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
|
||||
uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
|
||||
|
||||
///- Schedule script execution for all scripts in the script map
|
||||
ScriptMap const *s2 = &(s->second);
|
||||
bool immedScript = false;
|
||||
for (ScriptMap::const_iterator iter = s2->begin(); iter != s2->end(); ++iter)
|
||||
{
|
||||
ScriptAction sa;
|
||||
sa.sourceGUID = sourceGUID;
|
||||
sa.targetGUID = targetGUID;
|
||||
sa.ownerGUID = ownerGUID;
|
||||
|
||||
sa.script = &iter->second;
|
||||
m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(m_gameTime + iter->first, sa));
|
||||
if (iter->first == 0)
|
||||
immedScript = true;
|
||||
}
|
||||
///- If one of the effects should be immediate, launch the script execution
|
||||
if (start && immedScript)
|
||||
ScriptsProcess();
|
||||
}
|
||||
|
||||
void World::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target)
|
||||
{
|
||||
// NOTE: script record _must_ exist until command executed
|
||||
|
||||
// prepare static data
|
||||
uint64 sourceGUID = source ? source->GetGUID() : (uint64)0;
|
||||
uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
|
||||
uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
|
||||
|
||||
ScriptAction sa;
|
||||
sa.sourceGUID = sourceGUID;
|
||||
sa.targetGUID = targetGUID;
|
||||
sa.ownerGUID = ownerGUID;
|
||||
|
||||
sa.script = &script;
|
||||
m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(m_gameTime + delay, sa));
|
||||
|
||||
///- If effects should be immediate, launch the script execution
|
||||
if(delay == 0)
|
||||
ScriptsProcess();
|
||||
}
|
||||
|
||||
/// Process queued scripts
|
||||
void World::ScriptsProcess()
|
||||
{
|
||||
if (m_scriptSchedule.empty())
|
||||
return;
|
||||
|
||||
///- Process overdue queued scripts
|
||||
std::multimap<time_t, ScriptAction>::iterator iter = m_scriptSchedule.begin();
|
||||
// ok as multimap is a *sorted* associative container
|
||||
while (!m_scriptSchedule.empty() && (iter->first <= m_gameTime))
|
||||
{
|
||||
ScriptAction const& step = iter->second;
|
||||
|
||||
Object* source = NULL;
|
||||
|
||||
if(step.sourceGUID)
|
||||
{
|
||||
switch(GUID_HIPART(step.sourceGUID))
|
||||
{
|
||||
case HIGHGUID_ITEM:
|
||||
// case HIGHGUID_CONTAINER: ==HIGHGUID_ITEM
|
||||
{
|
||||
Player* player = HashMapHolder<Player>::Find(step.ownerGUID);
|
||||
if(player)
|
||||
source = player->GetItemByGuid(step.sourceGUID);
|
||||
break;
|
||||
}
|
||||
case HIGHGUID_UNIT:
|
||||
source = HashMapHolder<Creature>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_PET:
|
||||
source = HashMapHolder<Pet>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_VEHICLE:
|
||||
source = HashMapHolder<Vehicle>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_PLAYER:
|
||||
source = HashMapHolder<Player>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_GAMEOBJECT:
|
||||
source = HashMapHolder<GameObject>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_CORPSE:
|
||||
source = HashMapHolder<Corpse>::Find(step.sourceGUID);
|
||||
break;
|
||||
case HIGHGUID_MO_TRANSPORT:
|
||||
for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
|
||||
{
|
||||
if((*iter)->GetGUID() == step.sourceGUID)
|
||||
{
|
||||
source = reinterpret_cast<Object*>(*iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.sourceGUID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if(source && !source->IsInWorld()) source = NULL;
|
||||
|
||||
Object* target = NULL;
|
||||
|
||||
if(step.targetGUID)
|
||||
{
|
||||
switch(GUID_HIPART(step.targetGUID))
|
||||
{
|
||||
case HIGHGUID_UNIT:
|
||||
target = HashMapHolder<Creature>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_PET:
|
||||
target = HashMapHolder<Pet>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_VEHICLE:
|
||||
target = HashMapHolder<Vehicle>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_PLAYER: // empty GUID case also
|
||||
target = HashMapHolder<Player>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_GAMEOBJECT:
|
||||
target = HashMapHolder<GameObject>::Find(step.targetGUID);
|
||||
break;
|
||||
case HIGHGUID_CORPSE:
|
||||
target = HashMapHolder<Corpse>::Find(step.targetGUID);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.targetGUID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if(target && !target->IsInWorld()) target = NULL;
|
||||
|
||||
switch (step.script->command)
|
||||
{
|
||||
case SCRIPT_COMMAND_TALK:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong > 3)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK invalid chat type (%u), skipping.",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
uint64 unit_target = target ? target->GetGUID() : 0;
|
||||
|
||||
//datalong 0=normal say, 1=whisper, 2=yell, 3=emote text
|
||||
switch(step.script->datalong)
|
||||
{
|
||||
case 0: // Say
|
||||
((Creature *)source)->Say(step.script->dataint, LANG_UNIVERSAL, unit_target);
|
||||
break;
|
||||
case 1: // Whisper
|
||||
if(!unit_target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TALK attempt to whisper (%u) NULL, skipping.",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
((Creature *)source)->Whisper(step.script->dataint,unit_target);
|
||||
break;
|
||||
case 2: // Yell
|
||||
((Creature *)source)->Yell(step.script->dataint, LANG_UNIVERSAL, unit_target);
|
||||
break;
|
||||
case 3: // Emote text
|
||||
((Creature *)source)->TextEmote(step.script->dataint, unit_target);
|
||||
break;
|
||||
default:
|
||||
break; // must be already checked at load
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_EMOTE:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_EMOTE call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_EMOTE call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
((Creature *)source)->HandleEmoteCommand(step.script->datalong);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FIELD_SET:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FIELD_SET call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FIELD_SET call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->SetUInt32Value(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
case SCRIPT_COMMAND_MOVE_TO:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_MOVE_TO call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_UNIT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_MOVE_TO call for non-creature (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
((Creature*)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->datalong2 );
|
||||
((Creature*)source)->GetMap()->CreatureRelocation(((Creature*)source), step.script->x, step.script->y, step.script->z, 0);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FLAG_SET:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_SET call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_SET call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->SetFlag(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
case SCRIPT_COMMAND_FLAG_REMOVE:
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for NULL object.");
|
||||
break;
|
||||
}
|
||||
if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount())
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for wrong field %u (max count: %u) in object (TypeId: %u).",
|
||||
step.script->datalong,source->GetValuesCount(),source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
source->RemoveFlag(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
|
||||
case SCRIPT_COMMAND_TELEPORT_TO:
|
||||
{
|
||||
// accept player in any one from target/source arg
|
||||
if (!target && !source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for NULL object.");
|
||||
break;
|
||||
}
|
||||
|
||||
// must be only Player
|
||||
if((!target || target->GetTypeId() != TYPEID_PLAYER) && (!source || source->GetTypeId() != TYPEID_PLAYER))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0);
|
||||
break;
|
||||
}
|
||||
|
||||
Player* pSource = target && target->GetTypeId() == TYPEID_PLAYER ? (Player*)target : (Player*)source;
|
||||
|
||||
pSource->TeleportTo(step.script->datalong, step.script->x, step.script->y, step.script->z, step.script->o);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE:
|
||||
{
|
||||
if(!step.script->datalong) // creature not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL world object.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* summoner = dynamic_cast<WorldObject*>(source);
|
||||
|
||||
if(!summoner)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
float x = step.script->x;
|
||||
float y = step.script->y;
|
||||
float z = step.script->z;
|
||||
float o = step.script->o;
|
||||
|
||||
Creature* pCreature = summoner->SummonCreature(step.script->datalong, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,step.script->datalong2);
|
||||
if (!pCreature)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON failed for creature (entry: %u).",step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT:
|
||||
{
|
||||
if(!step.script->datalong) // gameobject not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL gameobject.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL world object.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* summoner = dynamic_cast<WorldObject*>(source);
|
||||
|
||||
if(!summoner)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
GameObject *go = NULL;
|
||||
int32 time_to_despawn = step.script->datalong2<5 ? 5 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(Trinity::ComputeCellPair(summoner->GetPositionX(), summoner->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(summoner, go,go_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *summoner->GetMap());
|
||||
|
||||
if ( !go )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
if( go->GetGoType()==GAMEOBJECT_TYPE_FISHINGNODE ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_DOOR ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_BUTTON ||
|
||||
go->GetGoType()==GAMEOBJECT_TYPE_TRAP )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT can not be used with gameobject of type %u (guid: %u).", uint32(go->GetGoType()), step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
if( go->isSpawned() )
|
||||
break; //gameobject already spawned
|
||||
|
||||
go->SetLootState(GO_READY);
|
||||
go->SetRespawnTime(time_to_despawn); //despawn object in ? seconds
|
||||
|
||||
go->GetMap()->Add(go);
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_OPEN_DOOR:
|
||||
{
|
||||
if(!step.script->datalong) // door not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL door.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *door = NULL;
|
||||
int32 time_to_close = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *caster->GetMap());
|
||||
|
||||
if (!door)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for non-door(GoType: %u).", door->GetGoType());
|
||||
break;
|
||||
}
|
||||
|
||||
if (door->GetGoState() != GO_STATE_READY)
|
||||
break; //door already open
|
||||
|
||||
door->UseDoorOrButton(time_to_close);
|
||||
|
||||
if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON)
|
||||
((GameObject*)target)->UseDoorOrButton(time_to_close);
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_CLOSE_DOOR:
|
||||
{
|
||||
if(!step.script->datalong) // guid for door not specified
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL door.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *door = NULL;
|
||||
int32 time_to_open = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2;
|
||||
|
||||
CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong);
|
||||
MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, object_checker, *caster->GetMap());
|
||||
|
||||
if ( !door )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for gameobject(guid: %u).", step.script->datalong);
|
||||
break;
|
||||
}
|
||||
if ( door->GetGoType() != GAMEOBJECT_TYPE_DOOR )
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for non-door(GoType: %u).", door->GetGoType());
|
||||
break;
|
||||
}
|
||||
|
||||
if( door->GetGoState() == GO_STATE_READY )
|
||||
break; //door already closed
|
||||
|
||||
door->UseDoorOrButton(time_to_open);
|
||||
|
||||
if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON)
|
||||
((GameObject*)target)->UseDoorOrButton(time_to_open);
|
||||
|
||||
break;
|
||||
}
|
||||
case SCRIPT_COMMAND_QUEST_EXPLORED:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL source.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL target.");
|
||||
break;
|
||||
}
|
||||
|
||||
// when script called for item spell casting then target == (unit or GO) and source is player
|
||||
WorldObject* worldObject;
|
||||
Player* player;
|
||||
|
||||
if(target->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
if(source->GetTypeId()!=TYPEID_UNIT && source->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
worldObject = (WorldObject*)source;
|
||||
player = (Player*)target;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(target->GetTypeId()!=TYPEID_UNIT && target->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(source->GetTypeId()!=TYPEID_PLAYER)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-player(TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
worldObject = (WorldObject*)target;
|
||||
player = (Player*)source;
|
||||
}
|
||||
|
||||
// quest id and flags checked at script loading
|
||||
if( (worldObject->GetTypeId()!=TYPEID_UNIT || ((Unit*)worldObject)->isAlive()) &&
|
||||
(step.script->datalong2==0 || worldObject->IsWithinDistInMap(player,float(step.script->datalong2))) )
|
||||
player->AreaExploredOrEventHappens(step.script->datalong);
|
||||
else
|
||||
player->FailQuest(step.script->datalong);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_ACTIVATE_OBJECT:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT must have source caster.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT source caster isn't unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for NULL gameobject.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(target->GetTypeId()!=TYPEID_GAMEOBJECT)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for non-gameobject (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* caster = (Unit*)source;
|
||||
|
||||
GameObject *go = (GameObject*)target;
|
||||
|
||||
go->Use(caster);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_REMOVE_AURA:
|
||||
{
|
||||
Object* cmdTarget = step.script->datalong2 ? source : target;
|
||||
|
||||
if(!cmdTarget)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_REMOVE_AURA call for NULL %s.",step.script->datalong2 ? "source" : "target");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdTarget->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_REMOVE_AURA %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 ? "source" : "target",cmdTarget->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
((Unit*)cmdTarget)->RemoveAurasDueToSpell(step.script->datalong);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_CAST_SPELL:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL must have source caster.");
|
||||
break;
|
||||
}
|
||||
|
||||
Object* cmdTarget = step.script->datalong2 & 0x01 ? source : target;
|
||||
|
||||
if(!cmdTarget)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x01 ? "source" : "target");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdTarget->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x01 ? "source" : "target",cmdTarget->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* spellTarget = (Unit*)cmdTarget;
|
||||
|
||||
Object* cmdSource = step.script->datalong2 & 0x02 ? target : source;
|
||||
|
||||
if(!cmdSource)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x02 ? "target" : "source");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!cmdSource->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x02 ? "target" : "source", cmdSource->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
Unit* spellSource = (Unit*)cmdSource;
|
||||
|
||||
//TODO: when GO cast implemented, code below must be updated accordingly to also allow GO spell cast
|
||||
spellSource->CastSpell(spellTarget,step.script->datalong,false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_LOAD_PATH:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE is tried to apply to NON-existing unit.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!source->isType(TYPEMASK_UNIT))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE source mover isn't unit (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!WaypointMgr.GetPath(step.script->datalong))
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_START_MOVE source mover has an invallid path, skipping.", step.script->datalong2);
|
||||
break;
|
||||
}
|
||||
|
||||
dynamic_cast<Unit*>(source)->GetMotionMaster()->MovePath(step.script->datalong, step.script->datalong2);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_CALLSCRIPT_TO_UNIT:
|
||||
{
|
||||
if(!step.script->datalong || !step.script->datalong2)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_CALLSCRIPT calls invallid db_script_id or lowguid not present: skipping.");
|
||||
break;
|
||||
}
|
||||
//our target
|
||||
Creature* target = NULL;
|
||||
|
||||
if(source) //using grid searcher
|
||||
{
|
||||
CellPair p(Trinity::ComputeCellPair(((Unit*)source)->GetPositionX(), ((Unit*)source)->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
|
||||
//sLog.outDebug("Attempting to find Creature: Db GUID: %i", step.script->datalong);
|
||||
Trinity::CreatureWithDbGUIDCheck target_check(((Unit*)source), step.script->datalong);
|
||||
Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(((Unit*)source), target, target_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker);
|
||||
CellLock<GridReadGuard> cell_lock(cell, p);
|
||||
cell_lock->Visit(cell_lock, unit_checker, *(((Unit*)source)->GetMap()));
|
||||
}
|
||||
else //check hashmap holders
|
||||
{
|
||||
if(CreatureData const* data = objmgr.GetCreatureData(step.script->datalong))
|
||||
target = ObjectAccessor::GetObjectInWorld<Creature>(data->mapid, data->posX, data->posY, MAKE_NEW_GUID(step.script->datalong, data->id, HIGHGUID_UNIT), target);
|
||||
}
|
||||
//sLog.outDebug("attempting to pass target...");
|
||||
if(!target)
|
||||
break;
|
||||
//sLog.outDebug("target passed");
|
||||
//Lets choose our ScriptMap map
|
||||
ScriptMapMap *datamap = NULL;
|
||||
switch(step.script->dataint)
|
||||
{
|
||||
case 1://QUEST END SCRIPTMAP
|
||||
datamap = &sQuestEndScripts;
|
||||
break;
|
||||
case 2://QUEST START SCRIPTMAP
|
||||
datamap = &sQuestStartScripts;
|
||||
break;
|
||||
case 3://SPELLS SCRIPTMAP
|
||||
datamap = &sSpellScripts;
|
||||
break;
|
||||
case 4://GAMEOBJECTS SCRIPTMAP
|
||||
datamap = &sGameObjectScripts;
|
||||
break;
|
||||
case 5://EVENTS SCRIPTMAP
|
||||
datamap = &sEventScripts;
|
||||
break;
|
||||
case 6://WAYPOINTS SCRIPTMAP
|
||||
datamap = &sWaypointScripts;
|
||||
break;
|
||||
default:
|
||||
sLog.outError("SCRIPT_COMMAND_CALLSCRIPT ERROR: no scriptmap present... ignoring");
|
||||
break;
|
||||
}
|
||||
//if no scriptmap present...
|
||||
if(!datamap)
|
||||
break;
|
||||
|
||||
uint32 script_id = step.script->datalong2;
|
||||
//insert script into schedule but do not start it
|
||||
ScriptsStart(*datamap, script_id, target, NULL, false);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_KILL:
|
||||
{
|
||||
if(!source || ((Creature*)source)->isDead())
|
||||
break;
|
||||
|
||||
((Creature*)source)->DealDamage(((Creature*)source), ((Creature*)source)->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
|
||||
switch(step.script->dataint)
|
||||
{
|
||||
case 0: break; //return false not remove corpse
|
||||
case 1: ((Creature*)source)->RemoveCorpse(); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCRIPT_COMMAND_PLAY_SOUND:
|
||||
{
|
||||
if(!source)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for NULL creature.");
|
||||
break;
|
||||
}
|
||||
|
||||
WorldObject* pSource = dynamic_cast<WorldObject*>(source);
|
||||
if(!pSource)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for non-world object (TypeId: %u), skipping.",source->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
// bitmask: 0/1=anyone/target, 0/2=with distance dependent
|
||||
Player* pTarget = NULL;
|
||||
if(step.script->datalong2 & 1)
|
||||
{
|
||||
if(!target)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for NULL target.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(target->GetTypeId()!=TYPEID_PLAYER)
|
||||
{
|
||||
sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for non-player (TypeId: %u), skipping.",target->GetTypeId());
|
||||
break;
|
||||
}
|
||||
|
||||
pTarget = (Player*)target;
|
||||
}
|
||||
|
||||
// bitmask: 0/1=anyone/target, 0/2=with distance dependent
|
||||
if(step.script->datalong2 & 2)
|
||||
pSource->PlayDistanceSound(step.script->datalong,pTarget);
|
||||
else
|
||||
pSource->PlayDirectSound(step.script->datalong,pTarget);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog.outError("Unknown script command %u called.",step.script->command);
|
||||
break;
|
||||
}
|
||||
|
||||
m_scriptSchedule.erase(iter);
|
||||
|
||||
iter = m_scriptSchedule.begin();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// Send a packet to all players (except self if mentioned)
|
||||
void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 team)
|
||||
{
|
||||
|
||||
+8
-6
@@ -29,6 +29,7 @@
|
||||
#include "Timer.h"
|
||||
#include "Policies/Singleton.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "ace/Atomic_Op.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
@@ -553,9 +554,10 @@ class World
|
||||
BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author);
|
||||
bool RemoveBanAccount(BanMode mode, std::string nameOrIP);
|
||||
|
||||
void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target, bool start = true);
|
||||
void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
|
||||
bool IsScriptScheduled() const { return !m_scriptSchedule.empty(); }
|
||||
uint32 IncreaseScheduledScriptsCount() { return (uint32)++m_scheduledScripts; }
|
||||
uint32 DecreaseScheduledScriptCount() { return (uint32)--m_scheduledScripts; }
|
||||
uint32 DecreaseScheduledScriptCount(size_t count) { return (uint32)(m_scheduledScripts -= count); }
|
||||
bool IsScriptScheduled() const { return m_scheduledScripts > 0; }
|
||||
|
||||
bool IsAllowedMap(uint32 mapid) { return m_forbiddenMapIds.count(mapid) == 0 ;}
|
||||
|
||||
@@ -592,7 +594,6 @@ class World
|
||||
void RecordTimeDiff(const char * text, ...);
|
||||
protected:
|
||||
void _UpdateGameTime();
|
||||
void ScriptsProcess();
|
||||
// callback for UpdateRealmCharacters
|
||||
void _UpdateRealmCharCount(QueryResult *resultCharCount, uint32 accountId);
|
||||
|
||||
@@ -606,6 +607,9 @@ class World
|
||||
|
||||
bool m_isClosed;
|
||||
|
||||
//atomic op counter for active scripts amount
|
||||
ACE_Atomic_Op<ACE_Thread_Mutex, long> m_scheduledScripts;
|
||||
|
||||
time_t m_startTime;
|
||||
time_t m_gameTime;
|
||||
IntervalTimer m_timers[WUPDATE_COUNT];
|
||||
@@ -626,8 +630,6 @@ class World
|
||||
uint32 m_PlayerCount;
|
||||
uint32 m_MaxPlayerCount;
|
||||
|
||||
std::multimap<time_t, ScriptAction> m_scriptSchedule;
|
||||
|
||||
std::string m_newCharString;
|
||||
|
||||
float rate_values[MAX_RATES];
|
||||
|
||||
Reference in New Issue
Block a user