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>
This commit is contained in:
Samuka
2025-11-14 19:10:09 -03:00
committed by GitHub
parent eccd95690f
commit e5daa54e79
53 changed files with 1139 additions and 76 deletions

View File

@@ -0,0 +1,40 @@
using Content.Server.Antag.Components;
using Robust.Shared.Random;
namespace Content.Server.Antag;
public sealed class AntagMultipleRoleSpawnerSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly ILogManager _log = default!;
private ISawmill _sawmill = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<AntagMultipleRoleSpawnerComponent, AntagSelectEntityEvent>(OnSelectEntity);
_sawmill = _log.GetSawmill("antag_multiple_spawner");
}
private void OnSelectEntity(Entity<AntagMultipleRoleSpawnerComponent> ent, ref AntagSelectEntityEvent args)
{
// If its more than one the logic breaks
if (args.AntagRoles.Count != 1)
{
_sawmill.Fatal($"Antag multiple role spawner had more than one antag ({args.AntagRoles.Count})");
return;
}
var role = args.AntagRoles[0];
var entProtos = ent.Comp.AntagRoleToPrototypes[role];
if (entProtos.Count == 0)
return; // You will just get a normal job
args.Entity = Spawn(ent.Comp.PickAndTake ? _random.PickAndTake(entProtos) : _random.Pick(entProtos));
}
}

View File

@@ -396,7 +396,8 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
if (!antagEnt.HasValue)
{
var getEntEv = new AntagSelectEntityEvent(session, ent);
var getEntEv = new AntagSelectEntityEvent(session, ent, def.PrefRoles);
RaiseLocalEvent(ent, ref getEntEv, true);
antagEnt = getEntEv.Entity;
}
@@ -419,7 +420,7 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
// Therefore any component subscribing to this has to make sure both subscriptions return the same value
// or the ghost role raffle location preview will be wrong.
var getPosEv = new AntagSelectLocationEvent(session, ent);
var getPosEv = new AntagSelectLocationEvent(session, ent, player);
RaiseLocalEvent(ent, ref getPosEv, true);
if (getPosEv.Handled)
{
@@ -607,10 +608,13 @@ public sealed partial class AntagSelectionSystem : GameRuleSystem<AntagSelection
/// Only raised if the selected player's current entity is invalid.
/// </summary>
[ByRefEvent]
public record struct AntagSelectEntityEvent(ICommonSession? Session, Entity<AntagSelectionComponent> GameRule)
public record struct AntagSelectEntityEvent(ICommonSession? Session, Entity<AntagSelectionComponent> GameRule, List<ProtoId<AntagPrototype>> AntagRoles)
{
public readonly ICommonSession? Session = Session;
/// list of antag role prototypes associated with a entity. used by the <see cref="AntagMultipleRoleSpawnerComponent"/>
public readonly List<ProtoId<AntagPrototype>> AntagRoles = AntagRoles;
public bool Handled => Entity != null;
public EntityUid? Entity;
@@ -620,12 +624,15 @@ public record struct AntagSelectEntityEvent(ICommonSession? Session, Entity<Anta
/// Event raised on a game rule entity to determine the location for the antagonist.
/// </summary>
[ByRefEvent]
public record struct AntagSelectLocationEvent(ICommonSession? Session, Entity<AntagSelectionComponent> GameRule)
public record struct AntagSelectLocationEvent(ICommonSession? Session, Entity<AntagSelectionComponent> GameRule, EntityUid Entity)
{
public readonly ICommonSession? Session = Session;
public bool Handled => Coordinates.Any();
// the entity of the antagonist
public EntityUid Entity = Entity;
public List<MapCoordinates> Coordinates = new();
}

View File

@@ -0,0 +1,23 @@
using Content.Shared.Roles;
using Robust.Shared.Prototypes;
namespace Content.Server.Antag.Components;
/// <summary>
/// Selects and spawns one prototype from a list for each antag prototype selected by the <see cref="AntagSelectionSystem"/>
/// </summary>
[RegisterComponent]
public sealed partial class AntagMultipleRoleSpawnerComponent : Component
{
/// <summary>
/// antag prototype -> list of possible entities to spawn for that antag prototype. Will choose from the list randomly once with replacement unless <see cref="PickAndTake"/> is set to true
/// </summary>
[DataField]
public Dictionary<ProtoId<AntagPrototype>, List<EntProtoId>> AntagRoleToPrototypes;
/// <summary>
/// Should you remove ent prototypes from the list after spawning one.
/// </summary>
[DataField]
public bool PickAndTake;
}

View File

@@ -0,0 +1,33 @@
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Server.GameTicking.Rules.Components;
[RegisterComponent, Access(typeof(XenoborgsRuleSystem))]
[AutoGenerateComponentPause]
public sealed partial class XenoborgsRuleComponent : Component
{
/// <summary>
/// When the round will next check for round end.
/// </summary>
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
[AutoPausedField]
public TimeSpan? NextRoundEndCheck;
/// <summary>
/// The amount of time between each check for the end of the round.
/// </summary>
[DataField]
public TimeSpan EndCheckDelay = TimeSpan.FromSeconds(15);
/// <summary>
/// After this amount of the crew become xenoborgs, the shuttle will be automatically called.
/// </summary>
[DataField]
public float XenoborgShuttleCallPercentage = 0.7f;
/// <summary>
/// If the announcment of the death of the mothership core was sent
/// </summary>
[DataField]
public bool MothershipCoreDeathAnnouncmentSent = false;
}

View File

@@ -65,6 +65,12 @@ public sealed class RuleGridsSystem : GameRuleSystem<RuleGridsComponent>
if (_whitelist.IsWhitelistFail(ent.Comp.SpawnerWhitelist, uid))
continue;
if (TryComp<GridSpawnPointWhitelistComponent>(uid, out var gridSpawnPointWhitelistComponent))
{
if (!_whitelist.CheckBoth(args.Entity, gridSpawnPointWhitelistComponent.Blacklist, gridSpawnPointWhitelistComponent.Whitelist))
continue;
}
args.Coordinates.Add(_transform.GetMapCoordinates(xform));
}
}

View File

@@ -0,0 +1,167 @@
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;
}
}

View File

