Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add bluespace shelter capsules #2566

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Content.Client/_DV/Salvage/Systems/ShelterCapsuleSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Content.Shared._DV.Salvage.Systems;

namespace Content.Client._DV.Salvage.Systems;

public sealed class ShelterCapsuleSystem : SharedShelterCapsuleSystem;
67 changes: 67 additions & 0 deletions Content.Server/_DV/Salvage/Systems/ShelterCapsuleSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Content.Server.Procedural;
using Content.Shared.Administration.Logs;
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.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 TurfSystem _turf = default!;

private HashSet<Entity<TransformComponent>> _entities = new();

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 gridXform = Transform(gridUid);
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 = CollisionGroup.MobMask;
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";

if (_turf.IsTileBlocked(gridUid, pos, mask, grid, gridXform))
return "shelter-capsule-error-obstructed";
}
}

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

QueueDel(ent);
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Content.Shared._DV.Salvage.Systems;
using Content.Shared.Procedural;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;

namespace Content.Shared._DV.Salvage.Components;

/// <summary>
/// Spawns a dungeon room after a delay when used and deletes itself.
/// </summary>
[RegisterComponent, NetworkedComponent, Access(typeof(SharedShelterCapsuleSystem))]
[AutoGenerateComponentPause]
public sealed partial class ShelterCapsuleComponent : Component
{
/// <summary>
/// The room to spawn.
/// </summary>
[DataField(required: true)]
public ProtoId<DungeonRoomPrototype> Room;

/// <summary>
/// How long to wait between using and spawning the room.
/// </summary>
[DataField]
public TimeSpan Delay = TimeSpan.FromSeconds(5);

/// <summary>
/// When to next spawn the room, also used to ignore activating multiple times.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
public TimeSpan? NextSpawn;

/// <summary>
/// The user of the capsule, used for logging.
/// </summary>
[DataField]
public EntityUid? User;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using Content.Shared._DV.Salvage.Components;
using Content.Shared.Interaction.Events;
using Content.Shared.Popups;
using Robust.Shared.Timing;

namespace Content.Shared._DV.Salvage.Systems;

/// <summary>
/// Handles interaction for shelter capsules.
/// Room spawning is done serverside.
/// </summary>
public abstract class SharedShelterCapsuleSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<ShelterCapsuleComponent, UseInHandEvent>(OnUse);
}

public override void Update(float frameTime)
{
base.Update(frameTime);

var now = _timing.CurTime;
var query = EntityQueryEnumerator<ShelterCapsuleComponent>();
while (query.MoveNext(out var uid, out var comp))
{
if (comp.NextSpawn is not {} nextSpawn || now < nextSpawn)
continue;

comp.User = null;
comp.NextSpawn = null;
if (TrySpawnRoom((uid, comp)) is {} id)
{
var msg = Loc.GetString(id, ("capsule", uid));
_popup.PopupEntity(msg, uid, PopupType.LargeCaution);
}
}
}

/// <summary>
/// Spawn the room, returning a locale string for an error. It gets "capsule" passed.
/// </summary>
protected virtual LocId? TrySpawnRoom(Entity<ShelterCapsuleComponent> ent)
{
return null;
}

private void OnUse(Entity<ShelterCapsuleComponent> ent, ref UseInHandEvent args)
{
if (args.Handled || ent.Comp.NextSpawn != null)
return;

args.Handled = true;

var msg = Loc.GetString("shelter-capsule-warning", ("capsule", ent));
_popup.PopupPredicted(msg, ent, args.User, PopupType.LargeCaution);

ent.Comp.User = args.User;
ent.Comp.NextSpawn = _timing.CurTime + ent.Comp.Delay;
}
}
3 changes: 3 additions & 0 deletions Resources/Locale/en-US/_DV/salvage/shelter-capsule.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
shelter-capsule-warning = {THE($capsule)} begins to shake. Stand back!
shelter-capsule-error-space = {THE($capsule)} needs ground to deploy on!
shelter-capsule-error-obstructed = {THE($capsule)} is obstructed, clear the area first!
Loading
Loading