First Commit

For Azeroth!
This commit is contained in:
Yehonal
2016-06-26 10:39:44 +02:00
commit e8e94a0a66
3777 changed files with 1419268 additions and 0 deletions

View File

@@ -0,0 +1,462 @@
/*
* Copyright (C)
* Copyright (C)
*
* 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/>.
*/
/* ScriptData
SDName: boss_Akilzon
SD%Complete: 75%
SDComment: Missing timer for Call Lightning and Sound ID's
SQLUpdate:
#Temporary fix for Soaring Eagles
EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "Cell.h"
#include "CellImpl.h"
#include "zulaman.h"
#include "Weather.h"
enum Spells
{
SPELL_STATIC_DISRUPTION = 43622,
SPELL_STATIC_VISUAL = 45265,
SPELL_CALL_LIGHTNING = 43661, // Missing timer
SPELL_GUST_OF_WIND = 43621,
SPELL_ELECTRICAL_STORM = 43648,
SPELL_BERSERK = 45078,
SPELL_ELECTRICAL_OVERLOAD = 43658,
SPELL_EAGLE_SWOOP = 44732,
SPELL_ZAP = 43137,
SPELL_SAND_STORM = 25160
};
enum Says
{
SAY_AGGRO = 0,
SAY_SUMMON = 1,
SAY_INTRO = 2, // Not used in script
SAY_ENRAGE = 3,
SAY_KILL = 4,
SAY_DEATH = 5
};
enum Misc
{
NPC_SOARING_EAGLE = 24858,
SE_LOC_X_MAX = 400,
SE_LOC_X_MIN = 335,
SE_LOC_Y_MAX = 1435,
SE_LOC_Y_MIN = 1370
};
enum Events
{
EVENT_STATIC_DISRUPTION = 1,
EVENT_GUST_OF_WIND = 2,
EVENT_CALL_LIGHTNING = 3,
EVENT_ELECTRICAL_STORM = 4,
EVENT_RAIN = 5,
EVENT_SUMMON_EAGLES = 6,
EVENT_STORM_SEQUENCE = 7,
EVENT_ENRAGE = 8
};
class boss_akilzon : public CreatureScript
{
public:
boss_akilzon() : CreatureScript("boss_akilzon") { }
struct boss_akilzonAI : public BossAI
{
boss_akilzonAI(Creature* creature) : BossAI(creature, DATA_AKILZONEVENT)
{
memset(BirdGUIDs, 0, sizeof(BirdGUIDs));
}
void Reset()
{
_Reset();
TargetGUID = 0;
CloudGUID = 0;
CycloneGUID = 0;
memset(BirdGUIDs, 0, sizeof(BirdGUIDs));
StormCount = 0;
isRaining = false;
SetWeather(WEATHER_STATE_FINE, 0.0f);
}
void EnterCombat(Unit* /*who*/)
{
events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(10000, 20000)); // 10 to 20 seconds (bosskillers)
events.ScheduleEvent(EVENT_GUST_OF_WIND, urand(20000, 30000)); // 20 to 30 seconds(bosskillers)
events.ScheduleEvent(EVENT_CALL_LIGHTNING, urand(10000, 20000)); // totaly random timer. can't find any info on this
events.ScheduleEvent(EVENT_ELECTRICAL_STORM, 60000); // 60 seconds(bosskillers)
events.ScheduleEvent(EVENT_RAIN, urand(47000, 52000));
events.ScheduleEvent(EVENT_ENRAGE, 10*MINUTE*IN_MILLISECONDS); // 10 minutes till enrage(bosskillers)
Talk(SAY_AGGRO);
//DoZoneInCombat();
instance->SetData(DATA_AKILZONEVENT, IN_PROGRESS);
}
void JustDied(Unit* /*killer*/)
{
Talk(SAY_DEATH);
_JustDied();
}
void KilledUnit(Unit* who)
{
if (who->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_KILL);
}
void SetWeather(uint32 weather, float grade)
{
Map* map = me->GetMap();
if (!map->IsDungeon())
return;
WorldPacket data(SMSG_WEATHER, (4+4+4));
data << uint32(weather) << float(grade) << uint8(0);
map->SendToPlayers(&data);
}
void HandleStormSequence(Unit* Cloud) // 1: begin, 2-9: tick, 10: end
{
if (StormCount < 10 && StormCount > 1)
{
// deal damage
int32 bp0 = 800;
for (uint8 i = 2; i < StormCount; ++i)
bp0 *= 2;
CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
Cell cell(p);
cell.SetNoCreate();
std::list<Unit*> tempUnitMap;
{
Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, SIZE_OF_GRIDS);
Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(me, tempUnitMap, u_check);
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
cell.Visit(p, world_unit_searcher, *me->GetMap(), *me, SIZE_OF_GRIDS);
cell.Visit(p, grid_unit_searcher, *me->GetMap(), *me, SIZE_OF_GRIDS);
}
// deal damage
for (std::list<Unit*>::const_iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i)
{
if (Unit* target = (*i))
{
if (Cloud && !Cloud->IsWithinDist(target, 6, false))
Cloud->CastCustomSpell(target, SPELL_ZAP, &bp0, NULL, NULL, true, 0, 0, me->GetGUID());
}
}
// visual
float x, y, z;
z = me->GetPositionZ();
for (uint8 i = 0; i < 5+rand()%5; ++i)
{
x = 343.0f+rand()%60;
y = 1380.0f+rand()%60;
if (Unit* trigger = me->SummonTrigger(x, y, z, 0, 2000))
{
trigger->setFaction(35);
trigger->SetMaxHealth(100000);
trigger->SetHealth(100000);
trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
if (Cloud)
Cloud->CastCustomSpell(trigger, /*43661*/SPELL_ZAP, &bp0, NULL, NULL, true, 0, 0, Cloud->GetGUID());
}
}
}
++StormCount;
if (StormCount > 10)
{
StormCount = 0; // finish
events.ScheduleEvent(EVENT_SUMMON_EAGLES, 5000);
me->InterruptNonMeleeSpells(false);
CloudGUID = 0;
if (Cloud)
Unit::DealDamage(Cloud, Cloud, Cloud->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
SetWeather(WEATHER_STATE_FINE, 0.0f);
isRaining = false;
}
events.ScheduleEvent(EVENT_STORM_SEQUENCE, 1000);
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_STATIC_DISRUPTION:
{
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1);
if (!target)
target = me->GetVictim();
if (target)
{
TargetGUID = target->GetGUID();
DoCast(target, SPELL_STATIC_DISRUPTION, false);
me->SetInFront(me->GetVictim());
}
/*if (float dist = me->IsWithinDist3d(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 5.0f) dist = 5.0f;
SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/
events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(10000, 18000));
break;
}
case EVENT_GUST_OF_WIND:
{
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1);
if (!target)
target = me->GetVictim();
if (target)
DoCast(target, SPELL_GUST_OF_WIND);
events.ScheduleEvent(EVENT_GUST_OF_WIND, urand(20000, 30000));
break;
}
case EVENT_CALL_LIGHTNING:
DoCastVictim(SPELL_CALL_LIGHTNING);
events.ScheduleEvent(EVENT_CALL_LIGHTNING, urand(12000, 17000)); // totaly random timer. can't find any info on this
break;
case EVENT_ELECTRICAL_STORM:
{
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true);
if (!target)
{
EnterEvadeMode();
return;
}
target->CastSpell(target, 44007, true); // cloud visual
DoCast(target, SPELL_ELECTRICAL_STORM, false); // storm cyclon + visual
float x, y, z;
target->GetPosition(x, y, z);
/// @todo: fix it in correct way, that causes player to can fly until logout
/*
if (target)
{
target->SetDisableGravity(true);
target->MonsterMoveWithSpeed(x, y, me->GetPositionZ()+15, 0);
}
*/
Unit* Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000);
if (Cloud)
{
CloudGUID = Cloud->GetGUID();
Cloud->SetDisableGravity(true);
Cloud->StopMoving();
Cloud->SetObjectScale(1.0f);
Cloud->setFaction(35);
Cloud->SetMaxHealth(9999999);
Cloud->SetHealth(9999999);
Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
StormCount = 1;
events.ScheduleEvent(EVENT_ELECTRICAL_STORM, 60000); // 60 seconds(bosskillers)
events.ScheduleEvent(EVENT_RAIN, urand(47000, 52000));
break;
}
case EVENT_RAIN:
if (!isRaining)
{
SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f);
isRaining = true;
}
else
events.ScheduleEvent(EVENT_RAIN, 1000);
break;
case EVENT_STORM_SEQUENCE:
{
Unit* target = ObjectAccessor::GetUnit(*me, CloudGUID);
if (!target || !target->IsAlive())
{
EnterEvadeMode();
return;
}
else if (Unit* Cyclone = ObjectAccessor::GetUnit(*me, CycloneGUID))
Cyclone->CastSpell(target, SPELL_SAND_STORM, true); // keep casting or...
HandleStormSequence(target);
break;
}
case EVENT_SUMMON_EAGLES:
Talk(SAY_SUMMON);
float x, y, z;
me->GetPosition(x, y, z);
for (uint8 i = 0; i < 8; ++i)
{
Unit* bird = ObjectAccessor::GetUnit(*me, BirdGUIDs[i]);
if (!bird) //they despawned on die
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
x = target->GetPositionX() + irand(-10, 10);
y = target->GetPositionY() + irand(-10, 10);
z = target->GetPositionZ() + urand(16, 20);
if (z > 95)
z = 95.0f - urand(0, 5);
}
Creature* creature = me->SummonCreature(NPC_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
if (creature)
{
creature->AddThreat(me->GetVictim(), 1.0f);
creature->AI()->AttackStart(me->GetVictim());
BirdGUIDs[i] = creature->GetGUID();
}
}
}
break;
case EVENT_ENRAGE:
Talk(SAY_ENRAGE);
DoCast(me, SPELL_BERSERK, true);
events.ScheduleEvent(EVENT_ENRAGE, 600000);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
uint64 BirdGUIDs[8];
uint64 TargetGUID;
uint64 CycloneGUID;
uint64 CloudGUID;
uint8 StormCount;
bool isRaining;
};
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_akilzonAI>(creature);
}
};
class npc_akilzon_eagle : public CreatureScript
{
public:
npc_akilzon_eagle() : CreatureScript("npc_akilzon_eagle") { }
struct npc_akilzon_eagleAI : public ScriptedAI
{
npc_akilzon_eagleAI(Creature* creature) : ScriptedAI(creature) { }
uint32 EagleSwoop_Timer;
bool arrived;
uint64 TargetGUID;
void Reset()
{
EagleSwoop_Timer = urand(5000, 10000);
arrived = true;
TargetGUID = 0;
me->SetDisableGravity(true);
}
void EnterCombat(Unit* /*who*/)
{
DoZoneInCombat();
}
void MoveInLineOfSight(Unit* /*who*/) { }
void MovementInform(uint32, uint32)
{
arrived = true;
if (TargetGUID)
{
if (Unit* target = ObjectAccessor::GetUnit(*me, TargetGUID))
DoCast(target, SPELL_EAGLE_SWOOP, true);
TargetGUID = 0;
me->SetSpeed(MOVE_RUN, 1.2f);
EagleSwoop_Timer = urand(5000, 10000);
}
}
void UpdateAI(uint32 diff)
{
if (EagleSwoop_Timer <= diff)
EagleSwoop_Timer = 0;
else
EagleSwoop_Timer -= diff;
if (arrived)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
float x, y, z;
if (EagleSwoop_Timer)
{
x = target->GetPositionX() + irand(-10, 10);
y = target->GetPositionY() + irand(-10, 10);
z = target->GetPositionZ() + urand(10, 15);
if (z > 95)
z = 95.0f - urand(0, 5);
}
else
{
target->GetContactPoint(me, x, y, z);
z += 2;
me->SetSpeed(MOVE_RUN, 5.0f);
TargetGUID = target->GetGUID();
}
me->GetMotionMaster()->MovePoint(0, x, y, z);
arrived = false;
}
}
}
};
CreatureAI* GetAI(Creature* creature) const
{
return new npc_akilzon_eagleAI(creature);
}
};
void AddSC_boss_akilzon()
{
new boss_akilzon();
new npc_akilzon_eagle();
}

