using Content.Shared.Doors.Components; using Content.Shared.Doors.Systems; using Robust.Client.Animations; using Robust.Client.GameObjects; using Robust.Client.ResourceManagement; using Robust.Shared.Serialization.TypeSerializers.Implementations; namespace Content.Client.Doors; public sealed class DoorSystem : SharedDoorSystem { [Dependency] private readonly AnimationPlayerSystem _animationSystem = default!; [Dependency] private readonly IResourceCache _resourceCache = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnAppearanceChange); } protected override void OnComponentInit(Entity ent, ref ComponentInit args) { var comp = ent.Comp; comp.OpenSpriteStates = new List<(DoorVisualLayers, string)>(2); comp.ClosedSpriteStates = new List<(DoorVisualLayers, string)>(2); comp.OpenSpriteStates.Add((DoorVisualLayers.Base, comp.OpenSpriteState)); comp.ClosedSpriteStates.Add((DoorVisualLayers.Base, comp.ClosedSpriteState)); comp.OpeningAnimation = new Animation { Length = TimeSpan.FromSeconds(comp.OpeningAnimationTime), AnimationTracks = { new AnimationTrackSpriteFlick { LayerKey = DoorVisualLayers.Base, KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.OpeningSpriteState, 0f), }, }, }, }; comp.ClosingAnimation = new Animation { Length = TimeSpan.FromSeconds(comp.ClosingAnimationTime), AnimationTracks = { new AnimationTrackSpriteFlick { LayerKey = DoorVisualLayers.Base, KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.ClosingSpriteState, 0f), }, }, }, }; comp.EmaggingAnimation = new Animation { Length = TimeSpan.FromSeconds(comp.EmaggingAnimationTime), AnimationTracks = { new AnimationTrackSpriteFlick { LayerKey = DoorVisualLayers.BaseUnlit, KeyFrames = { new AnimationTrackSpriteFlick.KeyFrame(comp.EmaggingSpriteState, 0f), }, }, }, }; } private void OnAppearanceChange(Entity entity, ref AppearanceChangeEvent args) { if (args.Sprite == null) return; if (!AppearanceSystem.TryGetData(entity, DoorVisuals.State, out var state, args.Component)) state = DoorState.Closed; if (AppearanceSystem.TryGetData(entity, DoorVisuals.BaseRSI, out var baseRsi, args.Component)) UpdateSpriteLayers(args.Sprite, baseRsi); if (_animationSystem.HasRunningAnimation(entity, DoorComponent.AnimationKey)) _animationSystem.Stop(entity.Owner, DoorComponent.AnimationKey); UpdateAppearanceForDoorState(entity, args.Sprite, state); } private void UpdateAppearanceForDoorState(Entity entity, SpriteComponent sprite, DoorState state) { sprite.DrawDepth = state is DoorState.Open ? entity.Comp.OpenDrawDepth : entity.Comp.ClosedDrawDepth; switch (state) { case DoorState.Open: foreach (var (layer, layerState) in entity.Comp.OpenSpriteStates) { sprite.LayerSetState(layer, layerState); } return; case DoorState.Closed: foreach (var (layer, layerState) in entity.Comp.ClosedSpriteStates) { sprite.LayerSetState(layer, layerState); } return; case DoorState.Opening: if (entity.Comp.OpeningAnimationTime == 0.0) return; _animationSystem.Play(entity, (Animation)entity.Comp.OpeningAnimation, DoorComponent.AnimationKey); return; case DoorState.Closing: if (entity.Comp.ClosingAnimationTime == 0.0 || entity.Comp.CurrentlyCrushing.Count != 0) return; _animationSystem.Play(entity, (Animation)entity.Comp.ClosingAnimation, DoorComponent.AnimationKey); return; case DoorState.Denying: _animationSystem.Play(entity, (Animation)entity.Comp.DenyingAnimation, DoorComponent.AnimationKey); return; case DoorState.Emagging: _animationSystem.Play(entity, (Animation)entity.Comp.EmaggingAnimation, DoorComponent.AnimationKey); return; } } private void UpdateSpriteLayers(SpriteComponent sprite, string baseRsi) { if (!_resourceCache.TryGetResource(SpriteSpecifierSerializer.TextureRoot / baseRsi, out var res)) { Log.Error("Unable to load RSI '{0}'. Trace:\n{1}", baseRsi, Environment.StackTrace); return; } sprite.BaseRSI = res.RSI; } }