Files
tbd-station-14/Content.Server/GameTicking/Rules/GameRuleSystem.Utility.cs
Rainfey 4e6c59cfe5 Refactor antag rule code (#23445)
* Initial Pass, Rev, Thief

* Zombie initial pass

* Rebase, Traitor

* Nukeops, More overloads

* Revert RevolutionaryRuleComponent

* Use TryRoundStartAttempt, Rewrite nukie spawning

* Comments, Add task scheduler to GameRuleSystem

* Zombie initial testing done

* Sort methods, rework GameRuleTask

* Add CCVar, Initial testing continues

* Might as well get rid of the obsolete logging

* Oops, i dont know how to log apparently

* Suggested formatting fixes

* Suggested changes

* Fix merge issues

* Minor optimisation

* Allowed thief to choose other antags

* Review changes

* Spawn items on floor first, then inserting

* minor tweaks

* Shift as much as possible to ProtoId<>

* Remove unneeded

* Add exclusive antag attribute

* Fix merge issues

* Minor formatting fix

* Convert to struct

* Cleanup

* Review cleanup (need to test a lot)

* Some fixes, (mostly) tested

* oop

* Pass tests (for real)

---------

Co-authored-by: Rainfall <rainfey0+git@gmail.com>
Co-authored-by: AJCM <AJCM@tutanota.com>
2024-02-29 17:25:10 +11:00

138 lines
4.3 KiB
C#

using System.Diagnostics.CodeAnalysis;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Station.Components;
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 bool TryRoundStartAttempt(RoundStartAttemptEvent ev, string localizedPresetName)
{
var query = EntityQueryEnumerator<ActiveGameRuleComponent, T, GameRuleComponent>();
while (query.MoveNext(out _, out _, out _, out var gameRule))
{
var minPlayers = gameRule.MinPlayers;
if (!ev.Forced && ev.Players.Length < minPlayers)
{
ChatManager.SendAdminAnnouncement(Loc.GetString("preset-not-enough-ready-players",
("readyPlayersCount", ev.Players.Length), ("minimumPlayers", minPlayers),
("presetName", localizedPresetName)));
ev.Cancel();
continue;
}
if (ev.Players.Length == 0)
{
ChatManager.DispatchServerAnnouncement(Loc.GetString("preset-no-one-ready"));
ev.Cancel();
}
}
return !ev.Cancelled;
}
/// <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;
var possibleTargets = station.Comp.Grids;
if (possibleTargets.Count == 0)
{
targetGrid = EntityUid.Invalid;
return false;
}
targetGrid = RobustRandom.Pick(possibleTargets);
if (!TryComp<MapGridComponent>(targetGrid, out var gridComp))
return false;
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,
mapGridComp: gridComp)
|| _atmosphere.IsTileAirBlocked(targetGrid, tile, mapGridComp: gridComp))
{
continue;
}
found = true;
targetCoords = _map.GridTileToLocal(targetGrid, gridComp, tile);
break;
}
return found;
}
}