View File

@@ -0,0 +1,381 @@
/*
* Copyright (C)
* Copyright (C)
*
* 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 "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulaman.h"
#include "SpellInfo.h"
enum Spells
{
SPELL_DUAL_WIELD = 29651,
SPELL_SABER_LASH = 43267,
SPELL_FRENZY = 43139,
SPELL_FLAMESHOCK = 43303,
SPELL_EARTHSHOCK = 43305,
SPELL_TRANSFORM_SPLIT = 43142,
SPELL_TRANSFORM_SPLIT2 = 43573,
SPELL_TRANSFORM_MERGE = 43271,
SPELL_SUMMON_LYNX = 43143,
SPELL_SUMMON_TOTEM = 43302,
SPELL_BERSERK = 45078,
SPELL_LYNX_FRENZY = 43290, // Used by Spirit Lynx
SPELL_SHRED_ARMOR = 43243 // Used by Spirit Lynx
};
enum Hal_CreatureIds
{
NPC_SPIRIT_LYNX = 24143,
NPC_TOTEM = 24224
};
enum PhaseHalazzi
{
PHASE_NONE = 0,
PHASE_LYNX = 1,
PHASE_SPLIT = 2,
PHASE_HUMAN = 3,
PHASE_MERGE = 4,
PHASE_ENRAGE = 5
};
enum Yells
{
SAY_AGGRO = 0,
SAY_SABER = 1,
SAY_SPLIT = 2,
SAY_MERGE = 3,
SAY_KILL = 4,
SAY_DEATH = 5,
SAY_BERSERK = 6
};
class boss_halazzi : public CreatureScript
{
public:
boss_halazzi() : CreatureScript("boss_halazzi") { }
struct boss_halazziAI : public ScriptedAI
{
boss_halazziAI(Creature* creature) : ScriptedAI(creature), summons(me)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
SummonList summons;
PhaseHalazzi Phase;
uint32 FrenzyTimer;
uint32 SaberlashTimer;
uint32 ShockTimer;
uint32 TotemTimer;
uint32 CheckTimer;
uint32 BerserkTimer;
uint32 TransformCount;
uint64 LynxGUID;
void Reset()
{
instance->SetData(DATA_HALAZZIEVENT, NOT_STARTED);
summons.DespawnAll();
LynxGUID = 0;
TransformCount = 0;
BerserkTimer = 600000;
CheckTimer = 1000;
DoCast(me, SPELL_DUAL_WIELD, true);
Phase = PHASE_NONE;
EnterPhase(PHASE_LYNX);
}
void EnterCombat(Unit* /*who*/)
{
instance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS);
Talk(SAY_AGGRO);
EnterPhase(PHASE_LYNX);
}
void JustSummoned(Creature* summon)
{
summon->AI()->AttackStart(me->GetVictim());
if (summon->GetEntry() == NPC_SPIRIT_LYNX)
LynxGUID = summon->GetGUID();
summons.Summon(summon);
}
void DamageTaken(Unit*, uint32 &damage, DamageEffectType, SpellSchoolMask)
{
if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE)
damage = 0;
}
void SpellHit(Unit*, const SpellInfo* spell)
{
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
EnterPhase(PHASE_HUMAN);
}
void AttackStart(Unit* who)
{
if (Phase != PHASE_MERGE)
ScriptedAI::AttackStart(who);
}
void EnterPhase(PhaseHalazzi NextPhase)
{
switch (NextPhase)
{
case PHASE_LYNX:
case PHASE_ENRAGE:
if (Phase == PHASE_MERGE)
{
DoCast(me, SPELL_TRANSFORM_MERGE, true);
me->Attack(me->GetVictim(), true);
me->GetMotionMaster()->MoveChase(me->GetVictim());
}
if (Creature* Lynx = ObjectAccessor::GetCreature(*me, LynxGUID))
Lynx->DisappearAndDie();
me->SetMaxHealth(600000);
me->SetHealth(600000 - 150000 * TransformCount);
FrenzyTimer = 16000;
SaberlashTimer = 20000;
ShockTimer = 10000;
TotemTimer = 12000;
break;
case PHASE_SPLIT:
Talk(SAY_SPLIT);
DoCast(me, SPELL_TRANSFORM_SPLIT, true);
break;
case PHASE_HUMAN:
//DoCast(me, SPELL_SUMMON_LYNX, true);
DoSpawnCreature(NPC_SPIRIT_LYNX, 5, 5, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
me->SetMaxHealth(400000);
me->SetHealth(400000);
ShockTimer = 10000;
TotemTimer = 12000;
break;
case PHASE_MERGE:
if (Unit* pLynx = ObjectAccessor::GetUnit(*me, LynxGUID))
{
Talk(SAY_MERGE);
pLynx->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
pLynx->GetMotionMaster()->Clear();
pLynx->GetMotionMaster()->MoveFollow(me, 0, 0);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveFollow(pLynx, 0, 0);
++TransformCount;
}
break;
default:
break;
}
Phase = NextPhase;
}
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
if (BerserkTimer <= diff)
{
Talk(SAY_BERSERK);
DoCast(me, SPELL_BERSERK, true);
BerserkTimer = 60000;
} else BerserkTimer -= diff;
if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE)
{
if (SaberlashTimer <= diff)
{
// A tank with more than 490 defense skills should receive no critical hit
//DoCast(me, 41296, true);
DoCastVictim(SPELL_SABER_LASH, true);
//me->RemoveAurasDueToSpell(41296);
SaberlashTimer = 30000;
} else SaberlashTimer -= diff;
if (FrenzyTimer <= diff)
{
DoCast(me, SPELL_FRENZY);
FrenzyTimer = urand(10000, 15000);
} else FrenzyTimer -= diff;
if (Phase == PHASE_LYNX)
{
if (CheckTimer <= diff)
{
if (HealthBelowPct(25 * (3 - TransformCount)))
EnterPhase(PHASE_SPLIT);
CheckTimer = 1000;
} else CheckTimer -= diff;
}
}
if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE)
{
if (TotemTimer <= diff)
{
DoCast(me, SPELL_SUMMON_TOTEM);
TotemTimer = 20000;
} else TotemTimer -= diff;
if (ShockTimer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
if (target->IsNonMeleeSpellCast(false))
DoCast(target, SPELL_EARTHSHOCK);
else
DoCast(target, SPELL_FLAMESHOCK);
ShockTimer = urand(10000, 15000);
}
} else ShockTimer -= diff;
if (Phase == PHASE_HUMAN)
{
if (CheckTimer <= diff)
{
if (!HealthAbovePct(20) /*HealthBelowPct(10)*/)
EnterPhase(PHASE_MERGE);
else
{
Unit* Lynx = ObjectAccessor::GetUnit(*me, LynxGUID);
if (Lynx && !Lynx->HealthAbovePct(20) /*Lynx->HealthBelowPct(10)*/)
EnterPhase(PHASE_MERGE);
}
CheckTimer = 1000;
} else CheckTimer -= diff;
}
}
if (Phase == PHASE_MERGE)
{
if (CheckTimer <= diff)
{
Unit* Lynx = ObjectAccessor::GetUnit(*me, LynxGUID);
if (Lynx)
{
Lynx->GetMotionMaster()->MoveFollow(me, 0, 0);
me->GetMotionMaster()->MoveFollow(Lynx, 0, 0);
if (me->IsWithinDistInMap(Lynx, 6.0f))
{
if (TransformCount < 3)
EnterPhase(PHASE_LYNX);
else
EnterPhase(PHASE_ENRAGE);
}
}
CheckTimer = 1000;
} else CheckTimer -= diff;
}
DoMeleeAttackIfReady();
}
void KilledUnit(Unit* victim)
{
if (victim->GetTypeId() != TYPEID_PLAYER)
return;
Talk(SAY_KILL);
}
void JustDied(Unit* /*killer*/)
{
instance->SetData(DATA_HALAZZIEVENT, DONE);
Talk(SAY_DEATH);
}
};
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_halazziAI>(creature);
}
};
// Spirits Lynx AI
class npc_halazzi_lynx : public CreatureScript
{
public:
npc_halazzi_lynx() : CreatureScript("npc_halazzi_lynx") { }
struct npc_halazzi_lynxAI : public ScriptedAI
{
npc_halazzi_lynxAI(Creature* creature) : ScriptedAI(creature) { }
uint32 FrenzyTimer;
uint32 shredder_timer;
void Reset()
{
FrenzyTimer = urand(30000, 50000); //frenzy every 30-50 seconds
shredder_timer = 4000;
}
void DamageTaken(Unit*, uint32 &damage, DamageEffectType, SpellSchoolMask)
{
if (damage >= me->GetHealth())
damage = 0;
}
void AttackStart(Unit* who)
{
if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
ScriptedAI::AttackStart(who);
}
void EnterCombat(Unit* /*who*/) {/*DoZoneInCombat();*/ }
void UpdateAI(uint32 diff)
{
if (!UpdateVictim())
return;
if (FrenzyTimer <= diff)
{
DoCast(me, SPELL_LYNX_FRENZY);
FrenzyTimer = urand(30000, 50000); //frenzy every 30-50 seconds
} else FrenzyTimer -= diff;
if (shredder_timer <= diff)
{
DoCastVictim(SPELL_SHRED_ARMOR);
shredder_timer = 4000;
} else shredder_timer -= diff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const
{
return new npc_halazzi_lynxAI(creature);
}
};
void AddSC_boss_halazzi()
{
new boss_halazzi();
new npc_halazzi_lynx();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,717 @@
/*
* Copyright (C)
* Copyright (C)
*
* 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/>.
*/
/* ScriptData
SDName: Boss_Janalai
SD%Complete: 100
SDComment:
SDCategory: Zul'Aman
EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulaman.h"
#include "GridNotifiers.h"
#include "CellImpl.h"
enum Yells
{
SAY_AGGRO = 0,
SAY_FIRE_BOMBS = 1,
SAY_SUMMON_HATCHER = 2,
SAY_ALL_EGGS = 3,
SAY_BERSERK = 4,
SAY_SLAY = 5,
SAY_DEATH = 6,
SAY_EVENT_STRANGERS = 7,
SAY_EVENT_FRIENDS = 8
};
enum Spells
{
// Jan'alai
SPELL_FLAME_BREATH = 43140,
SPELL_FIRE_WALL = 43113,
SPELL_ENRAGE = 44779,
SPELL_SUMMON_PLAYERS = 43097,
SPELL_TELE_TO_CENTER = 43098, // coord
SPELL_HATCH_ALL = 43144,
SPELL_BERSERK = 45078,
// Fire Bob Spells
SPELL_FIRE_BOMB_CHANNEL = 42621, // last forever
SPELL_FIRE_BOMB_THROW = 42628, // throw visual
SPELL_FIRE_BOMB_DUMMY = 42629, // bomb visual
SPELL_FIRE_BOMB_DAMAGE = 42630,
// Hatcher Spells
SPELL_HATCH_EGG = 42471, // 43734
SPELL_SUMMON_HATCHLING = 42493,
// Hatchling Spells
SPELL_FLAMEBUFFET = 43299
};
enum Creatures
{
NPC_AMANI_HATCHER = 23818,
NPC_HATCHLING = 23598, // 42493
NPC_EGG = 23817,
NPC_FIRE_BOMB = 23920
};
const int area_dx = 44;
const int area_dy = 51;
float JanalainPos[1][3] =
{
{-33.93f, 1149.27f, 19}
};
float FireWallCoords[4][4] =
{
{-10.13f, 1149.27f, 19, 3.1415f},
{-33.93f, 1123.90f, 19, 0.5f*3.1415f},
{-54.80f, 1150.08f, 19, 0},
{-33.93f, 1175.68f, 19, 1.5f*3.1415f}
};
float hatcherway[2][5][3] =
{
{
{-87.46f, 1170.09f, 6},
{-74.41f, 1154.75f, 6},
{-52.74f, 1153.32f, 19},
{-33.37f, 1172.46f, 19},
{-33.09f, 1203.87f, 19}
},
{
{-86.57f, 1132.85f, 6},
{-73.94f, 1146.00f, 6},
{-52.29f, 1146.51f, 19},
{-33.57f, 1125.72f, 19},
{-34.29f, 1095.22f, 19}
}
};
class boss_janalai : public CreatureScript
{
public:
boss_janalai()
: CreatureScript("boss_janalai")
{
}
struct boss_janalaiAI : public ScriptedAI
{
boss_janalaiAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
uint32 FireBreathTimer;
uint32 BombTimer;
uint32 BombSequenceTimer;
uint32 BombCount;
uint32 HatcherTimer;
uint32 EnrageTimer;
bool noeggs;
bool enraged;
bool isBombing;
bool isFlameBreathing;
uint64 FireBombGUIDs[40];
void Reset()
{
instance->SetData(DATA_JANALAIEVENT, NOT_STARTED);
FireBreathTimer = 8000;
BombTimer = 30000;
BombSequenceTimer = 1000;
BombCount = 0;
HatcherTimer = 10000;
EnrageTimer = MINUTE*5*IN_MILLISECONDS;
noeggs = false;
isBombing =false;
enraged = false;
isFlameBreathing = false;
for (uint8 i = 0; i < 40; ++i)
FireBombGUIDs[i] = 0;
HatchAllEggs(1);
}
void JustDied(Unit* /*killer*/)
{
Talk(SAY_DEATH);
instance->SetData(DATA_JANALAIEVENT, DONE);
}
void KilledUnit(Unit* /*victim*/)
{
Talk(SAY_SLAY);
}
void EnterCombat(Unit* /*who*/)
{
instance->SetData(DATA_JANALAIEVENT, IN_PROGRESS);
Talk(SAY_AGGRO);
// DoZoneInCombat();
}
void DamageDealt(Unit* target, uint32 &damage, DamageEffectType /*damagetype*/)
{
if (isFlameBreathing)
{
if (!me->HasInArc(M_PI/6, target))
damage = 0;
}
}
void FireWall()
{
uint8 WallNum;
Creature* wall = NULL;
for (uint8 i = 0; i < 4; ++i)
{
if (i == 0 || i == 2)
WallNum = 3;
else
WallNum = 2;
for (uint8 j = 0; j < WallNum; j++)
{
if (WallNum == 3)
wall = me->SummonCreature(NPC_FIRE_BOMB, FireWallCoords[i][0], FireWallCoords[i][1]+5*(j-1), FireWallCoords[i][2], FireWallCoords[i][3], TEMPSUMMON_TIMED_DESPAWN, 15000);
else
wall = me->SummonCreature(NPC_FIRE_BOMB, FireWallCoords[i][0]-2+4*j, FireWallCoords[i][1], FireWallCoords[i][2], FireWallCoords[i][3], TEMPSUMMON_TIMED_DESPAWN, 15000);
if (wall) wall->CastSpell(wall, SPELL_FIRE_WALL, true);
}
}
}
void SpawnBombs()
{
float dx, dy;
for (int i(0); i < 40; ++i)
{
dx = float(irand(-area_dx/2, area_dx/2));
dy = float(irand(-area_dy/2, area_dy/2));
Creature* bomb = DoSpawnCreature(NPC_FIRE_BOMB, dx, dy, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000);
if (bomb)
FireBombGUIDs[i] = bomb->GetGUID();
}
BombCount = 0;
}
bool HatchAllEggs(uint32 action) //1: reset, 2: isHatching all
{
std::list<Creature*> templist;
float x, y, z;
me->GetPosition(x, y, z);
{
CellCoord pair(Trinity::ComputeCellCoord(x, y));
Cell cell(pair);
cell.SetNoCreate();
Trinity::AllCreaturesOfEntryInRange check(me, NPC_EGG, 100);
Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, templist, check);
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> cSearcher(searcher);
cell.Visit(pair, cSearcher, *me->GetMap(), *me, me->GetGridActivationRange());
}
//TC_LOG_ERROR("scripts", "Eggs %d at middle", templist.size());
if (templist.empty())
return false;
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i)
{
if (action == 1)
(*i)->SetDisplayId(10056);
else if (action == 2 &&(*i)->GetDisplayId() != 11686)
(*i)->CastSpell(*i, SPELL_HATCH_EGG, false);
}
return true;
}
void Boom()
{
std::list<Creature*> templist;
float x, y, z;
me->GetPosition(x, y, z);
{
CellCoord pair(Trinity::ComputeCellCoord(x, y));
Cell cell(pair);
cell.SetNoCreate();
Trinity::AllCreaturesOfEntryInRange check(me, NPC_FIRE_BOMB, 100);
Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, templist, check);
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> cSearcher(searcher);
cell.Visit(pair, cSearcher, *me->GetMap(), *me, me->GetGridActivationRange());
}
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i)
{
(*i)->CastSpell(*i, SPELL_FIRE_BOMB_DAMAGE, true);
(*i)->RemoveAllAuras();
}
}
void HandleBombSequence()
{
if (BombCount < 40)
{
if (Unit* FireBomb = ObjectAccessor::GetUnit(*me, FireBombGUIDs[BombCount]))
{
FireBomb->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
DoCast(FireBomb, SPELL_FIRE_BOMB_THROW, true);
FireBomb->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
++BombCount;
if (BombCount == 40)
{
BombSequenceTimer = 5000;
} else BombSequenceTimer = 100;
}
else
{
Boom();
isBombing = false;
BombTimer = urand(20000, 40000);
me->RemoveAurasDueToSpell(SPELL_FIRE_BOMB_CHANNEL);
if (EnrageTimer <= 10000)
EnrageTimer = 0;
else
EnrageTimer -= 10000;
}
}
void UpdateAI(uint32 diff)
{
if (isFlameBreathing)
{
if (!me->IsNonMeleeSpellCast(false))
isFlameBreathing = false;
else
return;
}
if (isBombing)
{
if (BombSequenceTimer <= diff)
HandleBombSequence();
else
BombSequenceTimer -= diff;
return;
}
if (!UpdateVictim())
return;
//enrage if under 25% hp before 5 min.
if (!enraged && HealthBelowPct(25))
EnrageTimer = 0;
if (EnrageTimer <= diff)
{
if (!enraged)
{
DoCast(me, SPELL_ENRAGE, true);
enraged = true;
EnrageTimer = 300000;
}
else
{
Talk(SAY_BERSERK);
DoCast(me, SPELL_BERSERK, true);
EnrageTimer = 300000;
}
} else EnrageTimer -= diff;
if (BombTimer <= diff)
{
Talk(SAY_FIRE_BOMBS);
me->AttackStop();
me->GetMotionMaster()->Clear();
me->NearTeleportTo(JanalainPos[0][0], JanalainPos[0][1], JanalainPos[0][2], me->GetOrientation());
me->StopMovingOnCurrentPos();
DoCast(me, SPELL_FIRE_BOMB_CHANNEL, false);
//DoTeleportPlayer(me, JanalainPos[0][0], JanalainPos[0][1], JanalainPos[0][2], 0);
//DoCast(me, SPELL_TELE_TO_CENTER, true);
FireWall();
SpawnBombs();
isBombing = true;
BombSequenceTimer = 100;
//Teleport every Player into the middle
Map* map = me->GetMap();
if (!map->IsDungeon())
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())
DoTeleportPlayer(i_pl, JanalainPos[0][0]-5+rand()%10, JanalainPos[0][1]-5+rand()%10, JanalainPos[0][2], 0);
//DoCast(Temp, SPELL_SUMMON_PLAYERS, true) // core bug, spell does not work if too far
return;
} else BombTimer -= diff;
if (!noeggs)
{
if (HealthBelowPct(35))
{
Talk(SAY_ALL_EGGS);
me->AttackStop();
me->GetMotionMaster()->Clear();
me->NearTeleportTo(JanalainPos[0][0], JanalainPos[0][1], JanalainPos[0][2], me->GetOrientation());
me->StopMovingOnCurrentPos();
DoCast(me, SPELL_HATCH_ALL, false);
HatchAllEggs(2);
noeggs = true;
}
else if (HatcherTimer <= diff)
{
if (HatchAllEggs(0))
{
Talk(SAY_SUMMON_HATCHER);
me->SummonCreature(NPC_AMANI_HATCHER, hatcherway[0][0][0], hatcherway[0][0][1], hatcherway[0][0][2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
me->SummonCreature(NPC_AMANI_HATCHER, hatcherway[1][0][0], hatcherway[1][0][1], hatcherway[1][0][2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
HatcherTimer = 90000;
}
else
noeggs = true;
} else HatcherTimer -= diff;
}
EnterEvadeIfOutOfCombatArea();
DoMeleeAttackIfReady();
if (FireBreathTimer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
me->AttackStop();
me->GetMotionMaster()->Clear();
DoCast(target, SPELL_FLAME_BREATH, false);
me->StopMoving();
isFlameBreathing = true;
}
FireBreathTimer = 8000;
} else FireBreathTimer -= diff;
}
bool CheckEvadeIfOutOfCombatArea() const
{
return me->GetPositionZ() <= 12.0f;
}
};
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_janalaiAI>(creature);
}
};
class npc_janalai_firebomb : public CreatureScript
{
public:
npc_janalai_firebomb()
: CreatureScript("npc_janalai_firebomb")
{
}
struct npc_janalai_firebombAI : public ScriptedAI
{
npc_janalai_firebombAI(Creature* creature) : ScriptedAI(creature){ }
void Reset() { }
void SpellHit(Unit* /*caster*/, const SpellInfo* spell)
{
if (spell->Id == SPELL_FIRE_BOMB_THROW)
DoCast(me, SPELL_FIRE_BOMB_DUMMY, true);
}
void EnterCombat(Unit* /*who*/) { }
void AttackStart(Unit* /*who*/) { }
void MoveInLineOfSight(Unit* /*who*/) { }
void UpdateAI(uint32 /*diff*/) { }
};
CreatureAI* GetAI(Creature* creature) const
{
return new npc_janalai_firebombAI(creature);
}
};
class npc_janalai_hatcher : public CreatureScript
{
public:
npc_janalai_hatcher()
: CreatureScript("npc_janalai_hatcher")
{
}
struct npc_janalai_hatcherAI : public ScriptedAI
{
npc_janalai_hatcherAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
uint32 waypoint;
uint32 HatchNum;
uint32 WaitTimer;
bool side;
bool hasChangedSide;
bool isHatching;
void Reset()
{
me->SetWalk(true);
side =(me->GetPositionY() < 1150);
waypoint = 0;
isHatching = false;
hasChangedSide = false;
WaitTimer = 1;
HatchNum = 0;
}
bool HatchEggs(uint32 num)
{
std::list<Creature*> templist;
float x, y, z;
me->GetPosition(x, y, z);
{
CellCoord pair(Trinity::ComputeCellCoord(x, y));
Cell cell(pair);
cell.SetNoCreate();
Trinity::AllCreaturesOfEntryInRange check(me, 23817, 50);
Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, templist, check);
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> cSearcher(searcher);
cell.Visit(pair, cSearcher, *(me->GetMap()), *me, me->GetGridActivationRange());
}
//TC_LOG_ERROR("scripts", "Eggs %d at %d", templist.size(), side);
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end() && num > 0; ++i)
if ((*i)->GetDisplayId() != 11686)
{
(*i)->CastSpell(*i, SPELL_HATCH_EGG, false);
num--;
}
return num == 0; // if num == 0, no more templist
}
void EnterCombat(Unit* /*who*/) { }
void AttackStart(Unit* /*who*/) { }
void MoveInLineOfSight(Unit* /*who*/) { }
void MovementInform(uint32, uint32)
{
if (waypoint == 5)
{
isHatching = true;
HatchNum = 1;
WaitTimer = 5000;
}
else
WaitTimer = 1;
}
void UpdateAI(uint32 diff)
{
if (!instance || !(instance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS))
{
me->DisappearAndDie();
return;
}
if (!isHatching)
{
if (WaitTimer)
{
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MovePoint(0, hatcherway[side][waypoint][0], hatcherway[side][waypoint][1], hatcherway[side][waypoint][2]);
++waypoint;
WaitTimer = 0;
}
}
else
{
if (WaitTimer <= diff)
{
if (HatchEggs(HatchNum))
{
++HatchNum;
WaitTimer = 10000;
}
else if (!hasChangedSide)
{
side = side ? 0 : 1;
isHatching = false;
waypoint = 3;
WaitTimer = 1;
hasChangedSide = true;
}
else
me->DisappearAndDie();
} else WaitTimer -= diff;
}
}
};
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<npc_janalai_hatcherAI>(creature);
}
};
class npc_janalai_hatchling : public CreatureScript
{
public:
npc_janalai_hatchling()
: CreatureScript("npc_janalai_hatchling")
{
}
struct npc_janalai_hatchlingAI : public ScriptedAI
{
npc_janalai_hatchlingAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
uint32 BuffetTimer;
void Reset()
{
BuffetTimer = 7000;
if (me->GetPositionY() > 1150)
me->GetMotionMaster()->MovePoint(0, hatcherway[0][3][0]+rand()%4-2, 1150.0f+rand()%4-2, hatcherway[0][3][2]);
else
me->GetMotionMaster()->MovePoint(0, hatcherway[1][3][0]+rand()%4-2, 1150.0f+rand()%4-2, hatcherway[1][3][2]);
me->SetDisableGravity(true);
}
void EnterCombat(Unit* /*who*/) {/*DoZoneInCombat();*/ }
void UpdateAI(uint32 diff)
{
if (!instance || !(instance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS))
{
me->DisappearAndDie();
return;
}
if (!UpdateVictim())
return;
if (BuffetTimer <= diff)
{
DoCastVictim(SPELL_FLAMEBUFFET, false);
BuffetTimer = 10000;
} else BuffetTimer -= diff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<npc_janalai_hatchlingAI>(creature);
}
};
class npc_janalai_egg : public CreatureScript
{
public:
npc_janalai_egg(): CreatureScript("npc_janalai_egg") { }
CreatureAI* GetAI(Creature* creature) const
{
return new npc_janalai_eggAI(creature);
}
struct npc_janalai_eggAI : public ScriptedAI
{
npc_janalai_eggAI(Creature* creature) : ScriptedAI(creature){ }
void Reset() { }
void UpdateAI(uint32 /*diff*/) { }
void SpellHit(Unit* /*caster*/, const SpellInfo* spell)
{
if (spell->Id == SPELL_HATCH_EGG)
{
DoCast(SPELL_SUMMON_HATCHLING);
}
}
};
};
void AddSC_boss_janalai()
{
new boss_janalai();
new npc_janalai_firebomb();
new npc_janalai_hatcher();
new npc_janalai_hatchling();
new npc_janalai_egg();
}

View File

@@ -0,0 +1,461 @@
/*
* Copyright (C)
* Copyright (C)
*
* 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/>.
*/
/* ScriptData
SDName: Boss_Nalorakk
SD%Complete: 100
SDComment:
SDCategory: Zul'Aman
EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulaman.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
enum Spells
{
SPELL_BERSERK = 45078,
// Troll form
SPELL_BRUTALSWIPE = 42384,
SPELL_MANGLE = 42389,
SPELL_MANGLEEFFECT = 44955,
SPELL_SURGE = 42402,
SPELL_BEARFORM = 42377,
// Bear form
SPELL_LACERATINGSLASH = 42395,
SPELL_RENDFLESH = 42397,
SPELL_DEAFENINGROAR = 42398
};
// Trash Waves
float NalorakkWay[8][3] =
{
{ 18.569f, 1414.512f, 11.42f}, // waypoint 1
{-17.264f, 1419.551f, 12.62f},
{-52.642f, 1419.357f, 27.31f}, // waypoint 2
{-69.908f, 1419.721f, 27.31f},
{-79.929f, 1395.958f, 27.31f},
{-80.072f, 1374.555f, 40.87f}, // waypoint 3
{-80.072f, 1314.398f, 40.87f},
{-80.072f, 1295.775f, 48.60f} // waypoint 4
};
#define YELL_NALORAKK_WAVE1 "Get da move on, guards! It be killin' time!"
#define SOUND_NALORAKK_WAVE1 12066
#define YELL_NALORAKK_WAVE2 "Guards, go already! Who you more afraid of, dem... or me?"
#define SOUND_NALORAKK_WAVE2 12067
#define YELL_NALORAKK_WAVE3 "Ride now! Ride out dere and bring me back some heads!"
#define SOUND_NALORAKK_WAVE3 12068
#define YELL_NALORAKK_WAVE4 "I be losin' me patience! Go on: make dem wish dey was never born!"
#define SOUND_NALORAKK_WAVE4 12069
//Unimplemented SoundIDs
/*
#define SOUND_NALORAKK_EVENT1 12078
#define SOUND_NALORAKK_EVENT2 12079
*/
//General defines
#define YELL_AGGRO "You be dead soon enough!"
#define SOUND_YELL_AGGRO 12070
#define YELL_KILL_ONE "Mua-ha-ha! Now whatchoo got to say?"
#define SOUND_YELL_KILL_ONE 12075
#define YELL_KILL_TWO "Da Amani gonna rule again!"
#define SOUND_YELL_KILL_TWO 12076
#define YELL_DEATH "I... be waitin' on da udda side...."
#define SOUND_YELL_DEATH 12077
#define YELL_BERSERK "You had your chance, now it be too late!" //Never seen this being used, so just guessing from what I hear.
#define SOUND_YELL_BERSERK 12074
#define YELL_SURGE "I bring da pain!"
#define SOUND_YELL_SURGE 12071
#define YELL_SHIFTEDTOTROLL "Make way for Nalorakk!"
#define SOUND_YELL_TOTROLL 12073
#define YELL_SHIFTEDTOBEAR "You call on da beast, you gonna get more dan you bargain for!"
#define SOUND_YELL_TOBEAR 12072
class boss_nalorakk : public CreatureScript
{
public:
boss_nalorakk()
: CreatureScript("boss_nalorakk")
{
}
struct boss_nalorakkAI : public ScriptedAI
{
boss_nalorakkAI(Creature* creature) : ScriptedAI(creature)
{
MoveEvent = true;
MovePhase = 0;
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
uint32 BrutalSwipe_Timer;
uint32 Mangle_Timer;
uint32 Surge_Timer;
uint32 LaceratingSlash_Timer;
uint32 RendFlesh_Timer;
uint32 DeafeningRoar_Timer;
uint32 ShapeShift_Timer;
uint32 Berserk_Timer;
bool inBearForm;
bool MoveEvent;
bool inMove;
uint32 MovePhase;
uint32 waitTimer;
void Reset()
{
if (MoveEvent)
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
inMove = false;
waitTimer = 0;
me->SetSpeed(MOVE_RUN, 2);
me->SetWalk(false);
}else
{
(*me).GetMotionMaster()->MovePoint(0, NalorakkWay[7][0], NalorakkWay[7][1], NalorakkWay[7][2]);
}
instance->SetData(DATA_NALORAKKEVENT, NOT_STARTED);
Surge_Timer = urand(15000, 20000);
BrutalSwipe_Timer = urand(7000, 12000);
Mangle_Timer = urand(10000, 15000);
ShapeShift_Timer = urand(45000, 50000);
Berserk_Timer = 600000;
inBearForm = false;
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); /// @todo find the correct equipment id
}
void SendAttacker(Unit* target)
{
std::list<Creature*> templist;
float x, y, z;
me->GetPosition(x, y, z);
{
CellCoord pair(Trinity::ComputeCellCoord(x, y));
Cell cell(pair);
cell.SetNoCreate();
Trinity::AllFriendlyCreaturesInGrid check(me);
Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid> searcher(me, templist, check);
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid>, GridTypeMapContainer> cSearcher(searcher);
cell.Visit(pair, cSearcher, *(me->GetMap()), *me, me->GetGridActivationRange());
}
if (templist.empty())
return;
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i)
{
if ((*i) && me->IsWithinDistInMap((*i), 25))
{
(*i)->SetNoCallAssistance(true);
(*i)->AI()->AttackStart(target);
}
}
}
void AttackStart(Unit* who)
{
if (!MoveEvent)
ScriptedAI::AttackStart(who);
}
void MoveInLineOfSight(Unit* who)
{
if (!MoveEvent)
{
ScriptedAI::MoveInLineOfSight(who);
}
else
{
if (me->IsHostileTo(who))
{
if (!inMove)
{
switch (MovePhase)
{
case 0:
if (me->IsWithinDistInMap(who, 50))
{
me->MonsterYell(YELL_NALORAKK_WAVE1, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE1);
(*me).GetMotionMaster()->MovePoint(1, NalorakkWay[1][0], NalorakkWay[1][1], NalorakkWay[1][2]);
MovePhase ++;
inMove = true;
SendAttacker(who);
}
break;
case 2:
if (me->IsWithinDistInMap(who, 40))
{
me->MonsterYell(YELL_NALORAKK_WAVE2, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE2);
(*me).GetMotionMaster()->MovePoint(3, NalorakkWay[3][0], NalorakkWay[3][1], NalorakkWay[3][2]);
MovePhase ++;
inMove = true;
SendAttacker(who);
}
break;
case 5:
if (me->IsWithinDistInMap(who, 40))
{
me->MonsterYell(YELL_NALORAKK_WAVE3, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE3);
(*me).GetMotionMaster()->MovePoint(6, NalorakkWay[6][0], NalorakkWay[6][1], NalorakkWay[6][2]);
MovePhase ++;
inMove = true;
SendAttacker(who);
}
break;
case 7:
if (me->IsWithinDistInMap(who, 50))
{
SendAttacker(who);
me->MonsterYell(YELL_NALORAKK_WAVE4, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE4);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
MoveEvent = false;
}
break;
}
}
}
}
}
void EnterCombat(Unit* /*who*/)
{
instance->SetData(DATA_NALORAKKEVENT, IN_PROGRESS);
me->MonsterYell(YELL_AGGRO, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_YELL_AGGRO);
DoZoneInCombat();
}
void JustDied(Unit* /*killer*/)
{
instance->SetData(DATA_NALORAKKEVENT, DONE);
me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_YELL_DEATH);
}
void KilledUnit(Unit* /*victim*/)
{
switch (urand(0, 1))
{
case 0:
me->MonsterYell(YELL_KILL_ONE, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE);
break;
case 1:
me->MonsterYell(YELL_KILL_TWO, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO);
break;
}
}
void MovementInform(uint32 type, uint32 id)
{
if (MoveEvent)
{
if (type != POINT_MOTION_TYPE)
return;
if (!inMove)
return;
if (MovePhase != id)
return;
switch (MovePhase)
{
case 2:
me->SetOrientation(3.1415f*2);
inMove = false;
return;
case 1:
case 3:
case 4:
case 6:
MovePhase ++;
waitTimer = 1;
inMove = true;
return;
case 5:
me->SetOrientation(3.1415f*0.5f);
inMove = false;
return;
case 7:
me->SetOrientation(3.1415f*0.5f);
inMove = false;
return;
}
}
}
void UpdateAI(uint32 diff)
{
if (waitTimer && inMove)
{
if (waitTimer <= diff)
{
(*me).GetMotionMaster()->MovementExpired();
(*me).GetMotionMaster()->MovePoint(MovePhase, NalorakkWay[MovePhase][0], NalorakkWay[MovePhase][1], NalorakkWay[MovePhase][2]);
waitTimer = 0;
} else waitTimer -= diff;
}
if (!UpdateVictim())
return;
if (Berserk_Timer <= diff)
{
DoCast(me, SPELL_BERSERK, true);
me->MonsterYell(YELL_BERSERK, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_YELL_BERSERK);
Berserk_Timer = 600000;
} else Berserk_Timer -= diff;
if (ShapeShift_Timer <= diff)
{
if (inBearForm)
{
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122);
me->MonsterYell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_YELL_TOTROLL);
me->RemoveAurasDueToSpell(SPELL_BEARFORM);
Surge_Timer = urand(15000, 20000);
BrutalSwipe_Timer = urand(7000, 12000);
Mangle_Timer = urand(10000, 15000);
ShapeShift_Timer = urand(45000, 50000);
inBearForm = false;
}
else
{
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0);
me->MonsterYell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_YELL_TOBEAR);
DoCast(me, SPELL_BEARFORM, true);
LaceratingSlash_Timer = 2000; // dur 18s
RendFlesh_Timer = 3000; // dur 5s
DeafeningRoar_Timer = urand(5000, 10000); // dur 2s
ShapeShift_Timer = urand(20000, 25000); // dur 30s
inBearForm = true;
}
} else ShapeShift_Timer -= diff;
if (!inBearForm)
{
if (BrutalSwipe_Timer <= diff)
{
DoCastVictim(SPELL_BRUTALSWIPE);
BrutalSwipe_Timer = urand(7000, 12000);
} else BrutalSwipe_Timer -= diff;
if (Mangle_Timer <= diff)
{
if (me->GetVictim() && !me->GetVictim()->HasAura(SPELL_MANGLEEFFECT))
{
DoCastVictim(SPELL_MANGLE);
Mangle_Timer = 1000;
}
else Mangle_Timer = urand(10000, 15000);
} else Mangle_Timer -= diff;
if (Surge_Timer <= diff)
{
me->MonsterYell(YELL_SURGE, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(me, SOUND_YELL_SURGE);
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 45, true);
if (target)
DoCast(target, SPELL_SURGE);
Surge_Timer = urand(15000, 20000);
} else Surge_Timer -= diff;
}
else
{
if (LaceratingSlash_Timer <= diff)
{
DoCastVictim(SPELL_LACERATINGSLASH);
LaceratingSlash_Timer = urand(18000, 23000);
} else LaceratingSlash_Timer -= diff;
if (RendFlesh_Timer <= diff)
{
DoCastVictim(SPELL_RENDFLESH);
RendFlesh_Timer = urand(5000, 10000);
} else RendFlesh_Timer -= diff;
if (DeafeningRoar_Timer <= diff)
{
DoCastVictim(SPELL_DEAFENINGROAR);
DeafeningRoar_Timer = urand(15000, 20000);
} else DeafeningRoar_Timer -= diff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_nalorakkAI>(creature);
}
};
void AddSC_boss_nalorakk()
{
new boss_nalorakk();
}

