add: funny keys that can lock doors (#113)

This commit is contained in:
ThereDrD0
2024-02-23 22:10:38 +03:00
committed by GitHub
parent 26cb9ac1c2
commit 9d31a42880
32 changed files with 386 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
using Content.Shared._White.Keyhole.Components;
using Content.Shared._White.Keyhole;
using Content.Shared.DoAfter;
using Content.Shared.Doors.Components;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Random;
namespace Content.Server._White.Keyhole;
public sealed partial class KeyholeSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
public override void Initialize()
{
SubscribeLocalEvent<KeyComponent, ComponentInit>(OnKeyInit);
SubscribeLocalEvent<KeyComponent, AfterInteractEvent>(OnKeyInsert);
SubscribeLocalEvent<KeyholeComponent, KeyInsertDoAfterEvent>(OnDoAfter);
}
private void OnKeyInit(EntityUid uid, KeyComponent component, ComponentInit ev)
{
component.FormId = _random.Next(1000);
}
private void OnKeyInsert(EntityUid uid, KeyComponent component, AfterInteractEvent ev)
{
if (TryComp<KeyformComponent>(ev.Target, out var keyformComponent))
OnKeyInsertForm(uid, component, keyformComponent, ev);
if (!TryComp<KeyholeComponent>(ev.Target, out var keyholeComponent))
return;
keyholeComponent.FormId ??= component.FormId;
if (!CanLock(keyholeComponent.Owner, keyholeComponent, component))
return;
var doAfterEventArgs =
new DoAfterArgs(EntityManager, ev.User, keyholeComponent.Delay, new KeyInsertDoAfterEvent(), ev.Target, ev.Used)
{
BreakOnTargetMove = true,
BreakOnUserMove = true,
BreakOnDamage = true
};
_doAfter.TryStartDoAfter(doAfterEventArgs);
}
private bool CanLock(EntityUid uid, KeyholeComponent keyholeComponent, KeyComponent keyComponent)
{
var can = TryComp<DoorComponent>(uid, out var doorComponent) &&
keyholeComponent.FormId == keyComponent.FormId &&
doorComponent.State == DoorState.Closed;
return can;
}
private void OnDoAfter(EntityUid uid, KeyholeComponent component, KeyInsertDoAfterEvent args)
{
if (args.Handled || args.Cancelled)
return;
Lock(uid, component, args.User);
args.Handled = true;
}
private void Lock(EntityUid uid, KeyholeComponent component, EntityUid user)
{
var sound = component.Locked ? component.UnlockSound : component.LockSound;
var message = Loc.GetString(component.Locked ? "key-unlock-message" : "key-lock-message", ("name", user), ("door", uid));
var audioParams = new AudioParams().WithVolume(-5f);
_audio.PlayPvs(sound, user, audioParams);
_popupSystem.PopupEntity(message, uid);
component.Locked = !component.Locked;
}
private void OnKeyInsertForm(EntityUid uid, KeyComponent keyComponent, KeyformComponent keyformComponent, AfterInteractEvent args)
{
if (!keyformComponent.IsUsed)
{
keyformComponent.FormId ??= keyComponent.FormId;
_appearance.SetData(keyformComponent.Owner, KeyformVisuals.IsUsed, true);
_audio.PlayPvs(keyformComponent.PressSound, uid);
_popupSystem.PopupEntity(Loc.GetString("key-pressed-in-keyform-message-first", ("user", args.User), ("key", uid)), uid);
keyformComponent.IsUsed = true;
}
else
{
keyComponent.FormId = keyformComponent.FormId;
_popupSystem.PopupEntity(Loc.GetString("key-pressed-in-keyform-message", ("user", args.User), ("key", uid)), uid);
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Linq; using System.Linq;
using Content.Shared._White.Keyhole.Components;
using Content.Shared.Access.Components; using Content.Shared.Access.Components;
using Content.Shared.Access.Systems; using Content.Shared.Access.Systems;
using Content.Shared.Damage; using Content.Shared.Damage;
@@ -6,6 +7,7 @@ using Content.Shared.Doors.Components;
using Content.Shared.Hands.Components; using Content.Shared.Hands.Components;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Physics; using Content.Shared.Physics;
using Content.Shared.Popups;
using Content.Shared.Prying.Components; using Content.Shared.Prying.Components;
using Content.Shared.Stunnable; using Content.Shared.Stunnable;
using Content.Shared.Tag; using Content.Shared.Tag;
@@ -30,6 +32,7 @@ public abstract class SharedDoorSystem : EntitySystem
[Dependency] protected readonly SharedAppearanceSystem AppearanceSystem = default!; [Dependency] protected readonly SharedAppearanceSystem AppearanceSystem = default!;
[Dependency] private readonly OccluderSystem _occluder = default!; [Dependency] private readonly OccluderSystem _occluder = default!;
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!; [Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!; //WD edit
/// <summary> /// <summary>
/// A body must have an intersection percentage larger than this in order to be considered as colliding with a /// A body must have an intersection percentage larger than this in order to be considered as colliding with a
@@ -211,6 +214,19 @@ public abstract class SharedDoorSystem : EntitySystem
if (!Resolve(uid, ref door)) if (!Resolve(uid, ref door))
return false; return false;
// WD edit start
if (TryComp<KeyholeComponent>(uid, out var keyholeComponent))
{
if (keyholeComponent.Locked)
{
PlaySound(uid, keyholeComponent.DoorLockedSound, AudioParams.Default.WithVolume(-3), uid, true);
_popupSystem.PopupEntity(Loc.GetString("door-locked-via-key", ("door", uid)), uid);
return false;
}
}
// WD edit end
if (door.State is DoorState.Closed or DoorState.Denying) if (door.State is DoorState.Closed or DoorState.Denying)
{ {
return TryOpen(uid, door, user, predicted, quiet: door.State == DoorState.Denying); return TryOpen(uid, door, user, predicted, quiet: door.State == DoorState.Denying);

View File

@@ -0,0 +1,9 @@
namespace Content.Shared._White.Keyhole.Components;
[RegisterComponent]
public partial class KeyBaseComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public int? FormId;
}

View File

@@ -0,0 +1,7 @@
namespace Content.Shared._White.Keyhole.Components;
[RegisterComponent]
public sealed partial class KeyComponent : KeyBaseComponent
{
}

View File

@@ -0,0 +1,15 @@
using Robust.Shared.Audio;
namespace Content.Shared._White.Keyhole.Components;
[RegisterComponent]
public sealed partial class KeyformComponent : KeyBaseComponent
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public bool IsUsed;
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public SoundSpecifier PressSound = new SoundPathSpecifier("/Audio/White/Object/Tools/Form/press.ogg");
}

View File

@@ -0,0 +1,27 @@
using Robust.Shared.Audio;
namespace Content.Shared._White.Keyhole.Components;
[RegisterComponent]
public sealed partial class KeyholeComponent: KeyBaseComponent
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public bool Locked = false;
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public float Delay = 1f;
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public SoundSpecifier DoorLockedSound = new SoundPathSpecifier("/Audio/White/Object/Tools/Keyhole/locked.ogg");
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public SoundSpecifier UnlockSound = new SoundPathSpecifier("/Audio/White/Object/Tools/Keyhole/unlock.ogg");
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public SoundSpecifier LockSound = new SoundPathSpecifier("/Audio/White/Object/Tools/Keyhole/lock.ogg");
}

View File

@@ -0,0 +1,8 @@
using Content.Shared.DoAfter;
using Robust.Shared.Serialization;
namespace Content.Shared._White.Keyhole;
[Serializable, NetSerializable]
public sealed partial class KeyInsertDoAfterEvent : SimpleDoAfterEvent {}

View File

@@ -0,0 +1,9 @@
using Robust.Shared.Serialization;
namespace Content.Shared._White.Keyhole;
[Serializable, NetSerializable]
public enum KeyformVisuals : byte
{
IsUsed
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,5 @@
ent-KeyMetal = металлический ключ
.desc = заостренный кусок металла
key-lock-message = {$name} проворачивает ключ в замке {$door} и закрывает {POSS-ADJ($door)}
key-unlock-message = {$name} проворачивает ключ в замке {$door} и открывает {POSS-ADJ($door)}

View File

@@ -0,0 +1,5 @@
ent-KeyForm = пластиковая форма
.desc = мягкий кусок пластика
key-pressed-in-keyform-message-first = {$user} вдавливает {$key} в пластик, создавая в нем форму ключа
key-pressed-in-keyform-message = {$user} вставляет {$key} в форму, заставляя его скопировать уникальный узор

View File

@@ -0,0 +1 @@
door-locked-via-key = {$door} закрыта

View File

@@ -57,6 +57,7 @@
mode: NoSprite mode: NoSprite
- type: Occluder - type: Occluder
- type: ReflectAspectMark - type: ReflectAspectMark
- type: Keyhole
- type: entity - type: entity
parent: BaseMaterialDoor parent: BaseMaterialDoor

View File

@@ -0,0 +1,54 @@
- type: constructionGraph
id: KeyFormGraph
start: start
graph:
- node: start
edges:
- to: KeyFormNode
steps:
- material: Plastic
amount: 1
doAfter: 2
- node: KeyFormNode
entity: KeyForm
- type: construction
name: ent-KeyForm
id: KeyForm
graph: KeyFormGraph
startNode: start
targetNode: KeyFormNode
category: construction-category-tools
objectType: Item
description: ent-KeyForm.desc
icon:
sprite: White/Objects/Tools/form.rsi
state: empty
- type: constructionGraph
id: KeyGraph
start: start
graph:
- node: start
edges:
- to: KeyNode
steps:
- material: Steel
amount: 1
doAfter: 2
- node: KeyNode
entity: KeyMetal
- type: construction
name: ent-KeyMetal
id: KeyMetal
graph: KeyGraph
startNode: start
targetNode: KeyNode
category: construction-category-tools
objectType: Item
description: ent-KeyMetal.desc
icon:
sprite: White/Objects/Tools/key.rsi
state: icon

View File

@@ -0,0 +1,34 @@
- type: entity
name: form
parent: BaseItem
id: KeyForm
description: Makeshift piece of plastic
components:
- type: EmitSoundOnPickup
sound:
path: /Audio/White/Object/Tools/Form/pickup.ogg
- type: EmitSoundOnLand
sound:
path: /Audio/White/Object/Tools/Form/hit.ogg
- type: Sprite
sprite: White/Objects/Tools/form.rsi
state: empty
- type: Item
sprite: White/Objects/Tools/form.rsi
storedRotation: -180
- type: PhysicalComposition
materialComposition:
Steel: 100
- type: StaticPrice
price: 10
- type: Keyform
- type: GenericVisualizer
visuals:
enum.KeyformVisuals.IsUsed:
base:
True: { state: withkey }
False: { state: empty }
- type: Appearance
- type: Construction
graph: KeyFormGraph
node: KeyFormNode

View File

@@ -0,0 +1,38 @@
- type: entity
name: key
parent: BaseItem
id: KeyMetal
description: Makeshift sharp piece of metal
components:
- type: EmitSoundOnPickup
sound:
path: /Audio/White/Object/Tools/Key/pickup.ogg
- type: EmitSoundOnDrop
sound:
path: /Audio/White/Object/Tools/Key/drop.ogg
- type: EmitSoundOnLand
sound:
path: /Audio/White/Object/Tools/Key/drop.ogg
- type: Sprite
sprite: White/Objects/Tools/key.rsi
state: icon
- type: Item
sprite: White/Objects/Tools/key.rsi
storedRotation: -180
- type: MeleeWeapon
wideAnimationRotation: -180
attackRate: 1
damage:
types:
Piercing: 1
soundHit:
path: "/Audio/Weapons/bladeslice.ogg"
- type: PhysicalComposition
materialComposition:
Steel: 100
- type: StaticPrice
price: 10
- type: Key
- type: Construction
graph: KeyGraph
node: KeyNode

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

View File

@@ -0,0 +1,25 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "https://github.com/frosty-dev/white",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "empty"
},
{
"name": "withkey"
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

View File

@@ -0,0 +1,22 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "https://github.com/frosty-dev/white",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "inhand-left",
"directions": 4
},
{
"name": "inhand-right",
"directions": 4
}
]
}