diff --git a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs
new file mode 100644
index 0000000000..9d56d267b9
--- /dev/null
+++ b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs
@@ -0,0 +1,37 @@
+using Content.Shared.Silicons.Laws.Components;
+using Content.Shared.Administration.Logs;
+using Content.Shared.Database;
+
+namespace Content.Server.Silicons.Laws;
+
+///
+/// This handles running the ion storm event a on specific entity when that entity is spawned in.
+///
+public sealed class StartIonStormedSystem : EntitySystem
+{
+ [Dependency] private readonly IonStormSystem _ionStorm = default!;
+ [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
+ [Dependency] private readonly SiliconLawSystem _siliconLaw = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeLocalEvent(OnMapInit);
+ }
+
+ private void OnMapInit(Entity ent, ref MapInitEvent args)
+ {
+ if (!TryComp(ent.Owner, out var lawBound))
+ return;
+ if (!TryComp(ent.Owner, out var target))
+ return;
+
+ for (int currentIonStorm = 0; currentIonStorm < ent.Comp.IonStormAmount; currentIonStorm++)
+ {
+ _ionStorm.IonStormTarget((ent.Owner, lawBound, target), false);
+ }
+
+ var laws = _siliconLaw.GetLaws(ent.Owner, lawBound);
+ _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent.Owner):silicon} spawned with ion stormed laws: {laws.LoggingString()}");
+ }
+}
diff --git a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs
new file mode 100644
index 0000000000..d0124567ff
--- /dev/null
+++ b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs
@@ -0,0 +1,17 @@
+using Content.Shared.Roles;
+using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Silicons.Laws.Components;
+
+///
+/// Applies law altering ion storms on a specific entity IonStormAmount times when the entity is spawned.
+///
+[RegisterComponent]
+public sealed partial class StartIonStormedComponent : Component
+{
+ ///
+ /// Amount of times that the ion storm will be run on the entity on spawn.
+ ///
+ [DataField]
+ public int IonStormAmount = 1;
+}
diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl
index ad893876e7..bf09832800 100644
--- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl
+++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl
@@ -238,6 +238,9 @@ ghost-role-information-syndicate-cyborg-assault-name = Syndicate Assault Cyborg
ghost-role-information-syndicate-cyborg-saboteur-name = Syndicate Saboteur Cyborg
ghost-role-information-syndicate-cyborg-description = The Syndicate needs reinforcements. You, a cold silicon killing machine, will help them.
+ghost-role-information-derelict-cyborg-name = Derelict Cyborg
+ghost-role-information-derelict-cyborg-description = You are a regular cyborg that got lost in space. After years of exposure to ion storms you find yourself near a space station.
+
ghost-role-information-security-name = Security
ghost-role-information-security-description = You are part of a security task force, but seem to have found yourself in a strange situation...
diff --git a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl
index a180b698fa..23a7d74407 100644
--- a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl
+++ b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl
@@ -68,6 +68,7 @@ petting-success-janitor-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} d
petting-success-medical-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} sterile metal head.
petting-success-service-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} dapper looking metal head.
petting-success-syndicate-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} menacing metal head.
+petting-success-derelict-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} rusty metal head.
petting-success-recycler = You pet {THE($target)} on {POSS-ADJ($target)} mildly threatening steel exterior.
petting-failure-honkbot = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BASIC($target, "honk", "honks")} in refusal!
@@ -82,6 +83,7 @@ petting-failure-janitor-cyborg = You reach out to pet {THE($target)}, but {SUBJE
petting-failure-medical-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy saving lives!
petting-failure-service-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy serving others!
petting-failure-syndicate-cyborg = You reach out to pet {THE($target)}, but {POSS-ADJ($target)} treacherous affiliation makes you reconsider.
+petting-failure-derelict-cyborg = You reach out to pet {THE($target)}, but {POSS-ADJ($target)} rusty and jagged exterior makes you reconsider.
## Rattling fences
diff --git a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml
index 54e821cbd4..eda6816aa5 100644
--- a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml
+++ b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml
@@ -170,3 +170,21 @@
- state: green
- sprite: Objects/Weapons/Melee/energykatana.rsi
state: icon
+
+- type: entity
+ categories: [ HideSpawnMenu, Spawner ]
+ parent: BaseAntagSpawner
+ id: SpawnPointGhostDerelictCyborg
+ components:
+ - type: GhostRole
+ name: ghost-role-information-derelict-cyborg-name
+ description: ghost-role-information-derelict-cyborg-description
+ rules: ghost-role-information-silicon-rules
+ raffle:
+ settings: default
+ - type: Sprite
+ sprite: Markers/jobs.rsi
+ layers:
+ - state: green
+ - sprite: Mobs/Silicon/chassis.rsi
+ state: derelict_icon
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
index ab9dac1328..a5b4822e45 100644
--- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
+++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
@@ -328,3 +328,23 @@
Unsexed: UnisexSiliconSyndicate
- type: PointLight
color: "#dd200b"
+
+- type: entity
+ id: BaseBorgChassisDerelict
+ parent: BaseBorgChassis
+ abstract: true
+ components:
+ - type: NpcFactionMember
+ factions:
+ - NanoTrasen #The seemingly best fit. It was a regular NT cyborg once, after all.
+ - type: Access
+ enabled: false
+ groups:
+ - AllAccess #Randomized access would be fun. AllAccess is the best i can think of right now that does make it too hard for it to enter the station or navigate it..
+ - type: AccessReader
+ access: [["Command"], ["Research"]]
+ - type: StartIonStormed
+ ionStormAmount: 3
+ - type: IonStormTarget
+ chance: 1
+
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml
index fa324c0124..87b8d54a97 100644
--- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml
+++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml
@@ -187,3 +187,35 @@
interactFailureString: petting-failure-syndicate-cyborg
interactSuccessSound:
path: /Audio/Ambience/Objects/periodic_beep.ogg
+
+- type: entity
+ id: BorgChassisDerelict
+ parent: BaseBorgChassisDerelict
+ name: derelict cyborg
+ description: A man-machine hybrid that assists in station activity. This one is in a state of great disrepair.
+ components:
+ - type: Sprite
+ layers:
+ - state: derelict
+ - state: derelict_e_r
+ map: ["enum.BorgVisualLayers.Light"]
+ shader: unshaded
+ visible: false
+ - state: derelict_l
+ shader: unshaded
+ map: ["light"]
+ visible: false
+ - type: BorgChassis
+ maxModules: 5 # the sixth one broke lol
+ moduleWhitelist:
+ tags:
+ - BorgModuleGeneric
+ hasMindState: derelict_e
+ noMindState: derelict_e_r
+ - type: Construction
+ node: derelictcyborg
+ - type: InteractionPopup
+ interactSuccessString: petting-success-derelict-cyborg
+ interactFailureString: petting-failure-derelict-cyborg
+ interactSuccessSound:
+ path: /Audio/Ambience/Objects/periodic_beep.ogg
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
index b694b245b2..c161681202 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml
@@ -526,3 +526,37 @@
- PlayerBorgSyndicateAssaultGhostRole
- PlayerBorgSyndicateAssaultGhostRole # Saboteurs are kinda like cyborg medics, we want less.
- PlayerBorgSyndicateSaboteurGhostRole
+
+- type: entity
+ id: PlayerBorgDerelict
+ parent: BorgChassisDerelict
+ suffix: Battery, Module
+ components:
+ - type: ContainerFill
+ containers:
+ borg_brain:
+ - PositronicBrain
+ borg_module:
+ - BorgModuleTool
+ - BorgModuleFireExtinguisher
+ - BorgModuleGPS
+ - type: ItemSlots
+ slots:
+ cell_slot:
+ name: power-cell-slot-component-slot-name-default
+ startingItem: PowerCellHigh
+ - type: RandomMetadata
+ nameSegments: [names_borg]
+
+- type: entity
+ id: PlayerBorgDerelictGhostRole
+ parent: PlayerBorgDerelict
+ suffix: Ghost role
+ components:
+ - type: GhostRole
+ name: ghost-role-information-derelict-cyborg-name
+ description: ghost-role-information-derelict-cyborg-description
+ rules: ghost-role-information-silicon-rules
+ raffle:
+ settings: default
+ - type: GhostTakeoverAvailable
\ No newline at end of file
diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml
index 98b6690ebb..2051c24be8 100644
--- a/Resources/Prototypes/GameRules/events.yml
+++ b/Resources/Prototypes/GameRules/events.yml
@@ -37,6 +37,7 @@
- id: SleeperAgents
- id: ZombieOutbreak
- id: LoneOpsSpawn
+ - id: DerelictCyborgSpawn
- type: entity
id: BaseStationEvent
@@ -562,3 +563,24 @@
- Service
blacklist:
- External # don't space everything
+
+- type: entity
+ parent: BaseGameRule
+ id: DerelictCyborgSpawn
+ components:
+ - type: StationEvent
+ weight: 5
+ earliestStart: 15
+ reoccurrenceDelay: 20
+ minimumPlayers: 4
+ duration: null
+ - type: SpaceSpawnRule
+ spawnDistance: 0
+ - type: AntagSpawner
+ prototype: PlayerBorgDerelict
+ - type: AntagSelection
+ definitions:
+ - spawnerPrototype: SpawnPointGhostDerelictCyborg
+ min: 1
+ max: 1
+ pickPlayer: false
diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml
index 4ebc43667c..9f68a3b773 100644
--- a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml
+++ b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml
@@ -34,3 +34,6 @@
- node: cyborg
entity: BorgChassisSelectable
+
+ - node: derelictcyborg
+ entity: BorgChassisDerelict
\ No newline at end of file
diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict.png
new file mode 100644
index 0000000000..bbf72fc45b
Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict.png differ
diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e.png
new file mode 100644
index 0000000000..17349d74dc
Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e.png differ
diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e_r.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e_r.png
new file mode 100644
index 0000000000..3c8cf19acf
Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e_r.png differ
diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_icon.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_icon.png
new file mode 100644
index 0000000000..7f0ea2a255
Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_icon.png differ
diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_l.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_l.png
new file mode 100644
index 0000000000..f65fbaebc3
Binary files /dev/null and b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_l.png differ
diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json b/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json
index 68fbf1985e..7337a8e936 100644
--- a/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json
+++ b/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json
@@ -5,7 +5,7 @@
"y": 32
},
"license": "CC-BY-SA-3.0",
- "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/faf6db214927874c19b8fa8585d26b5d40de1acc",
+ "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/faf6db214927874c19b8fa8585d26b5d40de1acc, derelict sprites modified by GoldenCan(GitHub).",
"states": [
{
"name": "clown",
@@ -23,6 +23,26 @@
"name": "clown_l",
"directions": 4
},
+ {
+ "name": "derelict",
+ "directions": 4
+ },
+ {
+ "name": "derelict_e",
+ "directions": 4
+ },
+ {
+ "name": "derelict_e_r",
+ "directions": 4
+ },
+ {
+ "name": "derelict_icon",
+ "directions": 1
+ },
+ {
+ "name": "derelict_l",
+ "directions": 4
+ },
{
"name": "engineer",
"directions": 4