View File

@@ -0,0 +1,601 @@
/*
* Copyright (C)
* Copyright (C)
*
* 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/>.
*/
/* ScriptData
SDName: Boss_ZulJin
SD%Complete: 85%
SDComment:
EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulaman.h"
#include "SpellInfo.h"
enum Says
{
YELL_INTRO = 0,
YELL_AGGRO = 1,
YELL_TRANSFORM_TO_BEAR = 2,
YELL_TRANSFORM_TO_EAGLE = 3,
YELL_TRANSFORM_TO_LYNX = 4,
YELL_TRANSFORM_TO_DRAGONHAWK = 5,
YELL_FIRE_BREATH = 6,
YELL_BERSERK = 7,
YELL_KILL = 8,
YELL_DEATH = 9
};
enum Spells
{
// Troll Form
SPELL_WHIRLWIND = 17207,
SPELL_GRIEVOUS_THROW = 43093, // remove debuff after full healed
// Bear Form
SPELL_CREEPING_PARALYSIS = 43095, // should cast on the whole raid
SPELL_OVERPOWER = 43456, // use after melee attack dodged
// Eagle Form
SPELL_ENERGY_STORM = 43983, // enemy area aura, trigger 42577
SPELL_ZAP_INFORM = 42577,
SPELL_ZAP_DAMAGE = 43137, // 1250 damage
SPELL_SUMMON_CYCLONE = 43112, // summon four feather vortex
CREATURE_FEATHER_VORTEX = 24136,
SPELL_CYCLONE_VISUAL = 43119, // trigger 43147 visual
SPELL_CYCLONE_PASSIVE = 43120, // trigger 43121 (4y aoe) every second
// Lynx Form
SPELL_CLAW_RAGE_HASTE = 42583,
SPELL_CLAW_RAGE_TRIGGER = 43149,
SPELL_CLAW_RAGE_DAMAGE = 43150,
SPELL_LYNX_RUSH_HASTE = 43152,
SPELL_LYNX_RUSH_DAMAGE = 43153,
// Dragonhawk Form
SPELL_FLAME_WHIRL = 43213, // trigger two spells
SPELL_FLAME_BREATH = 43215,
SPELL_SUMMON_PILLAR = 43216, // summon 24187
CREATURE_COLUMN_OF_FIRE = 24187,
SPELL_PILLAR_TRIGGER = 43218, // trigger 43217
// Cosmetic
SPELL_SPIRIT_AURA = 42466,
SPELL_SIPHON_SOUL = 43501,
// Transforms:
SPELL_SHAPE_OF_THE_BEAR = 42594, // 15% dmg
SPELL_SHAPE_OF_THE_EAGLE = 42606,
SPELL_SHAPE_OF_THE_LYNX = 42607, // haste melee 30%
SPELL_SHAPE_OF_THE_DRAGONHAWK = 42608,
SPELL_BERSERK = 45078
};
enum Phase
{
PHASE_BEAR = 0,
PHASE_EAGLE = 1,
PHASE_LYNX = 2,
PHASE_DRAGONHAWK = 3,
PHASE_TROLL = 4
};
//coords for going for changing form
#define CENTER_X 120.148811f
#define CENTER_Y 703.713684f
#define CENTER_Z 45.111477f
struct SpiritInfoStruct
{
uint32 entry;
float x, y, z, orient;
};
static SpiritInfoStruct SpiritInfo[4] =
{
{23878, 147.87f, 706.51f, 45.11f, 3.04f},
{23880, 88.95f, 705.49f, 45.11f, 6.11f},
{23877, 137.23f, 725.98f, 45.11f, 3.71f},
{23879, 104.29f, 726.43f, 45.11f, 5.43f}
};
struct TransformStruct
{
uint8 text;
uint32 spell, unaura;
};
static TransformStruct Transform[4] =
{
{YELL_TRANSFORM_TO_BEAR, SPELL_SHAPE_OF_THE_BEAR, SPELL_WHIRLWIND},
{YELL_TRANSFORM_TO_EAGLE, SPELL_SHAPE_OF_THE_EAGLE, SPELL_SHAPE_OF_THE_BEAR},
{YELL_TRANSFORM_TO_LYNX, SPELL_SHAPE_OF_THE_LYNX, SPELL_SHAPE_OF_THE_EAGLE},
{YELL_TRANSFORM_TO_DRAGONHAWK, SPELL_SHAPE_OF_THE_DRAGONHAWK, SPELL_SHAPE_OF_THE_LYNX}
};
class boss_zuljin : public CreatureScript
{
public:
boss_zuljin()
: CreatureScript("boss_zuljin")
{
}
struct boss_zuljinAI : public ScriptedAI
{
boss_zuljinAI(Creature* creature) : ScriptedAI(creature), Summons(me)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
uint64 SpiritGUID[4];
uint64 ClawTargetGUID;
uint64 TankGUID;
uint32 Phase;
uint32 health_20;
uint32 Intro_Timer;
uint32 Berserk_Timer;
uint32 Whirlwind_Timer;
uint32 Grievous_Throw_Timer;
uint32 Creeping_Paralysis_Timer;
uint32 Overpower_Timer;
uint32 Claw_Rage_Timer;
uint32 Lynx_Rush_Timer;
uint32 Claw_Counter;
uint32 Claw_Loop_Timer;
uint32 Flame_Whirl_Timer;
uint32 Flame_Breath_Timer;
uint32 Pillar_Of_Fire_Timer;
SummonList Summons;
void Reset()
{
instance->SetData(DATA_ZULJINEVENT, NOT_STARTED);
Phase = 0;
health_20 = me->CountPctFromMaxHealth(20);
Intro_Timer = 37000;
Berserk_Timer = 600000;
Whirlwind_Timer = 7000;
Grievous_Throw_Timer = 8000;
Creeping_Paralysis_Timer = 7000;
Overpower_Timer = 0;
Claw_Rage_Timer = 5000;
Lynx_Rush_Timer = 14000;
Claw_Loop_Timer = 0;
Claw_Counter = 0;
Flame_Whirl_Timer = 5000;
Flame_Breath_Timer = 6000;
Pillar_Of_Fire_Timer = 7000;
ClawTargetGUID = 0;
TankGUID = 0;
Summons.DespawnAll();
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 33975);
//me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674);
//me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
}
void EnterCombat(Unit* /*who*/)
{
instance->SetData(DATA_ZULJINEVENT, IN_PROGRESS);
DoZoneInCombat();
Talk(YELL_INTRO);
SpawnAdds();
EnterPhase(0);
}
void KilledUnit(Unit* /*victim*/)
{
if (Intro_Timer)
return;
Talk(YELL_KILL);
}
void JustDied(Unit* /*killer*/)
{
instance->SetData(DATA_ZULJINEVENT, DONE);
Talk(YELL_DEATH);
Summons.DespawnEntry(CREATURE_COLUMN_OF_FIRE);
if (Unit* Temp = ObjectAccessor::GetUnit(*me, SpiritGUID[3]))
Temp->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD);
}
void AttackStart(Unit* who)
{
if (Phase == 2)
AttackStartNoMove(who);
else
ScriptedAI::AttackStart(who);
}
void DoMeleeAttackIfReady()
{
if (!me->IsNonMeleeSpellCast(false))
{
if (me->isAttackReady() && me->IsWithinMeleeRange(me->GetVictim()))
{
if (Phase == 1 && !Overpower_Timer)
{
uint32 health = me->GetVictim()->GetHealth();
me->AttackerStateUpdate(me->GetVictim());
if (me->GetVictim() && health == me->GetVictim()->GetHealth())
{
DoCastVictim(SPELL_OVERPOWER, false);
Overpower_Timer = 5000;
}
} else me->AttackerStateUpdate(me->GetVictim());
me->resetAttackTimer();
}
}
}
void SpawnAdds()
{
Creature* creature = NULL;
for (uint8 i = 0; i < 4; ++i)
{
creature = me->SummonCreature(SpiritInfo[i].entry, SpiritInfo[i].x, SpiritInfo[i].y, SpiritInfo[i].z, SpiritInfo[i].orient, TEMPSUMMON_DEAD_DESPAWN, 0);
if (creature)
{
creature->CastSpell(creature, SPELL_SPIRIT_AURA, true);
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
SpiritGUID[i] = creature->GetGUID();
}
}
}
void DespawnAdds()
{
for (uint8 i = 0; i < 4; ++i)
{
if (SpiritGUID[i])
{
if (Unit* temp = ObjectAccessor::GetUnit(*me, SpiritGUID[i]))
{
temp->SetVisible(false);
temp->setDeathState(DEAD);
}
}
SpiritGUID[i] = 0;
}
}
void JustSummoned(Creature* summon)
{
Summons.Summon(summon);
}
void SummonedCreatureDespawn(Creature* summon)
{
Summons.Despawn(summon);
}
void EnterPhase(uint32 NextPhase)
{
switch (NextPhase)
{
case 0:
break;
case 1:
case 2:
case 3:
case 4:
me->NearTeleportTo(CENTER_X, CENTER_Y, CENTER_Z, me->GetOrientation());
DoResetThreat();
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0);
me->RemoveAurasDueToSpell(Transform[Phase].unaura);
DoCast(me, Transform[Phase].spell);
Talk(Transform[Phase].text);
if (Phase > 0)
{
if (Unit* Temp = ObjectAccessor::GetUnit(*me, SpiritGUID[Phase - 1]))
Temp->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD);
}
if (Unit* Temp = ObjectAccessor::GetUnit(*me, SpiritGUID[NextPhase - 1]))
Temp->CastSpell(me, SPELL_SIPHON_SOUL, false); // should m cast on temp
if (NextPhase == 2)
{
me->GetMotionMaster()->Clear();
DoCast(me, SPELL_ENERGY_STORM, true); // enemy aura
for (uint8 i = 0; i < 4; ++i)
{
Creature* Vortex = DoSpawnCreature(CREATURE_FEATHER_VORTEX, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
if (Vortex)
{
Vortex->CastSpell(Vortex, SPELL_CYCLONE_PASSIVE, true);
Vortex->CastSpell(Vortex, SPELL_CYCLONE_VISUAL, true);
Vortex->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
Vortex->SetSpeed(MOVE_RUN, 1.0f);
Vortex->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0));
DoZoneInCombat(Vortex);
}
}
}
else
AttackStart(me->GetVictim());
if (NextPhase == 3)
{
me->RemoveAurasDueToSpell(SPELL_ENERGY_STORM);
Summons.DespawnEntry(CREATURE_FEATHER_VORTEX);
me->GetMotionMaster()->MoveChase(me->GetVictim());
}
break;
default:
break;
}
Phase = NextPhase;
}
void UpdateAI(uint32 diff)
{
if (!TankGUID)
{
if (!UpdateVictim())
return;
if (me->GetHealth() < health_20 * (4 - Phase))
EnterPhase(Phase + 1);
}
if (Berserk_Timer <= diff)
{
DoCast(me, SPELL_BERSERK, true);
Talk(YELL_BERSERK);
Berserk_Timer = 60000;
} else Berserk_Timer -= diff;
switch (Phase)
{
case 0:
if (Intro_Timer)
{
if (Intro_Timer <= diff)
{
Talk(YELL_AGGRO);
Intro_Timer = 0;
} else Intro_Timer -= diff;
}
if (Whirlwind_Timer <= diff)
{
DoCast(me, SPELL_WHIRLWIND);
Whirlwind_Timer = urand(15000, 20000);
} else Whirlwind_Timer -= diff;
if (Grievous_Throw_Timer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
DoCast(target, SPELL_GRIEVOUS_THROW, false);
Grievous_Throw_Timer = 10000;
} else Grievous_Throw_Timer -= diff;
break;
case 1:
if (Creeping_Paralysis_Timer <= diff)
{
DoCast(me, SPELL_CREEPING_PARALYSIS);
Creeping_Paralysis_Timer = 20000;
} else Creeping_Paralysis_Timer -= diff;
if (Overpower_Timer <= diff)
{
// implemented in DoMeleeAttackIfReady()
Overpower_Timer = 0;
} else Overpower_Timer -= diff;
break;
case 2:
return;
case 3:
if (Claw_Rage_Timer <= diff)
{
if (!TankGUID)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
TankGUID = me->GetVictim()->GetGUID();
me->SetSpeed(MOVE_RUN, 5.0f);
AttackStart(target); // change victim
Claw_Rage_Timer = 0;
Claw_Loop_Timer = 500;
Claw_Counter = 0;
}
}
else if (!Claw_Rage_Timer) // do not do this when Lynx_Rush
{
if (Claw_Loop_Timer <= diff)
{
Unit* target = me->GetVictim();
if (!target || !target->isTargetableForAttack()) target = ObjectAccessor::GetUnit(*me, TankGUID);
if (!target || !target->isTargetableForAttack()) target = SelectTarget(SELECT_TARGET_RANDOM, 0);
if (target)
{
AttackStart(target);
if (me->IsWithinMeleeRange(target))
{
DoCast(target, SPELL_CLAW_RAGE_DAMAGE, true);
++Claw_Counter;
if (Claw_Counter == 12)
{
Claw_Rage_Timer = urand(15000, 20000);
me->SetSpeed(MOVE_RUN, 1.2f);
AttackStart(ObjectAccessor::GetUnit(*me, TankGUID));
TankGUID = 0;
return;
}
else
Claw_Loop_Timer = 500;
}
}
else
{
EnterEvadeMode(); // if (target)
return;
}
} else Claw_Loop_Timer -= diff;
} //if (TankGUID)
} else Claw_Rage_Timer -= diff;
if (Lynx_Rush_Timer <= diff)
{
if (!TankGUID)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
TankGUID = me->GetVictim()->GetGUID();
me->SetSpeed(MOVE_RUN, 5.0f);
AttackStart(target); // change victim
Lynx_Rush_Timer = 0;
Claw_Counter = 0;
}
}
else if (!Lynx_Rush_Timer)
{
Unit* target = me->GetVictim();
if (!target || !target->isTargetableForAttack())
{
target = SelectTarget(SELECT_TARGET_RANDOM, 0);
AttackStart(target);
}
if (target)
{
if (me->IsWithinMeleeRange(target))
{
DoCast(target, SPELL_LYNX_RUSH_DAMAGE, true);
++Claw_Counter;
if (Claw_Counter == 9)
{
Lynx_Rush_Timer = urand(15000, 20000);
me->SetSpeed(MOVE_RUN, 1.2f);
AttackStart(ObjectAccessor::GetUnit(*me, TankGUID));
TankGUID = 0;
}
else
AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0));
}
}
else
{
EnterEvadeMode(); // if (target)
return;
}
} //if (TankGUID)
} else Lynx_Rush_Timer -= diff;
break;
case 4:
if (Flame_Whirl_Timer <= diff)
{
DoCast(me, SPELL_FLAME_WHIRL);
Flame_Whirl_Timer = 12000;
}Flame_Whirl_Timer -= diff;
if (Pillar_Of_Fire_Timer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_SUMMON_PILLAR);
Pillar_Of_Fire_Timer = 10000;
} else Pillar_Of_Fire_Timer -= diff;
if (Flame_Breath_Timer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
me->SetInFront(target);
DoCast(me, SPELL_FLAME_BREATH);
Flame_Breath_Timer = 10000;
} else Flame_Breath_Timer -= diff;
break;
default:
break;
}
if (!TankGUID)
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<boss_zuljinAI>(creature);
}
};
class npc_zuljin_vortex : public CreatureScript
{
public:
npc_zuljin_vortex()
: CreatureScript("npc_zuljin_vortex")
{
}
struct npc_zuljin_vortexAI : public ScriptedAI
{
npc_zuljin_vortexAI(Creature* creature) : ScriptedAI(creature) { }
void Reset() { }
void EnterCombat(Unit* /*target*/) { }
void SpellHit(Unit* caster, const SpellInfo* spell)
{
if (spell->Id == SPELL_ZAP_INFORM)
DoCast(caster, SPELL_ZAP_DAMAGE, true);
}
void UpdateAI(uint32 /*diff*/)
{
//if the vortex reach the target, it change his target to another player
if (me->IsWithinMeleeRange(me->GetVictim()))
AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0));
}
};
CreatureAI* GetAI(Creature* creature) const
{
return new npc_zuljin_vortexAI(creature);
}
};
void AddSC_boss_zuljin()
{
new boss_zuljin();
new npc_zuljin_vortex();
}

