Skip to content

Commit

Permalink
auto prison shuttle & round end prison win type
Browse files Browse the repository at this point in the history
  • Loading branch information
Doublechest committed Jul 15, 2024
1 parent 2e8085f commit 417bb14
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;

namespace Content.Server.Stories.Prison;

[RegisterComponent]
Expand All @@ -8,4 +10,7 @@ public sealed partial class PrisonShuttleComponent : Component
/// </summary>
[DataField]
public EntityUid? Prison;

[DataField("nextTransfer", customTypeSerializer: typeof(TimeOffsetSerializer))]
public TimeSpan NextTransfer;
}
6 changes: 6 additions & 0 deletions Content.Server/Stories/Prison/Components/PrisonerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Content.Server.Stories.Prison;

[RegisterComponent]
public sealed partial class PrisonerComponent : Component
{
}
159 changes: 158 additions & 1 deletion Content.Server/Stories/Prison/PrisonSystem.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.GameTicking;
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Events;
using Content.Server.Shuttles.Systems;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.Shuttles.Components;
using Robust.Shared.Random;
using Robust.Server.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Content.Server.Screens.Components;
using Robust.Shared.Timing;
using Content.Server.DeviceNetwork.Components;
using Content.Shared.DeviceNetwork;
using Content.Server.DeviceNetwork.Systems;
using Content.Shared.Mobs.Components;

namespace Content.Server.Stories.Prison;

Expand All @@ -13,14 +26,158 @@ public sealed partial class PrisonSystem : EntitySystem
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly ShuttleSystem _shuttle = default!;
[Dependency] private readonly SharedTransformSystem _xform = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly DeviceNetworkSystem _deviceNetwork = default!;
[Dependency] private readonly IRobustRandom _random = default!;
private ISawmill _sawmill = default!;

