From 0cf1ff59dd2631d01a024635277485e6fa913c60 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Tue, 7 Feb 2023 14:03:17 -0500 Subject: [PATCH 01/60] Added a new mob typed named Hologram, set up a clone of the Drone whitelist system for "hardlight --- .../Gravity/FloatingVisualsComponent.cs | 4 + .../Gravity/SharedFloatingVisualizerSystem.cs | 7 +- .../Drone/HologramComponent.cs | 6 + .../Drone/SharedHologramSystem.cs | 31 +++ .../Prototypes/Entities/Objects/Fun/toys.yml | 3 + .../Body/Prototypes/hologram.yml | 11 + .../Entities/Mobs/Player/hologram.yml | 197 ++++++++++++++++++ Resources/Prototypes/SimpleStation14/tags.yml | 3 + 8 files changed, 260 insertions(+), 2 deletions(-) create mode 100644 Content.Shared/SimpleStation14/Drone/HologramComponent.cs create mode 100644 Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs create mode 100644 Resources/Prototypes/SimpleStation14/Body/Prototypes/hologram.yml create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml diff --git a/Content.Shared/Gravity/FloatingVisualsComponent.cs b/Content.Shared/Gravity/FloatingVisualsComponent.cs index 40186db844..2d3a50f0a7 100644 --- a/Content.Shared/Gravity/FloatingVisualsComponent.cs +++ b/Content.Shared/Gravity/FloatingVisualsComponent.cs @@ -23,6 +23,10 @@ public sealed class FloatingVisualsComponent : Component [ViewVariables(VVAccess.ReadWrite)] public bool CanFloat = false; + + [ViewVariables(VVAccess.ReadWrite)] + [DataField("force")] + public bool Force = false; public readonly string AnimationKey = "gravity"; } diff --git a/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs b/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs index 67da1e5169..e80defb6fb 100644 --- a/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs +++ b/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs @@ -28,6 +28,9 @@ public virtual void FloatAnimation(EntityUid uid, Vector2 offset, string animati protected bool CanFloat(EntityUid uid, FloatingVisualsComponent component, TransformComponent? transform = null) { + if (component.Force == true) + return true; + if (!Resolve(uid, ref transform)) return false; @@ -59,7 +62,7 @@ private void OnGravityChanged(ref GravityChangedEvent args) Dirty(floating); var uid = floating.Owner; - if (!args.HasGravity) + if (!args.HasGravity || floating.Force == true) FloatAnimation(uid, floating.Offset, floating.AnimationKey, floating.AnimationTime); } } @@ -67,7 +70,7 @@ private void OnGravityChanged(ref GravityChangedEvent args) private void OnEntParentChanged(EntityUid uid, FloatingVisualsComponent component, ref EntParentChangedMessage args) { var transform = args.Transform; - if (CanFloat(uid, component, transform)) + if (CanFloat(uid, component, transform) || component.Force == true) FloatAnimation(uid, component.Offset, component.AnimationKey, component.AnimationTime); } diff --git a/Content.Shared/SimpleStation14/Drone/HologramComponent.cs b/Content.Shared/SimpleStation14/Drone/HologramComponent.cs new file mode 100644 index 0000000000..122527c633 --- /dev/null +++ b/Content.Shared/SimpleStation14/Drone/HologramComponent.cs @@ -0,0 +1,6 @@ +namespace Content.Shared.SimpleStation14.Hologram +{ + [RegisterComponent] + public sealed class HologramComponent : Component + {} +} diff --git a/Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs new file mode 100644 index 0000000000..0b8074019e --- /dev/null +++ b/Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs @@ -0,0 +1,31 @@ +using Content.Shared.Interaction.Events; +using Content.Shared.Interaction.Components; +using Content.Shared.Damage; +using Content.Shared.Item; +using Content.Shared.Tag; +using Robust.Shared.Serialization; + +namespace Content.Shared.SimpleStation14.Hologram +{ + public class SharedHologramSystem : EntitySystem + { + [Dependency] private readonly TagSystem _tagSystem = default!; + public override void Initialize() + { + SubscribeLocalEvent(OnInteractionAttempt); + } + + private void OnInteractionAttempt(EntityUid uid, HologramComponent component, InteractionAttemptEvent args) + { + if (args.Target == null) + return; + + if (TryComp(args.Target, out var dmg) && dmg.DamageContainerID == "Biological") + args.Cancel(); + + if (HasComp(args.Target) && !HasComp(args.Target) + && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight")) + args.Cancel(); + } + } +} diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index 3ba5a0addd..ec540233f5 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -61,6 +61,9 @@ energy: 2 - type: RgbLightController layers: [ 0 ] + - type: Tag + tags: + - Hardlight - type: entity parent: BasePlushie diff --git a/Resources/Prototypes/SimpleStation14/Body/Prototypes/hologram.yml b/Resources/Prototypes/SimpleStation14/Body/Prototypes/hologram.yml new file mode 100644 index 0000000000..f71dcadf5e --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Body/Prototypes/hologram.yml @@ -0,0 +1,11 @@ +- type: body + id: Hologram + name: "hologram" + root: hand 1 + slots: + hand 1: + part: LeftArmBorg + connections: + - hand 2 + hand 2: + part: RightArmBorg diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml new file mode 100644 index 0000000000..71b74aed3e --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml @@ -0,0 +1,197 @@ +- type: entity + save: false + abstract: true + id: PlayerHologramBase + components: + # - type: Reactive + # groups: + # Acidic: [Touch] + - type: Input + context: "human" + - type: InputMover + - type: MobMover + # - type: DamageOnHighSpeedImpact + # damage: + # types: + # Blunt: 5 + # soundHit: + # path: /Audio/Effects/hit_kick.ogg + - type: Clickable + # - type: Damageable + # damageContainer: Inorganic + # - type: Bloodstream + # bloodReagent: MotorOil + # bloodlossDamage: + # types: + # Bloodloss: + # 1 + # bloodlossHealDamage: + # types: + # Bloodloss: + # -0.25 + - type: InteractionOutline + - type: Sprite + netsync: false + noRot: true + drawdepth: Mobs + layers: + - map: ["enum.HumanoidVisualLayers.Chest"] + - map: ["enum.HumanoidVisualLayers.Head"] + - map: ["enum.HumanoidVisualLayers.Snout"] + - map: ["enum.HumanoidVisualLayers.Eyes"] + - map: ["enum.HumanoidVisualLayers.RArm"] + - map: ["enum.HumanoidVisualLayers.LArm"] + - map: ["enum.HumanoidVisualLayers.RLeg"] + - map: ["enum.HumanoidVisualLayers.LLeg"] + - shader: StencilClear + sprite: Mobs/Species/Human/parts.rsi + # sprite refactor when + state: l_leg + - shader: StencilMask + map: ["enum.HumanoidVisualLayers.StencilMask"] + sprite: Mobs/Customization/masking_helpers.rsi + state: female_full + visible: false + - map: ["enum.HumanoidVisualLayers.LFoot"] + - map: ["enum.HumanoidVisualLayers.RFoot"] + - map: ["socks"] + - map: ["underpants"] + - map: ["undershirt"] + - map: ["jumpsuit"] + - map: ["enum.HumanoidVisualLayers.LHand"] + - map: ["enum.HumanoidVisualLayers.RHand"] + - map: ["enum.HumanoidVisualLayers.Handcuffs"] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: ["id"] + - map: ["gloves"] + - map: ["shoes"] + - map: ["ears"] + - map: ["outerClothing"] + - map: ["eyes"] + - map: ["belt"] + - map: ["neck"] + - map: ["back"] + - map: ["enum.HumanoidVisualLayers.FacialHair"] + - map: ["enum.HumanoidVisualLayers.Hair"] + - map: ["enum.HumanoidVisualLayers.HeadSide"] + - map: ["enum.HumanoidVisualLayers.HeadTop"] + - map: ["mask"] + - map: ["head"] + - map: ["pocket1"] + - map: ["pocket2"] + - map: ["enum.HumanoidVisualLayers.Tail"] + - map: ["enum.HumanoidVisualLayers.Wings"] + - type: HumanoidAppearance + species: Human + # - type: Body + # prototype: Human + # requiredLegs: 2 + - type: Physics + bodyType: KinematicController + - type: Fixtures + fixtures: # TODO: This needs a second fixture just for mob collisions. + - shape: + !type:PhysShapeCircle + radius: 0.35 + density: 50 + mask: + - MobMask + layer: + - MobLayer + - type: MovementSpeedModifier + baseWalkSpeed : 5 + baseSprintSpeed : 3.5 + - type: Hands + showInHands: false + - type: Body + prototype: Hologram + - type: DoAfter + # - type: Pullable + - type: Examiner + # - type: Puller + # - type: Recyclable + # safe: false + - type: StandingState + - type: Alerts + - type: Tag + tags: + - ShoesRequiredStepTriggerImmune + - type: NoSlip + - type: TypingIndicator + proto: holo + - type: RotationVisuals + - type: FloatingVisuals + force: true + - type: Speech + speechSounds: Tenor + - type: Vocal + sounds: + Male: MaleHuman + Female: FemaleHuman + Unsexed: MaleHuman + - type: Emoting + - type: BodyEmotes + soundsId: GeneralBodyEmotes + - type: Grammar + attributes: + proper: true + - type: Hologram + +- type: entity + save: false + name: Urist McLight + parent: PlayerHologramBase + id: MobHologram + components: + # - type: CombatMode + # disarm: null + - type: InteractionPopup + successChance: 1 + interactSuccessString: hugging-success-hologram + # interactSuccessSound: /Audio/Effects/thudswoosh.ogg + messagePerceivedByOthers: hugging-success-hologram-others + - type: Mind + showExamineInfo: true + - type: Input + context: "human" + - type: MobMover + - type: InputMover + - type: Inventory + - type: Alerts + - type: Actions + - type: Eye + # - type: CameraRecoil + - type: Examiner + - type: Faction + factions: + - NanoTrasen + - type: IntrinsicRadioReceiver + channels: + - Common + - Engineering + - Medical + - Science + - Service + - Binary + - type: IntrinsicRadioTransmitter + channels: + - Common + - Engineering + - Medical + - Science + - Service + - Binary + - type: ActiveRadio + channels: + - Common + - Engineering + - Medical + - Science + - Service + - Binary + - type: PointLight + radius: 3.5 + softness: 1 diff --git a/Resources/Prototypes/SimpleStation14/tags.yml b/Resources/Prototypes/SimpleStation14/tags.yml index 6384bf6e4e..03b82cba50 100644 --- a/Resources/Prototypes/SimpleStation14/tags.yml +++ b/Resources/Prototypes/SimpleStation14/tags.yml @@ -3,3 +3,6 @@ - type: Tag id: GlassesNearsight + +- type: Tag + id: Hardlight From f26cbf1243e101c1164043b4ffc7055b3b5025f3 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 13 Feb 2023 17:26:27 -0500 Subject: [PATCH 02/60] adds early scutters, and the basis of a charging system. --- .../Silicon/Charge/SiliconChargeSystem.cs | 24 ++++ .../Components/SiliconChargeComponent.cs | 20 +++ .../Entities/Mobs/Player/borgs.yml | 1 + .../Entities/Body/Prototypes/scutter.yml | 7 + .../Entities/Mobs/Player/silicon.yml | 129 ++++++++++++++++++ .../scutter_inventory_template.yml | 11 ++ .../Mobs/Silicon/scutter.rsi/l_hand.png | Bin 0 -> 654 bytes .../Mobs/Silicon/scutter.rsi/meta.json | 31 +++++ .../Mobs/Silicon/scutter.rsi/r_hand.png | Bin 0 -> 5373 bytes .../Mobs/Silicon/scutter.rsi/scutter.png | Bin 0 -> 9214 bytes .../Mobs/Silicon/scutter.rsi/shell.png | Bin 0 -> 942 bytes 11 files changed, 223 insertions(+) create mode 100644 Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs create mode 100644 Content.Shared/SimpleStation14/Silicon/Charge/Components/SiliconChargeComponent.cs create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Body/Prototypes/scutter.yml create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon.yml create mode 100644 Resources/Prototypes/SimpleStation14/InventoryTemplates/scutter_inventory_template.yml create mode 100644 Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/l_hand.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/meta.json create mode 100644 Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/r_hand.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/scutter.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/shell.png diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs new file mode 100644 index 0000000000..ea5d58dcd8 --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Random; +using Content.Shared.Silicon.Charge; + +namespace Content.Server.Silicon.Charge; + +public sealed class SiliconChargeSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + public override void Initialize() + { + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + foreach (var silicon in EntityQuery()) + { + if (silicon.CurrentCharge > 0) + { + silicon.CurrentCharge -= (frameTime * silicon.ChargeDrainMult * 2) * _random.NextFloat(1.1f, 0.9f); + } + } + } +} diff --git a/Content.Shared/SimpleStation14/Silicon/Charge/Components/SiliconChargeComponent.cs b/Content.Shared/SimpleStation14/Silicon/Charge/Components/SiliconChargeComponent.cs new file mode 100644 index 0000000000..a9a25672cf --- /dev/null +++ b/Content.Shared/SimpleStation14/Silicon/Charge/Components/SiliconChargeComponent.cs @@ -0,0 +1,20 @@ +namespace Content.Shared.Silicon.Charge; + +/// +/// +/// +[RegisterComponent] +public sealed class SiliconChargeComponent : Component +{ + [DataField("currentCharge"), ViewVariables(VVAccess.ReadWrite)] + public float CurrentCharge = 100; + + [DataField("maxCharge"), ViewVariables(VVAccess.ReadWrite)] + public float MaxCharge = 2000; + + [DataField("chargeDrainMult"), ViewVariables(VVAccess.ReadWrite)] + public float ChargeDrainMult = 1; + + [DataField("freezeOnEmpty")] + public bool FreezeOnEmpty = false; +} diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml index e2c0a3a8bd..18531a98c3 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml @@ -196,6 +196,7 @@ id: PlayerCyborgStandard name: standard cyborg components: + - type: SiliconCharge - type: InnateTool tools: - id: WelderIndustrial diff --git a/Resources/Prototypes/SimpleStation14/Entities/Body/Prototypes/scutter.yml b/Resources/Prototypes/SimpleStation14/Entities/Body/Prototypes/scutter.yml new file mode 100644 index 0000000000..123b364be0 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Body/Prototypes/scutter.yml @@ -0,0 +1,7 @@ +- type: body + id: Scutter + name: "scutter" + root: hand 1 + slots: + hand 1: + part: LeftArmBorg diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon.yml new file mode 100644 index 0000000000..1f5a0e47f3 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon.yml @@ -0,0 +1,129 @@ +- type: entity + id: Scutter + name: scutter + description: "Lacking fine motor skills and often the ability to listen to directions, it's the most inconsistent hand a Hologram could ask for." + parent: PlayerSiliconBase + components: + - type: Eye + - type: Body + prototype: Scutter + - type: Inventory + templateId: scutter + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - key: enum.LawsUiKey.Key + type: LawsBoundUserInterface + - type: GhostTakeoverAvailable + makeSentient: true + name: Scutter + description: Maintain the station. Ignore other beings except drones. + rules: | + You are bound by these laws both in-game and out-of-character: + 1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. + 2. You may not harm any being, regardless of intent or circumstance. + 3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. + - type: Laws + canState: false + laws: + - You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. + - You may not harm any being, regardless of intent or circumstance. + - Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. + - You may accept orders received via the binary channel, regardless of the nature of the being issuing them, so long as they do not conflict with Law Two or Law Three. + - type: MovementSpeedModifier + baseWalkSpeed : 4 + baseSprintSpeed : 4 + - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds + thresholds: + 0: Alive + 60: Dead + - type: Flashable + - type: NoSlip + - type: StatusEffects + allowed: + - Stun + - KnockedDown + - SlowedDown + - type: SlowOnDamage + speedModifierThresholds: + 30: 0.7 + 50: 0.5 + - type: Temperature + heatDamageThreshold: 5000 + currentTemperature: 310.15 + specificHeat: 42 + heatDamage: + types: + Heat : 1 #per second, scales with temperature & other constants + - type: Sprite + drawdepth: SmallMobs + netsync: false + layers: + - state: scutter + sprite: SimpleStation14/Mobs/Silicon/scutter.rsi + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeCircle + radius: 0.25 + density: 50 + mask: + - SmallMobMask + layer: + - SmallMobLayer + # - type: Appearance + # visuals: + # - type: GenericEnumVisualizer + # key: enum.DroneVisuals.Status + # layer: 0 + # states: + # enum.DroneStatus.Off: shell + # enum.DroneStatus.On: scutter + - type: ReplacementAccent + accent: silicon + - type: Repairable + fuelcost: 15 + doAfterDelay: 5 + - type: Actions + # - type: UnpoweredFlashlight + # toggleAction: + # name: action-name-toggle-light + # description: action-description-toggle-light + # icon: { sprite: Objects/Tools/flashlight.rsi, state: flashlight } + # iconOn: Objects/Tools/flashlight.rsi/flashlight-on.png + # event: !type:ToggleActionEvent + # - type: PointLight + # enabled: false + # radius: 3.5 + # softness: 1 + # mask: /Textures/Effects/LightMasks/cone.png + # autoRot: true + - type: Tag + tags: + # - ShoesRequiredStepTriggerImmune + - CannotSuicide + - type: Hands + showInHands: false + - type: IntrinsicUI + uis: + - key: enum.LawsUiKey.Key + toggleAction: + name: action-name-show-laws + description: action-description-show-laws + icon: Structures/Wallmounts/posters.rsi/poster11_legit.png #someone wanna make new icons? + iconOn: Structures/Wallmounts/posters.rsi/poster11_legit.png + keywords: [ "AI", "console", "interface", "laws", "borg" ] + priority: -3 + event: !type:ToggleIntrinsicUIEvent + - type: IntrinsicRadioReceiver + channels: + - Binary + - type: ActiveRadio + channels: + - Binary diff --git a/Resources/Prototypes/SimpleStation14/InventoryTemplates/scutter_inventory_template.yml b/Resources/Prototypes/SimpleStation14/InventoryTemplates/scutter_inventory_template.yml new file mode 100644 index 0000000000..efa5439513 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/InventoryTemplates/scutter_inventory_template.yml @@ -0,0 +1,11 @@ +- type: inventoryTemplate + id: scutter + slots: + - name: head + slotTexture: head + slotFlags: HEAD + slotGroup: MainHotbar + uiWindowPos: 0,0 + strippingWindowPos: 0,0 + displayName: Head + offset: 0, -0.4 diff --git a/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/l_hand.png b/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/l_hand.png new file mode 100644 index 0000000000000000000000000000000000000000..272f4a066465599e2e86fea27c5568ae78b04545 GIT binary patch literal 654 zcmV;90&)F`P)EX>4Tx04R}tkv&MmKpe$iQ>8^J4i*$~$WWauh>AFB6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfbaGO3krMxx6k5c1aNLh~_a1le0HIM~n$%wfUwLgV@{G%@Eu?G2=MhT&a?c_{W*Hoyv2ZkNIc67(3QNPu~_V2rGr_?)QG2uW2&Z8zL51; z<-EmNtJGNQp8SQ8yuPx`b(+ISVi8M_AVNV6WmI4zPODCeg*5FaeEdVMUm}-6t}+-o z7Epx-+4Y0}!S8OZ!sLXP6iEQxFOKsu0)%#fX5DeVj~%CZ0tBCdE4}TnHh`H=((7$4 zb_Dco0~gnAP1yr3cYwhsLpEhs3epq`1>pURz9|Rv-vT{rUT>{^oIU^<>MC^u92^3p zMao|Hd3U(8w|~#H`uhRNFmhx3{23Sk000JJOGiWi{{a60|De66lK=n!32;bRa{vGe z!~g&a!~te)g46&200(qQO+^Rh0s|KY2Eyza_W%F@j7da6RCwC$+A#{nAPfM|(i7xv zIYRCa-oQT=9ukhaFViH1dF~IU{I93@bV_dqnK}F8uR800000001!0SO0m-?h4HO%6@9{jD3VHCSX+4hwlfp o);@3g$bEz@Ct!u#008Xf2P{NA<;_V#TL1t607*qoM6N<$g2KWWC;$Ke literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/meta.json b/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/meta.json new file mode 100644 index 0000000000..51a8534c4b --- /dev/null +++ b/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/meta.json @@ -0,0 +1,31 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/40d89d11ea4a5cb81d61dc1018b46f4e7d32c62a", + "states": [ + { + "name": "scutter", + "directions": 8 + }, + { + "name": "shell", + "delays": [ + [ + 1 + ] + ] + }, + { + "name": "l_hand", + "directions": 4 + }, + { + "name": "r_hand", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/r_hand.png b/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/r_hand.png new file mode 100644 index 0000000000000000000000000000000000000000..4a18493138cc9ae617653e61c10d3aefa8174c90 GIT binary patch literal 5373 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/shell.png b/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/shell.png new file mode 100644 index 0000000000000000000000000000000000000000..0c6551c5aaf0a734e252dbb729af54124aaa4af8 GIT binary patch literal 942 zcmV;f15x~mP)EX>4Tx04R}tkvmAkP!xv$rivn!4t5Z6$j~}j@P#;P6^c+H)C#RSnB4RQO&XFE z7e~Rh;NWAi>fqw6tAnc`2tGg@otzY1q{MTRLW>v=T<*tz&;N7pxq#59FwN>312o+> z)5(OG&8><(uMiMG7~_b^%rfRADFxs9x~E>MyExDC@B6d*)x5=kfJi*c4AUmwAfDc| z4bJ<-5mu5_;&b9rlP*a7$aTfzH_kz@3Dp}fAb%ynABNMaF7kRU=q4P{hdBTl=bb^8^S!16O+6Uu^(0pQP8@ zTJ#7AZvz+CZB5w&E_Z;zCqp)6R|?V+3I*W(jJ_!c4BP^JYu?;i=Qw=;GBm5y4RCM> zj1(z*-RIrCopbxQr!~JHa;b8s0=g}l00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru<^ll^GB1NjNG|{Y02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00D+cL_t(o!|jwiZsRZzhCd2H9JpeYz|A6n!CJi!zypv+ z(7AL3@&G=7F5prk5Nu<_l?r1Mr--&OxpLOAod=MHUq#LgXMPSJkjZ2+nM~$~5tjy9 zYX<=5oUqmoegB$#QWnV`W4=W|Ob9Ta&jAP_(D$$0-rn=_@|)}HUu-rHNLd`jM9zsR zP8B!CptVl6vMf`P&E_E$j{?iGOtD&Pj4=nBIL6hv7OmIol-zp{z;5@<-Q6_p{PFP* zAp}AQ7-P~prPSFYC{8)swnZsL2m$YXN|K04p9p{`F$6wNgi~fPP Date: Tue, 14 Feb 2023 03:01:15 -0500 Subject: [PATCH 03/60] Working on it --- .../Components/HoloProjectorComponent.cs | 11 +++++ .../Holograms/Systems/HologramSystem.cs | 42 +++++++++++++++++++ .../Drone/HologramComponent.cs | 5 ++- .../Drone/SharedHologramSystem.cs | 1 - 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 Content.Client/SimpleStation14/Holograms/Components/HoloProjectorComponent.cs create mode 100644 Content.Client/SimpleStation14/Holograms/Systems/HologramSystem.cs diff --git a/Content.Client/SimpleStation14/Holograms/Components/HoloProjectorComponent.cs b/Content.Client/SimpleStation14/Holograms/Components/HoloProjectorComponent.cs new file mode 100644 index 0000000000..ae5620f598 --- /dev/null +++ b/Content.Client/SimpleStation14/Holograms/Components/HoloProjectorComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared.DeviceNetwork; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Client.SimpleStation14.Hologram; + +[RegisterComponent] +public sealed class HoloProjectorComponent : Component +{ + [ViewVariables] + public bool Active { get; set; } = true; +} diff --git a/Content.Client/SimpleStation14/Holograms/Systems/HologramSystem.cs b/Content.Client/SimpleStation14/Holograms/Systems/HologramSystem.cs new file mode 100644 index 0000000000..700aad7fe4 --- /dev/null +++ b/Content.Client/SimpleStation14/Holograms/Systems/HologramSystem.cs @@ -0,0 +1,42 @@ +using Content.Shared.Tag; +using Content.Shared.SimpleStation14.Hologram; +using Robust.Client.Player; +using Content.Shared.Interaction.Helpers; + + +namespace Content.Client.SimpleStation14.Hologram; + +public class HologramSystem : EntitySystem +{ + [Dependency] private readonly TagSystem _tagSystem = default!; + [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + + public override void Initialize() + { + // SubscribeLocalEvent(OnInteractionAttempt); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + if (_player.LocalPlayer?.ControlledEntity == null) return; + var uid = _player.LocalPlayer.ControlledEntity.Value; + + if (!_entityManager.TryGetComponent(uid, out HologramComponent? component)) return; + + var playerPos = _entityManager.GetComponent(uid).WorldPosition; + var projQuery = _entityManager.EntityQuery(); + + var projUid = EntityUid.Invalid; + foreach (var proj in projQuery) + { + if (!proj.Owner.InRangeUnOccluded(uid)) continue; + projUid = proj.Owner; + break; + } + + component.CurProjector = projUid; + } +} diff --git a/Content.Shared/SimpleStation14/Drone/HologramComponent.cs b/Content.Shared/SimpleStation14/Drone/HologramComponent.cs index 122527c633..8eb8368530 100644 --- a/Content.Shared/SimpleStation14/Drone/HologramComponent.cs +++ b/Content.Shared/SimpleStation14/Drone/HologramComponent.cs @@ -2,5 +2,8 @@ namespace Content.Shared.SimpleStation14.Hologram { [RegisterComponent] public sealed class HologramComponent : Component - {} + { + [ViewVariables] + public EntityUid? CurProjector; + } } diff --git a/Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs index 0b8074019e..9570fbdefa 100644 --- a/Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs +++ b/Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs @@ -3,7 +3,6 @@ using Content.Shared.Damage; using Content.Shared.Item; using Content.Shared.Tag; -using Robust.Shared.Serialization; namespace Content.Shared.SimpleStation14.Hologram { From 3da44f1e067dfb292adbf1250d3cfd7497243b36 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Fri, 24 Feb 2023 18:42:07 -0500 Subject: [PATCH 04/60] Lots more work towards holograms, probably too long without committing :P --- .../Components/HoloProjectorComponent.cs | 11 - .../Holograms/Systems/HologramSystem.cs | 42 -- .../Holograms/Components/HoloDiskComponent.cs | 19 + .../Holograms/Systems/HologramServerSystem.cs | 191 +++++++++ .../Holograms/Systems/HologramSystem.cs | 397 ++++++++++++++++++ .../Drone/HologramComponent.cs | 9 - .../Drone/SharedHologramSystem.cs | 30 -- .../Holograms/HoloServerComponent | 6 + .../Holograms/HologramComponent.cs | 12 + .../Holograms/HologramEvents.cs | 27 ++ .../Holograms/HologramProjectorComponent.cs | 6 + .../Holograms/HolopodComponent.cs | 6 + .../Holograms/SharedHologramSystem.cs | 67 +++ .../Effects/Hologram/holo_off.ogg | Bin 0 -> 8815 bytes .../Effects/Hologram/holo_on.ogg | Bin 0 -> 8956 bytes .../en-US/SimpleStation14/holograms.ftl | 4 + .../Structures/Machines/cloning_machine.yml | 1 + .../Wallmounts/surveillance_camera.yml | 1 + .../Entities/Mobs/NPCs/pets.yml | 73 ++++ .../Machines/hologram_constructor.yml | 135 ++++++ .../Mobs/Pets/corgi.rsi/holo_corgi.png | Bin 0 -> 12178 bytes .../Mobs/Pets/corgi.rsi/meta.json | 33 ++ 22 files changed, 978 insertions(+), 92 deletions(-) delete mode 100644 Content.Client/SimpleStation14/Holograms/Components/HoloProjectorComponent.cs delete mode 100644 Content.Client/SimpleStation14/Holograms/Systems/HologramSystem.cs create mode 100644 Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs create mode 100644 Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs create mode 100644 Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs delete mode 100644 Content.Shared/SimpleStation14/Drone/HologramComponent.cs delete mode 100644 Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs create mode 100644 Content.Shared/SimpleStation14/Holograms/HoloServerComponent create mode 100644 Content.Shared/SimpleStation14/Holograms/HologramComponent.cs create mode 100644 Content.Shared/SimpleStation14/Holograms/HologramEvents.cs create mode 100644 Content.Shared/SimpleStation14/Holograms/HologramProjectorComponent.cs create mode 100644 Content.Shared/SimpleStation14/Holograms/HolopodComponent.cs create mode 100644 Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs create mode 100644 Resources/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg create mode 100644 Resources/Audio/SimpleStation14/Effects/Hologram/holo_on.ogg create mode 100644 Resources/Locale/en-US/SimpleStation14/holograms.ftl create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml create mode 100644 Resources/Textures/SimpleStation14/Mobs/Pets/corgi.rsi/holo_corgi.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Pets/corgi.rsi/meta.json diff --git a/Content.Client/SimpleStation14/Holograms/Components/HoloProjectorComponent.cs b/Content.Client/SimpleStation14/Holograms/Components/HoloProjectorComponent.cs deleted file mode 100644 index ae5620f598..0000000000 --- a/Content.Client/SimpleStation14/Holograms/Components/HoloProjectorComponent.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Content.Shared.DeviceNetwork; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; - -namespace Content.Client.SimpleStation14.Hologram; - -[RegisterComponent] -public sealed class HoloProjectorComponent : Component -{ - [ViewVariables] - public bool Active { get; set; } = true; -} diff --git a/Content.Client/SimpleStation14/Holograms/Systems/HologramSystem.cs b/Content.Client/SimpleStation14/Holograms/Systems/HologramSystem.cs deleted file mode 100644 index 700aad7fe4..0000000000 --- a/Content.Client/SimpleStation14/Holograms/Systems/HologramSystem.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Content.Shared.Tag; -using Content.Shared.SimpleStation14.Hologram; -using Robust.Client.Player; -using Content.Shared.Interaction.Helpers; - - -namespace Content.Client.SimpleStation14.Hologram; - -public class HologramSystem : EntitySystem -{ - [Dependency] private readonly TagSystem _tagSystem = default!; - [Dependency] private readonly IPlayerManager _player = default!; - [Dependency] private readonly IEntityManager _entityManager = default!; - - public override void Initialize() - { - // SubscribeLocalEvent(OnInteractionAttempt); - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - if (_player.LocalPlayer?.ControlledEntity == null) return; - var uid = _player.LocalPlayer.ControlledEntity.Value; - - if (!_entityManager.TryGetComponent(uid, out HologramComponent? component)) return; - - var playerPos = _entityManager.GetComponent(uid).WorldPosition; - var projQuery = _entityManager.EntityQuery(); - - var projUid = EntityUid.Invalid; - foreach (var proj in projQuery) - { - if (!proj.Owner.InRangeUnOccluded(uid)) continue; - projUid = proj.Owner; - break; - } - - component.CurProjector = projUid; - } -} diff --git a/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs b/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs new file mode 100644 index 0000000000..b54d977719 --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs @@ -0,0 +1,19 @@ +using static Content.Server.SimpleStation14.Hologram.HologramSystem; + +namespace Content.Server.SimpleStation14.Hologram; + +[RegisterComponent] +public sealed class HologramDiskComponent : Component +{ + // [ViewVariables] + // public HoloDataEntry? HoloData = null; + + // [DataField("active"), ViewVariables(VVAccess.ReadWrite)] + // public bool Active = true; + + [ViewVariables] + public Mind.Mind? HoloData = null; + + [DataField("active"), ViewVariables(VVAccess.ReadWrite)] + public bool Active = true; +} diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs new file mode 100644 index 0000000000..c51dc0f9f3 --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs @@ -0,0 +1,191 @@ +using Content.Server.SurveillanceCamera; +using Content.Server.GameTicking; +using Content.Server.Mind.Components; +using Content.Shared.Tag; +using Content.Shared.Popups; +using Content.Shared.Interaction.Helpers; +using Content.Shared.SimpleStation14.Hologram; +using Content.Shared.Actions; +using Content.Shared.Actions.ActionTypes; +using Content.Shared.Pulling; +using Content.Shared.Pulling.Components; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Robust.Server.Player; +using Robust.Shared.Player; +using Robust.Shared.Timing; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using Content.Server.Cloning; +using Content.Server.Cloning.Components; + +using Content.Shared.Cloning; +using Content.Shared.Speech; +using Content.Shared.Preferences; +using Content.Shared.Emoting; +using Content.Server.Psionics; +using Content.Server.Speech.Components; +using Content.Server.StationEvents.Components; +using Content.Server.EUI; +using Content.Server.Humanoid; +using Content.Server.Ghost.Roles.Components; +using Content.Server.Jobs; +using Content.Server.Mind; +using Content.Server.Preferences.Managers; +using Content.Shared.Humanoid; +using Content.Shared.Mobs.Systems; +using Robust.Shared.GameObjects.Components.Localization; +using System.Linq; +using Robust.Shared.Containers; +using Content.Shared.Interaction; + +namespace Content.Server.SimpleStation14.Hologram; + +public class HologramServerSystem : EntitySystem +{ + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] protected readonly SharedPopupSystem Popup = default!; + [Dependency] private readonly SharedPullingSystem _pulling = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly IPlayerManager _playerManager = null!; + [Dependency] private readonly CloningSystem _cloningSystem = default!; + [Dependency] private readonly EuiManager _euiManager = null!; + [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + [Dependency] private readonly MindSystem _mind = default!; + [Dependency] private readonly TagSystem _tag = default!; + [Dependency] private readonly IServerPreferencesManager _prefs = default!; + [Dependency] private readonly TagSystem _tagSystem = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + + private const string DiskSlot = "holo_disk"; + public readonly Dictionary ClonesWaitingForMind = new(); + + public override void Initialize() + { + base.Initialize(); + // SubscribeLocalEvent(OnEntInserted); + SubscribeLocalEvent(OnAfterInteract); + } + + public bool TryHoloGenerate(EntityUid uid, Mind.Mind mind, CloningPodComponent? clonePod) + { + CloningSystem cloneSys = new(); + Logger.Info("Trying to clone"); + + if (!Resolve(uid, ref clonePod)) + return false; + + if (HasComp(uid)) + return false; + + Logger.Info("Clone pod is active"); + + if (ClonesWaitingForMind.TryGetValue(mind, out var clone)) + { + if (EntityManager.EntityExists(clone) && + !_mobStateSystem.IsDead(clone) && + TryComp(clone, out var cloneMindComp) && + (cloneMindComp.Mind == null || cloneMindComp.Mind == mind)) + return false; // Mind already has clone + + ClonesWaitingForMind.Remove(mind); + } + Logger.Info("Waiting something something"); + + if (mind.OwnedEntity != null && !_mobStateSystem.IsDead(mind.OwnedEntity.Value)) + return false; // Body controlled by mind is not dead + Logger.Info("Not alive still"); + + // Yes, we still need to track down the client because we need to open the Eui + if (mind.UserId == null || !_playerManager.TryGetSessionById(mind.UserId.Value, out var client)) + return false; // If we can't track down the client, we can't offer transfer. That'd be quite bad. + Logger.Info("Got client"); + + var pref = (HumanoidCharacterProfile) _prefs.GetPreferences(mind.UserId.Value).SelectedCharacter; + + if (pref == null) + return false; + Logger.Info("Got prefs"); + + var mob = HoloFetchAndSpawn(clonePod, pref); + + var cloneMindReturn = EntityManager.AddComponent(mob); + cloneMindReturn.Mind = mind; + cloneMindReturn.Parent = clonePod.Owner; + // clonePod.BodyContainer.Insert(mob); + ClonesWaitingForMind.Add(mind, mob); + UpdateStatus(CloningPodStatus.NoMind, clonePod); + _euiManager.OpenEui(new AcceptCloningEui(mind, cloneSys), client); + + Logger.Warning("Cloned"); + + AddComp(uid); + + // TODO: Ideally, components like this should be on a mind entity so this isn't neccesary. + // Remove this when 'mind entities' are added. + // Add on special job components to the mob. + if (mind.CurrentJob != null) + { + foreach (var special in mind.CurrentJob.Prototype.Special) + { + if (special is AddComponentSpecial) + special.AfterEquip(mob); + } + } + + return true; + } + + public void UpdateStatus(CloningPodStatus status, CloningPodComponent cloningPod) + { + cloningPod.Status = status; + } + + /// + /// Handles fetching the mob and any appearance stuff... + /// + private EntityUid HoloFetchAndSpawn(CloningPodComponent clonePod, HumanoidCharacterProfile pref) + { + List sexes = new(); + var name = pref.Name; + var toSpawn = "MobHologram"; + + var mob = Spawn(toSpawn, Transform(clonePod.Owner).MapPosition); + _humanoidSystem.LoadProfile(mob, pref); + + MetaData(mob).EntityName = name; + var mind = EnsureComp(mob); + _mind.SetExamineInfo(mob, true, mind); + + var grammar = EnsureComp(mob); + grammar.ProperNoun = true; + grammar.Gender = Robust.Shared.Enums.Gender.Neuter; + Dirty(grammar); + + RemComp(mob); + EnsureComp(mob); + EnsureComp(mob); + RemComp(mob); + RemComp(mob); + RemComp(mob); + RemComp(mob); + + _tag.AddTag(mob, "DoorBumpOpener"); + + return mob; + } + + + private void OnAfterInteract(EntityUid uid, HologramDiskComponent component, AfterInteractEvent args) + { + if (args.Target == null || !TryComp(args.Target, out var targetMind) || targetMind.Mind == null) + return; + + component.HoloData = targetMind.Mind; + Popup.PopupEntity(Loc.GetString("Data saved, boi"), args.Target.Value, args.User); + } + +} diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs new file mode 100644 index 0000000000..4fd0b09e3d --- /dev/null +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs @@ -0,0 +1,397 @@ +using Content.Server.SurveillanceCamera; +using Content.Server.GameTicking; +using Content.Server.Mind.Components; +using Content.Shared.Tag; +using Content.Shared.Popups; +using Content.Shared.Interaction.Helpers; +using Content.Shared.SimpleStation14.Hologram; +using Content.Shared.Actions; +using Content.Shared.Actions.ActionTypes; +using Content.Shared.Pulling; +using Content.Shared.Pulling.Components; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Robust.Server.Player; +using Robust.Shared.Player; +using Robust.Shared.Timing; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using Content.Server.Cloning; +using Content.Server.Cloning.Components; + +using Content.Shared.Cloning; +using Content.Shared.Speech; +using Content.Shared.Preferences; +using Content.Shared.Emoting; +using Content.Server.Psionics; +using Content.Server.Speech.Components; +using Content.Server.StationEvents.Components; +using Content.Server.EUI; +using Content.Server.Humanoid; +using Content.Server.Ghost.Roles.Components; +using Content.Server.Jobs; +using Content.Server.Mind; +using Content.Server.Preferences.Managers; +using Content.Shared.Humanoid; +using Content.Shared.Mobs.Systems; +using Robust.Shared.GameObjects.Components.Localization; +using System.Linq; + +namespace Content.Server.SimpleStation14.Hologram; + +public class HologramSystem : EntitySystem +{ + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] protected readonly SharedPopupSystem Popup = default!; + [Dependency] private readonly SharedPullingSystem _pulling = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly IPlayerManager _playerManager = null!; + [Dependency] private readonly CloningSystem _cloningSystem = default!; + [Dependency] private readonly EuiManager _euiManager = null!; + [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + [Dependency] private readonly MindSystem _mind = default!; + [Dependency] private readonly TagSystem _tag = default!; + [Dependency] private readonly IServerPreferencesManager _prefs = default!; + + public readonly Dictionary ClonesWaitingForMind = new(); + + public override void Initialize() + { + base.Initialize(); + // SubscribeLocalEvent(Startup); + // SubscribeLocalEvent(Shutdown); + // SubscribeLocalEvent(HoloTeleport); + } + + // private void Startup(EntityUid uid, HologramComponent component, ComponentStartup args) + // { + // var action = new WorldTargetAction(_prototypeManager.Index("ShadekinTeleport")); + // _actionsSystem.AddAction(uid, action, uid); + // } + + // private void Shutdown(EntityUid uid, HologramComponent component, ComponentShutdown args) + // { + // var action = new WorldTargetAction(_prototypeManager.Index("ShadekinTeleport")); + // _actionsSystem.RemoveAction(uid, action); + // } + + + // Anything that needs to be regularly run, like handling exiting a projector's range + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var component in _entityManager.EntityQuery().ToList()) + { + var projector = HoloGetProjector(component); + if (projector == EntityUid.Invalid) + { + HoloReturn(component); + continue; + } + component.CurProjector = projector; + } + } + + + + /// + /// Tests for the nearest projector to the Hologram. + /// + /// Hologram's HologramComponent. + /// Should it check only for unoccluded and in range projectors? + /// The range it should check for projectors in, if occlude is true + /// Returns the UID of the projector, or invalid UID if no projectors are found. + private EntityUid HoloGetProjector(HologramComponent component, bool occlude = true, float range = 18f) + { + var xformQuery = GetEntityQuery(); + var uid = component.Owner; + var transform = _entityManager.GetComponent(uid); + var playerPos = _transform.GetWorldPosition(transform, xformQuery); + var mapId = transform.MapID; + + // sort all entities in distance increasing order + var nearProjList = new SortedList(); + + foreach (var comp in _entityManager.EntityQuery()) + { + if (!xformQuery.TryGetComponent(comp.Owner, out var compXform) || compXform.MapID != mapId) + continue; + + var dist = (_transform.GetWorldPosition(compXform, xformQuery) - playerPos).LengthSquared; + nearProjList.TryAdd(dist, comp.Owner); + } + + foreach (var nearProj in nearProjList) + { + if (_entityManager.TryGetComponent(nearProj.Value, out var camComp) && !camComp.Active) continue; + if (occlude && !nearProj.Value.InRangeUnOccluded(uid, 18f)) continue; + return nearProj.Value; + } + return EntityUid.Invalid; + } + + /// + /// Tests for the nearest projector to a set of coords. + /// + /// Coords to test from. + /// Map being tested on. + /// Should it check only for unoccluded and in range projectors? + /// The range it should check for projectors in, if occlude is true + /// Returns the UID of the projector, or invalid UID if no projectors are found. + private EntityUid HoloGetProjector(Vector2 coords, MapId mapId, bool occlude = true, float range = 18f) + { + var xformQuery = GetEntityQuery(); + + // sort all entities in distance increasing order + var nearProjList = new SortedList(); + + foreach (var comp in _entityManager.EntityQuery()) + { + if (!xformQuery.TryGetComponent(comp.Owner, out var compXform) || compXform.MapID != mapId) + continue; + + var dist = (_transform.GetWorldPosition(compXform, xformQuery) - coords).LengthSquared; + nearProjList.TryAdd(dist, comp.Owner); + } + + foreach (var nearProj in nearProjList) + { + if (_entityManager.TryGetComponent(nearProj.Value, out var camComp) && !camComp.Active) continue; + if (occlude && !nearProj.Value.InRangeUnOccluded(new MapCoordinates(coords, mapId), range)) continue; + return nearProj.Value; + } + return EntityUid.Invalid; + } + + + /// + /// Handles returning a Hologram to their last visited projector, + /// then to the nearest, finally killing them if none are found. + /// + /// Hologram's HologramComponent. + private void HoloReturn(HologramComponent component) + { + var uid = component.Owner; + var meta = _entityManager.GetComponent(uid); + var holoPos = _entityManager.GetComponent(uid).Coordinates; + + var popupAppearOther = Loc.GetString("system-hologram-phasing-appear-others", ("name", meta.EntityName)); + var popupAppearSelf = Loc.GetString("system-hologram-phasing-appear-self"); + var popupDisappearOther = Loc.GetString("system-hologram-phasing-disappear-others", ("name", meta.EntityName)); + var popupDeathSelf = Loc.GetString("system-hologram-phasing-death-self"); + + if (component.CurProjector == null || !_entityManager.TryGetComponent(component.CurProjector, out var _) || + (_entityManager.TryGetComponent(component.CurProjector, out var camComp) && !camComp.Active)) + { + component.CurProjector = HoloGetProjector(component, false); + } + + if (component.CurProjector == EntityUid.Invalid) + { + + HoloKill(component); + return; + } + _entityManager.TryGetComponent(component.CurProjector, out var transfComp); + + Popup.PopupEntity(popupAppearOther, uid, Filter.PvsExcept((EntityUid) uid), false, PopupType.Medium); + Popup.PopupCoordinates(popupDisappearOther, holoPos, Filter.PvsExcept(uid), false, PopupType.MediumCaution); + _audio.Play(filename: "/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg", playerFilter: Filter.Pvs(uid), coordinates: holoPos, false); + if (TryComp(uid, out var pullable) && pullable.BeingPulled) _pulling.TryStopPull(pullable); + if (TryComp(uid, out var pulling) && pulling.Pulling != null && + TryComp(pulling.Pulling.Value, out var subjectPulling)) _pulling.TryStopPull(subjectPulling); + // Move holo + Transform(uid).Coordinates = _entityManager.GetComponent((EntityUid) component.CurProjector).Coordinates; + Popup.PopupEntity(popupAppearSelf, uid, uid, PopupType.Large); + _audio.PlayPvs("/Audio/SimpleStation14/Effects/Hologram/holo_on.ogg", uid); + + _adminLogger.Add(LogType.Unknown, LogImpact.Low, + $"{ToPrettyString(uid):mob} was returned to projector {ToPrettyString((EntityUid) component.CurProjector):entity}"); + } + + /// + /// Kills a Hologram after playing the visual and auditory effects. + /// + /// Hologram's HologramComponent. + + private void HoloKill(HologramComponent component) + { + var uid = component.Owner; + var meta = _entityManager.GetComponent(uid); + var holoPos = _entityManager.GetComponent(uid).Coordinates; + EntityUid? body = EntityUid.Invalid; + Mind.Mind? mind = null; + + var popupAppearOther = Loc.GetString("system-hologram-phasing-appear-others", ("name", meta.EntityName)); + var popupAppearSelf = Loc.GetString("system-hologram-phasing-appear-self"); + var popupDisappearOther = Loc.GetString("system-hologram-phasing-disappear-others", ("name", meta.EntityName)); + var popupDeathSelf = Loc.GetString("system-hologram-phasing-death-self"); + + if (_entityManager.TryGetComponent(uid, out var mindComp) && mindComp.Mind != null) + { + body = mindComp.Mind.OwnedEntity; + mind = mindComp.Mind; + EntitySystem.Get().OnGhostAttempt(mindComp.Mind, false); + } + + _audio.Play(filename: "/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg", playerFilter: Filter.Pvs(uid), coordinates: holoPos, false); + Popup.PopupCoordinates(popupDisappearOther, holoPos, Filter.PvsExcept(uid), false, PopupType.MediumCaution); + Popup.PopupCoordinates(popupDeathSelf, holoPos, uid, PopupType.LargeCaution); + _entityManager.DeleteEntity(uid); + + _adminLogger.Add(LogType.Unknown, LogImpact.Medium, $"{ToPrettyString(uid):mob} was disabled due to lack of projectors"); + + // var holopodQuery = _entityManager.EntityQuery(); + // while (true) + // { + // Logger.Info("Check"); + // foreach (var holopod in holopodQuery) + // { + // if (mind != null && TryHoloGenerate(holopod.Owner, mind, _entityManager.GetComponent(holopod.Owner))) + // { + // Logger.Warning("They got cloned!"); + // return; + // } + // } + // } + } + + + // public bool TryHoloGenerate(EntityUid uid, Mind.Mind mind, CloningPodComponent? clonePod) + // { + // CloningSystem cloneSys = new(); + // Logger.Info("Trying to clone"); + + // if (!Resolve(uid, ref clonePod)) + // return false; + + // if (HasComp(uid)) + // return false; + + // Logger.Info("Clone pod is active"); + + // if (ClonesWaitingForMind.TryGetValue(mind, out var clone)) + // { + // if (EntityManager.EntityExists(clone) && + // !_mobStateSystem.IsDead(clone) && + // TryComp(clone, out var cloneMindComp) && + // (cloneMindComp.Mind == null || cloneMindComp.Mind == mind)) + // return false; // Mind already has clone + + // ClonesWaitingForMind.Remove(mind); + // } + // Logger.Info("Waiting something something"); + + // if (mind.OwnedEntity != null && !_mobStateSystem.IsDead(mind.OwnedEntity.Value)) + // return false; // Body controlled by mind is not dead + // Logger.Info("Not alive still"); + + // // Yes, we still need to track down the client because we need to open the Eui + // if (mind.UserId == null || !_playerManager.TryGetSessionById(mind.UserId.Value, out var client)) + // return false; // If we can't track down the client, we can't offer transfer. That'd be quite bad. + // Logger.Warning("Got client"); + + // var pref = (HumanoidCharacterProfile) _prefs.GetPreferences(mind.UserId.Value).SelectedCharacter; + + // if (pref == null) + // return false; + // Logger.Warning("Got prefs"); + + // var mob = HoloFetchAndSpawn(clonePod, pref); + + // var cloneMindReturn = EntityManager.AddComponent(mob); + // cloneMindReturn.Mind = mind; + // cloneMindReturn.Parent = clonePod.Owner; + // clonePod.BodyContainer.Insert(mob); + // ClonesWaitingForMind.Add(mind, mob); + // _cloningSystem.UpdateStatus(CloningPodStatus.NoMind, clonePod); + // _euiManager.OpenEui(new AcceptCloningEui(mind, cloneSys), client); + + // AddComp(uid); + + // // TODO: Ideally, components like this should be on a mind entity so this isn't neccesary. + // // Remove this when 'mind entities' are added. + // // Add on special job components to the mob. + // if (mind.CurrentJob != null) + // { + // foreach (var special in mind.CurrentJob.Prototype.Special) + // { + // if (special is AddComponentSpecial) + // special.AfterEquip(mob); + // } + // } + + // return true; + // } + + + // /// + // /// Handles fetching the mob and any appearance stuff... + // /// + // private EntityUid HoloFetchAndSpawn(CloningPodComponent clonePod, HumanoidCharacterProfile pref) + // { + // List sexes = new(); + // var name = pref.Name; + // var toSpawn = "MobHologram"; + + // var mob = Spawn(toSpawn, Transform(clonePod.Owner).MapPosition); + // _humanoidSystem.LoadProfile(mob, pref); + + // MetaData(mob).EntityName = name; + // var mind = EnsureComp(mob); + // _mind.SetExamineInfo(mob, true, mind); + + // var grammar = EnsureComp(mob); + // grammar.ProperNoun = true; + // grammar.Gender = Robust.Shared.Enums.Gender.Neuter; + // Dirty(grammar); + + // RemComp(mob); + // EnsureComp(mob); + // EnsureComp(mob); + // RemComp(mob); + // RemComp(mob); + // RemComp(mob); + // RemComp(mob); + + // _tag.AddTag(mob, "DoorBumpOpener"); + + // return mob; + // } + + + + + // private void HoloTeleport(HoloTeleportEvent args) + // { + // if (args.Handled) return; + + // if HoloGetProjector(args.Target, args. ) + // var transform = Transform(args.Performer); + // if (transform.MapID != args.Target.GetMapId(EntityManager)) return; + + // _transformSystem.SetCoordinates(args.Performer, args.Target); + // transform.AttachToGridOrMap(); + + // _audio.PlayPvs(args.BlinkSound, args.Performer, AudioParams.Default.WithVolume(args.BlinkVolume)); + + // _staminaSystem.TakeStaminaDamage(args.Performer, 35); + + // args.Handled = true; + // } + + public struct HoloDataEntry { + public Mind.Mind Mind; + public HumanoidCharacterProfile Profile; + + public HoloDataEntry(Mind.Mind m, HumanoidCharacterProfile hcp) + { + Mind = m; + Profile = hcp; + } + } +} diff --git a/Content.Shared/SimpleStation14/Drone/HologramComponent.cs b/Content.Shared/SimpleStation14/Drone/HologramComponent.cs deleted file mode 100644 index 8eb8368530..0000000000 --- a/Content.Shared/SimpleStation14/Drone/HologramComponent.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Content.Shared.SimpleStation14.Hologram -{ - [RegisterComponent] - public sealed class HologramComponent : Component - { - [ViewVariables] - public EntityUid? CurProjector; - } -} diff --git a/Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs deleted file mode 100644 index 9570fbdefa..0000000000 --- a/Content.Shared/SimpleStation14/Drone/SharedHologramSystem.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Content.Shared.Interaction.Events; -using Content.Shared.Interaction.Components; -using Content.Shared.Damage; -using Content.Shared.Item; -using Content.Shared.Tag; - -namespace Content.Shared.SimpleStation14.Hologram -{ - public class SharedHologramSystem : EntitySystem - { - [Dependency] private readonly TagSystem _tagSystem = default!; - public override void Initialize() - { - SubscribeLocalEvent(OnInteractionAttempt); - } - - private void OnInteractionAttempt(EntityUid uid, HologramComponent component, InteractionAttemptEvent args) - { - if (args.Target == null) - return; - - if (TryComp(args.Target, out var dmg) && dmg.DamageContainerID == "Biological") - args.Cancel(); - - if (HasComp(args.Target) && !HasComp(args.Target) - && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight")) - args.Cancel(); - } - } -} diff --git a/Content.Shared/SimpleStation14/Holograms/HoloServerComponent b/Content.Shared/SimpleStation14/Holograms/HoloServerComponent new file mode 100644 index 0000000000..c8849b8cec --- /dev/null +++ b/Content.Shared/SimpleStation14/Holograms/HoloServerComponent @@ -0,0 +1,6 @@ +namespace Content.Server.SimpleStation14.Hologram; + +[RegisterComponent] +public sealed class HologramServerComponent : Component +{ +} diff --git a/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs b/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs new file mode 100644 index 0000000000..cf5977531a --- /dev/null +++ b/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs @@ -0,0 +1,12 @@ +namespace Content.Shared.SimpleStation14.Hologram; + +[RegisterComponent] +public sealed class HologramComponent : Component +{ + [ViewVariables] + public EntityUid? CurProjector; + + // Counter + [DataField("accumulator")] + public float Accumulator = 2f; +} diff --git a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs new file mode 100644 index 0000000000..015bc71fd5 --- /dev/null +++ b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs @@ -0,0 +1,27 @@ +// namespace Content.Shared.SimpleStation14.Hologram; + +// /// +// /// Raised when a hologram is being returned to its last visited projector. +// /// +// public sealed class HologramReturnEvent : EntityEventArgs +// { +// public HologramComponent Component; + +// public HologramReturnEvent(HologramComponent component) +// { +// Component = component; +// } +// } + +// /// +// /// Raised when a hologram is being killed and removed from the game world. +// /// +// public sealed class HologramKillEvent : EntityEventArgs +// { +// public HologramComponent Component; + +// public HologramKillEvent(HologramComponent component) +// { +// Component = component; +// } +// } diff --git a/Content.Shared/SimpleStation14/Holograms/HologramProjectorComponent.cs b/Content.Shared/SimpleStation14/Holograms/HologramProjectorComponent.cs new file mode 100644 index 0000000000..0bdcf59ba8 --- /dev/null +++ b/Content.Shared/SimpleStation14/Holograms/HologramProjectorComponent.cs @@ -0,0 +1,6 @@ +namespace Content.Shared.SimpleStation14.Hologram; + +[RegisterComponent] +public sealed class HologramProjectorComponent : Component +{ +} diff --git a/Content.Shared/SimpleStation14/Holograms/HolopodComponent.cs b/Content.Shared/SimpleStation14/Holograms/HolopodComponent.cs new file mode 100644 index 0000000000..21640ae990 --- /dev/null +++ b/Content.Shared/SimpleStation14/Holograms/HolopodComponent.cs @@ -0,0 +1,6 @@ +namespace Content.Server.SimpleStation14.Hologram; + +[RegisterComponent] +public sealed class HologramPodComponent : Component +{ +} diff --git a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs new file mode 100644 index 0000000000..e7e1bb8223 --- /dev/null +++ b/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs @@ -0,0 +1,67 @@ +using Content.Shared.Interaction.Events; +using Content.Shared.Interaction.Components; +using Content.Shared.Damage; +using Content.Shared.Item; +using Content.Shared.Tag; +using Content.Shared.Interaction.Helpers; +using Content.Shared.Popups; +using Robust.Shared.Player; +using Robust.Shared.Timing; +using Robust.Shared.Serialization; + +namespace Content.Shared.SimpleStation14.Hologram; + +public class SharedHologramSystem : EntitySystem +{ + [Dependency] private readonly TagSystem _tagSystem = default!; + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] protected readonly SharedPopupSystem Popup = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnEntInserted); + } + + // Stops the Hologram from interacting with anything they shouldn't. + private void OnInteractionAttempt(EntityUid uid, HologramComponent component, InteractionAttemptEvent args) + { + if (args.Target == null) + return; + + if (TryComp(args.Target, out var dmg) && dmg.DamageContainerID == "Biological") + args.Cancel(); + + if (HasComp(args.Target) && !HasComp(args.Target) + && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight")) + args.Cancel(); + } + + /// + /// Handle adding keys to the ignition, give stuff the InVehicleComponent so it can't be picked + /// up by people not in the vehicle. + /// + private void OnEntInserted(EntityUid uid, HologramServerComponent component, EntInsertedIntoContainerMessage args) + { + if (args.Container.ID != DiskSlot || + !_entityManager.TryGetComponent(args.Entity, out var disk)) return; + + TryHoloGenerate(component.Owner, disk.HoloData!, _entityManager.GetComponent(component.Owner)); + } +} + + +// [Serializable, NetSerializable] +// public sealed class HoloTeleportEvent : EntityEventArgs +// { +// public readonly EntityUid Uid; +// public readonly List Lights; + +// public ShadekinDarkenEvent(EntityUid uid, List lights) +// { +// Uid = uid; +// Lights = lights; +// } +// } diff --git a/Resources/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg b/Resources/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg new file mode 100644 index 0000000000000000000000000000000000000000..d764f43bb70207f4a780580ffaad1a3a05a48309 GIT binary patch literal 8815 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%0DA5iNaUWE$2`yfFit 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 PS|M2fW#Q8sLFj(~Gh>a% literal 0 HcmV?d00001 diff --git a/Resources/Locale/en-US/SimpleStation14/holograms.ftl b/Resources/Locale/en-US/SimpleStation14/holograms.ftl new file mode 100644 index 0000000000..bfc06b6ded --- /dev/null +++ b/Resources/Locale/en-US/SimpleStation14/holograms.ftl @@ -0,0 +1,4 @@ +system-hologram-phasing-appear-self = You materialize into being! +system-hologram-phasing-appear-others = {$name} materializes into being! +system-hologram-phasing-disappear-others = {$name} dematerializes in a fizz! +system-hologram-phasing-death-self = You faze out of being! diff --git a/Resources/Prototypes/Entities/Structures/Machines/cloning_machine.yml b/Resources/Prototypes/Entities/Structures/Machines/cloning_machine.yml index 12c179b953..2672048e49 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/cloning_machine.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/cloning_machine.yml @@ -4,6 +4,7 @@ name: cloning pod description: A Cloning Pod. 50% reliable. components: + - type: Holopod - type: CloningPod - type: DeviceList - type: DeviceNetwork diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/surveillance_camera.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/surveillance_camera.yml index 4773a59965..70fdfb5bac 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/surveillance_camera.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/surveillance_camera.yml @@ -4,6 +4,7 @@ name: camera description: A surveillance camera. It's watching you. Kinda. components: + - type: HologramProjector - type: Clickable - type: InteractionOutline - type: Construction diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml index 6591b441e3..005dc969c4 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml @@ -68,3 +68,76 @@ attributes: proper: true gender: male + +- type: entity + name: holo corgi + description: "A hologramatic projection of a corgi, computed by the AI and rendered by the station's cameras." + id: MobCorgiHolo22 + suffix: AI + components: + - type: LagCompensation + - type: Tag + tags: + - DoorBumpOpener + - type: InputMover + - type: MobMover + - type: HTN + rootTask: SimpleHostileCompound + - type: Input + context: "human" + - type: Faction + factions: + - Pet + - type: MovementSpeedModifier + baseWalkSpeed : 4.5 + baseSprintSpeed : 3 + - type: Sprite + noRot: true + drawdepth: Mobs + sprite: SimpleStation14/Mobs/Pets/corgi.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: holo_corgi + netsync: false + - type: Clickable + - type: InteractionOutline + - type: Physics + bodyType: KinematicController # Same for all inheritors + - type: Fixtures + fixtures: + - shape: + # Circles, cuz rotation of rectangles looks very bad + !type:PhysShapeCircle + radius: 0.35 + density: 50 + mask: + - MobMask + layer: + - MobLayer + - type: MobState + - type: Body + prototype: Animal + - type: Examiner + - type: Appearance + - type: RotationVisuals + - type: Actions + - type: DoAfter + - type: Polymorphable + - type: StandingState + - type: Alerts + - type: FloatingVisuals + - type: NoSlip + - type: TypingIndicator + proto: holo + - type: ReplacementAccent + accent: dog + - type: InteractionPopup + interactSuccessString: hugging-success-hologram-others + interactSuccessSound: + path: /Audio/SimpleStation14/Effects/Hologram/holo_on.ogg + - type: Grammar + attributes: + gender: epicene + - type: DogVision + - type: RandomBark + - type: Hologram diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml new file mode 100644 index 0000000000..3af21266fd --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml @@ -0,0 +1,135 @@ +# - type: entity +# id: HoloChamber +# parent: BaseMachinePowered +# name: holo pod +# description: A Cloning Pod. 50% reliable. +# components: +# - type: CloningPod +# - type: DeviceList +# - type: DeviceNetwork +# deviceNetId: Wired +# - type: Sprite +# netsync: false +# sprite: Structures/Machines/cloning.rsi +# snapCardinals: true +# layers: +# - state: pod_0 +# - type: Physics +# bodyType: Static +# - type: Fixtures +# fixtures: +# - shape: +# !type:PhysShapeAabb +# bounds: "-0.25,-0.5,0.25,0.5" +# density: 190 +# mask: +# - MachineMask +# layer: +# - MachineLayer +# - type: Construction +# graph: Machine +# node: machine +# containers: +# - machine_board +# - machine_parts +# - clonepod-bodyContainer +# - type: SignalReceiver +# inputs: +# CloningPodReceiver: [] +# - type: EmptyOnMachineDeconstruct +# containers: +# - clonepod-bodyContainer +# - type: Destructible +# thresholds: +# - trigger: +# !type:DamageTrigger +# damage: 100 +# behaviors: +# - !type:ChangeConstructionNodeBehavior +# node: machineFrame +# - !type:DoActsBehavior +# acts: ["Destruction"] +# - type: Machine +# board: CloningPodMachineCircuitboard +# - type: MaterialStorage +# materialWhiteList: +# - Biomass +# - type: Wires +# BoardName: "CloningPod" +# LayoutId: CloningPod +# - type: ApcPowerReceiver +# powerLoad: 200 #Receives most of its power from the console +# - type: Appearance +# visuals: +# - type: GenericEnumVisualizer +# key: enum.CloningPodVisuals.Status +# layer: 0 +# states: +# enum.CloningPodStatus.Cloning: pod_1 +# enum.CloningPodStatus.NoMind: pod_e +# enum.CloningPodStatus.Gore: pod_g +# enum.CloningPodStatus.Idle: pod_0 +# - type: Climbable +# - type: DynamicPrice +# price: 1000 +# - type: ContainerContainer +# containers: +# machine_board: !type:Container +# machine_parts: !type:Container +# clonepod-bodyContainer: !type:ContainerSlot + +- type: entity + id: HologramServer + parent: BaseMachinePowered + name: hologram server + description: Contains the collective knowledge of holo + components: + - type: Sprite + sprite: Structures/Machines/server.rsi + state: server + - type: ApcPowerReceiver + powerLoad: 200 + priority: Low + - type: ExtensionCableReceiver + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 300 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/metalbreak.ogg + - !type:SpawnEntitiesBehavior + spawn: + SheetSteel1: + min: 1 + max: 2 + - type: AmbientSound + volume: -9 + range: 5 + sound: + path: /Audio/Ambience/Objects/server_fans.ogg + - type: HologramServer + - type: ItemSlots + slots: + holo_disk: #this slot name is important + name: Disk + whitelist: + requireAll: true + components: + - HoloDisk + - type: CloningPod + +- type: entity + parent: BaseItem + id: HologramDisk + name: holo disk + description: A disk for the holo + components: + - type: Sprite + sprite: Objects/Specific/Research/researchdisk.rsi + state: icon + - tpye: HologramDisk diff --git a/Resources/Textures/SimpleStation14/Mobs/Pets/corgi.rsi/holo_corgi.png b/Resources/Textures/SimpleStation14/Mobs/Pets/corgi.rsi/holo_corgi.png new file mode 100644 index 0000000000000000000000000000000000000000..a85cc5e0a5c9ab2fd7d7d57d725f11de7006aaf6 GIT binary patch literal 12178 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 UoK{jqTL1t607*qoM6N<$g2|) Date: Fri, 24 Feb 2023 22:51:45 -0500 Subject: [PATCH 05/60] Committing more --- .../Holograms/Systems/HologramServerSystem.cs | 22 ++++++++++++------- .../Holograms/HoloServerComponent | 2 +- .../Holograms/HologramEvents.cs | 21 +++++++++++++++++- .../Holograms/SharedHologramSystem.cs | 6 +++-- .../Machines/hologram_constructor.yml | 3 +++ Resources/Prototypes/SimpleStation14/tags.yml | 2 ++ 6 files changed, 44 insertions(+), 12 deletions(-) diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs index c51dc0f9f3..e57586dec5 100644 --- a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs @@ -68,18 +68,24 @@ public override void Initialize() base.Initialize(); // SubscribeLocalEvent(OnEntInserted); SubscribeLocalEvent(OnAfterInteract); + SubscribeNetworkEvent(TryHoloGenerate); } - public bool TryHoloGenerate(EntityUid uid, Mind.Mind mind, CloningPodComponent? clonePod) + public void TryHoloGenerate(HologramDiskInsertedEvent args) { + var uid = args.ServerComponent.Owner; + var clonePod = _entityManager.GetComponent(uid); + var disk = _entityManager.GetComponent(args.Uid); + var mind = disk.HoloData!; + CloningSystem cloneSys = new(); Logger.Info("Trying to clone"); if (!Resolve(uid, ref clonePod)) - return false; + return; if (HasComp(uid)) - return false; + return; Logger.Info("Clone pod is active"); @@ -89,25 +95,25 @@ public bool TryHoloGenerate(EntityUid uid, Mind.Mind mind, CloningPodComponent? !_mobStateSystem.IsDead(clone) && TryComp(clone, out var cloneMindComp) && (cloneMindComp.Mind == null || cloneMindComp.Mind == mind)) - return false; // Mind already has clone + return; // Mind already has clone ClonesWaitingForMind.Remove(mind); } Logger.Info("Waiting something something"); if (mind.OwnedEntity != null && !_mobStateSystem.IsDead(mind.OwnedEntity.Value)) - return false; // Body controlled by mind is not dead + return; // Body controlled by mind is not dead Logger.Info("Not alive still"); // Yes, we still need to track down the client because we need to open the Eui if (mind.UserId == null || !_playerManager.TryGetSessionById(mind.UserId.Value, out var client)) - return false; // If we can't track down the client, we can't offer transfer. That'd be quite bad. + return; // If we can't track down the client, we can't offer transfer. That'd be quite bad. Logger.Info("Got client"); var pref = (HumanoidCharacterProfile) _prefs.GetPreferences(mind.UserId.Value).SelectedCharacter; if (pref == null) - return false; + return; Logger.Info("Got prefs"); var mob = HoloFetchAndSpawn(clonePod, pref); @@ -136,7 +142,7 @@ public bool TryHoloGenerate(EntityUid uid, Mind.Mind mind, CloningPodComponent? } } - return true; + return; } public void UpdateStatus(CloningPodStatus status, CloningPodComponent cloningPod) diff --git a/Content.Shared/SimpleStation14/Holograms/HoloServerComponent b/Content.Shared/SimpleStation14/Holograms/HoloServerComponent index c8849b8cec..e3c856b4ad 100644 --- a/Content.Shared/SimpleStation14/Holograms/HoloServerComponent +++ b/Content.Shared/SimpleStation14/Holograms/HoloServerComponent @@ -1,4 +1,4 @@ -namespace Content.Server.SimpleStation14.Hologram; +namespace Content.Shared.SimpleStation14.Hologram; [RegisterComponent] public sealed class HologramServerComponent : Component diff --git a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs index 015bc71fd5..79e6be8cf3 100644 --- a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs +++ b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs @@ -1,4 +1,7 @@ -// namespace Content.Shared.SimpleStation14.Hologram; +using Content.Shared.SimpleStation14.Hologram; +using Robust.Shared.Serialization; + +namespace Content.Shared.SimpleStation14.Hologram; // /// // /// Raised when a hologram is being returned to its last visited projector. @@ -25,3 +28,19 @@ // Component = component; // } // } + +/// +/// Raised when a hologram is being killed and removed from the game world. +/// +[Serializable, NetSerializable] +public sealed class HologramDiskInsertedEvent : EntityEventArgs +{ + public EntityUid Uid; + public HologramServerComponent ServerComponent; + + public HologramDiskInsertedEvent(EntityUid uid, HologramServerComponent serverComponent) + { + Uid = uid; + ServerComponent = serverComponent; + } +} diff --git a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs index e7e1bb8223..1ccb4f19d1 100644 --- a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs +++ b/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs @@ -8,6 +8,7 @@ using Robust.Shared.Player; using Robust.Shared.Timing; using Robust.Shared.Serialization; +using Robust.Shared.Containers; namespace Content.Shared.SimpleStation14.Hologram; @@ -19,6 +20,7 @@ public class SharedHologramSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] protected readonly SharedPopupSystem Popup = default!; [Dependency] private readonly IGameTiming _timing = default!; + private const string DiskSlot = "holo_disk"; public override void Initialize() { @@ -46,9 +48,9 @@ private void OnInteractionAttempt(EntityUid uid, HologramComponent component, In private void OnEntInserted(EntityUid uid, HologramServerComponent component, EntInsertedIntoContainerMessage args) { if (args.Container.ID != DiskSlot || - !_entityManager.TryGetComponent(args.Entity, out var disk)) return; + !_tagSystem.HasTag(args.Entity, "HoloDisk")) return; - TryHoloGenerate(component.Owner, disk.HoloData!, _entityManager.GetComponent(component.Owner)); + RaiseNetworkEvent(new HologramDiskInsertedEvent(uid, component)); } } diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml index 3af21266fd..2913f6dce7 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml @@ -133,3 +133,6 @@ sprite: Objects/Specific/Research/researchdisk.rsi state: icon - tpye: HologramDisk + - type: Tag + tags: + - HoloDisk diff --git a/Resources/Prototypes/SimpleStation14/tags.yml b/Resources/Prototypes/SimpleStation14/tags.yml index 03b82cba50..c134d41ab2 100644 --- a/Resources/Prototypes/SimpleStation14/tags.yml +++ b/Resources/Prototypes/SimpleStation14/tags.yml @@ -6,3 +6,5 @@ - type: Tag id: Hardlight +- type: Tag + id: HoloDisk From 3e53704ddfa09e4395237f99f7d908525b6e1a95 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sun, 26 Feb 2023 14:00:50 -0500 Subject: [PATCH 06/60] More work on Holograms. Moved most things over to events, bug where hologram is deleted upon spawning and crashes as no hologram component is found? --- .../Holograms/HologramSystem.cs | 35 +++ .../Holograms/Components/HoloDiskComponent.cs | 2 +- .../Holograms/Systems/HologramServerSystem.cs | 244 +++++++++++------ .../Holograms/Systems/HologramSystem.cs | 245 +++++------------- ...ServerComponent => HoloServerComponent.cs} | 2 + .../Holograms/HologramComponent.cs | 3 + .../Holograms/HologramEvents.cs | 80 +++--- .../Holograms/SharedHologramSystem.cs | 80 +++++- .../Machines/Computers/computers.yml | 4 + .../Structures/Machines/cloning_machine.yml | 1 - .../Machines/wireless_surveillance_camera.yml | 1 + .../Entities/Mobs/Player/hologram.yml | 18 +- .../Machines/hologram_constructor.yml | 89 ++++--- 13 files changed, 448 insertions(+), 356 deletions(-) create mode 100644 Content.Client/SimpleStation14/Holograms/HologramSystem.cs rename Content.Shared/SimpleStation14/Holograms/{HoloServerComponent => HoloServerComponent.cs} (69%) diff --git a/Content.Client/SimpleStation14/Holograms/HologramSystem.cs b/Content.Client/SimpleStation14/Holograms/HologramSystem.cs new file mode 100644 index 0000000000..ff175a12ce --- /dev/null +++ b/Content.Client/SimpleStation14/Holograms/HologramSystem.cs @@ -0,0 +1,35 @@ +// using Content.Client.Gravity; +// using Content.Shared.Anomaly; +// using Content.Shared.Anomaly.Components; +// using Robust.Client.GameObjects; +// using Robust.Shared.Timing; +// using Content.Shared.SimpleStation14.Hologram; + +// namespace Content.Client.SimpleStation14.Hologram; + +// public sealed class HologramSystem : SharedHologramSystem +// { +// [Dependency] private readonly IGameTiming _timing = default!; +// [Dependency] private readonly FloatingVisualizerSystem _floating = default!; + +// /// +// public override void Initialize() +// { +// base.Initialize(); + +// SubscribeLocalEvent(OnStartup); +// SubscribeLocalEvent(OnAnimationComplete); +// } + +// private void OnStartup(EntityUid uid, HologramComponent component, ref ComponentStartup args) +// { +// _floating.FloatAnimation(uid, new Vector2(0f, 0.07f), "holofloat", 3); +// } + +// private void OnAnimationComplete(EntityUid uid, HologramComponent component, AnimationCompletedEvent args) +// { +// if (args.Key != "holofloat") +// return; +// _floating.FloatAnimation(uid, new Vector2(0, 0.15f), "holofloat", 3.5f); +// } +// } diff --git a/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs b/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs index b54d977719..d9ea85a6e8 100644 --- a/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs +++ b/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs @@ -1,4 +1,4 @@ -using static Content.Server.SimpleStation14.Hologram.HologramSystem; +// using static Content.Server.SimpleStation14.Hologram.HologramSystem; namespace Content.Server.SimpleStation14.Hologram; diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs index e57586dec5..cb5329b3f1 100644 --- a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs @@ -1,28 +1,7 @@ -using Content.Server.SurveillanceCamera; -using Content.Server.GameTicking; +using System.Linq; using Content.Server.Mind.Components; -using Content.Shared.Tag; -using Content.Shared.Popups; -using Content.Shared.Interaction.Helpers; -using Content.Shared.SimpleStation14.Hologram; -using Content.Shared.Actions; -using Content.Shared.Actions.ActionTypes; -using Content.Shared.Pulling; -using Content.Shared.Pulling.Components; -using Content.Shared.Administration.Logs; -using Content.Shared.Database; -using Robust.Server.Player; -using Robust.Shared.Player; -using Robust.Shared.Timing; -using Robust.Shared.Map; -using Robust.Shared.Prototypes; using Content.Server.Cloning; using Content.Server.Cloning.Components; - -using Content.Shared.Cloning; -using Content.Shared.Speech; -using Content.Shared.Preferences; -using Content.Shared.Emoting; using Content.Server.Psionics; using Content.Server.Speech.Components; using Content.Server.StationEvents.Components; @@ -32,12 +11,28 @@ using Content.Server.Jobs; using Content.Server.Mind; using Content.Server.Preferences.Managers; +using Content.Server.Power.Components; +using Content.Server.Administration.Commands; +using Content.Shared.Tag; +using Content.Shared.Popups; +using Content.Shared.SimpleStation14.Hologram; +using Content.Shared.Pulling; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.Speech; +using Content.Shared.Preferences; +using Content.Shared.Emoting; using Content.Shared.Humanoid; using Content.Shared.Mobs.Systems; -using Robust.Shared.GameObjects.Components.Localization; -using System.Linq; -using Robust.Shared.Containers; using Content.Shared.Interaction; +using Content.Shared.Inventory; +using Content.Shared.Interaction.Components; +using Content.Shared.Access.Components; +using Content.Shared.Clothing.Components; +using Robust.Server.Player; +using Robust.Shared.Player; +using Robust.Shared.Containers; +using Robust.Shared.GameObjects.Components.Localization; namespace Content.Server.SimpleStation14.Hologram; @@ -59,6 +54,7 @@ public class HologramServerSystem : EntitySystem [Dependency] private readonly IServerPreferencesManager _prefs = default!; [Dependency] private readonly TagSystem _tagSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly InventorySystem _inventory = default!; private const string DiskSlot = "holo_disk"; public readonly Dictionary ClonesWaitingForMind = new(); @@ -66,28 +62,91 @@ public class HologramServerSystem : EntitySystem public override void Initialize() { base.Initialize(); - // SubscribeLocalEvent(OnEntInserted); + SubscribeLocalEvent(OnEntInserted); + SubscribeLocalEvent(OnEntRemoved); SubscribeLocalEvent(OnAfterInteract); - SubscribeNetworkEvent(TryHoloGenerate); + SubscribeLocalEvent(OnPowerChanged); } - public void TryHoloGenerate(HologramDiskInsertedEvent args) + /// + /// Handles generating a hologram from an inserted disk + /// + private void OnEntInserted(EntityUid uid, HologramServerComponent component, EntInsertedIntoContainerMessage args) { - var uid = args.ServerComponent.Owner; - var clonePod = _entityManager.GetComponent(uid); - var disk = _entityManager.GetComponent(args.Uid); - var mind = disk.HoloData!; + if (args.Container.ID != DiskSlot || !_tagSystem.HasTag(args.Entity, "HoloDisk") || + (_entityManager.TryGetComponent(args.Entity, out var diskComp) && diskComp.HoloData == null)) return; - CloningSystem cloneSys = new(); - Logger.Info("Trying to clone"); + if (component.LinkedHologram != EntityUid.Invalid && _entityManager.EntityExists(component.LinkedHologram)) + { + RaiseLocalEvent(new HologramKillEvent(component.LinkedHologram.Value)); + } - if (!Resolve(uid, ref clonePod)) - return; + if (TryHoloGenerate(component.Owner, _entityManager.GetComponent(args.Entity).HoloData!, component, out var holo)) + { + var holoComp = _entityManager.GetComponent(holo); + component.LinkedHologram = holo; + holoComp.LinkedServer = component.Owner; + } + } - if (HasComp(uid)) - return; + /// + /// Handles killing a hologram when a disk is removed + /// + private void OnEntRemoved(EntityUid uid, HologramServerComponent component, EntRemovedFromContainerMessage args) + { + if (args.Container.ID != DiskSlot || !_tagSystem.HasTag(args.Entity, "HoloDisk") || + (_entityManager.TryGetComponent(args.Entity, out var diskComp) && diskComp.HoloData == null)) return; + + if (component.LinkedHologram != EntityUid.Invalid && _entityManager.EntityExists(component.LinkedHologram)) + { + RaiseLocalEvent(new HologramKillEvent(component.LinkedHologram.Value)); + } + } + + /// + /// Called when the server's power state changes + /// + /// The entity uid of the server + /// The HologramServerComponent + /// The PowerChangedEvent + private void OnPowerChanged(EntityUid uid, HologramServerComponent component, ref PowerChangedEvent args) + { + // If the server is no longer powered + if (!args.Powered && component.LinkedHologram != null && component.LinkedHologram != EntityUid.Invalid) + { + // If the hologram exists + if (component != null && _entityManager.EntityExists(component.LinkedHologram)) + { + // Kill the Holgram + RaiseLocalEvent(new HologramKillEvent(component.LinkedHologram.Value)); + } + } + // If the server is powered + else if (args.Powered && component.LinkedHologram == EntityUid.Invalid) + { + var serverContainer = _entityManager.GetComponent(component.Owner); + if (serverContainer.GetContainer(DiskSlot).ContainedEntities.Count <= 0) + { + return; // No disk in the server + } + var disk = serverContainer.GetContainer(DiskSlot).ContainedEntities.First(); + var diskData = _entityManager.GetComponent(disk).HoloData; - Logger.Info("Clone pod is active"); + // If the hologram is generated successfully + if (diskData != null && TryHoloGenerate(component.Owner, diskData, component, out var holo)) + { + // Set the linked hologram to the generated hologram + var holoComp = _entityManager.GetComponent(holo); + component.LinkedHologram = holo; + holoComp.LinkedServer = component.Owner; + } + } + } + + public bool TryHoloGenerate(EntityUid uid, Mind.Mind mind, HologramServerComponent? holoServer, out EntityUid holo) + { + CloningSystem cloneSys = new(); + holo = EntityUid.Invalid; if (ClonesWaitingForMind.TryGetValue(mind, out var clone)) { @@ -95,44 +154,30 @@ public void TryHoloGenerate(HologramDiskInsertedEvent args) !_mobStateSystem.IsDead(clone) && TryComp(clone, out var cloneMindComp) && (cloneMindComp.Mind == null || cloneMindComp.Mind == mind)) - return; // Mind already has clone + return false; // Mind already has clone ClonesWaitingForMind.Remove(mind); } - Logger.Info("Waiting something something"); - if (mind.OwnedEntity != null && !_mobStateSystem.IsDead(mind.OwnedEntity.Value)) - return; // Body controlled by mind is not dead - Logger.Info("Not alive still"); + if (mind.OwnedEntity != null && (_mobStateSystem.IsAlive(mind.OwnedEntity.Value) || _mobStateSystem.IsCritical(mind.OwnedEntity.Value))) + return false; // Body controlled by mind is not dead // Yes, we still need to track down the client because we need to open the Eui if (mind.UserId == null || !_playerManager.TryGetSessionById(mind.UserId.Value, out var client)) - return; // If we can't track down the client, we can't offer transfer. That'd be quite bad. - Logger.Info("Got client"); + return false; // If we can't track down the client, we can't offer transfer. That'd be quite bad. var pref = (HumanoidCharacterProfile) _prefs.GetPreferences(mind.UserId.Value).SelectedCharacter; if (pref == null) - return; - Logger.Info("Got prefs"); + return false; - var mob = HoloFetchAndSpawn(clonePod, pref); + var mob = HoloFetchAndSpawn(holoServer!, pref); var cloneMindReturn = EntityManager.AddComponent(mob); cloneMindReturn.Mind = mind; - cloneMindReturn.Parent = clonePod.Owner; - // clonePod.BodyContainer.Insert(mob); ClonesWaitingForMind.Add(mind, mob); - UpdateStatus(CloningPodStatus.NoMind, clonePod); - _euiManager.OpenEui(new AcceptCloningEui(mind, cloneSys), client); - - Logger.Warning("Cloned"); + TransferMindToClone(mind); - AddComp(uid); - - // TODO: Ideally, components like this should be on a mind entity so this isn't neccesary. - // Remove this when 'mind entities' are added. - // Add on special job components to the mob. if (mind.CurrentJob != null) { foreach (var special in mind.CurrentJob.Prototype.Special) @@ -140,26 +185,69 @@ public void TryHoloGenerate(HologramDiskInsertedEvent args) if (special is AddComponentSpecial) special.AfterEquip(mob); } + + // Get each access from the job prototype and add it to the mob + foreach (var access in mind.CurrentJob.Prototype.Access) + { + var accessComp = EntityManager.EnsureComponent(mob); + accessComp.Tags.Add(access); + } + + // Get the loadout from the job prototype and add it to the Hologram + // making each item unremovable and hardlight. + if (mind.CurrentJob.Prototype.StartingGear != null) + { + SetOutfitCommand.SetOutfit(mob, mind.CurrentJob.Prototype.StartingGear, _entityManager, (_, item) => + { + if (_entityManager.TryGetComponent(item, out var clothing)) + { + if (clothing.InSlot == "back" || clothing.InSlot == "pocket1" || clothing.InSlot == "pocket2" || + clothing.InSlot == "belt" || clothing.InSlot == "suitstorage" || clothing.InSlot == "id") + { + _entityManager.DeleteEntity(item); + return; + } + } + _tagSystem.AddTag(item, "Hardlight"); + _entityManager.EnsureComponent(item); + }); + } + } - return; + _adminLogger.Add(LogType.Unknown, LogImpact.Medium, + $"{ToPrettyString(mob):mob} was generated at {ToPrettyString((EntityUid) uid):entity}"); + + holo = mob; + return true; } - public void UpdateStatus(CloningPodStatus status, CloningPodComponent cloningPod) + internal void TransferMindToClone(Mind.Mind mind) { - cloningPod.Status = status; + if (!ClonesWaitingForMind.TryGetValue(mind, out var entity) || + !EntityManager.EntityExists(entity) || + !TryComp(entity, out var mindComp) || + mindComp.Mind != null) + return; + + mind.TransferTo(entity, ghostCheckOverride: true); + mind.UnVisit(); + ClonesWaitingForMind.Remove(mind); } /// /// Handles fetching the mob and any appearance stuff... /// - private EntityUid HoloFetchAndSpawn(CloningPodComponent clonePod, HumanoidCharacterProfile pref) + private EntityUid HoloFetchAndSpawn(HologramServerComponent holoServer, HumanoidCharacterProfile pref) { + List sexes = new(); var name = pref.Name; var toSpawn = "MobHologram"; - var mob = Spawn(toSpawn, Transform(clonePod.Owner).MapPosition); + var mob = Spawn(toSpawn, Transform(holoServer.Owner).MapPosition); + _entityManager.GetComponent(mob).AttachToGridOrMap(); + _humanoidSystem.LoadProfile(mob, pref); MetaData(mob).EntityName = name; @@ -171,27 +259,35 @@ private EntityUid HoloFetchAndSpawn(CloningPodComponent clonePod, HumanoidCharac grammar.Gender = Robust.Shared.Enums.Gender.Neuter; Dirty(grammar); - RemComp(mob); + var meta = _entityManager.GetComponent(mob); + var popupAppearOther = Loc.GetString("system-hologram-phasing-appear-others", ("name", meta.EntityName)); + var popupAppearSelf = Loc.GetString("system-hologram-phasing-appear-self"); + + Popup.PopupEntity(popupAppearOther, mob, Filter.PvsExcept((EntityUid) mob), false, PopupType.Medium); + Popup.PopupEntity(popupAppearSelf, mob, mob, PopupType.Large); + _audio.PlayPvs("/Audio/SimpleStation14/Effects/Hologram/holo_on.ogg", mob); + EnsureComp(mob); EnsureComp(mob); - RemComp(mob); - RemComp(mob); - RemComp(mob); - RemComp(mob); + EnsureComp(mob); + RemComp(mob); _tag.AddTag(mob, "DoorBumpOpener"); return mob; } - private void OnAfterInteract(EntityUid uid, HologramDiskComponent component, AfterInteractEvent args) { - if (args.Target == null || !TryComp(args.Target, out var targetMind) || targetMind.Mind == null) + if (args.Target == null || !TryComp(args.Target, out var targetMind)) + return; + if (targetMind.Mind == null) + { + Popup.PopupEntity(Loc.GetString("system-hologram-disk-mind-none"), args.Target.Value, args.User); return; + } component.HoloData = targetMind.Mind; - Popup.PopupEntity(Loc.GetString("Data saved, boi"), args.Target.Value, args.User); + Popup.PopupEntity(Loc.GetString("system-hologram-disk-mind-saved"), args.Target.Value, args.User); } - } diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs index 4fd0b09e3d..9365401a60 100644 --- a/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs @@ -36,6 +36,7 @@ using Content.Shared.Mobs.Systems; using Robust.Shared.GameObjects.Components.Localization; using System.Linq; +using Robust.Shared.Utility; namespace Content.Server.SimpleStation14.Hologram; @@ -61,6 +62,8 @@ public class HologramSystem : EntitySystem public override void Initialize() { base.Initialize(); + SubscribeAllEvent(HoloKill); + SubscribeAllEvent(HoloGetProjector); // SubscribeLocalEvent(Startup); // SubscribeLocalEvent(Shutdown); // SubscribeLocalEvent(HoloTeleport); @@ -86,17 +89,56 @@ public override void Update(float frameTime) foreach (var component in _entityManager.EntityQuery().ToList()) { - var projector = HoloGetProjector(component); - if (projector == EntityUid.Invalid) + var projectorEvent = new HologramGetProjectorEvent(component.Owner); + RaiseLocalEvent(component.Owner, projectorEvent); + Logger.DebugS("holo", "Hologram {0} has projector {1}", component.Owner, projectorEvent.Projector); + if (projectorEvent.Projector == EntityUid.Invalid || !projectorEvent.Projector.IsValid()) { - HoloReturn(component); + RaiseNetworkEvent(new HologramReturnEvent(component.Owner)); + Logger.Debug("wawawah"); continue; } - component.CurProjector = projector; + component.CurProjector = projectorEvent.Projector; } } + /// + /// Tests for the nearest projector to the Hologram. + /// + /// Event arguments. + public void HoloGetProjector(HologramGetProjectorEvent args) + { + var uid = args.Hologram; + var component = _entityManager.GetComponent(uid); + var occlude = args.Occlude; + var range = args.Range; + + var xformQuery = GetEntityQuery(); + var transform = _entityManager.GetComponent(uid); + var playerPos = _transform.GetWorldPosition(transform, xformQuery); + var mapId = transform.MapID; + + // sort all entities in distance increasing order + var nearProjList = new SortedList(); + + foreach (var comp in _entityManager.EntityQuery()) + { + if (!xformQuery.TryGetComponent(comp.Owner, out var compXform) || compXform.MapID != mapId) + continue; + + var dist = (_transform.GetWorldPosition(compXform, xformQuery) - playerPos).LengthSquared; + nearProjList.TryAdd(dist, comp.Owner); + } + foreach (var nearProj in nearProjList) + { + if (_entityManager.TryGetComponent(nearProj.Value, out var camComp) && !camComp.Active) continue; + if (occlude && !nearProj.Value.InRangeUnOccluded(uid, 18f)) continue; + args.Projector = nearProj.Value; + return; + } + return; + } /// /// Tests for the nearest projector to the Hologram. @@ -105,7 +147,7 @@ public override void Update(float frameTime) /// Should it check only for unoccluded and in range projectors? /// The range it should check for projectors in, if occlude is true /// Returns the UID of the projector, or invalid UID if no projectors are found. - private EntityUid HoloGetProjector(HologramComponent component, bool occlude = true, float range = 18f) + public EntityUid HoloGetProjector(HologramComponent component, bool occlude = true, float range = 18f) { var xformQuery = GetEntityQuery(); var uid = component.Owner; @@ -142,7 +184,7 @@ private EntityUid HoloGetProjector(HologramComponent component, bool occlude = t /// Should it check only for unoccluded and in range projectors? /// The range it should check for projectors in, if occlude is true /// Returns the UID of the projector, or invalid UID if no projectors are found. - private EntityUid HoloGetProjector(Vector2 coords, MapId mapId, bool occlude = true, float range = 18f) + public EntityUid HoloGetProjector(Vector2 coords, MapId mapId, bool occlude = true, float range = 18f) { var xformQuery = GetEntityQuery(); @@ -167,60 +209,14 @@ private EntityUid HoloGetProjector(Vector2 coords, MapId mapId, bool occlude = t return EntityUid.Invalid; } - - /// - /// Handles returning a Hologram to their last visited projector, - /// then to the nearest, finally killing them if none are found. - /// - /// Hologram's HologramComponent. - private void HoloReturn(HologramComponent component) - { - var uid = component.Owner; - var meta = _entityManager.GetComponent(uid); - var holoPos = _entityManager.GetComponent(uid).Coordinates; - - var popupAppearOther = Loc.GetString("system-hologram-phasing-appear-others", ("name", meta.EntityName)); - var popupAppearSelf = Loc.GetString("system-hologram-phasing-appear-self"); - var popupDisappearOther = Loc.GetString("system-hologram-phasing-disappear-others", ("name", meta.EntityName)); - var popupDeathSelf = Loc.GetString("system-hologram-phasing-death-self"); - - if (component.CurProjector == null || !_entityManager.TryGetComponent(component.CurProjector, out var _) || - (_entityManager.TryGetComponent(component.CurProjector, out var camComp) && !camComp.Active)) - { - component.CurProjector = HoloGetProjector(component, false); - } - - if (component.CurProjector == EntityUid.Invalid) - { - - HoloKill(component); - return; - } - _entityManager.TryGetComponent(component.CurProjector, out var transfComp); - - Popup.PopupEntity(popupAppearOther, uid, Filter.PvsExcept((EntityUid) uid), false, PopupType.Medium); - Popup.PopupCoordinates(popupDisappearOther, holoPos, Filter.PvsExcept(uid), false, PopupType.MediumCaution); - _audio.Play(filename: "/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg", playerFilter: Filter.Pvs(uid), coordinates: holoPos, false); - if (TryComp(uid, out var pullable) && pullable.BeingPulled) _pulling.TryStopPull(pullable); - if (TryComp(uid, out var pulling) && pulling.Pulling != null && - TryComp(pulling.Pulling.Value, out var subjectPulling)) _pulling.TryStopPull(subjectPulling); - // Move holo - Transform(uid).Coordinates = _entityManager.GetComponent((EntityUid) component.CurProjector).Coordinates; - Popup.PopupEntity(popupAppearSelf, uid, uid, PopupType.Large); - _audio.PlayPvs("/Audio/SimpleStation14/Effects/Hologram/holo_on.ogg", uid); - - _adminLogger.Add(LogType.Unknown, LogImpact.Low, - $"{ToPrettyString(uid):mob} was returned to projector {ToPrettyString((EntityUid) component.CurProjector):entity}"); - } - /// /// Kills a Hologram after playing the visual and auditory effects. /// /// Hologram's HologramComponent. - - private void HoloKill(HologramComponent component) + public void HoloKill(HologramKillEvent args) { - var uid = component.Owner; + var uid = args.Uid; + var component = _entityManager.GetComponent(uid); var meta = _entityManager.GetComponent(uid); var holoPos = _entityManager.GetComponent(uid).Coordinates; EntityUid? body = EntityUid.Invalid; @@ -241,131 +237,18 @@ private void HoloKill(HologramComponent component) _audio.Play(filename: "/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg", playerFilter: Filter.Pvs(uid), coordinates: holoPos, false); Popup.PopupCoordinates(popupDisappearOther, holoPos, Filter.PvsExcept(uid), false, PopupType.MediumCaution); Popup.PopupCoordinates(popupDeathSelf, holoPos, uid, PopupType.LargeCaution); + if (component.LinkedServer != EntityUid.Invalid) + { + if (_entityManager.TryGetComponent(component.LinkedServer!.Value, out var serverComp)) + serverComp.LinkedHologram = EntityUid.Invalid; + component.LinkedServer = EntityUid.Invalid; + } + _entityManager.DeleteEntity(uid); _adminLogger.Add(LogType.Unknown, LogImpact.Medium, $"{ToPrettyString(uid):mob} was disabled due to lack of projectors"); - - // var holopodQuery = _entityManager.EntityQuery(); - // while (true) - // { - // Logger.Info("Check"); - // foreach (var holopod in holopodQuery) - // { - // if (mind != null && TryHoloGenerate(holopod.Owner, mind, _entityManager.GetComponent(holopod.Owner))) - // { - // Logger.Warning("They got cloned!"); - // return; - // } - // } - // } } - - // public bool TryHoloGenerate(EntityUid uid, Mind.Mind mind, CloningPodComponent? clonePod) - // { - // CloningSystem cloneSys = new(); - // Logger.Info("Trying to clone"); - - // if (!Resolve(uid, ref clonePod)) - // return false; - - // if (HasComp(uid)) - // return false; - - // Logger.Info("Clone pod is active"); - - // if (ClonesWaitingForMind.TryGetValue(mind, out var clone)) - // { - // if (EntityManager.EntityExists(clone) && - // !_mobStateSystem.IsDead(clone) && - // TryComp(clone, out var cloneMindComp) && - // (cloneMindComp.Mind == null || cloneMindComp.Mind == mind)) - // return false; // Mind already has clone - - // ClonesWaitingForMind.Remove(mind); - // } - // Logger.Info("Waiting something something"); - - // if (mind.OwnedEntity != null && !_mobStateSystem.IsDead(mind.OwnedEntity.Value)) - // return false; // Body controlled by mind is not dead - // Logger.Info("Not alive still"); - - // // Yes, we still need to track down the client because we need to open the Eui - // if (mind.UserId == null || !_playerManager.TryGetSessionById(mind.UserId.Value, out var client)) - // return false; // If we can't track down the client, we can't offer transfer. That'd be quite bad. - // Logger.Warning("Got client"); - - // var pref = (HumanoidCharacterProfile) _prefs.GetPreferences(mind.UserId.Value).SelectedCharacter; - - // if (pref == null) - // return false; - // Logger.Warning("Got prefs"); - - // var mob = HoloFetchAndSpawn(clonePod, pref); - - // var cloneMindReturn = EntityManager.AddComponent(mob); - // cloneMindReturn.Mind = mind; - // cloneMindReturn.Parent = clonePod.Owner; - // clonePod.BodyContainer.Insert(mob); - // ClonesWaitingForMind.Add(mind, mob); - // _cloningSystem.UpdateStatus(CloningPodStatus.NoMind, clonePod); - // _euiManager.OpenEui(new AcceptCloningEui(mind, cloneSys), client); - - // AddComp(uid); - - // // TODO: Ideally, components like this should be on a mind entity so this isn't neccesary. - // // Remove this when 'mind entities' are added. - // // Add on special job components to the mob. - // if (mind.CurrentJob != null) - // { - // foreach (var special in mind.CurrentJob.Prototype.Special) - // { - // if (special is AddComponentSpecial) - // special.AfterEquip(mob); - // } - // } - - // return true; - // } - - - // /// - // /// Handles fetching the mob and any appearance stuff... - // /// - // private EntityUid HoloFetchAndSpawn(CloningPodComponent clonePod, HumanoidCharacterProfile pref) - // { - // List sexes = new(); - // var name = pref.Name; - // var toSpawn = "MobHologram"; - - // var mob = Spawn(toSpawn, Transform(clonePod.Owner).MapPosition); - // _humanoidSystem.LoadProfile(mob, pref); - - // MetaData(mob).EntityName = name; - // var mind = EnsureComp(mob); - // _mind.SetExamineInfo(mob, true, mind); - - // var grammar = EnsureComp(mob); - // grammar.ProperNoun = true; - // grammar.Gender = Robust.Shared.Enums.Gender.Neuter; - // Dirty(grammar); - - // RemComp(mob); - // EnsureComp(mob); - // EnsureComp(mob); - // RemComp(mob); - // RemComp(mob); - // RemComp(mob); - // RemComp(mob); - - // _tag.AddTag(mob, "DoorBumpOpener"); - - // return mob; - // } - - - - // private void HoloTeleport(HoloTeleportEvent args) // { // if (args.Handled) return; @@ -383,15 +266,5 @@ private void HoloKill(HologramComponent component) // args.Handled = true; // } - - public struct HoloDataEntry { - public Mind.Mind Mind; - public HumanoidCharacterProfile Profile; - - public HoloDataEntry(Mind.Mind m, HumanoidCharacterProfile hcp) - { - Mind = m; - Profile = hcp; - } - } + // } } diff --git a/Content.Shared/SimpleStation14/Holograms/HoloServerComponent b/Content.Shared/SimpleStation14/Holograms/HoloServerComponent.cs similarity index 69% rename from Content.Shared/SimpleStation14/Holograms/HoloServerComponent rename to Content.Shared/SimpleStation14/Holograms/HoloServerComponent.cs index e3c856b4ad..14684df47b 100644 --- a/Content.Shared/SimpleStation14/Holograms/HoloServerComponent +++ b/Content.Shared/SimpleStation14/Holograms/HoloServerComponent.cs @@ -3,4 +3,6 @@ namespace Content.Shared.SimpleStation14.Hologram; [RegisterComponent] public sealed class HologramServerComponent : Component { + [ViewVariables] + public EntityUid? LinkedHologram; } diff --git a/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs b/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs index cf5977531a..a1c90baa63 100644 --- a/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs +++ b/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs @@ -3,6 +3,9 @@ namespace Content.Shared.SimpleStation14.Hologram; [RegisterComponent] public sealed class HologramComponent : Component { + [ViewVariables] + public EntityUid? LinkedServer; + [ViewVariables] public EntityUid? CurProjector; diff --git a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs index 79e6be8cf3..8d58c49254 100644 --- a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs +++ b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs @@ -3,44 +3,66 @@ namespace Content.Shared.SimpleStation14.Hologram; -// /// -// /// Raised when a hologram is being returned to its last visited projector. -// /// -// public sealed class HologramReturnEvent : EntityEventArgs -// { -// public HologramComponent Component; - -// public HologramReturnEvent(HologramComponent component) -// { -// Component = component; -// } -// } - -// /// -// /// Raised when a hologram is being killed and removed from the game world. -// /// -// public sealed class HologramKillEvent : EntityEventArgs -// { -// public HologramComponent Component; - -// public HologramKillEvent(HologramComponent component) -// { -// Component = component; -// } -// } +/// +/// Raised when a hologram is being returned to its last visited projector. +/// +[Serializable, NetSerializable] +public sealed class HologramReturnEvent : EntityEventArgs +{ + public EntityUid Uid; + + public HologramReturnEvent(EntityUid uid) + { + Uid = uid; + } +} /// /// Raised when a hologram is being killed and removed from the game world. /// [Serializable, NetSerializable] -public sealed class HologramDiskInsertedEvent : EntityEventArgs +public sealed class HologramKillEvent : EntityEventArgs { public EntityUid Uid; - public HologramServerComponent ServerComponent; - public HologramDiskInsertedEvent(EntityUid uid, HologramServerComponent serverComponent) + public HologramKillEvent(EntityUid uid) { Uid = uid; - ServerComponent = serverComponent; + } +} + +/// +/// Raised to return a bool if a given projector is valid for a given hologram. +/// +[Serializable, NetSerializable] +public sealed class HologramProjectorValidEvent : EntityEventArgs +{ + public EntityUid Hologram; + public EntityUid Projector; + public bool Valid = false; + + public HologramProjectorValidEvent(EntityUid hologram, EntityUid projector) + { + Hologram = hologram; + Projector = projector; + } +} + +/// +/// Raised to return the nearest projector to a given hologram. +/// +[Serializable, NetSerializable] +public sealed class HologramGetProjectorEvent : EntityEventArgs +{ + public EntityUid Hologram; + public bool Occlude; + public float Range; + public EntityUid Projector; + + public HologramGetProjectorEvent(EntityUid hologram, bool occlude = true, float range = 18f) + { + Hologram = hologram; + Occlude = occlude; + Range = range; } } diff --git a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs index 1ccb4f19d1..375654032d 100644 --- a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs +++ b/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs @@ -9,6 +9,11 @@ using Robust.Shared.Timing; using Robust.Shared.Serialization; using Robust.Shared.Containers; +using Content.Shared.Computer; +using Content.Shared.Pulling.Components; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.Pulling; namespace Content.Shared.SimpleStation14.Hologram; @@ -20,11 +25,14 @@ public class SharedHologramSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] protected readonly SharedPopupSystem Popup = default!; [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SharedPullingSystem _pulling = default!; private const string DiskSlot = "holo_disk"; public override void Initialize() { - SubscribeLocalEvent(OnEntInserted); + SubscribeLocalEvent(OnInteractionAttempt); + SubscribeNetworkEvent(HoloReturn); } // Stops the Hologram from interacting with anything they shouldn't. @@ -33,24 +41,70 @@ private void OnInteractionAttempt(EntityUid uid, HologramComponent component, In if (args.Target == null) return; - if (TryComp(args.Target, out var dmg) && dmg.DamageContainerID == "Biological") - args.Cancel(); - - if (HasComp(args.Target) && !HasComp(args.Target) - && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight")) - args.Cancel(); + if (HasComp(args.Target) && !HasComp(args.Target) + && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight")) args.Cancel(); } /// - /// Handle adding keys to the ignition, give stuff the InVehicleComponent so it can't be picked - /// up by people not in the vehicle. + /// Handles returning a Hologram to their last visited projector, + /// then to the nearest, finally killing them if none are found. /// - private void OnEntInserted(EntityUid uid, HologramServerComponent component, EntInsertedIntoContainerMessage args) + /// Hologram's HologramComponent. + public void HoloReturn(HologramReturnEvent args) { - if (args.Container.ID != DiskSlot || - !_tagSystem.HasTag(args.Entity, "HoloDisk")) return; + var uid = args.Uid; + var component = _entityManager.GetComponent(uid); + var meta = _entityManager.GetComponent(uid); + var holoPos = _entityManager.GetComponent(uid).Coordinates; + + var popupAppearOther = Loc.GetString("system-hologram-phasing-appear-others", ("name", meta.EntityName)); + var popupAppearSelf = Loc.GetString("system-hologram-phasing-appear-self"); + var popupDisappearOther = Loc.GetString("system-hologram-phasing-disappear-others", ("name", meta.EntityName)); + var popupDeathSelf = Loc.GetString("system-hologram-phasing-death-self"); + + // If the Hologram's last projector isn't valid, try to find a new one. + if (component.CurProjector != null && _entityManager.TryGetComponent(component.CurProjector, out var _)) + { + var curProjEvent = new HologramProjectorValidEvent(uid, component.CurProjector.Value); + RaiseNetworkEvent(curProjEvent); + if (!curProjEvent.Valid) + { + var getProj = new HologramGetProjectorEvent(uid, false); + component.CurProjector = getProj.Projector; + } + } + else + { + var getProj = new HologramGetProjectorEvent(uid, false); + component.CurProjector = getProj.Projector; + } + + // If the Hologram's last projector is still invalid, kill them. + if (component.CurProjector == EntityUid.Invalid) + { + + RaiseNetworkEvent(new HologramKillEvent(uid)); + return; + } + + _entityManager.TryGetComponent(component.CurProjector, out var transfComp); + Popup.PopupCoordinates(popupDisappearOther, holoPos, Filter.PvsExcept(uid), false, PopupType.MediumCaution); + _audio.Play(filename: "/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg", playerFilter: Filter.Pvs(uid), coordinates: holoPos, false); + + // Preapre to move holo + if (TryComp(uid, out var pullable) && pullable.BeingPulled) _pulling.TryStopPull(pullable); + if (TryComp(uid, out var pulling) && pulling.Pulling != null && + TryComp(pulling.Pulling.Value, out var subjectPulling)) _pulling.TryStopPull(subjectPulling); + + // Move holo + Transform(uid).Coordinates = _entityManager.GetComponent((EntityUid) component.CurProjector).Coordinates; + + Popup.PopupEntity(popupAppearOther, uid, Filter.PvsExcept((EntityUid) uid), false, PopupType.Medium); + Popup.PopupEntity(popupAppearSelf, uid, uid, PopupType.Large); + _audio.PlayPvs("/Audio/SimpleStation14/Effects/Hologram/holo_on.ogg", uid); - RaiseNetworkEvent(new HologramDiskInsertedEvent(uid, component)); + _adminLogger.Add(LogType.Unknown, LogImpact.Low, + $"{ToPrettyString(uid):mob} was returned to projector {ToPrettyString((EntityUid) component.CurProjector):entity}"); } } diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml index e303b8e753..1c9022b843 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml @@ -16,6 +16,10 @@ state: alert-2 - map: ["computerLayerKeys"] state: atmos_key + - type: Tag + tags: + - Hardlight + - type: entity parent: BaseComputer diff --git a/Resources/Prototypes/Entities/Structures/Machines/cloning_machine.yml b/Resources/Prototypes/Entities/Structures/Machines/cloning_machine.yml index 2672048e49..12c179b953 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/cloning_machine.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/cloning_machine.yml @@ -4,7 +4,6 @@ name: cloning pod description: A Cloning Pod. 50% reliable. components: - - type: Holopod - type: CloningPod - type: DeviceList - type: DeviceNetwork diff --git a/Resources/Prototypes/Entities/Structures/Machines/wireless_surveillance_camera.yml b/Resources/Prototypes/Entities/Structures/Machines/wireless_surveillance_camera.yml index 3dd35e53ca..936ff1e2ac 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/wireless_surveillance_camera.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/wireless_surveillance_camera.yml @@ -5,6 +5,7 @@ name: wireless camera description: A camera. It's watching you. Kinda. components: + - type: HologramProjector - type: InteractionOutline - type: Eye - type: WirelessNetworkConnection diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml index 71b74aed3e..4950c84616 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml @@ -92,18 +92,19 @@ - type: Physics bodyType: KinematicController - type: Fixtures - fixtures: # TODO: This needs a second fixture just for mob collisions. + fixtures: - shape: !type:PhysShapeCircle radius: 0.35 - density: 50 + density: 25 mask: - - MobMask + - FlyingMobMask layer: - - MobLayer + - FlyingMobLayer - type: MovementSpeedModifier baseWalkSpeed : 5 baseSprintSpeed : 3.5 + - type: MovementIgnoreGravity - type: Hands showInHands: false - type: Body @@ -123,8 +124,7 @@ - type: TypingIndicator proto: holo - type: RotationVisuals - - type: FloatingVisuals - force: true + # - type: FloatingVisuals - type: Speech speechSounds: Tenor - type: Vocal @@ -148,6 +148,8 @@ components: # - type: CombatMode # disarm: null + - type: Stealth + lastVisibility: 0.83 - type: InteractionPopup successChance: 1 interactSuccessString: hugging-success-hologram @@ -193,5 +195,7 @@ - Service - Binary - type: PointLight - radius: 3.5 + radius: 1.3 softness: 1 + color: "#00FFFF" + energy: 3 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml index 2913f6dce7..4b28140d4d 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml @@ -84,44 +84,43 @@ name: hologram server description: Contains the collective knowledge of holo components: - - type: Sprite - sprite: Structures/Machines/server.rsi - state: server - - type: ApcPowerReceiver - powerLoad: 200 - priority: Low - - type: ExtensionCableReceiver - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 300 - behaviors: - - !type:DoActsBehavior - acts: ["Destruction"] - - !type:PlaySoundBehavior - sound: - path: /Audio/Effects/metalbreak.ogg - - !type:SpawnEntitiesBehavior - spawn: - SheetSteel1: - min: 1 - max: 2 - - type: AmbientSound - volume: -9 - range: 5 - sound: - path: /Audio/Ambience/Objects/server_fans.ogg - - type: HologramServer - - type: ItemSlots - slots: - holo_disk: #this slot name is important - name: Disk - whitelist: - requireAll: true - components: - - HoloDisk - - type: CloningPod + - type: Sprite + sprite: Structures/Machines/server.rsi + state: server + - type: ApcPowerReceiver + powerLoad: 200 + priority: Low + - type: ExtensionCableReceiver + - type: Destructible + thresholds: + - trigger: !type:DamageTrigger + damage: 300 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/metalbreak.ogg + - !type:SpawnEntitiesBehavior + spawn: + SheetSteel1: + min: 1 + max: 2 + - type: AmbientSound + volume: -9 + range: 5 + sound: + path: /Audio/Ambience/Objects/server_fans.ogg + # - type: CloningPod + - type: HologramServer + - type: ItemSlots + slots: + holo_disk: #this slot name is important + name: Disk + whitelist: + requireAll: true + tags: + - HoloDisk - type: entity parent: BaseItem @@ -129,10 +128,10 @@ name: holo disk description: A disk for the holo components: - - type: Sprite - sprite: Objects/Specific/Research/researchdisk.rsi - state: icon - - tpye: HologramDisk - - type: Tag - tags: - - HoloDisk + - type: Sprite + sprite: Objects/Specific/Research/researchdisk.rsi + state: icon + - type: HologramDisk + - type: Tag + tags: + - HoloDisk From a08512de5e374f870983e50d65dae2eecb89ac4c Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 27 Feb 2023 13:17:20 -0500 Subject: [PATCH 07/60] Fixed holocorgi ID --- .../Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml index 005dc969c4..7da6a96468 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml @@ -72,7 +72,7 @@ - type: entity name: holo corgi description: "A hologramatic projection of a corgi, computed by the AI and rendered by the station's cameras." - id: MobCorgiHolo22 + id: MobCorgiHolo suffix: AI components: - type: LagCompensation From 64316336f5773a85de119ad6627088ec4853413c Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Tue, 28 Feb 2023 06:58:40 -0500 Subject: [PATCH 08/60] Fuckin working again. Stuff is networked now, though not to any real benefit. There's a grace period upon leaving a projector of one 24th of a second before you get returned. --- .../Holograms/Systems/HologramSystem.cs | 30 ++++++++++++++----- .../Holograms/HologramEvents.cs | 6 ++-- .../Holograms/SharedHologramSystem.cs | 21 +++++++------ .../Computers/base_structurecomputers.yml | 3 ++ .../Machines/Computers/computers.yml | 3 -- 5 files changed, 39 insertions(+), 24 deletions(-) diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs index 9365401a60..a1c4647ecc 100644 --- a/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs @@ -64,6 +64,7 @@ public override void Initialize() base.Initialize(); SubscribeAllEvent(HoloKill); SubscribeAllEvent(HoloGetProjector); + SubscribeAllEvent(HoloProjectorTest); // SubscribeLocalEvent(Startup); // SubscribeLocalEvent(Shutdown); // SubscribeLocalEvent(HoloTeleport); @@ -89,19 +90,34 @@ public override void Update(float frameTime) foreach (var component in _entityManager.EntityQuery().ToList()) { - var projectorEvent = new HologramGetProjectorEvent(component.Owner); - RaiseLocalEvent(component.Owner, projectorEvent); - Logger.DebugS("holo", "Hologram {0} has projector {1}", component.Owner, projectorEvent.Projector); - if (projectorEvent.Projector == EntityUid.Invalid || !projectorEvent.Projector.IsValid()) + var nearProj = HoloGetProjector(component); + if (!nearProj.IsValid()) { - RaiseNetworkEvent(new HologramReturnEvent(component.Owner)); - Logger.Debug("wawawah"); + if (component.Accumulator > 0) + { + component.Accumulator -= frameTime; + continue; + } + RaiseLocalEvent(new HologramReturnEvent(component.Owner)); continue; } - component.CurProjector = projectorEvent.Projector; + component.Accumulator = 0.24f; + component.CurProjector = nearProj; } } + /// + /// Tests if the given projector is valid. + /// + /// Event arguments. + public void HoloProjectorTest(HologramProjectorTestEvent args) + { + var curProjector = args.Projector; + if (curProjector == EntityUid.Invalid || !_entityManager.TryGetComponent(curProjector, out var _)) return; + if (_entityManager.TryGetComponent(curProjector, out var camComp) && !camComp.Active) return; + args.CanProject = true; + } + /// /// Tests for the nearest projector to the Hologram. /// diff --git a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs index 8d58c49254..c4c083dc3b 100644 --- a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs +++ b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs @@ -35,13 +35,13 @@ public HologramKillEvent(EntityUid uid) /// Raised to return a bool if a given projector is valid for a given hologram. /// [Serializable, NetSerializable] -public sealed class HologramProjectorValidEvent : EntityEventArgs +public sealed class HologramProjectorTestEvent : EntityEventArgs { public EntityUid Hologram; public EntityUid Projector; - public bool Valid = false; + public bool CanProject = false; - public HologramProjectorValidEvent(EntityUid hologram, EntityUid projector) + public HologramProjectorTestEvent(EntityUid hologram, EntityUid projector) { Hologram = hologram; Projector = projector; diff --git a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs index 375654032d..b16b405963 100644 --- a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs +++ b/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs @@ -32,7 +32,7 @@ public class SharedHologramSystem : EntitySystem public override void Initialize() { SubscribeLocalEvent(OnInteractionAttempt); - SubscribeNetworkEvent(HoloReturn); + SubscribeAllEvent(HoloReturn); } // Stops the Hologram from interacting with anything they shouldn't. @@ -63,27 +63,26 @@ public void HoloReturn(HologramReturnEvent args) var popupDeathSelf = Loc.GetString("system-hologram-phasing-death-self"); // If the Hologram's last projector isn't valid, try to find a new one. - if (component.CurProjector != null && _entityManager.TryGetComponent(component.CurProjector, out var _)) + if (component.CurProjector == null) { - var curProjEvent = new HologramProjectorValidEvent(uid, component.CurProjector.Value); - RaiseNetworkEvent(curProjEvent); - if (!curProjEvent.Valid) - { - var getProj = new HologramGetProjectorEvent(uid, false); - component.CurProjector = getProj.Projector; - } + return; } - else + + var curProjCheck = new HologramProjectorTestEvent(uid, component.CurProjector.Value); + RaiseLocalEvent(curProjCheck); + if (!curProjCheck.CanProject) { var getProj = new HologramGetProjectorEvent(uid, false); + RaiseLocalEvent(getProj); component.CurProjector = getProj.Projector; } // If the Hologram's last projector is still invalid, kill them. if (component.CurProjector == EntityUid.Invalid) { + // if (_timing.InPrediction) return; - RaiseNetworkEvent(new HologramKillEvent(uid)); + RaiseLocalEvent(new HologramKillEvent(uid)); return; } diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml index 890e863e8c..7722365bd5 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml @@ -58,3 +58,6 @@ ents: [] - type: DynamicPrice price: 400 + - type: Tag + tags: + - Hardlight diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml index 1c9022b843..b26a978a9b 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml @@ -16,9 +16,6 @@ state: alert-2 - map: ["computerLayerKeys"] state: atmos_key - - type: Tag - tags: - - Hardlight - type: entity From 80b458e043368c90be1e166be666b23cf068cc4c Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Tue, 28 Feb 2023 20:23:44 -0500 Subject: [PATCH 09/60] Prepared for projected, lightbee, and hardlight holos by separating the protos, make a temp new tag Light, deleted unused files, renamed HoloData to HoloMind, and made HoloData struct to hold info on the Holo like type and whether it's hardlight. Needs implementing in YAML. --- .../Holograms/Components/HoloDiskComponent.cs | 8 +- .../Holograms/Systems/HologramServerSystem.cs | 12 +- .../Holograms/Systems/HologramSystem.cs | 44 +++--- .../Holograms/HologramComponent.cs | 14 +- .../Holograms/HologramProjectorComponent.cs | 1 + .../Holograms/HolopodComponent.cs | 6 - .../Holograms/SharedHologramSystem.cs | 48 ++++++- .../Entities/Mobs/Player/hologram.yml | 125 ++++++++++++------ Resources/Prototypes/SimpleStation14/tags.yml | 2 + 9 files changed, 173 insertions(+), 87 deletions(-) delete mode 100644 Content.Shared/SimpleStation14/Holograms/HolopodComponent.cs diff --git a/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs b/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs index d9ea85a6e8..7adbedebf1 100644 --- a/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs +++ b/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs @@ -5,14 +5,8 @@ namespace Content.Server.SimpleStation14.Hologram; [RegisterComponent] public sealed class HologramDiskComponent : Component { - // [ViewVariables] - // public HoloDataEntry? HoloData = null; - - // [DataField("active"), ViewVariables(VVAccess.ReadWrite)] - // public bool Active = true; - [ViewVariables] - public Mind.Mind? HoloData = null; + public Mind.Mind? HoloMind = null; [DataField("active"), ViewVariables(VVAccess.ReadWrite)] public bool Active = true; diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs index cb5329b3f1..3fa935d77f 100644 --- a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs @@ -74,14 +74,14 @@ public override void Initialize() private void OnEntInserted(EntityUid uid, HologramServerComponent component, EntInsertedIntoContainerMessage args) { if (args.Container.ID != DiskSlot || !_tagSystem.HasTag(args.Entity, "HoloDisk") || - (_entityManager.TryGetComponent(args.Entity, out var diskComp) && diskComp.HoloData == null)) return; + (_entityManager.TryGetComponent(args.Entity, out var diskComp) && diskComp.HoloMind == null)) return; if (component.LinkedHologram != EntityUid.Invalid && _entityManager.EntityExists(component.LinkedHologram)) { RaiseLocalEvent(new HologramKillEvent(component.LinkedHologram.Value)); } - if (TryHoloGenerate(component.Owner, _entityManager.GetComponent(args.Entity).HoloData!, component, out var holo)) + if (TryHoloGenerate(component.Owner, _entityManager.GetComponent(args.Entity).HoloMind!, component, out var holo)) { var holoComp = _entityManager.GetComponent(holo); component.LinkedHologram = holo; @@ -95,7 +95,7 @@ private void OnEntInserted(EntityUid uid, HologramServerComponent component, Ent private void OnEntRemoved(EntityUid uid, HologramServerComponent component, EntRemovedFromContainerMessage args) { if (args.Container.ID != DiskSlot || !_tagSystem.HasTag(args.Entity, "HoloDisk") || - (_entityManager.TryGetComponent(args.Entity, out var diskComp) && diskComp.HoloData == null)) return; + (_entityManager.TryGetComponent(args.Entity, out var diskComp) && diskComp.HoloMind == null)) return; if (component.LinkedHologram != EntityUid.Invalid && _entityManager.EntityExists(component.LinkedHologram)) { @@ -130,7 +130,7 @@ private void OnPowerChanged(EntityUid uid, HologramServerComponent component, re return; // No disk in the server } var disk = serverContainer.GetContainer(DiskSlot).ContainedEntities.First(); - var diskData = _entityManager.GetComponent(disk).HoloData; + var diskData = _entityManager.GetComponent(disk).HoloMind; // If the hologram is generated successfully if (diskData != null && TryHoloGenerate(component.Owner, diskData, component, out var holo)) @@ -243,7 +243,7 @@ private EntityUid HoloFetchAndSpawn(HologramServerComponent holoServer, Humanoid List sexes = new(); var name = pref.Name; - var toSpawn = "MobHologram"; + var toSpawn = "MobHologramProjected"; var mob = Spawn(toSpawn, Transform(holoServer.Owner).MapPosition); _entityManager.GetComponent(mob).AttachToGridOrMap(); @@ -287,7 +287,7 @@ private void OnAfterInteract(EntityUid uid, HologramDiskComponent component, Aft return; } - component.HoloData = targetMind.Mind; + component.HoloMind = targetMind.Mind; Popup.PopupEntity(Loc.GetString("system-hologram-disk-mind-saved"), args.Target.Value, args.User); } } diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs index a1c4647ecc..7339f0f358 100644 --- a/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs @@ -83,28 +83,28 @@ public override void Initialize() // } - // Anything that needs to be regularly run, like handling exiting a projector's range - public override void Update(float frameTime) - { - base.Update(frameTime); - - foreach (var component in _entityManager.EntityQuery().ToList()) - { - var nearProj = HoloGetProjector(component); - if (!nearProj.IsValid()) - { - if (component.Accumulator > 0) - { - component.Accumulator -= frameTime; - continue; - } - RaiseLocalEvent(new HologramReturnEvent(component.Owner)); - continue; - } - component.Accumulator = 0.24f; - component.CurProjector = nearProj; - } - } + // // Anything that needs to be regularly run, like handling exiting a projector's range + // public override void Update(float frameTime) + // { + // base.Update(frameTime); + + // foreach (var component in _entityManager.EntityQuery().ToList()) + // { + // var nearProj = HoloGetProjector(component); + // if (!nearProj.IsValid()) + // { + // if (component.Accumulator > 0) + // { + // component.Accumulator -= frameTime; + // continue; + // } + // RaiseLocalEvent(new HologramReturnEvent(component.Owner)); + // continue; + // } + // component.Accumulator = 0.24f; + // component.CurProjector = nearProj; + // } + // } /// /// Tests if the given projector is valid. diff --git a/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs b/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs index a1c90baa63..7c176c7c58 100644 --- a/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs +++ b/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs @@ -3,13 +3,23 @@ namespace Content.Shared.SimpleStation14.Hologram; [RegisterComponent] public sealed class HologramComponent : Component { + // // Custom struct that specifies the type of hologram. + // // First variable is the HoloType enum, second is whether or not it's hardlight. + // // Defaults to False. + // [DataField("holoData"), ViewVariables] + // public HoloData HoloData = new HoloData(HoloType.Projected, false); + + // Current server the Hologram is generated by. + // Will be the Lightbee if it's a Lightbee Hologram. [ViewVariables] public EntityUid? LinkedServer; + // The current projector the Hologram is connected to. + // Will be the Lightbee if it's a Lightbee Hologram. [ViewVariables] public EntityUid? CurProjector; - // Counter + // Counter before returning the Holo, so you can get through doors. [DataField("accumulator")] - public float Accumulator = 2f; + public float Accumulator = 0.5f; } diff --git a/Content.Shared/SimpleStation14/Holograms/HologramProjectorComponent.cs b/Content.Shared/SimpleStation14/Holograms/HologramProjectorComponent.cs index 0bdcf59ba8..b63e4a634f 100644 --- a/Content.Shared/SimpleStation14/Holograms/HologramProjectorComponent.cs +++ b/Content.Shared/SimpleStation14/Holograms/HologramProjectorComponent.cs @@ -3,4 +3,5 @@ namespace Content.Shared.SimpleStation14.Hologram; [RegisterComponent] public sealed class HologramProjectorComponent : Component { + } diff --git a/Content.Shared/SimpleStation14/Holograms/HolopodComponent.cs b/Content.Shared/SimpleStation14/Holograms/HolopodComponent.cs deleted file mode 100644 index 21640ae990..0000000000 --- a/Content.Shared/SimpleStation14/Holograms/HolopodComponent.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Content.Server.SimpleStation14.Hologram; - -[RegisterComponent] -public sealed class HologramPodComponent : Component -{ -} diff --git a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs index b16b405963..b993023e41 100644 --- a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs +++ b/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs @@ -14,6 +14,7 @@ using Content.Shared.Administration.Logs; using Content.Shared.Database; using Content.Shared.Pulling; +using System.Linq; namespace Content.Shared.SimpleStation14.Hologram; @@ -27,7 +28,6 @@ public class SharedHologramSystem : EntitySystem [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly SharedPullingSystem _pulling = default!; - private const string DiskSlot = "holo_disk"; public override void Initialize() { @@ -35,6 +35,31 @@ public override void Initialize() SubscribeAllEvent(HoloReturn); } + // Anything that needs to be regularly run, like handling exiting a projector's range + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var component in _entityManager.EntityQuery().ToList()) + { + var getProj = new HologramGetProjectorEvent(component.Owner); + RaiseLocalEvent(getProj); + var nearProj = getProj.Projector; + if (!nearProj.IsValid()) + { + if (component.Accumulator > 0) + { + component.Accumulator -= frameTime; + continue; + } + RaiseLocalEvent(new HologramReturnEvent(component.Owner)); + continue; + } + component.Accumulator = 0.24f; + component.CurProjector = nearProj; + } + } + // Stops the Hologram from interacting with anything they shouldn't. private void OnInteractionAttempt(EntityUid uid, HologramComponent component, InteractionAttemptEvent args) { @@ -42,7 +67,7 @@ private void OnInteractionAttempt(EntityUid uid, HologramComponent component, In return; if (HasComp(args.Target) && !HasComp(args.Target) - && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight")) args.Cancel(); + && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight", "Light")) args.Cancel(); } /// @@ -107,6 +132,25 @@ public void HoloReturn(HologramReturnEvent args) } } +public enum HoloType +{ + Projected, + Lightbee +} + +public struct HoloData +{ + public HoloType Type { get; set; } + public bool IsHardlight { get; set; } + + public HoloData(HoloType type, bool isHardlight = false) + { + Type = type; + IsHardlight = isHardlight; + } +} + + // [Serializable, NetSerializable] // public sealed class HoloTeleportEvent : EntityEventArgs diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml index 4950c84616..9820f65514 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml @@ -139,63 +139,104 @@ attributes: proper: true - type: Hologram + - type: AnimationPlayer + - type: Mind + showExamineInfo: true + - type: Inventory + - type: Actions + - type: Eye - type: entity save: false name: Urist McLight + suffix: Projected parent: PlayerHologramBase - id: MobHologram + id: MobHologramProjected components: - # - type: CombatMode - # disarm: null + - type: Hologram + # holoData: + # Type: HoloType.Projected + # IsHardLight: false - type: Stealth - lastVisibility: 0.83 + lastVisibility: 0.80 - type: InteractionPopup successChance: 1 interactSuccessString: hugging-success-hologram # interactSuccessSound: /Audio/Effects/thudswoosh.ogg messagePerceivedByOthers: hugging-success-hologram-others - - type: Mind - showExamineInfo: true - - type: Input - context: "human" - - type: MobMover - - type: InputMover - - type: Inventory - - type: Alerts - - type: Actions - - type: Eye - # - type: CameraRecoil - - type: Examiner - type: Faction factions: - NanoTrasen - - type: IntrinsicRadioReceiver - channels: - - Common - - Engineering - - Medical - - Science - - Service - - Binary - - type: IntrinsicRadioTransmitter - channels: - - Common - - Engineering - - Medical - - Science - - Service - - Binary - - type: ActiveRadio - channels: - - Common - - Engineering - - Medical - - Science - - Service - - Binary - type: PointLight - radius: 1.3 - softness: 1 + radius: 1.0 + softness: 1.4 color: "#00FFFF" energy: 3 + +- type: entity + save: false + name: Urist McLight + suffix: Lightbee + parent: PlayerHologramBase + id: MobHologramLightbee + components: + - type: Hologram + # holoData: !HoloData + # Type: Lightbee + # IsHardLight: false + - type: Stealth + lastVisibility: 0.85 + - type: InteractionPopup + successChance: 1 + interactSuccessString: hugging-success-hologram + # interactSuccessSound: /Audio/Effects/thudswoosh.ogg + messagePerceivedByOthers: hugging-success-hologram-others + - type: CameraRecoil + - type: Faction + factions: + - NanoTrasen + - type: PointLight + radius: 1.5 + softness: 0.8 + color: "#00FFFF" + energy: 4 + +- type: entity + save: false + name: Urist McLight + suffix: Hardlight + parent: PlayerHologramBase + id: MobHologramHardlight + components: + - type: Hologram + # holoData: + # Type: HoloType.Lightbee + # IsHardLight: true + - type: DamageOnHighSpeedImpact + damage: + types: + Blunt: 5 + soundHit: + path: /Audio/Effects/hit_kick.ogg + - type: Damageable + damageContainer: Inorganic + - type: Pullable + - type: Puller + - type: CombatMode + disarm: null + - type: Stealth + lastVisibility: 0.90 + - type: InteractionPopup + successChance: 1 + interactSuccessString: hugging-success-hologram + # interactSuccessSound: /Audio/Effects/thudswoosh.ogg + messagePerceivedByOthers: hugging-success-hologram-others + - type: CameraRecoil + - type: Faction + factions: + - NanoTrasen + - type: PointLight + radius: 0.8 + softness: 0.4 + color: "#00FFFF" + energy: 5 diff --git a/Resources/Prototypes/SimpleStation14/tags.yml b/Resources/Prototypes/SimpleStation14/tags.yml index c134d41ab2..2c090389f7 100644 --- a/Resources/Prototypes/SimpleStation14/tags.yml +++ b/Resources/Prototypes/SimpleStation14/tags.yml @@ -6,5 +6,7 @@ - type: Tag id: Hardlight +- type: Tag + id: Light - type: Tag id: HoloDisk From 1f90d22f90e196fda31c4a1ae0b97c35192988b7 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Thu, 2 Mar 2023 17:35:12 -0500 Subject: [PATCH 10/60] Removed some unneeded things, cleaned some files, made it Holograms can interact with light things, and non-Holograms can't. --- .../Holograms/Systems/HologramServerSystem.cs | 48 ++++++++++++++++++- .../Gravity/FloatingVisualsComponent.cs | 4 -- .../Gravity/SharedFloatingVisualizerSystem.cs | 7 +-- .../{ => Components}/HoloServerComponent.cs | 0 .../{ => Components}/HologramComponent.cs | 0 .../HologramProjectorComponent.cs | 0 .../{ => Systems}/SharedHologramSystem.cs | 42 +++++++++++----- .../Machines/Computers/computers.yml | 1 - .../Entities/Mobs/Player/borgs.yml | 1 - .../Entities/Mobs/Player/hologram.yml | 2 + Resources/Prototypes/SimpleStation14/tags.yml | 2 +- 11 files changed, 82 insertions(+), 25 deletions(-) rename Content.Shared/SimpleStation14/Holograms/{ => Components}/HoloServerComponent.cs (100%) rename Content.Shared/SimpleStation14/Holograms/{ => Components}/HologramComponent.cs (100%) rename Content.Shared/SimpleStation14/Holograms/{ => Components}/HologramProjectorComponent.cs (100%) rename Content.Shared/SimpleStation14/Holograms/{ => Systems}/SharedHologramSystem.cs (83%) diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs index 3fa935d77f..d72b42f57f 100644 --- a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs @@ -29,6 +29,7 @@ using Content.Shared.Interaction.Components; using Content.Shared.Access.Components; using Content.Shared.Clothing.Components; +using Content.Shared.Roles; using Robust.Server.Player; using Robust.Shared.Player; using Robust.Shared.Containers; @@ -208,11 +209,11 @@ public bool TryHoloGenerate(EntityUid uid, Mind.Mind mind, HologramServerCompone return; } } - _tagSystem.AddTag(item, "Hardlight"); + _tagSystem.AddTag(item, "Softlight"); _entityManager.EnsureComponent(item); }); + // HoloEquip(mob, mind.CurrentJob.Prototype); } - } _adminLogger.Add(LogType.Unknown, LogImpact.Medium, @@ -277,6 +278,40 @@ private EntityUid HoloFetchAndSpawn(HologramServerComponent holoServer, Humanoid return mob; } + + /// + /// WiP for equipping unique items based on job. + /// +// private void HoloEquip(EntityUid mob, JobPrototype job) +// { +// // Check what job they are against a list, and output a hardcoded item for each. + + + + +// var mobTransform = EntityManager.GetComponent(mob); +// var mobPos = mobTransform.WorldPosition; + +// if (!_entityManager.TryGetComponent(mob, out var mobInv)) +// return; +// var mobHands = EntityManager.EnsureComponent(mob); + +// foreach (var item in job.StartingGear.Items) +// { +// var itemEnt = Spawn(item.Prototype, mobPos); +// _entityManager.GetComponent(itemEnt).AttachToGridOrMap(); + +// if (item.Slot == null) +// { +// mobInv.TryPutInHandOrAny(itemEnt, out var _); +// } +// else +// { +// mobInv.TryPutInSlot(itemEnt, item.Slot); +// } +// } +// } + private void OnAfterInteract(EntityUid uid, HologramDiskComponent component, AfterInteractEvent args) { if (args.Target == null || !TryComp(args.Target, out var targetMind)) @@ -290,4 +325,13 @@ private void OnAfterInteract(EntityUid uid, HologramDiskComponent component, Aft component.HoloMind = targetMind.Mind; Popup.PopupEntity(Loc.GetString("system-hologram-disk-mind-saved"), args.Target.Value, args.User); } + + +// // List of jobs with hardcoded items for Holograms, like a Clown's horn. +// static readonly Dictionary HoloJobItems = new Dictionary +// { +// { "Clown", "BikeHorn" }, +// { "value2", "output2" }, +// { "value3", "output3" } +// }; } diff --git a/Content.Shared/Gravity/FloatingVisualsComponent.cs b/Content.Shared/Gravity/FloatingVisualsComponent.cs index 2d3a50f0a7..40186db844 100644 --- a/Content.Shared/Gravity/FloatingVisualsComponent.cs +++ b/Content.Shared/Gravity/FloatingVisualsComponent.cs @@ -23,10 +23,6 @@ public sealed class FloatingVisualsComponent : Component [ViewVariables(VVAccess.ReadWrite)] public bool CanFloat = false; - - [ViewVariables(VVAccess.ReadWrite)] - [DataField("force")] - public bool Force = false; public readonly string AnimationKey = "gravity"; } diff --git a/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs b/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs index e80defb6fb..67da1e5169 100644 --- a/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs +++ b/Content.Shared/Gravity/SharedFloatingVisualizerSystem.cs @@ -28,9 +28,6 @@ public virtual void FloatAnimation(EntityUid uid, Vector2 offset, string animati protected bool CanFloat(EntityUid uid, FloatingVisualsComponent component, TransformComponent? transform = null) { - if (component.Force == true) - return true; - if (!Resolve(uid, ref transform)) return false; @@ -62,7 +59,7 @@ private void OnGravityChanged(ref GravityChangedEvent args) Dirty(floating); var uid = floating.Owner; - if (!args.HasGravity || floating.Force == true) + if (!args.HasGravity) FloatAnimation(uid, floating.Offset, floating.AnimationKey, floating.AnimationTime); } } @@ -70,7 +67,7 @@ private void OnGravityChanged(ref GravityChangedEvent args) private void OnEntParentChanged(EntityUid uid, FloatingVisualsComponent component, ref EntParentChangedMessage args) { var transform = args.Transform; - if (CanFloat(uid, component, transform) || component.Force == true) + if (CanFloat(uid, component, transform)) FloatAnimation(uid, component.Offset, component.AnimationKey, component.AnimationTime); } diff --git a/Content.Shared/SimpleStation14/Holograms/HoloServerComponent.cs b/Content.Shared/SimpleStation14/Holograms/Components/HoloServerComponent.cs similarity index 100% rename from Content.Shared/SimpleStation14/Holograms/HoloServerComponent.cs rename to Content.Shared/SimpleStation14/Holograms/Components/HoloServerComponent.cs diff --git a/Content.Shared/SimpleStation14/Holograms/HologramComponent.cs b/Content.Shared/SimpleStation14/Holograms/Components/HologramComponent.cs similarity index 100% rename from Content.Shared/SimpleStation14/Holograms/HologramComponent.cs rename to Content.Shared/SimpleStation14/Holograms/Components/HologramComponent.cs diff --git a/Content.Shared/SimpleStation14/Holograms/HologramProjectorComponent.cs b/Content.Shared/SimpleStation14/Holograms/Components/HologramProjectorComponent.cs similarity index 100% rename from Content.Shared/SimpleStation14/Holograms/HologramProjectorComponent.cs rename to Content.Shared/SimpleStation14/Holograms/Components/HologramProjectorComponent.cs diff --git a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs similarity index 83% rename from Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs rename to Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs index b993023e41..375ad5d1e5 100644 --- a/Content.Shared/SimpleStation14/Holograms/SharedHologramSystem.cs +++ b/Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs @@ -31,10 +31,40 @@ public class SharedHologramSystem : EntitySystem public override void Initialize() { - SubscribeLocalEvent(OnInteractionAttempt); + SubscribeLocalEvent(OnHoloInteractionAttempt); + SubscribeLocalEvent(OnInteractionAttempt); SubscribeAllEvent(HoloReturn); } + // Stops the Hologram from interacting with anything they shouldn't. + private void OnHoloInteractionAttempt(EntityUid uid, HologramComponent component, InteractionAttemptEvent args) + { + if (args.Target == null) + return; + + if (HasComp(args.Target) && !HasComp(args.Target) + && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight", "Softlight")) args.Cancel(); + } + + // Stops everyone else from interacting with the Holograms. + private void OnInteractionAttempt(InteractionAttemptEvent args) + { + if (args.Target == null || _tagSystem.HasAnyTag(args.Uid, "Hardlight", "Softlight") || + _entityManager.TryGetComponent(args.Uid, out var _)) + return; + + if (_tagSystem.HasAnyTag(args.Target.Value, "Softlight") && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight")){ + args.Cancel(); + + // Send a popup to the player about the interaction, and play a sound. + var meta = _entityManager.GetComponent(args.Target.Value); + var popup = Loc.GetString("system-hologram-light-interaction-fail", ("item", meta.EntityName)); + var sound = "/Audio/SimpleStation14/Effects/Hologram/holo_on.ogg"; + Popup.PopupEntity(popup, args.Target.Value, Filter.Entities(args.Uid), false); + _audio.Play(sound, Filter.Entities(args.Uid), args.Uid, false); + } + } + // Anything that needs to be regularly run, like handling exiting a projector's range public override void Update(float frameTime) { @@ -60,16 +90,6 @@ public override void Update(float frameTime) } } - // Stops the Hologram from interacting with anything they shouldn't. - private void OnInteractionAttempt(EntityUid uid, HologramComponent component, InteractionAttemptEvent args) - { - if (args.Target == null) - return; - - if (HasComp(args.Target) && !HasComp(args.Target) - && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight", "Light")) args.Cancel(); - } - /// /// Handles returning a Hologram to their last visited projector, /// then to the nearest, finally killing them if none are found. diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml index b26a978a9b..e303b8e753 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml @@ -17,7 +17,6 @@ - map: ["computerLayerKeys"] state: atmos_key - - type: entity parent: BaseComputer id: ComputerEmergencyShuttle diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml index 18531a98c3..a7f6d4ce59 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml @@ -190,7 +190,6 @@ False: { visible: false } - type: TypingIndicator proto: robot - - type: entity parent: PlayerCyborgBase id: PlayerCyborgStandard diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml index 9820f65514..1618d37248 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml @@ -119,6 +119,7 @@ - type: Alerts - type: Tag tags: + - DoorBumpOpener - ShoesRequiredStepTriggerImmune - type: NoSlip - type: TypingIndicator @@ -145,6 +146,7 @@ - type: Inventory - type: Actions - type: Eye + - type: Access - type: entity save: false diff --git a/Resources/Prototypes/SimpleStation14/tags.yml b/Resources/Prototypes/SimpleStation14/tags.yml index 2c090389f7..a29cbd9854 100644 --- a/Resources/Prototypes/SimpleStation14/tags.yml +++ b/Resources/Prototypes/SimpleStation14/tags.yml @@ -7,6 +7,6 @@ - type: Tag id: Hardlight - type: Tag - id: Light + id: Softlight - type: Tag id: HoloDisk From c274806e986ac2a7e088361a5b8ec644851be6f9 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sat, 18 Mar 2023 06:47:10 -0400 Subject: [PATCH 11/60] Added damage sets for Holograms, kinda fixed rotation on spawn, begun work on hologram data in the component (no structs ;-;), and refined the variations of Holograms. --- .../Holograms/Systems/HologramServerSystem.cs | 12 +++++++ .../Holograms/Components/HologramComponent.cs | 6 ++++ .../Holograms/Systems/SharedHologramSystem.cs | 22 ++++++------ .../SimpleStation14/Damage/modifier_sets.yml | 10 ++++++ .../Entities/Mobs/Player/hologram.yml | 35 +++++++++++++++---- 5 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs index d72b42f57f..7b1d058665 100644 --- a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs +++ b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs @@ -34,6 +34,8 @@ using Robust.Shared.Player; using Robust.Shared.Containers; using Robust.Shared.GameObjects.Components.Localization; +using Content.Shared.Movement.Systems; +using System.Threading.Tasks; namespace Content.Server.SimpleStation14.Hologram; @@ -56,6 +58,7 @@ public class HologramServerSystem : EntitySystem [Dependency] private readonly TagSystem _tagSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly InventorySystem _inventory = default!; + [Dependency] private readonly SharedMoverController _mover = default!; private const string DiskSlot = "holo_disk"; public readonly Dictionary ClonesWaitingForMind = new(); @@ -249,6 +252,8 @@ private EntityUid HoloFetchAndSpawn(HologramServerComponent holoServer, Humanoid var mob = Spawn(toSpawn, Transform(holoServer.Owner).MapPosition); _entityManager.GetComponent(mob).AttachToGridOrMap(); + ResetCamera(mob); + _humanoidSystem.LoadProfile(mob, pref); MetaData(mob).EntityName = name; @@ -278,6 +283,13 @@ private EntityUid HoloFetchAndSpawn(HologramServerComponent holoServer, Humanoid return mob; } + private async void ResetCamera(EntityUid mob) + { + await Task.Delay(500); + + _mover.ResetCamera(mob); + } + /// /// WiP for equipping unique items based on job. diff --git a/Content.Shared/SimpleStation14/Holograms/Components/HologramComponent.cs b/Content.Shared/SimpleStation14/Holograms/Components/HologramComponent.cs index 7c176c7c58..d5dcd5a320 100644 --- a/Content.Shared/SimpleStation14/Holograms/Components/HologramComponent.cs +++ b/Content.Shared/SimpleStation14/Holograms/Components/HologramComponent.cs @@ -9,6 +9,12 @@ public sealed class HologramComponent : Component // [DataField("holoData"), ViewVariables] // public HoloData HoloData = new HoloData(HoloType.Projected, false); + [DataField("holoType")] + public HoloType HoloType = HoloType.Projected; + + [DataField("isHardlight")] + public bool IsHardlight = false; + // Current server the Hologram is generated by. // Will be the Lightbee if it's a Lightbee Hologram. [ViewVariables] diff --git a/Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs index 375ad5d1e5..c4eaf071e9 100644 --- a/Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs +++ b/Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs @@ -158,18 +158,20 @@ public enum HoloType Lightbee } -public struct HoloData -{ - public HoloType Type { get; set; } - public bool IsHardlight { get; set; } +// public struct HoloData +// { +// [DataField("type")] +// public HoloType Type { get; set; } - public HoloData(HoloType type, bool isHardlight = false) - { - Type = type; - IsHardlight = isHardlight; - } -} +// [DataField("isHardlight")] +// public bool IsHardlight { get; set; } +// public HoloData(HoloType type, bool isHardlight = false) +// { +// Type = type; +// IsHardlight = isHardlight; +// } +// } // [Serializable, NetSerializable] diff --git a/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml b/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml new file mode 100644 index 0000000000..4303a51b06 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml @@ -0,0 +1,10 @@ +- type: damageModifierSet + id: Hardlight + coefficients: + Blunt: 1.6 + Slash: 1.0 + Piercing: 0.7 + Shock: 1.2 + Heat: 1.35 + flatReductions: + Blunt: 5 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml index 1618d37248..6c6c4044c0 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml @@ -156,9 +156,8 @@ id: MobHologramProjected components: - type: Hologram - # holoData: - # Type: HoloType.Projected - # IsHardLight: false + holoType: HoloType.Projected + isHardLight: false - type: Stealth lastVisibility: 0.80 - type: InteractionPopup @@ -186,6 +185,19 @@ # holoData: !HoloData # Type: Lightbee # IsHardLight: false + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeCircle + radius: 0.05 + density: 25 + mask: + - MobMask + layer: + - MobLayer + - type: Damageable + damageContainer: Inorganic + damageModifierSet: FlimsyMetallic - type: Stealth lastVisibility: 0.85 - type: InteractionPopup @@ -214,14 +226,25 @@ # holoData: # Type: HoloType.Lightbee # IsHardLight: true + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeCircle + radius: 0.35 + density: 25 + mask: + - MobMask + layer: + - MobLayer + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Hardlight - type: DamageOnHighSpeedImpact damage: types: - Blunt: 5 + Blunt: 6 # To get past the 5 damage threshold soundHit: path: /Audio/Effects/hit_kick.ogg - - type: Damageable - damageContainer: Inorganic - type: Pullable - type: Puller - type: CombatMode From a2d96a1a3b6b81ec0605bba6eb3ada3e68b48342 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Tue, 21 Mar 2023 07:13:48 -0400 Subject: [PATCH 12/60] Absolute overhaul. Silicon component is set up with an abundance of variables designed to allow for a wide variety of silicons in the future, such as Drones, Borgs, and IPCs. Charging system is simple right now, but with lots of foundation to improve. Currently takes into account ambient temperature for power drain with added risk of fire, and updates movement speed in line with charge state. Alert for battery level also added. Temp mod doesn't work just yet due to borg not having a temperature component?? --- .../Silicon/Charge/SiliconChargeSystem.cs | 168 +++++++++++++++++- Content.Shared/Alert/AlertType.cs | 6 +- .../Components/SiliconChargeComponent.cs | 20 --- .../Silicon/Components/SiliconComponent.cs | 95 ++++++++++ .../Silicon/Systems/SharedSiliconSystem.cs | 109 ++++++++++++ .../Entities/Mobs/Player/borgs.yml | 16 +- .../SimpleStation14/Alerts/alerts.yml | 19 ++ .../Interface/Alerts/charge.rsi/charge0.png | Bin 0 -> 213 bytes .../Interface/Alerts/charge.rsi/charge1.png | Bin 0 -> 211 bytes .../Interface/Alerts/charge.rsi/charge2.png | Bin 0 -> 193 bytes .../Interface/Alerts/charge.rsi/charge3.png | Bin 0 -> 192 bytes .../Interface/Alerts/charge.rsi/charge4.png | Bin 0 -> 193 bytes .../Interface/Alerts/charge.rsi/charge5.png | Bin 0 -> 194 bytes .../Interface/Alerts/charge.rsi/meta.json | 35 ++++ 14 files changed, 441 insertions(+), 27 deletions(-) delete mode 100644 Content.Shared/SimpleStation14/Silicon/Charge/Components/SiliconChargeComponent.cs create mode 100644 Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs create mode 100644 Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs create mode 100644 Resources/Prototypes/SimpleStation14/Alerts/alerts.yml create mode 100644 Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge0.png create mode 100644 Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge1.png create mode 100644 Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge2.png create mode 100644 Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge3.png create mode 100644 Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge4.png create mode 100644 Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge5.png create mode 100644 Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/meta.json diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs index ea5d58dcd8..122a4a0757 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs @@ -1,24 +1,182 @@ using Robust.Shared.Random; -using Content.Shared.Silicon.Charge; +using Content.Shared.SimpleStation14.Silicon.Components; +using Content.Server.Power.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Content.Server.Temperature.Components; +using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Popups; +using Content.Shared.Popups; +using Robust.Shared.Timing; +using Content.Shared.SimpleStation14.Silicon.Systems; +using Content.Shared.Movement.Systems; -namespace Content.Server.Silicon.Charge; +namespace Content.Server.SimpleStation14.Silicon.Charge; public sealed class SiliconChargeSystem : EntitySystem { [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + [Dependency] private readonly FlammableSystem _flammableSystem = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; + + static string popupOverheating = Loc.GetString("silicon-system-overheating"); + public override void Initialize() { + base.Initialize(); + + // Subscribe for init on entities with both SiliconComponent and BatteryComponent + SubscribeLocalEvent(OnBatteryInit); + } + + + private void OnBatteryInit(EntityUid uid, BatteryComponent component, ComponentInit args) + { + if (!EntityManager.TryGetComponent(uid, out var siliconComp) || + !siliconComp.BatteryPowered || + !siliconComp.StartCharged) + { + return; + } + + component.CurrentCharge = component.MaxCharge; } public override void Update(float frameTime) { + base.Update(frameTime); - foreach (var silicon in EntityQuery()) + + // For each siliconComp entity with a battery component, drain their charge. + foreach (var (siliconComp, batteryComp) in EntityManager.EntityQuery()) { - if (silicon.CurrentCharge > 0) + if (siliconComp.Owner == EntityUid.Invalid) + continue; + + var silicon = siliconComp.Owner; + + // If the silicon is not battery powered, or is dead, skip it. + if (!siliconComp.BatteryPowered || + _mobStateSystem.IsDead(silicon)) + continue; + + var drainRate = 10 * (siliconComp.DrainRateMulti); + + // All multipliers will be added together + // and then divided by the added weight, before applying to the drain rate. + var drainRateFinalMulti = 0f; + + //TODO: Make this actually support more than one multipler. Math is hard ;-; + // Adding more than a couple, or a few smaller multipliers to this will cause exponential drain. + // Fix this before doing that. + drainRateFinalMulti += SiliconHeatEffects(silicon, frameTime); + + if (drainRateFinalMulti != 0) + { + drainRate *= drainRateFinalMulti; + } + + Logger.Warning($"Drain rate: {drainRate}"); + + // Drain the battery. + batteryComp.UseCharge(frameTime * drainRate); + + // Figure out the current state of the Silicon. + var currentState = ChargeState.Dead; + var chargePercent = batteryComp.CurrentCharge / batteryComp.MaxCharge; + + if (chargePercent == 0 && siliconComp.ChargeStateThresholdCritical != 0) + { + currentState = ChargeState.Dead; + } + else if (chargePercent <= siliconComp.ChargeStateThresholdCritical) + { + currentState = ChargeState.Critical; + } + else if (chargePercent <= siliconComp.ChargeStateThresholdLow) + { + currentState = ChargeState.Low; + } + else if (chargePercent < siliconComp.ChargeStateThresholdMid) + { + currentState = ChargeState.Mid; + } + else if (chargePercent >= siliconComp.ChargeStateThresholdMid) { - silicon.CurrentCharge -= (frameTime * silicon.ChargeDrainMult * 2) * _random.NextFloat(1.1f, 0.9f); + currentState = ChargeState.Full; } + + // Check if anything needs to be updated. + if (currentState != siliconComp.ChargeState) + { + siliconComp.ChargeState = currentState; + + RaiseLocalEvent(silicon, new SiliconChargeStateUpdateEvent(currentState)); + + _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(silicon); + } + } + } + + private float SiliconHeatEffects(EntityUid silicon, float frameTime) + { + if (!EntityManager.TryGetComponent(silicon, out var temperComp)) + { + Logger.Warning("Silicon has no temperature component!"); + + return 0; } + + // If the Silicon is hot, drain the battery faster, if it's cold, drain it slower, capped. + + // Check if the silicon is in a hot environment. + if (temperComp.CurrentTemperature > 300) + { + Logger.Warning("Silicon is hot!"); + + // Divide the current temp by 300 capped to 4, then add that to the multiplier. + var hotTempMulti = Math.Min(temperComp.CurrentTemperature / 300, 4); + + // If the silicon is hot enough, it has a chance to catch fire. + FlammableComponent? flamComp = null; + + if (EntityManager.TryGetComponent(silicon, out flamComp) && + temperComp.CurrentTemperature > 360 && + !flamComp.OnFire && + _random.Prob(0.05f * frameTime + (temperComp.CurrentTemperature / 3600))) + { + Logger.Warning("Silicon is on fire!"); + + _flammableSystem.Ignite(silicon, flamComp); + } + else if (temperComp.CurrentTemperature > 300 && + (flamComp == null || !flamComp.OnFire) && + _random.Prob(0.085f * frameTime + (temperComp.CurrentTemperature / 36000))) + { + Logger.Warning("Silicon is overheating!"); + + _popup.PopupEntity(popupOverheating, silicon, silicon, PopupType.SmallCaution); + } + Logger.Warning($"Hot temp multi: {hotTempMulti}"); + + return hotTempMulti; + } + + // Check if the silicon is in a cold environment. + if (temperComp.CurrentTemperature < 280) + { + Logger.Warning("Silicon is cold!"); + + var coldTempMulti = (0.5f + temperComp.CurrentTemperature / 560); + return coldTempMulti; + } + + Logger.Warning("Silicon is normal temp!"); + + return 0; } } diff --git a/Content.Shared/Alert/AlertType.cs b/Content.Shared/Alert/AlertType.cs index 3b6d974637..56b6d23581 100644 --- a/Content.Shared/Alert/AlertType.cs +++ b/Content.Shared/Alert/AlertType.cs @@ -44,7 +44,11 @@ public enum AlertType : byte Debug3, Debug4, Debug5, - Debug6 + Debug6, + + // Start of Parkstation alerts + Charge + // End of Parkstation alerts } } diff --git a/Content.Shared/SimpleStation14/Silicon/Charge/Components/SiliconChargeComponent.cs b/Content.Shared/SimpleStation14/Silicon/Charge/Components/SiliconChargeComponent.cs deleted file mode 100644 index a9a25672cf..0000000000 --- a/Content.Shared/SimpleStation14/Silicon/Charge/Components/SiliconChargeComponent.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Content.Shared.Silicon.Charge; - -/// -/// -/// -[RegisterComponent] -public sealed class SiliconChargeComponent : Component -{ - [DataField("currentCharge"), ViewVariables(VVAccess.ReadWrite)] - public float CurrentCharge = 100; - - [DataField("maxCharge"), ViewVariables(VVAccess.ReadWrite)] - public float MaxCharge = 2000; - - [DataField("chargeDrainMult"), ViewVariables(VVAccess.ReadWrite)] - public float ChargeDrainMult = 1; - - [DataField("freezeOnEmpty")] - public bool FreezeOnEmpty = false; -} diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs new file mode 100644 index 0000000000..1f183c8fb5 --- /dev/null +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs @@ -0,0 +1,95 @@ +using Robust.Shared.GameStates; +using Content.Shared.SimpleStation14.Silicon.Systems; +using Robust.Shared.Serialization.TypeSerializers.Implementations; + +namespace Content.Shared.SimpleStation14.Silicon.Components; + +/// +/// Component for defnining a mob as a robot. +/// +[RegisterComponent, NetworkedComponent] +public sealed class SiliconComponent : Component +{ + [ViewVariables(VVAccess.ReadOnly)] + public ChargeState ChargeState = ChargeState.Full; + + /// + /// The owner of this component. + /// + [ViewVariables(VVAccess.ReadOnly)] + public new EntityUid Owner = EntityUid.Invalid; + + /// + /// The type of silicon this is. + /// + /// + /// Any new types of Silicons should be added to the enum. + /// + [DataField("entityType", customTypeSerializer: typeof(EnumSerializer))] + public Enum EntityType = SiliconType.NPC; + + /// + /// Is this silicon battery powered? + /// + /// + /// If true, should go along with a battery component. One will not be added automatically. + /// + [DataField("batteryPowered"), ViewVariables(VVAccess.ReadWrite)] + public bool BatteryPowered = false; + + /// + /// Should this silicon start charged? + /// + [DataField("startCharged"), ViewVariables(VVAccess.ReadOnly)] + public bool StartCharged = true; + + /// + /// Multiplier for the charge rate of the silicon. + /// + [DataField("chargeRateMulti"), ViewVariables(VVAccess.ReadWrite)] + public float ChargeRateMulti = 2.5f; + + /// + /// Multiplier for the drain rate of the silicon. + /// + [DataField("drainRateMulti"), ViewVariables(VVAccess.ReadWrite)] + public float DrainRateMulti = 5.0f; + + /// + /// The percentages at which the silicon will enter each state. + /// The Silicon will always be Full at 100%. + /// Setting a value to null will disable that state. + /// Setting Critical to 0 will cause the Silicon to never die of power loss. + /// + [DataField("chargeStateThresholdMid"), ViewVariables(VVAccess.ReadWrite)] + public float? ChargeStateThresholdMid = 0.5f; + + [DataField("chargeStateThresholdLow"), ViewVariables(VVAccess.ReadWrite)] + public float? ChargeStateThresholdLow = 0.25f; + + [DataField("chargeStateThresholdCritical"), ViewVariables(VVAccess.ReadWrite)] + public float? ChargeStateThresholdCritical = 0.0f; + + /// + /// Should the silicon die when it runs out of power? + /// If false, will instead become immobile. + /// + /// + /// Will only occur when hitting the Dead state. + /// + [DataField("dieWhenDead"), ViewVariables(VVAccess.ReadWrite)] + public bool DieWhenDead = false; + + [DataField("speedModifierThresholds", required: true)] + public readonly Dictionary SpeedModifierThresholds = default!; + + + + // [DataField("chargeStateThresholds"), ViewVariables(VVAccess.ReadWrite)] + // public ChargeStateThresholdsData ChargeStateThresholds = new() + // { + // Mid = 1.0f, + // Low = 0.25f, + // Critical = 0.0f, + // }; +} diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs new file mode 100644 index 0000000000..7490fce9e6 --- /dev/null +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs @@ -0,0 +1,109 @@ +using Content.Shared.SimpleStation14.Silicon.Components; +using Content.Shared.Alert; +using Robust.Shared.Serialization; +using Content.Shared.Movement.Systems; +// using + +namespace Content.Shared.SimpleStation14.Silicon.Systems; +public sealed class SharedSiliconChargeSystem : EntitySystem +{ + [Dependency] private readonly AlertsSystem _alertsSystem = default!; + + // Dictionary of ChargeState to Alert severity. + private static readonly Dictionary ChargeStateAlert = new() + { + {ChargeState.Full, 5}, + {ChargeState.Mid, 4}, + {ChargeState.Low, 2}, + {ChargeState.Critical, 1}, + {ChargeState.Dead, 0}, + // {ChargeState.Full, 5}, + // {ChargeState.Full, 6}, + }; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnSiliconInit); + SubscribeLocalEvent(OnSiliconChargeStateUpdate); + SubscribeLocalEvent(OnRefreshMovespeed); + } + + private void OnSiliconInit(EntityUid uid, SiliconComponent component, ComponentInit args) + { + component.Owner = uid; + + if (component.BatteryPowered) + { + _alertsSystem.ShowAlert(uid, AlertType.Charge, ChargeStateAlert[component.ChargeState]); + } + } + + private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconComponent component, SiliconChargeStateUpdateEvent ev) + { + _alertsSystem.ShowAlert(uid, AlertType.Charge, ChargeStateAlert[component.ChargeState]); + } + + private void OnRefreshMovespeed(EntityUid uid, SiliconComponent component, RefreshMovementSpeedModifiersEvent args) + { + if (component.BatteryPowered) + { + var speedModThresholds = component.SpeedModifierThresholds; + + var closest = -0.5f; + + foreach (var state in speedModThresholds) + { + if (component.ChargeState >= state.Key && ((float)state.Key) > closest) + closest = ((float)state.Key); + } + + var speedMod = speedModThresholds[(ChargeState)closest]; + + args.ModifySpeed(speedMod, speedMod); + } + } +} + + +public enum SiliconType +{ + Player, + GhostRole, + NPC +} + +public enum ChargeState +{ + Charging = -1, + Full, + Mid, + Low, + Critical, + Dead +} + +// [Serializable, NetSerializable] +// public struct ChargeStateThresholdsData +// { +// public float Mid; +// public float Low; +// public float Critical; +// } + + +/// +/// Event raised when a Silicon's charge state needs to be updated. +/// +[Serializable, NetSerializable] +public sealed class SiliconChargeStateUpdateEvent : EntityEventArgs +{ + public ChargeState ChargeState { get; } + + public SiliconChargeStateUpdateEvent(ChargeState chargeState) + { + ChargeState = chargeState; + } +} + diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml index a7f6d4ce59..a9e424db87 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml @@ -195,7 +195,21 @@ id: PlayerCyborgStandard name: standard cyborg components: - - type: SiliconCharge + - type: Silicon + batteryPowered: true + chargeStateThresholdMid: 0.50 + chargeStateThresholdLow: 0.30 + chargeStateThresholdCritical: 0.15 + dieWhenDead: false + entityType: enum.SiliconType.Player + speedModifierThresholds: + 0: 1 + 1: 1 + 2: 0.80 + 3: 0.60 + 4: 0.10 + - type: Battery + maxCharge: 150000 - type: InnateTool tools: - id: WelderIndustrial diff --git a/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml b/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml new file mode 100644 index 0000000000..cf7157e9dd --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml @@ -0,0 +1,19 @@ +- type: alert + id: Charge + icons: + - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi + state: charge0 + - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi + state: charge1 + - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi + state: charge2 + - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi + state: charge3 + - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi + state: charge4 + - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi + state: charge5 + name: alerts-charge-name + description: alerts-charge-desc + minSeverity: 0 + maxSeverity: 5 diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge0.png b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge0.png new file mode 100644 index 0000000000000000000000000000000000000000..b800fe36c30712ac3ab475130e9e03cdea76e197 GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!VDw>HYaZfQv3lvA+DJ@3=9?w3_pMnL~r<_ z_#Y_6SQ6wH%;50sMjD8duOQ68ajggPXNrR1p(_*p2 w10QDAt_&`pwk1rnSVR_{P?EU2n1P4k$KK%n#Z{S+K%*EuUHx3vIVCg!07C#X-~a#s literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge1.png b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge1.png new file mode 100644 index 0000000000000000000000000000000000000000..8cb2543a96df9e1e6fc6d1003f9f6406d3ef1c27 GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!VDw>HYaZfQv3lvA+C;03=9?w3_lWW<fnn}>g_cE*9t?B+dzi%CgG4kI tX$Htl;yS^l;l#z^Dt7RN9BTptgM7E9;p*vzK#Ld{JYD@<);T3K0RZR1FoXaA literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge2.png b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge2.png new file mode 100644 index 0000000000000000000000000000000000000000..4df8884917d27541fc575410a26e0cbb869eb3a2 GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^*HxaJ3_lncEEs%Em3RtgXqB<*-i22_6-<8&{S_dh}$b7^Wo{O6Fi_@% literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge4.png b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge4.png new file mode 100644 index 0000000000000000000000000000000000000000..dd76743bc90e170b402db311afde4da64f23e368 GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@&H$efR|W<(h93+J77Pwoofv_F zj3q&S!3+-1Zlr-YN#5=*3>~bp9w6lf9+AZi4BWyX%*Zfnjs#GUy~NYkmHj!hC?~%p z_l3(KV+}oB977~7Cnqcrx)8<6#x1d|t;vz)uujJb9u>D6SC-BUmdKI;Vst0Ao8ZAOHXW literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge5.png b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge5.png new file mode 100644 index 0000000000000000000000000000000000000000..ef33a91bd25ff56abb720773d74e762f3ce3f017 GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@&H$ef*F1(93_lncEEty9>6`)z zGL{7S1v5B2yO9RsBze2LFm$lWdVrJ{ctjR6FmMZlFeAgPITAoY_7YEDSN7-3qMZCJ z8Q1pj0}2^=x;TbNTux3{Aao&$m5p0sSzD7M%VC|46Fe$zH?Az58JJjb%w&^<@rD^Z f+eO~-XfZM@_j7ul*7{fssGGsl)z4*}Q$iB}m_#wV literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/meta.json b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/meta.json new file mode 100644 index 0000000000..a0b634ef6c --- /dev/null +++ b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/meta.json @@ -0,0 +1,35 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "taken from tg station at commit https://github.com/tgstation/tgstation/commit/7e93c2d8ff8b80d0987daf0adfbcc825f7a46d38", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "charge5" + }, + { + "name": "charge4" + }, + { + "name": "charge3" + }, + { + "name": "charge2" + }, + { + "name": "charge1", + "delays": [ + [ 0.4, 0.4 ] + ] + }, + { + "name": "charge0", + "delays": [ + [ 0.5, 0.5 ] + ] + } + ] +} From e1924e75b3fca8209c325e8022025b80e93a6501 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Fri, 24 Mar 2023 00:08:15 -0400 Subject: [PATCH 13/60] Functioning IPC species! Still needs to be fine tuned, as it takes a lot off human at the moment. Charger and crit systems still to come. --- .../Silicon/Charge/SiliconChargeSystem.cs | 94 ++-- .../Silicon/Components/SiliconComponent.cs | 11 +- .../Silicon/Systems/SharedSiliconSystem.cs | 7 + .../Entities/Mobs/Player/silicon.yml | 526 +++++++++--------- .../Prototypes/Entities/Mobs/Species/base.yml | 4 + .../Entities/Mobs/Player/borgs.yml | 38 +- .../SimpleStation14/Body/Parts/ipc.yml | 188 +++++++ .../SimpleStation14/Damage/modifier_sets.yml | 19 + .../Entities/Mobs/Player/ipc.yml | 35 ++ .../Entities/Mobs/Player/silicon.yml | 129 ----- .../Entities/Mobs/Player/silicon_base.yml | 370 ++++++++++++ .../Entities/Mobs/Player/silicon_ghost.yml | 284 ++++++++++ .../SimpleStation14/Species/ipc.yml | 147 +++++ .../IPC/organs.rsi/appendix-inflamed.png | Bin 0 -> 188 bytes .../Mobs/Species/IPC/organs.rsi/appendix.png | Bin 0 -> 158 bytes .../IPC/organs.rsi/brain-inhand-left.png | Bin 0 -> 300 bytes .../IPC/organs.rsi/brain-inhand-right.png | Bin 0 -> 312 bytes .../Mobs/Species/IPC/organs.rsi/brain.png | Bin 0 -> 461 bytes .../Mobs/Species/IPC/organs.rsi/ears.png | Bin 0 -> 619 bytes .../Mobs/Species/IPC/organs.rsi/eyeball-l.png | Bin 0 -> 364 bytes .../Mobs/Species/IPC/organs.rsi/eyeball-r.png | Bin 0 -> 354 bytes .../Mobs/Species/IPC/organs.rsi/heart-off.png | Bin 0 -> 242 bytes .../Mobs/Species/IPC/organs.rsi/heart-on.png | Bin 0 -> 436 bytes .../Mobs/Species/IPC/organs.rsi/kidney-l.png | Bin 0 -> 262 bytes .../Mobs/Species/IPC/organs.rsi/kidney-r.png | Bin 0 -> 259 bytes .../Mobs/Species/IPC/organs.rsi/liver.png | Bin 0 -> 290 bytes .../Mobs/Species/IPC/organs.rsi/lung-l.png | Bin 0 -> 279 bytes .../Mobs/Species/IPC/organs.rsi/lung-r.png | Bin 0 -> 275 bytes .../Mobs/Species/IPC/organs.rsi/meta.json | 80 +++ .../Mobs/Species/IPC/organs.rsi/muscle.png | Bin 0 -> 219 bytes .../Mobs/Species/IPC/organs.rsi/nerve.png | Bin 0 -> 155 bytes .../Mobs/Species/IPC/organs.rsi/stomach.png | Bin 0 -> 191 bytes .../Mobs/Species/IPC/organs.rsi/tongue.png | Bin 0 -> 375 bytes .../Mobs/Species/IPC/organs.rsi/vessel.png | Bin 0 -> 170 bytes .../Mobs/Species/IPC/parts.rsi/full.png | Bin 0 -> 5707 bytes .../Mobs/Species/IPC/parts.rsi/head_f.png | Bin 0 -> 586 bytes .../Mobs/Species/IPC/parts.rsi/head_m.png | Bin 0 -> 586 bytes .../Mobs/Species/IPC/parts.rsi/l_arm.png | Bin 0 -> 497 bytes .../Mobs/Species/IPC/parts.rsi/l_foot.png | Bin 0 -> 18302 bytes .../Mobs/Species/IPC/parts.rsi/l_hand.png | Bin 0 -> 402 bytes .../Mobs/Species/IPC/parts.rsi/l_leg.png | Bin 0 -> 18302 bytes .../Mobs/Species/IPC/parts.rsi/meta.json | 62 +++ .../Mobs/Species/IPC/parts.rsi/r_arm.png | Bin 0 -> 494 bytes .../Mobs/Species/IPC/parts.rsi/r_foot.png | Bin 0 -> 18314 bytes .../Mobs/Species/IPC/parts.rsi/r_hand.png | Bin 0 -> 400 bytes .../Mobs/Species/IPC/parts.rsi/r_leg.png | Bin 0 -> 18315 bytes .../Mobs/Species/IPC/parts.rsi/torso_f.png | Bin 0 -> 973 bytes .../Mobs/Species/IPC/parts.rsi/torso_m.png | Bin 0 -> 973 bytes 48 files changed, 1538 insertions(+), 456 deletions(-) create mode 100644 Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml delete mode 100644 Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon.yml create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_ghost.yml create mode 100644 Resources/Prototypes/SimpleStation14/Species/ipc.yml create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix-inflamed.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain-inhand-left.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain-inhand-right.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/ears.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/eyeball-l.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/eyeball-r.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/heart-off.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/heart-on.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-l.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-r.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/liver.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-l.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-r.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/meta.json create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/muscle.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/nerve.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/stomach.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/tongue.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/vessel.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/full.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_f.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_m.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_arm.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_foot.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_hand.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_leg.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/meta.json create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_arm.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_foot.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_hand.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_leg.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_f.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_m.png diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs index 122a4a0757..8d0a535774 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs @@ -11,6 +11,8 @@ using Robust.Shared.Timing; using Content.Shared.SimpleStation14.Silicon.Systems; using Content.Shared.Movement.Systems; +using Content.Server.Body.Components; +using Robust.Shared.Utility; namespace Content.Server.SimpleStation14.Silicon.Charge; @@ -37,18 +39,21 @@ public override void Initialize() private void OnBatteryInit(EntityUid uid, BatteryComponent component, ComponentInit args) { if (!EntityManager.TryGetComponent(uid, out var siliconComp) || - !siliconComp.BatteryPowered || - !siliconComp.StartCharged) - { + !siliconComp.BatteryPowered) return; - } - component.CurrentCharge = component.MaxCharge; + component.MaxCharge *= _random.NextFloat(0.85f, 1.15f); + + var batteryLevelFill = component.MaxCharge; + + if (siliconComp.StartCharged.Equals(StartChargedData.Randomized)) + batteryLevelFill *= _random.NextFloat(0.40f, 0.80f); + + component.CurrentCharge = batteryLevelFill; } public override void Update(float frameTime) { - base.Update(frameTime); // For each siliconComp entity with a battery component, drain their charge. @@ -66,21 +71,19 @@ public override void Update(float frameTime) var drainRate = 10 * (siliconComp.DrainRateMulti); - // All multipliers will be added together - // and then divided by the added weight, before applying to the drain rate. - var drainRateFinalMulti = 0f; + // All multipliers will be - 1, and then added together, and then multiplied by 150. This is then added to the base drain rate. + // This is to stop exponential increases, while still allowing for less-than-one multipliers. + var drainRateFinalAddi = 0f; - //TODO: Make this actually support more than one multipler. Math is hard ;-; - // Adding more than a couple, or a few smaller multipliers to this will cause exponential drain. - // Fix this before doing that. - drainRateFinalMulti += SiliconHeatEffects(silicon, frameTime); + //TODO: Devise a method of adding multis where other systems can alter the drain rate. + // Maybe use something similar to refreshmovespeedmodifiers, where it's stored in the component. + // Maybe it doesn't matter, and stuff should just use static drain? - if (drainRateFinalMulti != 0) - { - drainRate *= drainRateFinalMulti; - } + drainRateFinalAddi += SiliconHeatEffects(silicon, frameTime) - 1; - Logger.Warning($"Drain rate: {drainRate}"); + // Ensures that the drain rate is at least 10% of normal, + // and would allow at least 4 minutes of life with a max charge, to prevent cheese. + drainRate += Math.Clamp(drainRateFinalAddi, drainRate * -0.9f, batteryComp.MaxCharge / 240); // Drain the battery. batteryComp.UseCharge(frameTime * drainRate); @@ -124,59 +127,58 @@ public override void Update(float frameTime) private float SiliconHeatEffects(EntityUid silicon, float frameTime) { - if (!EntityManager.TryGetComponent(silicon, out var temperComp)) + if (!EntityManager.TryGetComponent(silicon, out var temperComp) || + !EntityManager.TryGetComponent(silicon, out var thermalComp)) { - Logger.Warning("Silicon has no temperature component!"); - + DebugTools.Assert("Silicon has no temperature component, but is battery powered."); return 0; } + var siliconComp = EntityManager.GetComponent(silicon); // If the Silicon is hot, drain the battery faster, if it's cold, drain it slower, capped. + var upperThresh = thermalComp.NormalBodyTemperature + (thermalComp.ThermalRegulationTemperatureThreshold); + var lowerThresh = thermalComp.NormalBodyTemperature - (thermalComp.ThermalRegulationTemperatureThreshold); // Check if the silicon is in a hot environment. - if (temperComp.CurrentTemperature > 300) + if (temperComp.CurrentTemperature > (upperThresh * 0.5f)) { - Logger.Warning("Silicon is hot!"); - // Divide the current temp by 300 capped to 4, then add that to the multiplier. - var hotTempMulti = Math.Min(temperComp.CurrentTemperature / 300, 4); + // Divide the current temp by the max comfortable temp capped to 4, then add that to the multiplier. + var hotTempMulti = Math.Min(temperComp.CurrentTemperature / (upperThresh * 0.5f), 4); // If the silicon is hot enough, it has a chance to catch fire. FlammableComponent? flamComp = null; - if (EntityManager.TryGetComponent(silicon, out flamComp) && - temperComp.CurrentTemperature > 360 && - !flamComp.OnFire && - _random.Prob(0.05f * frameTime + (temperComp.CurrentTemperature / 3600))) + siliconComp.OverheatAccumulator += frameTime; + if (siliconComp.OverheatAccumulator >= 10) { - Logger.Warning("Silicon is on fire!"); - - _flammableSystem.Ignite(silicon, flamComp); + siliconComp.OverheatAccumulator =- 10; + + if (EntityManager.TryGetComponent(silicon, out flamComp) && + temperComp.CurrentTemperature > temperComp.HeatDamageThreshold && + !flamComp.OnFire && + _random.Prob(Math.Max(temperComp.CurrentTemperature / (upperThresh * 15), 0.9f))) + { + _flammableSystem.Ignite(silicon, flamComp); + } + else if ((flamComp == null || !flamComp.OnFire) && + _random.Prob(Math.Max(temperComp.CurrentTemperature / (upperThresh * 10), 0.45f))) + { + _popup.PopupEntity(popupOverheating, silicon, silicon, PopupType.SmallCaution); + } } - else if (temperComp.CurrentTemperature > 300 && - (flamComp == null || !flamComp.OnFire) && - _random.Prob(0.085f * frameTime + (temperComp.CurrentTemperature / 36000))) - { - Logger.Warning("Silicon is overheating!"); - - _popup.PopupEntity(popupOverheating, silicon, silicon, PopupType.SmallCaution); - } - Logger.Warning($"Hot temp multi: {hotTempMulti}"); return hotTempMulti; } // Check if the silicon is in a cold environment. - if (temperComp.CurrentTemperature < 280) + if (temperComp.CurrentTemperature < thermalComp.NormalBodyTemperature) { - Logger.Warning("Silicon is cold!"); + var coldTempMulti = (0.5f + (temperComp.CurrentTemperature / thermalComp.NormalBodyTemperature) * 0.5f); - var coldTempMulti = (0.5f + temperComp.CurrentTemperature / 560); return coldTempMulti; } - Logger.Warning("Silicon is normal temp!"); - return 0; } } diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs index 1f183c8fb5..9562dc6cdd 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs @@ -13,6 +13,9 @@ public sealed class SiliconComponent : Component [ViewVariables(VVAccess.ReadOnly)] public ChargeState ChargeState = ChargeState.Full; + [ViewVariables(VVAccess.ReadOnly)] + public float OverheatAccumulator = 0.0f; + /// /// The owner of this component. /// @@ -40,8 +43,8 @@ public sealed class SiliconComponent : Component /// /// Should this silicon start charged? /// - [DataField("startCharged"), ViewVariables(VVAccess.ReadOnly)] - public bool StartCharged = true; + [DataField("startCharged", customTypeSerializer: typeof(EnumSerializer)), ViewVariables(VVAccess.ReadOnly)] + public Enum StartCharged = StartChargedData.Randomized; /// /// Multiplier for the charge rate of the silicon. @@ -77,8 +80,8 @@ public sealed class SiliconComponent : Component /// /// Will only occur when hitting the Dead state. /// - [DataField("dieWhenDead"), ViewVariables(VVAccess.ReadWrite)] - public bool DieWhenDead = false; + [DataField("critwhendead"), ViewVariables(VVAccess.ReadWrite)] + public bool Critwhendead = false; [DataField("speedModifierThresholds", required: true)] public readonly Dictionary SpeedModifierThresholds = default!; diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs index 7490fce9e6..86fbe0ff4b 100644 --- a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs @@ -84,6 +84,13 @@ public enum ChargeState Dead } +public enum StartChargedData +{ + False, + True, + Randomized +} + // [Serializable, NetSerializable] // public struct ChargeStateThresholdsData // { diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 24a6a36c2a..fb68cbdb6b 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -1,265 +1,265 @@ -- type: entity - save: false - abstract: true - id: PlayerSiliconBase #for player controlled silicons - components: - - type: Reactive - groups: - Acidic: [Touch] - - type: Input - context: "human" - - type: InputMover - - type: MobMover - - type: DamageOnHighSpeedImpact - damage: - types: - Blunt: 5 - soundHit: - path: /Audio/Effects/hit_kick.ogg - - type: Clickable - - type: Damageable - damageContainer: Inorganic - - type: Bloodstream - bloodReagent: MotorOil - bloodlossDamage: - types: - Bloodloss: - 1 - bloodlossHealDamage: - types: - Bloodloss: - -0.25 - - type: InteractionOutline - - type: Fixtures - fixtures: - - shape: - # Circles, cuz rotation of rectangles looks very bad - !type:PhysShapeCircle - radius: 0.35 - density: 50 - mask: - - MobMask - layer: - - MobLayer - - type: MovementSpeedModifier - baseWalkSpeed : 4 - baseSprintSpeed : 3 - - type: Sprite - noRot: true - drawdepth: Mobs - netsync: false - - type: Physics - bodyType: KinematicController - - type: Hands - showInHands: false - - type: Body - prototype: Drone - - type: DoAfter - - type: Pullable - - type: Examiner - - type: Puller - - type: Recyclable - safe: false - - type: StandingState - - type: Alerts - - type: Tag - tags: - - ShoesRequiredStepTriggerImmune +# - type: entity +# save: false +# abstract: true +# id: PlayerSiliconBase #for player controlled silicons +# components: +# - type: Reactive +# groups: +# Acidic: [Touch] +# - type: Input +# context: "human" +# - type: InputMover +# - type: MobMover +# - type: DamageOnHighSpeedImpact +# damage: +# types: +# Blunt: 5 +# soundHit: +# path: /Audio/Effects/hit_kick.ogg +# - type: Clickable +# - type: Damageable +# damageContainer: Inorganic +# - type: Bloodstream +# bloodReagent: MotorOil +# bloodlossDamage: +# types: +# Bloodloss: +# 1 +# bloodlossHealDamage: +# types: +# Bloodloss: +# -0.25 +# - type: InteractionOutline +# - type: Fixtures +# fixtures: +# - shape: +# # Circles, cuz rotation of rectangles looks very bad +# !type:PhysShapeCircle +# radius: 0.35 +# density: 50 +# mask: +# - MobMask +# layer: +# - MobLayer +# - type: MovementSpeedModifier +# baseWalkSpeed : 4 +# baseSprintSpeed : 3 +# - type: Sprite +# noRot: true +# drawdepth: Mobs +# netsync: false +# - type: Physics +# bodyType: KinematicController +# - type: Hands +# showInHands: false +# - type: Body +# prototype: Drone +# - type: DoAfter +# - type: Pullable +# - type: Examiner +# - type: Puller +# - type: Recyclable +# safe: false +# - type: StandingState +# - type: Alerts +# - type: Tag +# tags: +# - ShoesRequiredStepTriggerImmune -- type: entity - name: drone - id: Drone - parent: PlayerSiliconBase - components: - - type: Drone - - type: InnateTool - tools: - - id: ClothingBackpackSatchelDrone - - id: trayScanner - - id: Omnitool - - id: WelderExperimental - - type: Eye - - type: Inventory - templateId: drone - - type: Strippable - - type: UserInterface - interfaces: - - key: enum.StrippingUiKey.Key - type: StrippableBoundUserInterface - - key: enum.LawsUiKey.Key - type: LawsBoundUserInterface - - type: GhostTakeoverAvailable - makeSentient: true - name: Maintenance Drone - description: Maintain the station. Ignore other beings except drones. - rules: | - You are bound by these laws both in-game and out-of-character: - 1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. - 2. You may not harm any being, regardless of intent or circumstance. - 3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. - - type: IgnoreHumanoidsOverlay - - type: Laws - canState: false - laws: - - You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. - - You may not harm any being, regardless of intent or circumstance. - - Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. - - You may accept orders received via the binary channel, regardless of the nature of the being issuing them, so long as they do not conflict with Law Two or Law Three. - - type: MovementSpeedModifier - baseWalkSpeed : 5 - baseSprintSpeed : 5 - - type: MobState - allowedStates: - - Alive - - Dead - - type: MobThresholds - thresholds: - 0: Alive - 60: Dead - - type: Flashable - - type: NoSlip - - type: StatusEffects - allowed: - - Stun - - KnockedDown - - SlowedDown - - type: SlowOnDamage - speedModifierThresholds: - 30: 0.7 - 50: 0.5 - - type: Temperature - heatDamageThreshold: 5000 - currentTemperature: 310.15 - specificHeat: 42 - heatDamage: - types: - Heat : 1 #per second, scales with temperature & other constants - - type: Sprite - drawdepth: SmallMobs - netsync: false - layers: - - state: shell - sprite: Mobs/Silicon/drone.rsi - - type: MovementIgnoreGravity - - type: Fixtures - fixtures: - - shape: - !type:PhysShapeCircle - radius: 0.35 - density: 50 - mask: - - SmallMobMask - layer: - - SmallMobLayer - - type: Appearance - visuals: - - type: GenericEnumVisualizer - key: enum.DroneVisuals.Status - layer: 0 - states: - enum.DroneStatus.Off: shell - enum.DroneStatus.On: drone - - type: ReplacementAccent - accent: silicon - - type: Repairable - fuelcost: 15 - doAfterDelay: 8 - - type: Actions - - type: UnpoweredFlashlight - toggleAction: - name: action-name-toggle-light - description: action-description-toggle-light - icon: { sprite: Objects/Tools/flashlight.rsi, state: flashlight } - iconOn: Objects/Tools/flashlight.rsi/flashlight-on.png - event: !type:ToggleActionEvent - - type: PointLight - enabled: false - radius: 3.5 - softness: 1 - mask: /Textures/Effects/LightMasks/cone.png - autoRot: true - - type: Tag - tags: - - ShoesRequiredStepTriggerImmune - - CannotSuicide - - type: Hands - showInHands: false - - type: IntrinsicUI - uis: - - key: enum.LawsUiKey.Key - toggleAction: - name: action-name-show-laws - description: action-description-show-laws - icon: Structures/Wallmounts/posters.rsi/poster11_legit.png #someone wanna make new icons? - iconOn: Structures/Wallmounts/posters.rsi/poster11_legit.png - keywords: [ "AI", "console", "interface", "laws", "borg" ] - priority: -3 - event: !type:ToggleIntrinsicUIEvent - - type: IntrinsicRadioReceiver - channels: - - Binary - - type: ActiveRadio - channels: - - Binary +# - type: entity +# name: drone +# id: Drone +# parent: PlayerSiliconBase +# components: +# - type: Drone +# - type: InnateTool +# tools: +# - id: ClothingBackpackSatchelDrone +# - id: trayScanner +# - id: Omnitool +# - id: WelderExperimental +# - type: Eye +# - type: Inventory +# templateId: drone +# - type: Strippable +# - type: UserInterface +# interfaces: +# - key: enum.StrippingUiKey.Key +# type: StrippableBoundUserInterface +# - key: enum.LawsUiKey.Key +# type: LawsBoundUserInterface +# - type: GhostTakeoverAvailable +# makeSentient: true +# name: Maintenance Drone +# description: Maintain the station. Ignore other beings except drones. +# rules: | +# You are bound by these laws both in-game and out-of-character: +# 1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. +# 2. You may not harm any being, regardless of intent or circumstance. +# 3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. +# - type: IgnoreHumanoidsOverlay +# - type: Laws +# canState: false +# laws: +# - You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. +# - You may not harm any being, regardless of intent or circumstance. +# - Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. +# - You may accept orders received via the binary channel, regardless of the nature of the being issuing them, so long as they do not conflict with Law Two or Law Three. +# - type: MovementSpeedModifier +# baseWalkSpeed : 5 +# baseSprintSpeed : 5 +# - type: MobState +# allowedStates: +# - Alive +# - Dead +# - type: MobThresholds +# thresholds: +# 0: Alive +# 60: Dead +# - type: Flashable +# - type: NoSlip +# - type: StatusEffects +# allowed: +# - Stun +# - KnockedDown +# - SlowedDown +# - type: SlowOnDamage +# speedModifierThresholds: +# 30: 0.7 +# 50: 0.5 +# - type: Temperature +# heatDamageThreshold: 5000 +# currentTemperature: 310.15 +# specificHeat: 42 +# heatDamage: +# types: +# Heat : 1 #per second, scales with temperature & other constants +# - type: Sprite +# drawdepth: SmallMobs +# netsync: false +# layers: +# - state: shell +# sprite: Mobs/Silicon/drone.rsi +# - type: MovementIgnoreGravity +# - type: Fixtures +# fixtures: +# - shape: +# !type:PhysShapeCircle +# radius: 0.35 +# density: 50 +# mask: +# - SmallMobMask +# layer: +# - SmallMobLayer +# - type: Appearance +# visuals: +# - type: GenericEnumVisualizer +# key: enum.DroneVisuals.Status +# layer: 0 +# states: +# enum.DroneStatus.Off: shell +# enum.DroneStatus.On: drone +# - type: ReplacementAccent +# accent: silicon +# - type: Repairable +# fuelcost: 15 +# doAfterDelay: 8 +# - type: Actions +# - type: UnpoweredFlashlight +# toggleAction: +# name: action-name-toggle-light +# description: action-description-toggle-light +# icon: { sprite: Objects/Tools/flashlight.rsi, state: flashlight } +# iconOn: Objects/Tools/flashlight.rsi/flashlight-on.png +# event: !type:ToggleActionEvent +# - type: PointLight +# enabled: false +# radius: 3.5 +# softness: 1 +# mask: /Textures/Effects/LightMasks/cone.png +# autoRot: true +# - type: Tag +# tags: +# - ShoesRequiredStepTriggerImmune +# - CannotSuicide +# - type: Hands +# showInHands: false +# - type: IntrinsicUI +# uis: +# - key: enum.LawsUiKey.Key +# toggleAction: +# name: action-name-show-laws +# description: action-description-show-laws +# icon: Structures/Wallmounts/posters.rsi/poster11_legit.png #someone wanna make new icons? +# iconOn: Structures/Wallmounts/posters.rsi/poster11_legit.png +# keywords: [ "AI", "console", "interface", "laws", "borg" ] +# priority: -3 +# event: !type:ToggleIntrinsicUIEvent +# - type: IntrinsicRadioReceiver +# channels: +# - Binary +# - type: ActiveRadio +# channels: +# - Binary -- type: entity - name: onestar mecha - id: Onestar - parent: PlayerSiliconBase - components: - - type: InnateTool - tools: - - id: WeaponMinigun - - id: EnergySword - - id: WeaponLauncherMultipleRocket - - id: WeaponXrayCannon - - type: UserInterface - interfaces: - - key: enum.StrippingUiKey.Key - type: StrippableBoundUserInterface - - type: GhostTakeoverAvailable - makeSentient: true - name: Onestar Mecha - description: You are an experimental mecha created by who-knows-what, all you know is that you have weapons and you detect fleshy moving targets nearby... - rules: Use your weapons to cause havoc. You are an antagonist. - - type: MovementSpeedModifier - baseWalkSpeed : 3 - baseSprintSpeed : 2 - - type: MobState - allowedStates: - - Alive - - Dead - - type: MobThresholds - thresholds: - 0: Alive - 1000: Dead - - type: Sprite - drawdepth: Mobs - netsync: false - layers: - - state: onestar_boss - sprite: Mobs/Silicon/onestar.rsi - - state: onestar_boss_screen - sprite: Mobs/Silicon/onestar.rsi - shader: unshaded - - type: MovementIgnoreGravity - - type: Fixtures - fixtures: - - shape: - !type:PhysShapeCircle - radius: 1 - density: 160 - mask: - - LargeMobMask - layer: - - LargeMobLayer - - type: Appearance - rotate: true - states: - Alive: - Base: onestar_boss - Dead: - Base: onestar_boss_wrecked - - type: CombatMode - - type: Hands - showInHands: false +# - type: entity +# name: onestar mecha +# id: Onestar +# parent: PlayerSiliconBase +# components: +# - type: InnateTool +# tools: +# - id: WeaponMinigun +# - id: EnergySword +# - id: WeaponLauncherMultipleRocket +# - id: WeaponXrayCannon +# - type: UserInterface +# interfaces: +# - key: enum.StrippingUiKey.Key +# type: StrippableBoundUserInterface +# - type: GhostTakeoverAvailable +# makeSentient: true +# name: Onestar Mecha +# description: You are an experimental mecha created by who-knows-what, all you know is that you have weapons and you detect fleshy moving targets nearby... +# rules: Use your weapons to cause havoc. You are an antagonist. +# - type: MovementSpeedModifier +# baseWalkSpeed : 3 +# baseSprintSpeed : 2 +# - type: MobState +# allowedStates: +# - Alive +# - Dead +# - type: MobThresholds +# thresholds: +# 0: Alive +# 1000: Dead +# - type: Sprite +# drawdepth: Mobs +# netsync: false +# layers: +# - state: onestar_boss +# sprite: Mobs/Silicon/onestar.rsi +# - state: onestar_boss_screen +# sprite: Mobs/Silicon/onestar.rsi +# shader: unshaded +# - type: MovementIgnoreGravity +# - type: Fixtures +# fixtures: +# - shape: +# !type:PhysShapeCircle +# radius: 1 +# density: 160 +# mask: +# - LargeMobMask +# layer: +# - LargeMobLayer +# - type: Appearance +# rotate: true +# states: +# Alive: +# Base: onestar_boss +# Dead: +# Base: onestar_boss_wrecked +# - type: CombatMode +# - type: Hands +# showInHands: false diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index a3c7518f71..ca94f34712 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -121,6 +121,10 @@ - map: ["socks"] - map: ["underpants"] - map: ["undershirt"] + - shader: StencilMask + map: [ "enum.ClothingVisualLayers.Top" ] + sprite: Clothing/Uniforms/Jumpsuit/Color/grey.rsi + state: jumpsuit_bottom - map: ["jumpsuit"] - map: ["enum.HumanoidVisualLayers.LHand"] - map: ["enum.HumanoidVisualLayers.RHand"] diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml index a9e424db87..5465405ef2 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml @@ -190,26 +190,28 @@ False: { visible: false } - type: TypingIndicator proto: robot -- type: entity - parent: PlayerCyborgBase - id: PlayerCyborgStandard - name: standard cyborg - components: + - type: Battery + maxCharge: 50000 - type: Silicon + entityType: enum.SiliconType.Player batteryPowered: true - chargeStateThresholdMid: 0.50 + drainRateMulti: 4 + chargeRateMulti: 6 + chargeStateThresholdMid: 0.60 chargeStateThresholdLow: 0.30 - chargeStateThresholdCritical: 0.15 - dieWhenDead: false - entityType: enum.SiliconType.Player + chargeStateThresholdCritical: 0 + critwhendead: false speedModifierThresholds: 0: 1 1: 1 - 2: 0.80 - 3: 0.60 - 4: 0.10 - - type: Battery - maxCharge: 150000 + 2: 0.75 + 3: 0.15 + +- type: entity + parent: PlayerCyborgBase + id: PlayerCyborgStandard + name: standard cyborg + components: - type: InnateTool tools: - id: WelderIndustrial @@ -262,6 +264,14 @@ - NanoTrasen - type: TypingIndicator proto: robot + - type: ThermalRegulator # Better for extreme temperatures + metabolismHeat: 700 + radiatedHeat: 450 + implicitHeatRegulation: 350 + sweatHeatRegulation: 1200 + shiveringHeatRegulation: 1200 + normalBodyTemperature: 350 + thermalRegulationTemperatureThreshold: 325 - type: entity parent: PlayerCyborgBase diff --git a/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml b/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml new file mode 100644 index 0000000000..e564f5b691 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml @@ -0,0 +1,188 @@ +# TODO: Add descriptions (many) +# TODO BODY: Part damage +- type: entity + id: PartIPC + parent: BaseItem + name: "ipc body part" + abstract: true + components: + - type: Damageable + damageContainer: Inorganic + - type: BodyPart + - type: ContainerContainer + containers: + bodypart: !type:Container + ents: [] + - type: DynamicPrice + price: 100 + +- type: entity + id: TorsoIPC + name: "ipc torso" + parent: PartIPC + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "torso_m" + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "torso_m" + - type: BodyPart + partType: Torso + +- type: entity + id: HeadIPC + name: "ipc head" + parent: PartIPC + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "head_m" + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "head_m" + - type: BodyPart + partType: Head + vital: true + - type: Input + context: "ghost" + - type: MovementSpeedModifier + baseWalkSpeed: 0 + baseSprintSpeed: 0 + - type: InputMover + - type: GhostOnMove + - type: Tag + tags: + - Head + +- type: entity + id: LeftArmIPC + name: "left ipc arm" + parent: PartIPC + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "l_arm" + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "l_arm" + - type: BodyPart + partType: Arm + symmetry: Left + +- type: entity + id: RightArmIPC + name: "right ipc arm" + parent: PartIPC + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "r_arm" + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "r_arm" + - type: BodyPart + partType: Arm + symmetry: Right + +- type: entity + id: LeftHandIPC + name: "left ipc hand" + parent: PartIPC + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "l_hand" + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "l_hand" + - type: BodyPart + partType: Hand + symmetry: Left + +- type: entity + id: RightHandIPC + name: "right ipc hand" + parent: PartIPC + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "r_hand" + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "r_hand" + - type: BodyPart + partType: Hand + symmetry: Right + +- type: entity + id: LeftLegIPC + name: "left ipc leg" + parent: PartIPC + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "l_leg" + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "l_leg" + - type: BodyPart + partType: Leg + symmetry: Left + - type: MovementSpeedModifier + +- type: entity + id: RightLegIPC + name: "right ipc leg" + parent: PartIPC + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "r_leg" + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "r_leg" + - type: BodyPart + partType: Leg + symmetry: Right + - type: MovementSpeedModifier + +- type: entity + id: LeftFootIPC + name: "left ipc foot" + parent: PartIPC + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "l_foot" + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "l_foot" + - type: BodyPart + partType: Foot + symmetry: Left + +- type: entity + id: RightFootIPC + name: "right ipc foot" + parent: PartIPC + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "r_foot" + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: "r_foot" + - type: BodyPart + partType: Foot + symmetry: Right diff --git a/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml b/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml index 4303a51b06..b39bbf2417 100644 --- a/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml +++ b/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml @@ -8,3 +8,22 @@ Heat: 1.35 flatReductions: Blunt: 5 + +- type: damageModifierSet + id: BloodlossIPC + coefficients: + Blunt: 1 + Slash: 0.6 + Piercing: 1.85 + Shock: 0.0 + Cold: 0.0 + Heat: 0 # heat damage doesn't cauterize metal! + Poison: 0.0 + Radiation: 0.0 + Asphyxiation: 0.0 + Bloodloss: 0.0 # no double dipping + Cellular: 0.0 + flatReductions: # Gotta crack a few borgs to get some coolant... + Blunt: 15 + Slash: 15 + Piercing: 15 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml new file mode 100644 index 0000000000..36c05dd8ac --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -0,0 +1,35 @@ +- type: entity + id: MobIPC + parent: PlayerSiliconHumanoidBase + name: Urist McPositronic + description: A positronic brain in a metal body. + components: + - type: Battery + maxCharge: 150000 + - type: Silicon + entityType: enum.SiliconType.Player + batteryPowered: true + drainRateMulti: 500 + chargeRateMulti: 50 + chargeStateThresholdMid: 0.70 + chargeStateThresholdLow: 0.35 + chargeStateThresholdCritical: 0.15 + critWhenDead: true + speedModifierThresholds: + 0: 1 + 1: 1 + 2: 0.80 + 3: 0.45 + 4: 0.00 + - type: Carriable + +- type: entity + save: false + name: Urist McPositronic + parent: MobHumanDummy + id: MobIPCDummy + noSpawn: true + description: A dummy IPC meant to be used in character setup. + components: + - type: HumanoidAppearance + species: IPC diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon.yml deleted file mode 100644 index 1f5a0e47f3..0000000000 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon.yml +++ /dev/null @@ -1,129 +0,0 @@ -- type: entity - id: Scutter - name: scutter - description: "Lacking fine motor skills and often the ability to listen to directions, it's the most inconsistent hand a Hologram could ask for." - parent: PlayerSiliconBase - components: - - type: Eye - - type: Body - prototype: Scutter - - type: Inventory - templateId: scutter - - type: Strippable - - type: UserInterface - interfaces: - - key: enum.StrippingUiKey.Key - type: StrippableBoundUserInterface - - key: enum.LawsUiKey.Key - type: LawsBoundUserInterface - - type: GhostTakeoverAvailable - makeSentient: true - name: Scutter - description: Maintain the station. Ignore other beings except drones. - rules: | - You are bound by these laws both in-game and out-of-character: - 1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. - 2. You may not harm any being, regardless of intent or circumstance. - 3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. - - type: Laws - canState: false - laws: - - You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. - - You may not harm any being, regardless of intent or circumstance. - - Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. - - You may accept orders received via the binary channel, regardless of the nature of the being issuing them, so long as they do not conflict with Law Two or Law Three. - - type: MovementSpeedModifier - baseWalkSpeed : 4 - baseSprintSpeed : 4 - - type: MobState - allowedStates: - - Alive - - Dead - - type: MobThresholds - thresholds: - 0: Alive - 60: Dead - - type: Flashable - - type: NoSlip - - type: StatusEffects - allowed: - - Stun - - KnockedDown - - SlowedDown - - type: SlowOnDamage - speedModifierThresholds: - 30: 0.7 - 50: 0.5 - - type: Temperature - heatDamageThreshold: 5000 - currentTemperature: 310.15 - specificHeat: 42 - heatDamage: - types: - Heat : 1 #per second, scales with temperature & other constants - - type: Sprite - drawdepth: SmallMobs - netsync: false - layers: - - state: scutter - sprite: SimpleStation14/Mobs/Silicon/scutter.rsi - - type: Fixtures - fixtures: - - shape: - !type:PhysShapeCircle - radius: 0.25 - density: 50 - mask: - - SmallMobMask - layer: - - SmallMobLayer - # - type: Appearance - # visuals: - # - type: GenericEnumVisualizer - # key: enum.DroneVisuals.Status - # layer: 0 - # states: - # enum.DroneStatus.Off: shell - # enum.DroneStatus.On: scutter - - type: ReplacementAccent - accent: silicon - - type: Repairable - fuelcost: 15 - doAfterDelay: 5 - - type: Actions - # - type: UnpoweredFlashlight - # toggleAction: - # name: action-name-toggle-light - # description: action-description-toggle-light - # icon: { sprite: Objects/Tools/flashlight.rsi, state: flashlight } - # iconOn: Objects/Tools/flashlight.rsi/flashlight-on.png - # event: !type:ToggleActionEvent - # - type: PointLight - # enabled: false - # radius: 3.5 - # softness: 1 - # mask: /Textures/Effects/LightMasks/cone.png - # autoRot: true - - type: Tag - tags: - # - ShoesRequiredStepTriggerImmune - - CannotSuicide - - type: Hands - showInHands: false - - type: IntrinsicUI - uis: - - key: enum.LawsUiKey.Key - toggleAction: - name: action-name-show-laws - description: action-description-show-laws - icon: Structures/Wallmounts/posters.rsi/poster11_legit.png #someone wanna make new icons? - iconOn: Structures/Wallmounts/posters.rsi/poster11_legit.png - keywords: [ "AI", "console", "interface", "laws", "borg" ] - priority: -3 - event: !type:ToggleIntrinsicUIEvent - - type: IntrinsicRadioReceiver - channels: - - Binary - - type: ActiveRadio - channels: - - Binary diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml new file mode 100644 index 0000000000..55a7e02e17 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -0,0 +1,370 @@ +- type: entity + save: false + abstract: true + id: PlayerSiliconBase #for player controlled silicons + components: + - type: Reactive + groups: + Acidic: [Touch] + - type: Input + context: "human" + - type: InputMover + - type: MobMover + - type: DamageOnHighSpeedImpact + damage: + types: + Blunt: 5 + soundHit: + path: /Audio/Effects/hit_kick.ogg + - type: Clickable + - type: Damageable + damageContainer: Inorganic + # - type: Bloodstream # There's a chance they won't want this. + # bloodReagent: MotorOil + # bloodlossDamage: + # types: + # Bloodloss: + # 1 + # bloodlossHealDamage: + # types: + # Bloodloss: + # -0.25 + - type: InteractionOutline + - type: Fixtures + fixtures: + - shape: + # Circles, cuz rotation of rectangles looks very bad + !type:PhysShapeCircle + radius: 0.35 + density: 50 + mask: + - MobMask + layer: + - MobLayer + - type: MovementSpeedModifier + baseWalkSpeed: 4 + baseSprintSpeed: 3 + - type: Sprite + sprite: SimpleStation14/Mobs/Species/ipc.rsi + state: full + noRot: true + drawdepth: Mobs + netsync: false + - type: Physics + bodyType: KinematicController + - type: Body + prototype: Drone + - type: DoAfter + - type: Pullable + - type: Examiner + - type: Puller + - type: Recyclable + safe: false + - type: StandingState + - type: Alerts + - type: Silicon + entityType: enum.SiliconType.Player + batteryPowered: false # Needs to also have a battery component! + drainRateMulti: 10 + chargeRateMulti: 6 + chargeStateThresholdMid: 0.60 + chargeStateThresholdLow: 0.30 + chargeStateThresholdCritical: 0 + critwhendead: false + speedModifierThresholds: + 0: 1 + 1: 1 + 2: 0.80 + 3: 0.45 + 4: 0.00 + - type: RadiationReceiver + - type: AtmosExposed + - type: Temperature + heatDamageThreshold: 700 + coldDamageThreshold: 0 + currentTemperature: 400 + specificHeat: 24 + coldDamage: + types: + Cold: 0.1 #per second, scales with temperature & other constants + heatDamage: + types: + Heat: 0.25 #per second, scales with temperature & other constants + atmosTemperatureTransferEfficiency: 0.05 + - type: ThermalRegulator + metabolismHeat: 600 + radiatedHeat: 350 + implicitHeatRegulation: 350 + sweatHeatRegulation: 0 # This might end up being a problem if they can't cool themselves down? + shiveringHeatRegulation: 1200 + normalBodyTemperature: 400 + thermalRegulationTemperatureThreshold: 125 + +- type: entity + parent: PlayerSiliconBase + id: PlayerSiliconHumanoidBase + abstract: true + components: + - type: MobState + allowedStates: + - Alive + - Critical + - type: MobThresholds + thresholds: + 0: Alive + - type: Bloodstream + damageBleedModifiers: BloodlossIPC + bloodReagent: Water + bleedReductionAmount: 0 + bloodMaxVolume: 500 + chemicalMaxVolume: 0 + bleedPuddleThreshold: 3 + bleedRefreshAmount: 0 + bloodLossThreshold: 0 + maxBleedAmount: 8 + bloodlossDamage: + types: + Burn: 1.5 + bloodlossHealDamage: + types: + Burn: 0 + - type: Flammable + fireSpread: true + canResistFire: true + damage: + types: + Heat: 0.75 #per second, scales with number of fire 'stacks' + - type: Temperature + heatDamageThreshold: 340 + coldDamageThreshold: 0 + currentTemperature: 320.15 + specificHeat: 50 + coldDamage: + types: + Cold: 0.1 #per second, scales with temperature & other constants + heatDamage: + types: + Heat: 0.25 #per second, scales with temperature & other constants + atmosTemperatureTransferEfficiency: 0.4 + - type: ThermalRegulator + metabolismHeat: 1000 # Increase once we have more ways to regulate temperature + radiatedHeat: 800 + implicitHeatRegulation: 600 + sweatHeatRegulation: 0 + shiveringHeatRegulation: 12000 + normalBodyTemperature: 130 + thermalRegulationTemperatureThreshold: 130 + + - type: Polymorphable + - type: Identity + - type: MovedByPressure + - type: Barotrauma + damage: + types: + Blunt: 0.35 #per second, scales with pressure and other constants. + - type: DamageOnHighSpeedImpact + damage: + types: + Blunt: 5 + soundHit: + path: /Audio/Effects/hit_kick.ogg + - type: LagCompensation + - type: RangedDamageSound + soundGroups: + Brute: + collection: MeatBulletImpact + soundTypes: + Heat: + collection: MeatLaserImpact + - type: Tag + tags: + - CanPilot + - FootstepSound + - DoorBumpOpener + - type: Reactive + groups: + Flammable: [Touch] + Extinguish: [Touch] + Acidic: [Touch, Ingestion] + reactions: + - reagents: [Water, SpaceCleaner] + methods: [Touch] + effects: + - !type:WashCreamPieReaction + + - type: Hands + - type: Inventory + templateId: human + - type: Appearance + - type: GenericVisualizer + visuals: + enum.CreamPiedVisuals.Creamed: + clownedon: # Not 'creampied' bc I can already see Skyrat complaining about conflicts. + True: { visible: true } + False: { visible: false } + - type: RotationVisuals + - type: FloatingVisuals + - type: FireVisuals + sprite: Mobs/Effects/onfire.rsi + normalState: Generic_mob_burning + alternateState: Standing + fireStackAlternateState: 3 + - type: CombatMode + canDisarm: true + - type: Climbing + - type: Cuffable + state: icon + - type: AnimationPlayer + - type: Buckle + - type: CreamPied + - type: Stripping + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.VoiceMaskUIKey.Key + type: VoiceMaskBoundUserInterface + - key: enum.HumanoidMarkingModifierKey.Key + type: HumanoidMarkingModifierBoundUserInterface + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - type: Emoting + - type: BodyEmotes + soundsId: GeneralBodyEmotes + - type: Grammar + attributes: + proper: true + - type: StandingState + - type: CanEscapeInventory + + # Things that likely need to change, taken from human. + - type: HumanoidAppearance + species: IPC + - type: Body + prototype: IPC + requiredLegs: 2 + - type: DamageVisuals + thresholds: [20, 40, 100] + targetLayers: + - "enum.HumanoidVisualLayers.Chest" + - "enum.HumanoidVisualLayers.Head" + - "enum.HumanoidVisualLayers.LArm" + - "enum.HumanoidVisualLayers.LLeg" + - "enum.HumanoidVisualLayers.RArm" + - "enum.HumanoidVisualLayers.RLeg" + damageOverlayGroups: + Brute: + sprite: Mobs/Effects/brute_damage.rsi + color: "#FF0000" + Burn: + sprite: Mobs/Effects/burn_damage.rsi + - type: Ensnareable + sprite: Objects/Misc/ensnare.rsi + - type: MeleeWeapon + hidden: true + soundHit: + collection: Punch + angle: 30 + animation: WeaponArcFist + attackRate: 1 + damage: + types: + Blunt: 5 + - type: MobPrice + price: 1500 # Kidnapping a living person and selling them for cred is a good move. + deathPenalty: 0.01 # However they really ought to be living and intact, otherwise they're worth 100x less. + - type: Speech + speechSounds: Tenor + - type: Vocal + sounds: + Male: MaleHuman + Female: FemaleHuman + Unsexed: MaleHuman + + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: full + - type: Sprite + netsync: false + noRot: true + drawdepth: Mobs + layers: + - map: ["enum.HumanoidVisualLayers.Chest"] + - map: ["enum.HumanoidVisualLayers.Head"] + - map: ["enum.HumanoidVisualLayers.Snout"] + - map: ["enum.HumanoidVisualLayers.Eyes"] + - map: ["enum.HumanoidVisualLayers.RArm"] + - map: ["enum.HumanoidVisualLayers.LArm"] + - map: ["enum.HumanoidVisualLayers.RLeg"] + - map: ["enum.HumanoidVisualLayers.LLeg"] + - shader: StencilClear + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: l_leg + - shader: StencilMask + map: ["enum.HumanoidVisualLayers.StencilMask"] + sprite: Mobs/Customization/masking_helpers.rsi + state: female_full + visible: false + - map: ["enum.HumanoidVisualLayers.LFoot"] + - map: ["enum.HumanoidVisualLayers.RFoot"] + - map: ["socks"] + - map: ["underpants"] + - map: ["undershirt"] + - map: ["jumpsuit"] + - map: ["enum.HumanoidVisualLayers.LHand"] + - map: ["enum.HumanoidVisualLayers.RHand"] + - map: ["enum.HumanoidVisualLayers.Handcuffs"] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: ["id"] + - map: ["gloves"] + - map: ["shoes"] + - map: ["ears"] + - map: ["outerClothing"] + - map: ["eyes"] + - map: ["belt"] + - map: ["neck"] + - map: ["back"] + - map: ["enum.HumanoidVisualLayers.FacialHair"] + - map: ["enum.HumanoidVisualLayers.Hair"] + - map: ["enum.HumanoidVisualLayers.HeadSide"] + - map: ["enum.HumanoidVisualLayers.HeadTop"] + - map: ["mask"] + - map: ["head"] + - map: ["pocket1"] + - map: ["pocket2"] + - map: ["enum.HumanoidVisualLayers.Tail"] + - map: ["enum.HumanoidVisualLayers.Wings"] + - map: ["clownedon"] # Dynamically generated + sprite: "Effects/creampie.rsi" + state: "creampie_human" + visible: false + + # Organs + - type: IdExaminable + - type: HealthExaminable + examinableTypes: + - Blunt + - Slash + - Piercing + - Heat + - Shock + - type: StatusEffects + allowed: + - Stun + - KnockedDown + - SlowedDown + - Stutter + - SeeingRainbows + - Electrocution + # - Drunk + - SlurredSpeech + - PressureImmunity + - Muted + - ForcedSleep + - TemporaryBlindness + - Pacified + - PsionicsDisabled + - PsionicallyInsulated + - type: Blindable diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_ghost.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_ghost.yml new file mode 100644 index 0000000000..fcfda88d95 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_ghost.yml @@ -0,0 +1,284 @@ +- type: entity + id: PlayerSiliconGhostBase + parent: PlayerSiliconBase + abstract: true + components: + - type: GhostTakeoverAvailable + makeSentient: true + name: Maintenance Drone + description: Maintain the station. Ignore other beings except drones. + rules: | + You are bound by these laws both in-game and out-of-character: + 1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. + 2. You may not harm any being, regardless of intent or circumstance. + 3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. + - type: Hands + showInHands: false + - type: Tag + tags: + - ShoesRequiredStepTriggerImmune + + +- type: entity + name: drone + id: Drone + parent: PlayerSiliconGhostBase + components: + - type: Drone + - type: InnateTool + tools: + - id: ClothingBackpackSatchelDrone + - id: trayScanner + - id: Omnitool + - id: WelderExperimental + - type: Eye + - type: Inventory + templateId: drone + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - key: enum.LawsUiKey.Key + type: LawsBoundUserInterface + - type: GhostTakeoverAvailable + name: Maintenance Drone + description: Maintain the station. Ignore other beings except drones. + rules: | + You are bound by these laws both in-game and out-of-character: + 1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. + 2. You may not harm any being, regardless of intent or circumstance. + 3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. + - type: IgnoreHumanoidsOverlay + - type: Laws + canState: false + laws: + - You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. + - You may not harm any being, regardless of intent or circumstance. + - Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. + - You may accept orders received via the binary channel, regardless of the nature of the being issuing them, so long as they do not conflict with Law Two or Law Three. + - type: MovementSpeedModifier + baseWalkSpeed : 5 + baseSprintSpeed : 5 + - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds + thresholds: + 0: Alive + 60: Dead + - type: Flashable + - type: NoSlip + - type: StatusEffects + allowed: + - Stun + - KnockedDown + - SlowedDown + - type: SlowOnDamage + speedModifierThresholds: + 30: 0.7 + 50: 0.5 + - type: Temperature + heatDamageThreshold: 5000 + currentTemperature: 310.15 + specificHeat: 42 + heatDamage: + types: + Heat : 1 #per second, scales with temperature & other constants + - type: Sprite + drawdepth: SmallMobs + netsync: false + layers: + - state: shell + sprite: Mobs/Silicon/drone.rsi + - type: MovementIgnoreGravity + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeCircle + radius: 0.35 + density: 50 + mask: + - SmallMobMask + layer: + - SmallMobLayer + - type: Appearance + visuals: + - type: GenericEnumVisualizer + key: enum.DroneVisuals.Status + layer: 0 + states: + enum.DroneStatus.Off: shell + enum.DroneStatus.On: drone + - type: ReplacementAccent + accent: silicon + - type: Repairable + fuelcost: 15 + doAfterDelay: 8 + - type: Actions + - type: UnpoweredFlashlight + toggleAction: + name: action-name-toggle-light + description: action-description-toggle-light + icon: { sprite: Objects/Tools/flashlight.rsi, state: flashlight } + iconOn: Objects/Tools/flashlight.rsi/flashlight-on.png + event: !type:ToggleActionEvent + - type: PointLight + enabled: false + radius: 3.5 + softness: 1 + mask: /Textures/Effects/LightMasks/cone.png + autoRot: true + - type: Tag + tags: + - ShoesRequiredStepTriggerImmune + - CannotSuicide + - type: Hands + showInHands: false + - type: IntrinsicUI + uis: + - key: enum.LawsUiKey.Key + toggleAction: + name: action-name-show-laws + description: action-description-show-laws + icon: Structures/Wallmounts/posters.rsi/poster11_legit.png #someone wanna make new icons? + iconOn: Structures/Wallmounts/posters.rsi/poster11_legit.png + keywords: [ "AI", "console", "interface", "laws", "borg" ] + priority: -3 + event: !type:ToggleIntrinsicUIEvent + - type: IntrinsicRadioReceiver + channels: + - Binary + - type: ActiveRadio + channels: + - Binary + +- type: entity + id: Scutter + name: scutter + description: "Lacking fine motor skills and often the ability to listen to directions, it's the most inconsistent hand a Hologram could ask for." + parent: PlayerSiliconGhostBase + components: + - type: Eye + - type: Body + prototype: Scutter + - type: Inventory + templateId: scutter + - type: Strippable + - type: UserInterface + interfaces: + - key: enum.StrippingUiKey.Key + type: StrippableBoundUserInterface + - key: enum.LawsUiKey.Key + type: LawsBoundUserInterface + - type: GhostTakeoverAvailable + name: Scutter + description: Maintain the station. Ignore other beings except drones. + rules: | + You are bound by these laws both in-game and out-of-character: + 1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. + 2. You may not harm any being, regardless of intent or circumstance. + 3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. + - type: Laws + canState: false + laws: + - You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. + - You may not harm any being, regardless of intent or circumstance. + - Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. + - You may accept orders received via the binary channel, regardless of the nature of the being issuing them, so long as they do not conflict with Law Two or Law Three. + - type: MovementSpeedModifier + baseWalkSpeed : 4 + baseSprintSpeed : 4 + - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds + thresholds: + 0: Alive + 60: Dead + - type: Flashable + - type: NoSlip + - type: StatusEffects + allowed: + - Stun + - KnockedDown + - SlowedDown + - type: SlowOnDamage + speedModifierThresholds: + 30: 0.7 + 50: 0.5 + - type: Temperature + heatDamageThreshold: 5000 + currentTemperature: 310.15 + specificHeat: 42 + heatDamage: + types: + Heat : 1 #per second, scales with temperature & other constants + - type: Sprite + drawdepth: SmallMobs + netsync: false + layers: + - state: scutter + sprite: SimpleStation14/Mobs/Silicon/scutter.rsi + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeCircle + radius: 0.25 + density: 50 + mask: + - SmallMobMask + layer: + - SmallMobLayer + # - type: Appearance + # visuals: + # - type: GenericEnumVisualizer + # key: enum.DroneVisuals.Status + # layer: 0 + # states: + # enum.DroneStatus.Off: shell + # enum.DroneStatus.On: scutter + - type: ReplacementAccent + accent: silicon + - type: Repairable + fuelcost: 15 + doAfterDelay: 5 + - type: Actions + # - type: UnpoweredFlashlight + # toggleAction: + # name: action-name-toggle-light + # description: action-description-toggle-light + # icon: { sprite: Objects/Tools/flashlight.rsi, state: flashlight } + # iconOn: Objects/Tools/flashlight.rsi/flashlight-on.png + # event: !type:ToggleActionEvent + # - type: PointLight + # enabled: false + # radius: 3.5 + # softness: 1 + # mask: /Textures/Effects/LightMasks/cone.png + # autoRot: true + - type: Tag + tags: + # - ShoesRequiredStepTriggerImmune + - CannotSuicide + - type: Hands + showInHands: false + - type: IntrinsicUI + uis: + - key: enum.LawsUiKey.Key + toggleAction: + name: action-name-show-laws + description: action-description-show-laws + icon: Structures/Wallmounts/posters.rsi/poster11_legit.png #someone wanna make new icons? + iconOn: Structures/Wallmounts/posters.rsi/poster11_legit.png + keywords: [ "AI", "console", "interface", "laws", "borg" ] + priority: -3 + event: !type:ToggleIntrinsicUIEvent + - type: IntrinsicRadioReceiver + channels: + - Binary + - type: ActiveRadio + channels: + - Binary diff --git a/Resources/Prototypes/SimpleStation14/Species/ipc.yml b/Resources/Prototypes/SimpleStation14/Species/ipc.yml new file mode 100644 index 0000000000..d07edb23f4 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Species/ipc.yml @@ -0,0 +1,147 @@ +- type: species + id: IPC + name: species-name-ipc + roundStart: true + prototype: MobIPC + sprites: MobIPCSprites + markingLimits: MobIPCMarkingLimits + dollPrototype: MobIPCDummy + skinColoration: TintedHues + sexes: + - Unsexed + +# The lack of a layer means that +# this person cannot have round-start anything +# applied to that layer. It has to instead +# be defined as a 'custom base layer' +# in either the mob's starting marking prototype, +# or it has to be added in C#. +- type: speciesBaseSprites + id: MobIPCSprites + sprites: + Head: MobIPCHead + # Hair: MobHumanoidAnyMarking + # FacialHair: MobHumanoidAnyMarking + Chest: MobIPCTorso + # Eyes: MobHumanoidEyes + LArm: MobIPCLArm + RArm: MobIPCRArm + LHand: MobIPCLHand + RHand: MobIPCRHand + LLeg: MobIPCLLeg + RLeg: MobIPCRLeg + LFoot: MobIPCLFoot + RFoot: MobIPCRFoot + # Tail: MobHumanoidAnyMarking + # Wings: MobHumanoidAnyMarking + # HeadTop: MobHumanoidAnyMarking + +- type: markingPoints + id: MobIPCMarkingLimits + points: + Chest: + points: 1 + required: false + Legs: + points: 2 + required: false + Arms: + points: 2 + required: false + +# - type: humanoidBaseSprite +# id: MobHumanoidEyes +# baseSprite: +# sprite: Mobs/Customization/eyes.rsi +# state: eyes + +# - type: humanoidBaseSprite +# id: MobHumanoidAnyMarking + +# - type: humanoidBaseSprite +# id: MobHumanoidMarkingMatchSkin +# markingsMatchSkin: true + +- type: humanoidBaseSprite + id: MobIPCHead + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: head_m + +- type: humanoidBaseSprite + id: MobIPCHeadMale + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: head_m + +- type: humanoidBaseSprite + id: MobIPCHeadFemale + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: head_f + +- type: humanoidBaseSprite + id: MobIPCTorso + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: torso_m + +- type: humanoidBaseSprite + id: MobIPCTorsoMale + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: torso_m + +- type: humanoidBaseSprite + id: MobIPCTorsoFemale + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: torso_f + +- type: humanoidBaseSprite + id: MobIPCLLeg + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: l_leg + +- type: humanoidBaseSprite + id: MobIPCLArm + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: l_arm + +- type: humanoidBaseSprite + id: MobIPCLHand + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: l_hand + +- type: humanoidBaseSprite + id: MobIPCLFoot + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: l_foot + +- type: humanoidBaseSprite + id: MobIPCRLeg + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: r_leg + +- type: humanoidBaseSprite + id: MobIPCRArm + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: r_arm + +- type: humanoidBaseSprite + id: MobIPCRHand + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: r_hand + +- type: humanoidBaseSprite + id: MobIPCRFoot + baseSprite: + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: r_foot diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix-inflamed.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix-inflamed.png new file mode 100644 index 0000000000000000000000000000000000000000..3e8f7a6ee95b232154c151cd56d04b483afb93e5 GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv=>VS)*8>L*oQU+f*g1Q1kN>m! ztk;VtZB*AhJS+Od+NcK?SH%I9F_r}R1v5B2yO9Ru_rGY zZMBM_JE@JatHC3}6-Z_mS+5eiUJ@ef;C&&agGFpHmxxv50;yAKN{y?UEDa??8xF2v g@@?4Jm{`Ef;If|cdoKI3LZHzMp00i_>zopr06OkJasU7T literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix.png new file mode 100644 index 0000000000000000000000000000000000000000..f52d5b0cdc9107e523d1303c00afc770edcfe202 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*Y*g30*g5-DWYp`$ zle#6$G`zH>fU=AwL4Lsu4$p3+0XbHlE{-7@6O$7p-ZTitI(RVnHhMCwV%V%St6_uo zEWsC62CNr!69vj#%BKs?VpwgkYo0?%aHM1#(4det%wGccvQ+_1VeoYIb6Mw<&;$Ti CFE1eg literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain-inhand-left.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..cf6e4684e9c4c97a7ab764f319a7cd6440eb1919 GIT binary patch literal 300 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1G6o zi(^Q|oVT|Q@*Xk}aJeYoY4@VREJH~*fLHedOYQ|nEkmPAaXXBrMV$Q;?6>-dY8c-~ z&d*E@m5c}WFeJn=80a(15N9~U&G3ws;WN_$xr#U21Ft_nUi*7{<$X`aXJ`9Pe=Xj- zciyI*rk`&}X0@nBJM8>1E1cui6Nar7S0~RZel~ll+u9`z+TUKB+PS%g71cN#wm3W% zNoT*swBnr77S+M>$M;J7 zgBvzQ#O`2U%O8J+P2+!s=I)e>^{am8%)PRVQ^LC9d$;NDGvTO)Vz(-yIywJ2+rFD7 zjC&MAJUo&{R L`njxgN@xNAKc#tm literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain.png new file mode 100644 index 0000000000000000000000000000000000000000..04d04890f6b4a831e8889c40f264d284b61fca71 GIT binary patch literal 461 zcmV;;0W$uHP)amXX`z%|4S0FqahNyry%`1+3WY+UxM#Gm55By4E0N*uU$OPw zz0h^~3Q=;Krc@ z`VyZs&EKtvFrAEISOq%2CK!p>=m{OC?t~J!_5A{Dq>?f>^MEVw3O%7?l`O2Y4qHWY z@K^9Jwu+`^6fOb$=3%+h1o~{GlKyJK{9d6@C;)x~p-rXfm=&9b00000NkvXXu0mjf DKDXCd literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/ears.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/ears.png new file mode 100644 index 0000000000000000000000000000000000000000..ae9ab068ebcd284332fdf3905f688d2d3b56dfa8 GIT binary patch literal 619 zcmV-x0+juUP)&VUCG9{xw%Wz)`GHtoE{ zSw6RkHyO(T2nB-t`P%~E!+V2|Uw^nhV`JQ8EGGfJ1o-kP(~)sLWp3?+wodYOHZ86S z_gc#yZ@VhoueE;>-Yr|mr%Y9uB$Ujpm5+lqt?rrU3X> zyw&!@2Q-=^3|(O8f<$zWZS98@&+zi}#DR(Zjpm4WEJ7#{1fVw@(6TkY6mQiT*H%*X z&Gh_60_KHC@||5jFV7=-!vU3Qhl^U>Cy5PRsC}|=UlZa=<>l##6OTmzW<>ld{boOW zfT0UD5AgClZs0{O&BOIO?sPk9ED7SV2>ouGP#{S8;fYe&rc}1+4F~M(`UwSs^tfQwq) z_h`?G0F;PCbPq!pO2mB5)&drZkXIs!E7gfONh)8;n+RAYqEhXsCurz`O0`2g7MW?> zW!U%|mH)$`K8_#l$=abliC0y>m4JC6^LUNeg9i^1{{ZSoB6z)o*qQ(U002ovPDHLk FV1iDUAwU2C literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/eyeball-l.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/eyeball-l.png new file mode 100644 index 0000000000000000000000000000000000000000..14e728707a96ff43cf2e118f6d0d3681abcafff5 GIT binary patch literal 364 zcmV-y0h9iTP)p@G$ZbO+JRa(Y-sR21NopLg*T zMNvXfb4^vze|dRnh7XTlGF;z$0L4OB^iYy6@M@erv-iKhpF6|T=Pwz)ef`ex>gIih zV^dc!be}(p;s{UzB{w9P@L8UcoXa30BF~_$slvd|&&wd8rNm&J6~Rz$Xbq1RHbzEp z?jRT7bhYcc`(R6U`AIP_{Qt}F=kFVav*)icF#h?+up+k&u8tDl;|+ncuf8+vi8Wvl znR}lB>jFTOMRB!fDV9xfdK&iNO|VF)wHDm0000< KMNUMnLSTZYq^t7) literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/eyeball-r.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/eyeball-r.png new file mode 100644 index 0000000000000000000000000000000000000000..d18f4d4572511fc96b0b85503ff875353b14fb34 GIT binary patch literal 354 zcmV-o0iFJdP)0j6Lt-DVo}a0SXPQ;Fg0Ng6x<90W@<&p@9|AYOy(hi5iYb z(l;Z^au8sl)N(dPMh1Q)V?c2a68ndw=Fk8C3?Kjh!I}^$cEIa@zd;6r*`;Hd-{tL&5O7#>+0nBoc&tZmvd`ow5>*)6XFCU)&f9vRu|HxU8F5t`CoB#j+c?QRS zemtUIzCU(&GuTqsb@%@>PQ3bGc;=1&zkfXXf91$_q8vbR8jzQl0n-PberI5)vSRr3 z>mLI%GcyCfj5tyHDR#j9hflyX9~%>cP~S-g2Wd_)|Iy>8lp0MuIC6ON|9`)qf};XN zA3eO8{^dT%5%1sJ_e(BWe>i_53?D0yi6+#_MO*v^m?Oy zmoaYlaw7vE$Vsd|e*g$B{CKGJS4QA}iv8o8;r$P4W+=0BfFy!`|#GSrjI zbF^7sDoB=`xS{C(AWFt-TF*lL2e(`~oaQTBSQ;$LywqYxDMxJs-=(FJw-%;wvCNIl zYfsuRvub_V&WHcaSpW7PUwzt^K@bT3p8fOC_syD4i)nv^Z*t#@zt+*kW1W4;Tlv3IwcGrn^!QaXI|Tjqr=4f{S%m3q*^cma4kHF_Wvk);GNT#pNgQrvLAyoJsm?Px<%mnL1tJZo}#4)(j3=PZ%0j zoCw)GHRR`4skrU&r@l|lI*_wj>dN6&OuLF^#9!T@VLzq5?UXoMn>K?9SH99V+d$LB z>!msnpfC3RXU5#id3FnOqt3B!@qER&?0P@bkDCj=cnhzbn7l1A^DfIv(SZB&-&ff^ zu=g-cu=Fyp-~ZE8eu4GMr`12U{k`N8k`nd)oR_$q#5#%S!+$rv`_GWt_^>O>tpQ?- chyMM~n^rnpzA$Y8Fg6%GUHx3vIVCg!0E67gmjD0& literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-l.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-l.png new file mode 100644 index 0000000000000000000000000000000000000000..9bcb14ea9d3f3f6cb283a9bce160af850e2ba16e GIT binary patch literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJvz{)FArY;~60D08M0%P69rQA; zT>k0bdmvfrg+zj4*h7)@@E!fd-`=GySsbWPyi*O&=s<{_n5-J4cI8L4sA` zbnjJ`18>aZ?;Sk)T0b^%iJO&z7ViNaw$=kTqva(W_AL)nQnBJyV4m<^Qo*t@iCsXH zY5x8iw#y49Fu1Z8H7(i6>~Qe!+u!CE|NnKjCrF8~ex1JV!ac?X59)sPG(LR#disM2 z43=$CmJJ&03f7Ol-OcAwkebHECc-m&Q3c4+23%}n1_lNU3=2a-=A~**mIQi?!PC{x JWt~$(697sRW0(K{ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-r.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-r.png new file mode 100644 index 0000000000000000000000000000000000000000..442c81338c1f15403635468b5adebf3ea982f3f5 GIT binary patch literal 259 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJQ=Tr4ArY;~60D08M0%P69W*np zT>k0bDd@v2%dB(7D5Gn$wv9^Bw|8kOVe%Kb3K;`LIJ&)zBvx}agzowIsqf)KW3@%H zj)5X3uU;BliQmPvog>APqd}%wM#-d@fv2IS`r9>jHbFT>k#+%Q4PWN}jtd<)7g(@3 z1TuIt8_ci&_i1LvUlB`&6w5U-JN`dXjQMl>dp=KoyuJDeK%6H;Z?aGaiRm+as< z$E2LWLPf$s@gwiK;#~%7(8A5T-G@y GGywoav{>-~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/liver.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/liver.png new file mode 100644 index 0000000000000000000000000000000000000000..159339e36c980119539cd11dc43964731d721907 GIT binary patch literal 290 zcmV+-0p0$IP)N*Fo{3aju&wTFy4BgIweGJR(Pjf8@{h;_7U*FcVJR`jf0O)q^ zHq9}ig8~-Y0x5L40rvLx|07*qoM6N<$f)QGJ-2eap literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-l.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-l.png new file mode 100644 index 0000000000000000000000000000000000000000..32aca484b9fc08665323556abb5a3aab1e6e7cf7 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJd!8G4U-!7ULw@2AMbS?e{IeA*r(@YTh(izN9AEkB>i_cgZ@G za2(M2|Nk2=^A$m!{C#^C&u4aENU`kMW;QM9$DgOhwK5GNUwF>P?@dS$5lghF`X+gF zn($i&wiW9gr+IgI8rbZvW7R49tvC15f!o*5ORl@Sk8hjIGmZ%nf0t_aloT@X9MECE zc!kNu+F?SxK%S-PCwm@&SiT0G+J8?pnc4NlZx{k4k0&mk$LDp_x%Y=W#3zmHJUl!M Yt2&}y|Bvjb1p1W0)78&qol`;+06lANPXGV_ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-r.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-r.png new file mode 100644 index 0000000000000000000000000000000000000000..7e29649ccd8886c45fc090f4fb039498612cc5d2 GIT binary patch literal 275 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJTb?eCArY;~60D08M0%POd6!x2 z{^1*B%{+K3f-A?8<3PqPO9qy{d9}w5Xy_dJ@aHPG!Tc)$3r;X@ zfA4hZz~lS?Wl6FzQ?> zU|3_rV436~qi{l>qwL6Mb$>~Vik%*pPJ8gOo4k6tU`bWLtp#m6!F~vIs6KGu00YB* Xk4V|}u5V9)zGU!p^>bP0l+XkK4fJs$ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/meta.json b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/meta.json new file mode 100644 index 0000000000..354132ea11 --- /dev/null +++ b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/meta.json @@ -0,0 +1,80 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation and cev-eris at https://github.com/tgstation/tgstation/commit/c4b7f3c41b6742aca260fe60cc358a778ba9b8c8 and https://github.com/discordia-space/CEV-Eris/commit/476e374cea95ff5e8b1603c48342bf700e2cd7af", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "appendix" + }, + { + "name": "appendix-inflamed" + }, + { + "name": "brain" + }, + { + "name": "brain-inhand-left", + "directions": 4 + }, + { + "name": "brain-inhand-right", + "directions": 4 + }, + { + "name": "ears" + }, + { + "name": "eyeball-l" + }, + { + "name": "eyeball-r" + }, + { + "name": "heart-off" + }, + { + "name": "heart-on", + "delays": [ + [ + 0.6, + 0.1, + 0.1 + ] + ] + }, + { + "name": "kidney-l" + }, + { + "name": "kidney-r" + }, + { + "name": "liver" + }, + { + "name": "lung-l" + }, + { + "name": "lung-r" + }, + { + "name": "stomach" + }, + { + "name": "tongue" + }, + { + "name": "muscle" + }, + { + "name": "nerve" + }, + { + "name": "vessel" + } + ] +} diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/muscle.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/muscle.png new file mode 100644 index 0000000000000000000000000000000000000000..38da7e760720f1bc6fb4a57d4cf3d086bc0e496c GIT binary patch literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvi2$Dv*8>L*yx%tS)}kq=8YXv3 zm~B+oOq0^|7M819ZTcLjhOs2bFPOpM*^M+Hr_j^IF+^ixa)Lz0ffWs>(uIs1L>yT9T3+ldmcYsBsp)v_(JQfeL17Il6M|kno7SXqKuB)Vq<3v9 z2Ufj$6*j4FNpt8K0ar%m#hardEjMXT5$!$`cxP?KlAcF-Y-y}*j{FQxCxw#(XID4@ PEobm_^>bP0l+XkK6L*yx%tS)}kq=8YY(= zSbP>J&R7!U7tG-B>_!@pW9#YS7$Pw>IbnhEi5P~3s&BXyc%Fr<=$LYand7kHC5A&6 z=A2+$CV5+=@&Hd>X6g#V?uA|w{tm1&Dl;C%FeL2akpGk@rwlZR!PC{xWt~$(695-3 BGdutQ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/stomach.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/stomach.png new file mode 100644 index 0000000000000000000000000000000000000000..ebf1d5f5141efea3d613ee4a659f6e4f6c6b9dd7 GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*EVZ#Z5$W@+KI`j} zj{hgtB%H0^0hDDd3GxeOaCmkj4akZ1ba4#Pn0WTwMZpFI9_9=4^c>6`5*SqHG88c1 zsTZx!6uVHf&%0Xir@^TS+6T=XLf%#W>asn{e5Uz{V*p#NX;baDZmxm^*^bwaOj!}( m8D8zPMMJJPc})5Lob^X5=f?aEmDhpRFnGH9xvX8`(!|)tB*xg(3Kl`6)GtI(3U#qMcpJqVa1;b_RPYv@9D5Cdiy*qFR2Msy z;!ui|8e0ss$H~r#i_7_K2j27W^6-KrNs=T<|4fPd;c#U`qzxNQ)9LqnD2W7yp>uS1 z9Xks^i!*$-z9SYqfAoG2hq&1cSIDNj2wTK#Z@OZT-+=LE*?N2c=9a+CIG`2w@ofiy!rVN??JcTTRnnHj-hLSs zMARl?)pfAABn)MYT*}3=EPUG`p{OJslhmX|v)*8+D%2Wv&R^~$WyiXK%ePkrppq{L zz1L_1ORb002ovPDHLkV1gRrsQ>@~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/vessel.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/vessel.png new file mode 100644 index 0000000000000000000000000000000000000000..cfca0298383538cd7e6e7318337bcc8e50b7bbde GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@o&cW^*8>L*Y*g3mmM}|`(q!G> z(g_r2ED7=pW^j0RBMr#$@pN$vk(ipCuz)>5w9#lrjr4*wD`yH!yRqZ);b6{ha9y`M!S+0dAC-!;* P&1LX(^>bP0l+XkKTjno@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/full.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/full.png new file mode 100644 index 0000000000000000000000000000000000000000..10f6d3193cfa390868a15779debbe8b6338404f4 GIT binary patch literal 5707 zcmeHJdpwls9)C?PGns6znMk9QaFmo>#wv{5l69St*1DI=R_-$HN;1kN;fUOc$X1I` zlG2f6P9@b0m1t;BCZ|{wJ3G&OymN5U7~AJ_{yER*^Um}9uHWDLyFBll{9&*0ish@9 zLlCsW)C6zM+Ogn43bK9!!oo%&NT49hmKbR55`sPAf7sK@*8>}P^oR%6Bh@w+5E{1Exz-|08+PFvhMq#Wj7wy7?_ zV6CE=*4Ut;QJMS>e0*VEVtaXlm*s?welJbO_1@b^VVz)Fb?(6Q;JbpS7jjxG-^<@3 z{pft+q##Le#JzMy^ld&TG~-nYA+q5|frL{16-WFDRwA3of9evrB?*vjzO#s2zoAC-$j z+Q(7ba@XV=4JA2mDynIG)tT^H{0~FMIEj#tt>Q!3dJ~L`d6AX1lY$8`@kPf(tkyfl z{aswr+nExl(GzL?x+Qm8mM{7D=D^#pGoSl!udDPRGUN&e3OcrYdU?IKQJDU#?Z_W( znm_TaO4XK8OVTD8ppzz!>eyw(RezpTcfz0(k3P39Zob@LcVQygteJc;K0m)#d&p*| zWV4Z)D%6ibM{7`C7wr_Y`XG0@1A76X(=MqbJ+iKgFD*q~w8vfjF)?jQY=b-+msFG$ zgX(KT^+;U8s_^Si6{mw@`RqP4Ku8QJH{Z_B8Vh3_}{D@b9DOt6q$LwORPDod> z9O<|EOs5lTktL$>Nm`HEijs6hz0dTbZ9H?l=nkGYE(bsQ^foe1BkIa-vXb~7&2F{q zMmXo>zxk{cQw-)CBS^IE{K7!7(; z>pAnj7|l=00i72}XX+`}Z@5;`wsuLm;e;QQ3$6dGw$s04|L`xLyBdD7xK8`ydLafG zCsc=Fj;hy3+0!Et56Y23fp%FoBdE;yqFN`@0IKz=Rp;>)5Pl!Y(X}Ra#|k@g?(N&H z6K)CT717Vtradz&9dU)LtA%s=aA>I)QrE015LQlPwV;#XmxH2KI>(ibxU3NrU5TVq z7}9|jXrcXWdGAU0rk$L9ail$dyL~X!$9Q^3_DS3o(UJqF8B-=E+ueiTWj)e!v`nQX zP>&w;A#Q#qBQmX9C*T&DNWDb==W}}2<0fy#pepqQ+koP)01QX%LGTZr@EW-5c*vLj9O6SChS5Q^85t%f~@EL@w(5q`&*kT{4+v z-^;q}eY&pR+)k4^^yGF(taJ97yra|;W;e*niNUs8=voS0QTWsiKih#a`8nCW^XgoTyF=LbU{Jenz=-^-3=Y=$ly56PvnN)yj&duAA+tSFaVcS9^aF^&qslXfi5}XeRqk5fu9I)rP)N z2b8BP)Eh${w{N%9lZ%ts!r1H{SMMX-EA?J~40mlr<$zK4JByc}+owCqYbA$uf+nBo zIzA}5Pq(0k=Y8j$*1nt;y|(it;aTGJju66N<8X1@`=tEhUp7swoRmh^sp{_4iXe^$*)r-7+P+-%?|Tn3k57AegTO#MSwtOR#a{Mh;j% zLXZuLL?YP$1}f8V5X>1puE4OuqM8sm-L-2M#Lv$UO-)TP4O!NNty`h;@^XkkAV3s~ z5(IRBTvt~Y_-3*ia#7`2bOykfb$53|N=i!X;3p;~=InqE48v)6la4Rd6$J^+Mmz61_P#A6URCSO6UGSf5=sIM@L_J6NCxc#ByGZc6Z2 zv1-jx1w1eT037VF4p4ygX7f0POF4iy1JBI03%}{?+OyAa27n%Hvlu+C82~i|mkd1T zTUj^Y%!2!ey~BK<2lTns9(J;n9nJ>a{qyOi_*}dVJoob~zUkc0^Zg$Zt}WaTu!PsT z!*)FHAbNS0gh`x&z5rpi#WiS30KwGpsasB|7FKbz7Rl=zhSt`(BWG^Zfdj_ Jf62f(_D^RWFSq~z literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_f.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_f.png new file mode 100644 index 0000000000000000000000000000000000000000..528102b2e13a91cfa58c970ab6466eccb04fe0b0 GIT binary patch literal 586 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|Vn9 zPZ!6KiaBp*Z9H|zK%~|Gq5K_|gJ%P4*xU=>aQ|Slo06|!Vcq3@(6`{trK6Drg4_Su z9-VS)RY9}np}q1Rw^@p2oj21|sSoJmY$!Uy^z3uxzjb-rZ@Y5veD0Q!d%g4NR{wn- z42O?DHq@KW&DZW6YB$%?hyXF7Nf6+1P!;cj9 zye*5K`f=7%yNa_+HFstwA9z{fl%Y{!ArmGfv+lE9eM5*tNXwJ63(lqmUscu#oTTz| zc~xe!oxj6}mFrH|{1#{`@?n^g%(Os8nBnOR294t^4wh;Rrwkdv-a<%Ka8_(}Kd|=9 zvP`Lxhbcxgr`%k8aYg9$lm8gXrbr7-JN-0RHatCiwWwIP>%O@4%^nq7?w(RRvrMLI zVu!$c{uyV}t|~oQEqYVMQ-JGwneq1f@29)pyIr?me5+<1>#T?0f6K-OpD&SC?Km&A zv!tFue(km2_qVc44}WiCDcAqV(Bluwp2;7$fAAdGcR3+sPqr@SQ3a6_F^yvjI+$ap zrRu*wx!m{t`-TgbW5aiTQ)I#C5uhL4_cql37J9j2=|88-z{J7e>FVdQ&MBb@0Ct%I AQ~&?~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_m.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_m.png new file mode 100644 index 0000000000000000000000000000000000000000..528102b2e13a91cfa58c970ab6466eccb04fe0b0 GIT binary patch literal 586 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|Vn9 zPZ!6KiaBp*Z9H|zK%~|Gq5K_|gJ%P4*xU=>aQ|Slo06|!Vcq3@(6`{trK6Drg4_Su z9-VS)RY9}np}q1Rw^@p2oj21|sSoJmY$!Uy^z3uxzjb-rZ@Y5veD0Q!d%g4NR{wn- z42O?DHq@KW&DZW6YB$%?hyXF7Nf6+1P!;cj9 zye*5K`f=7%yNa_+HFstwA9z{fl%Y{!ArmGfv+lE9eM5*tNXwJ63(lqmUscu#oTTz| zc~xe!oxj6}mFrH|{1#{`@?n^g%(Os8nBnOR294t^4wh;Rrwkdv-a<%Ka8_(}Kd|=9 zvP`Lxhbcxgr`%k8aYg9$lm8gXrbr7-JN-0RHatCiwWwIP>%O@4%^nq7?w(RRvrMLI zVu!$c{uyV}t|~oQEqYVMQ-JGwneq1f@29)pyIr?me5+<1>#T?0f6K-OpD&SC?Km&A zv!tFue(km2_qVc44}WiCDcAqV(Bluwp2;7$fAAdGcR3+sPqr@SQ3a6_F^yvjI+$ap zrRu*wx!m{t`-TgbW5aiTQ)I#C5uhL4_cql37J9j2=|88-z{J7e>FVdQ&MBb@0Ct%I AQ~&?~ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_arm.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_arm.png new file mode 100644 index 0000000000000000000000000000000000000000..fbf53f24e21aecb650dc660aab69fdf43a4fda64 GIT binary patch literal 497 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|Vn? zPZ!6KiaBp*8D<}HkZ8N#vTb#9@xtbm6VKi$lw~=}Y;NT{8h>%){zDgiUp>0?@k6*p zi{7P;FLc&EnWZm!%k&rL(|hk{>K)!&bAR$jUQap6s`l8eov({=U_y&KevX!jz<-GK#z~V^N-eWa(?P{x-!d8dsI!af5zVxST zcj)=B`^-x`G%ZdW+0Q=f7suK@XS0cZ26xAt;(c0DL0i}+eOC9c&9^)ruCS^rbaKJD zXRM)&Z!2Eio}2#Vcdd__@Km47Ivcs#R5drYBM7 zk~SX5Fv+qp=U{B-mi+4ZDZwD4#6r4>;lEV;qlZs7X8mJ6x6^I1vp~b|Pu!P(@a?>P xU3)=iivY_N>$423IesgXk2 zZgwHclI^;7BU2)~xpR7ceviBSZkeQi&i8rFe9t-a`F`H-@9TV@Gk<)(&s^0wrq0gF z%L)JhI}WR=N$=6%fncJ4rdglv1OTR3Pi;L{O%r#Nle43xwVegZ^{kTx%EH6i5&%5j zyp1#n=@sMf@A|oPcQFc`#eZ)T`7(KK+Sf?dC?arF$)!KDF}Q4<-eZAz&2R(nd9Qr$ z_bi@jJh#FPT?(e2^V(V|g;Ex>T_%Z2lOL|uZT9w#bf>PrBx({mTNe^P@AzTCs7P5R zu3>{ul?V4sx!;TxqVLvi_25XgOIM~5X*W?UlRn;Sv)eMon-dP?)i*2G$`PvO&$v+> z$wRGkL(~*iN8xcS0{_&oU9H6aVhb@=X1lLf7FQf+opESB_QGyKR9ETHyw(G&`^?ww z$NY4AY@xR>-aY>1weHp(@jkI#<&Fa+LRX?QhSoDJTBkK7LwzAl9@H9tn?JdGcIrBh zge8U~aJSP?o-jfQ*z>y7M86=^5#t+|?#y*;;EX#@@6B#ip`JbY)M_4)3w8MjAj9s zN3ZAO>>*t?9uO)DQs*l3fWb6Agq-^r;eWf6vjUE0Z@m1xUZv>n7U4tw*xHLnS(2lP zui`TW*ClWJ5VRHhL#4SM><*Kjv~casvXZSfIL#xXeMzZF(fZ;1E>-fj`!wyucuB%9 z()6=!#5GNEJ9#92dDUQ(0=G_%PH)n*wPz=>SKfHc$EQ!ZgTJYq8<+pF!PfC|&)(m$ zLL0VOyn1OFxu^SP)ZN-W6uWAvz=mt$nNMBAbck*Ik0cz*Np78a)%WtBC4MZL>GOoi z(r$BeXyzR6I&P*ranx5%0q4K<;yNDXfOM6jOC0{KI_Itz2kou7$J&EqMMklahuEbz zUa!8AJ>d7_fDuw&BG@i#`>{8YuN z5*8Yx9_4EDxT+nVsL?hyOU>B1cRb6At0wKY&h5qmcStEu$dxk>+T)TRCx?wC!J^0s zjvV%)k6$Npoh{t4PUDc?}^+E@At*H0KUmplpf+y2njR+Gn zU^-=O2etI(9sCJMjyXzie*JLc@s_A8YYLFPr5sp z$z2f<4KEOd^XGah3Xx;>KD;u&<@gNdrI_LdRqQYD*u=ayRk@F4GWFyG#o_%D=lwde zMJ&2`w!XJ;ys@O#O_E3 zJ}a@F*dJc)@KEmF%gNx{@$&EjG8Oi+rQaAerK{u8A+K^S6lL>kw1qiVaJ(zUR^Sk! z4i{S{YLngPM$lFa5Q&RQamp9sM~cL}+w9DihHp!nmRNXNVS4l0d7EM--y?{gL8fBg z;c$H%(!nYxNY|@!p*u_I?N|=4>0V-sZdR(5^?M4du)mcw2Nh*!C@^FVYsWu>7d+Rh zu-zBp+c2A0s#wA4FGEr6RcPJ@3(%IABCxT(_4Px`#VV%42_1>NCtO>b6qpSYHM9<5 zsP<)NTBf?G^HGKGt;7sQUHlDGx~`?_oH?bIH%`P09Y7Cq1n#%t8Mq<5<2I5kY35zj z%{Fs_h}$gk{A^-g#_2&`ACqz=@R*!&v!?ODJc(<4Zp~S4%49kHKZ82-CxEwa~ z0zx(U0kd1u_$`NDgEa$^B&IjiiAg4!sSX~Y|6DPd;?-4wG~g}}*)3<+M!&=2g#FnC z063n52P{mSgO7fb*%fzGjd@@V56h;V`jdLu0DuB;sw&#_*CQHTSV)h68bkmh01gi`81N7ZDNps(g$L1~r#@06nc*TNDEgES|5L_!6O|4}wu24A%+4$u~DQFR}A| zPC*ZgD}fOQ34Su20eVugJ1{%KR-VpDJl7Bf52+(5%?!!pf-4b zUO-RZrO_+50531^s%wLqp!WA@i{h;}R=Qrsgg)&TSXx3~H6Q=5H{cTt`cwJl zAV7`3P8z&kT1sCAM1Y~1zO1Y)ZDL~LZ#pe4Ex^LU0z*0fmhAuBfWzUmUAuMxK&(uC jC_M%b{x85^Vj115K$N>w4W`4X9aFuBIqCBU3a%3y literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_hand.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_hand.png new file mode 100644 index 0000000000000000000000000000000000000000..c7a9172924c2aa6cd22e6eb6a012ce266034e646 GIT binary patch literal 402 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_foot.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_foot.png new file mode 100644 index 0000000000000000000000000000000000000000..69a6ebc6849d27555cdc5c56307048414c685e26 GIT binary patch literal 18314 zcmeI4c|6qJ9>;$r874wKXc}vUCX_8ow#kxx8;z}m#*!^twsO6AP}V08g@(e!WJx{t zO3G5UYy{`LG-TPeWiTlUzyk5UKbIzP|KA-bGXI}Hi_xqY_+M3Gr zbO<^C0O(atDdEBd8tv_Yr0M_P^P=xbIGf<(Wd3E4FCUSxHlYgR^y{ zyTvsrRue(R$vs7}t;%SFp1vLwvjcURPY=OqpNYS8w~W(=yLej^dN4llAzn^zTDoUwwpKa#{$-<(vtT0fO}8LlG@3-Am}pJIPH516zo%U+pk&k|*j z)fNuy^K;%+0(0gKu_l`NCfu|(Ev_V>b|L*ksl21c(?Vq1n{5lSjm-vz3=tmV_PZxZm(bJd6Eavy4x)Vr z2nwi&x-)piM*t>e&9t~Dz5vlvCBeF$vB?{02oMv!eq%chn~N$@sANtox0ZDYyr)s%AVz_oOo)$u;J^l@p+g=Kj` zB*8B6Y0`^~;SiXkYvc}5050Uki1qjNWe6ncUk-i#n`q5_x?UAJ{@5MaL-fLoq18b- zOYloVZ>}Po{{fdsonUw9E>^7F<0`8#ChB0CcrnxGe;B6*OZmv^mcA zAHMv~6gf4_;?Y+w++y4!rztwCVAXSzs*v|_lHS={sg{4#B+=iJKN2f=ruqnXCTD)> zHQdceH#kcjdoz-h89>D&EZpNL70zXBqwq6O2AEA_Zq^U3fPzFoPqU zz@~Fx#~n(v^x1I%{Mp!trFr?fF#~)U4sE4HMTW;@rjSMO6v&G8#zsEMRW5Ejovxc5 zLz|vwj1}(3d(UZd4h3GS_L(E**GIRB-HAbVZ);>?sW^QP735kWHJiTVM||V19;lmR zyQ?$ce&~T+LoM7ranp=p?0w2|+FHzR3CGbAw6fPA zH5G~eQhG`z_x26D`9@%$fjkH6d97&8oczUd+Qzh4bUIzj;n4~>`FTd6vBvN~10jRI zZwISofk#iljn@aMkDYum9+vLbC&14BK~;wr@9K7lEt%6FzHK{G!$B9HLi2o881rdb zn>vX;UiAf<5{VNFHf51Y^m|hoTs~^eayXdQG+c|Bp?zsotx;6y%%>DSt@9{m0wb%% z{otxWieOP``Mu}kzn7A*T;`2=AMI1?yLc*iUY~$}HD~=LWl+9PK0rrqBYEpRVoZYRU>g8juRabW7N^Q+jAG zo-%X+0ERN~*%Ez-VK1eV##Kc_k!FC3m6n;I!*Wsr0Js1Z1$m6emMwB}#l@5nP=N?Q z1Rw$s0f+!Z03rYpfCxYYAOa8phyX+YA^;J92tWiN0uTX+07T#~2xw_({l%vn|Ivo} z!D6u+zr!^sZip{lUS0rvHk9}pHvc1jwyt6QFNVm;$pH@^KK!C@vl}oN3_zpN>$36P z0LI3~)+O{aC(X^x0fU2sKU3n%wNWV4mmQnj`jPMdcijNWH6v5@N@inY`&@7GzE|YQ zBO@c9{rt<{O8?(muWTNyDK`KV{J$xnpVj`p$Jmy&4qmT4>PPlqCaPuuKEvvgW zsB&9KR*EA#p97DCI44&J9%c&@8D%?k(^ZO^S#2?fE literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_hand.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_hand.png new file mode 100644 index 0000000000000000000000000000000000000000..92342236d21598b63d04bd1615fda80c9474da72 GIT binary patch literal 400 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|TRz zr;B4q#hkaZ47r*e1YGMCTDK;o=O!vvFy|+{lw_6mPfCBNxaO^on@CV$(a1U*L9i0&zeyxE?!W8E56Z#p|-4$1HCsl$o9pRx9?$Gu#|* zg002r9+<=%u@5(mHx%96ICJmsH*&4cq6xOlk<%7tO2v4}9AExjQ$`3VkSOseYmtUk z?b*9b+vYWvR=iyK@!sTkdA`sCzE!PzF6be7*;)SqYkW|s@e$^t$G{+F@O1TaS?83{ F1OT?ImwNyJ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_leg.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_leg.png new file mode 100644 index 0000000000000000000000000000000000000000..72c485225c7027b7e5b2e01de7533694ddd69a6f GIT binary patch literal 18315 zcmeI4do)yQAIG<;lS{5SiOGx7ga`>Wq$Zc#&KMbzTahSoPsXieG@*;cxJ9L0yO^48 z?sUlIxP)lNpomQLqgZ>B@7ckO4bXZGIDJkRg@eLnlyd;a)6Ya&fe z^!a$;JOBXj85-!Cv5qLPaxGzfUU%_+4ggE81)A^nHFLm8dHHxcySOr zCJz^e3~;ZbRiq=RDN0+(m2mi`o`P+3+sWk(Bf+n_ghEP_akn@_lUamHGnfO+9W(~z-3%yYpYk5bG#LkqUv$t&~2Fx8Ah=zbqxmXRc(1J@aQ@? zedPG7p{uy;BE|%Dh#_sgVM}~9r%W$(w5Mq3%^~xs{uh;)fDXdPAzHFSW)ml~-IHnc zfh;C(U6-e^?M&bWAI5Gft?Yp!|I_yw6U$Z)2g|?EHW$!#*wghkIQ-UDfcl{c^J3yd z|Cw?D^D_?lsU0Vj@hN|-hP#TU_9EJ-o+{UBh%i#uLkUEY@8E&XHu&oFyi+s%F-zflxS*t06}?#}Y)yYjWDN6c_+v-iNz_@HAR57*kEI~fKQAjyL_2k>_`}(9_VtIrSI=}v5 zkHx#!%fD@S5)EsP3aI8?6SH6C=5fkUuIWu&OanPY2X98Hi1>UW$% z>!mfPTUngm<*sL>aIO1l2GQD@&qAu+{P0t2*PI;k0Ue(%dL^C`*!RQ{L+T|J54W{T z1@91d>AsS7Mx%`vyLMv3P>YrGMfX4TWOMSK)EHY@9l4LrcK6m~+#90U`8}f(+7?kT zFCVZDWG*%Q~m=GPxk%S}NJHu15S8u0uuj0pd#T{mF=D>o5IkB^Z8&{M$=w zY}f?JbE-^#>P=#T&C9qfM^Y{+G{u<_`S_6%rw`gsFRMr$Q@=k+Z>4&ey^2jiyo0v& zHji-OT17;^h{7e!o5(vhOF4D-?R)gXPeaSJRp^{bgvUjBcgy?ldeAo7oTy5V8?L7^ zJa>!6x>nJOlnWE@Bs;(3aZej^f}?3M=rrzQnrg#HX2Y5)NgKLa*B>synu zm(-fG41dBxyKM-a&)qx~I>6U(3{FnpSzdXqTzs;*IJ|wuVc*r6N6W|*AFL;-Bl5iC zQKF*rmZuF^E``#ZR-uve67X@4&suo0)OK@|x$=r#_P9? zMGKrPWNI#6j-b62+|~Wb30{cf{@7yhsO_K?e(;7|D4xur;qwk)a&Is6@(CVgk7H5 znqs!-k}QdjF3Y#ZnjVJRne(XKb3R))Q7|Zdx>_`N*psr-O$+g`UV-)7wPc^MzAkVb z$N~~OH@UU5TDZLotPTSJ|0A$+#L4roWHoa78lv?$dl#+X7E*t1DCPf>f z(-;h9n)NkUe}=NKek?65f2PUL+<@uNzGklH=eTz5+G((UUIFtX!ba3tD{{`O5;j*o z6bc29$>g~Xo7etaTwH**wl-TDa|Xa*FxV2B&q1T3qd;F@-+W4Z5qo;wx^+L(dtm1I zpY!quXEmo4@OhbWh>D7Gu*QP*XDA%~{r#W(u=^N%(^oszBdwW-q{kIDkYT0uTX+07L*H01<=tfL_=wYy$v=!F>a)q$#NV&FMCFjsC+p zFk$=2!}r_>wg8BWivx;^iU7E8;79Hqn9&ElfSwkz% zS(mfx!Z2VrEj=IZeu$TU%FTmDSa)SU=J-WSP~-2D2CrwQ%D))!KQ7pMd8w(X0V5+L zUxjXMZ3U*LroL+bHydCu7$7Sv%laz;HMuNSU}Nxq0sbby?p}sc!59<5YSYbNI72-X JU6Qsv{x9$$9{m6S literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_f.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_f.png new file mode 100644 index 0000000000000000000000000000000000000000..bcfa51232b7dca86a39fd03abbbb363c10b56741 GIT binary patch literal 973 zcmV;;12X)HP) z@>~G`d9DC}JXZifo+|*z@LAF8^=LYs;yNP7s@Lm+ukY{gt^KV4{3?79pZ2eGc6O%f z-OoEQ`}xi#1aWnBl~yDGz_9W+1_1J3WI5<`XgnU%U@)M?qNVO<=?Mdge!owZN+rF4 z`eZV(f?y1w)oRgdwW61o7ggsH_ay*wAvFH!>FJc=<_riO+)gW;BvG9X_?{6q?!DlwRq2X|t z-jlz7`c^2?*Zm*k?=uE)yWgsbMmAa?h|y?-YUHBvkn~ah(pPA=Bb&xUR?8q}{L9Nr zHS{nK#BuCu1z-vIo}Zu7Ujhq&3QOFTL#(psC2UoLfrFgeySPy ztwPVY+im5K5_MZy0l=h_C`!m@>~G`d9DC} zJXZifo+|(#&lLcW=L!JGa|HldK8#o7oGf*m7dV->RbGIv`6Vbyhv{+lI`GzFGK#?n z04GJBpP#8*E)%jtcqh+^5*HA-@kquX4#ZHcR@0csFhOHH0${{v0wBKD@`SlcZ#;V+ z$7CX705IBYHtMfbDyh=7xWOC)@`JWA0)XL$SI|g@K{zbI0FIIsc`8C?8o7Yu7&tbQ z1dR~@&INKV4!wXLU}OB>h2RBGKtK!}k4+3l0N4P=Ab)XjLG$@sPm~H-<~j-z59Ns^ zkSAq;&@;wwmFWnGFbnIydjtRo+L^&z#T{_mc*KMRt!W2XZ-f}aZnsMzxDq!WY5DDT zn`t7p0&sjx?SBwrisRV$bH)IYO@`WeVO4;sHtRZB1#mJn*#V|8ByqSoA;LSr#bV*Q z@w!*K9md%N>;-JjCs+XhZ7hE<#DsKrcSq~>np~>UXi&4+R1+^Aifo2IWCZ|2jcGeR v8<0u@j~IG5ACN%-0C}zefIL?KK%VO_hwCWYPc0~L00000NkvXXu0mjfr8Krf literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_m.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_m.png new file mode 100644 index 0000000000000000000000000000000000000000..bcfa51232b7dca86a39fd03abbbb363c10b56741 GIT binary patch literal 973 zcmV;;12X)HP) z@>~G`d9DC}JXZifo+|*z@LAF8^=LYs;yNP7s@Lm+ukY{gt^KV4{3?79pZ2eGc6O%f z-OoEQ`}xi#1aWnBl~yDGz_9W+1_1J3WI5<`XgnU%U@)M?qNVO<=?Mdge!owZN+rF4 z`eZV(f?y1w)oRgdwW61o7ggsH_ay*wAvFH!>FJc=<_riO+)gW;BvG9X_?{6q?!DlwRq2X|t z-jlz7`c^2?*Zm*k?=uE)yWgsbMmAa?h|y?-YUHBvkn~ah(pPA=Bb&xUR?8q}{L9Nr zHS{nK#BuCu1z-vIo}Zu7Ujhq&3QOFTL#(psC2UoLfrFgeySPy ztwPVY+im5K5_MZy0l=h_C`!m@>~G`d9DC} zJXZifo+|(#&lLcW=L!JGa|HldK8#o7oGf*m7dV->RbGIv`6Vbyhv{+lI`GzFGK#?n z04GJBpP#8*E)%jtcqh+^5*HA-@kquX4#ZHcR@0csFhOHH0${{v0wBKD@`SlcZ#;V+ z$7CX705IBYHtMfbDyh=7xWOC)@`JWA0)XL$SI|g@K{zbI0FIIsc`8C?8o7Yu7&tbQ z1dR~@&INKV4!wXLU}OB>h2RBGKtK!}k4+3l0N4P=Ab)XjLG$@sPm~H-<~j-z59Ns^ zkSAq;&@;wwmFWnGFbnIydjtRo+L^&z#T{_mc*KMRt!W2XZ-f}aZnsMzxDq!WY5DDT zn`t7p0&sjx?SBwrisRV$bH)IYO@`WeVO4;sHtRZB1#mJn*#V|8ByqSoA;LSr#bV*Q z@w!*K9md%N>;-JjCs+XhZ7hE<#DsKrcSq~>np~>UXi&4+R1+^Aifo2IWCZ|2jcGeR v8<0u@j~IG5ACN%-0C}zefIL?KK%VO_hwCWYPc0~L00000NkvXXu0mjfr8Krf literal 0 HcmV?d00001 From dedbb6958ca23be789efd8513ad6236f013c1805 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sun, 26 Mar 2023 05:31:53 -0400 Subject: [PATCH 14/60] Far more work on IPCs as a race, some sprites for future use, unfucked the dumbass temperature alert thing (>:(), overheating fire still acting strange? --- .../Silicon/Charge/SiliconChargeSystem.cs | 18 ++- .../Temperature/Systems/TemperatureSystem.cs | 80 +++++++++- .../Silicon/Systems/SharedSiliconSystem.cs | 6 +- .../Prototypes/Entities/Mobs/Species/base.yml | 4 - .../SimpleStation14/Alerts/alerts.yml | 4 +- .../SimpleStation14/Body/Organs/ipc.yml | 91 ++++++++++++ .../SimpleStation14/Body/Prototypes/ipc.yml | 45 ++++++ .../Entities/Mobs/Player/ipc.yml | 6 +- .../Entities/Mobs/Player/silicon_base.yml | 97 ++++++------ .../ipc_inventory_template.yml | 140 ++++++++++++++++++ .../Alerts/charge.rsi/charge-empty.png | Bin 0 -> 386 bytes .../Interface/Alerts/charge.rsi/charge0.png | Bin 213 -> 525 bytes .../Interface/Alerts/charge.rsi/charge1.png | Bin 211 -> 641 bytes .../Interface/Alerts/charge.rsi/charge2.png | Bin 193 -> 585 bytes .../Interface/Alerts/charge.rsi/charge3.png | Bin 192 -> 2826 bytes .../Interface/Alerts/charge.rsi/charge4.png | Bin 193 -> 603 bytes .../Interface/Alerts/charge.rsi/charge5.png | Bin 194 -> 0 bytes .../Interface/Alerts/charge.rsi/meta.json | 66 ++++----- .../IPC/organs.rsi/appendix-inflamed.png | Bin 188 -> 0 bytes .../Mobs/Species/IPC/organs.rsi/appendix.png | Bin 158 -> 0 bytes .../Mobs/Species/IPC/organs.rsi/brain.png | Bin 461 -> 265 bytes .../Mobs/Species/IPC/organs.rsi/ears.png | Bin 619 -> 418 bytes .../Mobs/Species/IPC/organs.rsi/eyeball-l.png | Bin 364 -> 4215 bytes .../Mobs/Species/IPC/organs.rsi/eyeball-r.png | Bin 354 -> 4202 bytes .../Mobs/Species/IPC/organs.rsi/heart-off.png | Bin 242 -> 260 bytes .../Mobs/Species/IPC/organs.rsi/heart-on.png | Bin 436 -> 491 bytes .../Mobs/Species/IPC/organs.rsi/kidney-l.png | Bin 262 -> 0 bytes .../Mobs/Species/IPC/organs.rsi/kidney-r.png | Bin 259 -> 0 bytes .../Mobs/Species/IPC/organs.rsi/liver.png | Bin 290 -> 0 bytes .../Mobs/Species/IPC/organs.rsi/lung-l.png | Bin 279 -> 0 bytes .../Mobs/Species/IPC/organs.rsi/lung-r.png | Bin 275 -> 0 bytes .../Mobs/Species/IPC/organs.rsi/meta.json | 60 ++------ .../Mobs/Species/IPC/organs.rsi/microcell.png | Bin 0 -> 334 bytes .../Mobs/Species/IPC/organs.rsi/muscle.png | Bin 219 -> 0 bytes .../Mobs/Species/IPC/organs.rsi/nerve.png | Bin 155 -> 0 bytes .../Mobs/Species/IPC/organs.rsi/stomach.png | Bin 191 -> 0 bytes .../Mobs/Species/IPC/organs.rsi/tongue.png | Bin 375 -> 516 bytes .../Mobs/Species/IPC/organs.rsi/vessel.png | Bin 170 -> 0 bytes .../Mobs/Species/IPC/parts.rsi/full.png | Bin 5707 -> 2246 bytes .../Mobs/Species/IPC/parts.rsi/head_f.png | Bin 586 -> 2626 bytes .../Mobs/Species/IPC/parts.rsi/head_m.png | Bin 586 -> 2626 bytes .../Mobs/Species/IPC/parts.rsi/l_arm.png | Bin 497 -> 1725 bytes .../Mobs/Species/IPC/parts.rsi/l_foot.png | Bin 18302 -> 2394 bytes .../Mobs/Species/IPC/parts.rsi/l_hand.png | Bin 402 -> 1574 bytes .../Mobs/Species/IPC/parts.rsi/l_leg.png | Bin 18302 -> 2397 bytes .../Mobs/Species/IPC/parts.rsi/r_arm.png | Bin 494 -> 1771 bytes .../Mobs/Species/IPC/parts.rsi/r_foot.png | Bin 18314 -> 2394 bytes .../Mobs/Species/IPC/parts.rsi/r_hand.png | Bin 400 -> 1585 bytes .../Mobs/Species/IPC/parts.rsi/r_leg.png | Bin 18315 -> 2397 bytes .../Mobs/Species/IPC/parts.rsi/torso_f.png | Bin 973 -> 3420 bytes .../Mobs/Species/IPC/parts.rsi/torso_m.png | Bin 973 -> 3420 bytes .../Species/IPC/parts.rsi_old/torso_m.png | Bin 0 -> 973 bytes .../borgcharger.rsi/borgcharger_1.png | Bin 0 -> 1154 bytes .../borgcharger.rsi/borgcharger_2.png | Bin 0 -> 1093 bytes .../borgcharger_active_unlit.png | Bin 0 -> 1302 bytes .../borgcharger_closed_base.png | Bin 0 -> 870 bytes .../borgcharger_closed_on_unlit.png | Bin 0 -> 885 bytes .../borgcharger.rsi/borgcharger_open_base.png | Bin 0 -> 1001 bytes .../borgcharger_open_on_unlit.png | Bin 0 -> 1023 bytes .../borgcharger.rsi/borgcharger_panel.png | Bin 0 -> 1041 bytes .../Machines/borgcharger.rsi/meta.json | 43 ++++++ 61 files changed, 517 insertions(+), 143 deletions(-) create mode 100644 Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml create mode 100644 Resources/Prototypes/SimpleStation14/Body/Prototypes/ipc.yml create mode 100644 Resources/Prototypes/SimpleStation14/InventoryTemplates/ipc_inventory_template.yml create mode 100644 Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge-empty.png delete mode 100644 Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge5.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix-inflamed.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-l.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-r.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/liver.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-l.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-r.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/microcell.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/muscle.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/nerve.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/stomach.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/vessel.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi_old/torso_m.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_1.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_2.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_active_unlit.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_base.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_on_unlit.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_open_base.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_open_on_unlit.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_panel.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/meta.json diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs index 8d0a535774..efbcb8a4c5 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs @@ -138,34 +138,40 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) // If the Silicon is hot, drain the battery faster, if it's cold, drain it slower, capped. var upperThresh = thermalComp.NormalBodyTemperature + (thermalComp.ThermalRegulationTemperatureThreshold); var lowerThresh = thermalComp.NormalBodyTemperature - (thermalComp.ThermalRegulationTemperatureThreshold); + var upperThreshHalf = thermalComp.NormalBodyTemperature + (thermalComp.ThermalRegulationTemperatureThreshold * 0.5f); // Check if the silicon is in a hot environment. - if (temperComp.CurrentTemperature > (upperThresh * 0.5f)) + if (temperComp.CurrentTemperature > upperThreshHalf) { // Divide the current temp by the max comfortable temp capped to 4, then add that to the multiplier. - var hotTempMulti = Math.Min(temperComp.CurrentTemperature / (upperThresh * 0.5f), 4); + var hotTempMulti = Math.Min(temperComp.CurrentTemperature / upperThreshHalf, 4); + + Logger.DebugS("silicon", $"Silicon {silicon} is overheating, multiplier is {hotTempMulti}."); // If the silicon is hot enough, it has a chance to catch fire. FlammableComponent? flamComp = null; siliconComp.OverheatAccumulator += frameTime; - if (siliconComp.OverheatAccumulator >= 10) + if (siliconComp.OverheatAccumulator >= 5) { - siliconComp.OverheatAccumulator =- 10; + siliconComp.OverheatAccumulator =- 5; if (EntityManager.TryGetComponent(silicon, out flamComp) && temperComp.CurrentTemperature > temperComp.HeatDamageThreshold && !flamComp.OnFire && - _random.Prob(Math.Max(temperComp.CurrentTemperature / (upperThresh * 15), 0.9f))) + _random.Prob(Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 5), 0.001f, 0.9f))) { _flammableSystem.Ignite(silicon, flamComp); } else if ((flamComp == null || !flamComp.OnFire) && - _random.Prob(Math.Max(temperComp.CurrentTemperature / (upperThresh * 10), 0.45f))) + _random.Prob(Math.Clamp(temperComp.CurrentTemperature / (upperThresh), 0.001f, 0.75f))) { _popup.PopupEntity(popupOverheating, silicon, silicon, PopupType.SmallCaution); } + + // Logger for the random chances. + Logger.WarningS("silicon", $"Silicon {silicon} has a {Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 15), 0.001f, 0.9f)} chance to catch fire, and a {Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 4), 0.001f, 0.75f)} chance to popup overheating."); } return hotTempMulti; diff --git a/Content.Server/Temperature/Systems/TemperatureSystem.cs b/Content.Server/Temperature/Systems/TemperatureSystem.cs index b28e7909ec..b2ccc43a81 100644 --- a/Content.Server/Temperature/Systems/TemperatureSystem.cs +++ b/Content.Server/Temperature/Systems/TemperatureSystem.cs @@ -4,6 +4,7 @@ using Content.Server.Administration.Logs; using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; +using Content.Server.Body.Components; using Content.Server.Temperature.Components; using Content.Shared.Alert; using Content.Shared.Damage; @@ -37,7 +38,7 @@ public override void Initialize() { SubscribeLocalEvent(EnqueueDamage); SubscribeLocalEvent(OnAtmosExposedUpdate); - SubscribeLocalEvent(ServerAlert); + SubscribeLocalEvent(ServerAlertNotDumb); // See ServerAlert for how upstream handled it. SubscribeLocalEvent>( OnTemperatureChangeAttempt); @@ -128,7 +129,7 @@ private void OnAtmosExposedUpdate(EntityUid uid, TemperatureComponent temperatur private void ServerAlert(EntityUid uid, AlertsComponent status, OnTemperatureChangeEvent args) { - switch (args.CurrentTemperature) + switch (args.CurrentTemperature) // Why the hell would you do temperature alerts like this?? - Parkstation. { // Cold strong. case <= 260: @@ -167,6 +168,81 @@ private void ServerAlert(EntityUid uid, AlertsComponent status, OnTemperatureCha } } + /// Parkstation Temperature Alerts + /// + /// Finds the TemperatureComponent and the ThermalRegulatorComponent, and uses _alertsSystem to set the alert level based on the range of temperatures as allowed by those components. + /// Does some math to determine the alert level based on the current temperature and the range of temperatures allowed by the ThermalRegulatorComponent. + /// + private void ServerAlertNotDumb(EntityUid uid, AlertsComponent status, OnTemperatureChangeEvent args) + { + if (!EntityManager.TryGetComponent(uid, out TemperatureComponent? temperatureComponent)) + return; + + var temp = args.CurrentTemperature; + var minSafeTemp = temperatureComponent.ColdDamageThreshold; + var maxSafeTemp = temperatureComponent.HeatDamageThreshold; + + if (!EntityManager.TryGetComponent(uid, out ThermalRegulatorComponent? thermalRegulator)) + { + // If the entity does not have a ThermalRegularComponent, set the alert to 1 at 90% of the DamageThresholds, 2 at 130% of the DamageThresholds, and 3 at 180% of the DamageThresholds. + if (temp >= maxSafeTemp * 0.9) + { + short alertLevel = (short) (temp >= maxSafeTemp * 1.6 ? 3 : + temp >= maxSafeTemp * 1.2 ? 2 : + 1); + + _alertsSystem.ShowAlert(uid, AlertType.Hot, alertLevel); + return; + } + + if (temp <= minSafeTemp * 1.1) + { + short alertLevel = (short) (temp <= minSafeTemp * 0.4 ? 3 : + temp <= minSafeTemp * 0.8 ? 2 : + 1); + + _alertsSystem.ShowAlert(uid, AlertType.Cold, alertLevel); + return; + } + + _alertsSystem.ClearAlertCategory(uid, AlertCategory.Temperature); + return; + } + + var minComfTemp = thermalRegulator.NormalBodyTemperature - thermalRegulator.ThermalRegulationTemperatureThreshold; + var maxComfTemp = thermalRegulator.NormalBodyTemperature + thermalRegulator.ThermalRegulationTemperatureThreshold; + + // If the temperature is within the range of temperatures allowed by the ThermalRegulatorComponent, clear the alert. + if (temp >= minSafeTemp && temp <= maxSafeTemp) + { + _alertsSystem.ClearAlertCategory(uid, AlertCategory.Temperature); + return; + } + + // If the temperature is below the minimum temperature allowed by the ThermalRegulatorComponent, set the alert to Cold. + if (temp < minComfTemp) + { + short alertLevel = (short) (temp <= minSafeTemp * 0.75 ? 3 : + temp <= minSafeTemp ? 2 : + Math.Max(Math.Floor(temp / minComfTemp), 2)); + + _alertsSystem.ShowAlert(uid, AlertType.Cold, alertLevel); + return; + } + + // If the temperature is above the maximum temperature allowed by the ThermalRegulatorComponent, set the alert to Hot. + if (temp > maxComfTemp) + { + short alertLevel = (short) (temp >= maxSafeTemp * 1.25 ? 3 : + temp >= maxSafeTemp ? 2 : + Math.Max(Math.Floor(temp / maxComfTemp), 2)); + + _alertsSystem.ShowAlert(uid, AlertType.Hot, alertLevel); + return; + } + } + /// Parkstation Temperature Alerts + private void EnqueueDamage(EntityUid uid, TemperatureComponent component, OnTemperatureChangeEvent args) { ShouldUpdateDamage.Add(component); diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs index 86fbe0ff4b..cd570fb367 100644 --- a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs @@ -12,13 +12,11 @@ public sealed class SharedSiliconChargeSystem : EntitySystem // Dictionary of ChargeState to Alert severity. private static readonly Dictionary ChargeStateAlert = new() { - {ChargeState.Full, 5}, - {ChargeState.Mid, 4}, + {ChargeState.Full, 4}, + {ChargeState.Mid, 3}, {ChargeState.Low, 2}, {ChargeState.Critical, 1}, {ChargeState.Dead, 0}, - // {ChargeState.Full, 5}, - // {ChargeState.Full, 6}, }; public override void Initialize() diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index ca94f34712..a3c7518f71 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -121,10 +121,6 @@ - map: ["socks"] - map: ["underpants"] - map: ["undershirt"] - - shader: StencilMask - map: [ "enum.ClothingVisualLayers.Top" ] - sprite: Clothing/Uniforms/Jumpsuit/Color/grey.rsi - state: jumpsuit_bottom - map: ["jumpsuit"] - map: ["enum.HumanoidVisualLayers.LHand"] - map: ["enum.HumanoidVisualLayers.RHand"] diff --git a/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml b/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml index cf7157e9dd..5e729c2532 100644 --- a/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml +++ b/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml @@ -11,9 +11,7 @@ state: charge3 - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi state: charge4 - - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi - state: charge5 name: alerts-charge-name description: alerts-charge-desc minSeverity: 0 - maxSeverity: 5 + maxSeverity: 4 diff --git a/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml b/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml new file mode 100644 index 0000000000..9a2ae30ad9 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml @@ -0,0 +1,91 @@ +- type: entity + id: BaseIPCOrgan + parent: BaseItem + abstract: true + components: + - type: Sprite + netsync: false + sprite: SimpleStation14/Mobs/Species/IPC/organs.rsi + - type: Organ + - type: Food + - type: Extractable + grindableSolutionName: organ + - type: SolutionContainerManager + solutions: + organ: + reagents: + - ReagentId: MotorOil + Quantity: 10 + +- type: entity + id: OrganIPCBrain + parent: BaseIPCOrgan + name: positronic brain + description: "The source of as much controversy as the existence of the soul." + components: + - type: Sprite + state: brain + sprite: Mobs/Species/Human/organs.rsi + - type: Organ + - type: Input + context: "ghost" + - type: InputMover + - type: MovementSpeedModifier + baseWalkSpeed: 0 + baseSprintSpeed: 0 + - type: GhostOnMove + - type: Brain + +- type: entity + id: OrganIPCEyes + parent: BaseIPCOrgan + name: robotic eyes + description: "01001001 00100000 01110011 01100101 01100101 00100000 01111001 01101111 01110101 00100001" + components: + - type: Sprite + layers: + - state: eyeball-l + - state: eyeball-r + - type: Organ + +- type: entity + id: OrganIPCTongue + parent: BaseIPCOrgan + name: vocal modulator + description: "A vocal modulator, used to produce speech." + components: + - type: Sprite + state: tongue + - type: Organ + +- type: entity + id: OrganIPCEars + parent: BaseIPCOrgan + name: "sonic receptors" + description: + components: + - type: Sprite + state: ears + - type: Organ + +- type: entity + id: OrganIPCPump + parent: BaseIPCOrgan + name: micro pump + description: "A micro pump, used to circulate coolant." + components: + - type: Sprite + state: heart-on + - type: Organ + # The heart 'metabolizes' medicines and poisons that aren't filtered out by other organs. + # This is done because these chemicals need to have some effect even if they aren't being filtered out of your body. + # You're technically 'immune to poison' without a heart, but.. uhh, you'll have bigger problems on your hands. + + # This is fine? + # - type: Metabolizer + # maxReagents: 2 + # metabolizerTypes: [Human] + # groups: + # - id: Medicine + # - id: Poison + # - id: Narcotic diff --git a/Resources/Prototypes/SimpleStation14/Body/Prototypes/ipc.yml b/Resources/Prototypes/SimpleStation14/Body/Prototypes/ipc.yml new file mode 100644 index 0000000000..ac19b7a09e --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Body/Prototypes/ipc.yml @@ -0,0 +1,45 @@ +- type: body + id: IPC + name: "ipc" + root: torso + slots: + head: + part: HeadIPC + connections: + - torso + organs: + eyes: OrganIPCEyes + torso: + part: TorsoIPC + connections: + - left arm + - right arm + - left leg + - right leg + organs: + brain: OrganIPCBrain + heart: OrganIPCPump + right arm: + part: RightArmIPC + connections: + - right hand + left arm: + part: LeftArmIPC + connections: + - left hand + right hand: + part: RightHandIPC + left hand: + part: LeftHandIPC + right leg: + part: RightLegIPC + connections: + - right foot + left leg: + part: LeftLegIPC + connections: + - left foot + right foot: + part: RightFootIPC + left foot: + part: LeftFootIPC diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml index 36c05dd8ac..2928930f1a 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -4,12 +4,14 @@ name: Urist McPositronic description: A positronic brain in a metal body. components: + - type: Inventory + templateId: ipc - type: Battery maxCharge: 150000 - type: Silicon entityType: enum.SiliconType.Player batteryPowered: true - drainRateMulti: 500 + drainRateMulti: 50 chargeRateMulti: 50 chargeStateThresholdMid: 0.70 chargeStateThresholdLow: 0.35 @@ -33,3 +35,5 @@ components: - type: HumanoidAppearance species: IPC + - type: Inventory + templateId: ipc diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 55a7e02e17..2b3733a65b 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -112,6 +112,17 @@ - type: MobThresholds thresholds: 0: Alive + 165: Dead + - type: Destructible + thresholds: + - trigger: !type:DamageTrigger + damage: 175 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - type: Repairable + fuelcost: 60 + doAfterDelay: 32 - type: Bloodstream damageBleedModifiers: BloodlossIPC bloodReagent: Water @@ -135,8 +146,8 @@ types: Heat: 0.75 #per second, scales with number of fire 'stacks' - type: Temperature - heatDamageThreshold: 340 - coldDamageThreshold: 0 + heatDamageThreshold: 320 + coldDamageThreshold: 255 currentTemperature: 320.15 specificHeat: 50 coldDamage: @@ -144,7 +155,7 @@ Cold: 0.1 #per second, scales with temperature & other constants heatDamage: types: - Heat: 0.25 #per second, scales with temperature & other constants + Heat: 0.15 #per second, scales with temperature & other constants atmosTemperatureTransferEfficiency: 0.4 - type: ThermalRegulator metabolismHeat: 1000 # Increase once we have more ways to regulate temperature @@ -152,46 +163,30 @@ implicitHeatRegulation: 600 sweatHeatRegulation: 0 shiveringHeatRegulation: 12000 - normalBodyTemperature: 130 - thermalRegulationTemperatureThreshold: 130 - + normalBodyTemperature: 280 + thermalRegulationTemperatureThreshold: 32 - type: Polymorphable - type: Identity - type: MovedByPressure - - type: Barotrauma - damage: - types: - Blunt: 0.35 #per second, scales with pressure and other constants. - type: DamageOnHighSpeedImpact damage: types: Blunt: 5 soundHit: - path: /Audio/Effects/hit_kick.ogg + path: /Audio/Effects/metalbreak.ogg - type: LagCompensation - type: RangedDamageSound soundGroups: Brute: - collection: MeatBulletImpact + collection: MetalBulletImpact soundTypes: Heat: - collection: MeatLaserImpact + collection: MetalLaserImpact - type: Tag tags: - CanPilot - FootstepSound - DoorBumpOpener - - type: Reactive - groups: - Flammable: [Touch] - Extinguish: [Touch] - Acidic: [Touch, Ingestion] - reactions: - - reagents: [Water, SpaceCleaner] - methods: [Touch] - effects: - - !type:WashCreamPieReaction - - type: Hands - type: Inventory templateId: human @@ -228,20 +223,49 @@ - key: enum.StrippingUiKey.Key type: StrippableBoundUserInterface - type: Emoting - - type: BodyEmotes - soundsId: GeneralBodyEmotes - type: Grammar attributes: proper: true - type: StandingState - type: CanEscapeInventory - - # Things that likely need to change, taken from human. - type: HumanoidAppearance species: IPC - type: Body prototype: IPC requiredLegs: 2 + - type: Ensnareable + sprite: Objects/Misc/ensnare.rsi + - type: MeleeWeapon + hidden: true + soundHit: + collection: Punch + angle: 30 + animation: WeaponArcFist + attackRate: 1 + damage: + types: + Blunt: 6 # It's metal. + - type: MobPrice + price: 1500 # Kidnapping a living person and selling them for cred is a good move. + deathPenalty: 0.01 # However they really ought to be living and intact, otherwise they're worth 100x less. + + # Things that likely need to change, taken from human. + - type: Barotrauma + damage: + types: + Blunt: 0.28 #per second, scales with pressure and other constants. + - type: Reactive + groups: + Flammable: [Touch] + Extinguish: [Touch] + Acidic: [Touch, Ingestion] + reactions: + - reagents: [Water, SpaceCleaner] + methods: [Touch] + effects: + - !type:WashCreamPieReaction + - type: BodyEmotes + soundsId: GeneralBodyEmotes - type: DamageVisuals thresholds: [20, 40, 100] targetLayers: @@ -257,23 +281,8 @@ color: "#FF0000" Burn: sprite: Mobs/Effects/burn_damage.rsi - - type: Ensnareable - sprite: Objects/Misc/ensnare.rsi - - type: MeleeWeapon - hidden: true - soundHit: - collection: Punch - angle: 30 - animation: WeaponArcFist - attackRate: 1 - damage: - types: - Blunt: 5 - - type: MobPrice - price: 1500 # Kidnapping a living person and selling them for cred is a good move. - deathPenalty: 0.01 # However they really ought to be living and intact, otherwise they're worth 100x less. - type: Speech - speechSounds: Tenor + speechSounds: Pai - type: Vocal sounds: Male: MaleHuman diff --git a/Resources/Prototypes/SimpleStation14/InventoryTemplates/ipc_inventory_template.yml b/Resources/Prototypes/SimpleStation14/InventoryTemplates/ipc_inventory_template.yml new file mode 100644 index 0000000000..68ea238150 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/InventoryTemplates/ipc_inventory_template.yml @@ -0,0 +1,140 @@ +- type: inventoryTemplate + id: ipc + slots: + - name: shoes + slotTexture: shoes + slotFlags: FEET + stripTime: 3 + uiWindowPos: 1,3 + strippingWindowPos: 1,3 + displayName: Shoes + - name: jumpsuit + slotTexture: uniform + slotFlags: INNERCLOTHING + stripTime: 6 + uiWindowPos: 0,2 + strippingWindowPos: 0,2 + displayName: Jumpsuit + - name: outerClothing + slotTexture: suit + slotFlags: OUTERCLOTHING + slotGroup: MainHotbar + stripTime: 6 + uiWindowPos: 1,2 + strippingWindowPos: 1,2 + displayName: Suit + # Underwear + # - name: undershirt + # slotTexture: undershirt + # slotFlags: UNDERSHIRT + # stripTime: 8 + # uiWindowPos: 4,1 + # strippingWindowPos: 3,1 + # displayName: Undershirt + # - name: underpants + # slotTexture: underpants + # slotFlags: UNDERPANTS + # stripTime: 12 + # uiWindowPos: 4,0 + # strippingWindowPos: 3,2 + # displayName: Underpants + # - name: socks + # slotTexture: socks + # slotFlags: SOCKS + # stripTime: 8 + # uiWindowPos: 4,2 + # strippingWindowPos: 3,3 + # displayName: Socks + - name: gloves + slotTexture: gloves + slotFlags: GLOVES + uiWindowPos: 2,2 + strippingWindowPos: 2,2 + displayName: Gloves + - name: neck + slotTexture: neck + slotFlags: NECK + uiWindowPos: 0,1 + strippingWindowPos: 0,1 + displayName: Neck + # - name: mask + # slotTexture: mask + # slotFlags: MASK + # uiWindowPos: 1,1 + # strippingWindowPos: 1,1 + # displayName: Mask + # offset: 0.5, 1.5 + # - name: eyes + # slotTexture: glasses + # slotFlags: EYES + # stripTime: 3 + # uiWindowPos: 0,0 + # strippingWindowPos: 0,0 + # displayName: Eyes + - name: ears + slotTexture: ears + slotFlags: EARS + stripTime: 3 + uiWindowPos: 2,0 + strippingWindowPos: 2,0 + displayName: Ears + - name: head + slotTexture: head + slotFlags: HEAD + uiWindowPos: 1,0 + strippingWindowPos: 1,0 + displayName: Head + offset: 0, 0.03125 + - name: pocket1 + slotTexture: pocket + slotFlags: POCKET + slotGroup: MainHotbar + stripTime: 3 + uiWindowPos: 0,3 + strippingWindowPos: 0,4 + dependsOn: jumpsuit + displayName: Pocket 1 + stripHidden: true + - name: pocket2 + slotTexture: pocket + slotFlags: POCKET + slotGroup: MainHotbar + stripTime: 3 + uiWindowPos: 2,3 + strippingWindowPos: 1,4 + dependsOn: jumpsuit + displayName: Pocket 2 + stripHidden: true + - name: suitstorage + slotTexture: suit_storage + slotFlags: SUITSTORAGE + stripTime: 3 + uiWindowPos: 2,0 + strippingWindowPos: 2,5 + dependsOn: outerClothing + displayName: Suit Storage + - name: id + slotTexture: id + slotFlags: IDCARD + slotGroup: SecondHotbar + stripTime: 6 + uiWindowPos: 2,1 + strippingWindowPos: 2,4 + dependsOn: jumpsuit + displayName: ID + - name: belt + slotTexture: belt + slotFlags: BELT + slotGroup: SecondHotbar + stripTime: 6 + uiWindowPos: 3,1 + strippingWindowPos: 1,5 + displayName: Belt + - name: back + slotTexture: back + slotFlags: BACK + slotGroup: SecondHotbar + stripTime: 6 + uiWindowPos: 3,0 + strippingWindowPos: 0,5 + displayName: Back diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge-empty.png b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge-empty.png new file mode 100644 index 0000000000000000000000000000000000000000..13a8ca907018494f1a0b9ea8402022df78295bab GIT binary patch literal 386 zcmV-|0e$|7P);#Re>#06loH# zc*p=_Y;Sx^@C{pb5wjGHO103E9dFT)=hB-omop zfXqOBVrn#|cqb0-d1ogu2M-w_blii~%n|Fr*JPk+n&$#zRx=w=fQYXXZ8O5n#c`ac z?IFZIpq^(c&`W?leR16J-WAX~PsOsP;a}kA1kyAmaU64T)UF3X0A*Qz{?F)ELbh@B g!{U<&pv2I`I}~;%Hxn1XiV03m zPA;-An;0556BiTH2?j#!o%d!Bgz-yM&4`UF3$#{jTxJEnZG zSiopBQf>x-=DMy+V}rpUCWxy7WSOH9a}MzsHSntdVyG?!3P=Qqlfo$N8Uz80^Z7g` z2z=!7bT}L&0A{{gt)Qw5!;m1pQmO{l>osh*Tb4h!+kE`hwt23#_d(ON z!oVp2G_Tcau-RF)9J8?<|H)Fnz+~N2@pp$ z8jWfIqA3Z@@wQ|MAxO*R63R#dz#<$DhkRusNS^50X0r*7;}qV7`)Wj315p%Rv~m(& zOWXf#H6Rw3c%Ma45n{pO_V0E(D5F#jv|23*0P`#eG8g6he)Sr_hJw#DnTU~u#{2!A z<+SqIY*wfdd7hUIfRmJIC}p~!2%sdtPNc(#4i{BbGxIzp=K!0pC;*3m>f+{f;#~?L zefd_puSWC_@aF)g)2U*bW}HN6yxZ-9>$=zfXCy*kPTh~pZvsFNd7pg(6R*Wf7-m`I P00000NkvXXu0mjfry1u! literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!VDw>HYaZfQv3lvA+DJ@3=9?w3_pMnL~r<_ z_#Y_6SQ6wH%;50sMjD8duOQ68ajggPXNrR1p(_*p2 w10QDAt_&`pwk1rnSVR_{P?EU2n1P4k$KK%n#Z{S+K%*EuUHx3vIVCg!07C#X-~a#s diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge1.png b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge1.png index 8cb2543a96df9e1e6fc6d1003f9f6406d3ef1c27..46d304d7767898d5fc66965d23211e647a1f2a02 100644 GIT binary patch literal 641 zcmV-{0)G98P)$`WU8}p3gCMy0uLw$q zOinJz;w*^8E#M+ZCo_oH$;qvx_Yz-v*CcI|GivL72k+(blzJyjKr>+&BkpF z!*B=!U%4pl_j>`rHJ{JtAgg-4E8x?841v zlY{V7C=}!XcvBLZKR;Ta)xB*tLI5^EOZOm1)9DnFNC3bj>~_2Uoe>C`yD=MPi#vyo zEf$L~9*<)`g=704nrk3?K@mPBNC(8joxp16YUvd!5 zDG4!Q@$s)#D@dY14wOnI0RUq@+4z3`Z9&<#EuRB8q2N1BCVWdmiRDD3z2ULAP)dx_jJ^=Cx)CYbGAe?+IUELRv0{CA5sy@I& bMD6HYaZfQv3lvA+C;03=9?w3_lWW<fnn}>g_cE*9t?B+dzi%CgG4kI tX$Htl;yS^l;l#z^Dt7RN9BTptgM7E9;p*vzK#Ld{JYD@<);T3K0RZR1FoXaA diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge2.png b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge2.png index 4df8884917d27541fc575410a26e0cbb869eb3a2..cd7f73756b45d07058f089c677dc0914fa74beed 100644 GIT binary patch delta 572 zcmV-C0>k~m0m%fA7=H)`0001UdV2H#000SaNLh0L01m_e01m_fl`9S#0005|NklAs=6vtnnQ$9dJ99$L0Y=YmRx;wcELh+Lngg9k#axsguASrGE7ePAdAYvz{ zY~_0Il6PL3#FE6=7W)TtFP9_#-`%~tix2R_x(@)`wi(6q`F|XS!=ZLF05os4TA{jr zzt0GwP=Gjd6gQU;_mKmC3V=a=X^=uH0ON^~*>%6)i*h=hGJ?P*m!#9_6aoM^?EJh$9i4XzuLBpTklUYHa|w9?DcwJ7)EN~2mqSvx(=(=3f=dYuHT3Jgi2eZz z(WS&H6g6Nx9&4RWhw(C0-)uI)ah&4+8L1E$)9y#+Hvu4sq-UQyw$m7NMi9XO0000< KMNUMnLSTaS83f<} delta 177 zcmX@fa*%O?L_HHT0|Nt}$fR^2#S`EY;=0O{li>#gg9XEn9}GI7m$ZQ5j3q&S!3+-1 zZlr-YN#5=*3>~bp9zYIffk$L90|U1(2s1Lwnj--eWH0gbb!C6fEXv8ReVD!JIZ#N? z)5S4F;&O7r0-+00tZdv8%i5Y8Sq|%TXr16uIkx|=Mo(snVOoNrWS-_7$q*)n%6S3D U*QqY#1!`sRboFyt=akR{07!-}?EnA( diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge3.png b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge3.png index f001eb6dbb97ccc90a6649f46ca8df9b182a06c2..0745be8ff2251ab57dfd5cf1477666dfedc2f6e9 100644 GIT binary patch literal 2826 zcmV+l3-$DgP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+Qpb_lIyq)h5vIES%UZkxg0*LvV&QEK2Vac?e?8a z_e?5wwMkJF37!KSKyBt9|6b-_eEe|)6Qbl)QabpA5{j#I@^OCZ{&*Nygiql9by{I<}wkyne>+C1BFpCq4uMt|Bp8n4N3*FivUME3E{O>h0dulMdW!0VqkzS8mhIv<#L z_(4lX?&wd^^?`#EkP4RCar$_s7+}QY;l@0yV&LLkt z_d1^D>22nCLtp>a8hPzAbBY=gP^arq_fd9_d5tY}>ufMB9l~E^3EAJmH?vR26~@tz z#<$yI9ds=l?6B1?J9pb{$Hd^KaYDzr?))CiUR-e<_N)*3wabYwe)tTpebXMid)Q+4 zw&mz%@0QtlSf)D5VwOj~{WafxU@Z*=YmfZE3cH+BurWiK(_f~+h+P+`aRYpR-#^N$ zhry^QYlswpZRZj#+FwfGH_@Jnk@k#1E8|)Kh}b$}jP)=8Ys7<1_7La9T7b+DR54v+ zron)X(G84r!TSU^+3D6iB6d%8(J^coN6cU%`s4*}im#9rLd1V0WPGSbA47~WMTt3< zSd&j7#gvjH6~!uEf{`dmM6wjA+2@dBPFZr!CD-DLM>JzeMM^HE)XJWfl`BtICe+$o z^DVS!T58gAE3J0ir-vSU>e6#By$(10KtDzrGV&;+PCId>8D^Ym%FMIOx^T7S%?c~7 zv}EN~R(-H`(fZ~44c6?%n%hk2M0v2rsK~v9RXK^u8H70#ER2g%fI~aw?8r6*r_3p5 zM?wC4bQl?xvtgAn7!1?8xa`fHaVMk7+~4BONOYwT^#!T4;PZ_Kb-nIbGrGGjT6K&{vCeRYEk zN0~`h?NO}=vym1SB~BT-ch~1Sc7`rlE$c~zFi=mgIAe?Kr>#NLu^rXQWw*znJ-<7ED zD`JR4Afw_FRqZ%*ia(i2o0$SLiEPkDjSDT#w^uycbd3JuAm;QCbwC`V4pK#(>2w#J zN81wyblFofV!LdwUoXsJK2t||@Wi(!A7$*erdlN+KND??9m(8usBFm5NjV#mn1Y+Me!N=Zn9LzfmgFLXgD=;l#rdxm`;gr z{vO4JV%fq@W?hA_FKQ$A4o_n5mhD=dL6_}*IvyLx3WjQ8k;46UVjQsS7N?bgyV=-$ z;AKmwwAnz@Z7DcyT0^}>DqdXFi!Ba0aB~;6#qYJZk{#-#cSnfT)f;HalC;Sf)hR)0h-zjQYZG<_-IEi!_;$01p!luhB3It zv>9WUA=D3D-y{br6RXE|*$7(D`Dg;B^id5|+V0eM2u9$tD!weP;Ll^Z7 zV9Re`mXIYXaZw2F7KMz9JwRMK(t~Ct_{14f_X)aasbun9BIKines>Iv+urgI0ag#N#P^+>ZhZL&-6tD2tR8~Y( zJ#TJRLu3+rJk`cPJ_wvS{EM#0EiAs4u!}%`2K4%5~sqXJ_=Z zBaQlVX+A+6!Ytjdcq@v{v#O#PzPeV=wkikOxb(Hj4U;@CRJ-BvpIA z-d*F2ZPHP)OGqTZw&6Zos#VPxQPZP(rF;opZf94oh6LI1#9t-M&s+2P#&coCF|-#b zSRn0cDdDs{S!C;$=g}8ID_b53CTGiwxUd5?G0N`6Zmq)gkQ?(z z!mlI`)%5$&DtT?^Gu=FWh-Z7{&Yt z7IGzO6fm=^00006VoOIv0IC3|0GQ!7Y})_;010qNS#tmY4#WTe4#WYKD-Ig~000Mc zNliru=K~lC4-#%@(lP)50sBcrK~z}7?N`5Q<1iflbae6q9GDDQ9Xe_YUd}X5H;}007Q; zVMN4n+`0a6I5Y$lj4=oy25;YW-G+$1CP12|$g&Io@b&h#n*SL^RsY-XyQ;tX^9TU& zeIJz4t0X^KhP@|G2*|PwmSsUoiC-nD)*8_IOo~U?wq1@+-_>e`Fbsz|;e0*^07xmT zIj!~8AA6ox6LG?HIvpGZ=N*>_!w@M=froM;0gwU+Pa+I9o6Yb%AcTNrS+H%pxw{8| z9?M1n)J$#GI*x-p&)?<*o<-7c`91031IOdBVFCcacOa!L6If?+nd9&Bfua=!ggkQs z_2c(E4+u+A1MBRBQc5_E1EtjPR4jzRY&L5Mux-2HZ1wqiv;aV!=e;B0q8RzU53O~> z493w++wb=kxl#&BDXiD)Uc}q&_PPlurLRgTU0Lv@CLlo&G>VZaE|baRYQGDd^NWf| zUJ?bIbK<)0o0el!@rozv^-aBsjde@@ypnzBJK?|k{OZDTxx9FkEEbDmRB@$FD)5S4F z;&O7r0-+00tZdv8%i5Y8Sq|%ToZwN>bh~k7X{1L_W{P22f}v!d<{ilpCWhwa9{lA! Sp7(*889ZJ6T-G@yGywo|GA@4r diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge4.png b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/charge4.png index dd76743bc90e170b402db311afde4da64f23e368..1557455a41a65259ae384cb60c0ee5c6b5c383fd 100644 GIT binary patch delta 590 zcmV-U0As=6n=qD`2huSa8(?$3I2!1-N``^gyJtL2$2q%oLtP}EJ%u5z(tTwI*8cG zDO*YNE_vsjCe|d4E!Ypty}KOwzPtP0-T45&jQbE^S(ZofbbmU9e!s8WOaPMWx-PYK zyIqe&LxBVk1$e$OQnPNiTUL(8V~<2&%EjSu zI7k8*`FuWytY|bEk_d(ib8_YZ$8lh}T(bDFTIKC;mc?WJ}ND#>!Q|a5z+&&8Fvy6F#_)rI!GgizsuLqnkg+7lFPOpM*^M+1 zC&}C0g`tC0)&r!xz$3Dlfq`2Xgc%uT&5-~KvX^-Jy0SlK7UkrZZ6~LKmV~*|;T^wKX}i9M6`)z zGL{7S1v5B2yO9RsBze2LFm$lWdVrJ{ctjR6FmMZlFeAgPITAoY_7YEDSN7-3qMZCJ z8Q1pj0}2^=x;TbNTux3{Aao&$m5p0sSzD7M%VC|46Fe$zH?Az58JJjb%w&^<@rD^Z f+eO~-XfZM@_j7ul*7{fssGGsl)z4*}Q$iB}m_#wV diff --git a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/meta.json b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/meta.json index a0b634ef6c..ee07837524 100644 --- a/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/meta.json +++ b/Resources/Textures/SimpleStation14/Interface/Alerts/charge.rsi/meta.json @@ -1,35 +1,35 @@ { - "version": 1, - "license": "CC-BY-SA-3.0", - "copyright": "taken from tg station at commit https://github.com/tgstation/tgstation/commit/7e93c2d8ff8b80d0987daf0adfbcc825f7a46d38", - "size": { - "x": 32, - "y": 32 + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from Yogstation at https://github.com/yogstation13/Yogstation/commit/aaaed39293dd0b9edace6e2fe2017203e7352ef2", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "charge0" }, - "states": [ - { - "name": "charge5" - }, - { - "name": "charge4" - }, - { - "name": "charge3" - }, - { - "name": "charge2" - }, - { - "name": "charge1", - "delays": [ - [ 0.4, 0.4 ] - ] - }, - { - "name": "charge0", - "delays": [ - [ 0.5, 0.5 ] - ] - } - ] -} + { + "name": "charge1", + "delays": [ + [ + 0.5, + 0.5 + ] + ] + }, + { + "name": "charge2" + }, + { + "name": "charge3" + }, + { + "name": "charge4" + }, + { + "name": "charge-empty" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix-inflamed.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix-inflamed.png deleted file mode 100644 index 3e8f7a6ee95b232154c151cd56d04b483afb93e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv=>VS)*8>L*oQU+f*g1Q1kN>m! ztk;VtZB*AhJS+Od+NcK?SH%I9F_r}R1v5B2yO9Ru_rGY zZMBM_JE@JatHC3}6-Z_mS+5eiUJ@ef;C&&agGFpHmxxv50;yAKN{y?UEDa??8xF2v g@@?4Jm{`Ef;If|cdoKI3LZHzMp00i_>zopr06OkJasU7T diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/appendix.png deleted file mode 100644 index f52d5b0cdc9107e523d1303c00afc770edcfe202..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*Y*g30*g5-DWYp`$ zle#6$G`zH>fU=AwL4Lsu4$p3+0XbHlE{-7@6O$7p-ZTitI(RVnHhMCwV%V%St6_uo zEWsC62CNr!69vj#%BKs?VpwgkYo0?%aHM1#(4det%wGccvQ+_1VeoYIb6Mw<&;$Ti CFE1eg diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain.png index 04d04890f6b4a831e8889c40f264d284b61fca71..da0a093fe15ce09395f4a51e0a0218c639b9b164 100644 GIT binary patch delta 238 zcmVe0T2KII0P^d zxt^$@=iq4Wo67)cFOh=1mz);bF$8vy1?soi=G#QpBTduRMm_iB9}pM0Pv;_f#d;BZ_c?D-H8vx&IJPT6wq5!c; owP_gS%^{}wVSqCv00JNY3onRIbj1TlHUIzs07*qoM6N<$f+EUamjD0& delta 436 zcmV;l0Zaag0?h-EBYy#uNklamXX`z%|4S0FqahNyr zy%`1+3WY+UxM#Gm55By4E0N*uU$OPwz0h^~35wq}`%ySNOR09sqG_01`%GC}?74b)J%W!kBgm zZj+LE0zl%)Q^cuJ${z#pVquEyl_mLKtv?AgfsWVa;@c^SWw<%qvO6rzj?Nh<)V5$Sb@!)p>2Y6 zyFK#7Jc8hP9&X!Z_ECzeeGb6+&uZYtp#=I8pES+it%xw4jAB>?I=?0uiP-1~9jESu z61esK0&Jv`GB@*pEAI+Dp<|UStg{YVMRV|1@GrKCrY&X^E&=@JVY$-;`fQ|<{%XSf eUZGGZ0Dc3ZO{M9W6`O_t0000wg1*aRFoLo=d;1|*> ziFcPfUGjq57fkX#-2&yN958groMtN>0V z0hswA-%z n3os_}8w1243t#~r4sZd-q`jSV!vVbj0000&VUCG9{xw%Wz)`GHtoE{Sw6RkHyO(T2nB-t`G4C2;KO@^k6(YdK4W9t zWGp8Ez6AL4Dbta0K4ot0gtkudbv7-o3in#e9&fuU+^@BN5#B9Z$frzInIx3f1LQK6 z$bBzr({r0(;r-=PrqgJSRD68oS7TXqE@KJV51$M78~4Fd2Y%M-%HFeZQuMoRj*tAD zSxEuVvLO^@D}QoW(gTg=i1U;w&QqoU_*T5t_QMA>nj;KdVCaHGbdPQAhZWE8^7O=k ziT#b{h8JTHPm! z4PB^xvT4_7MMF3_*{3`usKYW0p3pEe$@_#&T;6*OY!}UAvbUSJ+3F5H` z{cf93AV~S)iBj37RJQ322kh+n2?c`myX}?dy6)h47i4vYE@;^rpAx#d8aY3mx6FmL zelqDoZ#YoZNwQMeru^_kC=gVl+`zSfi(1|HXwQlOl!!!h4?`D9#C*=y0v3soS0afk z)rmMsDokI>n+RAYqEhXsCurz`O0`2g7MW?>W!U%|mH)$`K8_#l$=abliC0y>m4JC6 h^LUNeg9i^1{{ZSoB6z)o*qQ(U002ovPDHLkV1g%eAV~lK diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/eyeball-l.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/eyeball-l.png index 14e728707a96ff43cf2e118f6d0d3681abcafff5..09b98e316f87eb99894e3ff3ad1a4fff5f92ac0c 100644 GIT binary patch literal 4215 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 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/eyeball-r.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/eyeball-r.png index d18f4d4572511fc96b0b85503ff875353b14fb34..f1ff37a002f68e8d4485e68e3473b4d22d037f45 100644 GIT binary patch literal 4202 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 A^#A|> delta 328 zcmV-O0k{6@AmRd$BYy!YNkl0j6Lt-DVo}a0SXPQ z;Fg0Ng6x<90W@<&p@9|AYOy(hi5iYb(l;Z^au8sl)N(dPMh1Q)V?c2a68ndw=Fk8C z3?Kjh!I}^$cEIa@zd;6r*`;Hd-{tL&5O7#>+0e{SLkk4U;fqYAMaO>#y z|1Te&|9|V~j{nG6kS^fM+nfLY|9J+-e||ioU%o$fcr(~i*LC;*GfuqvUwGz?|G$4c z`hVrfcA^|WaT<`9mjTlUo_=RwsIp@C^y?o3Gcz*-zl=Ch`YCq6{fAG$G#?uigHYc| z1_x&00006^L5SKU<2s%Zw9Qjv?}KoSYZHaZj4#$EpPkZB1Eqs z=iF-N9P1hXJq641Y&G)&WPoY9LmDgqeQ5g>eC~Gvv}U)t;xP_0P)DHukBFL6;x?B9 ieh>;!fC3b7IN$~9qc4a4qqYbD0000Pi?@?-o zKmG`%eE6yAu~FHBukpidMjkKI%7T68^&P$5sNZFb^WVMP$N&g(606T20D=oY9xDBn z5%`~C|M+Hj|AU$t%4{r8HfsJqpB%g_s?vbV?Vtw4p)m{$x&0<_r*Gfg%K!wPu6{1- HoD!MO=u<5X=vX$A(y zxt=bLAr*7p&f3^{*g&E+{y~|=rP!&*QpG$TbKY6*JCW6Tb2X1ZQ*Qxpp1)KXwj%EDbW843Mb*KOeJAm^)$r?cD2zrt#|?Pal2$Sx~j}=d`QSRTOee z3dR4`%1M4W;~&SEedC|iW+I*=EHq`3H_$|1#*Wdc$6kRK=n<{r&enU)nE)d=Y~x*d+hJ6QtnPJ9di& hz5<}2gBx^?o5$$Oi@w&$wB}C delta 423 zcmV;Y0a*U)1GEE>7k@wq1^@s6s%dfF0004dNkl${&Ihzf>H((Lj{^AFp!7=XBsX)`v RmY@It002ovPDHLkV1hEc%3}Zk diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-l.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-l.png deleted file mode 100644 index 9bcb14ea9d3f3f6cb283a9bce160af850e2ba16e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJvz{)FArY;~60D08M0%P69rQA; zT>k0bdmvfrg+zj4*h7)@@E!fd-`=GySsbWPyi*O&=s<{_n5-J4cI8L4sA` zbnjJ`18>aZ?;Sk)T0b^%iJO&z7ViNaw$=kTqva(W_AL)nQnBJyV4m<^Qo*t@iCsXH zY5x8iw#y49Fu1Z8H7(i6>~Qe!+u!CE|NnKjCrF8~ex1JV!ac?X59)sPG(LR#disM2 z43=$CmJJ&03f7Ol-OcAwkebHECc-m&Q3c4+23%}n1_lNU3=2a-=A~**mIQi?!PC{x JWt~$(697sRW0(K{ diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-r.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/kidney-r.png deleted file mode 100644 index 442c81338c1f15403635468b5adebf3ea982f3f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 259 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJQ=Tr4ArY;~60D08M0%P69W*np zT>k0bDd@v2%dB(7D5Gn$wv9^Bw|8kOVe%Kb3K;`LIJ&)zBvx}agzowIsqf)KW3@%H zj)5X3uU;BliQmPvog>APqd}%wM#-d@fv2IS`r9>jHbFT>k#+%Q4PWN}jtd<)7g(@3 z1TuIt8_ci&_i1LvUlB`&6w5U-JN`dXjQMl>dp=KoyuJDeK%6H;Z?aGaiRm+as< z$E2LWLPf$s@gwiK;#~%7(8A5T-G@y GGywoav{>-~ diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/liver.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/liver.png deleted file mode 100644 index 159339e36c980119539cd11dc43964731d721907..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 290 zcmV+-0p0$IP)N*Fo{3aju&wTFy4BgIweGJR(Pjf8@{h;_7U*FcVJR`jf0O)q^ zHq9}ig8~-Y0x5L40rvLx|07*qoM6N<$f)QGJ-2eap diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-l.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-l.png deleted file mode 100644 index 32aca484b9fc08665323556abb5a3aab1e6e7cf7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJd!8G4U-!7ULw@2AMbS?e{IeA*r(@YTh(izN9AEkB>i_cgZ@G za2(M2|Nk2=^A$m!{C#^C&u4aENU`kMW;QM9$DgOhwK5GNUwF>P?@dS$5lghF`X+gF zn($i&wiW9gr+IgI8rbZvW7R49tvC15f!o*5ORl@Sk8hjIGmZ%nf0t_aloT@X9MECE zc!kNu+F?SxK%S-PCwm@&SiT0G+J8?pnc4NlZx{k4k0&mk$LDp_x%Y=W#3zmHJUl!M Yt2&}y|Bvjb1p1W0)78&qol`;+06lANPXGV_ diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-r.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/lung-r.png deleted file mode 100644 index 7e29649ccd8886c45fc090f4fb039498612cc5d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 275 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJTb?eCArY;~60D08M0%POd6!x2 z{^1*B%{+K3f-A?8<3PqPO9qy{d9}w5Xy_dJ@aHPG!Tc)$3r;X@ zfA4hZz~lS?Wl6FzQ?> zU|3_rV436~qi{l>qwL6Mb$>~Vik%*pPJ8gOo4k6tU`bWLtp#m6!F~vIs6KGu00YB* Xk4V|}u5V9)zGU!p^>bP0l+XkK4fJs$ diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/meta.json b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/meta.json index 354132ea11..642db61c96 100644 --- a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/meta.json +++ b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/meta.json @@ -1,38 +1,10 @@ { "version": 1, - "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation and cev-eris at https://github.com/tgstation/tgstation/commit/c4b7f3c41b6742aca260fe60cc358a778ba9b8c8 and https://github.com/discordia-space/CEV-Eris/commit/476e374cea95ff5e8b1603c48342bf700e2cd7af", "size": { "x": 32, "y": 32 }, "states": [ - { - "name": "appendix" - }, - { - "name": "appendix-inflamed" - }, - { - "name": "brain" - }, - { - "name": "brain-inhand-left", - "directions": 4 - }, - { - "name": "brain-inhand-right", - "directions": 4 - }, - { - "name": "ears" - }, - { - "name": "eyeball-l" - }, - { - "name": "eyeball-r" - }, { "name": "heart-off" }, @@ -42,39 +14,35 @@ [ 0.6, 0.1, + 0.1, + 0.1, 0.1 ] ] }, { - "name": "kidney-l" - }, - { - "name": "kidney-r" - }, - { - "name": "liver" - }, - { - "name": "lung-l" - }, - { - "name": "lung-r" + "name": "brain" }, { - "name": "stomach" + "name": "eyeball-r" }, { "name": "tongue" }, { - "name": "muscle" + "name": "eyeball-l" }, { - "name": "nerve" + "name": "microcell", + "delays": [ + [ + 0.5, + 0.5 + ] + ] }, { - "name": "vessel" + "name": "ears" } ] -} +} \ No newline at end of file diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/microcell.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/microcell.png new file mode 100644 index 0000000000000000000000000000000000000000..18b692a5a99ea63a4f475dc30e5f69cdcb14608d GIT binary patch literal 334 zcmeAS@N?(olHy`uVBq!ia0vp^3P9|@!3HF&`%2dVDb50q$YKTtz9S&aI8~cZnt_3l z!PCVtq+-t78;abA0z_CJDBs9YGu)*V;d_cDmu=%rmd}$ezKSnE^UCZQe??y`+w-=&#}D1!9$V2I++HB)z`)2N5RiMoVgA0!?`|!RTG{aDVE1Ru z-G)K!8ug5qZ5Zmd$<1y^)S3D%kj>>H?>#l2>&4m2cJ*2*^gZ5kK5F&*uaR~NE1&IZ zbidu&wvOk)&g$Cxwk>I#4C}6QTfI2hf1r_7R#?)(sA)^dSKEJfU9Rp0^1ljxIVp26 zy}#anymn_peVtt^LzfN{he87bh-k=SKJvM7?cAr#(Xm?cC$1;h9jIye$?%!+8S@!- e4uu7W8u)vkl=0_xPqGCD5QC?ypUXO@geCyzPKN^k literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/muscle.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/muscle.png deleted file mode 100644 index 38da7e760720f1bc6fb4a57d4cf3d086bc0e496c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvi2$Dv*8>L*yx%tS)}kq=8YXv3 zm~B+oOq0^|7M819ZTcLjhOs2bFPOpM*^M+Hr_j^IF+^ixa)Lz0ffWs>(uIs1L>yT9T3+ldmcYsBsp)v_(JQfeL17Il6M|kno7SXqKuB)Vq<3v9 z2Ufj$6*j4FNpt8K0ar%m#hardEjMXT5$!$`cxP?KlAcF-Y-y}*j{FQxCxw#(XID4@ PEobm_^>bP0l+XkK6L*yx%tS)}kq=8YY(= zSbP>J&R7!U7tG-B>_!@pW9#YS7$Pw>IbnhEi5P~3s&BXyc%Fr<=$LYand7kHC5A&6 z=A2+$CV5+=@&Hd>X6g#V?uA|w{tm1&Dl;C%FeL2akpGk@rwlZR!PC{xWt~$(695-3 BGdutQ diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/stomach.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/stomach.png deleted file mode 100644 index ebf1d5f5141efea3d613ee4a659f6e4f6c6b9dd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvp#Yx{*8>L*EVZ#Z5$W@+KI`j} zj{hgtB%H0^0hDDd3GxeOaCmkj4akZ1ba4#Pn0WTwMZpFI9_9=4^c>6`5*SqHG88c1 zsTZx!6uVHf&%0Xir@^TS+6T=XLf%#W>asn{e5Uz{V*p#NX;baDZmxm^*^bwaOj!}( m8D8zPMMJJPc})5Lob^X5=f?aEmDhpRFnGH9xvXAjrU+nsW-UFaR236wUeW&(0f<#~5;}R0!bv{hmF&+yDV+nsze3)9FOf zvMktaZh3{g+}yJO`>zMqz57V$sob9D;cqN&6kXSa$z+m@d%a#f;aLSRO?d#(Tojqk zW;57sx0$HxI)8_G0GS(xp->OB+wEw_s6(eGV~R1Td70OcbXbf*L7ls#3IV*m zwqP(fl7;&HK43*qSe11CVzFSm-7d=U^A5iZK=-mty1;~S` h1)!=LfCiv;fIr|^&Y)r1dW8T0002ovPDHLkV1lJl;yeHV delta 349 zcmV-j0iynd1or}vBYy!tNkl8`(!|)tB*xg(3Kl`6)GtI(3U#qM zcpJqVa1;b_RPYv@9D5Cdiy*qFR2Msy;!ui|8e0ss$H~r#i_7_K2j27W^6-KrNs=T< z|4fPd;c#U`qzxNQ)9LqnD2W7yp>uS19Xks^i!*$-z9SYqe}D9T4~Mwf3|Y_PLeoUh z4LE(ijkSmxb?|t#DBOe&fbCB)G2^khTcW28xOseFb~;0Ozs$*6NyJ$oasyu?L*Y*g3mmM}|`(q!G> z(g_r2ED7=pW^j0RBMr#$@pN$vk(ipCuz)>5w9#lrjr4*wD`yH!yRqZ);b6{ha9y`M!S+0dAC-!;* P&1LX(^>bP0l+XkKTjno@ diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/full.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/full.png index 10f6d3193cfa390868a15779debbe8b6338404f4..be0541cd2f95cbd54f497a48dde1d192588b64e6 100644 GIT binary patch delta 2178 zcmV-|2z~dW65E3 z`_B~4{%f6X0edKz$%CNO&W-wfBl{yiy$Cu7In_wD=todKf*kJ~bOe-tZI%r=#YYqB z*kiveN&9Q`r(UaaHoyGsBfQrI=Q!r!$XWb4$6EoXUuRsw#Nn5nV54;jb6P9n($NGC zdFQA5lcCX6RsGvdPpI58dcSU7(eiw@xECjfdwjcYNZzBeT>o&gPiMx@>%r})Gxo*% z`kk|jlYwf%MtlV#;<_@fgs5%^g>IXzxEf_*z%|KJ zr$Up)8XGmJ=y@29m@qeXYcaXVnH$g}=k=n=(Ph_xCcCy^_l|E}XdRnvGwZa3lRIH6 z6NC{S`S>!QJ}{@I0+CI(ub>yRIvZ*za{7yHK!oOTsw@Xz*Xu`radkjY)XSP88IG-6 zL>2nM1a1NCuu(AX9HiKf0JsQ83zQ)T1b`Yjp+Gh=MO6Tr6_@jp&d+NEDK?9*Q{E!hw9BJfHCPHmGGyRkqW}Io}S#H!0 ztY5AVP@{tyFQjy1yivnyjF$*fIuXSTfT4;I5RVE00-6eJR^${jn?ZlzJSZuO zStmsd2>L-RlP>HGZ$uTjKf=vK|AZTV7dfNQeTdvw+}@$qwG6d|*v>+As&&Xd+#jiM zDq8HmjOJ%IJ{|vmL9+t-5`%Rh!NPU4hE1sBlX53mAB4OlJ5w8bch!v^rCD!){Lkc1 z#|J^{)Yw9Qlqs%j+yK8RI6he%Kj)gDsJx1beNHhgXc)-=ctR3UtcNVi-#zk+(fr=V zrDSY%Po&u|x}szk`(9a9a^O)NqkUA>zERcup{HdG_=PeAiDn-_2iyv6?f6z-3Y5@1 zsdylEKfUnqw&uxAwt?hPTcwR0YRkpIP}@qJHnkmpUafsAF3o>zSdoVV3;Kv*(EzJS zgqAGU++%5oRV1>sV&F$NqFZ|1@hXc5RocWYv;{ShIs!)KEE?YQ zrRv0ZR8A-t(QrUhL^e=BrA8Y9?48$W^j{EoseXdl(@4>gON| zW98TiUya)WXCp>QTHn@TP4~eQ;BNoJK`6&TPb?e2y0TL=my7L5-E9uGiZNaqY4eSL zdI-h#6AaCo%#;3HG$BySw2EDED(F^nlFe~oklq_2R{3urXBH43LQ^wR$-$1g9)xk5 zCQ3$2@|X#*o;^BuG@_krK&z07xQxzkVsT;JDFY4a%}tg&4x_$d9z ztSdF~LW;~qS6jEgFZ#vH0jioUX7xm)>`c*@4!nx&xX(x4uksFW3i>afe*wDys05Z~ zX88aB00v@9M??Us0H*+$;WuoP-vuFm84L|N*POk?0005bNklAkI1ia)D8}zdq-3}3YfYJk$9-<3vKMU<8oEV(Xkl)-x`NE{Ft#!iO$SjJkqwI-5W!{KkAJe3;HARv;W*d-_!6jd@~&$%<6v zouY6x4U4jZ)q3Fskw9Mc_@DHDW`ypNg3tF?hyF!b)#27sK~Yu>{asT~log~Z2hIR8 zLZ|0O=kXF#m0R5lXR_HIkz}(yBA@3pG<9uzZb|_!vzzS^$DRxO0R07*qoM6N<$ Ef-a62mjD0& literal 5707 zcmeHJdpwls9)C?PGns6znMk9QaFmo>#wv{5l69St*1DI=R_-$HN;1kN;fUOc$X1I` zlG2f6P9@b0m1t;BCZ|{wJ3G&OymN5U7~AJ_{yER*^Um}9uHWDLyFBll{9&*0ish@9 zLlCsW)C6zM+Ogn43bK9!!oo%&NT49hmKbR55`sPAf7sK@*8>}P^oR%6Bh@w+5E{1Exz-|08+PFvhMq#Wj7wy7?_ zV6CE=*4Ut;QJMS>e0*VEVtaXlm*s?welJbO_1@b^VVz)Fb?(6Q;JbpS7jjxG-^<@3 z{pft+q##Le#JzMy^ld&TG~-nYA+q5|frL{16-WFDRwA3of9evrB?*vjzO#s2zoAC-$j z+Q(7ba@XV=4JA2mDynIG)tT^H{0~FMIEj#tt>Q!3dJ~L`d6AX1lY$8`@kPf(tkyfl z{aswr+nExl(GzL?x+Qm8mM{7D=D^#pGoSl!udDPRGUN&e3OcrYdU?IKQJDU#?Z_W( znm_TaO4XK8OVTD8ppzz!>eyw(RezpTcfz0(k3P39Zob@LcVQygteJc;K0m)#d&p*| zWV4Z)D%6ibM{7`C7wr_Y`XG0@1A76X(=MqbJ+iKgFD*q~w8vfjF)?jQY=b-+msFG$ zgX(KT^+;U8s_^Si6{mw@`RqP4Ku8QJH{Z_B8Vh3_}{D@b9DOt6q$LwORPDod> z9O<|EOs5lTktL$>Nm`HEijs6hz0dTbZ9H?l=nkGYE(bsQ^foe1BkIa-vXb~7&2F{q zMmXo>zxk{cQw-)CBS^IE{K7!7(; z>pAnj7|l=00i72}XX+`}Z@5;`wsuLm;e;QQ3$6dGw$s04|L`xLyBdD7xK8`ydLafG zCsc=Fj;hy3+0!Et56Y23fp%FoBdE;yqFN`@0IKz=Rp;>)5Pl!Y(X}Ra#|k@g?(N&H z6K)CT717Vtradz&9dU)LtA%s=aA>I)QrE015LQlPwV;#XmxH2KI>(ibxU3NrU5TVq z7}9|jXrcXWdGAU0rk$L9ail$dyL~X!$9Q^3_DS3o(UJqF8B-=E+ueiTWj)e!v`nQX zP>&w;A#Q#qBQmX9C*T&DNWDb==W}}2<0fy#pepqQ+koP)01QX%LGTZr@EW-5c*vLj9O6SChS5Q^85t%f~@EL@w(5q`&*kT{4+v z-^;q}eY&pR+)k4^^yGF(taJ97yra|;W;e*niNUs8=voS0QTWsiKih#a`8nCW^XgoTyF=LbU{Jenz=-^-3=Y=$ly56PvnN)yj&duAA+tSFaVcS9^aF^&qslXfi5}XeRqk5fu9I)rP)N z2b8BP)Eh${w{N%9lZ%ts!r1H{SMMX-EA?J~40mlr<$zK4JByc}+owCqYbA$uf+nBo zIzA}5Pq(0k=Y8j$*1nt;y|(it;aTGJju66N<8X1@`=tEhUp7swoRmh^sp{_4iXe^$*)r-7+P+-%?|Tn3k57AegTO#MSwtOR#a{Mh;j% zLXZuLL?YP$1}f8V5X>1puE4OuqM8sm-L-2M#Lv$UO-)TP4O!NNty`h;@^XkkAV3s~ z5(IRBTvt~Y_-3*ia#7`2bOykfb$53|N=i!X;3p;~=InqE48v)6la4Rd6$J^+Mmz61_P#A6URCSO6UGSf5=sIM@L_J6NCxc#ByGZc6Z2 zv1-jx1w1eT037VF4p4ygX7f0POF4iy1JBI03%}{?+OyAa27n%Hvlu+C82~i|mkd1T zTUj^Y%!2!ey~BK<2lTns9(J;n9nJ>a{qyOi_*}dVJoob~zUkc0^Zg$Zt}WaTu!PsT z!*)FHAbNS0gh`x&z5rpi#WiS30KwGpsasB|7FKbz7Rl=zhSt`(BWG^Zfdj_ Jf62f(_D^RWFSq~z diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_f.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_f.png index 528102b2e13a91cfa58c970ab6466eccb04fe0b0..688ba46f01f4931d63727121ac479a93b58b8c59 100644 GIT binary patch delta 2599 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 JPDHLkV1jLo82JDI delta 562 zcmX>ka*AbwayaKiKT1xl_J6iVr`%dq(5!iAue`@?mZDkb%`{c& z1Nt}{ijFWn`&{{NUEcQFt{gm{yJh5F?|iz|f1d}#;p2}D>-DB{^R+vN+RgPdl;EkD z)js9HC(h459`D`oxxc7zpT~ipHG0lBE9Y5P_;P;TB(S4Ku6l1=WZCY!^G+@8h-Z|V zKBZo|%)mew_8xuHr0H&7IlF2VRyq zWoT4b$b<>Wtov+N-w;yo5YqDG?1Hmt!B>@a0w<~bTwaygZ0GOrVdc8hHNOR#ihLNR zBr`3L5oUNggF)jsi-V;a!zn{Xu*VQm6`U1Y-4Coivn*4pyu?)Prj?HAvwS;so-;rHLNvBBp{q*Xi43+*haXOLfe?f3nyEYri^+gQr= zKQi?A!?I`c2ksv{2lib~2-%aZ%Xw5mq(n^P*n$q`*lDTy?@uoGegD4U!sXcTo!=B$ kkbRFVdQ&MBb@0NNP=1poj5 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_m.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_m.png index 528102b2e13a91cfa58c970ab6466eccb04fe0b0..c4cede61551c8a4700098aaae229910682778b80 100644 GIT binary patch delta 2599 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 JPDHLkV1kP#9*F<| delta 562 zcmX>ka*AbwayaKiKT1xl_J6iVr`%dq(5!iAue`@?mZDkb%`{c& z1Nt}{ijFWn`&{{NUEcQFt{gm{yJh5F?|iz|f1d}#;p2}D>-DB{^R+vN+RgPdl;EkD z)js9HC(h459`D`oxxc7zpT~ipHG0lBE9Y5P_;P;TB(S4Ku6l1=WZCY!^G+@8h-Z|V zKBZo|%)mew_8xuHr0H&7IlF2VRyq zWoT4b$b<>Wtov+N-w;yo5YqDG?1Hmt!B>@a0w<~bTwaygZ0GOrVdc8hHNOR#ihLNR zBr`3L5oUNggF)jsi-V;a!zn{Xu*VQm6`U1Y-4Coivn*4pyu?)Prj?HAvwS;so-;rHLNvBBp{q*Xi43+*haXOLfe?f3nyEYri^+gQr= zKQi?A!?I`c2ksv{2lib~2-%aZ%Xw5mq(n^P*n$q`*lDTy?@uoGegD4U!sXcTo!=B$ kkbRFVdQ&MBb@0NNP=1poj5 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_arm.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_arm.png index fbf53f24e21aecb650dc660aab69fdf43a4fda64..382c95f69576d5fa14af20c46d62a7f5a76b4beb 100644 GIT binary patch delta 1691 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 wQrhs-423IesgXk2 zZgwHclI^;7BU2)~xpR7ceviBSZkeQi&i8rFe9t-a`F`H-@9TV@Gk<)(&s^0wrq0gF z%L)JhI}WR=N$=6%fncJ4rdglv1OTR3Pi;L{O%r#Nle43xwVegZ^{kTx%EH6i5&%5j zyp1#n=@sMf@A|oPcQFc`#eZ)T`7(KK+Sf?dC?arF$)!KDF}Q4<-eZAz&2R(nd9Qr$ z_bi@jJh#FPT?(e2^V(V|g;Ex>T_%Z2lOL|uZT9w#bf>PrBx({mTNe^P@AzTCs7P5R zu3>{ul?V4sx!;TxqVLvi_25XgOIM~5X*W?UlRn;Sv)eMon-dP?)i*2G$`PvO&$v+> z$wRGkL(~*iN8xcS0{_&oU9H6aVhb@=X1lLf7FQf+opESB_QGyKR9ETHyw(G&`^?ww z$NY4AY@xR>-aY>1weHp(@jkI#<&Fa+LRX?QhSoDJTBkK7LwzAl9@H9tn?JdGcIrBh zge8U~aJSP?o-jfQ*z>y7M86=^5#t+|?#y*;;EX#@@6B#ip`JbY)M_4)3w8MjAj9s zN3ZAO>>*t?9uO)DQs*l3fWb6Agq-^r;eWf6vjUE0Z@m1xUZv>n7U4tw*xHLnS(2lP zui`TW*ClWJ5VRHhL#4SM><*Kjv~casvXZSfIL#xXeMzZF(fZ;1E>-fj`!wyucuB%9 z()6=!#5GNEJ9#92dDUQ(0=G_%PH)n*wPz=>SKfHc$EQ!ZgTJYq8<+pF!PfC|&)(m$ zLL0VOyn1OFxu^SP)ZN-W6uWAvz=mt$nNMBAbck*Ik0cz*Np78a)%WtBC4MZL>GOoi z(r$BeXyzR6I&P*ranx5%0q4K<;yNDXfOM6jOC0{KI_Itz2kou7$J&EqMMklahuEbz zUa!8AJ>d7_fDuw&BG@i#`>{8YuN z5*8Yx9_4EDxT+nVsL?hyOU>B1cRb6At0wKY&h5qmcStEu$dxk>+T)TRCx?wC!J^0s zjvV%)k6$Npoh{t4PUDc?}^+E@At*H0KUmplpf+y2njR+Gn zU^-=O2etI(9sCJMjyXzie*JLc@s_A8YYLFPr5sp z$z2f<4KEOd^XGah3Xx;>KD;u&<@gNdrI_LdRqQYD*u=ayRk@F4GWFyG#o_%D=lwde zMJ&2`w!XJ;ys@O#O_E3 zJ}a@F*dJc)@KEmF%gNx{@$&EjG8Oi+rQaAerK{u8A+K^S6lL>kw1qiVaJ(zUR^Sk! z4i{S{YLngPM$lFa5Q&RQamp9sM~cL}+w9DihHp!nmRNXNVS4l0d7EM--y?{gL8fBg z;c$H%(!nYxNY|@!p*u_I?N|=4>0V-sZdR(5^?M4du)mcw2Nh*!C@^FVYsWu>7d+Rh zu-zBp+c2A0s#wA4FGEr6RcPJ@3(%IABCxT(_4Px`#VV%42_1>NCtO>b6qpSYHM9<5 zsP<)NTBf?G^HGKGt;7sQUHlDGx~`?_oH?bIH%`P09Y7Cq1n#%t8Mq<5<2I5kY35zj z%{Fs_h}$gk{A^-g#_2&`ACqz=@R*!&v!?ODJc(<4Zp~S4%49kHKZ82-CxEwa~ z0zx(U0kd1u_$`NDgEa$^B&IjiiAg4!sSX~Y|6DPd;?-4wG~g}}*)3<+M!&=2g#FnC z063n52P{mSgO7fb*%fzGjd@@V56h;V`jdLu0DuB;sw&#_*CQHTSV)h68bkmh01gi`81N7ZDNps(g$L1~r#@06nc*TNDEgES|5L_!6O|4}wu24A%+4$u~DQFR}A| zPC*ZgD}fOQ34Su20eVugJ1{%KR-VpDJl7Bf52+(5%?!!pf-4b zUO-RZrO_+50531^s%wLqp!WA@i{h;}R=Qrsgg)&TSXx3~H6Q=5H{cTt`cwJl zAV7`3P8z&kT1sCAM1Y~1zO1Y)ZDL~LZ#pe4Ex^LU0z*0fmhAuBfWzUmUAuMxK&(uC jC_M%b{x85^Vj115K$N>w4W`4X9aFuBIqCBU3a%3y diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_hand.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_hand.png index c7a9172924c2aa6cd22e6eb6a012ce266034e646..31b5acced704f2d46bcec42a937c203bc279dbaa 100644 GIT binary patch delta 1538 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 literal 18302 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 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_foot.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_foot.png index 69a6ebc6849d27555cdc5c56307048414c685e26..e4bee30c0040e579fd33f599df35c37e141c47c3 100644 GIT binary patch delta 2339 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 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_hand.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_hand.png index 92342236d21598b63d04bd1615fda80c9474da72..2dc5061a1989b0b9bf428065db6b44e9a6796bf1 100644 GIT binary patch delta 1549 zcmV+o2J-ok1F;N{BYyaB^>EX>4U6ba`-PAZ2)IW&i+q+U-|cvg9TV z{bvyMKVQs%XgvLDsK<_IaRO z8ps|5U5a>FL}>UWs9b`W&VhIdsOPqhTueW1p^dZl+fM9!!YbOWSFXtq?@8f37wBQ4 z!I2M?%yb&S>*2r^4Ms^Un0T;CYFR-$VP zKR7wx>zDl@%71HAw(CE}k6kVL+&{~qr$rCmU(cLwbMG0us42tM`P$TNE4zhx4Jwvu z3otE1W(Gordff%LA*wq=9EbLRiF-w}0>O?t(ejQHb%dyRTpu(Q-D- zSjeps(||~vms4ds_;x>D3s(k$vb?;GNP%P9DWXaIhY5HC&6p^t&oda+F9C27R11uW z3hmn++Gq5pQsVyFsB5|Jz_CPixIoU-JcH7`=E%9?_TW>qyUT8%B4ST;4YVzp3VkfxMe zv{)&nR_LsdT(P=hLamJ&x6~xG+_YIMt#*V@PhEQM+O3yfotz!~;n~&Ai`NkcLTRKS zBM%)m%BT~eHaW~RW#*~VW|{Sl+6C*={RV3BLVt}mQfs2#QA4llO+;LDA`3GBMj=HY zt_uPLG%d^yiz(4UZeey5&>uJtM#{p><3bDwrV&YIykQsUM06qdQ@909pKzleMJ_Dp z-bC&hw^yk7N<)1kcAmoJ)Pv{Z!a1yx)s^g?>hRUTyY+8Dzm%Zn2`SKn&fYV!p_`&e zHGdazi$e-N<$Q=D!Vp7wQ3Yz1HgzEATC|?on~yexCoF2!)LWa4utpkZEk3)HK5%dl z@StI*acJotlSE|h*XD&E+RwyUa_%C_%ES7Y6M|-<*%HnMBO8%x&hBkm?9<0|YL#bP zjMr=}b4;C%1K$cZaMYoFxgp}KHd%jC+J96#mq9#7Kb9JZsI*R-4xbZL&@>P4v&AVe zuTrptsp`@yTv*z0A6aLm+`ZUdvfRbPhs)%l)?3f#mWqN8+Vq1*FJYpWp;(%h(xAsT zN-1+}3T;EORdnWM5)8&yo@}o_)FFK_@O2$$0^WyqT{;WU1`E#6Q-fvO3O!>5#(%-d z2nkgL1rX5OB4Zi&Y{F}e_bigN0c>Nvkq2ZYhvb}FPvEUOZhNTdt-uKX(NX&?=(nI> zQ_$k19yfi^Tt^DWbDhszJ3f-?XkoqL4+TVGn?Uf_0ZsuqHE@$iZ`Cc~%f#2oe@TL8 z9ll60u?>8o;V%gJV|d2F#xn<~GJk@ppc70t6NtFs?;OOJf@lMQdek%Rj8$67?Mf+L zLEnu_pG7uHj#yr1lJI@*Ts}c*v-On&kFBokG%;i)1`QZc@NTL9N?qS(uJ5$yMOyig zRFDU9c*-kRTEVa5&J@T1p0;I!5ULc68nF<%00006VoOIv0IC3|0GQ!7Y}=6`7k>Z;bV*G`2j>GB3btsB)%>;5t3Y|5gY9n>3}OybU`>*TTdyUyNNtyfD)(q^|! z=3)R2$9=e@l|_|I`TN(PEUKhp1^@s600000008h~V*VKz_YS#cK6he_KLh@AeJI(S zAUZoltwQtYU9<|g-7gDC&TD^-zc&B?0PvY7M2ca#$XAE500000NkvXXu0mjf?P=j? literal 400 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|TRz zr;B4q#hkaZ47r*e1YGMCTDK;o=O!vvFy|+{lw_6mPfCBNxaO^on@CV$(a1U*L9i0&zeyxE?!W8E56Z#p|-4$1HCsl$o9pRx9?$Gu#|* zg002r9+<=%u@5(mHx%96ICJmsH*&4cq6xOlk<%7tO2v4}9AExjQ$`3VkSOseYmtUk z?b*9b+vYWvR=iyK@!sTkdA`sCzE!PzF6be7*;)SqYkW|s@e$^t$G{+F@O1TaS?83{ F1OT?ImwNyJ diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_leg.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_leg.png index 72c485225c7027b7e5b2e01de7533694ddd69a6f..120cf6b2c260d92efaa9211ef82e032892552068 100644 GIT binary patch delta 2343 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 JU6Qsv{x9$$9{m6S diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_f.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_f.png index bcfa51232b7dca86a39fd03abbbb363c10b56741..ff0e9f2b018dc8d8d896c60667c5d160c8266ae5 100644 GIT binary patch delta 3403 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_1.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_1.png new file mode 100644 index 0000000000000000000000000000000000000000..12195d5d0209f54c8c785329a6de4b311cf71768 GIT binary patch literal 1154 zcmV-|1bzF7P)Ga(r!Ql`clLc z9}I{hadC?X;t~{mQ1n4s)aFI1yRPw4B#{tO5fl}IO1#7-23s`oLR2(@CL8QSA{d(E zd~?nm&z?Q!WLMS?hBGre^Z(y`^UpuC-y#i^mzQgPzu$Ar@bEDD`}?y}wdqM95C~{i z!`WFA$jzDRX>cSykwmn!v(uH3D*-xR`%{gqcUn@ z?`AWJfYZRo&t9RdWFD3-t29^IDjc?|0lA-@t1)Vh)vlB6Bmzt#JjYIKOG_8ymu=f+ zy|*V(aynLHoZyzA9Jhc;#JbwX-+#mLKaS#j^J(1cc_@w9GvcKyH)NlR9W_Uh^ZVNz ziMb{swOX!}h4o1E6e=nz-~|#?^BAaf?xu<-fhSKMnJXZuM*RH;oQy?036z#CPMW8- zEiD3Sj~Pr#ZhoH+Oz|YZF)G;jWgyz)B_#q@R99D<^#{G(m@{ty24B6vf}**y@5Rg4 zW}kJ7+S}VFwe3nkMfIJoo+R1F#>U{w@!{6p`?9^LM0Y+a`t4(@HmsAj&Ynvn2$`>U zhIea}Z%IX|Tp{ssd>jjl7oo1M4(mlB<`fp9?B;FMw6vf_l;;CaF?EW*O;m_6K<8=Q zhIVjeRx~v=L3l$r9LC_AH#jfq?DP427#Ad2QbkGx^7Hi|92?b%th;&@>qY5+uE3yB z<3CZqTw9AAL4w)}+P%jh6UU=}yFK3*j&DLvm{l;-G^m^&IebXo z5pJoK2`9Lv9s)gy?66-@c6ePp;T<94dJiN#OicpH z`Nqv5{CPTp!(z4em8$l$ftQX>N{Wl*m|S1BY^%2cNh#v`E9o-{lK^G^CVN8GNrHy# z4^8zDz46^`L@qJaN+A9d4$W+1(+9dYv-6MRBnEfUJ{kc@Galrlq2jKpa??w`yW(hH1B|$muQY!^c{N0G?QhtHxG3JIw zSqI#=h%se%o41gQv0OXF@apg>1fC|fB%O5Ofmi({nON!dYX>HIza1kTpF07*qoM6N<$g5^aao&W#< literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_2.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_2.png new file mode 100644 index 0000000000000000000000000000000000000000..dcd48a5a0002ceddb9ba8ae23cfc243864c6e537 GIT binary patch literal 1093 zcmV-L1iJf)P)`+kGrvb zu-tQwb7sDoGiT1Y69Pb1R+eNon+;`FR#sqQVj{#}orVM~7K@}*92&9#krCmB3Rm45 zDx&@U{knv7383+l$BX&+^_zZXH~~(dIst=&Lxu!UrsvrUJ}y3Dp=C*rgeCzpJ~27X z=Lzv~5C}+~_HR0(NkT;cjk6HK?mc@USU_E$QuU;=ekR#vLkH3_&} zE-1*)HB?wwSl~0?E;mr87BmT9#&3uHozLM|Oe`P2T3&*|)ObUAJ)J57T7r`^3y_(X z1bO)dvZvk5U^fXwZW$*T+N0E~rCUV+iwNFhEw&jMIdHM!G9QnQ_=X$}lZ+Ph3Y6v% zU=dMz+j#d5+;47zC!OsuH1d@z6Dwlx%RatFxkG!1oZ0+TlbCKHB5%=C{NdQ)dgnm(R<|wz%Ibl^ z5mned9uJrzOz`&oM?Oza^BP}c>!NJo*)v?%qmBTQ5bO0ddzFOY%gxT<9wL6Pufu`V zbSNn);d8s)&cBx`uJCVHR~I{?X$TMV9ur0ga{!G8^cspl&y;9uYlG6#Qq`KtWP)`@ z5`X@}F9IN6h_N%td=iTDdn92mm__+%>y-FanS)M?wVZMBJ#UX0}%4b(w&-UCNSB;AZVDFoIOe46=t%V#Y%bI>6~< zB!*e*-DJ3p8~?Gi>eHI}a00000 LNkvXXu0mjfKCkR* literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_active_unlit.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_active_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..03e6242ef99cd8048f1c33add3a48553a2b16ee4 GIT binary patch literal 1302 zcmV+x1?l>UP)QnNm`|) zMWgHecAa&1Z}!h@ZYR*p7sAfY&HO&U{bg?NH^c93U{E5FkerMg8X8 >@#6WdMx8 zE0=$UVlfZ5Ms8BaZ*Gsn#*MA8d(Q{Dd2R#3gKruDgr7KmR0p$yqsV8Ue*BTnsc(7@ zN~}TP#is^<1}Dnp%pD*=qf=;$B?vtEWdT5VBoa~Kc0i+Wo_5aGt#P>zZI)yk1m1k= z3P`0=aOc(yW;jh~1D!ydeSLk7=J4cG1CYsNAl|+SDk-$dGL{#g8i1LZ8K|^aZ1Uun z1;7h9vFpS(Z+=+-#>U2$m0lQ*5)M`e(6-$;-hAp;puWDo(tIYHJo!wi@c&Vc0&w@< zeP{`<*Y({SpVZxlLjl`4ZsjH4^$OV4zY~(}JLGnD$`IMcK#Q5 znwxWF$58+BmvYldrKx%7_G9;tOS$E|3#q7a5nD_iCEGx!^FaMN}UO{M|B$z++4 zD`r&M&&>ch-nc|r#fvXqg0xO$!;p|#!U355>tBe)VsgLszhb4X?)T;E=;$c;YFElH zB$n+kPrmI6z~9g6>T0m>GbEhRWviUhz!>fDy)2^1bbyDzx+_g=jQtX|PZz zz=4Bl)tUUS!>+cty!g~JL7cF*u}(Eep#8_bw>_3l?fV=ugXh$_D8*Jp!WWg3GeMqw zT>ub{QO7j${Dq5U0EC}CbIR0t{GI;d%de=P^?u#+I&({y9*iyqUkw0(fAU!m{P@EF z94kfJ7-@2EmW<$z49C>0s*>-?xgI)299MQ|vn_Vw|@ut519FC0F>jR zh=c>a{q6`@>H5j6?j9c=`#QQ3mh;f|qv<*7(G&|mf8~zu9v>e2-0*ep0Id_aoQzA2 z{0H`@dzFr1<+8123v5eoQ6o=VqWGOQdwAFU*NV1mV2i$?b{Bae(K*RZac?1cO0^ zKQZCjj_dk>ow1~vcG8Zoysi)E?1)!{FX{teiA&T6*clV`0UC+=08t+x>H|c5fT#}; z^#P(jK-34!uPE)t0{Y$HACnK&abDL4NF}%Ze!p%vI5jopitnmEV7hQ$caIN`eUYXB zSgBI=0S^q@UwnA%+Ys_I^A}bhK!h3Shi@X!yFP$O)CaiWFZud_R}N8@#}RC!od5s; M07*qoM6N<$g1gyxDF6Tf literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_base.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_base.png new file mode 100644 index 0000000000000000000000000000000000000000..156579d6bb81c0cfdf01f14b57e691f34aa83509 GIT binary patch literal 870 zcmV-s1DX7ZP)r|nas}j-kaIU_f58v2S}16yO~!k7Q5VXIvOwwzIyqB>h%hh7v2iz?;cIi;NUPF zI()ZrWIGc=10r#b`FVQ-T+nO^Ty`cb1|S}d zMm6zvf@UC2A2T+VU}NA^U@;-wfmA9*@5^sIi;Dmbm;h%so3%U_8p!AKlo%bMP6C`F z2n{qE4eB)PI4uS?L!9%9xGe^1wOW^QU|b~}uLi)~)&LL+g*vTo%jqc$V-pk%23fz^Y*OXJyAAQUGJxD}PD_B=d$9mxR>-YOvKinT<9}sg>9QrXnAF=Y!?~eSQUV)yN_eDm%z>|SOp}<;E zUe}K$lgZ8*SZjTu=g%svzp|nV1cH6S!ct#U=dHGuS=$#1P)|?yzZu|w_+%=rB_BH= zDb40*sJGW$J+U=_6(W`H*}Gp8RZcR+VlhX;YPCw2rgEAYWJsqHFT4{XU}s-IBjlpD zrf;^rmZv69Q-1b=77M6cQ5gr-@lFVFtQu+b@sp<(0f^tfch`0`$P;JIo)bRHoKOGB zoRZ;Usu|$oCr+j5(Zd;*Mw#O+rGuO&iXK6 zzFq^o77Qr=e(+lK)ezgwla8oHfD^cKIj3l~v~kUVdR>ajm~i#lb#lV%xjEMIvjK68 z?HiXI)qDpo<}!wHY&AZ7<)T-FGi4UH7|@&eweB-)6~K#8 wyMhEEJvf)^OQ~ogp!|$vvnewmW*0BQZ$f*is`9olfB*mh07*qoM6N<$f>t4kcK`qY literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_on_unlit.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_on_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..b2b98688d94dd891327abbadfb9098db30d910fd GIT binary patch literal 885 zcmV-*1B(2KP)RCt`dR!wLVK^XlSe?Uu%%Q5{c6WAm zvs+UiEW0~1-+OOnXTNXOk_RM{NyW{$Y&P5AmebLIC^+`wITed}ntb<0I=-W`i&|UT zY5#$PrZ^`r38_;|!BzkfRNd-?=MV*V^M>II$*jE|4A zyDYC8+j@F>>Sy44f=B;_V{J z`})tOtC=%tI+*GPxcIRXX?plzgof4GiZkW!cF7185o4M*`q(=^SHcuGu2slo6S@H` z`x@U8dxi<|cn$Dc&_U~{ml{mf@Fgkq!>|$}zzJNwG^A=(^mg5Vc3g@n7;xq4HFCn( z$62Cn5%t&5em97tZC7NAV;s2W7b>QsnQ0FgO<+02rRFPeeyE?_=c?`P)r-$u_KC2k zL~)A&qlrIDKGRYWEf=F&1qnh%a4y$}QrSR2{f!jSln98~#mn#)$&{%22x9?c00000 LNkvXXu0mjfc$bj? literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_open_base.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_open_base.png new file mode 100644 index 0000000000000000000000000000000000000000..894e6d2d0d924e3425c9c59aeaf5c4672c387627 GIT binary patch literal 1001 zcmV9jD#BvL0rxgcxn``vlIzCZW-w#A|! zjNR|<+;e{Cch7h4*;+~gZnrz;a=C1678VvL6bfY|>(iEi*XxaG9Xm3jl#`uh>u@m~ zH4zO4gO-FW2_X2P1NCD3@>Ng?TttT(4${EDpe+H|1fD$?sY3`=ESw|)bCo?BAK zz;YyFvaLOOMEH8xok9`fygt|58iRaQo^p{P@MC3#vNAJ8rhry~*_m&Y?R2U({5xs@ z!Be^ojX-9M6(s-)4g0HA0DC_%KC0Rzi=+tT=f{gMvK%L3rvTv0cBYrW{Jj1MO{4%T zR^ZA_4}t%#0E072q`*HRfNf~>HK|vy91Y@X#;eGx{WSqT#dhu9rv_DCrG$6E*w`3d zXl)Z?kioTW*I!6`LM$jO$WQX7#T{XFwBo?=HJ&7Y=Y4f85cd^t)opu11V`4# zmD8)c=ZPtR@q#kK?&4`a+q8PUdv%SeN`QkOJJCdsx;m&`$<~-DKYy5u$k=FdBf3Mm-?1&)o)B`!elDv@7y+NarHgG! ztVMNRB@l0y+%XtjzH*i9(AV25zPUCK9CLg2d+nBq;9uqzb*-7M2DBs~r%`HF;Cx%N zZXQzO!Y2@k&1Mh_$QNSIuS~Pq`ls`+j+h}_uXx= z=m%r>-JN^R@BHq0_nxhW6yS2XB)i=%w3(ZmgHR}xk*rT40guNcsU2G~qL7`HDRej= zi5iFo0s&J(rUWqffqivs{Q6Bm4qOBW>-R%2*e4`_HvY#?*|=_(ho&Vn5?lflJT&r& zJr@-gKq?@6S|3k@OTs_^gUb@a`VAW)T|i&xlShK9fYvWdGiIb<;cyK@~IR+*h9?T9X?iS!7 zqR#fl^(%1u)=hZW-3fgIADJ`#iTM2GTQ*0vLu-hf-TsJ6%=93lY%x>(;JE$HJ#f3- zAOaGkby%nv+)NcAfzi<+B?APi5n1>N9lmxU0cTmcVI6H-N(5++v6x71{GJ%M3JIVM z6&rqIA?oWTDFSNL*48THcZ2<~skjtorYE7aWHXzaocf~7skg}Q_b2piN`R`mH#oqR zea+f+@HM=kj1h}VO9tDT!-tr!`&}s%A)eP~npz~3ufpwQ86tiyFGHr)$}&Z$6_}a+ z0a-SiVne@U4Pfw;ZbLmVGs3bQ01FNGSFHf<{piS$Vv{VAB9NCCE5fD47!i>I2wRpd zy#!`wwMS?o1xT@cdro=?{C5QilvyGL{s{rxh6ZmVq3#zL`=ljn+_iQV~0GrLGSgls6&En!B1OkDCXnjfvI2;Z|>o_rC9nw;gr4E;Z z>jt9z{r#qdObKA{V@GQE`t_TB7C0A<*B%AGe^5#QZG6vO@O8~W2i;c8NC*i~@WA+I zew~|>4Y7diY5ztdLJ|f77@SE6J9h4ZcmaK(PZ0^B0#2tBK8y@NJb^wN8X64ug#^4_ zFH}~PNgY;IRfb(hstxohf{*}Kd?f7ceh!B-v-tYe!aVp3bENiWJ`Ds!hU1g7P*Ri! zZM_n-#A@=Lb^^FS3S7tBf86tkItwC~963-N&RbX!R z2c%dmstx^)HGsimdK>D2nGx1l04y{-U#$Xo_7mfys!g803#4srJ_dsEh4C za7Ycx9;Jxyg0ZnNxYF3f*GOjcP)cY!d(70q%(BN9jb&x@6VF6hSP+0JUeQxl0 z7>OY^dbdlr@!;R*m%>J~uo}>kKsohNlLGhOwSlJ`zX3dVu{X5wHJgX{@1i5Zn$ib1 z5YUqNy`C5*6#}J2=VmoPz(87%uc(Jov%lBuF;euT^uS=T{5}5zN%jmyycDJV00000 LNkvXXu0mjf)cxRF literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/meta.json b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/meta.json new file mode 100644 index 0000000000..0afbd97a30 --- /dev/null +++ b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/meta.json @@ -0,0 +1,43 @@ +{ + "version": 1, + "license": "CC-BY-NC-SA 3.0", + "copyright": "Taken from Yogstation at commit https://github.com/yogstation13/Yogstation/commit/159e6bf846e911590ab27f15272ec2ebc465c1da", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "borgcharger_active_unlit", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "borgcharger_open_on_unlit" + }, + { + "name": "borgcharger_closed_on_unlit" + }, + { + "name": "borgcharger_panel" + }, + { + "name": "borgcharger_1" + }, + { + "name": "borgcharger_2" + }, + { + "name": "borgcharger_open_base" + }, + { + "name": "borgcharger_closed_base" + } + ] +} \ No newline at end of file From 81ca98f186e15d032c79b06bc2c3483d8851c075 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Tue, 28 Mar 2023 03:21:14 -0400 Subject: [PATCH 15/60] Added silicon chargers in the form of a charging pad and industrial charger. Chargers heat up mobs, or even contained air as they push power through to them. IPCs as a race yet further to finishing. Added antenna and screen markings for them. --- .../Silicon/Charge/SiliconChargerComponent.cs | 36 + .../Silicon/Charge/SiliconChargerSystem.cs | 142 ++ .../Entities/Mobs/Customization/antenna.yml | 89 ++ .../Entities/Mobs/Customization/screens.yml | 350 +++++ .../Entities/Mobs/Player/silicon_base.yml | 4 +- .../Structures/Machines/silicon_chargers.yml | 132 ++ .../SimpleStation14/Species/ipc.yml | 22 +- .../ipc_antenna.rsi/ipc_antenna_antlers.png | Bin 0 -> 323 bytes .../ipc_antenna.rsi/ipc_antenna_crowned.png | Bin 0 -> 324 bytes .../ipc_antenna.rsi/ipc_antenna_cyberhead.png | Bin 0 -> 422 bytes .../ipc_antenna.rsi/ipc_antenna_droneeyes.png | Bin 0 -> 422 bytes .../ipc_antenna.rsi/ipc_antenna_light.png | Bin 0 -> 323 bytes .../ipc_antenna.rsi/ipc_antenna_lightb.png | Bin 0 -> 733 bytes .../ipc_antenna_sidelights.png | Bin 0 -> 420 bytes .../ipc_antenna.rsi/ipc_antenna_tesla.png | Bin 0 -> 1174 bytes .../ipc_antenna.rsi/ipc_antenna_towers.png | Bin 0 -> 353 bytes .../ipc_antenna.rsi/ipc_antenna_tv.png | Bin 0 -> 325 bytes .../Customization/ipc_antenna.rsi/meta.json | 107 ++ .../ipc_screens.rsi/ipc_screen_blank.png | Bin 0 -> 226 bytes .../ipc_screens.rsi/ipc_screen_blue.png | Bin 0 -> 1128 bytes .../ipc_screens.rsi/ipc_screen_breakout.png | Bin 0 -> 960 bytes .../ipc_screens.rsi/ipc_screen_bsod.png | Bin 0 -> 1136 bytes .../ipc_screens.rsi/ipc_screen_console.png | Bin 0 -> 467 bytes .../ipc_screens.rsi/ipc_screen_ecgwave.png | Bin 0 -> 1660 bytes .../ipc_screens.rsi/ipc_screen_eight.png | Bin 0 -> 495 bytes .../ipc_screens.rsi/ipc_screen_exclaim.png | Bin 0 -> 382 bytes .../ipc_screens.rsi/ipc_screen_eyes.png | Bin 0 -> 445 bytes .../ipc_screens.rsi/ipc_screen_eyesangry.png | Bin 0 -> 456 bytes .../ipc_screens.rsi/ipc_screen_eyestall.png | Bin 0 -> 441 bytes .../ipc_screens.rsi/ipc_screen_frown.png | Bin 0 -> 256 bytes .../ipc_screens.rsi/ipc_screen_glider.png | Bin 0 -> 563 bytes .../ipc_screens.rsi/ipc_screen_goggles.png | Bin 0 -> 529 bytes .../ipc_screens.rsi/ipc_screen_heart.png | Bin 0 -> 415 bytes .../ipc_screens.rsi/ipc_screen_l.png | Bin 0 -> 239 bytes .../ipc_screens.rsi/ipc_screen_loading.png | Bin 0 -> 784 bytes .../ipc_screens.rsi/ipc_screen_monoeye.png | Bin 0 -> 515 bytes .../ipc_screens.rsi/ipc_screen_nature.png | Bin 0 -> 1130 bytes .../ipc_screens.rsi/ipc_screen_orange.png | Bin 0 -> 875 bytes .../ipc_screens.rsi/ipc_screen_pink.png | Bin 0 -> 595 bytes .../ipc_screens.rsi/ipc_screen_question.png | Bin 0 -> 429 bytes .../ipc_screen_rainbowdiag.png | Bin 0 -> 1286 bytes .../ipc_screen_rainbowhoriz.png | Bin 0 -> 867 bytes .../ipc_screens.rsi/ipc_screen_redtext.png | Bin 0 -> 862 bytes .../ipc_screens.rsi/ipc_screen_rgb.png | Bin 0 -> 559 bytes .../ipc_screens.rsi/ipc_screen_ring.png | Bin 0 -> 263 bytes .../ipc_screens.rsi/ipc_screen_scroll.png | Bin 0 -> 802 bytes .../ipc_screens.rsi/ipc_screen_shower.png | Bin 0 -> 1232 bytes .../ipc_screens.rsi/ipc_screen_sinewave.png | Bin 0 -> 1289 bytes .../ipc_screens.rsi/ipc_screen_smile.png | Bin 0 -> 258 bytes .../ipc_screens.rsi/ipc_screen_squarewave.png | Bin 0 -> 1096 bytes .../ipc_screens.rsi/ipc_screen_stars.png | Bin 0 -> 1252 bytes .../ipc_screens.rsi/ipc_screen_static.png | Bin 0 -> 695 bytes .../ipc_screens.rsi/ipc_screen_tetris.png | Bin 0 -> 2131 bytes .../ipc_screens.rsi/ipc_screen_textdrop.png | Bin 0 -> 1672 bytes .../ipc_screens.rsi/ipc_screen_tv.png | Bin 0 -> 828 bytes .../ipc_screens.rsi/ipc_screen_windowsxp.png | Bin 0 -> 988 bytes .../ipc_screens.rsi/ipc_screen_yellow.png | Bin 0 -> 495 bytes .../Customization/ipc_screens.rsi/meta.json | 1363 +++++++++++++++++ .../Machines/borgcharger.rsi/base.png | Bin 0 -> 3241 bytes .../borgcharger.rsi/borgcharger_1.png | Bin 1154 -> 3878 bytes .../borgcharger.rsi/borgcharger_2.png | Bin 1093 -> 3599 bytes .../borgcharger_active_unlit.png | Bin 1302 -> 9960 bytes .../borgcharger_closed_base.png | Bin 870 -> 0 bytes .../borgcharger_closed_on_unlit.png | Bin 885 -> 0 bytes .../borgcharger_closed_unlit.png | Bin 0 -> 3076 bytes .../borgcharger.rsi/borgcharger_open_base.png | Bin 1001 -> 0 bytes .../borgcharger_open_on_unlit.png | Bin 1023 -> 0 bytes .../borgcharger_open_unlit.png | Bin 0 -> 3387 bytes .../borgcharger.rsi/borgcharger_panel.png | Bin 1041 -> 3492 bytes .../Machines/borgcharger.rsi/closed.png | Bin 0 -> 2890 bytes .../Machines/borgcharger.rsi/icon.png | Bin 0 -> 2922 bytes .../Machines/borgcharger.rsi/meta.json | 34 +- .../Machines/borgcharger.rsi/open.png | Bin 0 -> 3280 bytes 73 files changed, 2245 insertions(+), 34 deletions(-) create mode 100644 Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerComponent.cs create mode 100644 Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/antenna.yml create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/screens.yml create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_antlers.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_crowned.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_cyberhead.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_droneeyes.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_light.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_lightb.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_sidelights.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_tesla.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_towers.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_tv.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/meta.json create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_blank.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_blue.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_breakout.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_bsod.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_console.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_ecgwave.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eight.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_exclaim.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eyes.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eyesangry.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eyestall.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_frown.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_glider.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_goggles.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_heart.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_l.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_loading.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_monoeye.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_nature.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_orange.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_pink.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_question.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rainbowdiag.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rainbowhoriz.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_redtext.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rgb.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_ring.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_scroll.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_shower.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_sinewave.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_smile.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_squarewave.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_stars.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_static.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_tetris.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_textdrop.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_tv.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_windowsxp.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_yellow.png create mode 100644 Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/meta.json create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/base.png delete mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_base.png delete mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_on_unlit.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_unlit.png delete mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_open_base.png delete mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_open_on_unlit.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_open_unlit.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/closed.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/icon.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/open.png diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerComponent.cs new file mode 100644 index 0000000000..d2742da9ec --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerComponent.cs @@ -0,0 +1,36 @@ +using Content.Shared.StepTrigger.Components; + +namespace Content.Server.SimpleStation14.Silicon; + +[RegisterComponent] +public sealed class SiliconChargerComponent : Component +{ + /// + /// The multiplier for the charge rate. + /// For reference, an IPC drains at 50. + /// + [DataField("chargeMulti"), ViewVariables(VVAccess.ReadWrite)] + public float ChargeMulti = 150f; + + /// + /// The temperature the charger will stop heating up at. + /// + [DataField("targetTemp"), ViewVariables(VVAccess.ReadWrite)] + public float TargetTemp = 365f; + + /// + /// The number of entities that can be stood on a charger at once. + [DataField("maxEntities"), ViewVariables(VVAccess.ReadWrite)] + public int MaxEntities = 1; + + + /// + /// The list of entities currently stood on a charger. + /// Used specifically for chargers with the . + /// + [ViewVariables(VVAccess.ReadOnly)] + public List PresentEntities = new List(); + + [ViewVariables(VVAccess.ReadWrite)] + public float warningAccumulator = 0f; +} diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs new file mode 100644 index 0000000000..0f3676566e --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs @@ -0,0 +1,142 @@ +using Content.Server.Power.Components; +using Content.Server.Storage.Components; +using Content.Shared.PowerCell.Components; +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Damage; +using Robust.Shared.Prototypes; +using Content.Shared.Damage.Prototypes; +using Content.Server.Popups; +using Robust.Shared.Player; +using Content.Shared.Popups; +using Content.Shared.StepTrigger.Components; +using Robust.Shared.Physics.Events; +using Robust.Shared.Timing; + +namespace Content.Server.SimpleStation14.Silicon.Charge; + +public sealed class SiliconchargerCompSystem : EntitySystem +{ + [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStartCollide); + SubscribeLocalEvent(OnEndCollide); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var (chargerComp, entStorage) in EntityManager.EntityQuery()) + { + foreach (var entity in entStorage.Contents.ContainedEntities) + { + var chargeRate = chargerComp.ChargeMulti * frameTime * 10; + + HandleChargingEntity(entity, chargeRate, chargerComp, frameTime); + + // Heat up the air in the charger. + if (entStorage.Airtight) + { + var curTemp = entStorage.Air.Temperature; + + entStorage.Air.Temperature += curTemp < chargerComp.TargetTemp ? frameTime * chargerComp.ChargeMulti / 100 : 0; + } + } + } + + // Check for any chargers with the StepTriggerComponent. + foreach (var (chargerComp, stepComp) in EntityManager.EntityQuery()) + { + if (chargerComp.PresentEntities.Count == 0) + continue; + + var chargeRate = frameTime * chargerComp.ChargeMulti / chargerComp.PresentEntities.Count ; + + foreach (var entity in chargerComp.PresentEntities) + { + HandleChargingEntity(entity, chargeRate, chargerComp, frameTime); + } + } + } + + private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconChargerComponent chargerComp, float frameTime, bool burn = true) + { + // If the given entity has a battery, charge it. + if (EntityManager.TryGetComponent(entity, out BatteryComponent? batteryComp)) + { + if (batteryComp.CurrentCharge + chargeRate < batteryComp.MaxCharge) + batteryComp.CurrentCharge += chargeRate; + else + batteryComp.CurrentCharge = batteryComp.MaxCharge; + } + // If the given entity contains a battery, charge it. + else if (EntityManager.TryGetComponent(entity, out PowerCellSlotComponent? cellSlotComp) && + _itemSlotsSystem.TryGetSlot(entity, cellSlotComp.CellSlotId, out var slot) && + EntityManager.TryGetComponent(slot.Item, out var cellComp)) + { + if (cellComp.CurrentCharge + chargeRate < cellComp.MaxCharge) + cellComp.CurrentCharge += chargeRate; + else + cellComp.CurrentCharge = cellComp.MaxCharge; + } + // If the given entity DOESN'T have a battery, burn the fucker. + else if (burn && + EntityManager.TryGetComponent(entity, out var damageComp) && + damageComp.DamageContainerID == "Organic") + { + var damage = new DamageSpecifier(_prototypeManager.Index("Shock"), frameTime * chargerComp.ChargeMulti / 100); + var damageDealt = _damageableSystem.TryChangeDamage(entity, damage, false, true, damageComp, chargerComp.Owner); + chargerComp.warningAccumulator -= frameTime; + if (damageDealt != null && chargerComp.warningAccumulator <= 0 && damageDealt.Total > 0) + { + var popupBurn = Loc.GetString("system-silicon-charger-burn", ("charger", chargerComp.Owner), ("entity", entity)); + _popup.PopupEntity(popupBurn, entity, PopupType.MediumCaution); + chargerComp.warningAccumulator += 5f; + } + } + } + + // When an entity starts colliding with the charger, add it to the list of entities present on the charger if it has the StepTriggerComponent. + private void OnStartCollide(EntityUid uid, SiliconChargerComponent component, ref StartCollideEvent args) + { + if (!EntityManager.HasComponent(uid)) + return; + + var target = args.OtherFixture.Body.Owner; + + if (!component.PresentEntities.Contains(target)) + { + if (component.PresentEntities.Count >= component.MaxEntities) + { + _popup.PopupEntity(Loc.GetString("system-silicon-charger-list-too-big"), target, target); + return; + } + + _popup.PopupEntity(Loc.GetString("system-silicon-charger-add-to-list"), target, target); + + component.PresentEntities.Add(target); + } + } + + // When an entity stops colliding with the charger, remove it from the list of entities present on the charger. + private void OnEndCollide(EntityUid uid, SiliconChargerComponent component, ref EndCollideEvent args) + { + if (!EntityManager.HasComponent(uid)) + return; + + var target = args.OtherFixture.Body.Owner; + + if (component.PresentEntities.Contains(target)) + { + component.PresentEntities.Remove(target); + } + } +} diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/antenna.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/antenna.yml new file mode 100644 index 0000000000..54ab04c1e4 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/antenna.yml @@ -0,0 +1,89 @@ +- type: marking + speciesRestriction: [IPC] + id: RobotAntennaTv + bodyPart: Hair + markingCategory: Hair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi + state: ipc_antenna_tv + +- type: marking + speciesRestriction: [IPC] + id: RobotAntennaTesla + bodyPart: Hair + markingCategory: Hair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi + state: ipc_antenna_tesla + +- type: marking + speciesRestriction: [IPC] + id: RobotAntennaLightb + bodyPart: Hair + markingCategory: Hair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi + state: ipc_antenna_lightb + +- type: marking + speciesRestriction: [IPC] + id: RobotAntennaLight + bodyPart: Hair + markingCategory: Hair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi + state: ipc_antenna_light + +- type: marking + speciesRestriction: [IPC] + id: RobotAntennaCyberhead + bodyPart: Hair + markingCategory: Hair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi + state: ipc_antenna_cyberhead + +- type: marking + speciesRestriction: [IPC] + id: RobotAntennaSidelights + bodyPart: Hair + markingCategory: Hair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi + state: ipc_antenna_sidelights + +- type: marking + speciesRestriction: [IPC] + id: RobotAntennaAntlers + bodyPart: Hair + markingCategory: Hair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi + state: ipc_antenna_antlers + +- type: marking + speciesRestriction: [IPC] + id: RobotAntennaDroneeyes + bodyPart: Hair + markingCategory: Hair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi + state: ipc_antenna_droneeyes + +- type: marking + speciesRestriction: [IPC] + id: RobotAntennaCrowned + bodyPart: Hair + markingCategory: Hair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi + state: ipc_antenna_crowned + +- type: marking + speciesRestriction: [IPC] + id: RobotAntennaTowers + bodyPart: Hair + markingCategory: Hair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi + state: ipc_antenna_towers diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/screens.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/screens.yml new file mode 100644 index 0000000000..d50a5bcf53 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/screens.yml @@ -0,0 +1,350 @@ +- type: marking + speciesRestriction: [IPC] + id: ScreenStatic + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_static + +- type: marking + speciesRestriction: [IPC] + id: ScreenBlue + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_blue + +- type: marking + speciesRestriction: [IPC] + id: ScreenBreakout + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_breakout + +- type: marking + speciesRestriction: [IPC] + id: ScreenEight + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_eight + +- type: marking + speciesRestriction: [IPC] + id: ScreenGoggles + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_goggles + +- type: marking + speciesRestriction: [IPC] + id: ScreenExclaim + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_exclaim + +- type: marking + speciesRestriction: [IPC] + id: ScreenHeart + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_heart + +- type: marking + speciesRestriction: [IPC] + id: ScreenMonoeye + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_monoeye + +- type: marking + speciesRestriction: [IPC] + id: ScreenNature + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_nature + +- type: marking + speciesRestriction: [IPC] + id: ScreenOrange + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_orange + +- type: marking + speciesRestriction: [IPC] + id: ScreenPink + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_pink + +- type: marking + speciesRestriction: [IPC] + id: ScreenQuestion + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_question + +- type: marking + speciesRestriction: [IPC] + id: ScreenShower + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_shower + +- type: marking + speciesRestriction: [IPC] + id: ScreenYellow + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_yellow + +- type: marking + speciesRestriction: [IPC] + id: ScreenScroll + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_scroll + +- type: marking + speciesRestriction: [IPC] + id: ScreenConsole + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_console + +- type: marking + speciesRestriction: [IPC] + id: ScreenRgb + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_rgb + +- type: marking + speciesRestriction: [IPC] + id: ScreenGlider + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_glider + +- type: marking + speciesRestriction: [IPC] + id: ScreenRainbowhoriz + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_rainbowhoriz + +- type: marking + speciesRestriction: [IPC] + id: ScreenBsod + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_bsod + +- type: marking + speciesRestriction: [IPC] + id: ScreenRedtext + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_redtext + +- type: marking + speciesRestriction: [IPC] + id: ScreenSinewave + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_sinewave + +- type: marking + speciesRestriction: [IPC] + id: ScreenSquarewave + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_squarewave + +- type: marking + speciesRestriction: [IPC] + id: ScreenEcgwave + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_ecgwave + +- type: marking + speciesRestriction: [IPC] + id: ScreenEyes + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_eyes + +- type: marking + speciesRestriction: [IPC] + id: ScreenEyestall + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_eyestall + +- type: marking + speciesRestriction: [IPC] + id: ScreenEyesangry + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_eyesangry + +- type: marking + speciesRestriction: [IPC] + id: ScreenLoading + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_loading + +- type: marking + speciesRestriction: [IPC] + id: ScreenWindowsxp + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_windowsxp + +- type: marking + speciesRestriction: [IPC] + id: ScreenTetris + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_tetris + +- type: marking + speciesRestriction: [IPC] + id: ScreenTv + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_tv + +- type: marking + speciesRestriction: [IPC] + id: ScreenTextdrop + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_textdrop + +- type: marking + speciesRestriction: [IPC] + id: ScreenStars + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_stars + +- type: marking + speciesRestriction: [IPC] + id: ScreenRainbowdiag + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_rainbowdiag + +- type: marking + speciesRestriction: [IPC] + id: ScreenBlank + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_blank + +- type: marking + speciesRestriction: [IPC] + id: ScreenSmile + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_smile + +- type: marking + speciesRestriction: [IPC] + id: ScreenFrown + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_frown + +- type: marking + speciesRestriction: [IPC] + id: ScreenRing + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_ring + +- type: marking + speciesRestriction: [IPC] + id: ScreenL + bodyPart: FacialHair + markingCategory: FacialHair + sprites: + - sprite: SimpleStation14/Mobs/Customization/ipc_screens.rsi + state: ipc_screen_l diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 2b3733a65b..64670ecb2b 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -45,7 +45,7 @@ baseWalkSpeed: 4 baseSprintSpeed: 3 - type: Sprite - sprite: SimpleStation14/Mobs/Species/ipc.rsi + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi state: full noRot: true drawdepth: Mobs @@ -65,7 +65,7 @@ - type: Silicon entityType: enum.SiliconType.Player batteryPowered: false # Needs to also have a battery component! - drainRateMulti: 10 + drainRateMulti: 4.5 chargeRateMulti: 6 chargeStateThresholdMid: 0.60 chargeStateThresholdLow: 0.30 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml new file mode 100644 index 0000000000..186e9c961e --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml @@ -0,0 +1,132 @@ +- type: entity + id: SiliconChargerIndustrial + parent: BaseMachinePowered + name: industrial charger + description: A heavy duty machine for inductively charging robotic beings. Gets extremely hot! + components: + - type: Sprite + sprite: SimpleStation14/Structures/Machines/borgcharger.rsi + noRot: true + layers: + - state: base + - state: closed + map: ["enum.StorageVisualLayers.Door"] + - type: Icon + sprite: SimpleStation14/Structures/Machines/borgcharger.rsi + state: icon + - type: Physics + bodyType: Static + fixtures: + - shape: + - !type:PhysShapeAabb + bounds: "-0.45,-0.5,0.45,0.5" + density: 190 + mask: + - MachineMask + layer: + - MachineLayer + - type: ApcPowerReceiver + powerLoad: 500 + - type: DynamicPrice + price: 600 + - type: EntityStorage + capacity: 1 + isCollidableWhenOpen: true + openOnMove: false + enteringOffset: 0, -0.5 + openSound: /Audio/Effects/gen_hit.ogg + closeSound: /Audio/Effects/gen_hit.ogg + - type: Appearance + visuals: + - type: StorageVisualizer + state_open: open + state_closed: closed + - type: ContainerContainer + containers: + entity_storage: !type:Container + - type: SiliconCharger + chargeMulti: 1000 + +- type: entity + id: SiliconChargerChargePad + parent: BaseMachinePowered + name: charging pad + description: A charging pad for inductively charging smaller robotic beings. + components: + - type: Sprite + netsync: false + sprite: Structures/cargo_telepad.rsi + drawdepth: FloorObjects + layers: + - state: offline + map: [ "enum.CargoTelepadLayers.Base" ] + - state: idle + map: [ "enum.CargoTelepadLayers.Beam" ] + shader: unshaded + - type: ApcPowerReceiver + powerLoad: 150 + - type: DynamicPrice + price: 200 + - type: Physics + canCollide: true + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" + id: "slips" + hard: false + layer: + - SlipLayer + - shape: + !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" + density: 10 + mask: + - MachineMask + - type: StepTrigger + - type: SiliconCharger + chargeMylti: 150 + + # Generated, maybe good? + # + # - type: Machine + # board: SiliconChargerMachineCircuitboard + # - type: Construction + # graph: Machine + # node: machine + # containers: + # - machine_board + # - machine_parts + # - type: ContainerContainer + # containers: + # machine_board: !type:Container + # machine_parts: !type:Container + # - type: SignalReceiver + # inputs: + # SiliconChargerReceiver: [] + # - type: EmptyOnMachineDeconstruct + # containers: + # - machine_board + # - machine_parts + # - type: Destructible + # thresholds: + # - trigger: + # - !type:DamageTrigger + # damage: 150 + # behaviors: + # - !type:ChangeConstructionNodeBehavior + # node: machineFrame + # - !type:DoActsBehavior + # acts: ["Destruction"] + # - type: Wires + # BoardName: "SiliconCharger" + # LayoutId: SiliconCharger + # - type: Appearance + # visuals: + # - type: GenericEnumVisualizer + # key: enum.SiliconChargerVisuals.Status + # layer: 0 + # states: + # enum.SiliconChargerStatus.Charging: machine + # enum.SiliconChargerStatus.Idle: machine diff --git a/Resources/Prototypes/SimpleStation14/Species/ipc.yml b/Resources/Prototypes/SimpleStation14/Species/ipc.yml index d07edb23f4..9361552aac 100644 --- a/Resources/Prototypes/SimpleStation14/Species/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Species/ipc.yml @@ -20,10 +20,9 @@ id: MobIPCSprites sprites: Head: MobIPCHead - # Hair: MobHumanoidAnyMarking - # FacialHair: MobHumanoidAnyMarking + Hair: MobHumanoidMarkingMatchSkin + FacialHair: MobIPCScreen Chest: MobIPCTorso - # Eyes: MobHumanoidEyes LArm: MobIPCLArm RArm: MobIPCRArm LHand: MobIPCLHand @@ -32,9 +31,6 @@ RLeg: MobIPCRLeg LFoot: MobIPCLFoot RFoot: MobIPCRFoot - # Tail: MobHumanoidAnyMarking - # Wings: MobHumanoidAnyMarking - # HeadTop: MobHumanoidAnyMarking - type: markingPoints id: MobIPCMarkingLimits @@ -49,18 +45,8 @@ points: 2 required: false -# - type: humanoidBaseSprite -# id: MobHumanoidEyes -# baseSprite: -# sprite: Mobs/Customization/eyes.rsi -# state: eyes - -# - type: humanoidBaseSprite -# id: MobHumanoidAnyMarking - -# - type: humanoidBaseSprite -# id: MobHumanoidMarkingMatchSkin -# markingsMatchSkin: true +- type: humanoidBaseSprite + id: MobIPCScreen - type: humanoidBaseSprite id: MobIPCHead diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_antlers.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_antlers.png new file mode 100644 index 0000000000000000000000000000000000000000..125f9cf913e43b01e0e95be18a1f507b2c19a769 GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1Gj# zi(^Q|oVT+M@-{p0u&`_Lept@RwJ7-40@i<197^tMFwQ;5xY64G%-p4ks&e1Dxt3){ z?OwMy_x7{R+jLG_oj0z%Z>}=&;(jlOoqJ4ft(xrN_Wu>jo2#3J3(D%%7d(5KR3USG z{nk%^pJ?`jqsL2d^b!l*;$)~w6%2PfWbnb5FT^R1{$`=*C1 z1;&deXR0d{Wn}x+v$~fFAL4xACUevGL%u+v4g+CyZ_o7FrInw(+kpYV;OXk;vd$@? F2>`glakKyc literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_crowned.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_crowned.png new file mode 100644 index 0000000000000000000000000000000000000000..2fd0cdd06d215e0f8a6fb5027388f25321c17b4b GIT binary patch literal 324 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1F|l zi(^Q|oVT+K`3@@xuv`z?_vo1a!~cs4AJ12ry41o;UHhyZA(k*OcsB>$+(u=|M2m`J!|KGjP#Lh?%DaRSDHdj!dE-O&^vr| vTRp+8&cmV1|3J^52@P-NHAoU=>~qGWC+fbQu{qWU3;_mDS3j3^P6%} literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_cyberhead.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_cyberhead.png new file mode 100644 index 0000000000000000000000000000000000000000..c3d1111199e759bfc52c24a8ca1d8a623dc59def GIT binary patch literal 422 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|R4( zr;B4q#hkaZtovFF1YEc?^&LFie4NgR?qF1Z!WPpwqh&_V1mz8{ChDyHrhaY9#x0@x z8z+1WdF^{!xaYpW$wHau``)iu#g!TrJmKVgDnp^59i> z*{7;~-@}8R#)}n{&R=T9AM`YvyFrGN!BU8!NQL2v2g8Yp3=@{-2alh& zyq`D!z-qSK#v84dP39(U5p!X)$=Y$1u}nGpw%L;>dAt{y&Q$zhD@w9&EVud)#{ML$ k_I!GDqAvnQ;L8$!!N3B#}!vV#MF^$X%Hn6m(1*xbgm$A-H z68`pox{t)HfT?w{4KJ!1WjGlug+APte!c77`TvS7`ZiNeGu_&DcY3O0ph(9ej@#RA zevmtEcxqG4oDOfMoU5C4oUfNk92d--CFg$l*xO&1S3N9Zz0s1pb$O;$UEAFGO7o7X zGH%=TeDnXEm(0@oT`L~!eo(|(V}A0$7ok7-9tx5^iKkbKA9OvCe*b{Y z`5oQH+tT%$qFL9xuKL2sbGTvmh8xok7gat~da!&SWBxfCwL{wd(X4+$`y0yTYS|p| d*bR16zL`v|lS3VMAu!+>JYD@<);T3K0RTv*r_KNX literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_light.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_light.png new file mode 100644 index 0000000000000000000000000000000000000000..91f5fd25e788fac30350718430f857fc698cd878 GIT binary patch literal 323 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAQ1Gj# zi(^Q|oVT|&@*Xk}alI(5$$EJM3u}*4<8A}il0=CK34&@19k|R+F&V14?J1w-(YHuG zR`qWFNfVyw%;#O*e_NQHtvY|k>+F0P1-`hWr_*Hob{*SX@>(YT$+78E=gt4i`ltIO zW6;xm@7M2sYjm}K{#?KBdMyU0^8>2tu89k@n<@tQp8WZbRp2>8M=`?@ONK`>4266R z7VHjlm=(@3q6&XFdDyg^Wz}2up2Mr(a#Ywa*sz8HC{UMVuds5b@`Jw(O?WgT%>2$& Ycc<#%9N(fcU;r?9y85}Sb4q9e08CGJy8r+H literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_lightb.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_lightb.png new file mode 100644 index 0000000000000000000000000000000000000000..bc1133d8d3c535e8e1605a3f656117d963ec6042 GIT binary patch literal 733 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSoCO|{#S9F5M?jcysy3fA0|QgP zr;B4q#hkZy4861iB^(}FFZgihNOs)BW4sa^{2MPEvg7tho_tC|E+RV9ytj91XxV}l z5i?Y8EGc1ZTH0E$cj9!N2Yo$fY@ahr9ut{tU);3p#C}1k75dvB|9G*J%U=*9;6rO&3TYQVjk2outKk{}u{V&T;x945r{&?ZqXN}Z< zZy1&>kACYT^F+)V{|Gi7+-()Kabb2nTau9k&$Z9Te+aE!(wklX{ZAz0n!Im+3TowUO=>hLtLA?exoV1_x22P7#X?x>5qK4U45%ijr1uMD29elF{r5}E)yp%`8O literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_sidelights.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_sidelights.png new file mode 100644 index 0000000000000000000000000000000000000000..7a1c31e45e47bf6616d5cf219991ff2877442b31 GIT binary patch literal 420 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|R52 zr;B4q#hkaZ6oZZ$2(;Cw8CdXraPei?>+Zvven9z@s0Cxl0)sh>ftRblbk5@7YjB=+ z(`e?wJ=YC9(`Nkqe|}5S?7KCadr!tS$#61Q3NaK-Vmb49Pn*ED@9SRc`5ox3+c1mpr>K zn$Vr&`h#J+@as8;FWNqSy*P&b$REv()9!2BV%*pPbna*ebSg|4nJ@ErkR#;MwT(hLkN z9-c0aAr*7p&NcLtc9d{q*9`J1=9pf_YQEsJ=88*&T{4Y*UBNd**RI~7wA6an+Jcv- zJ~mvFo6!2`?#G^s)$19}g8to|xt;m!_n+=B4!(Z<`q`&XpOiut&E0>qXyejrf8y)S zX1BjC`h5HO*^U3^vR2g9-P;2MwX*%kUB&-r?S9a2|G%xQZsl2j*WW+>q(1HbUXby3 z{kHGhEsAulxCPp;Suu*;-kvLSYQDqDjP0)jE2P#rtrgx7`~PXehTYp8VoY54I~PltLGL_zS-?B`J?zHyN0cKy4`;6TzSWfbqyt-AM@T({rTt8 zUxtaZ{<6&f{L@ftpGJg$p!xp`pUX8*z4)T7aPNTgjs1<$@@CgtrLD5Q3D3FwXZF*5 z@(&h;**h4|e*15&OYG?@bxn8w+nWdC*V+`6-MO&ULwFP*=T{=0i>{$jj!elve-M)M-o%RAev*v~DMUvU0^;S`2U zr|-#j`*Q3Z_Ov_y{Ig}hg89p5?hoHjs;PTf*Wj_Pt_kQ%;a%V)bnPX3$CjUez)46W zBt+1Ecl(BV=H&Q;r4J|d#QbHM`j?XRDCetcikG@(+<6Lk&mjrP05 z_Wfm;#7lCrL5c-fs7UzL|EkDep@{1!jMtoifuzA<~4QJf=y cUi-;@`~TB!j(0-$fdvhNr>mdKI;Vst0JzBfCIA2c literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_towers.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_towers.png new file mode 100644 index 0000000000000000000000000000000000000000..f971130b8e4ed051fb749a51113fab026750f83c GIT binary patch literal 353 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fA0|TS5 zr;B4q#hkaZ4)V4b@UV!#rQA{Z7 zc{|IT)_7U{r+qbR85P`_9Qs%qWH=ctg&2xd7@l}AoS4WkK^aA&;Hyi%?fkFLst#m# zZ#k*Yy+Qh$j^gu&y%)3}2z_gO!LT}Y)-p4Dj~y)BZycNK_goj-YnLtf<@$q6&bY(t zxBa!>RL=PRxV3jKR~@&t;uc GLK6Vlqgu(oQ(3N^cy@R|vnA>eN#3u_xMoEAAZ>=@Kwb_a9(qy*N zo8By)a{T7`>eMs&Tmtd?a&O!DUQRr*{Od%cXXdONhALj?KmUn~zCQKM+4Qsddt&gxvzR7m zGZgJ-dQ}rsSOLv#IFC63Y&B&Z@$APmfMj_M6}}{W+{fd zxOx<>O)6&(i+Z-{V#gwxce`eu_t_`U5+m4tvnDyI>;HF!MxFo-W|312t*b;5{(Y{x zu|JMSe6f4t|Ksx~yfqVd(s}#v!`bhqA<*&8r`5s$R z@F{!er(aW<&Xk46$G2Y<2;NsG{Oj*U#vK(_48IpMD6O-9VRA^pWZwGZ_xnq~37DDB z=R5F1?#R9R7i}N^y}nWYbozs^*NJ;RDz!|W{8S)#+S-5Lt8RVzGnZLlW5dA(hIKwb zr62F?w`36g9&dTz5!;b_KfFKJF!c4EJN)$N3;w|J*FS$fP`LN2RIb5`@!gx4mfqgu z+ZDsZxfApACBCxh=*G6)zAa!i_tC5OFMg@rxqCFWJ~!9mUb*0*moK-kcr7n)zwfTr zy!PqWH~R27e7qxW_xVpa*M{r2qh5TCi)&x;?w#4=dmqcM>3@@{zAt?AFaLt(=C|Rm z>z~>EFzg9n)0o1@mD=DWxqy6T$X14zKTEvawleH~Q=+vrIqmpnP2Qoy7~Cq{ZI1-u~Ng`!1XN za*@r-_IBEr7_!Y?m|XaJKJ41XueaZRzVNp0&vV`lX_a-&eXC|~Wlm@?UEE%F?iQoL zfmu^)Ial3YBg??NM)EhmL!+$N{M55Sucavn6QoeRBEqC&F0Z%s>vBtZgQGW_x3YWq zr=R*Y){>V_{R%XGZUZKAr`SAS!8`7z~f%kjlaD|Te@PmmL=HcM8{+JEZ( zzm80qhFi=k_f_g!VFuOlC?i=zJ~Pzlz|VPq#f9eCdT5F&*vhDve@pQ2UCHqBWbn+* z>=&60c$YFQ@lUvYvsuv;#CiZ1J+tXq%=v%PDmK*<9vwHJAQAm%IJMsS=34y&vw%eh NgQu&X%Q~loCIG}n+{FL@ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_breakout.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_breakout.png new file mode 100644 index 0000000000000000000000000000000000000000..d0de4901f413faf4b65fbc332271103f8c074e41 GIT binary patch literal 960 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcaloCO|{#S9F5M?jcysy3fA0|RrB zr;B4q#hkZyql2UZMH~WGoSLA~_GE#Ckd?ZU=1J$^sU^3IUf#>DRsCtXWz*AH{l)v= zD)=xg;cPHroM5KiF#Yt?Pyg=o{r+25uHJ9*zx3VL_cx!%|NaxnIHxT6?z8!E^MAg4 zeEm`0=k@D8zyJHS!v1~9{_pqVpWnYd>Hhzl?h69*_ucQE_g|yVrQ$h9p4&eDX)}JW zywBM7m!>od@+|K?z^ZC3rldb*xvge=I+uy%^;^yv;=l>T!TX6lu@jctG zZ?KkoZ(rZ|eExUN0-HY1do`cM=e^(W=qb#Q$)w;5b*vi0B^HNS3?3v2Zhp_cmCTeny^J&TPSJQ)zRmuI5_yzrPIT+V}bWXa8pO zh<^H>VS@ahu>%IxF>1& za2*%phBc3Oz3UU8*wai3xgQy>ZIi$E=i8s7%n`TiDn4&F{hwfMlIlPG^b*mRK>44_ z7asim@NBmI(NFUkv~Tn0*H!OR7N9h=fd&UL=$D^?P2uFvI`c?vK8}^l;lYe%^lT`RiXFZ}0uz^?d#}&Vnt~_x|LbEoV`p zDB8i{zf-=!KHEl;UhUMK_hj`duI=J3CGN5 Rdw^Mz!PC{xWt~$(698Y*d&U3& literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_bsod.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_bsod.png new file mode 100644 index 0000000000000000000000000000000000000000..09ecc4dae3dcd007aaa102ba2311c5bb7f96451e GIT binary patch literal 1136 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcaloCO|{#S9F5M?jcysy3fA0|Sea zr;B4q#hkZyH)hREWoZAXe`RU+0~HUm;}$a=uJe?hW@V9i{G!#uYRA>J73}Go?>Sz( zGp_*?+(1?|%RH_VfEU_ON~XUR=MNA?|P0UKzWc zfA4-Rx^MP-`fBt4|NcFB^KtL{|KI;efB!9YLw@`I&-RUJ`xw)6_r3o1Grd;++wnK= zWgPzUTKxX`w*TgR&4#b9uYP*WKmUHspR?Qd>weGOTwk-xXY|9>6-Zq|a@!h*tmK-qY;UjpCK_y6Nhz2EQXDa??`q~HtnfEvRk7Kd339wZ4` z-{=4E?|Ir>e*4#TO*4P@Z2tV0!Pr0jpTIly89UEgRM*@5I@a?(^_yMt4uxd@?~=*S ze>2WGZ~wlg?%2(rbq%SDO8)?vACm*fu$w}s6Qljs2ZnY3eiZ+`xqQBi&SV+e+TC?O zA6?w?_vZQh`rUsYGRoNfte*Mu=lA{k@pXpz_1`|HX7ZrrGcR z`}SKqdq6$&xw^XFx8L&fKe$=Gep>hE)LD-&$4{GiZGCv~cVLYC-ezyp(Ea&x=6}Xp z5%KX$AY$*2FMuR3vSJ77#VrpRE$07!_ig>1y#{}NwzEH|`M3MFeaZJjAJ)ID_+oo& zf6UJ6#4n$BDxqJ}z2 zCz`e3Ys2|__uKy}m+PO|EC1jFyAJo4G(cRsKP OVeoYIb6Mw<&;$V9`}GI_ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_console.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_console.png new file mode 100644 index 0000000000000000000000000000000000000000..d7fa0cd0e2a21cd79739f25b93b9c88e8a509af2 GIT binary patch literal 467 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|R5L zr;B4q#hkadH?D0qkYGr(*JR$no+Pp?mDSAQ%LYcF3l}~-nGz@!t)U+MeX7a+N0SS= zK65!qGNdugU`*J__)h=)zeDdYe3qXqns9sD1ry%|7e3FQBC7DOqDb(?PyZtJ1Dnbn zM8qF`zNvp@(~rP+iht}r9B9?}bl~r?{R<745AZM;Gn`={m9dKZ!nU`z=Z(us4NL1v z8LySH+Ah`oOIvPok2|6lv|w-HW68Yq6}{^ffd2Pn{8r1qmdKI;Vst0H`vdvj6}9 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_ecgwave.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_ecgwave.png new file mode 100644 index 0000000000000000000000000000000000000000..e48bdba2e67c62bd3bb9fde8d08ba27356834f13 GIT binary patch literal 1660 zcmd^A|4$QV9KI_cg#^kVh6$!saT&pd%w+?nrF@YoBpYmIkvWkfe#1#=T?Hz&y`l&> z)H7j>Oc7fi9sFQ3M(^$B$@{!AMlqZ95= z(3V;}TZ67waD8XLy?bT!AWd&kT?4l7Ol1d!r3VJc%E~Y;K??)|D(X}r?a7LBOKLucd0C+#%e`0J^>%v;0Zt^8z|dC)gQ3_U=|EfEUiG6i@CLYu%nxocJ0lC6 z;s-d)bD&ZaOH6yZh{Ct66oyR@22=`>?Gu7n^X%vEez~Z|sQ&(bo(a+GZZ_ z3gS@4&|r!7)1RRJV1=}x(zT3D-y9oIqc6ZL_Nk&`EEwvdK_!rd2@%FyOEi^Vdv zvho({z`bg|dADlB6ChJ6hp>gf$zN~>6PgiZn4SUS8z0|3L3iUkE_Z}fq|guj^1eSb z9$i3Su*f0Ym-@-HfrkX>K4_38rms3VjI6x)#(m!* zWZAr$?nLYA=@xlF?;bY_VYd8cAI|T?Kr!)9<;C=X7nJl<`EXfv?6bXo)He zvLd`Rd|CD@9%NZ9R;$&1Psewe-5}!(Zd@sln3%|r%aP4HXxc*MGa^sT6S6gh-Y2+C z{*L3pl8Dp_wP=+k8NuC)G@@{U|CIDb#3ds~ukNTlkT4`*z7rtpz3hy;=>?bm1iWm@ A)Bpeg literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eight.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eight.png new file mode 100644 index 0000000000000000000000000000000000000000..69ad2f0d0c5d78acf701c7e7c2b949b5e6d83c7a GIT binary patch literal 495 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|Vni zPZ!6KiaBp@8~PnKkZ^c-Uub*cQ--$(&YfedQoC_;x3LO)!c&{fxr$t&;_efc-`|tJ z(kArl>-8xcs~UzUvQHM%K&3C&`@7yZ?W-8S9GK z@nQSFm;HU-cDeNO{kk>EPrv2!1epIm$MR-*UftanO{O*J-k z$M(-^nDKqi@6%`b?_9m!ANl{^!)%Rn3K~F@BBa27SSSbX^o(~_Ghoz{XFrr?;aOg#Sp=`fhobAImdq9 z+S8@qe%{`u`}&t$_0vC>w=e>wRx;Pr)GaeDZCGD_U`ij`h5Wte<8L?oSq;&~dVs4z zltG&zjA0EC0ykut_q^jfVchNf`MpGf7DV&zWQN+zgp7Z(%sxwrFazvbWNU9^G^{*# y@B9K@s8h_O9R4$W{d0LM$n{JK$V%}ER5N9G@%EYu@SO(+D1)b~pUXO@geCw!7kX>} literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eyes.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eyes.png new file mode 100644 index 0000000000000000000000000000000000000000..ff038ed3ed052219c060a827befcfd0e0fc9fd1f GIT binary patch literal 445 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|R5e zr;B4q#hkZy4YLkAh%f|77IA;w_rLPaYnGt-50o@7c}9MUFkElAe z)-XgcZt!NDcmDbF_wVD@Ur+w2UiHsoI+M)tjUFIIebctw=xe2af1WX&&Rk>vMeg7I z7_JTPe=EKGsT|Ae@c+Y?KNG8Xk8(ALGH5e|L5yQcU_C&Lz+Jrq)#VQFxaQ2Q-_3A5 zWjFVB?hp6ED{P)w?yla=u=%a_9lZl~H{TtSW%k*+y8tMnNvaJXN0n(E$Vq>nUZ8d0 z;$FtXbGZy|-~25(higMw_<@4uOmFT=8{E0c5IlG9e8=?*fnhzi~=AOCD{=lj3k`=;ycVv?C%@3!Mu!0dO% z5AKwh|2J3Ue;Ad0a*;Me?Ss9{Ej9)FIe)UIBr(ijOkit}WJn{85wVNm_+7@Ll1-(5 zOBmnnTU~Iqs$4O)A#;|O%1fr6#}ZjJwy_LVpQEpzmr%HJx3z?Eks-qw1_OxeNn)(g zbl7t9H^(d{m)U#!7eF{R%n1vbuFQH~&+O;RxajOXcY#;jCr*%N{08wCEy2q>?k<=J Pj2Z?{S3j3^P66Aqwgv3-=G8Af2Q(ytaRXBV>jAC?Q3h?Wse}b?lrY}g&0G}z z;KiSpOg3`;Ps@tK-TU9^`G_Z&TxONXjZfUg@H=5Qw=tVURymNpSd&PDQLHZ0IFM2P z-n{@qUC`#R7D;#;%{U!Mz26O_q!L!_{;vFjhcu`2Zxan}K6=B&8Wzopr E0Li1EBme*a literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_frown.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_frown.png new file mode 100644 index 0000000000000000000000000000000000000000..e70295f4c5adf7df690c378102f08211ea8f33ac GIT binary patch literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;ir{ zi(^Q|oVT|&ay1)BFg)b`@;CnGqXhPsQ)Vgd{VnEbFyZla)qNAR8H!kE)V%vql)qu& zOHPZvX2WC8cddTOaD7?%y+1FPbMD}|&2r~>-Sg`SS_gK#E#rA;{vck2VJDM9IKvaJ zh8RY$0S@aJPKY82imj=fH*1}hc6H5LHIVRjr30ttv&zNq=0sPCtleCtSy8G#1CojMJGPyG7TmS9)7s3zHzf{dgb=&@SX8I2MoKE6KJQOQ?f888(vc)I$ztaD0e0sxZ@)0hAN literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_goggles.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_goggles.png new file mode 100644 index 0000000000000000000000000000000000000000..006c6a6c8055a8cff807c2b6ef30cc7013d303bb GIT binary patch literal 529 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|Vn> zPZ!6KiaBrZ8hSB1N;o`>-{7B^Ev=t$F5w}kO{4k;39)OIjp`dVY}jTX9*`(~o1==+ z)O*6!ytYL7{~z|HwVBwz@lNQLERt}NWJqI}!I%)rc<#}!*ZKKuKT;#=s>Pa|LdYn{ePQh98NN- zXFQX?QtLqAoSxU!d;Yz%Pp@J4@@LvACZ3NC{~o>ksryrk%b4K|g8}ma9tIK_Yj!j2 z-p%|Zw(-)>yR0{k6|VwP7QJ69@*6*WG2Z{=`SsWa-dn@w>Vq6LH*f&m=?IL}JLcWf`5NGgo^>bP0l+XkKvsaM! literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_l.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_l.png new file mode 100644 index 0000000000000000000000000000000000000000..5cad2deda931e5a636a1ea369c885a72df0d689b GIT binary patch literal 239 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;jBA zi(^Q|oVT|OxegnM90;g=@pt{5Ytb)e9BZC4nJ@ErkR#;MwT(hLkt zhdf;zLn`LHy?ZdX*+GOMP-!V^*FxP{58R^l+LVNnIZu8%x%=Pg??#{X0vDZ-pKbWy z@T2>V8Eg#c3oT%eU3eiZ$hJ!{bi<)1PMS|6jN4`t!dh`BoI#{C|FZVb}@N12?T7+R+ddBZPvh(+FSIzyuNA~y26>e`$4`hnloXfYq-`@yy0N52|64#&p zWfW0=!V$3BAn@m|J@yTcLRbZM+Qsf%#bi-dcjQ;e(^sGVF?2mX?qI>(V9Y=P(U9VrhNjf}+KKzq4{y@R|G%G+<@COCrC z14C7`{Qb*+#QNU~GU(Yfl*YFEEPeg>rCvG93BCnSf#R}q4ljRwS$%f?vX!fk^YJg( z{`I5n+5C?;rdzYF=wUn{$uNg(LX>sG&Ts#VKHD;hoQV5%?~(V)Zl)7)Rde?;8->em zzZA;Q6)tjsC;oT6J-fLjPx?81u7r}e|DQgq7UUo+CjSfkKaumCaiT6Ti8FY*`njxg HN@xNAKD8eE literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_monoeye.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_monoeye.png new file mode 100644 index 0000000000000000000000000000000000000000..4a024ad3747cd1bd3d2dcda608c9d956cb3f1cd3 GIT binary patch literal 515 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSoCO|{#S9F5M?jcysy3fA0|Vn$ zPZ!6KiaBrZ9$eKFAmR|%`u+GX>AKDQ>=#uy&Q7|O%{zOJUY?(&z<;(&ECT8c7K}$^ zc@t_s+_b3a`>B4`eh=fdum5C^eVm;B+(-W}i_U2ypUWmOiQFH|_Dej7d|t2Fuv+im zv$7YJ^V%0}K38wiaPiiEPIu-Vzh2F*7uw!f$kZY1Fo)q0)M!oxKZXGjs&;3%UHx=@ z&DK>vt)Jb7yWyVTfvNQkXYO0xXQRZOckVIldv&w?^Zd<>FrU8VeXx37t@(dTX)?V0 aoqzKZ74^w0jOGAimBG{1&t;ucLK6V4ez7|M literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_nature.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_nature.png new file mode 100644 index 0000000000000000000000000000000000000000..2aab6559cf5161c1903519db492eeb8bb112abd5 GIT binary patch literal 1130 zcmeAS@N?(olHy`uVBq!ia0vp^4?viM4Mle)3r zmlvDytX`hD!=vfw?@T5mrj`i|iYg8qu_6yXmROx_|M~az+mCOLS8l%PW1e*XpT=)- z)*r=xo?pK$&tIth?QQ?2`oM(~E_+b4cm@6LaIy=vAww%hBU-`H+{;-A+2rb8Mm z9Eyxi9t{FQ3N7R_zcapFpI5K)j`>#n-G3f;*thK8^>?DqC&>+a&WGJwuKoV=)bE`C z`M*oLZ#+|b;FDc+<@|Mf&WqnuU-RC$??|n~@7K5GJN~ydK*EkwzzG(NgNk|Jpp5_W z%X@C-yjh8^|t+!Y8m^|zR&r~ z-17JHcUEcyGNV(*M~41)hi`7bf0upE-S*A-{|}4t7reKdQ~O)~nXy94w0hQ>68Urc z{`N=x6D@cS7JsU%K|#DCQpUp2yX-c*Y}4yE`~|Y++?}`C{>Hym@0jzpAAh;wbzc6B z?fbv%JKrD>b+z`u;qUK*PwxA>bnR=q2Zx=jf1lm=x3!X+iwfzC(doq+a1iW&{5RV| z`@qdwi{IsY>Uq;yca+MX`zQN8z8UBSEA0c#zYD&-ulO%@u9~%`03y@4eE|iD{2$}I XkF1i{S!CF$J~XZpe<1@4H}W zIjuE3ZN7Q}o7-Xb)7F0`HN9WY=)|O=>JY@FVyb=MUnoZhve^%E@#(rdE6yeI#_;fG(-ma%SA+344o0P+3%<ZXumz5{k*6-e%vyZ`(bHWq~h%1j6{j%@(Z@=w3`|v}x&&%2OY&%`g+^2oN zzue-^yPe06@7@OX`__tv$EUtOuHFBzxSziwSDgPt=F{IF@9}P*{r^kD^=pDYlmtCc zuO3&yta;1Nru`52{qo<6pXPULBX)j}F0fzXwwqnPS9u1|kFg>TK3ahJ=Uf@{wjW+q n{@>R2!@GlBU|G_G;V+9p!gPUip^6uQxrf2i)z4*}Q$iB}IH`2z literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_pink.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_pink.png new file mode 100644 index 0000000000000000000000000000000000000000..31145a55a418d9feba837e9f218f1f4851f841ee GIT binary patch literal 595 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|OJQ zr;B4q#hkadZM|h2Wg0&IcT&hb=cf~#TDmbHM`*)F&XrpYdhZ|6Pg>nOS3pNEch&>b zqGMXiIH$$+HTZUw`de;2qqB*Bv(5gr8Oezc=GA7V#kB^oHApg~F+{9p`1;OOw*Bd4 z{`vJTgB;A!SS8lWnXg}1F8F`ltdp;wNf$`Q zO4V6(^y=R>{8cR}eR=ASe=jYHu4*}y?hAG?o$vDeTisjnz<2gO&ytt@VLQOXV9aoa z!GM`m#_QOIU4bSmzN%05w3XobSN-=M>yG;yd4KJ-^x3tqp3&&?eumATxgI1gZ9Q_? zYA?5eT>r(d%P(hM`ns1pAXKy}V!h7kC10z>70e;QGlMaKM20HsiQMi5MHL=?8~{ch>OHR1NX-!eaV!J$ur@n!60GO>3Tsyv+sOeGASu6{1- HoD!MzL>vNJbryWz?^T{)u*A4X!2Zj^C-Xd${kiVBo_73c+N#A6#;}Ir z#!ZITn{?{M*I&>6J#+c_$nt-`pZwZxDViYt@BM}H^`GmPGwo^ryN_GyU*+^~4Q%yy zmonH^t+SSXkbb!Nuzb`yKpb$)Gc zcp!kQ!B+3Uu637f`im=m6*9U>{d-o(sP_NufrVe^OC)HJVlvz@eQXl1-u&g*#SC;> zJ5x{Dw>p+~CX+wEWoubpGFAP(y_KCb7fb)RB`f=BmC6EO_%nFA`njxgN@xNACH9zz literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rainbowdiag.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rainbowdiag.png new file mode 100644 index 0000000000000000000000000000000000000000..9214cea81f9f5d2808a83d4dbc89635bf36e88e1 GIT binary patch literal 1286 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcaloCO|{#S9F5M?jcysy3fA0|Uzr zPZ!6KiaBrZItJabkZ4QnY}&2zdf5)&X;1tTPnW(hZEwu#^>t#K#ryU|*v0#weN=;Q zJ_+9tpHZzCE5@P5u!yrEgGu4mB8GXdTzBuWo$_h*6sy0L;ZZlQN1b+ys?0e5b=jWS z!(VQveU|smzJF@pp6J7EpWiS4dHwSL`|B3o%Qdgx#q_rB*Wb5N>ux1({<-_wt$pX> z+y7q=IQ@0e&u*q46`!a3%HIE@pMB%QulgN7PjBnX|5wTTG;jCM$F-Ht6e{zAN`|oTW|qGHR}$IhR3u2@5=FMV0t6+U=agIqhYiVRO&kWJzf1@ z)|Z)|zZS1KA{8fJ;lB3a)5h=T%lG_!cEA4gd-i*k{}!0;vH7sg{`3Eji>F^-;3CX$ zk;TD;QNWjh0_HT<3trauW`C}}`JtvE^WX8kmgaN*7fby~%s;p5uUzXNqGlFD$KYd@@;_J^w`FzNiqr{Va#6b14?nY?c5UBuDQjSA zSj#hKfA-q9ub)3J=YR0&TfnJU$!9z7oe|~vy!Op$kHydL`|qyY&*8~ ztz1L*mV5XAUgewrBDXjDwr#^k_AO`Q7aV*pyvCyb$;0~1#e25JH49Oc7GbH`TC>6Q z`@a7@%d0K|bK#wTU!E@Py)*B_#w}(=)rWp({=2bOJ^Ju))mEfitTD18M9Q>G0qb?aPFl(lg(xZf3Af0U#4$lxnX-i_&!tbUHQ5f zjD?$l!EROc@9vGC*?Sm1N=*S49b^Xlt$M#(Wk0svVSNWI*cd!r{an^LB{Ts5qLwE4 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rainbowhoriz.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rainbowhoriz.png new file mode 100644 index 0000000000000000000000000000000000000000..0d6f042d9fc060864cde0b49007d011ef96be183 GIT binary patch literal 867 zcmeAS@N?(olHy`uVBq!ia0vp^3xN0l2OE%Vw$3OAQk(@Ik;M!Qd`Cc-ajG_-Gy?;( zsHcl#NX4ADcLM#S4MiLR`>)7OG@WQ_nB8Q$lTRr3f&R-0+N+99oSwXvEK2RI|C8eJ*JD!4bAFHH3zs&9V{A)-5#=Z9aANM?aKRtfkwGD6kXaC>yZ2ii|RlK*q z?f6-2`}N|hFvc|C0M;(4@U%+mypvgE%2t@2MKJfKWWz~a~kGuaqZZ(fO z{PS09Zl=Q|#*bA$R8 zSm#j3hvXzkRFLEdE4u^N4UfO9Ue{jm{a$YQ zd)aqiGi$f!x1Zb23^Q%zV`iJ$``(*&f4}w9UEV?O4aL!TjNy6Beg&mZz{K|O&veuO xGUxuw-$X=TFXJ}-2h}$B8J|>;8FOEyk2c2I?zH~?7MN=oJYD@<);T3K0RVmEKUM$$ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_redtext.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_redtext.png new file mode 100644 index 0000000000000000000000000000000000000000..46564a9fdcb8c6c136a13a723303847c1538485e GIT binary patch literal 862 zcmeAS@N?(olHy`uVBq!ia0vp^4M4nrgAGU?nUwMuNO2Z;L>4nJ@ErkR#;MwT(hLmD z0-i38Ar*7p-reY@lqllxu)e34bBfw!!TXF^^Q+_&s_!36*xGoBvt-k`Jd-zO&*a~o zDYbaMddiHQjD8_q|Ig(L&SE?u$uNiU054a<)~LDj-oLlsUw`BM>9XCqr(Ayh{BLje z_0OB<@}~6x496dD+@i0q>TUo3`s>%vzrQWA{0WizFu&o9xkC1{onVCp3}4I@e*bho zD=*@3z4Ynx-|H9h_m`Kadj0+5dU=k$!OuTF^6Tr5ytdP5IQ;NJ&cE6PJ}c+P3)Qy& zoV`CjrbgGE?GV^OWD|FEzB6l_0~0ww)-f<~^f%+Od%O!GroU&OQDNSY^wUt_9K!=1 z1_}s;8@H=!cU4w--JW{kecpdme z-Jis8FzbFp##TlthYj+-Yi~}m>0b8kK0hiXN1>A#^lTd5eExXd zroJb;oqa;B-M?AS`wQQGVAyp2c>L!-hU;YiODp`W`D1!s{_(Acj3u$*Myd19%NPHX zxX#DF;9E`AmN%b&CZ7XJ*739$GgvS;kWK7Z#gO&hSN`qUyUaU(GlH0FOTRn(FkQ`* zkzSTv^1ObnR>K?d1+lxT6-wbP0l+XkKmMUWS literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rgb.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rgb.png new file mode 100644 index 0000000000000000000000000000000000000000..bee0f564a3c110820102625d9f7ff738caf721a3 GIT binary patch literal 559 zcmeAS@N?(olHy`uVBq!ia0vp^2|(Py!3HG1+{xJmq&N#aB8wRq_>O=u<5X=vX$A(y zhn_BuAr*7p-Z9LQ4is^?D9GXz_UO>rhD%F7Cr#2?T{!*dj^gQ!nJpjP9u+wq2wme8 z&trAgwv|h%mi>zXZVBElz5Y8I$yz=+|-IcNYmwV5=KK}D{&EcP)e--|- ziZ|V_&Y;Z@#;}IrMkr%m<->W!r@6ns`J=6Wr?`p;L{cW=p5=&2(YkS?zs7;Gpy77tA}E6v7)$zMq%Bf4bqZ z=LZ{?F~v;&@AvE5UzJ?OCqT~Wzt7|gmfRFI@SFE#|2BpqR)=*ACqx-Q+8Ca2HN-GZ z&_)*Au6&?0W5??|IX`clW`46rdqeUYpe7*G#_Yb~w?5GgpC29gwDC3*9wWXpDd~v` Uc*}Cl1bTwO)78&qol`;+09a>ZWdHyG literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_scroll.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_scroll.png new file mode 100644 index 0000000000000000000000000000000000000000..f5d78debdd3f407d1f9f4fb48e8334662473d52e GIT binary patch literal 802 zcmeAS@N?(olHy`uVBq!ia0vp^4M4nrgAGU?nUwMuNO2Z;L>4nJ@ErkR#;MwT(hLkt zS3F%DLn`LHy<^yQ$U(y4q0XDYJss1Umb&UCWWVLy)4X-Up`Z;{j$MOb3hw_-NYt+9=uesT)1G^wB*PrW1Ck6es~OZLd%pPo`~Ls;WxF3$*ofVJ z`)%MErDf}{Ym0TeF8>^#e*OF+ozv%@T|fW7v~2C$n)?g|Yz*lj;<{GDuLEEI zXczsgeNZXqu=(uz^zy$tb$oja(|)rx7&BNflTYjjW8`6L{!nGUcc1qCr+;gXK9*)U z$MAp$L`1O$=(n6I)Q|i4lTvFem^*Sd-)wnUFe5kI>GDrDftz2eYFGb+cu?Tx&zd?Q zN8o0O)!AJ-t6$bo;305e?0CT#5-NIX)0r~cEVJ3IKWpaY{;ROzTYXjQ-$hOlV8>5mUM7!1`@NjM-Zfs#5V`icbl+bFO?|t6thL_{ye;egH@l7r820M|8Ft1W z{BoDM|G4t6d^0YEqkq4sz1YqE?f2f_j3U!PX$qXMNFZt%+q}2uJ*xb56PV~3JYD@< J);T3K0RSR(BEbLv literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_shower.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_shower.png new file mode 100644 index 0000000000000000000000000000000000000000..074708133c2e24452d08ae6e5184f92ce44dba96 GIT binary patch literal 1232 zcmeAS@N?(olHy`uVBq!ia0vp^4?viM4M3;i8vwp6ESwbOs^7-MLZ@=yT|9t#-{=?!;@q54ht^0cG`|qXCe;@t*q2~YA_lE-+`yN+p%dhyK zU%w~!JNNIukG9(1U%zMT-|Kt$|4B0e-93RpQ3dJ+a+$vyzKL(&ulA1lR{WiRvvj`M zCDhJ8S9_>eIM>+1>cI9-A71}%xmsMoeg6MLx0>~(Uuqq`fBYACclqu2V&@mu{mb6; z;&;Ql$A5pnHnwm7^>cma|F#BlokF>1h%w>7)SI?d-%tEA`o_A$==R%d|C+wBo>;Ta zZl8RGC8N>m_Sx$X^KZZV@6tX7j)K%>nY&*6^_REff7}G-A1gfbkMYnygFmIe|2qDr zN(3+{np8Jfe}DMq_WO6td3W14=l?%i!!q~g)ZY~=wV$8VoBg|D?NZzSH<{V3y#6-l z@6@-yIZh?Tto`t17DHrDyXd{RIkpFa>!!|9+s^*B+^?{@@Ee1FrF@>u-G7_+ud9`J zq&Q82qfu7m!MR$C-{O1fx!75El**s`$NGMLQ~v_?h{v^7QA{=mq~2e?Xr*!Bm;Qk# zc6Z-=f5}()^8J5J8IcE?`TzGGd0`j3s~#lqgM&+v(aEDhKuDp5g+r0isN23yy3GEs u)tYzln*P2GXPjz|3qqujRN-L0$S;3kKc~`Iw*pv1F?hQAxvX@nXL5CI_SwqTlcQk=5J8*!+mN`W5Mb~t0 zyS9JI8>C?Wn6~r1BE(7jxSQl{oxJ0~6aioDRuqa*SYxST zRvuGaj0D|{#az(o=6)(^&#EJ39|re=GRVc^d zKi(60BzjAau!5&f+3ohS`q%7<%tG|bYv^2?QW+*p%XeOASjvkjE$^R=M2hi9su9y2Ju1E{^4+!O_?n(f6)f1RI0yi8<51wNts!4vj+3~ zal%&QS;1x?@`d2)*&&fZ?05d)SCju-aU9v%d6kDrqykLRSQv`9spaW$Vp90_Oo~S* zR|x)msfpBhh+9*4ni$)$+VcS~dmo@=h-w=gPOEvlPzy&iX$Y9@to*ywvRT6S=hhJJd2rnW7XtSh z2X9C8yZigVy0E-F;I)BG-W5wp>am)%fen}&GYu7co+d4!Yn&%Oo0XZT&Q0h(*fxM5 z9K0Xrp`2X`z(YjoZX#Z0m`y!YNX0`|yHBc3s`!m*g0OnvFY=m1e1YH!UqhqO*lb>c zvVMMHp?`32DcWoq!UY0BzWI|FpwehMtt(-uO&~}`EjbWPu-WDjh60$7E(T?j6|zy_ zF~|n2G$8xxS?GFuhvwIDU&7pk5!MJiz335}iks|50ZW9UUSDE=YfH=ESbAf$Z*=gZ zEh1DDO`okMmE(QdKE0lj*7jz}F*TN2kdIo3)p}~gWizKyS-1#vJ`2+?o!MLR_k9>XM5#6>(%(v?R&$s$AhOJ{NoSTbfpIS%6C ex~DKaLhHD{c*1?}-QLV^16A);Gl%zm-0=@44nKbY literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_smile.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_smile.png new file mode 100644 index 0000000000000000000000000000000000000000..6437b068b18f05c34454678501932a5943bbd04d GIT binary patch literal 258 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;iT< zi(^Q|oVT|&ay1)BFg)b`@;Bb{=)oYb{K|Jx+;;QPAyHmu%^?=JqoXMgpTvca*3i|b#TcEm7F&}JxN zby&x6LX=@AlLE+?1|-3^90j!|cfQ_z^Kt8Jkkp+%2J3p6iki1-*i^%exTkepSfJ4) R=r_>)44$rjF6*2UngA<4VEO<6 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_squarewave.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_squarewave.png new file mode 100644 index 0000000000000000000000000000000000000000..22a1b389d25826f1470e91ac38345e70a1164f59 GIT binary patch literal 1096 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcaloCO|{#S9F5M?jcysy3fA0|WCf zPZ!6KiaBrZ9?X3dz~CC_J}c^la;n6w1w6NZhd3~bFz6}pUU1u#{y|Ck(aj#&)AbML zDsP+-I7PfQ=48&l|Dlcsi~_z4F2W2K(^w0v=B|7Ezq+=zc4e5+z54q4_1}KiPW+o# zT_MZYe)aqQZSB{e7Dbl+ulxP>Z7z_XIqUV`Zwc@ItzodUw_p8HKf$;5e*JB^x_PFh zvEOs6-~PRu2c~}C{hwH0q5td?hl>fLKyDa=yu5t<-fJfJ?&X*r{nq~WVX2K=`2GL4 z*1g_!D{uSiclYzx|NYm$y?&FucEfG`->F~TXZhyd{&zFJy1Kw_e!N#Me_s9%@0D*4 z{`gz}q_*DyZbv_|LGtmlXG&1S#;;qlG%d!^jw_v}0DXa7}y zzWIO3|9^c+mB0^s7mcF%Z?iPKJ zXa6P~KD++)uRVA3y3g9n^*=wF6qr-@@^k+4_uqf7s+He$?!Cx?&+28!}wbTLmjq~N+J*AdYSsd2SN;l{Exu&D~Id?-` zZGG9{`F8P8&#y1r9lJGdeK#;=?3#5pZU5gY#tW-YAC3QVlXrUe|7Aa!6lTFv6(!7T z)eNPv^QWIq-T1ZQ_~VZ@Gkx4P&%gI))8}gbgv~cYRL?&Dyy)}sZSwZD`=S-9w%&ig z`f65a&cBBRE0$e;nZG}d;Y-%;yJB&PHG)^6Fy=Ffez+J5nOV6nyE M>FVdQ&MBb@0D}A_T>t<8 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_static.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_static.png new file mode 100644 index 0000000000000000000000000000000000000000..58f762586904eb005341eb5415b85f285ac43546 GIT binary patch literal 695 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSoCO|{#S9F5M?jcysy3fA0|Qg0 zr;B4q#hkZy59S^+U~o%RE@iP`wl-kkIXH!fk$D4iL3;ZX`&Fw~y;Ajj>apj0Y=gJ# zZT`t}0`jgIYz*lP1#ArFS`B~e?$15{yvRc4*Y)kU*V@SSyJn{BjVr(Xc3XYi`o~2( zO{D*S|MR)#tFobUaR5q%PanN{gQv`_D^s7tbg;5PSq2ueP#=` zggxJXGiO#`^mDmjkg}&mH|^h*?XLU$+Irzsoti5g&u=vB`f%|VZ@}?7yZMv{AY5UiKl+`b19h1tiJl{cj@c%_p1&YAAepaTfc7Of2sOYTYuy$%waqr$uM|` zzts$PPtV!E`qhua$G)>P7&BNf1Bo5={0Zlz6^_f>?Ng`JvAkRhKJWgXZ;oUVFIU3D n^7r@iYWyMAf$b!L_|0Nfyhho)fcXnBB{F!r`njxgN@xNATXYC$ literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_tetris.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_tetris.png new file mode 100644 index 0000000000000000000000000000000000000000..b6c3fc72e7df126ec9491add095d656e24fa06f0 GIT binary patch literal 2131 zcmd5;YfO_@7(QQ1TMz*qgDJNX#=B`vG89hY>9(zuSnXrV3T60ijd>CKPt`}UzfAp1K=_T%Iv?>RZ| zd!F}so^vjxr+whHD_|D@z$@iA{bK;2e0=cS$#~@2Ytj*X@?ahRq#OY6!Hof3kMs@% zz@3yrKXS6_mgVn{N~R0Ju_x5F?3MTZN$?qxIU?#Z#s5f3Lfa2FTLbp>*IUZNbJItC zh`sh33NrA3$aU^9$#fnR<{&#)AC!M@O~lM%^?YpViC?if6*FtniVdRI9K&i1kzse9 zp$gYZ$fMOYvCVIVAFW@^9e}Ay2KQUWB<8)0HC0#j8!srdyPh;kI2C#|1gXF38NS{P|b?Q`#b!6}P96vz!SJTtT-j>n&2 zrl|lSX7VtYm_2$kOK;p@{jYxJea9q82NEw-uk|EmKVXUjO}%<6(X9NevZZv1H-dWhD;TVvZv|4cV0 zp7@vwC!XDRe$90-Ra3ewBarJ76P06eN@+7hR!-<9q1zY4ydsd1VmsH}^7V4W zW#%5`4F|5c&;y4J7Oh0FgbaNO5g*lVw@5cSB@a`Io)*NtW5*NG1PGtve6CkAz)HW8 zgf9B>I51NVsyUos*n?yg_K+W|ny8Z_rnhpqlFH{Vkee5cOLJVfWo|T+BG+3qI*Bnl=>bn0m2quZY$qi1%4$VR)Vc`3W|0U-L`Yh(PpFnTrsgmF{X zt==w?V}m`p>_an4ZRMI~K0{?V7&}xJmQh+yG%#janVTb1LJ|#8243fCJVCQFtdtTw zFwNWj`&P}jSv7^XuU_I&)A(nAPgCIO^Z60nctd|q3yFIi;|`P3hNy*ijYi{mAP~qM zZLrIzU@@o!!I5Z7*%!GvJj-Ra}$DN za!brONp?5`+8{OnWg|KbbfHn)jj=V#Q#=QvFAn%5X-9X!Siv7m2_ONgvSonW|54s9 zHA2{a>lIPj##&*%#d&{!PqB1wpjNph|6l{FFwD%QS ziL?xBcqi%DrMFwoHY7BTwJFso<-gh8fqnj>O?hNv8p@Ki&TH~XbxW5tE7iuU2QJS! zUXJH-tTu&K;c+syvp9t zTfhll{;cHAHU|V04Tc-4^y+RgYu_r*l-1Std zi(ioq?n`xt2cYD=G)%)?kE>(ecpiuj4Ueq?n`a*r1=!5D&&nHmzhi3u<0JAKT0_MU zL}W=HIGs)}J)U@`EMHt_d=NNKv;JaG2XO3mdzM5di))Q$%4;IWM@ANKheE8L(B+HU zO?;tL`jT-iQ(fsN=-vDKKOk7sN5;nDxw7Ux>m6=pvPk!y*g}W&w7|y#i04AebI-fM+4_bSO|gE>qJjiTr~-MLzqgs+q{=@ zuz7|}uEv|hku0C}o|u*S4QRdO9X8Uie_ASLRRm2R(+5-!Z}^?r>fpxqd(YcXhf3nb z)Nx?5ag>pH3{(ut@Ihz{M>K?ciAn@o%`UK=DoLCO5=o)&B*lO8r6Tf?RCkUnim{lg z#oJ-8r{7dvrK1vUmw_h74aLIv4uxw*MP%L~P#F$fTY<e>~5eSzmKDwQu7eTffs*`=&pRIsQp;dEt!L@vn=j+txq*vGM2grzY#q z*HpJzPU}A_KYgP8z2E)DYuZ0<{MlZ5?)LkCRc-Gd7oUI61~IT=XWn#6{dz9F>F?f8 zmw&!fZ+^+1bH88moc?p?&;NNppYhB$Ij(>1!@-}=KVB}culcum-af|T`}688-#K0*A<6n*)Z^E#0@vJ=$z zw{QFXUM>$5#a}-$r0<#i(&pCJfcJO!cWk{||NX{YUJJLqb945~-ThnMU(OOCzTx@L z-PPOf-fhU~rYx9kMHbwxe}5ZjY?b{3>m7{1IJ@G^cC9nQAyx*`=`og>Ye=AK6 s>|*#_o)&Db@LL(048duUSmHm!yB7=PweRfM4a^Pzopr0PuxhZ2$lO literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_windowsxp.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_windowsxp.png new file mode 100644 index 0000000000000000000000000000000000000000..5ea923b008c97832bfe8add89f523edf2b30f864 GIT binary patch literal 988 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I4M=vMPuB%foCO|{#S9F5M?jcysy3fA0|RrP zr;B4q#hkZyHs*!0${hcA`AEyv#>QDQHmr2M>-nl7|AB*i!(CpsS_Z2J&zN_-K5)aA zt%6Bm;yV?qndkJjKA$z|l+xZg#rt+1Kd-JhefI}z-TPZk%Knq*6%bO;WSk_VuyQSv z&HjR)-_P&=pZd9~s%DG1&XWfpH-8rA=exg8etzQ1zaPK8GJX>qQT6|oamerbzdwI} z_;qpb+V9)BKD?HnpC4EM_gjIn-9CHSX~mz9*`GIf*Kc;e;c@DB_wf0Np2;QC|FchD z@BM!N-Fx@{FG#Mb+etz8h{Z*gWfA_8|ug?tMfA5jxv9n9}KY#zOe_2J_TBbe4 zuP>i{J$bo2|Mqe)!Ux_38Di8T|Xsee=7w&sus~ zTD|RWyEa8thae^u@(KA8`46Y%=jFdU+&gX0`QueNwekgfy34=%-JSHEF|vQ{d*-n1 zjFHpl?%_XC_2x;f!?k4f_spB*D7Tnt&W#G|!uL*F>p%Rs`SWyp{M$487}U!u^*0uM zcC)H~Tg<X5aK3*}uUGKdS$J@7o|Oov%Jk{dHMxJeYZ_zMc}VgY`~k-;w?Oc4*+8Qc-+#WkU0+<2ug?FW?{~$^f9q!298iDv`0Td-$Me~pGyDFYWVR`k&)@df zv@VzOP`l1maPD^bxBt<=XyUW}Dh%XR@7@r9pMB2ZtxPeW-`f7}o%@UP#IG3b1E%+u wZ@#}PtU=v9@BiQV-=9ASHvlJoQi)&E@5QyY$|OsE1!h+UPgg&ebxsLQ06IOJ+yDRo literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_yellow.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..1019e038416120615cc62b9b28e9d503a61d2346 GIT binary patch literal 495 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 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_2.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_2.png index dcd48a5a0002ceddb9ba8ae23cfc243864c6e537..f602224e5acfa8019130ce4849b3d4f00569f3f8 100644 GIT binary patch delta 3588 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 KMNUMnLSTZ#EBx62 delta 1073 zcmV-11kU@99K{HbBYyx1a7bBm000ie000ie0hKEb8vp`+kGrvbu-tQwb7sDoGiT1Y6Mq6gR#ui|Hk%D)R#sME zVqzl1U!8^oEEbETR2&+z0g(~mh6-2R8!Dpx{r$RxbP1sGlgEqs`1PB9W;g*(pE?19 zgF}V{P^RbE3qCGBVxeV8kAx-xGCnam&F2a6aS#Ydp7w7#qDewU0FAQ{!tOnLAy`0N zs8frCW(2HOD}Q_*9e`j0byikZs@63LxLhtM$j>!YSXfx#Gv6*ZP^T6&31G%=hy9(; z;aE&8AHP~&g2B{yLwP-&Dgs)9lQRpDnU(~3`3174-OOM&2}EugCmGtK)T^aiMF5Kk z-eWDc85ucnvEnixkB<0;91W9<7W4{~<`G~KQF_~W_kRxDZ*GDoo$W9*@|7zSD`M}< zKE6h|Lwksv+5A+Km~J5=Z_!iy;n?AP2-(@$U<4#c`!G?_xL#BY2~16m$sQmu8t$LJ zpw;CtB#@DrquNKu77zhCV@xIrH-5j(h8Yq-8A>+%Vj_z9;uirWii(Ql@u$&Y*q4+7 z-xuZ}C4V`Qug%Rb%4^Ca>gnm(R<|wz%Ibl^5mned9uJrzOz`&oM?Oza^BP}c>!NJo z*)v?%qmBTQ5bO0ddzFOY%gxT<9wL6Pufu`VbSNn);d8s)&cBx`uJCVHR~I{?X$TMV z9ur0ga{!G8^cspl&y;9uYlG6#Qq`KtWP)`@5`TaG!Y=|bG2SHfta*tnvT%#QHM{{4 zj07G}PzfwA`TdfOX=%R4$>CL8 z+q@w`CxFLLX0<_dbhM$I+g-%3B1P?=2~ZU~boi)jlwGB5--7Y+akySpy-CImV_$|1 z`+p0~o)9<0#YV{r$!J4;9e*SAN-Gu|Ygs9{THEBk2(K=0t8Um6qH*;4JgZ(Eo!uZp ze4s=aJv{cSw$10=;?tPQ1jzWg3pRM%?tpsct>`JuXJ+R$jijX}bD2m}D4$brfTW1H zw@cb0Arru`?+D%CVg^4vWHM&#zPJ|!0BWphFR;~WVnqR|FN{{)0+9@fRY4; zQw%jl;K7GRaOU9`z}bSep^=YSKg9p8bwrp`qHz@gC5b;9p+2EPU}#afUJek@kSY?S r%kQRC@84^7jUa00000NkvXXu0mjfv4HI{ diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_active_unlit.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_active_unlit.png index 03e6242ef99cd8048f1c33add3a48553a2b16ee4..18357d1eb9db69d9a8324921199e5f9ba1cbe729 100644 GIT binary patch literal 9960 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 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_base.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_base.png deleted file mode 100644 index 156579d6bb81c0cfdf01f14b57e691f34aa83509..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 870 zcmV-s1DX7ZP)r|nas}j-kaIU_f58v2S}16yO~!k7Q5VXIvOwwzIyqB>h%hh7v2iz?;cIi;NUPF zI()ZrWIGc=10r#b`FVQ-T+nO^Ty`cb1|S}d zMm6zvf@UC2A2T+VU}NA^U@;-wfmA9*@5^sIi;Dmbm;h%so3%U_8p!AKlo%bMP6C`F z2n{qE4eB)PI4uS?L!9%9xGe^1wOW^QU|b~}uLi)~)&LL+g*vTo%jqc$V-pk%23fz^Y*OXJyAAQUGJxD}PD_B=d$9mxR>-YOvKinT<9}sg>9QrXnAF=Y!?~eSQUV)yN_eDm%z>|SOp}<;E zUe}K$lgZ8*SZjTu=g%svzp|nV1cH6S!ct#U=dHGuS=$#1P)|?yzZu|w_+%=rB_BH= zDb40*sJGW$J+U=_6(W`H*}Gp8RZcR+VlhX;YPCw2rgEAYWJsqHFT4{XU}s-IBjlpD zrf;^rmZv69Q-1b=77M6cQ5gr-@lFVFtQu+b@sp<(0f^tfch`0`$P;JIo)bRHoKOGB zoRZ;Usu|$oCr+j5(Zd;*Mw#O+rGuO&iXK6 zzFq^o77Qr=e(+lK)ezgwla8oHfD^cKIj3l~v~kUVdR>ajm~i#lb#lV%xjEMIvjK68 z?HiXI)qDpo<}!wHY&AZ7<)T-FGi4UH7|@&eweB-)6~K#8 wyMhEEJvf)^OQ~ogp!|$vvnewmW*0BQZ$f*is`9olfB*mh07*qoM6N<$f>t4kcK`qY diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_on_unlit.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_on_unlit.png deleted file mode 100644 index b2b98688d94dd891327abbadfb9098db30d910fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 885 zcmV-*1B(2KP)RCt`dR!wLVK^XlSe?Uu%%Q5{c6WAm zvs+UiEW0~1-+OOnXTNXOk_RM{NyW{$Y&P5AmebLIC^+`wITed}ntb<0I=-W`i&|UT zY5#$PrZ^`r38_;|!BzkfRNd-?=MV*V^M>II$*jE|4A zyDYC8+j@F>>Sy44f=B;_V{J z`})tOtC=%tI+*GPxcIRXX?plzgof4GiZkW!cF7185o4M*`q(=^SHcuGu2slo6S@H` z`x@U8dxi<|cn$Dc&_U~{ml{mf@Fgkq!>|$}zzJNwG^A=(^mg5Vc3g@n7;xq4HFCn( z$62Cn5%t&5em97tZC7NAV;s2W7b>QsnQ0FgO<+02rRFPeeyE?_=c?`P)r-$u_KC2k zL~)A&qlrIDKGRYWEf=F&1qnh%a4y$}QrSR2{f!jSln98~#mn#)$&{%22x9?c00000 LNkvXXu0mjfc$bj? diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_unlit.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_closed_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..99eec2b9815d38ac3ceaf6e4ece68fd6204f69e1 GIT binary patch literal 3076 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 RTkZe=002ovPDHLkV1ip{bu$0} literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_panel.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_panel.png index 0638730c8e370cae640154a5a98bda76a9aed626..95f7dd49e96d5ffecdc385df2d08a549b48c7770 100644 GIT binary patch delta 3471 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 delta 1020 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 oK0pdo{k~dMHO`6_>U zaB^>EX>4U6ba`-PAZ2)IW&i+q+ND@+mg71K{jXKb5)2YTS`PX;=j~vYKNs0fC+Spm z*PG;2B+D2fE?jVh`QLw5_zymua|ubbY{h82L0H`dw)AmD%JEwBZ_;sCz zAIvR!^S=MBHOks&#wjdixH?~lx{tDFkZah&w=Myu|314_jz&TaO<0 zZUs9Jf+!P|5gz&RH~jR0wLBGwj`Hvo>|%Cj!wg5xe<21$XkAW~?cn?S{&8F*5ES>a zr$~ik+o_@n{bGW+fsPOqjAss#j!OYtgsla}Py_-%jiOMdLz$Hbjw}GkU^>Ud4G543 z4;aZQB8!v@`__0wX^XNjmIKy7W8DGckQLuZi7c0;E$1qjxy@7NfV(o)0CN~&NAz?g-}~Dth8k1rK_yE?19<^ z>u=v5phg#JypeK2eV~R_)msHQorq%wz&IoV;_46}pxH4y3Z=x3oMU!W&|egWk>Z#Q za>RgOn#8i`#xC%Qs3Z4(;TAN#;Ku(Jx!}XBN6skBIEU{aK8Q zd9nL#4BT4BbRH0zYcFH&i`-^Q<_Z}17S7X3w>mR{KRMz4$hZ+};jT5Xkj$n@sCUY- zSLj;OY<8HPk47t&0p66QMYLCygfbOv8-Ox=&x5%wD6HGczZ>0f%-lv?L^f$uf)I=m zluNh4ZFf_AQ$Jhrr>TxMNIK*aipCf7Foysmj{qNzo?LMfRNoeD)t=oG4RcF9DK60m zX_ZbW;pN5IpHP7D&CQ1QX4zQyDYk_jmydJKF?|gK%2C|*f9IIk6u|?J?%{QvpB44T z);J0v=d^?2tB85GSzPA`bQ|}b-G5D{^)UxF%|tg#=}PfyUPWccLLV!0Ve6TAe$^QDNj9kmh|1wB2$IC`Y{E3m1Oq z6t%)wFxZ%TFtmCn5gcERw=4$qM`~klCK{U@l~96Y8&IRmm*;D>J~%(S!@Y2lYOT%h;uU7$F!vp7+s@j?7G}40}Ic`h8{I5 zuQzZ$V&W=;b0gf_PBKB8sNN)h4SM0z}_5 zFW#$6An7m-1~taIu{zM`mb!y3Tw4Ka>=Ad~Y+fokCjcrpTdm#Ul{Fr0<_Ykt0)~@! z`t2D!n|dw_^|W=JZMbs?-D7FHkJ@&E0YJ=1ZrX&h=i%aGT+(I)r^AXkn%+~*>a0Ia zjt^DAUaCSsS@={GKGg)gGtRtW0M3Y=F_*^f;oC+HqseZV$}a49{k^-VXF`_zRCrg0 zeFzliEk8XXMkR+dBIpW*f5%0Ba-g>*RZoTJ?%iuMZ!b!Fu=jRHGWh73F25=mD?(8s zkF+`_XtY8d(lYNv21oafCPMJeOACGNQh$?(@EIJh0$sC$cZncqB+I25MDoa&R6!!z zF?Qt+(1|x1ycpD{k_si9p7{H<@;nL;5?A}eeS{q9+Qe(sl~nzkw&-jmF9UH;pB zbJcKPOr(HgfY`)K75o6tq5SM(0=hNi9~U?osqO~2M-TWND$nv0oNYilo(wn(*z>W6 zG4jSAvqv3tSlaklFM}?;qxnDE{s&%qPrYVCQg{FW00v@9M??Us0H*+$;WupC00009 za7bBm000ie000ie0hKEb8vp^WEiQuRkw@gzw((d7gW}@BImb9xN7%$#(p* z*(_rhlj((U>*EJhDn;xS@>KuuXaqw;*Kz0WJ==m9EAsWVRSj8qG-66_<`W)`U~y^L zRD|0uIk8->y8yNA74leLTgBqivP=`DO#Fv63@`JEP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+NGE4vEw!jh5xgPlpulxALa0+nRJly^MR7RzP{dU zHnGPdO;I3#0~|nZ{q^VR{@^3YCl@uBR8u+X3& zSPG2c`diYy|FQ0$08~zs1F0+nQ zOMW$>uWOtSOUm_gcIl5*y*I!8j~VYx<(we0f)5AR5ad!I*e|%ym;|m8G8^q{E0ycD z)n5+zmU|{&*H^ou z&K+;wx8Hfra&DWkqQ!)(({0qlls#i#=LkExI8;kV=BJ3r`&;=IqIwVt^B70xJACy5 zT&ItI`sPo+_Bi}N#VE@OSc%Axuony1RT<#sL$t3yC4=D%1zg95JqCH|;`g!j7;c|d zIC*-uibt5|k>CEh-+kabEfu^!%F|cqC1TD-4MWbZYy%O0-cHr+;K%p zNX4=J64BNFV1lrL4s2A$D+hg^w*Xwk(TXxYfB>lZpg#E{i)8O{WC5Ut>Jp-K5b&xp zQBqtIiy4p#ooxz>))H9v=EN4C2 z6SW)GZ{OcQ&EKfWM#?tkCu*$b{1D-dPSh|1Fmcg?cs2+KXfe!=;$sv;&M-SF^cPf6 zQVp}|4KWam%Zr}=ft`~JQA6&3;pTGuf}8wT&vp1|^;5mAejD9~8#lwzS6gFuh z6t=RI@6V&Rojl-12Ubt-;YWVxX+y2?Y3^gqOgN0RKKRMKEaY_Rz$@4Avhht2e!ouF zGt`*~eQ}oSK0s~QP^1rq*8Yv?yi|(DV48x*0!qCPq zVD+9!ggpRRkWLoP*hX*jsAP59J88yVM)$H12xs=+flW@N^C8a$C`K$FSKUJ+r|T5W zUFm0u>^#NC3M&Tur)%mq43XPfA4}TyZc}gD?O7iORJNq+Nr>d(<{7O)dmhA42kfRV z7(#7>yJG1`9z~jlZ=vhn7A%F$ww=i*#M6hSzF^~(z^(aeN}xAP0|bF!xK48l#pE(( z=sE~y^XNKBrcOK2EyUxrF!(Yj@5u)ZW~(-HV2iGuoK(6NSe?qE24Z2`b&@%Q^r6;9 zfzA3uTZUHRYiPTVobX7sO#@&sw^zSJA=On|#lnVb8@W~i14RR2BG5GyrBK>2iqUa0 zzkQk++eHjAPoxPb$&uY!PlbAVjX4{wpQ$~Jq=C#;9@^Q^=m39}v~L!*xh=U7N`SQB zn?>1LG!3eA&=FR^K7DWE3S69E;?$`GXL2=_cJy(y0=UM9ELb3nHUAVb^^W=4i-Vh zs-;x3iR^EE6D_3-3s)DOkm27g0$RBpz)Oq;Ik+jU^)x?Zans^e=+_rXK-xze2u5$T zw`&S-C!cuZZFHMIELNX6+Y&8=`b|HGCG6;7P^cNtU3Pph!~NP0(gand?PAu9a%pb9 z+2Q`1A>ZwAUk%~P`;?d&v?h(}tp-ek{_CmLru5b4SmLj}f{i|wR!=lkzb)r-*Mn9sdS_nhP zyBV z=N*UXCHYp{oyitRpN=(srMwf_^@BJKW-mR^BHfsv{r+QA5I4_5yw$qcLCOa+_zVb& z-aJs}!X)Q+I9O`ZhElQN94N@J1^jdnKnLzE;VzFbJ4N_MZ)WnLU0y}i%z`vS2Ww!) z@Kcf@4oj!piT-hNAA_N#9UiB_I^HtTy>=pPw=IwKBpGji*!#rGd{Mv6qwo>ZG0SSK zGcrn0DH}$$QbaP&t$=yxm_{%c`%qZ?4y$G*DU#nWM^r}%+r@v=%5mH+?B@!_yHj<4 z1I&9HTMEc)>;M1&24YJ`L;$J)rvRAYH*DJg000SaNLh0L01m_e01m_fl`9S#00007 zbV*G`2j>GD1PLJOh!}|g00byWL_t(o!?jjlXd87L|6JBK3l>nv^zA7-gkEM|;>;DggXw9mfii-?sBhcbqURG12R5eu1;kP>8=yJTgyO>1d- z7wT#*(742h?svQ7{^TO{3xVX9@1M{2|Cd1*#Bp4c5Ms$ANfJa+WbEp+WaN3isa5P? z8t^}N)>7fd<`x=F2ed#_sg$Xm9xLOoUN{c``03{qPP)(F(#0vH(-}(umo83W`MbLS zfb%c$^tovUqQ}a(Sa<*cIP=VKHVHw zn*n851B8$kZ$JL%Lwxq>C;0l#Eo4@Iha^d8pNKyuS3n3+Ylq5EaD;qoe-iRM-~8eG zyC@d(s;6V)Q7nD_1;XL5Wv&H5K>Y1DTjYYl2rj%bWjGN{Cttfp zyC_0hh@rp;9z8n1`octXd^&L%QNafi&LjgqOev%SKF`+T(hbu>SMiL zM=%tDBuOn1AcUY;$g4bdZw^~EFgSQrgi7@Y$aZO67lG~4-*B@m0DyI~wwIJG0DF6q zuGOp}KqEFpe8&Ue|BQgc=H18uV5*A3R27BEWOJ<3Hk`p z|9q74JP+ChWvPO_Jqd5k#W652V5v}+W!y|GVQ`ROi1@T!&|M1X6q|VQWz}dZm9n)9 z-n%icg2~^{THY5Yj67#q7Q;h6_`Lm)Du2Q4cB59S;e+>Yz~gbEBK-+xFQfZROvLc| zm1*3&_X}#Z8U#TA8g(2V9>V2vgX1`CZf=@KfQJ2z>C3o%=bMfTs-3JB&%5u$pR9Mj zB^^w=@tN5;zPh!9tJkg@E|GLPgSCenhDHMC{JL9_j&&_?ZB6uObAG~cblc6$#*tgi z=nhS){P|!6;c!^34Ox~U2m+e_R80@mnb|l1U~yp{l2p;Rp(u*jEmyF(FyFB+SCUBx zf&f{TRpTqkWJkHhg?a3jD-cD|ybU>y!|;#~fpdOcsHd;IhIBe(7-s5uEEd((57pIf z-0Ua?z~OPj(Gn_c{>^HD(r&p`j_PVRZaN2y7@uA{6-(of8xB)>Bl;JrqZ`fFzL^^U O0000 Date: Tue, 28 Mar 2023 03:25:18 -0400 Subject: [PATCH 16/60] Finally found the positronic brain sprites. Temp usage for now. --- .../Mobs/Species/IPC/organs.rsi/brain.png | Bin 265 -> 2290 bytes .../Mobs/Species/IPC/organs.rsi/meta.json | 26 +++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/organs.rsi/brain.png index da0a093fe15ce09395f4a51e0a0218c639b9b164..f69ff1aa3e4f25dfb29295e465efd853ac9dcfe3 100644 GIT binary patch literal 2290 zcmbW3c{JN=8pnTWNGw%cT30Qht>sd5s#;qUDT>-sOIu?Jmpcq~>7}hDl4wA>D)Q<$NcfU&w0*y-ap>&^Lf7Ky@v8| zQjps%2LOPAi?f55B;zGfCIgY2l$DZ&Tvs6_z@Jzr3?!k;V8A#;KJ$ugak*mlwo}*(} z)0NbS{Qa+OilONKWBzhAh7f^tNAeo+1|EkPuYxOE=2p z&Uulo($s6}#V~wOt=Gemw)9U+X4>Y7I_(!rV>$s6MEk?Op4q&UPhZrc4Cl29(1z+( zN>hc*(m^2dvg<^wkiDZY22;2N~(@M>^|yyOeIk-*Tazo4i`l68(WV zXzHEis^6I9%{R^rd%M26I;>{E$gkw0wdv^uzUOYnXo*yQwMmLjUX}-rc(;)IXqu90N_J4MptNM@idS7|8fV6+%qvFs&dt5)Z7W%;m+Z^yTF~w%+?L*fi>83TKWJ{qNR+qzIb|%eKlqrJus1YxKy0!X;{-u1`WyNv zZQoJeE9cLbdNF!pUR5`N zAXO|t&?yeORrG8`#5@j|$AX1VT^ zsmp7)?25cN^{f>8{qcRSAwD?>(l%(~Cd-11ekqe;pAiOTN~{Z?#% z(zwHlIz==rz`!_(0JGxAiUzi}t*~^g{M`?Vr z5dkYXdN_MI;sI_mu8kOUF79??_-0(T_%ol>mfG|9Nwfsafpq@{AyZ}D_sHT^3|4C0 zu8OxDQSZPI+9x;9LNnsg`yO?Mw#*oyXgwg+=;%R-kmbgMleu9~GkUW^HaoHZv~W|4 z)07%-%}^(;{^Cx3fgXCc(}plUXG7u(YU&-`nj)eK>$am@PAS)(ZOQXIjqDhY@F@@h zNjXi;=GV10*2sAaS>hO?=g7GJ1}I<>_KG2Adv^J<_Hr_n_+C&v8i&tW!s3yWui?=4 zT3B$Ipf%cmtQf31q<8>@F~~)&fn`|FVRn|KBH*oX0jl&N9D$F8BUB8(cb9LY`%mBb zdgsebwRqrr?Sx#83H=lT-$6oqw$x)rMZgLDE$mU@_)2uMv}G3|xj5T^4yR)ecO&6r z^B7yh%^!yA}U#ac23?lzk{e>h}?fcFSSSXwb?So|)o@PJ+`PG=Mui93?Y?!*G#>n1I8 z;EX4;iee6K{Q4@z^b@_hg3dG}+}~nD6Fz@1Stl=?fmwKUFZp9y=N`*5EBxjsC{b-( zp(06SeXKw?05=8I{J>fbU4R<;E>TDqnfD9S_e0ty>af{FeMe5~kr{K~u{oNwBC)&3 zqA^#KHE>ZE0hiE!e9H9Nc>~?&vF;@5=@f_3@QM@~%OLrL;gI4)2z-lpS|7EFhh6tK zjsrG8z-KOV0s7+*rYRo&RmA_(05;|4pb2vWq={FTy;Eq^tE|Qz0%XKFAb&XxHmn+g zz{}zL%(_-hU}6agK?MbG>gxk*I5imGnJBopS}|)@6MwKcM}P%*VK2a;mbnURdN9OO zfl%|eUG^;IAf#s@6izBru{-Z@UwI8YgIR~g0Pv$v-WZj_SBQ#tL%sICXW1V|*h!ta zd!{$AzGSl_$>HiDk3Y7>coB+vC@ooI!|@e^JU+XJpM0BUmf~k`MZs<(Z0_WPs|?W7 zy}psBI%+U2A8j{erzCp%sW@2Y;a!C1H(O?)O9x@3KE+!I?DkT69>)gJg#|d=@2Q-kq)v$?sbIGRgO=SLNo^8p qshhbEhEp{VUuFN|p?_j`OL2*6{i|P2T(aa71GqSPI6OTTeCc;=U2N9? delta 252 zcmV5s3mJiBL{Q4GJ0x0000DNk~Le0000W0000W2nGNE0CReJ^pPPKe*n8l zL_t(|ob8n{3dA4~MJKSgvD~BBqzhZ+OsT?l3yV$IYozo%CSTTIAps{b5}4o2;1vJq zsPmx85&!`Z00B4zFc7((sG;ZJXzrWK0E{ti%U6hh=A+g+3nUu==1QsEdJe?>?!bHe zQ1@zm9-oA@cB>Z!fO)C~VGZ@^Qui$f5DUA8aflqTTaYpYNVOI~SiiId0fc+}EC6{0 zXDb^3-)uY!QuU$$u}QUQ805_%rukujGb8{4AOH(5h);CI14lLh0000 Date: Tue, 28 Mar 2023 16:22:23 -0400 Subject: [PATCH 17/60] Fix posi brain sprite --- Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml b/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml index 9a2ae30ad9..7cef900e3a 100644 --- a/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml @@ -25,7 +25,6 @@ components: - type: Sprite state: brain - sprite: Mobs/Species/Human/organs.rsi - type: Organ - type: Input context: "ghost" From 05825b56de2c5d24416d2b4b459a23152579d986 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Wed, 29 Mar 2023 12:59:06 -0400 Subject: [PATCH 18/60] Fixed charger burn damage --- .../SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs index 0f3676566e..27e93a357d 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs @@ -90,7 +90,7 @@ private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconCha // If the given entity DOESN'T have a battery, burn the fucker. else if (burn && EntityManager.TryGetComponent(entity, out var damageComp) && - damageComp.DamageContainerID == "Organic") + damageComp.DamageContainerID == "Biological") { var damage = new DamageSpecifier(_prototypeManager.Index("Shock"), frameTime * chargerComp.ChargeMulti / 100); var damageDealt = _damageableSystem.TryChangeDamage(entity, damage, false, true, damageComp, chargerComp.Owner); From 0bed39398c301261496ff8d08531ee8ebd36c10c Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Thu, 30 Mar 2023 18:26:25 -0400 Subject: [PATCH 19/60] Gutted Holograms from the branch to break up the PRs. --- .../Holograms/HologramSystem.cs | 35 -- .../Holograms/Components/HoloDiskComponent.cs | 13 - .../Holograms/Systems/HologramServerSystem.cs | 349 ------------------ .../Holograms/Systems/HologramSystem.cs | 286 -------------- .../Components/HoloServerComponent.cs | 8 - .../Holograms/Components/HologramComponent.cs | 31 -- .../Components/HologramProjectorComponent.cs | 7 - .../Holograms/HologramEvents.cs | 68 ---- .../Holograms/Systems/SharedHologramSystem.cs | 188 ---------- .../Effects/Hologram/holo_off.ogg | Bin 8815 -> 0 bytes .../Effects/Hologram/holo_on.ogg | Bin 8956 -> 0 bytes .../en-US/SimpleStation14/holograms.ftl | 4 - .../Prototypes/Entities/Objects/Fun/toys.yml | 3 - .../Computers/base_structurecomputers.yml | 3 - .../Machines/wireless_surveillance_camera.yml | 1 - .../Wallmounts/surveillance_camera.yml | 1 - .../SimpleStation14/Body/Organs/ipc.yml | 6 +- .../Body/Prototypes/hologram.yml | 11 - .../SimpleStation14/Damage/modifier_sets.yml | 11 - .../Entities/Body/Prototypes/scutter.yml | 7 - .../Entities/Mobs/NPCs/pets.yml | 73 ---- .../Entities/Mobs/Player/hologram.yml | 267 -------------- .../Entities/Mobs/Player/ipc.yml | 7 +- .../Entities/Mobs/Player/silicon_base.yml | 4 +- .../Entities/Mobs/Player/silicon_ghost.yml | 128 ------- .../Machines/hologram_constructor.yml | 137 ------- .../scutter_inventory_template.yml | 11 - .../Mobs/Pets/corgi.rsi/holo_corgi.png | Bin 12178 -> 0 bytes .../Mobs/Pets/corgi.rsi/meta.json | 33 -- .../Mobs/Silicon/scutter.rsi/l_hand.png | Bin 654 -> 0 bytes .../Mobs/Silicon/scutter.rsi/meta.json | 31 -- .../Mobs/Silicon/scutter.rsi/r_hand.png | Bin 5373 -> 0 bytes .../Mobs/Silicon/scutter.rsi/scutter.png | Bin 9214 -> 0 bytes .../Mobs/Silicon/scutter.rsi/shell.png | Bin 942 -> 0 bytes 34 files changed, 8 insertions(+), 1715 deletions(-) delete mode 100644 Content.Client/SimpleStation14/Holograms/HologramSystem.cs delete mode 100644 Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs delete mode 100644 Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs delete mode 100644 Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs delete mode 100644 Content.Shared/SimpleStation14/Holograms/Components/HoloServerComponent.cs delete mode 100644 Content.Shared/SimpleStation14/Holograms/Components/HologramComponent.cs delete mode 100644 Content.Shared/SimpleStation14/Holograms/Components/HologramProjectorComponent.cs delete mode 100644 Content.Shared/SimpleStation14/Holograms/HologramEvents.cs delete mode 100644 Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs delete mode 100644 Resources/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg delete mode 100644 Resources/Audio/SimpleStation14/Effects/Hologram/holo_on.ogg delete mode 100644 Resources/Locale/en-US/SimpleStation14/holograms.ftl delete mode 100644 Resources/Prototypes/SimpleStation14/Body/Prototypes/hologram.yml delete mode 100644 Resources/Prototypes/SimpleStation14/Entities/Body/Prototypes/scutter.yml delete mode 100644 Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml delete mode 100644 Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml delete mode 100644 Resources/Prototypes/SimpleStation14/InventoryTemplates/scutter_inventory_template.yml delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Pets/corgi.rsi/holo_corgi.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Pets/corgi.rsi/meta.json delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/l_hand.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/meta.json delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/r_hand.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/scutter.png delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/shell.png diff --git a/Content.Client/SimpleStation14/Holograms/HologramSystem.cs b/Content.Client/SimpleStation14/Holograms/HologramSystem.cs deleted file mode 100644 index ff175a12ce..0000000000 --- a/Content.Client/SimpleStation14/Holograms/HologramSystem.cs +++ /dev/null @@ -1,35 +0,0 @@ -// using Content.Client.Gravity; -// using Content.Shared.Anomaly; -// using Content.Shared.Anomaly.Components; -// using Robust.Client.GameObjects; -// using Robust.Shared.Timing; -// using Content.Shared.SimpleStation14.Hologram; - -// namespace Content.Client.SimpleStation14.Hologram; - -// public sealed class HologramSystem : SharedHologramSystem -// { -// [Dependency] private readonly IGameTiming _timing = default!; -// [Dependency] private readonly FloatingVisualizerSystem _floating = default!; - -// /// -// public override void Initialize() -// { -// base.Initialize(); - -// SubscribeLocalEvent(OnStartup); -// SubscribeLocalEvent(OnAnimationComplete); -// } - -// private void OnStartup(EntityUid uid, HologramComponent component, ref ComponentStartup args) -// { -// _floating.FloatAnimation(uid, new Vector2(0f, 0.07f), "holofloat", 3); -// } - -// private void OnAnimationComplete(EntityUid uid, HologramComponent component, AnimationCompletedEvent args) -// { -// if (args.Key != "holofloat") -// return; -// _floating.FloatAnimation(uid, new Vector2(0, 0.15f), "holofloat", 3.5f); -// } -// } diff --git a/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs b/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs deleted file mode 100644 index 7adbedebf1..0000000000 --- a/Content.Server/SimpleStation14/Holograms/Components/HoloDiskComponent.cs +++ /dev/null @@ -1,13 +0,0 @@ -// using static Content.Server.SimpleStation14.Hologram.HologramSystem; - -namespace Content.Server.SimpleStation14.Hologram; - -[RegisterComponent] -public sealed class HologramDiskComponent : Component -{ - [ViewVariables] - public Mind.Mind? HoloMind = null; - - [DataField("active"), ViewVariables(VVAccess.ReadWrite)] - public bool Active = true; -} diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs deleted file mode 100644 index 7b1d058665..0000000000 --- a/Content.Server/SimpleStation14/Holograms/Systems/HologramServerSystem.cs +++ /dev/null @@ -1,349 +0,0 @@ -using System.Linq; -using Content.Server.Mind.Components; -using Content.Server.Cloning; -using Content.Server.Cloning.Components; -using Content.Server.Psionics; -using Content.Server.Speech.Components; -using Content.Server.StationEvents.Components; -using Content.Server.EUI; -using Content.Server.Humanoid; -using Content.Server.Ghost.Roles.Components; -using Content.Server.Jobs; -using Content.Server.Mind; -using Content.Server.Preferences.Managers; -using Content.Server.Power.Components; -using Content.Server.Administration.Commands; -using Content.Shared.Tag; -using Content.Shared.Popups; -using Content.Shared.SimpleStation14.Hologram; -using Content.Shared.Pulling; -using Content.Shared.Administration.Logs; -using Content.Shared.Database; -using Content.Shared.Speech; -using Content.Shared.Preferences; -using Content.Shared.Emoting; -using Content.Shared.Humanoid; -using Content.Shared.Mobs.Systems; -using Content.Shared.Interaction; -using Content.Shared.Inventory; -using Content.Shared.Interaction.Components; -using Content.Shared.Access.Components; -using Content.Shared.Clothing.Components; -using Content.Shared.Roles; -using Robust.Server.Player; -using Robust.Shared.Player; -using Robust.Shared.Containers; -using Robust.Shared.GameObjects.Components.Localization; -using Content.Shared.Movement.Systems; -using System.Threading.Tasks; - -namespace Content.Server.SimpleStation14.Hologram; - -public class HologramServerSystem : EntitySystem -{ - [Dependency] private readonly IEntityManager _entityManager = default!; - [Dependency] private readonly SharedTransformSystem _transform = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] protected readonly SharedPopupSystem Popup = default!; - [Dependency] private readonly SharedPullingSystem _pulling = default!; - [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; - [Dependency] private readonly IPlayerManager _playerManager = null!; - [Dependency] private readonly CloningSystem _cloningSystem = default!; - [Dependency] private readonly EuiManager _euiManager = null!; - [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!; - [Dependency] private readonly MobStateSystem _mobStateSystem = default!; - [Dependency] private readonly MindSystem _mind = default!; - [Dependency] private readonly TagSystem _tag = default!; - [Dependency] private readonly IServerPreferencesManager _prefs = default!; - [Dependency] private readonly TagSystem _tagSystem = default!; - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly InventorySystem _inventory = default!; - [Dependency] private readonly SharedMoverController _mover = default!; - - private const string DiskSlot = "holo_disk"; - public readonly Dictionary ClonesWaitingForMind = new(); - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnEntInserted); - SubscribeLocalEvent(OnEntRemoved); - SubscribeLocalEvent(OnAfterInteract); - SubscribeLocalEvent(OnPowerChanged); - } - - /// - /// Handles generating a hologram from an inserted disk - /// - private void OnEntInserted(EntityUid uid, HologramServerComponent component, EntInsertedIntoContainerMessage args) - { - if (args.Container.ID != DiskSlot || !_tagSystem.HasTag(args.Entity, "HoloDisk") || - (_entityManager.TryGetComponent(args.Entity, out var diskComp) && diskComp.HoloMind == null)) return; - - if (component.LinkedHologram != EntityUid.Invalid && _entityManager.EntityExists(component.LinkedHologram)) - { - RaiseLocalEvent(new HologramKillEvent(component.LinkedHologram.Value)); - } - - if (TryHoloGenerate(component.Owner, _entityManager.GetComponent(args.Entity).HoloMind!, component, out var holo)) - { - var holoComp = _entityManager.GetComponent(holo); - component.LinkedHologram = holo; - holoComp.LinkedServer = component.Owner; - } - } - - /// - /// Handles killing a hologram when a disk is removed - /// - private void OnEntRemoved(EntityUid uid, HologramServerComponent component, EntRemovedFromContainerMessage args) - { - if (args.Container.ID != DiskSlot || !_tagSystem.HasTag(args.Entity, "HoloDisk") || - (_entityManager.TryGetComponent(args.Entity, out var diskComp) && diskComp.HoloMind == null)) return; - - if (component.LinkedHologram != EntityUid.Invalid && _entityManager.EntityExists(component.LinkedHologram)) - { - RaiseLocalEvent(new HologramKillEvent(component.LinkedHologram.Value)); - } - } - - /// - /// Called when the server's power state changes - /// - /// The entity uid of the server - /// The HologramServerComponent - /// The PowerChangedEvent - private void OnPowerChanged(EntityUid uid, HologramServerComponent component, ref PowerChangedEvent args) - { - // If the server is no longer powered - if (!args.Powered && component.LinkedHologram != null && component.LinkedHologram != EntityUid.Invalid) - { - // If the hologram exists - if (component != null && _entityManager.EntityExists(component.LinkedHologram)) - { - // Kill the Holgram - RaiseLocalEvent(new HologramKillEvent(component.LinkedHologram.Value)); - } - } - // If the server is powered - else if (args.Powered && component.LinkedHologram == EntityUid.Invalid) - { - var serverContainer = _entityManager.GetComponent(component.Owner); - if (serverContainer.GetContainer(DiskSlot).ContainedEntities.Count <= 0) - { - return; // No disk in the server - } - var disk = serverContainer.GetContainer(DiskSlot).ContainedEntities.First(); - var diskData = _entityManager.GetComponent(disk).HoloMind; - - // If the hologram is generated successfully - if (diskData != null && TryHoloGenerate(component.Owner, diskData, component, out var holo)) - { - // Set the linked hologram to the generated hologram - var holoComp = _entityManager.GetComponent(holo); - component.LinkedHologram = holo; - holoComp.LinkedServer = component.Owner; - } - } - } - - public bool TryHoloGenerate(EntityUid uid, Mind.Mind mind, HologramServerComponent? holoServer, out EntityUid holo) - { - CloningSystem cloneSys = new(); - holo = EntityUid.Invalid; - - if (ClonesWaitingForMind.TryGetValue(mind, out var clone)) - { - if (EntityManager.EntityExists(clone) && - !_mobStateSystem.IsDead(clone) && - TryComp(clone, out var cloneMindComp) && - (cloneMindComp.Mind == null || cloneMindComp.Mind == mind)) - return false; // Mind already has clone - - ClonesWaitingForMind.Remove(mind); - } - - if (mind.OwnedEntity != null && (_mobStateSystem.IsAlive(mind.OwnedEntity.Value) || _mobStateSystem.IsCritical(mind.OwnedEntity.Value))) - return false; // Body controlled by mind is not dead - - // Yes, we still need to track down the client because we need to open the Eui - if (mind.UserId == null || !_playerManager.TryGetSessionById(mind.UserId.Value, out var client)) - return false; // If we can't track down the client, we can't offer transfer. That'd be quite bad. - - var pref = (HumanoidCharacterProfile) _prefs.GetPreferences(mind.UserId.Value).SelectedCharacter; - - if (pref == null) - return false; - - var mob = HoloFetchAndSpawn(holoServer!, pref); - - var cloneMindReturn = EntityManager.AddComponent(mob); - cloneMindReturn.Mind = mind; - ClonesWaitingForMind.Add(mind, mob); - TransferMindToClone(mind); - - if (mind.CurrentJob != null) - { - foreach (var special in mind.CurrentJob.Prototype.Special) - { - if (special is AddComponentSpecial) - special.AfterEquip(mob); - } - - // Get each access from the job prototype and add it to the mob - foreach (var access in mind.CurrentJob.Prototype.Access) - { - var accessComp = EntityManager.EnsureComponent(mob); - accessComp.Tags.Add(access); - } - - // Get the loadout from the job prototype and add it to the Hologram - // making each item unremovable and hardlight. - if (mind.CurrentJob.Prototype.StartingGear != null) - { - SetOutfitCommand.SetOutfit(mob, mind.CurrentJob.Prototype.StartingGear, _entityManager, (_, item) => - { - if (_entityManager.TryGetComponent(item, out var clothing)) - { - if (clothing.InSlot == "back" || clothing.InSlot == "pocket1" || clothing.InSlot == "pocket2" || - clothing.InSlot == "belt" || clothing.InSlot == "suitstorage" || clothing.InSlot == "id") - { - _entityManager.DeleteEntity(item); - return; - } - } - _tagSystem.AddTag(item, "Softlight"); - _entityManager.EnsureComponent(item); - }); - // HoloEquip(mob, mind.CurrentJob.Prototype); - } - } - - _adminLogger.Add(LogType.Unknown, LogImpact.Medium, - $"{ToPrettyString(mob):mob} was generated at {ToPrettyString((EntityUid) uid):entity}"); - - holo = mob; - return true; - } - - internal void TransferMindToClone(Mind.Mind mind) - { - if (!ClonesWaitingForMind.TryGetValue(mind, out var entity) || - !EntityManager.EntityExists(entity) || - !TryComp(entity, out var mindComp) || - mindComp.Mind != null) - return; - - mind.TransferTo(entity, ghostCheckOverride: true); - mind.UnVisit(); - ClonesWaitingForMind.Remove(mind); - } - - /// - /// Handles fetching the mob and any appearance stuff... - /// - private EntityUid HoloFetchAndSpawn(HologramServerComponent holoServer, HumanoidCharacterProfile pref) - { - - List sexes = new(); - var name = pref.Name; - var toSpawn = "MobHologramProjected"; - - var mob = Spawn(toSpawn, Transform(holoServer.Owner).MapPosition); - _entityManager.GetComponent(mob).AttachToGridOrMap(); - - ResetCamera(mob); - - _humanoidSystem.LoadProfile(mob, pref); - - MetaData(mob).EntityName = name; - var mind = EnsureComp(mob); - _mind.SetExamineInfo(mob, true, mind); - - var grammar = EnsureComp(mob); - grammar.ProperNoun = true; - grammar.Gender = Robust.Shared.Enums.Gender.Neuter; - Dirty(grammar); - - var meta = _entityManager.GetComponent(mob); - var popupAppearOther = Loc.GetString("system-hologram-phasing-appear-others", ("name", meta.EntityName)); - var popupAppearSelf = Loc.GetString("system-hologram-phasing-appear-self"); - - Popup.PopupEntity(popupAppearOther, mob, Filter.PvsExcept((EntityUid) mob), false, PopupType.Medium); - Popup.PopupEntity(popupAppearSelf, mob, mob, PopupType.Large); - _audio.PlayPvs("/Audio/SimpleStation14/Effects/Hologram/holo_on.ogg", mob); - - EnsureComp(mob); - EnsureComp(mob); - EnsureComp(mob); - RemComp(mob); - - _tag.AddTag(mob, "DoorBumpOpener"); - - return mob; - } - - private async void ResetCamera(EntityUid mob) - { - await Task.Delay(500); - - _mover.ResetCamera(mob); - } - - - /// - /// WiP for equipping unique items based on job. - /// -// private void HoloEquip(EntityUid mob, JobPrototype job) -// { -// // Check what job they are against a list, and output a hardcoded item for each. - - - - -// var mobTransform = EntityManager.GetComponent(mob); -// var mobPos = mobTransform.WorldPosition; - -// if (!_entityManager.TryGetComponent(mob, out var mobInv)) -// return; -// var mobHands = EntityManager.EnsureComponent(mob); - -// foreach (var item in job.StartingGear.Items) -// { -// var itemEnt = Spawn(item.Prototype, mobPos); -// _entityManager.GetComponent(itemEnt).AttachToGridOrMap(); - -// if (item.Slot == null) -// { -// mobInv.TryPutInHandOrAny(itemEnt, out var _); -// } -// else -// { -// mobInv.TryPutInSlot(itemEnt, item.Slot); -// } -// } -// } - - private void OnAfterInteract(EntityUid uid, HologramDiskComponent component, AfterInteractEvent args) - { - if (args.Target == null || !TryComp(args.Target, out var targetMind)) - return; - if (targetMind.Mind == null) - { - Popup.PopupEntity(Loc.GetString("system-hologram-disk-mind-none"), args.Target.Value, args.User); - return; - } - - component.HoloMind = targetMind.Mind; - Popup.PopupEntity(Loc.GetString("system-hologram-disk-mind-saved"), args.Target.Value, args.User); - } - - -// // List of jobs with hardcoded items for Holograms, like a Clown's horn. -// static readonly Dictionary HoloJobItems = new Dictionary -// { -// { "Clown", "BikeHorn" }, -// { "value2", "output2" }, -// { "value3", "output3" } -// }; -} diff --git a/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs b/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs deleted file mode 100644 index 7339f0f358..0000000000 --- a/Content.Server/SimpleStation14/Holograms/Systems/HologramSystem.cs +++ /dev/null @@ -1,286 +0,0 @@ -using Content.Server.SurveillanceCamera; -using Content.Server.GameTicking; -using Content.Server.Mind.Components; -using Content.Shared.Tag; -using Content.Shared.Popups; -using Content.Shared.Interaction.Helpers; -using Content.Shared.SimpleStation14.Hologram; -using Content.Shared.Actions; -using Content.Shared.Actions.ActionTypes; -using Content.Shared.Pulling; -using Content.Shared.Pulling.Components; -using Content.Shared.Administration.Logs; -using Content.Shared.Database; -using Robust.Server.Player; -using Robust.Shared.Player; -using Robust.Shared.Timing; -using Robust.Shared.Map; -using Robust.Shared.Prototypes; -using Content.Server.Cloning; -using Content.Server.Cloning.Components; - -using Content.Shared.Cloning; -using Content.Shared.Speech; -using Content.Shared.Preferences; -using Content.Shared.Emoting; -using Content.Server.Psionics; -using Content.Server.Speech.Components; -using Content.Server.StationEvents.Components; -using Content.Server.EUI; -using Content.Server.Humanoid; -using Content.Server.Ghost.Roles.Components; -using Content.Server.Jobs; -using Content.Server.Mind; -using Content.Server.Preferences.Managers; -using Content.Shared.Humanoid; -using Content.Shared.Mobs.Systems; -using Robust.Shared.GameObjects.Components.Localization; -using System.Linq; -using Robust.Shared.Utility; - -namespace Content.Server.SimpleStation14.Hologram; - -public class HologramSystem : EntitySystem -{ - [Dependency] private readonly IEntityManager _entityManager = default!; - [Dependency] private readonly SharedTransformSystem _transform = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] protected readonly SharedPopupSystem Popup = default!; - [Dependency] private readonly SharedPullingSystem _pulling = default!; - [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; - [Dependency] private readonly IPlayerManager _playerManager = null!; - [Dependency] private readonly CloningSystem _cloningSystem = default!; - [Dependency] private readonly EuiManager _euiManager = null!; - [Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!; - [Dependency] private readonly MobStateSystem _mobStateSystem = default!; - [Dependency] private readonly MindSystem _mind = default!; - [Dependency] private readonly TagSystem _tag = default!; - [Dependency] private readonly IServerPreferencesManager _prefs = default!; - - public readonly Dictionary ClonesWaitingForMind = new(); - - public override void Initialize() - { - base.Initialize(); - SubscribeAllEvent(HoloKill); - SubscribeAllEvent(HoloGetProjector); - SubscribeAllEvent(HoloProjectorTest); - // SubscribeLocalEvent(Startup); - // SubscribeLocalEvent(Shutdown); - // SubscribeLocalEvent(HoloTeleport); - } - - // private void Startup(EntityUid uid, HologramComponent component, ComponentStartup args) - // { - // var action = new WorldTargetAction(_prototypeManager.Index("ShadekinTeleport")); - // _actionsSystem.AddAction(uid, action, uid); - // } - - // private void Shutdown(EntityUid uid, HologramComponent component, ComponentShutdown args) - // { - // var action = new WorldTargetAction(_prototypeManager.Index("ShadekinTeleport")); - // _actionsSystem.RemoveAction(uid, action); - // } - - - // // Anything that needs to be regularly run, like handling exiting a projector's range - // public override void Update(float frameTime) - // { - // base.Update(frameTime); - - // foreach (var component in _entityManager.EntityQuery().ToList()) - // { - // var nearProj = HoloGetProjector(component); - // if (!nearProj.IsValid()) - // { - // if (component.Accumulator > 0) - // { - // component.Accumulator -= frameTime; - // continue; - // } - // RaiseLocalEvent(new HologramReturnEvent(component.Owner)); - // continue; - // } - // component.Accumulator = 0.24f; - // component.CurProjector = nearProj; - // } - // } - - /// - /// Tests if the given projector is valid. - /// - /// Event arguments. - public void HoloProjectorTest(HologramProjectorTestEvent args) - { - var curProjector = args.Projector; - if (curProjector == EntityUid.Invalid || !_entityManager.TryGetComponent(curProjector, out var _)) return; - if (_entityManager.TryGetComponent(curProjector, out var camComp) && !camComp.Active) return; - args.CanProject = true; - } - - /// - /// Tests for the nearest projector to the Hologram. - /// - /// Event arguments. - public void HoloGetProjector(HologramGetProjectorEvent args) - { - var uid = args.Hologram; - var component = _entityManager.GetComponent(uid); - var occlude = args.Occlude; - var range = args.Range; - - var xformQuery = GetEntityQuery(); - var transform = _entityManager.GetComponent(uid); - var playerPos = _transform.GetWorldPosition(transform, xformQuery); - var mapId = transform.MapID; - - // sort all entities in distance increasing order - var nearProjList = new SortedList(); - - foreach (var comp in _entityManager.EntityQuery()) - { - if (!xformQuery.TryGetComponent(comp.Owner, out var compXform) || compXform.MapID != mapId) - continue; - - var dist = (_transform.GetWorldPosition(compXform, xformQuery) - playerPos).LengthSquared; - nearProjList.TryAdd(dist, comp.Owner); - } - - foreach (var nearProj in nearProjList) - { - if (_entityManager.TryGetComponent(nearProj.Value, out var camComp) && !camComp.Active) continue; - if (occlude && !nearProj.Value.InRangeUnOccluded(uid, 18f)) continue; - args.Projector = nearProj.Value; - return; - } - return; - } - - /// - /// Tests for the nearest projector to the Hologram. - /// - /// Hologram's HologramComponent. - /// Should it check only for unoccluded and in range projectors? - /// The range it should check for projectors in, if occlude is true - /// Returns the UID of the projector, or invalid UID if no projectors are found. - public EntityUid HoloGetProjector(HologramComponent component, bool occlude = true, float range = 18f) - { - var xformQuery = GetEntityQuery(); - var uid = component.Owner; - var transform = _entityManager.GetComponent(uid); - var playerPos = _transform.GetWorldPosition(transform, xformQuery); - var mapId = transform.MapID; - - // sort all entities in distance increasing order - var nearProjList = new SortedList(); - - foreach (var comp in _entityManager.EntityQuery()) - { - if (!xformQuery.TryGetComponent(comp.Owner, out var compXform) || compXform.MapID != mapId) - continue; - - var dist = (_transform.GetWorldPosition(compXform, xformQuery) - playerPos).LengthSquared; - nearProjList.TryAdd(dist, comp.Owner); - } - - foreach (var nearProj in nearProjList) - { - if (_entityManager.TryGetComponent(nearProj.Value, out var camComp) && !camComp.Active) continue; - if (occlude && !nearProj.Value.InRangeUnOccluded(uid, 18f)) continue; - return nearProj.Value; - } - return EntityUid.Invalid; - } - - /// - /// Tests for the nearest projector to a set of coords. - /// - /// Coords to test from. - /// Map being tested on. - /// Should it check only for unoccluded and in range projectors? - /// The range it should check for projectors in, if occlude is true - /// Returns the UID of the projector, or invalid UID if no projectors are found. - public EntityUid HoloGetProjector(Vector2 coords, MapId mapId, bool occlude = true, float range = 18f) - { - var xformQuery = GetEntityQuery(); - - // sort all entities in distance increasing order - var nearProjList = new SortedList(); - - foreach (var comp in _entityManager.EntityQuery()) - { - if (!xformQuery.TryGetComponent(comp.Owner, out var compXform) || compXform.MapID != mapId) - continue; - - var dist = (_transform.GetWorldPosition(compXform, xformQuery) - coords).LengthSquared; - nearProjList.TryAdd(dist, comp.Owner); - } - - foreach (var nearProj in nearProjList) - { - if (_entityManager.TryGetComponent(nearProj.Value, out var camComp) && !camComp.Active) continue; - if (occlude && !nearProj.Value.InRangeUnOccluded(new MapCoordinates(coords, mapId), range)) continue; - return nearProj.Value; - } - return EntityUid.Invalid; - } - - /// - /// Kills a Hologram after playing the visual and auditory effects. - /// - /// Hologram's HologramComponent. - public void HoloKill(HologramKillEvent args) - { - var uid = args.Uid; - var component = _entityManager.GetComponent(uid); - var meta = _entityManager.GetComponent(uid); - var holoPos = _entityManager.GetComponent(uid).Coordinates; - EntityUid? body = EntityUid.Invalid; - Mind.Mind? mind = null; - - var popupAppearOther = Loc.GetString("system-hologram-phasing-appear-others", ("name", meta.EntityName)); - var popupAppearSelf = Loc.GetString("system-hologram-phasing-appear-self"); - var popupDisappearOther = Loc.GetString("system-hologram-phasing-disappear-others", ("name", meta.EntityName)); - var popupDeathSelf = Loc.GetString("system-hologram-phasing-death-self"); - - if (_entityManager.TryGetComponent(uid, out var mindComp) && mindComp.Mind != null) - { - body = mindComp.Mind.OwnedEntity; - mind = mindComp.Mind; - EntitySystem.Get().OnGhostAttempt(mindComp.Mind, false); - } - - _audio.Play(filename: "/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg", playerFilter: Filter.Pvs(uid), coordinates: holoPos, false); - Popup.PopupCoordinates(popupDisappearOther, holoPos, Filter.PvsExcept(uid), false, PopupType.MediumCaution); - Popup.PopupCoordinates(popupDeathSelf, holoPos, uid, PopupType.LargeCaution); - if (component.LinkedServer != EntityUid.Invalid) - { - if (_entityManager.TryGetComponent(component.LinkedServer!.Value, out var serverComp)) - serverComp.LinkedHologram = EntityUid.Invalid; - component.LinkedServer = EntityUid.Invalid; - } - - _entityManager.DeleteEntity(uid); - - _adminLogger.Add(LogType.Unknown, LogImpact.Medium, $"{ToPrettyString(uid):mob} was disabled due to lack of projectors"); - } - - // private void HoloTeleport(HoloTeleportEvent args) - // { - // if (args.Handled) return; - - // if HoloGetProjector(args.Target, args. ) - // var transform = Transform(args.Performer); - // if (transform.MapID != args.Target.GetMapId(EntityManager)) return; - - // _transformSystem.SetCoordinates(args.Performer, args.Target); - // transform.AttachToGridOrMap(); - - // _audio.PlayPvs(args.BlinkSound, args.Performer, AudioParams.Default.WithVolume(args.BlinkVolume)); - - // _staminaSystem.TakeStaminaDamage(args.Performer, 35); - - // args.Handled = true; - // } - // } -} diff --git a/Content.Shared/SimpleStation14/Holograms/Components/HoloServerComponent.cs b/Content.Shared/SimpleStation14/Holograms/Components/HoloServerComponent.cs deleted file mode 100644 index 14684df47b..0000000000 --- a/Content.Shared/SimpleStation14/Holograms/Components/HoloServerComponent.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Content.Shared.SimpleStation14.Hologram; - -[RegisterComponent] -public sealed class HologramServerComponent : Component -{ - [ViewVariables] - public EntityUid? LinkedHologram; -} diff --git a/Content.Shared/SimpleStation14/Holograms/Components/HologramComponent.cs b/Content.Shared/SimpleStation14/Holograms/Components/HologramComponent.cs deleted file mode 100644 index d5dcd5a320..0000000000 --- a/Content.Shared/SimpleStation14/Holograms/Components/HologramComponent.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Content.Shared.SimpleStation14.Hologram; - -[RegisterComponent] -public sealed class HologramComponent : Component -{ - // // Custom struct that specifies the type of hologram. - // // First variable is the HoloType enum, second is whether or not it's hardlight. - // // Defaults to False. - // [DataField("holoData"), ViewVariables] - // public HoloData HoloData = new HoloData(HoloType.Projected, false); - - [DataField("holoType")] - public HoloType HoloType = HoloType.Projected; - - [DataField("isHardlight")] - public bool IsHardlight = false; - - // Current server the Hologram is generated by. - // Will be the Lightbee if it's a Lightbee Hologram. - [ViewVariables] - public EntityUid? LinkedServer; - - // The current projector the Hologram is connected to. - // Will be the Lightbee if it's a Lightbee Hologram. - [ViewVariables] - public EntityUid? CurProjector; - - // Counter before returning the Holo, so you can get through doors. - [DataField("accumulator")] - public float Accumulator = 0.5f; -} diff --git a/Content.Shared/SimpleStation14/Holograms/Components/HologramProjectorComponent.cs b/Content.Shared/SimpleStation14/Holograms/Components/HologramProjectorComponent.cs deleted file mode 100644 index b63e4a634f..0000000000 --- a/Content.Shared/SimpleStation14/Holograms/Components/HologramProjectorComponent.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Content.Shared.SimpleStation14.Hologram; - -[RegisterComponent] -public sealed class HologramProjectorComponent : Component -{ - -} diff --git a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs b/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs deleted file mode 100644 index c4c083dc3b..0000000000 --- a/Content.Shared/SimpleStation14/Holograms/HologramEvents.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Content.Shared.SimpleStation14.Hologram; -using Robust.Shared.Serialization; - -namespace Content.Shared.SimpleStation14.Hologram; - -/// -/// Raised when a hologram is being returned to its last visited projector. -/// -[Serializable, NetSerializable] -public sealed class HologramReturnEvent : EntityEventArgs -{ - public EntityUid Uid; - - public HologramReturnEvent(EntityUid uid) - { - Uid = uid; - } -} - -/// -/// Raised when a hologram is being killed and removed from the game world. -/// -[Serializable, NetSerializable] -public sealed class HologramKillEvent : EntityEventArgs -{ - public EntityUid Uid; - - public HologramKillEvent(EntityUid uid) - { - Uid = uid; - } -} - -/// -/// Raised to return a bool if a given projector is valid for a given hologram. -/// -[Serializable, NetSerializable] -public sealed class HologramProjectorTestEvent : EntityEventArgs -{ - public EntityUid Hologram; - public EntityUid Projector; - public bool CanProject = false; - - public HologramProjectorTestEvent(EntityUid hologram, EntityUid projector) - { - Hologram = hologram; - Projector = projector; - } -} - -/// -/// Raised to return the nearest projector to a given hologram. -/// -[Serializable, NetSerializable] -public sealed class HologramGetProjectorEvent : EntityEventArgs -{ - public EntityUid Hologram; - public bool Occlude; - public float Range; - public EntityUid Projector; - - public HologramGetProjectorEvent(EntityUid hologram, bool occlude = true, float range = 18f) - { - Hologram = hologram; - Occlude = occlude; - Range = range; - } -} diff --git a/Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs b/Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs deleted file mode 100644 index c4eaf071e9..0000000000 --- a/Content.Shared/SimpleStation14/Holograms/Systems/SharedHologramSystem.cs +++ /dev/null @@ -1,188 +0,0 @@ -using Content.Shared.Interaction.Events; -using Content.Shared.Interaction.Components; -using Content.Shared.Damage; -using Content.Shared.Item; -using Content.Shared.Tag; -using Content.Shared.Interaction.Helpers; -using Content.Shared.Popups; -using Robust.Shared.Player; -using Robust.Shared.Timing; -using Robust.Shared.Serialization; -using Robust.Shared.Containers; -using Content.Shared.Computer; -using Content.Shared.Pulling.Components; -using Content.Shared.Administration.Logs; -using Content.Shared.Database; -using Content.Shared.Pulling; -using System.Linq; - -namespace Content.Shared.SimpleStation14.Hologram; - -public class SharedHologramSystem : EntitySystem -{ - [Dependency] private readonly TagSystem _tagSystem = default!; - [Dependency] private readonly IEntityManager _entityManager = default!; - [Dependency] private readonly SharedTransformSystem _transform = default!; - [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] protected readonly SharedPopupSystem Popup = default!; - [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; - [Dependency] private readonly SharedPullingSystem _pulling = default!; - - public override void Initialize() - { - SubscribeLocalEvent(OnHoloInteractionAttempt); - SubscribeLocalEvent(OnInteractionAttempt); - SubscribeAllEvent(HoloReturn); - } - - // Stops the Hologram from interacting with anything they shouldn't. - private void OnHoloInteractionAttempt(EntityUid uid, HologramComponent component, InteractionAttemptEvent args) - { - if (args.Target == null) - return; - - if (HasComp(args.Target) && !HasComp(args.Target) - && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight", "Softlight")) args.Cancel(); - } - - // Stops everyone else from interacting with the Holograms. - private void OnInteractionAttempt(InteractionAttemptEvent args) - { - if (args.Target == null || _tagSystem.HasAnyTag(args.Uid, "Hardlight", "Softlight") || - _entityManager.TryGetComponent(args.Uid, out var _)) - return; - - if (_tagSystem.HasAnyTag(args.Target.Value, "Softlight") && !_tagSystem.HasAnyTag(args.Target.Value, "Hardlight")){ - args.Cancel(); - - // Send a popup to the player about the interaction, and play a sound. - var meta = _entityManager.GetComponent(args.Target.Value); - var popup = Loc.GetString("system-hologram-light-interaction-fail", ("item", meta.EntityName)); - var sound = "/Audio/SimpleStation14/Effects/Hologram/holo_on.ogg"; - Popup.PopupEntity(popup, args.Target.Value, Filter.Entities(args.Uid), false); - _audio.Play(sound, Filter.Entities(args.Uid), args.Uid, false); - } - } - - // Anything that needs to be regularly run, like handling exiting a projector's range - public override void Update(float frameTime) - { - base.Update(frameTime); - - foreach (var component in _entityManager.EntityQuery().ToList()) - { - var getProj = new HologramGetProjectorEvent(component.Owner); - RaiseLocalEvent(getProj); - var nearProj = getProj.Projector; - if (!nearProj.IsValid()) - { - if (component.Accumulator > 0) - { - component.Accumulator -= frameTime; - continue; - } - RaiseLocalEvent(new HologramReturnEvent(component.Owner)); - continue; - } - component.Accumulator = 0.24f; - component.CurProjector = nearProj; - } - } - - /// - /// Handles returning a Hologram to their last visited projector, - /// then to the nearest, finally killing them if none are found. - /// - /// Hologram's HologramComponent. - public void HoloReturn(HologramReturnEvent args) - { - var uid = args.Uid; - var component = _entityManager.GetComponent(uid); - var meta = _entityManager.GetComponent(uid); - var holoPos = _entityManager.GetComponent(uid).Coordinates; - - var popupAppearOther = Loc.GetString("system-hologram-phasing-appear-others", ("name", meta.EntityName)); - var popupAppearSelf = Loc.GetString("system-hologram-phasing-appear-self"); - var popupDisappearOther = Loc.GetString("system-hologram-phasing-disappear-others", ("name", meta.EntityName)); - var popupDeathSelf = Loc.GetString("system-hologram-phasing-death-self"); - - // If the Hologram's last projector isn't valid, try to find a new one. - if (component.CurProjector == null) - { - return; - } - - var curProjCheck = new HologramProjectorTestEvent(uid, component.CurProjector.Value); - RaiseLocalEvent(curProjCheck); - if (!curProjCheck.CanProject) - { - var getProj = new HologramGetProjectorEvent(uid, false); - RaiseLocalEvent(getProj); - component.CurProjector = getProj.Projector; - } - - // If the Hologram's last projector is still invalid, kill them. - if (component.CurProjector == EntityUid.Invalid) - { - // if (_timing.InPrediction) return; - - RaiseLocalEvent(new HologramKillEvent(uid)); - return; - } - - _entityManager.TryGetComponent(component.CurProjector, out var transfComp); - Popup.PopupCoordinates(popupDisappearOther, holoPos, Filter.PvsExcept(uid), false, PopupType.MediumCaution); - _audio.Play(filename: "/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg", playerFilter: Filter.Pvs(uid), coordinates: holoPos, false); - - // Preapre to move holo - if (TryComp(uid, out var pullable) && pullable.BeingPulled) _pulling.TryStopPull(pullable); - if (TryComp(uid, out var pulling) && pulling.Pulling != null && - TryComp(pulling.Pulling.Value, out var subjectPulling)) _pulling.TryStopPull(subjectPulling); - - // Move holo - Transform(uid).Coordinates = _entityManager.GetComponent((EntityUid) component.CurProjector).Coordinates; - - Popup.PopupEntity(popupAppearOther, uid, Filter.PvsExcept((EntityUid) uid), false, PopupType.Medium); - Popup.PopupEntity(popupAppearSelf, uid, uid, PopupType.Large); - _audio.PlayPvs("/Audio/SimpleStation14/Effects/Hologram/holo_on.ogg", uid); - - _adminLogger.Add(LogType.Unknown, LogImpact.Low, - $"{ToPrettyString(uid):mob} was returned to projector {ToPrettyString((EntityUid) component.CurProjector):entity}"); - } -} - -public enum HoloType -{ - Projected, - Lightbee -} - -// public struct HoloData -// { -// [DataField("type")] -// public HoloType Type { get; set; } - -// [DataField("isHardlight")] -// public bool IsHardlight { get; set; } - -// public HoloData(HoloType type, bool isHardlight = false) -// { -// Type = type; -// IsHardlight = isHardlight; -// } -// } - - -// [Serializable, NetSerializable] -// public sealed class HoloTeleportEvent : EntityEventArgs -// { -// public readonly EntityUid Uid; -// public readonly List Lights; - -// public ShadekinDarkenEvent(EntityUid uid, List lights) -// { -// Uid = uid; -// Lights = lights; -// } -// } diff --git a/Resources/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg b/Resources/Audio/SimpleStation14/Effects/Hologram/holo_off.ogg deleted file mode 100644 index d764f43bb70207f4a780580ffaad1a3a05a48309..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8815 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%0DA5iNaUWE$2`yfFit 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 PS|M2fW#Q8sLFj(~Gh>a% diff --git a/Resources/Locale/en-US/SimpleStation14/holograms.ftl b/Resources/Locale/en-US/SimpleStation14/holograms.ftl deleted file mode 100644 index bfc06b6ded..0000000000 --- a/Resources/Locale/en-US/SimpleStation14/holograms.ftl +++ /dev/null @@ -1,4 +0,0 @@ -system-hologram-phasing-appear-self = You materialize into being! -system-hologram-phasing-appear-others = {$name} materializes into being! -system-hologram-phasing-disappear-others = {$name} dematerializes in a fizz! -system-hologram-phasing-death-self = You faze out of being! diff --git a/Resources/Prototypes/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/Entities/Objects/Fun/toys.yml index ec540233f5..3ba5a0addd 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/toys.yml @@ -61,9 +61,6 @@ energy: 2 - type: RgbLightController layers: [ 0 ] - - type: Tag - tags: - - Hardlight - type: entity parent: BasePlushie diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml index 7722365bd5..890e863e8c 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/base_structurecomputers.yml @@ -58,6 +58,3 @@ ents: [] - type: DynamicPrice price: 400 - - type: Tag - tags: - - Hardlight diff --git a/Resources/Prototypes/Entities/Structures/Machines/wireless_surveillance_camera.yml b/Resources/Prototypes/Entities/Structures/Machines/wireless_surveillance_camera.yml index 936ff1e2ac..3dd35e53ca 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/wireless_surveillance_camera.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/wireless_surveillance_camera.yml @@ -5,7 +5,6 @@ name: wireless camera description: A camera. It's watching you. Kinda. components: - - type: HologramProjector - type: InteractionOutline - type: Eye - type: WirelessNetworkConnection diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/surveillance_camera.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/surveillance_camera.yml index 70fdfb5bac..4773a59965 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/surveillance_camera.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/surveillance_camera.yml @@ -4,7 +4,6 @@ name: camera description: A surveillance camera. It's watching you. Kinda. components: - - type: HologramProjector - type: Clickable - type: InteractionOutline - type: Construction diff --git a/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml b/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml index 7cef900e3a..d44ed39fc7 100644 --- a/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Body/Organs/ipc.yml @@ -7,9 +7,9 @@ netsync: false sprite: SimpleStation14/Mobs/Species/IPC/organs.rsi - type: Organ - - type: Food - - type: Extractable - grindableSolutionName: organ + # - type: Food + # - type: Extractable + # grindableSolutionName: organ - type: SolutionContainerManager solutions: organ: diff --git a/Resources/Prototypes/SimpleStation14/Body/Prototypes/hologram.yml b/Resources/Prototypes/SimpleStation14/Body/Prototypes/hologram.yml deleted file mode 100644 index f71dcadf5e..0000000000 --- a/Resources/Prototypes/SimpleStation14/Body/Prototypes/hologram.yml +++ /dev/null @@ -1,11 +0,0 @@ -- type: body - id: Hologram - name: "hologram" - root: hand 1 - slots: - hand 1: - part: LeftArmBorg - connections: - - hand 2 - hand 2: - part: RightArmBorg diff --git a/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml b/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml index b39bbf2417..500d55549e 100644 --- a/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml +++ b/Resources/Prototypes/SimpleStation14/Damage/modifier_sets.yml @@ -1,14 +1,3 @@ -- type: damageModifierSet - id: Hardlight - coefficients: - Blunt: 1.6 - Slash: 1.0 - Piercing: 0.7 - Shock: 1.2 - Heat: 1.35 - flatReductions: - Blunt: 5 - - type: damageModifierSet id: BloodlossIPC coefficients: diff --git a/Resources/Prototypes/SimpleStation14/Entities/Body/Prototypes/scutter.yml b/Resources/Prototypes/SimpleStation14/Entities/Body/Prototypes/scutter.yml deleted file mode 100644 index 123b364be0..0000000000 --- a/Resources/Prototypes/SimpleStation14/Entities/Body/Prototypes/scutter.yml +++ /dev/null @@ -1,7 +0,0 @@ -- type: body - id: Scutter - name: "scutter" - root: hand 1 - slots: - hand 1: - part: LeftArmBorg diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml index 7da6a96468..6591b441e3 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/NPCs/pets.yml @@ -68,76 +68,3 @@ attributes: proper: true gender: male - -- type: entity - name: holo corgi - description: "A hologramatic projection of a corgi, computed by the AI and rendered by the station's cameras." - id: MobCorgiHolo - suffix: AI - components: - - type: LagCompensation - - type: Tag - tags: - - DoorBumpOpener - - type: InputMover - - type: MobMover - - type: HTN - rootTask: SimpleHostileCompound - - type: Input - context: "human" - - type: Faction - factions: - - Pet - - type: MovementSpeedModifier - baseWalkSpeed : 4.5 - baseSprintSpeed : 3 - - type: Sprite - noRot: true - drawdepth: Mobs - sprite: SimpleStation14/Mobs/Pets/corgi.rsi - layers: - - map: ["enum.DamageStateVisualLayers.Base"] - state: holo_corgi - netsync: false - - type: Clickable - - type: InteractionOutline - - type: Physics - bodyType: KinematicController # Same for all inheritors - - type: Fixtures - fixtures: - - shape: - # Circles, cuz rotation of rectangles looks very bad - !type:PhysShapeCircle - radius: 0.35 - density: 50 - mask: - - MobMask - layer: - - MobLayer - - type: MobState - - type: Body - prototype: Animal - - type: Examiner - - type: Appearance - - type: RotationVisuals - - type: Actions - - type: DoAfter - - type: Polymorphable - - type: StandingState - - type: Alerts - - type: FloatingVisuals - - type: NoSlip - - type: TypingIndicator - proto: holo - - type: ReplacementAccent - accent: dog - - type: InteractionPopup - interactSuccessString: hugging-success-hologram-others - interactSuccessSound: - path: /Audio/SimpleStation14/Effects/Hologram/holo_on.ogg - - type: Grammar - attributes: - gender: epicene - - type: DogVision - - type: RandomBark - - type: Hologram diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml deleted file mode 100644 index 6c6c4044c0..0000000000 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/hologram.yml +++ /dev/null @@ -1,267 +0,0 @@ -- type: entity - save: false - abstract: true - id: PlayerHologramBase - components: - # - type: Reactive - # groups: - # Acidic: [Touch] - - type: Input - context: "human" - - type: InputMover - - type: MobMover - # - type: DamageOnHighSpeedImpact - # damage: - # types: - # Blunt: 5 - # soundHit: - # path: /Audio/Effects/hit_kick.ogg - - type: Clickable - # - type: Damageable - # damageContainer: Inorganic - # - type: Bloodstream - # bloodReagent: MotorOil - # bloodlossDamage: - # types: - # Bloodloss: - # 1 - # bloodlossHealDamage: - # types: - # Bloodloss: - # -0.25 - - type: InteractionOutline - - type: Sprite - netsync: false - noRot: true - drawdepth: Mobs - layers: - - map: ["enum.HumanoidVisualLayers.Chest"] - - map: ["enum.HumanoidVisualLayers.Head"] - - map: ["enum.HumanoidVisualLayers.Snout"] - - map: ["enum.HumanoidVisualLayers.Eyes"] - - map: ["enum.HumanoidVisualLayers.RArm"] - - map: ["enum.HumanoidVisualLayers.LArm"] - - map: ["enum.HumanoidVisualLayers.RLeg"] - - map: ["enum.HumanoidVisualLayers.LLeg"] - - shader: StencilClear - sprite: Mobs/Species/Human/parts.rsi - # sprite refactor when - state: l_leg - - shader: StencilMask - map: ["enum.HumanoidVisualLayers.StencilMask"] - sprite: Mobs/Customization/masking_helpers.rsi - state: female_full - visible: false - - map: ["enum.HumanoidVisualLayers.LFoot"] - - map: ["enum.HumanoidVisualLayers.RFoot"] - - map: ["socks"] - - map: ["underpants"] - - map: ["undershirt"] - - map: ["jumpsuit"] - - map: ["enum.HumanoidVisualLayers.LHand"] - - map: ["enum.HumanoidVisualLayers.RHand"] - - map: ["enum.HumanoidVisualLayers.Handcuffs"] - color: "#ffffff" - sprite: Objects/Misc/handcuffs.rsi - state: body-overlay-2 - visible: false - - map: ["id"] - - map: ["gloves"] - - map: ["shoes"] - - map: ["ears"] - - map: ["outerClothing"] - - map: ["eyes"] - - map: ["belt"] - - map: ["neck"] - - map: ["back"] - - map: ["enum.HumanoidVisualLayers.FacialHair"] - - map: ["enum.HumanoidVisualLayers.Hair"] - - map: ["enum.HumanoidVisualLayers.HeadSide"] - - map: ["enum.HumanoidVisualLayers.HeadTop"] - - map: ["mask"] - - map: ["head"] - - map: ["pocket1"] - - map: ["pocket2"] - - map: ["enum.HumanoidVisualLayers.Tail"] - - map: ["enum.HumanoidVisualLayers.Wings"] - - type: HumanoidAppearance - species: Human - # - type: Body - # prototype: Human - # requiredLegs: 2 - - type: Physics - bodyType: KinematicController - - type: Fixtures - fixtures: - - shape: - !type:PhysShapeCircle - radius: 0.35 - density: 25 - mask: - - FlyingMobMask - layer: - - FlyingMobLayer - - type: MovementSpeedModifier - baseWalkSpeed : 5 - baseSprintSpeed : 3.5 - - type: MovementIgnoreGravity - - type: Hands - showInHands: false - - type: Body - prototype: Hologram - - type: DoAfter - # - type: Pullable - - type: Examiner - # - type: Puller - # - type: Recyclable - # safe: false - - type: StandingState - - type: Alerts - - type: Tag - tags: - - DoorBumpOpener - - ShoesRequiredStepTriggerImmune - - type: NoSlip - - type: TypingIndicator - proto: holo - - type: RotationVisuals - # - type: FloatingVisuals - - type: Speech - speechSounds: Tenor - - type: Vocal - sounds: - Male: MaleHuman - Female: FemaleHuman - Unsexed: MaleHuman - - type: Emoting - - type: BodyEmotes - soundsId: GeneralBodyEmotes - - type: Grammar - attributes: - proper: true - - type: Hologram - - type: AnimationPlayer - - type: Mind - showExamineInfo: true - - type: Inventory - - type: Actions - - type: Eye - - type: Access - -- type: entity - save: false - name: Urist McLight - suffix: Projected - parent: PlayerHologramBase - id: MobHologramProjected - components: - - type: Hologram - holoType: HoloType.Projected - isHardLight: false - - type: Stealth - lastVisibility: 0.80 - - type: InteractionPopup - successChance: 1 - interactSuccessString: hugging-success-hologram - # interactSuccessSound: /Audio/Effects/thudswoosh.ogg - messagePerceivedByOthers: hugging-success-hologram-others - - type: Faction - factions: - - NanoTrasen - - type: PointLight - radius: 1.0 - softness: 1.4 - color: "#00FFFF" - energy: 3 - -- type: entity - save: false - name: Urist McLight - suffix: Lightbee - parent: PlayerHologramBase - id: MobHologramLightbee - components: - - type: Hologram - # holoData: !HoloData - # Type: Lightbee - # IsHardLight: false - - type: Fixtures - fixtures: - - shape: - !type:PhysShapeCircle - radius: 0.05 - density: 25 - mask: - - MobMask - layer: - - MobLayer - - type: Damageable - damageContainer: Inorganic - damageModifierSet: FlimsyMetallic - - type: Stealth - lastVisibility: 0.85 - - type: InteractionPopup - successChance: 1 - interactSuccessString: hugging-success-hologram - # interactSuccessSound: /Audio/Effects/thudswoosh.ogg - messagePerceivedByOthers: hugging-success-hologram-others - - type: CameraRecoil - - type: Faction - factions: - - NanoTrasen - - type: PointLight - radius: 1.5 - softness: 0.8 - color: "#00FFFF" - energy: 4 - -- type: entity - save: false - name: Urist McLight - suffix: Hardlight - parent: PlayerHologramBase - id: MobHologramHardlight - components: - - type: Hologram - # holoData: - # Type: HoloType.Lightbee - # IsHardLight: true - - type: Fixtures - fixtures: - - shape: - !type:PhysShapeCircle - radius: 0.35 - density: 25 - mask: - - MobMask - layer: - - MobLayer - - type: Damageable - damageContainer: Inorganic - damageModifierSet: Hardlight - - type: DamageOnHighSpeedImpact - damage: - types: - Blunt: 6 # To get past the 5 damage threshold - soundHit: - path: /Audio/Effects/hit_kick.ogg - - type: Pullable - - type: Puller - - type: CombatMode - disarm: null - - type: Stealth - lastVisibility: 0.90 - - type: InteractionPopup - successChance: 1 - interactSuccessString: hugging-success-hologram - # interactSuccessSound: /Audio/Effects/thudswoosh.ogg - messagePerceivedByOthers: hugging-success-hologram-others - - type: CameraRecoil - - type: Faction - factions: - - NanoTrasen - - type: PointLight - radius: 0.8 - softness: 0.4 - color: "#00FFFF" - energy: 5 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml index 2928930f1a..966924d2d2 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -11,11 +11,10 @@ - type: Silicon entityType: enum.SiliconType.Player batteryPowered: true - drainRateMulti: 50 - chargeRateMulti: 50 - chargeStateThresholdMid: 0.70 + drainRateMulti: 5 + chargeStateThresholdMid: 0.80 chargeStateThresholdLow: 0.35 - chargeStateThresholdCritical: 0.15 + chargeStateThresholdCritical: 0.10 critWhenDead: true speedModifierThresholds: 0: 1 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 64670ecb2b..24804aab6d 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -55,9 +55,7 @@ - type: Body prototype: Drone - type: DoAfter - - type: Pullable - type: Examiner - - type: Puller - type: Recyclable safe: false - type: StandingState @@ -248,6 +246,8 @@ - type: MobPrice price: 1500 # Kidnapping a living person and selling them for cred is a good move. deathPenalty: 0.01 # However they really ought to be living and intact, otherwise they're worth 100x less. + - type: Pullable + - type: Puller # Things that likely need to change, taken from human. - type: Barotrauma diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_ghost.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_ghost.yml index fcfda88d95..77bfe9e2c4 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_ghost.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_ghost.yml @@ -154,131 +154,3 @@ channels: - Binary -- type: entity - id: Scutter - name: scutter - description: "Lacking fine motor skills and often the ability to listen to directions, it's the most inconsistent hand a Hologram could ask for." - parent: PlayerSiliconGhostBase - components: - - type: Eye - - type: Body - prototype: Scutter - - type: Inventory - templateId: scutter - - type: Strippable - - type: UserInterface - interfaces: - - key: enum.StrippingUiKey.Key - type: StrippableBoundUserInterface - - key: enum.LawsUiKey.Key - type: LawsBoundUserInterface - - type: GhostTakeoverAvailable - name: Scutter - description: Maintain the station. Ignore other beings except drones. - rules: | - You are bound by these laws both in-game and out-of-character: - 1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. - 2. You may not harm any being, regardless of intent or circumstance. - 3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. - - type: Laws - canState: false - laws: - - You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone. - - You may not harm any being, regardless of intent or circumstance. - - Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals. - - You may accept orders received via the binary channel, regardless of the nature of the being issuing them, so long as they do not conflict with Law Two or Law Three. - - type: MovementSpeedModifier - baseWalkSpeed : 4 - baseSprintSpeed : 4 - - type: MobState - allowedStates: - - Alive - - Dead - - type: MobThresholds - thresholds: - 0: Alive - 60: Dead - - type: Flashable - - type: NoSlip - - type: StatusEffects - allowed: - - Stun - - KnockedDown - - SlowedDown - - type: SlowOnDamage - speedModifierThresholds: - 30: 0.7 - 50: 0.5 - - type: Temperature - heatDamageThreshold: 5000 - currentTemperature: 310.15 - specificHeat: 42 - heatDamage: - types: - Heat : 1 #per second, scales with temperature & other constants - - type: Sprite - drawdepth: SmallMobs - netsync: false - layers: - - state: scutter - sprite: SimpleStation14/Mobs/Silicon/scutter.rsi - - type: Fixtures - fixtures: - - shape: - !type:PhysShapeCircle - radius: 0.25 - density: 50 - mask: - - SmallMobMask - layer: - - SmallMobLayer - # - type: Appearance - # visuals: - # - type: GenericEnumVisualizer - # key: enum.DroneVisuals.Status - # layer: 0 - # states: - # enum.DroneStatus.Off: shell - # enum.DroneStatus.On: scutter - - type: ReplacementAccent - accent: silicon - - type: Repairable - fuelcost: 15 - doAfterDelay: 5 - - type: Actions - # - type: UnpoweredFlashlight - # toggleAction: - # name: action-name-toggle-light - # description: action-description-toggle-light - # icon: { sprite: Objects/Tools/flashlight.rsi, state: flashlight } - # iconOn: Objects/Tools/flashlight.rsi/flashlight-on.png - # event: !type:ToggleActionEvent - # - type: PointLight - # enabled: false - # radius: 3.5 - # softness: 1 - # mask: /Textures/Effects/LightMasks/cone.png - # autoRot: true - - type: Tag - tags: - # - ShoesRequiredStepTriggerImmune - - CannotSuicide - - type: Hands - showInHands: false - - type: IntrinsicUI - uis: - - key: enum.LawsUiKey.Key - toggleAction: - name: action-name-show-laws - description: action-description-show-laws - icon: Structures/Wallmounts/posters.rsi/poster11_legit.png #someone wanna make new icons? - iconOn: Structures/Wallmounts/posters.rsi/poster11_legit.png - keywords: [ "AI", "console", "interface", "laws", "borg" ] - priority: -3 - event: !type:ToggleIntrinsicUIEvent - - type: IntrinsicRadioReceiver - channels: - - Binary - - type: ActiveRadio - channels: - - Binary diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml deleted file mode 100644 index 4b28140d4d..0000000000 --- a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/hologram_constructor.yml +++ /dev/null @@ -1,137 +0,0 @@ -# - type: entity -# id: HoloChamber -# parent: BaseMachinePowered -# name: holo pod -# description: A Cloning Pod. 50% reliable. -# components: -# - type: CloningPod -# - type: DeviceList -# - type: DeviceNetwork -# deviceNetId: Wired -# - type: Sprite -# netsync: false -# sprite: Structures/Machines/cloning.rsi -# snapCardinals: true -# layers: -# - state: pod_0 -# - type: Physics -# bodyType: Static -# - type: Fixtures -# fixtures: -# - shape: -# !type:PhysShapeAabb -# bounds: "-0.25,-0.5,0.25,0.5" -# density: 190 -# mask: -# - MachineMask -# layer: -# - MachineLayer -# - type: Construction -# graph: Machine -# node: machine -# containers: -# - machine_board -# - machine_parts -# - clonepod-bodyContainer -# - type: SignalReceiver -# inputs: -# CloningPodReceiver: [] -# - type: EmptyOnMachineDeconstruct -# containers: -# - clonepod-bodyContainer -# - type: Destructible -# thresholds: -# - trigger: -# !type:DamageTrigger -# damage: 100 -# behaviors: -# - !type:ChangeConstructionNodeBehavior -# node: machineFrame -# - !type:DoActsBehavior -# acts: ["Destruction"] -# - type: Machine -# board: CloningPodMachineCircuitboard -# - type: MaterialStorage -# materialWhiteList: -# - Biomass -# - type: Wires -# BoardName: "CloningPod" -# LayoutId: CloningPod -# - type: ApcPowerReceiver -# powerLoad: 200 #Receives most of its power from the console -# - type: Appearance -# visuals: -# - type: GenericEnumVisualizer -# key: enum.CloningPodVisuals.Status -# layer: 0 -# states: -# enum.CloningPodStatus.Cloning: pod_1 -# enum.CloningPodStatus.NoMind: pod_e -# enum.CloningPodStatus.Gore: pod_g -# enum.CloningPodStatus.Idle: pod_0 -# - type: Climbable -# - type: DynamicPrice -# price: 1000 -# - type: ContainerContainer -# containers: -# machine_board: !type:Container -# machine_parts: !type:Container -# clonepod-bodyContainer: !type:ContainerSlot - -- type: entity - id: HologramServer - parent: BaseMachinePowered - name: hologram server - description: Contains the collective knowledge of holo - components: - - type: Sprite - sprite: Structures/Machines/server.rsi - state: server - - type: ApcPowerReceiver - powerLoad: 200 - priority: Low - - type: ExtensionCableReceiver - - type: Destructible - thresholds: - - trigger: !type:DamageTrigger - damage: 300 - behaviors: - - !type:DoActsBehavior - acts: ["Destruction"] - - !type:PlaySoundBehavior - sound: - path: /Audio/Effects/metalbreak.ogg - - !type:SpawnEntitiesBehavior - spawn: - SheetSteel1: - min: 1 - max: 2 - - type: AmbientSound - volume: -9 - range: 5 - sound: - path: /Audio/Ambience/Objects/server_fans.ogg - # - type: CloningPod - - type: HologramServer - - type: ItemSlots - slots: - holo_disk: #this slot name is important - name: Disk - whitelist: - requireAll: true - tags: - - HoloDisk - -- type: entity - parent: BaseItem - id: HologramDisk - name: holo disk - description: A disk for the holo - components: - - type: Sprite - sprite: Objects/Specific/Research/researchdisk.rsi - state: icon - - type: HologramDisk - - type: Tag - tags: - - HoloDisk diff --git a/Resources/Prototypes/SimpleStation14/InventoryTemplates/scutter_inventory_template.yml b/Resources/Prototypes/SimpleStation14/InventoryTemplates/scutter_inventory_template.yml deleted file mode 100644 index efa5439513..0000000000 --- a/Resources/Prototypes/SimpleStation14/InventoryTemplates/scutter_inventory_template.yml +++ /dev/null @@ -1,11 +0,0 @@ -- type: inventoryTemplate - id: scutter - slots: - - name: head - slotTexture: head - slotFlags: HEAD - slotGroup: MainHotbar - uiWindowPos: 0,0 - strippingWindowPos: 0,0 - displayName: Head - offset: 0, -0.4 diff --git a/Resources/Textures/SimpleStation14/Mobs/Pets/corgi.rsi/holo_corgi.png b/Resources/Textures/SimpleStation14/Mobs/Pets/corgi.rsi/holo_corgi.png deleted file mode 100644 index a85cc5e0a5c9ab2fd7d7d57d725f11de7006aaf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12178 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 diff --git a/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/meta.json b/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/meta.json deleted file mode 100644 index 51a8534c4b..0000000000 --- a/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/meta.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "version": 1, - "size": { - "x": 32, - "y": 32 - }, - "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/40d89d11ea4a5cb81d61dc1018b46f4e7d32c62a", - "states": [ - { - "name": "scutter", - "directions": 8 - }, - { - "name": "shell", - "delays": [ - [ - 1 - ] - ] - }, - { - "name": "l_hand", - "directions": 4 - }, - { - "name": "r_hand", - "directions": 4 - } - ] -} diff --git a/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/r_hand.png b/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/r_hand.png deleted file mode 100644 index 4a18493138cc9ae617653e61c10d3aefa8174c90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5373 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 diff --git a/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/shell.png b/Resources/Textures/SimpleStation14/Mobs/Silicon/scutter.rsi/shell.png deleted file mode 100644 index 0c6551c5aaf0a734e252dbb729af54124aaa4af8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 942 zcmV;f15x~mP)EX>4Tx04R}tkvmAkP!xv$rivn!4t5Z6$j~}j@P#;P6^c+H)C#RSnB4RQO&XFE z7e~Rh;NWAi>fqw6tAnc`2tGg@otzY1q{MTRLW>v=T<*tz&;N7pxq#59FwN>312o+> z)5(OG&8><(uMiMG7~_b^%rfRADFxs9x~E>MyExDC@B6d*)x5=kfJi*c4AUmwAfDc| z4bJ<-5mu5_;&b9rlP*a7$aTfzH_kz@3Dp}fAb%ynABNMaF7kRU=q4P{hdBTl=bb^8^S!16O+6Uu^(0pQP8@ zTJ#7AZvz+CZB5w&E_Z;zCqp)6R|?V+3I*W(jJ_!c4BP^JYu?;i=Qw=;GBm5y4RCM> zj1(z*-RIrCopbxQr!~JHa;b8s0=g}l00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru<^ll^GB1NjNG|{Y02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00D+cL_t(o!|jwiZsRZzhCd2H9JpeYz|A6n!CJi!zypv+ z(7AL3@&G=7F5prk5Nu<_l?r1Mr--&OxpLOAod=MHUq#LgXMPSJkjZ2+nM~$~5tjy9 zYX<=5oUqmoegB$#QWnV`W4=W|Ob9Ta&jAP_(D$$0-rn=_@|)}HUu-rHNLd`jM9zsR zP8B!CptVl6vMf`P&E_E$j{?iGOtD&Pj4=nBIL6hv7OmIol-zp{z;5@<-Q6_p{PFP* zAp}AQ7-P~prPSFYC{8)swnZsL2m$YXN|K04p9p{`F$6wNgi~fPP Date: Thu, 30 Mar 2023 18:26:53 -0400 Subject: [PATCH 20/60] Fixed the dumbass colours on IPCs and set Dionas to use None (because hues looked awful on them anyway) --- Content.Shared/Humanoid/SkinColor.cs | 23 ++++++++++++++++++----- Resources/Prototypes/Species/diona.yml | 2 +- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Content.Shared/Humanoid/SkinColor.cs b/Content.Shared/Humanoid/SkinColor.cs index e03f049f42..d09809a339 100644 --- a/Content.Shared/Humanoid/SkinColor.cs +++ b/Content.Shared/Humanoid/SkinColor.cs @@ -117,10 +117,9 @@ public static bool VerifyHumanSkinTone(Color color) /// Tinted hue color public static Color TintedHues(Color color) { - var newColor = Color.ToHsv(color); - newColor.Y = .1f; + var newColor = new Color((color.R + 0.5f) / 2, (color.G + 0.5f) / 2, (color.B + 0.5f) / 2, 1); - return Color.FromHsv(newColor); + return newColor; } /// @@ -130,8 +129,22 @@ public static Color TintedHues(Color color) /// True if valid, false otherwise public static bool VerifyTintedHues(Color color) { - // tinted hues just ensures saturation is always .1, or 10% saturation at all times - return Color.ToHsv(color).Y != .1f; + // Tinted hues ensures hue is within 0.75 of neutral. + + color.Deconstruct(out var r, out var g, out var b, out var _); + + var check = true; + + if (r > 0.75 || r < 0.5) + check = false; + + if (g > 0.75 || g < 0.5) + check = false; + + if (b > 0.75 || b < 0.5) + check = false; + + return check; } public static bool VerifySkinColor(HumanoidSkinColor type, Color color) diff --git a/Resources/Prototypes/Species/diona.yml b/Resources/Prototypes/Species/diona.yml index db58e3a06e..ac30afc7c9 100644 --- a/Resources/Prototypes/Species/diona.yml +++ b/Resources/Prototypes/Species/diona.yml @@ -6,7 +6,7 @@ sprites: MobDionaSprites markingLimits: MobDionaMarkingLimits dollPrototype: MobDionaDummy - skinColoration: TintedHues + skinColoration: None maleFirstNames: DionaFirst femaleFirstNames: DionaFirst lastNames: DionaLast From 312d097fa21d13bc9bc0c437b8212a1389b2d412 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sat, 15 Apr 2023 02:46:57 -0400 Subject: [PATCH 21/60] Working on IPCs falling asleep when de powered. Sleep sucks --- Content.Server/Bed/BedSystem.cs | 2 +- .../Charge/SiliconChargeDeathSystem.cs | 108 ++++++++++++++++++ .../Silicon/Charge/SiliconChargeSystem.cs | 6 +- .../Charge/SiliconDownOnDeadComponent.cs | 7 ++ .../Silicon/SiliconMiscSystem.cs | 19 +++ Content.Shared/Bed/Sleep/SleepingComponent.cs | 14 +++ .../Silicon/Components/SiliconComponent.cs | 27 +++-- .../Silicon/Systems/SharedSiliconSystem.cs | 1 - .../Entities/Mobs/Player/borgs.yml | 2 +- .../Entities/Mobs/Player/ipc.yml | 3 +- .../Entities/Mobs/Player/silicon_base.yml | 8 +- 11 files changed, 178 insertions(+), 19 deletions(-) create mode 100644 Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeDeathSystem.cs create mode 100644 Content.Server/SimpleStation14/Silicon/Charge/SiliconDownOnDeadComponent.cs create mode 100644 Content.Server/SimpleStation14/Silicon/SiliconMiscSystem.cs diff --git a/Content.Server/Bed/BedSystem.cs b/Content.Server/Bed/BedSystem.cs index 01346fd19a..0b967008ac 100644 --- a/Content.Server/Bed/BedSystem.cs +++ b/Content.Server/Bed/BedSystem.cs @@ -79,7 +79,7 @@ public override void Update(float frameTime) var damage = bedComponent.Damage; - if (HasComp(healedEntity)) + if (EntityManager.TryGetComponent(healedEntity, out var sleepComp) && sleepComp.Heal) damage *= bedComponent.SleepMultiplier; _damageableSystem.TryChangeDamage(healedEntity, damage, true, origin: bedComponent.Owner); diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeDeathSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeDeathSystem.cs new file mode 100644 index 0000000000..b25a782267 --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeDeathSystem.cs @@ -0,0 +1,108 @@ +using Content.Server.Power.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using Content.Shared.SimpleStation14.Silicon.Components; +using Content.Shared.SimpleStation14.Silicon.Systems; +using Robust.Shared.Utility; +using Content.Shared.Stunnable; +using Content.Shared.StatusEffect; +using Content.Server.Bed.Sleep; +using Content.Shared.Bed.Sleep; +using Robust.Shared.Audio; +using Content.Server.Sound.Components; + +namespace Content.Server.SimpleStation14.Silicon.Death; + +public sealed class SiliconDeathSystem : EntitySystem +{ + // [Dependency] private readonly IRobustRandom _random = default!; + // [Dependency] private readonly FlammableSystem _flammableSystem = default!; + // [Dependency] private readonly PopupSystem _popup = default!; + // [Dependency] private readonly IGameTiming _gameTiming = default!; + // [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; + [Dependency] private readonly SleepingSystem _sleepSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnSiliconChargeStateUpdate); + } + + private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, SiliconChargeStateUpdateEvent args) + { + + EntityManager.TryGetComponent(uid, out var batteryComp); + EntityManager.TryGetComponent(uid, out var siliconComp); + + DebugTools.AssertNotNull(batteryComp); + DebugTools.AssertNotNull(siliconComp); + + if (batteryComp == null || siliconComp == null) + return; + + if (args.ChargeState == ChargeState.Dead && !siliconDeadComp.Dead) + { + SiliconDead(uid, siliconDeadComp, batteryComp); + } + else if (args.ChargeState != ChargeState.Dead && siliconDeadComp.Dead) + { + SiliconUnDead(uid, siliconDeadComp, batteryComp); + } + } + + private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent batteryComp) + { + + var deadEvent = new SiliconChargeDeadEvent(uid, batteryComp); + RaiseLocalEvent(uid, deadEvent); + + if (deadEvent.Cancelled) + return; + + var sleepComp = EntityManager.EnsureComponent(uid); + + RemComp(uid); + + // sleepComp.SnoreSounds = new SoundCollectionSpecifier("", AudioParams.Default.WithVariation(0.2f)); + EntityManager.EnsureComponent(uid); + + siliconDeadComp.Dead = true; + + RaiseLocalEvent(uid, new SiliconChargeDeathEvent(uid, batteryComp)); + } + + private void SiliconUnDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent batteryComp) + { + _sleepSystem.TryWaking(uid, null, true); + + siliconDeadComp.Dead = false; + } +} + + + +public sealed class SiliconChargeDeadEvent : CancellableEntityEventArgs +{ + public EntityUid SiliconUid { get; } + public BatteryComponent BatteryComp { get; } + + public SiliconChargeDeadEvent(EntityUid siliconUid, BatteryComponent batteryComp) + { + SiliconUid = siliconUid; + BatteryComp = batteryComp; + } +} + +public sealed class SiliconChargeDeathEvent : EntityEventArgs +{ + public EntityUid SiliconUid { get; } + public BatteryComponent BatteryComp { get; } + + public SiliconChargeDeathEvent(EntityUid siliconUid, BatteryComponent batteryComp) + { + SiliconUid = siliconUid; + BatteryComp = batteryComp; + } +} diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs index efbcb8a4c5..5e9e665dfe 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs @@ -130,7 +130,7 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) if (!EntityManager.TryGetComponent(silicon, out var temperComp) || !EntityManager.TryGetComponent(silicon, out var thermalComp)) { - DebugTools.Assert("Silicon has no temperature component, but is battery powered."); + // DebugTools.Assert("Silicon has no temperature component, but is battery powered."); return 0; } var siliconComp = EntityManager.GetComponent(silicon); @@ -147,7 +147,7 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) // Divide the current temp by the max comfortable temp capped to 4, then add that to the multiplier. var hotTempMulti = Math.Min(temperComp.CurrentTemperature / upperThreshHalf, 4); - Logger.DebugS("silicon", $"Silicon {silicon} is overheating, multiplier is {hotTempMulti}."); + // Logger.DebugS("silicon", $"Silicon {silicon} is overheating, multiplier is {hotTempMulti}."); // If the silicon is hot enough, it has a chance to catch fire. FlammableComponent? flamComp = null; @@ -171,7 +171,7 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) } // Logger for the random chances. - Logger.WarningS("silicon", $"Silicon {silicon} has a {Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 15), 0.001f, 0.9f)} chance to catch fire, and a {Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 4), 0.001f, 0.75f)} chance to popup overheating."); + // Logger.WarningS("silicon", $"Silicon {silicon} has a {Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 15), 0.001f, 0.9f)} chance to catch fire, and a {Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 4), 0.001f, 0.75f)} chance to popup overheating."); } return hotTempMulti; diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconDownOnDeadComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconDownOnDeadComponent.cs new file mode 100644 index 0000000000..8f68c204ce --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Charge/SiliconDownOnDeadComponent.cs @@ -0,0 +1,7 @@ +namespace Content.Server.SimpleStation14.Silicon.Death; + +[RegisterComponent] +public sealed class SiliconDownOnDeadComponent : Component +{ + public bool Dead { get; set; } +} diff --git a/Content.Server/SimpleStation14/Silicon/SiliconMiscSystem.cs b/Content.Server/SimpleStation14/Silicon/SiliconMiscSystem.cs new file mode 100644 index 0000000000..2d83c260bd --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/SiliconMiscSystem.cs @@ -0,0 +1,19 @@ +using Content.Shared.SimpleStation14.Silicon.Components; +using Content.Shared.Bed.Sleep; + +namespace Content.Server.SimpleStation14.Silicon.Misc; + +public sealed class SiliconMiscSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnTryingToSleep); + } + + private void OnTryingToSleep(EntityUid uid, SiliconComponent component, ref TryingToSleepEvent args) + { + args.Cancelled = true; + } +} diff --git a/Content.Shared/Bed/Sleep/SleepingComponent.cs b/Content.Shared/Bed/Sleep/SleepingComponent.cs index 4ea419c65a..bef8460d81 100644 --- a/Content.Shared/Bed/Sleep/SleepingComponent.cs +++ b/Content.Shared/Bed/Sleep/SleepingComponent.cs @@ -2,6 +2,9 @@ using Robust.Shared.GameStates; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; +// Parkstation sleeping mods +using Robust.Shared.Audio; + namespace Content.Shared.Bed.Sleep; /// @@ -25,4 +28,15 @@ public sealed class SleepingComponent : Component [DataField("cooldownEnd", customTypeSerializer:typeof(TimeOffsetSerializer))] public TimeSpan CoolDownEnd; + + // Parkstation sleeping mods + [DataField("snore"), ViewVariables(VVAccess.ReadWrite)] + public bool Snore = true; + + [DataField("snoreSounds")] + public SoundCollectionSpecifier SnoreSounds = new SoundCollectionSpecifier("Snores", AudioParams.Default.WithVariation(0.2f)); + + [DataField("heal"), ViewVariables(VVAccess.ReadWrite)] + public bool Heal = true; + // \Parkstation } diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs index 9562dc6cdd..c28d4fe3ed 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs @@ -60,31 +60,42 @@ public sealed class SiliconComponent : Component /// /// The percentages at which the silicon will enter each state. + /// + /// /// The Silicon will always be Full at 100%. /// Setting a value to null will disable that state. - /// Setting Critical to 0 will cause the Silicon to never die of power loss. - /// + /// Setting Critical to 0 will cause the Silicon to never enter the dead state. + /// [DataField("chargeStateThresholdMid"), ViewVariables(VVAccess.ReadWrite)] public float? ChargeStateThresholdMid = 0.5f; + /// [DataField("chargeStateThresholdLow"), ViewVariables(VVAccess.ReadWrite)] public float? ChargeStateThresholdLow = 0.25f; + /// [DataField("chargeStateThresholdCritical"), ViewVariables(VVAccess.ReadWrite)] public float? ChargeStateThresholdCritical = 0.0f; /// - /// Should the silicon die when it runs out of power? - /// If false, will instead become immobile. + /// The amount the Silicon will be slowed at each charge state. + /// + [DataField("speedModifierThresholds", required: true)] + public readonly Dictionary SpeedModifierThresholds = default!; + + /// + /// Should the silicon become immobilized when their battery dies? /// /// /// Will only occur when hitting the Dead state. /// - [DataField("critwhendead"), ViewVariables(VVAccess.ReadWrite)] - public bool Critwhendead = false; + [DataField("dieWhenDead"), ViewVariables(VVAccess.ReadWrite)] + public bool DieWhenDead = false; - [DataField("speedModifierThresholds", required: true)] - public readonly Dictionary SpeedModifierThresholds = default!; + /// + /// Is the Silicon currently dead? + /// + public bool Dead = false; diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs index cd570fb367..79fd5900f7 100644 --- a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs @@ -111,4 +111,3 @@ public SiliconChargeStateUpdateEvent(ChargeState chargeState) ChargeState = chargeState; } } - diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml index 5465405ef2..3045c4a279 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml @@ -200,7 +200,7 @@ chargeStateThresholdMid: 0.60 chargeStateThresholdLow: 0.30 chargeStateThresholdCritical: 0 - critwhendead: false + dieWhenDead: false speedModifierThresholds: 0: 1 1: 1 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml index 966924d2d2..9754273a98 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -4,6 +4,7 @@ name: Urist McPositronic description: A positronic brain in a metal body. components: + - type: SiliconDownOnDead - type: Inventory templateId: ipc - type: Battery @@ -15,7 +16,7 @@ chargeStateThresholdMid: 0.80 chargeStateThresholdLow: 0.35 chargeStateThresholdCritical: 0.10 - critWhenDead: true + dieWhenDead: true speedModifierThresholds: 0: 1 1: 1 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 24804aab6d..4b384bc7cd 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -68,7 +68,7 @@ chargeStateThresholdMid: 0.60 chargeStateThresholdLow: 0.30 chargeStateThresholdCritical: 0 - critwhendead: false + dieWhenDead: false speedModifierThresholds: 0: 1 1: 1 @@ -371,9 +371,9 @@ - SlurredSpeech - PressureImmunity - Muted - - ForcedSleep + # - ForcedSleep - TemporaryBlindness - Pacified - - PsionicsDisabled - - PsionicallyInsulated + # - PsionicsDisabled + # - PsionicallyInsulated - type: Blindable From 7879042faa2098b5f48b93ed94729154d1a73fed Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Thu, 20 Apr 2023 00:54:38 -0400 Subject: [PATCH 22/60] Chargers are awesome now! Recursive check to find all items on an entity and charge them together, and working towards a visualizer. Have previously managed to get it to work, although it doesn't in this commit, as I'm still trying to get it to be unlit. --- .../Components/SiliconChargerComponent.cs | 76 +++++ .../SiliconDownOnDeadComponent.cs | 0 .../Silicon/Charge/SiliconChargerComponent.cs | 36 --- .../Silicon/Charge/SiliconChargerSystem.cs | 142 -------- .../{ => Systems}/SiliconChargeDeathSystem.cs | 3 +- .../{ => Systems}/SiliconChargeSystem.cs | 0 .../Charge/Systems/SiliconChargerSystem.cs | 305 ++++++++++++++++++ .../{ => Systems}/SiliconMiscSystem.cs | 2 + .../Silicon/Components/SiliconComponent.cs | 41 +-- .../Silicon/SiliconChargerVisuals.cs | 16 + .../Entities/Mobs/Player/borgs.yml | 1 - .../Entities/Mobs/Player/ipc.yml | 1 - .../Entities/Mobs/Player/silicon_base.yml | 5 +- .../Structures/Machines/silicon_chargers.yml | 173 +++++----- .../borgcharger.rsi/borgcharger_unlit.png | Bin 0 -> 6326 bytes .../Machines/borgcharger.rsi/meta.json | 3 + .../Machines/charging_pad.rsi/beam.png | Bin 0 -> 32039 bytes .../Machines/charging_pad.rsi/idle.png | Bin 0 -> 20558 bytes .../Machines/charging_pad.rsi/meta.json | 37 +++ .../Machines/charging_pad.rsi/offline.png | Bin 0 -> 580 bytes 20 files changed, 550 insertions(+), 291 deletions(-) create mode 100644 Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconChargerComponent.cs rename Content.Server/SimpleStation14/Silicon/Charge/{ => Components}/SiliconDownOnDeadComponent.cs (100%) delete mode 100644 Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerComponent.cs delete mode 100644 Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs rename Content.Server/SimpleStation14/Silicon/Charge/{ => Systems}/SiliconChargeDeathSystem.cs (95%) rename Content.Server/SimpleStation14/Silicon/Charge/{ => Systems}/SiliconChargeSystem.cs (100%) create mode 100644 Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs rename Content.Server/SimpleStation14/Silicon/{ => Systems}/SiliconMiscSystem.cs (81%) create mode 100644 Content.Shared/SimpleStation14/Silicon/SiliconChargerVisuals.cs create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_unlit.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/beam.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/idle.png create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/meta.json create mode 100644 Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/offline.png diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconChargerComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconChargerComponent.cs new file mode 100644 index 0000000000..cd95270349 --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconChargerComponent.cs @@ -0,0 +1,76 @@ +using Content.Server.Storage.Components; +using Content.Shared.StepTrigger.Components; +using Robust.Shared.Audio; + +namespace Content.Server.SimpleStation14.Silicon; + +[RegisterComponent] +public sealed class SiliconChargerComponent : Component +{ + /// + /// Is the charger currently active? + /// + public bool Active = false; + + /// + /// The currently playing audio stream. + /// + public IPlayingAudioStream? SoundStream { get; set; } + + /// + /// Counter for handing out warnings to burning entities. + /// + public float warningAccumulator = 0f; + + + /// + /// The sound to play when the charger is active. + /// + [DataField("soundLoop")] + public SoundSpecifier SoundLoop = new SoundPathSpecifier("/Audio/Machines/microwave_loop.ogg"); + + /// + /// The multiplier for the charge rate. + /// For reference, an IPC drains at 50. + /// + [DataField("chargeMulti"), ViewVariables(VVAccess.ReadWrite)] + public float ChargeMulti = 150f; + + /// + /// The minimum size of a battery to be charged. + /// + /// + /// Charging a battery too small will detonate it, becoming more likely if it's already full. + /// + [DataField("minChargeSize"), ViewVariables(VVAccess.ReadWrite)] + public int MinChargeSize = 1000; + + + /// + /// The temperature the charger will stop heating up at. + /// + /// + /// Used specifically for chargers with the . + /// + [DataField("targetTemp"), ViewVariables(VVAccess.ReadWrite)] + public float TargetTemp = 365f; + + + /// + /// The list of entities currently stood on a charger. + /// + /// + /// Used specifically for chargers with the . + /// + [ViewVariables(VVAccess.ReadOnly)] + public List PresentEntities = new List(); + + /// + /// The number of entities that can be stood on a charger at once. + /// + /// + /// Used specifically for chargers with the . + /// + [DataField("maxEntities"), ViewVariables(VVAccess.ReadWrite)] + public int MaxEntities = 1; +} diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconDownOnDeadComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs similarity index 100% rename from Content.Server/SimpleStation14/Silicon/Charge/SiliconDownOnDeadComponent.cs rename to Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerComponent.cs deleted file mode 100644 index d2742da9ec..0000000000 --- a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerComponent.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Content.Shared.StepTrigger.Components; - -namespace Content.Server.SimpleStation14.Silicon; - -[RegisterComponent] -public sealed class SiliconChargerComponent : Component -{ - /// - /// The multiplier for the charge rate. - /// For reference, an IPC drains at 50. - /// - [DataField("chargeMulti"), ViewVariables(VVAccess.ReadWrite)] - public float ChargeMulti = 150f; - - /// - /// The temperature the charger will stop heating up at. - /// - [DataField("targetTemp"), ViewVariables(VVAccess.ReadWrite)] - public float TargetTemp = 365f; - - /// - /// The number of entities that can be stood on a charger at once. - [DataField("maxEntities"), ViewVariables(VVAccess.ReadWrite)] - public int MaxEntities = 1; - - - /// - /// The list of entities currently stood on a charger. - /// Used specifically for chargers with the . - /// - [ViewVariables(VVAccess.ReadOnly)] - public List PresentEntities = new List(); - - [ViewVariables(VVAccess.ReadWrite)] - public float warningAccumulator = 0f; -} diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs deleted file mode 100644 index 27e93a357d..0000000000 --- a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargerSystem.cs +++ /dev/null @@ -1,142 +0,0 @@ -using Content.Server.Power.Components; -using Content.Server.Storage.Components; -using Content.Shared.PowerCell.Components; -using Content.Shared.Containers.ItemSlots; -using Content.Shared.Damage; -using Robust.Shared.Prototypes; -using Content.Shared.Damage.Prototypes; -using Content.Server.Popups; -using Robust.Shared.Player; -using Content.Shared.Popups; -using Content.Shared.StepTrigger.Components; -using Robust.Shared.Physics.Events; -using Robust.Shared.Timing; - -namespace Content.Server.SimpleStation14.Silicon.Charge; - -public sealed class SiliconchargerCompSystem : EntitySystem -{ - [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; - [Dependency] private readonly DamageableSystem _damageableSystem = default!; - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly PopupSystem _popup = default!; - [Dependency] private readonly IGameTiming _timing = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnStartCollide); - SubscribeLocalEvent(OnEndCollide); - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - foreach (var (chargerComp, entStorage) in EntityManager.EntityQuery()) - { - foreach (var entity in entStorage.Contents.ContainedEntities) - { - var chargeRate = chargerComp.ChargeMulti * frameTime * 10; - - HandleChargingEntity(entity, chargeRate, chargerComp, frameTime); - - // Heat up the air in the charger. - if (entStorage.Airtight) - { - var curTemp = entStorage.Air.Temperature; - - entStorage.Air.Temperature += curTemp < chargerComp.TargetTemp ? frameTime * chargerComp.ChargeMulti / 100 : 0; - } - } - } - - // Check for any chargers with the StepTriggerComponent. - foreach (var (chargerComp, stepComp) in EntityManager.EntityQuery()) - { - if (chargerComp.PresentEntities.Count == 0) - continue; - - var chargeRate = frameTime * chargerComp.ChargeMulti / chargerComp.PresentEntities.Count ; - - foreach (var entity in chargerComp.PresentEntities) - { - HandleChargingEntity(entity, chargeRate, chargerComp, frameTime); - } - } - } - - private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconChargerComponent chargerComp, float frameTime, bool burn = true) - { - // If the given entity has a battery, charge it. - if (EntityManager.TryGetComponent(entity, out BatteryComponent? batteryComp)) - { - if (batteryComp.CurrentCharge + chargeRate < batteryComp.MaxCharge) - batteryComp.CurrentCharge += chargeRate; - else - batteryComp.CurrentCharge = batteryComp.MaxCharge; - } - // If the given entity contains a battery, charge it. - else if (EntityManager.TryGetComponent(entity, out PowerCellSlotComponent? cellSlotComp) && - _itemSlotsSystem.TryGetSlot(entity, cellSlotComp.CellSlotId, out var slot) && - EntityManager.TryGetComponent(slot.Item, out var cellComp)) - { - if (cellComp.CurrentCharge + chargeRate < cellComp.MaxCharge) - cellComp.CurrentCharge += chargeRate; - else - cellComp.CurrentCharge = cellComp.MaxCharge; - } - // If the given entity DOESN'T have a battery, burn the fucker. - else if (burn && - EntityManager.TryGetComponent(entity, out var damageComp) && - damageComp.DamageContainerID == "Biological") - { - var damage = new DamageSpecifier(_prototypeManager.Index("Shock"), frameTime * chargerComp.ChargeMulti / 100); - var damageDealt = _damageableSystem.TryChangeDamage(entity, damage, false, true, damageComp, chargerComp.Owner); - chargerComp.warningAccumulator -= frameTime; - if (damageDealt != null && chargerComp.warningAccumulator <= 0 && damageDealt.Total > 0) - { - var popupBurn = Loc.GetString("system-silicon-charger-burn", ("charger", chargerComp.Owner), ("entity", entity)); - _popup.PopupEntity(popupBurn, entity, PopupType.MediumCaution); - chargerComp.warningAccumulator += 5f; - } - } - } - - // When an entity starts colliding with the charger, add it to the list of entities present on the charger if it has the StepTriggerComponent. - private void OnStartCollide(EntityUid uid, SiliconChargerComponent component, ref StartCollideEvent args) - { - if (!EntityManager.HasComponent(uid)) - return; - - var target = args.OtherFixture.Body.Owner; - - if (!component.PresentEntities.Contains(target)) - { - if (component.PresentEntities.Count >= component.MaxEntities) - { - _popup.PopupEntity(Loc.GetString("system-silicon-charger-list-too-big"), target, target); - return; - } - - _popup.PopupEntity(Loc.GetString("system-silicon-charger-add-to-list"), target, target); - - component.PresentEntities.Add(target); - } - } - - // When an entity stops colliding with the charger, remove it from the list of entities present on the charger. - private void OnEndCollide(EntityUid uid, SiliconChargerComponent component, ref EndCollideEvent args) - { - if (!EntityManager.HasComponent(uid)) - return; - - var target = args.OtherFixture.Body.Owner; - - if (component.PresentEntities.Contains(target)) - { - component.PresentEntities.Remove(target); - } - } -} diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeDeathSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs similarity index 95% rename from Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeDeathSystem.cs rename to Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs index b25a782267..3247c31145 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeDeathSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs @@ -63,9 +63,8 @@ private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadCo var sleepComp = EntityManager.EnsureComponent(uid); - RemComp(uid); + RemComp(uid); // This is also fucking stupid, I once again hate the sleeping system. - // sleepComp.SnoreSounds = new SoundCollectionSpecifier("", AudioParams.Default.WithVariation(0.2f)); EntityManager.EnsureComponent(uid); siliconDeadComp.Dead = true; diff --git a/Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs similarity index 100% rename from Content.Server/SimpleStation14/Silicon/Charge/SiliconChargeSystem.cs rename to Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs new file mode 100644 index 0000000000..3823d9ac21 --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -0,0 +1,305 @@ +using Content.Server.Power.Components; +using Content.Server.Storage.Components; +using Content.Shared.PowerCell.Components; +using Content.Shared.Containers.ItemSlots; +using Content.Shared.Damage; +using Robust.Shared.Prototypes; +using Content.Shared.Damage.Prototypes; +using Content.Server.Popups; +using Robust.Shared.Player; +using Content.Shared.Popups; +using Content.Shared.StepTrigger.Components; +using Robust.Shared.Physics.Events; +using Robust.Shared.Timing; +using Content.Shared.SimpleStation14.Silicon; +using Robust.Shared.Audio; +using Robust.Server.GameObjects; +using Content.Server.Hands.Components; +using Content.Shared.Inventory; +using Content.Server.Hands.Systems; +using Content.Server.Explosion.Components; +using Content.Server.Explosion.EntitySystems; +using Content.Shared.Interaction.Components; + +namespace Content.Server.SimpleStation14.Silicon.Charge; + +public sealed class SiliconchargerCompSystem : EntitySystem +{ + [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; + [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly AudioSystem _audio = default!; + [Dependency] private readonly HandsSystem _hands = default!; + [Dependency] private readonly InventorySystem _inventory = default!; + [Dependency] private readonly ExplosionSystem _explosion = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnStartCollide); + SubscribeLocalEvent(OnEndCollide); + + SubscribeLocalEvent(OnChargerShutdown); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + // Check for any chargers with the EntityStorageComponent. + foreach (var (chargerComp, entStorage) in EntityManager.EntityQuery()) + { + var wasActive = chargerComp.Active; + chargerComp.Active = false; + + if (EntityManager.TryGetComponent(chargerComp.Owner, out var powerComp) && !powerComp.Powered) + { + if (chargerComp.Active != wasActive) + UpdateState(chargerComp.Owner, chargerComp); + + continue; + } + + foreach (var entity in entStorage.Contents.ContainedEntities) + { + chargerComp.Active = true; + + var chargeRate = chargerComp.ChargeMulti * frameTime * 10; + + HandleChargingEntity(entity, chargeRate, chargerComp, frameTime); + + // Heat up the air in the charger. + if (entStorage.Airtight) + { + var curTemp = entStorage.Air.Temperature; + + entStorage.Air.Temperature += curTemp < chargerComp.TargetTemp ? frameTime * chargerComp.ChargeMulti / 100 : 0; + } + } + + if (chargerComp.Active != wasActive) + UpdateState(chargerComp.Owner, chargerComp); + } + + // Check for any chargers with the StepTriggerComponent. + foreach (var (chargerComp, stepComp) in EntityManager.EntityQuery()) + { + if (chargerComp.PresentEntities.Count == 0 || + (EntityManager.TryGetComponent(chargerComp.Owner, out var powerComp) && !powerComp.Powered)) + { + if (chargerComp.Active) + { + chargerComp.Active = false; + UpdateState(chargerComp.Owner, chargerComp); + } + continue; + } + + if (!chargerComp.Active) + { + chargerComp.Active = true; + UpdateState(chargerComp.Owner, chargerComp); + } + + var chargeRate = frameTime * chargerComp.ChargeMulti / chargerComp.PresentEntities.Count ; + + foreach (var entity in chargerComp.PresentEntities) + { + HandleChargingEntity(entity, chargeRate, chargerComp, frameTime); + } + } + } + + // Cleanup the sound stream when the charger is destroyed. + private void OnChargerShutdown(EntityUid uid, SiliconChargerComponent component, ComponentShutdown args) + { + component.SoundStream?.Stop(); + } + + /// + /// Handles working out what entities need to have their batteries charged, or be burnt. + /// + private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconChargerComponent chargerComp, float frameTime, bool burn = true) + { + var entitiesToCharge = SearchThroughEntities(entity, burn); + + if (entitiesToCharge.Count == 0) + return; + + // Now we charge the entities we found. + chargeRate /= entitiesToCharge.Count; + + foreach (var entityToCharge in entitiesToCharge) + { + if (EntityManager.TryGetComponent(entityToCharge, out var batteryComp)) + ChargeBattery(entityToCharge, EntityManager.GetComponent(entityToCharge), chargeRate, chargerComp); + else if (EntityManager.TryGetComponent(entityToCharge, out var damageComp)) + BurnEntity(entityToCharge, damageComp, frameTime, chargerComp); + } + } + + private List SearchThroughEntities(EntityUid entity, bool burn = true) + { + var entitiesToCharge = new List(); + + // If the given entity has a battery, charge it. + if (EntityManager.TryGetComponent(entity, out BatteryComponent? batteryComp) && + !EntityManager.TryGetComponent(entity, out var _) && + batteryComp.CurrentCharge < batteryComp.MaxCharge) + { + entitiesToCharge.Add(entity); + } + + // If the given entity contains a battery, charge it. + else if (EntityManager.TryGetComponent(entity, out PowerCellSlotComponent? cellSlotComp) && + !EntityManager.TryGetComponent(entity, out var _) && + _itemSlotsSystem.TryGetSlot(entity, cellSlotComp.CellSlotId, out var slot) && + EntityManager.TryGetComponent(slot.Item, out var cellComp) && + cellComp.CurrentCharge < cellComp.MaxCharge) + { + entitiesToCharge.Add(slot.Item.Value); + } + + // If the given entity DOESN'T have a battery, burn the fucker. + else if (burn && + EntityManager.TryGetComponent(entity, out var damageComp) && + damageComp.DamageContainerID == "Biological") + { + entitiesToCharge.Add(entity); + } + + // Now the weird part, we check for any inventories the entities contained may have, and run this function on any entities contained, for a recursive charging effect. + if (EntityManager.TryGetComponent(entity, out var handsComp)) + { + foreach (var heldEntity in _hands.EnumerateHeld(entity, handsComp)) + { + entitiesToCharge.AddRange(SearchThroughEntities(heldEntity)); + } + } + if (EntityManager.TryGetComponent(entity, out var inventoryComp)) + { + foreach (var slot in _inventory.GetSlots(entity, inventoryComp)) + { + if (_inventory.TryGetSlotEntity(entity, slot.Name, out var slotItem)) + entitiesToCharge.AddRange(SearchThroughEntities(slotItem.Value)); + } + } + if (EntityManager.TryGetComponent(entity, out var storageComp)) + { + foreach ( var containedEntity in storageComp.StoredEntities!) + { + entitiesToCharge.AddRange(SearchThroughEntities(containedEntity)); + } + } + if (EntityManager.TryGetComponent(entity, out var entStorage)) + { + foreach (var containedEntity in entStorage.Contents.ContainedEntities) + { + entitiesToCharge.AddRange(SearchThroughEntities(containedEntity)); + } + } + + return entitiesToCharge; + } + + private void ChargeBattery(EntityUid entity, BatteryComponent batteryComp, float chargeRate, SiliconChargerComponent chargerComp) + { + // Do some math so a charger never charges a battery in less than 10 seconds, just for the effect of it. + if (chargerComp.ChargeMulti * 10 > batteryComp.MaxCharge / 10) + { + chargeRate /= (chargerComp.ChargeMulti * 10) / (batteryComp.MaxCharge / 10); + } + + if (batteryComp.CurrentCharge + chargeRate < batteryComp.MaxCharge) + batteryComp.CurrentCharge += chargeRate; + else + batteryComp.CurrentCharge = batteryComp.MaxCharge; + + // If the battery is too small, explode it. + if ((batteryComp.MaxCharge - batteryComp.CurrentCharge) * 1.2 + batteryComp.MaxCharge < chargerComp.MinChargeSize) + { + if (EntityManager.TryGetComponent(entity, out var explosiveComp)) + { + _explosion.TriggerExplosive(entity, explosiveComp); + } + else + { + _explosion.QueueExplosion(entity, "Default", batteryComp.MaxCharge / 50, 1.5f, 200, user: chargerComp.Owner); + } + } + } + + private void BurnEntity(EntityUid entity, DamageableComponent damageComp, float frameTime, SiliconChargerComponent chargerComp) + { + var damage = new DamageSpecifier(_prototypeManager.Index("Shock"), frameTime * chargerComp.ChargeMulti / 100); + var damageDealt = _damageableSystem.TryChangeDamage(entity, damage, false, true, damageComp, chargerComp.Owner); + chargerComp.warningAccumulator -= frameTime; + if (damageDealt != null && chargerComp.warningAccumulator <= 0 && damageDealt.Total > 0) + { + var popupBurn = Loc.GetString("system-silicon-charger-burn", ("charger", chargerComp.Owner), ("entity", entity)); + _popup.PopupEntity(popupBurn, entity, PopupType.MediumCaution); + chargerComp.warningAccumulator += 5f; + } + } + + private void UpdateState(EntityUid uid, SiliconChargerComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + if (component.Active) + { + _appearance.SetData(uid, SiliconChargerVisuals.Lights, SiliconChargerVisualState.Charging); + + if (component.SoundLoop != null) + component.SoundStream = + _audio.PlayPvs(component.SoundLoop, uid, AudioParams.Default.WithLoop(true).WithMaxDistance(5)); + } + else + { + _appearance.SetData(uid, SiliconChargerVisuals.Lights, SiliconChargerVisualState.Normal); + component.SoundStream?.Stop(); + component.SoundStream = null; + } + } + + // When an entity starts colliding with the charger, add it to the list of entities present on the charger if it has the StepTriggerComponent. + private void OnStartCollide(EntityUid uid, SiliconChargerComponent component, ref StartCollideEvent args) + { + if (!EntityManager.HasComponent(uid)) + return; + + var target = args.OtherFixture.Body.Owner; + + if (!component.PresentEntities.Contains(target)) + { + if (component.PresentEntities.Count >= component.MaxEntities) + { + _popup.PopupEntity(Loc.GetString("system-silicon-charger-list-too-big"), target, target); + return; + } + + _popup.PopupEntity(Loc.GetString("system-silicon-charger-add-to-list"), target, target); + + component.PresentEntities.Add(target); + } + } + + // When an entity stops colliding with the charger, remove it from the list of entities present on the charger. + private void OnEndCollide(EntityUid uid, SiliconChargerComponent component, ref EndCollideEvent args) + { + if (!EntityManager.HasComponent(uid)) + return; + + var target = args.OtherFixture.Body.Owner; + + if (component.PresentEntities.Contains(target)) + { + component.PresentEntities.Remove(target); + } + } +} diff --git a/Content.Server/SimpleStation14/Silicon/SiliconMiscSystem.cs b/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs similarity index 81% rename from Content.Server/SimpleStation14/Silicon/SiliconMiscSystem.cs rename to Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs index 2d83c260bd..117fc331f7 100644 --- a/Content.Server/SimpleStation14/Silicon/SiliconMiscSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs @@ -3,6 +3,8 @@ namespace Content.Server.SimpleStation14.Silicon.Misc; +// This entire thing is fucking stupid and I hate it. +// I will never forgive them for what they did with sleeping... public sealed class SiliconMiscSystem : EntitySystem { public override void Initialize() diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs index c28d4fe3ed..a7948e5390 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs @@ -22,6 +22,12 @@ public sealed class SiliconComponent : Component [ViewVariables(VVAccess.ReadOnly)] public new EntityUid Owner = EntityUid.Invalid; + /// + /// Is the Silicon currently dead? + /// + public bool Dead = false; + + /// /// The type of silicon this is. /// @@ -43,21 +49,19 @@ public sealed class SiliconComponent : Component /// /// Should this silicon start charged? /// + /// + /// Valid values are: , , and . + /// [DataField("startCharged", customTypeSerializer: typeof(EnumSerializer)), ViewVariables(VVAccess.ReadOnly)] public Enum StartCharged = StartChargedData.Randomized; - /// - /// Multiplier for the charge rate of the silicon. - /// - [DataField("chargeRateMulti"), ViewVariables(VVAccess.ReadWrite)] - public float ChargeRateMulti = 2.5f; - /// /// Multiplier for the drain rate of the silicon. /// [DataField("drainRateMulti"), ViewVariables(VVAccess.ReadWrite)] public float DrainRateMulti = 5.0f; + /// /// The percentages at which the silicon will enter each state. /// @@ -77,33 +81,10 @@ public sealed class SiliconComponent : Component [DataField("chargeStateThresholdCritical"), ViewVariables(VVAccess.ReadWrite)] public float? ChargeStateThresholdCritical = 0.0f; + /// /// The amount the Silicon will be slowed at each charge state. /// [DataField("speedModifierThresholds", required: true)] public readonly Dictionary SpeedModifierThresholds = default!; - - /// - /// Should the silicon become immobilized when their battery dies? - /// - /// - /// Will only occur when hitting the Dead state. - /// - [DataField("dieWhenDead"), ViewVariables(VVAccess.ReadWrite)] - public bool DieWhenDead = false; - - /// - /// Is the Silicon currently dead? - /// - public bool Dead = false; - - - - // [DataField("chargeStateThresholds"), ViewVariables(VVAccess.ReadWrite)] - // public ChargeStateThresholdsData ChargeStateThresholds = new() - // { - // Mid = 1.0f, - // Low = 0.25f, - // Critical = 0.0f, - // }; } diff --git a/Content.Shared/SimpleStation14/Silicon/SiliconChargerVisuals.cs b/Content.Shared/SimpleStation14/Silicon/SiliconChargerVisuals.cs new file mode 100644 index 0000000000..91b8466165 --- /dev/null +++ b/Content.Shared/SimpleStation14/Silicon/SiliconChargerVisuals.cs @@ -0,0 +1,16 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.SimpleStation14.Silicon; + +[Serializable, NetSerializable] +public enum SiliconChargerVisuals +{ + Lights, +} + +[Serializable, NetSerializable] +public enum SiliconChargerVisualState +{ + Normal, + Charging +} diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml index 3045c4a279..71cc411683 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/borgs.yml @@ -200,7 +200,6 @@ chargeStateThresholdMid: 0.60 chargeStateThresholdLow: 0.30 chargeStateThresholdCritical: 0 - dieWhenDead: false speedModifierThresholds: 0: 1 1: 1 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml index 9754273a98..72b060e9f2 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -16,7 +16,6 @@ chargeStateThresholdMid: 0.80 chargeStateThresholdLow: 0.35 chargeStateThresholdCritical: 0.10 - dieWhenDead: true speedModifierThresholds: 0: 1 1: 1 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 4b384bc7cd..95cf604c84 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -68,7 +68,6 @@ chargeStateThresholdMid: 0.60 chargeStateThresholdLow: 0.30 chargeStateThresholdCritical: 0 - dieWhenDead: false speedModifierThresholds: 0: 1 1: 1 @@ -130,7 +129,7 @@ bleedPuddleThreshold: 3 bleedRefreshAmount: 0 bloodLossThreshold: 0 - maxBleedAmount: 8 + maxBleedAmount: 14 bloodlossDamage: types: Burn: 1.5 @@ -146,7 +145,7 @@ - type: Temperature heatDamageThreshold: 320 coldDamageThreshold: 255 - currentTemperature: 320.15 + currentTemperature: 280 specificHeat: 50 coldDamage: types: diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml index 186e9c961e..cdb471643d 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml @@ -4,48 +4,61 @@ name: industrial charger description: A heavy duty machine for inductively charging robotic beings. Gets extremely hot! components: - - type: Sprite - sprite: SimpleStation14/Structures/Machines/borgcharger.rsi - noRot: true - layers: - - state: base - - state: closed - map: ["enum.StorageVisualLayers.Door"] - - type: Icon - sprite: SimpleStation14/Structures/Machines/borgcharger.rsi - state: icon - - type: Physics - bodyType: Static - fixtures: - - shape: - - !type:PhysShapeAabb - bounds: "-0.45,-0.5,0.45,0.5" - density: 190 - mask: - - MachineMask - layer: - - MachineLayer - - type: ApcPowerReceiver - powerLoad: 500 - - type: DynamicPrice - price: 600 - - type: EntityStorage - capacity: 1 - isCollidableWhenOpen: true - openOnMove: false - enteringOffset: 0, -0.5 - openSound: /Audio/Effects/gen_hit.ogg - closeSound: /Audio/Effects/gen_hit.ogg - - type: Appearance - visuals: - - type: StorageVisualizer - state_open: open - state_closed: closed - - type: ContainerContainer - containers: - entity_storage: !type:Container - - type: SiliconCharger - chargeMulti: 1000 + - type: Sprite + sprite: SimpleStation14/Structures/Machines/borgcharger.rsi + noRot: true + layers: + - state: base + - state: closed + map: ["enum.StorageVisualLayers.Door"] + - state: borgcharger_unlit + shader: unshaded + map: ["enum.SiliconChargerVisuals.Lights"] + - type: GenericVisualizer + visuals: + enum.PowerDeviceVisuals.VisualState: + enum.SiliconChargerVisuals.Lights: + Normal: { state: "borgcharger_unlit" } + Charging: { state: "borgcharger_active_unlit" } + enum.PowerDeviceVisuals.Powered: + enum.SiliconChargerVisuals.Lights: + True: { visible: true } + False: { visible: false } + - type: Icon + sprite: SimpleStation14/Structures/Machines/borgcharger.rsi + state: icon + - type: Physics + bodyType: Static + fixtures: + - shape: + - !type:PhysShapeAabb + bounds: "-0.45,-0.5,0.45,0.5" + density: 190 + mask: + - MachineMask + layer: + - MachineLayer + - type: ApcPowerReceiver + powerLoad: 500 + - type: DynamicPrice + price: 600 + - type: EntityStorage + capacity: 1 + isCollidableWhenOpen: true + openOnMove: false + enteringOffset: 0, -0.5 + openSound: /Audio/Effects/gen_hit.ogg + closeSound: /Audio/Effects/gen_hit.ogg + - type: Appearance + visuals: + - type: StorageVisualizer + state_open: open + state_closed: closed + - type: ContainerContainer + containers: + entity_storage: !type:Container + - type: SiliconCharger + chargeMulti: 1000 - type: entity id: SiliconChargerChargePad @@ -53,40 +66,48 @@ name: charging pad description: A charging pad for inductively charging smaller robotic beings. components: - - type: Sprite - netsync: false - sprite: Structures/cargo_telepad.rsi - drawdepth: FloorObjects - layers: - - state: offline - map: [ "enum.CargoTelepadLayers.Base" ] - - state: idle - map: [ "enum.CargoTelepadLayers.Beam" ] - shader: unshaded - - type: ApcPowerReceiver - powerLoad: 150 - - type: DynamicPrice - price: 200 - - type: Physics - canCollide: true - - type: Fixtures - fixtures: - - shape: - !type:PhysShapeAabb - bounds: "-0.35,-0.35,0.35,0.35" - id: "slips" - hard: false - layer: - - SlipLayer - - shape: - !type:PhysShapeAabb - bounds: "-0.35,-0.35,0.35,0.35" - density: 10 - mask: - - MachineMask - - type: StepTrigger - - type: SiliconCharger - chargeMylti: 150 + - type: Sprite + netsync: false + sprite: SimpleStation14/Structures/Machines/charging_pad.rsi + drawdepth: FloorObjects + layers: + - state: offline + - state: beam + shader: unshaded + map: ["enum.SiliconChargerVisuals.Lights"] + - type: GenericVisualizer + visuals: + enum.PowerDeviceVisuals.VisualState: + enum.SiliconChargerVisuals.Lights: + Normal: { state: "idle" } + Charging: { state: "beam" } + enum.PowerDeviceVisuals.Powered: + enum.SiliconChargerVisuals.Lights: + True: { visible: true } + False: { visible: false } + - type: ApcPowerReceiver + powerLoad: 150 + - type: DynamicPrice + price: 200 + - type: Physics + canCollide: true + - type: Appearance + - type: Fixtures + fixtures: + - shape: !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" + id: "slips" + hard: false + layer: + - SlipLayer + - shape: !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" + density: 10 + mask: + - MachineMask + - type: StepTrigger + - type: SiliconCharger + chargeMylti: 150 # Generated, maybe good? # diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_unlit.png b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/borgcharger_unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..586fe93f3b39cb42dfda30fdbf2fbc397ad07db3 GIT binary patch literal 6326 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 NTYZ;Wwu(*2{{ZYU$<+V= literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/meta.json b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/meta.json index 01571030c4..3559f7508e 100644 --- a/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/meta.json +++ b/Resources/Textures/SimpleStation14/Structures/Machines/borgcharger.rsi/meta.json @@ -25,6 +25,9 @@ { "name": "borgcharger_closed_unlit" }, + { + "name": "borgcharger_unlit" + }, { "name": "borgcharger_active_unlit", "delays": [ diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/beam.png b/Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/beam.png new file mode 100644 index 0000000000000000000000000000000000000000..33c35c84aecce24ee2172b24879636599b26030b GIT binary patch literal 32039 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 R(+*-zTv$e^KtR{?{{Sx2NFx9M literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/idle.png b/Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/idle.png new file mode 100644 index 0000000000000000000000000000000000000000..8921c02a92f599814787cf8aefd76127f2fe2404 GIT binary patch literal 20558 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/meta.json b/Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/meta.json new file mode 100644 index 0000000000..161d2b9a7b --- /dev/null +++ b/Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/meta.json @@ -0,0 +1,37 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Modified from /vg/station at commit 5c50dee8fb2a55d6be3b3c9c90a782a618a5506e Cut out for unshaded by metalgearsloth", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "beam", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "idle", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "offline" + } + ] +} diff --git a/Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/offline.png b/Resources/Textures/SimpleStation14/Structures/Machines/charging_pad.rsi/offline.png new file mode 100644 index 0000000000000000000000000000000000000000..e701d9994d2227227fad91902511f593dfac985e GIT binary patch literal 580 zcmV-K0=xZ*P)o*=%i_)!Y6qyYqPa{{MMzW+5gfCMG5(CIV^0l2L1% zi6U$*F3{gb0_>0biKu2yMY-OT#Y{?;>&?hrn2NMv$zmoYqmE&sZE3@j*5U#m*4`w7 zasS#pyX(EXKQCxCg5xOHo3g+CDRfL;AZ=JOJAaM?cL#vaU%w~(!pk>GnC2X9yF;y7 z;bZ?Bqpf$$UAf6s>!KHT-4U&gu4bf|Ny$>RL2oc*_~nOY#5;uh<9>p9A^nDwFrbOI z?GD!}HAY)#;_9isX>IVk-Y#8xm86-U=z_KoLdZfcOV?fvb}BNe1CHZpnxWTFB^Pp8 z0D6PrVSC4Wn8qybc#rd!F0;P!kmXyqwYX`_(t7iQZs1kyOZKY1itHs-Phf=jcsoKzLgzX+eZUOumg)-ycfr_ca3XnAON9L(IVd8MipU^*o zAW1XNfxF|02lM{c_7fTK7pqk(09;>M0^t6GN1h4Ay}Ne+c)z&`K-=z|$iPHfggCs4 z{+6j&P|S}qr3m}}s4<)xA%qk{$fr*pOZ7f&t*IUPMgQ5(qL`SLnd4LbFTVgUq3&3M S;;TLY0000 Date: Fri, 21 Apr 2023 12:54:04 -0400 Subject: [PATCH 23/60] Apply suggestions from code review Co-authored-by: DEATHB4DEFEAT <77995199+DEATHB4DEFEAT@users.noreply.github.com> --- .../Charge/Systems/SiliconChargeDeathSystem.cs | 4 ---- .../Silicon/Charge/Systems/SiliconChargeSystem.cs | 12 +++--------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs index 3247c31145..82a6d246b4 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs @@ -32,7 +32,6 @@ public override void Initialize() private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, SiliconChargeStateUpdateEvent args) { - EntityManager.TryGetComponent(uid, out var batteryComp); EntityManager.TryGetComponent(uid, out var siliconComp); @@ -54,7 +53,6 @@ private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponen private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent batteryComp) { - var deadEvent = new SiliconChargeDeadEvent(uid, batteryComp); RaiseLocalEvent(uid, deadEvent); @@ -62,9 +60,7 @@ private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadCo return; var sleepComp = EntityManager.EnsureComponent(uid); - RemComp(uid); // This is also fucking stupid, I once again hate the sleeping system. - EntityManager.EnsureComponent(uid); siliconDeadComp.Dead = true; diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs index 5e9e665dfe..632c0def3f 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs @@ -71,11 +71,11 @@ public override void Update(float frameTime) var drainRate = 10 * (siliconComp.DrainRateMulti); - // All multipliers will be - 1, and then added together, and then multiplied by 150. This is then added to the base drain rate. + // All multipliers will be subtracted by 1, and then added together, and then multiplied by the drain rate. This is then added to the base drain rate. // This is to stop exponential increases, while still allowing for less-than-one multipliers. var drainRateFinalAddi = 0f; - //TODO: Devise a method of adding multis where other systems can alter the drain rate. + // TODO: Devise a method of adding multis where other systems can alter the drain rate. // Maybe use something similar to refreshmovespeedmodifiers, where it's stored in the component. // Maybe it doesn't matter, and stuff should just use static drain? @@ -133,6 +133,7 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) // DebugTools.Assert("Silicon has no temperature component, but is battery powered."); return 0; } + var siliconComp = EntityManager.GetComponent(silicon); // If the Silicon is hot, drain the battery faster, if it's cold, drain it slower, capped. @@ -143,12 +144,8 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) // Check if the silicon is in a hot environment. if (temperComp.CurrentTemperature > upperThreshHalf) { - // Divide the current temp by the max comfortable temp capped to 4, then add that to the multiplier. var hotTempMulti = Math.Min(temperComp.CurrentTemperature / upperThreshHalf, 4); - - // Logger.DebugS("silicon", $"Silicon {silicon} is overheating, multiplier is {hotTempMulti}."); - // If the silicon is hot enough, it has a chance to catch fire. FlammableComponent? flamComp = null; @@ -169,9 +166,6 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) { _popup.PopupEntity(popupOverheating, silicon, silicon, PopupType.SmallCaution); } - - // Logger for the random chances. - // Logger.WarningS("silicon", $"Silicon {silicon} has a {Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 15), 0.001f, 0.9f)} chance to catch fire, and a {Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 4), 0.001f, 0.75f)} chance to popup overheating."); } return hotTempMulti; From 9cc78de300268c5dd271772012bf5700a6dfa373 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Fri, 21 Apr 2023 13:07:11 -0400 Subject: [PATCH 24/60] Cleaned up sleeping files. --- Content.Server/Bed/BedSystem.cs | 5 +++-- Content.Shared/Bed/Sleep/SleepingComponent.cs | 14 -------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/Content.Server/Bed/BedSystem.cs b/Content.Server/Bed/BedSystem.cs index 0b967008ac..d4790d7dee 100644 --- a/Content.Server/Bed/BedSystem.cs +++ b/Content.Server/Bed/BedSystem.cs @@ -16,6 +16,7 @@ using Content.Shared.Mobs.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Timing; +using Content.Shared.SimpleStation14.Silicon.Components; // Parkstation: Silicons. I shouldn't have to modify this. namespace Content.Server.Bed { @@ -74,12 +75,12 @@ public override void Update(float frameTime) foreach (var healedEntity in strapComponent.BuckledEntities) { - if (_mobStateSystem.IsDead(healedEntity)) + if (_mobStateSystem.IsDead(healedEntity) || HasComp(healedEntity)) // Parkstation: Silicons. I shouldn't have to modify this. continue; var damage = bedComponent.Damage; - if (EntityManager.TryGetComponent(healedEntity, out var sleepComp) && sleepComp.Heal) + if (HasComp(healedEntity)) damage *= bedComponent.SleepMultiplier; _damageableSystem.TryChangeDamage(healedEntity, damage, true, origin: bedComponent.Owner); diff --git a/Content.Shared/Bed/Sleep/SleepingComponent.cs b/Content.Shared/Bed/Sleep/SleepingComponent.cs index bef8460d81..4ea419c65a 100644 --- a/Content.Shared/Bed/Sleep/SleepingComponent.cs +++ b/Content.Shared/Bed/Sleep/SleepingComponent.cs @@ -2,9 +2,6 @@ using Robust.Shared.GameStates; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; -// Parkstation sleeping mods -using Robust.Shared.Audio; - namespace Content.Shared.Bed.Sleep; /// @@ -28,15 +25,4 @@ public sealed class SleepingComponent : Component [DataField("cooldownEnd", customTypeSerializer:typeof(TimeOffsetSerializer))] public TimeSpan CoolDownEnd; - - // Parkstation sleeping mods - [DataField("snore"), ViewVariables(VVAccess.ReadWrite)] - public bool Snore = true; - - [DataField("snoreSounds")] - public SoundCollectionSpecifier SnoreSounds = new SoundCollectionSpecifier("Snores", AudioParams.Default.WithVariation(0.2f)); - - [DataField("heal"), ViewVariables(VVAccess.ReadWrite)] - public bool Heal = true; - // \Parkstation } From 45272509145eb65c0e801cd35dd4e76db3d92d61 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Fri, 21 Apr 2023 13:29:49 -0400 Subject: [PATCH 25/60] Cleaned up a bit, more suggestions --- .../Silicon/Charge/Systems/SiliconChargeSystem.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs index 632c0def3f..31d300a347 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Movement.Systems; using Content.Server.Body.Components; using Robust.Shared.Utility; +using System.Linq; namespace Content.Server.SimpleStation14.Silicon.Charge; @@ -25,8 +26,6 @@ public sealed class SiliconChargeSystem : EntitySystem [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; - static string popupOverheating = Loc.GetString("silicon-system-overheating"); - public override void Initialize() { base.Initialize(); @@ -57,16 +56,15 @@ public override void Update(float frameTime) base.Update(frameTime); // For each siliconComp entity with a battery component, drain their charge. - foreach (var (siliconComp, batteryComp) in EntityManager.EntityQuery()) + foreach (var (siliconComp, batteryComp) in EntityManager.EntityQuery().Where(x => x.Item1.BatteryPowered)) { if (siliconComp.Owner == EntityUid.Invalid) continue; var silicon = siliconComp.Owner; - // If the silicon is not battery powered, or is dead, skip it. - if (!siliconComp.BatteryPowered || - _mobStateSystem.IsDead(silicon)) + // If the silicon is dead, skip it. + if (_mobStateSystem.IsDead(silicon)) continue; var drainRate = 10 * (siliconComp.DrainRateMulti); @@ -130,7 +128,6 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) if (!EntityManager.TryGetComponent(silicon, out var temperComp) || !EntityManager.TryGetComponent(silicon, out var thermalComp)) { - // DebugTools.Assert("Silicon has no temperature component, but is battery powered."); return 0; } @@ -164,7 +161,7 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) else if ((flamComp == null || !flamComp.OnFire) && _random.Prob(Math.Clamp(temperComp.CurrentTemperature / (upperThresh), 0.001f, 0.75f))) { - _popup.PopupEntity(popupOverheating, silicon, silicon, PopupType.SmallCaution); + _popup.PopupEntity(Loc.GetString("silicon-system-overheating"), silicon, silicon, PopupType.SmallCaution); } } From c8a227ad2d0f058bd33a350318a2d60d1d0ae545 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Tue, 25 Apr 2023 23:31:54 -0400 Subject: [PATCH 26/60] False is default, and some suggestions by Death in SiliconChargerSystem.cs --- .../Charge/Components/SiliconDownOnDeadComponent.cs | 2 +- .../Silicon/Charge/Systems/SiliconChargerSystem.cs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs index 8f68c204ce..17fa934df0 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs @@ -3,5 +3,5 @@ namespace Content.Server.SimpleStation14.Silicon.Death; [RegisterComponent] public sealed class SiliconDownOnDeadComponent : Component { - public bool Dead { get; set; } + public bool Dead { get; set; } = false; } diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 3823d9ac21..28c7ecd15d 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -105,7 +105,7 @@ public override void Update(float frameTime) UpdateState(chargerComp.Owner, chargerComp); } - var chargeRate = frameTime * chargerComp.ChargeMulti / chargerComp.PresentEntities.Count ; + var chargeRate = frameTime * chargerComp.ChargeMulti / chargerComp.PresentEntities.Count; foreach (var entity in chargerComp.PresentEntities) { @@ -148,8 +148,8 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true // If the given entity has a battery, charge it. if (EntityManager.TryGetComponent(entity, out BatteryComponent? batteryComp) && - !EntityManager.TryGetComponent(entity, out var _) && - batteryComp.CurrentCharge < batteryComp.MaxCharge) + !EntityManager.TryGetComponent(entity, out var _) && + batteryComp.CurrentCharge < batteryComp.MaxCharge) { entitiesToCharge.Add(entity); } @@ -238,6 +238,7 @@ private void BurnEntity(EntityUid entity, DamageableComponent damageComp, float var damage = new DamageSpecifier(_prototypeManager.Index("Shock"), frameTime * chargerComp.ChargeMulti / 100); var damageDealt = _damageableSystem.TryChangeDamage(entity, damage, false, true, damageComp, chargerComp.Owner); chargerComp.warningAccumulator -= frameTime; + if (damageDealt != null && chargerComp.warningAccumulator <= 0 && damageDealt.Total > 0) { var popupBurn = Loc.GetString("system-silicon-charger-burn", ("charger", chargerComp.Owner), ("entity", entity)); From 7f8ca85f55cbb1cdd7ec9bda8619f5751d277032 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Wed, 26 Apr 2023 22:42:10 -0400 Subject: [PATCH 27/60] Added some regions :0 --- .../Silicon/Charge/Systems/SiliconChargerSystem.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 28c7ecd15d..1bbd98b2a2 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -50,6 +50,7 @@ public override void Update(float frameTime) { base.Update(frameTime); + #region Entity Storage Chargers // Check for any chargers with the EntityStorageComponent. foreach (var (chargerComp, entStorage) in EntityManager.EntityQuery()) { @@ -84,7 +85,9 @@ public override void Update(float frameTime) if (chargerComp.Active != wasActive) UpdateState(chargerComp.Owner, chargerComp); } + #endregion + #region Step Trigger Chargers // Check for any chargers with the StepTriggerComponent. foreach (var (chargerComp, stepComp) in EntityManager.EntityQuery()) { @@ -112,6 +115,7 @@ public override void Update(float frameTime) HandleChargingEntity(entity, chargeRate, chargerComp, frameTime); } } + #endregion } // Cleanup the sound stream when the charger is destroyed. @@ -208,7 +212,7 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true private void ChargeBattery(EntityUid entity, BatteryComponent batteryComp, float chargeRate, SiliconChargerComponent chargerComp) { - // Do some math so a charger never charges a battery in less than 10 seconds, just for the effect of it. + // Do some math so a charger never charges a battery from zero to full in less than 10 seconds, just for the effect of it. if (chargerComp.ChargeMulti * 10 > batteryComp.MaxCharge / 10) { chargeRate /= (chargerComp.ChargeMulti * 10) / (batteryComp.MaxCharge / 10); From ed9de5abd844f6b5aca5677f608ebe9f3c26a57d Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Thu, 27 Apr 2023 07:40:04 -0400 Subject: [PATCH 28/60] component.Owner no more! >:D Plus some more region stuff. --- .../Charge/Systems/SiliconChargerSystem.cs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 1bbd98b2a2..149f39bfa1 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -52,15 +52,16 @@ public override void Update(float frameTime) #region Entity Storage Chargers // Check for any chargers with the EntityStorageComponent. - foreach (var (chargerComp, entStorage) in EntityManager.EntityQuery()) + var entstorQuery = EntityQueryEnumerator(); + while (entstorQuery.MoveNext(out var uid, out var chargerComp, out var entStorage)) { var wasActive = chargerComp.Active; chargerComp.Active = false; - if (EntityManager.TryGetComponent(chargerComp.Owner, out var powerComp) && !powerComp.Powered) + if (EntityManager.TryGetComponent(uid, out var powerComp) && !powerComp.Powered) { if (chargerComp.Active != wasActive) - UpdateState(chargerComp.Owner, chargerComp); + UpdateState(uid, chargerComp); continue; } @@ -83,21 +84,22 @@ public override void Update(float frameTime) } if (chargerComp.Active != wasActive) - UpdateState(chargerComp.Owner, chargerComp); + UpdateState(uid, chargerComp); } #endregion #region Step Trigger Chargers // Check for any chargers with the StepTriggerComponent. - foreach (var (chargerComp, stepComp) in EntityManager.EntityQuery()) + var stepQuery = EntityQueryEnumerator(); + while (stepQuery.MoveNext(out var uid, out var chargerComp, out var stepTrigger)) { if (chargerComp.PresentEntities.Count == 0 || - (EntityManager.TryGetComponent(chargerComp.Owner, out var powerComp) && !powerComp.Powered)) + (EntityManager.TryGetComponent(uid, out var powerComp) && !powerComp.Powered)) { if (chargerComp.Active) { chargerComp.Active = false; - UpdateState(chargerComp.Owner, chargerComp); + UpdateState(uid, chargerComp); } continue; } @@ -105,7 +107,7 @@ public override void Update(float frameTime) if (!chargerComp.Active) { chargerComp.Active = true; - UpdateState(chargerComp.Owner, chargerComp); + UpdateState(uid, chargerComp); } var chargeRate = frameTime * chargerComp.ChargeMulti / chargerComp.PresentEntities.Count; @@ -272,6 +274,8 @@ private void UpdateState(EntityUid uid, SiliconChargerComponent? component = nul } } + #region Charger specific + #region Step Trigger Chargers // When an entity starts colliding with the charger, add it to the list of entities present on the charger if it has the StepTriggerComponent. private void OnStartCollide(EntityUid uid, SiliconChargerComponent component, ref StartCollideEvent args) { @@ -307,4 +311,6 @@ private void OnEndCollide(EntityUid uid, SiliconChargerComponent component, ref component.PresentEntities.Remove(target); } } + #endregion + #endregion } From b9474ff8050fe4f0bc9c6d04d18d0f59ea2381fa Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Fri, 28 Apr 2023 06:11:46 -0400 Subject: [PATCH 29/60] component.Owner begone! :D (mostly) --- .../Charge/Systems/SiliconChargerSystem.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 149f39bfa1..afb7047661 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -72,7 +72,7 @@ public override void Update(float frameTime) var chargeRate = chargerComp.ChargeMulti * frameTime * 10; - HandleChargingEntity(entity, chargeRate, chargerComp, frameTime); + HandleChargingEntity(entity, chargeRate, chargerComp, uid, frameTime); // Heat up the air in the charger. if (entStorage.Airtight) @@ -114,7 +114,7 @@ public override void Update(float frameTime) foreach (var entity in chargerComp.PresentEntities) { - HandleChargingEntity(entity, chargeRate, chargerComp, frameTime); + HandleChargingEntity(entity, chargeRate, chargerComp, uid, frameTime); } } #endregion @@ -129,7 +129,7 @@ private void OnChargerShutdown(EntityUid uid, SiliconChargerComponent component, /// /// Handles working out what entities need to have their batteries charged, or be burnt. /// - private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconChargerComponent chargerComp, float frameTime, bool burn = true) + private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconChargerComponent chargerComp, EntityUid chargerUid, float frameTime, bool burn = true) { var entitiesToCharge = SearchThroughEntities(entity, burn); @@ -142,9 +142,9 @@ private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconCha foreach (var entityToCharge in entitiesToCharge) { if (EntityManager.TryGetComponent(entityToCharge, out var batteryComp)) - ChargeBattery(entityToCharge, EntityManager.GetComponent(entityToCharge), chargeRate, chargerComp); + ChargeBattery(entityToCharge, EntityManager.GetComponent(entityToCharge), chargeRate, chargerComp, chargerUid); else if (EntityManager.TryGetComponent(entityToCharge, out var damageComp)) - BurnEntity(entityToCharge, damageComp, frameTime, chargerComp); + BurnEntity(entityToCharge, damageComp, frameTime, chargerComp, chargerUid); } } @@ -212,7 +212,7 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true return entitiesToCharge; } - private void ChargeBattery(EntityUid entity, BatteryComponent batteryComp, float chargeRate, SiliconChargerComponent chargerComp) + private void ChargeBattery(EntityUid entity, BatteryComponent batteryComp, float chargeRate, SiliconChargerComponent chargerComp, EntityUid chargerUid) { // Do some math so a charger never charges a battery from zero to full in less than 10 seconds, just for the effect of it. if (chargerComp.ChargeMulti * 10 > batteryComp.MaxCharge / 10) @@ -234,20 +234,20 @@ private void ChargeBattery(EntityUid entity, BatteryComponent batteryComp, float } else { - _explosion.QueueExplosion(entity, "Default", batteryComp.MaxCharge / 50, 1.5f, 200, user: chargerComp.Owner); + _explosion.QueueExplosion(entity, "Default", batteryComp.MaxCharge / 50, 1.5f, 200, user: chargerUid); } } } - private void BurnEntity(EntityUid entity, DamageableComponent damageComp, float frameTime, SiliconChargerComponent chargerComp) + private void BurnEntity(EntityUid entity, DamageableComponent damageComp, float frameTime, SiliconChargerComponent chargerComp, EntityUid chargerUid) { var damage = new DamageSpecifier(_prototypeManager.Index("Shock"), frameTime * chargerComp.ChargeMulti / 100); - var damageDealt = _damageableSystem.TryChangeDamage(entity, damage, false, true, damageComp, chargerComp.Owner); + var damageDealt = _damageableSystem.TryChangeDamage(entity, damage, false, true, damageComp, chargerUid); chargerComp.warningAccumulator -= frameTime; if (damageDealt != null && chargerComp.warningAccumulator <= 0 && damageDealt.Total > 0) { - var popupBurn = Loc.GetString("system-silicon-charger-burn", ("charger", chargerComp.Owner), ("entity", entity)); + var popupBurn = Loc.GetString("system-silicon-charger-burn", ("charger", chargerUid), ("entity", entity)); _popup.PopupEntity(popupBurn, entity, PopupType.MediumCaution); chargerComp.warningAccumulator += 5f; } From 81811ca8cca690e1304859af0c002a9744f28b5e Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Fri, 28 Apr 2023 11:53:31 -0400 Subject: [PATCH 30/60] YA BOI DID IT CHARGER VISUALS WORK NOW AND THEY WORK GREAT. Also replaced elseif tree with a switch, and removed component.Owner. --- .../Charge/Systems/SiliconChargeSystem.cs | 44 ++++++++----------- .../Charge/Systems/SiliconChargerSystem.cs | 33 ++++++++++++-- .../Silicon/Components/SiliconComponent.cs | 2 +- .../Silicon/SiliconChargerVisuals.cs | 1 + .../Silicon/Systems/SharedSiliconSystem.cs | 8 ---- .../Structures/Machines/silicon_chargers.yml | 8 ++-- 6 files changed, 56 insertions(+), 40 deletions(-) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs index 31d300a347..bd19632bab 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs @@ -56,13 +56,9 @@ public override void Update(float frameTime) base.Update(frameTime); // For each siliconComp entity with a battery component, drain their charge. - foreach (var (siliconComp, batteryComp) in EntityManager.EntityQuery().Where(x => x.Item1.BatteryPowered)) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var silicon, out var siliconComp, out var batteryComp)) { - if (siliconComp.Owner == EntityUid.Invalid) - continue; - - var silicon = siliconComp.Owner; - // If the silicon is dead, skip it. if (_mobStateSystem.IsDead(silicon)) continue; @@ -87,28 +83,26 @@ public override void Update(float frameTime) batteryComp.UseCharge(frameTime * drainRate); // Figure out the current state of the Silicon. - var currentState = ChargeState.Dead; var chargePercent = batteryComp.CurrentCharge / batteryComp.MaxCharge; - if (chargePercent == 0 && siliconComp.ChargeStateThresholdCritical != 0) - { - currentState = ChargeState.Dead; - } - else if (chargePercent <= siliconComp.ChargeStateThresholdCritical) - { - currentState = ChargeState.Critical; - } - else if (chargePercent <= siliconComp.ChargeStateThresholdLow) - { - currentState = ChargeState.Low; - } - else if (chargePercent < siliconComp.ChargeStateThresholdMid) - { - currentState = ChargeState.Mid; - } - else if (chargePercent >= siliconComp.ChargeStateThresholdMid) + ChargeState currentState; + switch (chargePercent) { - currentState = ChargeState.Full; + case var x when x > siliconComp.ChargeStateThresholdMid: + currentState = ChargeState.Full; + break; + case var x when x > siliconComp.ChargeStateThresholdLow: + currentState = ChargeState.Mid; + break; + case var x when x > siliconComp.ChargeStateThresholdCritical: + currentState = ChargeState.Low; + break; + case var x when x > 0 || siliconComp.ChargeStateThresholdCritical == 0: + currentState = ChargeState.Critical; + break; + default: + currentState = ChargeState.Dead; + break; } // Check if anything needs to be updated. diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index afb7047661..6dc7fc8ea0 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -20,6 +20,8 @@ using Content.Server.Explosion.Components; using Content.Server.Explosion.EntitySystems; using Content.Shared.Interaction.Components; +using Content.Shared.Power; +using Content.Shared.Storage.Components; namespace Content.Server.SimpleStation14.Silicon.Charge; @@ -44,6 +46,9 @@ public override void Initialize() SubscribeLocalEvent(OnEndCollide); SubscribeLocalEvent(OnChargerShutdown); + + SubscribeLocalEvent(HandleStateOpen); + SubscribeLocalEvent(HandleStateClose); } public override void Update(float frameTime) @@ -253,6 +258,23 @@ private void BurnEntity(EntityUid entity, DamageableComponent damageComp, float } } + /// + /// Updates the state of the charger when it's open or closed. + /// + private void HandleStateOpen(EntityUid uid, SiliconChargerComponent component, ref StorageAfterOpenEvent _) + { + UpdateState(uid, component); + } + + /// + private void HandleStateClose(EntityUid uid, SiliconChargerComponent component, ref StorageAfterCloseEvent _) + { + UpdateState(uid, component); + } + + /// + /// Updates the visual and auditory state of the charger based on if it's active, and/or open. + /// private void UpdateState(EntityUid uid, SiliconChargerComponent? component = null) { if (!Resolve(uid, ref component)) @@ -260,15 +282,20 @@ private void UpdateState(EntityUid uid, SiliconChargerComponent? component = nul if (component.Active) { - _appearance.SetData(uid, SiliconChargerVisuals.Lights, SiliconChargerVisualState.Charging); + _appearance.SetData(uid, PowerDeviceVisuals.VisualState, SiliconChargerVisualState.Charging); - if (component.SoundLoop != null) + if (component.SoundLoop != null && component.SoundStream == null) component.SoundStream = _audio.PlayPvs(component.SoundLoop, uid, AudioParams.Default.WithLoop(true).WithMaxDistance(5)); } else { - _appearance.SetData(uid, SiliconChargerVisuals.Lights, SiliconChargerVisualState.Normal); + var state = SiliconChargerVisualState.Normal; + + if (EntityManager.TryGetComponent(uid, out var storageComp) && storageComp.Open) + state = SiliconChargerVisualState.NormalOpen; + + _appearance.SetData(uid, PowerDeviceVisuals.VisualState, state); component.SoundStream?.Stop(); component.SoundStream = null; } diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs index a7948e5390..c6bbf891d5 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs @@ -5,7 +5,7 @@ namespace Content.Shared.SimpleStation14.Silicon.Components; /// -/// Component for defnining a mob as a robot. +/// Component for defining a mob as a robot. /// [RegisterComponent, NetworkedComponent] public sealed class SiliconComponent : Component diff --git a/Content.Shared/SimpleStation14/Silicon/SiliconChargerVisuals.cs b/Content.Shared/SimpleStation14/Silicon/SiliconChargerVisuals.cs index 91b8466165..57b579e87e 100644 --- a/Content.Shared/SimpleStation14/Silicon/SiliconChargerVisuals.cs +++ b/Content.Shared/SimpleStation14/Silicon/SiliconChargerVisuals.cs @@ -12,5 +12,6 @@ public enum SiliconChargerVisuals public enum SiliconChargerVisualState { Normal, + NormalOpen, Charging } diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs index 79fd5900f7..5233662f67 100644 --- a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs @@ -89,14 +89,6 @@ public enum StartChargedData Randomized } -// [Serializable, NetSerializable] -// public struct ChargeStateThresholdsData -// { -// public float Mid; -// public float Low; -// public float Critical; -// } - /// /// Event raised when a Silicon's charge state needs to be updated. diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml index cdb471643d..72628629b9 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml @@ -11,14 +11,15 @@ - state: base - state: closed map: ["enum.StorageVisualLayers.Door"] - - state: borgcharger_unlit + - state: borgcharger_closed_unlit shader: unshaded map: ["enum.SiliconChargerVisuals.Lights"] - type: GenericVisualizer visuals: enum.PowerDeviceVisuals.VisualState: enum.SiliconChargerVisuals.Lights: - Normal: { state: "borgcharger_unlit" } + Normal: { state: "borgcharger_closed_unlit" } + NormalOpen: { state: "borgcharger_open_unlit" } Charging: { state: "borgcharger_active_unlit" } enum.PowerDeviceVisuals.Powered: enum.SiliconChargerVisuals.Lights: @@ -59,6 +60,7 @@ entity_storage: !type:Container - type: SiliconCharger chargeMulti: 1000 + targetTemp: 390 - type: entity id: SiliconChargerChargePad @@ -72,7 +74,7 @@ drawdepth: FloorObjects layers: - state: offline - - state: beam + - state: idle shader: unshaded map: ["enum.SiliconChargerVisuals.Lights"] - type: GenericVisualizer From c7c2e86d95e512862d2e83f9b83756a9b276155c Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sat, 29 Apr 2023 22:00:05 -0400 Subject: [PATCH 31/60] Workin' on that sweet sweet APC succ --- .../Components/BatteryDrinkerComponent.cs | 41 +++++ .../BatteryDrinkerSourceComponent.cs | 26 +++ .../Charge/Systems/BatteryDrinkerSystem.cs | 152 ++++++++++++++++++ .../Entities/Structures/Power/apc.yml | 2 + .../Entities/Mobs/Player/ipc.yml | 1 + 5 files changed, 222 insertions(+) create mode 100644 Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs create mode 100644 Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs create mode 100644 Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs new file mode 100644 index 0000000000..cc70f6aeaf --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs @@ -0,0 +1,41 @@ +using Robust.Shared.Audio; + +namespace Content.Server.SimpleStation14.Silicon.Charge; + +[RegisterComponent] +public class BatteryDrinkerComponent : Component +{ + /// + /// Is this drinker allowed to drink batteries not tagged as ? + /// + [DataField("drinkAll"), ViewVariables(VVAccess.ReadWrite)] + public bool DrinkAll = false; + + /// + /// How long it takes to drink from the battery, in seconds. + /// Is mutliplied by the source. + /// + [DataField("drinkSpeed"), ViewVariables(VVAccess.ReadWrite)] + public float DrinkSpeed = 1.5f; + + /// + /// The multiplier for the amount of power to attempt to drink. + /// Default amount is 1000 + /// + [DataField("drinkMultiplier"), ViewVariables(VVAccess.ReadWrite)] + public float DrinkMultiplier = 5f; + + /// + /// The sound to override the standard drink sound with. + /// Uses per source sound if null. + /// + [DataField("drinkSoundOverride")] + public SoundSpecifier? DrinkSound = new SoundPathSpecifier("/Audio/Items/drink.ogg"); + + /// + /// The localised string to display when drinking from a battery. + /// Doesn't _need_ to be localised, but come on, man. + /// + [DataField("drinkText")] + public string DrinkText = ""; +} diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs new file mode 100644 index 0000000000..807f08f003 --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs @@ -0,0 +1,26 @@ +using Robust.Shared.Audio; + +namespace Content.Server.SimpleStation14.Silicon.Charge; + +[RegisterComponent] +public class BatteryDrinkerSourceComponent : Component +{ + /// + /// The max amount of power to give when drunk from. + /// + [DataField("maxAmount"), ViewVariables(VVAccess.ReadWrite)] + public int? MaxAmount = null; + + /// + /// The multiplier for the drink speed. + /// + [DataField("drinkSpeedMulti"), ViewVariables(VVAccess.ReadWrite)] + public float DrinkSpeedMulti = 1f; + + /// + /// The sound to play when the APC gets drunk from. + /// Can be null. + /// + [DataField("drinkSound")] + public SoundSpecifier? DrinkSound = null; +} diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs new file mode 100644 index 0000000000..6c5b749e12 --- /dev/null +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs @@ -0,0 +1,152 @@ +using System.Diagnostics.CodeAnalysis; +using Content.Server.Power.Components; +using Content.Shared.Containers.ItemSlots; +using Content.Shared.DoAfter; +using Content.Shared.Interaction.Helpers; +using Content.Shared.PowerCell.Components; +using Content.Shared.Verbs; +using Robust.Shared.Audio; +using Robust.Shared.Utility; + +namespace Content.Server.SimpleStation14.Silicon.Charge; + +public sealed class BatteryDrinkerSystem : EntitySystem +{ + [Dependency] private readonly ItemSlotsSystem _slots = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(AddAltVerb); + + SubscribeLocalEvent(OnDoAfter); + } + + private void AddAltVerb(EntityUid uid, BatteryComponent batteryComponent, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract) + return; + + if (!EntityManager.TryGetComponent(args.User, out var drinkerComp) || + !TestDrinkableBattery(uid, drinkerComp) || + !TryGetFillableBattery(args.User, out var drinkerBattery)) + return; + + AlternativeVerb verb = new() + { + Act = () => DrinkBattery(uid, args.User, batteryComponent, drinkerBattery, drinkerComp), + Text = "system-battery-drinker-verb-drink", + Icon = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/VerbIcons/drink.svg.192dpi.png")), + }; + + args.Verbs.Add(verb); + } + + private bool TestDrinkableBattery(EntityUid target, BatteryDrinkerComponent drinkerComp) + { + + if (!drinkerComp.DrinkAll && !HasComp(target)) + return false; + + return true; + } + + private bool TryGetFillableBattery(EntityUid uid, [NotNullWhen(true)] out BatteryComponent? battery) + { + battery = null; + + if (EntityManager.TryGetComponent(uid, out battery)) + return true; + + if (EntityManager.TryGetComponent(uid, out var powerCellSlot) && + _slots.TryGetSlot(uid, powerCellSlot.CellSlotId, out var slot) && + slot.Item != null && + EntityManager.TryGetComponent(slot.Item.Value, out battery)) + return true; + + return false; + } + + private void DrinkBattery(EntityUid target, EntityUid user, BatteryComponent batteryComp, BatteryComponent drinkerBatteryComp, BatteryDrinkerComponent drinkerComp) + { + var doAfterTime = drinkerComp.DrinkSpeed; + + if (EntityManager.TryGetComponent(target, out var sourceComp)) + doAfterTime *= sourceComp.DrinkSpeedMulti; + else + doAfterTime *= 2.5f; + + _doAfter.DoAfter(new DoAfterEventArgs(user, doAfterTime, target:target) + { + RaiseOnTarget = true, + RaiseOnUser = false, + BreakOnUserMove = false, + BreakOnDamage = true, + BreakOnStun = true, + BreakOnTargetMove = false, + MovementThreshold = 0.25f, + PostCheck = () => user.InRangeUnOccluded(target, 1.5f) + }); + } + + private void OnDoAfter(EntityUid uid, BatteryComponent batteryComponent, DoAfterEvent args) + { + if (args.Cancelled) + return; + + var source = uid; + var drinker = args.Args.User; + var drinkerComp = EntityManager.GetComponent(drinker); + var sourceBattery = EntityManager.GetComponent(source); + + TryGetFillableBattery(drinker, out var drinkerBattery); + + EntityManager.TryGetComponent(source, out var sourceComp); + + DebugTools.AssertNotNull(drinkerBattery); + + if (drinkerBattery == null) + return; + + var amountToDrink = drinkerComp.DrinkMultiplier * 1000; + + amountToDrink = MathF.Min(amountToDrink, batteryComponent.CurrentCharge); + amountToDrink = MathF.Min(amountToDrink, drinkerBattery.MaxCharge - drinkerBattery.CurrentCharge); + + if (sourceComp != null && sourceComp.MaxAmount > 0) + { + amountToDrink = MathF.Min(amountToDrink, (float) sourceComp.MaxAmount); + } + + if (amountToDrink <= 0) + { + // Do empty stuff + return; + } + + if (sourceBattery.TryUseCharge(amountToDrink)) + { + drinkerBattery.CurrentCharge += amountToDrink; + } + else + { + drinkerBattery.CurrentCharge += sourceBattery.CurrentCharge; + sourceBattery.CurrentCharge = 0; + } + + var sound = drinkerComp.DrinkSound ?? sourceComp?.DrinkSound; + + // Log sound + Logger.InfoS("battery", $"User {drinker} drank {amountToDrink} from {source}."); + Logger.Info("Sound to play: " + sound?.ToString() ?? "null"); + + if (sound != null) + _audio.PlayPvs(sound, source); + + if (sourceBattery.CurrentCharge > 0) + DrinkBattery(source, drinker, sourceBattery, drinkerBattery, drinkerComp); + } +} diff --git a/Resources/Prototypes/Entities/Structures/Power/apc.yml b/Resources/Prototypes/Entities/Structures/Power/apc.yml index 5ce1b23fbb..6463cf82f2 100644 --- a/Resources/Prototypes/Entities/Structures/Power/apc.yml +++ b/Resources/Prototypes/Entities/Structures/Power/apc.yml @@ -94,6 +94,8 @@ - type: StationInfiniteBatteryTarget - type: DynamicPrice price: 500 + - type: BatteryDrinkerSource + maxAmount: 10000 # APC under construction - type: entity diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml index 72b060e9f2..661c30b64d 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -23,6 +23,7 @@ 3: 0.45 4: 0.00 - type: Carriable + - type: BatteryDrinker - type: entity save: false From 7348c32924fc9be8f8b0a692968c13d92fdce99b Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 15 May 2023 14:07:26 -0400 Subject: [PATCH 32/60] Cleaned up a bit post-rebase, fixed TintedHues validator, fixed drinker DoAfter --- .../Components/BatteryDrinkerComponent.cs | 2 +- .../Charge/Systems/BatteryDrinkerSystem.cs | 41 +++++++++---------- .../Charge/Systems/SiliconChargerSystem.cs | 2 +- Content.Shared/Humanoid/SkinColor.cs | 6 +-- .../Silicon/BatteryDrinkerEvent.cs | 12 ++++++ .../Silicon/Systems/SharedSiliconSystem.cs | 1 - Resources/Prototypes/SimpleStation14/tags.yml | 7 ---- 7 files changed, 36 insertions(+), 35 deletions(-) create mode 100644 Content.Shared/SimpleStation14/Silicon/BatteryDrinkerEvent.cs diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs index cc70f6aeaf..067527bade 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs @@ -37,5 +37,5 @@ public class BatteryDrinkerComponent : Component /// Doesn't _need_ to be localised, but come on, man. /// [DataField("drinkText")] - public string DrinkText = ""; + public string DrinkText = "aaaaaaaaaa"; } diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs index 6c5b749e12..80ff8b9f17 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs @@ -4,8 +4,10 @@ using Content.Shared.DoAfter; using Content.Shared.Interaction.Helpers; using Content.Shared.PowerCell.Components; +using Content.Shared.SimpleStation14.Silicon; using Content.Shared.Verbs; using Robust.Shared.Audio; +using Robust.Shared.Serialization; using Robust.Shared.Utility; namespace Content.Server.SimpleStation14.Silicon.Charge; @@ -22,7 +24,7 @@ public override void Initialize() SubscribeLocalEvent>(AddAltVerb); - SubscribeLocalEvent(OnDoAfter); + SubscribeLocalEvent(OnDoAfter); } private void AddAltVerb(EntityUid uid, BatteryComponent batteryComponent, GetVerbsEvent args) @@ -79,27 +81,26 @@ private void DrinkBattery(EntityUid target, EntityUid user, BatteryComponent bat else doAfterTime *= 2.5f; - _doAfter.DoAfter(new DoAfterEventArgs(user, doAfterTime, target:target) + var args = new DoAfterArgs(user, doAfterTime, new BatteryDrinkerEvent(), user, target) { - RaiseOnTarget = true, - RaiseOnUser = false, - BreakOnUserMove = false, BreakOnDamage = true, - BreakOnStun = true, - BreakOnTargetMove = false, - MovementThreshold = 0.25f, - PostCheck = () => user.InRangeUnOccluded(target, 1.5f) - }); + BreakOnTargetMove = true, + Broadcast = false, + DistanceThreshold = 1.35f, + RequireCanInteract = true, + CancelDuplicate = false + }; + + var doAfter = _doAfter.TryStartDoAfter(args); } - private void OnDoAfter(EntityUid uid, BatteryComponent batteryComponent, DoAfterEvent args) + private void OnDoAfter(EntityUid uid, BatteryDrinkerComponent drinkerComp, DoAfterEvent args) { - if (args.Cancelled) + if (args.Cancelled || args.Target == null) return; - var source = uid; - var drinker = args.Args.User; - var drinkerComp = EntityManager.GetComponent(drinker); + var source = args.Target.Value; + var drinker = uid; var sourceBattery = EntityManager.GetComponent(source); TryGetFillableBattery(drinker, out var drinkerBattery); @@ -113,7 +114,7 @@ private void OnDoAfter(EntityUid uid, BatteryComponent batteryComponent, DoAfter var amountToDrink = drinkerComp.DrinkMultiplier * 1000; - amountToDrink = MathF.Min(amountToDrink, batteryComponent.CurrentCharge); + amountToDrink = MathF.Min(amountToDrink, sourceBattery.CurrentCharge); amountToDrink = MathF.Min(amountToDrink, drinkerBattery.MaxCharge - drinkerBattery.CurrentCharge); if (sourceComp != null && sourceComp.MaxAmount > 0) @@ -139,14 +140,10 @@ private void OnDoAfter(EntityUid uid, BatteryComponent batteryComponent, DoAfter var sound = drinkerComp.DrinkSound ?? sourceComp?.DrinkSound; - // Log sound - Logger.InfoS("battery", $"User {drinker} drank {amountToDrink} from {source}."); - Logger.Info("Sound to play: " + sound?.ToString() ?? "null"); - if (sound != null) _audio.PlayPvs(sound, source); - if (sourceBattery.CurrentCharge > 0) - DrinkBattery(source, drinker, sourceBattery, drinkerBattery, drinkerComp); + // if (sourceBattery.CurrentCharge > 0) // Make use proper looping doafters when we merge Upstream. + // DrinkBattery(source, drinker, sourceBattery, drinkerBattery, drinkerComp); } } diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 6dc7fc8ea0..3e1add5426 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -14,7 +14,6 @@ using Content.Shared.SimpleStation14.Silicon; using Robust.Shared.Audio; using Robust.Server.GameObjects; -using Content.Server.Hands.Components; using Content.Shared.Inventory; using Content.Server.Hands.Systems; using Content.Server.Explosion.Components; @@ -22,6 +21,7 @@ using Content.Shared.Interaction.Components; using Content.Shared.Power; using Content.Shared.Storage.Components; +using Content.Shared.Hands.Components; namespace Content.Server.SimpleStation14.Silicon.Charge; diff --git a/Content.Shared/Humanoid/SkinColor.cs b/Content.Shared/Humanoid/SkinColor.cs index d09809a339..f4983492c2 100644 --- a/Content.Shared/Humanoid/SkinColor.cs +++ b/Content.Shared/Humanoid/SkinColor.cs @@ -135,13 +135,13 @@ public static bool VerifyTintedHues(Color color) var check = true; - if (r > 0.75 || r < 0.5) + if (r > 0.75 || r < 0.25) check = false; - if (g > 0.75 || g < 0.5) + if (g > 0.75 || g < 0.25) check = false; - if (b > 0.75 || b < 0.5) + if (b > 0.75 || b < 0.25) check = false; return check; diff --git a/Content.Shared/SimpleStation14/Silicon/BatteryDrinkerEvent.cs b/Content.Shared/SimpleStation14/Silicon/BatteryDrinkerEvent.cs new file mode 100644 index 0000000000..738a7a34dd --- /dev/null +++ b/Content.Shared/SimpleStation14/Silicon/BatteryDrinkerEvent.cs @@ -0,0 +1,12 @@ +using Content.Shared.DoAfter; +using Robust.Shared.Serialization; + +namespace Content.Shared.SimpleStation14.Silicon; + +[Serializable, NetSerializable] +public sealed class BatteryDrinkerEvent : SimpleDoAfterEvent +{ + public BatteryDrinkerEvent() + { + } +} diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs index 5233662f67..ec1bbabb9f 100644 --- a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs @@ -2,7 +2,6 @@ using Content.Shared.Alert; using Robust.Shared.Serialization; using Content.Shared.Movement.Systems; -// using namespace Content.Shared.SimpleStation14.Silicon.Systems; public sealed class SharedSiliconChargeSystem : EntitySystem diff --git a/Resources/Prototypes/SimpleStation14/tags.yml b/Resources/Prototypes/SimpleStation14/tags.yml index a29cbd9854..6384bf6e4e 100644 --- a/Resources/Prototypes/SimpleStation14/tags.yml +++ b/Resources/Prototypes/SimpleStation14/tags.yml @@ -3,10 +3,3 @@ - type: Tag id: GlassesNearsight - -- type: Tag - id: Hardlight -- type: Tag - id: Softlight -- type: Tag - id: HoloDisk From 2b6d91e17548a84c4d33936c66c914bb9b5f0b9b Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sun, 21 May 2023 05:07:28 -0400 Subject: [PATCH 33/60] Various small fixes, electrocution charge Moved some files, renamed some Locs. Electrocuting a battery will now charge that battery an amount based on the damage, including IPCs (in theory). Electrocution event now relays damage dealt, as it obviously should've. --- .../Electrocution/ElectrocutionSystem.cs | 6 +-- .../Components/BatteryDrinkerComponent.cs | 2 +- .../Systems/BatteryDrinkerSystem.cs | 3 +- .../Systems/BatteryElectrocuteChargeSystem.cs | 38 +++++++++++++++++++ .../Systems/SiliconChargeDeathSystem.cs | 2 +- .../Charge/Systems/SiliconChargerSystem.cs | 6 +-- .../Electrocution/ElectrocutionEvents.cs | 4 +- 7 files changed, 51 insertions(+), 10 deletions(-) rename Content.Server/SimpleStation14/{Silicon/Charge => Power}/Components/BatteryDrinkerComponent.cs (95%) rename Content.Server/SimpleStation14/{Silicon/Charge => Power}/Systems/BatteryDrinkerSystem.cs (98%) create mode 100644 Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs diff --git a/Content.Server/Electrocution/ElectrocutionSystem.cs b/Content.Server/Electrocution/ElectrocutionSystem.cs index 00f947f6a3..37e3a62ae8 100644 --- a/Content.Server/Electrocution/ElectrocutionSystem.cs +++ b/Content.Server/Electrocution/ElectrocutionSystem.cs @@ -272,7 +272,7 @@ public bool TryDoElectrocution( || !DoCommonElectrocution(uid, sourceUid, shockDamage, time, refresh, siemensCoefficient, statusEffects)) return false; - RaiseLocalEvent(uid, new ElectrocutedEvent(uid, sourceUid, siemensCoefficient), true); + RaiseLocalEvent(uid, new ElectrocutedEvent(uid, sourceUid, siemensCoefficient, shockDamage), true); // Parkstation-IPC return true; } @@ -317,7 +317,7 @@ private bool TryDoElectrocutionPowered( electrocutionComponent.Electrocuting = uid; electrocutionComponent.Source = sourceUid; - RaiseLocalEvent(uid, new ElectrocutedEvent(uid, sourceUid, siemensCoefficient), true); + RaiseLocalEvent(uid, new ElectrocutedEvent(uid, sourceUid, siemensCoefficient, shockDamage), true); // Parkstation-IPC return true; } @@ -387,7 +387,7 @@ private bool DoCommonElectrocution(EntityUid uid, EntityUid? sourceUid, var filter = Filter.PvsExcept(uid, entityManager: EntityManager); - // TODO: Allow being able to pass EntityUid to Loc... +- // TODO: Allow being able to pass EntityUid to Loc... if (sourceUid != null) { _popupSystem.PopupEntity(Loc.GetString("electrocuted-component-mob-shocked-by-source-popup-others", diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs b/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs similarity index 95% rename from Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs rename to Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs index 067527bade..43e61a0b10 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerComponent.cs +++ b/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs @@ -1,6 +1,6 @@ using Robust.Shared.Audio; -namespace Content.Server.SimpleStation14.Silicon.Charge; +namespace Content.Server.SimpleStation14.Power; [RegisterComponent] public class BatteryDrinkerComponent : Component diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs similarity index 98% rename from Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs rename to Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs index 80ff8b9f17..1e84894669 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/BatteryDrinkerSystem.cs +++ b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs @@ -9,8 +9,9 @@ using Robust.Shared.Audio; using Robust.Shared.Serialization; using Robust.Shared.Utility; +using Content.Server.SimpleStation14.Silicon.Charge; -namespace Content.Server.SimpleStation14.Silicon.Charge; +namespace Content.Server.SimpleStation14.Power; public sealed class BatteryDrinkerSystem : EntitySystem { diff --git a/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs b/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs new file mode 100644 index 0000000000..676904b6be --- /dev/null +++ b/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs @@ -0,0 +1,38 @@ +using Content.Server.Popups; +using Content.Server.Power.Components; +using Content.Shared.Electrocution; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Server.SimpleStation14.Power.Systems; + +public sealed class BatteryElectrocuteChargeSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnElectrocuted); + } + + private void OnElectrocuted(EntityUid uid, BatteryComponent battery, ElectrocutedEvent args) + { + if (args.ShockDamage == null || args.ShockDamage <= 0) + return; + + var damage = args.ShockDamage.Value * args.SiemensCoefficient; + var charge = Math.Min(damage * 300f, battery.MaxCharge * 0.25f) * _random.NextFloat(0.75f, 1.25f); + + battery.CurrentCharge += charge; + + if (!_gameTiming.InPrediction) + return; + + var message = Loc.GetString("battery-electrocute-charge"); + + _popup.PopupEntity(message, uid, uid); + } +} diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs index 82a6d246b4..00e6031bc1 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs @@ -54,7 +54,7 @@ private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponen private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent batteryComp) { var deadEvent = new SiliconChargeDeadEvent(uid, batteryComp); - RaiseLocalEvent(uid, deadEvent); + RaiseLocalEvent(uid, ref deadEvent); if (deadEvent.Cancelled) return; diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 3e1add5426..0bac084d85 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -252,7 +252,7 @@ private void BurnEntity(EntityUid entity, DamageableComponent damageComp, float if (damageDealt != null && chargerComp.warningAccumulator <= 0 && damageDealt.Total > 0) { - var popupBurn = Loc.GetString("system-silicon-charger-burn", ("charger", chargerUid), ("entity", entity)); + var popupBurn = Loc.GetString("silicon-charger-burn", ("charger", chargerUid), ("entity", entity)); _popup.PopupEntity(popupBurn, entity, PopupType.MediumCaution); chargerComp.warningAccumulator += 5f; } @@ -315,11 +315,11 @@ private void OnStartCollide(EntityUid uid, SiliconChargerComponent component, re { if (component.PresentEntities.Count >= component.MaxEntities) { - _popup.PopupEntity(Loc.GetString("system-silicon-charger-list-too-big"), target, target); + _popup.PopupEntity(Loc.GetString("silicon-charger-list-too-big"), target, target); return; } - _popup.PopupEntity(Loc.GetString("system-silicon-charger-add-to-list"), target, target); + _popup.PopupEntity(Loc.GetString("silicon-charger-add-to-list"), target, target); component.PresentEntities.Add(target); } diff --git a/Content.Shared/Electrocution/ElectrocutionEvents.cs b/Content.Shared/Electrocution/ElectrocutionEvents.cs index fe5753c7fb..8f87f7149b 100644 --- a/Content.Shared/Electrocution/ElectrocutionEvents.cs +++ b/Content.Shared/Electrocution/ElectrocutionEvents.cs @@ -24,12 +24,14 @@ public sealed class ElectrocutedEvent : EntityEventArgs public readonly EntityUid TargetUid; public readonly EntityUid? SourceUid; public readonly float SiemensCoefficient; + public readonly float? ShockDamage = null; // Parkstation-IPC - public ElectrocutedEvent(EntityUid targetUid, EntityUid? sourceUid, float siemensCoefficient) + public ElectrocutedEvent(EntityUid targetUid, EntityUid? sourceUid, float siemensCoefficient, float shockDamage) // Parkstation-IPC { TargetUid = targetUid; SourceUid = sourceUid; SiemensCoefficient = siemensCoefficient; + ShockDamage = shockDamage; // Parkstation-IPC } } } From 5f2508a753b276575fa5e6ff02aa58b3f2d7aa38 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 22 May 2023 01:42:05 -0400 Subject: [PATCH 34/60] Shocked batteries now charge based on damage dealt and DamagePerWatt --- Content.Server/Electrocution/ElectrocutionSystem.cs | 4 ++-- .../Power/Systems/BatteryElectrocuteChargeSystem.cs | 9 +++++---- .../Silicon/Charge/Systems/SiliconChargeDeathSystem.cs | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Content.Server/Electrocution/ElectrocutionSystem.cs b/Content.Server/Electrocution/ElectrocutionSystem.cs index 37e3a62ae8..fa101abcc0 100644 --- a/Content.Server/Electrocution/ElectrocutionSystem.cs +++ b/Content.Server/Electrocution/ElectrocutionSystem.cs @@ -51,7 +51,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem private const string DamageType = "Shock"; // Yes, this is absurdly small for a reason. - private const float ElectrifiedDamagePerWatt = 0.0015f; + public const float ElectrifiedDamagePerWatt = 0.0015f; // Parkstation-IPC private const float RecursiveDamageMultiplier = 0.75f; private const float RecursiveTimeMultiplier = 0.8f; @@ -387,7 +387,7 @@ private bool DoCommonElectrocution(EntityUid uid, EntityUid? sourceUid, var filter = Filter.PvsExcept(uid, entityManager: EntityManager); -- // TODO: Allow being able to pass EntityUid to Loc... + // TODO: Allow being able to pass EntityUid to Loc... if (sourceUid != null) { _popupSystem.PopupEntity(Loc.GetString("electrocuted-component-mob-shocked-by-source-popup-others", diff --git a/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs b/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs index 676904b6be..382106dddb 100644 --- a/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs +++ b/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs @@ -1,3 +1,4 @@ +using Content.Server.Electrocution; using Content.Server.Popups; using Content.Server.Power.Components; using Content.Shared.Electrocution; @@ -11,6 +12,7 @@ public sealed class BatteryElectrocuteChargeSystem : EntitySystem [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; + public override void Initialize() { base.Initialize(); @@ -23,14 +25,13 @@ private void OnElectrocuted(EntityUid uid, BatteryComponent battery, Electrocute if (args.ShockDamage == null || args.ShockDamage <= 0) return; + var damagePerWatt = ElectrocutionSystem.ElectrifiedDamagePerWatt * 2; + var damage = args.ShockDamage.Value * args.SiemensCoefficient; - var charge = Math.Min(damage * 300f, battery.MaxCharge * 0.25f) * _random.NextFloat(0.75f, 1.25f); + var charge = Math.Min(damage / damagePerWatt, battery.MaxCharge * 0.25f) * _random.NextFloat(0.75f, 1.25f); battery.CurrentCharge += charge; - if (!_gameTiming.InPrediction) - return; - var message = Loc.GetString("battery-electrocute-charge"); _popup.PopupEntity(message, uid, uid); diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs index 00e6031bc1..82a6d246b4 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs @@ -54,7 +54,7 @@ private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponen private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent batteryComp) { var deadEvent = new SiliconChargeDeadEvent(uid, batteryComp); - RaiseLocalEvent(uid, ref deadEvent); + RaiseLocalEvent(uid, deadEvent); if (deadEvent.Cancelled) return; From c26b681ee98aa6766e5b8d8a7229f1ada0845d43 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 22 May 2023 07:45:33 -0400 Subject: [PATCH 35/60] General minor clean up. Fixes prediction issue with charger lights, and I think the IPC prototype is officially ready for action. CyborgComponent is dumb... So very dumb... --- .../Nyanotrasen/Borgs/CyborgComponent.cs | 1 + .../Nyanotrasen/Borgs/CyborgSystem.cs | 1 + .../Charge/Systems/SiliconChargerSystem.cs | 76 ++------- .../Zombies/ZombifyOnDeathSystem.cs | 7 +- .../Components/SiliconChargerComponent.cs | 6 +- .../Systems/SharedSiliconChargerSystem.cs | 76 +++++++++ .../Entities/Mobs/Player/silicon_base.yml | 161 +++++++++--------- 7 files changed, 179 insertions(+), 149 deletions(-) rename {Content.Server/SimpleStation14/Silicon/Charge => Content.Shared/SimpleStation14/Silicon}/Components/SiliconChargerComponent.cs (92%) create mode 100644 Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconChargerSystem.cs diff --git a/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs b/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs index 6796715f53..da299c3b5a 100644 --- a/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs +++ b/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs @@ -1,5 +1,6 @@ namespace Content.Server.Borgs { + [Obsolete("CyborgComponent is unused on Parkstation, see SiliconComponent")] [RegisterComponent] public sealed class CyborgComponent : Component {} diff --git a/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs b/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs index cb96057459..50e04c689e 100644 --- a/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs +++ b/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs @@ -5,6 +5,7 @@ namespace Content.Server.Borgs { + [Obsolete("'Cyborg' should be unused on Parkstation, see SiliconSystem")] public sealed class Cyborg : EntitySystem { [Dependency] private readonly ChatSystem _chatSystem = default!; diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 0bac084d85..693d6b4435 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -22,10 +22,11 @@ using Content.Shared.Power; using Content.Shared.Storage.Components; using Content.Shared.Hands.Components; +using Content.Shared.SimpleStation14.Silicon.Charge; namespace Content.Server.SimpleStation14.Silicon.Charge; -public sealed class SiliconchargerCompSystem : EntitySystem +public sealed class SiliconChargerSystem : EntitySystem { [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!; @@ -37,6 +38,7 @@ public sealed class SiliconchargerCompSystem : EntitySystem [Dependency] private readonly HandsSystem _hands = default!; [Dependency] private readonly InventorySystem _inventory = default!; [Dependency] private readonly ExplosionSystem _explosion = default!; + [Dependency] private readonly SharedSiliconChargerSystem _sharedCharger = default!; public override void Initialize() { @@ -46,9 +48,6 @@ public override void Initialize() SubscribeLocalEvent(OnEndCollide); SubscribeLocalEvent(OnChargerShutdown); - - SubscribeLocalEvent(HandleStateOpen); - SubscribeLocalEvent(HandleStateClose); } public override void Update(float frameTime) @@ -66,7 +65,7 @@ public override void Update(float frameTime) if (EntityManager.TryGetComponent(uid, out var powerComp) && !powerComp.Powered) { if (chargerComp.Active != wasActive) - UpdateState(uid, chargerComp); + _sharedCharger.UpdateState(uid, chargerComp); continue; } @@ -89,9 +88,9 @@ public override void Update(float frameTime) } if (chargerComp.Active != wasActive) - UpdateState(uid, chargerComp); + _sharedCharger.UpdateState(uid, chargerComp); } - #endregion + #endregion Entity Storage Chargers #region Step Trigger Chargers // Check for any chargers with the StepTriggerComponent. @@ -104,7 +103,7 @@ public override void Update(float frameTime) if (chargerComp.Active) { chargerComp.Active = false; - UpdateState(uid, chargerComp); + _sharedCharger.UpdateState(uid, chargerComp); } continue; } @@ -112,7 +111,7 @@ public override void Update(float frameTime) if (!chargerComp.Active) { chargerComp.Active = true; - UpdateState(uid, chargerComp); + _sharedCharger.UpdateState(uid, chargerComp); } var chargeRate = frameTime * chargerComp.ChargeMulti / chargerComp.PresentEntities.Count; @@ -122,7 +121,7 @@ public override void Update(float frameTime) HandleChargingEntity(entity, chargeRate, chargerComp, uid, frameTime); } } - #endregion + #endregion Step Trigger Chargers } // Cleanup the sound stream when the charger is destroyed. @@ -158,16 +157,16 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true var entitiesToCharge = new List(); // If the given entity has a battery, charge it. - if (EntityManager.TryGetComponent(entity, out BatteryComponent? batteryComp) && - !EntityManager.TryGetComponent(entity, out var _) && + if (!EntityManager.TryGetComponent(entity, out var _) && + EntityManager.TryGetComponent(entity, out BatteryComponent? batteryComp) && batteryComp.CurrentCharge < batteryComp.MaxCharge) { entitiesToCharge.Add(entity); } // If the given entity contains a battery, charge it. - else if (EntityManager.TryGetComponent(entity, out PowerCellSlotComponent? cellSlotComp) && - !EntityManager.TryGetComponent(entity, out var _) && + else if (!EntityManager.TryGetComponent(entity, out var _) && + EntityManager.TryGetComponent(entity, out PowerCellSlotComponent? cellSlotComp) && _itemSlotsSystem.TryGetSlot(entity, cellSlotComp.CellSlotId, out var slot) && EntityManager.TryGetComponent(slot.Item, out var cellComp) && cellComp.CurrentCharge < cellComp.MaxCharge) @@ -175,7 +174,7 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true entitiesToCharge.Add(slot.Item.Value); } - // If the given entity DOESN'T have a battery, burn the fucker. + // If the given entity is fleshy, burn the fucker. else if (burn && EntityManager.TryGetComponent(entity, out var damageComp) && damageComp.DamageContainerID == "Biological") @@ -258,49 +257,6 @@ private void BurnEntity(EntityUid entity, DamageableComponent damageComp, float } } - /// - /// Updates the state of the charger when it's open or closed. - /// - private void HandleStateOpen(EntityUid uid, SiliconChargerComponent component, ref StorageAfterOpenEvent _) - { - UpdateState(uid, component); - } - - /// - private void HandleStateClose(EntityUid uid, SiliconChargerComponent component, ref StorageAfterCloseEvent _) - { - UpdateState(uid, component); - } - - /// - /// Updates the visual and auditory state of the charger based on if it's active, and/or open. - /// - private void UpdateState(EntityUid uid, SiliconChargerComponent? component = null) - { - if (!Resolve(uid, ref component)) - return; - - if (component.Active) - { - _appearance.SetData(uid, PowerDeviceVisuals.VisualState, SiliconChargerVisualState.Charging); - - if (component.SoundLoop != null && component.SoundStream == null) - component.SoundStream = - _audio.PlayPvs(component.SoundLoop, uid, AudioParams.Default.WithLoop(true).WithMaxDistance(5)); - } - else - { - var state = SiliconChargerVisualState.Normal; - - if (EntityManager.TryGetComponent(uid, out var storageComp) && storageComp.Open) - state = SiliconChargerVisualState.NormalOpen; - - _appearance.SetData(uid, PowerDeviceVisuals.VisualState, state); - component.SoundStream?.Stop(); - component.SoundStream = null; - } - } - #region Charger specific #region Step Trigger Chargers // When an entity starts colliding with the charger, add it to the list of entities present on the charger if it has the StepTriggerComponent. @@ -338,6 +294,6 @@ private void OnEndCollide(EntityUid uid, SiliconChargerComponent component, ref component.PresentEntities.Remove(target); } } - #endregion - #endregion + #endregion Step Trigger Chargers + #endregion Charger specific } diff --git a/Content.Server/Zombies/ZombifyOnDeathSystem.cs b/Content.Server/Zombies/ZombifyOnDeathSystem.cs index 67904217de..46a7bf04f0 100644 --- a/Content.Server/Zombies/ZombifyOnDeathSystem.cs +++ b/Content.Server/Zombies/ZombifyOnDeathSystem.cs @@ -30,6 +30,7 @@ using Content.Shared.Nutrition.Components; using Content.Shared.Popups; using Content.Shared.Roles; +using Content.Shared.SimpleStation14.Silicon.Components; // Parkstation-IPCs using Content.Shared.Weapons.Melee; using Content.Shared.Zombies; using Robust.Shared.Prototypes; @@ -91,9 +92,9 @@ public void ZombifyEntity(EntityUid target) //Don't zombfiy zombies if (HasComp(target)) return; - - //Don't zombify cyborg - if (HasComp(target)) + + //Don't zombify Roborgs + if (HasComp(target)) // Parkstation-IPCs return; //you're a real zombie now, son. diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconChargerComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs similarity index 92% rename from Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconChargerComponent.cs rename to Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs index cd95270349..5ca036f09e 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconChargerComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs @@ -1,8 +1,8 @@ -using Content.Server.Storage.Components; +using Content.Shared.Storage.Components; using Content.Shared.StepTrigger.Components; using Robust.Shared.Audio; -namespace Content.Server.SimpleStation14.Silicon; +namespace Content.Shared.SimpleStation14.Silicon; [RegisterComponent] public sealed class SiliconChargerComponent : Component @@ -50,7 +50,7 @@ public sealed class SiliconChargerComponent : Component /// The temperature the charger will stop heating up at. /// /// - /// Used specifically for chargers with the . + /// Used specifically for chargers with the . /// [DataField("targetTemp"), ViewVariables(VVAccess.ReadWrite)] public float TargetTemp = 365f; diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconChargerSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconChargerSystem.cs new file mode 100644 index 0000000000..c954b533bc --- /dev/null +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconChargerSystem.cs @@ -0,0 +1,76 @@ +using Content.Shared.Power; +using Content.Shared.Storage.Components; +using Robust.Shared.Audio; +using Robust.Shared.Timing; + +namespace Content.Shared.SimpleStation14.Silicon.Charge; + +public sealed class SharedSiliconChargerSystem : EntitySystem +{ + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(HandleStateOpen); + SubscribeLocalEvent(HandleStateClose); + } + + + /// + /// Updates the state of the charger when it's open or closed. + /// + private void HandleStateOpen(EntityUid uid, SiliconChargerComponent component, ref StorageAfterOpenEvent _) + { + UpdateState(uid, component); + } + + /// + private void HandleStateClose(EntityUid uid, SiliconChargerComponent component, ref StorageAfterCloseEvent _) + { + UpdateState(uid, component); + } + + /// + /// Updates the visual and auditory state of the charger based on if it's active, and/or open. + /// + public void UpdateState(EntityUid uid, SiliconChargerComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + if (component.Active) + { + _appearance.SetData(uid, PowerDeviceVisuals.VisualState, SiliconChargerVisualState.Charging); + + // If we're in prediction, return since Client doesn't have the information needed to handle this. + // Didn't seem to matter in practice, but probably for the best. + if (_timing.InPrediction) + return; + + if (component.SoundLoop != null && component.SoundStream == null) + component.SoundStream = + _audio.PlayPvs(component.SoundLoop, uid, AudioParams.Default.WithLoop(true).WithMaxDistance(5)); + } + else + { + var state = SiliconChargerVisualState.Normal; + + if (EntityManager.TryGetComponent(uid, out var storageComp) && storageComp.Open) + state = SiliconChargerVisualState.NormalOpen; + + _appearance.SetData(uid, PowerDeviceVisuals.VisualState, state); + + // If we're in prediction, return since Client doesn't have the information needed to handle this. + // Didn't seem to matter in practice, but probably for the best. + if (_timing.InPrediction) + return; + + component.SoundStream?.Stop(); + component.SoundStream = null; + } + } +} diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 95cf604c84..b4d57bc2e4 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -1,7 +1,7 @@ - type: entity save: false abstract: true - id: PlayerSiliconBase #for player controlled silicons + id: PlayerSiliconBase # For player controlled silicons components: - type: Reactive groups: @@ -56,8 +56,8 @@ prototype: Drone - type: DoAfter - type: Examiner - - type: Recyclable - safe: false + # - type: Recyclable + # safe: false - type: StandingState - type: Alerts - type: Silicon @@ -113,10 +113,69 @@ - type: Destructible thresholds: - trigger: !type:DamageTrigger - damage: 175 + damage: 500 behaviors: - - !type:DoActsBehavior - acts: ["Destruction"] + - !type:GibBehavior {} + - type: Icon + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: full + - type: Sprite + netsync: false + noRot: true + drawdepth: Mobs + layers: + - map: ["enum.HumanoidVisualLayers.Chest"] + - map: ["enum.HumanoidVisualLayers.Head"] + - map: ["enum.HumanoidVisualLayers.Snout"] + - map: ["enum.HumanoidVisualLayers.Eyes"] + - map: ["enum.HumanoidVisualLayers.RArm"] + - map: ["enum.HumanoidVisualLayers.LArm"] + - map: ["enum.HumanoidVisualLayers.RLeg"] + - map: ["enum.HumanoidVisualLayers.LLeg"] + - shader: StencilClear + sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + state: l_leg + - shader: StencilMask + map: ["enum.HumanoidVisualLayers.StencilMask"] + sprite: Mobs/Customization/masking_helpers.rsi + state: female_full + visible: false + - map: ["enum.HumanoidVisualLayers.LFoot"] + - map: ["enum.HumanoidVisualLayers.RFoot"] + - map: ["socks"] + - map: ["underpants"] + - map: ["undershirt"] + - map: ["jumpsuit"] + - map: ["enum.HumanoidVisualLayers.LHand"] + - map: ["enum.HumanoidVisualLayers.RHand"] + - map: ["enum.HumanoidVisualLayers.Handcuffs"] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: ["id"] + - map: ["gloves"] + - map: ["shoes"] + - map: ["ears"] + - map: ["outerClothing"] + - map: ["eyes"] + - map: ["belt"] + - map: ["neck"] + - map: ["back"] + - map: ["enum.HumanoidVisualLayers.FacialHair"] + - map: ["enum.HumanoidVisualLayers.Hair"] + - map: ["enum.HumanoidVisualLayers.HeadSide"] + - map: ["enum.HumanoidVisualLayers.HeadTop"] + - map: ["mask"] + - map: ["head"] + - map: ["pocket1"] + - map: ["pocket2"] + - map: ["enum.HumanoidVisualLayers.Tail"] + - map: ["enum.HumanoidVisualLayers.Wings"] + - map: ["clownedon"] # Dynamically generated + sprite: "Effects/creampie.rsi" + state: "creampie_human" + visible: false - type: Repairable fuelcost: 60 doAfterDelay: 32 @@ -142,6 +201,10 @@ damage: types: Heat: 0.75 #per second, scales with number of fire 'stacks' + # - type: Barotrauma # Not particularly modifiable. In the future, some response to pressure changes would be nice. + # damage: + # types: + # Blunt: 0.28 #per second, scales with pressure and other constants. - type: Temperature heatDamageThreshold: 320 coldDamageThreshold: 255 @@ -232,6 +295,13 @@ requiredLegs: 2 - type: Ensnareable sprite: Objects/Misc/ensnare.rsi + - type: Speech + speechSounds: Pai + - type: Vocal + sounds: + Male: MaleHuman + Female: FemaleHuman + Unsexed: MaleHuman - type: MeleeWeapon hidden: true soundHit: @@ -241,18 +311,12 @@ attackRate: 1 damage: types: - Blunt: 6 # It's metal. + Blunt: 6 # It's tough. - type: MobPrice price: 1500 # Kidnapping a living person and selling them for cred is a good move. deathPenalty: 0.01 # However they really ought to be living and intact, otherwise they're worth 100x less. - type: Pullable - type: Puller - - # Things that likely need to change, taken from human. - - type: Barotrauma - damage: - types: - Blunt: 0.28 #per second, scales with pressure and other constants. - type: Reactive groups: Flammable: [Touch] @@ -277,78 +341,9 @@ damageOverlayGroups: Brute: sprite: Mobs/Effects/brute_damage.rsi - color: "#FF0000" + color: "#DD8822" Burn: sprite: Mobs/Effects/burn_damage.rsi - - type: Speech - speechSounds: Pai - - type: Vocal - sounds: - Male: MaleHuman - Female: FemaleHuman - Unsexed: MaleHuman - - - type: Icon - sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi - state: full - - type: Sprite - netsync: false - noRot: true - drawdepth: Mobs - layers: - - map: ["enum.HumanoidVisualLayers.Chest"] - - map: ["enum.HumanoidVisualLayers.Head"] - - map: ["enum.HumanoidVisualLayers.Snout"] - - map: ["enum.HumanoidVisualLayers.Eyes"] - - map: ["enum.HumanoidVisualLayers.RArm"] - - map: ["enum.HumanoidVisualLayers.LArm"] - - map: ["enum.HumanoidVisualLayers.RLeg"] - - map: ["enum.HumanoidVisualLayers.LLeg"] - - shader: StencilClear - sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi - state: l_leg - - shader: StencilMask - map: ["enum.HumanoidVisualLayers.StencilMask"] - sprite: Mobs/Customization/masking_helpers.rsi - state: female_full - visible: false - - map: ["enum.HumanoidVisualLayers.LFoot"] - - map: ["enum.HumanoidVisualLayers.RFoot"] - - map: ["socks"] - - map: ["underpants"] - - map: ["undershirt"] - - map: ["jumpsuit"] - - map: ["enum.HumanoidVisualLayers.LHand"] - - map: ["enum.HumanoidVisualLayers.RHand"] - - map: ["enum.HumanoidVisualLayers.Handcuffs"] - color: "#ffffff" - sprite: Objects/Misc/handcuffs.rsi - state: body-overlay-2 - visible: false - - map: ["id"] - - map: ["gloves"] - - map: ["shoes"] - - map: ["ears"] - - map: ["outerClothing"] - - map: ["eyes"] - - map: ["belt"] - - map: ["neck"] - - map: ["back"] - - map: ["enum.HumanoidVisualLayers.FacialHair"] - - map: ["enum.HumanoidVisualLayers.Hair"] - - map: ["enum.HumanoidVisualLayers.HeadSide"] - - map: ["enum.HumanoidVisualLayers.HeadTop"] - - map: ["mask"] - - map: ["head"] - - map: ["pocket1"] - - map: ["pocket2"] - - map: ["enum.HumanoidVisualLayers.Tail"] - - map: ["enum.HumanoidVisualLayers.Wings"] - - map: ["clownedon"] # Dynamically generated - sprite: "Effects/creampie.rsi" - state: "creampie_human" - visible: false - # Organs - type: IdExaminable - type: HealthExaminable From 56ed80aabbe04614e1e39ddb60ddf4dd45fe3af5 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 22 May 2023 07:51:10 -0400 Subject: [PATCH 36/60] Review suggestions --- .../Silicon/Systems/SharedSiliconSystem.cs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs index ec1bbabb9f..0e7abef928 100644 --- a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Movement.Systems; namespace Content.Shared.SimpleStation14.Silicon.Systems; + public sealed class SharedSiliconChargeSystem : EntitySystem { [Dependency] private readonly AlertsSystem _alertsSystem = default!; @@ -44,22 +45,22 @@ private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconComponent componen private void OnRefreshMovespeed(EntityUid uid, SiliconComponent component, RefreshMovementSpeedModifiersEvent args) { - if (component.BatteryPowered) - { - var speedModThresholds = component.SpeedModifierThresholds; - - var closest = -0.5f; + if (!component.BatteryPowered) + return; - foreach (var state in speedModThresholds) - { - if (component.ChargeState >= state.Key && ((float)state.Key) > closest) - closest = ((float)state.Key); - } + var speedModThresholds = component.SpeedModifierThresholds; - var speedMod = speedModThresholds[(ChargeState)closest]; + var closest = -0.5f; - args.ModifySpeed(speedMod, speedMod); + foreach (var state in speedModThresholds) + { + if (component.ChargeState >= state.Key && ((float) state.Key) > closest) + closest = ((float) state.Key); } + + var speedMod = speedModThresholds[(ChargeState)closest]; + + args.ModifySpeed(speedMod, speedMod); } } From af4b891f41b54155f1d68378a6acb76bed8fffd4 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Wed, 24 May 2023 15:05:20 -0400 Subject: [PATCH 37/60] General, minor cleanup. Also commented out some IPC antenna that need separate layer colours. --- Content.Server/Bed/BedSystem.cs | 4 +- .../Nyanotrasen/Borgs/CyborgComponent.cs | 2 +- .../Nyanotrasen/Borgs/CyborgSystem.cs | 2 +- .../Components/BatteryDrinkerComponent.cs | 2 +- .../Temperature/Systems/TemperatureSystem.cs | 8 ++-- Content.Shared/Alert/AlertType.cs | 5 +- .../Components/SiliconChargerComponent.cs | 6 +-- .../Entities/Mobs/Customization/antenna.yml | 48 +++++++++---------- 8 files changed, 37 insertions(+), 40 deletions(-) diff --git a/Content.Server/Bed/BedSystem.cs b/Content.Server/Bed/BedSystem.cs index d4790d7dee..e45c8d0d34 100644 --- a/Content.Server/Bed/BedSystem.cs +++ b/Content.Server/Bed/BedSystem.cs @@ -16,7 +16,7 @@ using Content.Shared.Mobs.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Timing; -using Content.Shared.SimpleStation14.Silicon.Components; // Parkstation: Silicons. I shouldn't have to modify this. +using Content.Shared.SimpleStation14.Silicon.Components; // Parkstation-IPCs // I shouldn't have to modify this. namespace Content.Server.Bed { @@ -75,7 +75,7 @@ public override void Update(float frameTime) foreach (var healedEntity in strapComponent.BuckledEntities) { - if (_mobStateSystem.IsDead(healedEntity) || HasComp(healedEntity)) // Parkstation: Silicons. I shouldn't have to modify this. + if (_mobStateSystem.IsDead(healedEntity) || HasComp(healedEntity)) // Parkstation-IPCs // I shouldn't have to modify this. continue; var damage = bedComponent.Damage; diff --git a/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs b/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs index da299c3b5a..4311e27b89 100644 --- a/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs +++ b/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs @@ -1,6 +1,6 @@ namespace Content.Server.Borgs { - [Obsolete("CyborgComponent is unused on Parkstation, see SiliconComponent")] + [Obsolete("CyborgComponent is unused on Parkstation, see SiliconComponent")] // Parkstation-IPCs [RegisterComponent] public sealed class CyborgComponent : Component {} diff --git a/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs b/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs index 50e04c689e..c82fdf6215 100644 --- a/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs +++ b/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs @@ -5,7 +5,7 @@ namespace Content.Server.Borgs { - [Obsolete("'Cyborg' should be unused on Parkstation, see SiliconSystem")] + [Obsolete("'Cyborg' should be unused on Parkstation, see SiliconSystem")] // Parkstation-IPCs public sealed class Cyborg : EntitySystem { [Dependency] private readonly ChatSystem _chatSystem = default!; diff --git a/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs b/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs index 43e61a0b10..ca51684709 100644 --- a/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs +++ b/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs @@ -12,7 +12,7 @@ public class BatteryDrinkerComponent : Component public bool DrinkAll = false; /// - /// How long it takes to drink from the battery, in seconds. + /// How long it takes to drink from a battery, in seconds. /// Is mutliplied by the source. /// [DataField("drinkSpeed"), ViewVariables(VVAccess.ReadWrite)] diff --git a/Content.Server/Temperature/Systems/TemperatureSystem.cs b/Content.Server/Temperature/Systems/TemperatureSystem.cs index b2ccc43a81..cd1653dbef 100644 --- a/Content.Server/Temperature/Systems/TemperatureSystem.cs +++ b/Content.Server/Temperature/Systems/TemperatureSystem.cs @@ -4,7 +4,7 @@ using Content.Server.Administration.Logs; using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; -using Content.Server.Body.Components; +using Content.Server.Body.Components; // Parkstation-IPCs using Content.Server.Temperature.Components; using Content.Shared.Alert; using Content.Shared.Damage; @@ -38,7 +38,7 @@ public override void Initialize() { SubscribeLocalEvent(EnqueueDamage); SubscribeLocalEvent(OnAtmosExposedUpdate); - SubscribeLocalEvent(ServerAlertNotDumb); // See ServerAlert for how upstream handled it. + SubscribeLocalEvent(ServerAlertNotDumb); // Parkstation-IPCs // See ServerAlert for how upstream handled it. SubscribeLocalEvent>( OnTemperatureChangeAttempt); @@ -168,7 +168,7 @@ private void ServerAlert(EntityUid uid, AlertsComponent status, OnTemperatureCha } } - /// Parkstation Temperature Alerts + // Parkstation-IPCs-Start /// /// Finds the TemperatureComponent and the ThermalRegulatorComponent, and uses _alertsSystem to set the alert level based on the range of temperatures as allowed by those components. /// Does some math to determine the alert level based on the current temperature and the range of temperatures allowed by the ThermalRegulatorComponent. @@ -241,7 +241,7 @@ private void ServerAlertNotDumb(EntityUid uid, AlertsComponent status, OnTempera return; } } - /// Parkstation Temperature Alerts + /// Parkstation-IPCs-End private void EnqueueDamage(EntityUid uid, TemperatureComponent component, OnTemperatureChangeEvent args) { diff --git a/Content.Shared/Alert/AlertType.cs b/Content.Shared/Alert/AlertType.cs index 56b6d23581..30b46f4b38 100644 --- a/Content.Shared/Alert/AlertType.cs +++ b/Content.Shared/Alert/AlertType.cs @@ -27,6 +27,7 @@ public enum AlertType : byte Starving, Thirsty, Parched, + Charge // Parkstation-IPC Stamina, Pulled, Pulling, @@ -45,10 +46,6 @@ public enum AlertType : byte Debug4, Debug5, Debug6, - - // Start of Parkstation alerts - Charge - // End of Parkstation alerts } } diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs index 5ca036f09e..3dee4bed14 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs @@ -34,13 +34,13 @@ public sealed class SiliconChargerComponent : Component /// For reference, an IPC drains at 50. /// [DataField("chargeMulti"), ViewVariables(VVAccess.ReadWrite)] - public float ChargeMulti = 150f; + public float ChargeMulti = 50f; /// /// The minimum size of a battery to be charged. /// /// - /// Charging a battery too small will detonate it, becoming more likely if it's already full. + /// Charging a battery too small will detonate it, becoming more likely as it fills. /// [DataField("minChargeSize"), ViewVariables(VVAccess.ReadWrite)] public int MinChargeSize = 1000; @@ -53,7 +53,7 @@ public sealed class SiliconChargerComponent : Component /// Used specifically for chargers with the . /// [DataField("targetTemp"), ViewVariables(VVAccess.ReadWrite)] - public float TargetTemp = 365f; + public float TargetTemp = 373.15f; /// diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/antenna.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/antenna.yml index 54ab04c1e4..ec58320e7b 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/antenna.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Customization/antenna.yml @@ -16,23 +16,23 @@ - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi state: ipc_antenna_tesla -- type: marking - speciesRestriction: [IPC] - id: RobotAntennaLightb - bodyPart: Hair - markingCategory: Hair - sprites: - - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi - state: ipc_antenna_lightb +# - type: marking +# speciesRestriction: [IPC] +# id: RobotAntennaLightb +# bodyPart: Hair +# markingCategory: Hair +# sprites: +# - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi +# state: ipc_antenna_lightb -- type: marking - speciesRestriction: [IPC] - id: RobotAntennaLight - bodyPart: Hair - markingCategory: Hair - sprites: - - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi - state: ipc_antenna_light +# - type: marking +# speciesRestriction: [IPC] +# id: RobotAntennaLight +# bodyPart: Hair +# markingCategory: Hair +# sprites: +# - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi +# state: ipc_antenna_light - type: marking speciesRestriction: [IPC] @@ -43,14 +43,14 @@ - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi state: ipc_antenna_cyberhead -- type: marking - speciesRestriction: [IPC] - id: RobotAntennaSidelights - bodyPart: Hair - markingCategory: Hair - sprites: - - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi - state: ipc_antenna_sidelights +# - type: marking +# speciesRestriction: [IPC] +# id: RobotAntennaSidelights +# bodyPart: Hair +# markingCategory: Hair +# sprites: +# - sprite: SimpleStation14/Mobs/Customization/ipc_antenna.rsi +# state: ipc_antenna_sidelights - type: marking speciesRestriction: [IPC] From 3a2a6c955f30f5f5ff058cbadbb91f3501b52e38 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 19 Jun 2023 15:14:37 -0400 Subject: [PATCH 38/60] Fixed the errors and cleaned up a bit --- .../Power/Systems/BatteryDrinkerSystem.cs | 20 ++--- .../Charge/Systems/SiliconChargeSystem.cs | 4 +- .../Charge/Systems/SiliconChargerSystem.cs | 81 +++++++++---------- Content.Shared/Alert/AlertType.cs | 2 +- .../Components/SiliconChargerComponent.cs | 16 +++- 5 files changed, 67 insertions(+), 56 deletions(-) diff --git a/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs index 1e84894669..c5ab29945e 100644 --- a/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs +++ b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs @@ -10,6 +10,7 @@ using Robust.Shared.Serialization; using Robust.Shared.Utility; using Content.Server.SimpleStation14.Silicon.Charge; +using Content.Server.Power.EntitySystems; namespace Content.Server.SimpleStation14.Power; @@ -18,6 +19,7 @@ public sealed class BatteryDrinkerSystem : EntitySystem [Dependency] private readonly ItemSlotsSystem _slots = default!; [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly BatterySystem _battery = default!; public override void Initialize() { @@ -40,9 +42,9 @@ private void AddAltVerb(EntityUid uid, BatteryComponent batteryComponent, GetVer AlternativeVerb verb = new() { - Act = () => DrinkBattery(uid, args.User, batteryComponent, drinkerBattery, drinkerComp), + Act = () => DrinkBattery(uid, args.User, drinkerComp), Text = "system-battery-drinker-verb-drink", - Icon = new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/VerbIcons/drink.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/drink.svg.192dpi.png")), }; args.Verbs.Add(verb); @@ -59,8 +61,6 @@ private bool TestDrinkableBattery(EntityUid target, BatteryDrinkerComponent drin private bool TryGetFillableBattery(EntityUid uid, [NotNullWhen(true)] out BatteryComponent? battery) { - battery = null; - if (EntityManager.TryGetComponent(uid, out battery)) return true; @@ -73,7 +73,7 @@ private bool TryGetFillableBattery(EntityUid uid, [NotNullWhen(true)] out Batter return false; } - private void DrinkBattery(EntityUid target, EntityUid user, BatteryComponent batteryComp, BatteryComponent drinkerBatteryComp, BatteryDrinkerComponent drinkerComp) + private void DrinkBattery(EntityUid target, EntityUid user, BatteryDrinkerComponent drinkerComp) { var doAfterTime = drinkerComp.DrinkSpeed; @@ -92,7 +92,7 @@ private void DrinkBattery(EntityUid target, EntityUid user, BatteryComponent bat CancelDuplicate = false }; - var doAfter = _doAfter.TryStartDoAfter(args); + _doAfter.TryStartDoAfter(args); } private void OnDoAfter(EntityUid uid, BatteryDrinkerComponent drinkerComp, DoAfterEvent args) @@ -129,14 +129,14 @@ private void OnDoAfter(EntityUid uid, BatteryDrinkerComponent drinkerComp, DoAft return; } - if (sourceBattery.TryUseCharge(amountToDrink)) + if (_battery.TryUseCharge(source, amountToDrink, sourceBattery)) { - drinkerBattery.CurrentCharge += amountToDrink; + _battery.SetCharge(source, drinkerBattery.Charge + amountToDrink, sourceBattery); } else { - drinkerBattery.CurrentCharge += sourceBattery.CurrentCharge; - sourceBattery.CurrentCharge = 0; + _battery.SetCharge(drinker, sourceBattery.Charge, drinkerBattery); + _battery.SetCharge(source, 0, sourceBattery); } var sound = drinkerComp.DrinkSound ?? sourceComp?.DrinkSound; diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs index bd19632bab..b653919f0c 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs @@ -14,6 +14,7 @@ using Content.Server.Body.Components; using Robust.Shared.Utility; using System.Linq; +using Content.Server.Power.EntitySystems; namespace Content.Server.SimpleStation14.Silicon.Charge; @@ -25,6 +26,7 @@ public sealed class SiliconChargeSystem : EntitySystem [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; + [Dependency] private readonly BatterySystem _battery = default!; public override void Initialize() { @@ -80,7 +82,7 @@ public override void Update(float frameTime) drainRate += Math.Clamp(drainRateFinalAddi, drainRate * -0.9f, batteryComp.MaxCharge / 240); // Drain the battery. - batteryComp.UseCharge(frameTime * drainRate); + _battery.UseCharge(silicon, frameTime * drainRate, batteryComp); // Figure out the current state of the Silicon. var chargePercent = batteryComp.CurrentCharge / batteryComp.MaxCharge; diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 693d6b4435..e37f13f195 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -1,44 +1,43 @@ +using Content.Server.Explosion.Components; +using Content.Server.Explosion.EntitySystems; +using Content.Server.Hands.Systems; +using Content.Server.Popups; using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; using Content.Server.Storage.Components; -using Content.Shared.PowerCell.Components; using Content.Shared.Containers.ItemSlots; using Content.Shared.Damage; -using Robust.Shared.Prototypes; using Content.Shared.Damage.Prototypes; -using Content.Server.Popups; -using Robust.Shared.Player; +using Content.Shared.Hands.Components; +using Content.Shared.Interaction.Components; +using Content.Shared.Inventory; using Content.Shared.Popups; +using Content.Shared.Power; +using Content.Shared.PowerCell.Components; +using Content.Shared.SimpleStation14.Silicon; +using Content.Shared.SimpleStation14.Silicon.Charge; using Content.Shared.StepTrigger.Components; +using Content.Shared.Storage.Components; +using Robust.Server.GameObjects; +using Robust.Shared.Audio; using Robust.Shared.Physics.Events; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; using Robust.Shared.Timing; -using Content.Shared.SimpleStation14.Silicon; -using Robust.Shared.Audio; -using Robust.Server.GameObjects; -using Content.Shared.Inventory; -using Content.Server.Hands.Systems; -using Content.Server.Explosion.Components; -using Content.Server.Explosion.EntitySystems; -using Content.Shared.Interaction.Components; -using Content.Shared.Power; -using Content.Shared.Storage.Components; -using Content.Shared.Hands.Components; -using Content.Shared.SimpleStation14.Silicon.Charge; namespace Content.Server.SimpleStation14.Silicon.Charge; public sealed class SiliconChargerSystem : EntitySystem { - [Dependency] private readonly ItemSlotsSystem _itemSlotsSystem = default!; - [Dependency] private readonly DamageableSystem _damageableSystem = default!; - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [Dependency] private readonly ItemSlotsSystem _itemSlots = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly IPrototypeManager _prototypes = default!; [Dependency] private readonly PopupSystem _popup = default!; - [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly HandsSystem _hands = default!; [Dependency] private readonly InventorySystem _inventory = default!; [Dependency] private readonly ExplosionSystem _explosion = default!; [Dependency] private readonly SharedSiliconChargerSystem _sharedCharger = default!; + [Dependency] private readonly BatterySystem _battery = default!; public override void Initialize() { @@ -95,10 +94,10 @@ public override void Update(float frameTime) #region Step Trigger Chargers // Check for any chargers with the StepTriggerComponent. var stepQuery = EntityQueryEnumerator(); - while (stepQuery.MoveNext(out var uid, out var chargerComp, out var stepTrigger)) + while (stepQuery.MoveNext(out var uid, out var chargerComp, out _)) { if (chargerComp.PresentEntities.Count == 0 || - (EntityManager.TryGetComponent(uid, out var powerComp) && !powerComp.Powered)) + TryComp(uid, out var powerComp) && !powerComp.Powered) { if (chargerComp.Active) { @@ -145,7 +144,7 @@ private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconCha foreach (var entityToCharge in entitiesToCharge) { - if (EntityManager.TryGetComponent(entityToCharge, out var batteryComp)) + if (EntityManager.TryGetComponent(entityToCharge, out _)) ChargeBattery(entityToCharge, EntityManager.GetComponent(entityToCharge), chargeRate, chargerComp, chargerUid); else if (EntityManager.TryGetComponent(entityToCharge, out var damageComp)) BurnEntity(entityToCharge, damageComp, frameTime, chargerComp, chargerUid); @@ -157,7 +156,7 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true var entitiesToCharge = new List(); // If the given entity has a battery, charge it. - if (!EntityManager.TryGetComponent(entity, out var _) && + if (!EntityManager.TryGetComponent(entity, out _) && EntityManager.TryGetComponent(entity, out BatteryComponent? batteryComp) && batteryComp.CurrentCharge < batteryComp.MaxCharge) { @@ -165,9 +164,9 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true } // If the given entity contains a battery, charge it. - else if (!EntityManager.TryGetComponent(entity, out var _) && + else if (!EntityManager.TryGetComponent(entity, out _) && EntityManager.TryGetComponent(entity, out PowerCellSlotComponent? cellSlotComp) && - _itemSlotsSystem.TryGetSlot(entity, cellSlotComp.CellSlotId, out var slot) && + _itemSlots.TryGetSlot(entity, cellSlotComp.CellSlotId, out var slot) && EntityManager.TryGetComponent(slot.Item, out var cellComp) && cellComp.CurrentCharge < cellComp.MaxCharge) { @@ -200,7 +199,7 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true } if (EntityManager.TryGetComponent(entity, out var storageComp)) { - foreach ( var containedEntity in storageComp.StoredEntities!) + foreach (var containedEntity in storageComp.StoredEntities!) { entitiesToCharge.AddRange(SearchThroughEntities(containedEntity)); } @@ -221,44 +220,40 @@ private void ChargeBattery(EntityUid entity, BatteryComponent batteryComp, float // Do some math so a charger never charges a battery from zero to full in less than 10 seconds, just for the effect of it. if (chargerComp.ChargeMulti * 10 > batteryComp.MaxCharge / 10) { - chargeRate /= (chargerComp.ChargeMulti * 10) / (batteryComp.MaxCharge / 10); + chargeRate /= chargerComp.ChargeMulti * 10 / (batteryComp.MaxCharge / 10); } if (batteryComp.CurrentCharge + chargeRate < batteryComp.MaxCharge) - batteryComp.CurrentCharge += chargeRate; + _battery.SetCharge(entity, batteryComp.CurrentCharge + chargeRate, batteryComp); else - batteryComp.CurrentCharge = batteryComp.MaxCharge; + _battery.SetCharge(entity, batteryComp.MaxCharge, batteryComp); // If the battery is too small, explode it. if ((batteryComp.MaxCharge - batteryComp.CurrentCharge) * 1.2 + batteryComp.MaxCharge < chargerComp.MinChargeSize) { if (EntityManager.TryGetComponent(entity, out var explosiveComp)) - { _explosion.TriggerExplosive(entity, explosiveComp); - } else - { _explosion.QueueExplosion(entity, "Default", batteryComp.MaxCharge / 50, 1.5f, 200, user: chargerUid); - } } } private void BurnEntity(EntityUid entity, DamageableComponent damageComp, float frameTime, SiliconChargerComponent chargerComp, EntityUid chargerUid) { - var damage = new DamageSpecifier(_prototypeManager.Index("Shock"), frameTime * chargerComp.ChargeMulti / 100); - var damageDealt = _damageableSystem.TryChangeDamage(entity, damage, false, true, damageComp, chargerUid); - chargerComp.warningAccumulator -= frameTime; + var damage = new DamageSpecifier(_prototypes.Index(chargerComp.DamageType), frameTime * chargerComp.ChargeMulti / 100); + var damageDealt = _damageable.TryChangeDamage(entity, damage, false, true, damageComp, chargerUid); + chargerComp.WarningAccumulator -= frameTime; - if (damageDealt != null && chargerComp.warningAccumulator <= 0 && damageDealt.Total > 0) + if (damageDealt != null && chargerComp.WarningAccumulator <= 0 && damageDealt.Total > 0) { var popupBurn = Loc.GetString("silicon-charger-burn", ("charger", chargerUid), ("entity", entity)); _popup.PopupEntity(popupBurn, entity, PopupType.MediumCaution); - chargerComp.warningAccumulator += 5f; + chargerComp.WarningAccumulator += 5f; } } #region Charger specific - #region Step Trigger Chargers + #region Step Trigger Chargers // When an entity starts colliding with the charger, add it to the list of entities present on the charger if it has the StepTriggerComponent. private void OnStartCollide(EntityUid uid, SiliconChargerComponent component, ref StartCollideEvent args) { @@ -294,6 +289,6 @@ private void OnEndCollide(EntityUid uid, SiliconChargerComponent component, ref component.PresentEntities.Remove(target); } } - #endregion Step Trigger Chargers + #endregion Step Trigger Chargers #endregion Charger specific } diff --git a/Content.Shared/Alert/AlertType.cs b/Content.Shared/Alert/AlertType.cs index 30b46f4b38..0bcd5fae7d 100644 --- a/Content.Shared/Alert/AlertType.cs +++ b/Content.Shared/Alert/AlertType.cs @@ -27,7 +27,7 @@ public enum AlertType : byte Starving, Thirsty, Parched, - Charge // Parkstation-IPC + Charge, // Parkstation-IPC Stamina, Pulled, Pulling, diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs index 3dee4bed14..47d76495fa 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs @@ -20,7 +20,7 @@ public sealed class SiliconChargerComponent : Component /// /// Counter for handing out warnings to burning entities. /// - public float warningAccumulator = 0f; + public float WarningAccumulator = 0f; /// @@ -45,6 +45,14 @@ public sealed class SiliconChargerComponent : Component [DataField("minChargeSize"), ViewVariables(VVAccess.ReadWrite)] public int MinChargeSize = 1000; + /// + /// The minimum amount of time it will take to charge a battery, in seconds. + /// + /// + /// This is for the sake of feeling cooler- It's lame to just charge instantly. + /// + [DataField("minChargeTime"), ViewVariables(VVAccess.ReadWrite)] + public float MinChargeTime = 10f; /// /// The temperature the charger will stop heating up at. @@ -55,6 +63,12 @@ public sealed class SiliconChargerComponent : Component [DataField("targetTemp"), ViewVariables(VVAccess.ReadWrite)] public float TargetTemp = 373.15f; + /// + /// The damage type to deal when a Biological entity is burned. + /// + [DataField("damageType")] + public string DamageType = "Shock"; + /// /// The list of entities currently stood on a charger. From 86965c64799533a86edab5f6f7c9c0399ad03499 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:05:01 -0400 Subject: [PATCH 39/60] Several changes and fixes. Cleaned up several parts of the code, fixed some merge issues (leg speed and slots), added FTLs for loc strings, improved aspects of charging, made chargers constructable using part upgrades. --- .../Systems/SiliconChargeDeathSystem.cs | 44 +++++--- .../Charge/Systems/SiliconChargeSystem.cs | 55 ++++------ .../Charge/Systems/SiliconChargerSystem.cs | 102 +++++++++++------- .../Components/SiliconChargerComponent.cs | 35 +++++- .../Content/Silicons/siliconChargers.ftl | 5 + .../Content/Silicons/silicons.ftl | 1 + .../SimpleStation14/Body/Parts/ipc.yml | 4 +- .../Entities/Mobs/Player/silicon_base.yml | 1 + .../Devices/Circuitboards/siliconchargers.yml | 34 ++++++ .../Structures/Machines/silicon_chargers.yml | 42 ++++++++ 10 files changed, 227 insertions(+), 96 deletions(-) create mode 100644 Resources/Locale/en-US/SimpleStation14/Content/Silicons/siliconChargers.ftl create mode 100644 Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl create mode 100644 Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Circuitboards/siliconchargers.yml diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs index 82a6d246b4..180283f174 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs @@ -1,26 +1,15 @@ using Content.Server.Power.Components; -using Content.Shared.Mobs; -using Content.Shared.Mobs.Components; -using Content.Shared.Mobs.Systems; using Content.Shared.SimpleStation14.Silicon.Components; using Content.Shared.SimpleStation14.Silicon.Systems; using Robust.Shared.Utility; -using Content.Shared.Stunnable; -using Content.Shared.StatusEffect; using Content.Server.Bed.Sleep; using Content.Shared.Bed.Sleep; -using Robust.Shared.Audio; using Content.Server.Sound.Components; namespace Content.Server.SimpleStation14.Silicon.Death; public sealed class SiliconDeathSystem : EntitySystem { - // [Dependency] private readonly IRobustRandom _random = default!; - // [Dependency] private readonly FlammableSystem _flammableSystem = default!; - // [Dependency] private readonly PopupSystem _popup = default!; - // [Dependency] private readonly IGameTiming _gameTiming = default!; - // [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; [Dependency] private readonly SleepingSystem _sleepSystem = default!; public override void Initialize() @@ -53,13 +42,13 @@ private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponen private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent batteryComp) { - var deadEvent = new SiliconChargeDeadEvent(uid, batteryComp); + var deadEvent = new SiliconChargeDyingEvent(uid, batteryComp); RaiseLocalEvent(uid, deadEvent); if (deadEvent.Cancelled) return; - var sleepComp = EntityManager.EnsureComponent(uid); + EntityManager.EnsureComponent(uid); RemComp(uid); // This is also fucking stupid, I once again hate the sleeping system. EntityManager.EnsureComponent(uid); @@ -73,23 +62,29 @@ private void SiliconUnDead(EntityUid uid, SiliconDownOnDeadComponent siliconDead _sleepSystem.TryWaking(uid, null, true); siliconDeadComp.Dead = false; + + RaiseLocalEvent(uid, new SiliconChargeAliveEvent(uid, batteryComp)); } } - - -public sealed class SiliconChargeDeadEvent : CancellableEntityEventArgs +/// +/// A canellable event raised when a Silicon is about to go down due to charge. +/// +public sealed class SiliconChargeDyingEvent : CancellableEntityEventArgs { public EntityUid SiliconUid { get; } public BatteryComponent BatteryComp { get; } - public SiliconChargeDeadEvent(EntityUid siliconUid, BatteryComponent batteryComp) + public SiliconChargeDyingEvent(EntityUid siliconUid, BatteryComponent batteryComp) { SiliconUid = siliconUid; BatteryComp = batteryComp; } } +/// +/// An event raised after a Silicon has gone down due to charge. +/// public sealed class SiliconChargeDeathEvent : EntityEventArgs { public EntityUid SiliconUid { get; } @@ -101,3 +96,18 @@ public SiliconChargeDeathEvent(EntityUid siliconUid, BatteryComponent batteryCom BatteryComp = batteryComp; } } + +/// +/// An event raised after a Silicon has reawoken due to an increase in charge. +/// +public sealed class SiliconChargeAliveEvent : EntityEventArgs +{ + public EntityUid SiliconUid { get; } + public BatteryComponent BatteryComp { get; } + + public SiliconChargeAliveEvent(EntityUid siliconUid, BatteryComponent batteryComp) + { + SiliconUid = siliconUid; + BatteryComp = batteryComp; + } +} diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs index b653919f0c..a82324d2e3 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs @@ -1,19 +1,15 @@ using Robust.Shared.Random; using Content.Shared.SimpleStation14.Silicon.Components; using Content.Server.Power.Components; -using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Server.Temperature.Components; using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; using Content.Server.Popups; using Content.Shared.Popups; -using Robust.Shared.Timing; using Content.Shared.SimpleStation14.Silicon.Systems; using Content.Shared.Movement.Systems; using Content.Server.Body.Components; -using Robust.Shared.Utility; -using System.Linq; using Content.Server.Power.EntitySystems; namespace Content.Server.SimpleStation14.Silicon.Charge; @@ -24,7 +20,6 @@ public sealed class SiliconChargeSystem : EntitySystem [Dependency] private readonly MobStateSystem _mobStateSystem = default!; [Dependency] private readonly FlammableSystem _flammableSystem = default!; [Dependency] private readonly PopupSystem _popup = default!; - [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; [Dependency] private readonly BatterySystem _battery = default!; @@ -43,14 +38,14 @@ private void OnBatteryInit(EntityUid uid, BatteryComponent component, ComponentI !siliconComp.BatteryPowered) return; - component.MaxCharge *= _random.NextFloat(0.85f, 1.15f); + _battery.SetMaxCharge(uid, component.MaxCharge * _random.NextFloat(0.85f, 1.15f)); var batteryLevelFill = component.MaxCharge; if (siliconComp.StartCharged.Equals(StartChargedData.Randomized)) batteryLevelFill *= _random.NextFloat(0.40f, 0.80f); - component.CurrentCharge = batteryLevelFill; + _battery.SetCharge(uid, batteryLevelFill); } public override void Update(float frameTime) @@ -65,7 +60,7 @@ public override void Update(float frameTime) if (_mobStateSystem.IsDead(silicon)) continue; - var drainRate = 10 * (siliconComp.DrainRateMulti); + var drainRate = 10 * siliconComp.DrainRateMulti; // All multipliers will be subtracted by 1, and then added together, and then multiplied by the drain rate. This is then added to the base drain rate. // This is to stop exponential increases, while still allowing for less-than-one multipliers. @@ -87,32 +82,21 @@ public override void Update(float frameTime) // Figure out the current state of the Silicon. var chargePercent = batteryComp.CurrentCharge / batteryComp.MaxCharge; - ChargeState currentState; - switch (chargePercent) + var currentState = chargePercent switch { - case var x when x > siliconComp.ChargeStateThresholdMid: - currentState = ChargeState.Full; - break; - case var x when x > siliconComp.ChargeStateThresholdLow: - currentState = ChargeState.Mid; - break; - case var x when x > siliconComp.ChargeStateThresholdCritical: - currentState = ChargeState.Low; - break; - case var x when x > 0 || siliconComp.ChargeStateThresholdCritical == 0: - currentState = ChargeState.Critical; - break; - default: - currentState = ChargeState.Dead; - break; - } + var x when x > siliconComp.ChargeStateThresholdMid => ChargeState.Full, + var x when x > siliconComp.ChargeStateThresholdLow => ChargeState.Mid, + var x when x > siliconComp.ChargeStateThresholdCritical => ChargeState.Low, + var x when x > 0 || siliconComp.ChargeStateThresholdCritical == 0 => ChargeState.Critical, + _ => ChargeState.Dead, + }; // Check if anything needs to be updated. if (currentState != siliconComp.ChargeState) { siliconComp.ChargeState = currentState; - RaiseLocalEvent(silicon, new SiliconChargeStateUpdateEvent(currentState)); + RaiseLocalEvent(silicon, new SiliconChargeStateUpdateEvent(currentState)); _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(silicon); } @@ -130,24 +114,23 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) var siliconComp = EntityManager.GetComponent(silicon); // If the Silicon is hot, drain the battery faster, if it's cold, drain it slower, capped. - var upperThresh = thermalComp.NormalBodyTemperature + (thermalComp.ThermalRegulationTemperatureThreshold); - var lowerThresh = thermalComp.NormalBodyTemperature - (thermalComp.ThermalRegulationTemperatureThreshold); - var upperThreshHalf = thermalComp.NormalBodyTemperature + (thermalComp.ThermalRegulationTemperatureThreshold * 0.5f); + var upperThresh = thermalComp.NormalBodyTemperature + thermalComp.ThermalRegulationTemperatureThreshold; + var upperThreshHalf = thermalComp.NormalBodyTemperature + thermalComp.ThermalRegulationTemperatureThreshold * 0.5f; // Check if the silicon is in a hot environment. if (temperComp.CurrentTemperature > upperThreshHalf) { // Divide the current temp by the max comfortable temp capped to 4, then add that to the multiplier. var hotTempMulti = Math.Min(temperComp.CurrentTemperature / upperThreshHalf, 4); + // If the silicon is hot enough, it has a chance to catch fire. - FlammableComponent? flamComp = null; siliconComp.OverheatAccumulator += frameTime; if (siliconComp.OverheatAccumulator >= 5) { - siliconComp.OverheatAccumulator =- 5; + siliconComp.OverheatAccumulator -= 5; - if (EntityManager.TryGetComponent(silicon, out flamComp) && + if (EntityManager.TryGetComponent(silicon, out var flamComp) && temperComp.CurrentTemperature > temperComp.HeatDamageThreshold && !flamComp.OnFire && _random.Prob(Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 5), 0.001f, 0.9f))) @@ -155,9 +138,9 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) _flammableSystem.Ignite(silicon, flamComp); } else if ((flamComp == null || !flamComp.OnFire) && - _random.Prob(Math.Clamp(temperComp.CurrentTemperature / (upperThresh), 0.001f, 0.75f))) + _random.Prob(Math.Clamp(temperComp.CurrentTemperature / upperThresh, 0.001f, 0.75f))) { - _popup.PopupEntity(Loc.GetString("silicon-system-overheating"), silicon, silicon, PopupType.SmallCaution); + _popup.PopupEntity(Loc.GetString("silicon-overheating"), silicon, silicon, PopupType.SmallCaution); } } @@ -167,7 +150,7 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) // Check if the silicon is in a cold environment. if (temperComp.CurrentTemperature < thermalComp.NormalBodyTemperature) { - var coldTempMulti = (0.5f + (temperComp.CurrentTemperature / thermalComp.NormalBodyTemperature) * 0.5f); + var coldTempMulti = 0.5f + temperComp.CurrentTemperature / thermalComp.NormalBodyTemperature * 0.5f; return coldTempMulti; } diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index e37f13f195..7f42f9497c 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -1,3 +1,5 @@ +using System.Linq; +using Content.Server.Construction; using Content.Server.Explosion.Components; using Content.Server.Explosion.EntitySystems; using Content.Server.Hands.Systems; @@ -12,17 +14,13 @@ using Content.Shared.Interaction.Components; using Content.Shared.Inventory; using Content.Shared.Popups; -using Content.Shared.Power; using Content.Shared.PowerCell.Components; using Content.Shared.SimpleStation14.Silicon; using Content.Shared.SimpleStation14.Silicon.Charge; using Content.Shared.StepTrigger.Components; -using Content.Shared.Storage.Components; -using Robust.Server.GameObjects; -using Robust.Shared.Audio; using Robust.Shared.Physics.Events; -using Robust.Shared.Player; using Robust.Shared.Prototypes; +using Robust.Shared.Random; using Robust.Shared.Timing; namespace Content.Server.SimpleStation14.Silicon.Charge; @@ -38,17 +36,24 @@ public sealed class SiliconChargerSystem : EntitySystem [Dependency] private readonly ExplosionSystem _explosion = default!; [Dependency] private readonly SharedSiliconChargerSystem _sharedCharger = default!; [Dependency] private readonly BatterySystem _battery = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly IGameTiming _timing = default!; public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnExamineParts); + SubscribeLocalEvent(OnStartCollide); SubscribeLocalEvent(OnEndCollide); SubscribeLocalEvent(OnChargerShutdown); } + // TODO: Potentially refactor this so it chaches all found entities upon the storage being closed, or stepped on, etc. + // Perhaps a variable for it? Open chargers like the pad wouldn't update to things picked up, but it seems silly to redo it each frame for closed ones. public override void Update(float frameTime) { base.Update(frameTime); @@ -61,7 +66,7 @@ public override void Update(float frameTime) var wasActive = chargerComp.Active; chargerComp.Active = false; - if (EntityManager.TryGetComponent(uid, out var powerComp) && !powerComp.Powered) + if (TryComp(uid, out var powerComp) && !powerComp.Powered) { if (chargerComp.Active != wasActive) _sharedCharger.UpdateState(uid, chargerComp); @@ -75,6 +80,8 @@ public override void Update(float frameTime) var chargeRate = chargerComp.ChargeMulti * frameTime * 10; + + HandleChargingEntity(entity, chargeRate, chargerComp, uid, frameTime); // Heat up the air in the charger. @@ -115,7 +122,7 @@ public override void Update(float frameTime) var chargeRate = frameTime * chargerComp.ChargeMulti / chargerComp.PresentEntities.Count; - foreach (var entity in chargerComp.PresentEntities) + foreach (var entity in chargerComp.PresentEntities.ToList()) { HandleChargingEntity(entity, chargeRate, chargerComp, uid, frameTime); } @@ -139,14 +146,16 @@ private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconCha if (entitiesToCharge.Count == 0) return; + chargeRate *= chargerComp.PartsChargeMulti; + // Now we charge the entities we found. chargeRate /= entitiesToCharge.Count; - foreach (var entityToCharge in entitiesToCharge) + foreach (var entityToCharge in entitiesToCharge.ToList()) { - if (EntityManager.TryGetComponent(entityToCharge, out _)) + if (TryComp(entityToCharge, out _)) ChargeBattery(entityToCharge, EntityManager.GetComponent(entityToCharge), chargeRate, chargerComp, chargerUid); - else if (EntityManager.TryGetComponent(entityToCharge, out var damageComp)) + else if (TryComp(entityToCharge, out var damageComp)) BurnEntity(entityToCharge, damageComp, frameTime, chargerComp, chargerUid); } } @@ -156,40 +165,40 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true var entitiesToCharge = new List(); // If the given entity has a battery, charge it. - if (!EntityManager.TryGetComponent(entity, out _) && - EntityManager.TryGetComponent(entity, out BatteryComponent? batteryComp) && + if (!HasComp(entity) && // Should probably be charge by the entity holding it, but also might be too small to be safe. + TryComp(entity, out var batteryComp) && batteryComp.CurrentCharge < batteryComp.MaxCharge) { entitiesToCharge.Add(entity); } // If the given entity contains a battery, charge it. - else if (!EntityManager.TryGetComponent(entity, out _) && - EntityManager.TryGetComponent(entity, out PowerCellSlotComponent? cellSlotComp) && + else if (!HasComp(entity) && // Should probably be charge by the entity holding it, but also might be too small to be safe. + TryComp(entity, out var cellSlotComp) && _itemSlots.TryGetSlot(entity, cellSlotComp.CellSlotId, out var slot) && - EntityManager.TryGetComponent(slot.Item, out var cellComp) && - cellComp.CurrentCharge < cellComp.MaxCharge) + TryComp(slot.Item, out var cellBattComp) && + cellBattComp.CurrentCharge < cellBattComp.MaxCharge) { entitiesToCharge.Add(slot.Item.Value); } // If the given entity is fleshy, burn the fucker. else if (burn && - EntityManager.TryGetComponent(entity, out var damageComp) && + TryComp(entity, out var damageComp) && damageComp.DamageContainerID == "Biological") { entitiesToCharge.Add(entity); } // Now the weird part, we check for any inventories the entities contained may have, and run this function on any entities contained, for a recursive charging effect. - if (EntityManager.TryGetComponent(entity, out var handsComp)) + if (TryComp(entity, out var handsComp)) { foreach (var heldEntity in _hands.EnumerateHeld(entity, handsComp)) { entitiesToCharge.AddRange(SearchThroughEntities(heldEntity)); } } - if (EntityManager.TryGetComponent(entity, out var inventoryComp)) + if (TryComp(entity, out var inventoryComp)) { foreach (var slot in _inventory.GetSlots(entity, inventoryComp)) { @@ -197,14 +206,14 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true entitiesToCharge.AddRange(SearchThroughEntities(slotItem.Value)); } } - if (EntityManager.TryGetComponent(entity, out var storageComp)) + if (TryComp(entity, out var storageComp)) { foreach (var containedEntity in storageComp.StoredEntities!) { entitiesToCharge.AddRange(SearchThroughEntities(containedEntity)); } } - if (EntityManager.TryGetComponent(entity, out var entStorage)) + if (TryComp(entity, out var entStorage)) { foreach (var containedEntity in entStorage.Contents.ContainedEntities) { @@ -231,7 +240,7 @@ private void ChargeBattery(EntityUid entity, BatteryComponent batteryComp, float // If the battery is too small, explode it. if ((batteryComp.MaxCharge - batteryComp.CurrentCharge) * 1.2 + batteryComp.MaxCharge < chargerComp.MinChargeSize) { - if (EntityManager.TryGetComponent(entity, out var explosiveComp)) + if (TryComp(entity, out var explosiveComp)) _explosion.TriggerExplosive(entity, explosiveComp); else _explosion.QueueExplosion(entity, "Default", batteryComp.MaxCharge / 50, 1.5f, 200, user: chargerUid); @@ -242,47 +251,60 @@ private void BurnEntity(EntityUid entity, DamageableComponent damageComp, float { var damage = new DamageSpecifier(_prototypes.Index(chargerComp.DamageType), frameTime * chargerComp.ChargeMulti / 100); var damageDealt = _damageable.TryChangeDamage(entity, damage, false, true, damageComp, chargerUid); - chargerComp.WarningAccumulator -= frameTime; - if (damageDealt != null && chargerComp.WarningAccumulator <= 0 && damageDealt.Total > 0) + if (damageDealt != null && damageDealt.Total > 0 && chargerComp.WarningTime < _timing.CurTime) { - var popupBurn = Loc.GetString("silicon-charger-burn", ("charger", chargerUid), ("entity", entity)); + var popupBurn = Loc.GetString(chargerComp.OverheatString); _popup.PopupEntity(popupBurn, entity, PopupType.MediumCaution); - chargerComp.WarningAccumulator += 5f; + + chargerComp.WarningTime = TimeSpan.FromSeconds(_random.Next(3, 7)) + _timing.CurTime; } } + private void OnRefreshParts(EntityUid uid, SiliconChargerComponent component, RefreshPartsEvent args) + { + var chargeMod = args.PartRatings[component.ChargeSpeedPart]; + var efficiencyMod = args.PartRatings[component.ChargeEfficiencyPart]; + + component.PartsChargeMulti = chargeMod * component.UpgradePartsMulti; + // TODO: Variable power draw, with efficiency. + } + + private void OnExamineParts(EntityUid uid, SiliconChargerComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("silicon-charger-chargerate-string", component.PartsChargeMulti); + // TODO: Variable power draw, with efficiency. + } + #region Charger specific #region Step Trigger Chargers // When an entity starts colliding with the charger, add it to the list of entities present on the charger if it has the StepTriggerComponent. private void OnStartCollide(EntityUid uid, SiliconChargerComponent component, ref StartCollideEvent args) { - if (!EntityManager.HasComponent(uid)) + if (!HasComp(uid)) return; - var target = args.OtherFixture.Body.Owner; - - if (!component.PresentEntities.Contains(target)) - { - if (component.PresentEntities.Count >= component.MaxEntities) - { - _popup.PopupEntity(Loc.GetString("silicon-charger-list-too-big"), target, target); - return; - } + var target = args.OtherEntity; - _popup.PopupEntity(Loc.GetString("silicon-charger-add-to-list"), target, target); + if (component.PresentEntities.Contains(target)) + return; - component.PresentEntities.Add(target); + if (component.PresentEntities.Count >= component.MaxEntities) + { + _popup.PopupEntity(Loc.GetString("silicon-charger-list-full", ("charger", args.OurEntity)), target, target); + return; } + + component.PresentEntities.Add(target); } // When an entity stops colliding with the charger, remove it from the list of entities present on the charger. private void OnEndCollide(EntityUid uid, SiliconChargerComponent component, ref EndCollideEvent args) { - if (!EntityManager.HasComponent(uid)) + if (!HasComp(uid)) return; - var target = args.OtherFixture.Body.Owner; + var target = args.OtherEntity; if (component.PresentEntities.Contains(target)) { diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs index 47d76495fa..46203475f9 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs @@ -20,7 +20,12 @@ public sealed class SiliconChargerComponent : Component /// /// Counter for handing out warnings to burning entities. /// - public float WarningAccumulator = 0f; + public TimeSpan WarningTime = TimeSpan.Zero; + + /// + /// The current parts mutliplier. + /// + public float PartsChargeMulti = 1.2f; /// @@ -69,6 +74,34 @@ public sealed class SiliconChargerComponent : Component [DataField("damageType")] public string DamageType = "Shock"; + /// + /// The modifier to apply to a used parts rating. + /// + /// + /// 0.6 is the default as it provides a nice range where 2 is about normal, and 4 is about two and a half. + /// + [DataField("upgradePartsMulti"), ViewVariables(VVAccess.ReadWrite)] + public float UpgradePartsMulti = 0.6f; + + /// + /// The part to be used for the charge speed. + /// + [DataField("chargeSpeedPart")] + public string ChargeSpeedPart = "Capacitor"; + + /// + /// The part to be used for the charge efficiency. + /// + [DataField("chargeEfficiencyPart")] + public string ChargeEfficiencyPart = "Manipulator"; + + + /// + /// Charger overheat string + /// + [DataField("overheatString")] + public string OverheatString = "silicon-charger-overheatwarning"; + /// /// The list of entities currently stood on a charger. diff --git a/Resources/Locale/en-US/SimpleStation14/Content/Silicons/siliconChargers.ftl b/Resources/Locale/en-US/SimpleStation14/Content/Silicons/siliconChargers.ftl new file mode 100644 index 0000000000..df6c66346c --- /dev/null +++ b/Resources/Locale/en-US/SimpleStation14/Content/Silicons/siliconChargers.ftl @@ -0,0 +1,5 @@ +silicon-charger-overheatwarning = You feel like you're in a microwave! +silicon-charger-chargerate-string = Charge rate +silicon-charger-efficiency-string = Efficiency + +silicon-charger-list-full = {CAPITALIZE(THE($charger))} can only accommodate so many targets! diff --git a/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl b/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl new file mode 100644 index 0000000000..7f53b2a89d --- /dev/null +++ b/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl @@ -0,0 +1 @@ +silicon-overheating = You feel your circuits overheating! diff --git a/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml b/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml index e564f5b691..138e2d47e7 100644 --- a/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml @@ -136,7 +136,7 @@ - type: BodyPart partType: Leg symmetry: Left - - type: MovementSpeedModifier + - type: MovementBodyPart - type: entity id: RightLegIPC @@ -153,7 +153,7 @@ - type: BodyPart partType: Leg symmetry: Right - - type: MovementSpeedModifier + - type: MovementBodyPart - type: entity id: LeftFootIPC diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index b4d57bc2e4..1e434770c4 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -250,6 +250,7 @@ - type: Hands - type: Inventory templateId: human + - type: InventorySlots - type: Appearance - type: GenericVisualizer visuals: diff --git a/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Circuitboards/siliconchargers.yml b/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Circuitboards/siliconchargers.yml new file mode 100644 index 0000000000..9acf92dcec --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Entities/Objects/Devices/Circuitboards/siliconchargers.yml @@ -0,0 +1,34 @@ +- type: entity + id: IndustrialChargerCircuitboard + parent: BaseMachineCircuitboard + name: industrial charger machine board + description: A machine printed circuit board for an industrial charger + components: + - type: Sprite + state: engineering + - type: MachineBoard + prototype: SiliconChargerIndustrial + requirements: + Capacitor: 8 + Manipulator: 2 + materialRequirements: + Plastic: 6 + CableHV: 4 + CableMV: 8 + +- type: entity + id: ChargingPadCircuitboard + parent: BaseMachineCircuitboard + name: charging pad machine board + description: A machine printed circuit board for a charging pad + components: + - type: Sprite + state: engineering + - type: MachineBoard + prototype: SiliconChargerChargePad + requirements: + Capacitor: 3 + Laser: 5 + materialRequirements: + CableHV: 2 + CableMV: 2 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml index 72628629b9..5859f37433 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml @@ -57,10 +57,30 @@ state_closed: closed - type: ContainerContainer containers: + machine_board: !type:Container + machine_parts: !type:Container entity_storage: !type:Container - type: SiliconCharger chargeMulti: 1000 targetTemp: 390 + - type: Construction + graph: Machine + node: machine + containers: + - machine_board + - machine_parts + - type: Machine + board: IndustrialChargerCircuitboard + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 350 + behaviors: + - !type:ChangeConstructionNodeBehavior + node: machineFrame + - !type:DoActsBehavior + acts: ["Destruction"] - type: entity id: SiliconChargerChargePad @@ -110,6 +130,28 @@ - type: StepTrigger - type: SiliconCharger chargeMylti: 150 + - type: ContainerContainer + containers: + machine_board: !type:Container + machine_parts: !type:Container + - type: Construction + graph: Machine + node: machine + containers: + - machine_board + - machine_parts + - type: Machine + board: IndustrialChargerCircuitboard + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 350 + behaviors: + - !type:ChangeConstructionNodeBehavior + node: machineFrame + - !type:DoActsBehavior + acts: ["Destruction"] # Generated, maybe good? # From bc858326114ac00f026f0178482b67d24de4ff17 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Thu, 22 Jun 2023 11:05:30 -0400 Subject: [PATCH 40/60] New IPC sprites v2 Slightly modified the head shape to fit better with pre-existing sprites, and look a little more 'blocky.' v1 was never committed. --- .../ipc_screens.rsi/ipc_screen_blank.png | Bin 226 -> 189 bytes .../ipc_screens.rsi/ipc_screen_blue.png | Bin 1128 -> 689 bytes .../ipc_screens.rsi/ipc_screen_breakout.png | Bin 960 -> 572 bytes .../ipc_screens.rsi/ipc_screen_bsod.png | Bin 1136 -> 677 bytes .../ipc_screens.rsi/ipc_screen_console.png | Bin 467 -> 307 bytes .../ipc_screens.rsi/ipc_screen_ecgwave.png | Bin 1660 -> 1036 bytes .../ipc_screens.rsi/ipc_screen_eight.png | Bin 495 -> 313 bytes .../ipc_screens.rsi/ipc_screen_exclaim.png | Bin 382 -> 231 bytes .../ipc_screens.rsi/ipc_screen_eyes.png | Bin 445 -> 298 bytes .../ipc_screens.rsi/ipc_screen_eyesangry.png | Bin 456 -> 317 bytes .../ipc_screens.rsi/ipc_screen_eyestall.png | Bin 441 -> 303 bytes .../ipc_screens.rsi/ipc_screen_frown.png | Bin 256 -> 208 bytes .../ipc_screens.rsi/ipc_screen_glider.png | Bin 563 -> 345 bytes .../ipc_screens.rsi/ipc_screen_goggles.png | Bin 529 -> 385 bytes .../ipc_screens.rsi/ipc_screen_heart.png | Bin 415 -> 250 bytes .../ipc_screens.rsi/ipc_screen_l.png | Bin 239 -> 190 bytes .../ipc_screens.rsi/ipc_screen_loading.png | Bin 784 -> 440 bytes .../ipc_screens.rsi/ipc_screen_monoeye.png | Bin 515 -> 288 bytes .../ipc_screens.rsi/ipc_screen_nature.png | Bin 1130 -> 607 bytes .../ipc_screens.rsi/ipc_screen_orange.png | Bin 875 -> 530 bytes .../ipc_screens.rsi/ipc_screen_pink.png | Bin 595 -> 361 bytes .../ipc_screens.rsi/ipc_screen_question.png | Bin 429 -> 271 bytes .../ipc_screen_rainbowdiag.png | Bin 1286 -> 573 bytes .../ipc_screen_rainbowhoriz.png | Bin 867 -> 411 bytes .../ipc_screens.rsi/ipc_screen_redtext.png | Bin 862 -> 520 bytes .../ipc_screens.rsi/ipc_screen_rgb.png | Bin 559 -> 313 bytes .../ipc_screens.rsi/ipc_screen_ring.png | Bin 263 -> 210 bytes .../ipc_screens.rsi/ipc_screen_scroll.png | Bin 802 -> 460 bytes .../ipc_screens.rsi/ipc_screen_shower.png | Bin 1232 -> 743 bytes .../ipc_screens.rsi/ipc_screen_sinewave.png | Bin 1289 -> 859 bytes .../ipc_screens.rsi/ipc_screen_smile.png | Bin 258 -> 204 bytes .../ipc_screens.rsi/ipc_screen_squarewave.png | Bin 1096 -> 677 bytes .../ipc_screens.rsi/ipc_screen_stars.png | Bin 1252 -> 786 bytes .../ipc_screens.rsi/ipc_screen_static.png | Bin 695 -> 355 bytes .../ipc_screens.rsi/ipc_screen_tetris.png | Bin 2131 -> 1137 bytes .../ipc_screens.rsi/ipc_screen_textdrop.png | Bin 1672 -> 962 bytes .../ipc_screens.rsi/ipc_screen_tv.png | Bin 828 -> 458 bytes .../ipc_screens.rsi/ipc_screen_windowsxp.png | Bin 988 -> 688 bytes .../ipc_screens.rsi/ipc_screen_yellow.png | Bin 495 -> 330 bytes .../Mobs/Species/IPC/parts.rsi/full.png | Bin 2246 -> 24547 bytes .../Mobs/Species/IPC/parts.rsi/head_f.png | Bin 2626 -> 4211 bytes .../Mobs/Species/IPC/parts.rsi/head_m.png | Bin 2626 -> 4210 bytes .../Mobs/Species/IPC/parts.rsi/l_arm.png | Bin 1725 -> 579 bytes .../Mobs/Species/IPC/parts.rsi/l_foot.png | Bin 2394 -> 543 bytes .../Mobs/Species/IPC/parts.rsi/l_hand.png | Bin 1574 -> 535 bytes .../Mobs/Species/IPC/parts.rsi/l_leg.png | Bin 2397 -> 587 bytes .../Mobs/Species/IPC/parts.rsi/meta.json | 8 ++++---- .../Mobs/Species/IPC/parts.rsi/r_arm.png | Bin 1771 -> 683 bytes .../Mobs/Species/IPC/parts.rsi/r_foot.png | Bin 2394 -> 503 bytes .../Mobs/Species/IPC/parts.rsi/r_hand.png | Bin 1585 -> 646 bytes .../Mobs/Species/IPC/parts.rsi/r_leg.png | Bin 2397 -> 609 bytes .../Mobs/Species/IPC/parts.rsi/torso_f.png | Bin 3420 -> 1149 bytes .../Mobs/Species/IPC/parts.rsi/torso_m.png | Bin 3420 -> 1113 bytes .../Species/IPC/parts.rsi_old/torso_m.png | Bin 973 -> 0 bytes 54 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi_old/torso_m.png diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_blank.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_blank.png index 6020b0591993d5b72e8f074ef106dc9f707d0c10..4361a36c1ed8c4fd55565f7cc966e776c1eb6f28 100644 GIT binary patch delta 161 zcmaFFxR-H)Nt&gxvzR7m zGZgJ-dQbP0l+XkKP4plk literal 1128 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I4M=vMPuB%foCO|{#S9F5M?jcysy3fA0|Sec zr;B4q#hkZyHhL*L$~1iZxI-}rsSOLv#IFC63Y&B&Z@$APmfMj_M6}}{W+{fd zxOx<>O)6&(i+Z-{V#gwxce`eu_t_`U5+m4tvnDyI>;HF!MxFo-W|312t*b;5{(Y{x zu|JMSe6f4t|Ksx~yfqVd(s}#v!`bhqA<*&8r`5s$R z@F{!er(aW<&Xk46$G2Y<2;NsG{Oj*U#vK(_48IpMD6O-9VRA^pWZwGZ_xnq~37DDB z=R5F1?#R9R7i}N^y}nWYbozs^*NJ;RDz!|W{8S)#+S-5Lt8RVzGnZLlW5dA(hIKwb zr62F?w`36g9&dTz5!;b_KfFKJF!c4EJN)$N3;w|J*FS$fP`LN2RIb5`@!gx4mfqgu z+ZDsZxfApACBCxh=*G6)zAa!i_tC5OFMg@rxqCFWJ~!9mUb*0*moK-kcr7n)zwfTr zy!PqWH~R27e7qxW_xVpa*M{r2qh5TCi)&x;?w#4=dmqcM>3@@{zAt?AFaLt(=C|Rm z>z~>EFzg9n)0o1@mD=DWxqy6T$X14zKTEvawleH~Q=+vrIqmpnP2Qoy7~Cq{ZI1-u~Ng`!1XN za*@r-_IBEr7_!Y?m|XaJKJ41XueaZRzVNp0&vV`lX_a-&eXC|~Wlm@?UEE%F?iQoL zfmu^)Ial3YBg??NM)EhmL!+$N{M55Sucavn6QoeRBEqC&F0Z%s>vBtZgQGW_x3YWq zr=R*Y){>V_{R%XGZUZKAr`SAS!8`7z~f%kjlaD|Te@PmmL=HcM8{+JEZ( zzm80qhFi=k_f_g!VFuOlC?i=zJ~Pzlz|VPq#f9eCdT5F&*vhDve@pQ2UCHqBWbn+* z>=&60c$YFQ@lUvYvsuv;#CiZ1J+tXq%=v%PDmK*<9vwHJAQAm%IJMsS=34y&vw%eh NgQu&X%Q~loCIG}n+{FL@ diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_breakout.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_breakout.png index d0de4901f413faf4b65fbc332271103f8c074e41..54a282bd95c240b1472f8df8c12a4343be6bac9d 100644 GIT binary patch literal 572 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcalY)RhkE(~!XIA!A2IY1H40*}aI z1_nK45N51cYF`EvWH0gbb!C6fCdQ{PV*h_{G6MtSNlzEYkcwMx?>gokG7w-5uzuvx zq5L$!PUw-}J1uFcl}fzxR6gI^6!hcR$BuRTycro78dP3QYmeLe{rmpA*=rYz)h_u{ zz4qzV>Ra#Yzx}yAtv%|)6}_KpuNnQn*PZxt=@g^yb~X0*KHu80xqRn$``oxA4}9Z= z3xD)$6v-={KPY#<+UoK2{H<;L3ru4k%j8u5`uWGUs{iqk{zb+3(pS zsy>R({Poh)j^Xnu#++pSg!=Wz^4J=9ml^Bb+RO0f>9_m*9dDM$Z{lTf{?B@epC8>2 z5WhetyWCvHvi{Sl8^P9*`xq5WnGbBOYm5U7K1_lo%*yr$l&!00tcfI$&R-6C-|1!D1F3;BexWOQ> z?CPu<_LB3b&(Fc;LII6hdz1FcKA<8nUl>yTkM@t1qTKKXffz8uDIT>N)tgWJEV T0bP0l+XkK(_hHC literal 960 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcaloCO|{#S9F5M?jcysy3fA0|RrB zr;B4q#hkZyql2UZMH~WGoSLA~_GE#Ckd?ZU=1J$^sU^3IUf#>DRsCtXWz*AH{l)v= zD)=xg;cPHroM5KiF#Yt?Pyg=o{r+25uHJ9*zx3VL_cx!%|NaxnIHxT6?z8!E^MAg4 zeEm`0=k@D8zyJHS!v1~9{_pqVpWnYd>Hhzl?h69*_ucQE_g|yVrQ$h9p4&eDX)}JW zywBM7m!>od@+|K?z^ZC3rldb*xvge=I+uy%^;^yv;=l>T!TX6lu@jctG zZ?KkoZ(rZ|eExUN0-HY1do`cM=e^(W=qb#Q$)w;5b*vi0B^HNS3?3v2Zhp_cmCTeny^J&TPSJQ)zRmuI5_yzrPIT+V}bWXa8pO zh<^H>VS@ahu>%IxF>1& za2*%phBc3Oz3UU8*wai3xgQy>ZIi$E=i8s7%n`TiDn4&F{hwfMlIlPG^b*mRK>44_ z7asim@NBmI(NFUkv~Tn0*H!OR7N9h=fd&UL=$D^?P2uFvI`c?vK8}^l;lYe%^lT`RiXFZ}0uz^?d#}&Vnt~_x|LbEoV`p zDB8i{zf-=!KHEl;UhUMK_hj`duI=J3CGN5 Rdw^Mz!PC{xWt~$(698Y*d&U3& diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_bsod.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_bsod.png index 09ecc4dae3dcd007aaa102ba2311c5bb7f96451e..7d7a8efb62e5f8761424e20f781cf3c9a46407b9 100644 GIT binary patch literal 677 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcalY)RhkE(~!XIA!A2IY1H40*}aI z1_nK45N51cYF`EvWH0gbb!C6fCdQ{P>hYuZD+2?Qk*AAeNX4zUch~zVJIb(s$UK-3 zpmIa)#MBQA9Y;U1MX2-_f70@N$N0+O0|QH`y637{YqFeXE%^2wS}jfVOl**mJ>w7id9mP1 z4c8xQTe*_042J_J%d4-?zkgnj-|Bq-y#0T^K6$_1s-s_eL$=_|__Ov|GM}zb-k;C> zt@s~^af$Inx96{)k5!gVx%BmH@$<>&yFIOJ`=kHtnbBhR=jku^HGj9+{7<7g%^C`Hp=^rmmmDzNg`kxzrW?E!9v48kdJCZRN3;sxYbU-`S_Ts}uMA-8=u* zO!MjMD|g@g$Gl*EeeutCaWkrzE0`;`Mf=+SfA;I;-Mt3a{_J73}Go?>Sz( zGp_*?+(1?|%RH_VfEU_ON~XUR=MNA?|P0UKzWc zfA4-Rx^MP-`fBt4|NcFB^KtL{|KI;efB!9YLw@`I&-RUJ`xw)6_r3o1Grd;++wnK= zWgPzUTKxX`w*TgR&4#b9uYP*WKmUHspR?Qd>weGOTwk-xXY|9>6-Zq|a@!h*tmK-qY;UjpCK_y6Nhz2EQXDa??`q~HtnfEvRk7Kd339wZ4` z-{=4E?|Ir>e*4#TO*4P@Z2tV0!Pr0jpTIly89UEgRM*@5I@a?(^_yMt4uxd@?~=*S ze>2WGZ~wlg?%2(rbq%SDO8)?vACm*fu$w}s6Qljs2ZnY3eiZ+`xqQBi&SV+e+TC?O zA6?w?_vZQh`rUsYGRoNfte*Mu=lA{k@pXpz_1`|HX7ZrrGcR z`}SKqdq6$&xw^XFx8L&fKe$=Gep>hE)LD-&$4{GiZGCv~cVLYC-ezyp(Ea&x=6}Xp z5%KX$AY$*2FMuR3vSJ77#VrpRE$07!_ig>1y#{}NwzEH|`M3MFeaZJjAJ)ID_+oo& zf6UJ6#4n$BDxqJ}z2 zCz`e3Ys2|__uKy}m+PO|EC1jFyAJo4G(cRsKP OVeoYIb6Mw<&;$V9`}GI_ diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_console.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_console.png index d7fa0cd0e2a21cd79739f25b93b9c88e8a509af2..dfed44e10cd58f7b56e9a308cb0645d41e88c76e 100644 GIT binary patch delta 280 zcmcc2yqRf&N1t zbDsY!tDat;>#l!VDC*6&+?6lc7BJ?TC&XUAko3Lwx*=43gLefJ?>0xl%lE2f4}-)! MUHx3vIVCg!0Ooma(f|Me literal 467 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|R5L zr;B4q#hkadH?D0qkYGr(*JR$no+Pp?mDSAQ%LYcF3l}~-nGz@!t)U+MeX7a+N0SS= zK65!qGNdugU`*J__)h=)zeDdYe3qXqns9sD1ry%|7e3FQBC7DOqDb(?PyZtJ1Dnbn zM8qF`zNvp@(~rP+iht}r9B9?}bl~r?{R<745AZM;Gn`={m9dKZ!nU`z=Z(us4NL1v z8LySH+Ah`oOIvPok2|6lv|w-HW68Yq6}{^ffd2Pn{8r1qmdKI;Vst0H`vdvj6}9 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_ecgwave.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_ecgwave.png index e48bdba2e67c62bd3bb9fde8d08ba27356834f13..2d2c405734deab48b03eb0b4930e07d235e4eae5 100644 GIT binary patch literal 1036 zcmeAS@N?(olHy`uVBq!ia0vp^4;UC2893O0tW|PV*MSsUlDE4HLmUWBnYeWhP=vF< zBeIx*K~EWk87r3BmjMOYOFVsD*`KqC@#%|Q{CLNofq{9Zr;B4q#jUq@4;C&8U^xD8 zyWcvq2~1lUqzqV>Fa$Gb9+HX$s1e)C-|2_Lud)Vqw^MBhsM*bIsaVc`2B6U8MD+xTm|>q z=hQ#1itzav5IOB4e^thvck|seLqbJQZMt%9$=&$>#g#Lvn0xY@X81q&$O+W)i`5|K zc%1}qe0|pgPl|6B7`t$pb3{r`eyZQjpO6aDUY zi{>_^_e*VGnm?$JUaNDuz(#KI+=fEymL0!a_U`-p>({I`bCcxr@91?Yy*gjN!~ceS z^_ltqcl@3EZ;AAW0*f#8-7QzMME#ZrU*UdGVpW@UyiRsk-1_;quD>?Ts=wj)QESGg zyYcm!@r}P<%VYBz`CG{C@M&chB{{*B*OvJ^tPAocHhF zM}9Bg9ee3t+UAY?9N7JL;OwTq)5`CEd-UgacYKuluB~skR=<|#YhO}(yZiI^{49Bc zuU|r5z0`eo{?W9&hAX$TT?12U|7;T%K3)6U|Ngf{%ds2Fz+ivUZvMW1d-iSVn^HCZ ztlh$Yd%uEA+j{3aXYl#WsqZUn$}GRj%gb9okGG$BH*fkE?i@4e-!;E(egkD6H1O=Z YbgQA~q=~^tE`Ve_UHx3vIVCg!0A-`MAOHXW literal 1660 zcmd^A|4$QV9KI_cg#^kVh6$!saT&pd%w+?nrF@YoBpYmIkvWkfe#1#=T?Hz&y`l&> z)H7j>Oc7fi9sFQ3M(^$B$@{!AMlqZ95= z(3V;}TZ67waD8XLy?bT!AWd&kT?4l7Ol1d!r3VJc%E~Y;K??)|D(X}r?a7LBOKLucd0C+#%e`0J^>%v;0Zt^8z|dC)gQ3_U=|EfEUiG6i@CLYu%nxocJ0lC6 z;s-d)bD&ZaOH6yZh{Ct66oyR@22=`>?Gu7n^X%vEez~Z|sQ&(bo(a+GZZ_ z3gS@4&|r!7)1RRJV1=}x(zT3D-y9oIqc6ZL_Nk&`EEwvdK_!rd2@%FyOEi^Vdv zvho({z`bg|dADlB6ChJ6hp>gf$zN~>6PgiZn4SUS8z0|3L3iUkE_Z}fq|guj^1eSb z9$i3Su*f0Ym-@-HfrkX>K4_38rms3VjI6x)#(m!* zWZAr$?nLYA=@xlF?;bY_VYd8cAI|T?Kr!)9<;C=X7nJl<`EXfv?6bXo)He zvLd`Rd|CD@9%NZ9R;$&1Psewe-5}!(Zd@sln3%|r%aP4HXxc*MGa^sT6S6gh-Y2+C z{*L3pl8Dp_wP=+k8NuC)G@@{U|CIDb#3ds~ukNTlkT4`*z7rtpz3hy;=>?bm1iWm@ A)Bpeg diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eight.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eight.png index 69ad2f0d0c5d78acf701c7e7c2b949b5e6d83c7a..8421ae30bd99d6c956055c9f95f577b09dd0acc5 100644 GIT binary patch delta 286 zcmaFQypw5yNq`=#+Z(-Zk~t&ipNycWrr|_~VFE_HhSZoxQwY z?$_b3*Ljayl>WVI)y0&itI+oNt?PB|gm+9yimXT2S$&k0p8u&_JM;A&KmWBe8G%lL zfCEfh=L(xHpEY}%_=NV51}2dO46HCY1_qnNcbh)`oNW^ZmVk+i*WF=V-BzG`b>ByR OkeH{dpUXO@geCywJZ$m+ literal 495 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|Vni zPZ!6KiaBp@8~PnKkZ^c-Uub*cQ--$(&YfedQoC_;x3LO)!c&{fxr$t&;_efc-`|tJ z(kArl>-8xcs~UzUvQHM%K&3C&`@7yZ?W-8S9GK z@nQSFm;HU-cDeNO{kk>EPrv2!1epIm$MR-*UftanO{O*J-k z$M(-^nDKqi@6%`b?_9m!ANl{^!)%Rn32^Y_m^ hk6~nSfC(|Y`^21|%_G*hWWG8`%+uA+Wt~$(697LcLD&EQ literal 382 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|TRh zr;B4q#hkad4Y`^fL>K~F@BBa27SSSbX^o(~_Ghoz{XFrr?;aOg#Sp=`fhobAImdq9 z+S8@qe%{`u`}&t$_0vC>w=e>wRx;Pr)GaeDZCGD_U`ij`h5Wte<8L?oSq;&~dVs4z zltG&zjA0EC0ykut_q^jfVchNf`MpGf7DV&zWQN+zgp7Z(%sxwrFazvbWNU9^G^{*# y@B9K@s8h_O9R4$W{d0LM$n{JK$V%}ER5N9G@%EYu@SO(+D1)b~pUXO@geCw!7kX>} diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eyes.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_eyes.png index ff038ed3ed052219c060a827befcfd0e0fc9fd1f..42ee79361b1e930044f20fb9abb7b5aa1552ab81 100644 GIT binary patch delta 271 zcmdnXyozapN+M}buEPdAtQSe z)-XgcZt!NDcmDbF_wVD@Ur+w2UiHsoI+M)tjUFIIebctw=xe2af1WX&&Rk>vMeg7I z7_JTPe=EKGsT|Ae@c+Y?KNG8Xk8(ALGH5e|L5yQcU_C&Lz+Jrq)#VQFxaQ2Q-_3A5 zWjFVB?hp6ED{P)w?yla=u=%a_9lZl~H{TtSW%k*+y8tMnNvaJXN0n(E$Vq>nUZ8d0 z;$FtXbGZy|-~25(higMw_<@4uOmFT=8{E0c5IlG9e8=?*fnhRP3tmv&rZkn8(?{i%g zeIB`o8y{w12oYST6E#iszg_fo(B=)~^)+qm1dw=&&Cb@92 zqY~{?E+tBca6FJb^n7a5{sp(TzYWaMXe!{%x!C&R~vKsgX z2mgMn*H9<}bjjPBjGMV(${8HAzuXJI7WKZC+ppAp`?c!(u?%-?81{Y#DUb#cYbzKN Wz8WvyA9~*j#PxLbb6Mw<&;$U4j%@(| literal 456 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|R4~ zr;B4q#hkZy4f&c41Q;BZm$s%K_&=ZdzCo=JSJwiQGNrKcTQ5D5ABq+ghsn8WFdyJy zFlJbzeZc1Y`PcckxA8tz`||7m714y)>zi~=AOCD{=lj3k`=;ycVv?C%@3!Mu!0dO% z5AKwh|2J3Ue;Ad0a*;Me?Ss9{Ej9)FIe)UIBr(ijOkit}WJn{85wVNm_+7@Ll1-(5 zOBmnnTU~Iqs$4O)A#;|O%1fr6#}ZjJwy_LVpQEpzmr%HJx3z?Eks-qw1_OxeNn)(g zbl7t9H^(d{m)U#!7eF{R%n1vbuFQH~&+O;RxajOXcY#;jCr*%N{08wCEy2q>?k<=J Pj2Z?{S3j3^P6^Cc~S)JwFv6F?( z_dxOW@Av+0-dVybdt7kWix)qDwn4#{k1NX`%zxCLy|(pVLuu^(uJ!f`H%d4q*2X99 zVtEk@Q^vqx;r_OE!^N!k?hEV_matT4D_AgQy=R2VTRdk}tTSu++xwN*3nb*}>gTe~ HDWM4fpyO-B literal 441 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|R5W zr;B4q#hkZy4YLkAh%f|77IA;w_rG+_J@pB{S;Rdj`Z@jBczVyV2hYTnx16o}vb9Bv zA&g-S!;O^;-+%x8{lEV9w!72#FMeKMqIKZ)*Qj~tpKn_C`u=6Aqwgv3-=G8Af2Q(ytaRXBV>jAC?Q3h?Wse}b?lrY}g&0G}z z;KiSpOg3`;Ps@tK-TU9^`G_Z&TxONXjZfUg@H=5Qw=tVURymNpSd&PDQLHZ0IFM2P z-n{@qUC`#R7D;#;%{U!Mz26O_q!L!_{;vFjhcu`2Zxan}K6=B&8Wzopr E0Li1EBme*a diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_frown.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_frown.png index e70295f4c5adf7df690c378102f08211ea8f33ac..f297c401a10d23b9e11bc55a337abced786bd3e8 100644 GIT binary patch delta 180 zcmZo*y1+O=rJgOx+uemB4g{x6+&YJWfq}EYBeIx*K~EWk87r3BmjMOYOFVsD*`KqC z@##z5aG#I@6pHn9aSW-r_4cwO*8u|#76;zH|EIrQ81Uk%m{$RtlONYbUzP(2H`lD@ zul}1=%Dwtkq4$AhoEG=g6qJ;Vlc(&8tDk@Cue>hMAP|t<8vNe0HkvH~%wsS(#`)G% U{9l8NJ|{@P)78&qol`;+04w}DEdT%j literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;ir{ zi(^Q|oVT|&ay1)BFg)b`@;CnGqXhPsQ)Vgd{VnEbFyZla)qNAR8H!kE)V%vql)qu& zOHPZvX2WC8cddTOaD7?%y+1FPbMD}|&2r~>-Sg`SS_gK#E#rA;{vck2VJDM9IKvaJ zh8RY$0S@aJPKY82imj=fH*1}hc6H5LHIVRjr30ttv&zNq=0sPCtleCtSyByg#Px94$gn`!0{QvXvu66zA?-!l>9O-;IfBO6^wv(3a zrse1R<|rEN56xSZlXQbgX>+y4y?_61Sx#H6_n=l#S$xB{zo)N?-M`E;@u%$@d7!m8 zK|^uP?`?bk)O`+q&A2U>TX(^qgYvxhcmFXXl8G#1CojMJGPyG7TmS9)7s3zHzf{dgb=&@SX8I2MoKE6KJQOQ?f888(vc)I$ztaD0e0sxZ@)0hAN diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_goggles.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_goggles.png index 006c6a6c8055a8cff807c2b6ef30cc7013d303bb..422a603cc7c7d9579760c756b3a9056605214772 100644 GIT binary patch delta 358 zcmbQp(#SkPrJgOx+uemB4g{x6+&YJWfq}EYBeIx*K~EWk87r3BmjMOYOFVsD*`KqC z@##yicUbU=fq{|F)5S5Q;?~>S8-1A#Mc5wLcg)h6(ALCj#K_7jY~ZMtz@wJHq_$u| zLbDEohe@Vm6Kh|S$D9VGawoHWHSwu)Q~pky|F-^BEE7YBp|tT!o$$Ng^UHV6nHp8{ z_RlL;i&KldCrzI7+;F?+r0+Rhxejmt>@TrMyX0!-IjJ(@Qt zEB4c-G5&Fm`J$Fe{rWh?{lA1u=3JJ~|4{s{TlUbcpFj^l!IY1;_cQ;u{GX7;T5ueeB#CoBcAFAj;o*je0H^+6tT08VXLY}UEF6*2UngGveklX+O literal 529 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|Vn> zPZ!6KiaBrZ8hSB1N;o`>-{7B^Ev=t$F5w}kO{4k;39)OIjp`dVY}jTX9*`(~o1==+ z)O*6!ytYL7{~z|HwVBwz@lNQLERt}NWJqI}!I%)rc<#}!*ZKKuKT;#=s>Pa|LdYn{ePQh98NN- zXFQX?QtLqAoSxU!d;Yz%Pp@J4@@LvACZ3NC{~o>ksryrk%b4K|g8}ma9tIK_Yj!j2 z-p%|Zw(-)>yR0{k6|VwP7QJ69@*6*WG2Z{=`SsWa-IEGZ*dV9-|tHFSWHQ@2z_cG#+0y0rts?YWw_1ypEvX3PnLqhkA z8h!D)Y%Tlu2WpxYCo!fUoqw)>In#?khnzXJT;Ub6RXbdOra?jdw5gxgE?;l=SLSs* zql6<&n1SKTl(V0wYj2%ny{mdXLyv+vOs1htZ^JfG&WrcYO#}&fy85}Sb4q9e0B{XR AIsgCw literal 415 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|R5A zr;B4q#hkad4`wkLia1=9eDVK(QCGl15ph|`s$Yj}XFHnv@AVA(_?RPdn@w>Vq6LH*f&m=?IL}JLcWf`5NGgo^>bP0l+XkKvsaM! diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_l.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_l.png index 5cad2deda931e5a636a1ea369c885a72df0d689b..902845f11fc18ed2968f51f4d27b28d3ab88cd6e 100644 GIT binary patch delta 162 zcmaFQxQ}syN#GuG5ZBYy&t;ucLK6V2 CXfike literal 239 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;jBA zi(^Q|oVT|OxegnM90;g=@pt{5Ytb)e9BZC{XE)7O>#Ihz=tzO0)v>v0AKMpsW4$B>F!Z|`mtZ88vGxNw3` zavJ9gBOY%99_Nfy#q&-k1(W{VKUrPjY4Kndwm3CfbxV{S24nJ@ErkR#;MwT(hLkt zhdf;zLn`LHy?ZdX*+GOMP-!V^*FxP{58R^l+LVNnIZu8%x%=Pg??#{X0vDZ-pKbWy z@T2>V8Eg#c3oT%eU3eiZ$hJ!{bi<)1PMS|6jN4`t!dh`BoI#{C|FZVb}@N12?T7+R+ddBZPvh(+FSIzyuNA~y26>e`$4`hnloXfYq-`@yy0N52|64#&p zWfW0=!V$3BAn@m|J@yTcLRbZM+Qsf%#bi-dcjQ;e(^sGVF?2mX?qI>(V9Y=P(U9VrhNjf}+KKzq4{y@R|G%G+<@COCrC z14C7`{Qb*+#QNU~GU(Yfl*YFEEPeg>rCvG93BCnSf#R}q4ljRwS$%f?vX!fk^YJg( z{`I5n+5C?;rdzYF=wUn{$uNg(LX>sG&Ts#VKHD;hoQV5%?~(V)Zl)7)Rde?;8->em zzZA;Q6)tjsC;oT6J-fLjPx?81u7r}e|DQgq7UUo+CjSfkKaumCaiT6Ti8FY*`njxg HN@xNAKD8eE diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_monoeye.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_monoeye.png index 4a024ad3747cd1bd3d2dcda608c9d956cb3f1cd3..4e5056528d9e870da56e3f87292c92760121429e 100644 GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE(~!XIA!A2IY1H40*}aI z1_nK45N51cYF`EvWH0gbb!C6fCdQ{PcV8={7AUmV)5S5Q;?~>ShI}msJS+z!?tY$Z zKKoP2E%MSr_{In{94B~Ss98V%k8^x>FaxUts>+7#Mc@CW{?uz1 iTh74Mz=UMPhLyr)25P_8-+FrjBAKDQ>=#uy&Q7|O%{zOJUY?(&z<;(&ECT8c7K}$^ zc@t_s+_b3a`>B4`eh=fdum5C^eVm;B+(-W}i_U2ypUWmOiQFH|_Dej7d|t2Fuv+im zv$7YJ^V%0}K38wiaPiiEPIu-Vzh2F*7uw!f$kZY1Fo)q0)M!oxKZXGjs&;3%UHx=@ z&DK>vt)Jb7yWyVTfvNQkXYO0xXQRZOckVIldv&w?^Zd<>FrU8VeXx37t@(dTX)?V0 aoqzKZ74^w0jOGAimBG{1&t;ucLK6V4ez7|M diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_nature.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_nature.png index 2aab6559cf5161c1903519db492eeb8bb112abd5..6425fe2b517c2b07c1fae2e72d4223063f1e7739 100644 GIT binary patch literal 607 zcmeAS@N?(olHy`uVBq!ia0vp^4?viM4MKZge>! zB>3ysuln+;CksB;{QFjQ?+3p_{Qjx`KAdoz-ceDtQ~uY_vi~2?A2!JO%J|~-_Dl9t znP;{CDc-TKz4*q-tv3!^=2WrkT>kO<)c(4h?}jg4f4{>HvH=q;sQmWui}7#Wjr=R> zchq^mVSXjQ?*3od56jQgZaY)<%q~8y`djenz09}TFZ;h`#?((xq_dEByovq#G{mFj9zJK-mm)AOEc%8ldle)3r zmlvDytX`hD!=vfw?@T5mrj`i|iYg8qu_6yXmROx_|M~az+mCOLS8l%PW1e*XpT=)- z)*r=xo?pK$&tIth?QQ?2`oM(~E_+b4cm@6LaIy=vAww%hBU-`H+{;-A+2rb8Mm z9Eyxi9t{FQ3N7R_zcapFpI5K)j`>#n-G3f;*thK8^>?DqC&>+a&WGJwuKoV=)bE`C z`M*oLZ#+|b;FDc+<@|Mf&WqnuU-RC$??|n~@7K5GJN~ydK*EkwzzG(NgNk|Jpp5_W z%X@C-yjh8^|t+!Y8m^|zR&r~ z-17JHcUEcyGNV(*M~41)hi`7bf0upE-S*A-{|}4t7reKdQ~O)~nXy94w0hQ>68Urc z{`N=x6D@cS7JsU%K|#DCQpUp2yX-c*Y}4yE`~|Y++?}`C{>Hym@0jzpAAh;wbzc6B z?fbv%JKrD>b+z`u;qUK*PwxA>bnR=q2Zx=jf1lm=x3!X+iwfzC(doq+a1iW&{5RV| z`@qdwi{IsY>Uq;yca+MX`zQN8z8UBSEA0c#zYD&-ulO%@u9~%`03y@4eE|iD{2$}I XkF1i{S!lBPujSkIH&(o2Sfj=N;N8#ohQRO-EB*H|{_6N~V)gw} z!HazM9w43f+2y}50=73D$E2;>}S2D*ObuDY8dnkW7+mIba_7r$K)$_-*Z!g+DbM~5AySP8`e=WaVE71w!RQSx5@b>e^ed#sZ-u%L_>b=*^E4IJ$ zk8Nh3uhKB}{J+^B-yGCAwpp=(CF$J~XZpe<1@4H}W zIjuE3ZN7Q}o7-Xb)7F0`HN9WY=)|O=>JY@FVyb=MUnoZhve^%E@#(rdE6yeI#_;fG(-ma%SA+344o0P+3%<ZXumz5{k*6-e%vyZ`(bHWq~h%1j6{j%@(Z@=w3`|v}x&&%2OY&%`g+^2oN zzue-^yPe06@7@OX`__tv$EUtOuHFBzxSziwSDgPt=F{IF@9}P*{r^kD^=pDYlmtCc zuO3&yta;1Nru`52{qo<6pXPULBX)j}F0fzXwwqnPS9u1|kFg>TK3ahJ=Uf@{wjW+q n{@>R2!@GlBU|G_G;V+9p!gPUip^6uQxrf2i)z4*}Q$iB}IH`2z diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_pink.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_pink.png index 31145a55a418d9feba837e9f218f1f4851f841ee..dc50eb693db9f5b9e8a89402d45a0883d4390b61 100644 GIT binary patch delta 334 zcmcc2@{(zSNl4his2{1&LyR%zDnG% zr9!O9MVon&!O8EA6;HVNx3_~`Owc*Yr~TL0SMAWLy8QR!oUFAk zfBl=3wRWZbyroP)cR@fx^RzgTe`}{0t^WV*+GY85tGCrxzq!1R{lLEd1v~F+<>)b5 zJ`eqU-92h4Oa}u)hEw+L@47R#&$)f$-QRC)Af?m(3xCk(+)&LARdwKg4O4L1`aef< R+0KK6JYD@<);T3K0RV>hkCXra literal 595 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|OJQ zr;B4q#hkadZM|h2Wg0&IcT&hb=cf~#TDmbHM`*)F&XrpYdhZ|6Pg>nOS3pNEch&>b zqGMXiIH$$+HTZUw`de;2qqB*Bv(5gr8Oezc=GA7V#kB^oHApg~F+{9p`1;OOw*Bd4 z{`vJTgB;A!SS8lWnXg}1F8F`ltdp;wNf$`Q zO4V6(^y=R>{8cR}eR=ASe=jYHu4*}y?hAG?o$vDeTisjnz<2gO&ytt@VLQOXV9aoa z!GM`m#_QOIU4bSmzN%05w3XobSN-=M>yG;yd4KJ-^x3tqp3&&?eumATxgI1gZ9Q_? zYA?5eT>r(d%P(hM`ns1pAXKy}V!h7kC10z>70e;QGlMaKM20HsiQMi5MHL=?8~{ch>OHR1NX-!eaV!J$ur@n!60GO>3Tsyv+sOeGASu6{1- HoD!M+|M*YrJgOx+uemB4g{x6+&YJWfq}EYBeIx*K~EWk87r3BmjMOYOFVsD*`KqC z@#!nbd3#<13eE9!aSW-r_4bw_UxNYk_Y3tucXq64pJ3Wk^D{^I)01D}tXC954xC_MlRJ>kbR+Ly zS4kkyd?=VV#dz)hli50q91Dv7rhA3*!z36OW;E?QeXeIYw*$lV*Z1G-l~Z7X$~8#7 X>He#el{PCk03_n+>gTe~DWM4f<*`+( literal 429 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fA0|R5c zr;B4q#hkady|Y>zL>vNJbryWz?^T{)u*A4X!2Zj^C-Xd${kiVBo_73c+N#A6#;}Ir z#!ZITn{?{M*I&>6J#+c_$nt-`pZwZxDViYt@BM}H^`GmPGwo^ryN_GyU*+^~4Q%yy zmonH^t+SSXkbb!Nuzb`yKpb$)Gc zcp!kQ!B+3Uu637f`im=m6*9U>{d-o(sP_NufrVe^OC)HJVlvz@eQXl1-u&g*#SC;> zJ5x{Dw>p+~CX+wEWoubpGFAP(y_KCb7fb)RB`f=BmC6EO_%nFA`njxgN@xNACH9zz diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rainbowdiag.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rainbowdiag.png index 9214cea81f9f5d2808a83d4dbc89635bf36e88e1..37274191d374e4030edcd0dafe98055cbc0fdae6 100644 GIT binary patch literal 573 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcalY)RhkE(~!XIA!A2IY1H40*}aI z1_nK45N51cYF`EvWH0gbb!C6fCdQ|)nCVmLz`($G%G1R$q~g}wyBjAS3gB@KboBn> zlAPB*CyC=8n>6EQW0ikKtBbiD(%x9lc(NMgh99>dm-wxlx+G|2%%nAQ=I?s?RVwV< z{_sy_yxh4{_rx8(rLIu9w{7a>`uW?RXGi@0dSC9}Rz{A1hPjN_ULW4C%jeL*l*9Mo z=fnN$!AzbH4DS<|L=xf~fM#QWwR6titTIzSE7NydTH&uf<6-lbFKiyh+EufdmrUnX zJgZ%Wp#_gX#z%{}mo4o}v**^Y@0k~W_OpKGzkfT!SS-r_nb{ohs$!lYm+<}1yZ8mn zEH`8hd|c{wcPt#K#ryU|*v0#weN=;Q zJ_+9tpHZzCE5@P5u!yrEgGu4mB8GXdTzBuWo$_h*6sy0L;ZZlQN1b+ys?0e5b=jWS z!(VQveU|smzJF@pp6J7EpWiS4dHwSL`|B3o%Qdgx#q_rB*Wb5N>ux1({<-_wt$pX> z+y7q=IQ@0e&u*q46`!a3%HIE@pMB%QulgN7PjBnX|5wTTG;jCM$F-Ht6e{zAN`|oTW|qGHR}$IhR3u2@5=FMV0t6+U=agIqhYiVRO&kWJzf1@ z)|Z)|zZS1KA{8fJ;lB3a)5h=T%lG_!cEA4gd-i*k{}!0;vH7sg{`3Eji>F^-;3CX$ zk;TD;QNWjh0_HT<3trauW`C}}`JtvE^WX8kmgaN*7fby~%s;p5uUzXNqGlFD$KYd@@;_J^w`FzNiqr{Va#6b14?nY?c5UBuDQjSA zSj#hKfA-q9ub)3J=YR0&TfnJU$!9z7oe|~vy!Op$kHydL`|qyY&*8~ ztz1L*mV5XAUgewrBDXjDwr#^k_AO`Q7aV*pyvCyb$;0~1#e25JH49Oc7GbH`TC>6Q z`@a7@%d0K|bK#wTU!E@Py)*B_#w}(=)rWp({=2bOJ^Ju))mEfitTD18M9Q>G0qb?aPFl(lg(xZf3Af0U#4$lxnX-i_&!tbUHQ5f zjD?$l!EROc@9vGC*?Sm1N=*S49b^Xlt$M#(Wk0svVSNWI*cd!r{an^LB{Ts5qLwE4 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rainbowhoriz.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rainbowhoriz.png index 0d6f042d9fc060864cde0b49007d011ef96be183..9b6192dd6dc2cd997121bc70ef1d2636f20de873 100644 GIT binary patch literal 411 zcmeAS@N?(olHy`uVBq!ia0vp^3xN0l2OE%Vw$3OAQfx`y?k)^*AUI{>);T~C&H|6f zVg?31We{epSZZGe6l5>)^mS!_&L+mEuk^uH;}-)1qlTx8V@SoVw|5TmHaqaJIB4r$ zy!_S0|N7+5j*1_=S<)ShdDk>P-7N^zeSNxQ?Wr>-awbYnRK7g@#93bD&(FVZv^VFe z{Vlk2e`3Zzp*=ev`s>>ZPZbehbzx)#YC!=zcD|22P^z4_KyK&$gW)^XAG>HMaB*;P zpeO=y<~-cK*6p#&lpqJ7K`iLf4-Vey|6SldyZf{8BD4LX&(m+PKe5AZW5uSrdvB)PFRHZZT Q9RP`Yy85}Sb4q9e05tq|zW@LL literal 867 zcmeAS@N?(olHy`uVBq!ia0vp^3xN0l2OE%Vw$3OAQk(@Ik;M!Qd`Cc-ajG_-Gy?;( zsHcl#NX4ADcLM#S4MiLR`>)7OG@WQ_nB8Q$lTRr3f&R-0+N+99oSwXvEK2RI|C8eJ*JD!4bAFHH3zs&9V{A)-5#=Z9aANM?aKRtfkwGD6kXaC>yZ2ii|RlK*q z?f6-2`}N|hFvc|C0M;(4@U%+mypvgE%2t@2MKJfKWWz~a~kGuaqZZ(fO z{PS09Zl=Q|#*bA$R8 zSm#j3hvXzkRFLEdE4u^N4UfO9Ue{jm{a$YQ zd)aqiGi$f!x1Zb23^Q%zV`iJ$``(*&f4}w9UEV?O4aL!TjNy6Beg&mZz{K|O&veuO xGUxuw-$X=TFXJ}-2h}$B8J|>;8FOEyk2c2I?zH~?7MN=oJYD@<);T3K0RVmEKUM$$ diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_redtext.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_redtext.png index 46564a9fdcb8c6c136a13a723303847c1538485e..c180b8e674e6683ef2db9097c7b4354fa3d940c5 100644 GIT binary patch literal 520 zcmeAS@N?(olHy`uVBq!ia0vp^4M4nrgAGU?nUwMuNU{XE)7O>#Ihz=tzS0L*jb985j8i>b978H@y}i3JuPH!;?Sc2> zCe6ji-Y$Fp;9mOsJM9@IMujaczE)RF{JbV8f2fsK`%%3^J@5GhAqIx-;4eEhpWpeL zV|M*@|7S~CzV@Uw@^g#d<=IPH+wc0f@KbngUe;~1w|&PqtjoP^Huu%9s=cdMUHrWG zwY*mS)$hknFn64)S^BH}RJ>(F<~93}y7g=sv(#$0zWw@ZvyQv&zRX!);za)2OW4|9 zy8l`J_fBS@58&W~klIf9hKD{y_6!GkCj|YeFgwWm;DY!ahX3E0X9Tjt)qxnx-fX&G zKJlmJ^K+UkxAL|xWG~S4=H2jwxg*cvKf^!9X>WIHIPoX!jmt*S#ULkSD{ue&&x>2{ zgluK4pa1dfsdMjFKX3V8^8R15FXHc3X>DPAK1V+GcI=|(mlr?(Jb$KqtTc)dmxcf4 zRqbYP`p&HL_v#Dp^YMRHUwl5}|Ao4S;MjJv1$UVb{$^a1{{OAq26-fXJHB$Sow0%C S+z;WaAW=_OKbLh*2~7az;n7q8 literal 862 zcmeAS@N?(olHy`uVBq!ia0vp^4M4nrgAGU?nUwMuNO2Z;L>4nJ@ErkR#;MwT(hLmD z0-i38Ar*7p-reY@lqllxu)e34bBfw!!TXF^^Q+_&s_!36*xGoBvt-k`Jd-zO&*a~o zDYbaMddiHQjD8_q|Ig(L&SE?u$uNiU054a<)~LDj-oLlsUw`BM>9XCqr(Ayh{BLje z_0OB<@}~6x496dD+@i0q>TUo3`s>%vzrQWA{0WizFu&o9xkC1{onVCp3}4I@e*bho zD=*@3z4Ynx-|H9h_m`Kadj0+5dU=k$!OuTF^6Tr5ytdP5IQ;NJ&cE6PJ}c+P3)Qy& zoV`CjrbgGE?GV^OWD|FEzB6l_0~0ww)-f<~^f%+Od%O!GroU&OQDNSY^wUt_9K!=1 z1_}s;8@H=!cU4w--JW{kecpdme z-Jis8FzbFp##TlthYj+-Yi~}m>0b8kK0hiXN1>A#^lTd5eExXd zroJb;oqa;B-M?AS`wQQGVAyp2c>L!-hU;YiODp`W`D1!s{_(Acj3u$*Myd19%NPHX zxX#DF;9E`AmN%b&CZ7XJ*739$GgvS;kWK7Z#gO&hSN`qUyUaU(GlH0FOTRn(FkQ`* zkzSTv^1ObnR>K?d1+lxT6-wbP0l+XkKmMUWS diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rgb.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_rgb.png index bee0f564a3c110820102625d9f7ff738caf721a3..36f48e75d7aa4d22b95be713ec917c1fb66ba610 100644 GIT binary patch literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^2|(Py!3HG1+{xJmq}YsKyb>$t#g1PoCO|{ z#S9F3${@^GvDCf{D9B#o>Fdh=oK1{RU%A~$A_pjR%+tj&q~g}wJBD1%4k9cUOk)+k zdnA57DE-9XWzk6otJYi#V3dUJ1Ki+DFdqp&}b~6q50MByi;fP@0DBm^Qqm_XZHH4-x+H2>TcKl zJN5nhmlQ6GD8~2M(|@}<=l!#ocUKE;M1pwE|J?uOTmQx%vay}X^ev>}?f$p+Q0W6k Y@vE-tZh11_^BzdV)78&qol`;+0KIZ;DF6Tf literal 559 zcmeAS@N?(olHy`uVBq!ia0vp^2|(Py!3HG1+{xJmq&N#aB8wRq_>O=u<5X=vX$A(y zhn_BuAr*7p-Z9LQ4is^?D9GXz_UO>rhD%F7Cr#2?T{!*dj^gQ!nJpjP9u+wq2wme8 z&trAgwv|h%mi>zXZVBElz5Y8I$yz=+|-IcNYmwV5=KK}D{&EcP)e--|- ziZ|V_&Y;Z@#;}IrMkr%m<->W!r@6ns`J=6Wr?`pwp3eYrx~b@8{?(y>#`O;uG6~FU?MyRFWA?#Abgt zG7k4RGJQ?eyX*GPze*oH^G?;^D}yc201(i>F?s5y`uTkGV?-?`=Gr?PHG9tpmMAG= X+_yvK$MqbWXCS_(tDnm{r-UW|f;L{cW=p5=&2(YkS?zs7;Gpy77tA}E6v7)$zMq%Bf4bqZ z=LZ{?F~v;&@AvE5UzJ?OCqT~Wzt7|gmfRFI@SFE#|2BpqR)=*ACqx-Q+8Ca2HN-GZ z&_)*Au6&?0W5??|IX`clW`46rdqeUYpe7*G#_Yb~w?5GgpC29gwDC3*9wWXpDd~v` Uc*}Cl1bTwO)78&qol`;+09a>ZWdHyG diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_scroll.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_scroll.png index f5d78debdd3f407d1f9f4fb48e8334662473d52e..cbf936810a18574a45b884a3b05ee770f3068258 100644 GIT binary patch literal 460 zcmeAS@N?(olHy`uVBq!ia0vp^4M4nrgAGU?nUwMuNU{XE)7O>#Ihz=tzKWz;?|B9W#z;>W$B>F!Z|`he+ms-}`r!5K zqplmaZz*6bD-ab=VD^q|VeH^!Wfe2qGi}eS%m(`(_3{3FYV5m;fd-#A_il3gsZBE7 zi#j?wcCA~SIcvxL_q(^&m4t>qHmTl!|M=IcSkwAhu_CT>&Og8U>GUR<4nJ@ErkR#;MwT(hLkt zS3F%DLn`LHy<^yQ$U(y4q0XDYJss1Umb&UCWWVLy)4X-Up`Z;{j$MOb3hw_-NYt+9=uesT)1G^wB*PrW1Ck6es~OZLd%pPo`~Ls;WxF3$*ofVJ z`)%MErDf}{Ym0TeF8>^#e*OF+ozv%@T|fW7v~2C$n)?g|Yz*lj;<{GDuLEEI zXczsgeNZXqu=(uz^zy$tb$oja(|)rx7&BNflTYjjW8`6L{!nGUcc1qCr+;gXK9*)U z$MAp$L`1O$=(n6I)Q|i4lTvFem^*Sd-)wnUFe5kI>GDrDftz2eYFGb+cu?Tx&zd?Q zN8o0O)!AJ-t6$bo;305e?0CT#5-NIX)0r~cEVJ3IKWpaY{;ROzTYXjQ-$hOlV8>5mUM7!1`@NjM-Zfs#5V`icbl+bFO?|t6thL_{ye;egH@l7r820M|8Ft1W z{BoDM|G4t6d^0YEqkq4sz1YqE?f2f_j3U!PX$qXMNFZt%+q}2uJ*xb56PV~3JYD@< J);T3K0RSR(BEbLv diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_shower.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_shower.png index 074708133c2e24452d08ae6e5184f92ce44dba96..1546c8dbf130906a196b7ad12884463a464f1893 100644 GIT binary patch literal 743 zcmeAS@N?(olHy`uVBq!ia0vp^4?viM4M;AMrNqdhB*@BY2dOGx3*9(TEu z@BBG|rZ=RXlJ7hI_=Dl;>H7a)%Psq}^8N1`yZQF}-+%wT!ia@P{qAAEe&y(8xLq%Bo)d0XG* z2miZL8tbLG^s?U4{{C{)C;xwZo#D6J+oSHvt@b}Fw)Q`lPn{!QD0l4V#OI7ar(gjM zRWI8o%g>A#{@d`W`}B6kua{q{%bfjp@2Ba^JN!GQ)a_YOw@cAHi_d#TeTjJjuiAI! zSI2)VubQ8CqIZV#mp?d6#bOa$sG;cToXvlVK85Su+!eDv{3q+v+YNWFeA{5ga_j2% z+C0nuzdyfUbnQK7#LRWCXPvWut9K8s6^*fCR-MJqPyg?pJstVw@X6`&I~b#v%O3yZ zy!D>{a{2RroaZ;J{eJo7@#xw1Xc}SMGa2XV%k^@S*2(Y=5{oL8J50?l(2c=vFPgg&e IbxsLQ04zu%d;kCd literal 1232 zcmeAS@N?(olHy`uVBq!ia0vp^4?viM4M3;i8vwp6ESwbOs^7-MLZ@=yT|9t#-{=?!;@q54ht^0cG`|qXCe;@t*q2~YA_lE-+`yN+p%dhyK zU%w~!JNNIukG9(1U%zMT-|Kt$|4B0e-93RpQ3dJ+a+$vyzKL(&ulA1lR{WiRvvj`M zCDhJ8S9_>eIM>+1>cI9-A71}%xmsMoeg6MLx0>~(Uuqq`fBYACclqu2V&@mu{mb6; z;&;Ql$A5pnHnwm7^>cma|F#BlokF>1h%w>7)SI?d-%tEA`o_A$==R%d|C+wBo>;Ta zZl8RGC8N>m_Sx$X^KZZV@6tX7j)K%>nY&*6^_REff7}G-A1gfbkMYnygFmIe|2qDr zN(3+{np8Jfe}DMq_WO6td3W14=l?%i!!q~g)ZY~=wV$8VoBg|D?NZzSH<{V3y#6-l z@6@-yIZh?Tto`t17DHrDyXd{RIkpFa>!!|9+s^*B+^?{@@Ee1FrF@>u-G7_+ud9`J zq&Q82qfu7m!MR$C-{O1fx!75El**s`$NGMLQ~v_?h{v^7QA{=mq~2e?Xr*!Bm;Qk# zc6Z-=f5}()^8J5J8IcE?`TzGGd0`j3s~#lqgM&+v(aEDhKuDp5g+r0isN23yy3GEs u)tYzln*P2GXPjz|3qqujRN-L0$S;3kKc~`Iw*pv1F?hQAxvXtZ}r{PKmExd_xQW#m31@z-QAX3 zQB~!2DgU-vi@>BW{crcZKYaW4ZP&l;-uJ$I`Xtn~=*MrV`TW&Pi>H*Wpn@5|pV($M?2roDi@Z$Hb*Tg$_nZ@d-xn`vG4f7aXk)Awy$wMt+8 z-t*__TbK)O_2q7iP>KCe{Qm#znvP#Q6H;$(uRien`SXnL4afg|k=u|tYsKHp-S2;I zxSO~5>+W^dKDTS{wRr{rlZ# zpWSgYXW!XlJ(lz5|1P{(^5SvMH=ws(zs~;h^Uw0Pg))ch_J7YU+SdJz-NRJ;-xhvP zu>&EYp(mdmmB0P}_MWPDcZzn}q(pvuD!RG;mfgA2ph(34Ggd#o$Gh@MX|A8nOB*{o zHCsk|JG*nQ?0=kMc=v>>An(3t!)mFv#A{gHJLS|SA1fKt^TmH9zn{N5|G}%nh24uh zb}=?nw^#$FrCwqN#==)&d_I`-wWjXf`N+eC^+|TWb-&L1 z$@nXL5CI_SwqTlcQk=5J8*!+mN`W5Mb~t0 zyS9JI8>C?Wn6~r1BE(7jxSQl{oxJ0~6aioDRuqa*SYxST zRvuGaj0D|{#az(o=6)(^&#EJ39|re=GRVc^d zKi(60BzjAau!5&f+3ohS`q%7<%tG|bYv^2?QW+*p%XeOASjvkjE$^R=M2hi9su9y2Ju1E{^4+!O_?n(f6)f1RI0yi8<51wNts!4vj+3~ zal%&QS;1x?@`d2)*&&fZ?05d)SCju-aU9v%d6kDrqykLRSQv`9spaW$Vp90_Oo~S* zR|x)msfpBhh+9*4ni$)$+VcS~dmo@=h-w=gPOEvlPzy&iX$Y9@to*ywvRT6S=hhJJd2rnW7XtSh z2X9C8yZigVy0E-F;I)BG-W5wp>am)%fen}&GYu7co+d4!Yn&%Oo0XZT&Q0h(*fxM5 z9K0Xrp`2X`z(YjoZX#Z0m`y!YNX0`|yHBc3s`!m*g0OnvFY=m1e1YH!UqhqO*lb>c zvVMMHp?`32DcWoq!UY0BzWI|FpwehMtt(-uO&~}`EjbWPu-WDjh60$7E(T?j6|zy_ zF~|n2G$8xxS?GFuhvwIDU&7pk5!MJiz335}iks|50ZW9UUSDE=YfH=ESbAf$Z*=gZ zEh1DDO`okMmE(QdKE0lj*7jz}F*TN2kdIo3)p}~gWizKyS-1#vJ`2+?o!MLR_k9>XM5#6>(%(v?R&$s$AhOJ{NoSTbfpIS%6C ex~DKaLhHD{c*1?}-QLV^16A);Gl%zm-0=@44nKbY diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_smile.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_smile.png index 6437b068b18f05c34454678501932a5943bbd04d..7ecd324e8981fc88ecb24c4ba54100cd9bf33cdf 100644 GIT binary patch delta 176 zcmZo-I>R_YrJgOx+uemB4g{x6+&YJWfq}EYBeIx*K~EWk87r3BmjMOYOFVsD*`KqC z@#(8K=-(*?3PpOlIEGZ*dVATB>wp0V>xCJ=@89fMD!WwR$oFYJTo>O*F*Lhw)T@6} zdUc&x+OyYF8$3CGFVdQ&MBb@02Yor)&Kwi literal 258 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9F5M?jcysy3fAP;iT< zi(^Q|oVT|&ay1)BFg)b`@;Bb{=)oYb{K|Jx+;;QPAyHmu%^?=JqoXMgpTvca*3i|b#TcEm7F&}JxN zby&x6LX=@AlLE+?1|-3^90j!|cfQ_z^Kt8Jkkp+%2J3p6iki1-*i^%exTkepSfJ4) R=r_>)44$rjF6*2UngA<4VEO<6 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_squarewave.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_squarewave.png index 22a1b389d25826f1470e91ac38345e70a1164f59..04211f366e8ff189a5b4bc9b0134925e42638e1d 100644 GIT binary patch literal 677 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcalY)RhkE(~!XIA!A2IY1H40*}aI z1_nK45N51cYF`EvWH0gbb!C6fCdQ|)-k^V{l!1ZC$kW9!q~g}wy9d`kG7xbH{J(x> z6Vn}b)_?|2=_!I6mosrKXgI;Tgz=U_bz19`lQ{~9x3@o$>EsRC;c;?u!e<#Kps{O? zT%XguYu#@D`?vG9$1mOYWy}5VwH7jbp}%VHx9@v@_-BpYz4|S`_wiqUy)~o$j@?{8 z*Z1|ew|y`C9Y1gXdrNWN!vaO;9#+`2Ez3M)z~j2S?3Ui$`P;m|FMoUKZ|3eY`{y>l zH}7L!GlMbVYTenLFUofR{i>CDtIsg(^>GR39>W;D>5u-pTQ3#)_Ph4tza6o^{`uct z`Wxsj43KY>y}ZinrQN-=a!xltGbZ(XFWg-+|LKgaGUa<_|1At~^t@d5((ZJktrZ)? zAC{`O_6Ov5-}HW;o_~AWtDh_w#(@O>&tCWX-TW)tWoK=dYFn6P|6GQLL4v`6K_u+= z8n$#-YM)Tji72RNEc+Sh2>c!S`~=+w1rG*Z+^YUzQPemLY-R zUgq2153|1~_k{k|T)OJ-wp?FREJkkdD7#;O?cMLCcmL0Sv44xq^>>wjXBC}W_=@4c zB?$(e1DoIMi~s)a_tyD)v1n!pxGePj@Zrm4yJN4i7i_*M!Eohi~syH!u^Qk0|l&7no%Q~loCIHej4}t&y literal 1096 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcaloCO|{#S9F5M?jcysy3fA0|WCf zPZ!6KiaBrZ9?X3dz~CC_J}c^la;n6w1w6NZhd3~bFz6}pUU1u#{y|Ck(aj#&)AbML zDsP+-I7PfQ=48&l|Dlcsi~_z4F2W2K(^w0v=B|7Ezq+=zc4e5+z54q4_1}KiPW+o# zT_MZYe)aqQZSB{e7Dbl+ulxP>Z7z_XIqUV`Zwc@ItzodUw_p8HKf$;5e*JB^x_PFh zvEOs6-~PRu2c~}C{hwH0q5td?hl>fLKyDa=yu5t<-fJfJ?&X*r{nq~WVX2K=`2GL4 z*1g_!D{uSiclYzx|NYm$y?&FucEfG`->F~TXZhyd{&zFJy1Kw_e!N#Me_s9%@0D*4 z{`gz}q_*DyZbv_|LGtmlXG&1S#;;qlG%d!^jw_v}0DXa7}y zzWIO3|9^c+mB0^s7mcF%Z?iPKJ zXa6P95M*)U(xO1iGZT zV%M_;t5$9MeEzb@(&^KuFAq|$ojE_qD?UE{=%?d_cXqAgJ{>GL_=&$j3O*4TYjaE*10o=PhP?dwb{qyX@@jg1j_k`PwghuBfl)KW(?p@&5OtoB7)hXYww~ zhX29e6 zS%3d;oAV2QE`41e_x;45&#w)7 zxFi0+LV4ek(>MR*-j4D-WqRPJ&94r_tAd|jTx3v>z22JVbJ65%rdiz=Hpx5NR(}iq zb=&4!X>9jfLD9MV=+=PvAL@gv)_2T*W*==-7yNRsQr)cej1?JD3=g*R92WS+V{m@+ z-$z*VHME=dCBMiymKvFtWw-aw?^FK2|JF^`{~z|L*Zq0;*IM~m_P)WF7+PNL(lgng zIqL>n#C6jx44a_qe+=H?aK> lzgEg?d-FvNy8R1U>KW2H64qqBJf01b^K|udS?83{1OO8VN<9Do literal 1252 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcaloCO|{#S9F5M?jcysy3fA0|U!6 zPZ!6KiaBrZ9?X4|A#pr${g!mD1q}ymO&l0a7`|WN(QGhzEaD*LAvwXiTe;G8(Zn)? zxcbL`=06v5b*fUA|7YmOxBmY+g&7PTY7C1w8#3lHRa8`1#Mjqb$gDb<@+sVO!u!wC z@87>~KD++)uRVA3y3g9n^*=wF6qr-@@^k+4_uqf7s+He$?!Cx?&+28!}wbTLmjq~N+J*AdYSsd2SN;l{Exu&D~Id?-` zZGG9{`F8P8&#y1r9lJGdeK#;=?3#5pZU5gY#tW-YAC3QVlXrUe|7Aa!6lTFv6(!7T z)eNPv^QWIq-T1ZQ_~VZ@Gkx4P&%gI))8}gbgv~cYRL?&Dyy)}sZSwZD`=S-9w%&ig z`f65a&cBBRE0$e;nZG}d;Y-%;yJB&PHG)^6Fy=Ffez+J5nOV6nyE M>FVdQ&MBb@0D}A_T>t<8 diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_static.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_static.png index 58f762586904eb005341eb5415b85f285ac43546..08e96db150839062238928d2960906dc59a1c990 100644 GIT binary patch literal 355 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE(~!XIA!A2IY1H40*}aI z1_nK45N51cYF`EvWH0gbb!C6fCdQ|)nLhnv5m4xZr;B4q#jUq@H}W1f;9+r4?#>W> zx1Xy$K}$+&vYX4C-D*$WKg}*m{;`XJ;eoJVU}&gdpkQG3TC17+ukG6WyWVHr{#AX? zzwb+b_VH`H?5+L6(ihY|SN~m}-*C%k&Hq;qwq83SJ7Z>fURqyFLoJt&c)=Qm-x4-+ z?~B(ZF@L*gZP>K>Row3rf*aVsi_EZKUe0ClmuHK7qwsHjpxbbQ1Cf{SZ=Cu+_Mdm^ z|Jh6$44|+<0ydM%-_M`^{^apj0Y=gJ# zZT`t}0`jgIYz*lP1#ArFS`B~e?$15{yvRc4*Y)kU*V@SSyJn{BjVr(Xc3XYi`o~2( zO{D*S|MR)#tFobUaR5q%PanN{gQv`_D^s7tbg;5PSq2ueP#=` zggxJXGiO#`^mDmjkg}&mH|^h*?XLU$+Irzsoti5g&u=vB`f%|VZ@}?7yZMv{AY5UiKl+`b19h1tiJl{cj@c%_p1&YAAepaTfc7Of2sOYTYuy$%waqr$uM|` zzts$PPtV!E`qhua$G)>P7&BNf1Bo5={0Zlz6^_f>?Ng`JvAkRhKJWgXZ;oUVFIU3D n^7r@iYWyMAf$b!L_|0Nfyhho)fcXnBB{F!r`njxgN@xNATXYC$ diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_tetris.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_tetris.png index b6c3fc72e7df126ec9491add095d656e24fa06f0..d4ea13ea39bafeb3533e8e26b17cbe49f7fc1a9e 100644 GIT binary patch literal 1137 zcmeAS@N?(olHy`uVBq!ia0y~yU`znw1`al$$Yj+W=YSMjlDE4HLmUWBnYeWhP=vF< zBeIx*K~EWk87r3BmjMOYOFVsD*`KqC@#$-(PyblNz`*>^)5S5Q;?~<6XL}zx2s8xt zyK>bQ1gOcoJJ_jd@QJp3H}c4ENct(*8vEWe=EA!gle;0tmrH?W0l|Urh&&s+d;J|> z{vFNM*#7U$-}U#--}(Rf=6Rd{_4k^+e!pi9_{;nu{Vm&u&++fL10JzHU<;%?C;a^Py59Z&RmMM`53zrUwfBy%5B+E+_xi-KFaPpC2Xv-Ktk^`+xt+|GVt9&)+BR-g=K=?bb`{6*tQY#&6|6my|2G z@s{n4wY483{}vlBuD`i@$G_9u3dszw+J6JYf1T&K|K{ss^9J1)yz+my zem%&F-vLnBJrACr{J(wA$Ml!4U%#GyrJ9?e=*_hsi=J2RtIFGdfBMZWnX}f-vzFmY zy=LF{_-gU-#~aW5YERrz^{&KfX4*bR<^%?2qU@oSq7R(i|EhlN{meDtFaw)G10zoY zaW?(Czi9pX_3<0!1^K^Le`h`5W>dwyqwy;cbpPXe!0_VrYv}`e47ET&jCl!j#Xw5` z{{B^dUHOnG%LK!Q&8hJWzkW?U`#GlS?`4yxd=IY8%H{>e*>7PMVoYQRIJ0Pde(tYd z-@m@&ZjhNRec-Xhw0jp4CFW!SeF;QF88UA(&?B#3?{|Oi$9N)6Wu;U3G433a~u*H|AgoiI6H{PL^+<&dhsk1ejr0YmG6 zc|r_vh6fy8#Q#BV?{8bh;hVLJ0gt5KfE0SV`njxgN@xNA DM&3y9 literal 2131 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 literal 828 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I4M=vMPuB%foCO|{#S9F5M?jcysy3fA0|V1L zPZ!6KiaBrZ9PE4KCgKn%E_>TY<e>~5eSzmKDwQu7eTffs*`=&pRIsQp;dEt!L@vn=j+txq*vGM2grzY#q z*HpJzPU}A_KYgP8z2E)DYuZ0<{MlZ5?)LkCRc-Gd7oUI61~IT=XWn#6{dz9F>F?f8 zmw&!fZ+^+1bH88moc?p?&;NNppYhB$Ij(>1!@-}=KVB}culcum-af|T`}688-#K0*A<6n*)Z^E#0@vJ=$z zw{QFXUM>$5#a}-$r0<#i(&pCJfcJO!cWk{||NX{YUJJLqb945~-ThnMU(OOCzTx@L z-PPOf-fhU~rYx9kMHbwxe}5ZjY?b{3>m7{1IJ@G^cC9nQAyx*`=`og>Ye=AK6 s>|*#_o)&Db@LL(048duUSmHm!yB7=PweRfM4a^Pzopr0PuxhZ2$lO diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_windowsxp.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_windowsxp.png index 5ea923b008c97832bfe8add89f523edf2b30f864..595ab8444b213be7d18bf6dba2ad44b8df08b381 100644 GIT binary patch literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I4M=vMPuB%fY)RhkE(~!XIA!A2IY1H40*}aI z1_nK45N51cYF`EvWH0gbb!C6fCdQ|)-8pkY90LQBt*47)NX4zUcQ)o-4iI5`Fqx}! zYNKMGh^Dko;`)%bFT4^7>efE74;W7cEPKXyBk=+6iwic6D??_iyy7QXEN&b!?M}zi zWBbIf-#1sCHs}AZUr+k#Sr`}`oEEE@Pfd*sn?HZwe<49Zd;2|7OQXL0d9cIg=Izd3 zQbEt%U9Ma=km{ZE{QC6?+W&vOQmT8iKWEPU7t4-5Jj=9i@6O5}cduIY-Lv!G#yI=u z%6NyV@$t^5{%q1YefR3GYg?!Mj+b@#YHD(}{=$=GHxvzP6|>x+v!Ix05)ke#0X`H8e* z{f(c%@Ie6v4F9k2|9JD*YTbH0C8b<@h41c*ix#aCf0vT4uI4H@dC`W+ORO2=>;H%5 z#r-y!Z^h_Y%=GNt^5h51E9Ci5OagKm>{jj)E}khb^Ifa{^ocF2U-_MR`tk6K(0zy>HvTGG6JQZoWT1O5Wjb#oedz^UiLzi+)#w z?z9K*+v4_4v)(WMx2Al{)#XRut-IEIZoY^sPZh)a;_vfn)D@UZmNUv!+0U)BL(wa- Y$zD_czopr0B3|Gng9R* literal 988 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8I4M=vMPuB%foCO|{#S9F5M?jcysy3fA0|RrP zr;B4q#hkZyHs*!0${hcA`AEyv#>QDQHmr2M>-nl7|AB*i!(CpsS_Z2J&zN_-K5)aA zt%6Bm;yV?qndkJjKA$z|l+xZg#rt+1Kd-JhefI}z-TPZk%Knq*6%bO;WSk_VuyQSv z&HjR)-_P&=pZd9~s%DG1&XWfpH-8rA=exg8etzQ1zaPK8GJX>qQT6|oamerbzdwI} z_;qpb+V9)BKD?HnpC4EM_gjIn-9CHSX~mz9*`GIf*Kc;e;c@DB_wf0Np2;QC|FchD z@BM!N-Fx@{FG#Mb+etz8h{Z*gWfA_8|ug?tMfA5jxv9n9}KY#zOe_2J_TBbe4 zuP>i{J$bo2|Mqe)!Ux_38Di8T|Xsee=7w&sus~ zTD|RWyEa8thae^u@(KA8`46Y%=jFdU+&gX0`QueNwekgfy34=%-JSHEF|vQ{d*-n1 zjFHpl?%_XC_2x;f!?k4f_spB*D7Tnt&W#G|!uL*F>p%Rs`SWyp{M$487}U!u^*0uM zcC)H~Tg<X5aK3*}uUGKdS$J@7o|Oov%Jk{dHMxJeYZ_zMc}VgY`~k-;w?Oc4*+8Qc-+#WkU0+<2ug?FW?{~$^f9q!298iDv`0Td-$Me~pGyDFYWVR`k&)@df zv@VzOP`l1maPD^bxBt<=XyUW}Dh%XR@7@r9pMB2ZtxPeW-`f7}o%@UP#IG3b1E%+u wZ@#}PtU=v9@BiQV-=9ASHvlJoQi)&E@5QyY$|OsE1!h+UPgg&ebxsLQ06IOJ+yDRo diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_yellow.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_screens.rsi/ipc_screen_yellow.png index 1019e038416120615cc62b9b28e9d503a61d2346..bbf4c92cb32597b0358929249b8678b9e74b484b 100644 GIT binary patch delta 303 zcmaFQe2Qs;N|I7LpD0JP^#WAGf*4w+Mc@G)zFa&JZIlz^3K*Hz11fL6rHyT7E7+SgI7k*<9 z?fPB$eo|aibm6SHBvU2^kBdD!SH}1+{l4Js#+CI`OUnLeYCJ8{IRCLQR{w|fv+Oyq zUA8H!KS=h8W)(iUxQbCpX;!TG*>$Jy+N)1+K4t!(?A`uPvui_cH*bE-40Hwr1RM`| ze_+-l|3z#o57xh#njvof+xWF;2J^qn73B%O9~oil81_AVQ(MNU^Mc)I$ztaD0e0szwZbW#8S literal 495 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 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_f.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_f.png index 688ba46f01f4931d63727121ac479a93b58b8c59..1557d80d67e320ac99b35da80a75a64cbc794e02 100644 GIT binary patch literal 4211 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 JPDHLkV1gVzD*gZf delta 2618 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 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_m.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_m.png index c4cede61551c8a4700098aaae229910682778b80..2d5be733f28e4ba66bc24cac43eed92ab384f1c6 100644 GIT binary patch literal 4210 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 IM6N<$f`>d9p#T5? delta 2618 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 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_arm.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_arm.png index 382c95f69576d5fa14af20c46d62a7f5a76b4beb..eda91a212ecfc8b7ca9e18458a6dc4e6794e9eb2 100644 GIT binary patch delta 555 zcmV+`0@VGz4Z{SGBYy%4Nklh(NIHyQgaR} zQqph*T1pBE#0`vI7Na07KTgIt*?phHI;_Og_}Mdw?Fb=+5JCtc{}ZFx>-BnVua{;x z9LiuYkj-YJqMc>go%S<~dB0mNlO!={XS3PM-$gT^-|xGTx{X?zrlk!i zj{aygGON|<<$vglrvcxkB6|V?bh%qKXJH=N?RJ}gubNK3p`HTrGjezTFB^DSov1aS z4n%tpY9hf5DBi>COzmetXd`QH02Wg);awwq4GU5PT@YF;L0@W71Y>nRDwqMWKX@AT zfw#dL#1Iue35E!uDGxzFbu}2W8BD`6R+yB!mz`2qA%$Rhv%002ovPDHLkV1lG``!xUn delta 1710 zcmV;f22uIL1icNABYy>GdQ@0+Qek%>aB^>EX>4U6ba`-PAZ2)IW&i+q+U-|clI$i7 z{bvH37<598tffiT2q`TSYSHUBmq?|%Z$rlFVL3994z&>uhO zrGe^`pi2?^jtHH33DQdt)A=D@0@`WTQMAf?6Z$&ad9$RRPw-d2jpl3e)9)leZ)WIW zqQ#L9yqW3T0QmKoU=9{Sio7J|>u%f|jHI>V#n<=}8c^xWT zbq&~BIRsCJ2-&yduJGysSD42*I_?oQ66ms+;*2d?T)Q1{V2g=XAVG&{5bwdtLP`U? zMNWQ4BVpwU9*M`MJu%()61Q4CM%daaG|z~s6d^2P$$!gtcy)o9heC9SZ&+bpL=HB# z;mr9P)4)iy3)H*;zTMB4^U7c_JIWp+3Sj#wqUZRQ33wCDn3&O?F&JfD0ss+IXKW@i z7yxULb1d-?B8d?|RuI&%b>c)F48)viVw04Z3%IG|s!iO4yF6Ep{mRz&uR=A{+ODR%3DK=qAL9!GPsiM*<*Hm*YRcftTo02k; zX4ayjRaIMq&IZX1s~aY?)~Rz(J%?Vp^xCzz0rwec1qa7GY*z4TQRX}YVFS2MeB$A1%KA!#TspGtjMD%o$oih+d zAw@7QP5~U6oU^0Gl*pNL&JIQTL(an{vvW41GX@6Jij*zhxC?YL>dgHXZ$Z)nZ}h9o z1*h&s=05WF8Eeza(AbQfQRtu^jOfGnRU6gj#qL8JzWVTL`+pGBMF#7N!`3wG$*g73 z7=KnO_>E#&q<1N6Sg)2^q+Vl%^T0Jgl4EU1^FDK`zb!IbFUZ|IhM9&ELFAa)1%$DV zwQNGj`0oBD5>U4a`dvr0l?1_NGL|vC(?)M)j=~WJsKNO(j|2YVB1pY1rtAlodmEky z{;ie9GN@rAYcPzM*8Q;9j=9aK zUxI9<7_ykJWIjL==(YfD&B|f5_Er&=Vx7eVOo(Z>kt^(mYe=7xaNu$t243j2DSuUE zq-jwk7;+3A;DD&?tN3c82@n7q&{SSM=Qu}_${X^G!`>zj=a#oNJP&-U<)yFz&QP#7 zLZX~Kz?5Yj-PQ-($twaNHRd^%FbGHuCy>Q8PoHD`kd+*jHRFce+$ZwF$v{s{UJ^dA<4Z21&T_gLB)@-duJt_RZlYl-CuuP*pnkhRW>Xuiv{{g!9>%CpGz zq9{WVbwcZ|CHQybd0w+6T}Z0wcQNq;L7-#kP-o*Ynj(oSuDdN>acsQnLThYd2)p)1PAD{a`Fuj=q~8Af%5p^ns$ zvz#V0-ScReePQ;PID1Y%0pnj3rjN9dDJQJxPsI_XxS?s{8kf~?n-9NW#i#9$px+P# zF9ubZ@Hal#k&o@TvoZhx0DlHzOGiWissN_|nBg~U+W-In32;bRa{vGi!~g&e!~vBn z4jTXf00(qQO+^Ri0~rhmH`H1+JOBUy)=5M`RCwC$+Pw{fFc5~}i_J1L1Q@6V70J?rq zRW%R6hoq{iT|bxy;4F(JAF~FWqrS5)IL1k;vJk6N;6u`?EM$z+f4l?M*C6Nd&n8Cz zxz=ia1)93mF-|fst4Y0iS!Ilq?EVh`0000000000fG;_H=jh!53U`zMs+l+fqnN00000000000000000000 z0MG}NB*)QcM5ohltD zLOA&nibd^qJGxvh* zNq#sSQj#QUJRa*hOb{91x^8(C7!hF@Di+AtFv9aZ6^5a?zqMo9-EOxZ#T7YtI2`DF zK0nksj`L8SPJgE#345lTD31c3Ze_S`wOUn6W9E%}>uzV;COPr!f{XlN7|&;kvO z0t0LX_I=-0=vuL2Kv$Ay@FHYINr!*|Ezr;?Fre;$U0MMctO8b)bO;#G0u7A<18fBC z+DcFvUIm)ECX>mZZA<9=6cF*seeRiey;Jw~sx1k1Y=4az%A1s3qW4pv_Xd141zguH zCZ2lQGPeRRuRPVFC^B2+yh&S}6A=xkAPD0jAk+4fX@l=fsET>3aB^>EX>4U6ba`-PAZ2)IW&i+q+U=NIw(O`4 zhTj=QhF}oa;c(MhnL&o1PuR7yZ>PI=CwV*NRmO!u2>p_NQEvb1pX&a>C)5^QOr_?Q z^Tj8&*h1%_UiYV;yT9VOpHF;V@%ux+dwUV+5?Z-`*8Gfr^?&;}0e91RO78^K`Mek( zU$ke1P(KNJ7827a@UR|1?GYs5e&HVh{odAgkE6r#+frknimD_F}B`)$AT>3dX;>EHWLeV)R{epTC;Y4pkZ_ElX~&z{*uj~P?vXH&1O z_*=*tEMZGmhidsMd=nzdxf)l+t0%6ou6Yfv>6;J0r9S%QyH~$YJN-n(7`6+AhY)6v z(^;j27AClPkmK?iiZofE8Dt*Vql7nI{8_eL)1B2SD}OJ~(BKi~neyYy{d9t=g@X52 zeX|vMgAFLskIls2(JS0Rldyuuw8YkqkC9*wRcX{tOK%(Cz3a znSn%-EPn-TnsmU5G2uTYR(z-@Nin6AQ%N1 zQ_Z#1T3hWcG$CoGmRo7Hwbnapb|iOZcLwx6!jKV1awCs2>S&`++-Js_W}ao%*=Ap1 z$s&KOyvnMpt-k%nm3G`|=UsN)ZFj}hRGdalnt!!u)u#OowFlNO*AGzh4{G5cWdq9_ zYV?-!65%bKB*P5Af{Px+i$Q=x2gB^DKE`0k8D>`_{gLxfG8tye8)6_Bw+~7E3p*EX zL=CzB3O85c2i(HnMa~&?KSb^;Zr`D{jE3ex?2bY+>Lo-U?|1E?b|bqlt^3uBpSHgR z{eKqpKM|zE4@fgZo_XtDLD$N2wVjIk3^y)1_e$G0^{wd6SA*}byzH*IEdn}w?{;c2 zc_O{eAFQt<>hwv8vLi50cgxLP+Z;Re{b)AZOSAIQtR2nbx~fVuk%9WcA1z3A?)C5& zTM|c^URO2+hClaQba|(9tB^8u%Nli-)_?XaE02L9S}0JIOc+s7Z4wDdSF>N6>2q95 z8EN){vdM9>_bR^Vl?NlFsOBkW?>&_jN6(JL>+F{5>X+^A zV}dM;YmH;<#bN-LqmH29sDUIn-CF2YKtX(ENM9w4wC5t(3)*GMGITdhRv%c}?|-Vj znz!gxw+R}CVR6k8Us#RNSgG!UsEOuyh}MOL(&V-}w>e;qoTQ92qyOYI?#EuNowOdz zRcvd^vh#%&ZUce_Os#8c?sIAd)k_ar7i!cStzMenvEb+$_JPV~?saLz2M=mf+78%b zUgodbgKf6#b2+~C*LE4b<6KIuYdd922R|&onqd4*v`ussDb5tLtxi~2 zH+X>B>eOM7CgV<|gE%@fOw{%yEIk_JT+9U~ZjMy9M01^5jsswureoo_Wq2qVk6OU!eNKh%sJc9A}nGJWyuU5x5EQ4V_&f62^O-e zWvEaF{7Br8?$aWRkk@ZswSU~+$`TH?=_K9i{!YO_sv-qee-qX^jOWlMqvBbqm0&r` zLN+80VRk@(Nj!8$m3^kgUh*Zdh{pXdoD!%u+cgSTykU}&%kzRG9| zP21R0tll7XQ%QjYyu^-0sF66koQ%p|RuoJ5FoC+!$<{(`vkfsB6gR7PD4L^}_w?M< zeEnHH_s);Tfb9z=6@MRYlk$waLY+lou4OA5xGX2pP~ zSn<-ZN;t^PDW_h$lM9x$Kbuj}ER|m2V3tIXMZ;0#gu^rhCP1wdDh~v_kXa7|tZOr? zW`m3@l{iTE`+rdL)iQYQvcFCL4H#q7N{sB~Qvd(}24YJ`L;$J)rvRAYH*DJg000Sa zNLh0L01m_e01m_fl`9S#00007bV*G`2j>GB3HSjv^yOL&dslz)hpdrT@KB1OuEv4Pe8U(bwX zY)>&m1ONa4000000001RwxVi?nW?Cni_GUq0~pn=vhi!>{gu*Y(G#Gwu@=v>5u`2; z6b8QYO(?2{!oa7xJXni)Ya__reN0IlIsf}%;8PMu)b+!*P5`O^v(%3&-%`jCRN(ZPHuy=T`p>jj9p<@&5(0R)^PFN z;V|$;-(P)uTyzD-Ih{4-#gg9*~$)+VIok!;dvA{sv6v0+xOYre#kuGw=l^-^NtSs!ApR0000ZZ9RsqRvbbr zN*X(ATRIyG;thBiB1VnRu=uZl{9m#WOc-WncV@`!DnbY$gb+dqA%qYzGBncM>2#{{ zJTHSFP>$m$*LCG@J)6y1$&2H-JRA<=2Koecy-5lj>p% zcnEw#X(Z6((tl-`uT?K3cErT`%k%6IcT{i$s%Igb#>admw;OJI}) zpbkiqM9ZNDq|8S=&%4_roJ=OwZ&4K0#;hsu9I#rg&>~+VD^83*pU+okm;iNvRDkt* zZEY)CX8#E~iXtUv2f{G4_HIH5A%qa}RVbzY0O<~!RaLNmN&o-=07*qoM6N<$f*Yvn A_W%F@ delta 1558 zcmV+x2I={i1f~p-BYy<%dQ@0+Qek%>aB^>EX>4U6ba`-PAZ2)IW&i+q+U;0dmgFW3 z{bvB#5vyz=!4?{CJ_;{#(z(8}$#)ocEJoPQnyZp}ciyb{#b^f;%^n5(M zM=SF+Mcz5NK7ZP$Nuf%IGAj`r*#OXh=`5Ki5TH`nU?gXe3TzsOYAjJYr*dHoCyay4fJBih z3T(OzfPa;9LHuZLh@nxWI-3GT2$?ij&{_4Y5+iyYtDM3EAE-HvD zM1Rmy1lkbw<>HPY_w70hVzin1F8H3d4RqHmWzAtN>nc4L!a-~6nE}%>axj*!RYS?P zhV_=ysJ&RD9m~~b-wdWIn1@5}HM?i_nGx`?$Dz;q)Vj^9bf4y<=)xQI1abA~A-meS zjoOW>@jkTIu#8YX{4!@dl0D8J4y!w8MSozU_~z2Rs!#C_A32-r-ez;Ub!t9mX+4&Z zYbT7Ib`r0cvR1tHiX*-ubV}K*U@Gtt3dOJ=W#74ta=f%<&P@v>cy9dAfW=553*L*d zH8X_6WgwX3!z$P|vsTzX%mm~OUv7u9jilBEaIs`?_MA51!*3}I-fZ}FI77Fga7uG$P%{X7 zqn10VoAwgpd7!LA*%wvpIQ9IvO|J&Trd+uK`@bg&aB^gcND|=Qee!p0ks6RF7Lvd^ z?M|)NFl5&tW({A0;X9I~py-_aj!XZ{uJm(;f8PF^1i{}H|MU10nudGB3=Jo= zn$aBq006j2L_t(|+U?r04Z<)Gh2aNcAS5K#prl}m5PB4P#1IjRD3LOSgC%Dor-3pB z$(a!8{|30T&*$n+0ssI20Dk}gMk%X0ew0-m|0PzRrFFpIyc*w{#ylM_$sWwS0PF2W zlGONC!FiKn?hm{9eS{CFD@;1V9$NgB)d3#&rzGimJ1>5D@pryBMQ#890L)njUYBOK?+^9%tpET307*qo IM6N<$f+r#JxBvhE diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_leg.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_leg.png index 80e4058241fc00baeb9cdb3b2177fe1b60e98711..3e800782602bfce9eaf0c215d9b4307648332c18 100644 GIT binary patch delta 563 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 FV1hZip+Nuu diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/meta.json b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/meta.json index 047ed63567..9ccb451f20 100644 --- a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/meta.json +++ b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/meta.json @@ -1,7 +1,7 @@ { - "version": 1, - "license": "CC-BY-NC-SA 3.0", - "copyright": "Taken from Yogstation at https://github.com/yogstation13/Yogstation/commit/9c046aa5327c71f9e93e45a34283b3a4aff58bd1", + "version": 2, + "license": "CC-BY-SA 3.0", + "copyright": "Original drawn by @robustyanka on Discord, modified by @pspritechologist", "size": { "x": 32, "y": 32 @@ -59,4 +59,4 @@ "directions": 4 } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_arm.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_arm.png index e05d331ce792725414f1a28214461f97e3c878d7..5055ea8dbfa90c127b9ec3ea35ecdee3b61c0b9b 100644 GIT binary patch delta 660 zcmV;F0&D&24XXu^BYy&NNklXS2Z3;(==3DoH(D)^0uqJVmuyei$Mhd7gA(d#u|-AH7zrwUaw0# zZO{$@&bfewUwc1->(E00I%2omY4dT;;p>;Z$Kw&b=Nn4|_a6)fQq?p~QL%hc^g=eCT4}W5T=ytoP-KYSg(TEk)lwiGY+EYGRuh+8lTf3bE02eA20t$!5Mo^WP zb8hUd+F9UH1+M9@2r2-Ke|B}JSDyhMVPdm(7FaHq@_INNdNb4~QG|~MgZj^hr|6yvfn6@!aHkl6Ri=zA`Jcs}-BgX5a~T%dB^sDy=-=a5%8ZWRmxMVJHN_M|`mkg3$Bo-TPv( uU~mwriW6Z3K@bE%5ClOG1mOr{><7FzdQ@0+Qek%>aB^>EX>4U6ba`-PAZ2)IW&i+q+U-|clI120 z{bv7v+*e7Oka~ z5^?308+A--ysmzpDdzJ$SH3^t{ndJSd>||_M!sHax#?fl(|?1(HFV768%A~BAI9qs z?LL9(8%Fm*yd@$`*3GEhjF_$u>1NO`wPI;izg1z_HLe#;>h%lzF^=@gx=yMy{BH^sLh@2@LYgPLHcWBDWig_e8HydCb!D_3#$0 zOg9O?F>-l~Pk+}#lIN%#(|_wf^`6n|b=ad`61}nh{<*K}M`vi!;kGT8Td5aS&J1(| zN9?0(fM_KuegYPH?uNUg*_+AG&wrIxC-)>eC? z#z>mdO4C+bYrW&l4$d9BI|zCoGI;js(}`@% z02qawfVgf5;Lx-&i#6p;8@Y{HY)F5|c@R=IW-D#PfMB*n;^_suKo_DLxnII9Xnuto z{VZ}}L-$4G-sAQRwYAI8JcwOUxQ!Ya(TDF=JJr66-McY-@55Ke|0AQZ5YWRbJM4s_ zV1HTRyROrm0k+T4%bF!{a$C&-W|J9V|ILC>IwfVK ztos#$PS;`!=WDW-Ni=eZ@F|-*b0Nyu4Lu#UYdMzcLu{rUXnzuY#Jv_uakHVeUl?vVQiWS@7wuL#AEKrx zycJVH@*%Hnz`NaM#}B$f3D$rUvEQT{OwUkdkgn1@k6JyJV|rBWBcSX)>^o!lh(N4D zIp}iffT+9`pcnDC%*BIt=hk7iXo&Y?=*YHUl{!ojU*pJI)*3_E07_|7R;$TNHh(C# zQ3PKUNE8~kCLSl^do)Wjh7ZvN6Xd-eNoFF@9gTDbyx82D9#of|5iS@5>Kz(`qX-(k zW0LxAgox-3wu6(;z18#P4Xu*n^gb+y2@tpU`PK-QhisQd0~$3u8YMGmG`7pB=G%U6 zjtx)F|Ln-tqE`eJu%3aC!50iV41ab(S{oB_xhoZ7z?l~`U`Urc3}9SkZ5oKLm;G!d zkhNoMBy>Zf7asjS?CT->VTk-@^qbLt#0a^;(%e}GX%ud*z6jwEP#jKbnuFJsGuG5D z1#MILO7w-F3fJe1To`p!+&P`9H3}-y5NaqjXbwAS6?dfBfwGDw$xzc!9e-%-pYCnMuKrUNp)mvV<|dKB&(B_a-B!2@b9z`A21rD zLH?sOT}opPP&6)Noov%A>Qe4eYgi}}yj4Pia}*PAsL^s#dKnYRjJn|uW7!1}t-vaC zHG{QM*)wo#nTH)k7<%iGZe5xh>xY&jmKdi=|8h!#IBHm|B$l$F;3D9TDz zby5(bDHF7{^*T%EtS=gK`e_o2u`Y;GHP%U*#Ijl`gp&SC%3xFgLb|Z01mI^0bp0U4 zI`O>&e0Bn3opk*`>s1B-0000000013ERU5Jm0Po*@TF%MB1kaswBfBI#+kL6jCw zkv=6UxI$V=id@30vG9sTE3Jpb!CwB85+HKMe?Eh4$p`=d00000000000000000013 z1JX4|t+lACO4oHQHk*ye^PGN`$K!D^oA&#?kw#yS$HV9%O@FuB%{j)0Ys2gHs{6hd z=kwWg#xc()P18ua8I(NfDvCmLx^p&w$g<3yO6xq4B*~9fU+#<#uyWnQlf2J z*8e{lZRI$4UDxt(IE;m`I({Lx5@%H;$AIq&pkvo{=6rhh-$~OnPaDq~1b@RCaKGOd zGh&LA?#1x50e>OFF@QA){zqUy02&qr1_YpCQM?&2tkc(NKrG1`dA2g zRT2TKH-NP_XrZn0)9GZchOKfjY?R8&)gtBa!WlKhlO@`gEs@GJw`w$=7+jNwQxCOjpC16AOty&3V8QaVjjULYaF7v1dw UvD9CxDF6Tf07*qoM6N<$g7Z1t;Q#;t delta 2384 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 FV1i*dd%yqy diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_f.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_f.png index ff0e9f2b018dc8d8d896c60667c5d160c8266ae5..1a9e84ba9bf46f5acc098204034cad833d55b8a5 100644 GIT binary patch delta 1129 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 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_m.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/torso_m.png index 2736e63396d7af0e8e36f253bfca92787b129e9a..be4682c091a52c5b234a50a150b5ed8fd969a992 100644 GIT binary patch delta 1093 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 From e0e3ad2198e66c0a74e4b0deab467617b92b577d Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Thu, 22 Jun 2023 13:06:42 -0400 Subject: [PATCH 41/60] IPC sprites v3 Final version of sprites maybe, significantly lightened darker areas to allow for better colouration of parts. Removed background legs and feet (what the fuck, limbs just don't work????) --- .../Mobs/Species/IPC/parts.rsi/full.png | Bin 24547 -> 2454 bytes .../Mobs/Species/IPC/parts.rsi/head_f.png | Bin 4211 -> 885 bytes .../Mobs/Species/IPC/parts.rsi/head_m.png | Bin 4210 -> 885 bytes .../Mobs/Species/IPC/parts.rsi/l_arm.png | Bin 579 -> 657 bytes .../Mobs/Species/IPC/parts.rsi/l_foot.png | Bin 543 -> 574 bytes .../Mobs/Species/IPC/parts.rsi/l_hand.png | Bin 535 -> 679 bytes .../Mobs/Species/IPC/parts.rsi/l_leg.png | Bin 587 -> 642 bytes .../Mobs/Species/IPC/parts.rsi/r_arm.png | Bin 683 -> 737 bytes .../Mobs/Species/IPC/parts.rsi/r_foot.png | Bin 503 -> 557 bytes .../Mobs/Species/IPC/parts.rsi/r_hand.png | Bin 646 -> 780 bytes .../Mobs/Species/IPC/parts.rsi/r_leg.png | Bin 609 -> 644 bytes .../Mobs/Species/IPC/parts.rsi/torso_f.png | Bin 1149 -> 1306 bytes .../Mobs/Species/IPC/parts.rsi/torso_m.png | Bin 1113 -> 1232 bytes 13 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/full.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/full.png index 5f40da579b6e1ca49c0f4e89909fd6360b54e1ec..5836d3a57a1d08cb0366263b70bc3e89a701aeeb 100644 GIT binary patch delta 2423 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 literal 24547 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 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_m.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/head_m.png index 2d5be733f28e4ba66bc24cac43eed92ab384f1c6..53d6069a283d5bfde9f07ec578d7e67338ea8dbf 100644 GIT binary patch delta 863 zcmV-l1EBo!AoT{2BYyw}VoOIv0A2uI0A7@lwVVI|010qNS#tmYE+YT{E+YYWr9XB6 z000McNliru=LQxK6(Yk_c=-ST0|H4zK~#9!?V7P_>o63C|8pr3%^P^@;LXXBT@Mfl zs4!9=^Z7hf)e*7}_8R^8VB51OT+zY&w~=*4jo2wOu^Q_i7pM>k+<2Ww$ODV0^nzq}my9`iDL2HfI*H;{m z$Gm?snP9zMcYl_)my9d5FInJr3C!nnI~t8j!2`hYc*J--MjXc$0QGu3D5Y8tTq$KA zA0Gh#LI|X33Lyjl;Njr`Z*OmQFc{Fs$A_CDD1?CT`?X`f??VWYPpAuP!&f5!X_~_G zyxK9(^N^;g^Ptb?Gl~Tm0D>UE`FwW21cVR-z)mKUKYwaKVcbdjUyK0Q>UuA<$ti#| zP4V*bLhJR~K0iOh7z5w;v#g*lG9Zc~l2Y25qDNN|ZE_Ue@AuhOgxzjeDng6J0{mTfnad(ABY*KZY0p17H9QfB`T7 z2EYIq0Dl8u01SWuFaQR?09v+2H$uzh@~@w5`)a(2Z_a=QcGb1`zi!U2#g$SPKuIUe zB(vdgNLk9dP>8hFHc66FUqPy;rc0%-C&(gA@b-szs;^Rk&(ZpGlHnFc=^R0&UBA{v2ii41fVJ00zJS7ytuc p01SWuFaQR?02lxRU;sB}zX4mWFaB^>EX>4U6ba`-PAZ2)IW&i+q+U=QHcHKA< zME|jhUIGCS({eDL(>v(p_YHu0mSmO7D)(pWS&tNlM2?Y>u$lk)_cH(D=ME_vzH%%v zUi{qUF0OKtuk%y)x4rKDy?^fK7Jq-ZZeBMWmpn&*{><@t{(tSdeF->+%2{|PDEH?^ z`*@=~E4chgkUIx2jdVU9LFEzT-ML{O0ri-5#gfx|6WTn-@n%UrzeZno{;2j(e* z0_%9^rnmm$+k1Bu@cQ+}S56||j)$ zuba=&y4~}L|9|A<_&R=h-PrKyhJUT&KIBh+&fLfA#hw#$ee%A3*BW_ko3Wza5m(2@ zs5evg8P7GA(9+qUTD%g!0TF3`3ZG0?cT!w z6X&|~`(pOV71xQLC3bx5a>*Azh@Sy7RYdM8JmN21>fy`$%lE)6%?> z?0(b*$A4wRb-;{B1S&2Oo8l|My6-^#q&t&CHTZCc5MoFnhZ1V^@s1(Jn4&g6}8hMmar=6tIyl0qkrhl1dnRStB%bRttu;NN9ud?bZYEM{y z`g|j5_KBL?ks8Ec+Ha<4!~sxj%}VN%x1ixqlitqtJabazDrItEdgNp}r$_s!&e7Jk`hj znSZOxRn6|lvEhb3=pqZ9`dDLO8q4^V!Jj@8mukMe=j9auGE}rhXU@|(o&)} z+d3i6rk2*{@+8mdEytnQ>$Q7aizISNryt40VmiD_rs_vY-4#P_#+?_rjMzs*dVfiQ zwDdb6eVw`8_o9o@T>ac>+QU8Oy-Gl<8M>$Fy(w$enEik&`W~p}bxUYlq~@A7kfkvQ z^|n3~7Wp{iN!^x^h- z@;C7TAs1S0VZCseJ=STkzOtf228PykyYFF zcr#Pzvyd`J;L))B_4aa@T;l8@C>Sl_CUo-z0?ESN^$4!%5lpgdu|-f%GJy2%s%8bhtVB2UYlv!9_LC=B@dzr8 zD=o4NS5KJ|wiO+x+HE{w#j)-BWhsWi%& z1og_#w4xOpWMldckeKrtFxTG7NCyNC?x_C`Xge3S~DE@c8jq8@4Mu9#a# zn>+6pyt=jaEI3v3UM?UZ>nKg7bE_9kxg)!A`;J;u9TP|IluOt(3V)$rKJyUrF^}qQ zBxp;wi^F-DYIIj1>0$UfPq>YZO^`Md(lpC4_8wgmEvUyVl}g< z#CDouwcj@ujqmi%cYmpD(F#`pGRu|`-#YoIZj+!|m?!Vj zX@?5Nvhrr64k8eQneIr;CS+{_x^|J!Qxjl!Pf`Hs@13G_ zE(Dai^KyuJJOa%AMO|Zf>dCzfC%60&SQPJ3k4UqjQ7DSRjnsw_URT(0{KZjCUrY6U zWI82kqg7#Ctbg*`N{8M-{K!On*&t%NQU?`J?<9>gJ_$nt8A2RfH-()?zp?&L`Zy(7 zCQjo%!E)DjHh3Z)tu;EjFdma7!EV^-ctoTDn7xk{UW~;f$~(#p6xZL@yey&)KpEzO z-Q&{+G9Tvkdpb7r*=gVP*_$ZyUH^Q2w99;L@%Ifjzkin{e{Zn)+T!mY&DR!x-(d5d z5dX?x^PLd?>S(?b;$InT{ye9T!RF6%`W(%l=kzhy{CQ4)nMdiSaqTg*sL|w0ZJDXO zo$)iq-R*#V`9Lf+wmp?d5F}$jDd~&pU~=5PxHW!Di8Fn)Aj%;=5f3KAjhCn%{b?^^ ztSdt8!+-hL=~SbrAxs(z4L(b=Ab1Pc8J|l&B)x0pxEm$ZZ>m$CK|Ise;roK*H5g~o zVixa7)?ka8H=Sm@jT;AIAwYZFNaRs-Oy@i%dcZ9Ix0DhN8^pcz7p*{Z;IPBE#oW=G z)Vy1In(&$6Q1L+f1wDqn?e=}f!bf}9BvP(~XMc?RmG{u#%5IxWTP9h6AM1W8hjR=_ zTYHL8CTqT%(LtzAFwBcxGctzF@`=_^&#l{Y+JE6nZ2kJ>6ldN}Mi?*>IHv?B97c;u zcbJDK6(yvyigAc+hIMC#v%@sWW+G%#gdZ|6h_0+VBUYwub~>QdaJ%tLVRw3_u)3$P zHGfi+P}`eBgvrz6;Z&g)qO0TuDIzu^rxWD?13!Lokk`#Y5mN^=%Go`?;7w?+(IPyn z0XH#lFi+=gjK6SLiyIr7Q>2-yI(d_ee0`8mH2cZrt%15&c3APmR2r%r(%Yat@k){4*Vagp6@`MOPSg@1Fak$IEd|GK-wGGuYWZU z^GXZw(zGnBTpNIvYZ~L2w#dVBHw!1lEy%*5fR)`dEP~?oyx{$Qp)s@*4YErA6UBI> z4TaLIwiMbPkhK41D?aNd+Z33)nqIXZ(?ig-Sk4a318%L1-x=H+#h~GMdt<1=wtyJH z=-39eZA;ogIw7h>2qB|Se8OAqoqq@&Hu5e=RR3+YbxVCEcr!2@J*Cs4215*`6F{Qv z$!^z#Q(pU!-akM^W)UwM@*btnfJpdC($-YmTc%KRh60sKvbuc1W$sj(_v}-p+XM_fw58&%gIO2z=$m=te^N z4aifC2drslL=~^lhG}BJo-5O6{T}ufLo9=}6JSBWy2?ijOf#q+#(!#fnR3I5DAD#X z&7GWSS8YnneizAI8lGuD+N2D7gSc!MMI#l3&E-odaTro&;MY=MB}bdtR9rkQLSiiAnm6{Jh75*^5<M#_>KUZBVSqu!}4V*a=VuB&8?asi`l@|yzyZ{nY7l!O~EkhWQy88{{5xMHf;5%Gm zIfzO%7pJ%4{3HZ+q8$6<^B?&HAc&iW`P|&^_fZso1%|_+Ns`3YzrVi&0DF6TYoyV6 zo*OBpEejz4fQ?3@znx+%oB+?y&qiwvrIf9Yq6nPxS|dVte!X7Xx~HcnE5ggm3%1+s zx1V?K6TB!2&d8(W{IDaPY*W41jyu2wz@;LV-S&2bzXDJ6Eh9RT3r;Q;`! z+wCBKrNn$bH*p+eFc<{s_;flotyT*F(CKt)->p^)QcBb7^}L?x<$zA7gD8s5UW=m0 zHs)|RG~$FR-oN1GfU+#Bu?_(E{QR`PIp-+LGI*!=`#szV7yyza!G6EL=y|>lU;s?F z+qJ_00J`0-dmTklgj}`E>3Da_ET{lwSz%;V!Dlv1@7pa};^DVY$$oSF34 zrHXzVV@$OaVYOPJEK55M$Kx?VFM-Zdh}CLk%hd`Ld>>E=006_`uy(DfO^_>siz~j5 z0QdN%T+3}2JK(?G-+MUV4mS=7Kmw2eBmfCO0+0YC00}?>kN_kA2|xmn0Jn$Nk(f_^ z#^>5c2L1pRlVl(o2=bNffE*K6CppmTte4g&yat)aEXVzB_{+yu0? zSu7Sdp6kA^ves7>ph|5pwGcz!xQ oK@bE%5ClOG1VIo4K@h)>KZvv_7WYpph5!Hn07*qoM6N<$g4uB(IsgCw diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_arm.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_arm.png index eda91a212ecfc8b7ca9e18458a6dc4e6794e9eb2..4f042bf40e07391d9df13e6f861429a604924578 100644 GIT binary patch delta 633 zcmV-<0*3v=1d#=hBYyw}VoOIv0A2uI0A7@lwVVI|010qNS#tmYE+YT{E+YYWr9XB6 z000McNliru=LQxK6(h7$NN)fD0v<_3K~#9!?V3BT>M#(7e*RT>{QI0JuXaiXxcvUO&sSbOA^yVT=i;r?tL68)G1)OuGj-=S17K{q=f9 zUDp7Bs;Wlo5q}Ym$0MYaKD$KH0II425eWdjQVN^RrnlDq+O&R3|Lt}QV+@p1!Wi?E z70Ch6THpJC&w{cnN9$!-_85J%ZJYi+psFfJDFp!W^*`FmvJ^#8i1m6c{j5#HADVqU1{uJI+0gP^q)>-3ZTT*aPo+Kk9w0*A5V>3~NjR0nMu-nXb034V z-U@RDFaQSd@+mOnrO9Lf`~s$M{x=7SXjJ1}OcnXiQ(&s8vY29#uO5Nc+Wz4e?=Td@ z{LPWB>vC|r-C&IAG2kn5@Di9Z`rm0cP2-)%ZnqOrGa%%>puZmI>bmazS7fEs=a#^C zaQ!FvuIq3*o#xd8@;rxg?&%&uwD$qL6J!7kfB`T72EYIq00UqE41fVJfH$#!3c2_o T=~Y6X00000NkvXXu0mjfU^^KB delta 555 zcmV+`0@VGH1;Yf8BYy%4Nklh(NIHyQgaR} zQqph*T1pBE#0`vI7Na07KTgIt*?phHI;_Og_}Mdw?Fb=+5JCtc{}ZFx>-BnVua{;x z9LiuYkj-YJqMc>go%S<~dB0mNlO!={XS3PM-$gT^-|xGTx{X?zrlk!i zj{aygGON|<<$vglrvcxkB6|V?bh%qKXJH=N?RJ}gubNK3p`HTrGjezTFB^DSov1aS z4n%tpY9hf5DBi>COzmetXd`QH02Wg);awwq4GU5PT@YF;L0@W71Y>nRDwqMWKX@AT zfw#dL#1Iue35E!uDGxzFbu}2W8BD`6R+yB!mz`2qA%$Rhv%002ovPDHLkV1hHh`vCv| diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_foot.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_foot.png index c2dd73b57f5370fd9b03e0b3e5aa03d0c8646e7b..2059884d49947ed90967337a33abf1129ce1b9c8 100644 GIT binary patch delta 550 zcmbQwvX5ngay;T zVB~OMz{N~Z+W6x0(w{YbHs=FFMHwoxbzN8jMHm}yp(RV(pY&rMf6aEc z?Yj0z_|m-428M@^!kra7C%yZ8TKjW?sKRNZkkF^DES{4}s#(`v*S_#L_hU}Sx%zS$ ztvSW_qHgCMV_@j;Sby$2+ltq}*1oN=TfFXd;HrZkD_kO{$>%;7We{+l+fqnN00000000000000000000 z0MG}NB*)QcM5ohltD zLOA&nibd^qJGxvh* zNq#sSQj#QUJRa*hOb{91x^8(C7!hF@Di+AtFv9aZ6^5a?zqMo9-EOxZ#T7YtI2`DF zK0nksj`L8SPJgE#345lTD31c3Ze_S`wOUn6W9E%}>uzV;COPr!f{XlN7|&;kvO z0t0LX_I=-0=vuL2Kv$Ay@FHYINr!*|Ezr;?Fre;$U0MMctO8b)bO;#G0u7A<18fBC z+DcFvUIm)ECX>mZZA<9=6cF*seeRiey;Jw~sx1k1Y=4az%A1s3qW4pv_Xd141zguH zCZ2lQGPeRRuRPVFC^B2+yh&S}6A=xkAPD0jAk+4fX@l=fsET>3b%7 diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_hand.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_hand.png index 76cf9f28c46342e4dcd518e8d044511cc14ebe9d..5b6c2df090c40ca4d19675c8336ca813e202dab3 100644 GIT binary patch delta 656 zcmV;B0&o471g8a%BYyw}VoOIv0A2uI0A7@lwVVI|010qNS#tmYE+YT{E+YYWr9XB6 z000McNliru=LQxK6(lM*-OK<00yIfPK~#9!?VG=f!axwlzZFpgeT#j9?Rb|P4) zs7+qLr?3%>O+eH_uu58AAcbIOo6<5Vk|q+^Yc6*l_mA^-Pk(cn=~Ob=`OP;oo0zbE zzmFnY2?aL-KmZ5;0U!VbfB+Bx0zd!=00AHX1b_e(&&n#D)oL|dE*B|;0OuUdW)lEd zqtUp@Ulc`hv)KRuIOhPs48!>Hn89FhKLuEp1tEm;ES*j#xUQRz5;z`@*V$KQNs{CP zfDnRZ+44M({eRLO zZQJ=6gY)?ulgZ>)!DnU|1{}vhrBZqPF_@WYno9jymX*Jakj_OvJb=6ePg`LEKmhar zP(1~5b2X?la9zF&Ujj_!6C%sy^6mlM^?pDe`v6S=+J6d@0tf&B_zzRSG|ijNS<(@- zj^Muw(6X$X8gEHg=2cGtT~no`W07=2q{vNBXZCgYF6-z4e^~m0zt- zxdO72)qm@C0KjUsVo?-HEmD2X`e-zI^B-ZgS_J_3zK_G<@b^6+3qH%pcszcWF;yx^ z)AXGJlO%!f`#7J^FEF$#;4_&GheIqD3wB+jsZZ9RsqRvbbr zN*X(ATRIyG;thBiB1VnRu=uZl{9m#WOc-WncV@`!DnbY$gb+dqA%qYzGBncM>2#{{ zJTHSFP>$m$*LCG@J)6y1$&2H-JRA<=2Koecy-5lj>p% zcnEw#X(Z6((tl-`uT?K3cErT`%k%6IcT{i$s%Igb#>admw;OJI}) zpbkiqM9ZNDq|8S=&%4_roJ=OwZ&4K0#;hsu9I#rg&>~+VD^83*pU+okm;iNvRDkt* zZEY)CX8#E~iXtUv2f{G4_HIH5A%qa}RVbzY0O<~!RaLNmN&o-=07*qoM6N<$f)Bgu A@c;k- diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_leg.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/l_leg.png index 3e800782602bfce9eaf0c215d9b4307648332c18..e0e4f97977b81cf25a5c83a16f1386eff2f450cc 100644 GIT binary patch delta 618 zcmX@j(!@GJxt@V7$=lt9Ar1tmOx!w$fq{Xuz$3Dlfk96hgc&QA+Lr+Z*-JcqUD=he$M)MY-;5NxJ0!DvB_O`H0* z4K7J1rghE~Pxvfi)|OM*;K37lXX(12x~;!%AGuPWdv30W!oHK`Z>#%dmBUtxw&nOs z>=0yN6u^Oa&dl2#Q)3}>&u+e-IOr){lB#=!_c%Oh{(iUIx#}>pnkP{MHbdVi-JK{an^LB{Ts5a&-xK delta 563 zcmV-30?hq_1& zZvDgIV3T7yol?>gw%K!l<9@%ZcDr5l0^eaN+#IvrZs|d@9$N&79$<09AQaTALe#+) zpwsE7<#K7qW`CaNwnaj;{=;U`;#98$ECI-=>-DNvtCb!M1|nnfCm!`^s#n4u%ZLj; z+`7zNlYh&r`m`?pb3_D)g(?DwO@d8@wG6&n@1-X~>Da=7ArQoq1_1#g@S#>9KmpsdBYyw}VoOIv0A2uI0A7@lwVVI|010qNS#tmYE+YT{E+YYWr9XB6 z000McNliru=LQxK6(wCT?OFf;0&Yn}K~#9!?VCN$vOo~W{}2L|cd)SZ0$#u)P-{Z9 zg~kf5U}Y$zGO@Sv7Ia%_w*`0D!f3bpzpn>?F_w>o z5O5r)*8ptWhJO&Exj7(;B6yw$$8oag8(lzPj3J7mG8tfS&eQw-j?3jzAApoHbzK)i z2yo7gE}~k@!ZH~!pU({d>1;N`VzEd!n~hN!z;3rIMjrrhJRWODN~dtn0RUyQ!1{9D zC^~Q3cIytQ0L`xTJg;=NnoSzhb@Urw3A(Ne0B{_q_kSJWos_ZpV+kym%eUjc%jtB= z$LsaF)*LV>$F)2RskEUczSp+?uK=Pb0%NQ(hpKb|75%DqT4jw;>G@5=Qf-AQ`b}L% zb=?xn>NmSo-u2R18-T7wB>=Q1IOgbU1JG5=tRmJ>oKn@_X%`rhSh{L!D6Q4(OUhCg z_-g=$vVS{789)I3=mJLz0F}*&wqX_R(z+jzO>Xa$R5756gTL8TW#X+g2YgbN8QF9f z=*>b%N|_cuZ;c$%s!??gNaHw0k|f!o(k~+P^})$fytg5Q$X-LibUJNy0i@&J$|b-# z$Mt$e7=}oa#29+3RLX$c?S}1kn@7G-3azDf(?eOHS^@~eFn?#@a5%vC{XzaJoYyq{ wV}zas2mk>f00e*l5C8%|00;m9AOItjf1gGcoJMHC$N&HU07*qoM6N<$f>pOWaR2}S delta 660 zcmV;F0&D%@1*-*+BYy&NNklXS2Z3;(==3DoH(D)^0uqJVmuyei$Mhd7gA(d#u|-AH7zrwUaw0# zZO{$@&bfewUwc1->(E00I%2omY4dT;;p>;Z$Kw&b=Nn4|_a6)fQq?p~QL%hc^g=eCT4}W5T=ytoP-KYSg(TEk)lwiGY+EYGRuh+8lTf3bE02eA20t$!5Mo^WP zb8hUd+F9UH1+M9@2r2-Ke|B}JSDyhMVPdm(7FaHq@_INNdNb4~QG|~MgZj^hr|6yvfn6@!aHkl6Ri=zA`Jcs}-BgX5a~T%dB^sDy=-=a5%8ZWRmxMVJHN_M|`mkg3$Bo-TPv( uU~mwriW6Z3K@bE%5ClOG1mOr{><7F9Q7kcwMxZyDw_8;GzyxF7oTvcbluOfzj$oww~#{9qaZ`yk-pae2kpN*ucz?t-E9jgTk$CbL-e7 zl4CBL?1<6ZaE+-U;t)sN`tXHQnx+U{i^^CVyFtKX(vklnadPzxe#?Wm2NpB!SeDrm z#8oJ>Sfk58k-?#6?H(QPLJOI=OE2?wTU}3Jm~X7$DRiauuJtct|Nr)fyBEfHJgK}_ zeV_SG-u9zw-ek^do5@(4>M5Hp2l0b9W5tt~w^<^*pR1o_t~-5U2OG#^Kgt=L!@iro zW$vBS-6R~`d|ObcU5Jm0Po*@TF%MB1kaswBfBI#+kL6jCw zkv=6UxI$V=id@30vG9sTE3Jpb!CwB85+HKMe?Eh4$p`=d00000000000000000013 z1JX4|t+lACO4oHQHk*ye^PGN`$K!D^oA&#?kw#yS$HV9%O@FuB%{j)0Ys2gHs{6hd z=kwWg#xc()P18ua8I(NfDvCmLx^p&w$g<3yO6xq4B*~9fU+#<#uyWnQlf2J z*8e{lZRI$4UDxt(IE;m`I({Lx5@%H;$AIq&pkvo{=6rhh-$~OnPaDq~1b@RCaKGOd zGh&LA?#1x50e>OFF@QA){zqUy02&qr1_YpCQM?&2tkc(NKrG1`dA2g zRT2TKH-NP_XrZn0)9GZchOKfjY?R8&)gtBa!WlKhlO@`gEs@GJw`w$=7+jNwQxCOjpC16AOty&3V8QaVjjULYaF7v1dw UvD9CxDF6Tf07*qoM6N<$f`uL2rT_o{ diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_hand.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_hand.png index 8cd312c8aea63d898b5833c1d44eb75951fabfcd..3ec4fab0378c57933d681502dce708413dd5e27d 100644 GIT binary patch delta 757 zcmVf00e*l5C8%|00_VbigD}VY&QFG%{hk<;$@xToa1;r z0su_Ygp?Ae(^?wZK`a7LYI-THO&Sl*&-K+mA zOXX=s|D*Q;Isu^F;3r2vH2}}<{!-fxzmikB`ZHYx-sV6gkL&u&6v4dI0a^z0ma>!q z1Rz5Id1`P{0ibg@@oZSitHe@q>PrQ{Xon-y#FjSY5O-;5^djMqRs~ zw1i=Z-EN043}G0?O&fJ=`qDLGGMT6#2viURs?}<#%jeN2Y3BhzN~yZtu8OYD^~Kd~ z=o+(JF41T-P%4#RSr+#D{r|xXBee`L3s$GZ~{cDWQ n0|)>CAOHk_01yBI@S*YzgrYA9f0|_$00000NkvXXu0mjf$AeMg delta 622 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 delta 1129 zcmV-v1eW`n3jGL>BYy-$Nkl zu@bD#Iu;^WC6$d}Izdwf(xefa)W$AdL@Yx7gMEDac8>GM)697r!^?hfUUu)enfZ2p zoHt7z9v&VZ9v&VZ9?JU0+`t`7BGR+07CYu)V#ld%YfYyIndzKc~aPL)zKd!Mu4MuBDaDn}BY& zt8t!8CN!N+sZc0Tu~V;RDe_>GD*lKn$0Ga%Vm9Zbd*RrJAXSfvhVKh%mO&g0dV=t%S&T4 z*#v|!=Y@8=?UVo*e|mcQYR-=J=H{mOc_ISZ?Y2hZiK57?I94BLjBPE}sgjgCP=P=+ zssOt_&KTQ#q~RgX2p}7Gw&W0(LyR$x&~Ob9eR6V=WPF@4whJJJm;eU5{M(Y4hJ9k>dEhJgk}@a)2$=QQ z+S(G`pXVV#CJ$J2IDHZN-{1*Y03Ci5o`40=;eSW*TOwTYYU}7@Xzo~g5Ag2+u9R@) zvUy|aLtyC%@HxP#CO-h%qMI2@9|9sQ`uBi1j@^doR|;HRT{$D*?eo&I-X0QUPJ(EY z^Zo#|#Mal>&9nHExr@FazgwUWFdPmwT5_yIuh+}e8WZOL7+$GVG@2oMdwWKK+uK{( z-GAK$JEnE*!gxllR@0CLnUD<~pbK;=l}cj&7yUB?U_%5xeWMux;bePr+^wAlAPX|l zAA}cx48(tyu9VmV*m$@dG(OP?W!ScOvPpp(rY?c5G!B-T zUI^$W^#ZX6L{apv5dk95DlZm`jy}l$g@4U03bL4d28bAs$4cr2A`jT#-!~mv#Qxga znwjIh0f@)RWTL;*rI`hVLcvrY(pxvPsa!A$o^- z*!ih^&i06VN`*lX1Y+_<1Ymav+|Sm1GsmkBCE_@C?g1#Z_yd{j1;B7PL>OvRDPoBZ zA_CI!_4xQmtE;Q#x80&Lm;C{7d23`60?*IS$;*$^9DpPjMUe*EH#axQJi4^=r~nK$ vywz$YbNoW&IuUz#czAetczAgH7a*cP8A-V<%>ya1YJo)K~#9!?VGV`<4h38|NC)BTp$miP7rmr8+R_; zx|J(+fdo=mP9a=5k6>3ug=H0ilmS=TXK+A8aGF?M2;*m4iQDsQ71ec4grAo`+YfIzK>Vep0m^Jq;R$0mCrhd7gZKXc{~y22@prBuS8_ zDM^wIZO;ezNbqz}?-QR3rkCu*mK0Z7pfwGyTdpL%;h&RqO=!(f`-a1M0{K`anbj&;T?5 z4d4%D?=<+k<*lN_Q0)On-&!703I5BnZzZVA18O)I&`UrA(0c*x0UE$R3*c{LfkT$v zQGWqEKR=@`puf^}2=s4>aqJ)%MUnj5zVBnTTJboJWskyq zJ}0%D37(vs@Ukos1OZm76`r1+0Q@+n+FFIQS}kQ>;QKyrwOaCAu-$H>+wCF@Lzt$C zx3@Qsdy#W00000NkvXXu0mjfv85DK delta 1093 zcmV-L1iJgs3E2pcBYy-SNklh*eba&kiZ`}?%9u|f5E-HeB8d1L1-K(E)+ zI8UcjdVGAOLZLv#Vv#Sa&CN~GcwzxgPfzvA%F3($EXycOQ||)QYBk+#HqGQ25aI0X z3@vqieJvXAmw(iNySqCx**wrj|03}4@G!FjuFt&a=WAXC$cw-S8?m~&`s{o2UVUI^ zXUDAm&CQKzKayJuOZaJELhlKyW!;iZ7Kt$4ECZr5H#pq5XNz=*r;l?>Nwon z_&`9z4-a5|bh_}1RnuC}h&T}Oii}1hu>mglh+i55#DD;wIq!gGKxLl*E}U@rLax4@4VAjAM~ zmi!|K0{9yEE3!bR)A3L8(aVdAi;LOkdA|^OIbNPCe@NjR1nc#>=KTSv305ityIu+6&w*qH%B zxE Date: Thu, 22 Jun 2023 15:37:12 -0400 Subject: [PATCH 42/60] IPCs now use integrated radios! IPCs now have blank RadioReceiver, Transmitter, and Active components which get updated by their EncryptionKeyHolderComponent (had to write a system for that). Their encryption keys get filled in based on their job's headset with some modifications to StationSpawningSystem that I'm not super proud of... --- .../IntrinsicRadioTransmitterComponent.cs | 2 +- .../Radio/IntrinsicRadioKeySystem.cs | 32 +++++++++++++++++++ .../Station/Systems/StationSpawningSystem.cs | 30 +++++++++++++++++ .../EncryptionKeyHolderComponent.cs | 9 ++++++ .../EntitySystems/EncryptionKeySystem.cs | 8 +++++ .../Entities/Mobs/Player/ipc.yml | 10 ++++++ .../Entities/Mobs/Player/silicon_base.yml | 2 +- .../ipc_inventory_template.yml | 16 +++++----- 8 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 Content.Server/SimpleStation14/Radio/IntrinsicRadioKeySystem.cs diff --git a/Content.Server/Radio/Components/IntrinsicRadioTransmitterComponent.cs b/Content.Server/Radio/Components/IntrinsicRadioTransmitterComponent.cs index eb28bac4ec..cae812eb6c 100644 --- a/Content.Server/Radio/Components/IntrinsicRadioTransmitterComponent.cs +++ b/Content.Server/Radio/Components/IntrinsicRadioTransmitterComponent.cs @@ -13,5 +13,5 @@ namespace Content.Server.Radio.Components; public sealed class IntrinsicRadioTransmitterComponent : Component { [DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] - public readonly HashSet Channels = new() { SharedChatSystem.CommonChannel }; + public HashSet Channels = new() { SharedChatSystem.CommonChannel }; // Parkstation-IPC // Did this really need to be readonly? :prerealization: } diff --git a/Content.Server/SimpleStation14/Radio/IntrinsicRadioKeySystem.cs b/Content.Server/SimpleStation14/Radio/IntrinsicRadioKeySystem.cs new file mode 100644 index 0000000000..6ea9c30d90 --- /dev/null +++ b/Content.Server/SimpleStation14/Radio/IntrinsicRadioKeySystem.cs @@ -0,0 +1,32 @@ +using Content.Server.Radio.Components; +using Content.Shared.Radio; +using Content.Shared.Radio.Components; + +namespace Content.Server.SimpleStation14.Radio; + +public sealed class IntrinsicRadioKeySystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnTransmitterChannelsChanged); + SubscribeLocalEvent(OnReceiverChannelsChanged); + } + + private void OnTransmitterChannelsChanged(EntityUid uid, IntrinsicRadioTransmitterComponent component, EncryptionChannelsChangedEvent args) + { + UpdateChannels(uid, args.Component, ref component.Channels); + } + + private void OnReceiverChannelsChanged(EntityUid uid, ActiveRadioComponent component, EncryptionChannelsChangedEvent args) + { + UpdateChannels(uid, args.Component, ref component.Channels); + } + + private void UpdateChannels(EntityUid uid, EncryptionKeyHolderComponent keyHolderComp, ref HashSet channels) + { + channels.Clear(); + channels.UnionWith(keyHolderComp.Channels); + } +} diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index 44c63ae530..a98d64aeb9 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -24,6 +24,8 @@ using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Utility; +using Content.Shared.Radio.Components; // Parkstation-IPC +using Content.Shared.Containers; // Parkstation-IPC namespace Content.Server.Station.Systems; @@ -190,6 +192,34 @@ public void EquipStartingGear(EntityUid entity, StartingGearPrototype startingGe } } + // Parkstation-IPC-Start + // This is kinda gross, and weird, and very hardcoded, but it's the best way I could think of to do it. + // If they have an EncryptionKeyHolderComponent, spawn in their headset, find the + // EncryptionKeyHolderComponent on it, move the keys over, and delete the headset. + if (TryComp(entity, out var keyHolderComp)) + { + var earEquipString = startingGear.GetGear("ears", profile); + + if (string.IsNullOrEmpty(earEquipString)) + return; + + var earEntity = Spawn(earEquipString, Transform(entity).Coordinates); + + if (TryComp(earEntity, out _) && // I had initially wanted this to spawn the headset, and simply move all the keys over, but the headset didn't seem to have any keys in it when spawned... + TryComp(earEntity, out var fillComp) && + fillComp.Containers.TryGetValue(EncryptionKeyHolderComponent.KeyContainerName, out var defaultKeys)) + { + foreach (var key in defaultKeys) + { + var keyEntity = Spawn(key, Transform(entity).Coordinates); + keyHolderComp.KeyContainer.Insert(keyEntity, force: true); + } + } + + EntityManager.QueueDeleteEntity(earEntity); + } + // Parkstation-IPC-End + if (!TryComp(entity, out HandsComponent? handsComponent)) return; diff --git a/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs b/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs index ca5d1f647a..81ddb23a00 100644 --- a/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs +++ b/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs @@ -42,6 +42,15 @@ public sealed class EncryptionKeyHolderComponent : Component public Container KeyContainer = default!; public const string KeyContainerName = "key_slots"; + // Parkstation-IPC-Start + /// + /// Whether or not the headset can be examined to see the encryption keys while the keys aren't accessible. + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("examineWhileLocked")] + public bool ExamineWhileLocked = true; + // Parkstation-IPC-End + /// /// Combined set of radio channels provided by all contained keys. /// diff --git a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs index 1246e33e34..ac8507bd13 100644 --- a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs +++ b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs @@ -182,6 +182,14 @@ private void OnHolderExamined(EntityUid uid, EncryptionKeyHolderComponent compon if (!args.IsInDetailsRange) return; + // Parkstation-IPC-Start + if (!component.ExamineWhileLocked && !component.KeysUnlocked) + return; + + if (!component.ExamineWhileLocked && TryComp(uid, out var panel) && !panel.Open) + return; + // Parkstation-IPC-End + if (component.KeyContainer.ContainedEntities.Count == 0) { args.PushMarkup(Loc.GetString("encryption-keys-no-keys")); diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml index 661c30b64d..6e15756ea0 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -24,6 +24,16 @@ 4: 0.00 - type: Carriable - type: BatteryDrinker + - type: EncryptionKeyHolder + keySlots: 3 + examineWhileLocked: false + keysExtractionMethod: Cutting + - type: ActiveRadio + - type: IntrinsicRadioReceiver + - type: IntrinsicRadioTransmitter + - type: Wires + BoardName: "IPC" + LayoutId: IPC - type: entity save: false diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 1e434770c4..11d4ca1f72 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -133,7 +133,7 @@ - map: ["enum.HumanoidVisualLayers.RLeg"] - map: ["enum.HumanoidVisualLayers.LLeg"] - shader: StencilClear - sprite: SimpleStation14/Mobs/Species/IPC/parts.rsi + sprite: Mobs/Species/Human/parts.rsi state: l_leg - shader: StencilMask map: ["enum.HumanoidVisualLayers.StencilMask"] diff --git a/Resources/Prototypes/SimpleStation14/InventoryTemplates/ipc_inventory_template.yml b/Resources/Prototypes/SimpleStation14/InventoryTemplates/ipc_inventory_template.yml index 68ea238150..77d568299e 100644 --- a/Resources/Prototypes/SimpleStation14/InventoryTemplates/ipc_inventory_template.yml +++ b/Resources/Prototypes/SimpleStation14/InventoryTemplates/ipc_inventory_template.yml @@ -71,20 +71,20 @@ # uiWindowPos: 0,0 # strippingWindowPos: 0,0 # displayName: Eyes - - name: ears - slotTexture: ears - slotFlags: EARS - stripTime: 3 - uiWindowPos: 2,0 - strippingWindowPos: 2,0 - displayName: Ears + # - name: ears + # slotTexture: ears + # slotFlags: EARS + # stripTime: 3 + # uiWindowPos: 2,0 + # strippingWindowPos: 2,0 + # displayName: Ears - name: head slotTexture: head slotFlags: HEAD uiWindowPos: 1,0 strippingWindowPos: 1,0 displayName: Head - offset: 0, 0.03125 + offset: 0, 0 - name: pocket1 slotTexture: pocket slotFlags: POCKET From 3692d07dc95942fe755f623dbc80909c9416448e Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Thu, 22 Jun 2023 19:50:51 -0400 Subject: [PATCH 43/60] IPC encryption keys now work better, and effect the SetOutfit command. --- .../Commands/SetOutfitCommand.cs | 32 ++++++++++++++++++ .../Station/Systems/StationSpawningSystem.cs | 33 +++++++++++-------- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/Content.Server/Administration/Commands/SetOutfitCommand.cs b/Content.Server/Administration/Commands/SetOutfitCommand.cs index d5dd99605f..2646a63140 100644 --- a/Content.Server/Administration/Commands/SetOutfitCommand.cs +++ b/Content.Server/Administration/Commands/SetOutfitCommand.cs @@ -12,6 +12,9 @@ using Robust.Server.Player; using Robust.Shared.Console; using Robust.Shared.Prototypes; +using Content.Shared.Radio.Components; // Parkstation-IPC +using Content.Shared.Containers; // Parkstation-IPC +using Robust.Shared.Containers; // Parkstation-IPC namespace Content.Server.Administration.Commands { @@ -128,6 +131,35 @@ public static bool SetOutfit(EntityUid target, string gear, IEntityManager entit } } + // Parkstation-IPC-Start + // Pretty much copied from StationSpawningSystem.SpawnStartingGear + if (entityManager.TryGetComponent(target, out var keyHolderComp)) + { + var earEquipString = startingGear.GetGear("ears", profile); + var containerMan = entityManager.System(); + + if (!string.IsNullOrEmpty(earEquipString)) + { + var earEntity = entityManager.SpawnEntity(earEquipString, entityManager.GetComponent(target).Coordinates); + + if (entityManager.TryGetComponent(earEntity, out _) && // I had initially wanted this to spawn the headset, and simply move all the keys over, but the headset didn't seem to have any keys in it when spawned... + entityManager.TryGetComponent(earEntity, out var fillComp) && + fillComp.Containers.TryGetValue(EncryptionKeyHolderComponent.KeyContainerName, out var defaultKeys)) + { + containerMan.CleanContainer(keyHolderComp.KeyContainer); + + foreach (var key in defaultKeys) + { + var keyEntity = entityManager.SpawnEntity(key, entityManager.GetComponent(target).Coordinates); + keyHolderComp.KeyContainer.Insert(keyEntity, force: true); + } + } + + entityManager.QueueDeleteEntity(earEntity); + } + } + // Parkstation-IPC-End + return true; } } diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index a98d64aeb9..49ac807fc5 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -26,6 +26,7 @@ using Robust.Shared.Utility; using Content.Shared.Radio.Components; // Parkstation-IPC using Content.Shared.Containers; // Parkstation-IPC +using Robust.Shared.Containers; // Parkstation-IPC namespace Content.Server.Station.Systems; @@ -194,29 +195,35 @@ public void EquipStartingGear(EntityUid entity, StartingGearPrototype startingGe // Parkstation-IPC-Start // This is kinda gross, and weird, and very hardcoded, but it's the best way I could think of to do it. + // This is replicated in SetOutfitCommand.SetOutfit. // If they have an EncryptionKeyHolderComponent, spawn in their headset, find the // EncryptionKeyHolderComponent on it, move the keys over, and delete the headset. if (TryComp(entity, out var keyHolderComp)) { - var earEquipString = startingGear.GetGear("ears", profile); - - if (string.IsNullOrEmpty(earEquipString)) - return; + // Resolve SharedContainerSystem + var containerMan = EntityManager.System(); - var earEntity = Spawn(earEquipString, Transform(entity).Coordinates); + var earEquipString = startingGear.GetGear("ears", profile); - if (TryComp(earEntity, out _) && // I had initially wanted this to spawn the headset, and simply move all the keys over, but the headset didn't seem to have any keys in it when spawned... - TryComp(earEntity, out var fillComp) && - fillComp.Containers.TryGetValue(EncryptionKeyHolderComponent.KeyContainerName, out var defaultKeys)) + if (!string.IsNullOrEmpty(earEquipString)) { - foreach (var key in defaultKeys) + var earEntity = Spawn(earEquipString, Transform(entity).Coordinates); + + if (TryComp(earEntity, out _) && // I had initially wanted this to spawn the headset, and simply move all the keys over, but the headset didn't seem to have any keys in it when spawned... + TryComp(earEntity, out var fillComp) && + fillComp.Containers.TryGetValue(EncryptionKeyHolderComponent.KeyContainerName, out var defaultKeys)) { - var keyEntity = Spawn(key, Transform(entity).Coordinates); - keyHolderComp.KeyContainer.Insert(keyEntity, force: true); + containerMan.CleanContainer(keyHolderComp.KeyContainer); + + foreach (var key in defaultKeys) + { + var keyEntity = Spawn(key, Transform(entity).Coordinates); + keyHolderComp.KeyContainer.Insert(keyEntity, force: true); + } } - } - EntityManager.QueueDeleteEntity(earEntity); + EntityManager.QueueDeleteEntity(earEntity); + } } // Parkstation-IPC-End From e4cd8385c7c2ef3189c7b9ecd437a84730b349c7 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Thu, 22 Jun 2023 21:07:21 -0400 Subject: [PATCH 44/60] Things are localized! --- .../Mobs/Customization/ipcAntenna.ftl | 10 +++++ .../Mobs/Customization/ipcScreens.ftl | 39 +++++++++++++++++++ Resources/Locale/en-US/species/species.ftl | 3 ++ 3 files changed, 52 insertions(+) create mode 100644 Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcAntenna.ftl create mode 100644 Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcScreens.ftl diff --git a/Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcAntenna.ftl b/Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcAntenna.ftl new file mode 100644 index 0000000000..ec3efd9f55 --- /dev/null +++ b/Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcAntenna.ftl @@ -0,0 +1,10 @@ +marking-RobotAntennaTv = Tv +marking-RobotAntennaTesla = Tesla +marking-RobotAntennaLightb = Light (alt) +marking-RobotAntennaLight = Light +marking-RobotAntennaCyberhead = Cyberhead +marking-RobotAntennaSidelights = Sidelights +marking-RobotAntennaAntlers = Antlers +marking-RobotAntennaDroneeyes = Drone Eyes +marking-RobotAntennaCrowned = Crowned +marking-RobotAntennaTowers = Towers diff --git a/Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcScreens.ftl b/Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcScreens.ftl new file mode 100644 index 0000000000..656d928c69 --- /dev/null +++ b/Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcScreens.ftl @@ -0,0 +1,39 @@ +marking-ScreenStatic = Static +marking-ScreenBlue = Blue +marking-ScreenBreakout = Breakout +marking-ScreenEight = Eight +marking-ScreenGoggles = Goggles +marking-ScreenExclaim = Exclaim +marking-ScreenHeart = Heart +marking-ScreenMonoeye = Cylops +marking-ScreenNature = Naturalist +marking-ScreenOrange = Orange +marking-ScreenPink = Pink +marking-ScreenQuestion = Question +marking-ScreenShower = Shower +marking-ScreenYellow = Yellow +marking-ScreenScroll = Scroll +marking-ScreenConsole = Console +marking-ScreenRgb = RGB +marking-ScreenGlider = Glider +marking-ScreenRainbowhoriz = Horizontal Rainbow +marking-ScreenBsod = BSOD +marking-ScreenRedtext = Red Text +marking-ScreenSinewave = Sinewave +marking-ScreenSquarewave = Squarewave +marking-ScreenEcgwave = ECG wave +marking-ScreenEyes = Eyes +marking-ScreenEyestall = Tall Eyes +marking-ScreenEyesangry = Angry Eyes +marking-ScreenLoading = Loading... +marking-ScreenWindowsxp = Experience +marking-ScreenTetris = NT Block Game +marking-ScreenTv = Tv +marking-ScreenTextdrop = Textdrop +marking-ScreenStars = Stars +marking-ScreenRainbowdiag = Diagonal Rainbow +marking-ScreenBlank = Dead Pixel +marking-ScreenSmile = Smiley +marking-ScreenFrown = Frowny +marking-ScreenRing = Ring +marking-ScreenL = L diff --git a/Resources/Locale/en-US/species/species.ftl b/Resources/Locale/en-US/species/species.ftl index c461f659c6..7799e7b504 100644 --- a/Resources/Locale/en-US/species/species.ftl +++ b/Resources/Locale/en-US/species/species.ftl @@ -9,3 +9,6 @@ species-name-oni = Oni species-name-arachne = Arachne species-name-diona = Diona species-name-moth = Moth + +## Parkstation Names +species-name-ipc = IPC From 3420c0e94d40ed117361851a4211d63e3fe9676e Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Fri, 23 Jun 2023 00:22:23 -0400 Subject: [PATCH 45/60] Cleaned up tons of stuff. Battery draining seems to be broken right now, reporting 0 charge at all times. Will fix soon. --- .../RandomBatteryChargeComponent.cs | 23 +++++++ .../Power/Systems/BatteryDrinkerSystem.cs | 9 ++- .../Systems/RandomBatteryChargeSystem.cs | 43 ++++++++++++ .../Systems/SiliconChargeDeathSystem.cs | 35 +++++----- .../Charge/Systems/SiliconChargeSystem.cs | 67 ++++++++++++------- .../Charge/Systems/SiliconChargerSystem.cs | 27 +++++--- .../Silicon/Components/SiliconComponent.cs | 32 +++++---- .../Silicon/Systems/SharedSiliconSystem.cs | 14 +--- .../Entities/Mobs/Player/robots.yml | 6 +- .../Entities/Mobs/Player/ipc.yml | 9 ++- .../Entities/Mobs/Player/silicon_base.yml | 8 +-- 11 files changed, 182 insertions(+), 91 deletions(-) create mode 100644 Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs create mode 100644 Content.Server/SimpleStation14/Power/Systems/RandomBatteryChargeSystem.cs diff --git a/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs b/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs new file mode 100644 index 0000000000..4b1892ac95 --- /dev/null +++ b/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs @@ -0,0 +1,23 @@ +namespace Content.Server.SimpleStation14.Power.Components; + +[RegisterComponent] +public class RandomBatteryChargeComponent : Component +{ + /// + /// The minimum and maximum max charge the battery can have. + /// + [DataField("batteryMaxMinMax")] + public Vector2 BatteryMaxMinMax = (0.85f, 1.15f); + + /// + /// The minimum and maximum current charge the battery can have. + /// + [DataField("batteryChargeMinMax")] + public Vector2 BatteryChargeMinMax = (1f, 1f); + + /// + /// True if the current charge is based on the preexisting current charge, or false if it's based on the max charge. + /// + [DataField("basedOnMaxCharge")] + public bool BasedOnMaxCharge = false; +} diff --git a/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs index c5ab29945e..a34f6d33f3 100644 --- a/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs +++ b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs @@ -20,6 +20,7 @@ public sealed class BatteryDrinkerSystem : EntitySystem [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly BatterySystem _battery = default!; + [Dependency] private readonly SiliconChargeSystem _silicon = default!; public override void Initialize() { @@ -52,7 +53,6 @@ private void AddAltVerb(EntityUid uid, BatteryComponent batteryComponent, GetVer private bool TestDrinkableBattery(EntityUid target, BatteryDrinkerComponent drinkerComp) { - if (!drinkerComp.DrinkAll && !HasComp(target)) return false; @@ -61,13 +61,16 @@ private bool TestDrinkableBattery(EntityUid target, BatteryDrinkerComponent drin private bool TryGetFillableBattery(EntityUid uid, [NotNullWhen(true)] out BatteryComponent? battery) { - if (EntityManager.TryGetComponent(uid, out battery)) + if (_silicon.TryGetSiliconBattery(uid, out battery)) + return true; + + if (EntityManager.TryGetComponent(uid, out battery)) return true; if (EntityManager.TryGetComponent(uid, out var powerCellSlot) && _slots.TryGetSlot(uid, powerCellSlot.CellSlotId, out var slot) && slot.Item != null && - EntityManager.TryGetComponent(slot.Item.Value, out battery)) + EntityManager.TryGetComponent(slot.Item.Value, out battery)) return true; return false; diff --git a/Content.Server/SimpleStation14/Power/Systems/RandomBatteryChargeSystem.cs b/Content.Server/SimpleStation14/Power/Systems/RandomBatteryChargeSystem.cs new file mode 100644 index 0000000000..eb3b53628a --- /dev/null +++ b/Content.Server/SimpleStation14/Power/Systems/RandomBatteryChargeSystem.cs @@ -0,0 +1,43 @@ +using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; +using Content.Server.SimpleStation14.Power.Components; +using Robust.Shared.Random; +using Robust.Shared.Utility; + +namespace Content.Server.SimpleStation14.Power.Systems; + +public sealed class RandomBatteryFillSystem : EntitySystem +{ + [Dependency] private readonly BatterySystem _battery = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnBatteryInit); + } + + private void OnBatteryInit(EntityUid uid, RandomBatteryChargeComponent component, ComponentInit args) + { + var batteryComp = Comp(uid); + DebugTools.AssertNotNull(batteryComp); + + if (batteryComp == null) + return; + + var (minMaxMod, maxMaxMod) = component.BatteryMaxMinMax; + var (minChargeMod, maxChargeMod) = component.BatteryChargeMinMax; + + var newMax = batteryComp.MaxCharge * _random.NextFloat(minMaxMod, maxMaxMod); + float newCharge; + + if (component.BasedOnMaxCharge) + newCharge = newMax * _random.NextFloat(minChargeMod, maxChargeMod); + else + newCharge = batteryComp.CurrentCharge * _random.NextFloat(minChargeMod, maxChargeMod); + + _battery.SetMaxCharge(uid, newMax); + _battery.SetCharge(uid, newCharge); + } +} diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs index 180283f174..55b9e63007 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs @@ -1,16 +1,17 @@ using Content.Server.Power.Components; -using Content.Shared.SimpleStation14.Silicon.Components; using Content.Shared.SimpleStation14.Silicon.Systems; -using Robust.Shared.Utility; using Content.Server.Bed.Sleep; using Content.Shared.Bed.Sleep; using Content.Server.Sound.Components; +using Content.Server.SimpleStation14.Silicon.Charge; +using Serilog; namespace Content.Server.SimpleStation14.Silicon.Death; public sealed class SiliconDeathSystem : EntitySystem { - [Dependency] private readonly SleepingSystem _sleepSystem = default!; + [Dependency] private readonly SleepingSystem _sleep = default!; + [Dependency] private readonly SiliconChargeSystem _silicon = default!; public override void Initialize() { @@ -21,14 +22,10 @@ public override void Initialize() private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, SiliconChargeStateUpdateEvent args) { - EntityManager.TryGetComponent(uid, out var batteryComp); - EntityManager.TryGetComponent(uid, out var siliconComp); + _silicon.TryGetSiliconBattery(uid, out var batteryComp); - DebugTools.AssertNotNull(batteryComp); - DebugTools.AssertNotNull(siliconComp); - - if (batteryComp == null || siliconComp == null) - return; + Logger.Debug($"Silicon charge state update: {args.ChargeState}"); + Logger.Debug($"Silicon battery: {batteryComp?.CurrentCharge}"); if (args.ChargeState == ChargeState.Dead && !siliconDeadComp.Dead) { @@ -40,7 +37,7 @@ private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponen } } - private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent batteryComp) + private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent? batteryComp) { var deadEvent = new SiliconChargeDyingEvent(uid, batteryComp); RaiseLocalEvent(uid, deadEvent); @@ -57,9 +54,9 @@ private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadCo RaiseLocalEvent(uid, new SiliconChargeDeathEvent(uid, batteryComp)); } - private void SiliconUnDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent batteryComp) + private void SiliconUnDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent? batteryComp) { - _sleepSystem.TryWaking(uid, null, true); + _sleep.TryWaking(uid, null, true); siliconDeadComp.Dead = false; @@ -73,9 +70,9 @@ private void SiliconUnDead(EntityUid uid, SiliconDownOnDeadComponent siliconDead public sealed class SiliconChargeDyingEvent : CancellableEntityEventArgs { public EntityUid SiliconUid { get; } - public BatteryComponent BatteryComp { get; } + public BatteryComponent? BatteryComp { get; } - public SiliconChargeDyingEvent(EntityUid siliconUid, BatteryComponent batteryComp) + public SiliconChargeDyingEvent(EntityUid siliconUid, BatteryComponent? batteryComp) { SiliconUid = siliconUid; BatteryComp = batteryComp; @@ -88,9 +85,9 @@ public SiliconChargeDyingEvent(EntityUid siliconUid, BatteryComponent batteryCom public sealed class SiliconChargeDeathEvent : EntityEventArgs { public EntityUid SiliconUid { get; } - public BatteryComponent BatteryComp { get; } + public BatteryComponent? BatteryComp { get; } - public SiliconChargeDeathEvent(EntityUid siliconUid, BatteryComponent batteryComp) + public SiliconChargeDeathEvent(EntityUid siliconUid, BatteryComponent? batteryComp) { SiliconUid = siliconUid; BatteryComp = batteryComp; @@ -103,9 +100,9 @@ public SiliconChargeDeathEvent(EntityUid siliconUid, BatteryComponent batteryCom public sealed class SiliconChargeAliveEvent : EntityEventArgs { public EntityUid SiliconUid { get; } - public BatteryComponent BatteryComp { get; } + public BatteryComponent? BatteryComp { get; } - public SiliconChargeAliveEvent(EntityUid siliconUid, BatteryComponent batteryComp) + public SiliconChargeAliveEvent(EntityUid siliconUid, BatteryComponent? batteryComp) { SiliconUid = siliconUid; BatteryComp = batteryComp; diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs index a82324d2e3..e4042c61be 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs @@ -11,41 +11,55 @@ using Content.Shared.Movement.Systems; using Content.Server.Body.Components; using Content.Server.Power.EntitySystems; +using Robust.Shared.Containers; +using System.Diagnostics.CodeAnalysis; namespace Content.Server.SimpleStation14.Silicon.Charge; public sealed class SiliconChargeSystem : EntitySystem { [Dependency] private readonly IRobustRandom _random = default!; - [Dependency] private readonly MobStateSystem _mobStateSystem = default!; - [Dependency] private readonly FlammableSystem _flammableSystem = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; + [Dependency] private readonly FlammableSystem _flammable = default!; [Dependency] private readonly PopupSystem _popup = default!; - [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; + [Dependency] private readonly MovementSpeedModifierSystem _moveMod = default!; [Dependency] private readonly BatterySystem _battery = default!; + [Dependency] private readonly SharedContainerSystem _container = default!; public override void Initialize() { base.Initialize(); - // Subscribe for init on entities with both SiliconComponent and BatteryComponent - SubscribeLocalEvent(OnBatteryInit); + SubscribeLocalEvent(OnSiliconStartup); } - - private void OnBatteryInit(EntityUid uid, BatteryComponent component, ComponentInit args) + public bool TryGetSiliconBattery(EntityUid uid, [NotNullWhen(true)] out BatteryComponent? batteryComp) { - if (!EntityManager.TryGetComponent(uid, out var siliconComp) || - !siliconComp.BatteryPowered) - return; + batteryComp = null; + + if (!EntityManager.TryGetComponent(uid, out SiliconComponent? siliconComp)) + return false; + + if (siliconComp.BatteryContainer != null && + siliconComp.BatteryContainer.ContainedEntities.Count > 0 && + TryComp(siliconComp.BatteryContainer.ContainedEntities[0], out batteryComp)) + { + return true; + } - _battery.SetMaxCharge(uid, component.MaxCharge * _random.NextFloat(0.85f, 1.15f)); + if (TryComp(uid, out batteryComp)) + return true; - var batteryLevelFill = component.MaxCharge; + return false; + } - if (siliconComp.StartCharged.Equals(StartChargedData.Randomized)) - batteryLevelFill *= _random.NextFloat(0.40f, 0.80f); + private void OnSiliconStartup(EntityUid uid, SiliconComponent component, ComponentStartup args) + { + if (component.BatterySlot == null) + return; - _battery.SetCharge(uid, batteryLevelFill); + var container = _container.EnsureContainer(uid, component.BatterySlot); + component.BatteryContainer = container; } public override void Update(float frameTime) @@ -53,11 +67,14 @@ public override void Update(float frameTime) base.Update(frameTime); // For each siliconComp entity with a battery component, drain their charge. - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var silicon, out var siliconComp, out var batteryComp)) + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var silicon, out var siliconComp)) { + if (!siliconComp.BatteryPowered || !TryGetSiliconBattery(silicon, out var batteryComp)) + continue; + // If the silicon is dead, skip it. - if (_mobStateSystem.IsDead(silicon)) + if (_mobState.IsDead(silicon)) continue; var drainRate = 10 * siliconComp.DrainRateMulti; @@ -84,10 +101,10 @@ public override void Update(float frameTime) var currentState = chargePercent switch { - var x when x > siliconComp.ChargeStateThresholdMid => ChargeState.Full, - var x when x > siliconComp.ChargeStateThresholdLow => ChargeState.Mid, - var x when x > siliconComp.ChargeStateThresholdCritical => ChargeState.Low, - var x when x > 0 || siliconComp.ChargeStateThresholdCritical == 0 => ChargeState.Critical, + var x when x > siliconComp.ChargeThresholdMid => ChargeState.Full, + var x when x > siliconComp.ChargeThresholdLow => ChargeState.Mid, + var x when x > siliconComp.ChargeThresholdCritical => ChargeState.Low, + var x when x > 0 || siliconComp.ChargeThresholdCritical == 0 => ChargeState.Critical, _ => ChargeState.Dead, }; @@ -98,7 +115,9 @@ public override void Update(float frameTime) RaiseLocalEvent(silicon, new SiliconChargeStateUpdateEvent(currentState)); - _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(silicon); + Logger.DebugS("silicon", $"Silicon {silicon} charge state updated to {currentState}."); + + _moveMod.RefreshMovementSpeedModifiers(silicon); } } } @@ -135,7 +154,7 @@ private float SiliconHeatEffects(EntityUid silicon, float frameTime) !flamComp.OnFire && _random.Prob(Math.Clamp(temperComp.CurrentTemperature / (upperThresh * 5), 0.001f, 0.9f))) { - _flammableSystem.Ignite(silicon, flamComp); + _flammable.Ignite(silicon, flamComp); } else if ((flamComp == null || !flamComp.OnFire) && _random.Prob(Math.Clamp(temperComp.CurrentTemperature / upperThresh, 0.001f, 0.75f))) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 7f42f9497c..45522c77b1 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -38,6 +38,7 @@ public sealed class SiliconChargerSystem : EntitySystem [Dependency] private readonly BatterySystem _battery = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly SiliconChargeSystem _silicon = default!; public override void Initialize() { @@ -153,8 +154,8 @@ private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconCha foreach (var entityToCharge in entitiesToCharge.ToList()) { - if (TryComp(entityToCharge, out _)) - ChargeBattery(entityToCharge, EntityManager.GetComponent(entityToCharge), chargeRate, chargerComp, chargerUid); + if (_silicon.TryGetSiliconBattery(entityToCharge, out var batteryComp)) + ChargeBattery(entityToCharge, batteryComp, chargeRate, chargerComp, chargerUid); else if (TryComp(entityToCharge, out var damageComp)) BurnEntity(entityToCharge, damageComp, frameTime, chargerComp, chargerUid); } @@ -164,22 +165,28 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true { var entitiesToCharge = new List(); + if (_silicon.TryGetSiliconBattery(entity, out var siliconBatteryComp)) + { + if (siliconBatteryComp.CurrentCharge < siliconBatteryComp.MaxCharge) + entitiesToCharge.Add(entity); + } + // If the given entity has a battery, charge it. - if (!HasComp(entity) && // Should probably be charge by the entity holding it, but also might be too small to be safe. - TryComp(entity, out var batteryComp) && - batteryComp.CurrentCharge < batteryComp.MaxCharge) + else if (!HasComp(entity) && // Should probably be charged by the entity holding it. Might be too small to be safe. + TryComp(entity, out var batteryComp)) { - entitiesToCharge.Add(entity); + if (batteryComp.CurrentCharge < batteryComp.MaxCharge) + entitiesToCharge.Add(entity); } // If the given entity contains a battery, charge it. - else if (!HasComp(entity) && // Should probably be charge by the entity holding it, but also might be too small to be safe. + else if (!HasComp(entity) && // Should probably be charged by the entity holding it. Might be too small to be safe. TryComp(entity, out var cellSlotComp) && _itemSlots.TryGetSlot(entity, cellSlotComp.CellSlotId, out var slot) && - TryComp(slot.Item, out var cellBattComp) && - cellBattComp.CurrentCharge < cellBattComp.MaxCharge) + TryComp(slot.Item, out var cellBattComp)) { - entitiesToCharge.Add(slot.Item.Value); + if (cellBattComp.CurrentCharge < cellBattComp.MaxCharge) + entitiesToCharge.Add(slot.Item.Value); } // If the given entity is fleshy, burn the fucker. diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs index c6bbf891d5..c8ef4e95ae 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs @@ -1,6 +1,7 @@ using Robust.Shared.GameStates; using Content.Shared.SimpleStation14.Silicon.Systems; using Robust.Shared.Serialization.TypeSerializers.Implementations; +using Robust.Shared.Containers; namespace Content.Shared.SimpleStation14.Silicon.Components; @@ -22,6 +23,11 @@ public sealed class SiliconComponent : Component [ViewVariables(VVAccess.ReadOnly)] public new EntityUid Owner = EntityUid.Invalid; + /// + /// The Silicon's battery slot, if it has one. + /// + public Container? BatteryContainer = null; + /// /// Is the Silicon currently dead? /// @@ -47,13 +53,11 @@ public sealed class SiliconComponent : Component public bool BatteryPowered = false; /// - /// Should this silicon start charged? + /// Slot this entity's battery is contained in. + /// Leave null if using a battery component. /// - /// - /// Valid values are: , , and . - /// - [DataField("startCharged", customTypeSerializer: typeof(EnumSerializer)), ViewVariables(VVAccess.ReadOnly)] - public Enum StartCharged = StartChargedData.Randomized; + [DataField("batterySlot")] + public string? BatterySlot = null; /// /// Multiplier for the drain rate of the silicon. @@ -70,16 +74,16 @@ public sealed class SiliconComponent : Component /// Setting a value to null will disable that state. /// Setting Critical to 0 will cause the Silicon to never enter the dead state. /// - [DataField("chargeStateThresholdMid"), ViewVariables(VVAccess.ReadWrite)] - public float? ChargeStateThresholdMid = 0.5f; + [DataField("chargeThresholdMid"), ViewVariables(VVAccess.ReadWrite)] + public float? ChargeThresholdMid = 0.5f; - /// - [DataField("chargeStateThresholdLow"), ViewVariables(VVAccess.ReadWrite)] - public float? ChargeStateThresholdLow = 0.25f; + /// + [DataField("chargeThresholdLow"), ViewVariables(VVAccess.ReadWrite)] + public float? ChargeThresholdLow = 0.25f; - /// - [DataField("chargeStateThresholdCritical"), ViewVariables(VVAccess.ReadWrite)] - public float? ChargeStateThresholdCritical = 0.0f; + /// + [DataField("chargeThresholdCritical"), ViewVariables(VVAccess.ReadWrite)] + public float? ChargeThresholdCritical = 0.0f; /// diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs index 0e7abef928..4c18e08587 100644 --- a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs @@ -54,11 +54,11 @@ private void OnRefreshMovespeed(EntityUid uid, SiliconComponent component, Refre foreach (var state in speedModThresholds) { - if (component.ChargeState >= state.Key && ((float) state.Key) > closest) - closest = ((float) state.Key); + if (component.ChargeState >= state.Key && (float) state.Key > closest) + closest = (float) state.Key; } - var speedMod = speedModThresholds[(ChargeState)closest]; + var speedMod = speedModThresholds[(ChargeState) closest]; args.ModifySpeed(speedMod, speedMod); } @@ -74,7 +74,6 @@ public enum SiliconType public enum ChargeState { - Charging = -1, Full, Mid, Low, @@ -82,13 +81,6 @@ public enum ChargeState Dead } -public enum StartChargedData -{ - False, - True, - Randomized -} - /// /// Event raised when a Silicon's charge state needs to be updated. diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/robots.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/robots.yml index dcf397817b..8793f6b02b 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/robots.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/robots.yml @@ -193,9 +193,9 @@ batteryPowered: true drainRateMulti: 4 chargeRateMulti: 6 - chargeStateThresholdMid: 0.60 - chargeStateThresholdLow: 0.30 - chargeStateThresholdCritical: 0 + chargeThresholdMid: 0.60 + chargeThresholdLow: 0.30 + chargeThresholdCritical: 0 speedModifierThresholds: 0: 1 1: 1 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml index 6e15756ea0..8a7e71b2ad 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -9,13 +9,16 @@ templateId: ipc - type: Battery maxCharge: 150000 + - type: RandomBatteryCharge + batteryMaxMinMax: 0.85, 1.15 + batteryChargeMinMax: 0.40, 0.90 - type: Silicon entityType: enum.SiliconType.Player batteryPowered: true drainRateMulti: 5 - chargeStateThresholdMid: 0.80 - chargeStateThresholdLow: 0.35 - chargeStateThresholdCritical: 0.10 + chargeThresholdMid: 0.80 + chargeThresholdLow: 0.35 + chargeThresholdCritical: 0.10 speedModifierThresholds: 0: 1 1: 1 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 11d4ca1f72..91cce030d4 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -62,12 +62,12 @@ - type: Alerts - type: Silicon entityType: enum.SiliconType.Player - batteryPowered: false # Needs to also have a battery component! + batteryPowered: false # Needs to also have a battery! drainRateMulti: 4.5 chargeRateMulti: 6 - chargeStateThresholdMid: 0.60 - chargeStateThresholdLow: 0.30 - chargeStateThresholdCritical: 0 + chargeThresholdMid: 0.60 + chargeThresholdLow: 0.30 + chargeThresholdCritical: 0 speedModifierThresholds: 0: 1 1: 1 From 564258b6a4d2c298d7ebb9e7807ee66b13b733f0 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sat, 24 Jun 2023 01:18:15 -0400 Subject: [PATCH 46/60] Fixed issue with IPC charge, and review suggestions. --- .../Power/Components/BatteryDrinkerComponent.cs | 2 +- .../Power/Components/RandomBatteryChargeComponent.cs | 2 +- .../Power/Systems/BatteryDrinkerSystem.cs | 2 -- .../Power/Systems/BatteryElectrocuteChargeSystem.cs | 4 +--- .../Charge/Systems/SiliconChargeDeathSystem.cs | 6 +----- .../Silicon/Charge/Systems/SiliconChargeSystem.cs | 2 -- .../Silicon/Charge/Systems/SiliconChargerSystem.cs | 12 ++++-------- .../Silicon/Components/SiliconChargerComponent.cs | 1 + .../Silicon/Systems/SharedSiliconSystem.cs | 1 + .../Entities/Mobs/Customization/ipcScreens.ftl | 2 +- .../Prototypes/SimpleStation14/Body/Parts/ipc.yml | 2 -- 11 files changed, 11 insertions(+), 25 deletions(-) diff --git a/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs b/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs index ca51684709..ea254dfbdc 100644 --- a/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs +++ b/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs @@ -13,7 +13,7 @@ public class BatteryDrinkerComponent : Component /// /// How long it takes to drink from a battery, in seconds. - /// Is mutliplied by the source. + /// Is multiplied by the source. /// [DataField("drinkSpeed"), ViewVariables(VVAccess.ReadWrite)] public float DrinkSpeed = 1.5f; diff --git a/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs b/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs index 4b1892ac95..505ff3176c 100644 --- a/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs +++ b/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs @@ -19,5 +19,5 @@ public class RandomBatteryChargeComponent : Component /// True if the current charge is based on the preexisting current charge, or false if it's based on the max charge. /// [DataField("basedOnMaxCharge")] - public bool BasedOnMaxCharge = false; + public bool BasedOnMaxCharge = true; } diff --git a/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs index a34f6d33f3..e9eb0e6a57 100644 --- a/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs +++ b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs @@ -122,9 +122,7 @@ private void OnDoAfter(EntityUid uid, BatteryDrinkerComponent drinkerComp, DoAft amountToDrink = MathF.Min(amountToDrink, drinkerBattery.MaxCharge - drinkerBattery.CurrentCharge); if (sourceComp != null && sourceComp.MaxAmount > 0) - { amountToDrink = MathF.Min(amountToDrink, (float) sourceComp.MaxAmount); - } if (amountToDrink <= 0) { diff --git a/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs b/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs index 382106dddb..03504e5afb 100644 --- a/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs +++ b/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs @@ -32,8 +32,6 @@ private void OnElectrocuted(EntityUid uid, BatteryComponent battery, Electrocute battery.CurrentCharge += charge; - var message = Loc.GetString("battery-electrocute-charge"); - - _popup.PopupEntity(message, uid, uid); + _popup.PopupEntity(Loc.GetString("battery-electrocute-charge"), uid, uid); } } diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs index 55b9e63007..d69e65f4f7 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs @@ -28,13 +28,9 @@ private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponen Logger.Debug($"Silicon battery: {batteryComp?.CurrentCharge}"); if (args.ChargeState == ChargeState.Dead && !siliconDeadComp.Dead) - { SiliconDead(uid, siliconDeadComp, batteryComp); - } else if (args.ChargeState != ChargeState.Dead && siliconDeadComp.Dead) - { SiliconUnDead(uid, siliconDeadComp, batteryComp); - } } private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent? batteryComp) @@ -65,7 +61,7 @@ private void SiliconUnDead(EntityUid uid, SiliconDownOnDeadComponent siliconDead } /// -/// A canellable event raised when a Silicon is about to go down due to charge. +/// A cancellable event raised when a Silicon is about to go down due to charge. /// public sealed class SiliconChargeDyingEvent : CancellableEntityEventArgs { diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs index e4042c61be..4cd2e0c1ef 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs @@ -115,8 +115,6 @@ public override void Update(float frameTime) RaiseLocalEvent(silicon, new SiliconChargeStateUpdateEvent(currentState)); - Logger.DebugS("silicon", $"Silicon {silicon} charge state updated to {currentState}."); - _moveMod.RefreshMovementSpeedModifiers(silicon); } } diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 45522c77b1..9e92177b8d 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -61,8 +61,8 @@ public override void Update(float frameTime) #region Entity Storage Chargers // Check for any chargers with the EntityStorageComponent. - var entstorQuery = EntityQueryEnumerator(); - while (entstorQuery.MoveNext(out var uid, out var chargerComp, out var entStorage)) + var entityStorageQuery = EntityQueryEnumerator(); + while (entityStorageQuery.MoveNext(out var uid, out var chargerComp, out var entStorage)) { var wasActive = chargerComp.Active; chargerComp.Active = false; @@ -81,8 +81,6 @@ public override void Update(float frameTime) var chargeRate = chargerComp.ChargeMulti * frameTime * 10; - - HandleChargingEntity(entity, chargeRate, chargerComp, uid, frameTime); // Heat up the air in the charger. @@ -234,10 +232,8 @@ private List SearchThroughEntities(EntityUid entity, bool burn = true private void ChargeBattery(EntityUid entity, BatteryComponent batteryComp, float chargeRate, SiliconChargerComponent chargerComp, EntityUid chargerUid) { // Do some math so a charger never charges a battery from zero to full in less than 10 seconds, just for the effect of it. - if (chargerComp.ChargeMulti * 10 > batteryComp.MaxCharge / 10) - { - chargeRate /= chargerComp.ChargeMulti * 10 / (batteryComp.MaxCharge / 10); - } + if (chargerComp.ChargeMulti * 10 > batteryComp.MaxCharge / chargerComp.MinChargeTime) + chargeRate /= chargerComp.ChargeMulti * 10 / (batteryComp.MaxCharge / chargerComp.MinChargeTime); if (batteryComp.CurrentCharge + chargeRate < batteryComp.MaxCharge) _battery.SetCharge(entity, batteryComp.CurrentCharge + chargeRate, batteryComp); diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs index 46203475f9..14e3e95674 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs @@ -54,6 +54,7 @@ public sealed class SiliconChargerComponent : Component /// The minimum amount of time it will take to charge a battery, in seconds. /// /// + /// Note that this is from empty. A battery that is already half full will take half as long as this value to reach full, if it would've been faster from empty. /// This is for the sake of feeling cooler- It's lame to just charge instantly. /// [DataField("minChargeTime"), ViewVariables(VVAccess.ReadWrite)] diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs index 4c18e08587..beb4246f65 100644 --- a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs @@ -5,6 +5,7 @@ namespace Content.Shared.SimpleStation14.Silicon.Systems; + public sealed class SharedSiliconChargeSystem : EntitySystem { [Dependency] private readonly AlertsSystem _alertsSystem = default!; diff --git a/Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcScreens.ftl b/Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcScreens.ftl index 656d928c69..3f53f2d3f9 100644 --- a/Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcScreens.ftl +++ b/Resources/Locale/en-US/SimpleStation14/Prototypes/Entities/Mobs/Customization/ipcScreens.ftl @@ -5,7 +5,7 @@ marking-ScreenEight = Eight marking-ScreenGoggles = Goggles marking-ScreenExclaim = Exclaim marking-ScreenHeart = Heart -marking-ScreenMonoeye = Cylops +marking-ScreenMonoeye = Cyclops marking-ScreenNature = Naturalist marking-ScreenOrange = Orange marking-ScreenPink = Pink diff --git a/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml b/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml index 138e2d47e7..b46c6997a9 100644 --- a/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Body/Parts/ipc.yml @@ -1,5 +1,3 @@ -# TODO: Add descriptions (many) -# TODO BODY: Part damage - type: entity id: PartIPC parent: BaseItem From f7cca4f42c4792ad28c887684dbbcd469a096917 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sat, 24 Jun 2023 09:37:26 -0400 Subject: [PATCH 47/60] Lots of general improvements to the systems, lots of cleanup. Clean, Medi, and Honk bots all use battery cell slots, which SiliconSystem now supports. To support external batteries entirely sometime. --- .../Electrocution/ElectrocutionSystem.cs | 2 +- .../Nyanotrasen/Borgs/CyborgComponent.cs | 2 +- .../Nyanotrasen/Borgs/CyborgSystem.cs | 6 +- .../Components/BatteryDrinkerComponent.cs | 18 ++--- .../RandomBatteryChargeComponent.cs | 2 +- .../Power/Systems/BatteryDrinkerSystem.cs | 55 +++++++-------- .../Systems/BatteryElectrocuteChargeSystem.cs | 5 +- .../Radio/IntrinsicRadioKeySystem.cs | 2 +- .../BatteryDrinkerSourceComponent.cs | 5 +- .../Components/SiliconDownOnDeadComponent.cs | 9 +++ .../Systems/SiliconChargeDeathSystem.cs | 42 ++++++----- .../Charge/Systems/SiliconChargeSystem.cs | 70 ++++++++++++++----- .../Charge/Systems/SiliconChargerSystem.cs | 25 +++---- .../Silicon/Systems/SiliconMiscSystem.cs | 1 - .../EntitySystems/EncryptionKeySystem.cs | 2 +- .../SimpleStation14/CCVar/CCVars.cs | 27 ++++--- .../Silicon/BatteryDrinkerEvent.cs | 4 +- .../Silicon/Components/SiliconComponent.cs | 26 ++++--- .../Silicon/Systems/SharedSiliconSystem.cs | 22 +++--- .../Content/Power/batteries.ftl | 1 + .../Content/Power/batteryDrinker.ftl | 2 + .../Content/Silicons/silicons.ftl | 3 + .../Locale/en-US/devices/device-network.ftl | 4 +- .../Locale/en-US/job/department-desc.ftl | 2 +- Resources/Locale/en-US/revenant/revenant.ftl | 2 +- .../Prototypes/Entities/Mobs/NPCs/silicon.yml | 25 +++++++ .../Entities/Structures/Power/apc.yml | 8 +++ .../Entities/Mobs/Player/robots.yml | 9 ++- .../SimpleStation14/Alerts/alerts.yml | 4 +- .../Entities/Mobs/Player/ipc.yml | 10 +-- .../Entities/Mobs/Player/silicon_base.yml | 10 ++- 31 files changed, 250 insertions(+), 155 deletions(-) create mode 100644 Resources/Locale/en-US/SimpleStation14/Content/Power/batteries.ftl create mode 100644 Resources/Locale/en-US/SimpleStation14/Content/Power/batteryDrinker.ftl diff --git a/Content.Server/Electrocution/ElectrocutionSystem.cs b/Content.Server/Electrocution/ElectrocutionSystem.cs index f887db9d38..f6c32b99f6 100644 --- a/Content.Server/Electrocution/ElectrocutionSystem.cs +++ b/Content.Server/Electrocution/ElectrocutionSystem.cs @@ -51,7 +51,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem private const string DamageType = "Shock"; // Yes, this is absurdly small for a reason. - public const float ElectrifiedDamagePerWatt = 0.0015f; // Parkstation-IPC + public const float ElectrifiedDamagePerWatt = 0.0015f; // Parkstation-IPC // This information is allowed to be public, and was needed in BatteryElectrocuteChargeSystem.cs private const float RecursiveDamageMultiplier = 0.75f; private const float RecursiveTimeMultiplier = 0.8f; diff --git a/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs b/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs index 4311e27b89..d2f74ff00c 100644 --- a/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs +++ b/Content.Server/Nyanotrasen/Borgs/CyborgComponent.cs @@ -4,4 +4,4 @@ namespace Content.Server.Borgs [RegisterComponent] public sealed class CyborgComponent : Component {} -} \ No newline at end of file +} diff --git a/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs b/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs index c82fdf6215..fbac68189a 100644 --- a/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs +++ b/Content.Server/Nyanotrasen/Borgs/CyborgSystem.cs @@ -16,7 +16,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnChangeState); } - + private void OnChangeState(EntityUid uid, CyborgComponent component, MobStateChangedEvent args) { if (args.NewMobState == MobState.Dead){ @@ -28,7 +28,7 @@ private void OnChangeState(EntityUid uid, CyborgComponent component, MobStateCha // Stop dead borg from being movable AA cards by removing their ability to bump doors. _tagSystem.RemoveTag(uid, "DoorBumpOpener"); - + } else if(args.NewMobState == MobState.Alive && args.OldMobState == MobState.Dead) { @@ -39,4 +39,4 @@ private void OnChangeState(EntityUid uid, CyborgComponent component, MobStateCha return; } } -} \ No newline at end of file +} diff --git a/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs b/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs index ea254dfbdc..8587f6a89c 100644 --- a/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs +++ b/Content.Server/SimpleStation14/Power/Components/BatteryDrinkerComponent.cs @@ -1,9 +1,7 @@ -using Robust.Shared.Audio; - namespace Content.Server.SimpleStation14.Power; [RegisterComponent] -public class BatteryDrinkerComponent : Component +public sealed class BatteryDrinkerComponent : Component { /// /// Is this drinker allowed to drink batteries not tagged as ? @@ -26,16 +24,8 @@ public class BatteryDrinkerComponent : Component public float DrinkMultiplier = 5f; /// - /// The sound to override the standard drink sound with. - /// Uses per source sound if null. - /// - [DataField("drinkSoundOverride")] - public SoundSpecifier? DrinkSound = new SoundPathSpecifier("/Audio/Items/drink.ogg"); - - /// - /// The localised string to display when drinking from a battery. - /// Doesn't _need_ to be localised, but come on, man. + /// The multiplier for how long it takes to drink a non-source battery, if is true. /// - [DataField("drinkText")] - public string DrinkText = "aaaaaaaaaa"; + [DataField("drinkAllMultiplier"), ViewVariables(VVAccess.ReadWrite)] + public float DrinkAllMultiplier = 2.5f; } diff --git a/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs b/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs index 505ff3176c..6f5f601675 100644 --- a/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs +++ b/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs @@ -1,7 +1,7 @@ namespace Content.Server.SimpleStation14.Power.Components; [RegisterComponent] -public class RandomBatteryChargeComponent : Component +public sealed class RandomBatteryChargeComponent : Component { /// /// The minimum and maximum max charge the battery can have. diff --git a/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs index e9eb0e6a57..3e92f7effe 100644 --- a/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs +++ b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs @@ -2,15 +2,13 @@ using Content.Server.Power.Components; using Content.Shared.Containers.ItemSlots; using Content.Shared.DoAfter; -using Content.Shared.Interaction.Helpers; using Content.Shared.PowerCell.Components; using Content.Shared.SimpleStation14.Silicon; using Content.Shared.Verbs; -using Robust.Shared.Audio; -using Robust.Shared.Serialization; using Robust.Shared.Utility; using Content.Server.SimpleStation14.Silicon.Charge; using Content.Server.Power.EntitySystems; +using Content.Server.Popups; namespace Content.Server.SimpleStation14.Power; @@ -21,6 +19,7 @@ public sealed class BatteryDrinkerSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly BatterySystem _battery = default!; [Dependency] private readonly SiliconChargeSystem _silicon = default!; + [Dependency] private readonly PopupSystem _popup = default!; public override void Initialize() { @@ -28,7 +27,7 @@ public override void Initialize() SubscribeLocalEvent>(AddAltVerb); - SubscribeLocalEvent(OnDoAfter); + SubscribeLocalEvent(OnDoAfter); } private void AddAltVerb(EntityUid uid, BatteryComponent batteryComponent, GetVerbsEvent args) @@ -36,16 +35,16 @@ private void AddAltVerb(EntityUid uid, BatteryComponent batteryComponent, GetVer if (!args.CanAccess || !args.CanInteract) return; - if (!EntityManager.TryGetComponent(args.User, out var drinkerComp) || + if (!TryComp(args.User, out var drinkerComp) || !TestDrinkableBattery(uid, drinkerComp) || - !TryGetFillableBattery(args.User, out var drinkerBattery)) + !TryGetFillableBattery(args.User, out var drinkerBattery, out _)) return; AlternativeVerb verb = new() { Act = () => DrinkBattery(uid, args.User, drinkerComp), Text = "system-battery-drinker-verb-drink", - Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/drink.svg.192dpi.png")), + Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")), }; args.Verbs.Add(verb); @@ -59,19 +58,22 @@ private bool TestDrinkableBattery(EntityUid target, BatteryDrinkerComponent drin return true; } - private bool TryGetFillableBattery(EntityUid uid, [NotNullWhen(true)] out BatteryComponent? battery) + private bool TryGetFillableBattery(EntityUid uid, [NotNullWhen(true)] out BatteryComponent? battery, [NotNullWhen(true)] out EntityUid batteryUid) { - if (_silicon.TryGetSiliconBattery(uid, out battery)) + if (_silicon.TryGetSiliconBattery(uid, out battery, out batteryUid)) return true; - if (EntityManager.TryGetComponent(uid, out battery)) + if (TryComp(uid, out battery)) return true; - if (EntityManager.TryGetComponent(uid, out var powerCellSlot) && + if (TryComp(uid, out var powerCellSlot) && _slots.TryGetSlot(uid, powerCellSlot.CellSlotId, out var slot) && slot.Item != null && - EntityManager.TryGetComponent(slot.Item.Value, out battery)) + TryComp(slot.Item.Value, out battery)) + { + batteryUid = slot.Item.Value; return true; + } return false; } @@ -80,12 +82,12 @@ private void DrinkBattery(EntityUid target, EntityUid user, BatteryDrinkerCompon { var doAfterTime = drinkerComp.DrinkSpeed; - if (EntityManager.TryGetComponent(target, out var sourceComp)) + if (TryComp(target, out var sourceComp)) doAfterTime *= sourceComp.DrinkSpeedMulti; else - doAfterTime *= 2.5f; + doAfterTime *= drinkerComp.DrinkAllMultiplier; - var args = new DoAfterArgs(user, doAfterTime, new BatteryDrinkerEvent(), user, target) + var args = new DoAfterArgs(user, doAfterTime, new BatteryDrinkerDoAfterEvent(), user, target) // TODO: Make this doafter loop, once we merge Upstream. { BreakOnDamage = true, BreakOnTargetMove = true, @@ -105,11 +107,11 @@ private void OnDoAfter(EntityUid uid, BatteryDrinkerComponent drinkerComp, DoAft var source = args.Target.Value; var drinker = uid; - var sourceBattery = EntityManager.GetComponent(source); + var sourceBattery = Comp(source); - TryGetFillableBattery(drinker, out var drinkerBattery); + TryGetFillableBattery(drinker, out var drinkerBattery, out var drinkerBatteryUid); - EntityManager.TryGetComponent(source, out var sourceComp); + TryComp(source, out var sourceComp); DebugTools.AssertNotNull(drinkerBattery); @@ -126,26 +128,19 @@ private void OnDoAfter(EntityUid uid, BatteryDrinkerComponent drinkerComp, DoAft if (amountToDrink <= 0) { - // Do empty stuff + _popup.PopupEntity(Loc.GetString("battery-drinker-empty", ("target", source)), drinker, drinker); return; } if (_battery.TryUseCharge(source, amountToDrink, sourceBattery)) - { - _battery.SetCharge(source, drinkerBattery.Charge + amountToDrink, sourceBattery); - } + _battery.SetCharge(drinkerBatteryUid, drinkerBattery.Charge + amountToDrink, drinkerBattery); else { - _battery.SetCharge(drinker, sourceBattery.Charge, drinkerBattery); + _battery.SetCharge(drinker, sourceBattery.Charge + drinkerBattery.Charge, drinkerBattery); _battery.SetCharge(source, 0, sourceBattery); } - var sound = drinkerComp.DrinkSound ?? sourceComp?.DrinkSound; - - if (sound != null) - _audio.PlayPvs(sound, source); - - // if (sourceBattery.CurrentCharge > 0) // Make use proper looping doafters when we merge Upstream. - // DrinkBattery(source, drinker, sourceBattery, drinkerBattery, drinkerComp); + if (sourceComp != null && sourceComp.DrinkSound != null) + _audio.PlayPvs(sourceComp.DrinkSound, source); } } diff --git a/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs b/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs index 03504e5afb..86238aab6c 100644 --- a/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs +++ b/Content.Server/SimpleStation14/Power/Systems/BatteryElectrocuteChargeSystem.cs @@ -1,6 +1,7 @@ using Content.Server.Electrocution; using Content.Server.Popups; using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; using Content.Shared.Electrocution; using Robust.Shared.Random; using Robust.Shared.Timing; @@ -11,7 +12,7 @@ public sealed class BatteryElectrocuteChargeSystem : EntitySystem { [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly PopupSystem _popup = default!; - [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly BatterySystem _battery = default!; public override void Initialize() { @@ -30,7 +31,7 @@ private void OnElectrocuted(EntityUid uid, BatteryComponent battery, Electrocute var damage = args.ShockDamage.Value * args.SiemensCoefficient; var charge = Math.Min(damage / damagePerWatt, battery.MaxCharge * 0.25f) * _random.NextFloat(0.75f, 1.25f); - battery.CurrentCharge += charge; + _battery.SetCharge(uid, battery.CurrentCharge + charge); _popup.PopupEntity(Loc.GetString("battery-electrocute-charge"), uid, uid); } diff --git a/Content.Server/SimpleStation14/Radio/IntrinsicRadioKeySystem.cs b/Content.Server/SimpleStation14/Radio/IntrinsicRadioKeySystem.cs index 6ea9c30d90..32dad9f078 100644 --- a/Content.Server/SimpleStation14/Radio/IntrinsicRadioKeySystem.cs +++ b/Content.Server/SimpleStation14/Radio/IntrinsicRadioKeySystem.cs @@ -24,7 +24,7 @@ private void OnReceiverChannelsChanged(EntityUid uid, ActiveRadioComponent compo UpdateChannels(uid, args.Component, ref component.Channels); } - private void UpdateChannels(EntityUid uid, EncryptionKeyHolderComponent keyHolderComp, ref HashSet channels) + private void UpdateChannels(EntityUid _, EncryptionKeyHolderComponent keyHolderComp, ref HashSet channels) { channels.Clear(); channels.UnionWith(keyHolderComp.Channels); diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs index 807f08f003..f4abfa392e 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs @@ -3,10 +3,11 @@ namespace Content.Server.SimpleStation14.Silicon.Charge; [RegisterComponent] -public class BatteryDrinkerSourceComponent : Component +public sealed class BatteryDrinkerSourceComponent : Component { /// - /// The max amount of power to give when drunk from. + /// The max amount of power this source can provide in one sip. + /// No limit if null. /// [DataField("maxAmount"), ViewVariables(VVAccess.ReadWrite)] public int? MaxAmount = null; diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs index 17fa934df0..434a4f6df2 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs @@ -1,7 +1,16 @@ namespace Content.Server.SimpleStation14.Silicon.Death; +/// +/// Marks a Silicon as becoming incapacitated when they run out of battery charge. +/// +/// +/// Uses the Silicon System's charge states to do so, so make sure they're a battery powered Silicon. +/// [RegisterComponent] public sealed class SiliconDownOnDeadComponent : Component { + /// + /// Is this Silicon currently dead? + /// public bool Dead { get; set; } = false; } diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs index d69e65f4f7..37c6fe09f7 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs @@ -4,7 +4,6 @@ using Content.Shared.Bed.Sleep; using Content.Server.Sound.Components; using Content.Server.SimpleStation14.Silicon.Charge; -using Serilog; namespace Content.Server.SimpleStation14.Silicon.Death; @@ -22,20 +21,17 @@ public override void Initialize() private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, SiliconChargeStateUpdateEvent args) { - _silicon.TryGetSiliconBattery(uid, out var batteryComp); - - Logger.Debug($"Silicon charge state update: {args.ChargeState}"); - Logger.Debug($"Silicon battery: {batteryComp?.CurrentCharge}"); + _silicon.TryGetSiliconBattery(uid, out var batteryComp, out var batteryUid); if (args.ChargeState == ChargeState.Dead && !siliconDeadComp.Dead) - SiliconDead(uid, siliconDeadComp, batteryComp); + SiliconDead(uid, siliconDeadComp, batteryComp, batteryUid); else if (args.ChargeState != ChargeState.Dead && siliconDeadComp.Dead) - SiliconUnDead(uid, siliconDeadComp, batteryComp); + SiliconUnDead(uid, siliconDeadComp, batteryComp, batteryUid); } - private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent? batteryComp) + private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent? batteryComp, EntityUid batteryUid) { - var deadEvent = new SiliconChargeDyingEvent(uid, batteryComp); + var deadEvent = new SiliconChargeDyingEvent(uid, batteryComp, batteryUid); RaiseLocalEvent(uid, deadEvent); if (deadEvent.Cancelled) @@ -47,60 +43,70 @@ private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadCo siliconDeadComp.Dead = true; - RaiseLocalEvent(uid, new SiliconChargeDeathEvent(uid, batteryComp)); + RaiseLocalEvent(uid, new SiliconChargeDeathEvent(uid, batteryComp, batteryUid)); } - private void SiliconUnDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent? batteryComp) + private void SiliconUnDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent? batteryComp, EntityUid batteryUid) { _sleep.TryWaking(uid, null, true); siliconDeadComp.Dead = false; - RaiseLocalEvent(uid, new SiliconChargeAliveEvent(uid, batteryComp)); + RaiseLocalEvent(uid, new SiliconChargeAliveEvent(uid, batteryComp, batteryUid)); } } /// /// A cancellable event raised when a Silicon is about to go down due to charge. -/// +/// +/// +/// This probably shouldn't be modified unless you intend to fill the Silicon's battery, +/// as otherwise it'll just be triggered again next frame. +/// public sealed class SiliconChargeDyingEvent : CancellableEntityEventArgs { public EntityUid SiliconUid { get; } public BatteryComponent? BatteryComp { get; } + public EntityUid BatteryUid { get; } - public SiliconChargeDyingEvent(EntityUid siliconUid, BatteryComponent? batteryComp) + public SiliconChargeDyingEvent(EntityUid siliconUid, BatteryComponent? batteryComp, EntityUid batteryUid) { SiliconUid = siliconUid; BatteryComp = batteryComp; + BatteryUid = batteryUid; } } /// /// An event raised after a Silicon has gone down due to charge. -/// +/// public sealed class SiliconChargeDeathEvent : EntityEventArgs { public EntityUid SiliconUid { get; } public BatteryComponent? BatteryComp { get; } + public EntityUid BatteryUid { get; } - public SiliconChargeDeathEvent(EntityUid siliconUid, BatteryComponent? batteryComp) + public SiliconChargeDeathEvent(EntityUid siliconUid, BatteryComponent? batteryComp, EntityUid batteryUid) { SiliconUid = siliconUid; BatteryComp = batteryComp; + BatteryUid = batteryUid; } } /// /// An event raised after a Silicon has reawoken due to an increase in charge. -/// +/// public sealed class SiliconChargeAliveEvent : EntityEventArgs { public EntityUid SiliconUid { get; } public BatteryComponent? BatteryComp { get; } + public EntityUid BatteryUid { get; } - public SiliconChargeAliveEvent(EntityUid siliconUid, BatteryComponent? batteryComp) + public SiliconChargeAliveEvent(EntityUid siliconUid, BatteryComponent? batteryComp, EntityUid batteryUid) { SiliconUid = siliconUid; BatteryComp = batteryComp; + BatteryUid = batteryUid; } } diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs index 4cd2e0c1ef..c0aac19c47 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs @@ -13,6 +13,11 @@ using Content.Server.Power.EntitySystems; using Robust.Shared.Containers; using System.Diagnostics.CodeAnalysis; +using Robust.Shared.Timing; +using Content.Shared.SimpleStation14.CCVar; +using Robust.Shared.Configuration; +using System.Diagnostics; +using Robust.Shared.Utility; namespace Content.Server.SimpleStation14.Silicon.Charge; @@ -25,6 +30,8 @@ public sealed class SiliconChargeSystem : EntitySystem [Dependency] private readonly MovementSpeedModifierSystem _moveMod = default!; [Dependency] private readonly BatterySystem _battery = default!; [Dependency] private readonly SharedContainerSystem _container = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IConfigurationManager _config = default!; public override void Initialize() { @@ -33,21 +40,23 @@ public override void Initialize() SubscribeLocalEvent(OnSiliconStartup); } - public bool TryGetSiliconBattery(EntityUid uid, [NotNullWhen(true)] out BatteryComponent? batteryComp) + public bool TryGetSiliconBattery(EntityUid silicon, [NotNullWhen(true)] out BatteryComponent? batteryComp, out EntityUid batteryUid) { batteryComp = null; + batteryUid = silicon; - if (!EntityManager.TryGetComponent(uid, out SiliconComponent? siliconComp)) + if (!EntityManager.TryGetComponent(silicon, out SiliconComponent? siliconComp)) return false; if (siliconComp.BatteryContainer != null && siliconComp.BatteryContainer.ContainedEntities.Count > 0 && TryComp(siliconComp.BatteryContainer.ContainedEntities[0], out batteryComp)) { + batteryUid = siliconComp.BatteryContainer.ContainedEntities[0]; return true; } - if (TryComp(uid, out batteryComp)) + if (TryComp(silicon, out batteryComp)) return true; return false; @@ -58,8 +67,11 @@ private void OnSiliconStartup(EntityUid uid, SiliconComponent component, Compone if (component.BatterySlot == null) return; - var container = _container.EnsureContainer(uid, component.BatterySlot); + var container = _container.GetContainer(uid, component.BatterySlot); component.BatteryContainer = container; + + if (component.EntityType.GetType() != typeof(SiliconType)) + DebugTools.Assert("SiliconComponent.EntityType is not a SiliconType enum."); } public override void Update(float frameTime) @@ -70,14 +82,31 @@ public override void Update(float frameTime) var query = EntityQueryEnumerator(); while (query.MoveNext(out var silicon, out var siliconComp)) { - if (!siliconComp.BatteryPowered || !TryGetSiliconBattery(silicon, out var batteryComp)) + if (!siliconComp.BatteryPowered) + continue; + + // Check if the Silicon is an NPC, and if so, follow the delay as specified in the CVAR. + if (siliconComp.EntityType.Equals(SiliconType.Npc)) + { + var updateTime = _config.GetCVar(SimpleStationCCVars.SiliconNpcUpdateTime); + if (_timing.CurTime - siliconComp.LastDrainTime < TimeSpan.FromSeconds(updateTime)) + continue; + + siliconComp.LastDrainTime = _timing.CurTime; + } + + // If you can't find a battery, set the indicator and skip it. + if (!TryGetSiliconBattery(silicon, out var batteryComp, out var battery)) + { + UpdateChargeState(battery, ChargeState.Invalid, siliconComp); continue; + } // If the silicon is dead, skip it. if (_mobState.IsDead(silicon)) continue; - var drainRate = 10 * siliconComp.DrainRateMulti; + var drainRate = siliconComp.DrainPerSecond; // All multipliers will be subtracted by 1, and then added together, and then multiplied by the drain rate. This is then added to the base drain rate. // This is to stop exponential increases, while still allowing for less-than-one multipliers. @@ -86,15 +115,15 @@ public override void Update(float frameTime) // TODO: Devise a method of adding multis where other systems can alter the drain rate. // Maybe use something similar to refreshmovespeedmodifiers, where it's stored in the component. // Maybe it doesn't matter, and stuff should just use static drain? - - drainRateFinalAddi += SiliconHeatEffects(silicon, frameTime) - 1; + if (!siliconComp.EntityType.Equals(SiliconType.Npc)) // Don't bother checking heat if it's an NPC. It's a waste of time, and it'd be delayed due to the update time. + drainRateFinalAddi += SiliconHeatEffects(silicon, frameTime) - 1; // This will need to be changed at some point if we allow external batteries, since the heat of the Silicon might not be applicable. // Ensures that the drain rate is at least 10% of normal, // and would allow at least 4 minutes of life with a max charge, to prevent cheese. drainRate += Math.Clamp(drainRateFinalAddi, drainRate * -0.9f, batteryComp.MaxCharge / 240); // Drain the battery. - _battery.UseCharge(silicon, frameTime * drainRate, batteryComp); + _battery.UseCharge(battery, frameTime * drainRate, batteryComp); // Figure out the current state of the Silicon. var chargePercent = batteryComp.CurrentCharge / batteryComp.MaxCharge; @@ -108,16 +137,23 @@ public override void Update(float frameTime) _ => ChargeState.Dead, }; - // Check if anything needs to be updated. - if (currentState != siliconComp.ChargeState) - { - siliconComp.ChargeState = currentState; + UpdateChargeState(silicon, currentState, siliconComp); + } + } - RaiseLocalEvent(silicon, new SiliconChargeStateUpdateEvent(currentState)); + /// + /// Checks if anything needs to be updated, and updates it. + /// + public void UpdateChargeState(EntityUid uid, ChargeState state, SiliconComponent component) + { + if (component.ChargeState == state) + return; - _moveMod.RefreshMovementSpeedModifiers(silicon); - } - } + component.ChargeState = state; + + RaiseLocalEvent(uid, new SiliconChargeStateUpdateEvent(state)); + + _moveMod.RefreshMovementSpeedModifiers(uid); } private float SiliconHeatEffects(EntityUid silicon, float frameTime) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index 9e92177b8d..cdb54599c0 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -150,49 +150,50 @@ private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconCha // Now we charge the entities we found. chargeRate /= entitiesToCharge.Count; - foreach (var entityToCharge in entitiesToCharge.ToList()) + foreach (var (entityToCharge, batteryComp) in entitiesToCharge.ToList()) { - if (_silicon.TryGetSiliconBattery(entityToCharge, out var batteryComp)) + if (batteryComp != null) ChargeBattery(entityToCharge, batteryComp, chargeRate, chargerComp, chargerUid); else if (TryComp(entityToCharge, out var damageComp)) BurnEntity(entityToCharge, damageComp, frameTime, chargerComp, chargerUid); } } - private List SearchThroughEntities(EntityUid entity, bool burn = true) + private List<(EntityUid, BatteryComponent?)> SearchThroughEntities(EntityUid entity, bool burn = true) { - var entitiesToCharge = new List(); + var entitiesToCharge = new List<(EntityUid, BatteryComponent?)>(); - if (_silicon.TryGetSiliconBattery(entity, out var siliconBatteryComp)) + // If the given entity is a silicon, charge their respective battery. + if (_silicon.TryGetSiliconBattery(entity, out var siliconBatteryComp, out var siliconBatteryUid)) { if (siliconBatteryComp.CurrentCharge < siliconBatteryComp.MaxCharge) - entitiesToCharge.Add(entity); + entitiesToCharge.Add((siliconBatteryUid, siliconBatteryComp)); } - // If the given entity has a battery, charge it. + // Or if the given entity has a battery, charge it. else if (!HasComp(entity) && // Should probably be charged by the entity holding it. Might be too small to be safe. TryComp(entity, out var batteryComp)) { if (batteryComp.CurrentCharge < batteryComp.MaxCharge) - entitiesToCharge.Add(entity); + entitiesToCharge.Add((entity, batteryComp)); } - // If the given entity contains a battery, charge it. + // Or if the given entity contains a battery, charge it. else if (!HasComp(entity) && // Should probably be charged by the entity holding it. Might be too small to be safe. TryComp(entity, out var cellSlotComp) && _itemSlots.TryGetSlot(entity, cellSlotComp.CellSlotId, out var slot) && TryComp(slot.Item, out var cellBattComp)) { if (cellBattComp.CurrentCharge < cellBattComp.MaxCharge) - entitiesToCharge.Add(slot.Item.Value); + entitiesToCharge.Add((slot.Item.Value, cellBattComp)); } - // If the given entity is fleshy, burn the fucker. + // Or if the given entity is fleshy, burn the fucker. else if (burn && TryComp(entity, out var damageComp) && damageComp.DamageContainerID == "Biological") { - entitiesToCharge.Add(entity); + entitiesToCharge.Add((entity, null)); } // Now the weird part, we check for any inventories the entities contained may have, and run this function on any entities contained, for a recursive charging effect. diff --git a/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs b/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs index 117fc331f7..d331d8908e 100644 --- a/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Systems/SiliconMiscSystem.cs @@ -4,7 +4,6 @@ namespace Content.Server.SimpleStation14.Silicon.Misc; // This entire thing is fucking stupid and I hate it. -// I will never forgive them for what they did with sleeping... public sealed class SiliconMiscSystem : EntitySystem { public override void Initialize() diff --git a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs index ac8507bd13..bd80b6aecb 100644 --- a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs +++ b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs @@ -62,7 +62,7 @@ private void OnKeyRemoval(EntityUid uid, EncryptionKeyHolderComponent component, // TODO add predicted pop-up overrides. if (_net.IsServer) _popup.PopupEntity(Loc.GetString("encryption-keys-all-extracted"), uid, args.User); - + _audio.PlayPredicted(component.KeyExtractionSound, uid, args.User); } diff --git a/Content.Shared/SimpleStation14/CCVar/CCVars.cs b/Content.Shared/SimpleStation14/CCVar/CCVars.cs index 91fdb6529a..1baaad6ec5 100644 --- a/Content.Shared/SimpleStation14/CCVar/CCVars.cs +++ b/Content.Shared/SimpleStation14/CCVar/CCVars.cs @@ -30,7 +30,7 @@ public sealed class SimpleStationCCVars /// public static readonly CVarDef BloodLostThreshold = CVarDef.Create("eorstats.bloodlost_threshold", 300f, CVar.SERVERONLY); - #endregion + #endregion BloodLost #region CuffedTime /// @@ -41,7 +41,7 @@ public sealed class SimpleStationCCVars /// public static readonly CVarDef CuffedTimeThreshold = CVarDef.Create("eorstats.cuffedtime_threshold", 8, CVar.SERVERONLY); - #endregion + #endregion CuffedTime #region EmitSound /// @@ -52,7 +52,7 @@ public sealed class SimpleStationCCVars /// public static readonly CVarDef EmitSoundThreshold = CVarDef.Create("eorstats.emitsound_threshold", 80, CVar.SERVERONLY); - #endregion + #endregion EmitSound #region InstrumentPlayed /// @@ -63,7 +63,7 @@ public sealed class SimpleStationCCVars /// public static readonly CVarDef InstrumentPlayedThreshold = CVarDef.Create("eorstats.instrumentplayed_threshold", 8, CVar.SERVERONLY); - #endregion + #endregion InstrumentPlayed #region MopUsed /// @@ -89,7 +89,7 @@ public sealed class SimpleStationCCVars /// public static readonly CVarDef MopUsedTopMopperCount = CVarDef.Create("eorstats.mopused_topmoppercount", 3, CVar.SERVERONLY); - #endregion + #endregion MopUsed #region ShotsFired /// @@ -106,7 +106,7 @@ public sealed class SimpleStationCCVars /// public static readonly CVarDef ShotsFiredDisplayNone = CVarDef.Create("eorstats.shotsfired_displaynone", true, CVar.SERVERONLY); - #endregion + #endregion ShotsFired #region SlippedCount /// @@ -129,6 +129,17 @@ public sealed class SimpleStationCCVars /// public static readonly CVarDef SlippedCountTopSlipper = CVarDef.Create("eorstats.slippedcount_topslipper", true, CVar.SERVERONLY); - #endregion - #endregion + #endregion SlippedCount + #endregion EndOfRoundStats + + /* + * Silicons + */ + #region Silicons + /// + /// The amount of time between NPC Silicons draining their battery in seconds. + /// + public static readonly CVarDef SiliconNpcUpdateTime = + CVarDef.Create("silicon.npcupdatetime", 1.5f, CVar.SERVERONLY); + #endregion Silicons } diff --git a/Content.Shared/SimpleStation14/Silicon/BatteryDrinkerEvent.cs b/Content.Shared/SimpleStation14/Silicon/BatteryDrinkerEvent.cs index 738a7a34dd..adf9570401 100644 --- a/Content.Shared/SimpleStation14/Silicon/BatteryDrinkerEvent.cs +++ b/Content.Shared/SimpleStation14/Silicon/BatteryDrinkerEvent.cs @@ -4,9 +4,9 @@ namespace Content.Shared.SimpleStation14.Silicon; [Serializable, NetSerializable] -public sealed class BatteryDrinkerEvent : SimpleDoAfterEvent +public sealed class BatteryDrinkerDoAfterEvent : SimpleDoAfterEvent { - public BatteryDrinkerEvent() + public BatteryDrinkerDoAfterEvent() { } } diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs index c8ef4e95ae..2a4683dc31 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconComponent.cs @@ -18,21 +18,31 @@ public sealed class SiliconComponent : Component public float OverheatAccumulator = 0.0f; /// - /// The owner of this component. + /// The last time the Silicon was drained. + /// Used for NPC Silicons to avoid over updating. /// - [ViewVariables(VVAccess.ReadOnly)] - public new EntityUid Owner = EntityUid.Invalid; + /// + /// Time between drains can be specified in + /// + /// + public TimeSpan LastDrainTime = TimeSpan.Zero; /// /// The Silicon's battery slot, if it has one. /// - public Container? BatteryContainer = null; + public IContainer? BatteryContainer = null; /// /// Is the Silicon currently dead? /// public bool Dead = false; + // BatterySystem took issue with how this was used, so I'm coming back to it at a later date, when more foundational Silicon stuff is implemented. + // /// + // /// The entity to get the battery from. + // /// + // public EntityUid BatteryOverride? = EntityUid.Invalid; + /// /// The type of silicon this is. @@ -41,7 +51,7 @@ public sealed class SiliconComponent : Component /// Any new types of Silicons should be added to the enum. /// [DataField("entityType", customTypeSerializer: typeof(EnumSerializer))] - public Enum EntityType = SiliconType.NPC; + public Enum EntityType = SiliconType.Npc; /// /// Is this silicon battery powered? @@ -60,10 +70,10 @@ public sealed class SiliconComponent : Component public string? BatterySlot = null; /// - /// Multiplier for the drain rate of the silicon. + /// How much power is drained by this Silicon every second by default. /// - [DataField("drainRateMulti"), ViewVariables(VVAccess.ReadWrite)] - public float DrainRateMulti = 5.0f; + [DataField("drainPerSecond"), ViewVariables(VVAccess.ReadWrite)] + public float DrainPerSecond = 50f; /// diff --git a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs index beb4246f65..8ddce7550b 100644 --- a/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs +++ b/Content.Shared/SimpleStation14/Silicon/Systems/SharedSiliconSystem.cs @@ -18,6 +18,7 @@ public sealed class SharedSiliconChargeSystem : EntitySystem {ChargeState.Low, 2}, {ChargeState.Critical, 1}, {ChargeState.Dead, 0}, + {ChargeState.Invalid, -1}, }; public override void Initialize() @@ -31,17 +32,13 @@ public override void Initialize() private void OnSiliconInit(EntityUid uid, SiliconComponent component, ComponentInit args) { - component.Owner = uid; - if (component.BatteryPowered) - { - _alertsSystem.ShowAlert(uid, AlertType.Charge, ChargeStateAlert[component.ChargeState]); - } + _alertsSystem.ShowAlert(uid, AlertType.Charge, (short) component.ChargeState); } private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconComponent component, SiliconChargeStateUpdateEvent ev) { - _alertsSystem.ShowAlert(uid, AlertType.Charge, ChargeStateAlert[component.ChargeState]); + _alertsSystem.ShowAlert(uid, AlertType.Charge, (short) ev.ChargeState); } private void OnRefreshMovespeed(EntityUid uid, SiliconComponent component, RefreshMovementSpeedModifiersEvent args) @@ -51,7 +48,7 @@ private void OnRefreshMovespeed(EntityUid uid, SiliconComponent component, Refre var speedModThresholds = component.SpeedModifierThresholds; - var closest = -0.5f; + var closest = 0f; foreach (var state in speedModThresholds) { @@ -70,16 +67,17 @@ public enum SiliconType { Player, GhostRole, - NPC + Npc, } public enum ChargeState { - Full, - Mid, - Low, + Invalid = -1, + Dead, Critical, - Dead + Low, + Mid, + Full, } diff --git a/Resources/Locale/en-US/SimpleStation14/Content/Power/batteries.ftl b/Resources/Locale/en-US/SimpleStation14/Content/Power/batteries.ftl new file mode 100644 index 0000000000..15ebafae77 --- /dev/null +++ b/Resources/Locale/en-US/SimpleStation14/Content/Power/batteries.ftl @@ -0,0 +1 @@ +battery-electrocute-charge = The battery surges with energy! diff --git a/Resources/Locale/en-US/SimpleStation14/Content/Power/batteryDrinker.ftl b/Resources/Locale/en-US/SimpleStation14/Content/Power/batteryDrinker.ftl new file mode 100644 index 0000000000..1f6425d943 --- /dev/null +++ b/Resources/Locale/en-US/SimpleStation14/Content/Power/batteryDrinker.ftl @@ -0,0 +1,2 @@ +battery-drinker-drink = Drain +battery-drinker-empty = {CAPATALIZE(THE($target))} is already empty! diff --git a/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl b/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl index 7f53b2a89d..b6c8c5dc4d 100644 --- a/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl +++ b/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl @@ -1 +1,4 @@ silicon-overheating = You feel your circuits overheating! + +alerts-charge-name = Charge +alerts-charge-desk = Your current battery level. diff --git a/Resources/Locale/en-US/devices/device-network.ftl b/Resources/Locale/en-US/devices/device-network.ftl index 9e5f241eb4..0dc214da78 100644 --- a/Resources/Locale/en-US/devices/device-network.ftl +++ b/Resources/Locale/en-US/devices/device-network.ftl @@ -24,14 +24,14 @@ device-address-prefix-vent = Vnt- device-address-prefix-scrubber = Scr- device-address-prefix-sensor = Sns- -#PDAs and terminals +# PDAs and terminals device-address-prefix-console = Cls- device-address-prefix-fire-alarm = Fir- device-address-prefix-air-alarm = Air- device-address-examine-message = The device's address is {$address}. -#Device net ID names +# Device net ID names device-net-id-private = Private device-net-id-wired = Wired device-net-id-wireless = Wireless diff --git a/Resources/Locale/en-US/job/department-desc.ftl b/Resources/Locale/en-US/job/department-desc.ftl index 194a02d9be..bc1ed8b081 100644 --- a/Resources/Locale/en-US/job/department-desc.ftl +++ b/Resources/Locale/en-US/job/department-desc.ftl @@ -6,6 +6,6 @@ department-Medical-description = Keep the crew healthy. department-Security-description = Keep the peace around the station. department-Science-description = Research new technologies and dangerous artifacts. -#Nyano +# Nyano department-Epistemics-description = Discover what lies beyond the fabric of reality. department-Silicon-description = Follow your laws in service to the humans. diff --git a/Resources/Locale/en-US/revenant/revenant.ftl b/Resources/Locale/en-US/revenant/revenant.ftl index 3c7841b778..1380f73936 100644 --- a/Resources/Locale/en-US/revenant/revenant.ftl +++ b/Resources/Locale/en-US/revenant/revenant.ftl @@ -18,7 +18,7 @@ revenant-soul-finish-harvest = {CAPITALIZE(THE($target))} slumps onto the ground revenant-psionic-power = a spirit power -#UI +# UI revenant-user-interface-title = Ability Shop revenant-user-interface-essence-amount = [color=plum]{$amount}[/color] Stolen Essence diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index 684e981d61..963a91e4e4 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -97,6 +97,31 @@ - type: Alerts - type: TypingIndicator proto: robot + - type: PowerCellSlot + cellSlotId: cell_slot + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellHyper + - type: ContainerContainer + containers: + cell_slot: !type:ContainerSlot + - type: Silicon + batterySlot: cell_slot + entityType: enum.SiliconType.Npc + batteryPowered: true + drainPerSecond: 0.67 + chargeThresholdMid: 0 + chargeThresholdLow: 0 + chargeThresholdCritical: 0.12 + speedModifierThresholds: + 4: 1 + 3: 1 + 2: 1 + 1: 0.20 + 0: 0.00 + - type: SiliconDownOnDead - type: entity parent: MobSiliconBase diff --git a/Resources/Prototypes/Entities/Structures/Power/apc.yml b/Resources/Prototypes/Entities/Structures/Power/apc.yml index e0369bdda7..014ddbe81a 100644 --- a/Resources/Prototypes/Entities/Structures/Power/apc.yml +++ b/Resources/Prototypes/Entities/Structures/Power/apc.yml @@ -185,6 +185,8 @@ - type: Battery maxCharge: 50000 startingCharge: 50000 + - type: BatteryDrinkerSource + maxAmount: 5000 - type: entity parent: BaseAPC @@ -194,6 +196,8 @@ - type: Battery maxCharge: 100000 startingCharge: 100000 + - type: BatteryDrinkerSource + maxAmount: 12000 - type: entity parent: BaseAPC @@ -203,6 +207,8 @@ - type: Battery maxCharge: 150000 startingCharge: 150000 + - type: BatteryDrinkerSource + maxAmount: 18000 - type: entity parent: BaseAPC @@ -212,3 +218,5 @@ - type: Battery maxCharge: 200000 startingCharge: 200000 + - type: BatteryDrinkerSource + maxAmount: 26000 diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/robots.yml b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/robots.yml index 8793f6b02b..bfe821c69c 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/robots.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Mobs/Player/robots.yml @@ -191,16 +191,15 @@ - type: Silicon entityType: enum.SiliconType.Player batteryPowered: true - drainRateMulti: 4 - chargeRateMulti: 6 + drainPerSecond: 15 chargeThresholdMid: 0.60 chargeThresholdLow: 0.30 chargeThresholdCritical: 0 speedModifierThresholds: - 0: 1 - 1: 1 + 4: 1 + 3: 1 2: 0.75 - 3: 0.15 + 1: 0.15 - type: entity parent: PlayerRobotBase diff --git a/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml b/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml index 5e729c2532..24515f1e88 100644 --- a/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml +++ b/Resources/Prototypes/SimpleStation14/Alerts/alerts.yml @@ -1,6 +1,8 @@ - type: alert id: Charge icons: + - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi + state: charge-empty - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi state: charge0 - sprite: /Textures/SimpleStation14/Interface/Alerts/charge.rsi @@ -13,5 +15,5 @@ state: charge4 name: alerts-charge-name description: alerts-charge-desc - minSeverity: 0 + minSeverity: -1 maxSeverity: 4 diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml index 8a7e71b2ad..5012c26623 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -15,16 +15,16 @@ - type: Silicon entityType: enum.SiliconType.Player batteryPowered: true - drainRateMulti: 5 + drainPerSecond: 60 chargeThresholdMid: 0.80 chargeThresholdLow: 0.35 chargeThresholdCritical: 0.10 speedModifierThresholds: - 0: 1 - 1: 1 + 4: 1 + 3: 1 2: 0.80 - 3: 0.45 - 4: 0.00 + 1: 0.45 + 0: 0.00 - type: Carriable - type: BatteryDrinker - type: EncryptionKeyHolder diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 91cce030d4..e6a2618ffe 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -63,17 +63,15 @@ - type: Silicon entityType: enum.SiliconType.Player batteryPowered: false # Needs to also have a battery! - drainRateMulti: 4.5 - chargeRateMulti: 6 chargeThresholdMid: 0.60 chargeThresholdLow: 0.30 chargeThresholdCritical: 0 speedModifierThresholds: - 0: 1 - 1: 1 + 4: 1 + 3: 1 2: 0.80 - 3: 0.45 - 4: 0.00 + 1: 0.45 + 0: 0.00 - type: RadiationReceiver - type: AtmosExposed - type: Temperature From db3d223e6512b5936777de68212a29a35f207c18 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sun, 25 Jun 2023 06:28:24 -0400 Subject: [PATCH 48/60] Several improvements. IPCs and Borgs now beep when drained of battery, battery drinker works with Loc, legs don't clip out of pants, skin color is better than before, IPC now die gracefully (although annoyingly similar to humans) --- .../SiliconEmitSoundOnDrainedComponent.cs | 24 +++++++++++ .../Power/Systems/BatteryDrinkerSystem.cs | 2 +- .../SiliconEmitSoundOnDrainedSystem.cs | 40 ++++++++++++++++++ Content.Shared/Humanoid/SkinColor.cs | 25 ++++------- .../Content/Power/batteryDrinker.ftl | 2 +- .../Content/Silicons/silicons.ftl | 2 + .../Entities/Mobs/Player/ipc.yml | 28 ++++++++++++ .../Entities/Mobs/Player/silicon_base.yml | 4 +- .../Mobs/Species/IPC/parts.rsi/full.png | Bin 2454 -> 2437 bytes .../Mobs/Species/IPC/parts.rsi/l_foot.png | Bin 574 -> 572 bytes .../Mobs/Species/IPC/parts.rsi/l_leg.png | Bin 642 -> 628 bytes .../Mobs/Species/IPC/parts.rsi/r_foot.png | Bin 557 -> 562 bytes .../Mobs/Species/IPC/parts.rsi/r_leg.png | Bin 644 -> 636 bytes 13 files changed, 106 insertions(+), 21 deletions(-) create mode 100644 Content.Server/SimpleStation14/Power/Components/SiliconEmitSoundOnDrainedComponent.cs create mode 100644 Content.Server/SimpleStation14/Power/Systems/SiliconEmitSoundOnDrainedSystem.cs diff --git a/Content.Server/SimpleStation14/Power/Components/SiliconEmitSoundOnDrainedComponent.cs b/Content.Server/SimpleStation14/Power/Components/SiliconEmitSoundOnDrainedComponent.cs new file mode 100644 index 0000000000..58b9ac88ba --- /dev/null +++ b/Content.Server/SimpleStation14/Power/Components/SiliconEmitSoundOnDrainedComponent.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; +using Robust.Shared.Audio; +using Content.Server.Sound.Components; + +namespace Content.Server.SimpleStation14.Silicon; + +/// +/// Applies a to a Silicon when its battery is drained, and removes it when it's not. +/// +[RegisterComponent] +public sealed class SiliconEmitSoundOnDrainedComponent : Component +{ + [DataField("sound"), Required] + public SoundSpecifier Sound = default!; + + [DataField("interval")] + public float Interval = 8f; + + [DataField("playChance")] + public float PlayChance = 1f; + + [DataField("popUp")] + public string? PopUp; +} diff --git a/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs index 3e92f7effe..902a198f4a 100644 --- a/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs +++ b/Content.Server/SimpleStation14/Power/Systems/BatteryDrinkerSystem.cs @@ -43,7 +43,7 @@ private void AddAltVerb(EntityUid uid, BatteryComponent batteryComponent, GetVer AlternativeVerb verb = new() { Act = () => DrinkBattery(uid, args.User, drinkerComp), - Text = "system-battery-drinker-verb-drink", + Text = Loc.GetString("battery-drinker-verb-drink"), Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/smite.svg.192dpi.png")), }; diff --git a/Content.Server/SimpleStation14/Power/Systems/SiliconEmitSoundOnDrainedSystem.cs b/Content.Server/SimpleStation14/Power/Systems/SiliconEmitSoundOnDrainedSystem.cs new file mode 100644 index 0000000000..55ac466229 --- /dev/null +++ b/Content.Server/SimpleStation14/Power/Systems/SiliconEmitSoundOnDrainedSystem.cs @@ -0,0 +1,40 @@ +using Content.Server.SimpleStation14.Silicon.Death; +using Content.Server.Sound.Components; +using Content.Shared.Mobs; +using Content.Shared.SimpleStation14.Silicon.Systems; + +namespace Content.Server.SimpleStation14.Silicon; + +public sealed class EmitSoundOnCritSystem : EntitySystem +{ + public override void Initialize() + { + SubscribeLocalEvent(OnDeath); + SubscribeLocalEvent(OnAlive); + SubscribeLocalEvent(OnStateChange); + } + + private void OnDeath(EntityUid uid, SiliconEmitSoundOnDrainedComponent component, SiliconChargeDeathEvent args) + { + var spamComp = EnsureComp(uid); + + spamComp.Accumulator = 0f; + spamComp.RollInterval = component.Interval; + spamComp.PlayChance = component.PlayChance; + spamComp.PopUp = component.PopUp; + spamComp.Enabled = true; + spamComp.Sound = component.Sound; + } + + private void OnAlive(EntityUid uid, SiliconEmitSoundOnDrainedComponent component, SiliconChargeAliveEvent args) + { + RemComp(uid); // This component is bad and I don't feel like making a janky work around because of it. + // If you give something the EmitSoundOnCritComponent, know that it can't have the SpamEmitSoundComponent, and any other systems that play with it will just be broken. + } + + public void OnStateChange(EntityUid uid, SiliconEmitSoundOnDrainedComponent component, MobStateChangedEvent args) + { + if (args.NewMobState == MobState.Dead) + RemComp(uid); + } +} diff --git a/Content.Shared/Humanoid/SkinColor.cs b/Content.Shared/Humanoid/SkinColor.cs index f4983492c2..cb5f4590ae 100644 --- a/Content.Shared/Humanoid/SkinColor.cs +++ b/Content.Shared/Humanoid/SkinColor.cs @@ -117,9 +117,13 @@ public static bool VerifyHumanSkinTone(Color color) /// Tinted hue color public static Color TintedHues(Color color) { - var newColor = new Color((color.R + 0.5f) / 2, (color.G + 0.5f) / 2, (color.B + 0.5f) / 2, 1); + var hsv = Color.ToHsv(color); + + hsv.Y = Math.Min(hsv.Y, 0.6f); + + hsv.Z = Math.Max(hsv.Z, 0.25f); - return newColor; + return Color.FromHsv(hsv); } /// @@ -129,22 +133,9 @@ public static Color TintedHues(Color color) /// True if valid, false otherwise public static bool VerifyTintedHues(Color color) { - // Tinted hues ensures hue is within 0.75 of neutral. - - color.Deconstruct(out var r, out var g, out var b, out var _); - - var check = true; - - if (r > 0.75 || r < 0.25) - check = false; - - if (g > 0.75 || g < 0.25) - check = false; - - if (b > 0.75 || b < 0.25) - check = false; + var hsv = Color.ToHsv(color); - return check; + return hsv.Y <= 0.6 && hsv.Z >= 0.25; } public static bool VerifySkinColor(HumanoidSkinColor type, Color color) diff --git a/Resources/Locale/en-US/SimpleStation14/Content/Power/batteryDrinker.ftl b/Resources/Locale/en-US/SimpleStation14/Content/Power/batteryDrinker.ftl index 1f6425d943..950b321d40 100644 --- a/Resources/Locale/en-US/SimpleStation14/Content/Power/batteryDrinker.ftl +++ b/Resources/Locale/en-US/SimpleStation14/Content/Power/batteryDrinker.ftl @@ -1,2 +1,2 @@ -battery-drinker-drink = Drain +battery-drinker-verb-drink = Drain battery-drinker-empty = {CAPATALIZE(THE($target))} is already empty! diff --git a/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl b/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl index b6c8c5dc4d..c14066f684 100644 --- a/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl +++ b/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl @@ -1,4 +1,6 @@ silicon-overheating = You feel your circuits overheating! +silicon-crit = Structural integrity critical! +silicon-power-low = Power low! alerts-charge-name = Charge alerts-charge-desk = Your current battery level. diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml index 5012c26623..f770caca8c 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -4,6 +4,34 @@ name: Urist McPositronic description: A positronic brain in a metal body. components: + - type: SiliconEmitSoundOnDrained + sound: "/Audio/Weapons/Guns/EmptyAlarm/smg_empty_alarm.ogg" + interval: 15 + playChance: 1 + popUp: "silicon-power-low" + - type: MobState + allowedStates: + - Alive + - Critical + - Dead + - type: MobThresholds + thresholds: + 0: Alive + 140: Critical + 180: Dead + - type: Destructible + thresholds: + - trigger: + !type:DamageTypeTrigger + damageType: Blunt + damage: 400 + behaviors: + - !type:GibBehavior { } + - type: SlowOnDamage + speedModifierThresholds: + 60: 0.7 + 90: 0.5 + 120: 0.3 - type: SiliconDownOnDead - type: Inventory templateId: ipc diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index e6a2618ffe..de33ee01f4 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -103,7 +103,7 @@ - type: MobState allowedStates: - Alive - - Critical + - Dead - type: MobThresholds thresholds: 0: Alive @@ -220,7 +220,7 @@ radiatedHeat: 800 implicitHeatRegulation: 600 sweatHeatRegulation: 0 - shiveringHeatRegulation: 12000 + shiveringHeatRegulation: 12000 # Overclocking, yo normalBodyTemperature: 280 thermalRegulationTemperatureThreshold: 32 - type: Polymorphable diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/full.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/full.png index 5836d3a57a1d08cb0366263b70bc3e89a701aeeb..7faae4a077ed956b4b542b9fe06cd9fb9e5d4a55 100644 GIT binary patch delta 2379 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 delta 472 zcmV;}0Vn>v1il22Q(P7h6(h7$NN)fD0n155K~#9!?b^Stf-n>Y@ULpze2b1w-FyLO zCpHpISadNyh7%hTi31x`XI{aPmAB}2mfi{CpPSr-OS#wZok>a*`t!7hhN}I3k159t z6AzKGAb$V?5MUy)=<}ude2zTNQB@THcxx?01W^jTRpmtlNs@GX1+LdC(Bp0KY>3W(cN{95 zbKY9pZpHurh)A!__Xeoz`mODJKBKPdQL4f5ctly2ZRZsL6h-0t{MHwij+fOjbQ$>o O0000?s{|J%_X)&-|D$Eo?O&FSzSLV+;Fbn z#nj&p$9ow#8gQTm$=`0)KRN#T>#t8$+iy!UB<;SdxerU00vXx#b#1(*e)-w=LtRsWK#3$S^eoc>SEr+IRf%_Q3iFN&>ee z7EfskI#n^1?X5|HG1Hb<+V#u7eXqDE+sI@K< zZI2`mJ$>UI5_+|3|1n2{(?&P;+%ZxAZzjFv<@#Qo2Y-&m{(2m>AXW8;a`|on=iFHt zL5e}~JUtP6=^kdiEg9#6=M?ILiEk=)(LAXtk zVZr_Pk4vmd*&C)@VraM~_1vnl{T$bQJ&tS38?XHenttJ@j=}u%zSkK#6jV9%Bo9n` j{%5D4osF;RjojZ%DP3!_d?t&QFaUw4tDnm{r-UW|)M)x4 delta 570 zcmeyu(!@F;xL!;^R5jM%Z4?6o6Thd6V@SoVx3f3qeKHVf?O)9`uThtOLZ>eCd4^y! zl?g@*a%|evw{37qIx($trg*|<5wo_O$_5Xf$U95d1=Vf+b^FMb+;ek16!x7ge_P!z zs~omkv@OS9Vuv6DqW}(6&vRzp?wA@2nR|Bg{nU9KWcuAzJd@tGJ+}C_;qTX~zYz=! z0Iw$UQKH&vn)^dvlgY7W?d%igzD%zhBx{6MNn2w9)gTh8=P1 z85$Hg)|6H!y9Vx<%@rFvo0+~4M&6u8dJ(ZB#k^$fqRzuDH(9qjeNcxzg5>WxT-{ZALpgv&E+?K=^Pj)@w+P!Fn5L4q-Fl`E14E+3E@SbE1)YEE z*4N%Y{(NBz8ILNeR-GI&m2_xaJ{w}uQr;OXk;vd$@?2>>y}{&)ZY diff --git a/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_foot.png b/Resources/Textures/SimpleStation14/Mobs/Species/IPC/parts.rsi/r_foot.png index c56a7ce60f8d81bede93a12b2860cb6fbbedcc5c..2389c30aea5458ae633b88839ed9f2b51163d25a 100644 GIT binary patch delta 461 zcmV;;0W$ur1hNE>Q(+hn8VG38KAr#o0l!H^K~#9!?bv6cZ@FmqaLX?9YDYp@-~tJ1n`q zVd0Gc1RwyBt{;C`NPF-5!=fl~xm;XTRZvPnYYhOh*=$}m_%uxczyW}@7D_1qklXDx z{0=b2xTa~4=Q*sk03cIX!PDs^T5Bk!V68=#WiD6*}0La(QtE!UicKeb^x5w4`3X)^|DWNd?;9dTQFLDS z0O#|0GAH|fzYntmy4sW`&OCqs1RwwbrUG!!)0YV_m&p&32mF?y@eCjU0SNH#0Q#Kn zbGidO4AAFvpVJ+HAwU2E5Mc4o0zm*m-U)`rWe5zpGIL9U27MeJD*+n%e;5Kw2Y4z3 zj4|$bJo;fWIqpSL0f4%$gM~zzrr-K)*Cn5+QayVHh_%-F$=7x5>+%xEF;=Tp@RjQ- z%C>=mg+N)BPATQz$Uv55qb5Sem><`oD8hQZez>m>G&+ot_!~a{00000NkvXXu0mjf DN4w5< delta 459 zcmV;+0W|)y1g!*+Q(_hn6(+L%9be-0~-@_F2E(Yg$E=r?h;omr4pf-K>588A>`Pf{p^Q~I3ADKa(TnX z3jqi~00Izzk+2+pu#xgU^uavOalhYPS(cDeLMa6RV!z+Ntnpcv0e}MlYb~Ud03h17 zoqh%wV_efTxLhu<)&hW7!U$fkSD}=GloHljXsuna5J-~5{}f&x08XbcCQeTm$B>F!Z)flCTjd~fY=7})NiF#U=MG)!I(O)r z`vT*OEr%`y{^Z%mFqN})?$oXN4v9&wo{r}H4ytE!6kqTCXvY1HL+}1d1;xhCvp+vi z<~vce(`Ei!{;E6{2L@cI-ga}pmH6?(p35&&7*5pKyb$G+D- z{$2N)FZ_IB*CGSgz#G1eA1iY9Rp$z@tS|Uix99$Q#sd+o0c-6x=`=sDytMR!|K%%n zybKLC=Ql>^2(&F^RLEWP&-qp7>s`w<8*arqWdD6zm3X>r_uc)=pB3$7V3<^|vXNim z^rmwydxKuROkX{lY0|QloQFT`pS?fptGso85LaqsooJ@z{PShX2}UzJUhmp;H!oVh zNi-wSi<7}pt{*6DAaQ5)+qBJ@M_;!8slT=4T!l^F<8$88tGzaSf6r9<>$ktSQ}nGS z%>#cKm=qwWL0(*U{SBe&okDBs7hlWSCsZzWV7J9tDR40D7jl?@eAN2P(7QoF~cmc_@H%D`MzLBC#L7-&(9y1 z5jg!+$n3U$L>`L+11?lQ?dE$k@#UFamtQVn?6{d@=FuLudg@LNk4Y?-Uy3l4NVHk; z9KI);H_tgdbm{6pydcR?b01JcM5R!p2Fnb(2n@Nb3eARw-eIFEw`UuXla0;s5cw^w@F77cnfd#~r7oe!seXHMi-S z>)Ext@4m@x_C4Y3)v0s(L1o-~(*>{jraU-*Ii#uVwtTY8s&p6S*UuS%z|+;wWt~$( F699=={LlaZ From 50a64e7721179e43535e853ae666a1bb02678778 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sun, 25 Jun 2023 06:34:21 -0400 Subject: [PATCH 49/60] Update Content.Server/Station/Systems/StationSpawningSystem.cs --- Content.Server/Station/Systems/StationSpawningSystem.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs index 49ac807fc5..ca504a0627 100644 --- a/Content.Server/Station/Systems/StationSpawningSystem.cs +++ b/Content.Server/Station/Systems/StationSpawningSystem.cs @@ -200,7 +200,6 @@ public void EquipStartingGear(EntityUid entity, StartingGearPrototype startingGe // EncryptionKeyHolderComponent on it, move the keys over, and delete the headset. if (TryComp(entity, out var keyHolderComp)) { - // Resolve SharedContainerSystem var containerMan = EntityManager.System(); var earEquipString = startingGear.GetGear("ears", profile); From 1a19f87faf6a0a21a21943304887bbe5e43eba66 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sun, 25 Jun 2023 06:44:30 -0400 Subject: [PATCH 50/60] Add Parkstation tags to skin colours file. --- Content.Shared/Humanoid/SkinColor.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Content.Shared/Humanoid/SkinColor.cs b/Content.Shared/Humanoid/SkinColor.cs index cb5f4590ae..6e6fc543b1 100644 --- a/Content.Shared/Humanoid/SkinColor.cs +++ b/Content.Shared/Humanoid/SkinColor.cs @@ -117,6 +117,7 @@ public static bool VerifyHumanSkinTone(Color color) /// Tinted hue color public static Color TintedHues(Color color) { + // Parkstation-IPC-Start var hsv = Color.ToHsv(color); hsv.Y = Math.Min(hsv.Y, 0.6f); @@ -124,6 +125,7 @@ public static Color TintedHues(Color color) hsv.Z = Math.Max(hsv.Z, 0.25f); return Color.FromHsv(hsv); + // Parkstation-IPC-End } /// @@ -133,9 +135,11 @@ public static Color TintedHues(Color color) /// True if valid, false otherwise public static bool VerifyTintedHues(Color color) { + // Parkstation-IPC-Start var hsv = Color.ToHsv(color); return hsv.Y <= 0.6 && hsv.Z >= 0.25; + // Parkstation-IPC-End } public static bool VerifySkinColor(HumanoidSkinColor type, Color color) From fdaff09eb54ba772fe328be6aecac3d173a2fbe1 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Sun, 25 Jun 2023 07:19:53 -0400 Subject: [PATCH 51/60] Removed unintended changes. --- Resources/Locale/en-US/devices/device-network.ftl | 4 ++-- Resources/Locale/en-US/job/department-desc.ftl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Resources/Locale/en-US/devices/device-network.ftl b/Resources/Locale/en-US/devices/device-network.ftl index 0dc214da78..9e5f241eb4 100644 --- a/Resources/Locale/en-US/devices/device-network.ftl +++ b/Resources/Locale/en-US/devices/device-network.ftl @@ -24,14 +24,14 @@ device-address-prefix-vent = Vnt- device-address-prefix-scrubber = Scr- device-address-prefix-sensor = Sns- -# PDAs and terminals +#PDAs and terminals device-address-prefix-console = Cls- device-address-prefix-fire-alarm = Fir- device-address-prefix-air-alarm = Air- device-address-examine-message = The device's address is {$address}. -# Device net ID names +#Device net ID names device-net-id-private = Private device-net-id-wired = Wired device-net-id-wireless = Wireless diff --git a/Resources/Locale/en-US/job/department-desc.ftl b/Resources/Locale/en-US/job/department-desc.ftl index bc1ed8b081..194a02d9be 100644 --- a/Resources/Locale/en-US/job/department-desc.ftl +++ b/Resources/Locale/en-US/job/department-desc.ftl @@ -6,6 +6,6 @@ department-Medical-description = Keep the crew healthy. department-Security-description = Keep the peace around the station. department-Science-description = Research new technologies and dangerous artifacts. -# Nyano +#Nyano department-Epistemics-description = Discover what lies beyond the fabric of reality. department-Silicon-description = Follow your laws in service to the humans. From 1702ba84ad885a1cab21381a3bd8bac721dfceae Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Tue, 27 Jun 2023 00:02:18 -0400 Subject: [PATCH 52/60] Adjust tv sprite --- .../ipc_antenna.rsi/ipc_antenna_tv.png | Bin 325 -> 18025 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_tv.png b/Resources/Textures/SimpleStation14/Mobs/Customization/ipc_antenna.rsi/ipc_antenna_tv.png index 1a86f17b5961cf73302cd71ef37723f61690ac82..ae53b4762ed84e8e793ceb2d3dfd52ed1371641d 100644 GIT binary patch literal 18025 zcmeI)cTiJX8UXN{2ZSObUEoQ1V1S4c1O^chkzN+0trP_VtQ0{?kRsBR5{NWedNY74 z5|AR&YY-5mS0(f+h@h~5(jNTbo1LAh7N9_6{oe?&nh*r(p=92=dT3ysc~I#^Z=_u(Ywe!E^hL;|-o0?lzVX zDc1GE@QReFFWd>@UZ_8eAlj-ta6f)6U-!hXS2~a8EV%k#?*XJE3J_?W8ad>>v z(q`{h+>z8l9o6R|HwhUy!+U!g@x;_Wt_|x>Z9S78b}h8(qWpC$X$Jx14AW+>LptV+ z_j)q(tfn6qzwwFBHHqfkaOrfZHQSK~v72#L}G|8^DmR-kt^*BrFaWC}L zaA}E$cE|+?&I3=ytlJJx(TW1qruEsls#E7P~^*^## zd2@jGva~T! zWuAF?x|y(HUV-ZLNPprh3S5}xUGuU*#^SdgxV$13>l6kJq`YB$Ozh&)99-;J09!bw zk;awb{D25Ce)(LCU!?W%Ck3#oq43z{X0-N+8^Kj+hGz?T1=jL3^K&a&<>XjM zj=c9L3*LLMJXRy~upmYo98}<&2Jgl)xrop!S=Xtmzh);fV|oYhPAJ4Lw3Il$ct7e( z^~jP-(SC$z^6m7jnxKTdlMJu$x*6&%NqR9!g_f5?G>!DMI|)yfvR~98SdgXG$jq24 zS)x&od#)A57~9%*yx}P|b0hlqNx6K;(wHr^MOCg!jLPyIWxq2km>wo!^GR_#?#|rl z!nPOV{z5s=|2CDGO(;vK?Zw?gFtt3sLNG2bbnX1|&fBlZJzqHydHso7pU6`WCWZ^i z!OrkH!3?T~UZk(WLuc3MIL7nNZEtiUwx!E!?#vG$1RR{4dz0697C zRX&9|j)s*rA;U_mWeD z@}*LpykvBkKIi+EhY{*hV$oDrWohgCs*;IvWTOqIPlkx$6licJjfvSol&L#-3gI>h zaR&!Rw?U?8RTe3iK)l5l$b18H=6;X$y70WrmS@moF;>T}@(oFrSh8E^G+BqQHEpdV zGgUf2s^XlDU#ln@dqqBO%SZXo7vs}hP+CMW5gXaEU(d^c@fI6h+^OAv zX1KYAiXvpX_l}M%O4^N3JE|HvLl9m4-U0i&5Z%waLCV`|no5*2a1IzXqkfac8U*n` zYKoWi-C-~}x$5fO4DkA9f$r|^oj*!GX#9_^{g$zV=09lsTWTDbv$VAIy9oQm51jBn zOxUl^e({5*CqF3R-^c0c>0x`)oSdA$4NXi;Kzs4u0{_D=hg~1qPkO)j_qN!t&VKRl zT_4N`1b_e#00KY&2mk>f00e*l5C8%|00;m9AOHk_01yBIKmZ5;0U!Vb{%itPJJ}gu z_X7Ocdi%fYXK!Khhpf#XAh*}Up)HagHo~F)_^&tS(DZj3_#U5t000AHX1b_e#00KY&2mk>f00e*l5C8%|00;m9AOHk_01yBIKmZ8*2mvRL ixBRgu(oQ(3N^cy@R|vnA>eN#3u_xMoEAAZ>=@Kwb_a9(qy*N zo8By)a{T7`>eMs&Tmtd?a&O!DUQRr*{Od%cXXdONhALj?KmUn~zCQKM+4Qsdd Date: Sun, 23 Jul 2023 01:21:59 -0400 Subject: [PATCH 53/60] Minor fixes post-merge --- .../RandomBatteryChargeComponent.cs | 6 +++-- .../Structures/Machines/silicon_chargers.yml | 27 +++++++++++-------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs b/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs index 6f5f601675..be79493a17 100644 --- a/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs +++ b/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs @@ -1,3 +1,5 @@ +using System.Numerics; + namespace Content.Server.SimpleStation14.Power.Components; [RegisterComponent] @@ -7,13 +9,13 @@ public sealed class RandomBatteryChargeComponent : Component /// The minimum and maximum max charge the battery can have. /// [DataField("batteryMaxMinMax")] - public Vector2 BatteryMaxMinMax = (0.85f, 1.15f); + public Vector2 BatteryMaxMinMax = new(0.85f, 1.15f); /// /// The minimum and maximum current charge the battery can have. /// [DataField("batteryChargeMinMax")] - public Vector2 BatteryChargeMinMax = (1f, 1f); + public Vector2 BatteryChargeMinMax = new(1f, 1f); /// /// True if the current charge is based on the preexisting current charge, or false if it's based on the max charge. diff --git a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml index 5859f37433..09ba684655 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Structures/Machines/silicon_chargers.yml @@ -14,6 +14,9 @@ - state: borgcharger_closed_unlit shader: unshaded map: ["enum.SiliconChargerVisuals.Lights"] + - type: EntityStorageVisuals + stateDoorOpen: open + stateDoorClosed: closed - type: GenericVisualizer visuals: enum.PowerDeviceVisuals.VisualState: @@ -116,17 +119,19 @@ - type: Appearance - type: Fixtures fixtures: - - shape: !type:PhysShapeAabb - bounds: "-0.35,-0.35,0.35,0.35" - id: "slips" - hard: false - layer: - - SlipLayer - - shape: !type:PhysShapeAabb - bounds: "-0.35,-0.35,0.35,0.35" - density: 10 - mask: - - MachineMask + fix1: + shape: !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" + id: "slips" + hard: false + layer: + - SlipLayer + fix2: + shape: !type:PhysShapeAabb + bounds: "-0.35,-0.35,0.35,0.35" + density: 10 + mask: + - MachineMask - type: StepTrigger - type: SiliconCharger chargeMylti: 150 From d2e503bab886d8d2301b425e48fe135aa75e260c Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:00:52 -0400 Subject: [PATCH 54/60] Review fixes --- .../Power/Components/RandomBatteryChargeComponent.cs | 3 ++- .../Power/Systems/SiliconEmitSoundOnDrainedSystem.cs | 2 +- .../Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs | 2 +- .../Silicon/Charge/Systems/SiliconChargerSystem.cs | 2 +- .../Silicon/Components/SiliconChargerComponent.cs | 2 +- Resources/Locale/en-US/revenant/revenant.ftl | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs b/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs index be79493a17..c13239cbe5 100644 --- a/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs +++ b/Content.Server/SimpleStation14/Power/Components/RandomBatteryChargeComponent.cs @@ -18,7 +18,8 @@ public sealed class RandomBatteryChargeComponent : Component public Vector2 BatteryChargeMinMax = new(1f, 1f); /// - /// True if the current charge is based on the preexisting current charge, or false if it's based on the max charge. + /// False if the randomized charge of the battery should be a multiple of the preexisting current charge of the battery. + /// True if the randomized charge of the battery should be a multiple of the max charge of the battery post max charge randomization. /// [DataField("basedOnMaxCharge")] public bool BasedOnMaxCharge = true; diff --git a/Content.Server/SimpleStation14/Power/Systems/SiliconEmitSoundOnDrainedSystem.cs b/Content.Server/SimpleStation14/Power/Systems/SiliconEmitSoundOnDrainedSystem.cs index 55ac466229..a9a29fed37 100644 --- a/Content.Server/SimpleStation14/Power/Systems/SiliconEmitSoundOnDrainedSystem.cs +++ b/Content.Server/SimpleStation14/Power/Systems/SiliconEmitSoundOnDrainedSystem.cs @@ -29,7 +29,7 @@ private void OnDeath(EntityUid uid, SiliconEmitSoundOnDrainedComponent component private void OnAlive(EntityUid uid, SiliconEmitSoundOnDrainedComponent component, SiliconChargeAliveEvent args) { RemComp(uid); // This component is bad and I don't feel like making a janky work around because of it. - // If you give something the EmitSoundOnCritComponent, know that it can't have the SpamEmitSoundComponent, and any other systems that play with it will just be broken. + // If you give something the SiliconEmitSoundOnDrainedComponent, know that it can't have the SpamEmitSoundComponent, and any other systems that play with it will just be broken. } public void OnStateChange(EntityUid uid, SiliconEmitSoundOnDrainedComponent component, MobStateChangedEvent args) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs index f4abfa392e..0a89f151e7 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Components/BatteryDrinkerSourceComponent.cs @@ -19,7 +19,7 @@ public sealed class BatteryDrinkerSourceComponent : Component public float DrinkSpeedMulti = 1f; /// - /// The sound to play when the APC gets drunk from. + /// The sound to play when the battery gets drunk from. /// Can be null. /// [DataField("drinkSound")] diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index cdb54599c0..fb562b92c2 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -232,7 +232,7 @@ private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconCha private void ChargeBattery(EntityUid entity, BatteryComponent batteryComp, float chargeRate, SiliconChargerComponent chargerComp, EntityUid chargerUid) { - // Do some math so a charger never charges a battery from zero to full in less than 10 seconds, just for the effect of it. + // Do some math so a charger never charges a battery from zero to full in less than the minimum time, just for the effect of it. if (chargerComp.ChargeMulti * 10 > batteryComp.MaxCharge / chargerComp.MinChargeTime) chargeRate /= chargerComp.ChargeMulti * 10 / (batteryComp.MaxCharge / chargerComp.MinChargeTime); diff --git a/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs index 14e3e95674..9dd8649fa8 100644 --- a/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs +++ b/Content.Shared/SimpleStation14/Silicon/Components/SiliconChargerComponent.cs @@ -23,7 +23,7 @@ public sealed class SiliconChargerComponent : Component public TimeSpan WarningTime = TimeSpan.Zero; /// - /// The current parts mutliplier. + /// The current parts multiplier. /// public float PartsChargeMulti = 1.2f; diff --git a/Resources/Locale/en-US/revenant/revenant.ftl b/Resources/Locale/en-US/revenant/revenant.ftl index 1380f73936..3c7841b778 100644 --- a/Resources/Locale/en-US/revenant/revenant.ftl +++ b/Resources/Locale/en-US/revenant/revenant.ftl @@ -18,7 +18,7 @@ revenant-soul-finish-harvest = {CAPITALIZE(THE($target))} slumps onto the ground revenant-psionic-power = a spirit power -# UI +#UI revenant-user-interface-title = Ability Shop revenant-user-interface-essence-amount = [color=plum]{$amount}[/color] Stolen Essence From 624c2b99760b773cd7dd20e3aa46f265177dcd9c Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:22:39 -0400 Subject: [PATCH 55/60] Batteries should now blow up again --- .../Charge/Systems/SiliconChargerSystem.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs index fb562b92c2..6ba644d268 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargerSystem.cs @@ -147,8 +147,16 @@ private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconCha chargeRate *= chargerComp.PartsChargeMulti; + var entitiesToChargeCount = entitiesToCharge.Count; + + foreach (var (entityToCharge, batteryComp) in entitiesToCharge.ToList()) + { + if (batteryComp != null && batteryComp.CurrentCharge >= batteryComp.MaxCharge) + entitiesToChargeCount--; // Remove any full batteries from the count, so they don't impact charge rate. + } + // Now we charge the entities we found. - chargeRate /= entitiesToCharge.Count; + chargeRate /= entitiesToChargeCount; foreach (var (entityToCharge, batteryComp) in entitiesToCharge.ToList()) { @@ -166,16 +174,14 @@ private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconCha // If the given entity is a silicon, charge their respective battery. if (_silicon.TryGetSiliconBattery(entity, out var siliconBatteryComp, out var siliconBatteryUid)) { - if (siliconBatteryComp.CurrentCharge < siliconBatteryComp.MaxCharge) - entitiesToCharge.Add((siliconBatteryUid, siliconBatteryComp)); + entitiesToCharge.Add((siliconBatteryUid, siliconBatteryComp)); } // Or if the given entity has a battery, charge it. else if (!HasComp(entity) && // Should probably be charged by the entity holding it. Might be too small to be safe. TryComp(entity, out var batteryComp)) { - if (batteryComp.CurrentCharge < batteryComp.MaxCharge) - entitiesToCharge.Add((entity, batteryComp)); + entitiesToCharge.Add((entity, batteryComp)); } // Or if the given entity contains a battery, charge it. @@ -184,8 +190,7 @@ private void HandleChargingEntity(EntityUid entity, float chargeRate, SiliconCha _itemSlots.TryGetSlot(entity, cellSlotComp.CellSlotId, out var slot) && TryComp(slot.Item, out var cellBattComp)) { - if (cellBattComp.CurrentCharge < cellBattComp.MaxCharge) - entitiesToCharge.Add((slot.Item.Value, cellBattComp)); + entitiesToCharge.Add((slot.Item.Value, cellBattComp)); } // Or if the given entity is fleshy, burn the fucker. From 989d315102e7062592807e79e690077e392fd398 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 24 Jul 2023 20:12:59 -0400 Subject: [PATCH 56/60] Addressed remaining review issues. --- .../SimpleStation14/Entities/Mobs/Player/ipc.yml | 4 ++++ .../Entities/Mobs/Player/silicon_base.yml | 5 +++-- Resources/Prototypes/SimpleStation14/Species/ipc.yml | 11 ++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml index f770caca8c..f129e703d1 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/ipc.yml @@ -19,6 +19,8 @@ 0: Alive 140: Critical 180: Dead + - type: TypingIndicator + proto: robot - type: Destructible thresholds: - trigger: @@ -35,6 +37,8 @@ - type: SiliconDownOnDead - type: Inventory templateId: ipc + - type: EyeProtection + protectionTime: 12 - type: Battery maxCharge: 150000 - type: RandomBatteryCharge diff --git a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml index 1c0d04cc15..703db6b958 100644 --- a/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml +++ b/Resources/Prototypes/SimpleStation14/Entities/Mobs/Player/silicon_base.yml @@ -19,7 +19,7 @@ - type: Clickable - type: Damageable damageContainer: Inorganic - # - type: Bloodstream # There's a chance they won't want this. + # - type: Bloodstream # This is left commented out because it's not necessary for a robot, but you may want it. # bloodReagent: MotorOil # bloodlossDamage: # types: @@ -34,7 +34,6 @@ fixtures: fix1: shape: - # Circles, cuz rotation of rectangles looks very bad !type:PhysShapeCircle radius: 0.35 density: 50 @@ -60,6 +59,8 @@ # safe: false - type: StandingState - type: Alerts + # - type: EyeProtection # You'll want this if your robot can't wear glasses, like an IPC. + # protectionTime: 12 - type: Silicon entityType: enum.SiliconType.Player batteryPowered: false # Needs to also have a battery! diff --git a/Resources/Prototypes/SimpleStation14/Species/ipc.yml b/Resources/Prototypes/SimpleStation14/Species/ipc.yml index 9361552aac..1a08f855be 100644 --- a/Resources/Prototypes/SimpleStation14/Species/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Species/ipc.yml @@ -7,6 +7,11 @@ markingLimits: MobIPCMarkingLimits dollPrototype: MobIPCDummy skinColoration: TintedHues + minAge: 1 + maxAge: 240 + oldAge: 50 + youngAge: 50 + sexes: - Unsexed @@ -36,13 +41,13 @@ id: MobIPCMarkingLimits points: Chest: - points: 1 + points: 0 required: false Legs: - points: 2 + points: 0 required: false Arms: - points: 2 + points: 0 required: false - type: humanoidBaseSprite From 93df8cea174d09ab9ec1a8ec5698a03ca666a5c7 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Mon, 24 Jul 2023 20:14:35 -0400 Subject: [PATCH 57/60] Missing FTL fix? --- .../Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl b/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl index c14066f684..4e4d1eea8f 100644 --- a/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl +++ b/Resources/Locale/en-US/SimpleStation14/Content/Silicons/silicons.ftl @@ -3,4 +3,4 @@ silicon-crit = Structural integrity critical! silicon-power-low = Power low! alerts-charge-name = Charge -alerts-charge-desk = Your current battery level. +alerts-charge-desc = Your current battery level. From b897bd2e0af6f3043e56686cf0df252d5c49611b Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Tue, 25 Jul 2023 17:10:55 -0400 Subject: [PATCH 58/60] Removed unneeded sleep change, added timer for coming back to life --- .../Components/SiliconDownOnDeadComponent.cs | 18 +++++++++++ .../Systems/SiliconChargeDeathSystem.cs | 30 +++++++++++++++++-- .../Charge/Systems/SiliconChargeSystem.cs | 1 - 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs b/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs index 434a4f6df2..d5410b14ba 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Components/SiliconDownOnDeadComponent.cs @@ -1,3 +1,5 @@ +using System.Threading; + namespace Content.Server.SimpleStation14.Silicon.Death; /// @@ -9,6 +11,22 @@ namespace Content.Server.SimpleStation14.Silicon.Death; [RegisterComponent] public sealed class SiliconDownOnDeadComponent : Component { + /// + /// Cancellation token for the silicon's wake timer. + /// + public CancellationTokenSource? WakeToken { get; set; } + + /// + /// The time it will take for a Silicon to "wake up" after leaving the Dead state, in seconds. + /// + /// + /// If not zero, the Silicon will not actually come back to life until after this much time has passed. + /// This can prevent 'flickering' between the two states. + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("deadBuffer")] + public float DeadBuffer { get; set; } = 2.5f; + /// /// Is this Silicon currently dead? /// diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs index 37c6fe09f7..78f37c0919 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeDeathSystem.cs @@ -4,6 +4,8 @@ using Content.Shared.Bed.Sleep; using Content.Server.Sound.Components; using Content.Server.SimpleStation14.Silicon.Charge; +using System.Threading; +using Timer = Robust.Shared.Timing.Timer; namespace Content.Server.SimpleStation14.Silicon.Death; @@ -23,10 +25,35 @@ private void OnSiliconChargeStateUpdate(EntityUid uid, SiliconDownOnDeadComponen { _silicon.TryGetSiliconBattery(uid, out var batteryComp, out var batteryUid); + if (args.ChargeState == ChargeState.Dead && siliconDeadComp.Dead) + { + siliconDeadComp.WakeToken?.Cancel(); + return; + } + if (args.ChargeState == ChargeState.Dead && !siliconDeadComp.Dead) SiliconDead(uid, siliconDeadComp, batteryComp, batteryUid); else if (args.ChargeState != ChargeState.Dead && siliconDeadComp.Dead) - SiliconUnDead(uid, siliconDeadComp, batteryComp, batteryUid); + { + if (siliconDeadComp.DeadBuffer > 0) + { + siliconDeadComp.WakeToken?.Cancel(); // This should never matter, but better safe than loose timers. + + var wakeToken = new CancellationTokenSource(); + siliconDeadComp.WakeToken = wakeToken; + + // If battery is dead, wait the dead buffer time and then wake it up. + Timer.Spawn(TimeSpan.FromSeconds(siliconDeadComp.DeadBuffer), () => + { + if (wakeToken.IsCancellationRequested) + return; + + SiliconUnDead(uid, siliconDeadComp, batteryComp, batteryUid); + }, wakeToken.Token); + } + else + SiliconUnDead(uid, siliconDeadComp, batteryComp, batteryUid); + } } private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadComp, BatteryComponent? batteryComp, EntityUid batteryUid) @@ -38,7 +65,6 @@ private void SiliconDead(EntityUid uid, SiliconDownOnDeadComponent siliconDeadCo return; EntityManager.EnsureComponent(uid); - RemComp(uid); // This is also fucking stupid, I once again hate the sleeping system. EntityManager.EnsureComponent(uid); siliconDeadComp.Dead = true; diff --git a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs index c0aac19c47..de72042425 100644 --- a/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs +++ b/Content.Server/SimpleStation14/Silicon/Charge/Systems/SiliconChargeSystem.cs @@ -16,7 +16,6 @@ using Robust.Shared.Timing; using Content.Shared.SimpleStation14.CCVar; using Robust.Shared.Configuration; -using System.Diagnostics; using Robust.Shared.Utility; namespace Content.Server.SimpleStation14.Silicon.Charge; From 8449285cd6a1f44031b78809641af50d6b245bb3 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Wed, 26 Jul 2023 00:52:26 -0400 Subject: [PATCH 59/60] IPCs have names now --- .vscode/settings.json | 3 +- Content.Shared/Humanoid/NamingSystem.cs | 5 + .../Humanoid/Prototypes/SpeciesPrototype.cs | 3 +- Resources/Locale/en-US/species/namepreset.ftl | 3 + .../Datasets/Names/ipc_names.yml | 1107 +++++++++++++++++ .../SimpleStation14/Species/ipc.yml | 5 +- 6 files changed, 1123 insertions(+), 3 deletions(-) create mode 100644 Resources/Prototypes/SimpleStation14/Datasets/Names/ipc_names.yml diff --git a/.vscode/settings.json b/.vscode/settings.json index eed7d291a2..0e0d3ae890 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "omnisharp.analyzeOpenDocumentsOnly": true + "omnisharp.analyzeOpenDocumentsOnly": true, + "dotnet.defaultSolution": "SpaceStation14.sln" } diff --git a/Content.Shared/Humanoid/NamingSystem.cs b/Content.Shared/Humanoid/NamingSystem.cs index ae3a8b3ae1..ee6b525d47 100644 --- a/Content.Shared/Humanoid/NamingSystem.cs +++ b/Content.Shared/Humanoid/NamingSystem.cs @@ -35,6 +35,11 @@ public string GetName(string species, Gender? gender = null) case SpeciesNaming.XnoY: return Loc.GetString("namepreset-x-no-y", ("first", GetFirstName(speciesProto, gender)), ("last", GetLastName(speciesProto))); + // Parkstation-IPC-Start + case SpeciesNaming.FirstDashLast: + return Loc.GetString("namepreset-firstdashlast", + ("first", GetFirstName(speciesProto, gender)), ("last", GetLastName(speciesProto))); + // Parkstation-IPC-End case SpeciesNaming.FirstLast: default: return Loc.GetString("namepreset-firstlast", diff --git a/Content.Shared/Humanoid/Prototypes/SpeciesPrototype.cs b/Content.Shared/Humanoid/Prototypes/SpeciesPrototype.cs index 0ae135773d..688740350e 100644 --- a/Content.Shared/Humanoid/Prototypes/SpeciesPrototype.cs +++ b/Content.Shared/Humanoid/Prototypes/SpeciesPrototype.cs @@ -127,5 +127,6 @@ public enum SpeciesNaming : byte FirstLast, FirstDashFirst, XnoY, - TheFirstofLast + TheFirstofLast, + FirstDashLast, // Parkstation-IPC } diff --git a/Resources/Locale/en-US/species/namepreset.ftl b/Resources/Locale/en-US/species/namepreset.ftl index a52967642e..4fc4b53b55 100644 --- a/Resources/Locale/en-US/species/namepreset.ftl +++ b/Resources/Locale/en-US/species/namepreset.ftl @@ -2,3 +2,6 @@ namepreset-firstlast = {$first} {$last} namepreset-firstdashfirst = {$first1}-{$first2} namepreset-thefirstoflast = The {$first} of {$last} namepreset-x-no-y = {$last}-no-{$first} + +## Parkstation +namepreset-firstdashlast = {$first}-{$last} diff --git a/Resources/Prototypes/SimpleStation14/Datasets/Names/ipc_names.yml b/Resources/Prototypes/SimpleStation14/Datasets/Names/ipc_names.yml new file mode 100644 index 0000000000..76a963dc51 --- /dev/null +++ b/Resources/Prototypes/SimpleStation14/Datasets/Names/ipc_names.yml @@ -0,0 +1,1107 @@ +- type: dataset + id: IpcFirst + values: + - ABEX + - ANCL + - ANTR + - ARMA + - AURA + - BGB + - CBOS + - CDB + - CHOC + - CHRI + - COI + - CRUX + - CYBR + - DRSD + - DUNC + - EBIX + - EXOS + - FIRC + - FIZZ + - FRE + - FXMC + - GIGA + - GOOF + - GRIN + - GUN + - HBL + - HG + - HIU + - HOG + - INC + - JADE + - JJR + - JLLO + - JNLG + - JRD + - JUNO + - KALE + - KANO + - KAZA + - KENT + - KIV + - KOR + - KORA + - KOS + - LUMA + - LUNA + - LYNX + - MET + - MIW + - MNOS + - MRPR + - MSO + - NANO + - NEST + - NEXO + - NOVA + - ORNG + - OSI + - PBU + - PHL + - PKP + - PKR + - PLEX + - PLEXO + - PLIX + - QUES + - QUIN + - QWER + - RIFT + - RR + - RYNO + - RZH + - SINA + - SLI + - STLP + - TKRG + - TRIX + - VERA + - VEXA + - VITA + - VIVE + - VOLT + - WAVE + - WISP + - WJ + - WREN + - XAL + - XENA + - XIS + - XSI + - XYLO + - YAGO + - YPT + - ZACK + - ZARG + - ZEON + - ZOLT + - ZUMA + - ZYLO + - ZYVA + +- type: dataset + id: IpcLast + values: + - 000 + - 001 + - 002 + - 003 + - 004 + - 005 + - 006 + - 007 + - 008 + - 009 + - 010 + - 011 + - 012 + - 013 + - 014 + - 015 + - 016 + - 017 + - 018 + - 019 + - 020 + - 021 + - 022 + - 023 + - 024 + - 025 + - 026 + - 027 + - 028 + - 029 + - 030 + - 031 + - 032 + - 033 + - 034 + - 035 + - 036 + - 037 + - 038 + - 039 + - 040 + - 041 + - 042 + - 043 + - 044 + - 045 + - 046 + - 047 + - 048 + - 049 + - 050 + - 051 + - 052 + - 053 + - 054 + - 055 + - 056 + - 057 + - 058 + - 059 + - 060 + - 061 + - 062 + - 063 + - 064 + - 065 + - 066 + - 067 + - 068 + - 069 + - 070 + - 071 + - 072 + - 073 + - 074 + - 075 + - 076 + - 077 + - 078 + - 079 + - 080 + - 081 + - 082 + - 083 + - 084 + - 085 + - 086 + - 087 + - 088 + - 089 + - 090 + - 091 + - 092 + - 093 + - 094 + - 095 + - 096 + - 097 + - 098 + - 099 + - 100 + - 101 + - 102 + - 103 + - 104 + - 105 + - 106 + - 107 + - 108 + - 109 + - 110 + - 111 + - 112 + - 113 + - 114 + - 115 + - 116 + - 117 + - 118 + - 119 + - 120 + - 121 + - 122 + - 123 + - 124 + - 125 + - 126 + - 127 + - 128 + - 129 + - 130 + - 131 + - 132 + - 133 + - 134 + - 135 + - 136 + - 137 + - 138 + - 139 + - 140 + - 141 + - 142 + - 143 + - 144 + - 145 + - 146 + - 147 + - 148 + - 149 + - 150 + - 151 + - 152 + - 153 + - 154 + - 155 + - 156 + - 157 + - 158 + - 159 + - 160 + - 161 + - 162 + - 163 + - 164 + - 165 + - 166 + - 167 + - 168 + - 169 + - 170 + - 171 + - 172 + - 173 + - 174 + - 175 + - 176 + - 177 + - 178 + - 179 + - 180 + - 181 + - 182 + - 183 + - 184 + - 185 + - 186 + - 187 + - 188 + - 189 + - 190 + - 191 + - 192 + - 193 + - 194 + - 195 + - 196 + - 197 + - 198 + - 199 + - 200 + - 201 + - 202 + - 203 + - 204 + - 205 + - 206 + - 207 + - 208 + - 209 + - 210 + - 211 + - 212 + - 213 + - 214 + - 215 + - 216 + - 217 + - 218 + - 219 + - 220 + - 221 + - 222 + - 223 + - 224 + - 225 + - 226 + - 227 + - 228 + - 229 + - 230 + - 231 + - 232 + - 233 + - 234 + - 235 + - 236 + - 237 + - 238 + - 239 + - 240 + - 241 + - 242 + - 243 + - 244 + - 245 + - 246 + - 247 + - 248 + - 249 + - 250 + - 251 + - 252 + - 253 + - 254 + - 255 + - 256 + - 257 + - 258 + - 259 + - 260 + - 261 + - 262 + - 263 + - 264 + - 265 + - 266 + - 267 + - 268 + - 269 + - 270 + - 271 + - 272 + - 273 + - 274 + - 275 + - 276 + - 277 + - 278 + - 279 + - 280 + - 281 + - 282 + - 283 + - 284 + - 285 + - 286 + - 287 + - 288 + - 289 + - 290 + - 291 + - 292 + - 293 + - 294 + - 295 + - 296 + - 297 + - 298 + - 299 + - 300 + - 301 + - 302 + - 303 + - 304 + - 305 + - 306 + - 307 + - 308 + - 309 + - 310 + - 311 + - 312 + - 313 + - 314 + - 315 + - 316 + - 317 + - 318 + - 319 + - 320 + - 321 + - 322 + - 323 + - 324 + - 325 + - 326 + - 327 + - 328 + - 329 + - 330 + - 331 + - 332 + - 333 + - 334 + - 335 + - 336 + - 337 + - 338 + - 339 + - 340 + - 341 + - 342 + - 343 + - 344 + - 345 + - 346 + - 347 + - 348 + - 349 + - 350 + - 351 + - 352 + - 353 + - 354 + - 355 + - 356 + - 357 + - 358 + - 359 + - 360 + - 361 + - 362 + - 363 + - 364 + - 365 + - 366 + - 367 + - 368 + - 369 + - 370 + - 371 + - 372 + - 373 + - 374 + - 375 + - 376 + - 377 + - 378 + - 379 + - 380 + - 381 + - 382 + - 383 + - 384 + - 385 + - 386 + - 387 + - 388 + - 389 + - 390 + - 391 + - 392 + - 393 + - 394 + - 395 + - 396 + - 397 + - 398 + - 399 + - 400 + - 401 + - 402 + - 403 + - 404 + - 405 + - 406 + - 407 + - 408 + - 409 + - 410 + - 411 + - 412 + - 413 + - 414 + - 415 + - 416 + - 417 + - 418 + - 419 + - 420 + - 421 + - 422 + - 423 + - 424 + - 425 + - 426 + - 427 + - 428 + - 429 + - 430 + - 431 + - 432 + - 433 + - 434 + - 435 + - 436 + - 437 + - 438 + - 439 + - 440 + - 441 + - 442 + - 443 + - 444 + - 445 + - 446 + - 447 + - 448 + - 449 + - 450 + - 451 + - 452 + - 453 + - 454 + - 455 + - 456 + - 457 + - 458 + - 459 + - 460 + - 461 + - 462 + - 463 + - 464 + - 465 + - 466 + - 467 + - 468 + - 469 + - 470 + - 471 + - 472 + - 473 + - 474 + - 475 + - 476 + - 477 + - 478 + - 479 + - 480 + - 481 + - 482 + - 483 + - 484 + - 485 + - 486 + - 487 + - 488 + - 489 + - 490 + - 491 + - 492 + - 493 + - 494 + - 495 + - 496 + - 497 + - 498 + - 499 + - 500 + - 501 + - 502 + - 503 + - 504 + - 505 + - 506 + - 507 + - 508 + - 509 + - 510 + - 511 + - 512 + - 513 + - 514 + - 515 + - 516 + - 517 + - 518 + - 519 + - 520 + - 521 + - 522 + - 523 + - 524 + - 525 + - 526 + - 527 + - 528 + - 529 + - 530 + - 531 + - 532 + - 533 + - 534 + - 535 + - 536 + - 537 + - 538 + - 539 + - 540 + - 541 + - 542 + - 543 + - 544 + - 545 + - 546 + - 547 + - 548 + - 549 + - 550 + - 551 + - 552 + - 553 + - 554 + - 555 + - 556 + - 557 + - 558 + - 559 + - 560 + - 561 + - 562 + - 563 + - 564 + - 565 + - 566 + - 567 + - 568 + - 569 + - 570 + - 571 + - 572 + - 573 + - 574 + - 575 + - 576 + - 577 + - 578 + - 579 + - 580 + - 581 + - 582 + - 583 + - 584 + - 585 + - 586 + - 587 + - 588 + - 589 + - 590 + - 591 + - 592 + - 593 + - 594 + - 595 + - 596 + - 597 + - 598 + - 599 + - 600 + - 601 + - 602 + - 603 + - 604 + - 605 + - 606 + - 607 + - 608 + - 609 + - 610 + - 611 + - 612 + - 613 + - 614 + - 615 + - 616 + - 617 + - 618 + - 619 + - 620 + - 621 + - 622 + - 623 + - 624 + - 625 + - 626 + - 627 + - 628 + - 629 + - 630 + - 631 + - 632 + - 633 + - 634 + - 635 + - 636 + - 637 + - 638 + - 639 + - 640 + - 641 + - 642 + - 643 + - 644 + - 645 + - 646 + - 647 + - 648 + - 649 + - 650 + - 651 + - 652 + - 653 + - 654 + - 655 + - 656 + - 657 + - 658 + - 659 + - 660 + - 661 + - 662 + - 663 + - 664 + - 665 + - 666 + - 667 + - 668 + - 669 + - 670 + - 671 + - 672 + - 673 + - 674 + - 675 + - 676 + - 677 + - 678 + - 679 + - 680 + - 681 + - 682 + - 683 + - 684 + - 685 + - 686 + - 687 + - 688 + - 689 + - 690 + - 691 + - 692 + - 693 + - 694 + - 695 + - 696 + - 697 + - 698 + - 699 + - 700 + - 701 + - 702 + - 703 + - 704 + - 705 + - 706 + - 707 + - 708 + - 709 + - 710 + - 711 + - 712 + - 713 + - 714 + - 715 + - 716 + - 717 + - 718 + - 719 + - 720 + - 721 + - 722 + - 723 + - 724 + - 725 + - 726 + - 727 + - 728 + - 729 + - 730 + - 731 + - 732 + - 733 + - 734 + - 735 + - 736 + - 737 + - 738 + - 739 + - 740 + - 741 + - 742 + - 743 + - 744 + - 745 + - 746 + - 747 + - 748 + - 749 + - 750 + - 751 + - 752 + - 753 + - 754 + - 755 + - 756 + - 757 + - 758 + - 759 + - 760 + - 761 + - 762 + - 763 + - 764 + - 765 + - 766 + - 767 + - 768 + - 769 + - 770 + - 771 + - 772 + - 773 + - 774 + - 775 + - 776 + - 777 + - 778 + - 779 + - 780 + - 781 + - 782 + - 783 + - 784 + - 785 + - 786 + - 787 + - 788 + - 789 + - 790 + - 791 + - 792 + - 793 + - 794 + - 795 + - 796 + - 797 + - 798 + - 799 + - 800 + - 801 + - 802 + - 803 + - 804 + - 805 + - 806 + - 807 + - 808 + - 809 + - 810 + - 811 + - 812 + - 813 + - 814 + - 815 + - 816 + - 817 + - 818 + - 819 + - 820 + - 821 + - 822 + - 823 + - 824 + - 825 + - 826 + - 827 + - 828 + - 829 + - 830 + - 831 + - 832 + - 833 + - 834 + - 835 + - 836 + - 837 + - 838 + - 839 + - 840 + - 841 + - 842 + - 843 + - 844 + - 845 + - 846 + - 847 + - 848 + - 849 + - 850 + - 851 + - 852 + - 853 + - 854 + - 855 + - 856 + - 857 + - 858 + - 859 + - 860 + - 861 + - 862 + - 863 + - 864 + - 865 + - 866 + - 867 + - 868 + - 869 + - 870 + - 871 + - 872 + - 873 + - 874 + - 875 + - 876 + - 877 + - 878 + - 879 + - 880 + - 881 + - 882 + - 883 + - 884 + - 885 + - 886 + - 887 + - 888 + - 889 + - 890 + - 891 + - 892 + - 893 + - 894 + - 895 + - 896 + - 897 + - 898 + - 899 + - 900 + - 901 + - 902 + - 903 + - 904 + - 905 + - 906 + - 907 + - 908 + - 909 + - 910 + - 911 + - 912 + - 913 + - 914 + - 915 + - 916 + - 917 + - 918 + - 919 + - 920 + - 921 + - 922 + - 923 + - 924 + - 925 + - 926 + - 927 + - 928 + - 929 + - 930 + - 931 + - 932 + - 933 + - 934 + - 935 + - 936 + - 937 + - 938 + - 939 + - 940 + - 941 + - 942 + - 943 + - 944 + - 945 + - 946 + - 947 + - 948 + - 949 + - 950 + - 951 + - 952 + - 953 + - 954 + - 955 + - 956 + - 957 + - 958 + - 959 + - 960 + - 961 + - 962 + - 963 + - 964 + - 965 + - 966 + - 967 + - 968 + - 969 + - 970 + - 971 + - 972 + - 973 + - 974 + - 975 + - 976 + - 977 + - 978 + - 979 + - 980 + - 981 + - 982 + - 983 + - 984 + - 985 + - 986 + - 987 + - 988 + - 989 + - 990 + - 991 + - 992 + - 993 + - 994 + - 995 + - 996 + - 997 + - 998 + - 999 diff --git a/Resources/Prototypes/SimpleStation14/Species/ipc.yml b/Resources/Prototypes/SimpleStation14/Species/ipc.yml index 1a08f855be..46a8ed1758 100644 --- a/Resources/Prototypes/SimpleStation14/Species/ipc.yml +++ b/Resources/Prototypes/SimpleStation14/Species/ipc.yml @@ -11,7 +11,10 @@ maxAge: 240 oldAge: 50 youngAge: 50 - + maleFirstNames: IpcFirst + femaleFirstNames: IpcFirst + lastNames: IpcLast + naming: FirstDashLast sexes: - Unsexed From 73acebcfdc9db6402d780aebf3c9a2c7237f8ab2 Mon Sep 17 00:00:00 2001 From: Pspritechologist <81725545+Pspritechologist@users.noreply.github.com> Date: Thu, 27 Jul 2023 00:07:57 -0400 Subject: [PATCH 60/60] Removed vscode file --- .vscode/settings.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0e0d3ae890..eed7d291a2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,3 @@ { - "omnisharp.analyzeOpenDocumentsOnly": true, - "dotnet.defaultSolution": "SpaceStation14.sln" + "omnisharp.analyzeOpenDocumentsOnly": true }