View File

@@ -0,0 +1,378 @@
/*
* Copyright (C)
* Copyright (C)
*
* 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/>.
*/
/* ScriptData
SDName: instance_zulaman
SD%Complete: 80
SDComment:
SDCategory: Zul'Aman
EndScriptData */
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "zulaman.h"
#include "Player.h"
#include "TemporarySummon.h"
enum Misc
{
MAX_ENCOUNTER = 7,
RAND_VENDOR = 2,
WORLDSTATE_SHOW_TIMER = 3104,
WORLDSTATE_TIME_TO_SACRIFICE = 3106
};
// Chests spawn at bear/eagle/dragonhawk/lynx bosses
// The loots depend on how many bosses have been killed, but not the entries of the chests
// But we cannot add loots to gameobject, so we have to use the fixed loot_template
struct SHostageInfo
{
uint32 npc, go; // FIXME go Not used
float x, y, z, o;
};
static SHostageInfo HostageInfo[] =
{
{23790, 186648, -57, 1343, 40.77f, 3.2f}, // bear
{23999, 187021, 400, 1414, 74.36f, 3.3f}, // eagle
{24001, 186672, -35, 1134, 18.71f, 1.9f}, // dragonhawk
{24024, 186667, 413, 1117, 6.32f, 3.1f} // lynx
};
Position const HarrisonJonesLoc = {120.687f, 1674.0f, 42.0217f, 1.59044f};
class instance_zulaman : public InstanceMapScript
{
public:
instance_zulaman()
: InstanceMapScript("instance_zulaman", 568)
{
}
struct instance_zulaman_InstanceMapScript : public InstanceScript
{
instance_zulaman_InstanceMapScript(Map* map) : InstanceScript(map) {}
uint64 HarkorsSatchelGUID;
uint64 TanzarsTrunkGUID;
uint64 AshlisBagGUID;
uint64 KrazsPackageGUID;
uint64 StrangeGongGUID;
uint64 HarrisonJonesGUID;
uint64 HexLordGateGUID;
uint64 ZulJinGateGUID;
uint64 MassiveGateGUID;
uint64 AkilzonDoorGUID;
uint64 ZulJinDoorGUID;
uint64 HalazziDoorGUID;
uint32 QuestTimer;
uint16 BossKilled;
uint16 QuestMinute;
uint16 ChestLooted;
uint32 m_auiEncounter[MAX_ENCOUNTER];
uint32 RandVendor[RAND_VENDOR];
void Initialize()
{
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
HarkorsSatchelGUID = 0;
TanzarsTrunkGUID = 0;
AshlisBagGUID = 0;
KrazsPackageGUID = 0;
StrangeGongGUID = 0;
HexLordGateGUID = 0;
ZulJinGateGUID = 0;
MassiveGateGUID = 0;
AkilzonDoorGUID = 0;
HalazziDoorGUID = 0;
ZulJinDoorGUID = 0;
HarrisonJonesGUID = 0;
QuestTimer = 0;
QuestMinute = 0;
BossKilled = 0;
ChestLooted = 0;
for (uint8 i = 0; i < RAND_VENDOR; ++i)
RandVendor[i] = NOT_STARTED;
m_auiEncounter[DATA_GONGEVENT] = NOT_STARTED;
}
bool IsEncounterInProgress() const
{
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
if (m_auiEncounter[i] == IN_PROGRESS)
return true;
return false;
}
void OnPlayerEnter(Player* /*player*/)
{
if (!HarrisonJonesGUID)
instance->SummonCreature(NPC_HARRISON_JONES, HarrisonJonesLoc);
}
void OnCreatureCreate(Creature* creature)
{
switch (creature->GetEntry())
{
case NPC_HARRISON_JONES:
HarrisonJonesGUID = creature->GetGUID();
break;
case NPC_JANALAI:
case NPC_ZULJIN:
case NPC_HEXLORD:
case NPC_HALAZZI:
case NPC_NALORAKK:
default:
break;
}
}
void OnGameObjectCreate(GameObject* go)
{
switch (go->GetEntry())
{
case GO_DOOR_HALAZZI: HalazziDoorGUID = go->GetGUID(); break;
case GO_GATE_ZULJIN: ZulJinGateGUID = go->GetGUID(); break;
case GO_GATE_HEXLORD: HexLordGateGUID = go->GetGUID(); break;
case GO_MASSIVE_GATE: MassiveGateGUID = go->GetGUID(); break;
case GO_DOOR_AKILZON: AkilzonDoorGUID = go->GetGUID(); break;
case GO_DOOR_ZULJIN: ZulJinDoorGUID = go->GetGUID(); break;
case GO_HARKORS_SATCHEL: HarkorsSatchelGUID = go->GetGUID(); break;
case GO_TANZARS_TRUNK: TanzarsTrunkGUID = go->GetGUID(); break;
case GO_ASHLIS_BAG: AshlisBagGUID = go->GetGUID(); break;
case GO_KRAZS_PACKAGE: KrazsPackageGUID = go->GetGUID(); break;
case GO_STRANGE_GONG: StrangeGongGUID = go->GetGUID(); break;
default: break;
}
CheckInstanceStatus();
}
void SummonHostage(uint8 num)
{
if (!QuestMinute)
return;
Map::PlayerList const &PlayerList = instance->GetPlayers();
if (PlayerList.isEmpty())
return;
Map::PlayerList::const_iterator i = PlayerList.begin();
if (Player* i_pl = i->GetSource())
{
if (Unit* Hostage = i_pl->SummonCreature(HostageInfo[num].npc, HostageInfo[num].x, HostageInfo[num].y, HostageInfo[num].z, HostageInfo[num].o, TEMPSUMMON_DEAD_DESPAWN, 0))
{
Hostage->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
Hostage->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
}
}
void CheckInstanceStatus()
{
if (BossKilled >= DATA_HALAZZIEVENT)
HandleGameObject(HexLordGateGUID, true);
if (BossKilled >= DATA_HEXLORDEVENT)
HandleGameObject(ZulJinGateGUID, true);
}
std::string GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream ss;
ss << "S " << BossKilled << ' ' << ChestLooted << ' ' << QuestMinute;
OUT_SAVE_INST_DATA_COMPLETE;
return ss.str();
}
void Load(const char* load)
{
if (!load)
return;
std::istringstream ss(load);
//sLog->outError("Zul'aman loaded, %s.", ss.str().c_str());
char dataHead; // S
uint16 data1, data2, data3;
ss >> dataHead >> data1 >> data2 >> data3;
//sLog->outError("Zul'aman loaded, %d %d %d.", data1, data2, data3);
if (dataHead == 'S')
{
BossKilled = data1;
ChestLooted = data2;
QuestMinute = data3;
} else sLog->outError("Zul'aman: corrupted save data.");
}
void SetData(uint32 type, uint32 data)
{
switch (type)
{
case DATA_GONGEVENT:
m_auiEncounter[DATA_GONGEVENT] = data;
if (data == IN_PROGRESS)
SaveToDB();
else if (data == DONE)
QuestMinute = 21;
break;
case DATA_NALORAKKEVENT:
m_auiEncounter[DATA_NALORAKKEVENT] = data;
if (data == DONE)
{
if (QuestMinute)
{
QuestMinute += 15;
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, QuestMinute);
}
SummonHostage(0);
}
break;
case DATA_AKILZONEVENT:
m_auiEncounter[DATA_AKILZONEVENT] = data;
HandleGameObject(AkilzonDoorGUID, data != IN_PROGRESS);
if (data == DONE)
{
if (QuestMinute)
{
QuestMinute += 10;
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, QuestMinute);
}
SummonHostage(1);
}
break;
case DATA_JANALAIEVENT:
m_auiEncounter[DATA_JANALAIEVENT] = data;
if (data == DONE)
SummonHostage(2);
break;
case DATA_HALAZZIEVENT:
m_auiEncounter[DATA_HALAZZIEVENT] = data;
HandleGameObject(HalazziDoorGUID, data != IN_PROGRESS);
if (data == DONE) SummonHostage(3);
break;
case DATA_HEXLORDEVENT:
m_auiEncounter[DATA_HEXLORDEVENT] = data;
if (data == IN_PROGRESS)
HandleGameObject(HexLordGateGUID, false);
else if (data == NOT_STARTED)
CheckInstanceStatus();
break;
case DATA_ZULJINEVENT:
m_auiEncounter[DATA_ZULJINEVENT] = data;
HandleGameObject(ZulJinDoorGUID, data != IN_PROGRESS);
break;
case DATA_CHESTLOOTED:
++ChestLooted;
SaveToDB();
break;
case TYPE_RAND_VENDOR_1:
RandVendor[0] = data;
break;
case TYPE_RAND_VENDOR_2:
RandVendor[1] = data;
break;
}
if (data == DONE)
{
++BossKilled;
if (QuestMinute && BossKilled >= DATA_HALAZZIEVENT)
{
QuestMinute = 0;
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 0);
}
CheckInstanceStatus();
SaveToDB();
}
}
uint32 GetData(uint32 type) const
{
switch (type)
{
case DATA_GONGEVENT: return m_auiEncounter[DATA_GONGEVENT];
case DATA_NALORAKKEVENT: return m_auiEncounter[DATA_NALORAKKEVENT];
case DATA_AKILZONEVENT: return m_auiEncounter[DATA_AKILZONEVENT];
case DATA_JANALAIEVENT: return m_auiEncounter[DATA_JANALAIEVENT];
case DATA_HALAZZIEVENT: return m_auiEncounter[DATA_HALAZZIEVENT];
case DATA_HEXLORDEVENT: return m_auiEncounter[DATA_HEXLORDEVENT];
case DATA_ZULJINEVENT: return m_auiEncounter[DATA_ZULJINEVENT];
case DATA_CHESTLOOTED: return ChestLooted;
case TYPE_RAND_VENDOR_1: return RandVendor[0];
case TYPE_RAND_VENDOR_2: return RandVendor[1];
default: return 0;
}
}
void Update(uint32 diff)
{
if (QuestMinute)
{
if (QuestTimer <= diff)
{
QuestMinute--;
SaveToDB();
QuestTimer += 60000;
if (QuestMinute)
{
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 1);
DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, QuestMinute);
} else DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 0);
}
QuestTimer -= diff;
}
}
uint64 GetData64(uint32 type) const
{
switch (type)
{
case GO_STRANGE_GONG:
return StrangeGongGUID;
case GO_MASSIVE_GATE:
return MassiveGateGUID;
}
return 0;
}
};
InstanceScript* GetInstanceScript(InstanceMap* map) const
{
return new instance_zulaman_InstanceMapScript(map);
}
};
void AddSC_instance_zulaman()
{
new instance_zulaman();
}

