using Content.Server.Buckle.Components; using Content.Shared.Vehicle.Components; using Content.Shared.Vehicle; using Content.Shared.Buckle.Components; using Content.Shared.Movement.Components; using Content.Shared.Containers.ItemSlots; using Content.Shared.Actions; using Content.Shared.Audio; using Content.Server.Light.Components; using Content.Server.Hands.Systems; using Content.Shared.Tag; using Content.Shared.Movement.Systems; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.Physics; using Robust.Shared.Physics.Systems; using Robust.Shared.Player; using DrawDepth = Content.Shared.DrawDepth.DrawDepth; namespace Content.Server.Vehicle { public sealed partial class VehicleSystem : SharedVehicleSystem { [Dependency] private readonly HandVirtualItemSystem _virtualItemSystem = default!; [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; [Dependency] private readonly SharedJointSystem _joints = default!; [Dependency] private readonly SharedMoverController _mover = default!; public override void Initialize() { base.Initialize(); InitializeRider(); SubscribeLocalEvent(OnHonk); SubscribeLocalEvent(OnBuckleChange); } /// /// This fires when the rider presses the honk action /// private void OnHonk(EntityUid uid, VehicleComponent vehicle, HonkActionEvent args) { if (args.Handled || vehicle.HornSound == null) return; // TODO: Need audio refactor maybe, just some way to null it when the stream is over. // For now better to just not loop to keep the code much cleaner. vehicle.HonkPlayingStream?.Stop(); vehicle.HonkPlayingStream = SoundSystem.Play(vehicle.HornSound.GetSound(), Filter.Pvs(uid), uid, vehicle.HornSound.Params); args.Handled = true; } /// /// This just controls whether the wheels are turning. /// public override void Update(float frameTime) { foreach (var (vehicle, mover) in EntityQuery()) { if (_mover.GetVelocityInput(mover).Sprinting == Vector2.Zero) { UpdateAutoAnimate(vehicle.Owner, false); continue; } UpdateAutoAnimate(vehicle.Owner, true); } } /// /// Give the user the rider component if they're buckling to the vehicle, /// otherwise remove it. /// private void OnBuckleChange(EntityUid uid, VehicleComponent component, BuckleChangeEvent args) { // Add Rider if (args.Buckling) { // Add a virtual item to rider's hand, unbuckle if we can't. if (!_virtualItemSystem.TrySpawnVirtualItemInHand(uid, args.BuckledEntity)) { UnbuckleFromVehicle(args.BuckledEntity); return; } // Set up the rider and vehicle with each other EnsureComp(uid); var rider = EnsureComp(args.BuckledEntity); component.Rider = args.BuckledEntity; var relay = EnsureComp(args.BuckledEntity); _mover.SetRelay(args.BuckledEntity, uid, relay); rider.Vehicle = uid; // Update appearance stuff, add actions UpdateBuckleOffset(Transform(uid), component); UpdateDrawDepth(uid, GetDrawDepth(Transform(uid), component.NorthOnly)); if (TryComp(args.BuckledEntity, out var actions) && TryComp(uid, out var flashlight)) { _actionsSystem.AddAction(args.BuckledEntity, flashlight.ToggleAction, uid, actions); } if (component.HornSound != null) { _actionsSystem.AddAction(args.BuckledEntity, component.HornAction, uid, actions); } _joints.ClearJoints(args.BuckledEntity); return; } // Remove rider // Clean up actions and virtual items _actionsSystem.RemoveProvidedActions(args.BuckledEntity, uid); _virtualItemSystem.DeleteInHandsMatching(args.BuckledEntity, uid); // Entity is no longer riding RemComp(args.BuckledEntity); RemComp(args.BuckledEntity); // Reset component component.Rider = null; } } }