using Content.Server.Actions; using Content.Shared._White.Wizard; using Content.Shared._White.Wizard.Charging; using Content.Shared.Actions; using Content.Shared.Follower; using Content.Shared.Mobs; using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Player; namespace Content.Server._White.Wizard.Charging; public sealed class ChargingSystem : SharedChargingSystem { [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly FollowerSystem _followerSystem = default!; [Dependency] private readonly ActionsSystem _actionsSystem = default!; private readonly Dictionary> _charges = new(); private readonly Dictionary _chargingLoops = new(); private readonly Dictionary _chargedLoop = new(); public override void Initialize() { base.Initialize(); SubscribeNetworkEvent(OnCharging); SubscribeNetworkEvent(OnCharged); SubscribeNetworkEvent(OnStop); SubscribeLocalEvent(OnDetach); SubscribeLocalEvent(OnStateChanged); SubscribeNetworkEvent(Add); SubscribeNetworkEvent(Remove); } #region Audio private void OnCharging(RequestSpellChargingAudio msg, EntitySessionEventArgs args) { var user = args.SenderSession?.AttachedEntity; if (user == null) return; var shouldLoop = msg.Loop; var sound = msg.Sound; if (!shouldLoop) { _audio.PlayPvs(sound, user.Value); return; } if (_chargingLoops.TryGetValue(user.Value, out var currentStream)) { _audio.Stop(currentStream); _chargingLoops.Remove(user.Value); } var newStream = _audio.PlayPvs(sound, user.Value, AudioParams.Default.WithLoop(true)); if (newStream.HasValue) { _chargingLoops[user.Value] = newStream.Value.Entity; } } private void OnCharged(RequestSpellChargedAudio msg, EntitySessionEventArgs args) { var user = args.SenderSession?.AttachedEntity; if (user == null) return; if (_chargingLoops.TryGetValue(user.Value, out var currentStream)) { _audio.Stop(currentStream); _chargingLoops.Remove(user.Value); } var shouldLoop = msg.Loop; var sound = msg.Sound; if (!shouldLoop) { _audio.PlayPvs(sound, user.Value); return; } if (_chargedLoop.TryGetValue(user.Value, out var chargedLoop)) { _audio.Stop(chargedLoop); _chargedLoop.Remove(user.Value); } var newStream = _audio.PlayPvs(sound, user.Value, AudioParams.Default.WithLoop(true)); if (newStream.HasValue) { _chargedLoop[user.Value] = newStream.Value.Entity; } } private void OnStop(RequestAudioSpellStop msg, EntitySessionEventArgs args) { var user = args.SenderSession?.AttachedEntity; if (user == null) return; StopAllSounds(user.Value); } #endregion #region Charges private void OnDetach(PlayerDetachedEvent msg) { var user = msg.Entity; RemoveAllCharges(user); StopAllSounds(user); } private void OnStateChanged(MobStateChangedEvent ev) { var user = ev.Target; RemoveAllCharges(user); StopAllSounds(user); } private void Add(AddWizardChargeEvent msg, EntitySessionEventArgs args) { var spell = GetEntity(msg.Spell); if (!_actionsSystem.TryGetActionData(spell, out var baseAction) || baseAction is not BaseTargetActionComponent action || !action.IsChargeEnabled) { return; } if (args.SenderSession.AttachedEntity != null) AddCharge(args.SenderSession.AttachedEntity.Value, action.ChargeProto); } private void Remove(RemoveWizardChargeEvent msg, EntitySessionEventArgs args) { if (args.SenderSession.AttachedEntity != null) RemoveAllCharges(args.SenderSession.AttachedEntity.Value); } #endregion #region Helpers public void StopAllSounds(EntityUid uid) { if (_chargingLoops.TryGetValue(uid, out var currentStream)) { _audio.Stop(currentStream); _chargingLoops.Remove(uid); } if (_chargedLoop.TryGetValue(uid, out var chargedLoop)) { _audio.Stop(chargedLoop); _chargedLoop.Remove(uid); } } public void AddCharge(EntityUid uid, string msgChargeProto) { var itemEnt = Spawn(msgChargeProto, Transform(uid).Coordinates); _followerSystem.StartFollowingEntity(itemEnt, uid); if (!_charges.ContainsKey(uid)) { _charges[uid] = new List(); } _charges[uid].Add(itemEnt); } public void RemoveAllCharges(EntityUid uid) { if (!_charges.ContainsKey(uid)) return; foreach (var followerEnt in _charges[uid]) { Del(followerEnt); } _charges.Remove(uid); } #endregion }