Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
431
Scripts/SubSystem/VitaNex/Core/Items/Misc/GhostMulti.cs
Normal file
431
Scripts/SubSystem/VitaNex/Core/Items/Misc/GhostMulti.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
153
Scripts/SubSystem/VitaNex/Core/Items/Misc/SeveredHead.cs
Normal file
153
Scripts/SubSystem/VitaNex/Core/Items/Misc/SeveredHead.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
273
Scripts/SubSystem/VitaNex/Core/Items/Misc/StrobeLantern.cs
Normal file
273
Scripts/SubSystem/VitaNex/Core/Items/Misc/StrobeLantern.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user