feat: Adds option for houses to face east with proper calculations (#2204)

This commit is contained in:
Kamron Batman 2025-05-28 00:31:58 -07:00 • committed by GitHub
parent 4e23a8e205
commit 7fc98498e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 101 additions and 64 deletions

View file

@ -71,6 +71,8 @@ namespace Server.Multis.Deeds
[CommandProperty(AccessLevel.GameMaster)] [CommandProperty(AccessLevel.GameMaster)]
public Point3D Offset { get; set; } public Point3D Offset { get; set; }
public virtual Direction HouseDirection => Direction.South;
public abstract Rectangle2D[] Area { get; } public abstract Rectangle2D[] Area { get; }
public override void Serialize(IGenericWriter writer) public override void Serialize(IGenericWriter writer)
@ -153,7 +155,7 @@ namespace Server.Multis.Deeds
else else
{ {
var center = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z); var center = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z);
var res = HousePlacement.Check(from, MultiID, center, out var toMove); var res = HousePlacement.Check(from, MultiID, center, out var toMove, HouseDirection);
switch (res) switch (res)
{ {

View file

@ -100,6 +100,8 @@ namespace Server.Multis
[CommandProperty(AccessLevel.GameMaster)] [CommandProperty(AccessLevel.GameMaster)]
public bool RestrictDecay { get; set; } public bool RestrictDecay { get; set; }
public virtual Direction HouseDirection => Direction.South;
public virtual TimeSpan DecayPeriod => TimeSpan.FromDays(5.0); public virtual TimeSpan DecayPeriod => TimeSpan.FromDays(5.0);
public virtual DecayType DecayType public virtual DecayType DecayType

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Server.Collections; using Server.Collections;
using Server.Regions; using Server.Regions;
@ -37,7 +38,9 @@ namespace Server.Multis
0x0150, 0x015C // Furrows 0x0150, 0x015C // Furrows
}; };
public static HousePlacementResult Check(Mobile from, int multiID, Point3D center, out List<IEntity> toMove) public static HousePlacementResult Check(
Mobile from, int multiID, Point3D center, out List<IEntity> toMove, Direction houseFacing = Direction.South
)
{ {
// If this spot is considered valid, every item and mobile in this list will be moved under the house sign // If this spot is considered valid, every item and mobile in this list will be moved under the house sign
toMove = new List<IEntity>(); toMove = new List<IEntity>();
@ -77,7 +80,7 @@ namespace Server.Multis
HouseFoundation.AddStairsTo(ref mcl); // this is a AOS house, add the stairs HouseFoundation.AddStairsTo(ref mcl); // this is a AOS house, add the stairs
} }
// Location of the nortwest-most corner of the house // Location of the northwest-most corner of the house
var start = new Point3D(center.X + mcl.Min.X, center.Y + mcl.Min.Y, center.Z); var start = new Point3D(center.X + mcl.Min.X, center.Y + mcl.Min.Y, center.Z);
// These are storage lists. They hold items and mobiles found in the map for further processing // These are storage lists. They hold items and mobiles found in the map for further processing
@ -85,7 +88,7 @@ namespace Server.Multis
var mobiles = new List<Mobile>(); var mobiles = new List<Mobile>();
// These are also storage lists. They hold location values indicating the yard and border locations. // These are also storage lists. They hold location values indicating the yard and border locations.
List<Point2D> yard = new(), borders = new(); List<Point2D> borders = [];
/* RULES: /* RULES:
* *
@ -121,7 +124,7 @@ namespace Server.Multis
return HousePlacementResult.BadRegionTemp; return HousePlacementResult.BadRegionTemp;
} }
if (reg.IsPartOf<TreasureRegion>() || reg.IsPartOf<HouseRegion>()) if (reg.IsPartOf<TreasureRegion, HouseRegion>())
{ {
return HousePlacementResult.BadRegionHidden; return HousePlacementResult.BadRegionHidden;
} }
@ -218,16 +221,18 @@ namespace Server.Multis
{ {
var id = item.ItemData; var id = item.ItemData;
if (addTileTop > item.Z && item.Z + id.CalcHeight > addTileZ) if (addTileTop <= item.Z || item.Z + id.CalcHeight <= addTileZ)
{ {
if (item.Movable) continue;
{ }
toMove.Add(item);
} if (item.Movable)
else if (id.Impassable || id.Surface && !id.Background) {
{ toMove.Add(item);
return HousePlacementResult.BadItem; // Broke rule #2 }
} else if (id.Impassable || id.Surface && !id.Background)
{
return HousePlacementResult.BadItem; // Broke rule #2
} }
} }
@ -257,17 +262,9 @@ namespace Server.Multis
if (hasFoundation) if (hasFoundation)
{ {
for (var xOffset = -1; xOffset <= 1; ++xOffset) if (!CheckYard(map, tileX, tileY, YardSize, houseFacing))
{ {
for (var yOffset = -YardSize; yOffset <= YardSize; ++yOffset) return HousePlacementResult.BadStatic; // Broke rule #3
{
var yardPoint = new Point2D(tileX + xOffset, tileY + yOffset);
if (!yard.Contains(yardPoint))
{
yard.Add(yardPoint);
}
}
} }
for (var xOffset = -1; xOffset <= 1; ++xOffset) for (var xOffset = -1; xOffset <= 1; ++xOffset)
@ -364,37 +361,73 @@ namespace Server.Multis
} }
} }
for (var i = 0; i < yard.Count; i++) return HousePlacementResult.Valid;
{ }
var yardPoint = yard[i];
foreach (var house in map.GetMultisInSector<BaseHouse>(yardPoint)) private static bool CheckYard(Map map, int tileX, int tileY, int yardSize, Direction houseFacing)
{
var isSouthFacing = (houseFacing & Direction.South) != 0;
var isEastFacing = (houseFacing & Direction.East) != 0;
for (var xOffset = -yardSize; xOffset <= yardSize; ++xOffset)
{
var absXOffset = Math.Abs(xOffset);
for (var yOffset = -yardSize; yOffset <= yardSize; ++yOffset)
{ {
if (house.Contains(yard[i])) var absYOffset = Math.Abs(yOffset);
var yardPoint = new Point2D(tileX + xOffset, tileY + yOffset);
bool inSouthYard = yOffset > 0 && yOffset <= yardSize && absXOffset <= 1;
bool inEastYard = xOffset > 0 && xOffset <= yardSize && absYOffset <= 1;
bool inNorthYard = yOffset < 0 && yOffset >= -yardSize && absXOffset <= 1;
bool inWestYard = xOffset < 0 && xOffset >= -yardSize && absYOffset <= 1;
// Check each house at this point
foreach (var house in map.GetMultisInSector<BaseHouse>(yardPoint))
{ {
return HousePlacementResult.BadStatic; // Broke rule #3 if (!house.Contains(yardPoint))
{
continue;
}
var existingHouseFacing = house.HouseDirection;
var existingHouseIsSouthFacing = (existingHouseFacing & Direction.South) != 0;
var existingHouseIsEastFacing = (existingHouseFacing & Direction.East) != 0;
// Sub-Rule 1: No houses within immediate proximity (1 tile radius)
if (absXOffset <= 1 && absYOffset <= 1)
{
return false;
}
// Sub-Rule 2: If we're south facing, protect our south yard
if (isSouthFacing && inSouthYard)
{
return false;
}
// Sub-Rule 3: If we're east facing, protect our east yard
if (isEastFacing && inEastYard)
{
return false;
}
// Sub-Rule 4: If there's a south-facing house to our north, respect its yard
if (inNorthYard && existingHouseIsSouthFacing)
{
return false;
}
// Sub-Rule 5: If there's an east-facing house to our west, respect its yard
if (inWestYard && existingHouseIsEastFacing)
{
return false;
}
} }
} }
} }
// TODO: Should we check for MultiTilesAt each yard point? return true;
// for (var i = 0; i < yard.Count; i++)
// {
// var yardPoint = yard[i];
//
// foreach (var tiles in map.GetMultiTilesAt(yardPoint))
// {
// for (int j = 0; j < tiles.Length; ++j)
// {
// if ((TileData.ItemTable[tiles[j].ID & TileData.MaxItemValue].Flags & (TileFlag.Impassable | TileFlag.Surface)) != 0)
// {
// return HousePlacementResult.BadStatic; // Broke rule #3
// }
// }
// }
// }
return HousePlacementResult.Valid;
} }
} }
} }

View file

@ -303,7 +303,7 @@ public class HousePlacementEntry
public HousePlacementEntry( public HousePlacementEntry(
Type type, int description, int storage, int lockdowns, int newStorage, int newLockdowns, Type type, int description, int storage, int lockdowns, int newStorage, int newLockdowns,
int vendors, int cost, int xOffset, int yOffset, int zOffset, int multiID int vendors, int cost, int xOffset, int yOffset, int zOffset, int multiID, Direction direction = Direction.South
) )
{ {
Type = type; Type = type;
@ -318,6 +318,7 @@ public class HousePlacementEntry
Offset = new Point3D(xOffset, yOffset, zOffset); Offset = new Point3D(xOffset, yOffset, zOffset);
MultiID = multiID; MultiID = multiID;
HouseDirection = direction;
} }
public Type Type { get; } public Type Type { get; }
@ -334,6 +335,8 @@ public class HousePlacementEntry
public Point3D Offset { get; } public Point3D Offset { get; }
public Direction HouseDirection { get; }
public static HousePlacementEntry[] ClassicHouses { get; } = public static HousePlacementEntry[] ClassicHouses { get; } =
{ {
new(typeof(SmallOldHouse), 1011303, 425, 212, 489, 244, 10, 37000, 0, 4, 0, 0x0064), new(typeof(SmallOldHouse), 1011303, 425, 212, 489, 244, 10, 37000, 0, 4, 0, 0x0064),
@ -1981,7 +1984,7 @@ public class HousePlacementEntry
prevHouse.Delete(); prevHouse.Delete();
var res = HousePlacement.Check(from, MultiID, center, out var toMove); var res = HousePlacement.Check(from, MultiID, center, out var toMove, HouseDirection);
switch (res) switch (res)
{ {
@ -2008,21 +2011,18 @@ public class HousePlacementEntry
$"{Cost} gold would have been withdrawn from your bank if you were not a GM." $"{Cost} gold would have been withdrawn from your bank if you were not a GM."
); );
} }
else if (Banker.Withdraw(from, Cost))
{
// ~1_AMOUNT~ gold has been withdrawn from your bank box.
from.SendLocalizedMessage(1060398, Cost.ToString());
}
else else
{ {
if (Banker.Withdraw(from, Cost)) house.RemoveKeys(from);
{ house.Delete();
// ~1_AMOUNT~ gold has been withdrawn from your bank box. // You do not have the funds available in your bank box to purchase this house. Try placing a smaller house, or adding gold or checks to your bank box.
from.SendLocalizedMessage(1060398, Cost.ToString()); from.SendLocalizedMessage(1060646);
} return;
else
{
house.RemoveKeys(from);
house.Delete();
// You do not have the funds available in your bank box to purchase this house. Try placing a smaller house, or adding gold or checks to your bank box.
from.SendLocalizedMessage(1060646);
return;
}
} }
house.MoveToWorld(center, from.Map); house.MoveToWorld(center, from.Map);
@ -2087,7 +2087,7 @@ public class HousePlacementEntry
} }
var center = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z); var center = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z);
var res = HousePlacement.Check(from, MultiID, center, out var toMove); var res = HousePlacement.Check(from, MultiID, center, out var toMove, HouseDirection);
switch (res) switch (res)
{ {