The real movement refactor (#9645)
* The real movement refactor * ref events * Jetpack cleanup * a * Vehicles partially working * Balance tweaks * Restore some shitcode * AAAAAAAA * Even more prediction * ECS compstate trying to fix this * yml * vehicles kill me * Don't lock keys * a * Fix problem * Fix sounds * shuttle inputs * Shuttle controls * space brakes * Keybinds * Fix merge * Handle shutdown * Fix keys * Bump friction * fix buckle offset * Fix relay and friction * Fix jetpack turning * contexts amirite
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Vehicle.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Added to objects inside a vehicle to stop people besides the rider from
|
||||
/// removing them.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed class InVehicleComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The vehicle this rider is currently riding.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public VehicleComponent Vehicle = default!;
|
||||
[ViewVariables] public VehicleComponent? Vehicle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Vehicle.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Added to people when they are riding in a vehicle
|
||||
/// used mostly to keep track of them for entityquery.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed class RiderComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The vehicle this rider is currently riding.
|
||||
/// </summary>
|
||||
[ViewVariables] public VehicleComponent? Vehicle;
|
||||
[ViewVariables] public EntityUid? Vehicle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Content.Shared.Actions.ActionTypes;
|
||||
using Content.Shared.Sound;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -17,7 +16,7 @@ namespace Content.Shared.Vehicle.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether someone is currently riding the vehicle
|
||||
/// </summary
|
||||
/// </summary>
|
||||
public bool HasRider = false;
|
||||
|
||||
/// <summary>
|
||||
@@ -27,7 +26,47 @@ namespace Content.Shared.Vehicle.Components
|
||||
public EntityUid? Rider;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the vehicle should treat north as it's unique direction in its visualizer
|
||||
/// The base offset for the vehicle (when facing east)
|
||||
/// </summary>
|
||||
public Vector2 BaseBuckleOffset = Vector2.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// The sound that the horn makes
|
||||
/// </summary>
|
||||
[DataField("hornSound")] public SoundSpecifier? HornSound =
|
||||
new SoundPathSpecifier("/Audio/Effects/Vehicle/carhorn.ogg")
|
||||
{
|
||||
Params =
|
||||
{
|
||||
Volume = -3f,
|
||||
}
|
||||
};
|
||||
|
||||
public IPlayingAudioStream? HonkPlayingStream;
|
||||
|
||||
/// Use ambient sound component for the idle sound.
|
||||
|
||||
/// <summary>
|
||||
/// The action for the horn (if any)
|
||||
/// </summary>
|
||||
[DataField("hornAction")]
|
||||
public InstantAction HornAction = new()
|
||||
{
|
||||
UseDelay = TimeSpan.FromSeconds(3.4),
|
||||
Icon = new SpriteSpecifier.Texture(new ResourcePath("Objects/Fun/bikehorn.rsi/icon.png")),
|
||||
Name = "action-name-honk",
|
||||
Description = "action-desc-honk",
|
||||
Event = new HonkActionEvent(),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Whether the vehicle has a key currently inside it or not.
|
||||
/// </summary>
|
||||
public bool HasKey = false;
|
||||
|
||||
// TODO: Fix this
|
||||
/// <summary>
|
||||
/// Whether the vehicle should treat north as its unique direction in its visualizer
|
||||
/// </summary>
|
||||
[DataField("northOnly")]
|
||||
public bool NorthOnly = false;
|
||||
@@ -43,55 +82,5 @@ namespace Content.Shared.Vehicle.Components
|
||||
/// </summary>
|
||||
[DataField("southOverride")]
|
||||
public float SouthOverride = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// The base offset for the vehicle (when facing east)
|
||||
/// </summary>
|
||||
public Vector2 BaseBuckleOffset = Vector2.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// The sound that the horn makes
|
||||
/// </summary>
|
||||
[DataField("hornSound")]
|
||||
public SoundSpecifier? HornSound = new SoundPathSpecifier("/Audio/Effects/Vehicle/carhorn.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// Whether the horn is a siren or not.
|
||||
/// </summary>
|
||||
[DataField("hornIsSiren")]
|
||||
public bool HornIsLooping = false;
|
||||
|
||||
/// <summary>
|
||||
/// If this vehicle has a siren currently playing.
|
||||
/// </summary>
|
||||
public bool LoopingHornIsPlaying = false;
|
||||
|
||||
public IPlayingAudioStream? SirenPlayingStream;
|
||||
|
||||
/// Use ambient sound component for the idle sound.
|
||||
|
||||
/// <summary>
|
||||
/// The action for the horn (if any)
|
||||
/// </summary>
|
||||
[DataField("hornAction")]
|
||||
public InstantAction HornAction = new()
|
||||
{
|
||||
UseDelay = TimeSpan.FromSeconds(3.4),
|
||||
Icon = new SpriteSpecifier.Texture(new ResourcePath("Objects/Fun/bikehorn.rsi/icon.png")),
|
||||
Name = "action-name-honk",
|
||||
Description = "action-desc-honk",
|
||||
Event = new HonkActionEvent(),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The prototype ID of the key that was inserted so it can be
|
||||
/// spawned when the key is removed.
|
||||
/// </summary>
|
||||
public ItemSlot KeySlot = new();
|
||||
|
||||
/// <summary>
|
||||
/// Whether the vehicle has a key currently inside it or not.
|
||||
/// </summary>
|
||||
public bool HasKey = false;
|
||||
}
|
||||
}
|
||||
|
||||
20
Content.Shared/Vehicle/SharedVehicleSystem.Rider.cs
Normal file
20
Content.Shared/Vehicle/SharedVehicleSystem.Rider.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Content.Shared.Physics.Pull;
|
||||
using Content.Shared.Vehicle.Components;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Vehicle;
|
||||
|
||||
public abstract partial class SharedVehicleSystem
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
protected sealed class RiderComponentState : ComponentState
|
||||
{
|
||||
public EntityUid? Entity;
|
||||
}
|
||||
|
||||
private void OnRiderPull(EntityUid uid, RiderComponent component, PullAttemptEvent args)
|
||||
{
|
||||
if (component.Vehicle != null)
|
||||
args.Cancelled = true;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +1,174 @@
|
||||
using Content.Shared.Vehicle.Components;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared.Movement.Systems;
|
||||
using Content.Shared.Physics.Pull;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Vehicle;
|
||||
|
||||
/// <summary>
|
||||
/// Stores the VehicleVisuals and shared event
|
||||
/// Nothing for a system but these need to be put somewhere in
|
||||
/// Content.Shared
|
||||
/// </summary>
|
||||
namespace Content.Shared.Vehicle
|
||||
public abstract partial class SharedVehicleSystem : EntitySystem
|
||||
{
|
||||
public sealed class SharedVehicleSystem : EntitySystem
|
||||
[Dependency] private readonly MovementSpeedModifierSystem _modifier = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<InVehicleComponent, GettingPickedUpAttemptEvent>(OnPickupAttempt);
|
||||
}
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<InVehicleComponent, GettingPickedUpAttemptEvent>(OnPickupAttempt);
|
||||
SubscribeLocalEvent<RiderComponent, PullAttemptEvent>(OnRiderPull);
|
||||
SubscribeLocalEvent<VehicleComponent, RefreshMovementSpeedModifiersEvent>(OnVehicleModifier);
|
||||
SubscribeLocalEvent<VehicleComponent, ComponentStartup>(OnVehicleStartup);
|
||||
SubscribeLocalEvent<VehicleComponent, RotateEvent>(OnVehicleRotate);
|
||||
}
|
||||
|
||||
private void OnPickupAttempt(EntityUid uid, InVehicleComponent component, GettingPickedUpAttemptEvent args)
|
||||
private void OnVehicleModifier(EntityUid uid, VehicleComponent component, RefreshMovementSpeedModifiersEvent args)
|
||||
{
|
||||
if (!component.HasKey)
|
||||
{
|
||||
if (component.Vehicle == null || !component.Vehicle.HasRider)
|
||||
return;
|
||||
|
||||
if (component.Vehicle.Rider != args.User)
|
||||
args.Cancel();
|
||||
args.ModifySpeed(0f, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Stores the vehicle's draw depth mostly
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public enum VehicleVisuals : byte
|
||||
private void OnPickupAttempt(EntityUid uid, InVehicleComponent component, GettingPickedUpAttemptEvent args)
|
||||
{
|
||||
/// <summary>
|
||||
/// What layer the vehicle should draw on (assumed integer)
|
||||
/// </summary>
|
||||
DrawDepth,
|
||||
/// <summary>
|
||||
/// Whether the wheels should be turning
|
||||
/// </summary>
|
||||
AutoAnimate
|
||||
if (component.Vehicle == null || component.Vehicle.Rider != null && component.Vehicle.Rider != args.User)
|
||||
args.Cancel();
|
||||
}
|
||||
/// <summary>
|
||||
/// Raised when someone honks a vehicle horn
|
||||
/// </summary>
|
||||
public sealed class HonkActionEvent : InstantActionEvent { }
|
||||
|
||||
/// <summary>
|
||||
/// Raised on the rider when someone is buckled to a vehicle.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class BuckledToVehicleEvent : EntityEventArgs
|
||||
// TODO: Shitcode, needs to use sprites instead of actual offsets.
|
||||
private void OnVehicleRotate(EntityUid uid, VehicleComponent component, ref RotateEvent args)
|
||||
{
|
||||
public EntityUid Vehicle;
|
||||
|
||||
public EntityUid Rider;
|
||||
|
||||
/// <summary>
|
||||
/// Whether they were buckled or unbuckled
|
||||
/// </summary>
|
||||
public bool Buckling;
|
||||
public BuckledToVehicleEvent(EntityUid vehicle, EntityUid rider, bool buckling)
|
||||
// This first check is just for safety
|
||||
if (!HasComp<InputMoverComponent>(uid))
|
||||
{
|
||||
Vehicle = vehicle;
|
||||
Rider = rider;
|
||||
Buckling = buckling;
|
||||
UpdateAutoAnimate(uid, false);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateBuckleOffset(args.Component, component);
|
||||
UpdateDrawDepth(uid, GetDrawDepth(args.Component, component.NorthOnly));
|
||||
}
|
||||
|
||||
private void OnVehicleStartup(EntityUid uid, VehicleComponent component, ComponentStartup args)
|
||||
{
|
||||
UpdateDrawDepth(uid, 2);
|
||||
|
||||
// This code should be purged anyway but with that being said this doesn't handle components being changed.
|
||||
if (TryComp<SharedStrapComponent>(uid, out var strap))
|
||||
{
|
||||
component.BaseBuckleOffset = strap.BuckleOffset;
|
||||
strap.BuckleOffsetUnclamped = Vector2.Zero;
|
||||
}
|
||||
|
||||
_modifier.RefreshMovementSpeedModifiers(uid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Depending on which direction the vehicle is facing,
|
||||
/// change its draw depth. Vehicles can choose between special drawdetph
|
||||
/// when facing north or south. East and west are easy.
|
||||
/// </summary>
|
||||
protected int GetDrawDepth(TransformComponent xform, bool northOnly)
|
||||
{
|
||||
// TODO: I can't even
|
||||
if (northOnly)
|
||||
{
|
||||
return xform.LocalRotation.Degrees switch
|
||||
{
|
||||
< 135f => (int) DrawDepth.DrawDepth.Doors,
|
||||
<= 225f => (int) DrawDepth.DrawDepth.WallMountedItems,
|
||||
_ => 5
|
||||
};
|
||||
}
|
||||
return xform.LocalRotation.Degrees switch
|
||||
{
|
||||
< 45f => (int) DrawDepth.DrawDepth.Doors,
|
||||
<= 315f => (int) DrawDepth.DrawDepth.WallMountedItems,
|
||||
_ => (int) DrawDepth.DrawDepth.Doors,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change the buckle offset based on what direction the vehicle is facing and
|
||||
/// teleport any buckled entities to it. This is the most crucial part of making
|
||||
/// buckled vehicles work.
|
||||
/// </summary>
|
||||
protected void UpdateBuckleOffset(TransformComponent xform, VehicleComponent component)
|
||||
{
|
||||
if (!TryComp<SharedStrapComponent>(component.Owner, out var strap))
|
||||
return;
|
||||
|
||||
// TODO: Strap should handle this but buckle E/C moment.
|
||||
var oldOffset = strap.BuckleOffsetUnclamped;
|
||||
|
||||
strap.BuckleOffsetUnclamped = xform.LocalRotation.Degrees switch
|
||||
{
|
||||
< 45f => (0, component.SouthOverride),
|
||||
<= 135f => component.BaseBuckleOffset,
|
||||
< 225f => (0, component.NorthOverride),
|
||||
<= 315f => (component.BaseBuckleOffset.X * -1, component.BaseBuckleOffset.Y),
|
||||
_ => (0, component.SouthOverride)
|
||||
};
|
||||
|
||||
if (!oldOffset.Equals(strap.BuckleOffsetUnclamped))
|
||||
Dirty(strap);
|
||||
|
||||
foreach (var buckledEntity in strap.BuckledEntities)
|
||||
{
|
||||
var buckleXform = Transform(buckledEntity);
|
||||
_transform.SetLocalPositionNoLerp(buckleXform, strap.BuckleOffset);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the draw depth for the sprite.
|
||||
/// </summary>
|
||||
protected void UpdateDrawDepth(EntityUid uid, int drawDepth)
|
||||
{
|
||||
if (!TryComp<AppearanceComponent>(uid, out var appearance))
|
||||
return;
|
||||
|
||||
appearance.SetData(VehicleVisuals.DrawDepth, drawDepth);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set whether the vehicle's base layer is animating or not.
|
||||
/// </summary>
|
||||
protected void UpdateAutoAnimate(EntityUid uid, bool autoAnimate)
|
||||
{
|
||||
if (!TryComp<AppearanceComponent>(uid, out var appearance))
|
||||
return;
|
||||
|
||||
appearance.SetData(VehicleVisuals.AutoAnimate, autoAnimate);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the vehicle's draw depth mostly
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public enum VehicleVisuals : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// What layer the vehicle should draw on (assumed integer)
|
||||
/// </summary>
|
||||
DrawDepth,
|
||||
/// <summary>
|
||||
/// Whether the wheels should be turning
|
||||
/// </summary>
|
||||
AutoAnimate
|
||||
}
|
||||
/// <summary>
|
||||
/// Raised when someone honks a vehicle horn
|
||||
/// </summary>
|
||||
public sealed class HonkActionEvent : InstantActionEvent { }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user