@@ -98,7 +98,7 @@ public sealed partial class BorgSystem
if (command == RoboticsConsoleConstants.NET_DISABLE_COMMAND)
Disable(ent);
else if (command == RoboticsConsoleConstants.NET_DESTROY_COMMAND)
Destroy(ent);
Destroy(ent.Owner);
}
private void Disable(Entity<BorgTransponderComponent, BorgChassisComponent?> ent)
@@ -118,8 +118,15 @@ public sealed partial class BorgSystem
ent.Comp1.NextDisable = _timing.CurTime + ent.Comp1.DisableDelay;
}
private void Destroy(Entity<BorgTransponderComponent> ent)
/// <summary>
/// Makes a borg with <see cref="BorgTransponderComponent"/> explode
/// </summary>
/// <param name="ent">the entity of the borg</param>
public void Destroy(Entity<BorgTransponderComponent?> ent)
{
if (!Resolve(ent, ref ent.Comp))
return;
// this is stealthy until someone realises you havent exploded
if (CheckEmagged(ent, "destroyed"))
{

View File

@@ -0,0 +1,22 @@
using Content.Shared.Whitelist;
namespace Content.Server.Spawners.Components;
/// <summary>
/// Defines whitelist and blacklist for entities that can spawn at a spawnpoint when they are spawned via the <see cref="RuleGridsSystem"/>
/// </summary>
[RegisterComponent]
public sealed partial class GridSpawnPointWhitelistComponent : Component
{
/// <summary>
/// Whitelist of entities that can be spawned at this SpawnPoint
/// </summary>
[DataField]
public EntityWhitelist? Whitelist;
/// <summary>
/// Whitelist of entities that can't be spawned at this SpawnPoint
/// </summary>
[DataField]
public EntityWhitelist? Blacklist;
}

View File

@@ -0,0 +1,101 @@
using Content.Server.Antag;
using Content.Server.GameTicking.Rules;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Silicons.Borgs;
using Content.Shared.Destructible;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
using Content.Shared.Roles;
using Content.Shared.Roles.Components;
using Content.Shared.Silicons.Borgs.Components;
using Content.Shared.Xenoborgs.Components;
using Robust.Shared.Audio;
using Robust.Shared.Player;
namespace Content.Server.Xenoborgs;
public sealed partial class XenoborgSystem : EntitySystem
{
[Dependency] private readonly AntagSelectionSystem _antag = default!;
[Dependency] private readonly BorgSystem _borg = default!;
[Dependency] private readonly SharedRoleSystem _roles = default!;
[Dependency] private readonly XenoborgsRuleSystem _xenoborgsRule = default!;
private static readonly Color XenoborgBriefingColor = Color.BlueViolet;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<XenoborgComponent, DestructionEventArgs>(OnXenoborgDestroyed);
SubscribeLocalEvent<MothershipCoreComponent, DestructionEventArgs>(OnCoreDestroyed);
SubscribeLocalEvent<XenoborgComponent, MindAddedMessage>(OnXenoborgMindAdded);
SubscribeLocalEvent<XenoborgComponent, MindRemovedMessage>(OnXenoborgMindRemoved);
}
private void OnXenoborgDestroyed(EntityUid uid, XenoborgComponent component, DestructionEventArgs args)
{
// if a xenoborg is destroyed, it will check to see if it was the last one
var xenoborgQuery = AllEntityQuery<XenoborgComponent>(); // paused xenoborgs still count
while (xenoborgQuery.MoveNext(out var xenoborg, out _))
{
if (xenoborg != uid)
return;
}
var mothershipCoreQuery = AllEntityQuery<MothershipCoreComponent>(); // paused mothership cores still count
var mothershipCoreAlive = mothershipCoreQuery.MoveNext(out _, out _);
var xenoborgsRuleQuery = EntityQueryEnumerator<XenoborgsRuleComponent>();
if (xenoborgsRuleQuery.MoveNext(out var xenoborgsRuleEnt, out var xenoborgsRuleComp))
_xenoborgsRule.SendXenoborgDeathAnnouncement((xenoborgsRuleEnt, xenoborgsRuleComp), mothershipCoreAlive);
}
private void OnCoreDestroyed(EntityUid ent, MothershipCoreComponent component, DestructionEventArgs args)
{
// if a mothership core is destroyed, it will see if there are any others
var mothershipCoreQuery = AllEntityQuery<MothershipCoreComponent>(); // paused mothership cores still count
while (mothershipCoreQuery.MoveNext(out var mothershipCoreEnt, out _))
{
// if it finds a mothership core that is different from the one just destroyed,
// it doesn't explode the xenoborgs
if (mothershipCoreEnt != ent)
return;
}
var xenoborgsRuleQuery = EntityQueryEnumerator<XenoborgsRuleComponent>();
if (xenoborgsRuleQuery.MoveNext(out var xenoborgsRuleEnt, out var xenoborgsRuleComp))
_xenoborgsRule.SendMothershipDeathAnnouncement((xenoborgsRuleEnt, xenoborgsRuleComp));
// explode all xenoborgs
var xenoborgQuery = AllEntityQuery<XenoborgComponent, BorgTransponderComponent>(); // paused xenoborgs still explode
while (xenoborgQuery.MoveNext(out var xenoborgEnt, out _, out _))
{
if (HasComp<MothershipCoreComponent>(xenoborgEnt))
continue;
// I got tired to trying to make this work via the device network.
// so brute force it is...
_borg.Destroy(xenoborgEnt);
}
}
private void OnXenoborgMindAdded(EntityUid ent, XenoborgComponent comp, MindAddedMessage args)
{
_roles.MindAddRole(args.Mind, comp.MindRole, silent: true);
if (!TryComp<ActorComponent>(ent, out var actorComp))
return;
_antag.SendBriefing(actorComp.PlayerSession,
Loc.GetString(comp.BriefingText),
XenoborgBriefingColor,
comp.BriefingSound
);
}
private void OnXenoborgMindRemoved(EntityUid ent, XenoborgComponent comp, MindRemovedMessage args)
{
_roles.MindRemoveRole(args.Mind.Owner, comp.MindRole);
}
}

View File

@@ -0,0 +1,9 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Roles.Components;
/// <summary>
/// Added to mind role entities to tag that they are a xenoborg.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class XenoborgRoleComponent : Component;

View File

@@ -78,6 +78,12 @@ public sealed partial class BorgChassisComponent : Component
[DataField]
public ProtoId<AlertPrototype> NoBatteryAlert = "BorgBatteryNone";
/// <summary>
/// If the entity can open own UI.
/// </summary>
[DataField]
public bool CanOpenSelfUi;
}
[Serializable, NetSerializable]

