add bluespace shelter capsules (#2566) (2)

This commit is contained in:
tommy
2025-11-27 16:02:57 -05:00
parent 41d0338fcc
commit 5a8b515eb5
2 changed files with 110 additions and 8 deletions

View File

@@ -0,0 +1,109 @@
using Content.Server.Fluids.EntitySystems;
using Content.Server.Procedural;
using Content.Shared.Administration.Logs;
using Content.Shared.Chemistry.Components;
using Content.Shared.Database;
using Content.Shared._DV.Salvage.Components;
using Content.Shared._DV.Salvage.Systems;
using Content.Shared.Maps;
using Content.Shared.Physics;
using Robust.Shared.Map.Components;
using Robust.Shared.Maths;
using Robust.Shared.Physics;
using Robust.Shared.Prototypes;
using System.Numerics;
namespace Content.Server._DV.Salvage.Systems;
public sealed class ShelterCapsuleSystem : SharedShelterCapsuleSystem
{
[Dependency] private readonly DungeonSystem _dungeon = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly SharedMapSystem _map = default!;
[Dependency] private readonly SmokeSystem _smoke = default!;
public static readonly EntProtoId SmokePrototype = "Smoke";
private EntityQuery<FixturesComponent> _fixturesQuery;
private HashSet<EntityUid> _entities = new();
public override void Initialize()
{
base.Initialize();
_fixturesQuery = GetEntityQuery<FixturesComponent>();
}
protected override LocId? TrySpawnRoom(Entity<ShelterCapsuleComponent> ent)
{
var xform = Transform(ent);
if (xform.GridUid is not {} gridUid || !TryComp<MapGridComponent>(gridUid, out var grid))
return "shelter-capsule-error-space";
var center = _map.LocalToTile(gridUid, grid, xform.Coordinates);
var room = _proto.Index(ent.Comp.Room);
var origin = center - room.Size / 2;
// check that every tile it needs isn't blocked
var mask = (int) CollisionGroup.MobMask;
if (IsAreaBlocked(gridUid, center, room.Size, mask))
return "shelter-capsule-error-obstructed";
// check that it isn't on space or SpawnRoom will crash
for (int y = 0; y < room.Size.Y; y++)
{
for (int x = 0; x < room.Size.X; x++)
{
var pos = origin + new Vector2i(x, y);
var tile = _map.GetTileRef((gridUid, grid), pos);
if (tile.Tile.IsEmpty)
return "shelter-capsule-error-space";
}
}
var user = ent.Comp.User;
_adminLogger.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(user):user} expanded {ToPrettyString(ent):capsule} at {center} on {ToPrettyString(gridUid):grid}");
_dungeon.SpawnRoom(gridUid,
grid,
origin,
room,
new Random(),
null,
clearExisting: true); // already checked for mobs and structures here
var smoke = Spawn(SmokePrototype, xform.Coordinates);
var spreadAmount = (int) room.Size.Length * 2;
_smoke.StartSmoke(smoke, new Solution(), 3f, spreadAmount);
QueueDel(ent);
return null;
}
private bool IsAreaBlocked(EntityUid grid, Vector2i center, Vector2i size, int mask)
{
// This is scaled to 95 % so it doesn't encompass walls on other tiles.
var aabb = Box2.CenteredAround(center, size * 0.95f);
_entities.Clear();
_lookup.GetLocalEntitiesIntersecting(grid, aabb, _entities, LookupFlags.Dynamic | LookupFlags.Static);
foreach (var uid in _entities)
{
// don't care about non-physical entities
if (!_fixturesQuery.TryComp(uid, out var fixtures))
continue;
foreach (var fixture in fixtures.Fixtures.Values)
{
if (!fixture.Hard)
continue;
if ((fixture.CollisionLayer & mask) != 0)
return true;
}
}
return false; // no entities colliding with the mask found
}
}

View File

@@ -1992,7 +1992,7 @@ entities:
- type: Transform
pos: 20.5,5.5
parent: 1
- proto: WindowTintedReinforcedDirectional
- proto: WindowReinforcedDirectional
entities:
- uid: 325
components:
@@ -2099,11 +2099,4 @@ entities:
rot: 1.5707963267948966 rad
pos: 16.5,-1.5
parent: 1
- proto: WoodenKegBeer
entities:
- uid: 343
components:
- type: Transform
pos: 19.5,7.5
parent: 1
...