199 lines
4.7 KiB
C#
199 lines
4.7 KiB
C#
using ModernUO.Serialization;
|
|
using Server.Items;
|
|
|
|
namespace Server.Mobiles;
|
|
|
|
[SerializationGenerator(0, false)]
|
|
public partial class ArcherGuard : BaseGuard
|
|
{
|
|
private bool _shooting;
|
|
|
|
[Constructible]
|
|
public ArcherGuard(Mobile target = null) : base(target)
|
|
{
|
|
InitStats(100, 125, 25);
|
|
SpeechHue = Utility.RandomDyedHue();
|
|
Hue = Race.Human.RandomSkinHue();
|
|
|
|
if (Female = Utility.RandomBool())
|
|
{
|
|
Body = 0x191;
|
|
Name = NameList.RandomName("female");
|
|
}
|
|
else
|
|
{
|
|
Body = 0x190;
|
|
Name = NameList.RandomName("male");
|
|
}
|
|
|
|
new Horse().Rider = this;
|
|
|
|
AddItem(new StuddedChest());
|
|
AddItem(new StuddedArms());
|
|
AddItem(new StuddedGloves());
|
|
AddItem(new StuddedGorget());
|
|
AddItem(new StuddedLegs());
|
|
AddItem(new Boots());
|
|
AddItem(new SkullCap());
|
|
|
|
var bow = new Bow();
|
|
|
|
bow.Movable = false;
|
|
bow.Crafter = Name;
|
|
bow.Quality = WeaponQuality.Exceptional;
|
|
|
|
AddItem(bow);
|
|
|
|
var pack = new Backpack
|
|
{
|
|
Movable = false
|
|
};
|
|
|
|
pack.DropItem(new Arrow(250)
|
|
{
|
|
LootType = LootType.Newbied
|
|
});
|
|
pack.DropItem(new Gold(10, 25));
|
|
|
|
AddItem(pack);
|
|
|
|
Skills.Anatomy.Base = 120.0;
|
|
Skills.Tactics.Base = 120.0;
|
|
Skills.Archery.Base = 120.0;
|
|
Skills.MagicResist.Base = 120.0;
|
|
Skills.DetectHidden.Base = 100.0;
|
|
|
|
NextCombatTime = Core.TickCount + 500;
|
|
Focus = target;
|
|
}
|
|
|
|
[SerializableProperty(0)]
|
|
[CommandProperty(AccessLevel.GameMaster)]
|
|
public override Mobile Focus
|
|
{
|
|
get => _focus;
|
|
set
|
|
{
|
|
if (Deleted)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var oldFocus = _focus;
|
|
|
|
if (oldFocus != value)
|
|
{
|
|
_focus = value;
|
|
|
|
if (value != null)
|
|
{
|
|
AggressiveAction(value);
|
|
}
|
|
|
|
Combatant = value;
|
|
|
|
if (oldFocus?.Alive == false)
|
|
{
|
|
Say("Thou hast suffered thy punishment, scoundrel.");
|
|
}
|
|
|
|
if (value != null)
|
|
{
|
|
Say(500131); // Thou wilt regret thine actions, swine!
|
|
}
|
|
|
|
AttackTimer = null;
|
|
IdleTimer = null;
|
|
|
|
if (_focus != null)
|
|
{
|
|
AttackTimer = new GuardAttackTimer(this);
|
|
AttackTimer.Start();
|
|
}
|
|
else
|
|
{
|
|
IdleTimer = new GuardIdleTimer(this);
|
|
}
|
|
}
|
|
else if (_focus == null && IdleTimer == null && Spawner != null)
|
|
{
|
|
IdleTimer = new GuardIdleTimer(this);
|
|
}
|
|
|
|
this.MarkDirty();
|
|
}
|
|
}
|
|
|
|
public override bool OnBeforeDeath()
|
|
{
|
|
if (_focus?.Alive == true)
|
|
{
|
|
new GuardAvengeTimer(_focus).Start(); // If a guard dies, three more guards will spawn
|
|
}
|
|
|
|
return base.OnBeforeDeath();
|
|
}
|
|
|
|
public override void NonLethalAttack(Mobile target)
|
|
{
|
|
if (!InRange(target, 20))
|
|
{
|
|
_shooting = false;
|
|
Focus = null;
|
|
return;
|
|
}
|
|
|
|
if (!InLOS(target))
|
|
{
|
|
_shooting = false;
|
|
TeleportTo(this, target.Location);
|
|
return;
|
|
}
|
|
|
|
if (!CanSee(target))
|
|
{
|
|
_shooting = false;
|
|
|
|
if (InRange(target, 2))
|
|
{
|
|
if (UseSkill(SkillName.DetectHidden))
|
|
{
|
|
Say("Reveal!");
|
|
}
|
|
}
|
|
else if (!Move(GetDirectionTo(target) | Direction.Running) && OutOfMaxDistance(target))
|
|
{
|
|
TeleportTo(this, target.Location);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (_shooting)
|
|
{
|
|
if (TimeToSpare() || OutOfMaxDistance(target))
|
|
{
|
|
_shooting = false;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (InRange(target, 1) && !Move(GetDirectionTo(target) - 4 | Direction.Running) && OutOfMaxDistance(target))
|
|
{
|
|
TeleportTo(this, target.Location);
|
|
return;
|
|
}
|
|
|
|
if (InMinDistance(target))
|
|
{
|
|
_shooting = true;
|
|
}
|
|
}
|
|
|
|
private bool TimeToSpare() => NextCombatTime - Core.TickCount > 1000;
|
|
|
|
private bool OutOfMaxDistance(IPoint2D target) => !InRange(target, Weapon.MaxRange);
|
|
|
|
private bool InMinDistance(IPoint2D target) => InRange(target, 4);
|
|
}
|