aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQAston <none@none>2009-05-13 18:33:15 +0200
committerQAston <none@none>2009-05-13 18:33:15 +0200
commit131c29f1329aa6ec696f51fbe2c75178dc8f8262 (patch)
tree886fa69a8248b6b53eb7774944b35a8bf9bf5a3b
parent9aab3899376258c09b7caab7743494495b6374a1 (diff)
parent80c19013432ec49fb5c1b57bf2d5aca7be0d53c7 (diff)
*Merge.
--HG-- branch : trunk
-rw-r--r--sql/updates/3233_world_scripts_naxx.sql25
-rw-r--r--sql/world_scripts_full.sql1
-rw-r--r--sql/world_spell_full.sql2
-rw-r--r--src/bindings/scripts/ScriptMgr.cpp2
-rw-r--r--src/bindings/scripts/include/sc_creature.cpp79
-rw-r--r--src/bindings/scripts/include/sc_creature.h4
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp361
-rw-r--r--src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp8
-rw-r--r--src/game/AggressorAI.cpp2
-rw-r--r--src/game/Creature.cpp3
-rw-r--r--src/game/CreatureAI.cpp55
-rw-r--r--src/game/CreatureAI.h3
-rw-r--r--src/game/Unit.cpp2
13 files changed, 463 insertions, 84 deletions
diff --git a/sql/updates/3233_world_scripts_naxx.sql b/sql/updates/3233_world_scripts_naxx.sql
index 54d6c49a82b..a5a71ba6233 100644
--- a/sql/updates/3233_world_scripts_naxx.sql
+++ b/sql/updates/3233_world_scripts_naxx.sql
@@ -6,6 +6,7 @@ INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comm
(-28169, 28240, 0, 'Mutating Injection - Poison Cloud');
UPDATE creature_template SET scriptname = 'boss_grobbulus' WHERE entry = 15931;
+update creature_template set scriptname='mob_gothik_minion' where entry in (16124,16125,16126,16127,16148,16149,16150);
INSERT INTO creature_template (entry, spell1, flags_extra, scriptname) VALUES
(16363, 28158, 128, ''), # Grobbulus Cloud
@@ -44,16 +45,30 @@ INSERT INTO `spell_script_target` (`entry`, `type`, `targetEntry`) VALUES
(27936, 1, 16060); # To Anchor 2 - Gothik
INSERT INTO creature_template (entry, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8) VALUES
-(16573, 15284, 28991, 28969, 34970, 28864, 0, 0, 0), # Crypt Guard
-(29256, 15284, 28991, 56098, 34970, 28864, 0, 0, 0), # Crypt Guard (H)
-(16506, 54095, 28732, 0, 0, 0, 0, 0, 0), # Naxxramas Worshipper
-(29274, 54096, 54097, 0, 0, 0, 0, 0, 0), # Naxxramas Worshipper (H)
+(16573, 15284, 28991, 28969, 34970, 0, 0, 0, 28864), # Crypt Guard
+(29256, 15284, 28991, 56098, 34970, 0, 0, 0, 28864), # Crypt Guard (H)
+(16506, 54095, 0, 0, 0, 0, 0, 0, 28732), # Naxxramas Worshipper
+(29274, 54096, 0, 0, 0, 0, 0, 0, 54097), # Naxxramas Worshipper (H)
(16984, 15496, 0, 0, 0, 0, 0, 0, 0), # Plagued Warrior
(29632, 15496, 0, 0, 0, 0, 0, 0, 0), # Plagued Warrior (H)
(16290, 28156, 0, 0, 0, 0, 0, 0, 0), # Fallout Slime
(29388, 54367, 0, 0, 0, 0, 0, 0, 0), # Fallout Slime (H)
(16803, 0, 0, 0, 61696, 29060, 29061, 0, 0), # Death Knight Understudy
-(29941, 0, 0, 0, 61696, 29060, 29061, 0, 0) # Death Knight Understudy (H)
+(29941, 0, 0, 0, 61696, 29060, 29061, 0, 0), # Death Knight Understudy (H)
+(16124, 55604, 0, 0, 0, 0, 0, 0, 27892), # Unrelenting Trainee
+(16125, 27825, 0, 0, 0, 0, 0, 0, 27928), # Unrelenting Death Knight
+(16126, 27831, 55606, 0, 0, 0, 0, 0, 27935), # Unrelenting Rider
+(16127, 27989, 0, 0, 0, 0, 0, 0, 0), # Spectral Trainee
+(16148, 56408, 0, 0, 0, 0, 0, 0, 0), # Spectral Death Knight
+(16150, 27994, 55648, 55606, 0, 0, 0, 0, 0), # Spectral Rider
+(16149, 27993, 0, 0, 0, 0, 0, 0, 0), # Spectral Horse
+(29985, 55645, 0, 0, 0, 0, 0, 0, 27892), # Unrelenting Trainee (H)
+(29986, 27825, 0, 0, 0, 0, 0, 0, 27928), # Unrelenting Death Knight (H)
+(29987, 55638, 55608, 0, 0, 0, 0, 0, 27935), # Unrelenting Rider (H)
+(30264, 56407, 0, 0, 0, 0, 0, 0, 0), # Spectral Trainee (H)
+(29990, 56408, 0, 0, 0, 0, 0, 0, 0), # Spectral Death Knight (H)
+(29988, 55646, 27995, 55608, 0, 0, 0, 0, 0), # Spectral Rider (H)
+(29989, 27993, 0, 0, 0, 0, 0, 0, 0) # Spectral Horse (H)
ON DUPLICATE KEY UPDATE
spell1 = VALUES(spell1),
spell2 = VALUES(spell2),
diff --git a/sql/world_scripts_full.sql b/sql/world_scripts_full.sql
index a1df130d207..8b28c3bc370 100644
--- a/sql/world_scripts_full.sql
+++ b/sql/world_scripts_full.sql
@@ -645,6 +645,7 @@ UPDATE `creature_template` SET `ScriptName`='boss_heigan' WHERE `entry`=15936;
UPDATE `creature_template` SET `ScriptName`='boss_loatheb' WHERE `entry`=16011;
UPDATE `creature_template` SET `ScriptName`='boss_razuvious' WHERE `entry`=16061;
UPDATE `creature_template` SET `ScriptName`='boss_gothik' WHERE `entry`=16060;
+UPDATE `creature_template` SET `ScriptName`='mob_gothik_minion' where `entry` IN (16124,16125,16126,16127,16148,16149,16150);
UPDATE `creature_template` SET `ScriptName`='boss_thane_korthazz' WHERE `entry`=16064;
UPDATE `creature_template` SET `ScriptName`='boss_sir_zeliek' WHERE `entry`=16063;
UPDATE `creature_template` SET `ScriptName`='boss_lady_blaumeux' WHERE `entry`=16065;
diff --git a/sql/world_spell_full.sql b/sql/world_spell_full.sql
index c892b3291fa..7885866c854 100644
--- a/sql/world_spell_full.sql
+++ b/sql/world_spell_full.sql
@@ -153,7 +153,7 @@ INSERT INTO creature_template (entry, spell1, flags_extra, scriptname) VALUES
(17662, 30914, 128, ''), # Broggok Poison Cloud
(25879, 46262, 128, ''), # Void Zone Periodic
(16363, 28158, 128, ''), # Grobbulus Cloud
-(29379, 54362, 128, ''), # Grobbulus Cloud (H)
+(29379, 54362, 128, '') # Grobbulus Cloud (H)
ON DUPLICATE KEY UPDATE
spell1 = VALUES(spell1),
flags_extra = VALUES(flags_extra),
diff --git a/src/bindings/scripts/ScriptMgr.cpp b/src/bindings/scripts/ScriptMgr.cpp
index 4d7ed09fff4..849c4d64be5 100644
--- a/src/bindings/scripts/ScriptMgr.cpp
+++ b/src/bindings/scripts/ScriptMgr.cpp
@@ -389,6 +389,7 @@ extern void AddSC_boss_sapphiron();
extern void AddSC_boss_four_horsemen();
extern void AddSC_boss_faerlina();
extern void AddSC_boss_heigan();
+extern void AddSC_boss_gothik();
extern void AddSC_instance_naxxramas();
//Netherstorm
@@ -1327,6 +1328,7 @@ void ScriptsInit(char const* cfg_file = "trinitycore.conf")
AddSC_boss_sapphiron();
AddSC_boss_four_horsemen();
AddSC_boss_heigan();
+ AddSC_boss_gothik();
AddSC_instance_naxxramas();
//Netherstorm
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp
index 0b874773ffc..e575e40fac1 100644
--- a/src/bindings/scripts/include/sc_creature.cpp
+++ b/src/bindings/scripts/include/sc_creature.cpp
@@ -17,13 +17,26 @@ struct TSpellSummary {
uint8 Effects; // set of enum SelectEffect
} *SpellSummary;
+void SummonList::DoZoneInCombat(uint32 entry)
+{
+ for(iterator i = begin(); i != end();)
+ {
+ Creature *summon = Unit::GetCreature(*m_creature, *i);
+ ++i;
+ if(summon && summon->IsAIEnabled
+ && (!entry || summon->GetEntry() == entry))
+ summon->AI()->DoZoneInCombat();
+ }
+}
+
void SummonList::DoAction(uint32 entry, uint32 info)
{
for(iterator i = begin(); i != end();)
{
Creature *summon = Unit::GetCreature(*m_creature, *i);
++i;
- if(summon && summon->IsAIEnabled)
+ if(summon && summon->IsAIEnabled
+ && (!entry || summon->GetEntry() == entry))
summon->AI()->DoAction(info);
}
}
@@ -213,6 +226,19 @@ Creature* ScriptedAI::DoSpawnCreature(uint32 id, float x, float y, float z, floa
return m_creature->SummonCreature(id,m_creature->GetPositionX() + x,m_creature->GetPositionY() + y,m_creature->GetPositionZ() + z, angle, (TempSummonType)type, despawntime);
}
+Creature *ScriptedAI::DoSummon(uint32 entry, const float pos[4], uint32 despawntime, TempSummonType type)
+{
+ return me->SummonCreature(entry, pos[0], pos[1], pos[2], pos[3], type, despawntime);
+}
+
+Creature *ScriptedAI::DoSummon(uint32 entry, WorldObject *obj, float radius, uint32 despawntime, TempSummonType type)
+{
+ float x, y, z;
+ obj->GetGroundPointAroundUnit(x, y, z, radius * rand_norm(), rand_norm()*2*M_PI);
+ return me->SummonCreature(entry, x, y, z, me->GetOrientation(), type, despawntime);
+}
+
+
Unit* ScriptedAI::SelectUnit(SelectAggroTarget target, uint32 position)
{
//ThreatList m_threatlist;
@@ -493,6 +519,11 @@ void ScriptedAI::DoTeleportTo(float x, float y, float z, uint32 time)
m_creature->SendMonsterMove(x, y, z, time);
}
+void ScriptedAI::DoTeleportTo(const float pos[4])
+{
+ me->NearTeleportTo(pos[0], pos[1], pos[2], pos[3]);
+}
+
void ScriptedAI::DoTeleportPlayer(Unit* pUnit, float x, float y, float z, float o)
{
if(!pUnit || pUnit->GetTypeId() != TYPEID_PLAYER)
@@ -642,7 +673,8 @@ void BossAI::_EnterCombat()
void BossAI::JustSummoned(Creature *summon)
{
summons.Summon(summon);
- DoZoneInCombat(summon);
+ if(me->isInCombat())
+ DoZoneInCombat(summon);
}
void BossAI::SummonedCreatureDespawn(Creature *summon)
@@ -667,25 +699,36 @@ void LoadOverridenSQLData()
goInfo->trap.radius = 50;
}
-#define SPELL(x) const_cast<SpellEntry*>(GetSpellStore()->LookupEntry(x))
-
void LoadOverridenDBCData()
{
SpellEntry *spellInfo;
-
- // Black Temple : Illidan : Parasitic Shadowfiend Passive
- if(spellInfo = SPELL(41913))
- spellInfo->EffectApplyAuraName[0] = 4; // proc debuff, and summon infinite fiends
-
- //temp, not needed in 310
- if(spellInfo = SPELL(28531))
- {
- spellInfo->DurationIndex = 21;
- spellInfo->Effect[0] = SPELL_EFFECT_APPLY_AREA_AURA_ENEMY;
- }
- if(spellInfo = SPELL(55799))
+ for(uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i)
{
- spellInfo->DurationIndex = 21;
- spellInfo->Effect[0] = SPELL_EFFECT_APPLY_AREA_AURA_ENEMY;
+ spellInfo = (SpellEntry*)GetSpellStore()->LookupEntry(i);
+ if(!spellInfo)
+ continue;
+
+ switch(i)
+ {
+ // Black Temple : Illidan : Parasitic Shadowfiend Passive
+ case 41013:
+ spellInfo->EffectApplyAuraName[0] = 4; // proc debuff, and summon infinite fiends
+ break;
+ //temp, not needed in 310
+ case 28531:
+ case 55799:
+ spellInfo->DurationIndex = 21;
+ spellInfo->Effect[0] = SPELL_EFFECT_APPLY_AREA_AURA_ENEMY;
+ break;
+ // Naxxramas: Gothik : Inform Inf range
+ case 27892:
+ case 27928:
+ case 27935:
+ case 27915:
+ case 27931:
+ case 27937:
+ spellInfo->rangeIndex = 13;
+ break;
+ }
}
}
diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h
index 0fb716bbe0e..80016619e8b 100644
--- a/src/bindings/scripts/include/sc_creature.h
+++ b/src/bindings/scripts/include/sc_creature.h
@@ -23,6 +23,7 @@ class SummonList : private std::list<uint64>
void DespawnEntry(uint32 entry);
void DespawnAll();
void DoAction(uint32 entry, uint32 info);
+ void DoZoneInCombat(uint32 entry = 0);
private:
Creature *m_creature;
};
@@ -152,6 +153,7 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
void DoModifyThreatPercent(Unit *pUnit, int32 pct);
void DoTeleportTo(float x, float y, float z, uint32 time = 0);
+ void DoTeleportTo(const float pos[4]);
void DoAction(const int32 param) {}
@@ -170,6 +172,8 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
//Spawns a creature relative to m_creature
Creature* DoSpawnCreature(uint32 id, float x, float y, float z, float angle, uint32 type, uint32 despawntime);
+ Creature *DoSummon(uint32 entry, const float pos[4], uint32 despawntime = 30000, TempSummonType type = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
+ Creature *DoSummon(uint32 entry, WorldObject *obj, float radius = 5.0f, uint32 despawntime = 30000, TempSummonType type = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
//Selects a unit from the creature's current aggro list
Unit* SelectUnit(SelectAggroTarget target, uint32 position);
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp b/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp
index 3a9c6a5b47a..7def6c370f4 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/boss_gothik.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+/* Copyright (C) 2008 - 2009 Trinity <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
@@ -14,14 +14,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/* ScriptData
-SDName: Boss_Gothik
-SD%Complete: 0
-SDComment: Placeholder
-SDCategory: Naxxramas
-EndScriptData */
-
#include "precompiled.h"
+#include "def_naxxramas.h"
#define SAY_SPEECH -1533040
#define SAY_KILL -1533041
@@ -29,37 +23,336 @@ EndScriptData */
#define SAY_TELEPORT -1533043
//Gothik
-#define SPELL_HARVESTSOUL 28679
-#define SPELL_SHADOWBOLT HEROIC(29317,56405)
-#define SPELL_SOUL_SIPHON 43591 // cannot find the correct spell
+#define SPELL_HARVEST_SOUL 28679
+#define SPELL_SHADOW_BOLT HEROIC(29317,56405)
+
+#define SPELL_INFORM_LIVE_TRAINEE 27892
+#define SPELL_INFORM_LIVE_KNIGHT 27928
+#define SPELL_INFORM_LIVE_RIDER 27935
+#define SPELL_INFORM_DEAD_TRAINEE 27915
+#define SPELL_INFORM_DEAD_KNIGHT 27931
+#define SPELL_INFORM_DEAD_RIDER 27937
+
+#define MOB_LIVE_TRAINEE 16124
+#define MOB_LIVE_KNIGHT 16125
+#define MOB_LIVE_RIDER 16126
+#define MOB_DEAD_TRAINEE 16127
+#define MOB_DEAD_KNIGHT 16148
+#define MOB_DEAD_RIDER 16150
+#define MOB_DEAD_HORSE 16149
+
+const struct Waves { uint32 entry, number, time; }
+waves[] =
+{
+ {MOB_LIVE_TRAINEE, 2, 20000},
+ {MOB_LIVE_TRAINEE, 2, 20000},
+ {MOB_LIVE_TRAINEE, 2, 10000},
+ {MOB_LIVE_KNIGHT, 1, 10000},
+ {MOB_LIVE_TRAINEE, 2, 15000},
+ {MOB_LIVE_KNIGHT, 1, 10000},
+ {MOB_LIVE_TRAINEE, 2, 15000},
+ {MOB_LIVE_TRAINEE, 2, 0},
+ {MOB_LIVE_KNIGHT, 1, 10000},
+ {MOB_LIVE_RIDER, 1, 10000},
+ {MOB_LIVE_TRAINEE, 2, 5000},
+ {MOB_LIVE_KNIGHT, 1, 15000},
+ {MOB_LIVE_TRAINEE, 2, 0},
+ {MOB_LIVE_RIDER, 1, 10000},
+ {MOB_LIVE_KNIGHT, 2, 10000},
+ {MOB_LIVE_TRAINEE, 2, 10000},
+ {MOB_LIVE_RIDER, 1, 5000},
+ {MOB_LIVE_KNIGHT, 1, 5000},
+ {MOB_LIVE_TRAINEE, 2, 20000},
+ {MOB_LIVE_TRAINEE, 2, 0},
+ {MOB_LIVE_KNIGHT, 1, 0},
+ {MOB_LIVE_RIDER, 1, 15000},
+ {MOB_LIVE_TRAINEE, 2, 29000},
+ {0, 0, 0},
+};
+
+#define POS_Y_GATE -3360.78f
+
+enum Events
+{
+ EVENT_SUMMON = 1,
+ EVENT_HARVEST,
+ EVENT_BOLT,
+};
+
+#define POS_LIVE 3
+#define POS_DEAD 5
+
+const float PosSummonLive[POS_LIVE][4] =
+{
+ {2669.7, -3430.9, 268.56, 1.6},
+ {2692.0, -3430.9, 268.56, 1.6},
+ {2714.1, -3430.9, 268.56, 1.6},
+};
+
+const float PosSummonDead[POS_DEAD][4] =
+{
+ {2725.1, -3310.0, 268.85, 3.4},
+ {2699.3, -3322.8, 268.60, 3.3},
+ {2733.1, -3348.5, 268.84, 3.1},
+ {2682.8, -3304.2, 268.85, 3.9},
+ {2664.8, -3340.7, 268.23, 3.7},
+};
+
+const float PosGround[4] = {2691.2, -3362.7, 267.68, 1.7};
+const float PosPlatform[4] = {2640.5, -3360.6, 285.26, 0};
+
+struct TRINITY_DLL_DECL boss_gothikAI : public BossAI
+{
+ boss_gothikAI(Creature *c) : BossAI(c, BOSS_GOTHIK) {}
+
+ uint32 waveCount;
+ std::vector<Creature*> liveTrigger;
+ std::vector<Creature*> deadTrigger;
+
+ void Reset()
+ {
+ liveTrigger.clear();
+ deadTrigger.clear();
+ me->setActive(false);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
+ me->SetReactState(REACT_PASSIVE);
+ _Reset();
+ }
+
+ void EnterCombat(Unit *who)
+ {
+ for(uint32 i = 0; i < POS_LIVE; ++i)
+ if(Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonLive[i]))
+ liveTrigger.push_back(trigger);
+ for(uint32 i = 0; i < POS_DEAD; ++i)
+ if(Creature *trigger = DoSummon(WORLD_TRIGGER, PosSummonDead[i]))
+ deadTrigger.push_back(trigger);
+
+ if(liveTrigger.size() < POS_LIVE || deadTrigger.size() < POS_DEAD)
+ {
+ error_log("Script Gothik: cannot summon triggers!");
+ EnterEvadeMode();
+ return;
+ }
+
+ _EnterCombat();
+ me->setActive(true);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
+ waveCount = 0;
+ events.ScheduleEvent(EVENT_SUMMON, 30000);
+ DoTeleportTo(PosPlatform);
+ DoScriptText(SAY_SPEECH, me);
+ if(instance)
+ instance->SetData(DATA_GOTHIK_GATE, 1);
+ }
+
+ void JustSummoned(Creature *summon)
+ {
+ if(summon->GetEntry() == WORLD_TRIGGER)
+ summon->setActive(true);
+ else
+ {
+ summon->AI()->DoAction(me->HasReactState(REACT_PASSIVE) ? 1 : 0);
+ summon->AI()->EnterEvadeMode();
+ }
+ summons.Summon(summon);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if(!(rand()%5))
+ DoScriptText(SAY_KILL, me);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ _JustDied();
+ DoScriptText(SAY_DEATH, me);
+ }
+
+ void SpellHit(Unit *caster, const SpellEntry *spell)
+ {
+ uint32 spellId = 0;
+ switch(spell->Id)
+ {
+ case SPELL_INFORM_LIVE_TRAINEE: spellId = SPELL_INFORM_DEAD_TRAINEE; break;
+ case SPELL_INFORM_LIVE_KNIGHT: spellId = SPELL_INFORM_DEAD_KNIGHT; break;
+ case SPELL_INFORM_LIVE_RIDER: spellId = SPELL_INFORM_DEAD_RIDER; break;
+ }
+ if(spellId && me->isInCombat())
+ {
+ me->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST);
+ me->CastSpell(deadTrigger[rand()%POS_DEAD], spellId, true);
+ }
+ }
+
+ void SpellHitTarget(Unit *target, const SpellEntry *spell)
+ {
+ if(!me->isInCombat())
+ return;
+
+ switch(spell->Id)
+ {
+ case SPELL_INFORM_DEAD_TRAINEE: DoSummon(MOB_DEAD_TRAINEE, target, 0); break;
+ case SPELL_INFORM_DEAD_KNIGHT: DoSummon(MOB_DEAD_KNIGHT, target, 0); break;
+ case SPELL_INFORM_DEAD_RIDER: DoSummon(MOB_DEAD_RIDER, target, 1.0f);
+ DoSummon(MOB_DEAD_HORSE, target, 1.0f); break;
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if(!me->isInCombat())
+ return;
+
+ if(me->getThreatManager().isThreatListEmpty())
+ {
+ EnterEvadeMode();
+ return;
+ }
+
+ if(me->HasReactState(REACT_AGGRESSIVE) && !UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if(me->hasUnitState(UNIT_STAT_CASTING))
+ return;
+
+ while(uint32 eventId = events.ExecuteEvent())
+ {
+ switch(eventId)
+ {
+ case EVENT_SUMMON:
+ if(waves[waveCount].entry)
+ {
+ for(uint32 i = 0; i < waves[waveCount].number; ++i)
+ DoSummon(waves[waveCount].entry, liveTrigger[rand()%POS_LIVE], 1.0f);
+ events.ScheduleEvent(EVENT_SUMMON, waves[waveCount].time);
+ ++waveCount;
+ }
+ else
+ {
+ DoScriptText(SAY_TELEPORT, me);
+ DoTeleportTo(PosGround);
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
+ if(instance)
+ instance->SetData(DATA_GOTHIK_GATE, 0);
+ summons.DoAction(0, 0);
+ summons.DoZoneInCombat();
+ events.ScheduleEvent(EVENT_BOLT, 1000);
+ events.ScheduleEvent(EVENT_HARVEST, 15000);
+ }
+ break;
+ case EVENT_BOLT:
+ DoCast(me->getVictim(), SPELL_SHADOW_BOLT);
+ events.ScheduleEvent(EVENT_BOLT, 1000);
+ return;
+ case EVENT_HARVEST:
+ DoCast(me->getVictim(), SPELL_HARVEST_SOUL);
+ events.ScheduleEvent(EVENT_HARVEST, 15000);
+ return;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct TRINITY_DLL_DECL mob_gothik_minionAI : public SpellAI
+{
+ mob_gothik_minionAI(Creature *c) : SpellAI(c)
+ {
+ liveSide = me->GetPositionY() < POS_Y_GATE;
+ }
+
+ bool liveSide;
+ bool gateClose;
+
+#define SIDE_CHECK(who) (liveSide == (who->GetPositionY() < POS_Y_GATE))
+
+ void DoAction(const int32 param)
+ {
+ gateClose = param;
+ }
+
+ void DamageTaken(Unit *attacker, uint32 &damage)
+ {
+ if(gateClose && !SIDE_CHECK(attacker))
+ damage = 0;
+ }
+
+ void JustDied(Unit *killer)
+ {
+ if(me->isSummon())
+ {
+ if(Unit *owner = ((TempSummon*)me)->GetSummoner())
+ SpellAI::JustDied(owner);
+ }
+ }
+
+ void EnterEvadeMode()
+ {
+ if(!gateClose)
+ {
+ SpellAI::EnterEvadeMode();
+ return;
+ }
+
+ if(!_EnterEvadeMode())
+ return;
-//Unrelenting Trainee
-#define SPELL_EAGLECLAW 30285
-#define SPELL_KNOCKDOWN_PASSIVE 6961
+ Map *map = me->GetMap();
+ if(map->IsDungeon())
+ {
+ Map::PlayerList const &PlayerList = map->GetPlayers();
+ for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ {
+ if(i->getSource()->isAlive() && SIDE_CHECK(i->getSource()))
+ {
+ AttackStart(i->getSource());
+ return;
+ }
+ }
+ }
-//Unrelenting Deathknight
-#define SPELL_CHARGE 22120
-#define SPELL_SHADOW_MARK 27825
+ me->GetMotionMaster()->MoveIdle();
+ Reset();
+ }
-//Unrelenting Rider
-#define SPELL_UNHOLY_AURA 55606
-#define H_SPELL_UNHOLY_AURA 55608
-#define SPELL_SHADOWBOLT_VOLLEY 27831 //Search thru targets and find those who have the SHADOW_MARK to cast this on
-#define H_SPELL_SHADOWBOLT_VOLLEY 55638
+ void UpdateAI(const uint32 diff)
+ {
+ if(gateClose && (!SIDE_CHECK(me) || me->getVictim() && !SIDE_CHECK(me->getVictim())))
+ {
+ EnterEvadeMode();
+ return;
+ }
-//Spectral Trainee
-#define SPELL_ARCANE_EXPLOSION 27989
+ SpellAI::UpdateAI(diff);
+ }
+};
-//Spectral Deathknight
-#define SPELL_WHIRLWIND 28334
-#define SPELL_SUNDER_ARMOR 25051 //cannot find sunder that reduces armor by 2950
-#define SPELL_CLEAVE 20677
-#define SPELL_MANA_BURN 17631
+CreatureAI* GetAI_boss_gothik(Creature *_Creature)
+{
+ return new boss_gothikAI (_Creature);
+}
-//Spectral Rider
-#define SPELL_LIFEDRAIN 24300
-//USES SAME UNHOLY AURA AS UNRELENTING RIDER
+CreatureAI* GetAI_mob_gothik_minion(Creature *_Creature)
+{
+ return new mob_gothik_minionAI (_Creature);
+}
-//Spectral Horse
-#define SPELL_STOMP 27993
+void AddSC_boss_gothik()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name="boss_gothik";
+ newscript->GetAI = &GetAI_boss_gothik;
+ newscript->RegisterSelf();
+ newscript = new Script;
+ newscript->Name="mob_gothik_minion";
+ newscript->GetAI = &GetAI_mob_gothik_minion;
+ newscript->RegisterSelf();
+}
diff --git a/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp b/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp
index 23f44f5daf8..e5913660c3f 100644
--- a/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp
+++ b/src/bindings/scripts/scripts/zone/naxxramas/instance_naxxramas.cpp
@@ -86,9 +86,10 @@ struct TRINITY_DLL_DECL instance_naxxramas : public InstanceData
LoadDoorData(doorData);
}
+ std::set<Creature*> Worshipper;
std::set<GameObject*> HeiganEruption[4];
+ GameObject *GothikGate;
Creature *Sapphiron;
- std::set<Creature*> Worshipper;
void OnCreatureCreate(Creature *creature, bool add)
{
@@ -114,6 +115,7 @@ struct TRINITY_DLL_DECL instance_naxxramas : public InstanceData
switch(go->GetEntry())
{
case GO_BIRTH: if(!add && Sapphiron) Sapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH); return;
+ case GO_GOTHIK_GATE: GothikGate = add ? go : NULL; break;
}
AddDoor(go, add);
@@ -140,6 +142,10 @@ struct TRINITY_DLL_DECL instance_naxxramas : public InstanceData
case DATA_HEIGAN_ERUPT:
HeiganErupt(value);
break;
+ case DATA_GOTHIK_GATE:
+ if(GothikGate)
+ GothikGate->SetGoState(GOState(value));
+ break;
}
}
diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp
index 286138fc991..22ebe87cdc6 100644
--- a/src/game/AggressorAI.cpp
+++ b/src/game/AggressorAI.cpp
@@ -104,7 +104,7 @@ void SpellAI::UpdateAI(const uint32 diff)
break;
}
}
- me->CastSpell(target, spellId, false);
+ if(target) me->CastSpell(target, spellId, false);
events.ScheduleEvent(spellId, AISpellInfo[spellId].cooldown + rand()%AISpellInfo[spellId].cooldown);
}
else
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 85109997390..f322d8326e1 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -455,6 +455,9 @@ void Creature::Update(uint32 diff)
}
else
{
+ // for delayed spells
+ m_Events.Update( diff );
+
m_deathTimer -= diff;
if (m_groupLootTimer && lootingGroupLeaderGUID)
{
diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp
index ea65d233a17..0864bc973ab 100644
--- a/src/game/CreatureAI.cpp
+++ b/src/game/CreatureAI.cpp
@@ -39,6 +39,9 @@ void CreatureAI::DoZoneInCombat(Creature* creature)
if (!creature)
creature = me;
+ if(!creature->CanHaveThreatList())
+ return;
+
Map *map = creature->GetMap();
if (!map->IsDungeon()) //use IsDungeon instead of Instanceable, in case battlegrounds will be instantiated
{
@@ -46,7 +49,7 @@ void CreatureAI::DoZoneInCombat(Creature* creature)
return;
}
- if(!creature->getVictim())
+ if(!creature->HasReactState(REACT_PASSIVE) && !creature->getVictim())
{
if(Unit *target = creature->SelectNearestTarget())
creature->AI()->AttackStart(target);
@@ -54,29 +57,30 @@ void CreatureAI::DoZoneInCombat(Creature* creature)
{
if(Unit *summoner = ((TempSummon*)creature)->GetSummoner())
{
- if(summoner->getVictim()
- && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(summoner->getVictim())))
- creature->AI()->AttackStart(summoner->getVictim());
+ Unit *target = summoner->getAttackerForHelper();
+ if(!target && summoner->CanHaveThreatList() && !summoner->getThreatManager().isThreatListEmpty())
+ target = summoner->getThreatManager().getHostilTarget();
+ if(target && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(target)))
+ creature->AI()->AttackStart(target);
}
}
}
- if (!creature->CanHaveThreatList() || !creature->getVictim())
+ if(!creature->HasReactState(REACT_PASSIVE) && !creature->getVictim())
{
- sLog.outError("DoZoneInCombat called for creature that either cannot have threat list or has empty threat list (creature entry = %d)", creature->GetTypeId() == TYPEID_UNIT ? ((Creature*)creature)->GetEntry() : 0);
+ sLog.outError("DoZoneInCombat called for creature that has empty threat list (creature entry = %u)", creature->GetEntry());
return;
}
Map::PlayerList const &PlayerList = map->GetPlayers();
for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
- if (Player* i_pl = i->getSource())
- if (i_pl->isAlive())
- {
- creature->SetInCombatWith(i_pl);
- i_pl->SetInCombatWith(creature);
- creature->AddThreat(i_pl, 0.0f);
- }
+ if (i->getSource()->isAlive())
+ {
+ creature->SetInCombatWith(i->getSource());
+ i->getSource()->SetInCombatWith(creature);
+ creature->AddThreat(i->getSource(), 0.0f);
+ }
}
}
@@ -102,10 +106,10 @@ bool CreatureAI::UpdateVictim()
return me->getVictim();
}
-void CreatureAI::EnterEvadeMode()
+bool CreatureAI::_EnterEvadeMode()
{
- if(me->IsInEvadeMode())
- return;
+ if(me->IsInEvadeMode() || !me->isAlive())
+ return false;
me->RemoveAllAuras();
me->DeleteThreatList();
@@ -113,13 +117,18 @@ void CreatureAI::EnterEvadeMode()
me->LoadCreaturesAddon();
me->SetLootRecipient(NULL);
- if(me->isAlive())
- {
- if(Unit *owner = me->GetCharmerOrOwner())
- me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, MOTION_SLOT_IDLE);
- else
- me->GetMotionMaster()->MoveTargetedHome();
- }
+ return true;
+}
+
+void CreatureAI::EnterEvadeMode()
+{
+ if(!_EnterEvadeMode())
+ return;
+
+ if(Unit *owner = me->GetCharmerOrOwner())
+ me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE, MOTION_SLOT_IDLE);
+ else
+ me->GetMotionMaster()->MoveTargetedHome();
Reset();
}
diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h
index 605e904c71a..c46dd2a54f2 100644
--- a/src/game/CreatureAI.h
+++ b/src/game/CreatureAI.h
@@ -168,6 +168,9 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI
static AISpellInfoType *AISpellInfo;
static void FillAISpellInfo();
+
+ protected:
+ bool _EnterEvadeMode();
};
enum Permitions
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index f142ea623a5..66576396dfa 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -9958,7 +9958,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)
((Creature*)this)->SetHomePosition(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
if(enemy)
{
- if(!((Creature*)this)->HasReactState(REACT_PASSIVE) && ((Creature*)this)->IsAIEnabled)
+ if(((Creature*)this)->IsAIEnabled)
((Creature*)this)->AI()->EnterCombat(enemy);
if(((Creature*)this)->GetFormation())
((Creature*)this)->GetFormation()->MemberAttackStart((Creature*)this, enemy);