diff --git a/Content.Client/Doors/DoorSystem.cs b/Content.Client/Doors/DoorSystem.cs index 41680e4619..c4b88346de 100644 --- a/Content.Client/Doors/DoorSystem.cs +++ b/Content.Client/Doors/DoorSystem.cs @@ -111,11 +111,11 @@ public sealed class DoorSystem : SharedDoorSystem } break; case DoorState.Opening: - if (animPlayer != null && comp.OpeningAnimation != default) + if (animPlayer != null && comp.OpeningAnimationTime != 0.0) _animationSystem.Play(uid, animPlayer, (Animation)comp.OpeningAnimation, DoorComponent.AnimationKey); break; case DoorState.Closing: - if (animPlayer != null && comp.ClosingAnimation != default && comp.CurrentlyCrushing.Count == 0) + if (animPlayer != null && comp.ClosingAnimationTime != 0.0 && comp.CurrentlyCrushing.Count == 0) _animationSystem.Play(uid, animPlayer, (Animation)comp.ClosingAnimation, DoorComponent.AnimationKey); break; case DoorState.Denying: diff --git a/Content.Server/Climbing/ClimbSystem.cs b/Content.Server/Climbing/ClimbSystem.cs index af634976cb..8361cda62f 100644 --- a/Content.Server/Climbing/ClimbSystem.cs +++ b/Content.Server/Climbing/ClimbSystem.cs @@ -20,6 +20,7 @@ using Content.Shared.Physics; using Content.Shared.Popups; using Content.Shared.Verbs; using JetBrains.Annotations; +using Robust.Server.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.Physics; using Robust.Shared.Physics.Collision.Shapes; @@ -35,6 +36,7 @@ namespace Content.Server.Climbing; public sealed class ClimbSystem : SharedClimbSystem { [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; + [Dependency] private readonly AudioSystem _audio = default!; [Dependency] private readonly BodySystem _bodySystem = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; @@ -133,6 +135,7 @@ public sealed class ClimbSystem : SharedClimbSystem BreakOnDamage = true }; + _audio.PlayPvs(comp.StartClimbSound, climbable); _doAfterSystem.TryStartDoAfter(args, out id); return true; } @@ -148,17 +151,21 @@ public sealed class ClimbSystem : SharedClimbSystem } private void Climb(EntityUid uid, EntityUid user, EntityUid instigator, EntityUid climbable, bool silent = false, ClimbingComponent? climbing = null, - PhysicsComponent? physics = null, FixturesComponent? fixtures = null) + PhysicsComponent? physics = null, FixturesComponent? fixtures = null, ClimbableComponent? comp = null) { if (!Resolve(uid, ref climbing, ref physics, ref fixtures, false)) return; + if (!Resolve(climbable, ref comp)) + return; + if (!ReplaceFixtures(climbing, fixtures)) return; climbing.IsClimbing = true; Dirty(climbing); + _audio.PlayPvs(comp.FinishClimbSound, climbable); MoveEntityToward(uid, climbable, physics, climbing); // we may potentially need additional logic since we're forcing a player onto a climbable // there's also the cases where the user might collide with the person they are forcing onto the climbable that i haven't accounted for diff --git a/Content.Shared/Climbing/ClimbableComponent.cs b/Content.Shared/Climbing/ClimbableComponent.cs index f4859467b9..60f2cad9b9 100644 --- a/Content.Shared/Climbing/ClimbableComponent.cs +++ b/Content.Shared/Climbing/ClimbableComponent.cs @@ -19,5 +19,17 @@ namespace Content.Shared.Climbing /// [DataField("delay")] public float ClimbDelay = 0.8f; + + /// + /// Sound to be played when a climb is started. + /// + [DataField("startClimbSound")] + public SoundSpecifier? StartClimbSound = null; + + /// + /// Sound to be played when a climb finishes. + /// + [DataField("finishClimbSound")] + public SoundSpecifier? FinishClimbSound = null; } } diff --git a/Resources/Audio/Effects/attributions.yml b/Resources/Audio/Effects/attributions.yml index 0d5702171a..85e898997d 100644 --- a/Resources/Audio/Effects/attributions.yml +++ b/Resources/Audio/Effects/attributions.yml @@ -41,4 +41,9 @@ - files: ["hallelujah.ogg"] license: "CC-BY-SA-3.0" copyright: "Composer: Georg Friedrich Händel; Performed by: MIT Concert Choir; Directed by William C. Cutter; + cropped and mixed from stereo to mono" - source: "https://en.wikipedia.org/wiki/File:Handel_-_messiah_-_44_hallelujah.ogg" \ No newline at end of file + source: "https://en.wikipedia.org/wiki/File:Handel_-_messiah_-_44_hallelujah.ogg" + +- files: ["fence_rattle1.ogg", "fence_rattle2.ogg", "fence_rattle3.ogg"] + license: "CC0-1.0" + copyright: "Taken from MWsfx via freesound.org and cropped + mixed from stereo to mono." + source: "https://freesound.org/people/MWsfx/sounds/575388/" \ No newline at end of file diff --git a/Resources/Audio/Effects/fence_rattle1.ogg b/Resources/Audio/Effects/fence_rattle1.ogg new file mode 100644 index 0000000000..72cec176f8 Binary files /dev/null and b/Resources/Audio/Effects/fence_rattle1.ogg differ diff --git a/Resources/Audio/Effects/fence_rattle2.ogg b/Resources/Audio/Effects/fence_rattle2.ogg new file mode 100644 index 0000000000..f09b2fe5a0 Binary files /dev/null and b/Resources/Audio/Effects/fence_rattle2.ogg differ diff --git a/Resources/Audio/Effects/fence_rattle3.ogg b/Resources/Audio/Effects/fence_rattle3.ogg new file mode 100644 index 0000000000..8d0d963f9f Binary files /dev/null and b/Resources/Audio/Effects/fence_rattle3.ogg differ diff --git a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl index e7f38047cc..9c6324f39e 100644 --- a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl +++ b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl @@ -58,6 +58,10 @@ petting-failure-medibot = You reach out to pet {THE($target)}, but {POSS-ADJ($ta # Shown when knocking on a window comp-window-knock = *knock knock* +## Rattling fences + +fence-rattle-success = *rattle* + ## Hugging players hugging-success-generic = You hug {THE($target)}. diff --git a/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml b/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml new file mode 100644 index 0000000000..583ea2ebb2 --- /dev/null +++ b/Resources/Prototypes/Entities/Structures/Walls/fence_metal.yml @@ -0,0 +1,327 @@ +- type: entity + parent: BaseStructure + id: BaseFenceMetal + name: chain link fence + description: A metal piece of fencing cordoning off something likely very important. + abstract: true + components: + - type: MeleeSound + soundGroups: + Brute: + path: + "/Audio/Weapons/grille_hit.ogg" + - type: Tag + tags: + - RCDDeconstructWhitelist + - type: Sprite + sprite: Structures/Walls/fence.rsi + drawdepth: WallTops + - type: Physics + bodyType: Static + - type: Transform + anchored: true + - type: Damageable + damageContainer: Inorganic + damageModifierSet: FlimsyMetallic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/metalbreak.ogg + - !type:SpawnEntitiesBehavior + spawn: + PartRodMetal1: + min: 3 + max: 5 + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: Climbable + delay: 5.0 + startClimbSound: + collection: FenceRattle + finishClimbSound: + collection: FenceRattle + - type: PowerConsumer + showInMonitor: false + - type: Electrified + requirePower: true + noWindowInTile: true + highVoltageNode: high + mediumVoltageNode: medium + lowVoltageNode: low + - type: NodeContainer + nodes: + high: + !type:CableDeviceNode + nodeGroupID: HVPower + medium: + !type:CableDeviceNode + nodeGroupID: MVPower + low: + !type:CableDeviceNode + nodeGroupID: Apc + - type: Appearance + - type: GenericVisualizer + visuals: + enum.ElectrifiedVisuals.IsPowered: + enum.ElectrifiedLayers.Powered: + True: { visible: True } + False: { visible: False } + - type: AnimationPlayer + +- type: entity + parent: BaseFenceMetal + id: FenceMetalBroken + name: broken chain link fence + description: Someone got real mad at an inanimate object. + components: + - type: Sprite + layers: + - state: straight_broken + - state: electrified + sprite: Effects/electricity.rsi + map: ["enum.ElectrifiedLayers.Powered"] + shader: unshaded + visible: false + - type: Physics + canCollide: false + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.10,-0.5,0.10,0.5" + density: 1000 + mask: + - FullTileMask + layer: + - TableLayer + - type: InteractionPopup + interactSuccessString: fence-rattle-success + messagePerceivedByOthers: fence-rattle-success + interactSuccessSound: + collection: FenceRattle + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - trigger: + !type:DamageTrigger + damage: 50 + behaviors: + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/metalbreak.ogg + - !type:SpawnEntitiesBehavior + spawn: + PartRodMetal1: + min: 1 + max: 1 + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: Construction + graph: FenceMetal + node: broken + +- type: entity + parent: BaseFenceMetal + id: FenceMetalStraight + suffix: Straight + components: + - type: Icon + sprite: Structures/Walls/fence.rsi + state: icon_straight + - type: Sprite + layers: + - state: straight + - state: electrified + sprite: Effects/electricity.rsi + map: ["enum.ElectrifiedLayers.Powered"] + shader: unshaded + visible: false + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.10,-0.5,0.10,0.5" + density: 1000 + mask: + - FullTileMask + layer: + - TableLayer + - type: InteractionPopup + interactSuccessString: fence-rattle-success + messagePerceivedByOthers: fence-rattle-success + interactSuccessSound: + collection: FenceRattle + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:PlaySoundBehavior + sound: + path: /Audio/Items/wirecutter.ogg + - !type:SpawnEntitiesBehavior + spawn: + PartRodMetal1: + min: 2 + max: 4 + - !type:ChangeConstructionNodeBehavior + node: broken + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: Construction + graph: FenceMetal + node: straight + +- type: entity + parent: BaseFenceMetal + id: FenceMetalCorner + suffix: Corner + components: + - type: Sprite + layers: + - state: corner + - state: electrified + sprite: Effects/electricity.rsi + map: ["enum.ElectrifiedLayers.Powered"] + shader: unshaded + visible: false + - type: Fixtures + fixtures: + # needs two shapes to properly handle a triangle corner without weirdness + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.1,0.1,0.5" + density: 1000 + mask: + - TableMask + layer: + - TableLayer + fix2: + shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.1,-0.1,0.1" + density: 1000 + mask: + - TableMask + layer: + - TableLayer + - type: InteractionPopup + interactSuccessString: fence-rattle-success + messagePerceivedByOthers: fence-rattle-success + interactSuccessSound: + collection: FenceRattle + - type: Construction + graph: FenceMetal + node: corner + +- type: entity + parent: BaseFenceMetal + id: FenceMetalEnd + suffix: End + components: + - type: Icon + sprite: Structures/Walls/fence.rsi + state: icon_end + - type: Sprite + layers: + - state: end + - state: electrified + sprite: Effects/electricity.rsi + map: ["enum.ElectrifiedLayers.Powered"] + shader: unshaded + visible: false + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.1,-0.5,0.1,0.0" + density: 1000 + mask: + - TableMask + layer: + - TableLayer + - type: InteractionPopup + interactSuccessString: fence-rattle-success + messagePerceivedByOthers: fence-rattle-success + interactSuccessSound: + collection: FenceRattle + - type: Construction + graph: FenceMetal + node: end + +- type: entity + parent: BaseFenceMetal + id: FenceMetalGate + name: chain link fence gate + description: You could use the door instead of vaulting over--if you're a COWARD, that is. + components: + - type: Sprite + layers: + - state: end + map: ["enum.DoorVisualLayers.Base"] + - state: electrified + sprite: Effects/electricity.rsi + map: [ "enum.ElectrifiedLayers.Powered" ] + shader: unshaded + visible: false + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.5,-0.1,0.5,0.1" + density: 1000 + mask: + - TableMask + layer: + - TableLayer + - type: InteractionOutline + - type: Door + openSpriteState: door_opened + closedSpriteState: door_closed + canPry: false + occludes: false + changeAirtight: false + bumpOpen: false + clickOpen: true + canCrush: false + closeTimeOne: 0 + closeTimeTwo: 0 + openTimeOne: 0 + openTimeTwo: 0 + openingAnimationTime: 0 + closingAnimationTime: 0 + openSound: + path: /Audio/Effects/door_open.ogg + closeSound: + path: /Audio/Effects/door_close.ogg + - type: Construction + graph: FenceMetal + node: gate diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/structures/fence_metal.yml b/Resources/Prototypes/Recipes/Construction/Graphs/structures/fence_metal.yml new file mode 100644 index 0000000000..a68e1d50fb --- /dev/null +++ b/Resources/Prototypes/Recipes/Construction/Graphs/structures/fence_metal.yml @@ -0,0 +1,112 @@ +- type: constructionGraph + id: FenceMetal + start: start + graph: + - node: start + actions: + - !type:DeleteEntity { } + edges: + - to: straight + completed: + - !type:SnapToGrid + southRotation: true + steps: + - material: MetalRod + amount: 5 + doAfter: 6 + - to: corner + completed: + - !type:SnapToGrid + southRotation: true + steps: + - material: MetalRod + amount: 5 + doAfter: 6 + - to: end + completed: + - !type:SnapToGrid + southRotation: true + steps: + - material: MetalRod + amount: 5 + doAfter: 6 + - to: gate + completed: + - !type:SnapToGrid + southRotation: true + steps: + - material: MetalRod + amount: 5 + doAfter: 6 + + - node: straight + entity: FenceMetalStraight + edges: + - to: broken + completed: + - !type:SpawnPrototype + prototype: PartRodMetal1 + amount: 1 + steps: + - tool: Welding + doAfter: 4.0 + - tool: Cutting + doAfter: 1.0 + + - node: corner + entity: FenceMetalCorner + edges: + - to: start + completed: + - !type:SpawnPrototype + prototype: PartRodMetal1 + amount: 5 + - !type:DeleteEntity + steps: + - tool: Welding + doAfter: 4.0 + - tool: Cutting + doAfter: 2.0 + + - node: end + entity: FenceMetalEnd + edges: + - to: start + completed: + - !type:SpawnPrototype + prototype: PartRodMetal1 + amount: 5 + - !type:DeleteEntity + steps: + - tool: Welding + doAfter: 4.0 + - tool: Cutting + doAfter: 2.0 + + - node: gate + entity: FenceMetalGate + edges: + - to: start + completed: + - !type:SpawnPrototype + prototype: PartRodMetal1 + amount: 5 + - !type:DeleteEntity + steps: + - tool: Welding + doAfter: 4.0 + - tool: Cutting + doAfter: 2.0 + + - node: broken + entity: FenceMetalBroken + edges: + - to: start + completed: + - !type:SpawnPrototype + prototype: PartRodMetal1 + amount: 1 + - !type:DeleteEntity + steps: + - tool: Cutting + doAfter: 1.0 diff --git a/Resources/Prototypes/Recipes/Construction/structures.yml b/Resources/Prototypes/Recipes/Construction/structures.yml index 595235e220..2b4dbf0415 100644 --- a/Resources/Prototypes/Recipes/Construction/structures.yml +++ b/Resources/Prototypes/Recipes/Construction/structures.yml @@ -627,6 +627,75 @@ conditions: - !type:TileNotBlocked +# Chain link fencing +- type: construction + name: chain link fence + id: FenceMetal + graph: FenceMetal + startNode: start + targetNode: straight + category: construction-category-structures + description: Part of a chain link fence meant to cordon off areas. + icon: + sprite: Structures/Walls/fence.rsi + state: straight + objectType: Structure + placementMode: SnapgridCenter + canBuildInImpassable: false + conditions: + - !type:TileNotBlocked + +- type: construction + name: chain link fence corner + id: FenceMetalCorner + graph: FenceMetal + startNode: start + targetNode: corner + category: construction-category-structures + description: Part of a chain link fence meant to cordon off areas. + icon: + sprite: Structures/Walls/fence.rsi + state: corner + objectType: Structure + placementMode: SnapgridCenter + canBuildInImpassable: false + conditions: + - !type:TileNotBlocked + +- type: construction + name: chain link fence end-piece + id: FenceMetalEnd + graph: FenceMetal + startNode: start + targetNode: end + category: construction-category-structures + description: Part of a chain link fence meant to cordon off areas. + icon: + sprite: Structures/Walls/fence.rsi + state: end + objectType: Structure + placementMode: SnapgridCenter + canBuildInImpassable: false + conditions: + - !type:TileNotBlocked + +- type: construction + name: chain link fence gate + id: FenceMetalGate + graph: FenceMetal + startNode: start + targetNode: gate + category: construction-category-structures + description: An easy way to get through a chain link fence. + icon: + sprite: Structures/Walls/fence.rsi + state: door_closed + objectType: Structure + placementMode: SnapgridCenter + canBuildInImpassable: false + conditions: + - !type:TileNotBlocked + - type: construction name: airlock id: Airlock diff --git a/Resources/Prototypes/SoundCollections/fence_rattle.yml b/Resources/Prototypes/SoundCollections/fence_rattle.yml new file mode 100644 index 0000000000..f50dd33bf1 --- /dev/null +++ b/Resources/Prototypes/SoundCollections/fence_rattle.yml @@ -0,0 +1,6 @@ +- type: soundCollection + id: FenceRattle + files: + - /Audio/Effects/fence_rattle1.ogg + - /Audio/Effects/fence_rattle2.ogg + - /Audio/Effects/fence_rattle3.ogg diff --git a/Resources/Textures/Structures/Walls/fence.rsi/corner.png b/Resources/Textures/Structures/Walls/fence.rsi/corner.png new file mode 100644 index 0000000000..bf793f5d10 Binary files /dev/null and b/Resources/Textures/Structures/Walls/fence.rsi/corner.png differ diff --git a/Resources/Textures/Structures/Walls/fence.rsi/door_closed.png b/Resources/Textures/Structures/Walls/fence.rsi/door_closed.png new file mode 100644 index 0000000000..52270ef775 Binary files /dev/null and b/Resources/Textures/Structures/Walls/fence.rsi/door_closed.png differ diff --git a/Resources/Textures/Structures/Walls/fence.rsi/door_opened.png b/Resources/Textures/Structures/Walls/fence.rsi/door_opened.png new file mode 100644 index 0000000000..77ecdbc949 Binary files /dev/null and b/Resources/Textures/Structures/Walls/fence.rsi/door_opened.png differ diff --git a/Resources/Textures/Structures/Walls/fence.rsi/end.png b/Resources/Textures/Structures/Walls/fence.rsi/end.png new file mode 100644 index 0000000000..9ba2d74a22 Binary files /dev/null and b/Resources/Textures/Structures/Walls/fence.rsi/end.png differ diff --git a/Resources/Textures/Structures/Walls/fence.rsi/icon_end.png b/Resources/Textures/Structures/Walls/fence.rsi/icon_end.png new file mode 100644 index 0000000000..f993734b9f Binary files /dev/null and b/Resources/Textures/Structures/Walls/fence.rsi/icon_end.png differ diff --git a/Resources/Textures/Structures/Walls/fence.rsi/icon_straight.png b/Resources/Textures/Structures/Walls/fence.rsi/icon_straight.png new file mode 100644 index 0000000000..ce57105979 Binary files /dev/null and b/Resources/Textures/Structures/Walls/fence.rsi/icon_straight.png differ diff --git a/Resources/Textures/Structures/Walls/fence.rsi/meta.json b/Resources/Textures/Structures/Walls/fence.rsi/meta.json new file mode 100644 index 0000000000..f8d54149ee --- /dev/null +++ b/Resources/Textures/Structures/Walls/fence.rsi/meta.json @@ -0,0 +1,41 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "tgstation at bcdd834d17c8c6b20ba53cb270b695ca884fec98", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon_straight" + }, + { + "name": "icon_end" + }, + { + "name": "straight", + "directions": 4 + }, + { + "name": "end", + "directions": 4 + }, + { + "name": "corner", + "directions": 4 + }, + { + "name": "door_closed", + "directions": 4 + }, + { + "name": "door_opened", + "directions": 4 + }, + { + "name": "straight_broken", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Structures/Walls/fence.rsi/straight.png b/Resources/Textures/Structures/Walls/fence.rsi/straight.png new file mode 100644 index 0000000000..116efdb43b Binary files /dev/null and b/Resources/Textures/Structures/Walls/fence.rsi/straight.png differ diff --git a/Resources/Textures/Structures/Walls/fence.rsi/straight_broken.png b/Resources/Textures/Structures/Walls/fence.rsi/straight_broken.png new file mode 100644 index 0000000000..7b2c9e1d68 Binary files /dev/null and b/Resources/Textures/Structures/Walls/fence.rsi/straight_broken.png differ