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,271 @@
#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 Server;
using Server.Commands;
using VitaNex.IO;
#endregion
namespace VitaNex.Modules.Games
{
[CoreModule("Games Arcade", "1.0.0.0")]
public static class Arcade
{
public const AccessLevel Access = AccessLevel.Administrator;
public static ArcadeOptions CMOptions { get; private set; }
public static BinaryDataStore<Type, IGame> Games { get; private set; }
public static BinaryDataStore<Mobile, ArcadeProfile> Profiles { get; private set; }
public static Type[] GameTypes { get; private set; }
static Arcade()
{
CMOptions = new ArcadeOptions();
Games = new BinaryDataStore<Type, IGame>(VitaNexCore.SavesDirectory + "/Arcade", "Games")
{
Async = true,
OnSerialize = SerializeGames,
OnDeserialize = DeserializeGames
};
Profiles = new BinaryDataStore<Mobile, ArcadeProfile>(VitaNexCore.SavesDirectory + "/Arcade", "Profiles")
{
Async = true,
OnSerialize = SerializeProfiles,
OnDeserialize = DeserializeProfiles
};
GameTypes = typeof(IGame).GetConstructableChildren();
foreach (var t in GameTypes)
{
var g = CreateGame(t);
if (g != null)
{
Games[t] = g;
}
}
}
private static void CMConfig()
{
CommandUtility.Register("Arcade", AccessLevel.Player, HandleCommand);
CommandUtility.RegisterAlias("Arcade", "Games");
}
private static void CMInvoke()
{ }
private static void CMSave()
{
Games.Export();
}
private static void CMLoad()
{
Games.Import();
}
private static void HandleCommand(CommandEventArgs e)
{
if (CMOptions.ModuleEnabled)
{
new ArcadeUI(e.Mobile).Send();
}
}
private static IGame CreateGame(Type t)
{
try
{
return t.CreateInstanceSafe<IGame>();
}
catch
{
return null;
}
}
public static ArcadeProfile EnsureProfile(Mobile m)
{
if (m == null)
{
return null;
}
var p = Profiles.GetValue(m);
if (p == null || p.Owner != m)
{
if (!m.Player || m.Deleted)
{
Profiles.Remove(m);
if (p != null)
{
p.Clear();
p = null;
}
}
else
{
Profiles[m] = p = new ArcadeProfile(m);
}
}
else if (!m.Player || m.Deleted)
{
Profiles.Remove(m);
p.Clear();
p = null;
}
return p;
}
public static bool OpenGame(Type t, Mobile m)
{
return VitaNexCore.TryCatchGet(
() =>
{
var g = Games.GetValue(t);
return g != null && g.Open(m);
},
CMOptions.ToConsole);
}
public static bool OpenGame<T>(Mobile m)
where T : IGame
{
return OpenGame(typeof(T), m);
}
public static void CloseGame(Mobile m, Type t)
{
VitaNexCore.TryCatch(
() =>
{
var g = Games.GetValue(t);
if (g != null)
{
g.Close(m);
}
},
CMOptions.ToConsole);
}
private static bool SerializeGames(GenericWriter writer)
{
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteBlockDictionary(
Games,
(w, t, g) =>
{
w.WriteType(t);
g.Serialize(w);
});
}
break;
}
return true;
}
private static bool DeserializeGames(GenericReader reader)
{
var version = reader.GetVersion();
switch (version)
{
case 0:
{
reader.ReadBlockDictionary(
r =>
{
var t = r.ReadType();
var g = Games.GetValue(t) ?? CreateGame(t);
g.Deserialize(r);
return new KeyValuePair<Type, IGame>(t, g);
},
Games);
}
break;
}
return true;
}
private static bool SerializeProfiles(GenericWriter writer)
{
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.WriteBlockDictionary(
Profiles,
(w, m, p) =>
{
w.Write(m);
p.Serialize(w);
});
}
break;
}
return true;
}
private static bool DeserializeProfiles(GenericReader reader)
{
var version = reader.GetVersion();
switch (version)
{
case 0:
{
reader.ReadBlockDictionary(
r =>
{
var m = r.ReadMobile();
var p = new ArcadeProfile(r);
return new KeyValuePair<Mobile, ArcadeProfile>(m, p);
},
Profiles);
}
break;
}
return true;
}
}
}

View File

@@ -0,0 +1,57 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
#endregion
namespace VitaNex.Modules.Games
{
public sealed class TrapSweeper : Game<TrapSweeperEngine>
{
private readonly IconDefinition _Icon = IconDefinition.FromGump(24013, 1258);
public override IconDefinition Icon => _Icon;
public override string Name => "Trap Sweeper";
public override string Desc => "Sweep the castle for traps!";
public override string Help => _Help;
private static readonly string _Help = String.Concat(
"<BIG>Rules & Basics</BIG>",
"<BR>",
"<BR><BIG>Objective</BIG>",
"<BR>Find the empty tiles while avoiding the traps.",
"<BR>The faster you clear the floor, the better your score.",
"<BR>",
"<BR><BIG>Floors</BIG>",
"<BR>There are three floors to choose from, each more difficult than the last.",
"<BR>",
"<BR><B>* Rookie:</B> Easy mode, small floor.",
"<BR><B>* Guard:</B> Normal mode, medium floor.",
"<BR><B>* Knight:</B> Expert mode, large floor.",
"<BR><B>* Random:</B> Generates a random floor.",
"<BR>",
"<BR><BIG>Rules</BIG>",
"<BR>Reveal a trap, you die.",
"<BR>Reveal an empty tile, you continue sweeping.",
"<BR>Reveal a bonus tile, you continue and collect a reward when you win.",
"<BR>Reveal a number tile, you continue and it tells you how many traps lay hidden in the eight surrounding tiles.",
"<BR><I>These numbers will help you decide which tiles are safe to reveal.</I>",
"<BR>",
"<BR><BIG>Tips</BIG>",
"<BR>Mark the traps!",
"<BR>If you think a tile hides a trap, select Mark and click it, this will highlight the tile.",
"<BR>You can unhighlight a tile by selecting Mark and clicking it again.");
}
}

View File

