modernuo/Projects/UOContent/Items/Addons/TrainingDummies.cs
Kamron Batman 936000ecf7
feat: Adds SerializedCommandProperty (#1249)
## Breaking Change
* Removes `SerializableFieldAttrAttribute` in favor of `SerializedPropertyAttr`.

## Important Change
* Adds `SerializedCommandProperty`

Example:
```cs
    [InvalidateProperties]
    [SerializableField(0)]
    [SerializedCommandProperty(AccessLevel.GameMaster)]
    private Mobile _completedBy;
```
2022-11-14 18:24:33 -08:00

182 lines
4.9 KiB
C#

using System;
using ModernUO.Serialization;
namespace Server.Items
{
[SerializationGenerator(0, false)]
[Flippable(0x1070, 0x1074)]
public partial class TrainingDummy : AddonComponent
{
private Timer m_Timer;
[SerializableField(0)]
[SerializedCommandProperty(AccessLevel.GameMaster)]
private double _minSkill;
[SerializableField(1)]
[SerializedCommandProperty(AccessLevel.GameMaster)]
private double _maxSkill;
[Constructible]
public TrainingDummy(int itemID = 0x1074) : base(itemID)
{
MinSkill = -25.0;
MaxSkill = +25.0;
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Swinging => m_Timer != null;
public void UpdateItemID()
{
var baseItemID = ItemID / 2 * 2;
ItemID = baseItemID + (Swinging ? 1 : 0);
}
public void BeginSwing()
{
m_Timer?.Stop();
m_Timer = new InternalTimer(this);
m_Timer.Start();
}
public void EndSwing()
{
m_Timer?.Stop();
m_Timer = null;
UpdateItemID();
}
public void OnHit()
{
UpdateItemID();
Effects.PlaySound(GetWorldLocation(), Map, Utility.RandomList(0x3A4, 0x3A6, 0x3A9, 0x3AE, 0x3B4, 0x3B6));
}
public void Use(Mobile from, BaseWeapon weapon)
{
BeginSwing();
from.Direction = from.GetDirectionTo(GetWorldLocation());
weapon.PlaySwingAnimation(from);
from.CheckSkill(weapon.Skill, MinSkill, MaxSkill);
}
public override void OnDoubleClick(Mobile from)
{
var weapon = from.Weapon as BaseWeapon;
if (weapon is BaseRanged)
{
SendLocalizedMessageTo(from, 501822); // You can't practice ranged weapons on this.
}
else if (weapon == null || !from.InRange(GetWorldLocation(), weapon.MaxRange))
{
SendLocalizedMessageTo(from, 501816); // You are too far away to do that.
}
else if (Swinging)
{
SendLocalizedMessageTo(from, 501815); // You have to wait until it stops swinging.
}
else if (from.Skills[weapon.Skill].Base >= MaxSkill)
{
SendLocalizedMessageTo(
from,
501828
); // Your skill cannot improve any further by simply practicing with a dummy.
}
else if (from.Mounted)
{
SendLocalizedMessageTo(from, 501829); // You can't practice on this while on a mount.
}
else
{
Use(from, weapon);
}
}
[AfterDeserialization]
private void AfterDeserialization()
{
UpdateItemID();
}
private class InternalTimer : Timer
{
private readonly TrainingDummy m_Dummy;
private bool m_Delay = true;
public InternalTimer(TrainingDummy dummy) : base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(2.75))
{
m_Dummy = dummy;
}
protected override void OnTick()
{
if (m_Delay)
{
m_Dummy.OnHit();
}
else
{
m_Dummy.EndSwing();
}
m_Delay = !m_Delay;
}
}
}
[SerializationGenerator(0, false)]
public partial class TrainingDummyEastAddon : BaseAddon
{
[Constructible]
public TrainingDummyEastAddon()
{
AddComponent(new TrainingDummy(), 0, 0, 0);
}
public override BaseAddonDeed Deed => new TrainingDummyEastDeed();
}
[SerializationGenerator(0, false)]
public partial class TrainingDummyEastDeed : BaseAddonDeed
{
[Constructible]
public TrainingDummyEastDeed()
{
}
public override BaseAddon Addon => new TrainingDummyEastAddon();
public override int LabelNumber => 1044335; // training dummy (east)
}
[SerializationGenerator(0, false)]
public partial class TrainingDummySouthAddon : BaseAddon
{
[Constructible]
public TrainingDummySouthAddon()
{
AddComponent(new TrainingDummy(0x1070), 0, 0, 0);
}
public override BaseAddonDeed Deed => new TrainingDummySouthDeed();
}
[SerializationGenerator(0, false)]
public partial class TrainingDummySouthDeed : BaseAddonDeed
{
[Constructible]
public TrainingDummySouthDeed()
{
}
public override BaseAddon Addon => new TrainingDummySouthAddon();
public override int LabelNumber => 1044336; // training dummy (south)
}
}