202 lines
4.5 KiB
C#
202 lines
4.5 KiB
C#
#region References
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
using Server.Items;
|
|
using Server.Spells;
|
|
using Server.Spells.Ninjitsu;
|
|
#endregion
|
|
|
|
namespace Server.Mobiles
|
|
{
|
|
public class NinjaAI : MeleeAI
|
|
{
|
|
private DateTime m_NextCastTime;
|
|
private DateTime m_NextRanged;
|
|
|
|
public NinjaAI(BaseCreature bc)
|
|
: base(bc)
|
|
{
|
|
m_NextCastTime = DateTime.UtcNow;
|
|
}
|
|
|
|
private void TryPerformHide()
|
|
{
|
|
if (!m_Mobile.Alive || m_Mobile.Deleted)
|
|
return;
|
|
|
|
if (!m_Mobile.Hidden && Core.TickCount - m_Mobile.NextSkillTime >= 0)
|
|
{
|
|
var chance = 0.05;
|
|
|
|
if (m_Mobile.Hits < 20)
|
|
chance = 0.10;
|
|
|
|
if (m_Mobile.Poisoned)
|
|
chance = 0.01;
|
|
|
|
if (Utility.RandomDouble() < chance)
|
|
HideSelf();
|
|
}
|
|
}
|
|
|
|
private void HideSelf()
|
|
{
|
|
Effects.SendLocationParticles(
|
|
EffectItem.Create(m_Mobile.Location, m_Mobile.Map, EffectItem.DefaultDuration),
|
|
0x3728,
|
|
10,
|
|
10,
|
|
2023);
|
|
|
|
m_Mobile.PlaySound(0x22F);
|
|
m_Mobile.Hidden = true;
|
|
|
|
m_Mobile.UseSkill(SkillName.Stealth);
|
|
}
|
|
|
|
public virtual SpecialMove GetHiddenSpecialMove()
|
|
{
|
|
var skill = (int)m_Mobile.Skills[SkillName.Ninjitsu].Value;
|
|
|
|
if (skill < 40)
|
|
return null;
|
|
|
|
if (skill >= 60)
|
|
{
|
|
//return .5 > Utility.RandomDouble() ? new SupriseAttack() : new Backstab();
|
|
return .5 > Utility.RandomDouble() ? SpellRegistry.GetSpecialMove(504) : SpellRegistry.GetSpecialMove(505);
|
|
}
|
|
|
|
return SpellRegistry.GetSpecialMove(505); //new Backstab();
|
|
}
|
|
|
|
public virtual SpecialMove GetSpecialMove()
|
|
{
|
|
var skill = (int)m_Mobile.Skills[SkillName.Ninjitsu].Value;
|
|
|
|
if (skill < 40)
|
|
return null;
|
|
|
|
var avail = 1;
|
|
|
|
if (skill >= 85)
|
|
avail = 3;
|
|
else if (skill >= 80)
|
|
avail = 2;
|
|
|
|
switch (Utility.Random(avail))
|
|
{
|
|
case 0:
|
|
return SpellRegistry.GetSpecialMove(500); //new FocusAttack();
|
|
case 1:
|
|
return SpellRegistry.GetSpecialMove(503); //new KiAttack();
|
|
case 2:
|
|
return SpellRegistry.GetSpecialMove(501); //new DeathStrike();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void DoRangedAttack()
|
|
{
|
|
var c = m_Mobile.Combatant as Mobile;
|
|
|
|
if (c == null)
|
|
return;
|
|
|
|
var list = new List<INinjaWeapon>();
|
|
var d = (int)m_Mobile.GetDistanceToSqrt(c.Location);
|
|
|
|
foreach (var item in m_Mobile.Items)
|
|
if (item is INinjaWeapon && ((INinjaWeapon)item).UsesRemaining > 0 && d >= ((INinjaWeapon)item).WeaponMinRange &&
|
|
d <= ((INinjaWeapon)item).WeaponMaxRange)
|
|
list.Add(item as INinjaWeapon);
|
|
|
|
if (m_Mobile.Backpack != null)
|
|
{
|
|
foreach (var item in m_Mobile.Backpack.Items)
|
|
if (item is INinjaWeapon && ((INinjaWeapon)item).UsesRemaining > 0 && d >= ((INinjaWeapon)item).WeaponMinRange &&
|
|
d <= ((INinjaWeapon)item).WeaponMaxRange)
|
|
list.Add(item as INinjaWeapon);
|
|
}
|
|
|
|
if (list.Count > 0)
|
|
{
|
|
var toUse = list[Utility.Random(list.Count)];
|
|
|
|
if (toUse != null)
|
|
NinjaWeapon.Shoot(m_Mobile, c, toUse);
|
|
}
|
|
|
|
ColUtility.Free(list);
|
|
|
|
m_NextRanged = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 120));
|
|
}
|
|
|
|
public override bool DoActionWander()
|
|
{
|
|
base.DoActionWander();
|
|
|
|
if (m_Mobile.Combatant == null)
|
|
TryPerformHide();
|
|
|
|
return true;
|
|
}
|
|
|
|
public override bool DoActionCombat()
|
|
{
|
|
base.DoActionCombat();
|
|
|
|
if (m_Mobile.Combatant == null)
|
|
return true;
|
|
|
|
var special = SpecialMove.GetCurrentMove(m_Mobile);
|
|
|
|
if (special == null && m_NextCastTime < DateTime.UtcNow && 0.05 > Utility.RandomDouble())
|
|
{
|
|
if (0.05 > Utility.RandomDouble())
|
|
{
|
|
new MirrorImage(m_Mobile, null).Cast();
|
|
}
|
|
else
|
|
{
|
|
if (m_Mobile.Hidden)
|
|
special = GetHiddenSpecialMove();
|
|
else
|
|
special = GetSpecialMove();
|
|
|
|
if (special != null)
|
|
{
|
|
SpecialMove.SetCurrentMove(m_Mobile, special);
|
|
m_NextCastTime = DateTime.UtcNow + GetCastDelay();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_NextRanged < DateTime.UtcNow && 0.08 > Utility.RandomDouble())
|
|
DoRangedAttack();
|
|
|
|
return true;
|
|
}
|
|
|
|
public override bool DoActionFlee()
|
|
{
|
|
base.DoActionFlee();
|
|
TryPerformHide();
|
|
return true;
|
|
}
|
|
|
|
public TimeSpan GetCastDelay()
|
|
{
|
|
var skill = (int)m_Mobile.Skills[SkillName.Ninjitsu].Value;
|
|
|
|
if (skill >= 85)
|
|
return TimeSpan.FromSeconds(15);
|
|
if (skill > 40)
|
|
return TimeSpan.FromSeconds(30);
|
|
|
|
return TimeSpan.FromSeconds(45);
|
|
}
|
|
}
|
|
} |