@@ -0,0 +1,789 @@
#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 System.Threading;
using System.Threading.Tasks;
using Server;
#endregion
namespace VitaNex.Modules.Games
{
public class TrapSweeperEngine : GameEngine<TrapSweeper, TrapSweeperUI>
{
public const int MinWidth = 10;
public const int MaxWidth = 22;
public const int MinHeight = 10;
public const int MaxHeight = 15;
public const int MinDensity = 10;
public const int MaxDensity = 30;
public const int MinBonusDensity = 1;
public const int MaxBonusDensity = 3;
public const int MinPoints = 100;
public const int MaxPoints = 500;
private Grid<TrapSweeperTile> _Grid;
public int Width => _Grid != null ? _Grid.Width : 0;
public int Height => _Grid != null ? _Grid.Height : 0;
public int Capacity => _Grid != null ? _Grid.Capacity : 0;
public int Count => _Grid != null ? _Grid.Count : 0;
public TrapSweeperState State { get; private set; }
public TrapSweeperMode Mode { get; private set; }
public DateTime Started { get; private set; }
public DateTime Ended { get; private set; }
public bool Mark { get; private set; }
public int Blanks { get; private set; }
public int Traps { get; private set; }
public int Bonuses { get; private set; }
public int Visible { get; private set; }
public int Marked { get; private set; }
public int Rewards { get; private set; }
public TrapSweeperEngine(TrapSweeper game, Mobile user)
: base(game, user)
{
_Grid = new Grid<TrapSweeperTile>();
}
public override void Reset()
{
base.Reset();
Visible = 0;
Marked = 0;
Rewards = 0;
Mark = false;
}
public IEnumerable<TrapSweeperTile> AllTiles()
{
return _Grid ?? _Grid.Ensure();
}
public IEnumerable<TrapSweeperTile> FindTiles(int x, int y, int w, int h)
{
return _Grid == null ? _Grid.Ensure() : _Grid.FindCells(x, y, w, h);
}
public IEnumerable<T> AllTiles<T>()
where T : TrapSweeperTile
{
return (_Grid ?? _Grid.Ensure()).OfType<T>();
}
public IEnumerable<T> FindTiles<T>(int x, int y, int w, int h)
where T : TrapSweeperTile
{
return (_Grid == null ? _Grid.Ensure() : _Grid.FindCells(x, y, w, h)).OfType<T>();
}
public void Generate(int w, int h, int d, int b, int p)
{
if (!Validate())
{
Dispose();
return;
}
w = Math.Max(MinWidth, Math.Min(MaxWidth, w));
h = Math.Max(MinHeight, Math.Min(MaxHeight, h));
d = Math.Max(MinDensity, Math.Min(MaxDensity, d));
b = Math.Max(MinBonusDensity, Math.Min(MaxBonusDensity, b));
p = Math.Max(MinPoints, Math.Min(MaxPoints, p));
if (_Grid == null)
{
_Grid = new Grid<TrapSweeperTile>(w, h);
}
else if (_Grid.Width != w || _Grid.Height != h)
{
_Grid.Resize(w, h);
}
_Grid.SetAllContent((x, y) => null);
var q = new List<Point2D>(_Grid.Capacity);
_Grid.ForEach((x, y, t) => q.Add(new Point2D(x, y)));
q.Shuffle();
var traps = (int)Math.Floor(q.Count * (d / 100.0));
var bonus = (int)Math.Floor((q.Count - traps) * (b / 100.0));
Parallel.ForEach(
q,
t =>
{
if (traps > 0)
{
_Grid[t.X, t.Y] = new TrapSweeperTileTrap(this, t.X, t.Y);
Interlocked.Decrement(ref traps);
}
else if (bonus > 0)
{
_Grid[t.X, t.Y] = new TrapSweeperTileBonus(this, t.X, t.Y);
Interlocked.Decrement(ref bonus);
}
else
{
_Grid[t.X, t.Y] = new TrapSweeperTileBlank(this, t.X, t.Y);
}
});
q.Free(true);
Blanks = Traps = Bonuses = 0;
foreach (var t in AllTiles())
{
if (t is TrapSweeperTileBlank)
{
++Blanks;
t.Points = p;
}
else if (t is TrapSweeperTileTrap)
{
++Traps;
t.Points = 0;
}
else if (t is TrapSweeperTileBonus)
{
++Bonuses;
t.Points = p * 2;
}
}
Reset();
}
public void GenerateEasy()
{
if (!Validate())
{
Dispose();
return;
}
Generate(MinWidth, MinHeight, MinDensity, MinBonusDensity, MinPoints);
}
public void GenerateNormal()
{
if (!Validate())
{
Dispose();
return;
}
const int w = MinWidth + ((MaxWidth - MinWidth) / 2);
const int h = MinHeight + ((MaxHeight - MinHeight) / 2);
const int d = MinDensity + ((MaxDensity - MinDensity) / 2);
const int b = MinBonusDensity + ((MaxBonusDensity - MinBonusDensity) / 2);
const int p = MinPoints + ((MaxPoints - MinPoints) / 2);
Generate(w, h, d, b, p);
}
public void GenerateHard()
{
if (!Validate())
{
Dispose();
return;
}
Generate(MaxWidth, MaxHeight, MaxDensity, MaxBonusDensity, MaxPoints);
}
public void GenerateRandom()
{
if (!Validate())
{
Dispose();
return;
}
Generate(
Utility.RandomMinMax(MinWidth, MaxWidth),
Utility.RandomMinMax(MinHeight, MaxHeight),
Utility.RandomMinMax(MinDensity, MaxDensity),
Utility.RandomMinMax(MinBonusDensity, MaxBonusDensity),
Utility.RandomMinMax(MinPoints, MaxPoints));
}
public void DoCollect()
{
if (!Validate())
{
Dispose();
return;
}
// TODO: Give Rewards
DoMenu();
}
public void DoMenu()
{
if (!Validate())
{
Dispose();
return;
}
UI.CanDispose = true;
if (State == TrapSweeperState.Play)
{
State = TrapSweeperState.Menu;
DoEnd(false);
}
else
{
State = TrapSweeperState.Menu;
UI.Refresh(true);
}
}
public void DoMode(TrapSweeperMode opt)
{
if (!Validate())
{
Dispose();
return;
}
Mode = opt;
UI.Refresh(true);
}
public void DoMark()
{
if (!Validate())
{
Dispose();
return;
}
Mark = !Mark;
UI.Refresh(true);
}
public void DoPlay()
{
if (!Validate())
{
Dispose();
return;
}
UI.CanDispose = false;
switch (Mode)
{
case TrapSweeperMode.Easy:
GenerateEasy();
break;
case TrapSweeperMode.Normal:
GenerateNormal();
break;
case TrapSweeperMode.Hard:
GenerateHard();
break;
case TrapSweeperMode.Random:
GenerateRandom();
break;
}
DoStart();
}
public void DoQuit()
{
if (!Validate())
{
Dispose();
return;
}
UI.CanDispose = true;
if (State == TrapSweeperState.Play)
{
State = TrapSweeperState.Menu;
DoEnd(false);
}
else if (State != TrapSweeperState.Menu)
{
State = TrapSweeperState.Menu;
UI.Refresh(true);
}
else
{
State = TrapSweeperState.Menu;
UI.Close(true);
}
}
public void DoStart()
{
if (!Validate())
{
Dispose();
return;
}
UI.CanDispose = false;
State = TrapSweeperState.Play;
Started = DateTime.UtcNow;
UI.Refresh(true);
}
public void DoEnd(bool win)
{
if (!Validate())
{
Dispose();
return;
}
UI.CanDispose = true;
State = win ? TrapSweeperState.Win : TrapSweeperState.Lose;
Ended = DateTime.UtcNow;
if (win)
{
var factor = 1.0;
var time = Ended - Started;
if (time.TotalMinutes > 0)
{
double threshold, multiplier;
switch (Mode)
{
case TrapSweeperMode.Easy:
{
threshold = 10.0;
multiplier = 0.33;
}
break;
case TrapSweeperMode.Normal:
{
threshold = 10.0;
multiplier = 0.66;
}
break;
case TrapSweeperMode.Hard:
{
threshold = 10.0;
multiplier = 1.00;
}
break;
default:
{
threshold = Utility.RandomMinMax(10.0, 30.0);
multiplier = Utility.RandomMinMax(0.33, 1.00);
}
break;
}
if (time.TotalMinutes <= threshold)
{
factor += (1.0 - (time.TotalMinutes / threshold)) * multiplier;
}
}
OffsetPoints(Points * factor, true);
Log("Victories", 1, true);
}
else
{
OffsetPoints(-Points, true);
Log("Defeats", 1, true);
}
UI.Refresh(true);
}
protected override void OnDispose()
{
base.OnDispose();
if (_Grid != null)
{
_Grid.ForEach(
(x, y, t) =>
{
if (t != null)
{
t.Dispose();
}
});
_Grid.Free(true);
_Grid = null;
}
}
public abstract class TrapSweeperTile : IDisposable
{
public virtual int HiddenID => 9026;
public virtual int MarkID => 9026;
public virtual int ClickID => 9021;
public virtual int DisplayID => 9021;
public virtual int Hue => 0;
public bool IsDisposed { get; private set; }
public TrapSweeperEngine Engine { get; private set; }
public int X { get; private set; }
public int Y { get; private set; }
public int Points { get; set; }
private bool _Marked;
public bool Marked
{
get => _Marked;
set
{
if (!Validate())
{
Dispose();
return;
}
if (!_Marked && value)
{
if (Engine.Marked < Engine.Traps)
{
_Marked = true;
OnMarked();
}
}
else if (_Marked && !value)
{
_Marked = false;
OnUnmarked();
}
}
}
private bool _Visible;
public bool Visible
{
get => _Visible;
set
{
if (!Validate())
{
Dispose();
return;
}
if (!_Visible && value)
{
_Visible = true;
OnReveal();
}
else if (_Visible && !value)
{
_Visible = false;
OnHide();
}
}
}
public TrapSweeperTile(TrapSweeperEngine g, int x, int y)
{
Engine = g;
X = x;
Y = y;
}
~TrapSweeperTile()
{
Dispose();
}
public bool Validate()
{
return !IsDisposed && Engine != null && Engine.Validate();
}
public void Click()
{
if (!Validate())
{
Dispose();
return;
}
if (Engine.Mark)
{
ToggleMark();
}
else
{
ToggleVisibility();
}
Engine.UI.Refresh(true);
}
protected void ToggleMark()
{
if (!Validate())
{
Dispose();
return;
}
if (!Visible)
{
Marked = !Marked;
}
}
protected void ToggleVisibility()
{
if (!Validate())
{
Dispose();
return;
}
Marked = false;
Visible = !Visible;
}
public void Dispose()
{
if (IsDisposed)
{
return;
}
IsDisposed = true;
OnDispose();
if (Engine != null)
{
if (Engine._Grid != null)
{
Engine._Grid[X, Y] = null;
}
Engine = null;
}
X = Y = -1;
}
protected virtual void OnHide()
{
--Engine.Visible;
Engine.OffsetPoints(-Points, true);
}
protected virtual void OnReveal()
{
++Engine.Visible;
Engine.OffsetPoints(Points, true);
}
protected virtual void OnMarked()
{
++Engine.Marked;
}
protected virtual void OnUnmarked()
{
--Engine.Marked;
}
protected virtual void OnDispose()
{
if (Engine == null || Engine.IsDisposed)
{
_Visible = _Marked = false;
return;
}
if (_Visible)
{
--Engine.Visible;
}
if (_Marked)
{
--Engine.Marked;
}
_Visible = _Marked = false;
}
}
public sealed class TrapSweeperTileBlank : TrapSweeperTile
{
private int _Traps = -1;
public int Traps
{
get
{
if (!Validate())
{
Dispose();
return 0;
}
if (_Traps < 0)
{
_Traps = Engine.FindTiles<TrapSweeperTileTrap>(X - 1, Y - 1, 3, 3).Count();
}
return _Traps;
}
}
public override int DisplayID => Traps > 0 ? 2225 + (Traps - 1) : 9021;
public TrapSweeperTileBlank(TrapSweeperEngine g, int x, int y)
: base(g, x, y)
{ }
protected override void OnReveal()
{
base.OnReveal();
if (Engine.AllTiles<TrapSweeperTileBlank>().All(t => t.Visible))
{
Engine.DoEnd(true);
return;
}
Engine.IncreasePoints(Points, true);
if (Traps > 0)
{
return;
}
var p = 0.0;
foreach (var t in Engine.FindTiles<TrapSweeperTileBlank>(X - 1, Y - 1, 3, 3).Where(t => t != this && !t.Visible))
{
t.Visible = true;
p += t.Points;
}
Engine.OffsetPoints(p, true);
}
}
public sealed class TrapSweeperTileTrap : TrapSweeperTile
{
public override int DisplayID => 9020;
public override int Hue => 34;
public TrapSweeperTileTrap(TrapSweeperEngine g, int x, int y)
: base(g, x, y)
{ }
/*protected override void OnMarked()
{
base.OnMarked();
if (!Engine.AllTiles<SweeperTileTrap>().All(t => t.Marked))
{
return;
}
Engine.Rewards += Engine.AllTiles<SweeperTileBonus>().Count(t => !t.Visible);
Engine.DoEnd(true);
}*/
protected override void OnReveal()
{
base.OnReveal();
Engine.DecreasePoints(Points, true);
Engine.DoEnd(false);
}
}
public sealed class TrapSweeperTileBonus : TrapSweeperTile
{
public override int DisplayID => 9027;
public override int Hue => 85;
public TrapSweeperTileBonus(TrapSweeperEngine g, int x, int y)
: base(g, x, y)
{ }
protected override void OnReveal()
{
base.OnReveal();
++Engine.Rewards;
}
protected override void OnHide()
{
base.OnHide();
--Engine.Rewards;
}
}
}
}