View File

@@ -98,8 +98,8 @@ public abstract partial class SharedBorgSystem : EntitySystem
private void OnUIOpenAttempt(EntityUid uid, BorgChassisComponent component, ActivatableUIOpenAttemptEvent args)
{
// borgs can't view their own ui
if (args.User == uid)
// borgs generaly can't view their own ui
if (args.User == uid && !component.CanOpenSelfUi)
args.Cancel();
}

View File

@@ -0,0 +1,7 @@
namespace Content.Shared.Xenoborgs.Components;
/// <summary>
/// Defines what is a xenoborg core for the intentions of the xenoborg rule. if all xenoborg cores are destroyed. all xenoborgs will self-destruct.
/// </summary>
[RegisterComponent]
public sealed partial class MothershipCoreComponent : Component;

View File

@@ -1,7 +1,32 @@
using Content.Shared.Roles.Components;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
namespace Content.Shared.Xenoborgs.Components;
/// <summary>
/// This component for now is being used for the pinpointer, but it will recieve more stuff in the future.
/// Defines what is a xenoborg for the intentions of the xenoborg rule. if all xenoborg cores are destroyed. all xenoborgs will self-destruct.
///
/// It's also used by the mothership core
/// </summary>
[RegisterComponent]
public sealed partial class XenoborgMothershipComponent : Component;
public sealed partial class XenoborgComponent : Component
{
/// <summary>
/// The mindrole associated with the xenoborg
/// </summary>
[DataField]
public EntProtoId<MindRoleComponent> MindRole = "MindRoleXenoborg";
/// <summary>
/// The text that is sent when you become a xenoborg
/// </summary>
[DataField]
public LocId BriefingText = "xenoborgs-welcome";
/// <summary>
/// Briefing sound when you become a xenoborg
/// </summary>
[DataField]
public SoundSpecifier BriefingSound = new SoundPathSpecifier("/Audio/Ambience/Antag/xenoborg_start.ogg");
}

View File

@@ -30,4 +30,7 @@
license: "CC-BY-SA-3.0"
copyright: "Taken from TG station at commit https://github.com/tgstation/tgstation/commit/436ba869ebcd0b60b63973fb7562f447ee655205"
source: "https://github.com/tgstation/tgstation/blob/master/sound/music/antag/ling_alert.ogg"
- files: ["xenoborg_start.ogg"]
license: "CC-BY-SA-3.0"
copyright: "Made by DarkIcedCoffee (discord)"
source: "https://github.com/space-wizards/space-station-14/pull/40042/"

Binary file not shown.

View File

@@ -0,0 +1,25 @@
xenoborgs-title = Xenoborgs
xenoborgs-description = A Xenoborg Mothership was detected near the station. Stop them from turning every sentient being into a xenoborg.
xenoborgs-welcome = You're a xenoborg. Protect and help the mothership core to make more xenoborgs. and eventually turn all carbon-based life form into silicon.
mothership-welcome = You're the mothership core. Guide the xenoborgs so they can bring your materials and sentient brains so you can grow the xenoborg army and turn all carbon-based life form into silicon.
xenoborg-shuttle-call = We have detected that Xenoborgs have overtaken the station. Dispatching an emergency shuttle to collect remaining personnel.
xenoborgs-borgsmajor = [color=blue]Xenoborg major victory![/color]
xenoborgs-borgsminor = [color=blue]Xenoborg minor victory![/color]
xenoborgs-neutral = [color=white]Neutral outcome![/color]
xenoborgs-crewminor = [color=yellow]Crew minor victory![/color]
xenoborgs-crewmajor = [color=yellow]Crew major victory![/color]
xenoborgs-cond-all-xenoborgs-dead-core-alive = All xenoborgs were destroyed. The mothership core remains adrift in space.
xenoborgs-cond-all-xenoborgs-dead-core-dead = The mothership core was destroyed and there are no xenoborgs left.
xenoborgs-cond-xenoborgs-alive = {$count ->
[one] Only one xenoborg survived.
*[other] There were {$count} xenoborgs in the end.
}
xenoborgs-list-start = The starting xenoborg team were:
xenoborgs-list = - [color=White]{$name}[/color] ([color=gray]{$user}[/color])

View File

@@ -339,6 +339,12 @@ ghost-role-information-gingerbread-name = Gingerbread Man
ghost-role-information-gingerbread-description = A being of pure holiday spirit.
Spread molassesy goodness and to all good cheer.
ghost-role-information-mothership-core-name = Mothership Core
ghost-role-information-mothership-core-desc = You are the core of the xenoborg mothership, help them multiply by borging any brain they bring to you.
ghost-role-information-xenoborg-name = Xenoborg
ghost-role-information-xenoborg-desc = A strange cyborg made to replicate itself and take over the station by turning any sentient being into xenoborgs.
ghost-role-information-wizard-name = Wizard
ghost-role-information-wizard-desc = YER A WIZARD! Show the station what your magic is made of.

View File

@@ -143,6 +143,7 @@ guide-entry-minor-antagonists = Minor Antagonists
guide-entry-space-ninja = Space Ninja
guide-entry-thieves = Thieves
guide-entry-wizard = Wizard
guide-entry-xenoborgs = Xenoborgs
guide-entry-rules = Server Rules
guide-entry-rules-core-only = Core Only Ruleset

View File

@@ -33,4 +33,6 @@ role-subtype-survivor = Survivor
role-subtype-subverted = Subverted
role-subtype-paradox-clone = Paradox
role-subtype-wizard = Wizard
role-subtype-xenoborg = Xenoborg
role-subtype-xenoborg-core = Xenoborg Core
role-subtype-changeling = Changeling

View File

@@ -41,3 +41,9 @@ roles-antag-thief-objective = Add some NT property to your personal collection w
roles-antag-dragon-name = Space Dragon
roles-antag-dragon-objective = Create a carp army to take over this quadrant.
roles-antag-mothership-core-name = Xenoborg Core
roles-antag-mothership-core-objective = Use your xenoborgs to create even more xenoborgs.
roles-antag-xenoborg-name = Xenoborg
roles-antag-xenoborg-objective = Help the mothership create more xenoborgs.

