using Content.Server.Power.Components; using Content.Shared._NF.CrateMachine; using AppearanceSystem = Robust.Server.GameObjects.AppearanceSystem; using CrateMachineComponent = Content.Shared._NF.CrateMachine.Components.CrateMachineComponent; namespace Content.Server._NF.CrateMachine; /// /// Handles starting the opening animation. /// Updates the time remaining on the component. /// public sealed partial class CrateMachineSystem : SharedCrateMachineSystem { [Dependency] private readonly AppearanceSystem _appearanceSystem = default!; /// /// Keep track of time in this function, in order to process the animation. /// /// The current frame time public override void Update(float frameTime) { base.Update(frameTime); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var crateMachine, out var receiver)) { if (!receiver.Powered) continue; ProcessOpeningAnimation(uid, frameTime, crateMachine); ProcessClosingAnimation(uid, frameTime, crateMachine); } } /// /// Updates the time remaining for the opening animation, calls the delegate when the animation finishes, and updates the visual state. /// /// The Uid of the crate machine /// The current frame time /// The crate machine component private void ProcessOpeningAnimation(EntityUid uid, float frameTime, CrateMachineComponent comp) { if (comp.OpeningTimeRemaining <= 0) return; comp.OpeningTimeRemaining -= frameTime; // Automatically start closing after it finishes open animation. if (comp.OpeningTimeRemaining <= 0) { comp.DidTakeCrate = false; RaiseLocalEvent(uid, new CrateMachineOpenedEvent(uid)); } // Update at the end so the closing animation can start automatically. UpdateVisualState(uid, comp); } /// /// Updates the time remaining for the closing animation, calls the delegate when the animation finishes, and updates the visual state. /// /// The Uid of the crate machine /// The current frame time /// The crate machine component private void ProcessClosingAnimation(EntityUid uid, float frameTime, CrateMachineComponent comp) { if (!comp.DidTakeCrate && !IsOccupied(uid, comp, true)) { comp.DidTakeCrate = true; comp.ClosingTimeRemaining = comp.ClosingTime; } comp.ClosingTimeRemaining -= frameTime; UpdateVisualState(uid, comp); } /// /// Updates the visual state of the crate machine by setting the visual state using the appearance system. /// /// The Uid of the crate machine /// The crate machine component private void UpdateVisualState(EntityUid uid, CrateMachineComponent? component = null) { if (!Resolve(uid, ref component)) return; if (component.OpeningTimeRemaining > 0) _appearanceSystem.SetData(uid, CrateMachineVisuals.VisualState, CrateMachineVisualState.Opening); else if (component.ClosingTimeRemaining > 0) _appearanceSystem.SetData(uid, CrateMachineVisuals.VisualState, CrateMachineVisualState.Closing); else if (!component.DidTakeCrate) _appearanceSystem.SetData(uid, CrateMachineVisuals.VisualState, CrateMachineVisualState.Open); else _appearanceSystem.SetData(uid, CrateMachineVisuals.VisualState, CrateMachineVisualState.Closed); } /// /// Starts the opening animation of the crate machine and calls the delegate when the animation finishes. /// /// The Uid of the crate machine /// The crate machine component public void OpenFor(EntityUid crateMachineUid, CrateMachineComponent component) { component.OpeningTimeRemaining = component.OpeningTime; UpdateVisualState(crateMachineUid, component); } }