View File

@@ -0,0 +1,496 @@
/*
* Copyright (C)
* Copyright (C)
*
* 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/>.
*/
/* ScriptData
SDName: Zulaman
SD%Complete: 90
SDComment: Forest Frog will turn into different NPC's. Workaround to prevent new entry from running this script
SDCategory: Zul'Aman
EndScriptData */
/* ContentData
npc_forest_frog
EndContentData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "zulaman.h"
#include "Player.h"
#include "SpellInfo.h"
#include "SpellScript.h"
/*######
## npc_forest_frog
######*/
enum ForestFrog
{
// Spells
SPELL_REMOVE_AMANI_CURSE = 43732,
SPELL_PUSH_MOJO = 43923,
// Creatures
NPC_FOREST_FROG = 24396
};
class npc_forest_frog : public CreatureScript
{
public:
npc_forest_frog() : CreatureScript("npc_forest_frog") { }
struct npc_forest_frogAI : public ScriptedAI
{
npc_forest_frogAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
void Reset() { }
void EnterCombat(Unit* /*who*/) { }
void DoSpawnRandom()
{
uint32 cEntry = 24397;
switch (urand(0, 9))
{
//case 0: cEntry = 24397; break; //Mannuth
case 1: cEntry = 24403; break; //Deez
case 2: cEntry = 24404; break; //Galathryn
case 3: cEntry = 24405; break; //Adarrah
case 4: cEntry = 24406; break; //Fudgerick
case 5: cEntry = 24407; break; //Darwen
case 6: cEntry = 24445; break; //Mitzi
case 7: cEntry = 24448; break; //Christian
case 8: cEntry = 24453; break; //Brennan
case 9: cEntry = 24455; break; //Hollee
}
if (!instance->GetData(TYPE_RAND_VENDOR_1) && roll_chance_i(10))
{
cEntry = 24408; //Gunter
instance->SetData(TYPE_RAND_VENDOR_1, DONE);
}
else if (!instance->GetData(TYPE_RAND_VENDOR_2) && roll_chance_i(10))
{
cEntry = 24409; //Kyren
instance->SetData(TYPE_RAND_VENDOR_2, DONE);
}
me->UpdateEntry(cEntry);
me->DespawnOrUnsummon(2*MINUTE*IN_MILLISECONDS);
}
void SpellHit(Unit* caster, const SpellInfo* spell)
{
if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->GetTypeId() == TYPEID_PLAYER && me->GetEntry() == NPC_FOREST_FROG)
{
if (roll_chance_i(2))
DoCast(caster, SPELL_PUSH_MOJO, true);
else
DoSpawnRandom();
}
}
};
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<npc_forest_frogAI>(creature);
}
};
/*######
## npc_zulaman_hostage
######*/
#define GOSSIP_HOSTAGE1 "I am glad to help you."
static uint32 HostageEntry[] = {23790, 23999, 24024, 24001};
static uint32 ChestEntry[] = {186648, 187021, 186672, 186667};
class npc_zulaman_hostage : public CreatureScript
{
public:
npc_zulaman_hostage() : CreatureScript("npc_zulaman_hostage") { }
struct npc_zulaman_hostageAI : public ScriptedAI
{
npc_zulaman_hostageAI(Creature* creature) : ScriptedAI(creature)
{
IsLoot = false;
}
bool IsLoot;
uint64 PlayerGUID;
void Reset() { }
void EnterCombat(Unit* /*who*/) { }
void JustDied(Unit* /*killer*/)
{
if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID))
player->SendLoot(me->GetGUID(), LOOT_CORPSE);
}
void UpdateAI(uint32 /*diff*/)
{
if (IsLoot)
DoCast(me, 7, false);
}
};
CreatureAI* GetAI(Creature* creature) const
{
return new npc_zulaman_hostageAI(creature);
}
bool OnGossipHello(Player* player, Creature* creature)
{
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HOSTAGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
return true;
}
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action)
{
player->PlayerTalkClass->ClearMenus();
if (action == GOSSIP_ACTION_INFO_DEF + 1)
player->CLOSE_GOSSIP_MENU();
if (!creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
return true;
creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
InstanceScript* instance = creature->GetInstanceScript();
if (instance)
{
//uint8 progress = instance->GetData(DATA_CHESTLOOTED);
instance->SetData(DATA_CHESTLOOTED, 0);
float x, y, z;
creature->GetPosition(x, y, z);
uint32 entry = creature->GetEntry();
for (uint8 i = 0; i < 4; ++i)
{
if (HostageEntry[i] == entry)
{
creature->SummonGameObject(ChestEntry[i], x-2, y, z, 0, 0, 0, 0, 0, 0);
break;
}
}
}
return true;
}
};
/*######
## npc_harrison_jones
######*/
enum Says
{
SAY_HARRISON_0 = 0,
SAY_HARRISON_1 = 1,
SAY_HARRISON_2 = 0,
SAY_HARRISON_3 = 1
};
enum Spells
{
SPELL_BANGING_THE_GONG = 45225,
SPELL_STEALTH = 34189,
SPELL_COSMETIC_SPEAR_THROW = 43647
};
enum Events
{
GONG_EVENT_1 = 1,
GONG_EVENT_2 = 2,
GONG_EVENT_3 = 3,
GONG_EVENT_4 = 4,
GONG_EVENT_5 = 5,
GONG_EVENT_6 = 6,
GONG_EVENT_7 = 7,
GONG_EVENT_8 = 8,
GONG_EVENT_9 = 9,
GONG_EVENT_10 = 10,
GONG_EVENT_11 = 11
};
enum Waypoints
{
HARRISON_MOVE_1 = 860440,
HARRISON_MOVE_2 = 860441,
HARRISON_MOVE_3 = 860442
};
enum DisplayIds
{
MODEL_HARRISON_JONES_0 = 22340,
MODEL_HARRISON_JONES_1 = 22354,
MODEL_HARRISON_JONES_2 = 22347
};
enum EntryIds
{
NPC_HARRISON_JONES_1 = 24375,
NPC_HARRISON_JONES_2 = 24365,
NPC_AMANISHI_GUARDIAN = 23597,
};
enum Weapons
{
WEAPON_MACE = 5301,
WEAPON_SPEAR = 13631
};
class npc_harrison_jones : public CreatureScript
{
public:
npc_harrison_jones() : CreatureScript("npc_harrison_jones")
{
}
struct npc_harrison_jonesAI : public ScriptedAI
{
npc_harrison_jonesAI(Creature* creature) : ScriptedAI(creature)
{
instance = creature->GetInstanceScript();
}
InstanceScript* instance;
uint8 _gongEvent;
uint32 _gongTimer;
uint64 uiTargetGUID;
void Reset()
{
_gongEvent = 0;
_gongTimer = 0;
uiTargetGUID = 0;
}
void EnterCombat(Unit* /*who*/) { }
void sGossipSelect(Player* player, uint32 sender, uint32 action)
{
if (me->GetCreatureTemplate()->GossipMenuId == sender && !action)
{
player->CLOSE_GOSSIP_MENU();
me->SetFacingToObject(player);
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
Talk(SAY_HARRISON_0);
_gongEvent = GONG_EVENT_1;
_gongTimer = 4000;
}
}
void SpellHit(Unit*, const SpellInfo* spell)
{
if (spell->Id == SPELL_COSMETIC_SPEAR_THROW)
{
me->RemoveAllAuras();
me->SetEntry(NPC_HARRISON_JONES_2);
me->SetDisplayId(MODEL_HARRISON_JONES_2);
me->SetTarget(0);
me->SetByteValue(UNIT_FIELD_BYTES_1, 0, UNIT_STAND_STATE_DEAD);
me->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
instance->SetData(DATA_GONGEVENT, DONE);
}
}
void UpdateAI(uint32 diff)
{
if (_gongEvent)
{
if (_gongTimer <= diff)
{
switch (_gongEvent)
{
case GONG_EVENT_1:
me->GetMotionMaster()->MovePath(HARRISON_MOVE_1, false);
_gongEvent = GONG_EVENT_2;
_gongTimer = 12000;
break;
case GONG_EVENT_2:
me->SetFacingTo(6.235659f);
Talk(SAY_HARRISON_1);
DoCast(me, SPELL_BANGING_THE_GONG);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_MACE));
me->SetSheath(SHEATH_STATE_MELEE);
_gongEvent = GONG_EVENT_3;
_gongTimer = 4000;
break;
case GONG_EVENT_3:
if (GameObject* gong = me->GetMap()->GetGameObject(instance->GetData64(GO_STRANGE_GONG)))
gong->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
_gongEvent = GONG_EVENT_4;
_gongTimer = 105000;
break;
case GONG_EVENT_4:
me->RemoveAura(SPELL_BANGING_THE_GONG);
if (GameObject* gong = me->GetMap()->GetGameObject(instance->GetData64(GO_STRANGE_GONG)))
gong->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
// trigger or gong will need to be scripted to set IN_PROGRESS after enough hits.
// This is temp workaround.
instance->SetData(DATA_GONGEVENT, IN_PROGRESS); // to be removed.
if (instance->GetData(DATA_GONGEVENT) == IN_PROGRESS)
{
// Players are Now Saved to instance at SPECIAL (Player should be notified?)
me->GetMotionMaster()->MovePath(HARRISON_MOVE_2, false);
_gongEvent = GONG_EVENT_5;
_gongTimer = 5000;
}
else
{
_gongTimer = 1000;
_gongEvent = GONG_EVENT_9;
}
break;
case GONG_EVENT_5:
me->SetEntry(NPC_HARRISON_JONES_1);
me->SetDisplayId(MODEL_HARRISON_JONES_1);
Talk(SAY_HARRISON_2);
_gongTimer = 12000;
_gongEvent = GONG_EVENT_6;
break;
case GONG_EVENT_6:
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
Talk(SAY_HARRISON_3);
_gongTimer = 7000;
_gongEvent = GONG_EVENT_7;
break;
case GONG_EVENT_7:
if (!uiTargetGUID)
{
std::list<Creature*> targetList;
GetCreatureListWithEntryInGrid(targetList, me, NPC_AMANISHI_GUARDIAN, 26.0f);
if (!targetList.empty())
{
for (std::list<Creature*>::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
{
if (Creature* ptarget = *itr)
{
if (ptarget->GetPositionX() > 120)
{
ptarget->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_SPEAR));
ptarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
ptarget->SetReactState(REACT_PASSIVE);
ptarget->AI()->SetData(0, 1);
}
else
{
ptarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
ptarget->SetReactState(REACT_PASSIVE);
ptarget->AI()->SetData(0, 2);
}
}
}
}
}
if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetData64(GO_MASSIVE_GATE)))
gate->SetGoState(GO_STATE_ACTIVE);
_gongTimer = 2000;
_gongEvent = GONG_EVENT_8;
break;
case GONG_EVENT_8:
DoCast(me, SPELL_STEALTH);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(0));
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
me->GetMotionMaster()->MovePath(HARRISON_MOVE_3, false);
_gongTimer = 1000;
_gongEvent = 0;
break;
case GONG_EVENT_9:
me->GetMotionMaster()->MovePoint(0, 120.687f, 1674.0f, 42.0217f);
_gongTimer = 12000;
_gongEvent = GONG_EVENT_10;
break;
case GONG_EVENT_10:
me->SetFacingTo(1.59044f);
_gongEvent = 11;
_gongTimer = 6000;
break;
case GONG_EVENT_11:
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
instance->SetData(DATA_GONGEVENT, NOT_STARTED);
_gongEvent = 0;
_gongTimer = 1000;
break;
}
}
else
_gongTimer -= diff;
}
}
};
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<npc_harrison_jonesAI>(creature);
}
};
class spell_banging_the_gong : public SpellScriptLoader
{
public:
spell_banging_the_gong() : SpellScriptLoader("spell_banging_the_gong") { }
class spell_banging_the_gong_SpellScript : public SpellScript
{
PrepareSpellScript(spell_banging_the_gong_SpellScript);
void Activate(SpellEffIndex index)
{
PreventHitDefaultEffect(index);
GetHitGObj()->SendCustomAnim(0);
}
void Register()
{
OnEffectHitTarget += SpellEffectFn(spell_banging_the_gong_SpellScript::Activate, EFFECT_1, SPELL_EFFECT_ACTIVATE_OBJECT);
}
};
SpellScript* GetSpellScript() const
{
return new spell_banging_the_gong_SpellScript();
}
};
void AddSC_zulaman()
{
new npc_forest_frog();
new npc_zulaman_hostage();
new npc_harrison_jones();
new spell_banging_the_gong();
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C)
* Copyright (C)
*
* 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/>.
*/
#ifndef DEF_ZULAMAN_H
#define DEF_ZULAMAN_H
enum DataTypes
{
DATA_GONGEVENT = 0,
DATA_NALORAKKEVENT = 1,
DATA_AKILZONEVENT = 2,
DATA_JANALAIEVENT = 3,
DATA_HALAZZIEVENT = 4,
DATA_HEXLORDEVENT = 5,
DATA_ZULJINEVENT = 6,
DATA_CHESTLOOTED = 7,
TYPE_RAND_VENDOR_1 = 8,
TYPE_RAND_VENDOR_2 = 9
};
enum CreatureIds
{
NPC_HARRISON_JONES = 24358,
NPC_JANALAI = 23578,
NPC_ZULJIN = 23863,
NPC_HEXLORD = 24239,
NPC_HALAZZI = 23577,
NPC_NALORAKK = 23576
};
enum GameobjectIds
{
GO_DOOR_HALAZZI = 186303,
GO_GATE_ZULJIN = 186304,
GO_GATE_HEXLORD = 186305,
GO_MASSIVE_GATE = 186728,
GO_DOOR_AKILZON = 186858,
GO_DOOR_ZULJIN = 186859,
GO_HARKORS_SATCHEL = 187021,
GO_TANZARS_TRUNK = 186648,
GO_ASHLIS_BAG = 186672,
GO_KRAZS_PACKAGE = 186667,
GO_STRANGE_GONG = 187359
};
#endif