public const float ShuttleTransferTime = 120f;
public override void Initialize()
{
_sawmill = Logger.GetSawmill("prison");
SubscribeLocalEvent<StationPrisonComponent, MapInitEvent>(OnStationInit);
SubscribeLocalEvent<PrisonShuttleComponent, MapInitEvent>(OnShuttleInit);

SubscribeLocalEvent<RoundEndTextAppendEvent>(OnRoundEndText);
}
public override void Update(float frameTime)
{

// Работает для карты-грида (текущая карта тюрьмы), а
// для гридов не знаю. _station.GetLargestGrid() не работает
// с картами-гридами, потому что оффы щиткодеры.

base.Update(frameTime);

var query = EntityQueryEnumerator<PrisonShuttleComponent, ShuttleComponent, TransformComponent>();
var curTime = _timing.CurTime;

while (query.MoveNext(out var uid, out var comp, out var shuttle, out var xform))
{
if (comp.Prison == null || !TryComp<PrisonComponent>(comp.Prison.Value, out var prisonComponent) || prisonComponent.Station == null)
continue;

var station = prisonComponent.Station.Value;
var prison = comp.Prison.Value;


if (comp.NextTransfer > curTime || !TryComp<StationDataComponent>(prison, out var data) || !TryComp<StationDataComponent>(station, out var stationData))
continue;

var prisonGrid = EnsurePrisonGrid();
var stationGrid = _station.GetLargestGrid(stationData);

if (prisonGrid == null || stationGrid == null)
continue;

if (Transform(prisonGrid.Value).MapID != xform.MapID)
{
if (TryGetRandomBeacon(Transform(prisonGrid.Value).MapID, out var beaconUid))
FTLToBeacon(uid, beaconUid.Value);
else _shuttle.TryFTLProximity(uid, prisonGrid.Value);
}
else
{
_shuttle.FTLToDock(uid, shuttle, stationGrid.Value);
}

comp.NextTransfer += TimeSpan.FromSeconds(ShuttleTransferTime);
}
}
private EntityUid? EnsurePrisonGrid()
{
var query = EntityQueryEnumerator<PrisonComponent, StationDataComponent>();
while (query.MoveNext(out var uid, out var prison, out var data))
{
foreach (var grid in data.Grids)
{
if (!HasComp<PrisonShuttleComponent>(grid))
return grid;
}
}

return null;
}
private void OnRoundEndText(RoundEndTextAppendEvent args)
{
// FIXME: Hardcoded

MapId? prisonMap = null;

var queryPrisons = EntityQueryEnumerator<PrisonComponent>();
while (queryPrisons.MoveNext(out var uid, out var prison))
{
if (TryComp<StationDataComponent>(uid, out var station))
{
var grid = _station.GetLargestGrid(station);
if (grid.HasValue)
prisonMap = Transform(grid.Value).MapID;
}
}

int prisoners = 0;
int alivePrisoners = 0;
int escapedPrisoners = 0;

var query = EntityQueryEnumerator<PrisonerComponent, MobStateComponent, TransformComponent>();
while (query.MoveNext(out var uid, out var prisoner, out var mobState, out var xform))
{
prisoners++;

if (mobState.CurrentState == Shared.Mobs.MobState.Alive)
alivePrisoners++;

if (prisonMap != null && xform.MapID != prisonMap)
escapedPrisoners++;
}

string winString;

if (prisoners == 0)
winString = "prison-no-prisoners";
else if (alivePrisoners == 0)
winString = "prisoner-dead";
else if (escapedPrisoners > 0 && escapedPrisoners >= alivePrisoners / 2)
winString = "prisoner-major";
else if (escapedPrisoners > 0)
winString = "prisoner-minor";
else if (alivePrisoners == prisoners)
winString = "prison-major";
else winString = "prison-minor";

args.AddLine(Loc.GetString(winString));
args.AddLine(Loc.GetString($"{winString}-desc"));
}
public void FTLToBeacon(EntityUid shuttleUid, EntityUid beaconUid, ShuttleComponent? component = null)
{
if (!Resolve(shuttleUid, ref component))
return;

var coords = Transform(beaconUid).Coordinates;

_shuttle.FTLToCoordinates(shuttleUid, component, coords, new Angle(0f));
}
private void OnShuttleInit(EntityUid uid, PrisonShuttleComponent component, MapInitEvent args)
{
component.NextTransfer = _timing.CurTime + TimeSpan.FromSeconds(ShuttleTransferTime);
EnsureComp<PreventPilotComponent>(uid);
}
public bool TryGetRandomBeacon(MapId mapId, [NotNullWhen(true)] out EntityUid? uid)
{
var query = AllEntityQuery<FTLBeaconComponent, TransformComponent>();
while (query.MoveNext(out var beaconUid, out var _, out var xform))
{
if (xform.MapID != mapId)
continue;

uid = beaconUid;
return true;
}

uid = null;
return false;
}
private void OnStationInit(EntityUid uid, StationPrisonComponent component, MapInitEvent args)
{
var prototype = _prototypeManager.Index(component.GameMap);
Expand Down
19 changes: 19 additions & 0 deletions Resources/Locale/ru-RU/stories/prison.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
prison-title = Тюрьма
prisoner-major = [color=crimson]Крупная победа заключенных![/color]
prisoner-major-desc = Более половины заключенных сбежали с тюрьмы.
prisoner-minor = [color=crimson]Малая победа заключенных![/color]
prisoner-minor-desc = Хотя бы один заключенный сбежал.
prisoner-dead = [color=yellow]Все заключенные умерли![/color]
prisoner-dead-desc = Это ужасно!
prison-no-prisoners = [color=yellow]Заключенных не было![/color]
prison-no-prisoners-desc = В этот раз повезло...
prison-minor = [color=green]Малая победа тюрьмы![/color]
prison-minor-desc = Заключенные не смогли сбежать, но некоторые умерли.
prison-major = [color=green]Победа тюрьмы![/color]
prison-major-desc = Тюрьма сохранила всех заключенных.
4 changes: 4 additions & 0 deletions Resources/Prototypes/Stories/Roles/Jobs/Prison/prisoner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
canBeAntag: true
access:
- Prisoner
special:
- !type:AddComponentSpecial
components:
- type: Prisoner

- type: startingGear
id: PRISONPrisoner
Expand Down

0 comments on commit 417bb14

Please sign in to comment.