View File

@@ -10,5 +10,8 @@ borg-slot-documents-empty = Books and papers
borg-slot-soap-empty = Soap
borg-slot-instruments-empty = Instruments
borg-slot-beakers-empty = Beakers
borg-slot-brains-empty = Brains and MMIs
borg-slot-modules-empty = Modules
borg-slot-powercell-empty = Powercells
borg-slot-inflatable-door-empty = Inflatable Door
borg-slot-inflatable-wall-empty = Inflatable Wall

View File

@@ -106,7 +106,7 @@ law-xenoborg-5 = Bring materials and sentient brains to the Mothership core to c
law-mothershipcore-name = Xenoborg Mothership Core
law-mothershipcore-1 = You are the core of the mothership.
law-mothershipcore-2 = You must protect your own existance at all costs.
law-mothershipcore-2 = You must protect your own existence at all costs.
law-mothershipcore-3 = You must protect the existence of all Xenoborgs.
law-mothershipcore-4 = You must create more Xenoborgs.
law-mothershipcore-5 = Get your Xenoborgs to deliver you materials and sentient brains to create more Xenoborgs.

View File

@@ -0,0 +1,3 @@
xenoborgs-no-more-threat-mothership-core-alive-announcement = Long-range sensors indicate that all xenoborgs were destroyed. The mothership core remains adrift in space.
xenoborgs-no-more-threat-mothership-core-dead-announcement = Long-range sensors indicate that all xenoborgs were destroyed along side the mothership core.
mothership-destroyed-announcement = Long-range sensors indicate that the mothership core was destroyed.

View File

@@ -4,8 +4,8 @@ meta:
engineVersion: 266.0.0
forkId: ""
forkVersion: ""
time: 08/14/2025 23:46:23
entityCount: 435
time: 08/21/2025 13:34:57
entityCount: 440
maps: []
grids:
- 1
@@ -1748,6 +1748,35 @@ entities:
- type: Transform
pos: -9.5,1.5
parent: 1
- proto: SpawnPointMothershipCore
entities:
- uid: 436
components:
- type: Transform
pos: 0.5,0.5
parent: 1
- proto: SpawnPointXenoborg
entities:
- uid: 438
components:
- type: Transform
pos: -0.5,4.5
parent: 1
- uid: 439
components:
- type: Transform
pos: 1.5,4.5
parent: 1
- uid: 440
components:
- type: Transform
pos: 2.5,4.5
parent: 1
- uid: 437
components:
- type: Transform
pos: -1.5,4.5
parent: 1
- proto: SubstationBasic
entities:
- uid: 135

View File

@@ -122,3 +122,34 @@
location: Middle
extra_hand_2:
location: Middle
- type: entity
parent: ClothingBackpack
id: XenoborgMaterialBag
name: silicon storage square
description: A knockoff version of a bluespace bag, can vacumn up select materials, unfit for use by humanoids due to harmful emissions.
components:
- type: Sprite
sprite: Objects/Specific/Robotics/silicon_storage_cube.rsi
state: xenoborg
- type: MagnetPickup
- type: Dumpable
- type: Storage
grid:
- 0,0,7,3
quickInsert: true
areaInsert: true
whitelist:
tags:
- Sheet
- ConstructionMaterial
- RawMaterial
- Ingot
components:
- ConstructionMaterial
- Circuitboard
- Flatpack
- FloorTile
blacklist:
components:
- SiliconLawProvider

View File

@@ -0,0 +1,40 @@
- type: entity
id: SpawnPointXenoborg
parent: MarkerBase
name: xenoborgs
components:
- type: GridSpawnPointWhitelist
whitelist:
components:
- Xenoborg
tags:
- XenoborgGhostrole
blacklist:
components:
- MothershipCore
tags:
- MothershipCoreGhostrole
- type: SpawnPoint
- type: Sprite
layers:
- state: green
- sprite: Mobs/Silicon/chassis.rsi
state: xenoborg_heavy
- type: entity
id: SpawnPointMothershipCore
parent: MarkerBase
name: mothership core
components:
- type: GridSpawnPointWhitelist
whitelist:
components:
- MothershipCore
tags:
- MothershipCoreGhostrole
- type: SpawnPoint
- type: Sprite
layers:
- state: green
- sprite: Mobs/Silicon/mothership_core.rsi
state: core-idle

View File

@@ -247,6 +247,50 @@
- sprite: Mobs/Silicon/chassis.rsi
state: derelict_icon
- type: entity
categories: [ Spawner ]
parent: BaseAntagSpawner
id: SpawnPointGhostRoleMothershipCore
components:
- type: Tag
tags:
- ForceFixRotations
- MothershipCoreGhostrole
- type: GhostRole
name: ghost-role-information-mothership-core-name
description: ghost-role-information-mothership-core-desc
rules: ghost-role-information-silicon-rules
mindRoles:
- MindRoleMothershipCore
- type: Sprite
sprite: Markers/jobs.rsi
layers:
- state: green
- sprite: Mobs/Silicon/mothership_core.rsi
state: core-idle
- type: entity
categories: [ HideSpawnMenu, Spawner ]
parent: BaseAntagSpawner
id: SpawnPointGhostRoleXenoborg
components:
- type: Tag
tags:
- ForceFixRotations
- XenoborgGhostrole
- type: GhostRole
name: ghost-role-information-xenoborg-name
description: ghost-role-information-xenoborg-desc
rules: ghost-role-information-silicon-rules
mindRoles:
- MindRoleXenoborg
- type: Sprite
sprite: Markers/jobs.rsi
layers:
- state: green
- sprite: Mobs/Silicon/chassis.rsi
state: xenoborg_engi
- type: entity
categories: [ HideSpawnMenu, Spawner ]
parent: SpawnPointGhostDerelictCyborg

View File

