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)]
public Point3D Offset { get; set; }
public virtual Direction HouseDirection => Direction.South;
public abstract Rectangle2D[] Area { get; }
public override void Serialize(IGenericWriter writer)
@ -153,7 +155,7 @@ namespace Server.Multis.Deeds
else
{
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)
{

View file

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

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using Server.Collections;
using Server.Regions;
@ -37,7 +38,9 @@ namespace Server.Multis
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
toMove = new List<IEntity>();
@ -77,7 +80,7 @@ namespace Server.Multis
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);
// 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>();
// 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:
*
@ -121,7 +124,7 @@ namespace Server.Multis
return HousePlacementResult.BadRegionTemp;
}
if (reg.IsPartOf<TreasureRegion>() || reg.IsPartOf<HouseRegion>())
if (reg.IsPartOf<TreasureRegion, HouseRegion>())
{
return HousePlacementResult.BadRegionHidden;
}
@ -218,16 +221,18 @@ namespace Server.Multis
{
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)
{
toMove.Add(item);
}
else if (id.Impassable || id.Surface && !id.Background)
{
return HousePlacementResult.BadItem; // Broke rule #2
}
continue;
}
if (item.Movable)
{
toMove.Add(item);
}
else if (id.Impassable || id.Surface && !id.Background)
{
return HousePlacementResult.BadItem; // Broke rule #2
}
}
@ -257,17 +262,9 @@ namespace Server.Multis
if (hasFoundation)
{
for (var xOffset = -1; xOffset <= 1; ++xOffset)
if (!CheckYard(map, tileX, tileY, YardSize, houseFacing))
{
for (var yOffset = -YardSize; yOffset <= YardSize; ++yOffset)
{
var yardPoint = new Point2D(tileX + xOffset, tileY + yOffset);
if (!yard.Contains(yardPoint))
{
yard.Add(yardPoint);
}
}
return HousePlacementResult.BadStatic; // Broke rule #3
}
for (var xOffset = -1; xOffset <= 1; ++xOffset)
@ -364,37 +361,73 @@ namespace Server.Multis
}
}
for (var i = 0; i < yard.Count; i++)
{
var yardPoint = yard[i];
return HousePlacementResult.Valid;
}
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?
// 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;
return true;
}
}
}

View file

@ -303,7 +303,7 @@ public class HousePlacementEntry
public HousePlacementEntry(
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;
@ -318,6 +318,7 @@ public class HousePlacementEntry
Offset = new Point3D(xOffset, yOffset, zOffset);
MultiID = multiID;
HouseDirection = direction;
}
public Type Type { get; }
@ -334,6 +335,8 @@ public class HousePlacementEntry
public Point3D Offset { get; }
public Direction HouseDirection { get; }
public static HousePlacementEntry[] ClassicHouses { get; } =
{
new(typeof(SmallOldHouse), 1011303, 425, 212, 489, 244, 10, 37000, 0, 4, 0, 0x0064),
@ -1981,7 +1984,7 @@ public class HousePlacementEntry
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)
{
@ -2008,21 +2011,18 @@ public class HousePlacementEntry
$"{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
{
if (Banker.Withdraw(from, Cost))
{
// ~1_AMOUNT~ gold has been withdrawn from your bank box.
from.SendLocalizedMessage(1060398, Cost.ToString());
}
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.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);
@ -2087,7 +2087,7 @@ public class HousePlacementEntry
}
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)
{