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,913 @@
#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.ContextMenus;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Multis;
#endregion
namespace VitaNex.Items
{
public class RuneCodex : Item, ISecurable
{
public sealed class UICache : IEquatable<UICache>, IEquatable<PlayerMobile>
{
public enum ViewMode
{
Categories,
Entries
}
public PlayerMobile User { get; private set; }
public RuneCodexCategory Category { get; set; }
public Point2D CategoryScroll { get; set; }
public Point2D CategoryPoint { get; set; }
public RuneCodexEntry Entry { get; set; }
public Point2D EntryScroll { get; set; }
public Point2D EntryPoint { get; set; }
public ViewMode Mode { get; set; }
public bool EditMode { get; set; }
public UICache(PlayerMobile user)
{
User = user;
}
public override int GetHashCode()
{
return User == null ? 0 : User.Serial.Value;
}
public override bool Equals(object obj)
{
if (obj is UICache)
{
return Equals((UICache)obj);
}
if (obj is PlayerMobile)
{
return Equals((PlayerMobile)obj);
}
return false;
}
public bool Equals(UICache other)
{
return other != null && Equals(other.User);
}
public bool Equals(PlayerMobile other)
{
return User == other;
}
}
public static string DefaultDescription = "World Locations";
private string _Descripton = DefaultDescription;
private int _Charges;
[CommandProperty(AccessLevel.GameMaster)]
public string Descripton { get => _Descripton; set => SetDescription(value); }
[CommandProperty(AccessLevel.GameMaster)]
public RuneCodexCategoryGrid Categories { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public SecureLevel Level { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Charges
{
get => _Charges;
set
{
_Charges = Math.Max(0, value);
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int RecallChargeCost { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int GateChargeCost { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int CloneEntryChargeCost { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool EditLocked { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool AddLocked { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool RemoveLocked { get; set; }
public Dictionary<Type, int> ChargeTypes { get; private set; }
public List<UICache> Users { get; private set; }
[Constructable]
public RuneCodex()
: this(1000)
{ }
[Constructable]
public RuneCodex(int charges)
: base(0x22C5)
{
Users = new List<UICache>();
ChargeTypes = new Dictionary<Type, int>
{
{typeof(Gold), 100}
};
Categories = new RuneCodexCategoryGrid();
Charges = Math.Max(0, charges);
CloneEntryChargeCost = 5;
RecallChargeCost = 1;
GateChargeCost = 2;
Name = "Rune Codex";
Weight = 1.0;
Hue = 74;
LootType = LootType.Blessed;
}
public RuneCodex(Serial serial)
: base(serial)
{
Users = new List<UICache>();
}
public virtual bool CanAddCategories(Mobile m)
{
return m.AccessLevel > AccessLevel.Counselor || BlessedFor == m || (!AddLocked && IsAccessibleTo(m));
}
public virtual bool CanEditCategories(Mobile m)
{
return m.AccessLevel > AccessLevel.Counselor || BlessedFor == m || (!EditLocked && IsAccessibleTo(m));
}
public virtual bool CanRemoveCategories(Mobile m)
{
return m.AccessLevel > AccessLevel.Counselor || BlessedFor == m || (!RemoveLocked && IsAccessibleTo(m));
}
public virtual bool CanAddEntries(Mobile m)
{
return m.AccessLevel > AccessLevel.Counselor || BlessedFor == m || (!AddLocked && IsAccessibleTo(m));
}
public virtual bool CanEditEntries(Mobile m)
{
return m.AccessLevel > AccessLevel.Counselor || BlessedFor == m || (!EditLocked && IsAccessibleTo(m));
}
public virtual bool CanRemoveEntries(Mobile m)
{
return m.AccessLevel > AccessLevel.Counselor || BlessedFor == m || (!RemoveLocked && IsAccessibleTo(m));
}
public override bool IsAccessibleTo(Mobile check)
{
return check.AccessLevel > AccessLevel.Counselor || BlessedFor == check || base.IsAccessibleTo(check);
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
SetSecureLevelEntry.AddTo(from, this, list);
}
public override void OnDoubleClick(Mobile m)
{
if (!this.CheckDoubleClick(m, true, false, 3) || !(m is PlayerMobile))
{
return;
}
var pm = (PlayerMobile)m;
var ui = Users.FirstOrDefault(uic => uic.User == pm) ?? new UICache(pm);
Users.Update(ui);
new RuneCodexGump(pm, this).Send();
}
public void SetDescription(string desc)
{
_Descripton = String.IsNullOrWhiteSpace(desc) ? DefaultDescription : desc;
InvalidateProperties();
}
public virtual bool CanChargeWith(Mobile m, Item item, out int cost, bool message)
{
cost = 0;
if (m == null || m.Deleted || item == null || item.Deleted || !item.IsAccessibleTo(m))
{
return false;
}
var t = item.GetType();
if (ChargeTypes.ContainsKey(t))
{
cost = ChargeTypes[t];
return true;
}
if (message)
{
m.SendMessage("That item is not accepted for charging this codex.");
}
return false;
}
public virtual bool AddCharges(Mobile m, Item item, bool message)
{
if (m == null || m.Deleted || item == null || item.Deleted || !item.IsAccessibleTo(m))
{
return false;
}
if (!CanChargeWith(m, item, out var cost, message))
{
return false;
}
if (item.Amount < cost)
{
if (message)
{
m.SendMessage("One charge costs {0:#,0} {1}.", cost, item.ResolveName(m));
}
return false;
}
var c = (int)Math.Min((long)(Charges + (int)Math.Floor(item.Amount / (double)cost)), Int32.MaxValue) - Charges;
if (c <= 0)
{
return false;
}
var con = c * cost;
item.Consume(con);
Charges += c;
if (message)
{
m.SendMessage(
"You added {0:#,0} charge{1} to the codex and consumed {2:#,0} {3}.",
c,
c != 1 ? "s" : String.Empty,
con,
item.ResolveName());
}
InvalidateProperties();
return true;
}
public virtual bool AddRunebook(Mobile m, Runebook book, RuneCodexCategory cat, bool message)
{
if (m == null || m.Deleted || book == null || book.Deleted || !book.IsAccessibleTo(m))
{
return false;
}
if (cat == null)
{
var pm = m as PlayerMobile;
if (pm != null)
{
var ui = Users.FirstOrDefault(uic => uic.User == pm);
if (ui != null)
{
cat = ui.Category ?? Categories[ui.CategoryPoint.X, ui.CategoryPoint.Y];
}
else
{
cat = Categories[0, 0];
}
}
else
{
cat = Categories[0, 0];
}
}
if (book.Entries == null || book.Entries.Count == 0)
{
if (message)
{
m.SendMessage("That rune book is empty.");
}
return false;
}
if (Categories.Count >= Categories.Capacity)
{
if (message)
{
m.SendMessage("This rune codex can't hold more categories.");
}
return false;
}
if (cat != null && cat.AddRunebook(m, book, message))
{
InvalidateProperties();
return true;
}
return false;
}
public virtual bool AddRune(Mobile m, RecallRune rune, RuneCodexCategory cat, bool message)
{
if (m == null || m.Deleted || rune == null || rune.Deleted || !rune.IsAccessibleTo(m))
{
return false;
}
var pm = m as PlayerMobile;
var loc = Point2D.Zero;
if (cat == null)
{
if (pm != null)
{
var ui = Users.FirstOrDefault(uic => uic.User == pm);
if (ui != null)
{
cat = ui.Category ?? Categories[ui.CategoryPoint.X, ui.CategoryPoint.Y];
loc = ui.EntryPoint;
}
else
{
cat = Categories[0, 0];
}
}
else
{
cat = Categories[0, 0];
}
}
if (!rune.Marked || rune.Target == Point3D.Zero || rune.TargetMap == Map.Internal)
{
if (message)
{
m.SendMessage("That rune is blank.");
}
return false;
}
if (cat != null)
{
if (cat.Entries.Count >= cat.Entries.Capacity)
{
if (message)
{
m.SendMessage("The rune codex category \"{0}\" can't hold more runes.", cat.Description);
}
return false;
}
if (cat.SetRune(m, rune, loc, message))
{
InvalidateProperties();
return true;
}
}
return false;
}
public bool Add(Mobile m, Item item, RuneCodexCategory cat, bool message)
{
if (m == null || m.Deleted || item == null || item.Deleted || !item.IsAccessibleTo(m))
{
return false;
}
if (item is RecallRune)
{
return AddRune(m, (RecallRune)item, cat, message);
}
if (item is Runebook)
{
return AddRunebook(m, (Runebook)item, cat, message);
}
#region Master Runebook Support
//Using Reflection for shards that don't have it installed.
var t = item.GetType();
if (Insensitive.Equals(t.Name, "MasterRunebook"))
{
var pi = t.GetProperty("Books");
if (pi != null && pi.CanRead)
{
var obj = pi.GetValue(item, null);
if (obj is ICollection)
{
var ex = new Queue<Runebook>(((ICollection)obj).OfType<Runebook>().Where(r => r.Entries.Count > 0));
if (ex.Count == 0)
{
if (message)
{
m.SendMessage("That master rune book is empty.");
}
return false;
}
if (Categories.Count + ex.Count > Categories.Capacity)
{
if (message)
{
m.SendMessage("That master rune book won't fit in this rune codex.");
}
return false;
}
var extracted = 0;
while (ex.Count > 0)
{
var b = ex.Dequeue();
if (AddRunebook(m, b, cat, message))
{
++extracted;
}
}
if (extracted > 0)
{
if (message)
{
m.SendMessage(
"You extract {0:#,0} book{1} from the master rune book and add them to the codex.",
extracted,
extracted != 1 ? "s" : String.Empty);
}
return true;
}
if (message)
{
m.SendMessage("There was nothing in the master rune book to extract.");
}
}
}
return false;
}
#endregion Master Runebook Support
if (AddCharges(m, item, message))
{
return item.Deleted;
}
if (message)
{
m.SendMessage("Drop a rune book or recall rune on the codex to add them.");
}
return false;
}
public bool Remove(RuneCodexCategory cat)
{
for (var x = 0; x < Categories.Width; x++)
{
for (var y = 0; y < Categories.Height; y++)
{
if (Categories[x, y] != cat)
{
continue;
}
Categories[x, y] = null;
InvalidateProperties();
return true;
}
}
return false;
}
public bool Drop(Mobile m, RuneCodexCategory cat, bool message)
{
if (m == null || m.Deleted || cat == null)
{
return false;
}
if (cat.Entries == null || cat.Entries.Count == 0)
{
if (message)
{
m.SendMessage("The category \"{0}\" is empty.", cat.Name);
}
return false;
}
var cost = CloneEntryChargeCost * cat.Entries.Count;
if (!ConsumeCharges(cost))
{
if (message)
{
m.SendMessage("This action requires {0:#,0} charge{1}.", cost, cost != 1 ? "s" : String.Empty);
}
return false;
}
var entries = new Queue<RuneCodexEntry>(cat.Entries.Not(e => e == null));
var book = new Runebook();
var count = 1;
while (entries.Count > 0)
{
var entry = entries.Dequeue();
if (entry == null)
{
continue;
}
book.Entries.Add(
new RunebookEntry(
entry.Location,
entry.Location,
entry.Name,
BaseHouse.FindHouseAt(entry.Location, entry.Location, 16)));
if (book.Entries.Count < 16 && entries.Count > 0)
{
continue;
}
m.AddToBackpack(book);
if (entries.Count == 0)
{
continue;
}
book = new Runebook();
++count;
}
if (message)
{
m.SendMessage(
"You created {0:#,0} rune book{1} and consumed {2:#,0} charge{3} from the codex.",
count,
count != 1 ? "s" : String.Empty,
cost,
cost != 1 ? "s" : String.Empty);
}
return true;
}
public bool Drop(Mobile m, RuneCodexEntry entry, bool message)
{
if (m == null || m.Deleted || entry == null)
{
return false;
}
if (!ConsumeCharges(CloneEntryChargeCost))
{
m.SendMessage(
"This action requires {0:#,0} charge{1}.",
CloneEntryChargeCost,
CloneEntryChargeCost != 1 ? "s" : String.Empty);
return false;
}
m.AddToBackpack(
new RecallRune
{
Marked = true,
Target = entry.Location,
TargetMap = entry.Location,
Description = entry.Name,
House = BaseHouse.FindHouseAt(entry.Location, entry.Location, 16)
});
if (message)
{
m.SendMessage(
"You create a recall rune and consume {0:#,0} charge{1} from the codex.",
CloneEntryChargeCost,
CloneEntryChargeCost != 1 ? "s" : String.Empty);
}
return true;
}
public bool Recall(Mobile m, RuneCodexEntry entry, bool message)
{
if (m == null || m.Deleted || entry == null)
{
return false;
}
if (!ConsumeCharges(RecallChargeCost))
{
m.SendMessage(
"This action requires {0:#,0} charge{1}.",
RecallChargeCost,
RecallChargeCost != 1 ? "s" : String.Empty);
return false;
}
if (!entry.Recall(m))
{
Charges += RecallChargeCost;
return false;
}
return true;
}
public bool Gate(Mobile m, RuneCodexEntry entry, bool message)
{
if (m == null || m.Deleted || entry == null)
{
return false;
}
if (!ConsumeCharges(GateChargeCost))
{
m.SendMessage("This action requires {0:#,0} charge{1}.", GateChargeCost, GateChargeCost != 1 ? "s" : String.Empty);
return false;
}
if (!entry.Gate(m))
{
Charges += GateChargeCost;
return false;
}
return true;
}
public override bool OnDragDrop(Mobile m, Item dropped)
{
return Add(m, dropped, null, true);
}
public override void OnAfterDuped(Item newItem)
{
base.OnAfterDuped(newItem);
var c = newItem as RuneCodex;
if (c == null)
{
return;
}
c.AddLocked = AddLocked;
c.EditLocked = EditLocked;
c.RemoveLocked = RemoveLocked;
c.CloneEntryChargeCost = CloneEntryChargeCost;
c.RecallChargeCost = RecallChargeCost;
c.GateChargeCost = GateChargeCost;
c.Charges = Charges;
c.Descripton = Descripton;
c.Categories = new RuneCodexCategoryGrid();
c.ChargeTypes = new Dictionary<Type, int>(ChargeTypes);
c.Users = new List<UICache>();
RuneCodexCategory cata, catb;
RuneCodexEntry entrya, entryb;
for (var cx = 0; cx < Categories.Width; cx++)
{
for (var cy = 0; cy < Categories.Height; cy++)
{
cata = Categories[cx, cy];
if (cata == null)
{
continue;
}
catb = new RuneCodexCategory(cata.Name, cata.Description, cata.Hue);
c.Categories.SetContent(cx, cy, catb);
for (var ex = 0; ex < cata.Entries.Width; ex++)
{
for (var ey = 0; ey < cata.Entries.Width; ey++)
{
entrya = cata.Entries[ex, ey];
if (entrya == null)
{
continue;
}
entryb = new RuneCodexEntry(entrya.Name, entrya.Description, entrya.Location);
catb.Entries.SetContent(ex, ey, entryb);
}
}
}
}
}
public virtual bool ConsumeCharges(int amount)
{
amount = Math.Max(0, amount);
if (Charges < amount)
{
return false;
}
Charges -= amount;
return true;
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
// charges: ~1_val~
list.Add(1060741, Charges.ToString("#,0"));
var eTotal = 0;
var eCap = 0;
foreach (var c in Categories.Not(c => c == null))
{
eTotal += c.Entries.Count;
eCap += c.Entries.Capacity;
}
list.Add("Categories: {0} / {1}\nEntries: {2} / {3}", Categories.Count, Categories.Capacity, eTotal, eCap);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(3);
switch (version)
{
case 3:
writer.WriteFlag(Level);
goto case 2;
case 2:
writer.Write(RemoveLocked);
goto case 1;
case 1:
{
writer.Write(EditLocked);
writer.Write(AddLocked);
writer.Write(CloneEntryChargeCost);
writer.WriteDictionary(
ChargeTypes,
(k, v) =>
{
writer.WriteType(k);
writer.Write(v);
});
}
goto case 0;
case 0:
{
writer.Write(Charges);
writer.Write(RecallChargeCost);
writer.Write(GateChargeCost);
writer.Write(_Descripton);
Categories.Serialize(writer);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 3:
Level = reader.ReadFlag<SecureLevel>();
goto case 2;
case 2:
RemoveLocked = reader.ReadBool();
goto case 1;
case 1:
{
EditLocked = reader.ReadBool();
AddLocked = reader.ReadBool();
CloneEntryChargeCost = reader.ReadInt();
ChargeTypes = reader.ReadDictionary(
() =>
{
var k = reader.ReadType();
var v = reader.ReadInt();
return new KeyValuePair<Type, int>(k, v);
});
}
goto case 0;
case 0:
{
Charges = reader.ReadInt();
RecallChargeCost = reader.ReadInt();
GateChargeCost = reader.ReadInt();
_Descripton = reader.ReadString();
Categories = new RuneCodexCategoryGrid(reader);
}
break;
}
if (version > 0)
{
return;
}
Charges = 1000;
CloneEntryChargeCost = 5;
RecallChargeCost = 1;
GateChargeCost = 2;
ChargeTypes = new Dictionary<Type, int>
{
{typeof(Gold), 100}
};
}
}
}

View File

@@ -0,0 +1,349 @@
#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.Text;
using Server;
using Server.Items;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Items
{
public class RuneCodexCategory : PropertyObject
{
public static string DefaultName = "Misc Places";
public static string DefaultDescription = "A collection of places.";
public static int DefaultHue = 85;
private string _Name = DefaultName;
private string _Description = DefaultDescription;
private int _Hue = DefaultHue;
[CommandProperty(AccessLevel.GameMaster)]
public string Name { get => _Name; set => SetName(value); }
[CommandProperty(AccessLevel.GameMaster)]
public string Description { get => _Description; set => SetDescription(value); }
[CommandProperty(AccessLevel.GameMaster)]
public int Hue { get => _Hue; set => SetHue(value); }
[CommandProperty(AccessLevel.GameMaster)]
public RuneCodexEntryGrid Entries { get; set; }
public RuneCodexCategory()
: this(DefaultName, DefaultDescription, DefaultHue)
{ }
public RuneCodexCategory(string name, string desc, int hue)
{
Name = name;
Description = desc;
Hue = hue;
Entries = new RuneCodexEntryGrid();
}
public RuneCodexCategory(GenericReader reader)
: base(reader)
{ }
public override void Clear()
{
UseDefaults();
Empty();
}
public override void Reset()
{
UseDefaults();
Empty();
}
public virtual void UseDefaults()
{
Name = DefaultName;
Description = DefaultDescription;
Hue = DefaultHue;
}
public virtual void Empty()
{
Entries.SetAllContent(null, e => e != null);
}
public void SetName(string name)
{
_Name = String.IsNullOrWhiteSpace(name) ? DefaultName : name;
}
public void SetDescription(string desc)
{
_Description = String.IsNullOrWhiteSpace(desc) ? DefaultDescription : desc;
}
public void SetHue(int hue)
{
_Hue = hue <= 0 ? DefaultHue : hue;
}
public bool AddRunebook(Mobile m, Runebook book, bool message)
{
if (m == null || m.Deleted || book == null || book.Deleted)
{
return false;
}
var mrb = Insensitive.Equals(book.GetType().Name, "InternalRunebook");
if (book.Entries.Count == 0)
{
if (!mrb && message)
{
m.SendMessage("That rune book is empty.");
}
return false;
}
if (Entries.Count >= Entries.Capacity)
{
if (!mrb && message)
{
m.SendMessage("The category \"{0}\" can't hold more runes.", _Name);
}
return false;
}
if (Entries.Count + book.Entries.Count > Entries.Capacity)
{
if (!mrb && message)
{
m.SendMessage("That rune book won't fit in the category \"{0}\".", _Name);
}
return false;
}
var bEntries = new Queue<RunebookEntry>(book.Entries);
Entries.ForEach(
(x, y, e) =>
{
if (e != null || bEntries.Count <= 0)
{
return;
}
var be = bEntries.Dequeue();
Entries.SetContent(x, y, new RuneCodexEntry(book.Name, be.Description, be.Location.ToMapPoint(be.Map)));
});
if (mrb)
{
book.Entries.Clear();
return true;
}
book.Delete();
if (message)
{
m.SendMessage("You add the rune book to the category \"{0}\".", _Name);
}
return true;
}
public bool SetRune(Mobile m, RecallRune rune, Point2D loc, bool message)
{
if (m == null || m.Deleted || rune == null || rune.Deleted)
{
return false;
}
if (!rune.Marked || rune.Target == Point3D.Zero || rune.TargetMap == Map.Internal)
{
if (message)
{
m.SendMessage("That rune is blank.");
}
return false;
}
if (Entries.Count >= Entries.Capacity)
{
if (message)
{
m.SendMessage("The category \"{0}\" can't hold more runes.", _Name);
}
return false;
}
if (Entries[loc.X, loc.Y] != null)
{
return AddRune(m, rune, message);
}
Entries.SetContent(
loc.X,
loc.Y,
new RuneCodexEntry(rune.Description, rune.Name, rune.Target.ToMapPoint(rune.TargetMap)));
rune.Delete();
if (message)
{
m.SendMessage("You add the rune to the category \"{0}\".", _Name);
}
return true;
}
public bool AddRune(Mobile m, RecallRune rune, bool message)
{
if (m == null || m.Deleted || rune == null || rune.Deleted)
{
return false;
}
if (!rune.Marked || rune.Target == Point3D.Zero || rune.TargetMap == Map.Internal)
{
if (message)
{
m.SendMessage("That rune is blank.");
}
return false;
}
if (Entries.Count >= Entries.Capacity)
{
if (message)
{
m.SendMessage("The category \"{0}\" can't hold more runes.", _Name);
}
return false;
}
Entries.ForEach(
(x, y, e) =>
{
if (e != null || rune.Deleted)
{
return;
}
Entries.SetContent(x, y, new RuneCodexEntry(rune.Description, rune.Name, rune.Target.ToMapPoint(rune.TargetMap)));
rune.Delete();
});
if (message)
{
m.SendMessage("You add the rune to the rune codex category \"{0}\".", _Name);
}
return true;
}
public bool Remove(RuneCodexEntry entry)
{
for (var x = 0; x < Entries.Width; x++)
{
for (var y = 0; y < Entries.Height; y++)
{
if (Entries[x, y] != entry)
{
continue;
}
Entries[x, y] = null;
return true;
}
}
return false;
}
public virtual string ToHtmlString(Mobile viewer = null)
{
var html = new StringBuilder();
GetHtmlString(html, viewer);
return html.ToString();
}
public virtual void GetHtmlString(StringBuilder html, Mobile viewer = null)
{
html.Append("".WrapUOHtmlColor(SuperGump.DefaultHtmlColor, false));
html.AppendLine("Entries: {0:#,0} / {1:#,0}", Entries.Count, Entries.Capacity);
html.AppendLine();
if (!String.IsNullOrWhiteSpace(Description))
{
html.AppendLine(Description.WrapUOHtmlColor(Color.LawnGreen, SuperGump.DefaultHtmlColor));
}
html.Append("".WrapUOHtmlColor(SuperGump.DefaultHtmlColor, false));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(_Name);
writer.Write(_Description);
writer.Write(_Hue);
Entries.Serialize(writer);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
Name = reader.ReadString();
Description = reader.ReadString();
Hue = reader.ReadInt();
Entries = new RuneCodexEntryGrid(reader);
}
break;
}
}
}
}

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 Server;
#endregion
namespace VitaNex.Items
{
public class RuneCodexCategoryGrid : Grid<RuneCodexCategory>
{
public RuneCodexCategoryGrid()
: base(10, 10)
{
SetContent(0, 0, new RuneCodexCategory());
}
public RuneCodexCategoryGrid(GenericReader reader)
: base(reader)
{ }
public override RuneCodexCategory this[int x, int y]
{
get
{
if (x == 0 && y == 0 && base[x, y] == null)
{
return (base[x, y] = new RuneCodexCategory());
}
return base[x, y];
}
set
{
if (x == 0 && y == 0 && value == null)
{
value = new RuneCodexCategory();
}
base[x, y] = value;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
public override void SerializeContent(GenericWriter writer, RuneCodexCategory content, int x, int y)
{
base.SerializeContent(writer, content, x, y);
if (OnSerializeContent == null)
{
content.Serialize(writer);
}
}
public override RuneCodexCategory DeserializeContent(GenericReader reader, Type type, int x, int y)
{
if (OnDeserializeContent == null)
{
return new RuneCodexCategory(reader);
}
return base.DeserializeContent(reader, type, x, y);
}
}
}

View File

@@ -0,0 +1,259 @@
#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 Server;
using Server.Items;
using Server.Spells.Fourth;
using Server.Spells.Seventh;
using VitaNex.SuperGumps;
#endregion
namespace VitaNex.Items
{
public class RuneCodexEntry : PropertyObject
{
public static string DefaultName = "Unknown Place";
public static string DefaultDescription = String.Empty;
private string _Name = DefaultName;
private string _Description = DefaultDescription;
private MapPoint _Location = MapPoint.Empty;
[CommandProperty(AccessLevel.GameMaster)]
public string Name { get => _Name; set => SetName(value); }
[CommandProperty(AccessLevel.GameMaster)]
public string Description { get => _Description; set => SetDescription(value); }
[CommandProperty(AccessLevel.GameMaster)]
public MapPoint Location { get => _Location; set => SetLocation(value); }
public RuneCodexEntry()
: this(DefaultName, DefaultDescription, MapPoint.Empty)
{ }
public RuneCodexEntry(string name, string desc, MapPoint dest)
{
Name = name ?? DefaultName;
Description = desc ?? DefaultDescription;
Location = dest;
}
public RuneCodexEntry(GenericReader reader)
: base(reader)
{ }
public override void Clear()
{
UseDefaults();
Location = MapPoint.Empty;
}
public override void Reset()
{
UseDefaults();
Location = MapPoint.Empty;
}
public virtual void UseDefaults()
{
Name = DefaultName;
Description = DefaultDescription;
}
public void SetName(string name)
{
_Name = String.IsNullOrWhiteSpace(name) ? DefaultName : name;
}
public void SetDescription(string desc)
{
_Description = String.IsNullOrWhiteSpace(desc) ? DefaultDescription : desc;
}
public void SetLocation(MapPoint dest)
{
_Location = dest;
}
public bool Recall(Mobile m)
{
if (m == null || m.Deleted)
{
return false;
}
if (_Location.Internal || _Location.Zero)
{
m.SendMessage("That rune is blank.");
return false;
}
if (m.Player)
{
var t = GetType();
if (m.AccessLevel < AccessLevel.Counselor && !m.CanBeginAction(t))
{
m.SendMessage("You must wait before using the rune codex again.");
return false;
}
var spell = new RecallSpell(
m,
null,
new RunebookEntry(_Location.Location, _Location.Map, _Description, null),
null);
if (!spell.Cast())
{
return false;
}
m.BeginAction(t, TimeSpan.FromSeconds(3));
}
else
{
_Location.MoveToWorld(m);
}
return true;
}
public bool Gate(Mobile m)
{
if (m == null || m.Deleted)
{
return false;
}
if (_Location.Internal || _Location.Zero)
{
m.SendMessage("That rune is blank.");
return false;
}
if (m.Player)
{
var t = GetType();
if (m.AccessLevel < AccessLevel.Counselor && !m.CanBeginAction(t))
{
m.SendMessage("You must wait before using the rune codex again.");
return false;
}
var spell = new GateTravelSpell(m, null, new RunebookEntry(_Location.Location, _Location.Map, _Description, null));
if (!spell.Cast())
{
return false;
}
m.BeginAction(t, TimeSpan.FromSeconds(3));
}
else
{
_Location.MoveToWorld(m);
}
return true;
}
public virtual string ToHtmlString(Mobile viewer = null)
{
var html = new StringBuilder();
GetHtmlString(html);
return html.ToString();
}
public virtual void GetHtmlString(StringBuilder html, Mobile viewer = null)
{
html.Append("".WrapUOHtmlColor(SuperGump.DefaultHtmlColor, false));
html.AppendLine("Facet: {0}", Location.Map);
html.AppendLine("Location: {0}, {1}, {2}", Location.X, Location.Y, Location.Z);
int xLong = 0, yLat = 0;
int xMins = 0, yMins = 0;
bool xEast = false, ySouth = false;
if (Sextant.Format(Location, Location.Map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth))
{
html.AppendLine(
"Coords: {0}<7D> {1}'{2}, {3}<7D> {4}'{5}",
yLat,
yMins,
ySouth ? "S" : "N",
xLong,
xMins,
xEast ? "E" : "W");
}
if (!String.IsNullOrWhiteSpace(Description))
{
html.AppendLine();
html.AppendLine(Description.WrapUOHtmlColor(Color.LawnGreen, SuperGump.DefaultHtmlColor));
html.AppendLine();
}
html.Append("".WrapUOHtmlColor(SuperGump.DefaultHtmlColor, false));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
writer.Write(_Name);
goto case 0;
case 0:
{
writer.Write(_Description);
_Location.Serialize(writer);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 1:
_Name = reader.ReadString();
goto case 0;
case 0:
{
_Description = reader.ReadString();
_Location = new MapPoint(reader);
}
break;
}
}
}
}

View File

@@ -0,0 +1,64 @@
#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.Items
{
public class RuneCodexEntryGrid : Grid<RuneCodexEntry>
{
public RuneCodexEntryGrid()
: base(10, 10)
{ }
public RuneCodexEntryGrid(GenericReader reader)
: base(reader)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
public override void SerializeContent(GenericWriter writer, RuneCodexEntry content, int x, int y)
{
base.SerializeContent(writer, content, x, y);
if (OnSerializeContent == null)
{
content.Serialize(writer);
}
}
public override RuneCodexEntry DeserializeContent(GenericReader reader, Type type, int x, int y)
{
if (OnDeserializeContent == null)
{
return new RuneCodexEntry(reader);
}
return base.DeserializeContent(reader, type, x, y);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,119 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public abstract class CustomContainer : BaseContainer
{
private int _ContainerItemID;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public virtual int ContainerItemID
{
get
{
if (_ContainerItemID <= 0)
{
_ContainerItemID = DefaultContainerItemID;
}
return _ContainerItemID;
}
set
{
if (value <= 0)
{
value = DefaultContainerItemID;
}
if (_ContainerItemID == value)
{
return;
}
_ContainerItemID = value;
Update();
}
}
public virtual int DefaultContainerItemID => 0xE77;
public CustomContainer(int itemID)
: this(itemID, 0xE76)
{ }
public CustomContainer(int itemID, int containerID)
: base(itemID)
{
ItemID = ContainerItemID = containerID;
}
public CustomContainer(Serial serial)
: base(serial)
{ }
public virtual void Update()
{
UpdateContainerData();
}
public override void UpdateContainerData()
{
if (ContainerItemID > 0)
{
ContainerData = ContainerData.GetData(ContainerItemID);
}
else
{
base.UpdateContainerData();
}
GumpID = -1;
DropSound = -1;
Delta(ItemDelta.Update);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.Write(_ContainerItemID);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
_ContainerItemID = reader.ReadInt();
break;
}
Update();
}
}
}

View File

@@ -0,0 +1,58 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
[Flipable(0x4910, 0x4911)]
public class HugeWoodenChest : CustomContainer
{
public override int DefaultContainerItemID => 0x4910;
[Constructable]
public HugeWoodenChest()
: base(0x4910, 0x4910)
{ }
public HugeWoodenChest(Serial serial)
: base(serial)
{ }
public override void UpdateContainerData()
{
if (ItemID == 0x4910 || ItemID == 0x4911)
{
ContainerData = new ContainerData(0x3E8, new Rectangle2D(90, 90, 460, 280), 0x42);
return;
}
base.UpdateContainerData();
}
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,93 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Items
{
public interface IVendorToken
{
string Name { get; set; }
int Amount { get; set; }
bool Stackable { get; set; }
void Deserialize(GenericReader reader);
void Serialize(GenericWriter writer);
}
public abstract class VendorToken : Item, IVendorToken
{
public override bool DisplayWeight => false;
public VendorToken()
: this(1)
{ }
public VendorToken(int amount)
: base(0xEED)
{
Name = "Vendor Token";
Hue = 85;
Weight = 0;
Stackable = true;
Amount = Math.Max(1, Math.Min(60000, amount));
LootType = LootType.Blessed;
}
public VendorToken(Serial serial)
: base(serial)
{ }
public override DeathMoveResult OnInventoryDeath(Mobile parent)
{
if (parent is BaseCreature)
{
return DeathMoveResult.MoveToCorpse;
}
return base.OnInventoryDeath(parent);
}
public override int GetDropSound()
{
if (Amount <= 1)
{
return 0x2E4;
}
if (Amount <= 5)
{
return 0x2E5;
}
return 0x2E6;
}
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,726 @@
#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 Server;
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
using VitaNex.Network;
using VitaNex.SuperGumps.UI;
using VitaNex.Targets;
#endregion
namespace VitaNex.Items
{
public static class HueDeeds
{
public static event Action<IHueDeed> OnCreated;
public static void Register<T>(Action<T> onCreated)
where T : IHueDeed
{
OnCreated += o =>
{
if (o is T d)
{
onCreated(d);
}
};
}
public static void InvokeCreated(IHueDeed d)
{
if (OnCreated != null)
{
OnCreated(d);
}
}
}
public interface IHueDeed
{
List<int> Hues { get; }
void AddHue(int hue);
void AddHues(params int[] hues);
void AddHueRange(int hue, int count);
}
public abstract class BaseHueDeed<TEntity> : Item, IHueDeed
where TEntity : IEntity
{
private HueSelector _Gump;
private GenericSelectTarget<TEntity> _Target;
public List<int> Hues { get; private set; }
public virtual string TargetUsage => "an object";
public BaseHueDeed()
: base(0x14F0)
{
Hues = new List<int>();
Name = "Color Change Deed";
Weight = 1.0;
LootType = LootType.Blessed;
Timer.DelayCall(HueDeeds.InvokeCreated, this);
}
public BaseHueDeed(Serial serial)
: base(serial)
{ }
public void AddHue(int hue)
{
Hues.Update(hue);
}
public void AddHues(params int[] hues)
{
if (hues == null || hues.Length == 0)
{
return;
}
foreach (var h in hues)
{
AddHue(h);
}
}
public void AddHueRange(int hue, int count)
{
count = Math.Max(0, count);
while (--count >= 0)
{
AddHue(hue++);
}
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
ExtendedOPL.AddTo(list, "Use: Change the color of {0}".WrapUOHtmlColor(Color.LawnGreen), TargetUsage);
}
public override void OnDoubleClick(Mobile m)
{
if (this.CheckDoubleClick(m, true, false, 2, true))
{
BeginTarget(m);
}
}
protected virtual void BeginTarget(Mobile m)
{
if (_Target != null)
{
if (_Target.User != null && _Target.User.Target == _Target)
{
_Target.Cancel(_Target.User, TargetCancelType.Overriden);
}
_Target = null;
}
m.SendMessage("Target an object to recolor...");
_Target = new GenericSelectTarget<TEntity>(
(u, t) =>
{
_Target = null;
OpenGump(u, t);
},
u =>
{
OnTargetFail(u);
_Target = null;
});
m.Target = _Target;
}
protected virtual void OnTargetFail(Mobile m)
{
if (_Target.User == m && _Target.Result == TargetResult.Invalid)
{
m.SendMessage("That is not a valid target.");
}
}
protected virtual void OpenGump(Mobile m, TEntity t)
{
if (_Gump != null)
{
_Gump.Close();
_Gump = null;
}
m.SendMessage("Select a color from the chart...");
_Gump = new HueSelector(m)
{
PreviewIcon = GetPreviewIcon(t),
Hues = Hues.ToArray(),
AcceptCallback = hue =>
{
_Gump = null;
ApplyHue(m, t, hue);
},
CancelCallback = hue => _Gump = null
};
_Gump.Send();
}
public virtual int GetPreviewIcon(TEntity t)
{
return HueSelector.DefaultIcon;
}
protected virtual void ApplyHue(Mobile m, TEntity t, int hue)
{
if (m == null || t == null)
{
return;
}
if (hue < 0 || hue >= 3000)
{
m.SendMessage(0x22, "You cannot use an invalid hue.");
OpenGump(m, t);
return;
}
var item = t as Item;
if (item != null)
{
if (item.Hue == hue)
{
m.SendMessage(0x22, "The item is already that color.");
OpenGump(m, t);
return;
}
item.Hue = hue;
m.SendMessage(0x55, "The item has been recolored.");
Delete();
return;
}
var mob = t as Mobile;
if (mob != null)
{
if (mob.Hue == hue)
{
m.SendMessage(0x22, "{0} skin is already that color.", mob == m ? "Your" : "Their");
OpenGump(m, t);
return;
}
mob.Hue = hue;
m.SendMessage(0x55, "{0} skin has been recolored.", mob == m ? "Your" : "Their");
Delete();
return;
}
m.SendMessage(0x22, "Could not recolor that object.");
}
public override void OnDelete()
{
base.OnDelete();
_Gump = null;
_Target = null;
Hues.Free(true);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.WriteList(Hues, writer.Write);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
Hues = reader.ReadList(reader.ReadInt);
}
}
public abstract class ItemHueDeed<TItem> : BaseHueDeed<TItem>
where TItem : Item
{
public override string TargetUsage => "an item";
public ItemHueDeed()
{ }
public ItemHueDeed(Serial serial)
: base(serial)
{ }
protected override void OpenGump(Mobile m, TItem t)
{
if (m == null || t == null)
{
return;
}
if (m.AccessLevel < AccessLevel.GameMaster)
{
if (!t.Movable && !t.IsAccessibleTo(m))
{
m.SendMessage("That item is not accessible.");
return;
}
if (!t.IsChildOf(m.Backpack) && t.RootParent != m)
{
m.SendMessage("That item must be equipped or in your pack to recolor it.");
return;
}
}
base.OpenGump(m, t);
}
public override int GetPreviewIcon(TItem t)
{
return t == null ? HueSelector.DefaultIcon : t.ItemID;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public abstract class MobileHueDeed<TMobile> : BaseHueDeed<TMobile>
where TMobile : Mobile
{
public override string TargetUsage => "a mobile";
public MobileHueDeed()
{ }
public MobileHueDeed(Serial serial)
: base(serial)
{ }
protected override void OpenGump(Mobile m, TMobile t)
{
if (m == null || t == null)
{
return;
}
if (m.AccessLevel < t.AccessLevel)
{
m.SendMessage("They are not accessible.");
return;
}
base.OpenGump(m, t);
}
public override int GetPreviewIcon(TMobile t)
{
return t == null ? HueSelector.DefaultIcon : ShrinkTable.Lookup(t);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class SkinHueDeed : MobileHueDeed<PlayerMobile>
{
public override string TargetUsage => "your character";
[Constructable]
public SkinHueDeed()
{
Name = "Skin Recolor Deed";
AddHueRange(1002, 57);
}
public SkinHueDeed(Serial serial)
: base(serial)
{ }
protected override void BeginTarget(Mobile m)
{
OpenGump(m, m as PlayerMobile);
}
protected override void OpenGump(Mobile m, PlayerMobile t)
{
if (m == null || t == null)
{
return;
}
if (m.AccessLevel < AccessLevel.GameMaster)
{
if (m != t)
{
m.SendMessage("You can only recolor your own skin.");
return;
}
}
base.OpenGump(m, t);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class PetHueDeed : MobileHueDeed<BaseCreature>
{
public override string TargetUsage => "your pet";
[Constructable]
public PetHueDeed()
{
Name = "Pet Recolor Deed";
AddHueRange(2301, 18);
}
public PetHueDeed(Serial serial)
: base(serial)
{ }
protected override void OpenGump(Mobile m, BaseCreature t)
{
if (m == null || t == null)
{
return;
}
if (m.AccessLevel < AccessLevel.GameMaster)
{
if (t.GetMaster() != m)
{
m.SendMessage("You can only recolor the skin of pets that you own.");
return;
}
}
base.OpenGump(m, t);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class WeaponHueDeed : ItemHueDeed<BaseWeapon>
{
public override string TargetUsage => "a weapon";
[Constructable]
public WeaponHueDeed()
{
Name = "Weapon Recolor Deed";
AddHueRange(2401, 30);
}
public WeaponHueDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class ArmorHueDeed : ItemHueDeed<BaseArmor>
{
public override string TargetUsage => "armor";
[Constructable]
public ArmorHueDeed()
{
Name = "Armor Recolor Deed";
AddHueRange(2401, 30);
}
public ArmorHueDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class ClothingHueDeed : ItemHueDeed<BaseClothing>
{
public override string TargetUsage => "clothing";
[Constructable]
public ClothingHueDeed()
{
Name = "Clothing Recolor Deed";
AddHueRange(2, 1000);
}
public ClothingHueDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class JewelHueDeed : ItemHueDeed<BaseJewel>
{
public override string TargetUsage => "your jewelry";
[Constructable]
public JewelHueDeed()
{
Name = "Jewelry Recolor Deed";
AddHueRange(2401, 30);
}
public JewelHueDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class QuiverHueDeed : ItemHueDeed<BaseQuiver>
{
public override string TargetUsage => "your quiver";
[Constructable]
public QuiverHueDeed()
{
Name = "Quiver Recolor Deed";
AddHueRange(2, 1000);
}
public QuiverHueDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class LightHueDeed : ItemHueDeed<BaseEquipableLight>
{
public override string TargetUsage => "your light source";
[Constructable]
public LightHueDeed()
{
Name = "Light Source Recolor Deed";
AddHueRange(2401, 30);
}
public LightHueDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class SpellbookHueDeed : ItemHueDeed<Spellbook>
{
public override string TargetUsage => "your spellbook";
[Constructable]
public SpellbookHueDeed()
{
Name = "Spellbook Recolor Deed";
AddHueRange(2, 1000);
}
public SpellbookHueDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class ContainerHueDeed : ItemHueDeed<Container>
{
public override string TargetUsage => "a container";
[Constructable]
public ContainerHueDeed()
{
Name = "Container Recolor Deed";
AddHueRange(2, 1000);
}
public ContainerHueDeed(Serial serial)
: base(serial)
{ }
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,723 @@
#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 Server;
using Server.Items;
using Server.Misc;
using Server.Mobiles;
using Server.Targeting;
using VitaNex.Network;
using VitaNex.SuperGumps;
using VitaNex.SuperGumps.UI;
using VitaNex.Targets;
#endregion
namespace VitaNex.Items
{
public static class NameDeeds
{
public static event Action<INameDeed> OnCreated;
public static void Register<T>(Action<T> onCreated)
where T : INameDeed
{
OnCreated += o =>
{
if (o is T d)
{
onCreated(d);
}
};
}
public static void InvokeCreated(INameDeed d)
{
if (OnCreated != null)
{
OnCreated(d);
}
}
}
public interface INameDeed
{
List<string> Names { get; }
void AddName(string name);
void AddNames(params string[] names);
}
public abstract class BaseNameDeed<TEntity> : Item, INameDeed
where TEntity : IEntity
{
private SuperGump _Gump;
private GenericSelectTarget<TEntity> _Target;
public List<string> Names { get; private set; }
public virtual string TargetUsage => "an object";
public BaseNameDeed()
: base(0x14F0)
{
Names = new List<string>();
Name = "Rename Deed";
Weight = 1.0;
LootType = LootType.Blessed;
Timer.DelayCall(NameDeeds.InvokeCreated, this);
}
public BaseNameDeed(Serial serial)
: base(serial)
{ }
public void AddName(string name)
{
Names.Update(name);
}
public void AddNames(params string[] names)
{
if (names == null || names.Length == 0)
{
return;
}
foreach (var n in names)
{
AddName(n);
}
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
new ExtendedOPL(list)
{
{"Use: Change the name of {0}".WrapUOHtmlColor(Color.LawnGreen), TargetUsage}
}.Apply();
}
public override void OnDoubleClick(Mobile m)
{
if (this.CheckDoubleClick(m, true, false, 2, true))
{
BeginTarget(m);
}
}
protected virtual void BeginTarget(Mobile m)
{
if (_Target != null)
{
if (_Target.User != null && _Target.User.Target == _Target)
{
_Target.Cancel(_Target.User, TargetCancelType.Overriden);
}
_Target = null;
}
m.SendMessage("Target an object to rename...");
_Target = new GenericSelectTarget<TEntity>(
(u, t) =>
{
_Target = null;
OpenGump(u, t);
},
u =>
{
OnTargetFail(u);
_Target = null;
});
m.Target = _Target;
}
protected virtual void OnTargetFail(Mobile m)
{
if (_Target.User == m && _Target.Result == TargetResult.Invalid)
{
m.SendMessage("That is not a valid target.");
}
}
protected virtual void OpenGump(Mobile m, TEntity t)
{
if (_Gump != null)
{
_Gump.Close();
_Gump = null;
}
if (Names != null && Names.Count > 0)
{
m.SendMessage("Select a name from the registry...");
var opts = new MenuGumpOptions();
foreach (var name in Names.OrderByNatural())
{
var n = name;
opts.AppendEntry(
new ListGumpEntry(
n,
() =>
{
_Gump = null;
ApplyName(m, t, n);
}));
}
var menu = new MenuGump(m, null, opts);
menu.OnActionClose += HandleGumpClose;
_Gump = menu.Send();
}
else
{
string name;
int limit;
if (t is Item)
{
name = (t as Item).Name;
limit = 20;
}
else if (t is Mobile)
{
name = (t as Mobile).RawName;
limit = 20;
}
else
{
name = String.Empty;
limit = 0;
}
var dialog = new InputDialogGump(m)
{
Title = "Name Selection",
Html = "Type the name you wish to use and click OK to accept.",
InputText = name ?? String.Empty,
Limit = limit,
Callback = (b, n) =>
{
_Gump = null;
ApplyName(m, t, n);
}
};
dialog.OnActionClose += HandleGumpClose;
_Gump = dialog.Send();
}
}
private void HandleGumpClose(SuperGump g, bool all)
{
if (_Gump == g && all)
{
_Gump.OnActionClose -= HandleGumpClose;
_Gump = null;
}
}
protected virtual void ApplyName(Mobile m, TEntity t, string name)
{
if (m == null || t == null)
{
return;
}
if (String.IsNullOrWhiteSpace(name))
{
m.SendMessage(0x22, "You cannot use a blank name.");
OpenGump(m, t);
return;
}
name = Utility.FixHtml(name.Trim());
if (!NameVerification.Validate(name, 2, 20, true, t is Item, true, 1, NameVerification.SpaceDashPeriodQuote))
{
m.SendMessage(0x22, "That name is unacceptable.");
OpenGump(m, t);
return;
}
var item = t as Item;
if (item != null)
{
if (item.Name == name)
{
m.SendMessage(0x22, "The item is already named {0}.", name);
OpenGump(m, t);
return;
}
item.Name = name;
m.SendMessage(0x55, "The item has been renamed.");
Delete();
return;
}
var mob = t as Mobile;
if (mob != null)
{
if (mob.RawName == name)
{
m.SendMessage(0x22, "{0} are already named {1}.", mob == m ? "You" : "They", name);
OpenGump(m, t);
return;
}
mob.RawName = name;
m.SendMessage(0x55, "{0} name has been changed.", mob == m ? "Your" : "Their");
Delete();
if (mob is PlayerMobile)
{
var pm = (PlayerMobile)mob;
PlayerNames.Register(pm);
PlayerNames.ValidateSharedName(pm);
}
return;
}
m.SendMessage(0x22, "Could not rename that object.");
}
public override void OnDelete()
{
base.OnDelete();
_Gump = null;
_Target = null;
Names.Free(true);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.WriteList(Names, writer.Write);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
Names = reader.ReadList(reader.ReadString);
}
}
public abstract class ItemNameDeed<TItem> : BaseNameDeed<TItem>
where TItem : Item
{
public override string TargetUsage => "an item";
public ItemNameDeed()
{ }
public ItemNameDeed(Serial serial)
: base(serial)
{ }
protected override void OpenGump(Mobile m, TItem t)
{
if (m == null || t == null)
{
return;
}
if (m.AccessLevel < AccessLevel.GameMaster)
{
if (!t.Movable && !t.IsAccessibleTo(m))
{
m.SendMessage("That item is not accessible.");
return;
}
if (!t.IsChildOf(m.Backpack) && t.RootParent != m)
{
m.SendMessage("That item must be equipped or in your pack to rename it.");
return;
}
}
base.OpenGump(m, t);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public abstract class MobileNameDeed<TMobile> : BaseNameDeed<TMobile>
where TMobile : Mobile
{
public override string TargetUsage => "a mobile";
public MobileNameDeed()
{ }
public MobileNameDeed(Serial serial)
: base(serial)
{ }
protected override void OpenGump(Mobile m, TMobile t)
{
if (m == null || t == null)
{
return;
}
if (m.AccessLevel < t.AccessLevel)
{
m.SendMessage("They are not accessible.");
return;
}
base.OpenGump(m, t);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class PlayerNameDeed : MobileNameDeed<PlayerMobile>
{
public override string TargetUsage => "your character";
[Constructable]
public PlayerNameDeed()
{
Name = "Player Rename Deed";
}
public PlayerNameDeed(Serial serial)
: base(serial)
{ }
protected override void BeginTarget(Mobile m)
{
OpenGump(m, m as PlayerMobile);
}
protected override void OpenGump(Mobile m, PlayerMobile t)
{
if (m == null || t == null)
{
return;
}
if (m.AccessLevel < AccessLevel.GameMaster)
{
if (m != t)
{
m.SendMessage("You can only change your own name.");
return;
}
}
base.OpenGump(m, t);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class WeaponNameDeed : ItemNameDeed<BaseWeapon>
{
public override string TargetUsage => "your weapon";
[Constructable]
public WeaponNameDeed()
{
Name = "Weapon Rename Deed";
}
public WeaponNameDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class ArmorNameDeed : ItemNameDeed<BaseArmor>
{
public override string TargetUsage => "your armor";
[Constructable]
public ArmorNameDeed()
{
Name = "Armor Rename Deed";
}
public ArmorNameDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class ClothingNameDeed : ItemNameDeed<BaseClothing>
{
public override string TargetUsage => "your clothing";
[Constructable]
public ClothingNameDeed()
{
Name = "Clothing Rename Deed";
}
public ClothingNameDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class JewelNameDeed : ItemNameDeed<BaseJewel>
{
public override string TargetUsage => "your jewelry";
[Constructable]
public JewelNameDeed()
{
Name = "Jewelry Rename Deed";
}
public JewelNameDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class QuiverNameDeed : ItemNameDeed<BaseQuiver>
{
public override string TargetUsage => "your quiver";
[Constructable]
public QuiverNameDeed()
{
Name = "Quiver Rename Deed";
}
public QuiverNameDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class LightNameDeed : ItemNameDeed<BaseEquipableLight>
{
public override string TargetUsage => "your light source";
[Constructable]
public LightNameDeed()
{
Name = "Light Source Rename Deed";
}
public LightNameDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class SpellbookNameDeed : ItemNameDeed<Spellbook>
{
public override string TargetUsage => "your spellbook";
[Constructable]
public SpellbookNameDeed()
{
Name = "Spellbook Rename Deed";
}
public SpellbookNameDeed(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class ContainerNameDeed : ItemNameDeed<Container>
{
public override string TargetUsage => "a container";
[Constructable]
public ContainerNameDeed()
{
Name = "Container Rename Deed";
}
public ContainerNameDeed(Serial serial)
: base(serial)
{ }
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,449 @@
#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.Engines.Craft;
using Server.Items;
using VitaNex.FX;
using VitaNex.Network;
using VitaNex.SuperCrafts;
#endregion
namespace VitaNex.Items
{
public abstract class BaseFirework : Item, ICraftable
{
protected virtual object UseLock => GetType();
public virtual string DefToken => String.Empty;
public virtual TimeSpan DefUseDelay => TimeSpan.FromSeconds(3.0);
private string _Token;
private Mobile _Crafter;
[CommandProperty(AccessLevel.GameMaster)]
public string Token
{
get => _Token;
set
{
_Token = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Crafter
{
get => _Crafter;
set
{
_Crafter = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan UseDelay { get; set; }
#region Fuse
public virtual TimeSpan DefFuseDelay => TimeSpan.FromSeconds(1.0);
private Timer _FuseTimer;
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan FuseDelay { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool FuseLit => _FuseTimer != null && _FuseTimer.Running;
#endregion
#region Ignite Effect
public virtual int DefIgniteEffectID => 14276;
public virtual int DefIgniteEffectHue => 0;
public virtual int DefIgniteEffectSpeed => 5;
public virtual EffectRender DefIgniteEffectRender => EffectRender.LightenMore;
public virtual int DefIgniteEffectSound => 1232;
[CommandProperty(AccessLevel.GameMaster)]
public int IgniteEffectID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int IgniteEffectHue { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int IgniteEffectSpeed { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public EffectRender IgniteEffectRender { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int IgniteEffectSound { get; set; }
#endregion
#region Fail Effect
public virtual int DefFailEffectID => 14133;
public virtual int DefFailEffectHue => 0;
public virtual int DefFailEffectSpeed => 10;
public virtual int DefFailEffectDuration => 30;
public virtual EffectRender DefFailEffectRender => EffectRender.Normal;
public virtual int DefFailEffectSound => 1488;
[CommandProperty(AccessLevel.GameMaster)]
public int FailEffectID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int FailEffectHue { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int FailEffectSpeed { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int FailEffectDuration { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public EffectRender FailEffectRender { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int FailEffectSound { get; set; }
#endregion
public BaseFirework(int itemID, int hue)
: base(itemID)
{
Name = "Firework Rocket";
Weight = 1.0;
Light = LightType.Circle300;
Hue = hue;
UseDelay = DefUseDelay;
Token = DefToken;
FuseDelay = DefFuseDelay;
IgniteEffectID = DefIgniteEffectID;
IgniteEffectHue = DefIgniteEffectHue;
IgniteEffectSpeed = DefIgniteEffectSpeed;
IgniteEffectRender = DefIgniteEffectRender;
IgniteEffectSound = DefIgniteEffectSound;
FailEffectID = DefFailEffectID;
FailEffectHue = DefFailEffectHue;
FailEffectSpeed = DefFailEffectSpeed;
FailEffectDuration = DefFailEffectDuration;
FailEffectRender = DefFailEffectRender;
FailEffectSound = DefFailEffectSound;
}
public BaseFirework(Serial serial)
: base(serial)
{ }
public override bool IsAccessibleTo(Mobile check)
{
return base.IsAccessibleTo(check) && !FuseLit;
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (Crafter != null && !String.IsNullOrWhiteSpace(Crafter.RawName))
{
list.Add(1050043, Crafter.RawName);
}
var props = new StringBuilder();
GetProperties(props);
if (props.Length > 0)
{
list.Add(props.ToString());
}
}
public virtual void GetProperties(StringBuilder props)
{
if (!Visible)
{
return;
}
if (FuseLit)
{
var now = DateTime.UtcNow;
if (_FuseTimer.Next < now)
{
var ts = now - _FuseTimer.Next;
if (ts > TimeSpan.Zero)
{
props.AppendLine("Fuse: {0}", ts.ToSimpleString("h:m:s"));
}
}
}
else
{
props.AppendLine("Use: Light the fuse!".WrapUOHtmlColor(Color.LawnGreen));
}
if (!String.IsNullOrWhiteSpace(Token))
{
props.AppendLine("\"{0}\"".WrapUOHtmlColor(Color.Gold), Token);
}
}
public virtual int OnCraft(
int quality,
bool makersMark,
Mobile m,
CraftSystem craftSystem,
Type typeRes,
#if ServUO
ITool tool,
#else
BaseTool tool,
#endif
CraftItem craftItem,
int resHue)
{
if (makersMark)
{
Crafter = m;
}
var context = craftSystem.GetContext(m);
if (context != null && context.DoNotColor)
{
Hue = 0;
}
else if (resHue > 0)
{
Hue = resHue;
}
if (craftSystem is Pyrotechnics && craftItem != null)
{
var fuses = new List<CraftRes>(craftItem.Resources.Count);
fuses.SetAll(craftItem.Resources.GetAt);
fuses.RemoveAll(res => !res.ItemType.TypeEquals<FireworkFuse>());
var fuseDelay = FuseDelay.TotalSeconds * fuses.Sum(r => r.Amount);
fuses.Free(true);
if (fuseDelay > 0)
{
FuseDelay = TimeSpan.FromSeconds(fuseDelay);
}
}
return quality;
}
public override void OnDoubleClick(Mobile m)
{
if (m == null || m.Deleted)
{
return;
}
if (FuseLit)
{
m.SendMessage("The fuse is already burning.");
return;
}
if (!this.CheckDoubleClick(m, true, false, 10))
{
return;
}
if (!m.BeginAction(UseLock, UseDelay))
{
m.SendMessage("You must wait before you can light another {0}.", this.ResolveName(m));
return;
}
MoveToWorld(m.Location, m.Map);
IgniteFuse(m);
InvalidateProperties();
}
protected void IgniteFuse(Mobile m)
{
if (m == null || m.Deleted || FuseLit)
{
return;
}
if (!OnIgnite(m))
{
return;
}
if (IgniteEffectID > 0)
{
var fx = new EffectInfo(
GetWorldLocation(),
Map,
IgniteEffectID,
IgniteEffectHue,
IgniteEffectSpeed,
(int)Math.Ceiling(FuseDelay.TotalMilliseconds / 100.0),
IgniteEffectRender);
fx.Send();
}
if (IgniteEffectSound > 0)
{
Effects.PlaySound(GetWorldLocation(), Map, IgniteEffectSound);
}
_FuseTimer = Timer.DelayCall(
FuseDelay,
() =>
{
_FuseTimer = null;
InvalidateProperties();
if (!OnFuseBurned(m))
{
Fail(m);
}
});
}
protected virtual bool OnIgnite(Mobile m)
{
return true;
}
protected abstract bool OnFuseBurned(Mobile m);
protected void Fail(Mobile m)
{
if (FailEffectID > 0)
{
var fx = new EffectInfo(
GetWorldLocation(),
Map,
FailEffectID,
FailEffectHue,
FailEffectSpeed,
FailEffectDuration,
FailEffectRender);
fx.Send();
}
if (FailEffectSound > 0)
{
Effects.PlaySound(GetWorldLocation(), Map, 1488);
}
Movable = Visible = true;
OnFail(m);
}
protected virtual void OnFail(Mobile m)
{
if (m != null)
{
m.SendMessage("The fuse has failed to ignite on {0}!", this.ResolveName(m));
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(_Token);
writer.Write(_Crafter);
writer.Write(UseDelay);
writer.Write(FuseDelay);
writer.Write(IgniteEffectID);
writer.Write(IgniteEffectHue);
writer.Write(IgniteEffectSpeed);
writer.WriteFlag(IgniteEffectRender);
writer.Write(IgniteEffectSound);
writer.Write(FailEffectID);
writer.Write(FailEffectHue);
writer.Write(FailEffectSpeed);
writer.Write(FailEffectDuration);
writer.WriteFlag(FailEffectRender);
writer.Write(FailEffectSound);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
_Token = reader.ReadString();
_Crafter = reader.ReadMobile();
UseDelay = reader.ReadTimeSpan();
FuseDelay = reader.ReadTimeSpan();
IgniteEffectID = reader.ReadInt();
IgniteEffectHue = reader.ReadInt();
IgniteEffectSpeed = reader.ReadInt();
IgniteEffectRender = reader.ReadFlag<EffectRender>();
IgniteEffectSound = reader.ReadInt();
FailEffectID = reader.ReadInt();
FailEffectHue = reader.ReadInt();
FailEffectSpeed = reader.ReadInt();
FailEffectDuration = reader.ReadInt();
FailEffectRender = reader.ReadFlag<EffectRender>();
FailEffectSound = reader.ReadInt();
}
break;
}
}
}
}

View File

@@ -0,0 +1,129 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Text;
using Server;
using Server.Engines.Craft;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public abstract class FireworkComponent : Item, ICraftable
{
private Mobile _Crafter;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public Mobile Crafter
{
get => _Crafter;
set
{
_Crafter = value;
InvalidateProperties();
}
}
public FireworkComponent(int itemID)
: base(itemID)
{ }
public FireworkComponent(Serial serial)
: base(serial)
{ }
public override bool StackWith(Mobile m, Item dropped, bool playSound)
{
if (m == null || !(dropped is FireworkComponent) || ((FireworkComponent)dropped)._Crafter != _Crafter)
{
return false;
}
return base.StackWith(m, dropped, playSound);
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (Crafter != null)
{
list.Add(1050043, Crafter.RawName);
}
var props = new StringBuilder();
GetProperties(props);
if (props.Length > 0)
{
list.Add(props.ToString());
}
}
public virtual void GetProperties(StringBuilder props)
{ }
public virtual int OnCraft(
int quality,
bool makersMark,
Mobile m,
CraftSystem craft,
Type typeRes,
#if ServUO
ITool tool,
#else
BaseTool tool,
#endif
CraftItem item,
int resHue)
{
if (makersMark)
{
Crafter = m;
}
var context = craft.GetContext(m);
if (context != null && context.DoNotColor)
{
Hue = 0;
}
else if (resHue > 0)
{
Hue = resHue;
}
return quality;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(_Crafter);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
_Crafter = reader.ReadMobile();
}
}
}

View File

@@ -0,0 +1,55 @@
#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.Items
{
public class FireworkFuse : FireworkComponent
{
[Constructable]
public FireworkFuse()
: this(1)
{ }
[Constructable]
public FireworkFuse(int amount)
: base(3613)
{
Name = "Firework Fuse";
Hue = 85;
Stackable = true;
Amount = Math.Max(1, Math.Min(60000, amount));
}
public FireworkFuse(Serial serial)
: base(serial)
{ }
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,419 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Linq;
using Server;
using Server.Engines.Craft;
using Server.Items;
using VitaNex.SuperCrafts;
#endregion
namespace VitaNex.Items
{
public abstract class BaseFireworkStar : FireworkComponent
{
public static CraftResource GetMetal(Type star)
{
if (!star.IsEqualOrChildOf<BaseFireworkStar>() || star.IsEqualOrChildOf<FireworkStarCustom>())
{
return CraftResource.None;
}
if (star.IsEqualOrChildOf<FireworkStarIron>())
{
return CraftResource.Iron;
}
if (star.IsEqualOrChildOf<FireworkStarDullCopper>())
{
return CraftResource.DullCopper;
}
if (star.IsEqualOrChildOf<FireworkStarShadowIron>())
{
return CraftResource.ShadowIron;
}
if (star.IsEqualOrChildOf<FireworkStarCopper>())
{
return CraftResource.Copper;
}
if (star.IsEqualOrChildOf<FireworkStarBronze>())
{
return CraftResource.Bronze;
}
if (star.IsEqualOrChildOf<FireworkStarGold>())
{
return CraftResource.Gold;
}
if (star.IsEqualOrChildOf<FireworkStarAgapite>())
{
return CraftResource.Agapite;
}
if (star.IsEqualOrChildOf<FireworkStarVerite>())
{
return CraftResource.Verite;
}
if (star.IsEqualOrChildOf<FireworkStarValorite>())
{
return CraftResource.Valorite;
}
return CraftResource.None;
}
public static int[] GetEffectHues(Type star)
{
var res = GetMetal(star);
return res != CraftResource.None ? GetEffectHues(ref res) : new int[0];
}
public static int[] GetEffectHues(ref CraftResource res)
{
LimitResource(ref res);
int hue;
switch (res)
{
case CraftResource.Iron:
hue = 48; // Gold
break;
case CraftResource.DullCopper:
hue = 98; // Dark Blue
break;
case CraftResource.ShadowIron:
hue = 43; // Orange
break;
case CraftResource.Copper:
hue = 88; // Blue
break;
case CraftResource.Bronze:
hue = 38; // Red
break;
case CraftResource.Gold:
hue = 63; // Green
break;
case CraftResource.Agapite:
hue = 53; // Yellow
break;
case CraftResource.Verite:
hue = 13; // Purple
break;
case CraftResource.Valorite:
hue = 183; // Aqua
break;
default:
hue = 48;
break;
}
var hues = new int[9];
hues.SetAll(
i =>
{
if (i > 0 && i % 3 == 0)
{
hue += 100;
}
return hue++;
});
return hues;
}
public static void LimitResource(ref CraftResource res)
{
var r = (int)res;
if (r <= 0 || r > 9)
{
res = CraftResource.Iron;
}
}
private CraftResource _Resource;
[CommandProperty(AccessLevel.GameMaster)]
public CraftResource Resource
{
get
{
LimitResource(ref _Resource);
return _Resource;
}
set
{
LimitResource(ref value);
if (_Resource == value)
{
return;
}
var old = _Resource;
_Resource = value;
if (Hue == 0 || Hue == CraftResources.GetHue(old))
{
Hue = CraftResources.GetHue(_Resource);
}
InvalidateProperties();
}
}
public override double DefaultWeight => 0.1;
public BaseFireworkStar(CraftResource res, int amount)
: base(16932)
{
Name = "Firework Star";
Resource = res;
Stackable = true;
Amount = Math.Max(1, Math.Min(60000, amount));
}
public BaseFireworkStar(Serial serial)
: base(serial)
{ }
public override void AddNameProperty(ObjectPropertyList list)
{
var res = CraftResources.GetName(Resource);
if (CraftResources.IsStandard(Resource))
{
res = String.Empty;
}
else
{
if (Insensitive.Contains(res, "Normal") || Insensitive.Contains(res, "Plain"))
{
var typ = CraftResources.GetType(Resource).ToString();
res = res.Replace("Normal", typ);
res = res.Replace("Plain", typ);
}
res = res.Replace("Scales", "Scale");
res = res.Replace("Crystals", "Crystal");
}
if (Amount <= 1)
{
list.Add(1050039, "{0}\t{1}", res, this.ResolveName());
}
else
{
list.Add(1050039, "{0}\t{1} {2}", Amount, res, this.ResolveName());
}
}
public override bool StackWith(Mobile m, Item dropped, bool playSound)
{
if (m == null || !(dropped is BaseFireworkStar) || ((BaseFireworkStar)dropped)._Resource != _Resource)
{
return false;
}
return base.StackWith(m, dropped, playSound);
}
public override int OnCraft(
int quality,
bool makersMark,
Mobile m,
CraftSystem craftSystem,
Type typeRes,
#if ServUO
ITool tool,
#else
BaseTool tool,
#endif
CraftItem craftItem,
int resHue)
{
if (craftSystem is Pyrotechnics && craftItem != null)
{
var resourceType = typeRes ?? craftItem.Resources.GetAt(0).ItemType;
Resource = CraftResources.GetFromType(resourceType);
}
return base.OnCraft(quality, makersMark, m, craftSystem, typeRes, tool, craftItem, resHue);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.WriteFlag(_Resource);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
_Resource = reader.ReadFlag<CraftResource>();
}
}
public sealed class FireworkStarCustom : BaseFireworkStar
{
private bool _Converted;
[Constructable]
public FireworkStarCustom()
: this(CraftResource.Iron, 1)
{ }
[Constructable]
public FireworkStarCustom(CraftResource res, int amount)
: base(res, amount)
{ }
public FireworkStarCustom(Serial serial)
: base(serial)
{ }
public override void ReplaceWith(Item newItem)
{
if (Parent is Container)
{
var cont = (Container)Parent;
if (newItem is BaseFireworkStar)
{
var star = (BaseFireworkStar)newItem;
var starType = star.GetType();
var stackWith = cont.FindItemsByType<BaseFireworkStar>()
.FirstOrDefault(
s => s.Stackable && s.Resource == star.Resource && s.Amount + star.Amount <= 60000 &&
s.GetType().IsEqual(starType));
if (stackWith != null)
{
stackWith.Amount += newItem.Amount;
newItem.Delete();
}
else
{
cont.AddItem(newItem);
newItem.Location = Location;
}
}
else
{
cont.AddItem(newItem);
newItem.Location = Location;
}
}
else
{
newItem.MoveToWorld(GetWorldLocation(), Map);
}
Delete();
}
public void Convert()
{
if (_Converted || Deleted || Map == null || Map == Map.Internal)
{
return;
}
_Converted = true;
switch (Resource)
{
case CraftResource.Iron:
ReplaceWith(new FireworkStarIron(Amount));
break;
case CraftResource.DullCopper:
ReplaceWith(new FireworkStarDullCopper(Amount));
break;
case CraftResource.ShadowIron:
ReplaceWith(new FireworkStarShadowIron(Amount));
break;
case CraftResource.Copper:
ReplaceWith(new FireworkStarCopper(Amount));
break;
case CraftResource.Bronze:
ReplaceWith(new FireworkStarBronze(Amount));
break;
case CraftResource.Gold:
ReplaceWith(new FireworkStarGold(Amount));
break;
case CraftResource.Agapite:
ReplaceWith(new FireworkStarAgapite(Amount));
break;
case CraftResource.Verite:
ReplaceWith(new FireworkStarVerite(Amount));
break;
case CraftResource.Valorite:
ReplaceWith(new FireworkStarValorite(Amount));
break;
default:
ReplaceWith(new FireworkStarIron(Amount));
break;
}
}
#if NEWPARENT
public override void OnAdded(IEntity parent)
#else
public override void OnAdded(object parent)
#endif
{
base.OnAdded(parent);
if (Map != null && Map != Map.Internal)
{
Convert();
}
}
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,49 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public class FireworkStarAgapite : BaseFireworkStar
{
[Constructable]
public FireworkStarAgapite()
: this(1)
{ }
[Constructable]
public FireworkStarAgapite(int amount)
: base(CraftResource.Agapite, amount)
{ }
public FireworkStarAgapite(Serial serial)
: base(serial)
{ }
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,49 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public class FireworkStarBronze : BaseFireworkStar
{
[Constructable]
public FireworkStarBronze()
: this(1)
{ }
[Constructable]
public FireworkStarBronze(int amount)
: base(CraftResource.Bronze, amount)
{ }
public FireworkStarBronze(Serial serial)
: base(serial)
{ }
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,49 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public class FireworkStarCopper : BaseFireworkStar
{
[Constructable]
public FireworkStarCopper()
: this(1)
{ }
[Constructable]
public FireworkStarCopper(int amount)
: base(CraftResource.Copper, amount)
{ }
public FireworkStarCopper(Serial serial)
: base(serial)
{ }
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,49 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public class FireworkStarDullCopper : BaseFireworkStar
{
[Constructable]
public FireworkStarDullCopper()
: this(1)
{ }
[Constructable]
public FireworkStarDullCopper(int amount)
: base(CraftResource.DullCopper, amount)
{ }
public FireworkStarDullCopper(Serial serial)
: base(serial)
{ }
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,49 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public class FireworkStarGold : BaseFireworkStar
{
[Constructable]
public FireworkStarGold()
: this(1)
{ }
[Constructable]
public FireworkStarGold(int amount)
: base(CraftResource.Gold, amount)
{ }
public FireworkStarGold(Serial serial)
: base(serial)
{ }
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,49 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public class FireworkStarIron : BaseFireworkStar
{
[Constructable]
public FireworkStarIron()
: this(1)
{ }
[Constructable]
public FireworkStarIron(int amount)
: base(CraftResource.Iron, amount)
{ }
public FireworkStarIron(Serial serial)
: base(serial)
{ }
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,49 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public class FireworkStarShadowIron : BaseFireworkStar
{
[Constructable]
public FireworkStarShadowIron()
: this(1)
{ }
[Constructable]
public FireworkStarShadowIron(int amount)
: base(CraftResource.ShadowIron, amount)
{ }
public FireworkStarShadowIron(Serial serial)
: base(serial)
{ }
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,49 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public class FireworkStarValorite : BaseFireworkStar
{
[Constructable]
public FireworkStarValorite()
: this(1)
{ }
[Constructable]
public FireworkStarValorite(int amount)
: base(CraftResource.Valorite, amount)
{ }
public FireworkStarValorite(Serial serial)
: base(serial)
{ }
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,49 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public class FireworkStarVerite : BaseFireworkStar
{
[Constructable]
public FireworkStarVerite()
: this(1)
{ }
[Constructable]
public FireworkStarVerite(int amount)
: base(CraftResource.Verite, amount)
{ }
public FireworkStarVerite(Serial serial)
: base(serial)
{ }
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,25 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
namespace VitaNex.Items
{
public enum FireworkStars
{
None,
Peony,
Chrysanthemum,
Dahlia,
Willow,
BloomFlower,
Ring,
Crossette
}
}

View File

@@ -0,0 +1,297 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using VitaNex.FX;
using VitaNex.Geometry;
using VitaNex.Network;
#endregion
namespace VitaNex.Items
{
public static class Fireworks
{
public static void DoStarsEffect(
this FireworkStars fx,
IPoint3D p,
Map map,
int radius,
int sound,
int[] stars,
int[] hues)
{
if (fx == FireworkStars.None || stars == null || stars.Length == 0)
{
return;
}
radius = Math.Max(0, Math.Min(10, radius));
if (hues == null || hues.Length == 0)
{
hues = new int[9];
hues.SetAll(i => Utility.RandomBrightHue());
}
switch (fx)
{
case FireworkStars.Peony:
{
var shape = new Sphere3D(p, radius, true);
foreach (var b in shape)
{
new MovingEffectInfo(
p,
b,
map,
stars.GetRandom(),
hues.GetRandom(),
Utility.RandomMinMax(4, 6),
EffectRender.LightenMore).MovingImpact(
e =>
{
if (sound > 0 && Utility.RandomDouble() <= 0.25)
{
Effects.PlaySound(b, map, sound);
}
});
}
shape.Clear();
}
break;
case FireworkStars.Chrysanthemum:
{
var shape = new Disc3D(p, radius, false);
foreach (var b in shape)
{
new MovingEffectInfo(
p,
b,
map,
stars.GetRandom(),
hues.GetRandom(),
Utility.RandomMinMax(4, 6),
EffectRender.LightenMore).MovingImpact(
e =>
{
if (sound > 0 && Utility.RandomDouble() <= 0.25)
{
Effects.PlaySound(b, map, sound);
}
});
}
shape.Clear();
}
break;
case FireworkStars.Dahlia:
{
var shape = new Cylinder3D(p, radius, true, false);
foreach (var b in shape)
{
new MovingEffectInfo(
p,
b,
map,
stars.GetRandom(),
hues.GetRandom(),
Utility.RandomMinMax(6, 8),
EffectRender.LightenMore).MovingImpact(
e =>
{
if (sound > 0 && Utility.RandomDouble() <= 0.25)
{
Effects.PlaySound(b, map, sound);
}
});
}
shape.Clear();
}
break;
case FireworkStars.Willow:
{
var shape = new Disc3D(p, radius, true);
foreach (var b in shape)
{
new MovingEffectInfo(
p,
b,
map,
stars.GetRandom(),
hues.GetRandom(),
Utility.RandomMinMax(6, 8),
EffectRender.LightenMore).MovingImpact(
e =>
{
if (Utility.RandomDouble() < 0.66)
{
return;
}
var zL = b.Z;
var zR = b.GetWorldTop(map).Z;
if (zL <= zR || zL < p.Z)
{
return;
}
var zDiff = zL - zR;
if (zDiff < 30)
{
return;
}
var t = b.Clone3D(0, 0, -(zDiff / 2));
new MovingEffectInfo(b, t, map, e.EffectID, e.Hue, Math.Max(1, e.Speed / 2), e.Render).Send();
if (sound > 0 && Utility.RandomDouble() <= 0.25)
{
Effects.PlaySound(b, map, sound);
}
});
}
shape.Clear();
}
break;
case FireworkStars.BloomFlower:
{
var shape = new Ring3D(p, radius);
foreach (var b in shape)
{
new MovingEffectInfo(
p,
b,
map,
stars.GetRandom(),
hues.GetRandom(),
Utility.RandomMinMax(6, 8),
EffectRender.LightenMore).MovingImpact(
e =>
{
if (Utility.RandomDouble() < 0.66)
{
return;
}
var t = b.Clone3D(Utility.RandomMinMax(-3, 3), Utility.RandomMinMax(-3, 3), Utility.RandomMinMax(-10, 10));
new MovingEffectInfo(b, t, map, e.EffectID, e.Hue, e.Speed, e.Render).Send();
if (sound > 0 && Utility.RandomDouble() <= 0.25)
{
Effects.PlaySound(b, map, sound);
}
});
}
shape.Clear();
}
break;
case FireworkStars.Ring:
{
var shape = new Ring3D(p, radius);
foreach (var b in shape)
{
new MovingEffectInfo(
p,
b,
map,
stars.GetRandom(),
hues.GetRandom(),
Utility.RandomMinMax(6, 8),
EffectRender.LightenMore).MovingImpact(
e =>
{
var zL = b.Z;
var zR = b.GetWorldTop(map).Z;
if (zL <= zR || zL < p.Z)
{
return;
}
var zDiff = zL - zR;
if (zDiff < 30)
{
return;
}
var t = b.Clone3D(0, 0, -(zDiff / 2));
new MovingEffectInfo(b, t, map, e.EffectID, e.Hue, 2, e.Render).Send();
if (sound > 0 && Utility.RandomDouble() <= 0.25)
{
Effects.PlaySound(b, map, sound);
}
});
}
shape.Clear();
}
break;
case FireworkStars.Crossette:
{
var shape = new Plane3D(p, radius, true);
foreach (var b in shape)
{
new MovingEffectInfo(
p,
b,
map,
stars.GetRandom(),
hues.GetRandom(),
Utility.RandomMinMax(6, 8),
EffectRender.LightenMore).MovingImpact(
e =>
{
if (Utility.RandomDouble() < 0.33)
{
return;
}
var t = b.Clone3D(Utility.RandomMinMax(-5, 5), Utility.RandomMinMax(-5, 5));
new MovingEffectInfo(b, t, map, e.EffectID, e.Hue, e.Speed, e.Render).Send();
if (sound > 0 && Utility.RandomDouble() <= 0.25)
{
Effects.PlaySound(b, map, sound);
}
});
}
shape.Clear();
}
break;
}
}
}
}

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.Linq;
using Server;
using Server.Engines.Craft;
using Server.Items;
using VitaNex.FX;
using VitaNex.Network;
using VitaNex.SuperCrafts;
#endregion
namespace VitaNex.Items
{
public abstract class BaseFireworkRocket : BaseFirework
{
#region Launch Effect
public virtual int DefLaunchID => ItemID;
public virtual int DefLaunchHue => Hue;
public virtual int DefLaunchSpeed => 8;
public virtual EffectRender DefLaunchRender => EffectRender.Normal;
public virtual int DefLaunchSound => 551;
public virtual int DefLaunchRangeMin => 1;
public virtual int DefLaunchRangeMax => 3;
public virtual int DefLaunchHeightMin => 60;
public virtual int DefLaunchHeightMax => 80;
[CommandProperty(AccessLevel.GameMaster)]
public int LaunchID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int LaunchHue { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int LaunchSpeed { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public EffectRender LaunchRender { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int LaunchSound { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int LaunchHeightMin { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int LaunchHeightMax { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int LaunchRangeMin { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int LaunchRangeMax { get; set; }
#endregion
#region Trail Effect
public virtual int DefTrailID => 14120;
public virtual int DefTrailHue => 0;
public virtual int DefTrailSpeed => 10;
public virtual int DefTrailDuration => 10;
public virtual EffectRender DefTrailRender => EffectRender.SemiTransparent;
public virtual int DefTrailSound => 856;
[CommandProperty(AccessLevel.GameMaster)]
public int TrailID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int TrailHue { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int TrailSpeed { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int TrailDuration { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public EffectRender TrailRender { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int TrailSound { get; set; }
#endregion
#region Explode Effect
public virtual int DefExplodeID => 14000;
public virtual int DefExplodeHue => 0;
public virtual int DefExplodeSpeed => 10;
public virtual int DefExplodeDuration => 13;
public virtual EffectRender DefExplodeRender => EffectRender.LightenMore;
public virtual int DefExplodeSound => 776;
[CommandProperty(AccessLevel.GameMaster)]
public int ExplodeID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int ExplodeHue { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int ExplodeSpeed { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int ExplodeDuration { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public EffectRender ExplodeRender { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int ExplodeSound { get; set; }
#endregion
#region Stars Effect
public virtual FireworkStars DefStarsEffect => FireworkStars.Peony;
public virtual int DefStarsHue => 0;
public virtual int DefStarsSound => 776;
public virtual int DefStarsRangeMin => 5;
public virtual int DefStarsRangeMax => 10;
public virtual int[] DefStars => new[] { 14170, 14155, 14138, 10980, 10296, 10297, 10298, 10299, 10300, 10301 };
public virtual int[] DefStarHues => new int[0];
[CommandProperty(AccessLevel.GameMaster)]
public FireworkStars StarsEffect { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int StarsHue { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int StarsSound { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int StarsRangeMin { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int StarsRangeMax { get; set; }
public List<int> Stars { get; set; }
public List<int> StarHues { get; set; }
#endregion
public BaseFireworkRocket(int itemID, int hue)
: base(itemID, hue)
{
LaunchID = DefLaunchID;
LaunchHue = DefLaunchHue;
LaunchSpeed = DefLaunchSpeed;
LaunchRender = DefLaunchRender;
LaunchSound = DefLaunchSound;
LaunchHeightMin = DefLaunchHeightMin;
LaunchHeightMax = DefLaunchHeightMax;
LaunchRangeMin = DefLaunchRangeMin;
LaunchRangeMax = DefLaunchRangeMax;
TrailID = DefTrailID;
TrailHue = DefTrailHue;
TrailSpeed = DefTrailSpeed;
TrailDuration = DefTrailDuration;
TrailRender = DefTrailRender;
TrailSound = DefTrailSound;
ExplodeID = DefExplodeID;
ExplodeHue = DefExplodeHue;
ExplodeSpeed = DefExplodeSpeed;
ExplodeDuration = DefExplodeDuration;
ExplodeRender = DefExplodeRender;
ExplodeSound = DefExplodeSound;
StarsEffect = DefStarsEffect;
StarsHue = DefStarsHue;
StarsSound = DefStarsSound;
StarsRangeMin = DefStarsRangeMin;
StarsRangeMax = DefStarsRangeMax;
Stars = new List<int>(DefStars);
StarHues = new List<int>(DefStarHues);
}
public BaseFireworkRocket(Serial serial)
: base(serial)
{ }
protected virtual Point3D[] GetPath()
{
var start = GetWorldLocation();
var end = start.GetRandomPoint2D(Utility.RandomMinMax(LaunchRangeMin, LaunchRangeMax));
return start.GetLine3D(end.ToPoint3D(Utility.RandomMinMax(LaunchHeightMin, LaunchHeightMax)), Map, false);
}
protected override bool OnFuseBurned(Mobile m)
{
return Launch(m);
}
protected bool Launch(Mobile m)
{
if (m == null || m.Deleted)
{
return false;
}
var path = GetPath();
if (path == null || path.Length == 0)
{
return false;
}
var start = path.First();
var end = path.Last();
if (!OnLaunch(m, start, end))
{
return false;
}
var q = new MovingEffectQueue(() => Explode(m, end));
for (var i = 0; i < path.Length; i++)
{
var p = path[i];
if (i + 1 >= path.Length)
{
continue;
}
var pn = path[i + 1];
q.Add(
new MovingEffectInfo(
p,
pn,
Map,
LaunchID,
LaunchHue,
LaunchSpeed,
LaunchRender,
TimeSpan.Zero,
() => LaunchTrail(pn)));
}
q.Process();
if (LaunchSound > 0)
{
Effects.PlaySound(GetWorldLocation(), Map, LaunchSound);
}
Visible = false;
return true;
}
protected virtual bool OnLaunch(Mobile m, Point3D start, Point3D end)
{
return true;
}
protected void LaunchTrail(Point3D p)
{
if (TrailID > 0)
{
var fx = new EffectInfo(p, Map, TrailID, TrailHue, TrailSpeed, TrailDuration, TrailRender);
fx.Send();
}
if (TrailSound > 0)
{
Effects.PlaySound(p, Map, TrailSound);
}
}
protected void Explode(Mobile m, Point3D p)
{
if (m == null || m.Deleted)
{
return;
}
if (!OnExplode(m, p))
{
return;
}
if (ExplodeID > 0)
{
var fx = new EffectInfo(p, Map, ExplodeID, ExplodeHue, ExplodeSpeed, ExplodeDuration, ExplodeRender);
fx.Send();
}
if (ExplodeSound >= 0)
{
Effects.PlaySound(p, Map, ExplodeSound);
}
ExplodeStars(
m,
StarsEffect,
p,
Utility.RandomMinMax(StarsRangeMin, StarsRangeMax),
StarsSound,
Stars.ToArray(),
StarsHue > 0 ? new[] { StarsHue } : StarHues.ToArray());
Movable = false;
Timer.DelayCall(
TimeSpan.FromSeconds(1.0),
() =>
{
Movable = true;
Consume();
});
}
protected virtual bool OnExplode(Mobile m, Point3D p)
{
return true;
}
protected virtual void ExplodeStars(
Mobile m,
FireworkStars fx,
Point3D p,
int radius,
int sound,
int[] stars,
int[] hues)
{
if (m != null && !m.Deleted && fx != FireworkStars.None && stars != null && stars.Length != 0 && !Deleted)
{
fx.DoStarsEffect(p, Map, radius, sound, stars, hues);
}
}
public override void OnDelete()
{
base.OnDelete();
Stars.Clear();
Stars.TrimExcess();
StarHues.Clear();
StarHues.TrimExcess();
}
public override int OnCraft(
int quality,
bool makersMark,
Mobile m,
CraftSystem craftSystem,
Type typeRes,
#if ServUO
ITool tool,
#else
BaseTool tool,
#endif
CraftItem craftItem,
int resHue)
{
if (craftSystem is Pyrotechnics && craftItem != null)
{
var stars = new CraftRes[craftItem.Resources.Count];
stars.SetAll(i => craftItem.Resources.GetAt(i));
stars = stars.Where(res => res.ItemType.IsEqualOrChildOf<BaseFireworkStar>()).ToArray();
if (stars.Length > 0)
{
StarsRangeMin = 1 + stars.Sum(s => s.Amount);
StarsRangeMax = StarsRangeMin * 2;
LaunchHeightMin = Math.Max(50, Math.Min(100, StarsRangeMin * 5));
LaunchHeightMax = Math.Max(50, Math.Min(100, StarsRangeMax * 5));
StarHues.AddRange(BaseFireworkStar.GetEffectHues(typeRes ?? stars[0].ItemType));
if (stars.Length > 1)
{
StarHues.AddRange(stars.Skip(1).SelectMany(s => BaseFireworkStar.GetEffectHues(s.ItemType)));
}
}
}
return base.OnCraft(quality, makersMark, m, craftSystem, typeRes, tool, craftItem, resHue);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(LaunchID);
writer.Write(LaunchHue);
writer.Write(LaunchSpeed);
writer.WriteFlag(LaunchRender);
writer.Write(LaunchSound);
writer.Write(LaunchRangeMin);
writer.Write(LaunchRangeMax);
writer.Write(LaunchHeightMin);
writer.Write(LaunchHeightMax);
writer.Write(TrailID);
writer.Write(TrailHue);
writer.Write(TrailSpeed);
writer.Write(TrailDuration);
writer.WriteFlag(TrailRender);
writer.Write(TrailSound);
writer.Write(ExplodeID);
writer.Write(ExplodeHue);
writer.Write(ExplodeSpeed);
writer.Write(ExplodeDuration);
writer.WriteFlag(ExplodeRender);
writer.Write(ExplodeSound);
writer.WriteFlag(StarsEffect);
writer.Write(StarsHue);
writer.Write(StarsSound);
writer.Write(StarsRangeMin);
writer.Write(StarsRangeMax);
writer.WriteList(Stars, writer.Write);
writer.WriteList(StarHues, writer.Write);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
LaunchID = reader.ReadInt();
LaunchHue = reader.ReadInt();
LaunchSpeed = reader.ReadInt();
LaunchRender = reader.ReadFlag<EffectRender>();
LaunchSound = reader.ReadInt();
LaunchRangeMin = reader.ReadInt();
LaunchRangeMax = reader.ReadInt();
LaunchHeightMin = reader.ReadInt();
LaunchHeightMax = reader.ReadInt();
TrailID = reader.ReadInt();
TrailHue = reader.ReadInt();
TrailSpeed = reader.ReadInt();
TrailDuration = reader.ReadInt();
TrailRender = reader.ReadFlag<EffectRender>();
TrailSound = reader.ReadInt();
ExplodeID = reader.ReadInt();
ExplodeHue = reader.ReadInt();
ExplodeSpeed = reader.ReadInt();
ExplodeDuration = reader.ReadInt();
ExplodeRender = reader.ReadFlag<EffectRender>();
ExplodeSound = reader.ReadInt();
StarsEffect = reader.ReadFlag<FireworkStars>();
StarsHue = reader.ReadInt();
StarsSound = reader.ReadInt();
StarsRangeMin = reader.ReadInt();
StarsRangeMax = reader.ReadInt();
Stars = reader.ReadList(reader.ReadInt);
StarHues = reader.ReadList(reader.ReadInt);
}
break;
}
}
}
}

View File

@@ -0,0 +1,53 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Items
{
public class BigBettyRocket : BaseFireworkRocket
{
public override FireworkStars DefStarsEffect => FireworkStars.Willow;
[Constructable]
public BigBettyRocket()
: this(Utility.RandomMetalHue())
{ }
[Constructable]
public BigBettyRocket(int hue)
: base(2887, hue)
{
Name = "Big Betty";
Weight = 6.0;
}
public BigBettyRocket(Serial serial)
: base(serial)
{ }
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,53 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Items
{
public class BlockBusterRocket : BaseFireworkRocket
{
public override FireworkStars DefStarsEffect => FireworkStars.BloomFlower;
[Constructable]
public BlockBusterRocket()
: this(Utility.RandomMetalHue())
{ }
[Constructable]
public BlockBusterRocket(int hue)
: base(9242, hue)
{
Name = "Block Buster";
Weight = 8.0;
}
public BlockBusterRocket(Serial serial)
: base(serial)
{ }
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,53 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Items
{
public class BottleRocket : BaseFireworkRocket
{
public override FireworkStars DefStarsEffect => FireworkStars.Peony;
[Constructable]
public BottleRocket()
: this(Utility.RandomMetalHue())
{ }
[Constructable]
public BottleRocket(int hue)
: base(6189, hue)
{
Name = "Bottle Rocket";
Weight = 2.0;
}
public BottleRocket(Serial serial)
: base(serial)
{ }
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,53 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Items
{
public class LittleBoyRocket : BaseFireworkRocket
{
public override FireworkStars DefStarsEffect => FireworkStars.Dahlia;
[Constructable]
public LittleBoyRocket()
: this(Utility.RandomMetalHue())
{ }
[Constructable]
public LittleBoyRocket(int hue)
: base(2581, hue)
{
Name = "Little Boy";
Weight = 2.0;
}
public LittleBoyRocket(Serial serial)
: base(serial)
{ }
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,53 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Items
{
public class MoonShineRocket : BaseFireworkRocket
{
public override FireworkStars DefStarsEffect => FireworkStars.Ring;
[Constructable]
public MoonShineRocket()
: this(Utility.RandomMetalHue())
{ }
[Constructable]
public MoonShineRocket(int hue)
: base(18881, hue)
{
Name = "Moon Shine";
Weight = 4.0;
}
public MoonShineRocket(Serial serial)
: base(serial)
{ }
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,53 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Items
{
public class PenetratorRocket : BaseFireworkRocket
{
public override FireworkStars DefStarsEffect => FireworkStars.Chrysanthemum;
[Constructable]
public PenetratorRocket()
: this(Utility.RandomMetalHue())
{ }
[Constructable]
public PenetratorRocket(int hue)
: base(6202, hue)
{
Name = "The Penetrator";
Weight = 4.0;
}
public PenetratorRocket(Serial serial)
: base(serial)
{ }
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,53 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Items
{
public class SkyShieldRocket : BaseFireworkRocket
{
public override FireworkStars DefStarsEffect => FireworkStars.Crossette;
[Constructable]
public SkyShieldRocket()
: this(Utility.RandomMetalHue())
{ }
[Constructable]
public SkyShieldRocket(int hue)
: base(576, hue)
{
Name = "Sky Shield";
Weight = 3.0;
}
public SkyShieldRocket(Serial serial)
: base(serial)
{ }
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,199 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public interface IMagicFoodMod
{ }
public interface IMagicFood
{
TimeSpan BuffDuration { get; set; }
int IconID { get; set; }
int EffectID { get; set; }
int SoundID { get; set; }
bool Eat(Mobile m);
bool ApplyBuff(Mobile m);
bool RemoveBuff(Mobile m);
}
public abstract class MagicFood : Food, IMagicFood
{
private Timer DelayTimer { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual TimeSpan BuffDuration { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int IconID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int EffectID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int SoundID { get; set; }
public MagicFood(int itemID)
: this(itemID, 1)
{ }
public MagicFood(int itemID, int amount)
: base(amount, itemID)
{
BuffDuration = TimeSpan.FromSeconds(300.0);
}
public MagicFood(Serial serial)
: base(serial)
{ }
public override sealed bool Eat(Mobile m)
{
if (m == null || m.Deleted)
{
return false;
}
if (CheckHunger(m))
{
m.PlaySound(Utility.Random(0x3A, 3));
if (m.Body.IsHuman && !m.Mounted)
{
m.Animate(34, 5, 1, true, false, 0);
}
if (Poison != null)
{
m.ApplyPoison(Poisoner, Poison);
}
OnEaten(m);
Consume();
return true;
}
return false;
}
public abstract bool ApplyBuff(Mobile m);
public abstract bool RemoveBuff(Mobile m);
public override bool CheckHunger(Mobile m)
{
return FillFactor <= 0 || FillHunger(m, FillFactor);
}
protected virtual void OnEaten(Mobile m)
{
if (m != null && !m.Deleted)
{
DoApplyBuff(m);
}
}
protected virtual void DoApplyBuff(Mobile m)
{
if (m == null || m.Deleted || !ApplyBuff(m))
{
return;
}
if (SoundID > 0)
{
m.PlaySound(SoundID);
}
if (EffectID > 0)
{
m.FixedParticles(EffectID, 10, 15, 5018, EffectLayer.Waist);
}
if (IconID > 0)
{
m.Send(new AddBuffPacket(m, new BuffInfo((BuffIcon)IconID, LabelNumber)));
}
if (DelayTimer != null && DelayTimer.Running)
{
DelayTimer.Stop();
}
DelayTimer = Timer.DelayCall(BuffDuration, DoRemoveBuff, m);
}
protected virtual void DoRemoveBuff(Mobile m)
{
if (m == null || m.Deleted || !RemoveBuff(m))
{
return;
}
if (IconID > 0)
{
m.Send(new RemoveBuffPacket(m, (BuffIcon)IconID));
}
if (DelayTimer != null && DelayTimer.Running)
{
DelayTimer.Stop();
}
DelayTimer = null;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(BuffDuration);
writer.Write(IconID);
writer.Write(EffectID);
writer.Write(SoundID);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
BuffDuration = reader.ReadTimeSpan();
IconID = reader.ReadInt();
EffectID = reader.ReadInt();
SoundID = reader.ReadInt();
}
break;
}
}
}
}

View File

@@ -0,0 +1,431 @@
#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.Tasks;
using Server;
using Server.Network;
using VitaNex.FX;
using VitaNex.Network;
#endregion
namespace VitaNex.Items
{
public class GhostMulti : Item
{
private PollTimer _Timer;
private Point3D _Center;
private List<EffectInfo> _Effects;
private int _MultiID;
private EffectRender _Render;
private TimeSpan _Interval;
private int _Duration;
private int _Speed;
[Hue, CommandProperty(AccessLevel.GameMaster)]
public override int Hue
{
get => base.Hue;
set
{
value = Math.Max(0, Math.Min(3000, value));
base.Hue = value;
if (_Effects == null)
{
return;
}
foreach (var e in _Effects)
{
e.Hue = value;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int MultiID
{
get => _MultiID;
set
{
if (_MultiID == value)
{
return;
}
_MultiID = value;
Stop();
Start();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public EffectRender Render
{
get => _Render;
set
{
_Render = value;
if (_Effects == null)
{
return;
}
foreach (var e in _Effects)
{
e.Render = value;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan Interval
{
get => _Interval;
set
{
_Interval = value;
if (_Timer != null)
{
_Timer.Interval = value;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int Duration
{
get => _Duration;
set
{
_Duration = value;
if (_Effects == null)
{
return;
}
foreach (var e in _Effects)
{
e.Duration = value;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int Speed
{
get => _Speed;
set
{
_Speed = value;
if (_Effects == null)
{
return;
}
foreach (var e in _Effects)
{
e.Speed = value;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Active { get; set; }
public override bool Decays => false;
public override bool IsVirtualItem => true;
public override bool HandlesOnMovement => true;
public virtual bool PlayerRangeSensitive => true;
public virtual TimeSpan ActivityInterval => TimeSpan.FromSeconds(30.0);
private PollTimer _ActivityTimer;
private DateTime _LastActivity;
[Constructable]
public GhostMulti()
: this(1)
{ }
[Constructable]
public GhostMulti(int multiID)
: this(14284, multiID)
{ }
[Constructable]
public GhostMulti(int itemID, int multiID)
: base(itemID)
{
_MultiID = multiID;
_Interval = TimeSpan.FromSeconds(3.55);
_Render = EffectRender.Normal;
_Duration = 73;
_Speed = 10;
Name = "Ghostly Structure";
Light = LightType.DarkCircle300;
Weight = 0;
Visible = false;
Active = true;
}
public GhostMulti(Serial serial)
: base(serial)
{ }
public override void OnDelete()
{
base.OnDelete();
Stop();
}
public override void OnLocationChange(Point3D oldLocation)
{
base.OnLocationChange(oldLocation);
Start();
}
public override void OnMapChange()
{
base.OnMapChange();
Start();
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
base.OnMovement(m, oldLocation);
if (m == null || m.Deleted || !m.Player || m.NetState == null)
{
return;
}
_LastActivity = DateTime.UtcNow;
Start();
}
public void Start()
{
if (Deleted || !Active || Map == null || Map == Map.Internal || Parent != null)
{
Stop();
return;
}
if (_Effects == null || _Center != GetWorldLocation())
{
ClearEffects();
_Effects = new List<EffectInfo>(GetEffects());
}
if (_Timer == null)
{
_Timer = PollTimer.CreateInstance(
Interval,
() =>
{
if (!Active)
{
Stop();
return;
}
SendEffects();
},
() => !Deleted && Active && Map != null && Map != Map.Internal && Parent == null);
}
else
{
_Timer.Running = true;
}
if (!PlayerRangeSensitive)
{
if (_ActivityTimer != null)
{
_ActivityTimer.Running = false;
_ActivityTimer = null;
}
return;
}
if (_ActivityTimer != null)
{
_ActivityTimer.Running = true;
return;
}
_ActivityTimer = PollTimer.CreateInstance(
ActivityInterval,
() =>
{
if (DateTime.UtcNow - _LastActivity < ActivityInterval)
{
return;
}
var clients = GetClientsInRange(Core.GlobalMaxUpdateRange);
if (clients.Any())
{
clients.Free();
return;
}
clients.Free();
Stop();
},
() => !Deleted && Map != null && Map != Map.Internal && Parent == null);
}
public void Stop()
{
if (_ActivityTimer != null)
{
_ActivityTimer.Running = false;
_ActivityTimer = null;
}
ClearEffects();
if (_Timer == null)
{
return;
}
_Timer.Running = false;
_Timer = null;
}
protected EffectInfo[] GetEffects()
{
var l = GetWorldLocation();
var c = MultiData.GetComponents(MultiID);
_Center = l.Clone3D(c.Center.X, c.Center.Y, l.Z);
var list = new EffectInfo[c.List.Length];
Parallel.For(
0,
list.Length,
index =>
{
var t = c.List[index];
var p = l.Clone3D(t.m_OffsetX, t.m_OffsetY, t.m_OffsetZ);
list[index] = new EffectInfo(p, Map, t.m_ItemID, Hue, Speed, Duration, Render);
});
return list;
}
protected virtual void ClearEffects()
{
if (_Effects == null)
{
return;
}
foreach (var e in _Effects)
{
e.Dispose();
}
_Effects.Free(true);
_Effects = null;
}
protected virtual void SendEffects()
{
if (_Effects == null)
{
return;
}
foreach (var e in _Effects)
{
e.Send();
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
writer.Write(Active);
goto case 0;
case 0:
{
writer.Write(_MultiID);
writer.Write(_Center);
writer.WriteFlag(_Render);
writer.Write(_Duration);
writer.Write(_Speed);
writer.Write(_Interval);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 1:
Active = reader.ReadBool();
goto case 0;
case 0:
{
_MultiID = reader.ReadInt();
_Center = reader.ReadPoint3D();
_Render = reader.ReadFlag<EffectRender>();
_Duration = reader.ReadInt();
_Speed = reader.ReadInt();
_Interval = reader.ReadTimeSpan();
}
break;
}
Start();
}
}
}

View File

@@ -0,0 +1,30 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server.Items;
#endregion
namespace VitaNex.Items
{
public class LuckyDipBankCheckPrize : LuckyDipPrize
{
public int Worth => Args[0] as int? ?? 0;
public LuckyDipBankCheckPrize()
: this(0.0, 0)
{ }
public LuckyDipBankCheckPrize(double chance, int worth)
: base(chance, typeof(BankCheck), worth)
{ }
}
}

View File

@@ -0,0 +1,66 @@
#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.Items
{
public class LuckyDipPrize : IEquatable<LuckyDipPrize>
{
public double Chance { get; set; }
public Type Type { get; set; }
public object[] Args { get; set; }
public bool Disabled => Type == null || Chance <= 0.0;
public LuckyDipPrize()
: this(0.0, null, null)
{ }
public LuckyDipPrize(double chance, Type type, params object[] args)
{
Chance = Math.Min(0.0, Math.Max(1.0, chance));
Type = type;
Args = args ?? new object[0];
}
public bool Equals(LuckyDipPrize other)
{
return Equals(Args, other.Args) && Chance.Equals(other.Chance) && Type == other.Type;
}
public override bool Equals(object obj)
{
return !ReferenceEquals(null, obj) && (obj is LuckyDipPrize && Equals((LuckyDipPrize)obj));
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (Args != null ? Args.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ Chance.GetHashCode();
hashCode = (hashCode * 397) ^ (Type != null ? Type.GetHashCode() : 0);
return hashCode;
}
}
public TItem CreateInstance<TItem>()
where TItem : Item
{
return Type.CreateInstanceSafe<TItem>(Args);
}
}
}

View File

@@ -0,0 +1,314 @@
#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 Server;
#endregion
namespace VitaNex.Items
{
public class LuckyDipTicket : Item
{
private static void Normalize(ref double chance)
{
chance = Math.Max(0.0, Math.Min(1.0, chance));
}
private int _LuckCap = 3000;
private int _PrizeTier;
public List<LuckyDipPrize> Prizes { get; set; }
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int PrizeTier
{
get => _PrizeTier;
set
{
value = Math.Max(1, value);
if (_PrizeTier == value)
{
return;
}
_PrizeTier = value;
InitPrizes();
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int LuckCap
{
get => _LuckCap;
set
{
value = Math.Max(0, value);
if (_LuckCap == value)
{
return;
}
_LuckCap = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public virtual int GoldPrice => (int)Math.Ceiling(GetAveragePrizeWorth());
[Constructable]
public LuckyDipTicket()
: this(1)
{ }
[Constructable]
public LuckyDipTicket(int tierMin, int tierMax)
: this(Utility.RandomMinMax(tierMin, tierMax))
{ }
[Constructable]
public LuckyDipTicket(int tier)
: base(0x14F0)
{
PrizeTier = tier;
Name = "Lucky Dip Ticket";
Weight = 1.0;
LootType = LootType.Blessed;
}
public LuckyDipTicket(Serial serial)
: base(serial)
{ }
public void InitPrizes()
{
if (Prizes == null)
{
Prizes = new List<LuckyDipPrize>();
}
Prizes.Clear();
InitBankChecks();
InitItems();
}
protected virtual void InitItems()
{ }
protected virtual void InitBankChecks()
{
var f = (int)Math.Max(0, Math.Pow(10, PrizeTier));
AddPrize(new LuckyDipBankCheckPrize(0.80, 1 * f));
AddPrize(new LuckyDipBankCheckPrize(0.40, 10 * f));
AddPrize(new LuckyDipBankCheckPrize(0.20, 25 * f));
AddPrize(new LuckyDipBankCheckPrize(0.10, 50 * f));
AddPrize(new LuckyDipBankCheckPrize(0.05, 75 * f));
AddPrize(new LuckyDipBankCheckPrize(0.02, 100 * f));
}
public virtual int GetMinPrizeWorth()
{
return Prizes.OfType<LuckyDipBankCheckPrize>().Min(e => e.Worth);
}
public virtual int GetMaxPrizeWorth()
{
return Prizes.OfType<LuckyDipBankCheckPrize>().Max(e => e.Worth);
}
public virtual double GetAveragePrizeWorth()
{
return Prizes.OfType<LuckyDipBankCheckPrize>().Average(e => e.Worth);
}
public double GetMinChance()
{
return Prizes.Min(e => e.Chance);
}
public double GetMaxChance()
{
return Prizes.Max(e => e.Chance);
}
public double GetAverageChance()
{
return Prizes.Average(e => e.Chance);
}
public void AddPrize(LuckyDipPrize prize)
{
if (!Prizes.Contains(prize) && OnAddPrize(prize))
{
Prizes.Add(prize);
}
}
protected virtual bool OnAddPrize(LuckyDipPrize prize)
{
return true;
}
public virtual IEnumerable<LuckyDipPrize> GetPrizes(double chance)
{
if (Prizes == null || Prizes.Count == 0)
{
yield break;
}
Normalize(ref chance);
foreach (var p in Prizes.Where(e => !e.Disabled && e.Chance >= chance).OrderByDescending(e => e.Chance))
{
yield return p;
}
}
public virtual LuckyDipPrize GetPrize(double chance)
{
if (Prizes == null || Prizes.Count == 0)
{
return null;
}
Normalize(ref chance);
return GetPrizes(1.0 - chance).GetRandom();
}
protected void BeginGamble(Mobile from)
{
if (from == null || from.Deleted)
{
return;
}
if (from.BeginAction(GetType(), TimeSpan.FromSeconds(2.0), EndGamble))
{
from.SendMessage(85, "Please wait a moment while we process your ticket...");
}
else
{
from.SendMessage(34, "You must wait a moment before using another ticket.");
}
}
protected void EndGamble(Mobile from, Type t)
{
if (from == null || from.Deleted)
{
return;
}
var a = Utility.RandomDouble() * 0.5;
var b = (Math.Min(LuckCap, from.Luck) / (double)LuckCap) * 0.5;
var c = a + b;
Normalize(ref c);
//Console.WriteLine("LDT: A = {0} B = {1} C = {2}", a, b, c);
var prizeEntry = GetPrize(c);
if (prizeEntry == null || prizeEntry.Disabled)
{
from.SendMessage(34, "Sorry {0}, you didn't win anything, better luck next time!", from.RawName);
Delete();
return;
}
var prize = prizeEntry.CreateInstance<Item>();
if (prize == null)
{
Prizes.Remove(prizeEntry);
VitaNexCore.ToConsole(
"WARNING: An instance of {0} could not be constructed in {1} at {2}",
prizeEntry.Type.FullName,
GetType().FullName,
prizeEntry.GetType().FullName);
from.SendMessage(34, "We couldn't process your ticket, please try again.");
return;
}
from.SendMessage(85, "Congratulations, you won a prize! ({0})", prize.ResolveName(from));
ReplaceWith(prize);
}
public override void OnDoubleClick(Mobile from)
{
if (this.CheckDoubleClick(from, true, false, 2, true))
{
BeginGamble(from);
}
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
var props = String.Format("Use: A chance to win a Tier {0} prize!".WrapUOHtmlColor(Color.SkyBlue), PrizeTier);
if (LuckCap > 0)
{
props += "\n" + "Tip: Increase your luck to increase your odds!".WrapUOHtmlColor(Color.Gold);
}
list.Add(props);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(LuckCap);
writer.Write(PrizeTier);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
LuckCap = reader.ReadInt();
PrizeTier = reader.ReadInt();
}
break;
}
}
}
}

View File

@@ -0,0 +1,153 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Items;
using VitaNex.FX;
using VitaNex.Network;
#endregion
namespace VitaNex.Items
{
public delegate bool DecapitateHandler(Mobile from, Mobile target, Func<Mobile, Item> createHead = null);
public class SeveredHead : Item
{
public static DecapitateHandler Decapitate = HandleDecapitate;
public static bool HandleDecapitate(Mobile from, Mobile target, Func<Mobile, Item> createHead = null)
{
if (from == null || target == null)
{
return false;
}
var map = target.Map;
target.Freeze(TimeSpan.FromSeconds(1.0));
var range = Utility.RandomMinMax(5, 7);
var zOffset = target.Mounted ? 20 : 10;
var src = target.Location.Clone3D(0, 0, zOffset);
var points = src.GetAllPointsInRange(map, range, range);
Effects.PlaySound(target.Location, map, 0x19C);
target.Send(VNScreenLightFlash.Instance);
Timer.DelayCall(
TimeSpan.FromMilliseconds(100),
() =>
{
foreach (var trg in points)
{
var bloodID = Utility.RandomMinMax(4650, 4655);
new MovingEffectInfo(src, trg.Clone3D(0, 0, 2), from.Map, bloodID).MovingImpact(
info =>
{
new Blood(bloodID).MoveToWorld(info.Target.Location, info.Map);
Effects.PlaySound(info.Target, info.Map, 0x028);
});
}
});
target.Damage(target.HitsMax, from);
Timer.DelayCall(
TimeSpan.FromMilliseconds(100),
() =>
{
var corpse = target.Corpse as Corpse;
if (corpse != null && !corpse.Deleted)
{
corpse.TurnToBones();
}
});
var head = createHead != null ? createHead(target) : null;
int headID;
int headHue;
if (head != null)
{
headID = head.ItemID;
headHue = head.Hue;
}
else
{
headID = 7393;
headHue = target.SolidHueOverride >= 0 ? target.SolidHueOverride : target.Hue;
}
new MovingEffectInfo(src, src.Clone3D(0, 0, 40), map, headID, headHue).MovingImpact(
info => new MovingEffectInfo(
info.Target,
info.Source.Clone3D(Utility.RandomMinMax(-1, 1), Utility.RandomMinMax(-1, 1), 2),
info.Map,
headID,
headHue).MovingImpact(
hInfo =>
{
if (head != null && !head.Deleted)
{
head.MoveToWorld(hInfo.Target.Location, info.Map);
}
}));
return true;
}
public override string DefaultName => "a severed head";
[Constructable]
public SeveredHead()
: this(String.Empty)
{ }
[Constructable]
public SeveredHead(Mobile m)
: this(m == null || String.IsNullOrWhiteSpace(m.RawName) ? String.Empty : "the severed head of " + m.RawName)
{ }
[Constructable]
public SeveredHead(string name)
: base(7393)
{
Name = !String.IsNullOrWhiteSpace(name) ? name : DefaultName;
}
public SeveredHead(Serial serial)
: base(serial)
{ }
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,273 @@
#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.Items;
#endregion
namespace VitaNex.Items
{
public class StrobeLantern : Lantern
{
private static readonly short[] _Hues = { 11, 22, 33, 44, 55, 66, 77, 88, 99 };
private static readonly LightType[] _Lights = { LightType.Circle150, LightType.Circle225, LightType.Circle300 };
public static List<StrobeLantern> Instances { get; private set; }
private static readonly PollTimer _Timer;
static StrobeLantern()
{
Instances = new List<StrobeLantern>();
_Timer = PollTimer.FromSeconds(1.0, CheckStrobe, Instances.Any);
}
private static void CheckStrobe()
{
Instances.ForEachReverse(o => o.Strobe());
}
private long _NextUpdate;
private int _StrobeIndex;
[CommandProperty(AccessLevel.GameMaster)]
public bool StrobeReverse { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan StrobeInterval { get; set; }
[Hue, CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public override int Hue
{
get
{
if (CanStrobe() && Hues.InBounds(_StrobeIndex))
{
return Hues[_StrobeIndex];
}
return base.Hue;
}
set => base.Hue = value;
}
public virtual short[] Hues => _Hues;
public virtual LightType[] Lights => _Lights;
public virtual LightType DefaultLight => LightType.DarkCircle300;
public virtual TimeSpan DefaultStrobeInterval => TimeSpan.FromSeconds(0.5);
[Constructable]
public StrobeLantern()
{
Name = "Strobe Lantern";
Weight = 4;
Hue = 0;
Light = DefaultLight;
StrobeInterval = DefaultStrobeInterval;
Instances.Add(this);
}
public StrobeLantern(Serial serial)
: base(serial)
{
Instances.Add(this);
}
public override void OnDelete()
{
base.OnDelete();
Instances.Remove(this);
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
Instances.Remove(this);
}
public virtual bool CanStrobe()
{
return !Deleted && Burning && Map != null && Map != Map.Internal && !Hues.IsNullOrEmpty();
}
public void Strobe()
{
if (!CanStrobe() || VitaNexCore.Ticks < _NextUpdate)
{
return;
}
_NextUpdate = VitaNexCore.Ticks + (int)StrobeInterval.TotalMilliseconds;
var index = ++_StrobeIndex % Hues.Length;
if (StrobeReverse)
{
index = (Hues.Length - index) - 1;
}
_StrobeIndex = index;
OnStrobe();
}
public override void Ignite()
{
var old = Burning;
base.Ignite();
if (!old && Burning)
{
OnStrobeBegin();
}
else if (old && !Burning)
{
OnStrobeEnd();
}
}
public override void Douse()
{
var old = Burning;
base.Douse();
if (!old && Burning)
{
OnStrobeBegin();
}
else if (old && !Burning)
{
OnStrobeEnd();
}
}
protected virtual void OnStrobe()
{
Light = Lights.GetRandom(Light);
Update();
}
protected virtual void OnStrobeBegin()
{
Light = Lights.GetRandom(Light);
Update();
}
protected virtual void OnStrobeEnd()
{
Light = DefaultLight;
Update();
}
public virtual void Update()
{
ReleaseWorldPackets();
Delta(ItemDelta.Update);
}
public override void OnDoubleClick(Mobile m)
{
var access = Protected ? AccessLevel.Counselor : AccessLevel.Player;
if (this.CheckUse(m, true, false, 2, false, false, true, access))
{
base.OnDoubleClick(m);
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var v = writer.SetVersion(2);
switch (v)
{
case 2:
{
writer.Write(StrobeReverse);
writer.Write(StrobeInterval);
writer.Write(Burning);
}
break;
// Old
case 1:
writer.Write(Burning);
goto case 0;
case 0:
{
writer.Write(StrobeInterval);
writer.Write(_StrobeIndex);
writer.Write(StrobeReverse);
writer.WriteArray(Hues, (w, o) => w.Write(o));
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var v = reader.GetVersion();
var burning = false;
switch (v)
{
case 2:
{
StrobeReverse = reader.ReadBool();
StrobeInterval = reader.ReadTimeSpan();
burning = reader.ReadBool();
}
break;
// Old
case 1:
burning = reader.ReadBool();
goto case 0;
case 0:
{
StrobeInterval = reader.ReadTimeSpan();
_StrobeIndex = reader.ReadInt();
StrobeReverse = reader.ReadBool();
reader.ReadArray(r => r.ReadShort());
}
break;
}
if (burning)
{
Timer.DelayCall(Ignite);
}
}
}
}

View File

@@ -0,0 +1,78 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Items;
using Server.Network;
#endregion
namespace VitaNex.Items
{
public class BoundsPreviewTile : Static
{
public override bool IsVirtualItem => true;
public override bool DisplayLootType => false;
public override bool DisplayWeight => false;
public override double DefaultWeight => 0;
public override bool Decays => true;
public override TimeSpan DecayTime => TimeSpan.FromMinutes(10.0);
public BoundsPreviewTile(string name, int hue)
: base(9272, 1)
{
Name = name;
Hue = hue;
Movable = false;
}
public BoundsPreviewTile(Serial serial)
: base(serial)
{ }
public override void SendInfoTo(NetState state, bool sendOplPacket)
{
if (state == null || state.Mobile == null || state.Mobile.AccessLevel >= AccessLevel.Counselor)
{
base.SendInfoTo(state, sendOplPacket);
}
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
list.Add(String.Format("({0}, {1}, {2})", X, Y, Z));
}
public override void OnAosSingleClick(Mobile from)
{
OnSingleClick(from);
}
public override void OnSingleClick(Mobile from)
{
base.OnSingleClick(from);
LabelTo(from, String.Format("{0} ({1}, {2}, {3})", this.ResolveName(from.GetLanguage()), X, Y, Z));
}
public override void Serialize(GenericWriter writer)
{ }
public override void Deserialize(GenericReader reader)
{
Delete();
}
}
}

View File

@@ -0,0 +1,685 @@
#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 Server;
using VitaNex.SuperGumps;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Items
{
public enum SkillCodexFlags : byte
{
Base = 0x00,
Cap = 0x01,
Both = 0x02
}
public enum SkillCodexMode : byte
{
Fixed = 0x00,
Increase = 0x01,
Decrease = 0x02
}
public abstract class SkillCodex : Item
{
private SuperGump SelectionGump { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public SkillCodexMode Mode { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public SkillCodexFlags Flags { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Count { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public double Value { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int ValueFixed { get => (int)(Value * 10.0); set => Value = value / 10.0; }
[CommandProperty(AccessLevel.GameMaster)]
public bool DeleteWhenEmpty { get; set; }
public List<SkillName> IgnoredSkills { get; protected set; }
public List<SkillName> SelectedSkills { get; protected set; }
public SkillCodex()
: this(1)
{ }
public SkillCodex(int count)
: this(count, 100.0)
{ }
public SkillCodex(int count, double value)
: this(count, value, true)
{ }
public SkillCodex(int count, double value, bool deleteWhenEmpty)
: this(count, value, deleteWhenEmpty, SkillCodexMode.Fixed)
{ }
public SkillCodex(int count, double value, bool deleteWhenEmpty, SkillCodexMode mode)
: this(count, value, deleteWhenEmpty, mode, SkillCodexFlags.Base)
{ }
public SkillCodex(int count, double value, bool deleteWhenEmpty, SkillCodexMode mode, SkillCodexFlags flags)
: base(8793)
{
SelectedSkills = new List<SkillName>();
IgnoredSkills = new List<SkillName>();
Mode = mode;
Flags = flags;
Count = count;
Value = value;
DeleteWhenEmpty = deleteWhenEmpty;
Name = "Codex of Wisdom";
LootType = LootType.Blessed;
Stackable = false;
}
public SkillCodex(Serial serial)
: base(serial)
{ }
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
string html = String.Empty, flags = String.Empty;
html += String.Format("<basefont color=#{0:X6}>Use: ", Color.LawnGreen.ToRgb());
switch (Flags)
{
case SkillCodexFlags.Base:
flags = "value";
break;
case SkillCodexFlags.Cap:
flags = "cap";
break;
case SkillCodexFlags.Both:
flags = "value and cap";
break;
}
switch (Mode)
{
case SkillCodexMode.Increase:
{
html += String.Format(
"Increase {0} skill{1} {2} by {3:F2}%",
Count,
Count == 1 ? String.Empty : "s",
flags,
Value);
}
break;
case SkillCodexMode.Decrease:
{
html += String.Format(
"Decrease {0} skill{1} {2} by {3:F2}%",
Count,
Count == 1 ? String.Empty : "s",
flags,
Value);
}
break;
case SkillCodexMode.Fixed:
{
html += String.Format("Set {0} skill{1} {2} to {3:F2}%", Count, Count == 1 ? String.Empty : "s", flags, Value);
}
break;
}
list.Add(html);
}
public override void OnDoubleClick(Mobile from)
{
if (from == null || from.Deleted || !Validate(from, true))
{
return;
}
SelectSkills(from);
InvalidateProperties();
}
public virtual bool ValidateSkill(Mobile user, Skill skill, bool message)
{
if (user == null || user.Deleted || skill == null)
{
return false;
}
switch (Mode)
{
case SkillCodexMode.Increase:
{
if (Flags == SkillCodexFlags.Base || Flags == SkillCodexFlags.Both)
{
if (user.SkillsTotal + ValueFixed > user.SkillsCap)
{
if (!CanReduceSkills(user))
{
if (message)
{
user.SendMessage(
SuperGump.DefaultErrorHue,
"You already know everything this codex can offer, reduce some skills to make room for more knowledge.");
}
return false;
}
}
if (skill.IsCapped() || skill.WillCap(Value, false))
{
if (message)
{
user.SendMessage(
SuperGump.DefaultErrorHue,
"You already know everything this codex can offer about {0}.",
skill.Name);
}
return false;
}
if (!skill.IsLocked(SkillLock.Up))
{
if (message)
{
user.SendMessage(SuperGump.DefaultErrorHue, "The skill {0} is locked.", skill.Name);
}
return false;
}
}
}
break;
case SkillCodexMode.Decrease:
{
if (Flags == SkillCodexFlags.Base || Flags == SkillCodexFlags.Both)
{
if (user.SkillsTotal - ValueFixed < 0)
{
if (message)
{
user.SendMessage(SuperGump.DefaultErrorHue, "You already forgot everything this codex can offer.");
}
return false;
}
if (skill.IsZero() || skill.WillZero(Value, false))
{
if (message)
{
user.SendMessage(
SuperGump.DefaultErrorHue,
"You already forgot everything this codex can offer about {0}, any further and you'll forget how to breath!",
skill.Name);
}
return false;
}
if (!skill.IsLocked(SkillLock.Down))
{
if (message)
{
user.SendMessage(SuperGump.DefaultErrorHue, "The skill {0} is locked.", skill.Name);
}
return false;
}
}
}
break;
case SkillCodexMode.Fixed:
{
if (Flags == SkillCodexFlags.Cap)
{
if (skill.CapFixedPoint == ValueFixed)
{
if (message)
{
user.SendMessage(
SuperGump.DefaultErrorHue,
"You already know everything this codex can offer about {0}.",
skill.Name);
}
return false;
}
}
if (Flags == SkillCodexFlags.Base || Flags == SkillCodexFlags.Both)
{
if (skill.IsLocked(SkillLock.Locked))
{
if (message)
{
user.SendMessage(SuperGump.DefaultErrorHue, "The skill {0} is locked.", skill.Name);
}
return false;
}
if (ValueFixed < skill.BaseFixedPoint)
{
if (!skill.IsLocked(SkillLock.Down))
{
if (message)
{
user.SendMessage(SuperGump.DefaultErrorHue, "You can not decrease this skill because it is not locked down!");
}
return false;
}
if (user.SkillsTotal - (skill.BaseFixedPoint - ValueFixed) < 0)
{
if (message)
{
user.SendMessage(
SuperGump.DefaultErrorHue,
"You already forgot everything this codex can offer, any further and you'll forget how to breath!");
}
return false;
}
}
else if (ValueFixed > skill.BaseFixedPoint)
{
if (!skill.IsLocked(SkillLock.Up))
{
if (message)
{
user.SendMessage(SuperGump.DefaultErrorHue, "You can not increase this skill because it is not locked up!");
}
return false;
}
if (user.SkillsTotal + (ValueFixed - skill.BaseFixedPoint) > user.SkillsCap)
{
if (!CanReduceSkills(user))
{
if (message)
{
user.SendMessage(
SuperGump.DefaultErrorHue,
"You already know everything this codex can offer, reduce some skills to make room for more knowledge.");
}
return false;
}
}
}
else
{
if (message)
{
user.SendMessage(
SuperGump.DefaultErrorHue,
"You already know everything this codex can offer about {0}.",
skill.Name);
}
return false;
}
}
}
break;
}
return true;
}
public virtual bool Validate(Mobile user, bool message)
{
if (user == null || user.Deleted || !user.CanSee(this))
{
return false;
}
if (!IsChildOf(user.Backpack))
{
if (message)
{
user.SendMessage(SuperGump.DefaultErrorHue, "This codex must be in your backpack to read it.");
}
return false;
}
if (Count <= 0)
{
if (message)
{
user.SendMessage(SuperGump.DefaultErrorHue, "This codex does not contain any skills to learn.");
}
return false;
}
return true;
}
public virtual void SelectSkills(Mobile user)
{
if (user == null || user.Deleted || !Validate(user, true))
{
return;
}
if (SelectionGump != null)
{
SelectionGump.Close(true);
}
SelectionGump = new SkillSelectionGump(
user,
null,
Count,
null,
null,
skills =>
{
if (!ApplySkills(user, skills))
{
SelectSkills(user);
}
},
IgnoredSkills.ToArray()).Send();
}
public virtual bool ApplySkills(Mobile user, SkillName[] skills)
{
if (user == null || user.Deleted || skills == null || skills.Length == 0 || !Validate(user, true))
{
return false;
}
foreach (var sn in skills)
{
if (user.Deleted || !Validate(user, true))
{
return false;
}
var skill = user.Skills[sn];
if (!ValidateSkill(user, skill, true))
{
continue;
}
var charge = false;
if (Flags == SkillCodexFlags.Cap || Flags == SkillCodexFlags.Both)
{
switch (Mode)
{
case SkillCodexMode.Increase:
{
skill.IncreaseCap(Value);
}
break;
case SkillCodexMode.Decrease:
{
skill.DecreaseCap(Value);
}
break;
case SkillCodexMode.Fixed:
{
skill.SetCap(Value);
}
break;
}
if (Flags != SkillCodexFlags.Both)
{
EndApply(user, skill);
return true;
}
charge = true;
}
if (Flags == SkillCodexFlags.Base || Flags == SkillCodexFlags.Both)
{
charge = false;
switch (Mode)
{
case SkillCodexMode.Increase:
{
if (user.SkillsTotal + ValueFixed > user.SkillsCap)
{
if (TryReduceSkills(user) && skill.IncreaseBase(Value))
{
charge = true;
}
}
else if (skill.IncreaseBase(Value))
{
charge = true;
}
}
break;
case SkillCodexMode.Decrease:
{
if (skill.DecreaseBase(Value))
{
charge = true;
}
}
break;
case SkillCodexMode.Fixed:
{
if (ValueFixed > skill.BaseFixedPoint)
{
if (user.SkillsTotal + ValueFixed > user.SkillsCap)
{
if (TryReduceSkills(user) && skill.SetBase(Value))
{
charge = true;
}
}
else if (skill.SetBase(Value))
{
charge = true;
}
}
else if (ValueFixed < skill.BaseFixedPoint && skill.SetBase(Value))
{
charge = true;
}
}
break;
}
}
if (charge)
{
EndApply(user, skill);
}
}
return true;
}
protected virtual void EndApply(Mobile user, Skill skill)
{
skill.Normalize();
UseCharges();
if (Count <= 0 && DeleteWhenEmpty)
{
Delete();
}
}
protected virtual bool CanReduceSkills(Mobile user)
{
var target = (user.SkillsTotal + ValueFixed) - user.SkillsCap;
var canReduceBy = 0;
foreach (var s in user.Skills)
{
if (s.IsLocked(SkillLock.Down))
{
if (canReduceBy + s.BaseFixedPoint > target)
{
canReduceBy += (target - canReduceBy);
}
else
{
canReduceBy += s.BaseFixedPoint;
}
}
if (canReduceBy >= target)
{
return true;
}
}
return false;
}
protected virtual bool TryReduceSkills(Mobile user)
{
if (!CanReduceSkills(user))
{
return false;
}
var target = (user.SkillsTotal + ValueFixed) - user.SkillsCap;
var reducedBy = 0;
foreach (var s in user.Skills)
{
if (s.IsLocked(SkillLock.Down))
{
if (reducedBy + s.BaseFixedPoint > target)
{
var diff = (target - reducedBy);
if (s.DecreaseBase(diff / 10))
{
reducedBy += diff;
}
}
else
{
if (s.SetBase(0))
{
reducedBy += s.BaseFixedPoint;
}
}
}
if (reducedBy >= target)
{
return true;
}
}
return false;
}
public virtual void UseCharges(int count = 1)
{
Count = Math.Max(0, Count - count);
InvalidateProperties();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
{
writer.WriteFlag(Mode);
writer.WriteFlag(Flags);
writer.Write(Count);
writer.Write(Value);
writer.Write(DeleteWhenEmpty);
writer.WriteList(IgnoredSkills, skill => writer.WriteFlag(skill));
}
break;
case 0:
{
writer.Write((byte)Mode);
writer.Write((byte)Flags);
writer.Write(Count);
writer.Write(Value);
writer.Write(DeleteWhenEmpty);
writer.WriteList(IgnoredSkills, (w, skill) => w.Write((short)skill));
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 1:
{
Mode = reader.ReadFlag<SkillCodexMode>();
Flags = reader.ReadFlag<SkillCodexFlags>();
Count = reader.ReadInt();
Value = reader.ReadDouble();
DeleteWhenEmpty = reader.ReadBool();
IgnoredSkills = reader.ReadList(r => r.ReadFlag<SkillName>());
}
break;
case 0:
{
Mode = (SkillCodexMode)reader.ReadByte();
Flags = (SkillCodexFlags)reader.ReadByte();
Count = reader.ReadInt();
Value = reader.ReadDouble();
DeleteWhenEmpty = reader.ReadBool();
IgnoredSkills = reader.ReadList(r => (SkillName)r.ReadShort());
}
break;
}
}
}
}

View File

@@ -0,0 +1,116 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
using Server.Targeting;
#endregion
namespace VitaNex.Items
{
public class ThrowableCat : BaseThrowableAtMobile<Mobile>
{
[Constructable]
public ThrowableCat()
: this(1)
{ }
[Constructable]
public ThrowableCat(int amount)
: base(8475, amount)
{
Name = "Snowball";
Weight = 2.0;
Stackable = true;
Consumable = true;
AllowCombat = false;
TargetFlags = TargetFlags.None;
Delivery = ThrowableAtMobileDelivery.None;
DismountUser = false;
ThrowSound = 105;
ImpactSound = 676;
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.Zero;
}
public ThrowableCat(Serial serial)
: base(serial)
{ }
protected override void OnThrownAt(Mobile from, Mobile target)
{
if (from == null || from.Deleted || target == null || target.Deleted)
{
return;
}
var cat = new Cat
{
Name = "Snowball"
};
var pmTarget = target as PlayerMobile;
if (pmTarget != null)
{
if (pmTarget.Followers + cat.ControlSlots <= pmTarget.FollowersMax)
{
cat.Controlled = true;
cat.ControlMaster = pmTarget;
cat.ControlTarget = pmTarget;
cat.ControlOrder = OrderType.Follow;
}
}
cat.MoveToWorld(target.Location, target.Map);
base.OnThrownAt(from, target);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{ }
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{ }
break;
}
}
}
}

View File

@@ -0,0 +1,72 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public abstract class BaseThrowableBench : ThrowableFurniture
{
public BaseThrowableBench(int itemID)
: base(itemID)
{
Weight = 1.0;
}
public BaseThrowableBench(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0xB2D, 0xB2C)]
public class ThrowableWoodenBench : BaseThrowableBench
{
[Constructable]
public ThrowableWoodenBench()
: base(Utility.RandomList(0xB2D, 0xB2C))
{ }
public ThrowableWoodenBench(Serial serial)
: base(serial)
{ }
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,259 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public abstract class BaseThrowableChair : ThrowableFurniture
{
public BaseThrowableChair(int itemID)
: base(itemID)
{
Weight = 20.0;
}
public BaseThrowableChair(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0xB4F, 0xB4E, 0xB50, 0xB51)]
public abstract class ThrowableFancyWoodenChairCushion : BaseThrowableChair
{
public ThrowableFancyWoodenChairCushion()
: base(Utility.RandomList(0xB4F, 0xB4E, 0xB50, 0xB51))
{ }
public ThrowableFancyWoodenChairCushion(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0xB53, 0xB52, 0xB54, 0xB55)]
public abstract class ThrowableWoodenChairCushion : BaseThrowableChair
{
public ThrowableWoodenChairCushion()
: base(Utility.RandomList(0xB53, 0xB52, 0xB54, 0xB55))
{ }
public ThrowableWoodenChairCushion(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0xB57, 0xB56, 0xB59, 0xB58)]
public class ThrowableWoodenChair : BaseThrowableChair
{
[Constructable]
public ThrowableWoodenChair()
: base(Utility.RandomList(0xB57, 0xB56, 0xB59, 0xB58))
{ }
public ThrowableWoodenChair(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0xB5B, 0xB5A, 0xB5C, 0xB5D)]
public class ThrowableBambooChair : BaseThrowableChair
{
[Constructable]
public ThrowableBambooChair()
: base(Utility.RandomList(0xB5B, 0xB5A, 0xB5C, 0xB5D))
{ }
public ThrowableBambooChair(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0x1218, 0x1219, 0x121A, 0x121B)]
public class ThrowableStoneChair : BaseThrowableChair
{
[Constructable]
public ThrowableStoneChair()
: base(Utility.RandomList(0x1218, 0x1219, 0x121A, 0x121B))
{ }
public ThrowableStoneChair(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0x2DE3, 0x2DE4, 0x2DE5, 0x2DE6)]
public class ThrowableOrnateElvenChair : BaseThrowableChair
{
[Constructable]
public ThrowableOrnateElvenChair()
: base(Utility.RandomList(0x2DE3, 0x2DE4, 0x2DE5, 0x2DE6))
{ }
public ThrowableOrnateElvenChair(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0x2DEB, 0x2DEC, 0x2DED, 0x2DEE)]
public class ThrowableBigElvenChair : BaseThrowableChair
{
[Constructable]
public ThrowableBigElvenChair()
: base(Utility.RandomList(0x2DEB, 0x2DEC, 0x2DED, 0x2DEE))
{ }
public ThrowableBigElvenChair(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0x2DF5, 0x2DF6)]
public class ThrowableElvenReadingChair : BaseThrowableChair
{
[Constructable]
public ThrowableElvenReadingChair()
: base(Utility.RandomList(0x2DF5, 0x2DF6))
{ }
public ThrowableElvenReadingChair(Serial serial)
: base(serial)
{ }
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,75 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Items;
using Server.Targeting;
#endregion
namespace VitaNex.Items
{
public abstract class ThrowableFurniture : BaseThrowableAtMobile<Mobile>, IDyable
{
public ThrowableFurniture(int itemID)
: base(itemID, 1)
{
Weight = 10.0;
AllowCombat = true;
AllowDeadUser = false;
Consumable = true;
ClearHands = true;
DismountUser = true;
Damages = false;
Heals = false;
ThrowRange = 8;
ThrowSound = 1491;
ImpactSound = 1335;
RequiredSkillValue = 0.0;
TargetFlags = TargetFlags.None;
Delivery = ThrowableAtMobileDelivery.None;
ThrowRecovery = TimeSpan.Zero;
}
public ThrowableFurniture(Serial serial)
: base(serial)
{ }
public virtual bool Dye(Mobile m, DyeTub sender)
{
return m != null && sender is FurnitureDyeTub;
}
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,99 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Items
{
[Furniture]
public abstract class BaseThrowableStool : ThrowableFurniture
{
public BaseThrowableStool(int itemID)
: base(itemID)
{
Weight = 10.0;
}
public BaseThrowableStool(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture]
public class ThrowableStool : BaseThrowableStool
{
[Constructable]
public ThrowableStool()
: base(0xA2A)
{ }
public ThrowableStool(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture]
public class ThrowableFootStool : BaseThrowableStool
{
[Constructable]
public ThrowableFootStool()
: base(0xB5E)
{ }
public ThrowableFootStool(Serial serial)
: base(serial)
{ }
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,180 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public abstract class BaseThrowableTable : ThrowableFurniture
{
public BaseThrowableTable(int itemID)
: base(itemID)
{
Weight = 10.0;
}
public BaseThrowableTable(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture]
public class ThrowableElegantLowTable : BaseThrowableTable
{
[Constructable]
public ThrowableElegantLowTable()
: base(0x2819)
{ }
public ThrowableElegantLowTable(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture]
public class ThrowablePlainLowTable : BaseThrowableTable
{
[Constructable]
public ThrowablePlainLowTable()
: base(0x281A)
{ }
public ThrowablePlainLowTable(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0xB90, 0xB7D)]
public class ThrowableLargeTable : BaseThrowableTable
{
[Constructable]
public ThrowableLargeTable()
: base(Utility.RandomList(0xB90, 0xB7D))
{ }
public ThrowableLargeTable(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0xB35, 0xB34)]
public class ThrowableNightstand : BaseThrowableTable
{
[Constructable]
public ThrowableNightstand()
: base(Utility.RandomList(0xB35, 0xB34))
{ }
public ThrowableNightstand(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0xB8F, 0xB7C)]
public class ThrowableYewWoodTable : BaseThrowableTable
{
[Constructable]
public ThrowableYewWoodTable()
: base(Utility.RandomList(0xB8F, 0xB7C))
{ }
public ThrowableYewWoodTable(Serial serial)
: base(serial)
{ }
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,99 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
using Server.Items;
#endregion
namespace VitaNex.Items
{
public abstract class BaseThrowableThrone : ThrowableFurniture
{
public BaseThrowableThrone(int itemID)
: base(itemID)
{
Weight = 10.0;
}
public BaseThrowableThrone(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0xB32, 0xB33)]
public class ThrowableThrone : BaseThrowableThrone
{
[Constructable]
public ThrowableThrone()
: base(Utility.RandomList(0xB32, 0xB33))
{ }
public ThrowableThrone(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
[Furniture, Flipable(0xB2E, 0xB2F, 0xB31, 0xB30)]
public class ThrowableWoodenThrone : BaseThrowableThrone
{
[Constructable]
public ThrowableWoodenThrone()
: base(Utility.RandomList(0xB2E, 0xB2F, 0xB31, 0xB30))
{ }
public ThrowableWoodenThrone(Serial serial)
: base(serial)
{ }
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,520 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Movement;
using Server.Targeting;
#endregion
namespace VitaNex.Items
{
public class HauntedMomentoEntity : BaseCreature
{
private HauntedMomento _Momento;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public HauntedMomento Momento => _Momento;
public override bool ClickTitle => false;
public override bool AlwaysMurderer => true;
public override bool BardImmune => true;
public override bool BleedImmune => true;
public override bool NoHouseRestrictions => true;
public override bool ShowFameTitle => false;
public override bool Unprovokable => true;
public override bool CanMoveOverObstacles => true;
public override bool CanOpenDoors => true;
public override bool CanTarget => false;
//public override bool CanDrop => false;
public override bool Commandable => false;
public override bool DeleteCorpseOnDeath => true;
public override bool IsScaryToPets => true;
public override bool IsDispellable => false;
public override bool PlayerRangeSensitive => false;
public override bool CanFlee => false;
public HauntedMomentoEntity(HauntedMomento momento)
: base(AIType.AI_Use_Default, FightMode.None, 10, 0, 0.2, 0.2)
{
_Momento = momento;
Name = "?";
Hue = 0x4001;
BaseSoundID = 0;
Hidden = true;
Blessed = true;
Tamable = false;
CanSwim = true;
Fame = 0;
Karma = 0;
VirtualArmor = 1337;
SetStr(0);
SetDex(0);
SetInt(0);
SetHits(1);
SetDamage(0);
SetDamageType(ResistanceType.Cold, 0);
SetDamageType(ResistanceType.Energy, 0);
SetDamageType(ResistanceType.Fire, 0);
SetDamageType(ResistanceType.Physical, 0);
SetDamageType(ResistanceType.Poison, 0);
SetResistance(ResistanceType.Cold, 100);
SetResistance(ResistanceType.Energy, 100);
SetResistance(ResistanceType.Fire, 100);
SetResistance(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Poison, 100);
this.SetAllSkills(0, 0);
ChangeBody();
OnThink();
}
public HauntedMomentoEntity(Serial serial)
: base(serial)
{ }
public static bool IsBeingLookedAt(Direction facing, Direction to)
{
if (facing.HasFlag(Direction.Running))
{
facing &= ~Direction.Running;
}
switch (facing)
{
case Direction.Up:
return (to == Direction.Left || to == Direction.West || to == Direction.Up || to == Direction.North ||
to == Direction.Right);
case Direction.North:
return (to == Direction.West || to == Direction.Up || to == Direction.North || to == Direction.Right ||
to == Direction.East);
case Direction.Right:
return (to == Direction.Up || to == Direction.North || to == Direction.Right || to == Direction.East ||
to == Direction.Down);
case Direction.East:
return (to == Direction.North || to == Direction.Right || to == Direction.East || to == Direction.Down ||
to == Direction.South);
case Direction.Down:
return (to == Direction.Right || to == Direction.East || to == Direction.Down || to == Direction.South ||
to == Direction.Left);
case Direction.South:
return (to == Direction.East || to == Direction.Down || to == Direction.South || to == Direction.Left ||
to == Direction.West);
case Direction.Left:
return (to == Direction.Down || to == Direction.South || to == Direction.Left || to == Direction.West ||
to == Direction.Up);
case Direction.West:
return (to == Direction.South || to == Direction.Left || to == Direction.West || to == Direction.Up ||
to == Direction.North);
}
return true;
}
public virtual void ChangeBody()
{
Body = Utility.RandomList(26, 50, 146, 148, 196, 747, 748, 970);
PlaySound(1383);
}
public override void OnThink()
{
base.OnThink();
if (Deleted || _Momento == null || _Momento.Deleted || _Momento.Map == null || _Momento.Map == Map.Internal ||
!(_Momento.RootParent is Mobile))
{
Delete();
return;
}
var parent = (Mobile)_Momento.RootParent;
if (parent.Deleted || parent.Map == null || parent.Map == Map.Internal)
{
Delete();
return;
}
Hidden = true;
Home = parent.Location;
RangeHome = RangePerception;
var map = parent.Map;
if (Map == null || Map == Map.Internal || Map != map || !InRange(parent, 20))
{
MoveToWorld(parent.GetRandomPoint3D(RangeHome + (RangeHome / 2)).GetWorldTop(map), map);
ChangeBody();
}
var to = parent.GetDirectionTo(this);
var stop = (parent.InRange(this, RangeHome / 2));
if (parent is PlayerMobile)
{
var hide = (IsBeingLookedAt(parent.Direction, to) || !parent.InRange(this, RangeHome + (RangeHome / 2)));
if (hide)
{
((PlayerMobile)parent).VisibilityList.Update(this);
}
else
{
((PlayerMobile)parent).VisibilityList.Remove(this);
}
}
if (stop)
{
Frozen = true;
return;
}
Frozen = false;
int x = X, y = Y, z = Z;
Movement.Offset(GetDirectionTo(Home), ref x, ref y);
var p = new Point3D(x, y, z).GetWorldTop(map);
if (!map.CanFit(p, 16))
{
SetLocation(p, true);
}
else
{
Move(GetDirectionTo(p));
}
Direction = GetDirectionTo(parent);
}
public override void OnAfterDelete()
{
if (_Momento != null)
{
var parent = _Momento.RootParent as Mobile;
if (parent is PlayerMobile)
{
((PlayerMobile)parent).VisibilityList.Remove(this);
}
if (_Momento.Entity == this)
{
_Momento.Entity = null;
}
}
base.OnAfterDelete();
}
public override bool CanBeDamaged()
{
return false;
}
public override bool CanBeRenamedBy(Mobile from)
{
return false;
}
public override bool CanBeControlledBy(Mobile m)
{
return false;
}
public override bool CheckFlee()
{
return false;
}
protected override bool OnMove(Direction d)
{
return true;
}
public override bool OnMoveOver(Mobile m)
{
return true;
}
public override bool OnMoveOff(Mobile m)
{
return true;
}
public override bool CheckShove(Mobile shoved)
{
return true;
}
public override void OnDoubleClick(Mobile m)
{ }
public override void OnAosSingleClick(Mobile m)
{ }
public override void OnSingleClick(Mobile m)
{ }
public override bool OnDragDrop(Mobile from, Item dropped)
{
return false;
}
public override bool OnDragLift(Item item)
{
return false;
}
public override void OnStatsQuery(Mobile from)
{ }
public override void AddNameProperties(ObjectPropertyList list)
{ }
public override void GetProperties(ObjectPropertyList list)
{ }
public override void GenerateLoot()
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
writer.Write(_Momento);
if (version < 1)
{
writer.Write(false);
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
_Momento = reader.ReadItem<HauntedMomento>();
if (version < 1)
{
reader.ReadBool();
}
}
}
public class HauntedMomento : BaseThrowableAtMobile<Mobile>
{
private static bool _Initialized;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public HauntedMomentoEntity Entity { get; set; }
[Constructable]
public HauntedMomento()
: base(0x3679, 1)
{
Name = "Haunted Momento";
Token = "Mysterious Energies Surround This Momento";
Weight = 1.0;
Stackable = false;
LootType = LootType.Blessed;
AllowCombat = false;
TargetFlags = TargetFlags.None;
Delivery = ThrowableAtMobileDelivery.AddToPack;
DismountUser = false;
ThrowSound = 0x180;
ImpactSound = 0x181;
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.Zero;
}
public HauntedMomento(Serial serial)
: base(serial)
{ }
public static void Initialize()
{
if (_Initialized)
{
return;
}
EventSink.Login += e =>
{
if (e.Mobile == null || e.Mobile.Deleted || e.Mobile.Backpack == null)
{
return;
}
VitaNexCore.TryCatch(
() =>
{
var momentos = e.Mobile.Backpack.FindItemsByType<HauntedMomento>(true);
momentos.ForEach(
m =>
{
if (m != null && !m.Deleted)
{
m.InvalidateEntity();
}
});
momentos.Clear();
});
};
_Initialized = true;
}
public override bool CanThrowAt(Mobile from, Mobile target, bool message)
{
if (!base.CanThrowAt(from, target, message))
{
return false;
}
if (!target.Player)
{
if (message)
{
from.SendMessage(37, "You can only throw the {0} at other players.", Name);
}
return false;
}
return true;
}
public override void OnLocationChange(Point3D oldLocation)
{
base.OnLocationChange(oldLocation);
InvalidateEntity();
}
protected virtual HauntedMomentoEntity CreateEntity()
{
return new HauntedMomentoEntity(this);
}
public override void OnMapChange()
{
base.OnMapChange();
InvalidateEntity();
if (Entity != null)
{
Entity.ChangeBody();
}
}
#if NEWPARENT
public override void OnAdded(IEntity parent)
#else
public override void OnAdded(object parent)
#endif
{
base.OnAdded(parent);
InvalidateEntity();
}
protected virtual void InvalidateEntity()
{
if (Map == null || Map == Map.Internal || !(RootParent is Mobile) || Parent is BankBox)
{
if (Entity != null)
{
Entity.Delete();
Entity = null;
}
}
else if (Entity == null || Entity.Deleted)
{
Entity = CreateEntity();
}
}
public override void OnAfterDelete()
{
if (Entity != null)
{
Entity.Delete();
}
base.OnAfterDelete();
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.Write(Entity);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
Entity = reader.ReadMobile<HauntedMomentoEntity>();
break;
}
}
}
}

View File

@@ -0,0 +1,113 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
using Server.Targeting;
#endregion
namespace VitaNex.Items
{
public class ThrowableRat : BaseThrowableAtMobile<Mobile>
{
[Constructable]
public ThrowableRat()
: this(1)
{ }
[Constructable]
public ThrowableRat(int amount)
: base(8483, amount)
{
Name = "Reeking Rat";
Weight = 1.0;
Token = "Mickey's Ugly Cousin";
Consumable = true;
AllowCombat = false;
TargetFlags = TargetFlags.None;
Delivery = ThrowableAtMobileDelivery.None;
DismountUser = false;
ThrowSound = 206;
ImpactSound = 204;
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.Zero;
}
public ThrowableRat(Serial serial)
: base(serial)
{ }
protected override void OnThrownAt(Mobile from, Mobile target)
{
if (from == null || from.Deleted || target == null || target.Deleted)
{
return;
}
var rat = new Rat
{
Name = "Reeking Rat"
};
var pmTarget = target as PlayerMobile;
if (pmTarget != null)
{
if (pmTarget.Followers + rat.ControlSlots <= pmTarget.FollowersMax)
{
rat.Controlled = true;
rat.ControlMaster = pmTarget;
rat.ControlTarget = pmTarget;
rat.ControlOrder = OrderType.Follow;
}
}
rat.MoveToWorld(target.Location, target.Map);
base.OnThrownAt(from, target);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
break;
}
}
}
}

View File

@@ -0,0 +1,86 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Targeting;
#endregion
namespace VitaNex.Items
{
public class ThrowableRock : BaseThrowableAtMobile<Mobile>
{
[Constructable]
public ThrowableRock()
: this(1)
{ }
[Constructable]
public ThrowableRock(int amount)
: base(0x11B6, amount)
{
Name = "Gigantic Boulder";
Usage = "Pass The Rock!";
Token = "Your Strength Has Increased By Over 9000!";
Weight = 1.0;
Stackable = true;
AllowCombat = false;
TargetFlags = TargetFlags.None;
Delivery = ThrowableAtMobileDelivery.AddToPack;
DismountUser = false;
ThrowSound = 543;
ImpactSound = 1613;
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.Zero;
}
public ThrowableRock(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{ }
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{ }
break;
}
}
}
}

View File

@@ -0,0 +1,216 @@
#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.Items;
using Server.Targeting;
using VitaNex.FX;
#endregion
namespace VitaNex.Items
{
[Flipable(10248, 10249)]
public class ThrowableStinkBomb : BaseThrowableAtMobile<Mobile>
{
private static readonly PollTimer _InternalTimer;
public static Dictionary<Mobile, DateTime> Stinky { get; private set; }
static ThrowableStinkBomb()
{
Stinky = new Dictionary<Mobile, DateTime>();
_InternalTimer = PollTimer.FromSeconds(5.0, InternalCallback, () => Stinky.Count > 0);
}
private static void InternalCallback()
{
Stinky.RemoveKeyRange(m => !CheckStinky(m));
var now = DateTime.UtcNow;
var e = Enumerable.Empty<Tuple<Mobile, TimeSpan>>();
e = Stinky.Aggregate(e, (c, kv) => c.With(DoStinkEffect(kv.Key).Select(t => Tuple.Create(t, kv.Value - now))));
foreach (var t in e.Where(t => t.Item2.TotalSeconds > 0))
{
MakeStinky(t.Item1, t.Item2);
}
}
public static bool CheckStinky(Mobile m)
{
return Stinky.ContainsKey(m) && Stinky[m] >= DateTime.UtcNow;
}
public static void MakeStinky(Mobile m, TimeSpan duration)
{
Stinky[m] = DateTime.UtcNow + duration;
}
public static IEnumerable<Mobile> DoStinkEffect(Mobile m)
{
if (!CheckStinky(m) || m.Hidden || !m.Alive)
{
return Enumerable.Empty<Mobile>();
}
Effects.PlaySound(m.Location, m.Map, 1064);
new PoisonExplodeEffect(m, m.Map, 1)
{
EffectMutator = e =>
{
if (e.ProcessIndex == 0)
{
e.SoundID = 1064;
}
},
EffectHandler = e =>
{
if (e.ProcessIndex != 0)
{
return;
}
foreach (var t in e.Source.FindMobilesInRange(e.Map, 0)
.Where(t => t != null && !t.Deleted && t != m && !t.Hidden && t.Alive && t.Body.IsHuman))
{
Effects.PlaySound(t.Location, t.Map, Utility.RandomList(1065, 1066, 1067));
}
}
}.Send();
return m.FindMobilesInRange(m.Map, 1)
.Where(t => t != null && !t.Deleted && t != m && !t.Hidden && t.Alive && t.Body.IsHuman);
}
[CommandProperty(AccessLevel.GameMaster)]
public int ExplosionRange { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan StinkyDuration { get; set; }
[Constructable]
public ThrowableStinkBomb()
: this(1)
{ }
[Constructable]
public ThrowableStinkBomb(int amount)
: base(Utility.RandomList(10248, 10249), amount)
{
Name = "Stink Bomb";
Usage = "Throw To Unleash A Terrible Smell!";
Hue = 1270;
Weight = 1.0;
Stackable = true;
StinkyDuration = TimeSpan.FromSeconds(30.0);
TargetFlags = TargetFlags.None;
Delivery = ThrowableAtMobileDelivery.None;
ThrowSound = 1491;
ImpactSound = 1064;
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.FromSeconds(60.0);
ExplosionRange = 5;
RequiredSkill = SkillName.Alchemy;
RequiredSkillValue = 25.0;
}
public ThrowableStinkBomb(Serial serial)
: base(serial)
{ }
protected override void OnThrownAt(Mobile from, Mobile target)
{
if (from == null || from.Deleted || target == null)
{
return;
}
for (int layer = 0, range = ExplosionRange; layer < ExplosionRange && range >= 0; layer++, range--)
{
new PoisonExplodeEffect(target.Clone3D(0, 0, layer * 10), target.Map, range, 0, null, ExplosionStink).Send();
}
base.OnThrownAt(from, target);
}
public virtual void ExplosionStink(EffectInfo info)
{
Effects.PlaySound(info.Source.Location, info.Map, ImpactSound);
foreach (var m in info.Source.FindMobilesInRange(info.Map, 0)
.Not(t => t == null || t.Deleted || t.Hidden || (!t.Alive && !AllowDeadTarget)))
{
Effects.PlaySound(m.Location, m.Map, Utility.RandomList(1065, 1066, 1067));
if (StinkyDuration > TimeSpan.Zero)
{
MakeStinky(m, StinkyDuration);
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(ExplosionRange);
writer.Write(StinkyDuration);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
ExplosionRange = reader.ReadInt();
StinkyDuration = reader.ReadTimeSpan();
}
break;
}
if (StinkyDuration <= TimeSpan.Zero)
{
StinkyDuration = TimeSpan.FromSeconds(30);
}
}
}
}

View File

@@ -0,0 +1,141 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Linq;
using Server;
using Server.Items;
using VitaNex.FX;
#endregion
namespace VitaNex.Items
{
[Flipable(8790, 8791)]
public class ThrowableCureBomb : BaseThrowableAtMobile<Mobile>
{
[CommandProperty(AccessLevel.GameMaster)]
public int ExplosionRange { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public override string Usage
{
get => !String.IsNullOrWhiteSpace(base.Usage)
? base.Usage
: String.Format(
"Cause an explosion at the target which will attempt to cure all allies within {0:#,0} paces.",
ExplosionRange);
set => base.Usage = value;
}
[Constructable]
public ThrowableCureBomb()
: this(1)
{ }
[Constructable]
public ThrowableCureBomb(int amount)
: base(Utility.RandomList(8790, 8791), amount)
{
Name = "Curing Bobomb";
Usage = String.Empty;
Hue = 74;
Weight = 10.0;
Stackable = true;
Delivery = ThrowableAtMobileDelivery.None;
ThrowSound = 1491;
ImpactSound = Utility.RandomList(776, 777);
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.FromSeconds(60.0);
ExplosionRange = 5;
RequiredSkillValue = 100.0;
}
public ThrowableCureBomb(Serial serial)
: base(serial)
{ }
protected override void OnThrownAt(Mobile from, Mobile target)
{
if (from == null || from.Deleted || target == null || target.Deleted)
{
return;
}
var fx = new PoisonExplodeEffect(target, target.Map, ExplosionRange)
{
EffectHandler = e =>
{
if (e.ProcessIndex != 0)
{
ExplosionCure(e);
}
}
};
fx.Send();
base.OnThrownAt(from, target);
}
public virtual void ExplosionCure(EffectInfo info)
{
Effects.PlaySound(info.Source.Location, info.Map, ImpactSound);
var targets = info.Source.Location.GetMobilesInRange(info.Map, 0);
foreach (var m in targets.Where(m => m != null && !m.Deleted && User.CanBeBeneficial(m, false, false)))
{
m.PlaySound(ImpactSound);
m.CurePoison(User);
}
targets.Free(true);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.Write(ExplosionRange);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
ExplosionRange = reader.ReadInt();
break;
}
}
}
}

View File

@@ -0,0 +1,147 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Linq;
using Server;
using Server.Items;
using VitaNex.FX;
#endregion
namespace VitaNex.Items
{
[Flipable(8790, 8791)]
public class ThrowableHealBomb : BaseThrowableAtMobile<Mobile>
{
[CommandProperty(AccessLevel.GameMaster)]
public int ExplosionRange { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public override string Usage
{
get => !String.IsNullOrWhiteSpace(base.Usage)
? base.Usage
: String.Format(
"Cause an explosion at the target which will replenish {0:#,0} to {1:#,0} health for all allies within {2:#,0} paces.",
HealMin,
HealMax,
ExplosionRange);
set => base.Usage = value;
}
[Constructable]
public ThrowableHealBomb()
: this(1)
{ }
[Constructable]
public ThrowableHealBomb(int amount)
: base(Utility.RandomList(8790, 8791), amount)
{
Name = "Healing Bobomb";
Usage = String.Empty;
Hue = 55;
Weight = 10.0;
Stackable = true;
Delivery = ThrowableAtMobileDelivery.None;
Heals = true;
HealMin = 25;
HealMax = 100;
ThrowSound = 1491;
ImpactSound = Utility.RandomList(776, 777);
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.FromSeconds(60.0);
ExplosionRange = 5;
RequiredSkillValue = 100.0;
}
public ThrowableHealBomb(Serial serial)
: base(serial)
{ }
protected override void OnThrownAt(Mobile from, Mobile target)
{
if (from == null || from.Deleted || target == null || target.Deleted)
{
return;
}
var fx = new EnergyExplodeEffect(target, target.Map, ExplosionRange)
{
EffectHandler = e =>
{
if (e.ProcessIndex != 0)
{
ExplosionHeal(e);
}
}
};
fx.Send();
base.OnThrownAt(from, target);
}
public virtual void ExplosionHeal(EffectInfo info)
{
Effects.PlaySound(info.Source.Location, info.Map, ImpactSound);
var targets = info.Source.Location.GetMobilesInRange(info.Map, 0);
foreach (var m in targets.Where(m => m != null && !m.Deleted && User.CanBeBeneficial(m, false, false)))
{
m.PlaySound(ImpactSound);
m.Heal(Utility.RandomMinMax(HealMin, HealMax), User, true);
}
targets.Free(true);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.Write(ExplosionRange);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
ExplosionRange = reader.ReadInt();
break;
}
}
}
}

View File

@@ -0,0 +1,146 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Linq;
using Server;
using Server.Items;
using VitaNex.FX;
#endregion
namespace VitaNex.Items
{
[Flipable(8790, 8791)]
public class ThrowableManaBomb : BaseThrowableAtMobile<Mobile>
{
[CommandProperty(AccessLevel.GameMaster)]
public int ExplosionRange { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public override string Usage
{
get => !String.IsNullOrWhiteSpace(base.Usage)
? base.Usage
: String.Format(
"Cause an explosion at the target which will replenish {0:#,0} to {1:#,0} mana for all allies within {2:#,0} paces.",
HealMin,
HealMax,
ExplosionRange);
set => base.Usage = value;
}
[Constructable]
public ThrowableManaBomb()
: this(1)
{ }
[Constructable]
public ThrowableManaBomb(int amount)
: base(Utility.RandomList(8790, 8791), amount)
{
Name = "Mana Bobomb";
Usage = String.Empty;
Hue = 2;
Weight = 10.0;
Stackable = true;
Delivery = ThrowableAtMobileDelivery.None;
HealMin = 25;
HealMax = 100;
ThrowSound = 1491;
ImpactSound = Utility.RandomList(776, 777);
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.FromSeconds(60.0);
ExplosionRange = 5;
RequiredSkillValue = 100.0;
}
public ThrowableManaBomb(Serial serial)
: base(serial)
{ }
protected override void OnThrownAt(Mobile from, Mobile target)
{
if (from == null || from.Deleted || target == null || target.Deleted)
{
return;
}
var fx = new EnergyExplodeEffect(target, target.Map, ExplosionRange)
{
EffectHandler = e =>
{
if (e.ProcessIndex != 0)
{
ExplosionMana(e);
}
}
};
fx.Send();
base.OnThrownAt(from, target);
}
public virtual void ExplosionMana(EffectInfo info)
{
Effects.PlaySound(info.Source.Location, info.Map, ImpactSound);
var targets = info.Source.Location.GetMobilesInRange(info.Map, 0);
foreach (var m in targets.Where(m => m != null && !m.Deleted && User.CanBeBeneficial(m, false, false)))
{
m.PlaySound(ImpactSound);
m.Mana += Utility.RandomMinMax(HealMin, HealMax);
}
targets.Free(true);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.Write(ExplosionRange);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
ExplosionRange = reader.ReadInt();
break;
}
}
}
}

View File

@@ -0,0 +1,137 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Network;
using Server.Targeting;
#endregion
namespace VitaNex.Items
{
public class ThrowableAxe : BaseThrowableAtMobile<Mobile>
{
[CommandProperty(AccessLevel.GameMaster)]
public bool InstantKillForced { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int InstantKillChance { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool InstantKillHead { get; set; }
[Constructable]
public ThrowableAxe()
: this(1)
{ }
[Constructable]
public ThrowableAxe(int amount)
: base(0x255D, amount)
{
InstantKillForced = false;
InstantKillChance = 1;
Name = "Throwing Axe";
Usage = "When thrown, has a slight chance to decapitate the target.";
Token = "BOOM! Head Shot!";
Weight = 10.0;
Stackable = true;
Consumable = true;
AllowCombat = true;
TargetFlags = TargetFlags.Harmful;
Delivery = ThrowableAtMobileDelivery.MoveToWorld;
DismountUser = true;
Damages = true;
DamageMin = 30;
DamageMax = 50;
ThrowSound = 513;
ImpactSound = 1310;
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.FromMinutes(2.0);
RequiredSkill = SkillName.Tactics;
RequiredSkillValue = 50.0;
}
public ThrowableAxe(Serial serial)
: base(serial)
{ }
protected virtual SeveredHead CreateHead(Mobile target)
{
return !InstantKillHead || target == null || !target.Body.IsHuman || target.Blessed ? null : new SeveredHead(target);
}
protected override void OnThrownAt(Mobile m, Mobile target)
{
if (m != null && target != null && (InstantKillForced || Utility.RandomDouble() < InstantKillChance / 100.0))
{
SeveredHead.Decapitate(m, target, CreateHead);
m.PublicOverheadMessage(MessageType.Yell, 37, true, "BOOM! Head Shot!");
}
base.OnThrownAt(m, target);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(2);
switch (version)
{
case 2:
case 1:
writer.Write(InstantKillHead);
goto case 0;
case 0:
{
writer.Write(InstantKillForced);
writer.Write(InstantKillChance);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 2:
case 1:
InstantKillHead = reader.ReadBool();
goto case 0;
case 0:
{
InstantKillForced = reader.ReadBool();
InstantKillChance = version < 2 ? (int)reader.ReadDouble() : reader.ReadInt();
}
break;
}
}
}
}

View File

@@ -0,0 +1,154 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Linq;
using Server;
using Server.Items;
using VitaNex.FX;
#endregion
namespace VitaNex.Items
{
[Flipable(8790, 8791)]
public class ThrowableBomb : BaseThrowableAtMobile<Mobile>
{
[CommandProperty(AccessLevel.GameMaster)]
public int ExplosionRange { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public override string Usage
{
get => !String.IsNullOrWhiteSpace(base.Usage)
? base.Usage
: String.Format(
"Cause an explosion at the target which will deal {0:#,0} to {1:#,0} damage to all enemies within {2:#,0} paces.",
DamageMin,
DamageMax,
ExplosionRange);
set => base.Usage = value;
}
[Constructable]
public ThrowableBomb()
: this(1)
{ }
[Constructable]
public ThrowableBomb(int amount)
: base(Utility.RandomList(8790, 8791), amount)
{
Name = "Bobomb";
Token = "A.C.M.E";
Hue = 2104;
Weight = 10.0;
Stackable = true;
Delivery = ThrowableAtMobileDelivery.None;
Damages = true;
DamageMin = 25;
DamageMax = 50;
ThrowSound = 1491;
ImpactSound = Utility.RandomList(776, 777);
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.FromSeconds(60.0);
ExplosionRange = 5;
RequiredSkillValue = 100.0;
}
public ThrowableBomb(Serial serial)
: base(serial)
{ }
protected override void OnThrownAt(Mobile from, Mobile target)
{
if (from == null || from.Deleted || target == null || target.Deleted)
{
return;
}
var fx = new FireExplodeEffect(target, target.Map, ExplosionRange)
{
EffectHandler = e =>
{
if (e.ProcessIndex != 0)
{
ExplosionDamage(e);
}
}
};
fx.Send();
base.OnThrownAt(from, target);
}
public virtual void ExplosionDamage(EffectInfo info)
{
Effects.PlaySound(info.Source.Location, info.Map, ImpactSound);
foreach (var m in info.Source.Location.GetMobilesInRange(info.Map, 0)
.Where(m => m != null && !m.Deleted && User.CanBeHarmful(m, false, true)))
{
m.PlaySound(ImpactSound);
m.Damage(Utility.RandomMinMax(DamageMin, DamageMax), User, true);
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
case 0:
writer.Write(ExplosionRange);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 1:
case 0:
{
ExplosionRange = reader.ReadInt();
if (version < 1)
{
reader.ReadInt();
reader.ReadInt();
}
}
break;
}
}
}
}

View File

@@ -0,0 +1,216 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Items;
using Server.Targeting;
#endregion
namespace VitaNex.Items
{
public class ThrowableTrainingDagger : ThrowableDagger
{
private PollTimer TrainingTimer { get; set; }
private Point3D TrainingLocation { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public double SkillGainChance { get; set; }
[Constructable]
public ThrowableTrainingDagger()
: this(1)
{ }
[Constructable]
public ThrowableTrainingDagger(int amount)
: base(amount)
{
SkillGainChance = 25.0;
Name = "Throwing Training Dagger";
Usage = "Throw at a target to train your Throwing skill.";
Hue = 2020;
Layer = Layer.OneHanded;
Weight = 1.0;
Stackable = true;
TargetFlags = TargetFlags.None;
Consumable = false;
Delivery = ThrowableAtMobileDelivery.None;
DismountUser = false;
Damages = false;
DamageMin = 0;
DamageMax = 0;
ThrowRecovery = TimeSpan.Zero;
RequiredSkillValue = 0;
}
public ThrowableTrainingDagger(Serial serial)
: base(serial)
{ }
protected override void OnThrownAt(Mobile from, Mobile target)
{
base.OnThrownAt(from, target);
if (Utility.RandomDouble() * 100 <= SkillGainChance)
{
from.Skills[RequiredSkill].IncreaseBase(Utility.RandomDouble());
}
CheckTraining(from, target);
}
public virtual void CheckTraining(Mobile from, Mobile target)
{
if (from == null || from.Deleted || target == null || target.Deleted)
{
if (TrainingTimer != null)
{
TrainingTimer.Stop();
TrainingTimer = null;
}
return;
}
if (TrainingTimer == null)
{
TrainingLocation = from.Location;
TrainingTimer = PollTimer.CreateInstance(
TimeSpan.FromSeconds(1.0),
() =>
{
if (from.Location != TrainingLocation)
{
TrainingTimer.Stop();
TrainingTimer = null;
return;
}
BeginThrow(from, target);
});
}
else if (from.Location != TrainingLocation)
{
TrainingTimer.Stop();
TrainingTimer = null;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.Write(SkillGainChance);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
SkillGainChance = reader.ReadDouble();
break;
}
}
}
[Flipable(3921, 3922)]
public class ThrowableDagger : BaseThrowableAtMobile<Mobile>
{
[Constructable]
public ThrowableDagger()
: this(1)
{ }
[Constructable]
public ThrowableDagger(int amount)
: base(Utility.RandomList(3921, 3922), amount)
{
Name = "Throwing Dagger";
Layer = Layer.OneHanded;
Weight = 1.0;
Stackable = true;
TargetFlags = TargetFlags.Harmful;
Delivery = ThrowableAtMobileDelivery.AddToPack;
DismountUser = false;
Damages = true;
DamageMin = 20;
DamageMax = 40;
ThrowSound = 1492;
ImpactSound = 903;
EffectID = ItemID;
EffectHue = Hue;
ThrowRecovery = TimeSpan.FromSeconds(60.0);
RequiredSkillValue = 60.0;
}
public ThrowableDagger(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{ }
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{ }
break;
}
}
}
}

View File

@@ -0,0 +1,120 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Items
{
public abstract class BaseDazingThrowable<TMobile> : BaseThrowableAtMobile<TMobile>
where TMobile : Mobile
{
[CommandProperty(AccessLevel.GameMaster)]
public virtual TimeSpan MountRecovery { get; set; }
public BaseDazingThrowable(int itemID, int amount = 1)
: base(itemID, amount)
{
MountRecovery = TimeSpan.FromSeconds(3.0);
}
public BaseDazingThrowable(Serial serial)
: base(serial)
{ }
public override bool CanThrowAt(Mobile from, TMobile target, bool message)
{
if (!base.CanThrowAt(from, target, message))
{
return false;
}
if (!target.Mounted)
{
if (message)
{
from.SendMessage(37, "Your target is not mounted.");
}
return false;
}
return true;
}
protected override void OnThrownAt(Mobile from, TMobile target)
{
base.OnThrownAt(from, target);
var mounted = target.Mounted;
if (target is PlayerMobile)
{
var pm = target as PlayerMobile;
pm.SetMountBlock(BlockMountType.Dazed, MountRecovery, mounted);
}
if (!mounted)
{
return;
}
BaseMount.Dismount(target);
OnTargetDismounted(from, target, true);
}
protected virtual void OnTargetDismounted(Mobile from, TMobile target, bool message)
{
if (from == null || from.Deleted || target == null || target.Deleted)
{
return;
}
if (message)
{
target.SendMessage(37, "{0} has brought you down with the {1}!", from.RawName, Name);
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.Write(MountRecovery);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
MountRecovery = reader.ReadTimeSpan();
break;
}
}
}
}

View File

@@ -0,0 +1,633 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
using Server.Network;
using Server.Spells;
using Server.Targeting;
using VitaNex.FX;
using VitaNex.Network;
using VitaNex.Targets;
#endregion
namespace VitaNex.Items
{
public abstract class BaseThrowable<TEntity> : Item, IBaseThrowable
where TEntity : IEntity
{
public PollTimer UpdateTimer { get; protected set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool Silent { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual string Usage { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual string Token { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool AllowNoOwner { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool AllowCombat { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool AllowDeadUser { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool Consumable { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool ClearHands { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool DismountUser { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int EffectID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int EffectHue { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int EffectSpeed { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual EffectRender EffectRender { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual TargetFlags TargetFlags { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int ThrowSound { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int ImpactSound { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int ThrowRange { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual TimeSpan ThrowRecovery { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual DateTime ThrownLast { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual SkillName RequiredSkill { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual double RequiredSkillValue { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual Mobile User { get; set; }
public BaseThrowable(int itemID)
: this(itemID, 1)
{ }
public BaseThrowable(int itemID, int amount)
: base(itemID)
{
Stackable = true;
Amount = amount;
Weight = 1.0;
Usage = "Throw Me!";
AllowNoOwner = false;
AllowCombat = true;
AllowDeadUser = false;
Consumable = true;
ClearHands = true;
DismountUser = true;
EffectID = 0;
EffectHue = 0;
EffectRender = EffectRender.Normal;
EffectSpeed = 10;
ThrowSound = -1;
ImpactSound = -1;
ThrowRecovery = TimeSpan.FromSeconds(60.0);
ThrowRange = 12;
RequiredSkill = SkillName.Throwing;
RequiredSkillValue = 0;
}
public BaseThrowable(Serial serial)
: base(serial)
{ }
public override void OnAfterDuped(Item newItem)
{
base.OnAfterDuped(newItem);
var t = newItem as BaseThrowable<TEntity>;
if (t != null)
{
t.UpdateTimer = null;
}
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
if (UpdateTimer == null)
{
return;
}
UpdateTimer.Running = false;
UpdateTimer = null;
}
public virtual bool CanThrow(Mobile m, bool message)
{
if (m == null || m.Deleted)
{
return false;
}
if (m.AccessLevel >= AccessLevel.GameMaster)
{
return true;
}
if (!AllowNoOwner && RootParent != m)
{
if (message)
{
m.SendMessage(37, "You must own the {0} before you can throw it!", this.ResolveName(m));
}
return false;
}
if (!m.Alive && !AllowDeadUser)
{
if (message)
{
m.SendMessage(37, "You can't throw the {0} while dead.", this.ResolveName(m));
}
return false;
}
if (RequiredSkillValue > 0 && m.Skills[RequiredSkill].Value < RequiredSkillValue)
{
if (message)
{
m.SendMessage(37, "You do not have the skill required to throw the {0}.", this.ResolveName(m));
}
return false;
}
if (!m.CanBeginAction(GetType()))
{
if (message)
{
m.SendMessage(37, "Your arms are tired, you must wait to throw another {0}!", this.ResolveName(m));
}
return false;
}
if (!AllowCombat && SpellHelper.CheckCombat(m))
{
if (message)
{
m.SendMessage(37, "You can't throw the {0} while in combat!", this.ResolveName(m));
}
return false;
}
if (m.BodyMod > 0 && !m.BodyMod.IsHuman)
{
if (message)
{
m.SendMessage(37, "How are you supposed to throw the {0} with no hands, beast?", this.ResolveName(m));
}
return false;
}
return true;
}
public virtual bool CanThrowAt(Mobile m, TEntity target, bool message)
{
if (m == null || m.Deleted || target == null)
{
return false;
}
if (m == target as Mobile)
{
if (message)
{
m.SendMessage(37, "You can't throw the {0} at yourself!", this.ResolveName(m));
}
return false;
}
if (m.AccessLevel >= AccessLevel.GameMaster)
{
return true;
}
if (!m.CanSee(target) || !m.InLOS(target))
{
if (message)
{
m.SendMessage(37, "You can't aim at something you can't see!");
}
return false;
}
return true;
}
public virtual void BeginThrow(Mobile m, TEntity target)
{
if (m == null || m.Deleted || target == null)
{
return;
}
if (!CanThrow(m, true) || !CanThrowAt(m, target, true) ||
(m.AccessLevel < AccessLevel.GameMaster && !m.BeginAction(GetType())))
{
return;
}
User = m;
OnBeforeThrownAt(m, target);
var effect = EffectID > 0 ? EffectID : ItemID;
var hue = EffectHue > 0 ? EffectHue : Hue;
new MovingEffectInfo(m, target, target.Map, effect, hue, EffectSpeed, EffectRender).MovingImpact(
() => FinishThrow(m, target));
}
public virtual void FinishThrow(Mobile m, TEntity target)
{
if (m != null && !m.Deleted && target != null)
{
OnThrownAt(m, target);
}
}
public virtual Target BeginTarget(Mobile m)
{
return new GenericSelectTarget<TEntity>(BeginThrow, t => { }, ThrowRange, false, TargetFlags);
}
protected virtual void OnBeginTarget(Mobile m, bool message)
{
if (m == null || m.Deleted || !message || Silent)
{
return;
}
m.LocalOverheadMessage(
MessageType.Emote,
0x55,
true,
String.Format("You begin to swing the {0}...", this.ResolveName(m)));
m.NonlocalOverheadMessage(
MessageType.Emote,
0x55,
true,
String.Format("{0} begins to swing the {1}...", m.RawName, this.ResolveName(m)));
}
protected virtual void OnBeforeThrownAt(Mobile m, TEntity target)
{
if (m == null || m.Deleted || target == null || !CanThrowAt(m, target, false))
{
return;
}
if (m.Spell != null)
{
m.Spell.OnCasterUsingObject(this);
}
if (DismountUser)
{
EtherealMount.StopMounting(m);
}
if (ClearHands)
{
m.ClearHands();
}
if (DismountUser && m.Mounted)
{
BaseMount.Dismount(m);
}
if ((m.Direction & Direction.Running) != Direction.Running)
{
m.Direction = m.GetDirectionTo(target.Location);
}
m.Animate(11, 5, 1, true, false, 0);
if (ThrowSound >= 0)
{
m.PlaySound(ThrowSound);
}
}
protected virtual void OnThrownAt(Mobile m, TEntity target)
{
if (m == null || m.Deleted || target == null)
{
return;
}
if (ImpactSound >= 0)
{
Effects.PlaySound(target.Location, target.Map, ImpactSound);
}
ThrownLast = DateTime.UtcNow;
if (Consumable)
{
Consume();
}
if (ThrowRecovery > TimeSpan.Zero)
{
if (UpdateTimer == null)
{
UpdateTimer = PollTimer.FromSeconds(
1.0,
() =>
{
ClearProperties();
Delta(ItemDelta.Properties);
var readyWhen = ThrownLast + ThrowRecovery;
if (DateTime.UtcNow < readyWhen)
{
return;
}
m.EndAction(GetType());
if (UpdateTimer == null)
{
return;
}
UpdateTimer.Running = false;
UpdateTimer = null;
});
}
else
{
UpdateTimer.Running = true;
}
}
else
{
if (UpdateTimer != null)
{
UpdateTimer.Running = false;
UpdateTimer = null;
}
ClearProperties();
Delta(ItemDelta.Properties);
m.EndAction(GetType());
}
}
public override void OnDelete()
{
base.OnDelete();
if (UpdateTimer == null)
{
return;
}
UpdateTimer.Running = false;
UpdateTimer = null;
}
public override void OnDoubleClick(Mobile m)
{
if (m == null || m.Deleted)
{
return;
}
if (!CanThrow(m, true))
{
return;
}
if (m.Spell != null)
{
m.Spell.OnCasterUsingObject(this);
}
if (ClearHands)
{
m.ClearHands();
}
if (DismountUser)
{
EtherealMount.StopMounting(m);
}
if (DismountUser && m.Mounted)
{
BaseMount.Dismount(m);
}
m.Target = BeginTarget(m);
OnBeginTarget(m, true);
}
public override void OnAosSingleClick(Mobile from)
{
OnSingleClick(from);
}
public override void OnSingleClick(Mobile from)
{
base.OnSingleClick(from);
DateTime now = DateTime.UtcNow, readyWhen = ThrownLast + ThrowRecovery;
var diff = TimeSpan.Zero;
if (readyWhen > now)
{
diff = readyWhen - now;
}
if (diff > TimeSpan.Zero)
{
var time = String.Format("{0:D2}:{1:D2}:{2:D2}", diff.Hours, diff.Minutes, diff.Seconds);
LabelTo(from, "Use: {0}", time);
}
else if (!String.IsNullOrWhiteSpace(Usage))
{
LabelTo(from, "Use: {0}", Usage);
}
if (!String.IsNullOrWhiteSpace(Token))
{
LabelTo(from, "\"{0}\"", Token);
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(2);
switch (version)
{
case 3:
writer.Write(AllowNoOwner);
goto case 2;
case 2:
case 1:
writer.Write(Silent);
goto case 0;
case 0:
{
writer.Write(Usage);
writer.Write(Token);
writer.Write(AllowCombat);
writer.Write(AllowDeadUser);
writer.Write(Consumable);
writer.Write(ClearHands);
writer.Write(DismountUser);
writer.Write(EffectID);
writer.Write(EffectHue);
writer.Write(EffectSpeed);
if (version < 2)
{
writer.Write((short)EffectRender);
writer.Write((byte)TargetFlags);
}
else
{
writer.WriteFlag(EffectRender);
writer.WriteFlag(TargetFlags);
}
writer.Write(ThrowSound);
writer.Write(ImpactSound);
writer.Write(ThrowRange);
writer.Write(ThrowRecovery);
writer.Write(ThrownLast);
if (version < 2)
{
writer.Write((short)RequiredSkill);
}
else
{
writer.WriteFlag(RequiredSkill);
}
writer.Write(RequiredSkillValue);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 3:
AllowNoOwner = reader.ReadBool();
goto case 2;
case 2:
case 1:
Silent = reader.ReadBool();
goto case 0;
case 0:
{
Usage = reader.ReadString();
Token = reader.ReadString();
AllowCombat = reader.ReadBool();
AllowDeadUser = reader.ReadBool();
Consumable = reader.ReadBool();
ClearHands = reader.ReadBool();
DismountUser = reader.ReadBool();
EffectID = reader.ReadInt();
EffectHue = reader.ReadInt();
EffectSpeed = reader.ReadInt();
if (version < 2)
{
EffectRender = (EffectRender)reader.ReadShort();
TargetFlags = (TargetFlags)reader.ReadByte();
}
else
{
EffectRender = reader.ReadFlag<EffectRender>();
TargetFlags = reader.ReadFlag<TargetFlags>();
}
ThrowSound = reader.ReadInt();
ImpactSound = reader.ReadInt();
ThrowRange = reader.ReadInt();
ThrowRecovery = reader.ReadTimeSpan();
ThrownLast = reader.ReadDateTime();
if (version < 2)
{
RequiredSkill = (SkillName)reader.ReadShort();
}
else
{
RequiredSkill = reader.ReadFlag<SkillName>();
}
RequiredSkillValue = reader.ReadDouble();
}
break;
}
}
}
}

View File

@@ -0,0 +1,255 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Targeting;
using VitaNex.Targets;
#endregion
namespace VitaNex.Items
{
public enum ThrowableAtMobileDelivery : byte
{
None = 0x00,
MoveToWorld = 0x01,
AddToPack = 0x02
}
public abstract class BaseThrowableAtMobile<TMobile> : BaseThrowable<TMobile>
where TMobile : Mobile
{
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool AllowDeadTarget { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual ThrowableAtMobileDelivery Delivery { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool Damages { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int DamageMin { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int DamageMax { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool Heals { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int HealMin { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int HealMax { get; set; }
public BaseThrowableAtMobile(int itemID)
: this(itemID, 1)
{ }
public BaseThrowableAtMobile(int itemID, int amount)
: base(itemID, amount)
{
AllowDeadTarget = false;
Delivery = ThrowableAtMobileDelivery.MoveToWorld;
Damages = false;
DamageMin = 0;
DamageMax = 0;
Heals = false;
HealMin = 0;
HealMax = 0;
}
public BaseThrowableAtMobile(Serial serial)
: base(serial)
{ }
public override bool CanThrowAt(Mobile from, TMobile target, bool message)
{
if (from == null || from.Deleted || target == null || target.Deleted || !base.CanThrowAt(from, target, message))
{
return false;
}
if (!target.Alive && !AllowDeadTarget)
{
if (message)
{
from.SendMessage(37, "You can't throw the {0} at the dead.", Name);
}
return false;
}
if (target.Alive && Damages && !from.CanBeHarmful(target, false, true))
{
if (message)
{
from.SendMessage(37, "You can't harm them.");
}
return false;
}
if (target.Alive && Heals && !from.CanBeBeneficial(target, false, true))
{
if (message)
{
from.SendMessage(37, "You can't heal them.");
}
return false;
}
return true;
}
protected override void OnBeforeThrownAt(Mobile from, TMobile target)
{
if (from == null || from.Deleted || target == null || target.Deleted)
{
return;
}
if (target.Alive && Heals)
{
from.DoBeneficial(target);
}
if (target.Alive && Damages)
{
from.DoHarmful(target);
}
base.OnBeforeThrownAt(from, target);
}
protected override void OnThrownAt(Mobile from, TMobile target)
{
if (from == null || from.Deleted || target == null || target.Deleted)
{
return;
}
if (target.Alive && Damages)
{
target.Damage(Utility.RandomMinMax(DamageMin, DamageMax), from);
}
if (target.Alive && Heals)
{
target.Heal(Utility.RandomMinMax(HealMin, HealMax), from);
}
if (Delivery != ThrowableAtMobileDelivery.None)
{
var instance = VitaNexCore.TryCatchGet(() => GetType().CreateInstance<BaseThrowableAtMobile<TMobile>>());
if (instance != null)
{
switch (Delivery)
{
case ThrowableAtMobileDelivery.MoveToWorld:
instance.MoveToWorld(target.Location, target.Map);
break;
case ThrowableAtMobileDelivery.AddToPack:
{
if (!target.AddToBackpack(instance))
{
instance.MoveToWorld(target.Location, target.Map);
}
}
break;
default:
instance.Delete();
break;
}
}
}
base.OnThrownAt(from, target);
}
public override Target BeginTarget(Mobile from)
{
return new MobileSelectTarget<TMobile>(BeginThrow, src => { }, ThrowRange, false, TargetFlags);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(1);
switch (version)
{
case 1:
case 0:
{
writer.Write(AllowDeadTarget);
if (version < 1)
{
writer.Write((byte)Delivery);
}
else
{
writer.WriteFlag(Delivery);
}
writer.Write(Damages);
writer.Write(DamageMin);
writer.Write(DamageMax);
writer.Write(Heals);
writer.Write(HealMin);
writer.Write(HealMax);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 1:
case 0:
{
AllowDeadTarget = reader.ReadBool();
if (version < 1)
{
Delivery = (ThrowableAtMobileDelivery)reader.ReadByte();
}
else
{
Delivery = reader.ReadFlag<ThrowableAtMobileDelivery>();
}
Damages = reader.ReadBool();
DamageMin = reader.ReadInt();
DamageMax = reader.ReadInt();
Heals = reader.ReadBool();
HealMin = reader.ReadInt();
HealMax = reader.ReadInt();
}
break;
}
}
}
}

View File

@@ -0,0 +1,116 @@
#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 Server;
using VitaNex.Network;
#endregion
namespace VitaNex.Items
{
public static class BaseThrowableOPL
{
public static void Initialize()
{
ExtendedOPL.OnItemOPLRequest += OnItemOPLRequest;
}
private static void OnItemOPLRequest(Item item, Mobile viewer, ExtendedOPL list)
{
if (item == null || list == null)
{
return;
}
if (viewer == null && item.Parent is Mobile)
{
viewer = (Mobile)item.Parent;
}
if (viewer == null)
{
return;
}
var throwable = item as IBaseThrowable;
if (throwable == null)
{
return;
}
GetProperties(throwable, viewer, list);
}
public static void GetProperties(IBaseThrowable throwable, Mobile viewer, ExtendedOPL list)
{
if (throwable == null || list == null)
{
return;
}
var lines = new List<string>();
if (throwable.Consumable)
{
lines.Add("Consumable");
}
if (throwable.ClearHands)
{
lines.Add("Clears Hands");
}
if (!throwable.AllowCombat)
{
lines.Add("Non-Combat");
}
if (lines.Count > 0)
{
list.Add(String.Join(", ", lines).WrapUOHtmlColor(Color.Orange));
lines.Clear();
}
if (throwable.RequiredSkillValue > 0)
{
list.Add("Required Skill: {0} - {1:F2}%", throwable.RequiredSkill, throwable.RequiredSkillValue);
}
DateTime now = DateTime.UtcNow, readyWhen = (throwable.ThrownLast + throwable.ThrowRecovery);
var diff = TimeSpan.Zero;
if (readyWhen > now)
{
diff = readyWhen - now;
}
if (diff > TimeSpan.Zero)
{
list.Add("Use: {0:D2}:{1:D2}:{2:D2}".WrapUOHtmlColor(Color.LimeGreen), diff.Hours, diff.Minutes, diff.Seconds);
}
else if (!String.IsNullOrWhiteSpace(throwable.Usage))
{
list.Add("Use: {0}".WrapUOHtmlColor(Color.Cyan), throwable.Usage);
}
if (!String.IsNullOrWhiteSpace(throwable.Token))
{
list.Add("\"{0}\"".WrapUOHtmlColor(Color.Gold), throwable.Token);
}
}
}
}

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 System;
using Server;
using Server.Targeting;
using VitaNex.Network;
#endregion
namespace VitaNex.Items
{
public interface IBaseThrowable
{
string Token { get; set; }
string Usage { get; set; }
bool AllowCombat { get; set; }
bool AllowDeadUser { get; set; }
bool ClearHands { get; set; }
bool Consumable { get; set; }
bool DismountUser { get; set; }
int EffectHue { get; set; }
int EffectID { get; set; }
int EffectSpeed { get; set; }
EffectRender EffectRender { get; set; }
int ThrowSound { get; set; }
int ImpactSound { get; set; }
SkillName RequiredSkill { get; set; }
double RequiredSkillValue { get; set; }
TargetFlags TargetFlags { get; set; }
DateTime ThrownLast { get; set; }
TimeSpan ThrowRecovery { get; set; }
int ThrowRange { get; set; }
}
}

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 Server;
using Server.Engines.Craft;
using Server.Items;
using VitaNex.SuperCrafts;
#endregion
namespace VitaNex.Items
{
public class PyrotechnicsKit : BaseTool
{
public override CraftSystem CraftSystem => SuperCraftSystem.Resolve<Pyrotechnics>();
[Constructable]
public PyrotechnicsKit()
: this(50)
{ }
[Constructable]
public PyrotechnicsKit(int uses)
: base(uses, Utility.RandomList(39213, 39214))
{
Name = "Pyrotechnics Kit";
Weight = 2.0;
}
public PyrotechnicsKit(Serial serial)
: base(serial)
{ }
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,194 @@
#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;
#endregion
namespace VitaNex.Items
{
public class AccessCloak : BaseCloak
{
private AccessLevel _AccessTemp;
private AccessLevel _AccessMask;
[CommandProperty(AccessLevel.GameMaster)]
public AccessLevel AccessMask
{
get => _AccessMask;
set
{
if (value <= _AccessTemp)
{
_AccessMask = value;
}
}
}
public override bool DisplayLootType => false;
public override bool DisplayWeight => false;
[Constructable]
public AccessCloak()
: this(AccessLevel.Player)
{ }
public AccessCloak(Mobile owner)
: this(owner, AccessLevel.Player)
{ }
public AccessCloak(Mobile owner, AccessLevel mask)
: this(mask)
{
_AccessTemp = owner != null ? owner.AccessLevel : AccessLevel.Player;
}
public AccessCloak(AccessLevel mask)
: base(0x1515)
{
_AccessMask = mask;
Name = "Access Cloak";
Hue = Utility.RandomDyedHue();
LootType = LootType.Blessed;
StrRequirement = 0;
Weight = 0;
}
public AccessCloak(Serial serial)
: base(serial)
{ }
public override DeathMoveResult OnParentDeath(Mobile parent)
{
return DeathMoveResult.MoveToBackpack;
}
public override bool OnEquip(Mobile from)
{
if (BlessedFor == null)
{
BlessedFor = from;
_AccessTemp = BlessedFor.AccessLevel;
}
if (BlessedFor != from)
{
from.SendMessage("That does not belong to you.");
return false;
}
return base.OnEquip(from);
}
#if NEWPARENT
public override void OnAdded(IEntity parent)
#else
public override void OnAdded(object parent)
#endif
{
if (BlessedFor != null)
{
BlessedFor.AccessLevel = _AccessMask;
BlessedFor.Hits = BlessedFor.HitsMax;
BlessedFor.Stam = BlessedFor.StamMax;
BlessedFor.Mana = BlessedFor.ManaMax;
}
base.OnAdded(parent);
}
#if NEWPARENT
public override void OnRemoved(IEntity parent)
#else
public override void OnRemoved(object parent)
#endif
{
if (BlessedFor != null)
{
BlessedFor.AccessLevel = _AccessTemp;
BlessedFor.Hits = BlessedFor.HitsMax;
BlessedFor.Stam = BlessedFor.StamMax;
BlessedFor.Mana = BlessedFor.ManaMax;
}
base.OnRemoved(parent);
}
public override void OnDelete()
{
if (BlessedFor != null)
{
BlessedFor.AccessLevel = _AccessTemp;
BlessedFor.Hits = BlessedFor.HitsMax;
BlessedFor.Stam = BlessedFor.StamMax;
BlessedFor.Mana = BlessedFor.ManaMax;
}
base.OnDelete();
}
public override void AddNameProperty(ObjectPropertyList list)
{
base.AddNameProperty(list);
list.Add(
"<basefont color=#{0:X6}>Cloak: {1} => {2}<basefont color=#FFFFFF>",
Color.Gold.ToRgb(),
_AccessTemp,
_AccessMask);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(BlessedFor);
writer.WriteFlag(_AccessMask);
writer.WriteFlag(_AccessTemp);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
BlessedFor = reader.ReadMobile();
_AccessMask = reader.ReadFlag<AccessLevel>();
_AccessTemp = reader.ReadFlag<AccessLevel>();
}
break;
}
}
}
}

View File

@@ -0,0 +1,501 @@
#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.Linq;
using Server;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Network;
using VitaNex.SuperGumps.UI;
#endregion
namespace VitaNex.Items
{
public class BroadcastScrollGump : TextInputPanelGump<BroadcastScroll>
{
public bool UseConfirmDialog { get; set; }
public BroadcastScrollGump(
PlayerMobile user,
Gump parent = null,
BroadcastScroll scroll = null,
bool useConfirm = true)
: base(
user,
parent,
null,
null,
400,
150,
"No scroll selected.",
"Broadcast Scroll Message (200 Chars)",
null,
scroll,
null,
200)
{
UseConfirmDialog = useConfirm;
}
protected override void Compile()
{
if (Selected != null && Selected.Message != Input)
{
Input = Selected.Message;
}
base.Compile();
}
protected override void ParseInput(string text)
{
base.ParseInput(text);
if (Selected != null)
{
Selected.Message = Input ?? String.Empty;
}
}
protected override void CompileMenuOptions(MenuGumpOptions list)
{
if (Selected != null && !String.IsNullOrWhiteSpace(Selected.Message))
{
list.AppendEntry(
new ListGumpEntry(
"Broadcast",
b =>
{
if (Selected != null)
{
Selected.Message = Input ?? String.Empty;
Selected.Broadcast(User);
}
Refresh(true);
},
HighlightHue));
list.AppendEntry(
new ListGumpEntry(
"Clear",
b =>
{
if (Selected != null)
{
Selected.Message = Input = String.Empty;
}
Refresh(true);
},
ErrorHue));
}
base.CompileMenuOptions(list);
}
}
[Flipable(0xE34, 0xEF3)]
public class BroadcastScroll : Item, IUsesRemaining
{
public static bool Feedback = false;
private bool _ShowUsesRemaining = true;
private int _UsesRemaining = 10;
[CommandProperty(AccessLevel.GameMaster)]
public virtual string Message { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int MessageHue { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public virtual int UsesRemaining
{
get => _UsesRemaining;
set
{
_UsesRemaining = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool ShowUsesRemaining
{
get => _ShowUsesRemaining;
set
{
_ShowUsesRemaining = value;
InvalidateProperties();
}
}
public override bool DisplayLootType => false;
public override bool DisplayWeight => false;
[Constructable]
public BroadcastScroll()
: this(1)
{ }
[Constructable]
public BroadcastScroll(int uses)
: base(0xE34)
{
UsesRemaining = Math.Max(1, uses);
Name = "Broadcast Scroll";
LootType = LootType.Blessed;
Stackable = false;
Weight = 0;
}
public BroadcastScroll(Serial serial)
: base(serial)
{ }
public void Broadcast(Mobile from)
{
if (from == null || from.Deleted || !from.Player)
{
return;
}
if (!IsChildOf(from.Backpack) || !IsAccessibleTo(from) || !from.CanSee(this) || InSecureTrade)
{
return;
}
if (String.IsNullOrWhiteSpace(Message))
{
new NoticeDialogGump(from)
{
Title = "Empty Message",
Html = "Your broadcast message can't be blank and can't consist only of white-space."
}.Send();
return;
}
if (Deleted || UsesRemaining <= 0)
{
if (from is PlayerMobile)
{
new NoticeDialogGump((PlayerMobile)from)
{
Title = "Scroll Exhausted",
Html = "Your broadcast scroll has been exhausted, you can't send another message."
}.Send();
}
return;
}
//Send the message to all online players, including staff.
int reach = 0, staff = 0;
foreach (var state in NetState.Instances.Where(ns => ns != null && ns.Running && ns.Mobile != null))
{
state.Mobile.SendMessage(MessageHue > 0 ? MessageHue : from.SpeechHue, "Message from {0}:", from.RawName);
state.Mobile.SendMessage(MessageHue > 0 ? MessageHue : from.SpeechHue, Message);
if (state.Mobile == from || (DateTime.UtcNow - state.ConnectedOn) < TimeSpan.FromMinutes(1))
{
continue;
}
//If receiver is not sender and receiver has been logged in for over 1 minute, include them in total reached.
reach++;
if (state.Mobile.AccessLevel >= AccessLevel.Counselor)
{
staff++;
}
}
//If we reached people and they weren't just staff, charge for the message.
if (reach - staff > 0)
{
if (Feedback)
{
from.SendMessage(0x55, "Your broadcast was seen by {0:#,0} people!", reach);
}
if (--UsesRemaining <= 0)
{
from.SendMessage(0x22, "Your broadcast scroll has been exhausted, you throw away the scrap paper.");
Delete();
}
}
else
{
from.SendMessage(0x22, "Your broadcast was not seen by anyone, your scroll was not consumed this time.");
}
}
public override void OnDoubleClick(Mobile from)
{
base.OnDoubleClick(from);
if (!this.CheckDoubleClick(from, true, true, 2, true))
{
return;
}
if (from is PlayerMobile && UsesRemaining > 0)
{
new BroadcastScrollGump((PlayerMobile)from, scroll: this).Send();
}
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (ShowUsesRemaining)
{
// uses remaining: ~1_val~
list.Add(1060584, UsesRemaining == Int32.MaxValue ? "unlimited" : String.Format("{0:#,0}", UsesRemaining));
}
list.Add("Use: Broadcast A Global Message".WrapUOHtmlColor(Color.SkyBlue));
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(Message);
writer.Write(_UsesRemaining);
writer.Write(_ShowUsesRemaining);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
Message = reader.ReadString();
_UsesRemaining = reader.ReadInt();
_ShowUsesRemaining = reader.ReadBool();
}
break;
}
}
}
public class BroadcastScroll_Unlimited : BroadcastScroll
{
public override int UsesRemaining { get => Int32.MaxValue; set { } }
[Constructable]
public BroadcastScroll_Unlimited()
: base(Int32.MaxValue)
{
ShowUsesRemaining = false;
}
public BroadcastScroll_Unlimited(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class BroadcastScroll_3Uses : BroadcastScroll
{
[Constructable]
public BroadcastScroll_3Uses()
: base(3)
{ }
public BroadcastScroll_3Uses(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class BroadcastScroll_5Uses : BroadcastScroll
{
[Constructable]
public BroadcastScroll_5Uses()
: base(5)
{ }
public BroadcastScroll_5Uses(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class BroadcastScroll_10Uses : BroadcastScroll
{
[Constructable]
public BroadcastScroll_10Uses()
: base(10)
{ }
public BroadcastScroll_10Uses(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class BroadcastScroll_30Uses : BroadcastScroll
{
[Constructable]
public BroadcastScroll_30Uses()
: base(30)
{ }
public BroadcastScroll_30Uses(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class BroadcastScroll_50Uses : BroadcastScroll
{
[Constructable]
public BroadcastScroll_50Uses()
: base(50)
{ }
public BroadcastScroll_50Uses(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class BroadcastScroll_100Uses : BroadcastScroll
{
[Constructable]
public BroadcastScroll_100Uses()
: base(100)
{ }
public BroadcastScroll_100Uses(Serial serial)
: base(serial)
{ }
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,407 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
using Server.Mobiles;
#endregion
namespace VitaNex.Items
{
public abstract class FloorTile<TMob> : Item
where TMob : Mobile
{
public override double DefaultWeight => 0;
public override bool DisplayWeight => false;
public override bool DisplayLootType => false;
public override bool Decays => false;
public Func<TMob, bool> MoveOverHandler { get; set; }
public Func<TMob, bool> MoveOffHandler { get; set; }
public FloorTile()
: this(null, null)
{ }
public FloorTile(Func<TMob, bool> moveOver, Func<TMob, bool> moveOff)
: base(9272)
{
MoveOverHandler = moveOver;
MoveOffHandler = moveOff;
Name = "Floor Tile";
Movable = false;
Visible = false;
}
public FloorTile(Serial serial)
: base(serial)
{ }
public override sealed bool OnMoveOver(Mobile m)
{
if (m == null || m.Deleted || !(m is TMob))
{
return base.OnMoveOver(m);
}
return OnMoveOver(m as TMob);
}
public virtual bool OnMoveOver(TMob mob)
{
if (base.OnMoveOver(mob))
{
if (MoveOverHandler != null)
{
return MoveOverHandler(mob);
}
return true;
}
return false;
}
public override sealed bool OnMoveOff(Mobile m)
{
if (m == null || m.Deleted || !(m is TMob))
{
return base.OnMoveOff(m);
}
return OnMoveOff(m as TMob);
}
public virtual bool OnMoveOff(TMob mob)
{
if (base.OnMoveOff(mob))
{
if (MoveOffHandler != null)
{
return MoveOffHandler(mob);
}
return true;
}
return false;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public abstract class RestrictMobileTile<TMob> : FloorTile<TMob>
where TMob : Mobile
{
[CommandProperty(AccessLevel.GameMaster)]
public bool Restricted { get; set; }
public RestrictMobileTile()
: this(null, null)
{ }
public RestrictMobileTile(Func<TMob, bool> moveOver, Func<TMob, bool> moveOff)
: base(moveOver, moveOff)
{
Restricted = true;
Name = "Restrict Mobiles";
}
public RestrictMobileTile(Serial serial)
: base(serial)
{ }
public override bool OnMoveOver(TMob m)
{
if (base.OnMoveOver(m))
{
return !Restricted;
}
return false;
}
public override bool OnMoveOff(TMob m)
{
if (base.OnMoveOff(m))
{
return !Restricted;
}
return false;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.Write(Restricted);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
Restricted = reader.ReadBool();
break;
}
}
}
public class RestrictMobileTile : RestrictMobileTile<Mobile>
{
[Constructable]
public RestrictMobileTile()
: this(null, null)
{ }
public RestrictMobileTile(Func<Mobile, bool> moveOver, Func<Mobile, bool> moveOff)
: base(moveOver, moveOff)
{
Name = "Restrict Mobiles";
}
public RestrictMobileTile(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
}
}
public class RestrictCreatureTile : RestrictMobileTile<BaseCreature>
{
[CommandProperty(AccessLevel.GameMaster)]
public bool AllowControlled { get; set; }
[Constructable]
public RestrictCreatureTile()
: this(null, null)
{ }
public RestrictCreatureTile(Func<BaseCreature, bool> moveOver, Func<BaseCreature, bool> moveOff)
: base(moveOver, moveOff)
{
AllowControlled = true;
Name = "Restrict Creatures";
}
public RestrictCreatureTile(Serial serial)
: base(serial)
{ }
public override bool OnMoveOver(BaseCreature m)
{
if (!base.OnMoveOver(m))
{
if (m.Controlled && AllowControlled)
{
return true;
}
return false;
}
return true;
}
public override bool OnMoveOff(BaseCreature m)
{
if (!base.OnMoveOff(m))
{
if (m.Controlled && AllowControlled)
{
return true;
}
return false;
}
return true;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
writer.Write(AllowControlled);
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
AllowControlled = reader.ReadBool();
break;
}
}
}
public class RestrictPlayerTile : RestrictMobileTile<PlayerMobile>
{
[CommandProperty(AccessLevel.GameMaster)]
public bool AllowDead { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool AllowYoung { get; set; }
[Constructable]
public RestrictPlayerTile()
: this(null, null)
{ }
public RestrictPlayerTile(Func<PlayerMobile, bool> moveOver, Func<PlayerMobile, bool> moveOff)
: base(moveOver, moveOff)
{
AllowYoung = true;
AllowDead = true;
Name = "Restrict Players";
}
public RestrictPlayerTile(Serial serial)
: base(serial)
{ }
public override bool OnMoveOver(PlayerMobile m)
{
if (m.Player && m.AccessLevel > AccessLevel.Counselor)
{
return true;
}
if (!base.OnMoveOver(m))
{
if (!m.Alive && AllowDead)
{
return true;
}
if (m.Young && AllowYoung)
{
return true;
}
return false;
}
return true;
}
public override bool OnMoveOff(PlayerMobile m)
{
if (m.Player && m.AccessLevel > AccessLevel.Counselor)
{
return true;
}
if (!base.OnMoveOff(m))
{
if (!m.Alive && AllowDead)
{
return true;
}
if (m.Young && AllowYoung)
{
return true;
}
return false;
}
return true;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
var version = writer.SetVersion(0);
switch (version)
{
case 0:
{
writer.Write(AllowDead);
writer.Write(AllowYoung);
}
break;
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.GetVersion();
switch (version)
{
case 0:
{
AllowDead = reader.ReadBool();
AllowYoung = reader.ReadBool();
}
break;
}
}
}
}