View File

@@ -0,0 +1,21 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
namespace VitaNex.Modules.Games
{
public enum TrapSweeperMode
{
Easy,
Normal,
Hard,
Random
}
}

View File

@@ -0,0 +1,21 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
namespace VitaNex.Modules.Games
{
public enum TrapSweeperState
{
Menu,
Play,
Win,
Lose
}
}

View File

@@ -0,0 +1,368 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Drawing;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Modules.Games
{
public class TrapSweeperUI : GameUI<TrapSweeperEngine>
{
public TrapSweeperUI(TrapSweeperEngine engine)
: base(engine)
{
HighlightHue = 1258;
}
protected override void CompileLayout(SuperGumpLayout layout)
{
base.CompileLayout(layout);
if (Engine == null || Engine.IsDisposed)
{
return;
}
switch (Engine.State)
{
case TrapSweeperState.Menu:
CompileMenuLayout(layout);
break;
default:
CompilePlayLayout(layout);
break;
}
}
private void CompileMenuLayout(SuperGumpLayout layout)
{
layout.Add(
"window/menu/start",
() =>
{
AddImage(354, 256, 4501, HighlightHue);
AddButton(351, 254, 4501, 4501, b => Engine.DoPlay());
AddHtml(
140,
300,
435,
40,
"START SWEEPING!".WrapUOHtmlBold().WrapUOHtmlCenter().WrapUOHtmlColor(Color.Gold, false),
false,
false);
});
layout.Add(
"window/menu/option/easy",
() =>
{
var s = false;
// EASY
if (Engine.Mode != TrapSweeperMode.Easy)
{
AddImage(155, 330, 1417);
AddButton(164, 339, 5575, 5576, b => Engine.DoMode(TrapSweeperMode.Easy));
AddButton(145, 420, 5403, 5403, b => Engine.DoMode(TrapSweeperMode.Easy));
}
else
{
AddImage(155, 330, 1417, HighlightHue);
AddImage(164, 339, 5576);
s = true;
}
var text = "ROOKIE";
text = s ? text.WrapUOHtmlTag("U") : text;
text = text.WrapUOHtmlBig().WrapUOHtmlCenter().WrapUOHtmlColor(Color.Green, false);
AddBackground(145, 415, 100, 30, 9350);
AddHtml(145, 420, 100, 40, text, false, false);
});
layout.Add(
"window/menu/option/normal",
() =>
{
var s = false;
// NORMAL
if (Engine.Mode != TrapSweeperMode.Normal)
{
AddImage(262, 330, 1417);
AddButton(271, 339, 5587, 5588, b => Engine.DoMode(TrapSweeperMode.Normal));
AddButton(252, 420, 5403, 5403, b => Engine.DoMode(TrapSweeperMode.Normal));
}
else
{
AddImage(262, 330, 1417, HighlightHue);
AddImage(271, 339, 5588);
s = true;
}
var text = "GUARD";
text = s ? text.WrapUOHtmlTag("U") : text;
text = text.WrapUOHtmlBig().WrapUOHtmlCenter().WrapUOHtmlColor(Color.Yellow, false);
AddBackground(252, 415, 100, 30, 9350);
AddHtml(252, 420, 100, 40, text, false, false);
});
layout.Add(
"window/menu/option/hard",
() =>
{
var s = false;
// HARD
if (Engine.Mode != TrapSweeperMode.Hard)
{
AddImage(368, 330, 1417);
AddButton(377, 339, 5547, 5548, b => Engine.DoMode(TrapSweeperMode.Hard));
AddButton(358, 420, 5403, 5403, b => Engine.DoMode(TrapSweeperMode.Hard));
}
else
{
AddImage(368, 330, 1417, HighlightHue);
AddImage(377, 339, 5548);
s = true;
}
var text = "KNIGHT";
text = s ? text.WrapUOHtmlTag("U") : text;
text = text.WrapUOHtmlBig().WrapUOHtmlCenter().WrapUOHtmlColor(Color.Red, false);
AddBackground(358, 415, 100, 30, 9350);
AddHtml(358, 420, 100, 40, text, false, false);
});
layout.Add(
"window/menu/option/random",
() =>
{
var s = false;
// RANDOM
if (Engine.Mode != TrapSweeperMode.Random)
{
AddImage(475, 330, 1417);
AddButton(484, 339, 5583, 5584, b => Engine.DoMode(TrapSweeperMode.Random));
AddButton(465, 420, 5403, 5403, b => Engine.DoMode(TrapSweeperMode.Random));
}
else
{
AddImage(475, 330, 1417, HighlightHue);
AddImage(484, 339, 5584);
s = true;
}
var text = "RANDOM";
text = s ? text.WrapUOHtmlTag("U") : text;
text = text.WrapUOHtmlBig().WrapUOHtmlCenter().WrapUOHtmlColor(Color.Blue, false);
AddBackground(465, 415, 100, 30, 9350);
AddHtml(465, 420, 100, 40, text, false, false);
});
}
private void CompilePlayLayout(SuperGumpLayout layout)
{
layout.Add(
"window/play",
() =>
{
AddBackground(133, 100, 450, 350, 9200);
AddBackground(142, 130, 435, 315, 9300);
});
layout.Add(
"window/play/info",
() =>
{
if (Engine.State == TrapSweeperState.Lose)
{
AddImage(325, 55, 7034, 34);
AddImage(270, 32, 50562);
}
else
{
AddImage(325, 55, 7034);
}
AddImage(230, 60, 30082, HighlightHue);
AddImage(315, 45, 30061, HighlightHue);
AddImage(390, 60, 30080, HighlightHue);
});
layout.Add(
"window/play/info/traps",
() =>
{
AddImage(260, 50, 20999);
AddBackground(185, 50, 75, 44, 9300);
var count = Engine.Traps - Engine.Marked;
AddHtml(185, 65, 75, 40, count.ToString("#,0").WrapUOHtmlCenter(), false, false);
});
layout.Add(
"window/play/info/time",
() =>
{
AddImage(415, 50, 23000);
AddBackground(460, 50, 75, 44, 9300);
TimeSpan time;
switch (Engine.State)
{
case TrapSweeperState.Lose:
time = Engine.Ended - Engine.Started;
break;
default:
time = DateTime.UtcNow - Engine.Started;
break;
}
AddHtml(460, 65, 75, 40, time.ToSimpleString("h:m:s").WrapUOHtmlCenter(), false, false);
});
layout.Add(
"window/play/game/grid",
() =>
{
var w = Engine.Width * 19;
var h = Engine.Height * 20;
var xo = 148 + ((418 - w) / 2);
var yo = 137 + ((300 - h) / 2);
foreach (var t in Engine.AllTiles())
{
if (t == null)
{
return;
}
if (Engine.State == TrapSweeperState.Play && !t.Visible)
{
AddButton(xo + (t.X * 19), yo + (t.Y * 20), t.Marked ? t.MarkID : t.HiddenID, t.ClickID, b => t.Click());
}
else
{
AddImage(xo + (t.X * 19), yo + (t.Y * 20), t.DisplayID, t.Hue);
}
AddImage(xo + (t.X * 19), yo + (t.Y * 20), 9028, t.Marked ? HighlightHue : 0);
}
});
switch (Engine.State)
{
case TrapSweeperState.Play:
{
layout.Add(
"window/play/mark",
() =>
{
var text = "MARK";
text = text.WrapUOHtmlBold().WrapUOHtmlCenter().WrapUOHtmlColor(Color.PaleGoldenrod, false);
AddHtml(45, 355, 80, 40, text, false, false);
AddButton(50, 380, 7031, 7031, b => Engine.DoMark());
if (Engine.Mark)
{
AddImage(50, 380, 7031, HighlightHue);
}
});
}
break;
case TrapSweeperState.Win:
{
layout.Add("window/play/results", () => AddAlphaRegion(142, 130, 435, 315));
layout.Add(
"window/play/collect",
() =>
{
var text = "COLLECT";
text = text.WrapUOHtmlBold().WrapUOHtmlCenter().WrapUOHtmlColor(Color.LawnGreen, false);
AddHtml(45, 355, 80, 40, text, false, false);
AddButton(50, 380, 7012, 7012, b => Engine.DoCollect());
AddImage(50, 380, 7012, 85);
});
}
break;
case TrapSweeperState.Lose:
{
layout.Add(
"window/play/menu",
() =>
{
var text = "RESURRECT";
text = text.WrapUOHtmlBold().WrapUOHtmlCenter().WrapUOHtmlColor(Color.Orange, false);
AddHtml(45, 355, 80, 40, text, false, false);
AddButton(50, 380, 7007, 7007, b => Engine.DoMenu());
AddImage(50, 380, 7007, HighlightHue);
});
layout.Add(
"window/play/blood",
() =>
{
AddItem(65, 73, 7572);
AddItem(273, 59, 7574);
AddItem(348, 58, 4655);
AddItem(599, 37, 7573);
AddItem(585, 310, 4652);
AddItem(603, 327, 4653);
AddItem(594, 450, 4650);
});
}
break;
}
}
protected override void OnQuit()
{
base.OnQuit();
if (Engine.State == TrapSweeperState.Win)
{
Engine.DoCollect();
}
else
{
Engine.DoQuit();
}
}
}
}

