Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,167 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Drawing;
using Server;
using Server.Items;
using Server.Mobiles;
using VitaNex.Network;
#endregion
namespace VitaNex.TimeBoosts
{
[Flipable(4173, 4174)]
public class TimeBoostToken : Item
{
private ITimeBoost _Boost;
[CommandProperty(AccessLevel.Counselor, true)]
public ITimeBoost Boost
{
get => _Boost ?? (_Boost = TimeBoosts.MinValue);
private set
{
if (_Boost == value)
{
return;
}
_Boost = value ?? TimeBoosts.MinValue;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.Administrator)]
public TimeSpan Value { get => Boost.Value; set => Boost = TimeBoosts.Find(value); }
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public override int Hue
{
get
{
if (World.Saving)
{
return base.Hue;
}
var hue = base.Hue;
return hue > 0 ? hue : Boost.Hue;
}
set => base.Hue = value;
}
public override string DefaultName => Boost.Name;
[Constructable(AccessLevel.Administrator)]
public TimeBoostToken()
: this(TimeBoosts.RandomValue, 1)
{ }
[Constructable(AccessLevel.Administrator)]
public TimeBoostToken(string time)
: this(time, 1)
{ }
[Constructable(AccessLevel.Administrator)]
public TimeBoostToken(string time, int amount)
: this(TimeSpan.Parse(time), amount)
{ }
public TimeBoostToken(TimeSpan time)
: this(TimeBoosts.Find(time))
{ }
public TimeBoostToken(TimeSpan time, int amount)
: this(TimeBoosts.Find(time), amount)
{ }
public TimeBoostToken(ITimeBoost boost)
: this(boost, 1)
{ }
public TimeBoostToken(ITimeBoost boost, int amount)
: base(Utility.RandomList(4173, 4174))
{
Boost = boost;
Stackable = true;
Amount = Math.Max(1, Math.Min(60000, amount));
LootType = LootType.Blessed;
}
public TimeBoostToken(Serial serial)
: base(serial)
{ }
public override bool StackWith(Mobile m, Item dropped, bool playSound)
{
if (!(dropped is TimeBoostToken) || ((TimeBoostToken)dropped).Boost != Boost)
{
return false;
}
return base.StackWith(m, dropped, playSound);
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
new ExtendedOPL(list)
{
{"Use: Credits {0:#,0} {1} to your account".WrapUOHtmlColor(Color.LawnGreen), Amount, Boost},
"\"Time Boosts reduce the time required to do certain things\"".WrapUOHtmlColor(Color.Gold)
}.Apply();
}
public override void OnDoubleClick(Mobile m)
{
if (!this.CheckDoubleClick(m, true, false, -1, true, false, false) || !(m is PlayerMobile))
{
return;
}
var user = (PlayerMobile)m;
if (TimeBoosts.Credit(user, Boost, Amount))
{
TimeBoostsUI.Update(user);
m.SendMessage(85, "{0:#,0} {1} has been credited to your account.", Amount, Boost);
Delete();
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(Boost);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
Boost = reader.ReadTimeBoost();
}
}
}

View File

@@ -0,0 +1,27 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
#endregion
namespace VitaNex.TimeBoosts
{
public interface ITimeBoost
{
int RawValue { get; }
TimeSpan Value { get; }
string Desc { get; }
string Name { get; }
int Hue { get; }
}
}

View File

@@ -0,0 +1,71 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
#endregion
namespace VitaNex.TimeBoosts
{
public struct TimeBoostHours : ITimeBoost
{
public int RawValue { get; private set; }
public TimeSpan Value { get; private set; }
public string Desc => "Hour";
public string Name => String.Format("{0}-{1} Boost", RawValue, Desc);
public int Hue => 2118;
public TimeBoostHours(int hours)
: this()
{
Value = TimeSpan.FromHours(RawValue = hours);
}
public override string ToString()
{
return Name;
}
public override int GetHashCode()
{
unchecked
{
var hash = RawValue;
hash = (hash * 397) ^ Value.Days;
hash = (hash * 397) ^ Value.Hours;
hash = (hash * 397) ^ Value.Minutes;
return hash;
}
}
public static implicit operator TimeBoostHours(int hours)
{
return new TimeBoostHours(hours);
}
public static implicit operator TimeBoostHours(TimeSpan time)
{
return new TimeBoostHours(time.Hours);
}
public static implicit operator TimeSpan(TimeBoostHours value)
{
return value.Value;
}
public static implicit operator int(TimeBoostHours value)
{
return value.RawValue;
}
}
}

View File

@@ -0,0 +1,71 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
#endregion
namespace VitaNex.TimeBoosts
{
public struct TimeBoostMinutes : ITimeBoost
{
public int RawValue { get; private set; }
public TimeSpan Value { get; private set; }
public string Desc => "Minute";
public string Name => String.Format("{0}-{1} Boost", RawValue, Desc);
public int Hue => 2106;
public TimeBoostMinutes(int minutes)
: this()
{
Value = TimeSpan.FromMinutes(RawValue = minutes);
}
public override string ToString()
{
return Name;
}
public override int GetHashCode()
{
unchecked
{
var hash = RawValue;
hash = (hash * 397) ^ Value.Days;
hash = (hash * 397) ^ Value.Hours;
hash = (hash * 397) ^ Value.Minutes;
return hash;
}
}
public static implicit operator TimeBoostMinutes(int minutes)
{
return new TimeBoostMinutes(minutes);
}
public static implicit operator TimeBoostMinutes(TimeSpan time)
{
return new TimeBoostMinutes(time.Minutes);
}
public static implicit operator TimeSpan(TimeBoostMinutes value)
{
return value.Value;
}
public static implicit operator int(TimeBoostMinutes value)
{
return value.RawValue;
}
}
}

View File

@@ -0,0 +1,256 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Accounting;
#endregion
namespace VitaNex.TimeBoosts
{
public sealed class TimeBoostProfile : PropertyObject, IEnumerable<KeyValuePair<ITimeBoost, int>>
{
public IAccount Owner { get; private set; }
private Dictionary<ITimeBoost, int> _Boosts = new Dictionary<ITimeBoost, int>();
public int this[ITimeBoost key] { get => _Boosts.GetValue(key); set => _Boosts.Update(key, value); }
public TimeSpan TotalTime => TimeSpan.FromTicks(_Boosts.Sum(kv => kv.Key.Value.Ticks * kv.Value));
public TimeBoostProfile(IAccount owner)
{
Owner = owner;
}
public TimeBoostProfile(GenericReader reader)
: base(reader)
{ }
public override void Clear()
{
_Boosts.Clear();
}
public override void Reset()
{
_Boosts.Clear();
}
#region Credit
public bool CanCredit(ITimeBoost b, int amount)
{
return b != null && amount >= 0 && (long)this[b] + amount <= Int32.MaxValue;
}
public bool Credit(ITimeBoost b, int amount)
{
if (CanCredit(b, amount))
{
this[b] += amount;
return true;
}
return false;
}
public bool CreditHours(int value)
{
return Credit(value, 0);
}
public bool CreditMinutes(int value)
{
return Credit(0, value);
}
public bool Credit(int hours, int minutes)
{
return Credit(hours, minutes, false) && Credit(hours, minutes, true);
}
private bool Credit(int hours, int minutes, bool update)
{
return Credit(hours, minutes, update, out _, out _);
}
private bool Credit(int hours, int minutes, bool update, out int totalHours, out int totalMinutes)
{
totalHours = totalMinutes = 0;
return (hours == 0 || Credit(hours, 0, update, out totalHours)) && (minutes == 0 || Credit(minutes, 1, update, out totalMinutes));
}
private bool Credit(int time, byte index, bool update, out int totalTime)
{
totalTime = 0;
if (!TimeBoosts.Times.InBounds(index))
{
return false;
}
ITimeBoost k;
int v, t = time;
var i = TimeBoosts.Times[index].Length;
while (--i >= 0)
{
k = TimeBoosts.Times[index][i];
v = k.RawValue;
if (time >= v && this[k] < Int32.MaxValue)
{
time -= v;
totalTime += v;
if (update)
{
++this[k];
}
}
}
return totalTime >= t;
}
#endregion Credit
#region Consume
public bool CanConsume(ITimeBoost b, int amount)
{
return b != null && amount >= 0 && this[b] >= amount;
}
public bool Consume(ITimeBoost b, int amount)
{
if (CanConsume(b, amount))
{
this[b] -= amount;
return true;
}
return false;
}
public bool ConsumeHours(int value)
{
return Consume(value, 0);
}
public bool ConsumeMinutes(int value)
{
return Consume(0, value);
}
public bool Consume(int hours, int minutes)
{
return Consume(hours, minutes, false) && Consume(hours, minutes, true);
}
private bool Consume(int hours, int minutes, bool update)
{
return Consume(hours, minutes, update, out _, out _);
}
private bool Consume(int hours, int minutes, bool update, out int totalHours, out int totalMinutes)
{
totalHours = totalMinutes = 0;
return (hours == 0 || Consume(hours, 0, update, out totalHours)) && (minutes == 0 || Consume(minutes, 1, update, out totalMinutes));
}
private bool Consume(int time, byte index, bool update, out int totalTime)
{
totalTime = 0;
if (!TimeBoosts.Times.InBounds(index))
{
return false;
}
ITimeBoost k;
int v, t = time;
var i = TimeBoosts.Times[index].Length;
while (--i >= 0)
{
k = TimeBoosts.Times[index][i];
v = k.RawValue;
if (time >= v && this[k] > 0)
{
time -= v;
totalTime += v;
if (update)
{
--this[k];
}
}
}
return totalTime >= t;
}
#endregion Consume
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<KeyValuePair<ITimeBoost, int>> GetEnumerator()
{
return _Boosts.GetEnumerator();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(Owner);
writer.WriteDictionary(_Boosts, (w, k, v) =>
{
w.Write(k);
w.Write(v);
});
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
Owner = reader.ReadAccount();
_Boosts = reader.ReadDictionary(r =>
{
var k = r.ReadTimeBoost();
var v = r.ReadInt();
return new KeyValuePair<ITimeBoost, int>(k, v);
},
_Boosts);
_Boosts.RemoveValueRange(v => v <= 0);
}
}
}

View File

@@ -0,0 +1,261 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Accounting;
using Server.Mobiles;
using VitaNex.IO;
#endregion
namespace VitaNex.TimeBoosts
{
public static partial class TimeBoosts
{
public static TimeBoostHours[] Hours { get; private set; }
public static TimeBoostMinutes[] Minutes { get; private set; }
public static ITimeBoost[][] Times { get; private set; }
public static ITimeBoost[] AllTimes { get; private set; }
public static ITimeBoost RandomHours => Hours.GetRandom();
public static ITimeBoost RandomMinutes => Minutes.GetRandom();
public static ITimeBoost RandomValue => AllTimes.GetRandom();
public static ITimeBoost MinValue => AllTimes.Lowest(b => b.Value);
public static ITimeBoost MaxValue => AllTimes.Highest(b => b.Value);
public static BinaryDataStore<IAccount, TimeBoostProfile> Profiles { get; private set; }
public static TimeBoostProfile FindProfile(PlayerMobile m)
{
if (m == null || m.Account == null)
{
return null;
}
return FindProfile(m.Account);
}
public static TimeBoostProfile FindProfile(IAccount a)
{
return Profiles.GetValue(a);
}
public static TimeBoostProfile EnsureProfile(PlayerMobile m)
{
if (m == null || m.Account == null)
{
return null;
}
return EnsureProfile(m.Account);
}
public static TimeBoostProfile EnsureProfile(IAccount a)
{
TimeBoostProfile profile = null;
Profiles.Update(a, p => profile = p ?? new TimeBoostProfile(a));
return profile;
}
public static IEnumerable<KeyValuePair<ITimeBoost, int>> FindBoosts(PlayerMobile m)
{
if (m == null || m.Account == null)
{
return Enumerable.Empty<KeyValuePair<ITimeBoost, int>>();
}
return FindBoosts(m.Account);
}
public static IEnumerable<KeyValuePair<ITimeBoost, int>> FindBoosts(IAccount a)
{
return FindProfile(a) ?? Enumerable.Empty<KeyValuePair<ITimeBoost, int>>();
}
#region Credit
public static bool CanCredit(PlayerMobile m, ITimeBoost b, int amount)
{
return m != null && CanCredit(m.Account, b, amount);
}
public static bool Credit(PlayerMobile m, ITimeBoost b, int amount)
{
return m != null && Credit(m.Account, b, amount);
}
public static bool CreditHours(PlayerMobile m, int value)
{
return m != null && CreditHours(m.Account, value);
}
public static bool CreditMinutes(PlayerMobile m, int value)
{
return m != null && CreditMinutes(m.Account, value);
}
public static bool Credit(PlayerMobile m, int hours, int minutes)
{
return m != null && Credit(m.Account, hours, minutes);
}
public static bool CanCredit(IAccount a, ITimeBoost b, int amount)
{
var p = EnsureProfile(a);
return p != null && p.CanCredit(b, amount);
}
public static bool Credit(IAccount a, ITimeBoost b, int amount)
{
var p = EnsureProfile(a);
return p != null && p.Credit(b, amount);
}
public static bool CreditHours(IAccount a, int value)
{
var p = EnsureProfile(a);
return p != null && p.CreditHours(value);
}
public static bool CreditMinutes(IAccount a, int value)
{
var p = EnsureProfile(a);
return p != null && p.CreditMinutes(value);
}
public static bool Credit(IAccount a, int hours, int minutes)
{
var p = EnsureProfile(a);
return p != null && p.Credit(hours, minutes);
}
#endregion Credit
#region Consume
public static bool CanConsume(PlayerMobile m, ITimeBoost b, int amount)
{
return m != null && CanConsume(m.Account, b, amount);
}
public static bool Consume(PlayerMobile m, ITimeBoost b, int amount)
{
return m != null && Consume(m.Account, b, amount);
}
public static bool ConsumeHours(PlayerMobile m, int value)
{
return m != null && ConsumeHours(m.Account, value);
}
public static bool ConsumeMinutes(PlayerMobile m, int value)
{
return m != null && ConsumeMinutes(m.Account, value);
}
public static bool Consume(PlayerMobile m, int hours, int minutes)
{
return m != null && Consume(m.Account, hours, minutes);
}
public static bool CanConsume(IAccount a, ITimeBoost b, int amount)
{
var p = EnsureProfile(a);
return p != null && p.CanConsume(b, amount);
}
public static bool Consume(IAccount a, ITimeBoost b, int amount)
{
var p = EnsureProfile(a);
return p != null && p.Consume(b, amount);
}
public static bool ConsumeHours(IAccount a, int value)
{
var p = EnsureProfile(a);
return p != null && p.ConsumeHours(value);
}
public static bool ConsumeMinutes(IAccount a, int value)
{
var p = EnsureProfile(a);
return p != null && p.ConsumeMinutes(value);
}
public static bool Consume(IAccount a, int hours, int minutes)
{
var p = EnsureProfile(a);
return p != null && p.Consume(hours, minutes);
}
#endregion Consume
public static ITimeBoost Find(TimeSpan time)
{
var index = AllTimes.Length;
while (--index >= 0)
{
var b = AllTimes[index];
if (time >= b.Value)
{
return b;
}
}
return null;
}
public static void Write(this GenericWriter writer, ITimeBoost boost)
{
writer.SetVersion(0);
if (boost != null)
{
writer.Write(true);
writer.Write(boost.Value);
}
else
{
writer.Write(false);
}
}
public static ITimeBoost ReadTimeBoost(this GenericReader reader)
{
reader.GetVersion();
if (reader.ReadBool())
{
return Find(reader.ReadTimeSpan());
}
return null;
}
}
}

View File

@@ -0,0 +1,88 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Accounting;
using VitaNex.IO;
#endregion
namespace VitaNex.TimeBoosts
{
[CoreService("Time Boosts", "1.0.0.0", TaskPriority.High)]
public static partial class TimeBoosts
{
public static CoreServiceOptions CSOptions { get; private set; }
static TimeBoosts()
{
Hours = new TimeBoostHours[] { 1, 3, 6, 12 };
Minutes = new TimeBoostMinutes[] { 1, 3, 5, 15, 30 };
Times = new[] { Hours.CastToArray<ITimeBoost>(), Minutes.CastToArray<ITimeBoost>() };
AllTimes = Times.SelectMany(t => t).OrderBy(b => b.Value).ToArray();
CSOptions = new CoreServiceOptions(typeof(TimeBoosts));
Profiles = new BinaryDataStore<IAccount, TimeBoostProfile>(VitaNexCore.SavesDirectory + "/TimeBoosts", "Profiles")
{
Async = true,
OnSerialize = Serialize,
OnDeserialize = Deserialize
};
}
private static void CSSave()
{
Profiles.Export();
}
private static void CSLoad()
{
Profiles.Import();
}
private static bool Serialize(GenericWriter writer)
{
writer.SetVersion(0);
writer.WriteBlockDictionary(Profiles, (w, k, v) =>
{
w.Write(k);
v.Serialize(w);
});
return true;
}
private static bool Deserialize(GenericReader reader)
{
reader.GetVersion();
reader.ReadBlockDictionary(r =>
{
var k = r.ReadAccount();
var v = new TimeBoostProfile(r);
return new KeyValuePair<IAccount, TimeBoostProfile>(k, v);
},
Profiles);
return true;
}
}
}

View File

@@ -0,0 +1,551 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Server;
using Server.Gumps;
using Server.Mobiles;
using VitaNex.SuperGumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.TimeBoosts
{
public class TimeBoostsUI : SuperGumpList<ITimeBoost>
{
public static string DefaultTitle = "Time Boosts";
public static string DefaultSubTitle = String.Empty;
public static string DefaultEmptyText = "No available Time Boosts.";
public static string DefaultSummaryText = "Time Left";
public static string DefaultHelpText = "Tip: Click an available time boost to update the time remaining!";
public static Color DefaultTitleColor = Color.PaleGoldenrod;
public static Color DefaultSubTitleColor = Color.Goldenrod;
public static Color DefaultEmptyTextColor = Color.SaddleBrown;
public static Color DefaultBoostTextColor = Color.Yellow;
public static Color DefaultBoostCountColor = Color.LawnGreen;
public static Color DefaultSummaryTextColor = Color.Goldenrod;
public static Color DefaultHelpTextColor = Color.Gold;
public static void Update(PlayerMobile user)
{
foreach (var info in EnumerateInstances<TimeBoostsUI>(user, true).Where(g => g != null && !g.IsDisposed && g.IsOpen))
info.Refresh(true);
}
public string Title { get; set; }
public string SubTitle { get; set; }
public string EmptyText { get; set; }
public string SummaryText { get; set; }
public string HelpText { get; set; }
public Color TitleColor { get; set; }
public Color SubTitleColor { get; set; }
public Color EmptyTextColor { get; set; }
public Color BoostTextColor { get; set; }
public Color BoostCountColor { get; set; }
public Color SummaryTextColor { get; set; }
public Color HelpTextColor { get; set; }
public TimeBoostProfile Profile { get; set; }
public bool ApplyAutoAllowed { get; set; }
public bool ApplyAutoPreview { get; set; }
public Func<ITimeBoost, bool> CanApply { get; set; }
public Action<ITimeBoost> BoostUsed { get; set; }
public Func<TimeSpan> GetTime { get; set; }
public Action<TimeSpan> SetTime { get; set; }
public TimeSpan? OldTime { get; private set; }
public TimeSpan? Time { get => GetTime?.Invoke(); set => SetTime?.Invoke(value ?? TimeSpan.Zero); }
public TimeBoostsUI(Mobile user, Gump parent = null, TimeBoostProfile profile = null, Func<ITimeBoost, bool> canApply = null, Action<ITimeBoost> boostUsed = null, Func<TimeSpan> getTime = null, Action<TimeSpan> setTime = null)
: base(user, parent)
{
Profile = profile;
CanApply = canApply;
BoostUsed = boostUsed;
GetTime = getTime;
SetTime = setTime;
Title = DefaultTitle;
SubTitle = DefaultSubTitle;
EmptyText = DefaultEmptyText;
SummaryText = DefaultSummaryText;
HelpText = DefaultHelpText;
TitleColor = DefaultTitleColor;
SubTitleColor = DefaultSubTitleColor;
EmptyTextColor = DefaultEmptyTextColor;
BoostTextColor = DefaultBoostTextColor;
BoostCountColor = DefaultBoostCountColor;
SummaryTextColor = DefaultSummaryTextColor;
HelpTextColor = DefaultHelpTextColor;
ApplyAutoAllowed = true;
EntriesPerPage = 4;
Sorted = true;
CanClose = true;
CanDispose = true;
CanMove = true;
CanResize = false;
AutoRefreshRate = TimeSpan.FromMinutes(1.0);
AutoRefresh = true;
ForceRecompile = true;
}
protected override void Compile()
{
if (Profile == null && User != null)
Profile = TimeBoosts.EnsureProfile(User.Account);
if (!ApplyAutoAllowed)
ApplyAutoPreview = false;
base.Compile();
}
protected override void CompileList(List<ITimeBoost> list)
{
list.Clear();
var boosts = TimeBoosts.AllTimes.Where(b => Profile == null || Profile[b] > 0);
if (ApplyAutoAllowed && ApplyAutoPreview)
{
var time = Time?.Ticks ?? 0;
if (time > 0)
{
foreach (var boost in boosts.OrderByDescending(b => b.Value.Ticks))
{
if (boost.Value.Ticks > time)
break;
var take = Math.Min(Profile[boost], (int)(time / boost.Value.Ticks));
if (take <= 0)
break;
time -= take * boost.Value.Ticks;
list.Add(new BoostPreview(boost, take));
}
}
}
else
list.AddRange(boosts);
base.CompileList(list);
}
protected override void CompileLayout(SuperGumpLayout layout)
{
base.CompileLayout(layout);
layout.Add("background", () =>
{
AddBackground(0, 0, 480, 225, 9270);
AddBackground(15, 40, 450, 140, 9350);
});
layout.Add("title", () =>
{
if (String.IsNullOrWhiteSpace(Title))
return;
var text = Title;
text = text.ToUpper();
text = text.WrapUOHtmlBold();
text = text.WrapUOHtmlColor(TitleColor, false);
AddHtml(20, 15, 235, 40, text, false, false);
});
layout.Add("subtitle", () =>
{
if (String.IsNullOrWhiteSpace(SubTitle))
return;
var text = SubTitle;
text = text.ToUpper();
text = text.WrapUOHtmlBold();
text = text.WrapUOHtmlColor(SubTitleColor, false);
text = text.WrapUOHtmlRight();
AddHtml(255, 15, 200, 40, text, false, false);
});
layout.Add("page/prev", () =>
{
if (HasPrevPage)
AddButton(7, 150, 9910, 9911, PreviousPage);
else
AddImage(7, 150, 9909);
});
layout.Add("page/next", () =>
{
if (HasNextPage)
AddButton(451, 150, 9904, 9905, NextPage);
else
AddImage(451, 150, 9903);
});
CompileEntryLayout(layout, GetListRange());
layout.Add("summary", () =>
{
TimeSpan time;
if (ApplyAutoPreview)
time = TimeSpan.FromTicks(List.OfType<BoostPreview>().Aggregate(0L, (t, b) => t + (b.Value.Ticks * b.Amount)));
else
time = Time ?? TimeSpan.Zero;
if (time < TimeSpan.Zero)
time = TimeSpan.Zero;
var text = SummaryText;
if (ApplyAutoPreview)
text = "Total Time";
text = text.ToUpper();
text = text.WrapUOHtmlBold();
text = text.WrapUOHtmlColor(SummaryTextColor, false);
text = text.WrapUOHtmlCenter();
AddHtml(20, 192, 87, 40, text, false, false);
AddImage(112, 185, 30223);
if (ApplyAutoPreview)
AddImageTime(140, 185, time, 0x55); // 175 x 28
else
AddImageTime(140, 185, time, 0x33); // 175 x 28
AddImage(315, 185, 30223);
});
layout.Add("auto", () =>
{
if (ApplyAutoPreview)
AddButton(350, 187, 2124, 2123, b => ApplyAuto(false));
else if (ApplyAutoAllowed)
AddButton(350, 187, 2113, 2112, b => ApplyAuto(true));
else
AddImage(350, 187, 2113, 900);
});
layout.Add("okay", () =>
{
if (ApplyAutoPreview)
AddButton(410, 187, 2121, 2120, b => ApplyAuto(null));
else
AddButton(410, 187, 2130, 2129, Close);
});
layout.Add("tip", () =>
{
AddBackground(0, 225, 480, 40, 9270);
var text = HelpText;
if (ApplyAutoPreview)
text = "Automatically use boosts as displayed above.";
text = text.WrapUOHtmlSmall();
text = text.WrapUOHtmlCenter();
text = text.WrapUOHtmlColor(HelpTextColor);
AddHtml(20, 235, 440, 40, text, false, false);
});
}
protected virtual void CompileEntryLayout(SuperGumpLayout layout, Dictionary<int, ITimeBoost> range)
{
if (range.Count > 0)
{
var i = 0;
foreach (var kv in range)
{
CompileEntryLayout(layout, range.Count, kv.Key, i, 53 + (i * 93), kv.Value);
++i;
}
}
else
{
layout.Add("empty", () =>
{
var text = EmptyText;
text = text.WrapUOHtmlColor(EmptyTextColor, false);
text = text.WrapUOHtmlCenter();
AddHtml(35, 150, 355, 40, text, false, false);
});
}
}
protected virtual void CompileEntryLayout(SuperGumpLayout layout, int length, int index, int pIndex, int xOffset, ITimeBoost boost)
{
layout.Add("boosts/" + index, () =>
{
BoostPreview? bp = null;
if (boost is BoostPreview p)
bp = p;
int hue = boost.Hue, bellID = 10850;
var text = String.Empty;
if (boost.Value.Hours != 0)
{
bellID = 10810; //Blue Gem
text = "Hour";
}
else if (boost.Value.Minutes != 0)
{
bellID = 10830; //Green Gem
text = "Min";
}
else
hue = 2999;
if (!String.IsNullOrWhiteSpace(text) && boost.RawValue != 1)
text += "s";
if (hue == 2999)
{
AddImage(xOffset + 7, 56, bellID, hue); //Left Bell
AddImage(xOffset + 57, 56, bellID, hue); //Right Bell
}
else
{
AddImage(xOffset + 7, 56, bellID); //Left Bell
AddImage(xOffset + 57, 56, bellID); //Right Bell
}
AddImage(xOffset, 45, 30058, hue); //Hammer
if (Profile != null && bp == null)
AddButton(xOffset + 5, 65, 1417, 1417, b => SelectBoost(boost)); //Disc
AddImage(xOffset + 5, 65, 1417, hue); //Disc
AddImage(xOffset + 14, 75, 5577, 2999); //Blackout
AddImageNumber(xOffset + 44, 99, boost.RawValue, hue, Axis.Both);
if (!String.IsNullOrWhiteSpace(text))
{
text = text.WrapUOHtmlSmall();
text = text.WrapUOHtmlCenter();
text = text.WrapUOHtmlColor(BoostTextColor, false);
AddHtml(xOffset + 20, 110, 50, 40, text, false, false);
}
if (hue == 2999)
AddImage(xOffset, 130, 30062, hue); //Feet
else
{
if (Profile != null)
AddBackground(xOffset + 10, 143, 70, 30, 9270); //9300
AddImage(xOffset, 130, 30062); //Feet
if (Profile != null)
{
text = $"{(bp?.Amount ?? Profile[boost]):N0}";
text = text.WrapUOHtmlBold();
text = text.WrapUOHtmlCenter();
text = text.WrapUOHtmlColor(BoostCountColor, false);
AddHtml(xOffset + 12, 150, 65, 40, text, false, false);
}
}
});
}
public virtual void ApplyAuto(bool? state)
{
if (!ApplyAutoAllowed || state == null)
ApplyAutoPreview = false;
else if (state == true)
ApplyAutoPreview = true;
else if (ApplyAutoPreview)
{
foreach (var bp in List.OfType<BoostPreview>())
{
var amount = bp.Amount;
while (--amount >= 0 && (IsOpen || Hidden))
{
if (ApplyBoost(bp.Boost))
{
OnBoostUsed(bp.Boost);
if (IsOpen || Hidden)
continue;
}
break;
}
if (!IsOpen && !Hidden)
break;
}
ApplyAutoPreview = false;
}
if (IsOpen || Hidden)
Refresh(true);
}
public virtual void SelectBoost(ITimeBoost boost)
{
if (CanApplyBoost(boost))
ApplyBoost(boost, boost.Value.TotalHours >= 6);
else
Refresh(true);
}
public virtual void ApplyBoost(ITimeBoost boost, bool confirm)
{
if (CanApplyBoost(boost))
{
if (confirm)
{
new ConfirmDialogGump(User, Hide(true))
{
Icon = 7057,
Title = $"Use {boost.Name}?",
Html = $"{Title}: {SubTitle}\n{boost.RawValue} {boost.Desc}{(boost.RawValue != 1 ? "s" : String.Empty)}.\nClick OK to apply this Time Boost.",
AcceptHandler = b => ApplyBoost(boost, false),
CancelHandler = b => Refresh(true)
}.Send();
return;
}
if (ApplyBoost(boost))
OnBoostUsed(boost);
}
if (IsOpen || Hidden)
Refresh(true);
}
public virtual bool ApplyBoost(ITimeBoost boost)
{
if (!CanApplyBoost(boost) || !Profile.Consume(boost, 1))
return false;
OldTime = Time;
Time -= boost.Value;
return true;
}
protected virtual bool CanApplyBoost(ITimeBoost boost)
{
return GetTime != null && SetTime != null && Time > TimeSpan.Zero && boost != null && boost.RawValue > 0 &&
Profile != null && Profile.Owner == User.Account && (CanApply == null || CanApply(boost));
}
protected virtual void OnBoostUsed(ITimeBoost boost)
{
BoostUsed?.Invoke(boost);
LogBoostUsed(boost);
}
protected virtual void LogBoostUsed(ITimeBoost boost)
{
var log = new StringBuilder();
log.AppendLine();
log.AppendLine("UI: '{0}' : '{1}' : '{2}'", Title, SubTitle, SummaryText);
log.AppendLine("User: {0}", User);
log.AppendLine("Boost: {0}", boost);
log.AppendLine("Get: {0}", GetTime.Trace());
log.AppendLine("Set: {0}", SetTime.Trace());
log.AppendLine("Time: {0} > {1}", OldTime, Time);
log.AppendLine();
log.Log($"/TimeBoosts/{DateTime.Now.ToDirectoryName()}/{boost}.log");
}
public override int SortCompare(ITimeBoost a, ITimeBoost b)
{
var res = 0;
if (a.CompareNull(b, ref res))
return res;
if (a.Value < b.Value)
return -1;
if (a.Value > b.Value)
return 1;
return 0;
}
protected override void OnDisposed()
{
base.OnDisposed();
Profile = null;
}
protected struct BoostPreview : ITimeBoost
{
public readonly ITimeBoost Boost;
public readonly int Amount;
public int RawValue => Boost.RawValue;
public TimeSpan Value => Boost.Value;
public string Desc => Boost.Desc;
public string Name => Boost.Name;
public int Hue => Boost.Hue;
public BoostPreview(ITimeBoost boost, int amount)
{
Boost = boost;
Amount = amount;
}
}
}
}