Jumpability collisions (#39710)
This commit is contained in:
16
Content.Shared/Movement/Components/ActiveLeaperComponent.cs
Normal file
16
Content.Shared/Movement/Components/ActiveLeaperComponent.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared.Movement.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marker component given to the users of the <see cref="JumpAbilityComponent"/> if they are meant to collide with environment.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
public sealed partial class ActiveLeaperComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The duration to stun the owner on collide with environment.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public TimeSpan KnockdownDuration;
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ using Content.Shared.Actions;
|
|||||||
using Content.Shared.Movement.Systems;
|
using Content.Shared.Movement.Systems;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Shared.Movement.Components;
|
namespace Content.Shared.Movement.Components;
|
||||||
|
|
||||||
@@ -13,6 +14,18 @@ namespace Content.Shared.Movement.Components;
|
|||||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedJumpAbilitySystem))]
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(SharedJumpAbilitySystem))]
|
||||||
public sealed partial class JumpAbilityComponent : Component
|
public sealed partial class JumpAbilityComponent : Component
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The action prototype that allows you to jump.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public EntProtoId Action = "ActionGravityJump";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Entity to hold the action prototype.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntityUid? ActionEntity;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// How far you will jump (in tiles).
|
/// How far you will jump (in tiles).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -25,11 +38,29 @@ public sealed partial class JumpAbilityComponent : Component
|
|||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public float JumpThrowSpeed = 10f;
|
public float JumpThrowSpeed = 10f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this entity can collide with another entity, leading to it getting knocked down.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public bool CanCollide = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The duration of the knockdown in case of a collision from CanCollide.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public TimeSpan CollideKnockdown = TimeSpan.FromSeconds(2);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This gets played whenever the jump action is used.
|
/// This gets played whenever the jump action is used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField, AutoNetworkedField]
|
[DataField, AutoNetworkedField]
|
||||||
public SoundSpecifier? JumpSound;
|
public SoundSpecifier? JumpSound;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The popup to show if the entity is unable to perform a jump.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public LocId? JumpFailedPopup = "jump-ability-failure";
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed partial class GravityJumpEvent : InstantActionEvent;
|
public sealed partial class GravityJumpEvent : InstantActionEvent;
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.Actions.Components;
|
||||||
|
using Content.Shared.Cloning.Events;
|
||||||
using Content.Shared.Gravity;
|
using Content.Shared.Gravity;
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Standing;
|
||||||
|
using Content.Shared.Stunnable;
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
using Robust.Shared.Audio.Systems;
|
using Robust.Shared.Audio.Systems;
|
||||||
|
using Robust.Shared.Physics.Events;
|
||||||
|
|
||||||
namespace Content.Shared.Movement.Systems;
|
namespace Content.Shared.Movement.Systems;
|
||||||
|
|
||||||
@@ -10,18 +17,64 @@ public sealed partial class SharedJumpAbilitySystem : EntitySystem
|
|||||||
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
[Dependency] private readonly SharedGravitySystem _gravity = default!;
|
[Dependency] private readonly SharedGravitySystem _gravity = default!;
|
||||||
|
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||||
|
[Dependency] private readonly SharedStunSystem _stun = default!;
|
||||||
|
[Dependency] private readonly StandingStateSystem _standing = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<JumpAbilityComponent, MapInitEvent>(OnInit);
|
||||||
|
SubscribeLocalEvent<JumpAbilityComponent, ComponentShutdown>(OnShutdown);
|
||||||
|
|
||||||
SubscribeLocalEvent<JumpAbilityComponent, GravityJumpEvent>(OnGravityJump);
|
SubscribeLocalEvent<JumpAbilityComponent, GravityJumpEvent>(OnGravityJump);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ActiveLeaperComponent, StartCollideEvent>(OnLeaperCollide);
|
||||||
|
SubscribeLocalEvent<ActiveLeaperComponent, LandEvent>(OnLeaperLand);
|
||||||
|
SubscribeLocalEvent<ActiveLeaperComponent, StopThrowEvent>(OnLeaperStopThrow);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<JumpAbilityComponent, CloningEvent>(OnClone);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInit(Entity<JumpAbilityComponent> entity, ref MapInitEvent args)
|
||||||
|
{
|
||||||
|
if (!TryComp(entity, out ActionsComponent? comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_actions.AddAction(entity, ref entity.Comp.ActionEntity, entity.Comp.Action, component: comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnShutdown(Entity<JumpAbilityComponent> entity, ref ComponentShutdown args)
|
||||||
|
{
|
||||||
|
_actions.RemoveAction(entity.Owner, entity.Comp.ActionEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLeaperCollide(Entity<ActiveLeaperComponent> entity, ref StartCollideEvent args)
|
||||||
|
{
|
||||||
|
_stun.TryKnockdown(entity.Owner, entity.Comp.KnockdownDuration, force: true);
|
||||||
|
RemCompDeferred<ActiveLeaperComponent>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLeaperLand(Entity<ActiveLeaperComponent> entity, ref LandEvent args)
|
||||||
|
{
|
||||||
|
RemCompDeferred<ActiveLeaperComponent>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLeaperStopThrow(Entity<ActiveLeaperComponent> entity, ref StopThrowEvent args)
|
||||||
|
{
|
||||||
|
RemCompDeferred<ActiveLeaperComponent>(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnGravityJump(Entity<JumpAbilityComponent> entity, ref GravityJumpEvent args)
|
private void OnGravityJump(Entity<JumpAbilityComponent> entity, ref GravityJumpEvent args)
|
||||||
{
|
{
|
||||||
if (_gravity.IsWeightless(args.Performer))
|
if (_gravity.IsWeightless(args.Performer) || _standing.IsDown(args.Performer))
|
||||||
|
{
|
||||||
|
if (entity.Comp.JumpFailedPopup != null)
|
||||||
|
_popup.PopupClient(Loc.GetString(entity.Comp.JumpFailedPopup.Value), args.Performer, args.Performer);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var xform = Transform(args.Performer);
|
var xform = Transform(args.Performer);
|
||||||
var throwing = xform.LocalRotation.ToWorldVec() * entity.Comp.JumpDistance;
|
var throwing = xform.LocalRotation.ToWorldVec() * entity.Comp.JumpDistance;
|
||||||
@@ -30,6 +83,29 @@ public sealed partial class SharedJumpAbilitySystem : EntitySystem
|
|||||||
_throwing.TryThrow(args.Performer, direction, entity.Comp.JumpThrowSpeed);
|
_throwing.TryThrow(args.Performer, direction, entity.Comp.JumpThrowSpeed);
|
||||||
|
|
||||||
_audio.PlayPredicted(entity.Comp.JumpSound, args.Performer, args.Performer);
|
_audio.PlayPredicted(entity.Comp.JumpSound, args.Performer, args.Performer);
|
||||||
|
|
||||||
|
if (entity.Comp.CanCollide)
|
||||||
|
{
|
||||||
|
EnsureComp<ActiveLeaperComponent>(entity, out var leaperComp);
|
||||||
|
leaperComp.KnockdownDuration = entity.Comp.CollideKnockdown;
|
||||||
|
Dirty(entity.Owner, leaperComp);
|
||||||
|
}
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnClone(Entity<JumpAbilityComponent> ent, ref CloningEvent args)
|
||||||
|
{
|
||||||
|
if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var targetComp = Factory.GetComponent<JumpAbilityComponent>();
|
||||||
|
targetComp.Action = ent.Comp.Action;
|
||||||
|
targetComp.CanCollide = ent.Comp.CanCollide;
|
||||||
|
targetComp.JumpSound = ent.Comp.JumpSound;
|
||||||
|
targetComp.CollideKnockdown = ent.Comp.CollideKnockdown;
|
||||||
|
targetComp.JumpDistance = ent.Comp.JumpDistance;
|
||||||
|
targetComp.JumpThrowSpeed = ent.Comp.JumpThrowSpeed;
|
||||||
|
AddComp(args.CloneUid, targetComp, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
Resources/Locale/en-US/jump-ability/jump-ability.ftl
Normal file
1
Resources/Locale/en-US/jump-ability/jump-ability.ftl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
jump-ability-failure = You cannot jump right now.
|
||||||
@@ -121,6 +121,7 @@
|
|||||||
- Rootable # diona
|
- Rootable # diona
|
||||||
- Sericulture # arachnids
|
- Sericulture # arachnids
|
||||||
- MovementSpeedModifier # moths when weightless
|
- MovementSpeedModifier # moths when weightless
|
||||||
|
- JumpAbility # vulp leaping
|
||||||
copyEquipment: null
|
copyEquipment: null
|
||||||
copyInternalStorage: false
|
copyInternalStorage: false
|
||||||
copyImplants: false
|
copyImplants: false
|
||||||
|
|||||||
Reference in New Issue
Block a user