#W# Added: More things to the ToAdd Folder.
This commit is contained in:
parent
cdc061dc54
commit
910cdde124
16 changed files with 3389 additions and 0 deletions
180
ToAdd/AutoBandCommand.cs
Normal file
180
ToAdd/AutoBandCommand.cs
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/**********************************
|
||||
* Author: Expa (refactored) *
|
||||
* Script Name: AutoBandCommand.cs *
|
||||
* Target: ModernUO (.NET 10/C#14) *
|
||||
**********************************/
|
||||
using System;
|
||||
using ModernUO.Serialization;
|
||||
using Server;
|
||||
using Server.Commands;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Scripts.Commands;
|
||||
|
||||
public static class AutoBandCommand
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register("bas", AccessLevel.Player, OnBandSelf);
|
||||
CommandSystem.Register("bat", AccessLevel.Player, OnBandTarget);
|
||||
}
|
||||
|
||||
public static void OnBandSelf(CommandEventArgs e)
|
||||
{
|
||||
if (e.Mobile is not PlayerMobile pm) return;
|
||||
Start(pm, pm);
|
||||
}
|
||||
|
||||
public static void OnBandTarget(CommandEventArgs e)
|
||||
=> e.Mobile.BeginTarget(-1, false, TargetFlags.None, OnTarget);
|
||||
|
||||
private static void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (from is not PlayerMobile pm || targeted is not Mobile target || target.Deleted || !target.Alive)
|
||||
{
|
||||
from.SendMessage("Invalid target.");
|
||||
return;
|
||||
}
|
||||
|
||||
Start(pm, target);
|
||||
}
|
||||
|
||||
private static void Start(PlayerMobile pm, Mobile target)
|
||||
{
|
||||
if (pm.AutoBandageTimer is AutoBandageTimer existing && existing.Targets(target))
|
||||
{
|
||||
StopTimer(pm);
|
||||
SendHealthMessage(pm, $"Bandage auto-heal DISABLED{(pm == target ? "" : $" on {target.Name}")}.");
|
||||
return;
|
||||
}
|
||||
|
||||
StopTimer(pm);
|
||||
|
||||
var band = pm.Backpack?.FindItemByType<Bandage>();
|
||||
if (band == null || band.Amount <= 0)
|
||||
{
|
||||
pm.SendMessage("You have no bandages!");
|
||||
return;
|
||||
}
|
||||
|
||||
var timer = new AutoBandageTimer(pm, target);
|
||||
pm.AutoBandageTimer = timer;
|
||||
timer.Start();
|
||||
|
||||
SendHealthMessage(pm, $"Bandage auto-heal ENABLED{(pm == target ? "" : $" on {target.Name}")}. Health: {target.Hits}/{target.HitsMax}");
|
||||
}
|
||||
|
||||
internal static void SendHealthMessage(Mobile m, string msg)
|
||||
{
|
||||
var denom = Math.Max(1, m.HitsMax);
|
||||
double p = (double)m.Hits / denom;
|
||||
var hue = p < 0.3 ? 33 : p < 0.7 ? 53 : 63;
|
||||
m.SendMessage(hue, msg);
|
||||
}
|
||||
|
||||
private static void StopTimer(PlayerMobile pm)
|
||||
{
|
||||
pm.AutoBandageTimer?.Stop();
|
||||
pm.AutoBandageTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
[SerializationGenerator(0)]
|
||||
public partial class AutoBandageTimer : Timer
|
||||
{
|
||||
private const double ResumeAt = 90.0;
|
||||
private const double PauseAt = 100.0;
|
||||
private static readonly TimeSpan TickInterval = TimeSpan.FromMilliseconds(100);
|
||||
|
||||
private readonly WeakReference<Mobile> _casterRef;
|
||||
private readonly WeakReference<Mobile> _targetRef;
|
||||
private bool _paused;
|
||||
private DateTime _next;
|
||||
|
||||
public AutoBandageTimer(Mobile caster, Mobile target)
|
||||
: base(TimeSpan.Zero, TickInterval)
|
||||
{
|
||||
_casterRef = new(caster);
|
||||
_targetRef = new(target);
|
||||
_next = Core.Now;
|
||||
}
|
||||
|
||||
public bool Targets(Mobile m)
|
||||
=> m is not null && _targetRef.TryGetTarget(out var t) && t == m;
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (!_casterRef.TryGetTarget(out var caster) || caster.Deleted || !caster.Alive || caster.Map == Map.Internal)
|
||||
{
|
||||
Stop();
|
||||
Cleanup(caster);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_targetRef.TryGetTarget(out var target) || target.Deleted || !target.Alive || target.Map == Map.Internal)
|
||||
{
|
||||
caster.SendMessage("Target is no longer valid. Automatic bandaging stopped.");
|
||||
Stop();
|
||||
Cleanup(caster);
|
||||
return;
|
||||
}
|
||||
|
||||
if (BandageContext.GetContext(caster) != null)
|
||||
return;
|
||||
|
||||
var denom = Math.Max(1, target.HitsMax);
|
||||
double hpPercent = (double)target.Hits / denom * 100.0;
|
||||
|
||||
if (!_paused && hpPercent >= PauseAt)
|
||||
{
|
||||
_paused = true;
|
||||
caster.SendMessage("Bandaging paused. Target's health is full.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_paused && hpPercent < ResumeAt)
|
||||
{
|
||||
_paused = false;
|
||||
caster.SendMessage($"Bandaging resumed. Target's health dropped below {ResumeAt}%.");
|
||||
_next = Core.Now;
|
||||
}
|
||||
|
||||
if (_paused || Core.Now < _next) return;
|
||||
|
||||
var band = caster.Backpack?.FindItemByType<Bandage>();
|
||||
if (band == null || band.Amount <= 0)
|
||||
{
|
||||
caster.SendMessage("Out of bandages. Automatic bandaging stopped.");
|
||||
Stop();
|
||||
Cleanup(caster);
|
||||
return;
|
||||
}
|
||||
|
||||
int preHits = target.Hits;
|
||||
double delaySec = 5.0 + 0.05 * Math.Max(0, 120 - caster.Dex);
|
||||
_next = Core.Now + TimeSpan.FromSeconds(delaySec);
|
||||
|
||||
Bandage.BandageTargetRequest(caster, band, target);
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(delaySec * 0.95), () => ShowResult(caster, target, preHits));
|
||||
}
|
||||
|
||||
private static void ShowResult(Mobile? caster, Mobile? target, int preHits)
|
||||
{
|
||||
if (caster == null || target == null) return;
|
||||
if (caster.Deleted || !caster.Alive || target.Deleted || !target.Alive) return;
|
||||
|
||||
int healed = target.Hits - preHits;
|
||||
string msg = healed > 0
|
||||
? $"Healing {target.Name}: {target.Hits}/{target.HitsMax} HP (+{healed})"
|
||||
: $"Healing {target.Name}: {target.Hits}/{target.HitsMax} HP";
|
||||
|
||||
AutoBandCommand.SendHealthMessage(caster, msg);
|
||||
}
|
||||
|
||||
private static void Cleanup(Mobile? caster)
|
||||
{
|
||||
if (caster is PlayerMobile pm) pm.AutoBandageTimer = null;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue