Convert Regions/Spawns to JSON (#138)
This commit is contained in:
parent
b8316e9202
commit
390f30e706
117 changed files with 97306 additions and 4848 deletions
|
|
@ -1148,7 +1148,7 @@ namespace Server.Engines.ConPVP
|
|||
if (!pm.CheckAlive())
|
||||
{
|
||||
}
|
||||
else if (pm.Region.IsPartOf<Jail>())
|
||||
else if (pm.Region.IsPartOf<JailRegion>())
|
||||
{
|
||||
}
|
||||
else if (CheckCombat(pm))
|
||||
|
|
@ -1942,7 +1942,7 @@ namespace Server.Engines.ConPVP
|
|||
if (dp == null)
|
||||
return "a slot is empty";
|
||||
|
||||
if (dp.Mobile.Region.IsPartOf<Jail>())
|
||||
if (dp.Mobile.Region.IsPartOf<JailRegion>())
|
||||
return $"{dp.Mobile.Name} is in jail";
|
||||
|
||||
if (Sigil.ExistsOn(dp.Mobile))
|
||||
|
|
|
|||
|
|
@ -595,7 +595,7 @@ namespace Server.Engines.ConPVP
|
|||
Mobile check = part.Players[j];
|
||||
|
||||
if (check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive ||
|
||||
Sigil.ExistsOn(check) || check.Region.IsPartOf<Jail>())
|
||||
Sigil.ExistsOn(check) || check.Region.IsPartOf<JailRegion>())
|
||||
{
|
||||
bad = true;
|
||||
break;
|
||||
|
|
@ -776,7 +776,7 @@ namespace Server.Engines.ConPVP
|
|||
Mobile check = part.Players[j];
|
||||
|
||||
if (check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive ||
|
||||
Sigil.ExistsOn(check) || check.Region.IsPartOf<Jail>())
|
||||
Sigil.ExistsOn(check) || check.Region.IsPartOf<JailRegion>())
|
||||
{
|
||||
bad = true;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ namespace Server.Engines.Help
|
|||
{
|
||||
from.Location = house.BanLocation;
|
||||
}
|
||||
else if (from.Region.IsPartOf<Jail>())
|
||||
else if (from.Region.IsPartOf<JailRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(1114345, "", 0x35); // You'll need a better jailbreak plan than that!
|
||||
}
|
||||
|
|
@ -313,7 +313,7 @@ namespace Server.Engines.Help
|
|||
{
|
||||
if (IsYoung(from))
|
||||
{
|
||||
if (from.Region.IsPartOf<Jail>())
|
||||
if (from.Region.IsPartOf<JailRegion>())
|
||||
from.SendLocalizedMessage(1114345, "", 0x35); // You'll need a better jailbreak plan than that!
|
||||
else if (from.Region.IsPartOf("Haven Island"))
|
||||
from.SendLocalizedMessage(1041529); // You're already in Haven
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Configurations;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
@ -275,4 +276,4 @@ namespace Server.Engines.MLQuests.Definitions
|
|||
reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
@ -82,4 +83,4 @@ namespace Server.Engines.MLQuests.Definitions
|
|||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using Server.Engines.MLQuests.Items;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
@ -2518,4 +2519,4 @@ namespace Server.Engines.MLQuests.Definitions
|
|||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using Server.Engines.MLQuests.Gumps;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Engines.Spawners;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ namespace Server.Engines.Quests
|
|||
|
||||
public override void UseGate(Mobile m)
|
||||
{
|
||||
if (m.Region.IsPartOf<Jail>())
|
||||
if (m.Region.IsPartOf<JailRegion>())
|
||||
{
|
||||
m.SendLocalizedMessage(1114345); // You'll need a better jailbreak plan than that!
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
using System;
|
||||
using System.Xml;
|
||||
using Server.Mobiles;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server.Engines.Quests
|
||||
{
|
||||
public class CancelQuestRegion : BaseRegion
|
||||
{
|
||||
private readonly Type m_Quest;
|
||||
|
||||
public CancelQuestRegion(XmlElement xml, Map map, Region parent) : base(xml, map, parent)
|
||||
{
|
||||
ReadType(xml["quest"], "type", ref m_Quest);
|
||||
}
|
||||
|
||||
public Type Quest => m_Quest;
|
||||
|
||||
public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation)
|
||||
{
|
||||
if (!base.OnMoveInto(m, d, newLocation, oldLocation))
|
||||
return false;
|
||||
|
||||
if (m.AccessLevel > AccessLevel.Player)
|
||||
return true;
|
||||
|
||||
if (m_Quest == null)
|
||||
return true;
|
||||
|
||||
if (m is PlayerMobile player && player.Quest != null && player.Quest.GetType() == m_Quest)
|
||||
{
|
||||
if (!player.HasGump<QuestCancelGump>())
|
||||
player.Quest.BeginCancelQuest();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
using System;
|
||||
using System.Xml;
|
||||
using Server.Mobiles;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server.Engines.Quests
|
||||
{
|
||||
public class QuestCompleteObjectiveRegion : BaseRegion
|
||||
{
|
||||
private readonly Type m_Objective;
|
||||
private readonly Type m_Quest;
|
||||
|
||||
public QuestCompleteObjectiveRegion(XmlElement xml, Map map, Region parent) : base(xml, map, parent)
|
||||
{
|
||||
XmlElement questEl = xml["quest"];
|
||||
|
||||
ReadType(questEl, "type", ref m_Quest);
|
||||
ReadType(questEl, "complete", ref m_Objective);
|
||||
}
|
||||
|
||||
public Type Quest => m_Quest;
|
||||
public Type Objective => m_Objective;
|
||||
|
||||
public override void OnEnter(Mobile m)
|
||||
{
|
||||
base.OnEnter(m);
|
||||
|
||||
if (m_Quest != null && m_Objective != null)
|
||||
if (m is PlayerMobile player && player.Quest != null && player.Quest.GetType() == m_Quest)
|
||||
{
|
||||
QuestObjective obj = player.Quest.FindObjective(m_Objective);
|
||||
|
||||
if (obj?.Completed == false)
|
||||
obj.Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
using System;
|
||||
using System.Xml;
|
||||
using Server.Mobiles;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server.Engines.Quests
|
||||
{
|
||||
public class QuestNoEntryRegion : BaseRegion
|
||||
{
|
||||
private readonly Type m_MaxObjective;
|
||||
private readonly int m_Message;
|
||||
private readonly Type m_MinObjective;
|
||||
private readonly Type m_Quest;
|
||||
|
||||
public QuestNoEntryRegion(XmlElement xml, Map map, Region parent) : base(xml, map, parent)
|
||||
{
|
||||
XmlElement questEl = xml["quest"];
|
||||
|
||||
ReadType(questEl, "type", ref m_Quest);
|
||||
ReadType(questEl, "min", ref m_MinObjective, false);
|
||||
ReadType(questEl, "max", ref m_MaxObjective, false);
|
||||
ReadInt32(questEl, "message", ref m_Message, false);
|
||||
}
|
||||
|
||||
public Type Quest => m_Quest;
|
||||
public Type MinObjective => m_MinObjective;
|
||||
public Type MaxObjective => m_MaxObjective;
|
||||
public int Message => m_Message;
|
||||
|
||||
public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation)
|
||||
{
|
||||
if (!base.OnMoveInto(m, d, newLocation, oldLocation))
|
||||
return false;
|
||||
|
||||
if (m.AccessLevel > AccessLevel.Player)
|
||||
return true;
|
||||
|
||||
if (m is BaseCreature bc && !bc.Controlled && !bc.Summoned)
|
||||
return true;
|
||||
|
||||
if (m_Quest == null)
|
||||
return true;
|
||||
|
||||
if (m is PlayerMobile player && player.Quest != null && player.Quest.GetType() == m_Quest
|
||||
&& (m_MinObjective == null || player.Quest.FindObjective(m_MinObjective) != null)
|
||||
&& (m_MaxObjective == null || player.Quest.FindObjective(m_MaxObjective) == null))
|
||||
return true;
|
||||
|
||||
if (m_Message != 0)
|
||||
m.SendLocalizedMessage(m_Message);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
using System;
|
||||
using System.Xml;
|
||||
using Server.Mobiles;
|
||||
using Server.Regions;
|
||||
using Server.Utilities;
|
||||
|
||||
namespace Server.Engines.Quests
|
||||
{
|
||||
public class QuestOfferRegion : BaseRegion
|
||||
{
|
||||
private readonly Type m_Quest;
|
||||
|
||||
public QuestOfferRegion(XmlElement xml, Map map, Region parent) : base(xml, map, parent)
|
||||
{
|
||||
ReadType(xml["quest"], "type", ref m_Quest);
|
||||
}
|
||||
|
||||
public Type Quest => m_Quest;
|
||||
|
||||
public override void OnEnter(Mobile m)
|
||||
{
|
||||
base.OnEnter(m);
|
||||
|
||||
if (m_Quest == null)
|
||||
return;
|
||||
|
||||
if (m is PlayerMobile player && player.Quest == null && QuestSystem.CanOfferQuest(m, m_Quest))
|
||||
try
|
||||
{
|
||||
QuestSystem qs = (QuestSystem)ActivatorUtil.CreateInstance(m_Quest, player);
|
||||
qs.SendOffer();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error creating quest {0}: {1}", m_Quest, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class SpawnerType
|
||||
{
|
||||
public static Type GetType(string name) => AssemblyHandler.FindFirstTypeForName(name);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +1,47 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using Server.Commands;
|
||||
using Server.Items;
|
||||
using Server.Json;
|
||||
using Server.Mobiles;
|
||||
using Server.Utilities;
|
||||
using CPA = Server.CommandPropertyAttribute;
|
||||
|
||||
namespace Server.Mobiles
|
||||
namespace Server.Engines.Spawners
|
||||
{
|
||||
public class Spawner : Item, ISpawner
|
||||
public abstract class BaseSpawner : Item, ISpawner
|
||||
{
|
||||
private static WarnTimer m_WarnTimer;
|
||||
private int m_Count;
|
||||
private bool m_Group;
|
||||
private int m_HomeRange;
|
||||
private int m_Team;
|
||||
private TimeSpan m_MaxDelay;
|
||||
private TimeSpan m_MinDelay;
|
||||
private bool m_Running;
|
||||
private int m_Team;
|
||||
|
||||
private InternalTimer m_Timer;
|
||||
private int m_WalkingRange = -1;
|
||||
|
||||
// [Constructible]
|
||||
public Spawner(int amount, int minDelay, int maxDelay, int team, int homeRange, string spawnedNames) : base(0x1f13)
|
||||
public BaseSpawner() : this(1, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(10), 0, 4)
|
||||
{
|
||||
InitSpawn(amount, TimeSpan.FromMinutes(minDelay), TimeSpan.FromMinutes(maxDelay), team, homeRange);
|
||||
AddEntry(spawnedNames, 100, amount, false);
|
||||
}
|
||||
|
||||
// [Constructible]
|
||||
public Spawner(string spawnedName) : base(0x1f13)
|
||||
public BaseSpawner(string spawnedName) : this(1, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(10), 0, 4, spawnedName)
|
||||
{
|
||||
InitSpawn(1, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(10), 0, 4);
|
||||
AddEntry(spawnedName, 100, 1, false);
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public Spawner() : base(0x1f13)
|
||||
public BaseSpawner(int amount, int minDelay, int maxDelay, int team, int homeRange,
|
||||
params string[] spawnedNames) : this(amount, TimeSpan.FromMinutes(minDelay), TimeSpan.FromMinutes(maxDelay),
|
||||
team, homeRange, spawnedNames)
|
||||
{
|
||||
InitSpawn(1, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(10), 0, 4);
|
||||
}
|
||||
|
||||
public Spawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange,
|
||||
public BaseSpawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange,
|
||||
params string[] spawnedNames) : base(0x1f13)
|
||||
{
|
||||
InitSpawn(amount, minDelay, maxDelay, team, homeRange);
|
||||
|
|
@ -51,7 +49,25 @@ namespace Server.Mobiles
|
|||
AddEntry(spawnedNames[i], 100, amount, false);
|
||||
}
|
||||
|
||||
public Spawner(Serial serial) : base(serial)
|
||||
public BaseSpawner(DynamicJson json, JsonSerializerOptions options) : base(0x1f13)
|
||||
{
|
||||
json.GetProperty("count", options, out int amount);
|
||||
json.GetProperty("minDelay", options, out TimeSpan minDelay);
|
||||
json.GetProperty("maxDelay", options, out TimeSpan maxDelay);
|
||||
json.GetProperty("team", options, out int team);
|
||||
json.GetProperty("homeRange", options, out int homeRange);
|
||||
json.GetProperty("walkingRange", options, out int walkingRange);
|
||||
m_WalkingRange = walkingRange;
|
||||
|
||||
InitSpawn(amount, minDelay, maxDelay, team, homeRange);
|
||||
|
||||
json.GetProperty("entries", options, out List<SpawnerEntry> entries);
|
||||
|
||||
foreach (var entry in entries)
|
||||
AddEntry(entry.SpawnedName, entry.SpawnedProbability, entry.SpawnedMaxCount, false);
|
||||
}
|
||||
|
||||
public BaseSpawner(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -64,6 +80,9 @@ namespace Server.Mobiles
|
|||
|
||||
public Dictionary<ISpawnable, SpawnerEntry> Spawned { get; private set; }
|
||||
|
||||
[CommandProperty(AccessLevel.Developer)]
|
||||
public bool ReturnOnDeactivate { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.Developer)]
|
||||
public int Count
|
||||
{
|
||||
|
|
@ -72,9 +91,8 @@ namespace Server.Mobiles
|
|||
{
|
||||
m_Count = value;
|
||||
|
||||
if (m_Timer != null)
|
||||
if ((!IsFull && !m_Timer.Running) || (IsFull && m_Timer.Running))
|
||||
DoTimer();
|
||||
if (m_Timer != null && (!IsFull && !m_Timer.Running || IsFull && m_Timer.Running))
|
||||
DoTimer();
|
||||
|
||||
InvalidateProperties();
|
||||
}
|
||||
|
|
@ -164,7 +182,7 @@ namespace Server.Mobiles
|
|||
}
|
||||
}
|
||||
|
||||
public Point3D HomeLocation => Location;
|
||||
public virtual Point3D HomeLocation => Location;
|
||||
public bool UnlinkOnTaming => true;
|
||||
|
||||
[CommandProperty(AccessLevel.Developer)]
|
||||
|
|
@ -199,7 +217,7 @@ namespace Server.Mobiles
|
|||
|
||||
public override void OnAfterDuped(Item newItem)
|
||||
{
|
||||
if (newItem is Spawner newSpawner)
|
||||
if (newItem is BaseSpawner newSpawner)
|
||||
for (int i = 0; i < Entries.Count; i++)
|
||||
newSpawner.AddEntry(Entries[i].SpawnedName, Entries[i].SpawnedProbability, Entries[i].SpawnedMaxCount,
|
||||
false);
|
||||
|
|
@ -238,6 +256,10 @@ namespace Server.Mobiles
|
|||
from.SendGump(new SpawnerGump(this));
|
||||
}
|
||||
|
||||
public virtual void GetSpawnerProperties(ObjectPropertyList list)
|
||||
{
|
||||
}
|
||||
|
||||
public override void GetProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.GetProperties(list);
|
||||
|
|
@ -248,14 +270,16 @@ namespace Server.Mobiles
|
|||
|
||||
list.Add(1060656, m_Count.ToString()); // amount to make: ~1_val~
|
||||
list.Add(1061169, m_HomeRange.ToString()); // range ~1_val~
|
||||
list.Add(1060658, "walking range\t{0}", m_WalkingRange); // ~1_val~: ~2_val~
|
||||
list.Add(1050039, "walking range:\t{0}", m_WalkingRange); // ~1_NUMBER~ ~2_ITEMNAME~
|
||||
|
||||
list.Add(1060658, "group\t{0}", m_Group); // ~1_val~: ~2_val~
|
||||
list.Add(1060659, "team\t{0}", m_Team); // ~1_val~: ~2_val~
|
||||
list.Add(1060660, "speed\t{0} to {1}", m_MinDelay, m_MaxDelay); // ~1_val~: ~2_val~
|
||||
list.Add(1053099, "group:\t{0}", m_Group); // ~1_oretype~: ~2_armortype~
|
||||
list.Add(1060847, "team:\t{0}", m_Team); // ~1_val~ ~2_val~
|
||||
list.Add(1063483, "delay:\t{0} to {1}", m_MinDelay, m_MaxDelay); // ~1_MATERIAL~: ~2_ITEMNAME~
|
||||
|
||||
for (int i = 0; i < 3 && i < Entries.Count; ++i)
|
||||
list.Add(1060661 + i, "{0}\t{1}", Entries[i].SpawnedName, CountSpawns(Entries[i]));
|
||||
GetSpawnerProperties(list);
|
||||
|
||||
for (int i = 0; i < 6 && i < Entries.Count; ++i)
|
||||
list.Add(1060658 + i, "\t{0}\t{1}", Entries[i].SpawnedName, CountSpawns(Entries[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -300,6 +324,22 @@ namespace Server.Mobiles
|
|||
Entries[i].Defrag(this);
|
||||
}
|
||||
|
||||
public virtual bool OnDefragSpawn(ISpawnable spawned, bool remove)
|
||||
{
|
||||
if (!remove) // Override could have set it to true already
|
||||
remove = spawned.Deleted || spawned.Spawner == null || spawned switch
|
||||
{
|
||||
Item item => item.RootParent is Mobile || item.IsLockedDown || item.IsSecure,
|
||||
Mobile m => m is BaseCreature c && (c.Controlled || c.IsStabled),
|
||||
_ => true
|
||||
};
|
||||
|
||||
if (remove)
|
||||
Spawned.Remove(spawned);
|
||||
|
||||
return remove;
|
||||
}
|
||||
|
||||
public void OnTick()
|
||||
{
|
||||
if (m_Group)
|
||||
|
|
@ -336,11 +376,7 @@ namespace Server.Mobiles
|
|||
if (Entries.Count <= 0 || IsFull)
|
||||
return;
|
||||
|
||||
int probsum = 0;
|
||||
|
||||
for (int i = 0; i < Entries.Count; i++)
|
||||
if (!Entries[i].IsFull)
|
||||
probsum += Entries[i].SpawnedProbability;
|
||||
int probsum = Entries.Where(t => !t.IsFull).Sum(t => t.SpawnedProbability);
|
||||
|
||||
if (probsum <= 0)
|
||||
return;
|
||||
|
|
@ -443,7 +479,7 @@ namespace Server.Mobiles
|
|||
// Defrag taken care of in Spawn(), beforehand
|
||||
// Count check taken care of in Spawn(), beforehand
|
||||
|
||||
Type type = SpawnerType.GetType(entry.SpawnedName);
|
||||
Type type = AssemblyHandler.FindFirstTypeForName(entry.SpawnedName);
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
|
|
@ -453,10 +489,8 @@ namespace Server.Mobiles
|
|||
string[] paramargs;
|
||||
string[] propargs;
|
||||
|
||||
if (string.IsNullOrEmpty(entry.Properties))
|
||||
propargs = Array.Empty<string>();
|
||||
else
|
||||
propargs = CommandSystem.Split(entry.Properties.Trim());
|
||||
propargs = string.IsNullOrEmpty(entry.Properties) ?
|
||||
Array.Empty<string>() : CommandSystem.Split(entry.Properties.Trim());
|
||||
|
||||
string[,] props = FormatProperties(propargs);
|
||||
|
||||
|
|
@ -468,10 +502,8 @@ namespace Server.Mobiles
|
|||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(entry.Parameters))
|
||||
paramargs = Array.Empty<string>();
|
||||
else
|
||||
paramargs = entry.Parameters.Trim().Split(' ');
|
||||
paramargs = string.IsNullOrEmpty(entry.Parameters) ?
|
||||
Array.Empty<string>() : entry.Parameters.Trim().Split(' ');
|
||||
|
||||
if (paramargs.Length == 0)
|
||||
{
|
||||
|
|
@ -504,7 +536,6 @@ namespace Server.Mobiles
|
|||
}
|
||||
|
||||
for (int i = 0; i < realProps.Length; i++)
|
||||
{
|
||||
if (realProps[i] != null)
|
||||
{
|
||||
object toSet = null;
|
||||
|
|
@ -523,7 +554,6 @@ namespace Server.Mobiles
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (o is Mobile m)
|
||||
{
|
||||
|
|
@ -591,75 +621,7 @@ namespace Server.Mobiles
|
|||
|
||||
public virtual int GetWalkingRange() => m_WalkingRange;
|
||||
|
||||
public virtual Point3D GetSpawnPosition(ISpawnable spawned, Map map)
|
||||
{
|
||||
if (map == null || map == Map.Internal)
|
||||
return Location;
|
||||
|
||||
bool waterMob, waterOnlyMob;
|
||||
|
||||
if (spawned is Mobile mob)
|
||||
{
|
||||
waterMob = mob.CanSwim;
|
||||
waterOnlyMob = mob.CanSwim && mob.CantWalk;
|
||||
}
|
||||
else
|
||||
{
|
||||
waterMob = false;
|
||||
waterOnlyMob = false;
|
||||
}
|
||||
|
||||
// Try 10 times to find a Spawnable location.
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int x = Location.X + (Utility.Random(m_HomeRange * 2 + 1) - m_HomeRange);
|
||||
int y = Location.Y + (Utility.Random(m_HomeRange * 2 + 1) - m_HomeRange);
|
||||
|
||||
int mapZ = map.GetAverageZ(x, y);
|
||||
|
||||
if (waterMob)
|
||||
{
|
||||
if (IsValidWater(map, x, y, Z))
|
||||
return new Point3D(x, y, Z);
|
||||
if (IsValidWater(map, x, y, mapZ))
|
||||
return new Point3D(x, y, mapZ);
|
||||
}
|
||||
|
||||
if (!waterOnlyMob)
|
||||
{
|
||||
if (map.CanSpawnMobile(x, y, Z))
|
||||
return new Point3D(x, y, Z);
|
||||
if (map.CanSpawnMobile(x, y, mapZ))
|
||||
return new Point3D(x, y, mapZ);
|
||||
}
|
||||
}
|
||||
|
||||
return Location;
|
||||
}
|
||||
|
||||
public static bool IsValidWater(Map map, int x, int y, int z)
|
||||
{
|
||||
if (!Region.Find(new Point3D(x, y, z), map).AllowSpawn() || !map.CanFit(x, y, z, 16, false, true, false))
|
||||
return false;
|
||||
|
||||
LandTile landTile = map.Tiles.GetLandTile(x, y);
|
||||
|
||||
if (landTile.Z == z && (TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags & TileFlag.Wet) != 0)
|
||||
return true;
|
||||
|
||||
StaticTile[] staticTiles = map.Tiles.GetStaticTiles(x, y, true);
|
||||
|
||||
for (int i = 0; i < staticTiles.Length; ++i)
|
||||
{
|
||||
StaticTile staticTile = staticTiles[i];
|
||||
|
||||
if (staticTile.Z == z &&
|
||||
(TileData.ItemTable[staticTile.ID & TileData.MaxItemValue].Flags & TileFlag.Wet) != 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public abstract Point3D GetSpawnPosition(ISpawnable spawned, Map map);
|
||||
|
||||
public virtual Map GetSpawnMap() => Map;
|
||||
|
||||
|
|
@ -783,7 +745,9 @@ namespace Server.Mobiles
|
|||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(7); // version
|
||||
writer.Write(8); // version
|
||||
|
||||
writer.Write(ReturnOnDeactivate);
|
||||
|
||||
writer.Write(Entries.Count);
|
||||
|
||||
|
|
@ -820,6 +784,11 @@ namespace Server.Mobiles
|
|||
|
||||
switch (version)
|
||||
{
|
||||
case 8:
|
||||
{
|
||||
ReturnOnDeactivate = reader.ReadBool();
|
||||
goto case 7;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
int size = reader.ReadInt();
|
||||
|
|
@ -909,7 +878,7 @@ namespace Server.Mobiles
|
|||
else
|
||||
Entries[i].SpawnedName = typeName;
|
||||
|
||||
if (SpawnerType.GetType(typeName) == null)
|
||||
if (AssemblyHandler.FindFirstTypeForName(typeName) == null)
|
||||
{
|
||||
m_WarnTimer ??= new WarnTimer();
|
||||
|
||||
|
|
@ -928,7 +897,7 @@ namespace Server.Mobiles
|
|||
e.Spawner = this;
|
||||
|
||||
for (int j = 0; j < Entries.Count; j++)
|
||||
if (SpawnerType.GetType(Entries[j].SpawnedName) == e.GetType())
|
||||
if (AssemblyHandler.FindFirstTypeForName(Entries[j].SpawnedName) == e.GetType())
|
||||
{
|
||||
Entries[j].Spawned.Add(e);
|
||||
Spawned.Add(e, Entries[j]);
|
||||
|
|
@ -947,30 +916,11 @@ namespace Server.Mobiles
|
|||
m_WalkingRange = m_HomeRange;
|
||||
}
|
||||
|
||||
public static string ConvertTypes(string type)
|
||||
{
|
||||
type = type.ToLower();
|
||||
return type switch
|
||||
{
|
||||
"wheat" => "WheatSheaf",
|
||||
"noxxiousmage" => "NoxiousMage",
|
||||
"noxxiousarcher" => "NoxiousArcher",
|
||||
"noxxiouswarrior" => "NoxiousWarrior",
|
||||
"noxxiouswarlord" => "NoxiousWarlord",
|
||||
"obsidian" => "obsidianstatue",
|
||||
"adeepwaterelemental" => "deepwaterelemental",
|
||||
"noxskeleton" => "poisonskeleton",
|
||||
"earthcaller" => "earthsummoner",
|
||||
"bonedemon" => "bonedaemon",
|
||||
_ => type
|
||||
};
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private readonly Spawner m_Spawner;
|
||||
private readonly BaseSpawner m_Spawner;
|
||||
|
||||
public InternalTimer(Spawner spawner, TimeSpan delay) : base(delay)
|
||||
public InternalTimer(BaseSpawner spawner, TimeSpan delay) : base(delay)
|
||||
{
|
||||
if (spawner.IsFull)
|
||||
Priority = TimerPriority.FiveSeconds;
|
||||
|
|
@ -1052,142 +1002,4 @@ namespace Server.Mobiles
|
|||
InvalidProps = 0x004,
|
||||
InvalidEntry = 0x008
|
||||
}
|
||||
|
||||
public class SpawnerEntry
|
||||
{
|
||||
public SpawnerEntry(string name, int probability, int maxcount)
|
||||
{
|
||||
SpawnedName = name;
|
||||
SpawnedProbability = probability;
|
||||
SpawnedMaxCount = maxcount;
|
||||
Spawned = new List<ISpawnable>();
|
||||
}
|
||||
|
||||
public SpawnerEntry(Spawner parent, IGenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
SpawnedName = reader.ReadString();
|
||||
SpawnedProbability = reader.ReadInt();
|
||||
SpawnedMaxCount = reader.ReadInt();
|
||||
|
||||
Properties = reader.ReadString();
|
||||
Parameters = reader.ReadString();
|
||||
|
||||
int count = reader.ReadInt();
|
||||
|
||||
Spawned = new List<ISpawnable>(count);
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
// IEntity e = World.FindEntity( reader.ReadInt() );
|
||||
|
||||
if (reader.ReadEntity() is ISpawnable e)
|
||||
{
|
||||
e.Spawner = parent;
|
||||
|
||||
if (e is BaseCreature creature)
|
||||
creature.RemoveIfUntamed = true;
|
||||
|
||||
Spawned.Add(e);
|
||||
|
||||
if (!parent.Spawned.ContainsKey(e))
|
||||
parent.Spawned.Add(e, this);
|
||||
}
|
||||
}
|
||||
|
||||
public int SpawnedProbability { get; set; }
|
||||
|
||||
public int SpawnedMaxCount { get; set; }
|
||||
|
||||
public string SpawnedName { get; set; }
|
||||
|
||||
public string Properties { get; set; }
|
||||
|
||||
public string Parameters { get; set; }
|
||||
|
||||
public EntryFlags Valid { get; set; }
|
||||
|
||||
public List<ISpawnable> Spawned { get; }
|
||||
|
||||
public bool IsFull => Spawned.Count >= SpawnedMaxCount;
|
||||
|
||||
public void Serialize(IGenericWriter writer)
|
||||
{
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(SpawnedName);
|
||||
writer.Write(SpawnedProbability);
|
||||
writer.Write(SpawnedMaxCount);
|
||||
|
||||
writer.Write(Properties);
|
||||
writer.Write(Parameters);
|
||||
|
||||
writer.Write(Spawned.Count);
|
||||
|
||||
for (int i = 0; i < Spawned.Count; ++i)
|
||||
{
|
||||
object o = Spawned[i];
|
||||
|
||||
if (o is Item item)
|
||||
writer.Write(item);
|
||||
else if (o is Mobile mobile)
|
||||
writer.Write(mobile);
|
||||
else
|
||||
writer.Write(Serial.MinusOne);
|
||||
}
|
||||
}
|
||||
|
||||
public void Defrag(Spawner parent)
|
||||
{
|
||||
for (int i = 0; i < Spawned.Count; ++i)
|
||||
{
|
||||
ISpawnable e = Spawned[i];
|
||||
bool remove = false;
|
||||
|
||||
if (e is Item item)
|
||||
{
|
||||
if (item.Deleted || item.RootParent is Mobile || item.IsLockedDown || item.IsSecure ||
|
||||
item.Spawner == null)
|
||||
remove = true;
|
||||
}
|
||||
else if (e is Mobile m)
|
||||
{
|
||||
if (m.Deleted)
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
else if (m is BaseCreature c)
|
||||
{
|
||||
if (c.Controlled || c.IsStabled)
|
||||
remove = true;
|
||||
/*
|
||||
else if (c.Combatant == null && ( c.GetDistanceToSqrt( Location ) > (c.RangeHome * 4) ))
|
||||
{
|
||||
//m_Spawned[i].Delete();
|
||||
m_Spawned.RemoveAt( i );
|
||||
--i;
|
||||
c.Delete();
|
||||
remove = true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (m.Spawner == null)
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
|
||||
if (remove)
|
||||
{
|
||||
Spawned.RemoveAt(i--);
|
||||
if (parent.Spawned.ContainsKey(e))
|
||||
parent.Spawned.Remove(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
Projects/UOContent/Engines/Spawners/GenerateSpawners.cs
Normal file
116
Projects/UOContent/Engines/Spawners/GenerateSpawners.cs
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Utilities;
|
||||
|
||||
namespace Server.Engines.Spawners
|
||||
{
|
||||
public static class GenerateSpawners
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register("GenerateSpawners", AccessLevel.Developer, GenerateSpawners_OnCommand);
|
||||
}
|
||||
|
||||
private static void GenerateSpawners_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
Mobile from = e.Mobile;
|
||||
|
||||
if (e.Arguments.Length == 0)
|
||||
{
|
||||
from.SendMessage("Usage: [GenerateSpawners <path|search pattern>");
|
||||
return;
|
||||
}
|
||||
|
||||
var di = new DirectoryInfo(Core.BaseDirectory);
|
||||
|
||||
var files = di.GetFiles(e.Arguments[0], SearchOption.AllDirectories);
|
||||
|
||||
if (files.Length == 0)
|
||||
{
|
||||
from.SendMessage("GenerateSpawners: No files found matching the pattern");
|
||||
return;
|
||||
}
|
||||
|
||||
JsonSerializerOptions options = new JsonSerializerOptions();
|
||||
options.Converters.Add(new MapConverterFactory());
|
||||
options.Converters.Add(new Point3DConverterFactory());
|
||||
options.Converters.Add(new TimeSpanConverterFactory());
|
||||
options.Converters.Add(new TextDefinitionConverterFactory());
|
||||
|
||||
for (int i = 0; i < files.Length; i++)
|
||||
{
|
||||
var file = files[i];
|
||||
from.SendMessage("GenerateSpawners: Generating spawners for {0}...", file.Name);
|
||||
List<DynamicJson> spawners = JsonConfig.Deserialize<List<DynamicJson>>(file.FullName);
|
||||
ParseSpawnerList(from, spawners, options);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseSpawnerList(Mobile from, List<DynamicJson> spawners, JsonSerializerOptions options)
|
||||
{
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
List<string> failures = new List<string>();
|
||||
int count = 0;
|
||||
|
||||
for (var i = 0; i < spawners.Count; i++)
|
||||
{
|
||||
var json = spawners[i];
|
||||
Type type = AssemblyHandler.FindFirstTypeForName(json.Type);
|
||||
|
||||
if (type == null || !typeof(BaseSpawner).IsAssignableFrom(type))
|
||||
{
|
||||
string failure = $"GenerateSpawners: Invalid spawner type {json.Type ?? "(-null-)"} ({i})";
|
||||
if (!failures.Contains(failure))
|
||||
{
|
||||
failures.Add(failure);
|
||||
from.SendMessage(failure);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
json.GetProperty("location", options, out Point3D location);
|
||||
json.GetProperty("map", options, out Map map);
|
||||
|
||||
var eable = map.GetItemsInRange<BaseSpawner>(location, 0);
|
||||
|
||||
if (eable.Any(sp => sp.GetType() == type))
|
||||
{
|
||||
eable.Free();
|
||||
continue;
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
|
||||
try
|
||||
{
|
||||
var spawner = ActivatorUtil.CreateInstance(type, json, options) as ISpawner;
|
||||
|
||||
spawner!.MoveToWorld(location, map);
|
||||
spawner!.Respawn();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
string failure = $"GenerateSpawners: Spawner {type} failed to construct";
|
||||
if (!failures.Contains(failure))
|
||||
{
|
||||
failures.Add(failure);
|
||||
from.SendMessage(failure);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
watch.Stop();
|
||||
from.SendMessage("GenerateSpawners: Generated {0} spawners ({1:F2} seconds, {2} failures)", count, watch.Elapsed.TotalSeconds, failures.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +1,30 @@
|
|||
using System;
|
||||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Mobiles
|
||||
namespace Server.Engines.Spawners
|
||||
{
|
||||
public class ProximitySpawner : Spawner
|
||||
{
|
||||
[Constructible]
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public ProximitySpawner()
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public ProximitySpawner(string spawnName)
|
||||
: base(spawnName)
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public ProximitySpawner(int amount, int minDelay, int maxDelay, int team, int homeRange, string spawnName)
|
||||
: base(amount, minDelay, maxDelay, team, homeRange, spawnName)
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public ProximitySpawner(int amount, int minDelay, int maxDelay, int team, int homeRange, int triggerRange,
|
||||
string spawnMessage, bool instantFlag, string spawnName)
|
||||
: base(amount, minDelay, maxDelay, team, homeRange, spawnName)
|
||||
|
|
@ -31,12 +34,14 @@ namespace Server.Mobiles
|
|||
InstantFlag = instantFlag;
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public ProximitySpawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange,
|
||||
params string[] spawnedNames)
|
||||
: base(amount, minDelay, maxDelay, team, homeRange, spawnedNames)
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public ProximitySpawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, int triggerRange,
|
||||
TextDefinition spawnMessage, bool instantFlag, params string[] spawnedNames)
|
||||
: base(amount, minDelay, maxDelay, team, homeRange, spawnedNames)
|
||||
|
|
@ -46,6 +51,17 @@ namespace Server.Mobiles
|
|||
InstantFlag = instantFlag;
|
||||
}
|
||||
|
||||
public ProximitySpawner(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
{
|
||||
json.GetProperty("triggerRange", options, out int triggerRange);
|
||||
json.GetProperty("spawnMessage", options, out TextDefinition spawnMessage);
|
||||
json.GetProperty("instant", options, out bool instant);
|
||||
|
||||
TriggerRange = triggerRange;
|
||||
SpawnMessage = spawnMessage;
|
||||
InstantFlag = instant;
|
||||
}
|
||||
|
||||
public ProximitySpawner(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
|
|
@ -129,4 +145,4 @@ namespace Server.Mobiles
|
|||
InstantFlag = reader.ReadBool();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
152
Projects/UOContent/Engines/Spawners/RegionSpawner.cs
Normal file
152
Projects/UOContent/Engines/Spawners/RegionSpawner.cs
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
using System;
|
||||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server.Engines.Spawners
|
||||
{
|
||||
public class RegionSpawner : Spawner
|
||||
{
|
||||
private BaseRegion m_SpawnRegion;
|
||||
|
||||
[CommandProperty(AccessLevel.Developer)]
|
||||
public BaseRegion SpawnRegion
|
||||
{
|
||||
get => m_SpawnRegion;
|
||||
set
|
||||
{
|
||||
m_SpawnRegion = value;
|
||||
m_SpawnRegion?.InitRectangles();
|
||||
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public RegionSpawner()
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public RegionSpawner(string spawnedName) : base(spawnedName)
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public RegionSpawner(int amount, int minDelay, int maxDelay, int team, int homeRange,
|
||||
params string[] spawnedNames) : this(amount, TimeSpan.FromMinutes(minDelay), TimeSpan.FromMinutes(maxDelay),
|
||||
team, homeRange, spawnedNames)
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public RegionSpawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange,
|
||||
params string[] spawnedNames) : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames)
|
||||
{
|
||||
}
|
||||
|
||||
public RegionSpawner(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
{
|
||||
json.GetProperty("map", options, out Map map);
|
||||
json.GetProperty("region", options, out string spawnRegion);
|
||||
|
||||
m_SpawnRegion = Region.Find(spawnRegion, map) as BaseRegion;
|
||||
m_SpawnRegion?.InitRectangles();
|
||||
}
|
||||
|
||||
public RegionSpawner(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void GetSpawnerProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.GetSpawnerProperties(list);
|
||||
|
||||
if (Running && m_SpawnRegion != null) list.Add(1076228, "region:\t{0}", m_SpawnRegion.Name); // ~1_DUMMY~ ~2_DUMMY~
|
||||
}
|
||||
|
||||
public override Point3D GetSpawnPosition(ISpawnable spawned, Map map)
|
||||
{
|
||||
if (m_SpawnRegion == null || map == null || map == Map.Internal || map != m_SpawnRegion.Map || m_SpawnRegion.TotalWeight <= 0)
|
||||
return Location;
|
||||
|
||||
bool waterMob, waterOnlyMob;
|
||||
|
||||
if (spawned is Mobile mob)
|
||||
{
|
||||
waterMob = mob.CanSwim;
|
||||
waterOnlyMob = mob.CanSwim && mob.CantWalk;
|
||||
}
|
||||
else
|
||||
{
|
||||
waterMob = false;
|
||||
waterOnlyMob = false;
|
||||
}
|
||||
|
||||
// Try 10 times to find a valid location.
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int rand = Utility.Random(m_SpawnRegion.TotalWeight);
|
||||
|
||||
int x = int.MinValue;
|
||||
int y = int.MinValue;
|
||||
|
||||
for (int j = 0; j < m_SpawnRegion.RectangleWeights.Length; j++)
|
||||
{
|
||||
int curWeight = m_SpawnRegion.RectangleWeights[j];
|
||||
|
||||
if (rand < curWeight)
|
||||
{
|
||||
Rectangle3D rect = m_SpawnRegion.Rectangles[j];
|
||||
|
||||
x = rect.Start.X + rand % rect.Width;
|
||||
y = rect.Start.Y + rand / rect.Width;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
rand -= curWeight;
|
||||
}
|
||||
|
||||
int mapZ = map.GetAverageZ(x, y);
|
||||
|
||||
if (waterMob)
|
||||
{
|
||||
if (IsValidWater(map, x, y, Z))
|
||||
return new Point3D(x, y, Z);
|
||||
if (IsValidWater(map, x, y, mapZ))
|
||||
return new Point3D(x, y, mapZ);
|
||||
}
|
||||
|
||||
if (!waterOnlyMob)
|
||||
{
|
||||
if (map.CanSpawnMobile(x, y, Z))
|
||||
return new Point3D(x, y, Z);
|
||||
if (map.CanSpawnMobile(x, y, mapZ))
|
||||
return new Point3D(x, y, mapZ);
|
||||
}
|
||||
}
|
||||
|
||||
return HomeLocation;
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
|
||||
m_SpawnRegion = Region.Find(reader.ReadString(), Map) as BaseRegion;
|
||||
m_SpawnRegion?.InitRectangles();
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); // version
|
||||
|
||||
writer.Write(m_SpawnRegion?.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
139
Projects/UOContent/Engines/Spawners/Spawner.cs
Normal file
139
Projects/UOContent/Engines/Spawners/Spawner.cs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
using System;
|
||||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
|
||||
namespace Server.Engines.Spawners
|
||||
{
|
||||
public class Spawner : BaseSpawner
|
||||
{
|
||||
public static bool IsValidWater(Map map, int x, int y, int z)
|
||||
{
|
||||
if (!Region.Find(new Point3D(x, y, z), map).AllowSpawn() || !map.CanFit(x, y, z, 16, false, true, false))
|
||||
return false;
|
||||
|
||||
LandTile landTile = map.Tiles.GetLandTile(x, y);
|
||||
|
||||
if (landTile.Z == z && (TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags & TileFlag.Wet) != 0)
|
||||
return true;
|
||||
|
||||
StaticTile[] staticTiles = map.Tiles.GetStaticTiles(x, y, true);
|
||||
|
||||
for (int i = 0; i < staticTiles.Length; ++i)
|
||||
{
|
||||
StaticTile staticTile = staticTiles[i];
|
||||
|
||||
if (staticTile.Z == z &&
|
||||
(TileData.ItemTable[staticTile.ID & TileData.MaxItemValue].Flags & TileFlag.Wet) != 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public Spawner()
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public Spawner(string spawnedName) : base(spawnedName)
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public Spawner(int amount, int minDelay, int maxDelay, int team, int homeRange,
|
||||
params string[] spawnedNames) : this(amount, TimeSpan.FromMinutes(minDelay), TimeSpan.FromMinutes(maxDelay),
|
||||
team, homeRange, spawnedNames)
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible(AccessLevel.Developer)]
|
||||
public Spawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange,
|
||||
params string[] spawnedNames) : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames)
|
||||
{
|
||||
}
|
||||
|
||||
public Spawner(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
{
|
||||
}
|
||||
|
||||
public Spawner(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
public override bool OnDefragSpawn(ISpawnable spawned, bool remove)
|
||||
{
|
||||
// To despawn a mob that was lured 4x away from its spawner
|
||||
// TODO: Move this to a config
|
||||
if (spawned is BaseCreature c && c.Combatant == null && c.GetDistanceToSqrt( Location ) > c.RangeHome * 4)
|
||||
{
|
||||
c.Delete();
|
||||
remove = true;
|
||||
}
|
||||
|
||||
return base.OnDefragSpawn(entry, spawned, remove);
|
||||
}
|
||||
*/
|
||||
|
||||
public override Point3D GetSpawnPosition(ISpawnable spawned, Map map)
|
||||
{
|
||||
if (map == null || map == Map.Internal)
|
||||
return Location;
|
||||
|
||||
bool waterMob, waterOnlyMob;
|
||||
|
||||
if (spawned is Mobile mob)
|
||||
{
|
||||
waterMob = mob.CanSwim;
|
||||
waterOnlyMob = mob.CanSwim && mob.CantWalk;
|
||||
}
|
||||
else
|
||||
{
|
||||
waterMob = false;
|
||||
waterOnlyMob = false;
|
||||
}
|
||||
|
||||
// Try 10 times to find a valid location.
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int x = Location.X + (Utility.Random(HomeRange * 2 + 1) - HomeRange);
|
||||
int y = Location.Y + (Utility.Random(HomeRange * 2 + 1) - HomeRange);
|
||||
|
||||
int mapZ = map.GetAverageZ(x, y);
|
||||
|
||||
if (waterMob)
|
||||
{
|
||||
if (IsValidWater(map, x, y, Z))
|
||||
return new Point3D(x, y, Z);
|
||||
if (IsValidWater(map, x, y, mapZ))
|
||||
return new Point3D(x, y, mapZ);
|
||||
}
|
||||
|
||||
if (!waterOnlyMob)
|
||||
{
|
||||
if (map.CanSpawnMobile(x, y, Z))
|
||||
return new Point3D(x, y, Z);
|
||||
if (map.CanSpawnMobile(x, y, mapZ))
|
||||
return new Point3D(x, y, mapZ);
|
||||
}
|
||||
}
|
||||
|
||||
return HomeLocation;
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); // version
|
||||
}
|
||||
}
|
||||
}
|
||||
113
Projects/UOContent/Engines/Spawners/SpawnerEntry.cs
Normal file
113
Projects/UOContent/Engines/Spawners/SpawnerEntry.cs
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.Spawners
|
||||
{
|
||||
public class SpawnerEntry
|
||||
{
|
||||
public SpawnerEntry() => Spawned = new List<ISpawnable>();
|
||||
|
||||
public SpawnerEntry(string name, int probability, int maxcount) : this()
|
||||
{
|
||||
SpawnedName = name;
|
||||
SpawnedProbability = probability;
|
||||
SpawnedMaxCount = maxcount;
|
||||
}
|
||||
|
||||
public SpawnerEntry(BaseSpawner parent, IGenericReader reader)
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
SpawnedName = reader.ReadString();
|
||||
SpawnedProbability = reader.ReadInt();
|
||||
SpawnedMaxCount = reader.ReadInt();
|
||||
|
||||
Properties = reader.ReadString();
|
||||
Parameters = reader.ReadString();
|
||||
|
||||
int count = reader.ReadInt();
|
||||
|
||||
Spawned = new List<ISpawnable>(count);
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
// IEntity e = World.FindEntity( reader.ReadInt() );
|
||||
|
||||
if (reader.ReadEntity() is ISpawnable e)
|
||||
{
|
||||
e.Spawner = parent;
|
||||
|
||||
if (e is BaseCreature creature)
|
||||
creature.RemoveIfUntamed = true;
|
||||
|
||||
Spawned.Add(e);
|
||||
|
||||
if (!parent.Spawned.ContainsKey(e))
|
||||
parent.Spawned.Add(e, this);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonPropertyName("probability")]
|
||||
public int SpawnedProbability { get; set; }
|
||||
|
||||
[JsonPropertyName("maxCount")]
|
||||
public int SpawnedMaxCount { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string SpawnedName { get; set; }
|
||||
|
||||
[JsonPropertyName("properties")]
|
||||
public string Properties { get; set; }
|
||||
|
||||
[JsonPropertyName("parameters")]
|
||||
public string Parameters { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public EntryFlags Valid { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public List<ISpawnable> Spawned { get; }
|
||||
|
||||
public bool IsFull => Spawned.Count >= SpawnedMaxCount;
|
||||
|
||||
public void Serialize(IGenericWriter writer)
|
||||
{
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(SpawnedName);
|
||||
writer.Write(SpawnedProbability);
|
||||
writer.Write(SpawnedMaxCount);
|
||||
|
||||
writer.Write(Properties);
|
||||
writer.Write(Parameters);
|
||||
|
||||
writer.Write(Spawned.Count);
|
||||
|
||||
for (int i = 0; i < Spawned.Count; ++i)
|
||||
{
|
||||
object o = Spawned[i];
|
||||
|
||||
if (o is Item item)
|
||||
writer.Write(item);
|
||||
else if (o is Mobile mobile)
|
||||
writer.Write(mobile);
|
||||
else
|
||||
writer.Write(Serial.MinusOne);
|
||||
}
|
||||
}
|
||||
|
||||
public void Defrag(BaseSpawner parent)
|
||||
{
|
||||
for (int i = 0; i < Spawned.Count; ++i)
|
||||
{
|
||||
ISpawnable spawned = Spawned[i];
|
||||
|
||||
if (parent.OnDefragSpawn(spawned, false))
|
||||
{
|
||||
Spawned.RemoveAt(i--);
|
||||
parent.Spawned.Remove(spawned);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,15 +3,15 @@ using System.Collections.Generic;
|
|||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Mobiles
|
||||
namespace Server.Engines.Spawners
|
||||
{
|
||||
public class SpawnerGump : Gump
|
||||
{
|
||||
private SpawnerEntry m_Entry;
|
||||
private int m_Page;
|
||||
private readonly Spawner m_Spawner;
|
||||
private readonly BaseSpawner m_Spawner;
|
||||
|
||||
public SpawnerGump(Spawner spawner, SpawnerEntry focusentry = null, int page = 0) : base(50, 50)
|
||||
public SpawnerGump(BaseSpawner spawner, SpawnerEntry focusentry = null, int page = 0) : base(50, 50)
|
||||
{
|
||||
m_Spawner = spawner;
|
||||
m_Entry = focusentry;
|
||||
|
|
@ -124,7 +124,7 @@ namespace Server.Mobiles
|
|||
|
||||
public int GetButtonID(int type, int index) => 1 + index * 10 + type;
|
||||
|
||||
public void CreateArray(RelayInfo info, Mobile from, Spawner spawner)
|
||||
public void CreateArray(RelayInfo info, Mobile from, BaseSpawner spawner)
|
||||
{
|
||||
int ocount = spawner.Entries.Count;
|
||||
|
||||
|
|
@ -148,47 +148,46 @@ namespace Server.Mobiles
|
|||
|
||||
if (str.Length > 0)
|
||||
{
|
||||
Type type = SpawnerType.GetType(str);
|
||||
Type type = AssemblyHandler.FindFirstTypeForName(str);
|
||||
|
||||
if (type != null)
|
||||
if (type == null)
|
||||
{
|
||||
SpawnerEntry entry;
|
||||
from.SendMessage("{0} is not a valid type name for entry #{1}.", str, i);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entryindex < ocount)
|
||||
{
|
||||
entry = spawner.Entries[entryindex];
|
||||
entry.SpawnedName = str;
|
||||
SpawnerEntry entry;
|
||||
|
||||
if (mte != null)
|
||||
entry.SpawnedMaxCount = Utility.ToInt32(mte.Text.Trim());
|
||||
if (entryindex < ocount)
|
||||
{
|
||||
entry = spawner.Entries[entryindex];
|
||||
entry.SpawnedName = str;
|
||||
|
||||
if (poste != null)
|
||||
entry.SpawnedProbability = Utility.ToInt32(poste.Text.Trim());
|
||||
}
|
||||
else
|
||||
{
|
||||
int maxcount = 1;
|
||||
int probcount = 100;
|
||||
if (mte != null)
|
||||
entry.SpawnedMaxCount = Utility.ToInt32(mte.Text.Trim());
|
||||
|
||||
if (mte != null)
|
||||
maxcount = Utility.ToInt32(mte.Text.Trim());
|
||||
|
||||
if (poste != null)
|
||||
probcount = Utility.ToInt32(poste.Text.Trim());
|
||||
|
||||
entry = spawner.AddEntry(str, probcount, maxcount);
|
||||
}
|
||||
|
||||
if (parmte != null)
|
||||
entry.Parameters = parmte.Text.Trim();
|
||||
|
||||
if (propte != null)
|
||||
entry.Properties = propte.Text.Trim();
|
||||
if (poste != null)
|
||||
entry.SpawnedProbability = Utility.ToInt32(poste.Text.Trim());
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage("{0} is not a valid type name for entry #{1}.", str, i);
|
||||
int maxcount = 1;
|
||||
int probcount = 100;
|
||||
|
||||
if (mte != null)
|
||||
maxcount = Utility.ToInt32(mte.Text.Trim());
|
||||
|
||||
if (poste != null)
|
||||
probcount = Utility.ToInt32(poste.Text.Trim());
|
||||
|
||||
entry = spawner.AddEntry(str, probcount, maxcount);
|
||||
}
|
||||
|
||||
if (parmte != null)
|
||||
entry.Parameters = parmte.Text.Trim();
|
||||
|
||||
if (propte != null)
|
||||
entry.Properties = propte.Text.Trim();
|
||||
}
|
||||
else if (entryindex < ocount && spawner.Entries[entryindex] != null)
|
||||
{
|
||||
|
|
@ -120,7 +120,7 @@ namespace Server.Items
|
|||
|
||||
private void InternalCallback(Mobile from, object targeted)
|
||||
{
|
||||
if (Deleted || UsesRemaining <= 0 || !from.InRange(GetWorldLocation(), 3) ||
|
||||
if (Deleted || UsesRemaining <= 0 || !from.InRange(GetWorldLocation(), 3) ||
|
||||
!IsAccessibleTo(from))
|
||||
return;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue