Files
CypherCore/Scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/GrandChampions.cs
T

650 lines
21 KiB
C#

/*
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
*
* 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 3 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/>.
*/
using Framework.Constants;
using Framework.Dynamic;
using Game.AI;
using Game.Entities;
using Game.Maps;
using Game.Scripting;
using System;
using System.Collections.Generic;
namespace Scripts.Northrend.CrusadersColiseum.TrialOfTheChampion
{
struct TrialOfChampionSpells
{
//Vehicle
public const uint CHARGE = 63010;
public const uint SHIELD_BREAKER = 68504;
public const uint SHIELD = 66482;
// Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior
public const uint MORTAL_STRIKE = 68783;
public const uint MORTAL_STRIKE_H = 68784;
public const uint BLADESTORM = 63784;
public const uint INTERCEPT = 67540;
public const uint ROLLING_THROW = 47115; //not implemented in the AI yet...
// Ambrose Boltspark && Eressea Dawnsinger || Mage
public const uint FIREBALL = 66042;
public const uint FIREBALL_H = 68310;
public const uint BLAST_WAVE = 66044;
public const uint BLAST_WAVE_H = 68312;
public const uint HASTE = 66045;
public const uint POLYMORPH = 66043;
public const uint POLYMORPH_H = 68311;
// Colosos && Runok Wildmane || Shaman
public const uint CHAIN_LIGHTNING = 67529;
public const uint CHAIN_LIGHTNING_H = 68319;
public const uint EARTH_SHIELD = 67530;
public const uint HEALING_WAVE = 67528;
public const uint HEALING_WAVE_H = 68318;
public const uint HEX_OF_MENDING = 67534;
// Jaelyne Evensong && Zul'tore || Hunter
public const uint DISENGAGE = 68340; //not implemented in the AI yet...
public const uint LIGHTNING_ARROWS = 66083;
public const uint MULTI_SHOT = 66081;
public const uint SHOOT = 65868;
public const uint SHOOT_H = 67988;
// Lana Stouthammer Evensong && Deathstalker Visceri || Rouge
public const uint EVISCERATE = 67709;
public const uint EVISCERATE_H = 68317;
public const uint FAN_OF_KNIVES = 67706;
public const uint POISON_BOTTLE = 67701;
}
[Script]
class generic_vehicleAI_toc5 : npc_escortAI
{
public generic_vehicleAI_toc5(Creature creature) : base(creature)
{
Initialize();
SetDespawnAtEnd(false);
uiWaypointPath = 0;
instance = creature.GetInstanceScript();
}
void Initialize()
{
uiChargeTimer = 5000;
uiShieldBreakerTimer = 8000;
uiBuffTimer = RandomHelper.URand(30000, 60000);
}
public override void Reset()
{
Initialize();
}
public override void SetData(uint uiType, uint uiData)
{
switch (uiType)
{
case 1:
AddWaypoint(0, 747.36f, 634.07f, 411.572f);
AddWaypoint(1, 780.43f, 607.15f, 411.82f);
AddWaypoint(2, 785.99f, 599.41f, 411.92f);
AddWaypoint(3, 778.44f, 601.64f, 411.79f);
uiWaypointPath = 1;
break;
case 2:
AddWaypoint(0, 747.35f, 634.07f, 411.57f);
AddWaypoint(1, 768.72f, 581.01f, 411.92f);
AddWaypoint(2, 763.55f, 590.52f, 411.71f);
uiWaypointPath = 2;
break;
case 3:
AddWaypoint(0, 747.35f, 634.07f, 411.57f);
AddWaypoint(1, 784.02f, 645.33f, 412.39f);
AddWaypoint(2, 775.67f, 641.91f, 411.91f);
uiWaypointPath = 3;
break;
}
if (uiType <= 3)
Start(false, true);
}
public override void WaypointReached(uint waypointId)
{
switch (waypointId)
{
case 2:
if (uiWaypointPath == 3 || uiWaypointPath == 2)
instance.SetData((uint)Data.DATA_MOVEMENT_DONE, instance.GetData((uint)Data.DATA_MOVEMENT_DONE) + 1);
break;
case 3:
instance.SetData((uint)Data.DATA_MOVEMENT_DONE, instance.GetData((uint)Data.DATA_MOVEMENT_DONE) + 1);
break;
}
}
public override void EnterCombat(Unit who)
{
DoCastSpellShield();
}
void DoCastSpellShield()
{
for (byte i = 0; i < 3; ++i)
DoCast(me, TrialOfChampionSpells.SHIELD, true);
}
public override void UpdateAI(uint uiDiff)
{
base.UpdateAI(uiDiff);
if (!UpdateVictim())
return;
if (uiBuffTimer <= uiDiff)
{
if (!me.HasAura(TrialOfChampionSpells.SHIELD))
DoCastSpellShield();
uiBuffTimer = RandomHelper.URand(30000, 45000);
}
else
uiBuffTimer -= uiDiff;
if (uiChargeTimer <= uiDiff)
{
var players = me.GetMap().GetPlayers();
if (!players.Empty())
{
foreach (var player in players)
{
if (player && !player.IsGameMaster() && me.IsInRange(player, 8.0f, 25.0f, false))
{
DoResetThreat();
me.AddThreat(player, 1.0f);
DoCast(player, TrialOfChampionSpells.CHARGE);
break;
}
}
}
uiChargeTimer = 5000;
}
else
uiChargeTimer -= uiDiff;
//dosen't work at all
if (uiShieldBreakerTimer <= uiDiff)
{
Vehicle pVehicle = me.GetVehicleKit();
if (!pVehicle)
return;
Unit pPassenger = pVehicle.GetPassenger(0);
if (pPassenger)
{
var players = me.GetMap().GetPlayers();
if (!players.Empty())
{
foreach (var player in players)
{
if (player && !player.IsGameMaster() && me.IsInRange(player, 10.0f, 30.0f, false))
{
pPassenger.CastSpell(player, TrialOfChampionSpells.SHIELD_BREAKER, true);
break;
}
}
}
}
uiShieldBreakerTimer = 7000;
}
else
uiShieldBreakerTimer -= uiDiff;
DoMeleeAttackIfReady();
}
InstanceScript instance;
uint uiChargeTimer;
uint uiShieldBreakerTimer;
uint uiBuffTimer;
uint uiWaypointPath;
}
abstract class boss_basic_toc5AI : ScriptedAI
{
public boss_basic_toc5AI(Creature creature) : base(creature)
{
Initialize();
instance = creature.GetInstanceScript();
bDone = false;
bHome = false;
uiPhase = 0;
uiPhaseTimer = 0;
me.SetReactState(ReactStates.Passive);
// THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.ImmuneToPc);
}
public abstract void Initialize();
public override void Reset()
{
Initialize();
}
public override void JustReachedHome()
{
base.JustReachedHome();
if (!bHome)
return;
uiPhaseTimer = 15000;
uiPhase = 1;
bHome = false;
}
public override void JustDied(Unit killer)
{
instance.SetData((uint)Data.BOSS_GRAND_CHAMPIONS, (uint)EncounterState.Done);
}
public override void UpdateAI(uint diff)
{
if (!bDone && GrandChampionsOutVehicle(me))
{
bDone = true;
if (me.GetGUID() == instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_1))
me.SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f);
else if (me.GetGUID() == instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_2))
me.SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f);
else if (me.GetGUID() == instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_3))
me.SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f);
EnterEvadeMode();
bHome = true;
}
if (uiPhaseTimer <= diff)
{
if (uiPhase == 1)
{
AggroAllPlayers(me);
uiPhase = 0;
}
}
else
uiPhaseTimer -= diff;
}
public bool InVehicle()
{
return !me.m_movementInfo.transport.guid.IsEmpty();
}
void AggroAllPlayers(Creature temp)
{
var PlList = temp.GetMap().GetPlayers();
if (PlList.Empty())
return;
foreach (var player in PlList)
{
if (player)
{
if (player.IsGameMaster())
continue;
if (player.IsAlive())
{
temp.RemoveFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.ImmuneToPc);
temp.SetReactState(ReactStates.Aggressive);
temp.SetInCombatWith(player);
player.SetInCombatWith(temp);
temp.AddThreat(player, 0.0f);
}
}
}
}
bool GrandChampionsOutVehicle(Creature me)
{
InstanceScript instance = me.GetInstanceScript();
if (instance == null)
return false;
Creature pGrandChampion1 = ObjectAccessor.GetCreature(me, instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_1));
Creature pGrandChampion2 = ObjectAccessor.GetCreature(me, instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_2));
Creature pGrandChampion3 = ObjectAccessor.GetCreature(me, instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_3));
if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3)
{
if (pGrandChampion1.m_movementInfo.transport.guid.IsEmpty() &&
pGrandChampion2.m_movementInfo.transport.guid.IsEmpty() &&
pGrandChampion3.m_movementInfo.transport.guid.IsEmpty())
return true;
}
return false;
}
public TaskScheduler NonCombatEvents = new TaskScheduler();
public InstanceScript instance;
public byte uiPhase;
public uint uiPhaseTimer;
bool bDone;
public bool bHome;
}
[Script]
// Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior
class boss_warrior_toc5 : boss_basic_toc5AI
{
public boss_warrior_toc5(Creature creature) : base(creature) { }
public override void Initialize()
{
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(20), task =>
{
DoCastVictim(TrialOfChampionSpells.BLADESTORM);
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(20));
});
_scheduler.Schedule(TimeSpan.FromSeconds(7), task =>
{
var players = me.GetMap().GetPlayers();
if (!players.Empty())
{
foreach (var player in players)
{
if (player && !player.IsGameMaster() && me.IsInRange(player, 8.0f, 25.0f, false))
{
DoResetThreat();
me.AddThreat(player, 5.0f);
DoCast(player, TrialOfChampionSpells.INTERCEPT);
break;
}
}
}
task.Repeat(TimeSpan.FromSeconds(7));
});
_scheduler.Schedule(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(12), task =>
{
DoCastVictim(TrialOfChampionSpells.MORTAL_STRIKE);
task.Repeat(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(12));
});
}
public override void UpdateAI(uint diff)
{
base.UpdateAI(diff);
if (!UpdateVictim() || InVehicle())
return;
_scheduler.Update(diff);
DoMeleeAttackIfReady();
}
}
[Script]
// Ambrose Boltspark && Eressea Dawnsinger || Mage
class boss_mage_toc5 : boss_basic_toc5AI
{
public boss_mage_toc5(Creature creature) : base(creature) { }
public override void Initialize()
{
_scheduler.Schedule(TimeSpan.FromSeconds(5), task =>
{
DoCastVictim(TrialOfChampionSpells.FIREBALL);
task.Repeat(TimeSpan.FromSeconds(5));
});
_scheduler.Schedule(TimeSpan.FromSeconds(8), task =>
{
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
if (target)
DoCast(target, TrialOfChampionSpells.POLYMORPH);
task.Repeat(TimeSpan.FromSeconds(8));
});
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
{
DoCastAOE(TrialOfChampionSpells.BLAST_WAVE, false);
task.Repeat(TimeSpan.FromSeconds(13));
});
_scheduler.Schedule(TimeSpan.FromSeconds(22), task =>
{
me.InterruptNonMeleeSpells(true);
DoCast(me, TrialOfChampionSpells.HASTE);
task.Repeat(TimeSpan.FromSeconds(22));
});
}
public override void UpdateAI(uint diff)
{
base.UpdateAI(diff);
if (!UpdateVictim() || InVehicle())
return;
_scheduler.Update(diff);
DoMeleeAttackIfReady();
}
}
[Script]
// Colosos && Runok Wildmane || Shaman
class boss_shaman_toc5 : boss_basic_toc5AI
{
public boss_shaman_toc5(Creature creature) : base(creature) { }
public override void Initialize()
{
_scheduler.Schedule(TimeSpan.FromSeconds(16), task =>
{
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
if (target)
DoCast(target, TrialOfChampionSpells.CHAIN_LIGHTNING);
task.Repeat(TimeSpan.FromSeconds(16));
});
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
{
bool bChance = RandomHelper.randChance(50);
if (!bChance)
{
Unit pFriend = DoSelectLowestHpFriendly(40);
if (pFriend)
DoCast(pFriend, TrialOfChampionSpells.HEALING_WAVE);
}
else
DoCast(me, TrialOfChampionSpells.HEALING_WAVE);
task.Repeat(TimeSpan.FromSeconds(12));
});
_scheduler.Schedule(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35), task =>
{
DoCast(me, TrialOfChampionSpells.EARTH_SHIELD);
task.Repeat(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35));
});
_scheduler.Schedule(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(25), task =>
{
DoCastVictim(TrialOfChampionSpells.HEX_OF_MENDING, true);
task.Repeat(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(25));
});
}
public override void EnterCombat(Unit who)
{
DoCast(me, TrialOfChampionSpells.EARTH_SHIELD);
DoCast(who, TrialOfChampionSpells.HEX_OF_MENDING);
}
public override void UpdateAI(uint diff)
{
base.UpdateAI(diff);
if (!UpdateVictim() || InVehicle())
return;
_scheduler.Update(diff);
DoMeleeAttackIfReady();
}
}
[Script]
// Jaelyne Evensong && Zul'tore || Hunter
class boss_hunter_toc5 : boss_basic_toc5AI
{
public boss_hunter_toc5(Creature creature) : base(creature) { }
public override void Initialize()
{
_scheduler.Schedule(TimeSpan.FromSeconds(7), task =>
{
DoCastAOE(TrialOfChampionSpells.LIGHTNING_ARROWS, false);
task.Repeat(TimeSpan.FromSeconds(7));
});
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
{
ObjectGuid uiTargetGUID = ObjectGuid.Empty;
Unit target = SelectTarget(SelectAggroTarget.Farthest, 0, 30.0f);
if (target)
{
uiTargetGUID = target.GetGUID();
DoCast(target, TrialOfChampionSpells.SHOOT);
}
bool bShoot = true;
task.Repeat(TimeSpan.FromSeconds(12));
task.Schedule(TimeSpan.FromSeconds(3), task1 =>
{
if (bShoot)
{
me.InterruptNonMeleeSpells(true);
Unit target1 = Global.ObjAccessor.GetUnit(me, uiTargetGUID);
if (target1 && me.IsInRange(target1, 5.0f, 30.0f, false))
{
DoCast(target1, TrialOfChampionSpells.MULTI_SHOT);
}
else
{
var players = me.GetMap().GetPlayers();
if (!players.Empty())
{
foreach (var player in players)
{
if (player && !player.IsGameMaster() && me.IsInRange(player, 5.0f, 30.0f, false))
{
DoCast(player, TrialOfChampionSpells.MULTI_SHOT);
break;
}
}
}
}
bShoot = false;
}
});
});
}
public override void UpdateAI(uint diff)
{
base.UpdateAI(diff);
if (!UpdateVictim() || InVehicle())
return;
_scheduler.Update(diff);
DoMeleeAttackIfReady();
}
}
[Script]
// Lana Stouthammer Evensong && Deathstalker Visceri || Rouge
class boss_rouge_toc5 : boss_basic_toc5AI
{
public boss_rouge_toc5(Creature creature) : base(creature) { }
public override void Initialize()
{
_scheduler.Schedule(TimeSpan.FromSeconds(8), task =>
{
DoCastVictim(TrialOfChampionSpells.EVISCERATE);
task.Repeat(TimeSpan.FromSeconds(8));
});
_scheduler.Schedule(TimeSpan.FromSeconds(14), task =>
{
DoCastAOE(TrialOfChampionSpells.FAN_OF_KNIVES, false);
task.Repeat(TimeSpan.FromSeconds(14));
});
_scheduler.Schedule(TimeSpan.FromSeconds(19), task =>
{
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
if (target)
DoCast(target, TrialOfChampionSpells.POISON_BOTTLE);
task.Repeat(TimeSpan.FromSeconds(19));
});
}
public override void UpdateAI(uint diff)
{
base.UpdateAI(diff);
if (!UpdateVictim() || !me.m_movementInfo.transport.guid.IsEmpty())
return;
_scheduler.Update(diff);
DoMeleeAttackIfReady();
}
}
}