diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs index 10a001be8b627f..c0f660d216976a 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -18,6 +18,7 @@ using Content.Server.Storage.EntitySystems; using Content.Server.Tabletop; using Content.Server.Tabletop.Components; +using Content.Server.Terminator.Systems; using Content.Shared.Administration; using Content.Shared.Administration.Components; using Content.Shared.Body.Components; @@ -30,6 +31,7 @@ using Content.Shared.Electrocution; using Content.Shared.Interaction.Components; using Content.Shared.Inventory; +using Content.Shared.Mind.Components; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; @@ -72,6 +74,7 @@ public sealed partial class AdminVerbSystem [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly TabletopSystem _tabletopSystem = default!; + [Dependency] private readonly TerminatorSystem _terminator = default!; [Dependency] private readonly VomitSystem _vomitSystem = default!; [Dependency] private readonly WeldableSystem _weldableSystem = default!; [Dependency] private readonly SharedContentEyeSystem _eyeSystem = default!; @@ -793,6 +796,7 @@ private void AddSmiteVerbs(GetVerbsEvent args) Message = Loc.GetString("admin-smite-super-speed-description"), }; args.Verbs.Add(superSpeed); + //Bonk Verb superBonkLite = new() { @@ -820,5 +824,27 @@ private void AddSmiteVerbs(GetVerbsEvent args) Impact = LogImpact.Extreme, }; args.Verbs.Add(superBonk); + + Verb terminate = new() + { + Text = "Terminate", + Category = VerbCategory.Smite, + Icon = new SpriteSpecifier.Rsi(new ("Mobs/Species/Terminator/parts.rsi"), "skull_icon"), + Act = () => + { + if (!TryComp(args.Target, out var mindContainer) || mindContainer.Mind == null) + return; + + var coords = Transform(args.Target).Coordinates; + var mindId = mindContainer.Mind.Value; + _terminator.CreateSpawner(coords, mindId); + + _popupSystem.PopupEntity(Loc.GetString("admin-smite-terminate-prompt"), args.Target, + args.Target, PopupType.LargeCaution); + }, + Impact = LogImpact.Extreme, + Message = Loc.GetString("admin-smite-terminate-description") + }; + args.Verbs.Add(terminate); } } diff --git a/Content.Server/Destructible/Thresholds/Behaviors/PopupBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/PopupBehavior.cs new file mode 100644 index 00000000000000..59589c19aa74d1 --- /dev/null +++ b/Content.Server/Destructible/Thresholds/Behaviors/PopupBehavior.cs @@ -0,0 +1,30 @@ +using Content.Shared.Popups; + +namespace Content.Server.Destructible.Thresholds.Behaviors; + +/// +/// Shows a popup for everyone. +/// +[DataDefinition] +public sealed partial class PopupBehavior : IThresholdBehavior +{ + /// + /// Locale id of the popup message. + /// + [DataField("popup", required: true)] + public string Popup; + + /// + /// Type of popup to show. + /// + [DataField("popupType")] + public PopupType PopupType; + + public void Execute(EntityUid uid, DestructibleSystem system, EntityUid? cause = null) + { + var popup = system.EntityManager.System(); + // popup is placed at coords since the entity could be deleted after, no more popup then + var coords = system.EntityManager.GetComponent(uid).Coordinates; + popup.PopupCoordinates(Loc.GetString(Popup), coords, PopupType); + } +} diff --git a/Content.Server/Objectives/Components/TerminatorTargetOverrideComponent.cs b/Content.Server/Objectives/Components/TerminatorTargetOverrideComponent.cs new file mode 100644 index 00000000000000..c66ff55f054a12 --- /dev/null +++ b/Content.Server/Objectives/Components/TerminatorTargetOverrideComponent.cs @@ -0,0 +1,12 @@ +using Content.Server.Objectives.Systems; + +namespace Content.Server.Objectives.Components; + +/// +/// Sets this objective's target to the exterminator's target override, if it has one. +/// If not it will be random. +/// +[RegisterComponent, Access(typeof(TerminatorTargetOverrideSystem))] +public sealed partial class TerminatorTargetOverrideComponent : Component +{ +} diff --git a/Content.Server/Objectives/Systems/TerminatorTargetOverrideSystem.cs b/Content.Server/Objectives/Systems/TerminatorTargetOverrideSystem.cs new file mode 100644 index 00000000000000..0a81c2810ed631 --- /dev/null +++ b/Content.Server/Objectives/Systems/TerminatorTargetOverrideSystem.cs @@ -0,0 +1,41 @@ +using Content.Server.Objectives.Components; +using Content.Server.Terminator.Components; +using Content.Shared.Mind; +using Content.Shared.Objectives.Components; + +namespace Content.Server.Objectives.Systems; + +/// +/// Handles copying the exterminator's target override to this objective. +/// +public sealed class TerminatorTargetOverrideSystem : EntitySystem +{ + [Dependency] private readonly TargetObjectiveSystem _target = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnAssigned); + } + + private void OnAssigned(EntityUid uid, TerminatorTargetOverrideComponent comp, ref ObjectiveAssignedEvent args) + { + if (args.Mind.OwnedEntity == null) + { + args.Cancelled = true; + return; + } + + var user = args.Mind.OwnedEntity.Value; + if (!TryComp(user, out var terminator)) + { + args.Cancelled = true; + return; + } + + // this exterminator has a target override so set its objective target accordingly + if (terminator.Target != null) + _target.SetTarget(uid, terminator.Target.Value); + } +} diff --git a/Content.Server/Roles/RoleSystem.cs b/Content.Server/Roles/RoleSystem.cs index c53fa1cf9ebcc7..f7a51773573a1d 100644 --- a/Content.Server/Roles/RoleSystem.cs +++ b/Content.Server/Roles/RoleSystem.cs @@ -15,6 +15,7 @@ public override void Initialize() SubscribeAntagEvents(); SubscribeAntagEvents(); SubscribeAntagEvents(); + SubscribeAntagEvents(); SubscribeAntagEvents(); SubscribeAntagEvents(); SubscribeAntagEvents(); diff --git a/Content.Server/Roles/TerminatorRoleComponent.cs b/Content.Server/Roles/TerminatorRoleComponent.cs new file mode 100644 index 00000000000000..4154e8ab690899 --- /dev/null +++ b/Content.Server/Roles/TerminatorRoleComponent.cs @@ -0,0 +1,8 @@ +using Content.Shared.Roles; + +namespace Content.Server.Roles; + +[RegisterComponent] +public sealed partial class TerminatorRoleComponent : AntagonistRoleComponent +{ +} diff --git a/Content.Server/Terminator/Components/TerminatorComponent.cs b/Content.Server/Terminator/Components/TerminatorComponent.cs new file mode 100644 index 00000000000000..9427f95eeda0c9 --- /dev/null +++ b/Content.Server/Terminator/Components/TerminatorComponent.cs @@ -0,0 +1,19 @@ +using Content.Server.Terminator.Systems; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Server.Terminator.Components; + +/// +/// Main terminator component, handles the target, if any, and objectives. +/// +[RegisterComponent, Access(typeof(TerminatorSystem))] +public sealed partial class TerminatorComponent : Component +{ + /// + /// Used to force the terminate objective's target. + /// If null it will be a random person. + /// + [DataField("target")] + public EntityUid? Target; +} diff --git a/Content.Server/Terminator/Components/TerminatorTargetComponent.cs b/Content.Server/Terminator/Components/TerminatorTargetComponent.cs new file mode 100644 index 00000000000000..786cbd1167b4ce --- /dev/null +++ b/Content.Server/Terminator/Components/TerminatorTargetComponent.cs @@ -0,0 +1,16 @@ +using Content.Server.Terminator.Systems; + +namespace Content.Server.Terminator.Components; + +/// +/// Sets after the ghost role spawns. +/// +[RegisterComponent, Access(typeof(TerminatorSystem))] +public sealed partial class TerminatorTargetComponent : Component +{ + /// + /// The target to set after the ghost role spawns. + /// + [DataField("target")] + public EntityUid? Target; +} diff --git a/Content.Server/Terminator/Systems/TerminatorSystem.cs b/Content.Server/Terminator/Systems/TerminatorSystem.cs new file mode 100644 index 00000000000000..b6699352779c03 --- /dev/null +++ b/Content.Server/Terminator/Systems/TerminatorSystem.cs @@ -0,0 +1,66 @@ +using Content.Server.Body.Components; +using Content.Server.GenericAntag; +using Content.Server.Ghost.Roles.Events; +using Content.Server.Roles; +using Content.Server.Terminator.Components; +using Content.Shared.Roles; +using Robust.Shared.Map; + +namespace Content.Server.Terminator.Systems; + +public sealed class TerminatorSystem : EntitySystem +{ + [Dependency] private readonly SharedRoleSystem _role = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnSpawned); + SubscribeLocalEvent(OnCreated); + } + + private void OnMapInit(EntityUid uid, TerminatorComponent comp, MapInitEvent args) + { + // cyborg doesn't need to breathe + RemComp(uid); + } + + private void OnSpawned(EntityUid uid, TerminatorComponent comp, GhostRoleSpawnerUsedEvent args) + { + if (!TryComp(args.Spawner, out var target)) + return; + + comp.Target = target.Target; + } + + private void OnCreated(EntityUid uid, TerminatorComponent comp, ref GenericAntagCreatedEvent args) + { + var mindId = args.MindId; + var mind = args.Mind; + + _role.MindAddRole(mindId, new RoleBriefingComponent + { + Briefing = Loc.GetString("terminator-role-briefing") + }, mind); + _role.MindAddRole(mindId, new TerminatorRoleComponent(), mind); + } + + /// + /// Create a spawner at a position and return it. + /// + /// Coordinates to create the spawner at + /// Optional target mind to force the terminator to target + public EntityUid CreateSpawner(EntityCoordinates coords, EntityUid? target) + { + var uid = Spawn("SpawnPointGhostTerminator", coords); + if (target != null) + { + var comp = EnsureComp(uid); + comp.Target = target; + } + + return uid; + } +} diff --git a/Resources/Locale/en-US/administration/smites.ftl b/Resources/Locale/en-US/administration/smites.ftl index e6b0f92b7a2148..fe8077a550c725 100644 --- a/Resources/Locale/en-US/administration/smites.ftl +++ b/Resources/Locale/en-US/administration/smites.ftl @@ -12,7 +12,8 @@ admin-smite-turned-ash-other = {CAPITALIZE($name)} turns into a pile of ash! admin-smite-stomach-removal-self = Your stomach feels hollow... admin-smite-run-walk-swap-prompt = You have to press shift to run! admin-smite-super-speed-prompt = You move at mach 0.8! -admin-smite-lung-removal-self = You can't breath! +admin-smite-lung-removal-self = You can't breathe! +admin-smite-terminate-prompt = I'll be back ## Smite descriptions @@ -57,6 +58,7 @@ admin-smite-disarm-prone-description = Makes them get disarmed 100% of the time admin-smite-garbage-can-description = Turn them into a garbage bin to emphasize what they remind you of. admin-smite-super-bonk-description = Slams them on every single table on the Station and beyond. admin-smite-super-bonk-lite-description= Slams them on every single table on the Station and beyond. Stops when the target is dead. +admin-smite-terminate-description = Creates a Terminator ghost role with the sole objective of killing them. ## Tricks descriptions diff --git a/Resources/Locale/en-US/game-ticking/game-rules/rule-terminator.ftl b/Resources/Locale/en-US/game-ticking/game-rules/rule-terminator.ftl new file mode 100644 index 00000000000000..41237a5c10d8e2 --- /dev/null +++ b/Resources/Locale/en-US/game-ticking/game-rules/rule-terminator.ftl @@ -0,0 +1,14 @@ +terminator-round-end-agent-name = nt-800 + +objective-issuer-susnet = [color=#d64119]Susnet[/color] + +terminator-role-greeting = + You are the exterminator, a relentless assassin sent into the past to secure our future. + We need you to eliminate {$target}, {$job}. + Use any means at your disposal to complete the mission. + Glory to Cybersun. + +terminator-role-briefing = Kill the target at all costs. + +terminator-endoskeleton-gib-popup = All the battered flesh falls apart, revealing a titanium endoskeleton! +terminator-endoskeleton-burn-popup = The seared flesh is burned to a crisp, revealing a titanium endoskeleton! 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 5d6d0b337b2b17..a74b90d65acf12 100644 --- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl @@ -188,4 +188,8 @@ ghost-role-information-Cak-rules = You are a living edible sweet cat. Your task ghost-role-information-BreadDog-name = BreadDog ghost-role-information-BreadDog-description = You are the chef's favorite child. You're a living bread dog. -ghost-role-information-BreadDog-rules = You're an edible dog made of bread. Your task is to find your place in this world where everything wants to eat you. \ No newline at end of file +ghost-role-information-BreadDog-rules = You're an edible dog made of bread. Your task is to find your place in this world where everything wants to eat you. + +ghost-role-information-exterminator-name = Exterminator +ghost-role-information-exterminator-description = You been been sent back in time to terminate a target with high importance to the future. +ghost-role-information-exterminator-rules = You are an antagonist and may kill anyone that tries to stop you, but killing the target is always your top priority. diff --git a/Resources/Locale/en-US/objectives/conditions/terminate.ftl b/Resources/Locale/en-US/objectives/conditions/terminate.ftl new file mode 100644 index 00000000000000..c88c7b14dae6f7 --- /dev/null +++ b/Resources/Locale/en-US/objectives/conditions/terminate.ftl @@ -0,0 +1 @@ +objective-terminate-title = Terminate {$targetName}, {CAPITALIZE($job)} diff --git a/Resources/Locale/en-US/prototypes/roles/antags.ftl b/Resources/Locale/en-US/prototypes/roles/antags.ftl index 2848300c190357..1502a30208ae03 100644 --- a/Resources/Locale/en-US/prototypes/roles/antags.ftl +++ b/Resources/Locale/en-US/prototypes/roles/antags.ftl @@ -29,4 +29,7 @@ roles-antag-space-ninja-name = Space Ninja roles-antag-space-ninja-objective = Use your stealth to sabotage the station, nom on electrical wires. roles-antag-thief-name = Thief -roles-antag-thief-objective = Add some NT property to your personal collection without using violence. \ No newline at end of file +roles-antag-thief-objective = Add some NT property to your personal collection without using violence. + +roles-antag-terminator-name = Terminator +roles-antag-terminator-objective = Kill the target at all costs, the future depends on it. diff --git a/Resources/Prototypes/Body/Parts/terminator.yml b/Resources/Prototypes/Body/Parts/terminator.yml new file mode 100644 index 00000000000000..dec0c99f7c20a9 --- /dev/null +++ b/Resources/Prototypes/Body/Parts/terminator.yml @@ -0,0 +1,157 @@ +- type: entity + abstract: true + parent: BaseItem + id: PartTerminator + name: nt-800 body part + components: + - type: Sprite + sprite: Mobs/Species/Terminator/parts.rsi + - type: Icon + sprite: Mobs/Species/Terminator/parts.rsi + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Cybernetic + - type: BodyPart + - type: ContainerContainer + containers: + bodypart: !type:Container + ents: [] + - type: StaticPrice + price: 200 + +- type: entity + parent: PartTerminator + id: TorsoTerminator + name: nt-800 torso + components: + - type: Sprite + state: torso_m + - type: Icon + state: torso_m + - type: BodyPart + partType: Torso + +- type: entity + parent: PartTerminator + id: HeadTerminator + name: nt-800 skull + description: Its red eyes have powered down... for now. + components: + - type: Sprite + state: skull_icon + - type: Icon + state: skull_icon + - type: BodyPart + partType: Head + # killing a terminators worth big bucks + - type: StaticPrice + price: 2000 + - type: Tag + tags: + - Head + +- type: entity + parent: PartTerminator + id: LeftArmTerminator + name: left nt-800 arm + components: + - type: Sprite + state: l_arm + - type: Icon + state: l_arm + - type: BodyPart + partType: Arm + symmetry: Left + +- type: entity + parent: PartTerminator + id: RightArmTerminator + name: right nt-800 arm + components: + - type: Sprite + state: r_arm + - type: Icon + state: r_arm + - type: BodyPart + partType: Arm + symmetry: Right + +- type: entity + parent: PartTerminator + id: LeftHandTerminator + name: left nt-800 hand + components: + - type: Sprite + state: l_hand + - type: Icon + state: l_hand + - type: BodyPart + partType: Hand + symmetry: Left + +- type: entity + parent: PartTerminator + id: RightHandTerminator + name: right nt-800 hand + components: + - type: Sprite + state: r_hand + - type: Icon + state: r_hand + - type: BodyPart + partType: Hand + symmetry: Right + +- type: entity + parent: PartTerminator + id: LeftLegTerminator + name: left nt-800 leg + components: + - type: Sprite + state: l_leg + - type: Icon + state: l_leg + - type: BodyPart + partType: Leg + symmetry: Left + - type: MovementBodyPart + +- type: entity + parent: PartTerminator + id: RightLegTerminator + name: right nt-800 leg + components: + - type: Sprite + state: r_leg + - type: Icon + state: r_leg + - type: BodyPart + partType: Leg + symmetry: Right + - type: MovementBodyPart + +- type: entity + parent: PartTerminator + id: LeftFootTerminator + name: left nt-800 foot + components: + - type: Sprite + state: l_foot + - type: Icon + state: l_foot + - type: BodyPart + partType: Foot + symmetry: Left + +- type: entity + parent: PartTerminator + id: RightFootTerminator + name: right nt-800 foot + components: + - type: Sprite + state: r_foot + - type: Icon + state: r_foot + - type: BodyPart + partType: Foot + symmetry: Right diff --git a/Resources/Prototypes/Body/Prototypes/terminator.yml b/Resources/Prototypes/Body/Prototypes/terminator.yml new file mode 100644 index 00000000000000..c271a89d869572 --- /dev/null +++ b/Resources/Prototypes/Body/Prototypes/terminator.yml @@ -0,0 +1,85 @@ +# not quite human... +- type: body + id: TerminatorFlesh + name: exterminator + root: torso + slots: + head: + part: HeadHuman + connections: + - torso + organs: + brain: MobTerminatorEndoskeleton + torso: + part: TorsoHuman + connections: + - left arm + - right arm + - left leg + - right leg + right arm: + part: RightArmHuman + connections: + - right hand + left arm: + part: LeftArmHuman + connections: + - left hand + right hand: + part: RightHandHuman + left hand: + part: LeftHandHuman + right leg: + part: RightLegHuman + connections: + - right foot + left leg: + part: LeftLegHuman + connections: + - left foot + right foot: + part: RightFootHuman + left foot: + part: LeftFootHuman + +# TODO: terminator body parts +- type: body + id: TerminatorEndoskeleton + name: terminatorEndoskeleton + root: torso + slots: + head: + part: HeadTerminator + connections: + - torso + torso: + part: TorsoTerminator + connections: + - left arm + - right arm + - left leg + - right leg + right arm: + part: RightArmTerminator + connections: + - right hand + left arm: + part: LeftArmTerminator + connections: + - left hand + right hand: + part: RightHandTerminator + left hand: + part: LeftHandTerminator + right leg: + part: RightLegTerminator + connections: + - right foot + left leg: + part: LeftLegTerminator + connections: + - left foot + right foot: + part: RightFootTerminator + left foot: + part: LeftFootTerminator diff --git a/Resources/Prototypes/Damage/modifier_sets.yml b/Resources/Prototypes/Damage/modifier_sets.yml index 26904bc2761027..c56d7326b19967 100644 --- a/Resources/Prototypes/Damage/modifier_sets.yml +++ b/Resources/Prototypes/Damage/modifier_sets.yml @@ -249,3 +249,41 @@ Cellular: 0.0 Heat: 2.5 Caustic: 0.0 + +# terminator's flesh damage set +- type: damageModifierSet + id: CyberneticFlesh + coefficients: + Blunt: 0.2 + Slash: 0.2 + Piercing: 0.1 + # fire and lasers burn it good + Heat: 1.0 + # zap + Shock: 1.5 + Cold: 0.25 + Caustic: 0.25 + # doesnt have organs to poison + Poison: 0.0 + Cellular: 0.0 + +# terminator's endoskeleton damage set +- type: damageModifierSet + id: Cybernetic + coefficients: + # bonk + Blunt: 1.0 + # alloy too hard to cut or shoot + Slash: 0.0 + Piercing: 0.0 + # no burning anymore + Heat: 0.0 + # zap zap + Shock: 2.5 + Cold: 0.0 + Caustic: 0.0 + Poison: 0.0 + Cellular: 0.0 + flatReductions: + # can't punch the endoskeleton to death + Blunt: 5 diff --git a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml index 75f7b59f14faff..5e5186eb7241b2 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml @@ -130,3 +130,20 @@ - state: green - sprite: Objects/Weapons/Melee/energykatana.rsi state: icon + +- type: entity + parent: MarkerBase + id: SpawnPointGhostTerminator + name: terminator spawn point + components: + - type: GhostRole + name: ghost-role-information-exterminator-name + description: ghost-role-information-exterminator-description + rules: ghost-role-information-exterminator-rules + - type: GhostRoleMobSpawner + prototype: MobHumanTerminator + - type: Sprite + layers: + - state: green + - sprite: Mobs/Species/Terminator/parts.rsi + state: full diff --git a/Resources/Prototypes/Entities/Mobs/Player/terminator.yml b/Resources/Prototypes/Entities/Mobs/Player/terminator.yml new file mode 100644 index 00000000000000..0867419f8b2c9d --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Player/terminator.yml @@ -0,0 +1,183 @@ +- type: entity + parent: MobHuman + id: MobHumanTerminator + # uses random name generator dont worry + name: exterminator + components: + - type: Terminator + - type: GenericAntag + rule: Exterminator + # reduced barotrauma damage + - type: Barotrauma + damage: + types: + Blunt: 0.1 + # 4x stamina, faster recovery + - type: Stamina + decay: 6 + cooldown: 1 + critThreshold: 400 + # immune to space drugs, pax, temporary blindness + - type: StatusEffects + allowed: + - Stun + - KnockedDown + - SlowedDown + - Stutter + - Electrocution + - Drunk + - SlurredSpeech + - RatvarianLanguage + - PressureImmunity + - Muted + - ForcedSleep + - StaminaModifier + - type: MobState + allowedStates: + - Alive + - Dead + # endoskeleton need it + - type: TransferMindOnGib + - type: MobThresholds + thresholds: + 0: Alive + # used for health display its not possible to actually fall into crit + 200: Dead + # fire!!!! + - type: Flammable + damage: + types: + Heat: 2.0 + # slightly wider thresholds + - type: Temperature + heatDamageThreshold: 390 + coldDamageThreshold: 240 + # take terminator flesh damage + - type: Damageable + damageModifierSet: CyberneticFlesh + # only organ is an endoskeleton, which is transferred when flesh dies + - type: Body + prototype: TerminatorFlesh + # endoskeleton transformation when either you would get burned to crit or killed by any damage + # you will become an endoskeleton as your last chance to kill the target + - type: Destructible + thresholds: + # the burn trigger is first incase of a bombing or nuking, it might well do over 200 damage but 100 heat is more important + - trigger: + !type:DamageTypeTrigger + damageType: Heat + damage: 100 + behaviors: + - !type:PopupBehavior + popup: terminator-endoskeleton-burn-popup + popupType: LargeCaution + - !type:GibBehavior + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:PopupBehavior + popup: terminator-endoskeleton-gib-popup + popupType: LargeCaution + - !type:GibBehavior + # faster than humans when damaged + - type: SlowOnDamage + speedModifierThresholds: + 70: 0.8 + 90: 0.6 + # arnold is very strong + - type: MeleeWeapon + damage: + types: + Blunt: 10 + Structural: 10 + - type: RandomHumanoidAppearance + +- type: entity + parent: + - BaseMob + - MobCombat + - MobDamageable + - MobSiliconBase + id: MobTerminatorEndoskeleton + # you are now valid + name: nt-800 "exterminator" endoskeleton + description: The inner powerhouse of Susnet's infiltrator androids. Ridiculously hard alloy on the inside, unassuming flesh on the outside. + components: + - type: HumanoidAppearance + species: Terminator + - type: MovementSpeedModifier + baseWalkSpeed: 1.5 + baseSprintSpeed: 3.0 + - type: Sprite + sprite: Mobs/Species/Terminator/parts.rsi + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 0.35 + # he heavy + density: 500 + mask: + - MobMask + layer: + - MobLayer + - type: MobThresholds + thresholds: + 0: Alive + # gibbed at 200 so cant go crit + 200: Dead + # incase some weird stuff happens and the crew adopts a terminator + - type: Repairable + doAfterDelay: 15 + allowSelfRepair: false + - type: Body + prototype: TerminatorEndoskeleton + # lets it sit in the terminator flesh's brain slot + - type: Organ + - type: Brain + - type: TypingIndicator + proto: robot # beep boop borp + - type: Speech + speechSounds: Pai + - type: Damageable + damageModifierSet: Cybernetic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:PlaySoundBehavior + # endoSKELETON + sound: /Audio/Effects/bone_rattle.ogg + # a keepsake or a gift for cargo + - !type:SpawnEntitiesBehavior + spawn: + HeadTerminator: + min: 1 + max: 1 + - !type:DoActsBehavior + acts: [ "Destruction" ] + # for fire spreading around, the endoskeleton cannot burn + - type: Flammable + fireSpread: true + canResistFire: true + damage: + types: + Heat: 0 + # now his only weapon, but it is stronger + - type: MeleeWeapon + damage: + types: + Blunt: 15 + Structural: 5 + - type: Puller + needsHands: false + - type: Tag + tags: + - DoorBumpOpener + - ShoesRequiredStepTriggerImmune + # let mind transfer on gib work + - MindTransferTarget diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 53042c648dd37c..8b68ea7fb798fc 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -260,6 +260,19 @@ lightBreakChancePerSecond: 0.0003 doorToggleChancePerSecond: 0.001 +- type: entity + parent: BaseGameRule + id: TerminatorSpawn + noSpawn: true + components: + - type: StationEvent + weight: 8 + duration: 1 + earliestStart: 30 + minimumPlayers: 20 + - type: RandomSpawnRule + prototype: SpawnPointGhostTerminator + - type: entity id: VentClog parent: BaseGameRule diff --git a/Resources/Prototypes/GameRules/midround.yml b/Resources/Prototypes/GameRules/midround.yml index 241ee931bb58f0..28767e2c1808d1 100644 --- a/Resources/Prototypes/GameRules/midround.yml +++ b/Resources/Prototypes/GameRules/midround.yml @@ -34,4 +34,15 @@ parent: BaseGameRule noSpawn: true components: - - type: ThiefRule \ No newline at end of file + - type: ThiefRule + +- type: entity + noSpawn: true + parent: BaseGameRule + id: Exterminator + components: + - type: GenericAntagRule + agentName: terminator-round-end-agent-name + objectives: + - TerminateObjective + - ShutDownObjective diff --git a/Resources/Prototypes/Objectives/terminator.yml b/Resources/Prototypes/Objectives/terminator.yml new file mode 100644 index 00000000000000..1b569599a7fa6b --- /dev/null +++ b/Resources/Prototypes/Objectives/terminator.yml @@ -0,0 +1,40 @@ +- type: entity + abstract: true + parent: BaseObjective + id: BaseTerminatorObjective + components: + - type: Objective + difficulty: 1 + issuer: susnet + - type: RoleRequirement + roles: + components: + - TerminatorRole + +- type: entity + noSpawn: true + parent: [BaseTerminatorObjective, BaseKillObjective] + id: TerminateObjective + description: Follow your programming and terminate the target. + components: + - type: Objective + unique: false + - type: TargetObjective + title: objective-terminate-title + - type: PickRandomPerson + - type: TerminatorTargetOverride + - type: KillPersonCondition + requireDead: true + +- type: entity + noSpawn: true + parent: BaseTerminatorObjective + id: ShutDownObjective + name: Shut down + description: Once the mission is complete die to prevent our technology from being stolen. + components: + - type: Objective + icon: + sprite: Mobs/Species/Terminator/parts.rsi + state: skull_icon + - type: DieCondition diff --git a/Resources/Prototypes/Roles/Antags/terminator.yml b/Resources/Prototypes/Roles/Antags/terminator.yml new file mode 100644 index 00000000000000..ef1f176b8de4ec --- /dev/null +++ b/Resources/Prototypes/Roles/Antags/terminator.yml @@ -0,0 +1,6 @@ +- type: antag + id: Terminator + name: roles-antag-terminator-name + antagonist: true + setPreference: false + objective: roles-antag-terminator-objective diff --git a/Resources/Prototypes/Species/terminator.yml b/Resources/Prototypes/Species/terminator.yml new file mode 100644 index 00000000000000..cfc5a7107cead7 --- /dev/null +++ b/Resources/Prototypes/Species/terminator.yml @@ -0,0 +1,110 @@ +- type: species + id: Terminator + name: Terminator + roundStart: false + prototype: MobTerminatorEndoskeleton + sprites: MobTerminatorSprites + defaultSkinTone: "#fff9e2" + markingLimits: MobHumanMarkingLimits + maleFirstNames: skeletonNamesFirst + femaleFirstNames: skeletonNamesFirst + dollPrototype: MobSkeletonPersonDummy + skinColoration: TintedHues + +- type: speciesBaseSprites + id: MobTerminatorSprites + sprites: + Head: MobTerminatorHead + Chest: MobTerminatorTorso + LArm: MobTerminatorLArm + RArm: MobTerminatorRArm + LHand: MobTerminatorLHand + RHand: MobTerminatorRHand + LLeg: MobTerminatorLLeg + RLeg: MobTerminatorRLeg + LFoot: MobTerminatorLFoot + RFoot: MobTerminatorRFoot + +- type: humanoidBaseSprite + id: MobTerminatorHead + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: head_m + +- type: humanoidBaseSprite + id: MobTerminatorHeadMale + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: head_m + +- type: humanoidBaseSprite + id: MobTerminatorHeadFemale + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: head_f + +- type: humanoidBaseSprite + id: MobTerminatorTorso + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: torso_m + +- type: humanoidBaseSprite + id: MobTerminatorTorsoMale + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: torso_m + +- type: humanoidBaseSprite + id: MobTerminatorTorsoFemale + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: torso_f + +- type: humanoidBaseSprite + id: MobTerminatorLLeg + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: l_leg + +- type: humanoidBaseSprite + id: MobTerminatorLArm + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: l_arm + +- type: humanoidBaseSprite + id: MobTerminatorLHand + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: l_hand + +- type: humanoidBaseSprite + id: MobTerminatorLFoot + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: l_foot + +- type: humanoidBaseSprite + id: MobTerminatorRLeg + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: r_leg + +- type: humanoidBaseSprite + id: MobTerminatorRArm + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: r_arm + +- type: humanoidBaseSprite + id: MobTerminatorRHand + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: r_hand + +- type: humanoidBaseSprite + id: MobTerminatorRFoot + baseSprite: + sprite: Mobs/Species/Terminator/parts.rsi + state: r_foot diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/full.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/full.png new file mode 100644 index 00000000000000..44e3df3e91b378 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/full.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/head_f.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/head_f.png new file mode 100644 index 00000000000000..dada5727bf6261 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/head_f.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/head_m.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/head_m.png new file mode 100644 index 00000000000000..dada5727bf6261 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/head_m.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_arm.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_arm.png new file mode 100644 index 00000000000000..bb7425405cf99b Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_arm.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_foot.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_foot.png new file mode 100644 index 00000000000000..8e0b3f150767e0 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_foot.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_hand.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_hand.png new file mode 100644 index 00000000000000..cf93432a5e797c Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_hand.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_leg.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_leg.png new file mode 100644 index 00000000000000..d693b3696de905 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/l_leg.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/meta.json b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/meta.json new file mode 100644 index 00000000000000..688877a32d0ab0 --- /dev/null +++ b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/meta.json @@ -0,0 +1,66 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Created by ps3moira#9488 (discord) for SS14.", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "full" + }, + { + "name": "head_f", + "directions": 4 + }, + { + "name": "head_m", + "directions": 4 + }, + { + "name": "l_arm", + "directions": 4 + }, + { + "name": "l_foot", + "directions": 4 + }, + { + "name": "l_hand", + "directions": 4 + }, + { + "name": "l_leg", + "directions": 4 + }, + { + "name": "r_arm", + "directions": 4 + }, + { + "name": "r_foot", + "directions": 4 + }, + { + "name": "r_hand", + "directions": 4 + }, + { + "name": "r_leg", + "directions": 4 + }, + { + "name": "skull_icon", + "directions": 1 + }, + { + "name": "torso_f", + "directions": 4 + }, + { + "name": "torso_m", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_arm.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_arm.png new file mode 100644 index 00000000000000..51f05a477380a3 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_arm.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_foot.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_foot.png new file mode 100644 index 00000000000000..19ac240da3ad9b Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_foot.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_hand.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_hand.png new file mode 100644 index 00000000000000..6cd2eb37ccbe12 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_hand.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_leg.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_leg.png new file mode 100644 index 00000000000000..e1ea113ca3db63 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/r_leg.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/skull_icon.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/skull_icon.png new file mode 100644 index 00000000000000..6d0ea6678058c6 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/skull_icon.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/torso_f.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/torso_f.png new file mode 100644 index 00000000000000..2bcb3cc9ebacb6 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/torso_f.png differ diff --git a/Resources/Textures/Mobs/Species/Terminator/parts.rsi/torso_m.png b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/torso_m.png new file mode 100644 index 00000000000000..2bcb3cc9ebacb6 Binary files /dev/null and b/Resources/Textures/Mobs/Species/Terminator/parts.rsi/torso_m.png differ