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