View File

@@ -0,0 +1,178 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Drawing;
using System.Text;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Modules.Games
{
public abstract class GameUI<TEngine> : SuperGump, IGameUI
where TEngine : class, IGameEngine
{
public bool IsDisposing { get; private set; }
public TEngine Engine { get; private set; }
public GameUI(TEngine engine)
: base(engine.User)
{
Engine = engine;
RandomButtonID = true;
ForceRecompile = true;
}
public bool Validate()
{
return !IsDisposed && !IsDisposing && Engine != null && !Engine.IsDisposed && User != null && !User.Deleted;
}
protected override void OnDispose()
{
if (IsDisposed || IsDisposing)
{
return;
}
IsDisposing = true;
base.OnDispose();
}
protected override void OnDisposed()
{
base.OnDisposed();
IsDisposing = false;
}
protected override void OnClosed(bool all)
{
base.OnClosed(all);
if (!all)
{
OnQuit();
}
else
{
Engine.Dispose();
}
}
protected override void CompileLayout(SuperGumpLayout layout)
{
base.CompileLayout(layout);
layout.Add(
"window",
() =>
{
AddBackground(0, 0, 650, 490, 2620);
AddImage(5, 5, 9001);
AddImage(5, 5, 9002, 901);
});
layout.Add(
"window/title",
() =>
{
var title = GetTitle();
AddImage(10, 10, 2440, 901);
AddHtml(10, 12, 166, 40, title, false, false);
});
layout.Add(
"window/score",
() =>
{
var points = GetPoints();
AddImage(180, 10, 2440, 901);
AddHtml(180, 12, 166, 40, points, false, false);
});
layout.Add("window/quit", () => { AddButton(560, 5, 5514, 5515, Close); });
}
protected virtual void OnQuit()
{ }
public virtual string GetPoints()
{
if (Engine == null)
{
return String.Empty;
}
var p = String.Format("Points: {0:#,0.##}", Engine.Points);
var t = new StringBuilder();
var c1 = Color.Gold;
var c2 = Color.PaleGoldenrod;
for (var i = 0; i < p.Length; i++)
{
if (!Char.IsWhiteSpace(p, i))
{
t.Append(p[i].ToString().WrapUOHtmlColor(c1.Interpolate(c2, i / (p.Length - 1.0)), false));
}
else
{
t.Append(p[i]);
}
}
return t.ToString().WrapUOHtmlBig().WrapUOHtmlCenter();
}
public virtual string GetTitle()
{
if (Engine == null || Engine.Game == null)
{
return String.Empty;
}
var n = Engine.Game.Name.Trim();
var t = new StringBuilder();
var c1 = Color.Gold;
var c2 = Color.PaleGoldenrod;
for (var i = 0; i < n.Length; i++)
{
if (!Char.IsWhiteSpace(n, i))
{
t.Append(n[i].ToString().WrapUOHtmlColor(c1.Interpolate(c2, i / (n.Length - 1.0)), false));
}
else
{
t.Append(n[i]);
}
}
return t.ToString().WrapUOHtmlBig().WrapUOHtmlCenter();
}
#region Explicit Impl
IGameEngine IGameUI.Engine => Engine;
#endregion
}
}