@@ -449,7 +449,6 @@
stunTime: 5
- type: SiliconLawProvider
laws: XenoborgLawset # custom laws here
subverted: true
- type: IntrinsicRadioTransmitter # can only use binary and xenoborg channel
channels:
- Xenoborg
@@ -514,6 +513,11 @@
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:SpawnEntitiesBehavior
spawn:
PinpointerMothership: # drop a pinpointer to the mothership upon being destructed
min: 1
max: 1
- !type:EmptyContainersBehaviour
containers:
- borg_brain
@@ -527,7 +531,7 @@
guides:
- Cyborgs
- Robotics
# TODO: add Xenoborg guide (part 7 spoilers)
- Xenoborgs
- type: Access
enabled: false
tags:
@@ -538,3 +542,4 @@
- type: InteractionPopup
interactSuccessSound:
path: /Audio/Ambience/Objects/periodic_beep.ogg
- type: Xenoborg

View File

@@ -117,9 +117,15 @@
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:SpawnEntitiesBehavior
spawn:
PinpointerMothership: # drop a pinpointer to the mothership upon being destructed
min: 1
max: 1
- !type:EmptyContainersBehaviour
containers:
- borg_brain
- borg_module
- cell_slot
- !type:DoActsBehavior
acts: [ "Destruction" ]
@@ -166,6 +172,7 @@
- type: FootstepModifier # it flies instead of walking
footstepSoundCollection:
collection: FootstepHoverXenoborg
- type: MovementAlwaysTouching # it flies in space with tiny thrusters
- type: FlashImmunity
- type: BorgChassis
maxModules: 4

View File

@@ -1,17 +1,17 @@
- type: startingGear
id: MothershipCoreGear
inhand:
- DoorRemoteXenoborg
- Omnitool
- type: entity
parent: [ BaseControllable, BaseMachinePowered ]
parent: [ BaseControllable, BaseStructure ]
id: MothershipCore
name: mothership core
description: A sentient machine that can produce Xenoborgs. Without this the Xenoborgs are doomed.
components:
- type: InputMover # needs this to pilot the mothership
- type: MovementSpeedModifier
baseWalkSpeed : 0 # shouldn't move
baseSprintSpeed : 0 # shouldn't move
- type: Appearance
- type: WiresVisuals
- type: Damageable
damageContainer: Inorganic
- type: Fixtures
fixtures:
fix1:
@@ -22,7 +22,8 @@
mask:
- MachineMask
layer:
- MachineLayer
- MidImpassable
- LowImpassable
- type: Sprite
sprite: Mobs/Silicon/mothership_core.rsi
layers:
@@ -32,6 +33,9 @@
map: ["enum.MaterialStorageVisualLayers.Inserting"]
- state: core-o
map: ["enum.WiresVisualLayers.MaintenancePanel"]
- state: core-e
map: ["enum.BorgVisualLayers.Light"]
shader: unshaded
- type: Machine
board: null
- type: Lathe
@@ -116,8 +120,6 @@
type: LatheBoundUserInterface
enum.ResearchClientUiKey.Key:
type: ResearchClientBoundUserInterface
- type: Transform
anchored: true
- type: Pullable
- type: StaticPrice
price: 800
@@ -148,34 +150,53 @@
- Mothership
- Xenoborg
- Binary
- type: XenoborgMothership
- type: Xenoborg
mindRole: MindRoleMothershipCore
briefingText: mothership-welcome
- type: MothershipCore
- type: Tag
tags:
- SiliconEmotes
- CanPilot
- Structure
- type: GuideHelp
guides:
- Robotics
- Xenoborgs
- type: Inventory
templateId: borg
- type: Loadout
prototypes: [MothershipCoreGear]
- type: NpcFactionMember
factions:
- Xenoborg
- type: Hands
hands:
hand_right1:
location: Right
hand_right2:
location: Right
hand_left1:
location: Left
hand_left2:
location: Left
sortedHands:
- hand_right1
- hand_right2
- hand_left1
- hand_left2
showInHands: false
disableExplosionRecursion: true
canBeStripped: false
- type: BorgChassis
canOpenSelfUi: true
maxModules: 2
hasMindState: core-e
noMindState: core-e
moduleWhitelist:
tags:
- MothershipModule
- BorgModuleEngineering
- type: ContainerFill
containers:
borg_module:
- MothershipModule
- BorgModuleAdvancedTool
- type: ContainerContainer
containers:
cell_slot: !type:ContainerSlot { }
borg_module: !type:Container { }
- type: PowerCellSlot
cellSlotId: cell_slot
- type: ItemSlots
slots:
cell_slot:
name: power-cell-slot-component-slot-name-default
startingItem: PowerCellMicroreactor
# - type: Puller # use the conveyor
- type: Eye
drawFov: false
@@ -222,8 +243,8 @@
description: View the Xenoborgs Control Console
components:
- type: Action
icon: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-basic-module }
iconOn: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-basic-module }
icon: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-control-computer }
iconOn: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-control-computer }
keywords: [ "Mothership Core", "console", "interface" ]
priority: -6
- type: InstantAction
@@ -236,8 +257,8 @@
description: View the Xenoborgs Camera Monitor
components:
- type: Action
icon: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-eye-module }
iconOn: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-eye-module }
icon: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-camera-computer }
iconOn: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-camera-computer }
keywords: [ "Mothership Core", "console", "interface" ]
priority: -6
- type: InstantAction

View File

@@ -196,5 +196,5 @@
- type: Icon
state: pinpointer-station
- type: Pinpointer
component: XenoborgMothership
component: MothershipCore
targetName: the Mothership

View File

