using System.Collections.Generic; using System.Numerics; namespace AcDream.Core.World.Cells; /// /// Base for every cell the player can stand in. Retail anchor: CObjCell /// (acclient.h:30915). The id magnitude is the type discriminator /// (): low-16 >= 0x100 => indoor , /// else outdoor . /// public abstract class ObjCell { public uint Id { get; } public Matrix4x4 WorldTransform { get; } public Matrix4x4 InverseWorldTransform { get; } public Vector3 LocalBoundsMin { get; } public Vector3 LocalBoundsMax { get; } public IReadOnlyList Portals { get; } public IReadOnlyList StabList { get; } public bool SeenOutside { get; } /// /// Retail magnitude dispatch (CObjCell::GetVisible, pseudo_c:308215). /// Note: retail's CObjCell::GetVisible tests the full id; every real prefixed EnvCell id is >= 0x100. /// This masks the low-16 so it works for both bare-16 and landblock-prefixed ids. /// public bool IsEnv => (Id & 0xFFFFu) >= 0x100u; protected ObjCell(uint id, Matrix4x4 worldTransform, Matrix4x4 inverseWorldTransform, Vector3 localBoundsMin, Vector3 localBoundsMax, IReadOnlyList portals, IReadOnlyList stabList, bool seenOutside) { Id = id; WorldTransform = worldTransform; InverseWorldTransform = inverseWorldTransform; LocalBoundsMin = localBoundsMin; LocalBoundsMax = localBoundsMax; Portals = portals; StabList = stabList; SeenOutside = seenOutside; } /// Retail CObjCell::point_in_cell (vtable +0x84). Is a world point inside this cell? public abstract bool PointInCell(Vector3 worldPoint); }