using Content.Shared.Interaction; using Robust.Shared.Random; using Content.Shared._Sunrise.Fun; using Content.Shared.Popups; using Content.Shared.Hands; using Content.Shared.Verbs; using Content.Shared.Ghost; namespace Content.Server._Sunrise.Fun { public sealed partial class SpinnerSystem : EntitySystem { [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly SharedTransformSystem _xform = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnActivateInWorld); SubscribeLocalEvent(OnGotEquippedHand); SubscribeLocalEvent>(OnAlternativeInteract); } private void OnAlternativeInteract(Entity ent, ref GetVerbsEvent args) { if (CompOrNull(args.User) is not null || CompOrNull(ent) is null) return; HandleSpinnerActivation(ent, args.User); } private void OnGotEquippedHand(Entity ent, ref GotEquippedHandEvent args) { ent.Comp.IsSpinning = false; ent.Comp.RemainingSeconds = 0f; ent.Comp.CurrentDegPerSec = 0f; Dirty(ent, ent.Comp); return; } private void OnActivateInWorld(Entity ent, ref ActivateInWorldEvent args) { var transformComp = CompOrNull(ent); if (transformComp is null || !transformComp.Anchored) return; HandleSpinnerActivation(ent, args.User); } private void HandleSpinnerActivation(Entity ent, EntityUid userId) { var userName = CompOrNull(userId)?.EntityName; if (!ent.Comp.IsSpinning) { StartSpin(ent, ent.Comp); _popupSystem.PopupEntity($"{userName} {Loc.GetString("arrow-spin-start")}", userId); return; } if (ent.Comp.RemainingSeconds > ent.Comp.MaxSpinSeconds) return; if (ent.Comp.CurrentDegPerSec > ent.Comp.MaxDegPerSec) return; var seconds = _random.NextFloat(ent.Comp.MinSpinSeconds, ent.Comp.MaxSpinSeconds); var degPerSec = _random.NextFloat(ent.Comp.MinDegPerSec, ent.Comp.MaxDegPerSec); ent.Comp.RemainingSeconds += seconds; ent.Comp.CurrentDegPerSec += degPerSec; _popupSystem.PopupEntity($"{userName} {Loc.GetString("arrow-speed-up")}", userId); Dirty(ent, ent.Comp); } private void StartSpin(EntityUid uid, SpinnerComponent comp) { var seconds = _random.NextFloat(comp.MinSpinSeconds, comp.MaxSpinSeconds); var degPerSec = _random.NextFloat(comp.MinDegPerSec, comp.MaxDegPerSec); comp.IsSpinning = true; comp.RemainingSeconds = seconds; comp.CurrentDegPerSec = degPerSec; Dirty(uid, comp); } public override void Update(float frameTime) { base.Update(frameTime); var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out var comp, out var xform)) { if (!comp.IsSpinning) continue; var dt = frameTime; var deltaDeg = comp.CurrentDegPerSec * dt; var newAngle = xform.LocalRotation.Degrees + deltaDeg; _xform.SetLocalRotation(uid, Angle.FromDegrees(newAngle)); comp.RemainingSeconds -= dt; if (comp.RemainingSeconds <= 0f) { comp.CurrentDegPerSec *= comp.BrakeFactor; if (MathF.Abs(comp.CurrentDegPerSec) < comp.ForceStopSpeed) { comp.IsSpinning = false; comp.CurrentDegPerSec = 0f; comp.RemainingSeconds = 0f; Dirty(uid, comp); continue; } } if (comp.RemainingSeconds > 0f && comp.RemainingSeconds < comp.SmoothStopAtSecond) comp.CurrentDegPerSec *= comp.SmoothStopBrakeFactor; Dirty(uid, comp); } } } }