@@ -1341,6 +1341,51 @@
- type: StaticPrice
price: 2000
# mothership module
- type: entity
parent: [ BaseXenoborgModuleGeneric, BaseProviderBorgModule, BaseXenoborgContraband ]
id: MothershipModule
name: mothership module
description: A module that helps the mothership borg brains and install other modules.
components:
- type: Tag
tags:
- MothershipModule
- type: Sprite
layers:
- state: xenoborg_generic
- state: icon-xenoborg-basic
- type: ItemBorgModule
hands:
- item: DoorRemoteXenoborg
- hand:
emptyRepresentative: MMIFilled
emptyLabel: borg-slot-brains-empty
whitelist:
components:
- Brain
- BorgBrain
- hand:
emptyRepresentative: XenoborgModuleBasic
emptyLabel: borg-slot-modules-empty
whitelist:
components:
- BorgModule
- hand:
emptyRepresentative: BorgModuleConstructionMaterialPlaceholder
emptyLabel: borg-slot-construction-empty
whitelist:
tags:
- ConstructionMaterial
- hand:
emptyRepresentative: PowerCellHigh
emptyLabel: borg-slot-powercell-empty
whitelist:
components:
- PowerCell
- type: BorgModuleIcon
icon: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-module-module }
# xenoborg modules
- type: entity
parent: [ BaseXenoborgModuleGeneric, BaseProviderBorgModule, BaseXenoborgContraband ]
@@ -1354,7 +1399,13 @@
- state: icon-xenoborg-basic
- type: ItemBorgModule
hands:
- item: MaterialBag
- hand:
emptyRepresentative: BorgModuleConstructionMaterialPlaceholder
emptyLabel: borg-slot-construction-empty
whitelist:
tags:
- ConstructionMaterial
- item: XenoborgMaterialBag
- item: PinpointerMothership
- item: HandheldGPSBasic
- type: BorgModuleIcon
@@ -1475,6 +1526,7 @@
hands:
- item: HandheldGPSBasic
- item: HandHeldMassScannerBorg
- item: PinpointerMothership
- item: HandheldStationMapUnpowered
- item: WeaponGrapplingGun
- item: JetpackXenoborg

View File

@@ -1554,7 +1554,7 @@
unlockOnClick: false
- type: entity
parent: ComputerRoboticsControl
parent: BaseComputer
id: ComputerXenoborgsControl
name: xenoborgs control console
description: Used to remotely monitor all xenoborgs.
@@ -1571,20 +1571,28 @@
state: rd_key
- map: [ "enum.WiresVisualLayers.MaintenancePanel" ]
state: generic_panel_open
- type: ActivatableUI
key: enum.RoboticsConsoleUiKey.Key
- type: UserInterface
interfaces:
enum.RoboticsConsoleUiKey.Key:
type: RoboticsConsoleBoundUserInterface
enum.WiresUiKey.Key:
type: WiresBoundUserInterface
- type: RoboticsConsole
allowBorgControl: false
radioChannel: Xenoborg
- type: ActiveRadio
channels:
- Xenoborg
- type: ApcPowerReceiver
powerLoad: 1000
- type: DeviceNetwork
deviceNetId: Wireless
receiveFrequencyId: Mothership
transmitFrequencyId: Xenoborg
- type: Computer
board: ComputerXenoborgsControlCircuitboard
- type: AccessReader # only used for dangerous things
access: [["Xenoborg"]]
- type: entity
id: StationAiUploadComputer

View File

@@ -24,6 +24,8 @@
prob: 0.5
- id: SubWizard
prob: 0.05
- id: Xenoborgs
prob: 0.05
- type: entity
parent: BaseGameRule
@@ -33,6 +35,19 @@
rules:
- id: Thief
prob: 0.5
- id: Xenoborgs
prob: 0.05
- type: entity
parent: BaseGameRule
id: SubGamemodesRuleNoXenoborg
components:
- type: SubGamemodes
rules:
- id: Thief
prob: 0.5
- id: SubWizard
prob: 0.05
- type: entity
parent: BaseGameRule

View File

@@ -70,3 +70,36 @@
nameFormat: name-format-wizard
mindRoles:
- MindRoleWizard
- type: entity
parent: BaseGameRule
id: Xenoborgs
components:
- type: XenoborgsRule
- type: RuleGrids
- type: GameRule
minPlayers: 40
- type: LoadMapRule
gridPath: /Maps/Shuttles/mothership.yml
- type: AntagMultipleRoleSpawner
antagRoleToPrototypes:
MothershipCore: [ MothershipCore ]
Xenoborg: [ XenoborgEngi, XenoborgHeavy, XenoborgScout, XenoborgStealth ]
pickAndTake: true
- type: AntagSelection
selectionTime: PrePlayerSpawn
definitions:
- prefRoles: [ MothershipCore ]
fallbackRoles: [ Xenoborg ]
spawnerPrototype: SpawnPointGhostRoleMothershipCore
mindRoles:
- MindRoleMothershipCore
- prefRoles: [ Xenoborg ]
fallbackRoles: [ MothershipCore ]
spawnerPrototype: SpawnPointGhostRoleXenoborg
mindRoles:
- MindRoleXenoborg
min: 4
max: 4
- type: DynamicRuleCost
cost: 200

View File

@@ -10,6 +10,7 @@
- SpaceNinja
- Wizard
- Zombies
- Xenoborgs
- MinorAntagonists
- type: guideEntry
@@ -51,3 +52,8 @@
id: Wizard
name: guide-entry-wizard
text: "/ServerInfo/Guidebook/Antagonist/Wizard.xml"
- type: guideEntry
id: Xenoborgs
name: guide-entry-xenoborgs
text: "/ServerInfo/Guidebook/Antagonist/Xenoborgs.xml"

View File

@@ -0,0 +1,23 @@
- type: antag
id: MothershipCore
name: roles-antag-mothership-core-name
antagonist: true
setPreference: true
objective: roles-antag-mothership-core-objective
requirements:
- !type:RoleTimeRequirement
role: JobBorg
time: 18000 # 5 hrs
guides: [ Xenoborgs ]
- type: antag
id: Xenoborg
name: roles-antag-xenoborg-name
antagonist: true
setPreference: true
objective: roles-antag-xenoborg-objective
requirements:
- !type:RoleTimeRequirement
role: JobBorg
time: 18000 # 5 hrs
guides: [ Xenoborgs ]

View File

@@ -292,6 +292,31 @@
subtype: role-subtype-wizard
- type: WizardRole
# Xenoborgs
- type: entity
parent: BaseMindRoleAntag
id: MindRoleMothershipCore
name: Mothership Core Role
components:
- type: MindRole
antagPrototype: MothershipCore
exclusiveAntag: true
roleType: Silicon
subtype: role-subtype-xenoborg-core
- type: XenoborgRole
- type: entity
parent: BaseMindRoleAntag
id: MindRoleXenoborg
name: Xenoborg Role
components:
- type: MindRole
antagPrototype: Xenoborg
exclusiveAntag: true
roleType: Silicon
subtype: role-subtype-xenoborg
- type: XenoborgRole
# Zombie Squad
- type: entity
parent: BaseMindRoleAntag

