diff --git a/Projects/UOContent/Mobiles/Guards/ArcherGuard.cs b/Projects/UOContent/Mobiles/Guards/ArcherGuard.cs
index e1719b94b..91797cc47 100644
--- a/Projects/UOContent/Mobiles/Guards/ArcherGuard.cs
+++ b/Projects/UOContent/Mobiles/Guards/ArcherGuard.cs
@@ -1,4 +1,3 @@
-using System;
using ModernUO.Serialization;
using Server.Items;
@@ -7,17 +6,13 @@ namespace Server.Mobiles;
[SerializationGenerator(0, false)]
public partial class ArcherGuard : BaseGuard
{
- private Timer _attackTimer;
- private Timer _idleTimer;
+ private bool _shooting;
[Constructible]
public ArcherGuard(Mobile target = null) : base(target)
{
InitStats(100, 125, 25);
- Title = "the guard";
-
SpeechHue = Utility.RandomDyedHue();
-
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
@@ -107,34 +102,22 @@ public partial class ArcherGuard : BaseGuard
Say(500131); // Thou wilt regret thine actions, swine!
}
- if (_attackTimer != null)
- {
- _attackTimer.Stop();
- _attackTimer = null;
- }
-
- if (_idleTimer != null)
- {
- _idleTimer.Stop();
- _idleTimer = null;
- }
+ AttackTimer = null;
+ IdleTimer = null;
if (_focus != null)
{
- _attackTimer = new AttackTimer(this);
- _attackTimer.Start();
- ((AttackTimer)_attackTimer).DoOnTick();
+ AttackTimer = new GuardAttackTimer(this);
+ AttackTimer.DoOnTick();
}
else
{
- _idleTimer = new IdleTimer(this);
- _idleTimer.Start();
+ IdleTimer = new GuardIdleTimer(this);
}
}
- else if (_focus == null && _idleTimer == null)
+ else if (_focus == null && IdleTimer == null && Spawner != null)
{
- _idleTimer = new IdleTimer(this);
- _idleTimer.Start();
+ IdleTimer = new GuardIdleTimer(this);
}
this.MarkDirty();
@@ -145,245 +128,72 @@ public partial class ArcherGuard : BaseGuard
{
if (_focus?.Alive == true)
{
- new AvengeTimer(_focus).Start(); // If a guard dies, three more guards will spawn
+ new GuardAvengeTimer(_focus).Start(); // If a guard dies, three more guards will spawn
}
return base.OnBeforeDeath();
}
- [AfterDeserialization]
- private void AfterDeserialization()
+ public override void NonLethalAttack(Mobile target)
{
- if (_focus != null)
+ if (!InRange(target, 20))
{
- _attackTimer = new AttackTimer(this);
- _attackTimer.Start();
- }
- else
- {
- _idleTimer = new IdleTimer(this);
- _idleTimer.Start();
- }
- }
-
- public override void OnAfterDelete()
- {
- if (_attackTimer != null)
- {
- _attackTimer.Stop();
- _attackTimer = null;
+ _shooting = false;
+ Focus = null;
+ return;
}
- if (_idleTimer != null)
+ if (!InLOS(target))
{
- _idleTimer.Stop();
- _idleTimer = null;
+ _shooting = false;
+ TeleportTo(this, target.Location);
+ return;
}
- base.OnAfterDelete();
- }
-
- private class AvengeTimer : Timer
- {
- private readonly Mobile m_Focus;
-
- // After 2.5 seconds, one guard will spawn every 1.0 second, three times
- public AvengeTimer(Mobile focus) : base(TimeSpan.FromSeconds(2.5), TimeSpan.FromSeconds(1.0), 3) =>
- m_Focus = focus;
-
- protected override void OnTick()
+ if (!CanSee(target))
{
- Spawn(m_Focus, m_Focus, 1, true);
- }
- }
+ _shooting = false;
- private class AttackTimer : Timer
- {
- private readonly ArcherGuard m_Owner;
- // private bool m_Shooting;
-
- public AttackTimer(ArcherGuard owner) : base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(0.1)) =>
- m_Owner = owner;
-
- public void DoOnTick()
- {
- OnTick();
- }
-
- protected override void OnTick()
- {
- if (m_Owner.Deleted)
+ if (InRange(target, 2))
{
- Stop();
- return;
- }
-
- m_Owner.Criminal = false;
- m_Owner.Kills = 0;
- m_Owner.Stam = m_Owner.StamMax;
-
- var target = m_Owner.Focus;
-
- if (target != null && (target.Deleted || !target.Alive || !m_Owner.CanBeHarmful(target)))
- {
- m_Owner.Focus = null;
- Stop();
- return;
- }
-
- if (m_Owner.Weapon is Fists)
- {
- m_Owner.Kill();
- Stop();
- return;
- }
-
- if (target != null && m_Owner.Combatant != target)
- {
- m_Owner.Combatant = target;
- }
-
- if (target == null)
- {
- Stop();
- }
- else
- {
- //
- TeleportTo(target);
- target.BoltEffect(0);
-
- if (target is BaseCreature creature)
+ if (UseSkill(SkillName.DetectHidden))
{
- creature.NoKillAwards = true;
+ Say("Reveal!");
}
-
- target.Damage(target.HitsMax, m_Owner);
- target.Kill(); // just in case, maybe Damage is overridden on some shard
-
- if (target.Corpse != null && !target.Player)
- {
- target.Corpse.Delete();
- }
-
- m_Owner.Focus = null;
- Stop();
- } //
-
- /*else if (!m_Owner.InRange( target, 20 ))
- {
- m_Shooting = false;
- m_Owner.Focus = null;
}
- else if (!m_Owner.InLOS( target ))
+ else if (!Move(GetDirectionTo(target) | Direction.Running) && OutOfMaxDistance(target))
{
- m_Shooting = false;
- TeleportTo( target );
+ TeleportTo(this, target.Location);
}
- else if (!m_Owner.CanSee( target ))
- {
- m_Shooting = false;
- if (!m_Owner.InRange( target, 2 ))
- {
- if (!m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running ) && OutOfMaxDistance( target ))
- TeleportTo( target );
- }
- else
- {
- if (!m_Owner.UseSkill( SkillName.DetectHidden ) && Utility.Random( 50 ) == 0)
- m_Owner.Say( "Reveal!" );
- }
- }
- else
- {
- if (m_Shooting && (TimeToSpare() || OutOfMaxDistance( target )))
- m_Shooting = false;
- else if (!m_Shooting && InMinDistance( target ))
- m_Shooting = true;
-
- if (!m_Shooting)
- {
- if (m_Owner.InRange( target, 1 ))
- {
- if (!m_Owner.Move( (Direction)(m_Owner.GetDirectionTo( target ) - 4) | Direction.Running ) && OutOfMaxDistance( target ))
- TeleportTo( target ); // Too close, move away
- }
- else if (!m_Owner.InRange( target, 2 ))
- {
- if (!m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running ) && OutOfMaxDistance( target ))
- TeleportTo( target );
- }
- }
- }*/
+ return;
}
- private bool TimeToSpare() => m_Owner.NextCombatTime - Core.TickCount > 1000;
-
- private bool OutOfMaxDistance(IPoint2D target) => !m_Owner.InRange(target, m_Owner.Weapon.MaxRange);
-
- private bool InMinDistance(IPoint2D target) => m_Owner.InRange(target, 4);
-
- private void TeleportTo(IEntity target)
+ if (_shooting)
{
- var from = m_Owner.Location;
- var to = target.Location;
+ if (TimeToSpare() || OutOfMaxDistance(target))
+ {
+ _shooting = false;
+ }
- m_Owner.Location = to;
+ return;
+ }
- Effects.SendLocationParticles(
- EffectItem.Create(from, m_Owner.Map, EffectItem.DefaultDuration),
- 0x3728,
- 10,
- 10,
- 2023
- );
- Effects.SendLocationParticles(
- EffectItem.Create(to, m_Owner.Map, EffectItem.DefaultDuration),
- 0x3728,
- 10,
- 10,
- 5023
- );
+ if (InRange(target, 1) && !Move(GetDirectionTo(target) - 4 | Direction.Running) && OutOfMaxDistance(target))
+ {
+ TeleportTo(this, target.Location);
+ return;
+ }
- m_Owner.PlaySound(0x1FE);
+ if (InMinDistance(target))
+ {
+ _shooting = true;
}
}
- private class IdleTimer : Timer
- {
- private readonly ArcherGuard m_Owner;
- private int m_Stage;
+ private bool TimeToSpare() => NextCombatTime - Core.TickCount > 1000;
- public IdleTimer(ArcherGuard owner) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.5)) =>
- m_Owner = owner;
+ private bool OutOfMaxDistance(IPoint2D target) => !InRange(target, Weapon.MaxRange);
- protected override void OnTick()
- {
- if (m_Owner.Deleted)
- {
- Stop();
- return;
- }
-
- if (m_Stage++ % 4 == 0 || !m_Owner.Move(m_Owner.Direction))
- {
- m_Owner.Direction = (Direction)Utility.Random(8);
- }
-
- if (m_Stage > 16)
- {
- Effects.SendLocationParticles(
- EffectItem.Create(m_Owner.Location, m_Owner.Map, EffectItem.DefaultDuration),
- 0x3728,
- 10,
- 10,
- 2023
- );
- m_Owner.PlaySound(0x1FE);
-
- m_Owner.Delete();
- }
- }
- }
+ private bool InMinDistance(IPoint2D target) => InRange(target, 4);
}
diff --git a/Projects/UOContent/Mobiles/Guards/BaseGuard.cs b/Projects/UOContent/Mobiles/Guards/BaseGuard.cs
index 25d302394..9d84e8caa 100644
--- a/Projects/UOContent/Mobiles/Guards/BaseGuard.cs
+++ b/Projects/UOContent/Mobiles/Guards/BaseGuard.cs
@@ -1,3 +1,4 @@
+using System;
using ModernUO.Serialization;
using Server.Items;
@@ -6,25 +7,12 @@ namespace Server.Mobiles;
[SerializationGenerator(0)]
public abstract partial class BaseGuard : Mobile
{
- public BaseGuard(Mobile target)
+ public static bool GuardsInstantKill { get; private set; }
+ public static void Configure()
{
- if (target != null)
- {
- Location = target.Location;
- Map = target.Map;
-
- Effects.SendLocationParticles(
- EffectItem.Create(Location, Map, EffectItem.DefaultDuration),
- 0x3728,
- 10,
- 10,
- 5023
- );
- }
+ GuardsInstantKill = ServerConfiguration.GetSetting("guards.instantKill", true);
}
- public abstract Mobile Focus { get; set; }
-
public static void Spawn(Mobile caller, Mobile target, int amount = 1, bool onlyAdditional = false)
{
if (target?.Deleted != false)
@@ -55,6 +43,85 @@ public abstract partial class BaseGuard : Mobile
}
}
+ public static void TeleportTo(Mobile source, Point3D to)
+ {
+ Effects.SendLocationParticles(
+ EffectItem.Create(source.Location, source.Map, EffectItem.DefaultDuration),
+ 0x3728,
+ 10,
+ 10,
+ 2023
+ );
+
+ source.Location = to;
+
+ Effects.SendLocationParticles(
+ EffectItem.Create(to, source.Map, EffectItem.DefaultDuration),
+ 0x3728,
+ 10,
+ 10,
+ 5023
+ );
+
+ source.PlaySound(0x1FE);
+ }
+
+
+ private GuardIdleTimer _idleTimer;
+ private GuardAttackTimer _attackTimer;
+
+ public BaseGuard(Mobile target)
+ {
+ Title = "the guard";
+
+ if (target != null)
+ {
+ Location = target.Location;
+ Map = target.Map;
+
+ Effects.SendLocationParticles(
+ EffectItem.Create(Location, Map, EffectItem.DefaultDuration),
+ 0x3728,
+ 10,
+ 10,
+ 5023
+ );
+
+ Focus = target;
+ }
+ }
+
+ protected GuardAttackTimer AttackTimer
+ {
+ get => _attackTimer;
+ set
+ {
+ _attackTimer?.Stop();
+ _attackTimer = value;
+ _attackTimer?.Start();
+ }
+ }
+
+ protected GuardIdleTimer IdleTimer
+ {
+ get => _idleTimer;
+ set
+ {
+ _idleTimer?.Stop();
+ _idleTimer = value;
+ _idleTimer?.Start();
+ }
+ }
+
+ public abstract Mobile Focus { get; set; }
+
+ public override void OnAfterDelete()
+ {
+ AttackTimer = null;
+ IdleTimer = null;
+ base.OnAfterDelete();
+ }
+
public override bool OnBeforeDeath()
{
Effects.SendLocationParticles(
@@ -66,9 +133,153 @@ public abstract partial class BaseGuard : Mobile
);
PlaySound(0x1FE);
-
Delete();
-
return false;
}
+
+ public abstract void NonLethalAttack(Mobile target);
+
+ [AfterDeserialization]
+ private void AfterDeserialization()
+ {
+ if (Focus != null)
+ {
+ AttackTimer = new GuardAttackTimer(this);
+ }
+ else
+ {
+ IdleTimer = new GuardIdleTimer(this);
+ }
+ }
+}
+
+public class GuardAvengeTimer : Timer
+{
+ private readonly Mobile _focus;
+
+ public GuardAvengeTimer(Mobile focus) : base(TimeSpan.FromSeconds(2.5), TimeSpan.FromSeconds(1.0), 3) =>
+ _focus = focus;
+
+ protected override void OnTick() => BaseGuard.Spawn(_focus, _focus, 1, true);
+}
+
+public class GuardIdleTimer : Timer
+{
+ private readonly BaseGuard _owner;
+ private int m_Stage;
+
+ public GuardIdleTimer(BaseGuard owner) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.5)) =>
+ _owner = owner;
+
+ protected override void OnTick()
+ {
+ if (_owner.Deleted)
+ {
+ Stop();
+ return;
+ }
+
+ if (m_Stage++ % 4 == 0 || !_owner.Move(_owner.Direction))
+ {
+ _owner.Direction = (Direction)Utility.Random(8);
+ }
+
+ if (m_Stage > 16)
+ {
+ Effects.SendLocationParticles(
+ EffectItem.Create(_owner.Location, _owner.Map, EffectItem.DefaultDuration),
+ 0x3728,
+ 10,
+ 10,
+ 2023
+ );
+ _owner.PlaySound(0x1FE);
+
+ if (_owner.Spawner == null)
+ {
+ _owner.Delete();
+ }
+ else
+ {
+ BaseGuard.TeleportTo(_owner, _owner.Spawner.HomeLocation);
+ }
+ }
+ }
+}
+
+public class GuardAttackTimer : Timer
+{
+ private readonly BaseGuard _owner;
+
+ public GuardAttackTimer(BaseGuard owner) : base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(0.1)) =>
+ _owner = owner;
+
+ public void DoOnTick()
+ {
+ OnTick();
+ }
+
+ protected override void OnTick()
+ {
+ if (_owner.Deleted)
+ {
+ Stop();
+ return;
+ }
+
+ _owner.Criminal = false;
+ _owner.Kills = 0;
+ _owner.Stam = _owner.StamMax;
+
+ var target = _owner.Focus;
+
+ if (target != null && (target.Deleted || !target.Alive || !_owner.CanBeHarmful(target)))
+ {
+ _owner.Focus = null;
+ Stop();
+ return;
+ }
+
+ if (_owner.Weapon is Fists)
+ {
+ _owner.Kill();
+ Stop();
+ return;
+ }
+
+ if (target != null && _owner.Combatant != target)
+ {
+ _owner.Combatant = target;
+ }
+
+ if (target == null)
+ {
+ Stop();
+ }
+ else if (BaseGuard.GuardsInstantKill)
+ {
+ BaseGuard.TeleportTo(_owner, target.Location);
+ target.BoltEffect(0);
+
+ if (target is BaseCreature creature)
+ {
+ creature.NoKillAwards = true;
+ }
+
+ target.Damage(target.HitsMax, _owner);
+ target.Kill(); // just in case, maybe Damage is overridden on some shard
+
+ if (target.Corpse != null && !target.Player)
+ {
+ target.Corpse.Delete();
+ }
+
+ _owner.Focus = null;
+ Stop();
+ }
+ else
+ {
+ _owner.NonLethalAttack(target);
+ }
+ }
}
diff --git a/Projects/UOContent/Mobiles/Guards/WarriorGuard.cs b/Projects/UOContent/Mobiles/Guards/WarriorGuard.cs
index c818fa0aa..3ee7bf47f 100644
--- a/Projects/UOContent/Mobiles/Guards/WarriorGuard.cs
+++ b/Projects/UOContent/Mobiles/Guards/WarriorGuard.cs
@@ -1,4 +1,3 @@
-using System;
using ModernUO.Serialization;
using Server.Items;
@@ -7,17 +6,11 @@ namespace Server.Mobiles;
[SerializationGenerator(0, false)]
public partial class WarriorGuard : BaseGuard
{
- private Timer _attackTimer;
- private Timer _idleTimer;
-
[Constructible]
public WarriorGuard(Mobile target = null) : base(target)
{
- InitStats(1000, 1000, 1000);
- Title = "the guard";
-
+ InitStats(100, 125, 25);
SpeechHue = Utility.RandomDyedHue();
-
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())
@@ -73,12 +66,12 @@ public partial class WarriorGuard : BaseGuard
AddItem(weapon);
- Container pack = new Backpack();
-
- pack.Movable = false;
+ var pack = new Backpack
+ {
+ Movable = false
+ };
pack.DropItem(new Gold(10, 25));
-
AddItem(pack);
Skills.Anatomy.Base = 120.0;
@@ -88,7 +81,6 @@ public partial class WarriorGuard : BaseGuard
Skills.DetectHidden.Base = 100.0;
NextCombatTime = Core.TickCount + 500;
- Focus = target;
}
[SerializableProperty(0)]
@@ -126,34 +118,22 @@ public partial class WarriorGuard : BaseGuard
Say(500131); // Thou wilt regret thine actions, swine!
}
- if (_attackTimer != null)
- {
- _attackTimer.Stop();
- _attackTimer = null;
- }
-
- if (_idleTimer != null)
- {
- _idleTimer.Stop();
- _idleTimer = null;
- }
+ AttackTimer = null;
+ IdleTimer = null;
if (_focus != null)
{
- _attackTimer = new AttackTimer(this);
- _attackTimer.Start();
- ((AttackTimer)_attackTimer).DoOnTick();
+ AttackTimer = new GuardAttackTimer(this);
+ AttackTimer.DoOnTick();
}
else
{
- _idleTimer = new IdleTimer(this);
- _idleTimer.Start();
+ IdleTimer = new GuardIdleTimer(this);
}
}
- else if (_focus == null && _idleTimer == null)
+ else if (_focus == null && IdleTimer == null && Spawner != null)
{
- _idleTimer = new IdleTimer(this);
- _idleTimer.Start();
+ IdleTimer = new GuardIdleTimer(this);
}
this.MarkDirty();
@@ -164,209 +144,32 @@ public partial class WarriorGuard : BaseGuard
{
if (_focus?.Alive == true)
{
- new AvengeTimer(_focus).Start(); // If a guard dies, three more guards will spawn
+ new GuardAvengeTimer(_focus).Start(); // If a guard dies, three more guards will spawn
}
return base.OnBeforeDeath();
}
- [AfterDeserialization]
- private void AfterDeserialization()
+ public override void NonLethalAttack(Mobile target)
{
- if (_focus != null)
+ if (!InRange(target, 20))
{
- _attackTimer = new AttackTimer(this);
- _attackTimer.Start();
+ Focus = null;
}
- else
+ else if (!InRange(target, 10) || !InLOS(target))
{
- _idleTimer = new IdleTimer(this);
- _idleTimer.Start();
+ TeleportTo(this, target.Location);
}
- }
-
- public override void OnAfterDelete()
- {
- if (_attackTimer != null)
+ else if (!InRange(target, 1))
{
- _attackTimer.Stop();
- _attackTimer = null;
+ if (!Move(GetDirectionTo(target) | Direction.Running))
+ {
+ TeleportTo(this, target.Location);
+ }
}
-
- if (_idleTimer != null)
+ else if (!CanSee(target) && UseSkill(SkillName.DetectHidden))
{
- _idleTimer.Stop();
- _idleTimer = null;
- }
-
- base.OnAfterDelete();
- }
-
- private class AvengeTimer : Timer
- {
- private readonly Mobile m_Focus;
-
- public AvengeTimer(Mobile focus) : base(TimeSpan.FromSeconds(2.5), TimeSpan.FromSeconds(1.0), 3) =>
- m_Focus = focus;
-
- protected override void OnTick()
- {
- Spawn(m_Focus, m_Focus, 1, true);
- }
- }
-
- private class AttackTimer : Timer
- {
- private readonly WarriorGuard m_Owner;
-
- public AttackTimer(WarriorGuard owner) : base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(0.1)) =>
- m_Owner = owner;
-
- public void DoOnTick()
- {
- OnTick();
- }
-
- protected override void OnTick()
- {
- if (m_Owner.Deleted)
- {
- Stop();
- return;
- }
-
- m_Owner.Criminal = false;
- m_Owner.Kills = 0;
- m_Owner.Stam = m_Owner.StamMax;
-
- var target = m_Owner.Focus;
-
- if (target != null && (target.Deleted || !target.Alive || !m_Owner.CanBeHarmful(target)))
- {
- m_Owner.Focus = null;
- Stop();
- return;
- }
-
- if (m_Owner.Weapon is Fists)
- {
- m_Owner.Kill();
- Stop();
- return;
- }
-
- if (target != null && m_Owner.Combatant != target)
- {
- m_Owner.Combatant = target;
- }
-
- if (target == null)
- {
- Stop();
- }
- else
- {
- //
- TeleportTo(target);
- target.BoltEffect(0);
-
- if (target is BaseCreature creature)
- {
- creature.NoKillAwards = true;
- }
-
- target.Damage(target.HitsMax, m_Owner);
- target.Kill(); // just in case, maybe Damage is overridden on some shard
-
- if (target.Corpse != null && !target.Player)
- {
- target.Corpse.Delete();
- }
-
- m_Owner.Focus = null;
- Stop();
- } //
-
- /*else if (!m_Owner.InRange( target, 20 ))
- {
- m_Owner.Focus = null;
- }
- else if (!m_Owner.InRange( target, 10 ) || !m_Owner.InLOS( target ))
- {
- TeleportTo( target );
- }
- else if (!m_Owner.InRange( target, 1 ))
- {
- if (!m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running ))
- TeleportTo( target );
- }
- else if (!m_Owner.CanSee( target ))
- {
- if (!m_Owner.UseSkill( SkillName.DetectHidden ) && Utility.Random( 50 ) == 0)
- m_Owner.Say( "Reveal!" );
- }*/
- }
-
- private void TeleportTo(Mobile target)
- {
- var from = m_Owner.Location;
- var to = target.Location;
-
- m_Owner.Location = to;
-
- Effects.SendLocationParticles(
- EffectItem.Create(from, m_Owner.Map, EffectItem.DefaultDuration),
- 0x3728,
- 10,
- 10,
- 2023
- );
- Effects.SendLocationParticles(
- EffectItem.Create(to, m_Owner.Map, EffectItem.DefaultDuration),
- 0x3728,
- 10,
- 10,
- 5023
- );
-
- m_Owner.PlaySound(0x1FE);
- }
- }
-
- private class IdleTimer : Timer
- {
- private readonly WarriorGuard m_Owner;
- private int m_Stage;
-
- public IdleTimer(WarriorGuard owner) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.5)) =>
- m_Owner = owner;
-
- protected override void OnTick()
- {
- if (m_Owner.Deleted)
- {
- Stop();
- return;
- }
-
- if (m_Stage++ % 4 == 0 || !m_Owner.Move(m_Owner.Direction))
- {
- m_Owner.Direction = (Direction)Utility.Random(8);
- }
-
- if (m_Stage > 16)
- {
- Effects.SendLocationParticles(
- EffectItem.Create(m_Owner.Location, m_Owner.Map, EffectItem.DefaultDuration),
- 0x3728,
- 10,
- 10,
- 2023
- );
- m_Owner.PlaySound(0x1FE);
-
- m_Owner.Delete();
- }
+ Say("Reveal!");
}
}
}