Files
ss14-wega/Content.Server/GameTicking/Rules/XenoborgsRuleSystem.cs
Samuka e5daa54e79 Xenoborgs part 7 (#40042)
* add mothership module

* option for mothership to open self UI

* fix mothership module

* remove mothership body

* swapp real hands for modules

* action sprite for mothership module

* removed hands from mothership core sprite

* xenoborgs now drop a pinpointer to the mothership core once destroyed

* add pinpointer to space movment module

* add base for XenoborgRule

* add xenoborg antag option

* something was needed

* something else was needed

* add ghost role spawn points

* change name in antag selection to Xenoborg Core

* add random spawnPoint markers that don't do anything

* add spawn points to mothership

* update spawn points

* add xenoborgs rule

* add xenoborgs rule to rotation

* add xenoborgs preset

* update preset with secret version
also added xenoborg mode description

* modify Antag Selection system to allow for custom entities via the AntagSelectionDefinition

* fix ghostroles spawners

* fix rule with new entityPrototype

* add spawnpoints to the mothership

* whitelist system to spawnpoints

* updated xenoborg components

* added xenoborg component to xenoborgs

* updated spawnpoints of xenoborgs in the mothership

* add new tags for xenoborg and mothership core

* add new tags for xenoborgs and mothership core

* update ghostrole spawners for xenoborgs

* message for when you get the xenoborg role

* explode all xenoborgs when mothership core dies

* for real now. explode all xenoborgs when mothership core is destroyed

* round end summary for xenoborgs

* temporary

* add guidebook entry for xenoborgs

* instructions on how to borg players

* removed lock from xenoborg control computer

* announcement when all xenoborgs die

* announcement when mothership core is destroyed

* typos

* fix error

* improve xenoborg mind role

* move sounds to xenoborg and mothership component

* play sounds when turned into xenoborg

* change sprites of mothership core actions

* minor fix

* add custom xenoborg start sound

* carps now attack xenoborgs

* added guide link to xenoborgs

* add guidebook link to xenoborgs

* added guidebook link to mothership core

* add link to source of the sound

* fixed minor issue

* has to be 1

* typo

* add light layer to mothership core sprite

* fixed antag selection system

* update guideboook

* update the guidebook again

* alphabet

* documentation

* simplify documentation

Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>

* make the briefing yml instead of code

* fix bug with sprites

* fix formating

* remove stuff from AntagSelection

* add stuff to AntagSpawner

* fix game rule

* removed secret xenoborg preset

* support for more than one entity for each antag role

* fix gamerule

* fixes

* no xeonborgs

* add xenoborgs to all at once

* engi xenoborg included

* more comments

* more recognizable

* more xenoborgs when more players

* removed unused stuff

* correct access

* removed unnecessary stuff

* use GetAliveHumans and make comments better

* Make the system more robust

* use a constant

* remove overload from the Destroy method

* has to be public to be used in the xenoborg system

* fix the mindrole methods

* not sure, but I was asked to do it

* use a constant for the color

* forgot to make it static

* removed param comments

* removed useless parameters

* fixed stuff

* added event listeneers to xenoborg mind change

* only 4

* unfuck the antagSpawner

* comment

* unfix stuff

* commentary

* removed xenoborg stuff from siliconLawSystem

* move some stuff to the component

* removed space

* removed uncessary stuff

* no need to crate a var

* move stuff from mothership comp to xenoborg comp

* removed XenoborgCoreRoleComponent

* comment on the AntagSelectLocationEvent

* added back empty line

* comment

* make the summary better

* make AntagRoleToPrototypes summary better

* adding useless stuff back cause it was there before

* hascomp instead of trycomp

* again

* LocId instead of string

* make a new logic for the whitelist of the spawnpoint

* added ghostrole tags back

* use hascomp instead of trycomp

* removed whitelist from SpawnPointComponent

* not needed anymore

* no longer subverted

* fixed names

* make it better

* add not

* i'm dumb

* briefing is now handled by the xenoborg system

* call evac if there is too many xenoborgs

* update submodule

* fix division

* Add AutoGenerateComponentPause and AutoPausedField to XenoborgsRuleComponent

* add lines between stuff

* Make the Blocking system more robust

* Make mothership inherit from BaseMob

* remove this stuff cause is bad

* Revert "Make the Blocking system more robust"

This reverts commit 099babfe1daef00e6073e04108920327416e4ca4.

* Mothership core snaps to grid

* stop mothership core from moving

* mothership core is static again

* make guidebook entry on how to xenoborg crew better

* Make mothership core damageable

* If xenoborgs need it, so do zombies i guess

* Start the NextRoundEndCheck

* follow private static readonly naming rule

* Samething

* Fix announcments

* Make it a datafield, no?

* Revert "Make it a datafield, no?"

This reverts commit 62f6255ccccdd583d7f833ae4dbcd09a670f721a.

* remove stuff

* doesn't need to move

* is kinda of a structure

* so it doesn't pry floors as soon as it spawns

* powercell hand to mothership core module

* label for new hand

* core_e -> core-e

* mothership core can pilot the shuttle again

* fix duplicated tag + description to xenoborg tags

* scout xenoborg can now move in space without the jetpack so it can better use the sword module

* improve basic xenoborg module

* remove changes from zombie rule comp

* swap AllEntityQuery for EntityQueryEnumerator

* new line at the end

* change to 15 seconds

* make MothershipCoreDeathAnnouncmentSent into a datafield

---------

Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Co-authored-by: beck-thompson <beck314159@hotmail.com>
2025-11-14 22:10:09 +00:00

168 lines
6.2 KiB
C#

using Content.Server.Antag;
using Content.Server.Chat.Systems;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.RoundEnd;
using Content.Server.Station.Systems;
using Content.Shared.Destructible;
using Content.Shared.GameTicking.Components;
using Content.Shared.Mind;
using Content.Shared.Mobs.Systems;
using Content.Shared.Xenoborgs.Components;
using Robust.Shared.Timing;
namespace Content.Server.GameTicking.Rules;
public sealed class XenoborgsRuleSystem : GameRuleSystem<XenoborgsRuleComponent>
{
[Dependency] private readonly AntagSelectionSystem _antag = default!;
[Dependency] private readonly ChatSystem _chatSystem = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly SharedMindSystem _mindSystem = default!;
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly IGameTiming _timing = default!;
private static readonly Color AnnouncmentColor = Color.Gold;
public void SendXenoborgDeathAnnouncement(Entity<XenoborgsRuleComponent> ent, bool mothershipCoreAlive)
{
if (ent.Comp.MothershipCoreDeathAnnouncmentSent)
return;
var status = mothershipCoreAlive ? "alive" : "dead";
_chatSystem.DispatchGlobalAnnouncement(
Loc.GetString($"xenoborgs-no-more-threat-mothership-core-{status}-announcement"),
colorOverride: AnnouncmentColor);
}
public void SendMothershipDeathAnnouncement(Entity<XenoborgsRuleComponent> ent)
{
_chatSystem.DispatchGlobalAnnouncement(
Loc.GetString("mothership-destroyed-announcement"),
colorOverride: AnnouncmentColor);
ent.Comp.MothershipCoreDeathAnnouncmentSent = true;
}
// TODO: Refactor the end of round text
protected override void AppendRoundEndText(EntityUid uid,
XenoborgsRuleComponent component,
GameRuleComponent gameRule,
ref RoundEndTextAppendEvent args)
{
base.AppendRoundEndText(uid, component, gameRule, ref args);
var numXenoborgs = GetNumberXenoborgs();
var numHumans = _mindSystem.GetAliveHumans().Count;
if (numXenoborgs < 5)
args.AddLine(Loc.GetString("xenoborgs-crewmajor"));
else if (4 * numXenoborgs < numHumans)
args.AddLine(Loc.GetString("xenoborgs-crewmajor"));
else if (2 * numXenoborgs < numHumans)
args.AddLine(Loc.GetString("xenoborgs-crewminor"));
else if (1.5 * numXenoborgs < numHumans)
args.AddLine(Loc.GetString("xenoborgs-neutral"));
else if (numXenoborgs < numHumans)
args.AddLine(Loc.GetString("xenoborgs-borgsminor"));
else
args.AddLine(Loc.GetString("xenoborgs-borgsmajor"));
var numMothershipCores = GetNumberMothershipCores();
if (numMothershipCores == 0)
args.AddLine(Loc.GetString("xenoborgs-cond-all-xenoborgs-dead-core-dead"));
else if (numXenoborgs == 0)
args.AddLine(Loc.GetString("xenoborgs-cond-all-xenoborgs-dead-core-alive"));
else
args.AddLine(Loc.GetString("xenoborgs-cond-xenoborgs-alive", ("count", numXenoborgs)));
args.AddLine(Loc.GetString("xenoborgs-list-start"));
var antags = _antag.GetAntagIdentifiers(uid);
foreach (var (_, sessionData, name) in antags)
{
args.AddLine(Loc.GetString("xenoborgs-list", ("name", name), ("user", sessionData.UserName)));
}
}
private void CheckRoundEnd(XenoborgsRuleComponent xenoborgsRuleComponent)
{
var numXenoborgs = GetNumberXenoborgs();
var numHumans = _mindSystem.GetAliveHumans().Count;
if ((float)numXenoborgs / numHumans > xenoborgsRuleComponent.XenoborgShuttleCallPercentage)
{
foreach (var station in _station.GetStations())
{
_chatSystem.DispatchStationAnnouncement(station, Loc.GetString("xenoborg-shuttle-call"), colorOverride: Color.BlueViolet);
}
_roundEnd.RequestRoundEnd(null, false);
}
}
protected override void Started(EntityUid uid, XenoborgsRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
{
base.Started(uid, component, gameRule, args);
component.NextRoundEndCheck = _timing.CurTime + component.EndCheckDelay;
}
protected override void ActiveTick(EntityUid uid, XenoborgsRuleComponent component, GameRuleComponent gameRule, float frameTime)
{
base.ActiveTick(uid, component, gameRule, frameTime);
if (!component.NextRoundEndCheck.HasValue || component.NextRoundEndCheck > _timing.CurTime)
return;
CheckRoundEnd(component);
component.NextRoundEndCheck = _timing.CurTime + component.EndCheckDelay;
}
/// <summary>
/// Get the number of xenoborgs
/// </summary>
/// <param name="playerControlled">if it should only include xenoborgs with a mind</param>
/// <param name="alive">if it should only include xenoborgs that are alive</param>
/// <returns>the number of xenoborgs</returns>
private int GetNumberXenoborgs(bool playerControlled = true, bool alive = true)
{
var numberXenoborgs = 0;
var query = EntityQueryEnumerator<XenoborgComponent>();
while (query.MoveNext(out var xenoborg, out _))
{
if (HasComp<MothershipCoreComponent>(xenoborg))
continue;
if (playerControlled && !_mindSystem.TryGetMind(xenoborg, out _, out _))
continue;
if (alive && !_mobState.IsAlive(xenoborg))
continue;
numberXenoborgs++;
}
return numberXenoborgs;
}
/// <summary>
/// Gets the number of xenoborg cores
/// </summary>
/// <returns>the number of xenoborg cores</returns>
private int GetNumberMothershipCores()
{
var numberMothershipCores = 0;
var mothershipCoreQuery = EntityQueryEnumerator<MothershipCoreComponent>();
while (mothershipCoreQuery.MoveNext(out _, out _))
{
numberMothershipCores++;
}
return numberMothershipCores;
}
}