fix: Converts stealable artifacts to a system instead of a spawner. (#979)
This commit is contained in:
parent
b61968db86
commit
e148e1cabb
4 changed files with 450 additions and 437 deletions
444
Projects/UOContent/Engines/Stealables/StealableArtifacts.cs
Normal file
444
Projects/UOContent/Engines/Stealables/StealableArtifacts.cs
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Items;
|
||||
using Server.Logging;
|
||||
using Server.Utilities;
|
||||
|
||||
namespace Server.Engines.Stealables;
|
||||
|
||||
public static class StealableArtifacts
|
||||
{
|
||||
private static readonly ILogger logger = LogFactory.GetLogger(typeof(StealableArtifacts));
|
||||
|
||||
private static bool _enabled;
|
||||
private static Type[] _typesOfEntries;
|
||||
private static StealableInstance[] _artifacts;
|
||||
|
||||
private static Timer _respawnTimer;
|
||||
private static Dictionary<Item, StealableInstance> _table;
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
GenericPersistence.Register("stealable-artifacts", Serialize, Deserialize);
|
||||
}
|
||||
|
||||
private static void RemoveStealableArtifacts()
|
||||
{
|
||||
_enabled = false;
|
||||
_respawnTimer?.Stop();
|
||||
_respawnTimer = null;
|
||||
|
||||
if (_artifacts?.Length > 0)
|
||||
{
|
||||
foreach (var si in _artifacts)
|
||||
{
|
||||
var item = si.Item;
|
||||
if (item.Deleted == false && !item.Movable && item.Parent == null)
|
||||
{
|
||||
item.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_artifacts = null;
|
||||
}
|
||||
|
||||
private static void CreateStealableArtifacts()
|
||||
{
|
||||
_enabled = true;
|
||||
|
||||
_artifacts = new StealableInstance[Entries.Length];
|
||||
_table ??= new Dictionary<Item, StealableInstance>(Entries.Length);
|
||||
|
||||
for (var i = 0; i < Entries.Length; i++)
|
||||
{
|
||||
_artifacts[i] = new StealableInstance(Entries[i]);
|
||||
}
|
||||
|
||||
_respawnTimer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromMinutes(15.0), CheckRespawn);
|
||||
}
|
||||
|
||||
public static StealableEntry[] Entries { get; } =
|
||||
{
|
||||
// Doom - Artifact rarity 1
|
||||
new(Map.Malas, new Point3D(317, 56, -1), 72, 108, typeof(RockArtifact)),
|
||||
new(Map.Malas, new Point3D(360, 31, 8), 72, 108, typeof(SkullCandleArtifact)),
|
||||
new(Map.Malas, new Point3D(369, 372, -1), 72, 108, typeof(BottleArtifact)),
|
||||
new(Map.Malas, new Point3D(378, 372, 0), 72, 108, typeof(DamagedBooksArtifact)),
|
||||
// Doom - Artifact rarity 2
|
||||
new(Map.Malas, new Point3D(432, 16, -1), 144, 216, typeof(StretchedHideArtifact)),
|
||||
new(Map.Malas, new Point3D(489, 9, 0), 144, 216, typeof(BrazierArtifact)),
|
||||
// Doom - Artifact rarity 3
|
||||
new(Map.Malas, new Point3D(471, 96, -1), 288, 432, typeof(LampPostArtifact), GetLampPostHue()),
|
||||
new(Map.Malas, new Point3D(421, 198, 2), 288, 432, typeof(BooksNorthArtifact)),
|
||||
new(Map.Malas, new Point3D(431, 189, -1), 288, 432, typeof(BooksWestArtifact)),
|
||||
new(Map.Malas, new Point3D(435, 196, -1), 288, 432, typeof(BooksFaceDownArtifact)),
|
||||
// Doom - Artifact rarity 5
|
||||
new(Map.Malas, new Point3D(447, 9, 8), 1152, 1728, typeof(StuddedLeggingsArtifact)),
|
||||
new(Map.Malas, new Point3D(423, 28, 0), 1152, 1728, typeof(EggCaseArtifact)),
|
||||
new(Map.Malas, new Point3D(347, 44, 4), 1152, 1728, typeof(SkinnedGoatArtifact)),
|
||||
new(Map.Malas, new Point3D(497, 57, -1), 1152, 1728, typeof(GruesomeStandardArtifact)),
|
||||
new(Map.Malas, new Point3D(381, 375, 11), 1152, 1728, typeof(BloodyWaterArtifact)),
|
||||
new(Map.Malas, new Point3D(489, 369, 2), 1152, 1728, typeof(TarotCardsArtifact)),
|
||||
new(Map.Malas, new Point3D(497, 369, 5), 1152, 1728, typeof(BackpackArtifact)),
|
||||
// Doom - Artifact rarity 7
|
||||
new(Map.Malas, new Point3D(475, 23, 4), 4608, 6912, typeof(StuddedTunicArtifact)),
|
||||
new(Map.Malas, new Point3D(423, 28, 0), 4608, 6912, typeof(CocoonArtifact)),
|
||||
// Doom - Artifact rarity 8
|
||||
new(Map.Malas, new Point3D(354, 36, -1), 9216, 13824, typeof(SkinnedDeerArtifact)),
|
||||
// Doom - Artifact rarity 9
|
||||
new(Map.Malas, new Point3D(433, 11, -1), 18432, 27648, typeof(SaddleArtifact)),
|
||||
new(Map.Malas, new Point3D(403, 31, 4), 18432, 27648, typeof(LeatherTunicArtifact)),
|
||||
// Doom - Artifact rarity 10
|
||||
new(Map.Malas, new Point3D(257, 70, -2), 36864, 55296, typeof(ZyronicClaw)),
|
||||
new(Map.Malas, new Point3D(354, 176, 7), 36864, 55296, typeof(TitansHammer)),
|
||||
new(Map.Malas, new Point3D(369, 389, -1), 36864, 55296, typeof(BladeOfTheRighteous)),
|
||||
new(Map.Malas, new Point3D(467, 92, 4), 36864, 55296, typeof(InquisitorsResolution)),
|
||||
// Doom - Artifact rarity 12
|
||||
new(Map.Malas, new Point3D(487, 364, -1), 147456, 221184, typeof(RuinedPaintingArtifact)),
|
||||
|
||||
// Yomotsu Mines - Artifact rarity 1
|
||||
new(Map.Malas, new Point3D(18, 110, -1), 72, 108, typeof(Basket1Artifact)),
|
||||
new(Map.Malas, new Point3D(66, 114, -1), 72, 108, typeof(Basket2Artifact)),
|
||||
// Yomotsu Mines - Artifact rarity 2
|
||||
new(Map.Malas, new Point3D(63, 12, 11), 144, 216, typeof(Basket4Artifact)),
|
||||
new(Map.Malas, new Point3D(5, 29, -1), 144, 216, typeof(Basket5NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(30, 81, 3), 144, 216, typeof(Basket5WestArtifact)),
|
||||
// Yomotsu Mines - Artifact rarity 3
|
||||
new(Map.Malas, new Point3D(115, 7, -1), 288, 432, typeof(Urn1Artifact)),
|
||||
new(Map.Malas, new Point3D(85, 13, -1), 288, 432, typeof(Urn2Artifact)),
|
||||
new(Map.Malas, new Point3D(110, 53, -1), 288, 432, typeof(Sculpture1Artifact)),
|
||||
new(Map.Malas, new Point3D(108, 37, -1), 288, 432, typeof(Sculpture2Artifact)),
|
||||
new(Map.Malas, new Point3D(121, 14, -1), 288, 432, typeof(TeapotNorthArtifact)),
|
||||
new(Map.Malas, new Point3D(121, 115, -1), 288, 432, typeof(TeapotWestArtifact)),
|
||||
new(Map.Malas, new Point3D(84, 40, -1), 288, 432, typeof(TowerLanternArtifact)),
|
||||
// Yomotsu Mines - Artifact rarity 9
|
||||
new(Map.Malas, new Point3D(94, 7, -1), 18432, 27648, typeof(ManStatuetteSouthArtifact)),
|
||||
|
||||
// Fan Dancer's Dojo - Artifact rarity 1
|
||||
new(Map.Malas, new Point3D(113, 640, -2), 72, 108, typeof(Basket3NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(102, 355, -1), 72, 108, typeof(Basket3WestArtifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 2
|
||||
new(Map.Malas, new Point3D(99, 370, -1), 144, 216, typeof(Basket6Artifact)),
|
||||
new(Map.Malas, new Point3D(100, 357, -1), 144, 216, typeof(ZenRock1Artifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 3
|
||||
new(Map.Malas, new Point3D(73, 473, -1), 288, 432, typeof(FanNorthArtifact)),
|
||||
new(Map.Malas, new Point3D(99, 372, -1), 288, 432, typeof(FanWestArtifact)),
|
||||
new(Map.Malas, new Point3D(92, 326, -1), 288, 432, typeof(BowlsVerticalArtifact)),
|
||||
new(Map.Malas, new Point3D(97, 470, -1), 288, 432, typeof(ZenRock2Artifact)),
|
||||
new(Map.Malas, new Point3D(103, 691, -1), 288, 432, typeof(ZenRock3Artifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 4
|
||||
new(Map.Malas, new Point3D(103, 336, 4), 576, 864, typeof(Painting1NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(59, 381, 4), 576, 864, typeof(Painting1WestArtifact)),
|
||||
new(Map.Malas, new Point3D(84, 401, 2), 576, 864, typeof(Painting2NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(59, 392, 2), 576, 864, typeof(Painting2WestArtifact)),
|
||||
new(Map.Malas, new Point3D(107, 483, -1), 576, 864, typeof(TripleFanNorthArtifact)),
|
||||
new(Map.Malas, new Point3D(50, 475, -1), 576, 864, typeof(TripleFanWestArtifact)),
|
||||
new(Map.Malas, new Point3D(107, 460, -1), 576, 864, typeof(BowlArtifact)),
|
||||
new(Map.Malas, new Point3D(90, 502, -1), 576, 864, typeof(CupsArtifact)),
|
||||
new(Map.Malas, new Point3D(107, 688, -1), 576, 864, typeof(BowlsHorizontalArtifact)),
|
||||
new(Map.Malas, new Point3D(112, 676, -1), 576, 864, typeof(SakeArtifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 5
|
||||
new(Map.Malas, new Point3D(135, 614, -1), 1152, 1728, typeof(SwordDisplay1NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(50, 482, -1), 1152, 1728, typeof(SwordDisplay1WestArtifact)),
|
||||
new(Map.Malas, new Point3D(119, 672, -1), 1152, 1728, typeof(Painting3Artifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 6
|
||||
new(Map.Malas, new Point3D(90, 326, -1), 2304, 3456, typeof(Painting4NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(99, 354, -1), 2304, 3456, typeof(Painting4WestArtifact)),
|
||||
new(Map.Malas, new Point3D(179, 652, -1), 2304, 3456, typeof(SwordDisplay2NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(118, 627, -1), 2304, 3456, typeof(SwordDisplay2WestArtifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 7
|
||||
new(Map.Malas, new Point3D(90, 483, -1), 4608, 6912, typeof(FlowersArtifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 8
|
||||
new(Map.Malas, new Point3D(71, 562, -1), 9216, 13824, typeof(DolphinLeftArtifact)),
|
||||
new(Map.Malas, new Point3D(102, 677, -1), 9216, 13824, typeof(DolphinRightArtifact)),
|
||||
new(Map.Malas, new Point3D(61, 499, 0), 9216, 13824, typeof(SwordDisplay3SouthArtifact)),
|
||||
new(Map.Malas, new Point3D(182, 669, -1), 9216, 13824, typeof(SwordDisplay3EastArtifact)),
|
||||
new(Map.Malas, new Point3D(162, 647, -1), 9216, 13824, typeof(SwordDisplay4WestArtifact)),
|
||||
new(Map.Malas, new Point3D(124, 624, 0), 9216, 13824, typeof(Painting5NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(146, 649, 2), 9216, 13824, typeof(Painting5WestArtifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 9
|
||||
new(Map.Malas, new Point3D(100, 488, -1), 18432, 27648, typeof(SwordDisplay4NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(175, 606, 0), 18432, 27648, typeof(SwordDisplay5NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(157, 608, -1), 18432, 27648, typeof(SwordDisplay5WestArtifact)),
|
||||
new(Map.Malas, new Point3D(187, 643, 1), 18432, 27648, typeof(Painting6NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(146, 623, 1), 18432, 27648, typeof(Painting6WestArtifact)),
|
||||
new(Map.Malas, new Point3D(178, 629, -1), 18432, 27648, typeof(ManStatuetteEastArtifact))
|
||||
};
|
||||
|
||||
public static Type[] TypesOfEntries
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_typesOfEntries == null)
|
||||
{
|
||||
_typesOfEntries = new Type[Entries.Length];
|
||||
|
||||
for (var i = 0; i < Entries.Length; i++)
|
||||
{
|
||||
_typesOfEntries[i] = Entries[i].Type;
|
||||
}
|
||||
}
|
||||
|
||||
return _typesOfEntries;
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetLampPostHue() =>
|
||||
Utility.RandomDouble() < 0.9 ? 0 : Utility.RandomList(0x455, 0x47E, 0x482, 0x486, 0x48F, 0x4F2, 0x58C, 0x66C);
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register("GenStealArties", AccessLevel.Administrator, GenStealArties_OnCommand);
|
||||
CommandSystem.Register("RemoveStealArties", AccessLevel.Administrator, RemoveStealArties_OnCommand);
|
||||
}
|
||||
|
||||
[Usage("GenStealArties"), Description("Generates the stealable artifacts spawner.")]
|
||||
private static void GenStealArties_OnCommand(CommandEventArgs args)
|
||||
{
|
||||
var from = args.Mobile;
|
||||
|
||||
if (_enabled)
|
||||
{
|
||||
from.SendMessage("Stealable artifacts spawner already present.");
|
||||
return;
|
||||
}
|
||||
|
||||
CreateStealableArtifacts();
|
||||
from.SendMessage("Stealable artifacts spawner generated.");
|
||||
}
|
||||
|
||||
[Usage("RemoveStealArties")]
|
||||
[Description("Removes the stealable artifacts spawner and every not yet stolen stealable artifacts.")]
|
||||
private static void RemoveStealArties_OnCommand(CommandEventArgs args)
|
||||
{
|
||||
var from = args.Mobile;
|
||||
|
||||
if (!_enabled)
|
||||
{
|
||||
from.SendMessage("Stealable artifacts spawner not present.");
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveStealableArtifacts();
|
||||
from.SendMessage("Stealable artifacts spawner removed.");
|
||||
}
|
||||
|
||||
public static StealableInstance GetStealableInstance(Item item)
|
||||
{
|
||||
if (_enabled && _table.TryGetValue(item, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void CheckRespawn()
|
||||
{
|
||||
foreach (var si in _artifacts)
|
||||
{
|
||||
si.CheckRespawn();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Serialize(IGenericWriter writer)
|
||||
{
|
||||
writer.WriteEncodedInt(1); // version
|
||||
|
||||
writer.Write(_enabled);
|
||||
|
||||
if (_enabled)
|
||||
{
|
||||
writer.WriteEncodedInt(_artifacts.Length);
|
||||
|
||||
for (var i = 0; i < _artifacts.Length; i++)
|
||||
{
|
||||
var si = _artifacts[i];
|
||||
|
||||
writer.Write(si.Item);
|
||||
writer.WriteDeltaTime(si.NextRespawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void Deserialize(IGenericReader reader)
|
||||
{
|
||||
var version = reader.ReadEncodedInt();
|
||||
|
||||
_enabled = version > 0 && reader.ReadBool();
|
||||
|
||||
if (_enabled)
|
||||
{
|
||||
_artifacts = new StealableInstance[Entries.Length];
|
||||
_table = new Dictionary<Item, StealableInstance>(Entries.Length);
|
||||
|
||||
var length = reader.ReadEncodedInt();
|
||||
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
var item = reader.ReadEntity<Item>();
|
||||
var nextRespawn = reader.ReadDeltaTime();
|
||||
|
||||
if (i < _artifacts.Length)
|
||||
{
|
||||
var si = new StealableInstance(Entries[i], item, nextRespawn);
|
||||
_artifacts[i] = si;
|
||||
|
||||
if (si.Item != null)
|
||||
{
|
||||
_table[si.Item] = si;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = length; i < Entries.Length; i++)
|
||||
{
|
||||
_artifacts[i] = new StealableInstance(Entries[i]);
|
||||
}
|
||||
|
||||
_enabled = _artifacts.Length > 0;
|
||||
|
||||
if (_enabled)
|
||||
{
|
||||
_respawnTimer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromMinutes(15.0), CheckRespawn);
|
||||
}
|
||||
else
|
||||
{
|
||||
_artifacts = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class StealableEntry
|
||||
{
|
||||
public StealableEntry(Map map, Point3D location, int minDelay, int maxDelay, Type type, int hue = 0)
|
||||
{
|
||||
Map = map;
|
||||
Location = location;
|
||||
MinDelay = minDelay;
|
||||
MaxDelay = maxDelay;
|
||||
Type = type;
|
||||
Hue = hue;
|
||||
}
|
||||
|
||||
public Map Map { get; }
|
||||
|
||||
public Point3D Location { get; }
|
||||
|
||||
public int MinDelay { get; }
|
||||
|
||||
public int MaxDelay { get; }
|
||||
|
||||
public Type Type { get; }
|
||||
|
||||
public int Hue { get; }
|
||||
|
||||
public Item CreateInstance()
|
||||
{
|
||||
try
|
||||
{
|
||||
var item = Type.CreateInstance<Item>();
|
||||
|
||||
if (Hue > 0)
|
||||
{
|
||||
item.Hue = Hue;
|
||||
}
|
||||
|
||||
item.Movable = false;
|
||||
item.MoveToWorld(Location, Map);
|
||||
|
||||
return item;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Warning(e, $"Failed to construct stealable artifact: {Type.FullName}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class StealableInstance
|
||||
{
|
||||
private Item m_Item;
|
||||
|
||||
public StealableInstance(StealableEntry entry) : this(entry, null, Core.Now)
|
||||
{
|
||||
}
|
||||
|
||||
public StealableInstance(StealableEntry entry, Item item, DateTime nextRespawn)
|
||||
{
|
||||
m_Item = item;
|
||||
NextRespawn = nextRespawn;
|
||||
Entry = entry;
|
||||
}
|
||||
|
||||
public StealableEntry Entry { get; }
|
||||
|
||||
public Item Item
|
||||
{
|
||||
get => m_Item;
|
||||
set
|
||||
{
|
||||
if (m_Item != null && value == null)
|
||||
{
|
||||
var delay = Utility.RandomMinMax(Entry.MinDelay, Entry.MaxDelay);
|
||||
NextRespawn = Core.Now + TimeSpan.FromMinutes(delay);
|
||||
}
|
||||
|
||||
if (_enabled)
|
||||
{
|
||||
if (m_Item != null)
|
||||
{
|
||||
_table.Remove(m_Item);
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
_table[value] = this;
|
||||
}
|
||||
}
|
||||
|
||||
m_Item = value;
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime NextRespawn { get; set; }
|
||||
|
||||
public void CheckRespawn()
|
||||
{
|
||||
if (Item != null && (Item.Deleted || Item.Movable || Item.Parent != null))
|
||||
{
|
||||
Item = null;
|
||||
}
|
||||
|
||||
if (Item == null && Core.Now >= NextRespawn)
|
||||
{
|
||||
Item = Entry.CreateInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ManualDirtyChecking]
|
||||
[TypeAlias("Server.Items.StealableArtifactsSpawner")]
|
||||
[Obsolete("Deprecated in favor of the static system. Only used for legacy deserialization")]
|
||||
public class StealableArtifactsSpawner : Item
|
||||
{
|
||||
private StealableArtifactsSpawner()
|
||||
{
|
||||
}
|
||||
|
||||
public StealableArtifactsSpawner(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
StealableArtifacts.Deserialize(reader);
|
||||
|
||||
Timer.DelayCall(Delete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using Server.Engines.Stealables;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
|
@ -234,7 +235,7 @@ namespace Server.Items
|
|||
|| IsInTypeList(t, DemonKnight.ArtifactRarity10)
|
||||
|| IsInTypeList(t, DemonKnight.ArtifactRarity11)
|
||||
|| IsInTypeList(t, MondainsLegacy.Artifacts)
|
||||
|| IsInTypeList(t, StealableArtifactsSpawner.TypesOfEntires)
|
||||
|| IsInTypeList(t, StealableArtifacts.TypesOfEntries)
|
||||
|| IsInTypeList(t, Paragon.Artifacts)
|
||||
|| IsInTypeList(t, Leviathan.Artifacts)
|
||||
|| IsInTypeList(t, TreasureMapChest.Artifacts)
|
||||
|
|
|
|||
|
|
@ -1,431 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Logging;
|
||||
using Server.Utilities;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class StealableArtifactsSpawner : Item
|
||||
{
|
||||
private static readonly ILogger logger = LogFactory.GetLogger(typeof(StealableArtifactsSpawner));
|
||||
|
||||
private static Type[] m_TypesOfEntries;
|
||||
private StealableInstance[] m_Artifacts;
|
||||
|
||||
private Timer _respawnTimer;
|
||||
private Dictionary<Item, StealableInstance> m_Table;
|
||||
|
||||
private StealableArtifactsSpawner() : base(1)
|
||||
{
|
||||
Movable = false;
|
||||
|
||||
m_Artifacts = new StealableInstance[Entries.Length];
|
||||
m_Table = new Dictionary<Item, StealableInstance>(Entries.Length);
|
||||
|
||||
for (var i = 0; i < Entries.Length; i++)
|
||||
{
|
||||
m_Artifacts[i] = new StealableInstance(Entries[i]);
|
||||
}
|
||||
|
||||
_respawnTimer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromMinutes(15.0), CheckRespawn);
|
||||
}
|
||||
|
||||
public StealableArtifactsSpawner(Serial serial) : base(serial) => Instance = this;
|
||||
|
||||
public static StealableEntry[] Entries { get; } =
|
||||
{
|
||||
// Doom - Artifact rarity 1
|
||||
new(Map.Malas, new Point3D(317, 56, -1), 72, 108, typeof(RockArtifact)),
|
||||
new(Map.Malas, new Point3D(360, 31, 8), 72, 108, typeof(SkullCandleArtifact)),
|
||||
new(Map.Malas, new Point3D(369, 372, -1), 72, 108, typeof(BottleArtifact)),
|
||||
new(Map.Malas, new Point3D(378, 372, 0), 72, 108, typeof(DamagedBooksArtifact)),
|
||||
// Doom - Artifact rarity 2
|
||||
new(Map.Malas, new Point3D(432, 16, -1), 144, 216, typeof(StretchedHideArtifact)),
|
||||
new(Map.Malas, new Point3D(489, 9, 0), 144, 216, typeof(BrazierArtifact)),
|
||||
// Doom - Artifact rarity 3
|
||||
new(Map.Malas, new Point3D(471, 96, -1), 288, 432, typeof(LampPostArtifact), GetLampPostHue()),
|
||||
new(Map.Malas, new Point3D(421, 198, 2), 288, 432, typeof(BooksNorthArtifact)),
|
||||
new(Map.Malas, new Point3D(431, 189, -1), 288, 432, typeof(BooksWestArtifact)),
|
||||
new(Map.Malas, new Point3D(435, 196, -1), 288, 432, typeof(BooksFaceDownArtifact)),
|
||||
// Doom - Artifact rarity 5
|
||||
new(Map.Malas, new Point3D(447, 9, 8), 1152, 1728, typeof(StuddedLeggingsArtifact)),
|
||||
new(Map.Malas, new Point3D(423, 28, 0), 1152, 1728, typeof(EggCaseArtifact)),
|
||||
new(Map.Malas, new Point3D(347, 44, 4), 1152, 1728, typeof(SkinnedGoatArtifact)),
|
||||
new(Map.Malas, new Point3D(497, 57, -1), 1152, 1728, typeof(GruesomeStandardArtifact)),
|
||||
new(Map.Malas, new Point3D(381, 375, 11), 1152, 1728, typeof(BloodyWaterArtifact)),
|
||||
new(Map.Malas, new Point3D(489, 369, 2), 1152, 1728, typeof(TarotCardsArtifact)),
|
||||
new(Map.Malas, new Point3D(497, 369, 5), 1152, 1728, typeof(BackpackArtifact)),
|
||||
// Doom - Artifact rarity 7
|
||||
new(Map.Malas, new Point3D(475, 23, 4), 4608, 6912, typeof(StuddedTunicArtifact)),
|
||||
new(Map.Malas, new Point3D(423, 28, 0), 4608, 6912, typeof(CocoonArtifact)),
|
||||
// Doom - Artifact rarity 8
|
||||
new(Map.Malas, new Point3D(354, 36, -1), 9216, 13824, typeof(SkinnedDeerArtifact)),
|
||||
// Doom - Artifact rarity 9
|
||||
new(Map.Malas, new Point3D(433, 11, -1), 18432, 27648, typeof(SaddleArtifact)),
|
||||
new(Map.Malas, new Point3D(403, 31, 4), 18432, 27648, typeof(LeatherTunicArtifact)),
|
||||
// Doom - Artifact rarity 10
|
||||
new(Map.Malas, new Point3D(257, 70, -2), 36864, 55296, typeof(ZyronicClaw)),
|
||||
new(Map.Malas, new Point3D(354, 176, 7), 36864, 55296, typeof(TitansHammer)),
|
||||
new(Map.Malas, new Point3D(369, 389, -1), 36864, 55296, typeof(BladeOfTheRighteous)),
|
||||
new(Map.Malas, new Point3D(467, 92, 4), 36864, 55296, typeof(InquisitorsResolution)),
|
||||
// Doom - Artifact rarity 12
|
||||
new(Map.Malas, new Point3D(487, 364, -1), 147456, 221184, typeof(RuinedPaintingArtifact)),
|
||||
|
||||
// Yomotsu Mines - Artifact rarity 1
|
||||
new(Map.Malas, new Point3D(18, 110, -1), 72, 108, typeof(Basket1Artifact)),
|
||||
new(Map.Malas, new Point3D(66, 114, -1), 72, 108, typeof(Basket2Artifact)),
|
||||
// Yomotsu Mines - Artifact rarity 2
|
||||
new(Map.Malas, new Point3D(63, 12, 11), 144, 216, typeof(Basket4Artifact)),
|
||||
new(Map.Malas, new Point3D(5, 29, -1), 144, 216, typeof(Basket5NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(30, 81, 3), 144, 216, typeof(Basket5WestArtifact)),
|
||||
// Yomotsu Mines - Artifact rarity 3
|
||||
new(Map.Malas, new Point3D(115, 7, -1), 288, 432, typeof(Urn1Artifact)),
|
||||
new(Map.Malas, new Point3D(85, 13, -1), 288, 432, typeof(Urn2Artifact)),
|
||||
new(Map.Malas, new Point3D(110, 53, -1), 288, 432, typeof(Sculpture1Artifact)),
|
||||
new(Map.Malas, new Point3D(108, 37, -1), 288, 432, typeof(Sculpture2Artifact)),
|
||||
new(Map.Malas, new Point3D(121, 14, -1), 288, 432, typeof(TeapotNorthArtifact)),
|
||||
new(Map.Malas, new Point3D(121, 115, -1), 288, 432, typeof(TeapotWestArtifact)),
|
||||
new(Map.Malas, new Point3D(84, 40, -1), 288, 432, typeof(TowerLanternArtifact)),
|
||||
// Yomotsu Mines - Artifact rarity 9
|
||||
new(Map.Malas, new Point3D(94, 7, -1), 18432, 27648, typeof(ManStatuetteSouthArtifact)),
|
||||
|
||||
// Fan Dancer's Dojo - Artifact rarity 1
|
||||
new(Map.Malas, new Point3D(113, 640, -2), 72, 108, typeof(Basket3NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(102, 355, -1), 72, 108, typeof(Basket3WestArtifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 2
|
||||
new(Map.Malas, new Point3D(99, 370, -1), 144, 216, typeof(Basket6Artifact)),
|
||||
new(Map.Malas, new Point3D(100, 357, -1), 144, 216, typeof(ZenRock1Artifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 3
|
||||
new(Map.Malas, new Point3D(73, 473, -1), 288, 432, typeof(FanNorthArtifact)),
|
||||
new(Map.Malas, new Point3D(99, 372, -1), 288, 432, typeof(FanWestArtifact)),
|
||||
new(Map.Malas, new Point3D(92, 326, -1), 288, 432, typeof(BowlsVerticalArtifact)),
|
||||
new(Map.Malas, new Point3D(97, 470, -1), 288, 432, typeof(ZenRock2Artifact)),
|
||||
new(Map.Malas, new Point3D(103, 691, -1), 288, 432, typeof(ZenRock3Artifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 4
|
||||
new(Map.Malas, new Point3D(103, 336, 4), 576, 864, typeof(Painting1NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(59, 381, 4), 576, 864, typeof(Painting1WestArtifact)),
|
||||
new(Map.Malas, new Point3D(84, 401, 2), 576, 864, typeof(Painting2NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(59, 392, 2), 576, 864, typeof(Painting2WestArtifact)),
|
||||
new(Map.Malas, new Point3D(107, 483, -1), 576, 864, typeof(TripleFanNorthArtifact)),
|
||||
new(Map.Malas, new Point3D(50, 475, -1), 576, 864, typeof(TripleFanWestArtifact)),
|
||||
new(Map.Malas, new Point3D(107, 460, -1), 576, 864, typeof(BowlArtifact)),
|
||||
new(Map.Malas, new Point3D(90, 502, -1), 576, 864, typeof(CupsArtifact)),
|
||||
new(Map.Malas, new Point3D(107, 688, -1), 576, 864, typeof(BowlsHorizontalArtifact)),
|
||||
new(Map.Malas, new Point3D(112, 676, -1), 576, 864, typeof(SakeArtifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 5
|
||||
new(Map.Malas, new Point3D(135, 614, -1), 1152, 1728, typeof(SwordDisplay1NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(50, 482, -1), 1152, 1728, typeof(SwordDisplay1WestArtifact)),
|
||||
new(Map.Malas, new Point3D(119, 672, -1), 1152, 1728, typeof(Painting3Artifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 6
|
||||
new(Map.Malas, new Point3D(90, 326, -1), 2304, 3456, typeof(Painting4NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(99, 354, -1), 2304, 3456, typeof(Painting4WestArtifact)),
|
||||
new(Map.Malas, new Point3D(179, 652, -1), 2304, 3456, typeof(SwordDisplay2NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(118, 627, -1), 2304, 3456, typeof(SwordDisplay2WestArtifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 7
|
||||
new(Map.Malas, new Point3D(90, 483, -1), 4608, 6912, typeof(FlowersArtifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 8
|
||||
new(Map.Malas, new Point3D(71, 562, -1), 9216, 13824, typeof(DolphinLeftArtifact)),
|
||||
new(Map.Malas, new Point3D(102, 677, -1), 9216, 13824, typeof(DolphinRightArtifact)),
|
||||
new(Map.Malas, new Point3D(61, 499, 0), 9216, 13824, typeof(SwordDisplay3SouthArtifact)),
|
||||
new(Map.Malas, new Point3D(182, 669, -1), 9216, 13824, typeof(SwordDisplay3EastArtifact)),
|
||||
new(Map.Malas, new Point3D(162, 647, -1), 9216, 13824, typeof(SwordDisplay4WestArtifact)),
|
||||
new(Map.Malas, new Point3D(124, 624, 0), 9216, 13824, typeof(Painting5NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(146, 649, 2), 9216, 13824, typeof(Painting5WestArtifact)),
|
||||
// Fan Dancer's Dojo - Artifact rarity 9
|
||||
new(Map.Malas, new Point3D(100, 488, -1), 18432, 27648, typeof(SwordDisplay4NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(175, 606, 0), 18432, 27648, typeof(SwordDisplay5NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(157, 608, -1), 18432, 27648, typeof(SwordDisplay5WestArtifact)),
|
||||
new(Map.Malas, new Point3D(187, 643, 1), 18432, 27648, typeof(Painting6NorthArtifact)),
|
||||
new(Map.Malas, new Point3D(146, 623, 1), 18432, 27648, typeof(Painting6WestArtifact)),
|
||||
new(Map.Malas, new Point3D(178, 629, -1), 18432, 27648, typeof(ManStatuetteEastArtifact))
|
||||
};
|
||||
|
||||
public static Type[] TypesOfEntires
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_TypesOfEntries == null)
|
||||
{
|
||||
m_TypesOfEntries = new Type[Entries.Length];
|
||||
|
||||
for (var i = 0; i < Entries.Length; i++)
|
||||
{
|
||||
m_TypesOfEntries[i] = Entries[i].Type;
|
||||
}
|
||||
}
|
||||
|
||||
return m_TypesOfEntries;
|
||||
}
|
||||
}
|
||||
|
||||
public static StealableArtifactsSpawner Instance { get; private set; }
|
||||
|
||||
public override string DefaultName => "Stealable Artifacts Spawner - Internal";
|
||||
|
||||
private static int GetLampPostHue()
|
||||
{
|
||||
if (Utility.RandomDouble() < 0.9)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Utility.RandomList(0x455, 0x47E, 0x482, 0x486, 0x48F, 0x4F2, 0x58C, 0x66C);
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register("GenStealArties", AccessLevel.Administrator, GenStealArties_OnCommand);
|
||||
CommandSystem.Register("RemoveStealArties", AccessLevel.Administrator, RemoveStealArties_OnCommand);
|
||||
}
|
||||
|
||||
[Usage("GenStealArties"), Description("Generates the stealable artifacts spawner.")]
|
||||
private static void GenStealArties_OnCommand(CommandEventArgs args)
|
||||
{
|
||||
var from = args.Mobile;
|
||||
|
||||
if (Create())
|
||||
{
|
||||
from.SendMessage("Stealable artifacts spawner generated.");
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage("Stealable artifacts spawner already present.");
|
||||
}
|
||||
}
|
||||
|
||||
[Usage("RemoveStealArties"),
|
||||
Description("Removes the stealable artifacts spawner and every not yet stolen stealable artifacts.")]
|
||||
private static void RemoveStealArties_OnCommand(CommandEventArgs args)
|
||||
{
|
||||
var from = args.Mobile;
|
||||
|
||||
if (Remove())
|
||||
{
|
||||
from.SendMessage("Stealable artifacts spawner removed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage("Stealable artifacts spawner not present.");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Create()
|
||||
{
|
||||
if (Instance?.Deleted == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Instance = new StealableArtifactsSpawner();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool Remove()
|
||||
{
|
||||
if (Instance == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Instance.Delete();
|
||||
Instance = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static StealableInstance GetStealableInstance(Item item)
|
||||
{
|
||||
if (Instance == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Instance.m_Table.TryGetValue(item, out var value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public override void OnDelete()
|
||||
{
|
||||
base.OnDelete();
|
||||
|
||||
_respawnTimer.Stop();
|
||||
_respawnTimer = null;
|
||||
|
||||
foreach (var si in m_Artifacts)
|
||||
{
|
||||
si.Item?.Delete();
|
||||
}
|
||||
|
||||
Instance = null;
|
||||
}
|
||||
|
||||
public void CheckRespawn()
|
||||
{
|
||||
foreach (var si in m_Artifacts)
|
||||
{
|
||||
si.CheckRespawn();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); // version
|
||||
|
||||
writer.WriteEncodedInt(m_Artifacts.Length);
|
||||
|
||||
for (var i = 0; i < m_Artifacts.Length; i++)
|
||||
{
|
||||
var si = m_Artifacts[i];
|
||||
|
||||
writer.Write(si.Item);
|
||||
writer.WriteDeltaTime(si.NextRespawn);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadEncodedInt();
|
||||
|
||||
m_Artifacts = new StealableInstance[Entries.Length];
|
||||
m_Table = new Dictionary<Item, StealableInstance>(Entries.Length);
|
||||
|
||||
var length = reader.ReadEncodedInt();
|
||||
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
var item = reader.ReadEntity<Item>();
|
||||
var nextRespawn = reader.ReadDeltaTime();
|
||||
|
||||
if (i < m_Artifacts.Length)
|
||||
{
|
||||
var si = new StealableInstance(Entries[i], item, nextRespawn);
|
||||
m_Artifacts[i] = si;
|
||||
|
||||
if (si.Item != null)
|
||||
{
|
||||
m_Table[si.Item] = si;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = length; i < Entries.Length; i++)
|
||||
{
|
||||
m_Artifacts[i] = new StealableInstance(Entries[i]);
|
||||
}
|
||||
|
||||
_respawnTimer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromMinutes(15.0), CheckRespawn);
|
||||
}
|
||||
|
||||
public class StealableEntry
|
||||
{
|
||||
public StealableEntry(Map map, Point3D location, int minDelay, int maxDelay, Type type, int hue = 0)
|
||||
{
|
||||
Map = map;
|
||||
Location = location;
|
||||
MinDelay = minDelay;
|
||||
MaxDelay = maxDelay;
|
||||
Type = type;
|
||||
Hue = hue;
|
||||
}
|
||||
|
||||
public Map Map { get; }
|
||||
|
||||
public Point3D Location { get; }
|
||||
|
||||
public int MinDelay { get; }
|
||||
|
||||
public int MaxDelay { get; }
|
||||
|
||||
public Type Type { get; }
|
||||
|
||||
public int Hue { get; }
|
||||
|
||||
public Item CreateInstance()
|
||||
{
|
||||
try
|
||||
{
|
||||
var item = Type.CreateInstance<Item>();
|
||||
|
||||
if (Hue > 0)
|
||||
{
|
||||
item.Hue = Hue;
|
||||
}
|
||||
|
||||
item.Movable = false;
|
||||
item.MoveToWorld(Location, Map);
|
||||
|
||||
return item;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Warning(e, $"Failed to construct stealable artifact: {Type.FullName}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class StealableInstance
|
||||
{
|
||||
private Item m_Item;
|
||||
|
||||
public StealableInstance(StealableEntry entry) : this(entry, null, Core.Now)
|
||||
{
|
||||
}
|
||||
|
||||
public StealableInstance(StealableEntry entry, Item item, DateTime nextRespawn)
|
||||
{
|
||||
m_Item = item;
|
||||
NextRespawn = nextRespawn;
|
||||
Entry = entry;
|
||||
}
|
||||
|
||||
public StealableEntry Entry { get; }
|
||||
|
||||
public Item Item
|
||||
{
|
||||
get => m_Item;
|
||||
set
|
||||
{
|
||||
if (m_Item != null && value == null)
|
||||
{
|
||||
var delay = Utility.RandomMinMax(Entry.MinDelay, Entry.MaxDelay);
|
||||
NextRespawn = Core.Now + TimeSpan.FromMinutes(delay);
|
||||
}
|
||||
|
||||
if (Instance != null)
|
||||
{
|
||||
if (m_Item != null)
|
||||
{
|
||||
Instance.m_Table.Remove(m_Item);
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
Instance.m_Table[value] = this;
|
||||
}
|
||||
}
|
||||
|
||||
m_Item = value;
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime NextRespawn { get; set; }
|
||||
|
||||
public void CheckRespawn()
|
||||
{
|
||||
if (Item != null && (Item.Deleted || Item.Movable || Item.Parent != null))
|
||||
{
|
||||
Item = null;
|
||||
}
|
||||
|
||||
if (Item == null && Core.Now >= NextRespawn)
|
||||
{
|
||||
Item = Entry.CreateInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Engines.ConPVP;
|
||||
using Server.Engines.Stealables;
|
||||
using Server.Factions;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
|
@ -79,11 +80,9 @@ namespace Server.SkillHandlers
|
|||
var root = toSteal.RootParent;
|
||||
var mobRoot = root as Mobile;
|
||||
|
||||
StealableArtifactsSpawner.StealableInstance si = null;
|
||||
if (toSteal.Parent == null || !toSteal.Movable)
|
||||
{
|
||||
si = StealableArtifactsSpawner.GetStealableInstance(toSteal);
|
||||
}
|
||||
StealableArtifacts.StealableInstance si = toSteal.Parent == null || !toSteal.Movable
|
||||
? StealableArtifacts.GetStealableInstance(toSteal)
|
||||
: null;
|
||||
|
||||
if (!IsEmptyHanded(m_Thief))
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue