-
Notifications
You must be signed in to change notification settings - Fork 6k
/
instance_naxxramas.cpp
410 lines (364 loc) · 13.6 KB
/
instance_naxxramas.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/*
* Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptPCH.h"
#include "naxxramas.h"
const DoorData doorData[] =
{
{181126, BOSS_ANUBREKHAN, DOOR_TYPE_ROOM, BOUNDARY_S},
{181195, BOSS_ANUBREKHAN, DOOR_TYPE_PASSAGE, 0},
{194022, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0},
{181209, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0},
{181209, BOSS_MAEXXNA, DOOR_TYPE_ROOM, BOUNDARY_SW},
{181200, BOSS_NOTH, DOOR_TYPE_ROOM, BOUNDARY_N},
{181201, BOSS_NOTH, DOOR_TYPE_PASSAGE, BOUNDARY_E},
{181202, BOSS_NOTH, DOOR_TYPE_PASSAGE, 0},
{181202, BOSS_HEIGAN, DOOR_TYPE_ROOM, BOUNDARY_N},
{181203, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, BOUNDARY_E},
{181241, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, 0},
{181241, BOSS_LOATHEB, DOOR_TYPE_ROOM, BOUNDARY_W},
{181123, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE, 0},
{181123, BOSS_GROBBULUS, DOOR_TYPE_ROOM, 0},
{181120, BOSS_GLUTH, DOOR_TYPE_PASSAGE, BOUNDARY_NW},
{181121, BOSS_GLUTH, DOOR_TYPE_PASSAGE, 0},
{181121, BOSS_THADDIUS, DOOR_TYPE_ROOM, 0},
{181124, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE, 0},
{181124, BOSS_GOTHIK, DOOR_TYPE_ROOM, BOUNDARY_N},
{181125, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, BOUNDARY_S},
{181119, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, 0},
{181119, BOSS_HORSEMEN, DOOR_TYPE_ROOM, BOUNDARY_NE},
{181225, BOSS_SAPPHIRON, DOOR_TYPE_PASSAGE, BOUNDARY_W},
{181228, BOSS_KELTHUZAD, DOOR_TYPE_ROOM, BOUNDARY_S},
{0, 0, DOOR_TYPE_ROOM, 0}, // EOF
};
const MinionData minionData[] =
{
//{16573, BOSS_ANUBREKHAN}, there is no spawn point in db, so we do not add them here
{16506, BOSS_FAERLINA},
{16803, BOSS_RAZUVIOUS},
{16063, BOSS_HORSEMEN},
{16064, BOSS_HORSEMEN},
{16065, BOSS_HORSEMEN},
{30549, BOSS_HORSEMEN},
{0, 0, }
};
enum eEnums
{
GO_HORSEMEN_CHEST_HERO = 193426,
GO_HORSEMEN_CHEST = 181366, //four horsemen event, DoRespawnGameObject() when event == DONE
GO_GOTHIK_GATE = 181170,
GO_KELTHUZAD_PORTAL01 = 181402,
GO_KELTHUZAD_PORTAL02 = 181403,
GO_KELTHUZAD_PORTAL03 = 181404,
GO_KELTHUZAD_PORTAL04 = 181405,
GO_KELTHUZAD_TRIGGER = 181444,
SPELL_ERUPTION = 29371
};
const float HeiganPos[2] = {2796, -3707};
const float HeiganEruptionSlope[3] =
{
(-3685 - HeiganPos[1]) /(2724 - HeiganPos[0]),
(-3647 - HeiganPos[1]) /(2749 - HeiganPos[0]),
(-3637 - HeiganPos[1]) /(2771 - HeiganPos[0]),
};
// 0 H x
// 1 ^
// 2 |
// 3 y<--o
inline uint32 GetEruptionSection(float x, float y)
{
y -= HeiganPos[1];
if (y < 1.0f)
return 0;
x -= HeiganPos[0];
if (x > -1.0f)
return 3;
float slope = y/x;
for (uint32 i = 0; i < 3; ++i)
if (slope > HeiganEruptionSlope[i])
return i;
return 3;
}
class instance_naxxramas : public InstanceMapScript
{
public:
instance_naxxramas() : InstanceMapScript("instance_naxxramas", 533) { }
InstanceScript* GetInstanceScript(InstanceMap* pMap) const
{
return new instance_naxxramas_InstanceMapScript(pMap);
}
struct instance_naxxramas_InstanceMapScript : public InstanceScript
{
instance_naxxramas_InstanceMapScript(Map* pMap) : InstanceScript(pMap)
{
SetBossNumber(MAX_BOSS_NUMBER);
LoadDoorData(doorData);
LoadMinionData(minionData);
}
std::set<uint64> HeiganEruptionGUID[4];
uint64 GothikGateGUID;
uint64 HorsemenChestGUID;
uint64 SapphironGUID;
uint64 uiFaerlina;
uint64 uiThane;
uint64 uiLady;
uint64 uiBaron;
uint64 uiSir;
uint64 uiThaddius;
uint64 uiHeigan;
uint64 uiFeugen;
uint64 uiStalagg;
uint64 uiKelthuzad;
uint64 uiKelthuzadTrigger;
uint64 uiPortals[4];
uint32 AbominationCount;
GOState gothikDoorState;
time_t minHorsemenDiedTime;
time_t maxHorsemenDiedTime;
void OnCreatureCreate(Creature* creature)
{
switch(creature->GetEntry())
{
case 15989: SapphironGUID = creature->GetGUID(); return;
case 15953: uiFaerlina = creature->GetGUID(); return;
case 16064: uiThane = creature->GetGUID(); return;
case 16065: uiLady = creature->GetGUID(); return;
case 30549: uiBaron = creature->GetGUID(); return;
case 16063: uiSir = creature->GetGUID(); return;
case 15928: uiThaddius = creature->GetGUID(); return;
case 15936: uiHeigan = creature->GetGUID(); return;
case 15930: uiFeugen = creature->GetGUID(); return;
case 15929: uiStalagg = creature->GetGUID(); return;
case 15990: uiKelthuzad = creature->GetGUID(); return;
}
AddMinion(creature, true);
}
void OnCreatureRemove(Creature* creature)
{
AddMinion(creature, false);
}
void OnGameObjectCreate(GameObject* go)
{
if (go->GetGOInfo()->displayId == 6785 || go->GetGOInfo()->displayId == 1287)
{
uint32 section = GetEruptionSection(go->GetPositionX(), go->GetPositionY());
HeiganEruptionGUID[section].insert(go->GetGUID());
return;
}
switch (go->GetEntry())
{
case GO_GOTHIK_GATE:
GothikGateGUID = go->GetGUID();
go->SetGoState(gothikDoorState);
break;
case GO_HORSEMEN_CHEST:
HorsemenChestGUID = go->GetGUID();
break;
case GO_HORSEMEN_CHEST_HERO:
HorsemenChestGUID = go->GetGUID();
break;
case GO_KELTHUZAD_PORTAL01:
uiPortals[0] = go->GetGUID();
break;
case GO_KELTHUZAD_PORTAL02:
uiPortals[1] = go->GetGUID();
break;
case GO_KELTHUZAD_PORTAL03:
uiPortals[2] = go->GetGUID();
break;
case GO_KELTHUZAD_PORTAL04:
uiPortals[3] = go->GetGUID();
break;
case GO_KELTHUZAD_TRIGGER:
uiKelthuzadTrigger = go->GetGUID();
break;
default:
break;
}
AddDoor(go, true);
}
void OnGameObjectRemove(GameObject* go)
{
if (go->GetGOInfo()->displayId == 6785 || go->GetGOInfo()->displayId == 1287)
{
uint32 section = GetEruptionSection(go->GetPositionX(), go->GetPositionY());
HeiganEruptionGUID[section].erase(go->GetGUID());
return;
}
switch (go->GetEntry())
{
case GO_BIRTH:
if (SapphironGUID)
{
if (Creature* pSapphiron = instance->GetCreature(SapphironGUID))
pSapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH);
return;
}
break;
default:
break;
}
AddDoor(go, false);
}
void SetData(uint32 id, uint32 value)
{
switch(id)
{
case DATA_HEIGAN_ERUPT:
HeiganErupt(value);
break;
case DATA_GOTHIK_GATE:
if (GameObject* gothikGate = instance->GetGameObject(GothikGateGUID))
gothikGate->SetGoState(GOState(value));
gothikDoorState = GOState(value);
break;
case DATA_HORSEMEN0:
case DATA_HORSEMEN1:
case DATA_HORSEMEN2:
case DATA_HORSEMEN3:
if (value == NOT_STARTED)
{
minHorsemenDiedTime = 0;
maxHorsemenDiedTime = 0;
}
else if (value == DONE)
{
time_t now = time(NULL);
if (minHorsemenDiedTime == 0)
minHorsemenDiedTime = now;
maxHorsemenDiedTime = now;
}
break;
case DATA_ABOMINATION_KILLED:
AbominationCount = value;
break;
}
}
uint32 GetData(uint32 id)
{
switch (id)
{
case DATA_ABOMINATION_KILLED:
return AbominationCount;
default:
break;
}
return 0;
}
uint64 GetData64(uint32 id)
{
switch(id)
{
case DATA_FAERLINA:
return uiFaerlina;
case DATA_THANE:
return uiThane;
case DATA_LADY:
return uiLady;
case DATA_BARON:
return uiBaron;
case DATA_SIR:
return uiSir;
case DATA_THADDIUS:
return uiThaddius;
case DATA_HEIGAN:
return uiHeigan;
case DATA_FEUGEN:
return uiFeugen;
case DATA_STALAGG:
return uiStalagg;
case DATA_KELTHUZAD:
return uiKelthuzad;
case DATA_KELTHUZAD_PORTAL01:
return uiPortals[0];
case DATA_KELTHUZAD_PORTAL02:
return uiPortals[1];
case DATA_KELTHUZAD_PORTAL03:
return uiPortals[2];
case DATA_KELTHUZAD_PORTAL04:
return uiPortals[3];
case DATA_KELTHUZAD_TRIGGER:
return uiKelthuzadTrigger;
}
return 0;
}
bool SetBossState(uint32 id, EncounterState state)
{
if (!InstanceScript::SetBossState(id, state))
return false;
if (id == BOSS_HORSEMEN && state == DONE)
{
if (GameObject* pHorsemenChest = instance->GetGameObject(HorsemenChestGUID))
pHorsemenChest->SetRespawnTime(pHorsemenChest->GetRespawnDelay());
}
return true;
}
void HeiganErupt(uint32 section)
{
for (uint32 i = 0; i < 4; ++i)
{
if (i == section)
continue;
for (std::set<uint64>::const_iterator itr = HeiganEruptionGUID[i].begin(); itr != HeiganEruptionGUID[i].end(); ++itr)
{
if (GameObject* pHeiganEruption = instance->GetGameObject(*itr))
{
pHeiganEruption->SendCustomAnim(pHeiganEruption->GetGoAnimProgress());
pHeiganEruption->CastSpell(NULL, SPELL_ERUPTION);
}
}
}
}
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target = NULL*/, uint32 /*miscvalue1 = 0*/)
{
switch(criteria_id)
{
case 7600: // Criteria for achievement 2176: And They Would All Go Down Together 15sec of each other 10-man
if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15)
return true;
return false;
case 7601: // Criteria for achievement 2177: And They Would All Go Down Together 15sec of each other 25-man
if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_25MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15)
return true;
return false;
case 13233: // Criteria for achievement 2186: The Immortal (25-man)
// TODO.
break;
case 13237: // Criteria for achievement 2187: The Undying (10-man)
// TODO.
break;
}
return false;
}
std::string GetSaveData()
{
std::ostringstream saveStream;
saveStream << GetBossSaveData() << ' ' << gothikDoorState;
return saveStream.str();
}
void Load(const char * data)
{
std::istringstream loadStream(LoadBossState(data));
uint32 buff;
loadStream >> buff;
gothikDoorState = GOState(buff);
}
};
};
void AddSC_instance_naxxramas()
{
new instance_naxxramas();
}