diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index 11f96b3c48..5c3711fe19 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -308,6 +308,7 @@ namespace Content.Client.Entry "RandomArtifactSprite", "EnergySword", "DoorRemote", + "InteractionPopup", }; } } diff --git a/Content.Client/Window/WindowComponent.cs b/Content.Client/Window/WindowComponent.cs deleted file mode 100644 index fdf936629b..0000000000 --- a/Content.Client/Window/WindowComponent.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Content.Shared.Window; -using Robust.Shared.GameObjects; - -namespace Content.Client.Window -{ - [RegisterComponent] - [ComponentReference(typeof(SharedWindowComponent))] - public class WindowComponent : SharedWindowComponent - { - } -} diff --git a/Content.Server/Electrocution/ElectrocutionSystem.cs b/Content.Server/Electrocution/ElectrocutionSystem.cs index a756043223..9f21653f46 100644 --- a/Content.Server/Electrocution/ElectrocutionSystem.cs +++ b/Content.Server/Electrocution/ElectrocutionSystem.cs @@ -8,7 +8,6 @@ using Content.Server.NodeContainer.Nodes; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Server.Power.NodeGroups; -using Content.Server.Window; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.Database; @@ -21,6 +20,7 @@ using Content.Shared.Pulling.Components; using Content.Shared.Speech.EntitySystems; using Content.Shared.StatusEffect; using Content.Shared.Stunnable; +using Content.Shared.Tag; using Content.Shared.Weapons.Melee; using Robust.Shared.GameObjects; using Robust.Shared.IoC; @@ -166,12 +166,14 @@ namespace Content.Server.Electrocution if (!electrified.Enabled) return false; + var tagSystem = EntitySystem.Get(); + if (electrified.NoWindowInTile) { foreach (var entity in transform.Coordinates.GetEntitiesInTile( LookupFlags.Approximate | LookupFlags.IncludeAnchored, _entityLookup)) { - if (EntityManager.HasComponent(entity)) + if (tagSystem.HasTag(entity, "Window")) return false; } } diff --git a/Content.Server/Interaction/Components/InteractionPopupComponent.cs b/Content.Server/Interaction/Components/InteractionPopupComponent.cs new file mode 100644 index 0000000000..2df01a8641 --- /dev/null +++ b/Content.Server/Interaction/Components/InteractionPopupComponent.cs @@ -0,0 +1,67 @@ +using Content.Shared.Sound; + +namespace Content.Server.Interaction.Components; + +[RegisterComponent, Friend(typeof(InteractionPopupSystem))] + + public sealed class InteractionPopupComponent : Component + { + /// + /// Time delay between interactions to avoid spam. + /// + [DataField("interactDelay")] + [ViewVariables(VVAccess.ReadWrite)] + public TimeSpan InteractDelay = TimeSpan.FromSeconds(1.0); + + /// + /// String will be used to fetch the localized message to be played if the interaction succeeds. + /// Nullable in case none is specified on the yaml prototype. + /// + [DataField("interactSuccessString")] + public string? InteractSuccessString; + + /// + /// String will be used to fetch the localized message to be played if the interaction fails. + /// Nullable in case no message is specified on the yaml prototype. + /// + [DataField("interactFailureString")] + public string? InteractFailureString; + + /// + /// Sound effect to be played when the interaction succeeds. + /// Nullable in case no path is specified on the yaml prototype. + /// + [DataField("interactSuccessSound")] + public SoundSpecifier? InteractSuccessSound; + + /// + /// Sound effect to be played when the interaction fails. + /// Nullable in case no path is specified on the yaml prototype. + /// + [DataField("interactFailureSound")] + public SoundSpecifier? InteractFailureSound; + + /// + /// Chance that an interaction attempt will succeed. + /// 1 = always play "success" popup and sound. + /// 0.5 = 50% chance to play either success or failure popup and sound. + /// 0 = always play "failure" popup and sound. + /// + [DataField("successChance")] + public float SuccessChance = 1.0f; // Always succeed, unless specified otherwise on the yaml prototype. + + /// + /// Will the popup message be perceived by entities not involved in the interaction? + /// + [DataField("popupPerceivedByOthers")] + public bool PopupPerceivedByOthers = false; + + /// + /// Will the sound effect be perceived by entities not involved in the interaction? + /// + [DataField("soundPerceivedByOthers")] + public bool SoundPerceivedByOthers = true; + + [ViewVariables(VVAccess.ReadWrite)] + public TimeSpan LastInteractTime; + } diff --git a/Content.Server/Interaction/InteractionPopupSystem.cs b/Content.Server/Interaction/InteractionPopupSystem.cs new file mode 100644 index 0000000000..a01bf92a2a --- /dev/null +++ b/Content.Server/Interaction/InteractionPopupSystem.cs @@ -0,0 +1,72 @@ +using Content.Server.Popups; +using Content.Server.Interaction.Components; +using Content.Shared.Interaction; +using Content.Shared.MobState.Components; +using Robust.Shared.Audio; +using Robust.Shared.Player; +using Robust.Shared.Timing; +using Robust.Shared.Random; + + +namespace Content.Server.Interaction; + +public sealed class InteractionPopupSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnInteractHand); + } + + private void OnInteractHand(EntityUid uid, InteractionPopupComponent component, InteractHandEvent args) + { + if (args.Handled) + return; + + var curTime = _gameTiming.CurTime; + + if (curTime < component.LastInteractTime + component.InteractDelay) + return; + + if (TryComp(uid, out var state) // if it has a MobStateComponent, + && !state.IsAlive()) // AND if that state is not Alive (e.g. dead/incapacitated/critical) + return; + + string msg = ""; // Stores the text to be shown in the popup message + string sfx = ""; // Stores the filepath of the sound to be played + + if (_random.Prob(component.SuccessChance)) + { + if (component.InteractSuccessString != null) + msg = Loc.GetString(component.InteractSuccessString, ("target", uid)); // Success message (localized). + + if (component.InteractSuccessSound != null) + sfx = component.InteractSuccessSound.GetSound(); + } + else + { + if (component.InteractFailureString != null) + msg = Loc.GetString(component.InteractFailureString, ("target", uid)); // Failure message (localized). + + if (component.InteractFailureSound != null) + sfx = component.InteractFailureSound.GetSound(); + } + + if (component.PopupPerceivedByOthers) + _popupSystem.PopupEntity(msg, uid, Filter.Pvs(uid)); //play for everyone in range + else + _popupSystem.PopupEntity(msg, uid, Filter.Entities(args.User)); //play only for the initiating entity. + + if (component.SoundPerceivedByOthers) + SoundSystem.Play(Filter.Pvs(args.Target), sfx, args.Target); //play for everyone in range + else + SoundSystem.Play(Filter.Entities(args.User, args.Target), sfx, args.Target); //play only for the initiating entity and its target. + + component.LastInteractTime = curTime; + args.Handled = true; + } +} diff --git a/Content.Server/Window/WindowComponent.cs b/Content.Server/Window/WindowComponent.cs deleted file mode 100644 index 44b5a3333f..0000000000 --- a/Content.Server/Window/WindowComponent.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using Content.Shared.Sound; -using Content.Shared.Window; -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; - -namespace Content.Server.Window -{ - [RegisterComponent] - [ComponentReference(typeof(SharedWindowComponent))] - public class WindowComponent : SharedWindowComponent - { - [DataField("knockDelay")] - [ViewVariables(VVAccess.ReadWrite)] - public TimeSpan KnockDelay = TimeSpan.FromSeconds(0.5); - - [DataField("knockSound")] - public SoundSpecifier KnockSound = new SoundPathSpecifier("/Audio/Effects/glass_knock.ogg"); - - [ViewVariables(VVAccess.ReadWrite)] - public TimeSpan LastKnockTime; - } -} diff --git a/Content.Server/Window/WindowSystem.cs b/Content.Server/Window/WindowSystem.cs deleted file mode 100644 index 290d52bcb0..0000000000 --- a/Content.Server/Window/WindowSystem.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Content.Server.Popups; -using Content.Shared.Audio; -using Content.Shared.Interaction; -using Robust.Shared.Audio; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Localization; -using Robust.Shared.Player; -using Robust.Shared.Timing; - -namespace Content.Server.Window; - -public class WindowSystem : EntitySystem -{ - [Dependency] private readonly IGameTiming _gameTiming = default!; - [Dependency] private readonly PopupSystem _popupSystem = default!; - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnInteractHand); - } - - private void OnInteractHand(EntityUid uid, WindowComponent component, InteractHandEvent args) - { - if (args.Handled) - return; - - if (component.KnockDelay.TotalSeconds <= 0) - return; - - if (_gameTiming.CurTime < component.LastKnockTime + component.KnockDelay) - return; - - SoundSystem.Play(Filter.Pvs(args.Target), component.KnockSound.GetSound(), - Transform(args.Target).Coordinates, AudioHelpers.WithVariation(0.05f)); - - var msg = Loc.GetString("comp-window-knock"); - _popupSystem.PopupEntity(msg, uid, Filter.Pvs(uid)); - - component.LastKnockTime = _gameTiming.CurTime; - args.Handled = true; - } -} diff --git a/Content.Shared/Construction/Conditions/EmptyOrWindowValidInTile.cs b/Content.Shared/Construction/Conditions/EmptyOrWindowValidInTile.cs index 9e12089294..5c987db9f6 100644 --- a/Content.Shared/Construction/Conditions/EmptyOrWindowValidInTile.cs +++ b/Content.Shared/Construction/Conditions/EmptyOrWindowValidInTile.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Content.Shared.Maps; -using Content.Shared.Window; using JetBrains.Annotations; using Robust.Shared.GameObjects; using Robust.Shared.IoC; diff --git a/Content.Shared/Construction/Conditions/NoWindowsInTile.cs b/Content.Shared/Construction/Conditions/NoWindowsInTile.cs index a5f37f5aff..2174e18f7b 100644 --- a/Content.Shared/Construction/Conditions/NoWindowsInTile.cs +++ b/Content.Shared/Construction/Conditions/NoWindowsInTile.cs @@ -1,5 +1,5 @@ using Content.Shared.Maps; -using Content.Shared.Window; +using Content.Shared.Tag; using JetBrains.Annotations; using Robust.Shared.GameObjects; using Robust.Shared.IoC; @@ -15,9 +15,10 @@ namespace Content.Shared.Construction.Conditions { public bool Condition(EntityUid user, EntityCoordinates location, Direction direction) { + var tagSystem = EntitySystem.Get(); foreach (var entity in location.GetEntitiesInTile(LookupFlags.Approximate | LookupFlags.IncludeAnchored)) { - if (IoCManager.Resolve().HasComponent(entity)) + if (tagSystem.HasTag(entity, "Window")) return false; } diff --git a/Content.Shared/Window/SharedWindowComponent.cs b/Content.Shared/Window/SharedWindowComponent.cs deleted file mode 100644 index ae0ef6ee67..0000000000 --- a/Content.Shared/Window/SharedWindowComponent.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Robust.Shared.GameObjects; -using Robust.Shared.GameStates; - -namespace Content.Shared.Window -{ - [NetworkedComponent] - public class SharedWindowComponent : Component - { - } -} diff --git a/Resources/Audio/Animals/cat_meow.ogg b/Resources/Audio/Animals/cat_meow.ogg new file mode 100644 index 0000000000..b65b6cd7ec Binary files /dev/null and b/Resources/Audio/Animals/cat_meow.ogg differ diff --git a/Resources/Audio/Animals/chicken_cluck_happy.ogg b/Resources/Audio/Animals/chicken_cluck_happy.ogg new file mode 100644 index 0000000000..7599cd57e9 Binary files /dev/null and b/Resources/Audio/Animals/chicken_cluck_happy.ogg differ diff --git a/Resources/Audio/Animals/duck_quack_happy.ogg b/Resources/Audio/Animals/duck_quack_happy.ogg new file mode 100644 index 0000000000..4427202ff7 Binary files /dev/null and b/Resources/Audio/Animals/duck_quack_happy.ogg differ diff --git a/Resources/Audio/Animals/license.txt b/Resources/Audio/Animals/license.txt new file mode 100644 index 0000000000..3196554abf --- /dev/null +++ b/Resources/Audio/Animals/license.txt @@ -0,0 +1,9 @@ +The following sounds were used from freesound: + +cat_meow.ogg: modified from "Meow 4.wav" by freesound user "TRNGLE" (https://freesound.org/people/TRNGLE/sounds/368006/) licensed under CCBY 3.0. The original audio was trimmed, split to mono, and converted from WAV to OGG format. + +small_dog_bark_happy.ogg: modified from "Dog bark2.wav" by freesound user "MisterTood" (https://freesound.org/people/MisterTood/sounds/9032/) licensed under CC0 1.0 (public domain). The original audio was trimmed and converted from WAV to OGG format. + +duck_quack_happy.ogg: modified from "Duck Quack - Sound Effect (HD).mp3" by freesound user "Tabby+Gus." (https://freesound.org/people/Tabby+Gus./sounds/515408/) licensed under CC0 1.0 (public domain). The original audio was trimmed, looped, split to mono, and converted from MP3 to OGG format. + +chicken_cluck_happy.ogg: modified from "Chicken Single Alarm Call" by freesound user "Rudmer_Rotteveel" (https://freesound.org/people/Rudmer_Rotteveel/sounds/316920/) licensed under CC0 1.0 (public domain). The original audio was trimmed and converted from WAV to OGG format. diff --git a/Resources/Audio/Animals/small_dog_bark_happy.ogg b/Resources/Audio/Animals/small_dog_bark_happy.ogg new file mode 100644 index 0000000000..6842e1b951 Binary files /dev/null and b/Resources/Audio/Animals/small_dog_bark_happy.ogg differ diff --git a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl new file mode 100644 index 0000000000..fc278c1578 --- /dev/null +++ b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl @@ -0,0 +1,34 @@ +### Interaction Popup component + +## Petting animals + +petting-success-generic = You pet {THE($target)} on {POSS-ADJ($target)} head. +petting-success-soft-floofy = You pet {THE($target)} on {POSS-ADJ($target)} soft floofy head. + +petting-success-bird = You pet {THE($target)} on {POSS-ADJ($target)} cute feathery head. +petting-success-cat = You pet {THE($target)} on {POSS-ADJ($target)} fuzzy little head. +petting-success-corrupted-corgi = In an act of hubris, you pet {THE($target)} on {POSS-ADJ($target)} cursed little head. +petting-success-crab = You pet {THE($target)} on {POSS-ADJ($target)} smooth little head. +petting-success-dog = You pet {THE($target)} on {POSS-ADJ($target)} soft floofy head. +petting-success-frog = You pet {THE($target)} on {POSS-ADJ($target)} slippery little head. +petting-success-goat = You pet {THE($target)} on {POSS-ADJ($target)} horned floofy head. +petting-success-goose = Against all odds, you manage to pet {THE($target)} on {POSS-ADJ($target)} horrible little head. +petting-success-reptile = You pet {THE($target)} on {POSS-ADJ($target)} scaly little head. +petting-success-sloth = You pet {THE($target)} on {POSS-ADJ($target)} slow moving head. +petting-success-space-cat = You pet {THE($target)} on {POSS-ADJ($target)} glass domed head. +petting-success-tarantula = You pet {THE($target)} on {POSS-ADJ($target)} hairy little head. + + +petting-failure-generic = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} aloof towards you. + +petting-failure-bat = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} too hard to catch! +petting-failure-corrupted-corgi = You reach out to pet {THE($target)}, but think better of it. +petting-failure-crab = You reach out to pet {THE($target)}, but {SUBJECT($target)} snaps {POSS-ADJ($target)} claws in your general direction! +petting-failure-goat = You reach out to pet {THE($target)}, but {SUBJECT($target)} stubbornly refuses! +petting-failure-goose = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} too horrible! +petting-failure-sloth = You reach out to pet {THE($target)}, but {SUBJECT($target)} somehow dodge with ludicrous speed! + +## Knocking on windows + +# Shown when knocking on a window +comp-window-knock = *knock knock* diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index e5f253bc9c..d573fefb12 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -39,6 +39,10 @@ - type: Butcherable meat: FoodMeat pieces: 1 + - type: InteractionPopup + successChance: 0.2 + interactSuccessString: petting-success-soft-floofy + interactFailureString: petting-failure-bat - type: entity name: bee @@ -130,6 +134,12 @@ - type: Butcherable meat: FoodMeatChicken pieces: 1 + - type: InteractionPopup + successChance: 0.8 + interactSuccessString: petting-success-bird + interactFailureString: petting-failure-generic + interactSuccessSound: + path: /Audio/Animals/chicken_cluck_happy.ogg - type: entity name: mallard duck #Quack @@ -152,6 +162,12 @@ - type: Butcherable meat: FoodMeatDuck pieces: 1 + - type: InteractionPopup + successChance: 0.9 + interactSuccessString: petting-success-bird + interactFailureString: petting-failure-generic + interactSuccessSound: + path: /Audio/Animals/duck_quack_happy.ogg - type: entity name: white duck #Quack @@ -174,6 +190,12 @@ - type: Butcherable meat: FoodMeatDuck pieces: 1 + - type: InteractionPopup + successChance: 0.9 + interactSuccessString: petting-success-bird + interactFailureString: petting-failure-generic + interactSuccessSound: + path: /Audio/Animals/duck_quack_happy.ogg - type: entity name: brown duck #Quack @@ -196,6 +218,12 @@ - type: Butcherable meat: FoodMeatDuck pieces: 1 + - type: InteractionPopup + successChance: 0.9 + interactSuccessString: petting-success-bird + interactFailureString: petting-failure-generic + interactSuccessSound: + path: /Audio/Animals/duck_quack_happy.ogg - type: entity name: butterfly @@ -295,6 +323,13 @@ - type: Butcherable meat: FoodMeat pieces: 5 + - type: Grammar + attributes: + gender: female # Here because of UdderComponent + - type: InteractionPopup + successChance: 0.7 + interactSuccessString: petting-success-soft-floofy + interactFailureString: petting-failure-generic - type: entity name: crab @@ -332,12 +367,16 @@ - type: Butcherable meat: FoodMeatCrab pieces: 2 + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-crab + interactFailureString: petting-failure-crab - type: entity name: goat parent: SimpleMobBase id: MobGoat - description: His spine consists of long sharp segments, no wonder he is so grumpy. + description: Her spine consists of long sharp segments, no wonder she is so grumpy. components: - type: Sprite drawdepth: Mobs @@ -366,6 +405,13 @@ - type: Butcherable meat: FoodMeat pieces: 4 + - type: Grammar + attributes: + gender: female # Here because of UdderComponent + - type: InteractionPopup + successChance: 0.2 + interactSuccessString: petting-success-goat + interactFailureString: petting-failure-goat # Note that we gotta make this bitch vomit someday when you feed it anthrax or sumthin. Needs to be a small item thief too and aggressive if attacked. - type: entity @@ -389,6 +435,10 @@ - type: Butcherable meat: FoodMeatChicken pieces: 2 + - type: InteractionPopup # TODO: Make it so there's a separate chance to make certain animals outright hostile towards you. + successChance: 0.1 # Yeah, good luck with that. + interactSuccessString: petting-success-goose + interactFailureString: petting-failure-goose - type: entity name: gorilla @@ -679,6 +729,10 @@ - type: Butcherable meat: FoodMeat pieces: 1 + - type: InteractionPopup + successChance: 0.3 + interactSuccessString: petting-success-reptile + interactFailureString: petting-failure-generic - type: entity name: frog @@ -718,6 +772,10 @@ - type: Butcherable meat: FoodMeat pieces: 1 + - type: InteractionPopup + successChance: 0.6 + interactSuccessString: petting-success-frog + interactFailureString: petting-failure-generic # Would be cool to have some functionality for the parrot to be able to sit on stuff - type: entity @@ -758,6 +816,10 @@ - type: Butcherable meat: FoodMeat pieces: 1 + - type: InteractionPopup + successChance: 0.6 + interactSuccessString: petting-success-bird + interactFailureString: petting-failure-generic - type: entity name: penguin @@ -794,6 +856,10 @@ - type: Butcherable meat: FoodMeatPenguin pieces: 3 + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-bird + interactFailureString: petting-failure-generic - type: entity name: snake @@ -833,6 +899,10 @@ - type: Butcherable meat: FoodMeat pieces: 1 + - type: InteractionPopup + successChance: 0.6 + interactSuccessString: petting-success-reptile + interactFailureString: petting-failure-generic # Code unique spider prototypes or combine them all into one spider and get a # random sprite state when you spawn it. @@ -871,3 +941,7 @@ - type: Butcherable meat: FoodMeatSpider pieces: 2 + - type: InteractionPopup + successChance: 0.5 + interactSuccessString: petting-success-tarantula + interactFailureString: petting-failure-generic diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index 30341e30c8..a03912a5d1 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -38,6 +38,14 @@ pieces: 3 - type: ReplacementAccent accent: dog + - type: InteractionPopup + interactSuccessString: petting-success-dog + interactFailureString: petting-failure-generic + interactSuccessSound: + path: /Audio/Animals/small_dog_bark_happy.ogg + - type: Grammar + attributes: + gender: epicene - type: entity name: corrupted corgi @@ -71,6 +79,13 @@ - type: AiFactionTag factions: - SimpleHostile + - type: InteractionPopup + successChance: 0 # Override the automatic success that would normally be inherited from MobCorgi. + interactSuccessString: petting-success-corrupted-corgi # Normally impossible but added an easter egg just in case. + interactFailureString: petting-failure-corrupted-corgi + - type: Grammar + attributes: + gender: epicene - type: entity name: Ian @@ -90,6 +105,10 @@ normal: ian crit: ian_dead dead: ian_dead + - type: Grammar + attributes: + proper: true + gender: male - type: entity name: Old Ian @@ -109,6 +128,10 @@ normal: old_ian crit: old_ian_dead dead: old_ian_dead + - type: Grammar + attributes: + proper: true + gender: male - type: entity name: Lisa @@ -128,6 +151,10 @@ normal: lisa crit: lisa_dead dead: lisa_dead + - type: Grammar + attributes: + proper: true + gender: female - type: entity name: corgi puppy @@ -147,6 +174,9 @@ normal: puppy crit: puppy_dead dead: puppy_dead + - type: Grammar + attributes: + gender: epicene - type: entity name: cat @@ -185,6 +215,15 @@ pieces: 2 - type: ReplacementAccent accent: cat + - type: InteractionPopup + successChance: 0.7 + interactSuccessString: petting-success-cat + interactFailureString: petting-failure-generic + interactSuccessSound: + path: /Audio/Animals/cat_meow.ogg + - type: Grammar + attributes: + gender: epicene - type: entity name: calico cat @@ -204,6 +243,9 @@ normal: cat2 crit: cat2_dead dead: cat2_dead + - type: Grammar + attributes: + gender: epicene - type: entity name: space cat @@ -223,6 +265,15 @@ normal: spacecat crit: spacecat_dead dead: spacecat_dead + - type: InteractionPopup + successChance: 0.7 + interactSuccessString: petting-success-space-cat + interactFailureString: petting-failure-generic + interactSuccessSound: + path: /Audio/Animals/cat_meow.ogg + - type: Grammar + attributes: + gender: epicene - type: entity name: caracal cat @@ -242,6 +293,9 @@ normal: caracal_flop crit: caracal_dead dead: caracal_dead + - type: Grammar + attributes: + gender: epicene - type: entity name: sloth @@ -281,3 +335,10 @@ - type: Butcherable meat: FoodMeat pieces: 3 + - type: InteractionPopup + successChance: 0.9 + interactSuccessString: petting-success-sloth + interactFailureString: petting-failure-sloth + - type: Grammar + attributes: + gender: epicene diff --git a/Resources/Prototypes/Entities/Structures/Windows/window.yml b/Resources/Prototypes/Entities/Structures/Windows/window.yml index 142676cde1..84c75e9990 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/window.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/window.yml @@ -12,6 +12,7 @@ tags: - RCDDeconstructWhitelist - ForceFixRotations + - Window - type: Sprite netsync: false drawdepth: WallTops @@ -64,7 +65,11 @@ - type: IconSmooth key: windows base: window - - type: Window + - type: InteractionPopup + interactSuccessString: comp-window-knock + popupPerceivedByOthers: true + interactSuccessSound: + path: /Audio/Effects/glass_knock.ogg - type: Construction graph: Window node: window @@ -89,6 +94,9 @@ components: # Attention! If adding tags here: # Keep WindowTintedDirectional in mind + - type: Tag + tags: + - Window - type: Sprite netsync: false sprite: Structures/Windows/directional.rsi @@ -96,6 +104,11 @@ - type: Icon sprite: Structures/Windows/directional.rsi state: window + - type: InteractionPopup + interactSuccessString: comp-window-knock + popupPerceivedByOthers: true + interactSuccessSound: + path: /Audio/Effects/glass_knock.ogg - type: Physics - type: Fixtures fixtures: @@ -136,7 +149,6 @@ noAirWhenFullyAirBlocked: false airBlockedDirection: - South - - type: Window - type: Construction graph: WindowDirectional node: windowDirectional diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 8a43625186..910c6da7f0 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -285,6 +285,9 @@ - type: Tag id: Wall +- type: Tag + id: Window + - type: Tag id: Wirecutter