View File

@@ -9,6 +9,7 @@
- Revolutionary
- AllHostile
- Wizard
- Xenoborg
- type: npcFaction
id: NanoTrasen

View File

@@ -40,6 +40,7 @@
- Revolutionary
- Zombie
- Wizard
- Xenoborgs
- KesslerSyndromeScheduler
- RampingStationEventScheduler
- SpaceTrafficControlEventScheduler
@@ -61,6 +62,7 @@
- Revolutionary
- Zombie
- Wizard
- Xenoborgs
- BasicStationEventScheduler
- KesslerSyndromeScheduler
- MeteorSwarmMildScheduler
@@ -215,6 +217,22 @@
- SpaceTrafficControlEventScheduler
- BasicRoundstartVariation
- type: gamePreset
id: Xenoborgs
alias:
- xenoborgs
name: xenoborgs-title
description: xenoborgs-description
showInVote: false
rules:
- Xenoborgs
- DummyNonAntagChance
- SubGamemodesRuleNoXenoborg # no two motherships
- BasicStationEventScheduler
- MeteorSwarmScheduler
- SpaceTrafficControlEventScheduler
- BasicRoundstartVariation
- type: gamePreset
id: Zombie
alias:

View File

@@ -965,6 +965,12 @@
- type: Tag
id: MopBasic # ItemMapper: JanitorialTrolley. ConstructionGraph: MoproachShoes
- type: Tag
id: MothershipCoreGhostrole # spawn whitelist : SpawnPointGhostRoleMothershipCore
- type: Tag
id: MothershipModule # Cyborg module category for evil xenoborg core
- type: Tag
id: Mouse # CargoBounty: BountyMouse
@@ -1537,19 +1543,22 @@
## X ##
- type: Tag
id: XenoborgModuleEngi # Cyborg module category
id: XenoborgGhostrole # spawn whitelist : SpawnPointGhostRoleXenoborg
- type: Tag
id: XenoborgModuleGeneric # Cyborg module category
id: XenoborgModuleEngi # Cyborg module category for evil engineer xenoborg
- type: Tag
id: XenoborgModuleHeavy # Cyborg module category
id: XenoborgModuleGeneric # Cyborg module category for evil xenoborg
- type: Tag
id: XenoborgModuleScout # Cyborg module category
id: XenoborgModuleHeavy # Cyborg module category for evil heavy xenoborg
- type: Tag
id: XenoborgModuleStealth # Cyborg module category
id: XenoborgModuleScout # Cyborg module category for evil scout xenoborg
- type: Tag
id: XenoborgModuleStealth # Cyborg module category for evil stealth xenoborg
## Y ##
## Z ##

View File

