fix: Fixes region priority and resolution. (#1254)
- [X] Fixes world location JSON deserializer. - [X] Fixes region resolver and priorities. - [X] Removes DynamicJson from regions. - [X] Adds missing region music.
This commit is contained in:
parent
139be1bc23
commit
18c4459e6b
31 changed files with 3809 additions and 3677 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -1,46 +0,0 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: JsonDtoConverter.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Server.Json;
|
||||
|
||||
public class JsonDtoConverter<TDto, TObject> : JsonConverter<TObject>
|
||||
where TDto : IJsonRootDtoConvertible<TDto, TObject>, new() where TObject : new()
|
||||
{
|
||||
public override TObject Read(
|
||||
ref Utf8JsonReader reader,
|
||||
Type typeToConvert,
|
||||
JsonSerializerOptions options
|
||||
)
|
||||
{
|
||||
if (typeof(TObject) != typeToConvert)
|
||||
{
|
||||
throw new JsonException($"Invalid object type to deserialize for '{typeof(TObject).Name}'");
|
||||
}
|
||||
|
||||
// Deserialize to the DTO
|
||||
var dto = JsonSerializer.Deserialize<TDto>(ref reader, options);
|
||||
|
||||
return TDto.ToObject(dto);
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, TObject value, JsonSerializerOptions options)
|
||||
{
|
||||
JsonSerializer.Serialize(writer, TDto.FromObject(value), options);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: JsonDtoConverter.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Server.Json;
|
||||
|
||||
public class JsonDtoConverterFactory<TDto, TObject> : JsonConverterFactory
|
||||
where TDto : IJsonRootDtoConvertible<TDto, TObject>, new() where TObject : new()
|
||||
{
|
||||
public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(TObject);
|
||||
|
||||
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
|
||||
new JsonDtoConverter<TDto, TObject>();
|
||||
}
|
||||
|
|
@ -80,7 +80,6 @@ public class WorldLocationConverter : JsonConverter<WorldLocation>
|
|||
private WorldLocation DeserializeObj(ref Utf8JsonReader reader, JsonSerializerOptions options)
|
||||
{
|
||||
Span<int> data = stackalloc int[3];
|
||||
var count = 0;
|
||||
var hasLoc = false;
|
||||
var hasXYZ = false;
|
||||
var hasMap = false;
|
||||
|
|
@ -150,7 +149,6 @@ public class WorldLocationConverter : JsonConverter<WorldLocation>
|
|||
data[0] = loc.X;
|
||||
data[1] = loc.Y;
|
||||
data[2] = loc.Z;
|
||||
count = 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -160,7 +158,7 @@ public class WorldLocationConverter : JsonConverter<WorldLocation>
|
|||
hasMap = true;
|
||||
}
|
||||
|
||||
if (!hasMap || count != 3)
|
||||
if (!hasMap)
|
||||
{
|
||||
throw new JsonException("WorldLocation must have an x, y, z, and map properties");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: IJsonConvertible.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
namespace Server.Json;
|
||||
|
||||
public interface IJsonRootDtoConvertible<TSelf, TObject> where TSelf : IJsonRootDtoConvertible<TSelf, TObject> where TObject : new()
|
||||
{
|
||||
public abstract static TSelf FromObject(TObject obj);
|
||||
public abstract static TObject ToObject(TSelf obj);
|
||||
}
|
||||
|
||||
public interface IJsonDtoConvertible<TSelf, TObject> where TSelf : IJsonDtoConvertible<TSelf, TObject> where TObject : new()
|
||||
{
|
||||
public abstract TSelf HydrateDto(TObject obj);
|
||||
public abstract TObject HydrateObject(TObject obj);
|
||||
}
|
||||
|
|
@ -19,7 +19,6 @@ using System.Diagnostics;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
|
@ -509,7 +508,7 @@ public static class Core
|
|||
|
||||
TileMatrixLoader.LoadTileMatrix();
|
||||
|
||||
RegionLoader.LoadRegions();
|
||||
RegionJsonSerializer.LoadRegions();
|
||||
World.Load();
|
||||
|
||||
AssemblyHandler.Invoke("Initialize");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Logging;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
|
@ -78,6 +76,42 @@ public enum MusicName
|
|||
SelimsBar,
|
||||
SerpentIsleCombat_U7,
|
||||
ValoriaShips,
|
||||
TheWanderer,
|
||||
Castle,
|
||||
Festival,
|
||||
Honor,
|
||||
Medieval,
|
||||
BattleOnStones,
|
||||
Docktown,
|
||||
GargoyleQueen,
|
||||
GenericCombat,
|
||||
Holycity,
|
||||
HumanLevel,
|
||||
LoginLoop,
|
||||
NorthernForestBattleonStones,
|
||||
PrimevalLich,
|
||||
QueenPalace,
|
||||
RoyalCity,
|
||||
SlasherVeil,
|
||||
StygianAbyss,
|
||||
StygianDragon,
|
||||
Void,
|
||||
CodexShrine,
|
||||
AnvilStrikeInMinoc,
|
||||
ASkaranLullaby,
|
||||
BlackthornsMarch,
|
||||
DupresNightInTrinsic,
|
||||
FayaxionAndTheSix,
|
||||
FlightOfTheNexus,
|
||||
GalehavenJaunt,
|
||||
JhelomToArms,
|
||||
MidnightInYew,
|
||||
MoonglowSonata,
|
||||
NewMaginciaMarch,
|
||||
NujelmWaltz,
|
||||
SherrysSong,
|
||||
StarlightInBritain,
|
||||
TheVesperMist,
|
||||
NoMusic = 0x1FFF
|
||||
}
|
||||
|
||||
|
|
@ -98,9 +132,16 @@ public class Region : IComparable<Region>
|
|||
{
|
||||
}
|
||||
|
||||
public Region(string name, Map map, params Rectangle3D[] area) : this(name, map, null, area)
|
||||
{
|
||||
}
|
||||
|
||||
public Region(string name, Map map, int priority, params Rectangle3D[] area) : this(name, map, null, area) =>
|
||||
Priority = priority;
|
||||
|
||||
public Region(string name, Map map, Region parent, int priority, params Rectangle3D[] area) : this(name, map, parent, area) =>
|
||||
Priority = priority;
|
||||
|
||||
public Region(string name, Map map, Region parent, params Rectangle2D[] area) : this(
|
||||
name,
|
||||
map,
|
||||
|
|
@ -131,54 +172,6 @@ public class Region : IComparable<Region>
|
|||
}
|
||||
}
|
||||
|
||||
public Region(DynamicJson json, JsonSerializerOptions options)
|
||||
{
|
||||
Map = json.GetProperty("map", options, out Map map) ? map : null;
|
||||
Parent = json.GetProperty("parent", options, out string parent) ? Find(parent, Map) : null;
|
||||
Name = json.GetProperty("name", options, out string name) ? name : null;
|
||||
|
||||
Dynamic = false;
|
||||
|
||||
if (Parent == null)
|
||||
{
|
||||
ChildLevel = 0;
|
||||
Priority = DefaultPriority;
|
||||
}
|
||||
else
|
||||
{
|
||||
ChildLevel = Parent.ChildLevel + 1;
|
||||
Priority = Parent.Priority;
|
||||
}
|
||||
|
||||
Priority = json.GetProperty("priority", options, out int priority) ? priority : Priority;
|
||||
|
||||
Area = json.GetProperty("rects", options, out List<Rectangle3D> rects)
|
||||
? rects.ToArray()
|
||||
: Array.Empty<Rectangle3D>();
|
||||
|
||||
if (Area.Length == 0)
|
||||
{
|
||||
logger.Debug("Empty area for region '{Region}'", this);
|
||||
}
|
||||
|
||||
if (json.GetProperty("go", options, out Point3D go))
|
||||
{
|
||||
GoLocation = go;
|
||||
}
|
||||
else if (Area.Length > 0)
|
||||
{
|
||||
var start = Area[0].Start;
|
||||
var end = Area[0].End;
|
||||
|
||||
var x = start.X + (end.X - start.X) / 2;
|
||||
var y = start.Y + (end.Y - start.Y) / 2;
|
||||
|
||||
GoLocation = new Point3D(x, y, Map?.GetAverageZ(x, y) ?? start.Z + (end.Z - start.Z) / 2);
|
||||
}
|
||||
|
||||
Music = json.GetEnumProperty("music", options, out MusicName music) ? music : DefaultMusic;
|
||||
}
|
||||
|
||||
public static List<Region> Regions { get; } = new();
|
||||
|
||||
public static TimeSpan StaffLogoutDelay { get; set; } = TimeSpan.Zero;
|
||||
|
|
@ -239,6 +232,11 @@ public class Region : IComparable<Region>
|
|||
// This is not optimized. Use sparingly
|
||||
public static Region Find(string name, Map map, bool insensitive = false)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (insensitive)
|
||||
{
|
||||
name = name.ToLower();
|
||||
|
|
|
|||
61
Projects/Server/Regions/RegionJsonDto.cs
Normal file
61
Projects/Server/Regions/RegionJsonDto.cs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: RegionJsonDto.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using Server.Utilities;
|
||||
|
||||
namespace Server;
|
||||
|
||||
public class RegionJsonDto
|
||||
{
|
||||
[JsonIgnore]
|
||||
public virtual Type RegionType => typeof(Region);
|
||||
|
||||
public Map Map { get; set; }
|
||||
public string? Parent { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int? Priority { get; set; }
|
||||
public Rectangle3D[] Area { get; set; }
|
||||
public Point3D GoLocation { get; set; }
|
||||
public MusicName? Music { get; set; }
|
||||
|
||||
public virtual void FromRegion(Region region)
|
||||
{
|
||||
Map = region.Map;
|
||||
Parent = region.Parent?.Name;
|
||||
Name = region.Name;
|
||||
Priority = region.Priority;
|
||||
Area = region.Area;
|
||||
GoLocation = region.GoLocation;
|
||||
Music = region.Music != region.DefaultMusic ? region.Music : null;
|
||||
}
|
||||
|
||||
public Region ToRegion()
|
||||
{
|
||||
var region = Priority != null
|
||||
? RegionType.CreateInstance<Region>(Name, Map, Region.Find(Parent, Map), Priority, Area)
|
||||
: RegionType.CreateInstance<Region>(Name, Map, Region.Find(Parent, Map), Area);
|
||||
|
||||
HydrateRegion(region);
|
||||
return region;
|
||||
}
|
||||
|
||||
protected virtual void HydrateRegion(Region region)
|
||||
{
|
||||
region.GoLocation = GoLocation;
|
||||
region.Music = Music ?? region.DefaultMusic;
|
||||
}
|
||||
}
|
||||
148
Projects/Server/Regions/RegionJsonSerializer.cs
Normal file
148
Projects/Server/Regions/RegionJsonSerializer.cs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: RegionJsonSerializer.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
using Server.Json;
|
||||
using Server.Logging;
|
||||
using Server.Utilities;
|
||||
|
||||
namespace Server;
|
||||
|
||||
public static class RegionJsonSerializer
|
||||
{
|
||||
private static readonly ILogger logger = LogFactory.GetLogger(typeof(RegionJsonSerializer));
|
||||
|
||||
// Note: This is filled during the `Configure` phase by RegisterRegionForSerialization,
|
||||
// so it is not available to a JsonConverter which might be used during earlier phases.
|
||||
private static Dictionary<Type, Type> _regionToDtoLookup = new() { { typeof(Region), typeof(RegionJsonDto) } };
|
||||
private static JsonDerivedType[] _derivedTypes = { new(typeof(RegionJsonDto), nameof(Region)) };
|
||||
|
||||
private static JsonSerializerOptions _options = new(JsonConfig.DefaultOptions)
|
||||
{
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
|
||||
TypeInfoResolver = new DefaultJsonTypeInfoResolver
|
||||
{
|
||||
Modifiers =
|
||||
{
|
||||
static typeInfo =>
|
||||
{
|
||||
if (typeInfo.Type != typeof(RegionJsonDto))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
typeInfo.PolymorphismOptions = new JsonPolymorphismOptions();
|
||||
for (var i = 0; i < _derivedTypes.Length; i++)
|
||||
{
|
||||
typeInfo.PolymorphismOptions.DerivedTypes.Add(_derivedTypes[i]);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static void RegisterRegionForSerialization<TDto, TRegion>()
|
||||
where TDto : RegionJsonDto, new() where TRegion : Region
|
||||
{
|
||||
for (var i = 0; i < _derivedTypes.Length; i++)
|
||||
{
|
||||
if (_derivedTypes[i].DerivedType == typeof(TDto))
|
||||
{
|
||||
throw new Exception(
|
||||
$"Type '{typeof(TDto)}' has already been registered for serialization with the region loader."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Array.Resize(ref _derivedTypes, _derivedTypes.Length + 1);
|
||||
_derivedTypes[^1] = new JsonDerivedType(typeof(TDto), typeof(TRegion).Name);
|
||||
_regionToDtoLookup[typeof(TRegion)] = typeof(TDto);
|
||||
}
|
||||
|
||||
internal static void LoadRegions()
|
||||
{
|
||||
var path = Path.Join(Core.BaseDirectory, "Data/regions.json");
|
||||
|
||||
logger.Information("Loading regions");
|
||||
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
|
||||
var regions = JsonConfig.Deserialize<List<RegionJsonDto>>(path, _options);
|
||||
if (regions == null)
|
||||
{
|
||||
throw new JsonException($"Failed to deserialize {path}.");
|
||||
}
|
||||
|
||||
foreach (var dto in regions)
|
||||
{
|
||||
var region = dto.ToRegion();
|
||||
region.Register();
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
logger.Information(
|
||||
"Loading regions {Status} ({Count} regions) ({Duration:F2} seconds)",
|
||||
"done",
|
||||
regions.Count,
|
||||
stopwatch.Elapsed.TotalSeconds
|
||||
);
|
||||
}
|
||||
|
||||
// Note: This is not thread safe. To make `SerializeRegions` threadsafe, use `[ThreadStatic]` or just create the lists
|
||||
// in the function and take the GC hit.
|
||||
private static List<RegionJsonDto> _regionJsonDtos;
|
||||
|
||||
public static void SerializeRegions(string path, IEnumerable<Region> regions)
|
||||
{
|
||||
_regionJsonDtos ??= new List<RegionJsonDto>();
|
||||
foreach (var region in regions)
|
||||
{
|
||||
if (_regionToDtoLookup.TryGetValue(region.GetType(), out var dtoType))
|
||||
{
|
||||
var dto = dtoType.CreateInstance<RegionJsonDto>();
|
||||
dto.FromRegion(region);
|
||||
_regionJsonDtos.Add(dto);
|
||||
}
|
||||
}
|
||||
|
||||
JsonConfig.Serialize(path, _regionJsonDtos, _options);
|
||||
_regionJsonDtos.Clear();
|
||||
}
|
||||
|
||||
public static string SerializeRegions(IEnumerable<Region> regions)
|
||||
{
|
||||
_regionJsonDtos ??= new List<RegionJsonDto>();
|
||||
foreach (var region in regions)
|
||||
{
|
||||
if (_regionToDtoLookup.TryGetValue(region.GetType(), out var dtoType))
|
||||
{
|
||||
var dto = dtoType.CreateInstance<RegionJsonDto>();
|
||||
dto.FromRegion(region);
|
||||
_regionJsonDtos.Add(dto);
|
||||
}
|
||||
}
|
||||
|
||||
var output = JsonConfig.Serialize(_regionJsonDtos, _options);
|
||||
_regionJsonDtos.Clear();
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: RegionLoader.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Logging;
|
||||
using Server.Utilities;
|
||||
|
||||
namespace Server;
|
||||
|
||||
internal static class RegionLoader
|
||||
{
|
||||
private static readonly ILogger logger = LogFactory.GetLogger(typeof(RegionLoader));
|
||||
|
||||
internal static void LoadRegions()
|
||||
{
|
||||
var path = Path.Join(Core.BaseDirectory, "Data/regions.json");
|
||||
|
||||
var failures = new List<string>();
|
||||
var count = 0;
|
||||
|
||||
logger.Information("Loading regions");
|
||||
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var regions = JsonConfig.Deserialize<List<DynamicJson>>(path);
|
||||
if (regions == null)
|
||||
{
|
||||
throw new JsonException($"Failed to deserialize {path}.");
|
||||
}
|
||||
|
||||
foreach (var json in regions)
|
||||
{
|
||||
var type = AssemblyHandler.FindTypeByName(json.Type);
|
||||
|
||||
if (type == null || !typeof(Region).IsAssignableFrom(type))
|
||||
{
|
||||
failures.Add($"\tInvalid region type {json.Type}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var region = type.CreateInstance<Region>(json, JsonConfig.DefaultOptions);
|
||||
region?.Register();
|
||||
count++;
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
if (failures.Count == 0)
|
||||
{
|
||||
logger.Information(
|
||||
"Loading regions {Status} ({Count} regions, {FailureCount} failures) ({Duration:F2} seconds)",
|
||||
"done",
|
||||
count,
|
||||
failures.Count,
|
||||
stopwatch.Elapsed.TotalSeconds
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Warning(
|
||||
$"Loading regions {{Status}} ({{Count}} regions, {{FailureCount}} failures) ({{Duration:F2}} seconds){Environment.NewLine}{{Failures}}",
|
||||
"failed",
|
||||
count,
|
||||
failures.Count,
|
||||
stopwatch.Elapsed.TotalSeconds,
|
||||
failures
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ namespace Server.Commands
|
|||
|
||||
if (map != null)
|
||||
{
|
||||
var reg = from.Region;
|
||||
var reg = Region.Find(from.Location, from.Map);
|
||||
|
||||
if (!reg.IsDefault)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ namespace Server.Engines.ConPVP
|
|||
|
||||
if (m_Region != null)
|
||||
{
|
||||
m_Region.Disabled = !m_IsGuarded;
|
||||
m_Region.GuardsDisabled = !m_IsGuarded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Server.Engines.ConPVP
|
|||
{
|
||||
GoLocation = goloc;
|
||||
|
||||
Disabled = !isGuarded;
|
||||
GuardsDisabled = !isGuarded;
|
||||
|
||||
Register();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4416,10 +4416,10 @@ namespace Server.Mobiles
|
|||
Map map;
|
||||
|
||||
var dungeon = Region.GetRegion<DungeonRegion>();
|
||||
if (dungeon != null && dungeon.EntranceLocation != Point3D.Zero)
|
||||
if (dungeon != null && dungeon.Entrance != Point3D.Zero)
|
||||
{
|
||||
loc = dungeon.EntranceLocation;
|
||||
map = dungeon.EntranceMap;
|
||||
loc = dungeon.Entrance;
|
||||
map = dungeon.Map;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,178 +1,170 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using Server.Gumps;
|
||||
using Server.Json;
|
||||
using Server.Mobiles;
|
||||
using Server.Spells;
|
||||
|
||||
namespace Server.Regions
|
||||
namespace Server.Regions;
|
||||
|
||||
public class BaseRegion : Region
|
||||
{
|
||||
public class BaseRegion : Region
|
||||
private static readonly List<Rectangle3D> m_RectBuffer1 = new();
|
||||
private static readonly List<Rectangle3D> m_RectBuffer2 = new();
|
||||
|
||||
public BaseRegion(string name, Map map, int priority, params Rectangle2D[] area) : base(name, map, priority, area)
|
||||
{
|
||||
private static readonly List<Rectangle3D> m_RectBuffer1 = new();
|
||||
private static readonly List<Rectangle3D> m_RectBuffer2 = new();
|
||||
}
|
||||
|
||||
public BaseRegion(string name, Map map, int priority, params Rectangle2D[] area) : base(name, map, priority, area)
|
||||
{
|
||||
}
|
||||
public BaseRegion(string name, Map map, int priority, params Rectangle3D[] area) : base(name, map, priority, area)
|
||||
{
|
||||
}
|
||||
|
||||
public BaseRegion(string name, Map map, int priority, params Rectangle3D[] area) : base(name, map, priority, area)
|
||||
{
|
||||
}
|
||||
public BaseRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area)
|
||||
{
|
||||
}
|
||||
|
||||
public BaseRegion(string name, Map map, Region parent, params Rectangle2D[] area) : base(name, map, parent, area)
|
||||
{
|
||||
}
|
||||
public BaseRegion(string name, Map map, Region parent, params Rectangle2D[] area) : base(name, map, parent, area)
|
||||
{
|
||||
}
|
||||
|
||||
public BaseRegion(string name, Map map, Region parent, params Rectangle3D[] area) : base(name, map, parent, area)
|
||||
{
|
||||
}
|
||||
public BaseRegion(string name, Map map, Region parent, params Rectangle3D[] area) : base(name, map, parent, area)
|
||||
{
|
||||
}
|
||||
|
||||
public BaseRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
public bool ExcludeFromParentSpawns { get; set; }
|
||||
|
||||
public Rectangle3D[] Rectangles { get; private set; }
|
||||
public int[] RectangleWeights { get; private set; }
|
||||
public int TotalWeight { get; private set; }
|
||||
|
||||
public virtual bool YoungProtected => true;
|
||||
public virtual bool YoungMayEnter => true;
|
||||
public virtual bool MountsAllowed => true;
|
||||
public virtual bool DeadMayEnter => true;
|
||||
public virtual bool ResurrectionAllowed => true;
|
||||
public virtual bool LogoutAllowed => true;
|
||||
|
||||
public string RuneName { get; set; }
|
||||
|
||||
public bool NoLogoutDelay { get; set; }
|
||||
|
||||
public static string GetRuneNameFor(Region region)
|
||||
{
|
||||
while (region != null)
|
||||
{
|
||||
if (json.GetProperty<string>("rune", options, out var runeName))
|
||||
var br = region as BaseRegion;
|
||||
|
||||
if (br?.RuneName != null)
|
||||
{
|
||||
RuneName = runeName;
|
||||
return br.RuneName;
|
||||
}
|
||||
|
||||
NoLogoutDelay = json.GetProperty<bool>("logoutDelay", options, out var logoutDelay) && !logoutDelay;
|
||||
region = region.Parent;
|
||||
}
|
||||
|
||||
public bool ExcludeFromParentSpawns { get; set; }
|
||||
return null;
|
||||
}
|
||||
|
||||
public Rectangle3D[] Rectangles { get; private set; }
|
||||
public int[] RectangleWeights { get; private set; }
|
||||
public int TotalWeight { get; private set; }
|
||||
public override TimeSpan GetLogoutDelay(Mobile m) =>
|
||||
NoLogoutDelay && m.Aggressors.Count == 0 && m.Aggressed.Count == 0 && !m.Criminal
|
||||
? TimeSpan.Zero
|
||||
: base.GetLogoutDelay(m);
|
||||
|
||||
public virtual bool YoungProtected => true;
|
||||
public virtual bool YoungMayEnter => true;
|
||||
public virtual bool MountsAllowed => true;
|
||||
public virtual bool DeadMayEnter => true;
|
||||
public virtual bool ResurrectionAllowed => true;
|
||||
public virtual bool LogoutAllowed => true;
|
||||
|
||||
public string RuneName { get; set; }
|
||||
|
||||
public bool NoLogoutDelay { get; set; }
|
||||
|
||||
public static string GetRuneNameFor(Region region)
|
||||
public override void OnEnter(Mobile m)
|
||||
{
|
||||
if (m is PlayerMobile mobile && mobile.Young && !YoungProtected)
|
||||
{
|
||||
while (region != null)
|
||||
{
|
||||
var br = region as BaseRegion;
|
||||
mobile.SendGump(new YoungDungeonWarning());
|
||||
}
|
||||
}
|
||||
|
||||
if (br?.RuneName != null)
|
||||
public override bool AcceptsSpawnsFrom(Region region) =>
|
||||
(region == this || !ExcludeFromParentSpawns) && base.AcceptsSpawnsFrom(region);
|
||||
|
||||
// TODO: Clean this up
|
||||
public void InitRectangles()
|
||||
{
|
||||
if (Rectangles != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Test if area rectangles are overlapping, and in that case break them into smaller non overlapping rectangles
|
||||
for (var i = 0; i < Area.Length; i++)
|
||||
{
|
||||
m_RectBuffer2.Add(Area[i]);
|
||||
|
||||
for (var j = 0; j < m_RectBuffer1.Count && m_RectBuffer2.Count > 0; j++)
|
||||
{
|
||||
var comp = m_RectBuffer1[j];
|
||||
|
||||
for (var k = m_RectBuffer2.Count - 1; k >= 0; k--)
|
||||
{
|
||||
return br.RuneName;
|
||||
}
|
||||
var rect = m_RectBuffer2[k];
|
||||
|
||||
region = region.Parent;
|
||||
}
|
||||
int l1 = rect.Start.X, r1 = rect.End.X, t1 = rect.Start.Y, b1 = rect.End.Y;
|
||||
int l2 = comp.Start.X, r2 = comp.End.X, t2 = comp.Start.Y, b2 = comp.End.Y;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override TimeSpan GetLogoutDelay(Mobile m) =>
|
||||
NoLogoutDelay && m.Aggressors.Count == 0 && m.Aggressed.Count == 0 && !m.Criminal
|
||||
? TimeSpan.Zero
|
||||
: base.GetLogoutDelay(m);
|
||||
|
||||
public override void OnEnter(Mobile m)
|
||||
{
|
||||
if (m is PlayerMobile mobile && mobile.Young && !YoungProtected)
|
||||
{
|
||||
mobile.SendGump(new YoungDungeonWarning());
|
||||
}
|
||||
}
|
||||
|
||||
public override bool AcceptsSpawnsFrom(Region region) =>
|
||||
(region == this || !ExcludeFromParentSpawns) && base.AcceptsSpawnsFrom(region);
|
||||
|
||||
// TODO: Clean this up
|
||||
public void InitRectangles()
|
||||
{
|
||||
if (Rectangles != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Test if area rectangles are overlapping, and in that case break them into smaller non overlapping rectangles
|
||||
for (var i = 0; i < Area.Length; i++)
|
||||
{
|
||||
m_RectBuffer2.Add(Area[i]);
|
||||
|
||||
for (var j = 0; j < m_RectBuffer1.Count && m_RectBuffer2.Count > 0; j++)
|
||||
{
|
||||
var comp = m_RectBuffer1[j];
|
||||
|
||||
for (var k = m_RectBuffer2.Count - 1; k >= 0; k--)
|
||||
if (l1 < r2 && r1 > l2 && t1 < b2 && b1 > t2)
|
||||
{
|
||||
var rect = m_RectBuffer2[k];
|
||||
m_RectBuffer2.RemoveAt(k);
|
||||
|
||||
int l1 = rect.Start.X, r1 = rect.End.X, t1 = rect.Start.Y, b1 = rect.End.Y;
|
||||
int l2 = comp.Start.X, r2 = comp.End.X, t2 = comp.Start.Y, b2 = comp.End.Y;
|
||||
var sz = rect.Start.Z;
|
||||
var ez = rect.End.X;
|
||||
|
||||
if (l1 < r2 && r1 > l2 && t1 < b2 && b1 > t2)
|
||||
if (l1 < l2)
|
||||
{
|
||||
m_RectBuffer2.RemoveAt(k);
|
||||
m_RectBuffer2.Add(new Rectangle3D(new Point3D(l1, t1, sz), new Point3D(l2, b1, ez)));
|
||||
}
|
||||
|
||||
var sz = rect.Start.Z;
|
||||
var ez = rect.End.X;
|
||||
if (r1 > r2)
|
||||
{
|
||||
m_RectBuffer2.Add(new Rectangle3D(new Point3D(r2, t1, sz), new Point3D(r1, b1, ez)));
|
||||
}
|
||||
|
||||
if (l1 < l2)
|
||||
{
|
||||
m_RectBuffer2.Add(new Rectangle3D(new Point3D(l1, t1, sz), new Point3D(l2, b1, ez)));
|
||||
}
|
||||
if (t1 < t2)
|
||||
{
|
||||
m_RectBuffer2.Add(
|
||||
new Rectangle3D(
|
||||
new Point3D(Math.Max(l1, l2), t1, sz),
|
||||
new Point3D(Math.Min(r1, r2), t2, ez)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (r1 > r2)
|
||||
{
|
||||
m_RectBuffer2.Add(new Rectangle3D(new Point3D(r2, t1, sz), new Point3D(r1, b1, ez)));
|
||||
}
|
||||
|
||||
if (t1 < t2)
|
||||
{
|
||||
m_RectBuffer2.Add(
|
||||
new Rectangle3D(
|
||||
new Point3D(Math.Max(l1, l2), t1, sz),
|
||||
new Point3D(Math.Min(r1, r2), t2, ez)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (b1 > b2)
|
||||
{
|
||||
m_RectBuffer2.Add(
|
||||
new Rectangle3D(
|
||||
new Point3D(Math.Max(l1, l2), b2, sz),
|
||||
new Point3D(Math.Min(r1, r2), b1, ez)
|
||||
)
|
||||
);
|
||||
}
|
||||
if (b1 > b2)
|
||||
{
|
||||
m_RectBuffer2.Add(
|
||||
new Rectangle3D(
|
||||
new Point3D(Math.Max(l1, l2), b2, sz),
|
||||
new Point3D(Math.Min(r1, r2), b1, ez)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_RectBuffer1.AddRange(m_RectBuffer2);
|
||||
m_RectBuffer2.Clear();
|
||||
}
|
||||
|
||||
Rectangles = m_RectBuffer1.ToArray();
|
||||
m_RectBuffer1.Clear();
|
||||
|
||||
RectangleWeights = new int[Rectangles.Length];
|
||||
for (var i = 0; i < Rectangles.Length; i++)
|
||||
{
|
||||
var rect = Rectangles[i];
|
||||
var weight = rect.Width * rect.Height;
|
||||
|
||||
RectangleWeights[i] = weight;
|
||||
TotalWeight += weight;
|
||||
}
|
||||
m_RectBuffer1.AddRange(m_RectBuffer2);
|
||||
m_RectBuffer2.Clear();
|
||||
}
|
||||
|
||||
public override string ToString() => Name ?? RuneName ?? GetType().Name;
|
||||
Rectangles = m_RectBuffer1.ToArray();
|
||||
m_RectBuffer1.Clear();
|
||||
|
||||
public virtual bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => true;
|
||||
RectangleWeights = new int[Rectangles.Length];
|
||||
for (var i = 0; i < Rectangles.Length; i++)
|
||||
{
|
||||
var rect = Rectangles[i];
|
||||
var weight = rect.Width * rect.Height;
|
||||
|
||||
RectangleWeights[i] = weight;
|
||||
TotalWeight += weight;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => Name ?? RuneName ?? GetType().Name;
|
||||
|
||||
public virtual bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,26 @@
|
|||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
namespace Server.Regions;
|
||||
|
||||
namespace Server.Regions
|
||||
public class DungeonRegion : BaseRegion
|
||||
{
|
||||
public class DungeonRegion : BaseRegion
|
||||
public DungeonRegion(string name, Map map, Region parent, params Rectangle3D[] area) : base(name, map, parent, area)
|
||||
{
|
||||
public DungeonRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
{
|
||||
if (json.GetProperty("map", options, out Map map))
|
||||
{
|
||||
EntranceMap = map;
|
||||
}
|
||||
|
||||
if (json.GetProperty("entrance", options, out Point3D entrance))
|
||||
{
|
||||
EntranceLocation = entrance;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool YoungProtected => false;
|
||||
|
||||
public Point3D EntranceLocation { get; set; }
|
||||
|
||||
public Map EntranceMap { get; set; }
|
||||
|
||||
public override bool AllowHousing(Mobile from, Point3D p) => false;
|
||||
|
||||
public override void AlterLightLevel(Mobile m, ref int global, ref int personal)
|
||||
{
|
||||
global = LightCycle.DungeonLevel;
|
||||
}
|
||||
|
||||
public override bool CanUseStuckMenu(Mobile m) => Map != Map.Felucca && base.CanUseStuckMenu(m);
|
||||
}
|
||||
|
||||
public DungeonRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool YoungProtected => false;
|
||||
|
||||
public Point3D Entrance { get; set; }
|
||||
|
||||
public override bool AllowHousing(Mobile from, Point3D p) => false;
|
||||
|
||||
public override void AlterLightLevel(Mobile m, ref int global, ref int personal)
|
||||
{
|
||||
global = LightCycle.DungeonLevel;
|
||||
}
|
||||
|
||||
public override bool CanUseStuckMenu(Mobile m) => Map != Map.Felucca && base.CanUseStuckMenu(m);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,33 @@
|
|||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Spells;
|
||||
using Server.Spells.Sixth;
|
||||
|
||||
namespace Server.Regions
|
||||
namespace Server.Regions;
|
||||
|
||||
public class GreenAcresRegion : BaseRegion
|
||||
{
|
||||
public class GreenAcresRegion : BaseRegion
|
||||
public GreenAcresRegion(string name, Map map, Region parent, params Rectangle3D[] area) : base(name, map, parent, area)
|
||||
{
|
||||
public GreenAcresRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
}
|
||||
|
||||
public GreenAcresRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool AllowHousing(Mobile from, Point3D p) =>
|
||||
from.AccessLevel != AccessLevel.Player && base.AllowHousing(from, p);
|
||||
|
||||
public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) =>
|
||||
m.AccessLevel != AccessLevel.Player;
|
||||
|
||||
public override bool OnBeginSpellCast(Mobile m, ISpell s)
|
||||
{
|
||||
if (m.AccessLevel == AccessLevel.Player && s is MarkSpell)
|
||||
{
|
||||
m.SendLocalizedMessage(501802); // Thy spell doth not appear to work...
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool AllowHousing(Mobile from, Point3D p) =>
|
||||
from.AccessLevel != AccessLevel.Player && base.AllowHousing(from, p);
|
||||
|
||||
public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) =>
|
||||
m.AccessLevel != AccessLevel.Player;
|
||||
|
||||
public override bool OnBeginSpellCast(Mobile m, ISpell s)
|
||||
{
|
||||
if (m.AccessLevel == AccessLevel.Player && s is MarkSpell)
|
||||
{
|
||||
m.SendLocalizedMessage(501802); // Thy spell doth not appear to work...
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.OnBeginSpellCast(m, s);
|
||||
}
|
||||
return base.OnBeginSpellCast(m, s);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,131 +1,90 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Logging;
|
||||
using Server.Mobiles;
|
||||
using Server.Utilities;
|
||||
|
||||
namespace Server.Regions
|
||||
namespace Server.Regions;
|
||||
|
||||
public class GuardedRegion : BaseRegion
|
||||
{
|
||||
public class GuardedRegion : BaseRegion
|
||||
private static readonly ILogger logger = LogFactory.GetLogger(typeof(GuardedRegion));
|
||||
|
||||
private static readonly object[] m_GuardParams = new object[1];
|
||||
|
||||
private readonly Dictionary<Mobile, GuardTimer> m_GuardCandidates = new();
|
||||
|
||||
public GuardedRegion(string name, Map map, int priority, params Rectangle3D[] area) :
|
||||
base(name, map, priority, area) => GuardType = DefaultGuardType;
|
||||
|
||||
public GuardedRegion(string name, Map map, int priority, params Rectangle2D[] area) :
|
||||
base(name, map, priority, area) => GuardType = DefaultGuardType;
|
||||
|
||||
public GuardedRegion(string name, Map map, Region parent, params Rectangle3D[] area) : base(name, map, parent, area) =>
|
||||
GuardType = DefaultGuardType;
|
||||
|
||||
public GuardedRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area) => GuardType = DefaultGuardType;
|
||||
|
||||
public GuardedRegion(string name, Map map, Region parent, int priority, Type guardType, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area) => GuardType = guardType ?? DefaultGuardType;
|
||||
|
||||
public Type GuardType { get; set; }
|
||||
|
||||
public bool GuardsDisabled { get; set; }
|
||||
|
||||
public virtual bool AllowReds => Core.AOS;
|
||||
|
||||
public virtual Type DefaultGuardType
|
||||
{
|
||||
private static readonly ILogger logger = LogFactory.GetLogger(typeof(GuardedRegion));
|
||||
|
||||
private static readonly object[] m_GuardParams = new object[1];
|
||||
|
||||
private readonly Dictionary<Mobile, GuardTimer> m_GuardCandidates = new();
|
||||
private readonly Type m_GuardType;
|
||||
|
||||
public GuardedRegion(string name, Map map, int priority, params Rectangle3D[] area) :
|
||||
base(name, map, priority, area) =>
|
||||
m_GuardType = DefaultGuardType;
|
||||
|
||||
public GuardedRegion(string name, Map map, int priority, params Rectangle2D[] area) :
|
||||
base(name, map, priority, area) =>
|
||||
m_GuardType = DefaultGuardType;
|
||||
|
||||
public GuardedRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
get
|
||||
{
|
||||
if (json.GetProperty("guardsType", options, out string guardType))
|
||||
if (Map == Map.Ilshenar || Map == Map.Malas)
|
||||
{
|
||||
m_GuardType = AssemblyHandler.FindTypeByName(guardType);
|
||||
|
||||
if (!typeof(BaseGuard).IsAssignableFrom(m_GuardType))
|
||||
{
|
||||
logger.Warning("Invalid guard type for region '{Region}'", this);
|
||||
m_GuardType = DefaultGuardType;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_GuardType = DefaultGuardType;
|
||||
return typeof(ArcherGuard);
|
||||
}
|
||||
|
||||
Disabled = json.GetProperty("guardsDisabled", options, out bool disabled) && disabled;
|
||||
return typeof(WarriorGuard);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Disabled { get; set; }
|
||||
public virtual bool IsDisabled() => GuardsDisabled;
|
||||
|
||||
public virtual bool AllowReds => Core.AOS;
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register("CheckGuarded", AccessLevel.GameMaster, CheckGuarded_OnCommand);
|
||||
CommandSystem.Register("SetGuarded", AccessLevel.Administrator, SetGuarded_OnCommand);
|
||||
CommandSystem.Register("ToggleGuarded", AccessLevel.Administrator, ToggleGuarded_OnCommand);
|
||||
}
|
||||
|
||||
public virtual Type DefaultGuardType
|
||||
[Usage("CheckGuarded"), Description("Returns a value indicating if the current region is guarded or not.")]
|
||||
private static void CheckGuarded_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
var from = e.Mobile;
|
||||
var reg = from.Region.GetRegion<GuardedRegion>();
|
||||
|
||||
if (reg == null)
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Map == Map.Ilshenar || Map == Map.Malas)
|
||||
{
|
||||
return typeof(ArcherGuard);
|
||||
}
|
||||
|
||||
return typeof(WarriorGuard);
|
||||
}
|
||||
from.SendMessage("You are not in a guardable region.");
|
||||
}
|
||||
|
||||
public virtual bool IsDisabled() => Disabled;
|
||||
|
||||
public static void Initialize()
|
||||
else if (reg.GuardsDisabled)
|
||||
{
|
||||
CommandSystem.Register("CheckGuarded", AccessLevel.GameMaster, CheckGuarded_OnCommand);
|
||||
CommandSystem.Register("SetGuarded", AccessLevel.Administrator, SetGuarded_OnCommand);
|
||||
CommandSystem.Register("ToggleGuarded", AccessLevel.Administrator, ToggleGuarded_OnCommand);
|
||||
from.SendMessage("The guards in this region have been disabled.");
|
||||
}
|
||||
|
||||
[Usage("CheckGuarded"), Description("Returns a value indicating if the current region is guarded or not.")]
|
||||
private static void CheckGuarded_OnCommand(CommandEventArgs e)
|
||||
else
|
||||
{
|
||||
var from = e.Mobile;
|
||||
var reg = from.Region.GetRegion<GuardedRegion>();
|
||||
|
||||
if (reg == null)
|
||||
{
|
||||
from.SendMessage("You are not in a guardable region.");
|
||||
}
|
||||
else if (reg.Disabled)
|
||||
{
|
||||
from.SendMessage("The guards in this region have been disabled.");
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage("This region is actively guarded.");
|
||||
}
|
||||
from.SendMessage("This region is actively guarded.");
|
||||
}
|
||||
}
|
||||
|
||||
[Usage("SetGuarded <true|false>"), Description("Enables or disables guards for the current region.")]
|
||||
private static void SetGuarded_OnCommand(CommandEventArgs e)
|
||||
[Usage("SetGuarded <true|false>"), Description("Enables or disables guards for the current region.")]
|
||||
private static void SetGuarded_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
var from = e.Mobile;
|
||||
|
||||
if (e.Length == 1)
|
||||
{
|
||||
var from = e.Mobile;
|
||||
|
||||
if (e.Length == 1)
|
||||
{
|
||||
var reg = from.Region.GetRegion<GuardedRegion>();
|
||||
|
||||
if (reg == null)
|
||||
{
|
||||
from.SendMessage("You are not in a guardable region.");
|
||||
}
|
||||
else
|
||||
{
|
||||
reg.Disabled = !e.GetBoolean(0);
|
||||
|
||||
from.SendMessage(
|
||||
reg.Disabled
|
||||
? "The guards in this region have been disabled."
|
||||
: "The guards in this region have been enabled."
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage("Format: SetGuarded <true|false>");
|
||||
}
|
||||
}
|
||||
|
||||
[Usage("ToggleGuarded"), Description("Toggles the state of guards for the current region.")]
|
||||
private static void ToggleGuarded_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
var from = e.Mobile;
|
||||
var reg = from.Region.GetRegion<GuardedRegion>();
|
||||
|
||||
if (reg == null)
|
||||
|
|
@ -134,252 +93,278 @@ namespace Server.Regions
|
|||
}
|
||||
else
|
||||
{
|
||||
reg.Disabled = !reg.Disabled;
|
||||
reg.GuardsDisabled = !e.GetBoolean(0);
|
||||
|
||||
from.SendMessage(
|
||||
reg.Disabled
|
||||
reg.GuardsDisabled
|
||||
? "The guards in this region have been disabled."
|
||||
: "The guards in this region have been enabled."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static GuardedRegion Disable(GuardedRegion reg)
|
||||
else
|
||||
{
|
||||
reg.Disabled = true;
|
||||
return reg;
|
||||
from.SendMessage("Format: SetGuarded <true|false>");
|
||||
}
|
||||
}
|
||||
|
||||
[Usage("ToggleGuarded"), Description("Toggles the state of guards for the current region.")]
|
||||
private static void ToggleGuarded_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
var from = e.Mobile;
|
||||
var reg = from.Region.GetRegion<GuardedRegion>();
|
||||
|
||||
if (reg == null)
|
||||
{
|
||||
from.SendMessage("You are not in a guardable region.");
|
||||
}
|
||||
else
|
||||
{
|
||||
reg.GuardsDisabled = !reg.GuardsDisabled;
|
||||
|
||||
from.SendMessage(
|
||||
reg.GuardsDisabled
|
||||
? "The guards in this region have been disabled."
|
||||
: "The guards in this region have been enabled."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static GuardedRegion Disable(GuardedRegion reg)
|
||||
{
|
||||
reg.GuardsDisabled = true;
|
||||
return reg;
|
||||
}
|
||||
|
||||
public virtual bool CheckVendorAccess(BaseVendor vendor, Mobile from) =>
|
||||
from.AccessLevel >= AccessLevel.GameMaster || IsDisabled() || from.Kills < 5;
|
||||
|
||||
public override bool OnBeginSpellCast(Mobile m, ISpell s)
|
||||
{
|
||||
if (!IsDisabled() && !s.OnCastInTown(this))
|
||||
{
|
||||
m.SendLocalizedMessage(500946); // You cannot cast this in town!
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool CheckVendorAccess(BaseVendor vendor, Mobile from) =>
|
||||
from.AccessLevel >= AccessLevel.GameMaster || IsDisabled() || from.Kills < 5;
|
||||
return base.OnBeginSpellCast(m, s);
|
||||
}
|
||||
|
||||
public override bool OnBeginSpellCast(Mobile m, ISpell s)
|
||||
public override bool AllowHousing(Mobile from, Point3D p) => false;
|
||||
|
||||
public override void MakeGuard(Mobile focus)
|
||||
{
|
||||
var eable = focus.GetMobilesInRange<BaseGuard>(8);
|
||||
var useGuard = eable.FirstOrDefault(m => m.Focus == null);
|
||||
|
||||
eable.Free();
|
||||
|
||||
if (useGuard == null)
|
||||
{
|
||||
if (!IsDisabled() && !s.OnCastInTown(this))
|
||||
m_GuardParams[0] = focus;
|
||||
|
||||
try
|
||||
{
|
||||
m.SendLocalizedMessage(500946); // You cannot cast this in town!
|
||||
return false;
|
||||
GuardType.CreateInstance<object>(m_GuardParams);
|
||||
}
|
||||
|
||||
return base.OnBeginSpellCast(m, s);
|
||||
}
|
||||
|
||||
public override bool AllowHousing(Mobile from, Point3D p) => false;
|
||||
|
||||
public override void MakeGuard(Mobile focus)
|
||||
{
|
||||
var eable = focus.GetMobilesInRange<BaseGuard>(8);
|
||||
var useGuard = eable.FirstOrDefault(m => m.Focus == null);
|
||||
|
||||
eable.Free();
|
||||
|
||||
if (useGuard == null)
|
||||
catch
|
||||
{
|
||||
m_GuardParams[0] = focus;
|
||||
|
||||
try
|
||||
{
|
||||
m_GuardType.CreateInstance<object>(m_GuardParams);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
useGuard.Focus = focus;
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEnter(Mobile m)
|
||||
else
|
||||
{
|
||||
if (IsDisabled())
|
||||
useGuard.Focus = focus;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEnter(Mobile m)
|
||||
{
|
||||
if (IsDisabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AllowReds && m.Kills >= 5)
|
||||
{
|
||||
CheckGuardCandidate(m);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnExit(Mobile m)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSpeech(SpeechEventArgs args)
|
||||
{
|
||||
base.OnSpeech(args);
|
||||
|
||||
if (IsDisabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Mobile.Alive && args.HasKeyword(0x0007)) // *guards*
|
||||
{
|
||||
CallGuards(args.Mobile.Location);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAggressed(Mobile aggressor, Mobile aggressed, bool criminal)
|
||||
{
|
||||
base.OnAggressed(aggressor, aggressed, criminal);
|
||||
|
||||
if (!IsDisabled() && aggressor != aggressed && criminal)
|
||||
{
|
||||
CheckGuardCandidate(aggressor);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGotBeneficialAction(Mobile helper, Mobile helped)
|
||||
{
|
||||
base.OnGotBeneficialAction(helper, helped);
|
||||
|
||||
if (IsDisabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var noto = Notoriety.Compute(helper, helped);
|
||||
|
||||
if (helper != helped && noto is Notoriety.Criminal or Notoriety.Murderer)
|
||||
{
|
||||
CheckGuardCandidate(helper);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnCriminalAction(Mobile m, bool message)
|
||||
{
|
||||
base.OnCriminalAction(m, message);
|
||||
|
||||
if (!IsDisabled())
|
||||
{
|
||||
CheckGuardCandidate(m);
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckGuardCandidate(Mobile m)
|
||||
{
|
||||
if (IsDisabled() || !IsGuardCandidate(m))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_GuardCandidates.TryGetValue(m, out var timer))
|
||||
{
|
||||
timer = new GuardTimer(m, m_GuardCandidates);
|
||||
timer.Start();
|
||||
|
||||
m_GuardCandidates[m] = timer;
|
||||
m.SendLocalizedMessage(502275); // Guards can now be called on you!
|
||||
|
||||
var map = m.Map;
|
||||
|
||||
if (map == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AllowReds && m.Kills >= 5)
|
||||
Mobile fakeCall = null;
|
||||
var prio = 0.0;
|
||||
|
||||
foreach (var v in m.GetMobilesInRange(8))
|
||||
{
|
||||
CheckGuardCandidate(m);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnExit(Mobile m)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSpeech(SpeechEventArgs args)
|
||||
{
|
||||
base.OnSpeech(args);
|
||||
|
||||
if (IsDisabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Mobile.Alive && args.HasKeyword(0x0007)) // *guards*
|
||||
{
|
||||
CallGuards(args.Mobile.Location);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAggressed(Mobile aggressor, Mobile aggressed, bool criminal)
|
||||
{
|
||||
base.OnAggressed(aggressor, aggressed, criminal);
|
||||
|
||||
if (!IsDisabled() && aggressor != aggressed && criminal)
|
||||
{
|
||||
CheckGuardCandidate(aggressor);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGotBeneficialAction(Mobile helper, Mobile helped)
|
||||
{
|
||||
base.OnGotBeneficialAction(helper, helped);
|
||||
|
||||
if (IsDisabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var noto = Notoriety.Compute(helper, helped);
|
||||
|
||||
if (helper != helped && noto is Notoriety.Criminal or Notoriety.Murderer)
|
||||
{
|
||||
CheckGuardCandidate(helper);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnCriminalAction(Mobile m, bool message)
|
||||
{
|
||||
base.OnCriminalAction(m, message);
|
||||
|
||||
if (!IsDisabled())
|
||||
{
|
||||
CheckGuardCandidate(m);
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckGuardCandidate(Mobile m)
|
||||
{
|
||||
if (IsDisabled() || !IsGuardCandidate(m))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_GuardCandidates.TryGetValue(m, out var timer))
|
||||
{
|
||||
timer = new GuardTimer(m, m_GuardCandidates);
|
||||
timer.Start();
|
||||
|
||||
m_GuardCandidates[m] = timer;
|
||||
m.SendLocalizedMessage(502275); // Guards can now be called on you!
|
||||
|
||||
var map = m.Map;
|
||||
|
||||
if (map == null)
|
||||
if (!v.Player && v != m && !IsGuardCandidate(v) &&
|
||||
((v as BaseCreature)?.IsHumanInTown() ?? v.Body.IsHuman && v.Region.IsPartOf(this)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var dist = m.GetDistanceToSqrt(v);
|
||||
|
||||
Mobile fakeCall = null;
|
||||
var prio = 0.0;
|
||||
|
||||
foreach (var v in m.GetMobilesInRange(8))
|
||||
{
|
||||
if (!v.Player && v != m && !IsGuardCandidate(v) &&
|
||||
((v as BaseCreature)?.IsHumanInTown() ?? v.Body.IsHuman && v.Region.IsPartOf(this)))
|
||||
if (fakeCall == null || dist < prio)
|
||||
{
|
||||
var dist = m.GetDistanceToSqrt(v);
|
||||
|
||||
if (fakeCall == null || dist < prio)
|
||||
{
|
||||
fakeCall = v;
|
||||
prio = dist;
|
||||
}
|
||||
fakeCall = v;
|
||||
prio = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if (fakeCall != null)
|
||||
{
|
||||
fakeCall.Say(
|
||||
Utility.RandomList(
|
||||
1007037,
|
||||
501603,
|
||||
1013037,
|
||||
1013038,
|
||||
1013039,
|
||||
1013041,
|
||||
1013042,
|
||||
1013043,
|
||||
1013052
|
||||
)
|
||||
);
|
||||
MakeGuard(m);
|
||||
timer.Stop();
|
||||
m_GuardCandidates.Remove(m);
|
||||
m.SendLocalizedMessage(502276); // Guards can no longer be called on you.
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (fakeCall != null)
|
||||
{
|
||||
fakeCall.Say(
|
||||
Utility.RandomList(
|
||||
1007037,
|
||||
501603,
|
||||
1013037,
|
||||
1013038,
|
||||
1013039,
|
||||
1013041,
|
||||
1013042,
|
||||
1013043,
|
||||
1013052
|
||||
)
|
||||
);
|
||||
MakeGuard(m);
|
||||
timer.Stop();
|
||||
timer.Start();
|
||||
m_GuardCandidates.Remove(m);
|
||||
m.SendLocalizedMessage(502276); // Guards can no longer be called on you.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.Stop();
|
||||
timer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public void CallGuards(Point3D p)
|
||||
{
|
||||
if (IsDisabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var eable = Map.GetMobilesInRange(p, 14);
|
||||
|
||||
foreach (var m in eable)
|
||||
{
|
||||
if (IsGuardCandidate(m) &&
|
||||
(!AllowReds && m.Kills >= 5 && m.Region.IsPartOf(this) || m_GuardCandidates.ContainsKey(m)))
|
||||
{
|
||||
if (m_GuardCandidates.Remove(m, out var timer))
|
||||
{
|
||||
timer.Stop();
|
||||
}
|
||||
|
||||
MakeGuard(m);
|
||||
m.SendLocalizedMessage(502276); // Guards can no longer be called on you.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void CallGuards(Point3D p)
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
public bool IsGuardCandidate(Mobile m) =>
|
||||
m is not BaseGuard && m.Alive && m.AccessLevel <= AccessLevel.Player && !m.Blessed &&
|
||||
(m is not BaseCreature creature || !creature.IsInvulnerable) && !IsDisabled() &&
|
||||
(!AllowReds && m.Kills >= 5 || m.Criminal);
|
||||
|
||||
private class GuardTimer : Timer
|
||||
{
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly Dictionary<Mobile, GuardTimer> m_Table;
|
||||
|
||||
public GuardTimer(Mobile m, Dictionary<Mobile, GuardTimer> table) : base(TimeSpan.FromSeconds(15.0))
|
||||
{
|
||||
if (IsDisabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var eable = Map.GetMobilesInRange(p, 14);
|
||||
|
||||
foreach (var m in eable)
|
||||
{
|
||||
if (IsGuardCandidate(m) &&
|
||||
(!AllowReds && m.Kills >= 5 && m.Region.IsPartOf(this) || m_GuardCandidates.ContainsKey(m)))
|
||||
{
|
||||
if (m_GuardCandidates.Remove(m, out var timer))
|
||||
{
|
||||
timer.Stop();
|
||||
}
|
||||
|
||||
MakeGuard(m);
|
||||
m.SendLocalizedMessage(502276); // Guards can no longer be called on you.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
m_Mobile = m;
|
||||
m_Table = table;
|
||||
}
|
||||
|
||||
public bool IsGuardCandidate(Mobile m) =>
|
||||
m is not BaseGuard && m.Alive && m.AccessLevel <= AccessLevel.Player && !m.Blessed &&
|
||||
(m is not BaseCreature creature || !creature.IsInvulnerable) && !IsDisabled() &&
|
||||
(!AllowReds && m.Kills >= 5 || m.Criminal);
|
||||
|
||||
private class GuardTimer : Timer
|
||||
protected override void OnTick()
|
||||
{
|
||||
private readonly Mobile m_Mobile;
|
||||
private readonly Dictionary<Mobile, GuardTimer> m_Table;
|
||||
|
||||
public GuardTimer(Mobile m, Dictionary<Mobile, GuardTimer> table) : base(TimeSpan.FromSeconds(15.0))
|
||||
if (m_Table.Remove(m_Mobile))
|
||||
{
|
||||
|
||||
m_Mobile = m;
|
||||
m_Table = table;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (m_Table.Remove(m_Mobile))
|
||||
{
|
||||
m_Mobile.SendLocalizedMessage(502276); // Guards can no longer be called on you.
|
||||
}
|
||||
m_Mobile.SendLocalizedMessage(502276); // Guards can no longer be called on you.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,407 +4,406 @@ using Server.Items;
|
|||
using Server.Mobiles;
|
||||
using Server.Multis;
|
||||
|
||||
namespace Server.Regions
|
||||
namespace Server.Regions;
|
||||
|
||||
public class HouseRegion : BaseRegion
|
||||
{
|
||||
public class HouseRegion : BaseRegion
|
||||
public static readonly int HousePriority = DefaultPriority + 1;
|
||||
|
||||
public static TimeSpan CombatHeatDelay = TimeSpan.FromSeconds(30.0);
|
||||
|
||||
private bool m_Recursion;
|
||||
|
||||
public HouseRegion(BaseHouse house) : base(null, house.Map, HousePriority, GetArea(house))
|
||||
{
|
||||
public static readonly int HousePriority = DefaultPriority + 1;
|
||||
House = house;
|
||||
|
||||
public static TimeSpan CombatHeatDelay = TimeSpan.FromSeconds(30.0);
|
||||
var ban = house.RelativeBanLocation;
|
||||
|
||||
private bool m_Recursion;
|
||||
GoLocation = new Point3D(house.X + ban.X, house.Y + ban.Y, house.Z + ban.Z);
|
||||
}
|
||||
|
||||
public HouseRegion(BaseHouse house) : base(null, house.Map, HousePriority, GetArea(house))
|
||||
public BaseHouse House { get; }
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.Login += OnLogin;
|
||||
}
|
||||
|
||||
public static void OnLogin(Mobile m)
|
||||
{
|
||||
var house = BaseHouse.FindHouseAt(m);
|
||||
|
||||
if (house?.Public == false && !house.IsFriend(m))
|
||||
{
|
||||
House = house;
|
||||
m.Location = house.BanLocation;
|
||||
}
|
||||
}
|
||||
|
||||
var ban = house.RelativeBanLocation;
|
||||
public override bool AllowHousing(Mobile from, Point3D p) => false;
|
||||
|
||||
GoLocation = new Point3D(house.X + ban.X, house.Y + ban.Y, house.Z + ban.Z);
|
||||
private static Rectangle3D[] GetArea(BaseHouse house)
|
||||
{
|
||||
var x = house.X;
|
||||
var y = house.Y;
|
||||
// int z = house.Z;
|
||||
|
||||
var houseArea = house.Area;
|
||||
var area = new Rectangle3D[houseArea.Length];
|
||||
|
||||
for (var i = 0; i < area.Length; i++)
|
||||
{
|
||||
var rect = houseArea[i];
|
||||
area[i] = ConvertTo3D(new Rectangle2D(x + rect.Start.X, y + rect.Start.Y, rect.Width, rect.Height));
|
||||
}
|
||||
|
||||
public BaseHouse House { get; }
|
||||
return area;
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
public override bool SendInaccessibleMessage(Item item, Mobile from)
|
||||
{
|
||||
if (item is Container)
|
||||
{
|
||||
EventSink.Login += OnLogin;
|
||||
item.SendLocalizedMessageTo(from, 501647); // That is secure.
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SendLocalizedMessageTo(from, 1061637); // You are not allowed to access this.
|
||||
}
|
||||
|
||||
public static void OnLogin(Mobile m)
|
||||
{
|
||||
var house = BaseHouse.FindHouseAt(m);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (house?.Public == false && !house.IsFriend(m))
|
||||
{
|
||||
m.Location = house.BanLocation;
|
||||
}
|
||||
public override bool CheckAccessibility(Item item, Mobile from) => House.CheckAccessibility(item, from);
|
||||
|
||||
// Use OnLocationChanged instead of OnEnter because it can be that we enter a house region even though we're not actually inside the house
|
||||
public override void OnLocationChanged(Mobile m, Point3D oldLocation)
|
||||
{
|
||||
if (m_Recursion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public override bool AllowHousing(Mobile from, Point3D p) => false;
|
||||
base.OnLocationChanged(m, oldLocation);
|
||||
|
||||
private static Rectangle3D[] GetArea(BaseHouse house)
|
||||
m_Recursion = true;
|
||||
|
||||
var bc = m as BaseCreature;
|
||||
|
||||
if (bc?.NoHouseRestrictions != true &&
|
||||
(bc?.IsHouseSummonable != true || BaseCreature.Summoning || House.IsInside(oldLocation, 16)))
|
||||
{
|
||||
var x = house.X;
|
||||
var y = house.Y;
|
||||
// int z = house.Z;
|
||||
|
||||
var houseArea = house.Area;
|
||||
var area = new Rectangle3D[houseArea.Length];
|
||||
|
||||
for (var i = 0; i < area.Length; i++)
|
||||
if ((House.Public || !House.IsAosRules) && House.IsBanned(m) && House.IsInside(m))
|
||||
{
|
||||
var rect = houseArea[i];
|
||||
area[i] = ConvertTo3D(new Rectangle2D(x + rect.Start.X, y + rect.Start.Y, rect.Width, rect.Height));
|
||||
}
|
||||
m.Location = House.BanLocation;
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
public override bool SendInaccessibleMessage(Item item, Mobile from)
|
||||
{
|
||||
if (item is Container)
|
||||
{
|
||||
item.SendLocalizedMessageTo(from, 501647); // That is secure.
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SendLocalizedMessageTo(from, 1061637); // You are not allowed to access this.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CheckAccessibility(Item item, Mobile from) => House.CheckAccessibility(item, from);
|
||||
|
||||
// Use OnLocationChanged instead of OnEnter because it can be that we enter a house region even though we're not actually inside the house
|
||||
public override void OnLocationChanged(Mobile m, Point3D oldLocation)
|
||||
{
|
||||
if (m_Recursion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
base.OnLocationChanged(m, oldLocation);
|
||||
|
||||
m_Recursion = true;
|
||||
|
||||
var bc = m as BaseCreature;
|
||||
|
||||
if (bc?.NoHouseRestrictions != true &&
|
||||
(bc?.IsHouseSummonable != true || BaseCreature.Summoning || House.IsInside(oldLocation, 16)))
|
||||
{
|
||||
if ((House.Public || !House.IsAosRules) && House.IsBanned(m) && House.IsInside(m))
|
||||
if (!Core.SE)
|
||||
{
|
||||
m.Location = House.BanLocation;
|
||||
|
||||
if (!Core.SE)
|
||||
{
|
||||
m.SendLocalizedMessage(501284); // You may not enter.
|
||||
}
|
||||
}
|
||||
else if (House.IsAosRules && !House.Public && !House.HasAccess(m) && House.IsInside(m))
|
||||
{
|
||||
m.Location = House.BanLocation;
|
||||
|
||||
if (!Core.SE)
|
||||
{
|
||||
m.SendLocalizedMessage(501284); // You may not enter.
|
||||
}
|
||||
}
|
||||
else if (House.IsCombatRestricted(m) && House.IsInside(m) && !House.IsInside(oldLocation, 16))
|
||||
{
|
||||
m.Location = House.BanLocation;
|
||||
m.SendLocalizedMessage(1061637); // You are not allowed to access this.
|
||||
}
|
||||
else if (House is HouseFoundation foundation && foundation.Customizer != null &&
|
||||
foundation.Customizer != m &&
|
||||
House.IsInside(m))
|
||||
{
|
||||
m.Location = House.BanLocation;
|
||||
m.SendLocalizedMessage(501284); // You may not enter.
|
||||
}
|
||||
}
|
||||
|
||||
if (House.InternalizedVendors.Count > 0 && House.IsInside(m) && !House.IsInside(oldLocation, 16) &&
|
||||
House.IsOwner(m) && m.Alive && !m.HasGump<NoticeGump>())
|
||||
else if (House.IsAosRules && !House.Public && !House.HasAccess(m) && House.IsInside(m))
|
||||
{
|
||||
m.SendGump(new NoticeGump(1060635, 30720, 1061826, 32512, 320, 180));
|
||||
}
|
||||
m.Location = House.BanLocation;
|
||||
|
||||
m_Recursion = false;
|
||||
if (!Core.SE)
|
||||
{
|
||||
m.SendLocalizedMessage(501284); // You may not enter.
|
||||
}
|
||||
}
|
||||
else if (House.IsCombatRestricted(m) && House.IsInside(m) && !House.IsInside(oldLocation, 16))
|
||||
{
|
||||
m.Location = House.BanLocation;
|
||||
m.SendLocalizedMessage(1061637); // You are not allowed to access this.
|
||||
}
|
||||
else if (House is HouseFoundation foundation && foundation.Customizer != null &&
|
||||
foundation.Customizer != m &&
|
||||
House.IsInside(m))
|
||||
{
|
||||
m.Location = House.BanLocation;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnMoveInto(Mobile from, Direction d, Point3D newLocation, Point3D oldLocation)
|
||||
if (House.InternalizedVendors.Count > 0 && House.IsInside(m) && !House.IsInside(oldLocation, 16) &&
|
||||
House.IsOwner(m) && m.Alive && !m.HasGump<NoticeGump>())
|
||||
{
|
||||
if (!base.OnMoveInto(from, d, newLocation, oldLocation))
|
||||
m.SendGump(new NoticeGump(1060635, 30720, 1061826, 32512, 320, 180));
|
||||
}
|
||||
|
||||
m_Recursion = false;
|
||||
}
|
||||
|
||||
public override bool OnMoveInto(Mobile from, Direction d, Point3D newLocation, Point3D oldLocation)
|
||||
{
|
||||
if (!base.OnMoveInto(from, d, newLocation, oldLocation))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var bc = from as BaseCreature;
|
||||
|
||||
if (bc?.NoHouseRestrictions != true)
|
||||
{
|
||||
if (bc?.Controlled == false) // Untamed creatures cannot enter public houses
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var bc = from as BaseCreature;
|
||||
|
||||
if (bc?.NoHouseRestrictions != true)
|
||||
if (bc?.IsHouseSummonable == true &&
|
||||
!(BaseCreature.Summoning || House.IsInside(oldLocation, 16)))
|
||||
{
|
||||
if (bc?.Controlled == false) // Untamed creatures cannot enter public houses
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bc?.IsHouseSummonable == true &&
|
||||
!(BaseCreature.Summoning || House.IsInside(oldLocation, 16)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bc?.Controlled == false && House.IsAosRules && !House.Public)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((House.Public || !House.IsAosRules) && House.IsBanned(from) && House.IsInside(newLocation, 16))
|
||||
{
|
||||
from.Location = House.BanLocation;
|
||||
|
||||
if (!Core.SE)
|
||||
{
|
||||
from.SendLocalizedMessage(501284); // You may not enter.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (House.IsAosRules && !House.Public && !House.HasAccess(from) && House.IsInside(newLocation, 16))
|
||||
{
|
||||
if (!Core.SE)
|
||||
{
|
||||
from.SendLocalizedMessage(501284); // You may not enter.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (House.IsCombatRestricted(from) && !House.IsInside(oldLocation, 16) && House.IsInside(newLocation, 16))
|
||||
{
|
||||
from.SendLocalizedMessage(1061637); // You are not allowed to access this.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (House is HouseFoundation foundation && foundation.Customizer != null && foundation.Customizer != from &&
|
||||
House.IsInside(newLocation, 16))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (House.InternalizedVendors.Count > 0 && House.IsInside(from) && !House.IsInside(oldLocation, 16) &&
|
||||
House.IsOwner(from) && from.Alive &&
|
||||
!from.HasGump<NoticeGump>())
|
||||
if (bc?.Controlled == false && House.IsAosRules && !House.Public)
|
||||
{
|
||||
from.SendGump(new NoticeGump(1060635, 30720, 1061826, 32512, 320, 180));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if ((House.Public || !House.IsAosRules) && House.IsBanned(from) && House.IsInside(newLocation, 16))
|
||||
{
|
||||
from.Location = House.BanLocation;
|
||||
|
||||
if (!Core.SE)
|
||||
{
|
||||
from.SendLocalizedMessage(501284); // You may not enter.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (House.IsAosRules && !House.Public && !House.HasAccess(from) && House.IsInside(newLocation, 16))
|
||||
{
|
||||
if (!Core.SE)
|
||||
{
|
||||
from.SendLocalizedMessage(501284); // You may not enter.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (House.IsCombatRestricted(from) && !House.IsInside(oldLocation, 16) && House.IsInside(newLocation, 16))
|
||||
{
|
||||
from.SendLocalizedMessage(1061637); // You are not allowed to access this.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (House is HouseFoundation foundation && foundation.Customizer != null && foundation.Customizer != from &&
|
||||
House.IsInside(newLocation, 16))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnDecay(Item item) =>
|
||||
(!House.HasLockedDownItem(item) && !House.HasSecureItem(item) || !House.IsInside(item)) && base.OnDecay(item);
|
||||
|
||||
public override TimeSpan GetLogoutDelay(Mobile m)
|
||||
if (House.InternalizedVendors.Count > 0 && House.IsInside(from) && !House.IsInside(oldLocation, 16) &&
|
||||
House.IsOwner(from) && from.Alive &&
|
||||
!from.HasGump<NoticeGump>())
|
||||
{
|
||||
if (!House.IsFriend(m) || !House.IsInside(m))
|
||||
from.SendGump(new NoticeGump(1060635, 30720, 1061826, 32512, 320, 180));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnDecay(Item item) =>
|
||||
(!House.HasLockedDownItem(item) && !House.HasSecureItem(item) || !House.IsInside(item)) && base.OnDecay(item);
|
||||
|
||||
public override TimeSpan GetLogoutDelay(Mobile m)
|
||||
{
|
||||
if (!House.IsFriend(m) || !House.IsInside(m))
|
||||
{
|
||||
return base.GetLogoutDelay(m);
|
||||
}
|
||||
|
||||
foreach (var info in m.Aggressed)
|
||||
{
|
||||
if (info.Defender.Player && Core.Now - info.LastCombatTime < CombatHeatDelay)
|
||||
{
|
||||
return base.GetLogoutDelay(m);
|
||||
}
|
||||
|
||||
foreach (var info in m.Aggressed)
|
||||
{
|
||||
if (info.Defender.Player && Core.Now - info.LastCombatTime < CombatHeatDelay)
|
||||
{
|
||||
return base.GetLogoutDelay(m);
|
||||
}
|
||||
}
|
||||
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
|
||||
public override void OnSpeech(SpeechEventArgs e)
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
|
||||
public override void OnSpeech(SpeechEventArgs e)
|
||||
{
|
||||
base.OnSpeech(e);
|
||||
|
||||
var from = e.Mobile;
|
||||
Item sign = House.Sign;
|
||||
|
||||
var isOwner = House.IsOwner(from);
|
||||
var isCoOwner = isOwner || House.IsCoOwner(from);
|
||||
var isFriend = isCoOwner || House.IsFriend(from);
|
||||
|
||||
if (!isFriend)
|
||||
{
|
||||
base.OnSpeech(e);
|
||||
return;
|
||||
}
|
||||
|
||||
var from = e.Mobile;
|
||||
Item sign = House.Sign;
|
||||
if (!from.Alive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var isOwner = House.IsOwner(from);
|
||||
var isCoOwner = isOwner || House.IsCoOwner(from);
|
||||
var isFriend = isCoOwner || House.IsFriend(from);
|
||||
|
||||
if (!isFriend)
|
||||
if (Core.ML && e.Speech.InsensitiveEquals("I wish to resize my house"))
|
||||
{
|
||||
if (from.Map != sign.Map || !from.InRange(sign, 0))
|
||||
{
|
||||
return;
|
||||
from.SendLocalizedMessage(500295); // you are too far away to do that.
|
||||
}
|
||||
|
||||
if (!from.Alive)
|
||||
else if (Core.Now <= House.BuiltOn.AddHours(1))
|
||||
{
|
||||
return;
|
||||
from.SendLocalizedMessage(1080178); // You must wait one hour between each house demolition.
|
||||
}
|
||||
|
||||
if (Core.ML && e.Speech.InsensitiveEquals("I wish to resize my house"))
|
||||
else if (isOwner)
|
||||
{
|
||||
if (from.Map != sign.Map || !from.InRange(sign, 0))
|
||||
{
|
||||
from.SendLocalizedMessage(500295); // you are too far away to do that.
|
||||
}
|
||||
else if (Core.Now <= House.BuiltOn.AddHours(1))
|
||||
{
|
||||
from.SendLocalizedMessage(1080178); // You must wait one hour between each house demolition.
|
||||
}
|
||||
else if (isOwner)
|
||||
{
|
||||
from.CloseGump<ConfirmHouseResize>();
|
||||
from.CloseGump<HouseGumpAOS>();
|
||||
from.SendGump(new ConfirmHouseResize(from, House));
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(501320); // Only the house owner may do this.
|
||||
}
|
||||
from.CloseGump<ConfirmHouseResize>();
|
||||
from.CloseGump<HouseGumpAOS>();
|
||||
from.SendGump(new ConfirmHouseResize(from, House));
|
||||
}
|
||||
|
||||
if (!House.IsInside(from) || !House.IsActive)
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.HasKeyword(0x33)) // remove thyself
|
||||
{
|
||||
from.SendLocalizedMessage(501326); // Target the individual to eject from this house.
|
||||
from.Target = new HouseKickTarget(House);
|
||||
}
|
||||
else if (e.HasKeyword(0x34)) // I ban thee
|
||||
{
|
||||
if (!House.Public && House.IsAosRules)
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
1062521
|
||||
); // You cannot ban someone from a private house. Revoke their access instead.
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(501325); // Target the individual to ban from this house.
|
||||
from.Target = new HouseBanTarget(true, House);
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x23)) // I wish to lock this down
|
||||
{
|
||||
if (isCoOwner)
|
||||
{
|
||||
from.SendLocalizedMessage(502097); // Lock what down?
|
||||
from.Target = new LockdownTarget(false, House);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1010587); // You are not a co-owner of this house.
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x24)) // I wish to release this
|
||||
{
|
||||
if (isCoOwner)
|
||||
{
|
||||
from.SendLocalizedMessage(502100); // Choose the item you wish to release
|
||||
from.Target = new LockdownTarget(true, House);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1010587); // You are not a co-owner of this house.
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x25)) // I wish to secure this
|
||||
{
|
||||
if (isOwner)
|
||||
{
|
||||
from.SendLocalizedMessage(502103); // Choose the item you wish to secure
|
||||
from.Target = new SecureTarget(false, House);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(502094); // You must be in your house to do this.
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x26)) // I wish to unsecure this
|
||||
{
|
||||
if (isOwner)
|
||||
{
|
||||
from.SendLocalizedMessage(502106); // Choose the item you wish to unsecure
|
||||
from.Target = new SecureTarget(true, House);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(502094); // You must be in your house to do this.
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x27)) // I wish to place a strongbox
|
||||
{
|
||||
if (isOwner)
|
||||
{
|
||||
from.SendLocalizedMessage(502109); // Owners do not get a strongbox of their own.
|
||||
}
|
||||
else if (isCoOwner)
|
||||
{
|
||||
House.AddStrongBox(from);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1010587); // You are not a co-owner of this house.
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x28)) // trash barrel
|
||||
{
|
||||
if (isCoOwner)
|
||||
{
|
||||
House.AddTrashBarrel(from);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1010587); // You are not a co-owner of this house.
|
||||
}
|
||||
from.SendLocalizedMessage(501320); // Only the house owner may do this.
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnDoubleClick(Mobile from, object o)
|
||||
if (!House.IsInside(from) || !House.IsActive)
|
||||
{
|
||||
if (o is Container c)
|
||||
{
|
||||
var res = House.CheckSecureAccess(from, c);
|
||||
|
||||
if (res == SecureAccessResult.Accessible)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (res == SecureAccessResult.Inaccessible)
|
||||
{
|
||||
c.SendLocalizedMessageTo(from, 1010563);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return base.OnDoubleClick(from, o);
|
||||
return;
|
||||
}
|
||||
|
||||
public override bool OnSingleClick(Mobile from, object o)
|
||||
if (e.HasKeyword(0x33)) // remove thyself
|
||||
{
|
||||
if (o is Item item)
|
||||
from.SendLocalizedMessage(501326); // Target the individual to eject from this house.
|
||||
from.Target = new HouseKickTarget(House);
|
||||
}
|
||||
else if (e.HasKeyword(0x34)) // I ban thee
|
||||
{
|
||||
if (!House.Public && House.IsAosRules)
|
||||
{
|
||||
if (House.HasLockedDownItem(item))
|
||||
{
|
||||
item.LabelTo(from, 501643); // [locked down]
|
||||
}
|
||||
else if (House.HasSecureItem(item))
|
||||
{
|
||||
item.LabelTo(from, 501644); // [locked down & secure]
|
||||
}
|
||||
from.SendLocalizedMessage(
|
||||
1062521
|
||||
); // You cannot ban someone from a private house. Revoke their access instead.
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(501325); // Target the individual to ban from this house.
|
||||
from.Target = new HouseBanTarget(true, House);
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x23)) // I wish to lock this down
|
||||
{
|
||||
if (isCoOwner)
|
||||
{
|
||||
from.SendLocalizedMessage(502097); // Lock what down?
|
||||
from.Target = new LockdownTarget(false, House);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1010587); // You are not a co-owner of this house.
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x24)) // I wish to release this
|
||||
{
|
||||
if (isCoOwner)
|
||||
{
|
||||
from.SendLocalizedMessage(502100); // Choose the item you wish to release
|
||||
from.Target = new LockdownTarget(true, House);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1010587); // You are not a co-owner of this house.
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x25)) // I wish to secure this
|
||||
{
|
||||
if (isOwner)
|
||||
{
|
||||
from.SendLocalizedMessage(502103); // Choose the item you wish to secure
|
||||
from.Target = new SecureTarget(false, House);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(502094); // You must be in your house to do this.
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x26)) // I wish to unsecure this
|
||||
{
|
||||
if (isOwner)
|
||||
{
|
||||
from.SendLocalizedMessage(502106); // Choose the item you wish to unsecure
|
||||
from.Target = new SecureTarget(true, House);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(502094); // You must be in your house to do this.
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x27)) // I wish to place a strongbox
|
||||
{
|
||||
if (isOwner)
|
||||
{
|
||||
from.SendLocalizedMessage(502109); // Owners do not get a strongbox of their own.
|
||||
}
|
||||
else if (isCoOwner)
|
||||
{
|
||||
House.AddStrongBox(from);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1010587); // You are not a co-owner of this house.
|
||||
}
|
||||
}
|
||||
else if (e.HasKeyword(0x28)) // trash barrel
|
||||
{
|
||||
if (isCoOwner)
|
||||
{
|
||||
House.AddTrashBarrel(from);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1010587); // You are not a co-owner of this house.
|
||||
}
|
||||
|
||||
return base.OnSingleClick(from, o);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnDoubleClick(Mobile from, object o)
|
||||
{
|
||||
if (o is Container c)
|
||||
{
|
||||
var res = House.CheckSecureAccess(from, c);
|
||||
|
||||
if (res == SecureAccessResult.Accessible)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (res == SecureAccessResult.Inaccessible)
|
||||
{
|
||||
c.SendLocalizedMessageTo(from, 1010563);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return base.OnDoubleClick(from, o);
|
||||
}
|
||||
|
||||
public override bool OnSingleClick(Mobile from, object o)
|
||||
{
|
||||
if (o is Item item)
|
||||
{
|
||||
if (House.HasLockedDownItem(item))
|
||||
{
|
||||
item.LabelTo(from, 501643); // [locked down]
|
||||
}
|
||||
else if (House.HasSecureItem(item))
|
||||
{
|
||||
item.LabelTo(from, 501644); // [locked down & secure]
|
||||
}
|
||||
}
|
||||
|
||||
return base.OnSingleClick(from, o);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,77 +1,80 @@
|
|||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Spells;
|
||||
|
||||
namespace Server.Regions
|
||||
namespace Server.Regions;
|
||||
|
||||
public class JailRegion : BaseRegion
|
||||
{
|
||||
public class JailRegion : BaseRegion
|
||||
public JailRegion(string name, Map map, Region parent, params Rectangle3D[] area)
|
||||
: base(name, map, parent, area)
|
||||
{
|
||||
public JailRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool AllowBeneficial(Mobile from, Mobile target)
|
||||
{
|
||||
if (from.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
from.SendMessage("You may not do that in jail.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool AllowHarmful(Mobile from, Mobile target)
|
||||
{
|
||||
if (from.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
from.SendMessage("You may not do that in jail.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool AllowHousing(Mobile from, Point3D p) => false;
|
||||
|
||||
public override void AlterLightLevel(Mobile m, ref int global, ref int personal)
|
||||
{
|
||||
global = LightCycle.JailLevel;
|
||||
}
|
||||
|
||||
public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType)
|
||||
{
|
||||
if (m?.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
m.SendLocalizedMessage(1114345); // You'll need a better jailbreak plan than that!
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.CheckTravel(m, newLocation, travelType);
|
||||
}
|
||||
|
||||
public override bool OnBeginSpellCast(Mobile from, ISpell s)
|
||||
{
|
||||
if (from.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
from.SendLocalizedMessage(502629); // You cannot cast spells here.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnSkillUse(Mobile from, int Skill)
|
||||
{
|
||||
if (from.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
from.SendMessage("You may not use skills in jail.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnCombatantChange(Mobile from, Mobile Old, Mobile New) => from.AccessLevel > AccessLevel.Player;
|
||||
}
|
||||
|
||||
public JailRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool AllowBeneficial(Mobile from, Mobile target)
|
||||
{
|
||||
if (from.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
from.SendMessage("You may not do that in jail.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool AllowHarmful(Mobile from, Mobile target)
|
||||
{
|
||||
if (from.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
from.SendMessage("You may not do that in jail.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool AllowHousing(Mobile from, Point3D p) => false;
|
||||
|
||||
public override void AlterLightLevel(Mobile m, ref int global, ref int personal)
|
||||
{
|
||||
global = LightCycle.JailLevel;
|
||||
}
|
||||
|
||||
public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType)
|
||||
{
|
||||
if (m?.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
m.SendLocalizedMessage(1114345); // You'll need a better jailbreak plan than that!
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.CheckTravel(m, newLocation, travelType);
|
||||
}
|
||||
|
||||
public override bool OnBeginSpellCast(Mobile from, ISpell s)
|
||||
{
|
||||
if (from.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
from.SendLocalizedMessage(502629); // You cannot cast spells here.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnSkillUse(Mobile from, int Skill)
|
||||
{
|
||||
if (from.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
from.SendMessage("You may not use skills in jail.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnCombatantChange(Mobile from, Mobile Old, Mobile New) => from.AccessLevel > AccessLevel.Player;
|
||||
}
|
||||
|
|
|
|||
29
Projects/UOContent/Regions/JsonDtos/BaseRegionJsonDto.cs
Normal file
29
Projects/UOContent/Regions/JsonDtos/BaseRegionJsonDto.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
namespace Server.Regions;
|
||||
|
||||
public class BaseRegionJsonDto<TRegion> : GenericRegionJsonDto<TRegion> where TRegion : BaseRegion
|
||||
{
|
||||
public string RuneName { get; set; }
|
||||
public bool NoLogoutDelay { get; set; }
|
||||
|
||||
public override void FromRegion(Region region)
|
||||
{
|
||||
base.FromRegion(region);
|
||||
|
||||
if (region is BaseRegion baseRegion)
|
||||
{
|
||||
RuneName = baseRegion.RuneName;
|
||||
NoLogoutDelay = baseRegion.NoLogoutDelay;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HydrateRegion(Region region)
|
||||
{
|
||||
base.HydrateRegion(region);
|
||||
|
||||
if (region is BaseRegion baseRegion)
|
||||
{
|
||||
baseRegion.RuneName = RuneName;
|
||||
baseRegion.NoLogoutDelay = NoLogoutDelay;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
Projects/UOContent/Regions/JsonDtos/DungeonRegionJsonDto.cs
Normal file
26
Projects/UOContent/Regions/JsonDtos/DungeonRegionJsonDto.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
namespace Server.Regions;
|
||||
|
||||
public class DungeonRegionJsonDto<TRegion> : BaseRegionJsonDto<TRegion> where TRegion : DungeonRegion
|
||||
{
|
||||
public Point3D Entrance { get; set; }
|
||||
|
||||
public override void FromRegion(Region region)
|
||||
{
|
||||
base.FromRegion(region);
|
||||
|
||||
if (region is DungeonRegion dungeonRegion)
|
||||
{
|
||||
Entrance = dungeonRegion.Entrance;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HydrateRegion(Region region)
|
||||
{
|
||||
base.HydrateRegion(region);
|
||||
|
||||
if (region is DungeonRegion dungeonRegion)
|
||||
{
|
||||
dungeonRegion.Entrance = Entrance;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Projects/UOContent/Regions/JsonDtos/GenericRegionJsonDto.cs
Normal file
34
Projects/UOContent/Regions/JsonDtos/GenericRegionJsonDto.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Server.Regions;
|
||||
|
||||
public class GenericRegionJsonDto<TRegion> : RegionJsonDto where TRegion : BaseRegion
|
||||
{
|
||||
[JsonIgnore]
|
||||
public override Type RegionType => typeof(TRegion);
|
||||
public string RuneName { get; set; }
|
||||
public bool NoLogoutDelay { get; set; }
|
||||
|
||||
public override void FromRegion(Region region)
|
||||
{
|
||||
base.FromRegion(region);
|
||||
|
||||
if (region is BaseRegion baseRegion)
|
||||
{
|
||||
RuneName = baseRegion.RuneName;
|
||||
NoLogoutDelay = baseRegion.NoLogoutDelay;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HydrateRegion(Region region)
|
||||
{
|
||||
base.HydrateRegion(region);
|
||||
|
||||
if (region is BaseRegion baseRegion)
|
||||
{
|
||||
baseRegion.RuneName = RuneName;
|
||||
baseRegion.NoLogoutDelay = NoLogoutDelay;
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Projects/UOContent/Regions/JsonDtos/GuardedRegionJsonDto.cs
Normal file
30
Projects/UOContent/Regions/JsonDtos/GuardedRegionJsonDto.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
|
||||
namespace Server.Regions;
|
||||
|
||||
public class GuardedRegionJsonDto<TRegion> : BaseRegionJsonDto<TRegion> where TRegion : GuardedRegion
|
||||
{
|
||||
public bool GuardsDisabled { get; set; }
|
||||
public Type? GuardType { get; set; }
|
||||
|
||||
public override void FromRegion(Region region)
|
||||
{
|
||||
base.FromRegion(region);
|
||||
|
||||
if (region is GuardedRegion guardedRegion)
|
||||
{
|
||||
GuardsDisabled = guardedRegion.GuardsDisabled;
|
||||
GuardType = guardedRegion.GuardType == guardedRegion.DefaultGuardType ? null : guardedRegion.GuardType;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HydrateRegion(Region region)
|
||||
{
|
||||
base.HydrateRegion(region);
|
||||
if (region is GuardedRegion guardedRegion)
|
||||
{
|
||||
guardedRegion.GuardsDisabled = GuardsDisabled;
|
||||
guardedRegion.GuardType = GuardType ?? guardedRegion.DefaultGuardType;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Projects/UOContent/Regions/JsonDtos/RegionJsonDtoExt.cs
Normal file
21
Projects/UOContent/Regions/JsonDtos/RegionJsonDtoExt.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
namespace Server.Regions;
|
||||
|
||||
public static class RegionJsonDtoExt
|
||||
{
|
||||
public static void Configure()
|
||||
{
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<BaseRegionJsonDto<BaseRegion>, BaseRegion>();
|
||||
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<DungeonRegionJsonDto<DungeonRegion>, DungeonRegion>();
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<GuardedRegionJsonDto<GuardedRegion>, GuardedRegion>();
|
||||
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<BaseRegionJsonDto<GreenAcresRegion>, GreenAcresRegion>();
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<BaseRegionJsonDto<JailRegion>, JailRegion>();
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<BaseRegionJsonDto<MondainRegion>, MondainRegion>();
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<BaseRegionJsonDto<NewMaginciaRegion>, NewMaginciaRegion>();
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<BaseRegionJsonDto<NoHousingRegion>, NoHousingRegion>();
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<BaseRegionJsonDto<NoTravelSpellsAllowedRegion>, NoTravelSpellsAllowedRegion>();
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<BaseRegionJsonDto<TownRegion>, TownRegion>();
|
||||
RegionJsonSerializer.RegisterRegionForSerialization<BaseRegionJsonDto<TwistedWealdDesertRegion>, TwistedWealdDesertRegion>();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +1,27 @@
|
|||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Spells.Sixth;
|
||||
|
||||
namespace Server.Regions
|
||||
namespace Server.Regions;
|
||||
|
||||
public class MondainRegion : NoTravelSpellsAllowedRegion
|
||||
{
|
||||
public class MondainRegion : NoTravelSpellsAllowedRegion
|
||||
public MondainRegion(string name, Map map, Region parent, params Rectangle3D[] area)
|
||||
: base(name, map, parent, area)
|
||||
{
|
||||
public MondainRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
}
|
||||
|
||||
public MondainRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool OnBeginSpellCast(Mobile m, ISpell s)
|
||||
{
|
||||
if (m.Player && s is MarkSpell)
|
||||
{
|
||||
m.SendLocalizedMessage(501802); // Thy spell doth not appear to work...
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool OnBeginSpellCast(Mobile m, ISpell s)
|
||||
{
|
||||
if (m.Player && s is MarkSpell)
|
||||
{
|
||||
m.SendLocalizedMessage(501802); // Thy spell doth not appear to work...
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.OnBeginSpellCast(m, s);
|
||||
}
|
||||
return base.OnBeginSpellCast(m, s);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Regions;
|
||||
namespace Server.Regions;
|
||||
|
||||
namespace Server.Engines.NewMagincia
|
||||
public class NewMaginciaRegion : TownRegion
|
||||
{
|
||||
public class NewMaginciaRegion : TownRegion
|
||||
public NewMaginciaRegion(string name, Map map, Region parent, params Rectangle3D[] area)
|
||||
: base(name, map, parent, area)
|
||||
{
|
||||
}
|
||||
|
||||
public NewMaginciaRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area)
|
||||
{
|
||||
public NewMaginciaRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
namespace Server.Regions;
|
||||
|
||||
namespace Server.Regions
|
||||
public class NoHousingRegion : BaseRegion
|
||||
{
|
||||
public class NoHousingRegion : BaseRegion
|
||||
public NoHousingRegion(string name, Map map, Region parent, params Rectangle3D[] area)
|
||||
: base(name, map, parent, area)
|
||||
{
|
||||
public NoHousingRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) =>
|
||||
SmartChecking = json.GetProperty("smartNoHousing", options, out bool smartNoHousing) && smartNoHousing;
|
||||
|
||||
/* False: this uses 'stupid OSI' house placement checking: part of the house may be placed here provided that the center is not in the region
|
||||
* True: this uses 'smart RunUO' house placement checking: no part of the house may be in the region
|
||||
*/
|
||||
public bool SmartChecking { get; }
|
||||
|
||||
public override bool AllowHousing(Mobile from, Point3D p) => SmartChecking;
|
||||
}
|
||||
|
||||
public NoHousingRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool AllowHousing(Mobile from, Point3D p) => true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
using System.Text.Json;
|
||||
using Server;
|
||||
using Server.Json;
|
||||
using Server.Regions;
|
||||
using Server.Spells;
|
||||
|
||||
public class NoTravelSpellsAllowedRegion : DungeonRegion
|
||||
{
|
||||
public NoTravelSpellsAllowedRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
public NoTravelSpellsAllowedRegion(string name, Map map, Region parent, params Rectangle3D[] area)
|
||||
: base(name, map, parent, area)
|
||||
{
|
||||
}
|
||||
|
||||
public NoTravelSpellsAllowedRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
namespace Server.Regions;
|
||||
|
||||
namespace Server.Regions
|
||||
public class TownRegion : GuardedRegion
|
||||
{
|
||||
public class TownRegion : GuardedRegion
|
||||
public TownRegion(string name, Map map, Region parent, params Rectangle3D[] area)
|
||||
: base(name, map, parent, area)
|
||||
{
|
||||
}
|
||||
|
||||
public TownRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area)
|
||||
{
|
||||
public TownRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,50 @@
|
|||
using System.Text.Json;
|
||||
using Server.Json;
|
||||
using Server.Network;
|
||||
using Server.Spells;
|
||||
using Server.Spells.Ninjitsu;
|
||||
|
||||
namespace Server.Regions
|
||||
namespace Server.Regions;
|
||||
|
||||
public class TwistedWealdDesertRegion : MondainRegion
|
||||
{
|
||||
public class TwistedWealdDesertRegion : MondainRegion
|
||||
public TwistedWealdDesertRegion(string name, Map map, Region parent, params Rectangle3D[] area)
|
||||
: base(name, map, parent, area)
|
||||
{
|
||||
public TwistedWealdDesertRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.Login += Desert_OnLogin;
|
||||
}
|
||||
public TwistedWealdDesertRegion(string name, Map map, Region parent, int priority, params Rectangle3D[] area)
|
||||
: base(name, map, parent, priority, area)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnEnter(Mobile m)
|
||||
{
|
||||
var ns = m.NetState;
|
||||
if (ns != null && !TransformationSpellHelper.UnderTransformation(m, typeof(AnimalForm)) &&
|
||||
m.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
ns.SendSpeedControl(SpeedControlSetting.Walk);
|
||||
}
|
||||
}
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.Login += Desert_OnLogin;
|
||||
}
|
||||
|
||||
public override void OnExit(Mobile m)
|
||||
public override void OnEnter(Mobile m)
|
||||
{
|
||||
var ns = m.NetState;
|
||||
if (ns != null && !TransformationSpellHelper.UnderTransformation(m, typeof(AnimalForm)) &&
|
||||
m.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
var ns = m.NetState;
|
||||
if (ns != null && !TransformationSpellHelper.UnderTransformation(m, typeof(AnimalForm)))
|
||||
{
|
||||
ns.SendSpeedControl(SpeedControlSetting.Disable);
|
||||
}
|
||||
ns.SendSpeedControl(SpeedControlSetting.Walk);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Desert_OnLogin(Mobile m)
|
||||
public override void OnExit(Mobile m)
|
||||
{
|
||||
var ns = m.NetState;
|
||||
if (ns != null && !TransformationSpellHelper.UnderTransformation(m, typeof(AnimalForm)))
|
||||
{
|
||||
if (m.Region.IsPartOf<TwistedWealdDesertRegion>() && m.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
m.NetState.SendSpeedControl(SpeedControlSetting.Walk);
|
||||
}
|
||||
ns.SendSpeedControl(SpeedControlSetting.Disable);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Desert_OnLogin(Mobile m)
|
||||
{
|
||||
if (m.Region.IsPartOf<TwistedWealdDesertRegion>() && m.AccessLevel == AccessLevel.Player)
|
||||
{
|
||||
m.NetState.SendSpeedControl(SpeedControlSetting.Walk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue