OregonCore  revision 3611e8a-git
Your Favourite TBC server
MapScripts.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Map.h"
19 #include "World.h"
20 #include "CellImpl.h"
21 #include "GridNotifiers.h"
22 #include "GridNotifiersImpl.h"
23 #include "MapManager.h"
24 #include "Transports.h"
25 #include "ScriptedCreature.h"
26 #include "WaypointManager.h"
27 #include "GossipDef.h"
28 #include "ObjectMgr.h"
29 #include "MoveSplineInit.h"
30 #include "MoveSpline.h"
31 
32 // Put scripts in the execution queue
33 void Map::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target)
34 {
35  // Find the script map
36  ScriptMapMap::const_iterator s = scripts.find(id);
37  if (s == scripts.end())
38  return;
39 
40  // prepare static data
41  uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; //some script commands doesn't have source
42  uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
43  uint64 ownerGUID = (source->GetTypeId() == TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
44 
45  // Schedule script execution for all scripts in the script map
46  ScriptMap const* s2 = &(s->second);
47  bool immedScript = false;
48  for (ScriptMap::const_iterator iter = s2->begin(); iter != s2->end(); ++iter)
49  {
50  ScriptAction sa;
51  sa.sourceGUID = sourceGUID;
52  sa.targetGUID = targetGUID;
53  sa.ownerGUID = ownerGUID;
54 
55  sa.script = &iter->second;
56  m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(time_t(sWorld.GetGameTime() + iter->first), sa));
57  if (iter->first == 0)
58  immedScript = true;
59 
60  sWorld.IncreaseScheduledScriptsCount();
61  }
62  // If one of the effects should be immediate, launch the script execution
63  if (/*start &&*/ immedScript && !i_scriptLock)
64  {
65  i_scriptLock = true;
67  i_scriptLock = false;
68  }
69 }
70 
71 void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target)
72 {
73  // NOTE: script record _must_ exist until command executed
74 
75  // prepare static data
76  uint64 sourceGUID = source ? source->GetGUID() : (uint64)0;
77  uint64 targetGUID = target ? target->GetGUID() : (uint64)0;
78  uint64 ownerGUID = (source->GetTypeId() == TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0;
79 
80  ScriptAction sa;
81  sa.sourceGUID = sourceGUID;
82  sa.targetGUID = targetGUID;
83  sa.ownerGUID = ownerGUID;
84 
85  sa.script = &script;
86  m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(time_t(sWorld.GetGameTime() + delay), sa));
87 
88  sWorld.IncreaseScheduledScriptsCount();
89 
90  // If effects should be immediate, launch the script execution
91  if (delay == 0 && !i_scriptLock)
92  {
93  i_scriptLock = true;
95  i_scriptLock = false;
96  }
97 }
98 
99 // Helpers for ScriptProcess method.
100 inline Player* Map::_GetScriptPlayerSourceOrTarget(Object* source, Object* target, const ScriptInfo* scriptInfo) const
101 {
102  Player* pPlayer = NULL;
103  if (!source && !target)
104  sLog.outError("%s source and target objects are NULL.", scriptInfo->GetDebugInfo().c_str());
105  else
106  {
107  // Check target first, then source.
108  if (target)
109  pPlayer = target->ToPlayer();
110  if (!pPlayer && source)
111  pPlayer = source->ToPlayer();
112 
113  if (!pPlayer)
114  sLog.outError("%s neither source nor target object is player (source: TypeId: %u, Entry: %u, GUID: %u; target: TypeId: %u, Entry: %u, GUID: %u), skipping.",
115  scriptInfo->GetDebugInfo().c_str(),
116  source ? source->GetTypeId() : 0, source ? source->GetEntry() : 0, source ? source->GetGUIDLow() : 0,
117  target ? target->GetTypeId() : 0, target ? target->GetEntry() : 0, target ? target->GetGUIDLow() : 0);
118  }
119  return pPlayer;
120 }
121 
122 inline Creature* Map::_GetScriptCreatureSourceOrTarget(Object* source, Object* target, const ScriptInfo* scriptInfo, bool bReverse) const
123 {
124  Creature* pCreature = NULL;
125  if (!source && !target)
126  sLog.outError("%s source and target objects are NULL.", scriptInfo->GetDebugInfo().c_str());
127  else
128  {
129  if (bReverse)
130  {
131  // Check target first, then source.
132  if (target)
133  pCreature = target->ToCreature();
134  if (!pCreature && source)
135  pCreature = source->ToCreature();
136  }
137  else
138  {
139  // Check source first, then target.
140  if (source)
141  pCreature = source->ToCreature();
142  if (!pCreature && target)
143  pCreature = target->ToCreature();
144  }
145 
146  if (!pCreature)
147  sLog.outError("%s neither source nor target are creatures (source: TypeId: %u, Entry: %u, GUID: %u; target: TypeId: %u, Entry: %u, GUID: %u), skipping.",
148  scriptInfo->GetDebugInfo().c_str(),
149  source ? source->GetTypeId() : 0, source ? source->GetEntry() : 0, source ? source->GetGUIDLow() : 0,
150  target ? target->GetTypeId() : 0, target ? target->GetEntry() : 0, target ? target->GetGUIDLow() : 0);
151  }
152  return pCreature;
153 }
154 
155 inline Unit* Map::_GetScriptUnit(Object* obj, bool isSource, const ScriptInfo* scriptInfo) const
156 {
157  Unit* pUnit = NULL;
158  if (!obj)
159  sLog.outError("%s %s object is NULL.", scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target");
160  else if (!obj->isType(TYPEMASK_UNIT))
161  sLog.outError("%s %s object is not unit (TypeId: %u, Entry: %u, GUID: %u), skipping.",
162  scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUIDLow());
163  else
164  {
165  pUnit = dynamic_cast<Unit*>(obj);
166  if (!pUnit)
167  sLog.outError("%s %s object could not be casted to unit.",
168  scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target");
169  }
170  return pUnit;
171 }
172 
173 inline Player* Map::_GetScriptPlayer(Object* obj, bool isSource, const ScriptInfo* scriptInfo) const
174 {
175  Player* pPlayer = NULL;
176  if (!obj)
177  sLog.outError("%s %s object is NULL.", scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target");
178  else
179  {
180  pPlayer = obj->ToPlayer();
181  if (!pPlayer)
182  sLog.outError("%s %s object is not a player (TypeId: %u, Entry: %u, GUID: %u).",
183  scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUIDLow());
184  }
185  return pPlayer;
186 }
187 
188 inline Creature* Map::_GetScriptCreature(Object* obj, bool isSource, const ScriptInfo* scriptInfo) const
189 {
190  Creature* pCreature = NULL;
191  if (!obj)
192  sLog.outError("%s %s object is NULL.", scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target");
193  else
194  {
195  pCreature = obj->ToCreature();
196  if (!pCreature)
197  sLog.outError("%s %s object is not a creature (TypeId: %u, Entry: %u, GUID: %u).", scriptInfo->GetDebugInfo().c_str(),
198  isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUIDLow());
199  }
200  return pCreature;
201 }
202 
203 inline WorldObject* Map::_GetScriptWorldObject(Object* obj, bool isSource, const ScriptInfo* scriptInfo) const
204 {
205  WorldObject* pWorldObject = NULL;
206  if (!obj)
207  sLog.outError("%s %s object is NULL.",
208  scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target");
209  else
210  {
211  pWorldObject = dynamic_cast<WorldObject*>(obj);
212  if (!pWorldObject)
213  sLog.outError("%s %s object is not a world object (TypeId: %u, Entry: %u, GUID: %u).",
214  scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target", obj->GetTypeId(), obj->GetEntry(), obj->GetGUIDLow());
215  }
216  return pWorldObject;
217 }
218 
219 inline void Map::_ScriptProcessDoor(Object* source, Object* target, const ScriptInfo* scriptInfo) const
220 {
221  bool bOpen = false;
222  uint32 guid = scriptInfo->ToggleDoor.GOGuid;
223  int32 nTimeToToggle = std::max(15, int32(scriptInfo->ToggleDoor.ResetDelay));
224  switch (scriptInfo->command)
225  {
227  bOpen = true;
228  break;
230  break;
231  default:
232  sLog.outError("%s unknown command for _ScriptProcessDoor.", scriptInfo->GetDebugInfo().c_str());
233  return;
234  }
235  if (!guid)
236  sLog.outError("%s door guid is not specified.", scriptInfo->GetDebugInfo().c_str());
237  else if (!source)
238  sLog.outError("%s source object is NULL.", scriptInfo->GetDebugInfo().c_str());
239  else if (!source->isType(TYPEMASK_UNIT))
240  sLog.outError("%s source object is not unit (TypeId: %u, Entry: %u, GUID: %u), skipping.", scriptInfo->GetDebugInfo().c_str(),
241  source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
242  else
243  {
244  WorldObject* wSource = dynamic_cast <WorldObject*> (source);
245  if (!wSource)
246  sLog.outError("%s source object could not be casted to world object (TypeId: %u, Entry: %u, GUID: %u), skipping.",
247  scriptInfo->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
248  else
249  {
250  GameObject* pDoor = _FindGameObject(wSource, guid);
251  if (!pDoor)
252  sLog.outError("%s gameobject was not found (guid: %u).", scriptInfo->GetDebugInfo().c_str(), guid);
253  else if (pDoor->GetGoType() != GAMEOBJECT_TYPE_DOOR && pDoor->GetGoType () != GAMEOBJECT_TYPE_BUTTON)
254  sLog.outError("%s gameobject is not a door (or button) (GoType: %u, Entry: %u, GUID: %u).",
255  scriptInfo->GetDebugInfo().c_str(), pDoor->GetGoType(), pDoor->GetEntry(), pDoor->GetGUIDLow());
256  else if (bOpen == (pDoor->GetGoState() == GO_STATE_READY))
257  {
258  pDoor->UseDoorOrButton(nTimeToToggle);
259 
260  if (target && target->isType(TYPEMASK_GAMEOBJECT))
261  {
262  GameObject* goTarget = dynamic_cast<GameObject*>(target);
263  if (goTarget && goTarget->GetGoType() == GAMEOBJECT_TYPE_BUTTON)
264  goTarget->UseDoorOrButton(nTimeToToggle);
265  }
266  }
267  }
268  }
269 }
270 
271 inline GameObject* Map::_FindGameObject(WorldObject* searchObject, uint32 guid) const
272 {
273  GameObject* gameobject = NULL;
274 
275  CellCoord p(Oregon::ComputeCellCoord(searchObject->GetPositionX(), searchObject->GetPositionY()));
276  Cell cell(p);
277 
278  Oregon::GameObjectWithDbGUIDCheck goCheck(*searchObject, guid);
280 
282  cell.Visit(p, objectChecker, *searchObject->GetMap(), *searchObject, searchObject->GetGridActivationRange());
283 
284  return gameobject;
285 }
286 
287 // Process queued scripts
289 {
290  if (m_scriptSchedule.empty())
291  return;
292 
293  // Process overdue queued scripts
294  std::multimap<time_t, ScriptAction>::iterator iter = m_scriptSchedule.begin();
295  // ok as multimap is a *sorted* associative container
296  while (!m_scriptSchedule.empty() && (iter->first <= sWorld.GetGameTime()))
297  {
298  ScriptAction const& step = iter->second;
299 
300  Object* source = NULL;
301 
302  if (step.sourceGUID)
303  {
304  switch (GUID_HIPART(step.sourceGUID))
305  {
306  case HIGHGUID_ITEM:
307  // case HIGHGUID_CONTAINER: == HIGHGUID_ITEM
308  {
310  if (player)
311  source = player->GetItemByGuid(step.sourceGUID);
312  break;
313  }
314  case HIGHGUID_UNIT:
316  break;
317  case HIGHGUID_PET:
318  source = HashMapHolder<Pet>::Find(step.sourceGUID);
319  break;
320  case HIGHGUID_PLAYER:
322  break;
323  case HIGHGUID_GAMEOBJECT:
325  break;
326  case HIGHGUID_CORPSE:
328  break;
330  for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
331  {
332  if ((*iter)->GetGUID() == step.sourceGUID)
333  {
334  source = reinterpret_cast<Object*>(*iter);
335  break;
336  }
337  }
338  break;
339  default:
340  sLog.outError("*_script source with unsupported high guid value %u", GUID_HIPART(step.sourceGUID));
341  break;
342  }
343  }
344 
345  //if (source && !source->IsInWorld()) source = NULL;
346 
347  Object* target = NULL;
348 
349  if (step.targetGUID)
350  {
351  switch (GUID_HIPART(step.targetGUID))
352  {
353  case HIGHGUID_UNIT:
355  break;
356  case HIGHGUID_PET:
357  target = HashMapHolder<Pet>::Find(step.targetGUID);
358  break;
359  case HIGHGUID_PLAYER: // empty GUID case also
361  break;
362  case HIGHGUID_GAMEOBJECT:
364  break;
365  case HIGHGUID_CORPSE:
367  break;
368  default:
369  sLog.outError("*_script source with unsupported high guid value %u", GUID_HIPART(step.targetGUID));
370  break;
371  }
372  }
373 
374  //if (target && !target->IsInWorld()) target = NULL;
375 
376  std::string tableName = GetScriptsTableNameByType(step.script->type);
377  std::string commandName = GetScriptCommandName(step.script->command);
378  switch (step.script->command)
379  {
380  case SCRIPT_COMMAND_TALK:
381  if (step.script->Talk.ChatType > CHAT_TYPE_WHISPER && step.script->Talk.ChatType != CHAT_MSG_RAID_BOSS_WHISPER)
382  {
383  sLog.outError("%s invalid chat type (%u) specified, skipping.", step.script->GetDebugInfo().c_str(), step.script->Talk.ChatType);
384  break;
385  }
386  if (step.script->Talk.Flags & SF_TALK_USE_PLAYER)
387  {
388  if (Player* pSource = _GetScriptPlayerSourceOrTarget(source, target, step.script))
389  {
390  uint64 targetGUID = target ? target->GetGUID() : 0;
391  uint32 loc_idx = pSource->GetSession()->GetSessionDbLocaleIndex();
392  std::string text(sObjectMgr.GetOregonString(step.script->Talk.TextID, loc_idx));
393 
394  switch (step.script->Talk.ChatType)
395  {
396  case CHAT_TYPE_SAY:
397  pSource->Say(text, LANG_UNIVERSAL);
398  break;
399  case CHAT_TYPE_YELL:
400  pSource->Yell(text, LANG_UNIVERSAL);
401  break;
404  pSource->TextEmote(text);
405  break;
406  case CHAT_TYPE_WHISPER:
408  if (!targetGUID || !IS_PLAYER_GUID(targetGUID))
409  {
410  sLog.outError("%s attempt to whisper to non-player unit, skipping.", step.script->GetDebugInfo().c_str());
411  break;
412  }
413  pSource->Whisper(text, LANG_UNIVERSAL, targetGUID);
414  break;
415  default:
416  break; // must be already checked at load
417  }
418  }
419  }
420  else
421  {
422  // Source or target must be Creature.
423  if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script))
424  {
425  uint64 targetGUID = target ? target->GetGUID() : 0;
426  switch (step.script->Talk.ChatType)
427  {
428  case CHAT_TYPE_SAY:
429  cSource->Say(step.script->Talk.TextID, LANG_UNIVERSAL, targetGUID);
430  break;
431  case CHAT_TYPE_YELL:
432  cSource->Yell(step.script->Talk.TextID, LANG_UNIVERSAL, targetGUID);
433  break;
435  cSource->TextEmote(step.script->Talk.TextID, targetGUID);
436  break;
438  cSource->MonsterTextEmote(step.script->Talk.TextID, targetGUID, true);
439  break;
440  case CHAT_TYPE_WHISPER:
441  if (!targetGUID || !IS_PLAYER_GUID(targetGUID))
442  {
443  sLog.outError("%s attempt to whisper to non-player unit, skipping.", step.script->GetDebugInfo().c_str());
444  break;
445  }
446  cSource->Whisper(step.script->Talk.TextID, targetGUID);
447  break;
448  case CHAT_MSG_RAID_BOSS_WHISPER: //42
449  if (!targetGUID || !IS_PLAYER_GUID(targetGUID))
450  {
451  sLog.outError("%s attempt to raidbosswhisper to non-player unit, skipping.", step.script->GetDebugInfo().c_str());
452  break;
453  }
454  cSource->MonsterWhisper(step.script->Talk.TextID, targetGUID, true);
455  break;
456  default:
457  break; // must be already checked at load
458  }
459  }
460  }
461  break;
462 
464  // Source or target must be Creature.
465  if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script))
466  {
467  if (step.script->Emote.Flags & SF_EMOTE_USE_STATE)
468  cSource->SetUInt32Value(UNIT_NPC_EMOTESTATE, step.script->Emote.EmoteID);
469  else
470  cSource->HandleEmoteCommand(step.script->Emote.EmoteID);
471  }
472  break;
473 
475  // Source or target must be Creature.
476  if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script))
477  {
478  // Validate field number.
479  if (step.script->FieldSet.FieldID <= OBJECT_FIELD_ENTRY || step.script->FieldSet.FieldID >= cSource->GetValuesCount())
480  sLog.outError("%s wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u) specified, skipping.",
481  step.script->GetDebugInfo().c_str(), step.script->FieldSet.FieldID,
482  cSource->GetValuesCount(), cSource->GetTypeId(), cSource->GetEntry(), cSource->GetGUIDLow());
483  else
484  cSource->SetUInt32Value(step.script->FieldSet.FieldID, step.script->FieldSet.FieldValue);
485  }
486  break;
487 
489  // Source or target must be Creature.
490  if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script))
491  {
492  Movement::MoveSplineInit init(*cSource);
493  init.MoveTo(step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, true);
494  int32 duration = init.Launch();
495  if (duration != step.script->MoveTo.TravelTime)
496  sLog.outError("SCRIPT_COMMAND_MOVE_TO : Travel time and duration from spline don't match (travel time : %u, duration : %i). Object (TypeId: %u, Entry: %u, GUID: %u)",
497  step.script->MoveTo.TravelTime, duration,
498  source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
499  cSource->GetMap()->CreatureRelocation(cSource, step.script->MoveTo.DestX, step.script->MoveTo.DestY, step.script->MoveTo.DestZ, ((Unit *)source)->GetAngle(step.script->MoveTo.DestX, step.script->MoveTo.DestY));
500  }
501  break;
502 
504  // Source or target must be Creature.
505  if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script))
506  {
507  // Validate field number.
508  if (step.script->FlagToggle.FieldID <= OBJECT_FIELD_ENTRY || step.script->FlagToggle.FieldID >= cSource->GetValuesCount())
509  sLog.outError("%s wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u) specified, skipping.",
510  step.script->GetDebugInfo().c_str(), step.script->FlagToggle.FieldID,
511  source->GetValuesCount(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
512  else
513  cSource->SetFlag(step.script->FlagToggle.FieldID, step.script->FlagToggle.FieldValue);
514  }
515  break;
516 
518  // Source or target must be Creature.
519  if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script))
520  {
521  // Validate field number.
522  if (step.script->FlagToggle.FieldID <= OBJECT_FIELD_ENTRY || step.script->FlagToggle.FieldID >= cSource->GetValuesCount())
523  sLog.outError("%s wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u) specified, skipping.",
524  step.script->GetDebugInfo().c_str(), step.script->FlagToggle.FieldID,
525  source->GetValuesCount(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
526  else
527  cSource->RemoveFlag(step.script->FlagToggle.FieldID, step.script->FlagToggle.FieldValue);
528  }
529  break;
530 
532  if (step.script->TeleportTo.Flags & SF_TELEPORT_USE_CREATURE)
533  {
534  // Source or target must be Creature.
535  if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script, true))
536  cSource->NearTeleportTo(step.script->TeleportTo.DestX, step.script->TeleportTo.DestY, step.script->TeleportTo.DestZ, step.script->TeleportTo.Orientation);
537  }
538  else
539  {
540  // Source or target must be Player.
541  if (Player* pSource = _GetScriptPlayerSourceOrTarget(source, target, step.script))
542  pSource->TeleportTo(step.script->TeleportTo.MapID, step.script->TeleportTo.DestX, step.script->TeleportTo.DestY, step.script->TeleportTo.DestZ, step.script->TeleportTo.Orientation);
543  }
544  break;
545 
547  {
548  if (!source)
549  {
550  sLog.outError("%s source object is NULL.", step.script->GetDebugInfo().c_str());
551  break;
552  }
553  if (!target)
554  {
555  sLog.outError("%s target object is NULL.", step.script->GetDebugInfo().c_str());
556  break;
557  }
558 
559  // when script called for item spell casting then target == (unit or GO) and source is player
560  WorldObject* worldObject;
561  Player* pTarget = target->ToPlayer();
562  if (pTarget)
563  {
564  if (source->GetTypeId() != TYPEID_UNIT && source->GetTypeId() != TYPEID_GAMEOBJECT && source->GetTypeId() != TYPEID_PLAYER)
565  {
566  sLog.outError("%s source is not unit, gameobject or player (TypeId: %u, Entry: %u, GUID: %u), skipping.",
567  step.script->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
568  break;
569  }
570  worldObject = dynamic_cast<WorldObject*>(source);
571  }
572  else
573  {
574  pTarget = source->ToPlayer();
575  if (pTarget)
576  {
577  if (target->GetTypeId() != TYPEID_UNIT && target->GetTypeId() != TYPEID_GAMEOBJECT && target->GetTypeId() != TYPEID_PLAYER)
578  {
579  sLog.outError("%s target is not unit, gameobject or player (TypeId: %u, Entry: %u, GUID: %u), skipping.",
580  step.script->GetDebugInfo().c_str(), target->GetTypeId(), target->GetEntry(), target->GetGUIDLow());
581  break;
582  }
583  worldObject = dynamic_cast<WorldObject*>(target);
584  }
585  else
586  {
587  sLog.outError("%s neither source nor target is player (source: TypeId: %u, Entry: %u, GUID: %u; target: TypeId: %u, Entry: %u, GUID: %u), skipping.",
588  step.script->GetDebugInfo().c_str(),
589  source ? source->GetTypeId() : 0, source ? source->GetEntry() : 0, source ? source->GetGUIDLow() : 0,
590  target ? target->GetTypeId() : 0, target ? target->GetEntry() : 0, target ? target->GetGUIDLow() : 0);
591  break;
592  }
593  }
594 
595  // quest id and flags checked at script loading
596  if ((worldObject->GetTypeId() != TYPEID_UNIT || ((Unit*)worldObject)->IsAlive()) &&
597  (step.script->QuestExplored.Distance == 0 || worldObject->IsWithinDistInMap(pTarget, float(step.script->QuestExplored.Distance))))
598  pTarget->AreaExploredOrEventHappens(step.script->QuestExplored.QuestID);
599  else
600  pTarget->FailQuest(step.script->QuestExplored.QuestID);
601 
602  break;
603  }
604 
606  // Source or target must be Player.
607  if (Player* pSource = _GetScriptPlayerSourceOrTarget(source, target, step.script))
608  {
609  if (step.script->KillCredit.Flags & SF_KILLCREDIT_REWARD_GROUP)
610  pSource->RewardPlayerAndGroupAtEvent(step.script->KillCredit.CreatureEntry, pSource);
611  else
612  pSource->KilledMonsterCredit(step.script->KillCredit.CreatureEntry, 0);
613  }
614  break;
615 
617  if (!step.script->RespawnGameobject.GOGuid)
618  {
619  sLog.outError("%s gameobject guid (datalong) is not specified.", step.script->GetDebugInfo().c_str());
620  break;
621  }
622 
623  // Source or target must be WorldObject.
624  if (WorldObject* pSummoner = _GetScriptWorldObject(source, true, step.script))
625  {
626  GameObject* pGO = _FindGameObject(pSummoner, step.script->RespawnGameobject.GOGuid);
627  if (!pGO)
628  {
629  sLog.outError("%s gameobject was not found (guid: %u).", step.script->GetDebugInfo().c_str(), step.script->RespawnGameobject.GOGuid);
630  break;
631  }
632 
633  if (pGO->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE ||
634  pGO->GetGoType() == GAMEOBJECT_TYPE_DOOR ||
635  pGO->GetGoType() == GAMEOBJECT_TYPE_BUTTON ||
637  {
638  sLog.outError("%s can not be used with gameobject of type %u (guid: %u).",
639  step.script->GetDebugInfo().c_str(), uint32(pGO->GetGoType()), step.script->RespawnGameobject.GOGuid);
640  break;
641  }
642 
643  // Check that GO is not spawned
644  if (!pGO->isSpawned())
645  {
646  int32 nTimeToDespawn = std::max(5, int32(step.script->RespawnGameobject.DespawnDelay));
647  pGO->SetLootState(GO_READY);
648  pGO->SetRespawnTime(nTimeToDespawn);
649 
650  pGO->GetMap()->AddToMap(pGO);
651  }
652  }
653  break;
654 
656  {
657  // Source must be WorldObject.
658  if (WorldObject* pSummoner = _GetScriptWorldObject(source, true, step.script))
659  {
660  if (!step.script->TempSummonCreature.CreatureEntry)
661  sLog.outError("%s creature entry (datalong) is not specified.", step.script->GetDebugInfo().c_str());
662  else
663  {
664  float x = step.script->TempSummonCreature.PosX;
665  float y = step.script->TempSummonCreature.PosY;
666  float z = step.script->TempSummonCreature.PosZ;
667  float o = step.script->TempSummonCreature.Orientation;
668 
669  if (!pSummoner->SummonCreature(step.script->TempSummonCreature.CreatureEntry, x, y, z, o, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, step.script->TempSummonCreature.DespawnDelay))
670  sLog.outError("%s creature was not spawned (entry: %u).", step.script->GetDebugInfo().c_str(), step.script->TempSummonCreature.CreatureEntry);
671  }
672  }
673  break;
674  }
675 
678  _ScriptProcessDoor(source, target, step.script);
679  break;
680 
682  // Source must be Unit.
683  if (Unit* pSource = _GetScriptUnit(source, true, step.script))
684  {
685  // Target must be GameObject.
686  if (!target)
687  {
688  sLog.outError("%s target object is NULL.", step.script->GetDebugInfo().c_str());
689  break;
690  }
691 
692  if (target->GetTypeId() != TYPEID_GAMEOBJECT)
693  {
694  sLog.outError("%s target object is not gameobject (TypeId: %u, Entry: %u, GUID: %u), skipping.",
695  step.script->GetDebugInfo().c_str(), target->GetTypeId(), target->GetEntry(), target->GetGUIDLow());
696  break;
697  }
698 
699  if (GameObject* pGO = dynamic_cast<GameObject*>(target))
700  if (pGO->IsUsedBy(pSource->GetGUID()))
701  pGO->Use(pSource);
702  }
703  break;
704 
706  {
707  // Source (datalong2 != 0) or target (datalong2 == 0) must be Unit.
708  bool bReverse = step.script->RemoveAura.Flags & SF_REMOVEAURA_REVERSE;
709  if (Unit* pTarget = _GetScriptUnit(bReverse ? source : target, bReverse, step.script))
710  pTarget->RemoveAurasDueToSpell(step.script->RemoveAura.SpellID);
711  break;
712  }
713 
715  {
716  // @todo Allow gameobjects to be targets and casters
717  if (!source && !target)
718  {
719  sLog.outError("%s source and target objects are NULL.", step.script->GetDebugInfo().c_str());
720  break;
721  }
722 
723  Unit* uSource = NULL;
724  Unit* uTarget = NULL;
725  // source/target cast spell at target/source (script->datalong2: 0: s->t 1: s->s 2: t->t 3: t->s
726  switch (step.script->CastSpell.Flags)
727  {
728  case SF_CASTSPELL_SOURCE_TO_TARGET: // source -> target
729  uSource = dynamic_cast<Unit*>(source);
730  uTarget = dynamic_cast<Unit*>(target);
731  break;
732  case SF_CASTSPELL_SOURCE_TO_SOURCE: // source -> source
733  uSource = dynamic_cast<Unit*>(source);
734  uTarget = uSource;
735  break;
736  case SF_CASTSPELL_TARGET_TO_TARGET: // target -> target
737  uSource = dynamic_cast<Unit*>(target);
738  uTarget = uSource;
739  break;
740  case SF_CASTSPELL_TARGET_TO_SOURCE: // target -> source
741  uSource = dynamic_cast<Unit*>(target);
742  uTarget = dynamic_cast<Unit*>(source);
743  break;
744  case SF_CASTSPELL_SEARCH_CREATURE: // source -> creature with entry
745  uSource = dynamic_cast<Unit*>(source);
746  uTarget = GetClosestCreatureWithEntry(uSource, abs(step.script->CastSpell.CreatureEntry), step.script->CastSpell.SearchRadius);
747  break;
748  }
749 
750  if (!uSource || !uSource->isType(TYPEMASK_UNIT))
751  {
752  sLog.outError("%s no source unit found for spell %u", step.script->GetDebugInfo().c_str(), step.script->CastSpell.SpellID);
753  break;
754  }
755 
756  if (!uTarget || !uTarget->isType(TYPEMASK_UNIT))
757  {
758  sLog.outError("%s no target unit found for spell %u", step.script->GetDebugInfo().c_str(), step.script->CastSpell.SpellID);
759  break;
760  }
761 
762  bool triggered = (step.script->CastSpell.Flags != 4) ?
763  step.script->CastSpell.CreatureEntry & SF_CASTSPELL_TRIGGERED :
764  step.script->CastSpell.CreatureEntry < 0;
765  uSource->CastSpell(uTarget, step.script->CastSpell.SpellID, triggered);
766  break;
767  }
768 
770  // Source must be WorldObject.
771  if (WorldObject* pSource = _GetScriptWorldObject(source, true, step.script))
772  {
773  // PlaySound.Flags bitmask: 0/1=anyone/target
774  Player* pTarget = NULL;
775  if (step.script->PlaySound.Flags & SF_PLAYSOUND_TARGET_PLAYER)
776  {
777  // Target must be Player.
778  pTarget = _GetScriptPlayer(target, false, step.script);
779  if (!pTarget)
780  break;
781  }
782 
783  // PlaySound.Flags bitmask: 0/2=without/with distance dependent
784  if (step.script->PlaySound.Flags & SF_PLAYSOUND_DISTANCE_SOUND)
785  pSource->PlayDistanceSound(step.script->PlaySound.SoundID, pTarget);
786  else
787  pSource->PlayDirectSound(step.script->PlaySound.SoundID, pTarget);
788  }
789  break;
790 
792  // Target or source must be Player.
793  if (Player* pReceiver = _GetScriptPlayerSourceOrTarget(source, target, step.script))
794  {
795  ItemPosCountVec dest;
796  uint8 msg = pReceiver->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, step.script->CreateItem.ItemEntry, step.script->CreateItem.Amount);
797  if (msg == EQUIP_ERR_OK)
798  {
799  if (Item* item = pReceiver->StoreNewItem(dest, step.script->CreateItem.ItemEntry, true))
800  pReceiver->SendNewItem(item, step.script->CreateItem.Amount, false, true);
801  }
802  else
803  pReceiver->SendEquipError(msg, NULL, NULL);
804  }
805  break;
806 
808  // Target or source must be Creature.
809  if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script, true))
810  cSource->ForcedDespawn(step.script->DespawnSelf.DespawnDelay);
811  break;
813  break;
815  // Source must be Unit.
816  if (Unit* pSource = _GetScriptUnit(source, true, step.script))
817  {
818  if (!sWaypointMgr->GetPath(step.script->LoadPath.PathID))
819  sLog.outError("%s source object has an invalid path (%u), skipping.", step.script->GetDebugInfo().c_str(), step.script->LoadPath.PathID);
820  else
821  pSource->GetMotionMaster()->MovePath(step.script->LoadPath.PathID, step.script->LoadPath.IsRepeatable);
822  }
823  break;
824 
826  {
827  if (!step.script->CallScript.CreatureEntry)
828  {
829  sLog.outError("%s creature entry is not specified, skipping.", step.script->GetDebugInfo().c_str());
830  break;
831  }
832  if (!step.script->CallScript.ScriptID)
833  {
834  sLog.outError("%s script id is not specified, skipping.", step.script->GetDebugInfo().c_str());
835  break;
836  }
837 
838  Creature* cTarget = NULL;
839  WorldObject* wSource = dynamic_cast <WorldObject*> (source);
840  if (wSource) //using grid searcher
841  {
842  CellCoord p(Oregon::ComputeCellCoord(wSource->GetPositionX(), wSource->GetPositionY()));
843  Cell cell(p);
844 
845  Oregon::CreatureWithDbGUIDCheck target_check(wSource, step.script->CallScript.CreatureEntry);
846  Oregon::CreatureSearcher<Oregon::CreatureWithDbGUIDCheck> checker(cTarget, target_check);
847 
849  cell.Visit(p, unit_checker, *wSource->GetMap(), *wSource, wSource->GetGridActivationRange());
850  }
851  else //check hashmap holders
852  {
853  if (CreatureData const* data = sObjectMgr.GetCreatureData(step.script->CallScript.CreatureEntry))
854  cTarget = ObjectAccessor::GetObjectInWorld<Creature>(data->mapid, data->posX, data->posY, MAKE_NEW_GUID(step.script->CallScript.CreatureEntry, data->id, HIGHGUID_UNIT), cTarget);
855  }
856 
857  if (!cTarget)
858  {
859  sLog.outError("%s target was not found (entry: %u)", step.script->GetDebugInfo().c_str(), step.script->CallScript.CreatureEntry);
860  break;
861  }
862 
863  //Lets choose our ScriptMap map
864  ScriptMapMap* datamap = GetScriptsMapByType(ScriptsType(step.script->CallScript.ScriptType));
865  //if no scriptmap present...
866  if (!datamap)
867  {
868  sLog.outError("%s unknown scriptmap (%u) specified, skipping.", step.script->GetDebugInfo().c_str(), step.script->CallScript.ScriptType);
869  break;
870  }
871 
872  // Insert script into schedule but do not start it
873  ScriptsStart(*datamap, step.script->CallScript.ScriptID, cTarget, NULL);
874  break;
875  }
876 
877  case SCRIPT_COMMAND_KILL:
878  // Source or target must be Creature.
879  if (Creature* cSource = _GetScriptCreatureSourceOrTarget(source, target, step.script))
880  {
881  if (cSource->isDead())
882  sLog.outError("%s creature is already dead (Entry: %u, GUID: %u)",
883  step.script->GetDebugInfo().c_str(), cSource->GetEntry(), cSource->GetGUIDLow());
884  else
885  {
886  cSource->setDeathState(JUST_DIED);
887  if (step.script->Kill.RemoveCorpse == 1)
888  cSource->RemoveCorpse();
889  }
890  }
891  break;
892 
894  // Source must be Unit.
895  if (Unit* pSource = _GetScriptUnit(source, true, step.script))
896  {
898  {
899  // Target must be Unit.
900  Unit* pTarget = _GetScriptUnit(target, false, step.script);
901  if (!pTarget)
902  break;
903 
904  pSource->SetFacingToObject(pTarget);
905  }
906  else
907  pSource->SetFacingTo(step.script->Orientation.Orientation);
908  }
909  break;
910 
912  // Source must be Creature.
913  if (Creature* cSource = _GetScriptCreature(source, true, step.script))
914  cSource->LoadEquipment(step.script->Equip.EquipmentID);
915  break;
916 
918  // Source must be Creature.
919  if (Creature* cSource = _GetScriptCreature(source, true, step.script))
920  cSource->SetDisplayId(step.script->Model.ModelID);
921  break;
922 
924  // Source must be Player.
925  if (Player* pSource = _GetScriptPlayer(source, true, step.script))
926  pSource->PlayerTalkClass->CloseGossip();
927  break;
928 
929  default:
930  sLog.outError("Unknown script command %s.", step.script->GetDebugInfo().c_str());
931  break;
932  }
933 
934  m_scriptSchedule.erase(iter);
935  sWorld.DecreaseScheduledScriptCount();
936 
937  iter = m_scriptSchedule.begin();
938  }
939 }
std::multimap< time_t, ScriptAction > m_scriptSchedule
Definition: Map.h:644
float GetGridActivationRange() const
Definition: Object.cpp:1528
Definition: Object.h:124
struct ScriptInfo::@99::@106 FlagToggle
bool AddToMap(T *)
Definition: Map.cpp:424
std::string GetScriptCommandName(ScriptCommands command)
Definition: ObjectMgr.cpp:120
std::multimap< uint32, ScriptInfo > ScriptMap
Definition: ObjectMgr.h:327
void ScriptsStart(std::map< uint32, std::multimap< uint32, ScriptInfo > > const &scripts, uint32 id, Object *source, Object *target)
Definition: MapScripts.cpp:33
GOState GetGoState() const
Definition: GameObject.h:726
struct ScriptInfo::@99::@114 CastSpell
struct ScriptInfo::@99::@103 Emote
Map * GetMap() const
Definition: Object.h:829
struct ScriptInfo::@99::@104 FieldSet
float Orientation
Definition: ObjectMgr.h:205
void _ScriptProcessDoor(Object *source, Object *target, const ScriptInfo *scriptInfo) const
Definition: MapScripts.cpp:219
Player * _GetScriptPlayer(Object *obj, bool isSource, const ScriptInfo *scriptInfo) const
Definition: MapScripts.cpp:173
struct ScriptInfo::@99::@123 Model
ScriptCommands command
Definition: ObjectMgr.h:149
ScriptsType
Definition: ObjectMgr.h:96
bool isType(uint16 mask) const
Definition: Object.h:208
ScriptInfo const * script
Definition: Map.h:63
std::map< uint32, ScriptMap > ScriptMapMap
Definition: ObjectMgr.h:328
#define sLog
Log class singleton.
Definition: Log.h:187
std::string GetDebugInfo() const
Definition: ObjectMgr.cpp:218
ACE_INT32 int32
Definition: Define.h:67
static T * Find(uint64 guid)
void SetRespawnTime(int32 respawn)
Definition: GameObject.h:691
#define GUID_HIPART(x)
Definition: ObjectGuid.h:82
struct ScriptInfo::@99::@119 CallScript
uint32 GetGUIDLow() const
Definition: Object.h:160
struct ScriptInfo::@99::@102 Talk
ScriptsType type
Definition: ObjectMgr.h:146
void MoveTo(const Vector3 &destination, bool generatePath=false, bool forceDestination=false)
struct ScriptInfo::@99::@115 PlaySound
#define sObjectMgr
Definition: ObjectMgr.h:1285
bool i_scriptLock
Definition: Map.h:640
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true) const
Definition: Object.h:762
Player * ToPlayer()
Definition: Object.h:386
struct ScriptInfo::@99::@109 KillCredit
struct ScriptInfo::@99::@122 Equip
#define IS_PLAYER_GUID(Guid)
Definition: ObjectGuid.h:69
void SetLootState(LootState s, Unit *unit=NULL)
void FailQuest(uint32 questId)
Definition: Player.cpp:13178
uint8 GetTypeId() const
Definition: Object.h:204
ACE_UINT8 uint8
Definition: Define.h:73
#define sWaypointMgr
struct ScriptInfo::@99::@118 LoadPath
Definition: Unit.h:297
std::string GetScriptsTableNameByType(ScriptsType type)
Definition: ObjectMgr.cpp:56
uint64 sourceGUID
Definition: Map.h:60
struct ScriptInfo::@99::@116 CreateItem
Creature * _GetScriptCreature(Object *obj, bool isSource, const ScriptInfo *scriptInfo) const
Definition: MapScripts.cpp:188
float GetPositionY() const
Definition: Position.h:98
#define MAKE_NEW_GUID(l, e, h)
Definition: ObjectGuid.h:80
Definition: Item.h:196
void CastSpell(Unit *Victim, uint32 spellId, bool triggered, Item *castItem=NULL, Aura *triggeredByAura=NULL, uint64 originalCaster=0)
Definition: Unit.cpp:1174
Unit * _GetScriptUnit(Object *obj, bool isSource, const ScriptInfo *scriptInfo) const
Definition: MapScripts.cpp:155
uint64 targetGUID
Definition: Map.h:61
struct ScriptInfo::@99::@107 TeleportTo
WorldObject * _GetScriptWorldObject(Object *obj, bool isSource, const ScriptInfo *scriptInfo) const
Definition: MapScripts.cpp:203
ScriptMapMap * GetScriptsMapByType(ScriptsType type)
Definition: ObjectMgr.cpp:88
Creature * GetClosestCreatureWithEntry(WorldObject *pSource, uint32 uiEntry, float fMaxSearchRange, bool bAlive)
void ScriptCommandStart(ScriptInfo const &script, uint32 delay, Object *source, Object *target)
Definition: MapScripts.cpp:71
CellCoord ComputeCellCoord(float x, float y)
Definition: GridDefines.h:167
void UseDoorOrButton(uint32 time_to_restore=0, bool alternative=false, Unit *user=NULL)
Definition: GameObject.cpp:950
Player * _GetScriptPlayerSourceOrTarget(Object *source, Object *target, const ScriptInfo *scriptInfo) const
Definition: MapScripts.cpp:100
std::vector< ItemPosCount > ItemPosCountVec
Definition: Player.h:605
ACE_UINT64 uint64
Definition: Define.h:70
Definition: Cell.h:46
despawns after a specified time OR when the creature disappears
uint16 GetValuesCount() const
Definition: Object.h:367
bool isSpawned() const
Definition: GameObject.h:697
GameobjectTypes GetGoType() const
Definition: GameObject.h:718
struct ScriptInfo::@99::@105 MoveTo
Creature * ToCreature()
Definition: Object.h:389
struct ScriptInfo::@99::@108 QuestExplored
struct ScriptInfo::@99::@111 TempSummonCreature
void AreaExploredOrEventHappens(uint32 questId)
Definition: Player.cpp:13731
struct ScriptInfo::@99::@120 Kill
struct ScriptInfo::@99::@112 ToggleDoor
TransportSet m_Transports
Definition: MapManager.h:127
uint32 GetEntry() const
Definition: Object.h:186
#define sWorld
Definition: World.h:860
GameObject * _FindGameObject(WorldObject *pWorldObject, uint32 guid) const
Definition: MapScripts.cpp:271
uint64 ownerGUID
Definition: Map.h:62
ACE_UINT32 uint32
Definition: Define.h:71
float GetPositionX() const
Definition: Position.h:97
Creature * _GetScriptCreatureSourceOrTarget(Object *source, Object *target, const ScriptInfo *scriptInfo, bool bReverse=false) const
Definition: MapScripts.cpp:122
struct ScriptInfo::@99::@110 RespawnGameobject
Definition: Unit.h:884
struct ScriptInfo::@99::@113 RemoveAura
void ScriptsProcess()
Definition: MapScripts.cpp:288
Definition: Player.h:922
void Visit(CellCoord const &, TypeContainerVisitor< T, CONTAINER > &visitor, Map &, WorldObject const &, float) const
Definition: CellImpl.h:121
struct ScriptInfo::@99::@117 DespawnSelf
Item * GetItemByGuid(uint64 guid) const
Definition: Player.cpp:8583
const uint64 & GetGUID() const
Definition: Object.h:156