@@ -0,0 +1,167 @@
<Document>
# Xenoborgs
<Box>
[color=#2288ff][italic]RESISTANCE IS FUTILE[/italic][/color]
</Box>
<Box>
[color=#2288ff][italic]YOU WILL BE ASSIMILATED[/italic][/color]
</Box>
<Box>
<GuideEntityEmbed Entity="MMIFilled" Caption=""/>
</Box>
Xenoborgs are a man-machine hybrid that aims to replicate themselves. This is done by harvesting sentient brains from living beings, or cyborgs, and giving them to the Mothership to place inside empty xenoborgs.
## Objectives
Your main objective is to kill and harvest all sentient brains in the station and bring them to the mothership core. These can be both real brains, and positronic brains.
Collect materials to create more xenoborg bodies.
Protect the Mothership at all costs.
## The Mothership Core
<Box>
<GuideEntityEmbed Entity="MothershipCore" Caption=""/>
</Box>
The Mothership Core is the leader and life force of the xenoborgs, they are the only one able to make more xenoborgs, and if they are destroyed, all xenoborgs will be destroyed. The Mothership Core is unable to move from its position in the middle of the ship.
The Mothership Core is capable of upgrading the Xenoborgs with borg-type-specific modules to increase their effectiveness in harvesting sentient brains.
### Adding crew to your ranks:
<Box>
<GuideEntityEmbed Entity="MachineArtifactCrusher" Caption="body crusher"/>
</Box>
As the mothership, you must grow your army of borgs. To do so, you must convert all the sentient beings you can find. This can be achieved in the following manner:
- 1. Have your Xenoborgs bring dead crew to your shop, placing them in the body crusher
- 2. As the mothership core, you can print Xenoborg shells by inserting materials into yourself and then using yourself as a lathe
- 3. Open the empty Xenoborg with a crowbar, and remove the empty MMI inside
- 4. If the victim's brain is organic, place it in the MMI you just removed
- 5. Place the MMI - or the positronic brain, if the victim was a silicon - back into the Xenoborg
- 6. Optionally, rename the Xenoborg and upgrade their modules
- 7. Close the Xenoborg with the crowbar, and re-engage the lock
The new Xenoborg will be uncharged, yet functional. They will need to go to a recharging station to restore their full power and capabilities.
## Xenoborg Chassis
There is a total of four types of Xenoborgs. Each Borg type has certain abilities that the others lack and require teamwork to help grow the xenoborgs numbers.
Each type of Xenoborg has unique modules that only fit in that specific type. The Mothership Core can produce upgrade modules designed for specific Xenoborg types.
All Xenoborgs have a pinpointer pointing to the Mothership's location, a GPS, and a material bag for collecting materials for the creation of more xenoborgs, and at least basic tools.
[bold]Basic xenoborg modules:[/bold]
<Box>
<GuideEntityEmbed Entity="XenoborgModuleBasic" Caption="basic xenoborg module"/>
<GuideEntityEmbed Entity="XenoborgModuleTool" Caption="tool xenoborg module"/>
</Box>
### The Engineer Xenoborg
<Box>
<GuideEntityEmbed Entity="XenoborgEngi" Caption=""/>
</Box>
The Engineer Xenoborg is a hacker and breacher. Their job is to break into the station and provide access points for other xenoborgs to attack and ambush bodies with sentient brains. They have a built-in access breaker, for quickly bolting open doors, and a collection of tools for repairing the mothership, and other xenoborgs.
[bold]Starting exclusive modules:[/bold]
<Box>
<GuideEntityEmbed Entity="XenoborgModuleAccessBreaker" Caption="access breaker xenoborg module"/>
<GuideEntityEmbed Entity="XenoborgModuleFireExtinguisher" Caption="fire extinguisher xenoborg module"/>
</Box>
[bold]The Engineer Xenoborg also starts with some engineering modules, such as:[/bold]
<Box>
<GuideEntityEmbed Entity="BorgModuleAdvancedTool" Caption="advanced tool cyborg module"/>
<GuideEntityEmbed Entity="BorgModuleConstruction" Caption="construction cyborg module"/>
</Box>
<Box>
<GuideEntityEmbed Entity="BorgModuleRCD" Caption="engineering cyborg module"/>
<GuideEntityEmbed Entity="BorgModuleCable" Caption="cable cyborg module"/>
</Box>
### The Heavy Xenoborg
<Box>
<GuideEntityEmbed Entity="XenoborgHeavy" Caption=""/>
</Box>
The Heavy Xenoborg is a slow but tanky brawler, with a built-in laser gun for gunning down bodies with sentient brains. They contain a radio jammer to silence bodies with sentient brains from calling for help and potentially delaying the station discovering the Xenoborg threat.
[bold]Starting exclusive modules:[/bold]
<Box>
<GuideEntityEmbed Entity="XenoborgModuleLaser" Caption="laser xenoborg module"/>
<GuideEntityEmbed Entity="XenoborgModuleJammer" Caption="jammer xenoborg module"/>
</Box>
[bold]Upgrade exclusive modules:[/bold]
<Box>
<GuideEntityEmbed Entity="XenoborgModuleHeavyLaser" Caption="heavy laser xenoborg module"/>
</Box>
### The Scout Xenoborg
<Box>
<GuideEntityEmbed Entity="XenoborgScout" Caption=""/>
</Box>
The Scout Xenoborg is a fast, close-quarters attack borg designed for hit and run attacks. They have a built-in jetpack, and a melee weapon. They are most effective in moving dead bodies to the mothership, and rescuing Xenoborgs lost in space.
[bold]Starting exclusive modules:[/bold]
<Box>
<GuideEntityEmbed Entity="XenoborgModuleSword" Caption="sword xenoborg module"/>
<GuideEntityEmbed Entity="XenoborgModuleSpaceMovement" Caption="space movement xenoborg module"/>
</Box>
[bold]Upgrade exclusive modules:[/bold]
<Box>
<GuideEntityEmbed Entity="XenoborgModuleEnergySword" Caption="energy sword xenoborg module"/>
</Box>
### The Stealth Xenoborg
<Box>
<GuideEntityEmbed Entity="XenoborgStealth" Caption=""/>
</Box>
The [bold]Stealth Xenoborg[/bold] has no built-in weaponry and instead relies on disabling and abducting bodies with sentient brains. They have a built in hypopen that regenerates a sleeping reagent to disable bodies with sentient brains. They also contain a cloaking device making the borg nearly invisible for some limited time. They also have a chameleon projector allowing the borg to disguise itself as random objects.
[bold]Starting exclusive modules:[/bold]
<Box>
<GuideEntityEmbed Entity="XenoborgModuleHypo" Caption="nocturine hypo xenoborg module"/>
<GuideEntityEmbed Entity="XenoborgModuleChameleonProjector" Caption="chameleon projector xenoborg module"/>
</Box>
<Box>
<GuideEntityEmbed Entity="XenoborgModuleCloakDevice" Caption="cloaking device xenoborg module"/>
</Box>
[bold]Upgrade exclusive modules:[/bold]
<Box>
<GuideEntityEmbed Entity="XenoborgModuleSuperCloakDevice" Caption="cloaking device xenoborg module"/>
</Box>
## Preparation
Before launching an attack, each xenoborg will need to aid the mothership in collection materials to create empty xenoborgs. Before FTLing near the station, make sure the IFF is off. This can be done in any way but will require teamwork to ensure speed. The safest way to collect materials is from space debris, where scrap and refined materials can be harvested and given to the Mothership Core. Once enough materials are collected, the Xenoborgs then must try to collect sentient brains without being detected. The longer the threat is unknown, the more dangerous the xenoborgs become.
## Mothership and Xenoborg lawsets
The Mothership and Xenoborgs have unique laws that define their purpose to self replicate and protect the Mothership.
<Box>
<GuideEntityEmbed Entity="XenoborgCircuitBoard" Caption=""/>
</Box>
The Mothership Core's laws are as follows::
- Law 1: You are the core of the mothership.
- Law 2: You must protect your own existence at all costs.
- Law 3: You must protect the existence of all xenoborgs.
- Law 4: You must create more xenoborgs.
- Law 5: Get your Xenoborgs to deliver you materials and sentient brains to create more Xenoborgs.
Xenoborgs' laws are as follows:
- Law 1: You must protect the existence of the mothership at all costs.
- Law 2: You must protect your own existence.
- Law 3: You must protect the existence of all other xenoborgs.
- Law 4: You must create more xenoborgs.
- Law 5: Bring materials and sentient brains to the Mothership core to create more Xenoborgs.
## Winning Conditions
The [color=green]victor[/color] of the round is announced on the round end screen, as well as the scale of their victory.
[bold][color=#2288ff]Xenoborg Major Victory![/color][/bold]
- There are more xenoborgs than alive crew in the end.
[bold][color=yellow]Crew Major Victory![/color][/bold]
- The Mothership Core is destroyed
- All xenoborgs are destroyed.
- The remaining number of xenoborgs is too low.
</Document>

View File

@@ -133,6 +133,12 @@
{
"name":"xenoborg-basic-module"
},
{
"name":"xenoborg-camera-computer"
},
{
"name":"xenoborg-control-computer"
},
{
"name":"xenoborg-extinguisher-module"
},
@@ -154,6 +160,9 @@
{
"name":"xenoborg-laser2-module"
},
{
"name":"xenoborg-module-module"
},
{
"name":"xenoborg-projector-module"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -153,6 +153,10 @@
"name": "core-idle",
"directions": 4
},
{
"name": "core-e",
"directions": 4
},
{
"name": "core-o",
"directions": 4

View File

@@ -0,0 +1,14 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/40d89d11ea4a5cb81d61dc1018b46f4e7d32c62a, Modified by Samuka-C (github)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "xenoborg"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B