Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
InstanceScript.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Creature.h"
7#include "CreatureAI.h"
8#include "DatabaseEnv.h"
9#include "GameObject.h"
10#include "Group.h"
11#include "InstanceScript.h"
12#include "LFGMgr.h"
13#include "Log.h"
14#include "Map.h"
15#include "Opcodes.h"
16#include "Pet.h"
17#include "Player.h"
18#include "WorldSession.h"
19
21{
22 std::string data = GetSaveData();
23 if (data.empty())
24 return;
25
28 stmt->setString(1, data);
29 stmt->setUInt32(2, instance->GetInstanceId());
30 CharacterDatabase.Execute(stmt);
31}
32
34{
35 if (!go)
36 go = instance->GetGameObject(GUID);
37 if (go)
39 else
40 SF_LOG_DEBUG("scripts", "InstanceScript: HandleGameObject failed");
41}
42
44{
45 for (std::vector<BossInfo>::const_iterator itr = bosses.begin(); itr != bosses.end(); ++itr)
46 if (itr->state == IN_PROGRESS)
47 return true;
48
49 return false;
50}
51
53{
54 while (data->entry)
55 {
56 if (data->bossId < bosses.size())
57 minions.insert(std::make_pair(data->entry, MinionInfo(&bosses[data->bossId])));
58
59 ++data;
60 }
61 SF_LOG_DEBUG("scripts", "InstanceScript::LoadMinionData: " UI64FMTD " minions loaded.", uint64(minions.size()));
62}
63
65{
66 while (data->entry)
67 {
68 if (data->bossId < bosses.size())
69 doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type, BoundaryType(data->boundary))));
70
71 ++data;
72 }
73 SF_LOG_DEBUG("scripts", "InstanceScript::LoadDoorData: " UI64FMTD " doors loaded.", uint64(doors.size()));
74}
75
77{
78 switch (state)
79 {
80 case NOT_STARTED:
81 if (!minion->IsAlive())
82 minion->Respawn();
83 else if (minion->IsInCombat())
84 minion->AI()->EnterEvadeMode();
85 break;
86 case IN_PROGRESS:
87 if (!minion->IsAlive())
88 minion->Respawn();
89 else if (!minion->GetVictim())
90 minion->AI()->DoZoneInCombat();
91 break;
92 default:
93 break;
94 }
95}
96
98{
99 DoorInfoMapBounds range = doors.equal_range(door->GetEntry());
100 if (range.first == range.second)
101 return;
102
103 bool open = true;
104 for (; range.first != range.second && open; ++range.first)
105 {
106 DoorInfo const& info = range.first->second;
107 switch (info.type)
108 {
109 case DOOR_TYPE_ROOM:
110 open = (info.bossInfo->state != IN_PROGRESS);
111 break;
113 open = (info.bossInfo->state == DONE);
114 break;
116 open = (info.bossInfo->state == IN_PROGRESS);
117 break;
118 default:
119 break;
120 }
121 }
122
124}
125
127{
128 DoorInfoMapBounds range = doors.equal_range(door->GetEntry());
129 if (range.first == range.second)
130 return;
131
132 for (; range.first != range.second; ++range.first)
133 {
134 DoorInfo const& data = range.first->second;
135
136 if (add)
137 {
138 data.bossInfo->door[data.type].insert(door);
139 switch (data.boundary)
140 {
141 default:
142 case BOUNDARY_NONE:
143 break;
144 case BOUNDARY_N:
145 case BOUNDARY_S:
146 data.bossInfo->boundary[data.boundary] = door->GetPositionX();
147 break;
148 case BOUNDARY_E:
149 case BOUNDARY_W:
150 data.bossInfo->boundary[data.boundary] = door->GetPositionY();
151 break;
152 case BOUNDARY_NW:
153 case BOUNDARY_SE:
154 data.bossInfo->boundary[data.boundary] = door->GetPositionX() + door->GetPositionY();
155 break;
156 case BOUNDARY_NE:
157 case BOUNDARY_SW:
158 data.bossInfo->boundary[data.boundary] = door->GetPositionX() - door->GetPositionY();
159 break;
160 }
161 }
162 else
163 data.bossInfo->door[data.type].erase(door);
164 }
165
166 if (add)
167 UpdateDoorState(door);
168}
169
170void InstanceScript::AddMinion(Creature* minion, bool add)
171{
172 MinionInfoMap::iterator itr = minions.find(minion->GetEntry());
173 if (itr == minions.end())
174 return;
175
176 if (add)
177 itr->second.bossInfo->minion.insert(minion);
178 else
179 itr->second.bossInfo->minion.erase(minion);
180}
181
183{
184 if (id < bosses.size())
185 {
186 BossInfo* bossInfo = &bosses[id];
187 if (bossInfo->state == TO_BE_DECIDED) // loading
188 {
189 bossInfo->state = state;
190 //SF_LOG_ERROR("misc", "Inialize boss %u state as %u.", id, (uint32)state);
191 return false;
192 }
193 else
194 {
195 if (bossInfo->state == state)
196 return false;
197
198 if (state == DONE)
199 for (MinionSet::iterator i = bossInfo->minion.begin(); i != bossInfo->minion.end(); ++i)
200 if ((*i)->isWorldBoss() && (*i)->IsAlive())
201 return false;
202
203 bossInfo->state = state;
204 SaveToDB();
205 }
206
207 for (uint32 type = 0; type < MAX_DOOR_TYPES; ++type)
208 for (DoorSet::iterator i = bossInfo->door[type].begin(); i != bossInfo->door[type].end(); ++i)
209 UpdateDoorState(*i);
210
211 for (MinionSet::iterator i = bossInfo->minion.begin(); i != bossInfo->minion.end(); ++i)
212 UpdateMinionState(*i, state);
213
214 return true;
215 }
216 return false;
217}
218
219void InstanceScript::LoadBossState(const char* data)
220{
221 if (!data)
222 {
223 //OUT_LOAD_INST_DATA_FAIL
224 return;
225 }
226 //OUT_LOAD_INST_DATA(data);
227 std::istringstream loadStream(data);
228 uint32 buff;
229 uint32 bossId = 0;
230 for (std::vector<BossInfo>::iterator i = bosses.begin(); i != bosses.end(); ++i, ++bossId)
231 {
232 loadStream >> buff;
233 if (buff < TO_BE_DECIDED)
234 SetBossState(bossId, (EncounterState)buff);
235 }
236 //OUT_LOAD_INST_DATA_COMPLETE
237}
238
240{
241 std::ostringstream saveStream;
242 for (std::vector<BossInfo>::iterator i = bosses.begin(); i != bosses.end(); ++i)
243 saveStream << (uint32)i->state << ' ';
244 return saveStream.str();
245}
246
247void InstanceScript::DoUseDoorOrButton(uint64 uiGuid, uint32 uiWithRestoreTime, bool bUseAlternativeState)
248{
249 if (!uiGuid)
250 return;
251
252 GameObject* go = instance->GetGameObject(uiGuid);
253
254 if (go)
255 {
257 {
259 go->UseDoorOrButton(uiWithRestoreTime, bUseAlternativeState);
260 else if (go->getLootState() == LootState::GO_ACTIVATED)
261 go->ResetDoorOrButton();
262 }
263 else
264 SF_LOG_ERROR("misc", "SD2: Script call DoUseDoorOrButton, but gameobject entry %u is type %u.", go->GetEntry(), go->GetGoType());
265 }
266}
267
269{
270 if (GameObject* go = instance->GetGameObject(uiGuid))
271 {
272 //not expect any of these should ever be handled
273 if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE || go->GetGoType() == GAMEOBJECT_TYPE_DOOR ||
274 go->GetGoType() == GAMEOBJECT_TYPE_BUTTON || go->GetGoType() == GAMEOBJECT_TYPE_TRAP)
275 return;
276
277 if (go->isSpawned())
278 return;
279
280 go->SetRespawnTime(uiTimeToDespawn);
281 }
282}
283
285{
286 Map::PlayerList const& lPlayers = instance->GetPlayers();
287
288 if (!lPlayers.isEmpty())
289 {
290 for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr)
291 if (Player* player = itr->GetSource())
292 player->SendUpdateWorldState(uiStateId, uiStateData);
293 }
294 else
295 SF_LOG_DEBUG("scripts", "DoUpdateWorldState attempt send data but no players in map.");
296}
297
298// Send Notify to all players in instance
299void InstanceScript::DoSendNotifyToInstance(char const* format, ...)
300{
301 InstanceMap::PlayerList const& players = instance->GetPlayers();
302
303 if (!players.isEmpty())
304 {
305 va_list ap;
306 va_start(ap, format);
307 char buff[1024];
308 vsnprintf(buff, 1024, format, ap);
309 va_end(ap);
310 for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
311 if (Player* player = i->GetSource())
312 if (WorldSession* session = player->GetSession())
313 session->SendNotification("%s", buff);
314 }
315}
316
317// Update Achievement Criteria for all players in instance
318void InstanceScript::DoUpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= NULL*/)
319{
320 Map::PlayerList const& PlayerList = instance->GetPlayers();
321
322 if (!PlayerList.isEmpty())
323 for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
324 if (Player* player = i->GetSource())
325 player->UpdateAchievementCriteria(type, miscValue1, miscValue2, 0, unit);
326}
327
328// Start timed achievement for all players in instance
330{
331 Map::PlayerList const& PlayerList = instance->GetPlayers();
332
333 if (!PlayerList.isEmpty())
334 for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
335 if (Player* player = i->GetSource())
336 player->StartTimedAchievement(type, entry);
337}
338
339// Stop timed achievement for all players in instance
341{
342 Map::PlayerList const& PlayerList = instance->GetPlayers();
343
344 if (!PlayerList.isEmpty())
345 for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
346 if (Player* player = i->GetSource())
347 player->RemoveTimedAchievement(type, entry);
348}
349
350// Remove Auras due to Spell on all players in instance
352{
353 Map::PlayerList const& PlayerList = instance->GetPlayers();
354 if (!PlayerList.isEmpty())
355 {
356 for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)
357 {
358 if (Player* player = itr->GetSource())
359 {
360 player->RemoveAurasDueToSpell(spell);
361 if (Pet* pet = player->GetPet())
362 pet->RemoveAurasDueToSpell(spell);
363 }
364 }
365 }
366}
367
368// Cast spell on all players in instance
370{
371 Map::PlayerList const& PlayerList = instance->GetPlayers();
372
373 if (!PlayerList.isEmpty())
374 for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
375 if (Player* player = i->GetSource())
376 player->CastSpell(player, spell, true);
377}
378
379bool InstanceScript::CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/ /*= NULL*/, uint32 /*miscvalue1*/ /*= 0*/)
380{
381 SF_LOG_ERROR("misc", "Achievement system call InstanceScript::CheckAchievementCriteriaMeet but instance script for map %u not have implementation for achievement criteria %u",
382 instance->GetId(), criteria_id);
383 return false;
384}
385
386void InstanceScript::SendEncounterUnit(uint32 type, Unit* unit /*= NULL*/, uint8 param1 /*= 0*/, uint8 param2 /*= 0*/)
387{
388 // size of this packet is at most 15 (usually less)
390 data << uint32(type);
391
392 switch (type)
393 {
397 if (!unit)
398 return;
399 data.append(unit->GetPackGUID());
400 data << uint8(param1);
401 break;
406 data << uint8(param1);
407 break;
409 data << uint8(param1);
410 data << uint8(param2);
411 break;
415 default:
416 break;
417 }
418
419 instance->SendToPlayers(&data);
420}
421
423{
424 DungeonEncounterList const* encounters = sObjectMgr->GetDungeonEncounterList(instance->GetId(), instance->GetDifficulty());
425 if (!encounters)
426 return;
427
428 uint32 dungeonId = 0;
429
430 for (DungeonEncounterList::const_iterator itr = encounters->begin(); itr != encounters->end(); ++itr)
431 {
432 DungeonEncounter const* encounter = *itr;
433 if (encounter->creditType == type && encounter->creditEntry == creditEntry)
434 {
435 completedEncounters |= 1 << encounter->dbcEntry->encounterIndex;
436 if (encounter->lastEncounterDungeon)
437 {
438 dungeonId = encounter->lastEncounterDungeon;
439 SF_LOG_DEBUG("lfg", "UpdateEncounterState: Instance %s (instanceId %u) completed encounter %s. Credit Dungeon: %u", instance->GetMapName(), instance->GetInstanceId(), encounter->dbcEntry->encounterName, dungeonId);
440 break;
441 }
442 }
443 }
444
445 if (dungeonId)
446 {
447 Map::PlayerList const& players = instance->GetPlayers();
448 for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
449 {
450 if (Player* player = i->GetSource())
451 if (Group* grp = player->GetGroup())
452 if (grp->isLFGGroup())
453 {
454 sLFGMgr->FinishDungeon(grp->GetGUID(), dungeonId);
455 return;
456 }
457 }
458 }
459}
460
462{
463 Map::PlayerList const& players = instance->GetPlayers();
464 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
465 if (Player* player = itr->GetSource())
466 player->UpdatePhasing();
467}
@ CHAR_UPD_INSTANCE_DATA
#define vsnprintf
Definition Common.h:100
AchievementCriteriaTimedTypes
Definition DBCEnums.h:157
AchievementCriteriaTypes
Definition DBCEnums.h:170
#define UI64FMTD
Definition Define.h:64
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
@ GO_STATE_ACTIVE
Definition GameObject.h:576
@ GO_STATE_READY
Definition GameObject.h:577
EncounterState
@ IN_PROGRESS
@ DONE
@ NOT_STARTED
@ TO_BE_DECIDED
@ ENCOUNTER_FRAME_RESET_COMBAT_RES_LIMIT
@ ENCOUNTER_FRAME_ENABLE_OBJECTIVE
@ ENCOUNTER_FRAME_SET_COMBAT_RES_LIMIT
@ ENCOUNTER_FRAME_UNK7
@ ENCOUNTER_FRAME_DISENGAGE
@ ENCOUNTER_FRAME_ADD_COMBAT_RES_LIMIT
@ ENCOUNTER_FRAME_UPDATE_PRIORITY
@ ENCOUNTER_FRAME_DISABLE_OBJECTIVE
@ ENCOUNTER_FRAME_UPDATE_OBJECTIVE
@ ENCOUNTER_FRAME_ADD_TIMER
@ ENCOUNTER_FRAME_ENGAGE
@ DOOR_TYPE_SPAWN_HOLE
@ DOOR_TYPE_ROOM
@ DOOR_TYPE_PASSAGE
@ MAX_DOOR_TYPES
std::pair< DoorInfoMap::const_iterator, DoorInfoMap::const_iterator > DoorInfoMapBounds
BoundaryType
@ BOUNDARY_NONE
@ BOUNDARY_SE
@ BOUNDARY_SW
@ BOUNDARY_NE
@ BOUNDARY_W
@ BOUNDARY_NW
@ BOUNDARY_S
@ BOUNDARY_N
@ BOUNDARY_E
#define sLFGMgr
Definition LFGMgr.h:518
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
EncounterCreditType
Definition ObjectMgr.h:638
#define sObjectMgr
Definition ObjectMgr.h:1617
std::list< DungeonEncounter const * > DungeonEncounterList
Definition ObjectMgr.h:654
@ GAMEOBJECT_TYPE_BUTTON
@ GAMEOBJECT_TYPE_TRAP
@ GAMEOBJECT_TYPE_FISHINGNODE
@ GAMEOBJECT_TYPE_DOOR
void append(T value)
Definition ByteBuffer.h:147
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
virtual void EnterEvadeMode()
void Respawn(bool force=false)
CreatureAI * AI() const
Definition Creature.h:483
void SetGoState(GOState state)
LootState getLootState() const
Definition GameObject.h:742
void UseDoorOrButton(uint32 time_to_restore=0, bool alternative=false, Unit *user=NULL)
GameobjectTypes GetGoType() const
Definition GameObject.h:719
void ResetDoorOrButton()
Definition Group.h:147
void DoUpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, Unit *unit=NULL)
void UpdateMinionState(Creature *minion, EncounterState state)
uint32 GetCompletedEncounterMask() const
virtual bool SetBossState(uint32 id, EncounterState state)
void DoUseDoorOrButton(uint64 guid, uint32 withRestoreTime=0, bool useAlternativeState=false)
MinionInfoMap minions
uint32 completedEncounters
void DoCastSpellOnPlayers(uint32 spell)
void UpdateEncounterState(EncounterCreditType type, uint32 creditEntry, Unit *source)
void DoRemoveAurasDueToSpellOnPlayers(uint32 spell)
std::string GetBossSaveData()
DoorInfoMap doors
void AddMinion(Creature *minion, bool add)
virtual bool IsEncounterInProgress() const
virtual std::string GetSaveData()
void LoadBossState(char const *data)
void AddDoor(GameObject *door, bool add)
virtual bool CheckAchievementCriteriaMeet(uint32, Player const *, Unit const *=NULL, uint32=0)
void LoadMinionData(MinionData const *data)
void LoadDoorData(DoorData const *data)
void DoStartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
std::vector< BossInfo > bosses
void SendEncounterUnit(uint32 type, Unit *unit=NULL, uint8 param1=0, uint8 param2=0)
void HandleGameObject(uint64 guid, bool open, GameObject *go=NULL)
void UpdateDoorState(GameObject *door)
void DoRespawnGameObject(uint64 guid, uint32 timeToDespawn=MINUTE)
void DoStopTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
void DoUpdateWorldState(uint32 worldstateId, uint32 worldstateValue)
void DoSendNotifyToInstance(char const *format,...)
bool isEmpty() const
Definition LinkedList.h:86
MapRefManager PlayerList
Definition Map.h:406
iterator end()
iterator begin()
LinkedListHead::Iterator< MapReference const > const_iterator
const ByteBuffer & GetPackGUID() const
Definition Object.h:124
uint32 GetEntry() const
Definition Object.h:125
Definition Pet.h:28
void setString(const uint8 index, const std::string &value)
void setUInt32(const uint8 index, const uint32 value)
Definition Unit.h:1367
bool IsAlive() const
Definition Unit.h:2032
Unit * GetVictim() const
Definition Unit.h:1468
bool IsInCombat() const
Definition Unit.h:1896
Player session in the World.
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition Main.cpp:41
@ SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT
Definition Opcodes.h:1050
EncounterState state
DoorSet door[MAX_DOOR_TYPES]
BossBoundaryMap boundary
MinionSet minion
uint32 entry
uint32 boundary
DoorType type
uint32 bossId
BossInfo * bossInfo
BoundaryType boundary
DoorType type
uint32 encounterIndex
char * encounterName
DungeonEncounterEntry const * dbcEntry
Definition ObjectMgr.h:648
EncounterCreditType creditType
Definition ObjectMgr.h:649
uint32 lastEncounterDungeon
Definition ObjectMgr.h:651
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329