Turnstiles (#36313)
* construction rotation fix * Turnstiles * renaming * review-slarticodefast-1 * mild attempts to fix (sorry sloth) * move some more shit * Remove engine dependency * grid agnostic * remove debug string * fix json * Update Content.Shared/Movement/Pulling/Systems/PullingSystem.cs Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> * Update Content.Shared/Movement/Pulling/Systems/PullingSystem.cs Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> * remove pass delay for mispredict reasons. * most minor of changes * Give directional indicator on examine --------- Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
This commit is contained in:
75
Content.Client/Doors/TurnstileSystem.cs
Normal file
75
Content.Client/Doors/TurnstileSystem.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using Content.Shared.Doors.Components;
|
||||||
|
using Content.Shared.Doors.Systems;
|
||||||
|
using Content.Shared.Examine;
|
||||||
|
using Robust.Client.Animations;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Client.Doors;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public sealed class TurnstileSystem : SharedTurnstileSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly AnimationPlayerSystem _animationPlayer = default!;
|
||||||
|
|
||||||
|
private static EntProtoId _examineArrow = "TurnstileArrow";
|
||||||
|
|
||||||
|
private const string AnimationKey = "Turnstile";
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<TurnstileComponent, AnimationCompletedEvent>(OnAnimationCompleted);
|
||||||
|
SubscribeLocalEvent<TurnstileComponent, ExaminedEvent>(OnExamined);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAnimationCompleted(Entity<TurnstileComponent> ent, ref AnimationCompletedEvent args)
|
||||||
|
{
|
||||||
|
if (args.Key != AnimationKey)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||||
|
return;
|
||||||
|
sprite.LayerSetState(TurnstileVisualLayers.Base, new RSI.StateId(ent.Comp.DefaultState));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnExamined(Entity<TurnstileComponent> ent, ref ExaminedEvent args)
|
||||||
|
{
|
||||||
|
Spawn(_examineArrow, new EntityCoordinates(ent, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void PlayAnimation(EntityUid uid, string stateId)
|
||||||
|
{
|
||||||
|
if (!TryComp<AnimationPlayerComponent>(uid, out var animation) || !TryComp<SpriteComponent>(uid, out var sprite))
|
||||||
|
return;
|
||||||
|
var ent = (uid, animation);
|
||||||
|
|
||||||
|
if (_animationPlayer.HasRunningAnimation(animation, AnimationKey))
|
||||||
|
_animationPlayer.Stop(ent, AnimationKey);
|
||||||
|
|
||||||
|
if (sprite.BaseRSI == null || !sprite.BaseRSI.TryGetState(stateId, out var state))
|
||||||
|
return;
|
||||||
|
var animLength = state.AnimationLength;
|
||||||
|
|
||||||
|
var anim = new Animation
|
||||||
|
{
|
||||||
|
AnimationTracks =
|
||||||
|
{
|
||||||
|
new AnimationTrackSpriteFlick
|
||||||
|
{
|
||||||
|
LayerKey = TurnstileVisualLayers.Base,
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackSpriteFlick.KeyFrame(state.StateId, 0f),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Length = TimeSpan.FromSeconds(animLength),
|
||||||
|
};
|
||||||
|
|
||||||
|
_animationPlayer.Play(ent, anim, AnimationKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
6
Content.Server/Doors/Systems/TurnstileSystem.cs
Normal file
6
Content.Server/Doors/Systems/TurnstileSystem.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
using Content.Shared.Doors.Systems;
|
||||||
|
|
||||||
|
namespace Content.Server.Doors.Systems;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public sealed class TurnstileSystem : SharedTurnstileSystem;
|
||||||
71
Content.Shared/Doors/Components/TurnstileComponent.cs
Normal file
71
Content.Shared/Doors/Components/TurnstileComponent.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
using Content.Shared.Doors.Systems;
|
||||||
|
using Content.Shared.Whitelist;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
|
namespace Content.Shared.Doors.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is used for a condition door that allows entry only through a single side.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
||||||
|
[Access(typeof(SharedTurnstileSystem))]
|
||||||
|
public sealed partial class TurnstileComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A whitelist of the things this turnstile can choose to block or let through.
|
||||||
|
/// Things not in this whitelist will be ignored by default.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public EntityWhitelist? ProcessWhitelist;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The next time at which the resist message can show.
|
||||||
|
/// </summary>
|
||||||
|
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField, AutoPausedField]
|
||||||
|
public TimeSpan NextResistTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maintained hashset of entities currently passing through the turnstile.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public HashSet<EntityUid> CollideExceptions = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// default state of the turnstile sprite.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public string DefaultState = "turnstile";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// animation state of the turnstile spinning.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public string SpinState = "operate";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// animation state of the turnstile denying entry.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public string DenyState = "deny";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sound to play when the turnstile admits a mob through.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public SoundSpecifier? TurnSound = new SoundPathSpecifier("/Audio/Items/ratchet.ogg");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sound to play when the turnstile denies entry
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public SoundSpecifier? DenySound = new SoundPathSpecifier("/Audio/Machines/airlock_deny.ogg");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum TurnstileVisualLayers : byte
|
||||||
|
{
|
||||||
|
Base
|
||||||
|
}
|
||||||
131
Content.Shared/Doors/Systems/SharedTurnstileSystem.cs
Normal file
131
Content.Shared/Doors/Systems/SharedTurnstileSystem.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
using Content.Shared.Access.Systems;
|
||||||
|
using Content.Shared.Doors.Components;
|
||||||
|
using Content.Shared.Movement.Pulling.Systems;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Whitelist;
|
||||||
|
using Robust.Shared.Audio.Systems;
|
||||||
|
using Robust.Shared.Physics.Events;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Shared.Doors.Systems;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This handles logic and interactions related to <see cref="TurnstileComponent"/>
|
||||||
|
/// </summary>
|
||||||
|
public abstract partial class SharedTurnstileSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
|
||||||
|
[Dependency] private readonly PullingSystem _pulling = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<TurnstileComponent, PreventCollideEvent>(OnPreventCollide);
|
||||||
|
SubscribeLocalEvent<TurnstileComponent, StartCollideEvent>(OnStartCollide);
|
||||||
|
SubscribeLocalEvent<TurnstileComponent, EndCollideEvent>(OnEndCollide);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPreventCollide(Entity<TurnstileComponent> ent, ref PreventCollideEvent args)
|
||||||
|
{
|
||||||
|
if (args.Cancelled || !args.OurFixture.Hard || !args.OtherFixture.Hard)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ent.Comp.CollideExceptions.Contains(args.OtherEntity))
|
||||||
|
{
|
||||||
|
args.Cancelled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to add this in here too for chain pulls
|
||||||
|
if (_pulling.GetPuller(args.OtherEntity) is { } puller && ent.Comp.CollideExceptions.Contains(puller))
|
||||||
|
{
|
||||||
|
ent.Comp.CollideExceptions.Add(args.OtherEntity);
|
||||||
|
Dirty(ent);
|
||||||
|
args.Cancelled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unblockables go through for free.
|
||||||
|
if (_entityWhitelist.IsWhitelistFail(ent.Comp.ProcessWhitelist, args.OtherEntity))
|
||||||
|
{
|
||||||
|
args.Cancelled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CanPassDirection(ent, args.OtherEntity))
|
||||||
|
{
|
||||||
|
if (!_accessReader.IsAllowed(args.OtherEntity, ent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ent.Comp.CollideExceptions.Add(args.OtherEntity);
|
||||||
|
if (_pulling.GetPulling(args.OtherEntity) is { } uid)
|
||||||
|
ent.Comp.CollideExceptions.Add(uid);
|
||||||
|
|
||||||
|
args.Cancelled = true;
|
||||||
|
Dirty(ent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_timing.CurTime >= ent.Comp.NextResistTime)
|
||||||
|
{
|
||||||
|
_popup.PopupClient(Loc.GetString("turnstile-component-popup-resist", ("turnstile", ent.Owner)), ent, args.OtherEntity);
|
||||||
|
ent.Comp.NextResistTime = _timing.CurTime + TimeSpan.FromSeconds(0.1);
|
||||||
|
Dirty(ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStartCollide(Entity<TurnstileComponent> ent, ref StartCollideEvent args)
|
||||||
|
{
|
||||||
|
if (!ent.Comp.CollideExceptions.Contains(args.OtherEntity))
|
||||||
|
{
|
||||||
|
if (CanPassDirection(ent, args.OtherEntity))
|
||||||
|
{
|
||||||
|
if (!_accessReader.IsAllowed(args.OtherEntity, ent))
|
||||||
|
{
|
||||||
|
_audio.PlayPredicted(ent.Comp.DenySound, ent, args.OtherEntity);
|
||||||
|
PlayAnimation(ent, ent.Comp.DenyState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// if they passed through:
|
||||||
|
PlayAnimation(ent, ent.Comp.SpinState);
|
||||||
|
_audio.PlayPredicted(ent.Comp.TurnSound, ent, args.OtherEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEndCollide(Entity<TurnstileComponent> ent, ref EndCollideEvent args)
|
||||||
|
{
|
||||||
|
if (!args.OurFixture.Hard)
|
||||||
|
{
|
||||||
|
ent.Comp.CollideExceptions.Remove(args.OtherEntity);
|
||||||
|
Dirty(ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool CanPassDirection(Entity<TurnstileComponent> ent, EntityUid other)
|
||||||
|
{
|
||||||
|
var xform = Transform(ent);
|
||||||
|
var otherXform = Transform(other);
|
||||||
|
|
||||||
|
var (pos, rot) = _transform.GetWorldPositionRotation(xform);
|
||||||
|
var otherPos = _transform.GetWorldPosition(otherXform);
|
||||||
|
|
||||||
|
var approachAngle = (pos - otherPos).ToAngle();
|
||||||
|
var rotateAngle = rot.ToWorldVec().ToAngle();
|
||||||
|
|
||||||
|
var dif = Math.Min(Math.Abs(approachAngle.Theta - rotateAngle.Theta), Math.Abs(rotateAngle.Theta - approachAngle.Theta));
|
||||||
|
return dif < Math.PI / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void PlayAnimation(EntityUid uid, string stateId)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -341,6 +341,16 @@ public sealed class PullingSystem : EntitySystem
|
|||||||
return Resolve(puller, ref component, false) && component.Pulling != null;
|
return Resolve(puller, ref component, false) && component.Pulling != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EntityUid? GetPuller(EntityUid puller, PullableComponent? component = null)
|
||||||
|
{
|
||||||
|
return !Resolve(puller, ref component, false) ? null : component.Puller;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityUid? GetPulling(EntityUid puller, PullerComponent? component = null)
|
||||||
|
{
|
||||||
|
return !Resolve(puller, ref component, false) ? null : component.Pulling;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnReleasePulledObject(ICommonSession? session)
|
private void OnReleasePulledObject(ICommonSession? session)
|
||||||
{
|
{
|
||||||
if (session?.AttachedEntity is not { Valid: true } player)
|
if (session?.AttachedEntity is not { Valid: true } player)
|
||||||
|
|||||||
1
Resources/Locale/en-US/doors/components/turnstile.ftl
Normal file
1
Resources/Locale/en-US/doors/components/turnstile.ftl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
turnstile-component-popup-resist = {CAPITALIZE(THE($turnstile))} resists your efforts!
|
||||||
77
Resources/Prototypes/Entities/Structures/Doors/turnstile.yml
Normal file
77
Resources/Prototypes/Entities/Structures/Doors/turnstile.yml
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
- type: entity
|
||||||
|
id: Turnstile
|
||||||
|
parent: BaseStructure
|
||||||
|
name: turnstile
|
||||||
|
description: A mechanical door that permits one-way access and prevents tailgating.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Structures/Doors/turnstile.rsi
|
||||||
|
snapCardinals: true
|
||||||
|
drawdepth: Doors
|
||||||
|
layers:
|
||||||
|
- state: turnstile
|
||||||
|
map: [ "enum.TurnstileVisualLayers.Base" ]
|
||||||
|
- type: AnimationPlayer
|
||||||
|
- type: Fixtures
|
||||||
|
fixtures:
|
||||||
|
fix1:
|
||||||
|
shape:
|
||||||
|
!type:PhysShapeAabb
|
||||||
|
bounds: "-0.49,-0.49,0.49,0.49" # same dimensions as a door for tall turnstile, prevents objects being thrown through
|
||||||
|
density: 100
|
||||||
|
mask:
|
||||||
|
- FullTileMask
|
||||||
|
layer:
|
||||||
|
- AirlockLayer
|
||||||
|
fix2:
|
||||||
|
shape:
|
||||||
|
!type:PhysShapeAabb
|
||||||
|
bounds: "-0.50,-0.50,0.50,0.50" # same dimensions as a door for tall turnstile, prevents objects being thrown through
|
||||||
|
hard: false
|
||||||
|
mask:
|
||||||
|
- FullTileMask
|
||||||
|
layer:
|
||||||
|
- AirlockLayer
|
||||||
|
- type: MeleeSound
|
||||||
|
soundGroups:
|
||||||
|
Brute:
|
||||||
|
path:
|
||||||
|
"/Audio/Weapons/smash.ogg"
|
||||||
|
- type: InteractionOutline
|
||||||
|
- type: Turnstile
|
||||||
|
processWhitelist:
|
||||||
|
components:
|
||||||
|
- MobState # no mobs
|
||||||
|
- Pullable # no dragging things in
|
||||||
|
- type: Appearance
|
||||||
|
- type: Damageable
|
||||||
|
damageContainer: Inorganic
|
||||||
|
damageModifierSet: StrongMetallic
|
||||||
|
- type: Destructible
|
||||||
|
thresholds:
|
||||||
|
- trigger:
|
||||||
|
!type:DamageTrigger
|
||||||
|
damage: 500
|
||||||
|
behaviors:
|
||||||
|
- !type:DoActsBehavior
|
||||||
|
acts: ["Destruction"]
|
||||||
|
- type: Construction
|
||||||
|
graph: Turnstile
|
||||||
|
node: turnstile
|
||||||
|
|
||||||
|
- # Spawned by the client-side turnstile examine code to indicate the direction to pass through.
|
||||||
|
type: entity
|
||||||
|
id: TurnstileArrow
|
||||||
|
categories: [ HideSpawnMenu ]
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Structures/Doors/turnstile.rsi
|
||||||
|
color: "#FFFFFFBB"
|
||||||
|
layers:
|
||||||
|
- state: arrow
|
||||||
|
offset: 0, 0.78125
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 2
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- HideContextMenu
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
- type: constructionGraph
|
||||||
|
id: Turnstile
|
||||||
|
start: start
|
||||||
|
graph:
|
||||||
|
- node: start
|
||||||
|
actions:
|
||||||
|
- !type:DeleteEntity { }
|
||||||
|
edges:
|
||||||
|
- to: turnstile
|
||||||
|
completed:
|
||||||
|
- !type:SnapToGrid
|
||||||
|
steps:
|
||||||
|
- material: MetalRod
|
||||||
|
amount: 4
|
||||||
|
doAfter: 6
|
||||||
|
- material: Steel
|
||||||
|
amount: 1
|
||||||
|
doAfter: 2
|
||||||
|
|
||||||
|
- node: turnstile
|
||||||
|
entity: Turnstile
|
||||||
|
edges:
|
||||||
|
- to: start
|
||||||
|
completed:
|
||||||
|
- !type:SpawnPrototype
|
||||||
|
prototype: PartRodMetal1
|
||||||
|
amount: 4
|
||||||
|
- !type:DeleteEntity
|
||||||
|
steps:
|
||||||
|
- tool: Welding
|
||||||
|
doAfter: 4.0
|
||||||
|
- tool: Cutting
|
||||||
|
doAfter: 2.0
|
||||||
@@ -796,6 +796,23 @@
|
|||||||
conditions:
|
conditions:
|
||||||
- !type:TileNotBlocked
|
- !type:TileNotBlocked
|
||||||
|
|
||||||
|
- type: construction
|
||||||
|
name: turnstile
|
||||||
|
id: Turnstile
|
||||||
|
graph: Turnstile
|
||||||
|
startNode: start
|
||||||
|
targetNode: turnstile
|
||||||
|
category: construction-category-structures
|
||||||
|
description: A mechanical door that permits one-way access and prevents tailgating.
|
||||||
|
icon:
|
||||||
|
sprite: Structures/Doors/turnstile.rsi
|
||||||
|
state: turnstile
|
||||||
|
objectType: Structure
|
||||||
|
placementMode: SnapgridCenter
|
||||||
|
canBuildInImpassable: false
|
||||||
|
conditions:
|
||||||
|
- !type:TileNotBlocked
|
||||||
|
|
||||||
- type: construction
|
- type: construction
|
||||||
name: shutter
|
name: shutter
|
||||||
id: Shutters
|
id: Shutters
|
||||||
|
|||||||
BIN
Resources/Textures/Structures/Doors/turnstile.rsi/arrow.png
Normal file
BIN
Resources/Textures/Structures/Doors/turnstile.rsi/arrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 543 B |
BIN
Resources/Textures/Structures/Doors/turnstile.rsi/deny.png
Normal file
BIN
Resources/Textures/Structures/Doors/turnstile.rsi/deny.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
65
Resources/Textures/Structures/Doors/turnstile.rsi/meta.json
Normal file
65
Resources/Textures/Structures/Doors/turnstile.rsi/meta.json
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from OracleStation at https://github.com/OracleStation/OracleStation/blob/c1046bdd14674dc5a8631074aaa6650770b2937e/icons/obj/turnstile.dmi. Arrow by EmoGarbage404 (github).",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "arrow",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.5,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "turnstile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "turnstile_map",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "operate",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "deny",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
Resources/Textures/Structures/Doors/turnstile.rsi/operate.png
Normal file
BIN
Resources/Textures/Structures/Doors/turnstile.rsi/operate.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
BIN
Resources/Textures/Structures/Doors/turnstile.rsi/turnstile.png
Normal file
BIN
Resources/Textures/Structures/Doors/turnstile.rsi/turnstile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
Reference in New Issue
Block a user