ModernUO/Projects/UOContent/Engines/Spawners/RegionSpawner.cs
2024-06-06 16:31:48 -07:00

187 lines
5.5 KiB
C#

/*************************************************************************
* ModernUO *
* Copyright 2019-2023 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: RegionSpawner.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 ModernUO.Serialization;
using Server.Json;
using Server.Regions;
namespace Server.Engines.Spawners;
[SerializationGenerator(0)]
public partial class RegionSpawner : Spawner
{
[SerializableField(0, getter: "private", setter: "private")]
private string _spawnRegionName;
private BaseRegion _spawnRegion;
[Constructible(AccessLevel.Developer)]
public RegionSpawner()
{
}
[Constructible(AccessLevel.Developer)]
public RegionSpawner(string spawnedName) : base(spawnedName)
{
}
[Constructible(AccessLevel.Developer)]
public RegionSpawner(
int amount, int minDelay, int maxDelay, int team, int homeRange,
params string[] spawnedNames
) : this(
amount,
TimeSpan.FromMinutes(minDelay),
TimeSpan.FromMinutes(maxDelay),
team,
homeRange,
spawnedNames
)
{
}
[Constructible(AccessLevel.Developer)]
public RegionSpawner(
int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange,
params string[] spawnedNames
) : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames)
{
}
public RegionSpawner(DynamicJson json, JsonSerializerOptions options) : base(json, options)
{
json.GetProperty("map", options, out Map map);
json.GetProperty("region", options, out string spawnRegion);
_spawnRegion = Region.Find(spawnRegion, map) as BaseRegion;
_spawnRegion?.InitRectangles();
}
[CommandProperty(AccessLevel.Developer)]
public BaseRegion SpawnRegion
{
get => _spawnRegion;
set
{
_spawnRegion = value;
SpawnRegionName = _spawnRegion?.Name;
_spawnRegion?.InitRectangles();
InvalidateProperties();
}
}
public override void ToJson(DynamicJson json, JsonSerializerOptions options)
{
base.ToJson(json, options);
json.SetProperty("region", options, SpawnRegion.Name);
}
public override void GetSpawnerProperties(IPropertyList list)
{
base.GetSpawnerProperties(list);
if (Running && _spawnRegion != null)
{
list.Add(1076228, $"{"region:"}\t{_spawnRegion.Name}"); // ~1_DUMMY~ ~2_DUMMY~
}
}
public override Point3D GetSpawnPosition(ISpawnable spawned, Map map)
{
if (_spawnRegion == null || map == null || map == Map.Internal || map != _spawnRegion.Map ||
_spawnRegion.TotalWeight <= 0)
{
return Location;
}
bool waterMob, waterOnlyMob;
if (spawned is Mobile mob)
{
waterMob = mob.CanSwim;
waterOnlyMob = mob.CanSwim && mob.CantWalk;
}
else
{
waterMob = false;
waterOnlyMob = false;
}
// Try 10 times to find a valid location.
for (var i = 0; i < 10; i++)
{
var rand = Utility.Random(_spawnRegion.TotalWeight);
var x = int.MinValue;
var y = int.MinValue;
for (var j = 0; j < _spawnRegion.RectangleWeights.Length; j++)
{
var curWeight = _spawnRegion.RectangleWeights[j];
if (rand < curWeight)
{
var rect = _spawnRegion.Rectangles[j];
x = rect.Start.X + rand % rect.Width;
y = rect.Start.Y + rand / rect.Width;
break;
}
rand -= curWeight;
}
var mapZ = map.GetAverageZ(x, y);
if (waterMob)
{
if (IsValidWater(map, x, y, Z))
{
return new Point3D(x, y, Z);
}
if (IsValidWater(map, x, y, mapZ))
{
return new Point3D(x, y, mapZ);
}
}
if (!waterOnlyMob)
{
if (map.CanSpawnMobile(x, y, Z))
{
return new Point3D(x, y, Z);
}
if (map.CanSpawnMobile(x, y, mapZ))
{
return new Point3D(x, y, mapZ);
}
}
}
return HomeLocation;
}
[AfterDeserialization(false)]
private void AfterDeserialization()
{
_spawnRegion = Region.Find(_spawnRegionName, Map) as BaseRegion;
_spawnRegion?.InitRectangles();
}
}