Files
tbd-station-14/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs
SlamBamActionman 2ff59f153e Add support for antag-before-job selection (#35789)
* Add support for antag-before-job selection

* Include logging
2025-03-12 16:48:39 +01:00

139 lines
4.3 KiB
C#

using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Station.Components;
using Content.Shared.GameTicking.Components;
using Content.Shared.Random.Helpers;
using Robust.Server.GameObjects;
using Robust.Shared.Collections;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Random;
namespace Content.Server.GameTicking.Rules;
public abstract partial class GameRuleSystem<T> where T: IComponent
{
protected EntityQueryEnumerator<ActiveGameRuleComponent, T, GameRuleComponent> QueryActiveRules()
{
return EntityQueryEnumerator<ActiveGameRuleComponent, T, GameRuleComponent>();
}
protected EntityQueryEnumerator<DelayedStartRuleComponent, T, GameRuleComponent> QueryDelayedRules()
{
return EntityQueryEnumerator<DelayedStartRuleComponent, T, GameRuleComponent>();
}
/// <summary>
/// Queries all gamerules, regardless of if they're active or not.
/// </summary>
protected EntityQueryEnumerator<T, GameRuleComponent> QueryAllRules()
{
return EntityQueryEnumerator<T, GameRuleComponent>();
}
/// <summary>
/// Utility function for finding a random event-eligible station entity
/// </summary>
protected bool TryGetRandomStation([NotNullWhen(true)] out EntityUid? station, Func<EntityUid, bool>? filter = null)
{
var stations = new ValueList<EntityUid>(Count<StationEventEligibleComponent>());
filter ??= _ => true;
var query = AllEntityQuery<StationEventEligibleComponent>();
while (query.MoveNext(out var uid, out _))
{
if (!filter(uid))
continue;
stations.Add(uid);
}
if (stations.Count == 0)
{
station = null;
return false;
}
// TODO: Engine PR.
station = stations[RobustRandom.Next(stations.Count)];
return true;
}
protected bool TryFindRandomTile(out Vector2i tile,
[NotNullWhen(true)] out EntityUid? targetStation,
out EntityUid targetGrid,
out EntityCoordinates targetCoords)
{
tile = default;
targetStation = EntityUid.Invalid;
targetGrid = EntityUid.Invalid;
targetCoords = EntityCoordinates.Invalid;
if (TryGetRandomStation(out targetStation))
{
return TryFindRandomTileOnStation((targetStation.Value, Comp<StationDataComponent>(targetStation.Value)),
out tile,
out targetGrid,
out targetCoords);
}
return false;
}
protected bool TryFindRandomTileOnStation(Entity<StationDataComponent> station,
out Vector2i tile,
out EntityUid targetGrid,
out EntityCoordinates targetCoords)
{
tile = default;
targetCoords = EntityCoordinates.Invalid;
targetGrid = EntityUid.Invalid;
// Weight grid choice by tilecount
var weights = new Dictionary<Entity<MapGridComponent>, float>();
foreach (var possibleTarget in station.Comp.Grids)
{
if (!TryComp<MapGridComponent>(possibleTarget, out var comp))
continue;
weights.Add((possibleTarget, comp), _map.GetAllTiles(possibleTarget, comp).Count());
}
if (weights.Count == 0)
{
targetGrid = EntityUid.Invalid;
return false;
}
(targetGrid, var gridComp) = RobustRandom.Pick(weights);
var found = false;
var aabb = gridComp.LocalAABB;
for (var i = 0; i < 10; i++)
{
var randomX = RobustRandom.Next((int) aabb.Left, (int) aabb.Right);
var randomY = RobustRandom.Next((int) aabb.Bottom, (int) aabb.Top);
tile = new Vector2i(randomX, randomY);
if (_atmosphere.IsTileSpace(targetGrid, Transform(targetGrid).MapUid, tile)
|| _atmosphere.IsTileAirBlocked(targetGrid, tile, mapGridComp: gridComp))
{
continue;
}
found = true;
targetCoords = _map.GridTileToLocal(targetGrid, gridComp, tile);
break;
}
return found;
}
protected void ForceEndSelf(EntityUid uid, GameRuleComponent? component = null)
{
GameTicker.EndGameRule(uid, component);
}
}