using System.Drawing;
using Server.MirDatabase;
using Server.MirEnvir;
using S = ServerPackets;
namespace Server.MirObjects.Monsters
{
///
/// Attack1 - Basic melee attack
/// Attack2 - Basic melee attack alt
/// Attack3 - Charge up then Spin attack (between 5 and 10 damage multiplier) twice
/// Attack4 - Charge up then AOE rock fall (between 5 and 10 damage multiplier)
/// Attack5 - Immunity shield, Summons slave (Under 10% HP)
/// AttackRange1 - Teleport
/// AttackRange2 - Hammer smash AOE in front
/// AttackRange3 - Summon rock spikes (Between 10% - 30% HP)
/// Summons Rock Slaves
///
public class HornedCommander : MonsterObject
{
private bool _StartAdvanced;
private bool _Immune;
private Point _MapCentre
{
get
{
if (CurrentMap == null) return Point.Empty;
//Should be spawned on "HY01_morae_chon". Change me to correct centre if its spawned on another map.
return new Point(26, 32);
}
}
//Phase 0
private readonly byte _BoulderHealthPercent = 80;
private bool _CalledBoulders, _StartedBoulderWalk;
//Phase 1
private readonly byte _RockHealthPercent = 50;
private bool _CalledRockSpikes;
private long _RockSpikeTime;
private readonly Point[,] _RockSpikeArea = new Point[7, 7];
private readonly List _RockSpikeEffects = new List();
//Phase 2
private readonly byte _ShieldHealthPercent = 10;
private bool _CalledShield;
private readonly byte _ShieldSeconds = 20;
protected internal HornedCommander(MonsterInfo info)
: base(info)
{
}
public override bool IsAttackTarget(MonsterObject attacker)
{
return !_Immune && base.IsAttackTarget(attacker);
}
public override bool IsAttackTarget(HumanObject attacker)
{
return !_Immune && base.IsAttackTarget(attacker);
}
protected override void ProcessAI()
{
if ((HealthPercent < _BoulderHealthPercent || _StartedBoulderWalk) && !_CalledBoulders)
{
_StartedBoulderWalk = true;
SpawnBoulder();
}
if (_Immune) return;
if (HealthPercent < _ShieldHealthPercent && !_CalledShield)
{
KillRockSpikes();
_CalledShield = true;
_Immune = true;
Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 4, Level = _ShieldSeconds });
AddBuff(BuffType.HornedCommanderShield, this, Settings.Second * _ShieldSeconds, new Stats());
SpawnSlave();
return;
}
if (HealthPercent < _RockHealthPercent && HealthPercent >= _ShieldHealthPercent)
{
if (!_CalledRockSpikes)
{
SetupRockSpike();
_CalledRockSpikes = true;
Broadcast(new S.ObjectRangeAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 2 });
}
}
if (_CalledRockSpikes && Envir.Time > _RockSpikeTime)
{
var spawned = SpawnRockSpikes();
_RockSpikeTime = Envir.Time + 5000;
if (!spawned)
{
_RockSpikeTime = long.MaxValue;
}
}
if (HealthPercent < 100 && !_StartAdvanced)
{
_StartAdvanced = true;
}
else if (HealthPercent == 100 && _StartAdvanced)
{
Reset();
}
base.ProcessAI();
}
private void Reset()
{
_StartAdvanced = false;
_StartedBoulderWalk = false;
_CalledBoulders = false;
_CalledRockSpikes = false;
_CalledShield = false;
_RockSpikeTime = 0;
KillRockSpikes();
KillSlaves();
}
protected override void ProcessBuffEnd(Buff buff)
{
if (buff.Type == BuffType.HornedCommanderShield)
{
_Immune = false;
AttackTime = Envir.Time + AttackSpeed;
ActionTime = Envir.Time + 300;
}
}
protected override void ProcessTarget()
{
if (Target == null || !CanAttack) return;
if (InAttackRange())
{
Attack();
if (Target != null && Target.Dead)
{
FindTarget();
}
return;
}
if (Envir.Time < ShockTime)
{
Target = null;
return;
}
MoveTo(Target.CurrentLocation);
}
protected override void Attack()
{
if (!Target.IsAttackTarget(this))
{
Target = null;
return;
}
AttackTime = Envir.Time + AttackSpeed;
ShockTime = 0;
Direction = Functions.DirectionFromPoint(CurrentLocation, Target.CurrentLocation);
//Charge-Up AOE Rock Fall
if (_StartAdvanced && Envir.Random.Next(20) == 0)
{
byte rockFallLoops = (byte)Envir.Random.Next(5, 10);
int rockFallDuration = rockFallLoops * 500;
_Immune = true;
ActionTime = Envir.Time + (rockFallDuration) + 500;
AttackTime = Envir.Time + (rockFallDuration) + 500 + AttackSpeed;
Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 3, Level = rockFallLoops });
var front = Functions.PointMove(CurrentLocation, Direction, 2);
MassSpawnRockFall(front, rockFallDuration);
int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]) * rockFallLoops;
DelayedAction action = new DelayedAction(DelayedType.RangeDamage, Envir.Time + (rockFallDuration) + 500, Target, damage, DefenceType.AC, 5);
ActionList.Add(action);
return;
}
//Charge-Up Spin Hit
if (_StartAdvanced && Envir.Random.Next(15) == 0)
{
byte spinLoops = (byte)Envir.Random.Next(5, 10);
int spinDuration = spinLoops * 700;
_Immune = true;
ActionTime = Envir.Time + spinDuration + 1500;
AttackTime = Envir.Time + spinDuration + 1500 + AttackSpeed;
Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 2, Level = spinLoops });
int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]) * spinLoops;
DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + spinDuration + 500, Target, damage, DefenceType.AC, true);
ActionList.Add(action);
action = new DelayedAction(DelayedType.Damage, Envir.Time + spinDuration + 1000, Target, damage, DefenceType.AC, true);
ActionList.Add(action);
return;
}
//Hammer Smash
if (_StartAdvanced && Envir.Random.Next(10) == 0)
{
Broadcast(new S.ObjectRangeAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 1 });
int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]);
if (damage == 0) return;
DelayedAction action = new DelayedAction(DelayedType.RangeDamage, Envir.Time + 300, Target, damage, DefenceType.AC, 3);
ActionList.Add(action);
return;
}
//Teleport
if (_StartAdvanced && Envir.Random.Next(10) == 0)
{
Broadcast(new S.ObjectRangeAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 0 });
DelayedAction action = new DelayedAction(DelayedType.RangeDamage, Envir.Time + 300);
ActionList.Add(action);
return;
}
//Normal Attacks
if (Envir.Random.Next(2) == 0)
{
Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 0 });
int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]);
if (damage == 0) return;
DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 500, Target, damage, DefenceType.ACAgility, false);
ActionList.Add(action);
}
else
{
Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 1 });
int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]);
if (damage == 0) return;
DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 500, Target, damage, DefenceType.ACAgility, false);
ActionList.Add(action);
}
}
protected override void CompleteAttack(IList