View File

@@ -0,0 +1,56 @@
#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 Server;
#endregion
namespace VitaNex.Modules.Games
{
public interface IGame
{
Type EngineType { get; }
IconDefinition Icon { get; }
string Name { get; }
string Desc { get; }
string Help { get; }
bool Enabled { get; set; }
IEnumerable<IGameEngine> Sessions { get; }
int SessionCount { get; }
IGameEngine this[Mobile user] { get; set; }
GameStatistics Statistics { get; }
void Enable();
void Disable();
bool Validate(Mobile user);
bool Open(Mobile user);
void Close(Mobile user);
void Reset(Mobile user);
void Log(string context, double value, bool offset);
void LogIncrease(string context, double value);
void LogDecrease(string context, double value);
void Serialize(GenericWriter writer);
void Deserialize(GenericReader reader);
}
}

View File

@@ -0,0 +1,57 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.Games
{
public interface IGameEngine : IDisposable
{
Type UIType { get; }
bool IsDisposed { get; }
bool IsDisposing { get; }
Mobile User { get; }
IGame Game { get; }
IGameUI UI { get; }
ArcadeProfile Profile { get; }
GameStatistics Statistics { get; }
double Points { get; }
bool Validate();
bool Open();
void Close();
void Reset();
void LogStatistics();
void Log(string context, double value, bool offset);
void LogIncrease(string context, double value);
void LogDecrease(string context, double value);
void OffsetPoints(double value, bool log);
void IncreasePoints(double value, bool log);
void DecreasePoints(double value, bool log);
void Serialize(GenericWriter writer);
void Deserialize(GenericReader reader);
}
}

View File

@@ -0,0 +1,31 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Modules.Games
{
public interface IGameUI : IDisposable
{
bool IsDisposed { get; }
bool IsDisposing { get; }
IGameEngine Engine { get; }
Mobile User { get; }
bool Validate();
}
}

View File

@@ -0,0 +1,162 @@
#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 Server;
#endregion
namespace VitaNex.Modules.Games
{
public sealed class ArcadeProfile : PropertyObject, IEnumerable<KeyValuePair<string, GameStatistics>>
{
private Dictionary<string, GameStatistics> _Statistics = new Dictionary<string, GameStatistics>();
public GameStatistics this[string key]
{
get => _Statistics.GetValue(key) ?? (_Statistics[key] = new GameStatistics());
set => _Statistics[key] = value;
}
public Dictionary<string, GameStatistics>.KeyCollection Categories => _Statistics.Keys;
public Mobile Owner { get; private set; }
public int Credits { get; set; }
public ArcadeProfile(Mobile owner)
{
Owner = owner;
}
public ArcadeProfile(GenericReader reader)
: base(reader)
{ }
public override void Clear()
{
foreach (var v in _Statistics.Values)
{
v.Clear();
}
_Statistics.Clear();
}
public override void Reset()
{
foreach (var v in _Statistics.Values)
{
v.Reset();
}
}
public void Log(IGame g, string context, double value, bool offset)
{
if (offset)
{
if (value > 0)
{
LogIncrease(g, context, value);
}
else if (value < 0)
{
LogDecrease(g, context, value);
}
}
else
{
this[g.Name][context] = value;
}
}
public void LogIncrease(IGame g, string context, double value)
{
value = Math.Abs(value);
this[g.Name][context] += value;
}
public void LogDecrease(IGame g, string context, double value)
{
value = Math.Abs(value);
this[g.Name][context] -= value;
}
public IEnumerator<KeyValuePair<string, GameStatistics>> GetEnumerator()
{
return _Statistics.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
writer.Write(Owner);
switch (version)
{
case 0:
{
writer.Write(Credits);
writer.WriteBlockDictionary(
_Statistics,
(w, k, v) =>
{
w.Write(k);
v.Serialize(w);
});
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
Owner = reader.ReadMobile();
switch (version)
{
case 0:
{
Credits = reader.ReadInt();
_Statistics = reader.ReadBlockDictionary(
r =>
{
var k = r.ReadString();
var v = new GameStatistics(r);
return new KeyValuePair<string, GameStatistics>(k, v);
},
_Statistics);
}
break;
}
}
}
}

View File

@@ -0,0 +1,343 @@
#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 Server;
#endregion
namespace VitaNex.Modules.Games
{
public abstract class Game<TEngine> : IGame, IEnumerable<TEngine>
where TEngine : class, IGameEngine
{
private readonly Type _EngineType = typeof(TEngine);
[CommandProperty(Arcade.Access)]
public Type EngineType => _EngineType;
[CommandProperty(Arcade.Access)]
public abstract IconDefinition Icon { get; }
[CommandProperty(Arcade.Access)]
public abstract string Name { get; }
[CommandProperty(Arcade.Access)]
public abstract string Desc { get; }
[CommandProperty(Arcade.Access)]
public abstract string Help { get; }
private bool _Enabled;
[CommandProperty(Arcade.Access)]
public bool Enabled
{
get => _Enabled;
set
{
if (_Enabled && !value)
{
_Enabled = false;
OnDisabled();
Flush();
}
else if (!_Enabled && value)
{
_Enabled = true;
OnEnabled();
}
}
}
private List<TEngine> _Sessions;
public IEnumerable<TEngine> Sessions
{
get
{
var c = _Sessions.Count;
while (--c >= 0)
{
if (!_Sessions.InBounds(c))
{
continue;
}
var e = _Sessions[c];
if (e != null && !e.IsDisposed && !e.IsDisposing)
{
yield return e;
}
}
}
}
[CommandProperty(Arcade.Access)]
public int SessionCount => _Sessions.Count;
public TEngine this[Mobile user]
{
get => _Sessions.Find(e => e != null && e.User == user);
private set
{
if (user == null)
{
return;
}
var e = this[user];
if (value != null)
{
if (e == value)
{
return;
}
if (e != null)
{
e.Dispose();
_Sessions.Remove(e);
}
_Sessions.Update(value);
}
else if (e != null)
{
e.Dispose();
_Sessions.Remove(e);
}
}
}
[CommandProperty(Arcade.Access)]
public GameStatistics Statistics { get; private set; }
public Game()
{
_Sessions = new List<TEngine>();
Statistics = new GameStatistics();
}
public void Flush()
{
foreach (var e in Sessions)
{
e.Dispose();
}
_Sessions.Clear();
}
public void Enable()
{
Enabled = true;
}
public void Disable()
{
Enabled = false;
}
protected virtual void OnEnabled()
{ }
protected virtual void OnDisabled()
{ }
protected TEngine EnsureSession(Mobile user)
{
if (user == null)
{
return null;
}
var e = this[user];
if (e == null || !e.IsDisposing || e.IsDisposed)
{
if (user.Deleted || !user.IsOnline())
{
return null;
}
this[user] = e = EngineType.CreateInstanceSafe<TEngine>(this, user);
}
else if (user.Deleted || !user.IsOnline())
{
this[user] = null;
}
return e;
}
public bool Validate(Mobile user)
{
var e = EnsureSession(user);
return e != null && e.Validate();
}
public bool Open(Mobile user)
{
var e = EnsureSession(user);
if (e == null)
{
return false;
}
if (!e.Open() || !e.Validate())
{
e.Dispose();
return false;
}
return true;
}
public void Close(Mobile user)
{
this[user] = null;
}
public void Reset(Mobile user)
{
var e = EnsureSession(user);
if (e != null && e.Validate())
{
e.Reset();
}
}
public void Log(string context, double value, bool offset)
{
if (offset)
{
if (value > 0)
{
LogIncrease(context, value);
}
else if (value < 0)
{
LogDecrease(context, value);
}
}
else
{
Statistics[context] = value;
}
}
public void LogIncrease(string context, double value)
{
value = Math.Abs(value);
Statistics[context] += value;
}
public void LogDecrease(string context, double value)
{
value = Math.Abs(value);
Statistics[context] -= value;
}
public IEnumerator<TEngine> GetEnumerator()
{
return _Sessions.GetEnumerator();
}
public virtual void Serialize(GenericWriter writer)
{
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(_Enabled);
Statistics.Serialize(writer);
writer.WriteBlockList(
_Sessions,
(w, e) =>
{
w.Write(e.User);
e.Serialize(w);
});
}
break;
}
}
public virtual void Deserialize(GenericReader reader)
{
var version = reader.GetVersion();
switch (version)
{
case 0:
{
_Enabled = reader.ReadBool();
Statistics.Deserialize(reader);
_Sessions = reader.ReadBlockList(
r =>
{
var e = EnsureSession(r.ReadMobile());
e.Deserialize(r);
return e;
},
_Sessions);
}
break;
}
}
#region Explicit Impl
IEnumerable<IGameEngine> IGame.Sessions => Sessions;
IGameEngine IGame.this[Mobile user]
{
get => this[user];
set
{
if (value == null || value is TEngine)
{
this[user] = (TEngine)value;
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
}

View File

@@ -0,0 +1,302 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Modules.Games
{
public abstract class GameEngine<TGame, TGump> : IGameEngine
where TGame : class, IGame
where TGump : SuperGump, IGameUI
{
private readonly Type _UIType = typeof(TGump);
public Type UIType => _UIType;
public bool IsDisposing { get; private set; }
public bool IsDisposed { get; private set; }
public Mobile User { get; private set; }
public TGame Game { get; private set; }
public TGump UI { get; private set; }
public ArcadeProfile Profile => Arcade.EnsureProfile(User);
public GameStatistics Statistics { get; private set; }
public double PointsTotal
{
get => Statistics["Points Total"];
private set => Statistics["Points Total"] = value;
}
public double PointsGained
{
get => Statistics["Points Gained"];
private set => Statistics["Points Gained"] = value;
}
public double PointsLost
{
get => Statistics["Points Lost"];
private set => Statistics["Points Lost"] = value;
}
public double Points { get; private set; }
public GameEngine(TGame game, Mobile user)
{
Game = game;
User = user;
Statistics = new GameStatistics();
}
~GameEngine()
{
Dispose();
}
protected bool EnsureUI()
{
if (IsDisposed || IsDisposing)
{
return false;
}
if (User == null || User.Deleted)
{
if (UI != null)
{
UI.Close(true);
UI = null;
}
return false;
}
if (UI != null && UI.User != User)
{
UI.Close(true);
UI = null;
}
if (UI == null || UI.IsDisposed || UI.IsDisposing)
{
UI = UIType.CreateInstanceSafe<TGump>(this);
}
return UI != null && UI.Validate();
}
public bool Validate()
{
return !IsDisposed && !IsDisposing && UI != null && UI.Validate();
}
public virtual bool Open()
{
if (!EnsureUI() || !Validate())
{
Dispose();
return false;
}
UI.Refresh(true);
return true;
}
public virtual void Close()
{
if (UI != null && !UI.IsDisposed)
{
UI.Close(true);
}
}
public virtual void Reset()
{
Points = 0;
Statistics.Reset();
}
public void LogStatistics()
{
var p = Profile;
foreach (var kv in Statistics)
{
Game.Log(kv.Key, kv.Value, true);
if (p != null)
{
p.Log(Game, kv.Key, kv.Value, true);
}
}
Statistics.Reset();
}
public void Log(string context, double value, bool offset)
{
if (offset)
{
if (value > 0)
{
LogIncrease(context, value);
}
else if (value < 0)
{
LogDecrease(context, value);
}
}
else
{
Statistics[context] = value;
}
}
public void LogIncrease(string context, double value)
{
value = Math.Abs(value);
Statistics[context] += value;
}
public void LogDecrease(string context, double value)
{
value = Math.Abs(value);
Statistics[context] -= value;
}
public void OffsetPoints(double value, bool log)
{
if (value > 0)
{
IncreasePoints(value, log);
}
else if (value < 0)
{
DecreasePoints(value, log);
}
}
public void IncreasePoints(double value, bool log)
{
value = Math.Abs(value);
Points += value;
PointsTotal += value;
if (log)
{
PointsGained += value;
}
}
public void DecreasePoints(double value, bool log)
{
value = Math.Abs(value);
Points -= value;
PointsTotal -= value;
if (log)
{
PointsLost += value;
}
}
public void Dispose()
{
if (IsDisposed || IsDisposing)
{
return;
}
IsDisposing = true;
LogStatistics();
Close();
if (UI == null)
{
return;
}
if (UI.IsOpen || UI.Hidden)
{
UI.Close(true);
}
UI = null;
OnDispose();
if (Game != null && User != null)
{
Game[User] = null;
}
Statistics.Clear();
Statistics = null;
Game = null;
User = null;
IsDisposed = true;
OnDisposed();
IsDisposing = false;
}
protected virtual void OnDispose()
{ }
protected virtual void OnDisposed()
{ }
public virtual void Serialize(GenericWriter writer)
{
writer.SetVersion(0);
writer.Write(Points);
Statistics.Serialize(writer);
}
public virtual void Deserialize(GenericReader reader)
{
reader.GetVersion();
Points = reader.ReadDouble();
Statistics.Deserialize(reader);
}
#region Explicit Impl
IGame IGameEngine.Game => Game;
IGameUI IGameEngine.UI => UI;
#endregion
}
}

View File

@@ -0,0 +1,94 @@
#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 Server;
#endregion
namespace VitaNex.Modules.Games
{
public sealed class GameStatistics : PropertyObject, IEnumerable<KeyValuePair<string, double>>
{
private readonly Dictionary<string, double> _Statistics = new Dictionary<string, double>();
public double this[string key] { get => _Statistics.GetValue(key); set => _Statistics[key] = value; }
public Dictionary<string, double>.KeyCollection Entries => _Statistics.Keys;
public GameStatistics()
{ }
public GameStatistics(GenericReader reader)
: base(reader)
{ }
public override void Clear()
{
_Statistics.Clear();
}
public override void Reset()
{
_Statistics.Keys.ForEach(k => _Statistics[k] = 0);
}
public bool Remove(string key)
{
return key != null && _Statistics.Remove(key);
}
public IEnumerator<KeyValuePair<string, double>> GetEnumerator()
{
return _Statistics.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.WriteDictionary(
_Statistics,
(w, k, v) =>
{
w.Write(k);
w.Write(v);
});
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
reader.ReadDictionary(
r =>
{
var k = r.ReadString();
var v = r.ReadDouble();
return new KeyValuePair<string, double>(k, v);
},
_Statistics);
}
}
}

View File

@@ -0,0 +1,50 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Modules.Games
{
public sealed class ArcadeOptions : CoreModuleOptions
{
public ArcadeOptions()
: base(typeof(Arcade))
{ }
/*
public override void Clear()
{
base.Clear();
}
public override void Reset()
{
base.Reset();
}
*/
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
}

View File

@@ -0,0 +1,493 @@
#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 VitaNex.SuperGumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Modules.Games
{
public sealed class ArcadeUI : SuperGumpList<IGame>
{
public ArcadeProfile Profile { get; private set; }
public int Width { get; set; }
public int Height { get; set; }
public int Margin { get; set; }
public int Padding { get; set; }
public int MenuSize { get; set; }
public int IconSize { get; set; }
public int Rows { get; private set; }
public int Cols { get; private set; }
public IGame SelectedGame { get; private set; }
public ArcadeUI(Mobile user)
: base(user)
{
Profile = Arcade.EnsureProfile(User);
Sorted = true;
EnsureDefaults();
}
public void EnsureDefaults()
{
Width = 800;
Height = 600;
Margin = 30;
Padding = 15;
MenuSize = 250;
IconSize = 120;
InvalidateGrid();
}
public void InvalidateGrid()
{
Width = Math.Max(300, Math.Min(1024, Width));
Height = Math.Max(300, Math.Min(768, Height));
MenuSize = Math.Max(200, Math.Min(400, MenuSize));
IconSize = Math.Max(100, Math.Min(250, IconSize));
Rows = (int)Math.Floor(((Width - MenuSize) - (Padding * 2)) / (double)IconSize);
Cols = (int)Math.Floor((Height - (Padding * 2)) / (double)IconSize);
EntriesPerPage = Rows * Cols;
}
protected override void Compile()
{
if (Profile == null || Profile.Owner != User)
{
Profile = Arcade.EnsureProfile(User);
}
InvalidateGrid();
base.Compile();
}
protected override void CompileList(List<IGame> list)
{
list.Clear();
list.AddRange(Arcade.Games.Values);
base.CompileList(list);
}
public override int SortCompare(IGame a, IGame b)
{
var res = 0;
if (a.CompareNull(b, ref res))
{
return res;
}
return Insensitive.Compare(a.Name, b.Name);
}
protected override void CompileLayout(SuperGumpLayout layout)
{
base.CompileLayout(layout);
layout.Add(
"body",
() =>
{
AddBackground(0, 0, Width + (Margin * 2), Height + (Margin * 2), 2600);
AddBackground(Margin, Margin, MenuSize, Height, 9250);
AddBackground(Margin + MenuSize, Margin, Width - MenuSize, Height, 9250);
});
layout.Add(
"title",
() =>
{
var x = Margin + MenuSize + Padding;
var y = Margin + Padding;
var w = Width - (MenuSize + (Padding * 2));
var title = "Games Arcade";
title = title.WrapUOHtmlBig().WrapUOHtmlCenter().WrapUOHtmlColor(Color.Gold, false);
AddHtml(x, y, w, 40, title, false, false);
});
layout.Add(
"menu",
() =>
{
var x = Margin + Padding;
var y = Margin + Padding;
var w = MenuSize - (Padding * 2);
var h = Height - (Padding * 2);
CompileMenuLayout(x, y, w, h);
});
var games = GetListRange();
if (games != null)
{
var width = Cols * IconSize;
var height = Rows * IconSize;
var initX = Margin + MenuSize;
var initY = Margin + Padding;
if (width < Width - MenuSize)
{
initX += ((Width - MenuSize) - width) / 2;
}
if (height < Height)
{
initY += (Height - height) / 2;
}
var xOffset = initX;
var yOffset = initY;
var index = 0;
var col = 0;
var row = 0;
foreach (var game in games.Values)
{
CompileGameLayout(layout, index++, xOffset, yOffset, game);
xOffset += IconSize;
if (++col % Cols == 0)
{
xOffset = initX;
yOffset += IconSize;
if (++row % Rows == 0)
{
break;
}
}
}
if (col < Cols || row < Rows)
{
while (index < EntriesPerPage)
{
CompileGameLayout(layout, index++, xOffset, yOffset, null);
xOffset += IconSize;
if (++col % Cols == 0)
{
xOffset = initX;
yOffset += IconSize;
if (++row % Rows == 0)
{
break;
}
}
}
}
}
}
private void CompileGameLayout(SuperGumpLayout layout, int index, int x, int y, IGame game)
{
layout.Add("games/" + index, () => CompileGameLayout(x, y, IconSize, IconSize, game));
}
private void CompileGameLayout(int x, int y, int w, int h, IGame game)
{
if (game != null)
{
AddTileButton(x + Margin, y + Margin, w - (Margin * 2), h - (Margin * 2), b => SelectGame(game));
}
AddBackground(x, y, w, h, 2600);
if (game == null)
{
return;
}
y += Margin;
h -= Margin;
if (game.Icon != null && !game.Icon.IsEmpty)
{
var s = game.Icon.Size;
if (game.Enabled)
{
game.Icon.AddToGump(this, x + ((w - s.Width) / 2), y);
}
else
{
game.Icon.AddToGump(this, x + ((w - s.Width) / 2), y, 900);
}
y += s.Height + 5;
h -= s.Height + 5;
}
var text = game.Name.WrapUOHtmlBig().WrapUOHtmlCenter().WrapUOHtmlColor(Color.Gold, false);
AddHtml(x, y, w, h, text, false, false);
}
private void CompileMenuLayout(int x, int y, int w, int h)
{
if (SelectedGame == null)
{
return;
}
AddHtml(x, y, w, h - 95, GetDescription(SelectedGame), false, false);
y += h - 85;
var help = "Help";
help = help.WrapUOHtmlCenter();
if (SupportsUltimaStore)
{
help = help.WrapUOHtmlColor(Color.Gold, false);
AddButton(x + ((w - 126) / 2), y, 40019, 40029, b => SelectHelp(SelectedGame));
AddHtml(x + ((w - 126) / 2), y + 2, 126, 40, help, false, false);
}
else
{
help = help.WrapUOHtmlBig();
AddHtmlButton(x + ((w - 126) / 2), y, 126, 25, b => SelectHelp(SelectedGame), help, Color.White, Color.Empty);
}
y += 25;
var play = "Play";
play = play.WrapUOHtmlCenter();
if (SupportsUltimaStore)
{
if (SelectedGame.Enabled || User.AccessLevel >= Arcade.Access)
{
play = play.WrapUOHtmlColor(Color.Gold, false);
AddButton(x + ((w - 126) / 2), y, 40019, 40029, b => PlayGame(SelectedGame));
AddHtml(x + ((w - 126) / 2), y + 2, 126, 40, play, false, false);
}
else
{
play = play.WrapUOHtmlColor(Color.Gray, false);
AddImage(x + ((w - 126) / 2), y, 40019, 900);
AddHtml(x + ((w - 126) / 2), y + 2, 126, 40, play, false, false);
}
}
else
{
if (SelectedGame.Enabled)
{
play = play.WrapUOHtmlBig();
AddHtmlButton(x + ((w - 126) / 2), y, 126, 25, b => PlayGame(SelectedGame), play, Color.White, Color.Black);
}
else
{
play = play.WrapUOHtmlColor(Color.Gray, false);
AddRectangle(x + ((w - 126) / 2), y, 126, 25, Color.Black, true);
AddHtml(x + ((w - 126) / 2), y + 2, 126, 40, play, false, false);
}
}
if (User.AccessLevel < Arcade.Access)
{
return;
}
y += 25;
var label = SelectedGame.Enabled ? "Enabled" : "Disabled";
label = label.WrapUOHtmlCenter();
if (SupportsUltimaStore)
{
if (SelectedGame.Enabled)
{
label = label.WrapUOHtmlColor(Color.PaleGreen, false);
AddButton(x + ((w - 126) / 2), y, 40019, 40029, b => DisableGame(SelectedGame));
AddHtml(x + ((w - 126) / 2), y + 2, 126, 40, label, false, false);
}
else
{
label = label.WrapUOHtmlColor(Color.Gray, false);
AddButton(x + ((w - 126) / 2), y, 40019, 40029, b => EnableGame(SelectedGame));
AddHtml(x + ((w - 126) / 2), y + 2, 126, 40, label, false, false);
}
}
else
{
if (SelectedGame.Enabled)
{
label = label.WrapUOHtmlBig();
AddHtmlButton(
x + ((w - 126) / 2),
y,
126,
25,
b => DisableGame(SelectedGame),
label,
Color.PaleGreen,
Color.Black);
}
else
{
label = label.WrapUOHtmlBig();
AddHtmlButton(x + ((w - 126) / 2), y, 126, 25, b => EnableGame(SelectedGame), label, Color.Gray, Color.Black);
}
}
}
public string GetDescription(IGame game)
{
if (game == null)
{
return String.Empty;
}
var desc = new StringBuilder();
desc.Append("<CENTER>");
desc.AppendLine(game.Name.WrapUOHtmlBig().WrapUOHtmlColor(Color.Gold, false));
desc.AppendLine(String.Empty.WrapUOHtmlColor(Color.White, false));
desc.AppendLine(game.Desc);
desc.Append("</CENTER>");
return desc.ToString();
}
public void EnableGame(IGame game)
{
if (game == null)
{
Refresh(true);
return;
}
game.Enabled = true;
Refresh(true);
}
public void DisableGame(IGame game)
{
if (game == null)
{
Refresh(true);
return;
}
game.Enabled = false;
Refresh(true);
}
public void PlayGame(IGame game)
{
if (game == null || !game.Open(User))
{
Refresh(true);
}
}
public void SelectGame(IGame game)
{
SelectedGame = SelectedGame == game ? null : game;
Refresh(true);
}
public void SelectHelp(IGame game)
{
if (game == null)
{
Refresh(true);
return;
}
new NoticeDialogGump(User, Refresh())
{
Title = game.Name,
Html = game.Help,
Width = 500,
Height = 400,
HtmlColor = Color.White,
AcceptHandler = Refresh,
CancelHandler = Refresh
}.Send();
}
protected override void OnLayoutApplied()
{
base.OnLayoutApplied();
if (!SupportsUltimaStore)
{
return;
}
foreach (var e in Entries.OfType<GumpBackground>())
{
switch (e.GumpID)
{
case 2600:
e.GumpID = 39925;
break;
case 9250:
e.GumpID = 40000;
break;
}
}
}
}
}