lay down + scope (#476)

* remove old system

* new scope, new laying
This commit is contained in:
haiwwkes 2024-10-11 13:52:39 +05:00 committed by GitHub
parent faea6bced4
commit 40568a243c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 689 additions and 232 deletions

View file

@ -58,17 +58,11 @@ internal sealed class BuckleSystem : SharedBuckleSystem
private void OnAppearanceChange(EntityUid uid, BuckleComponent component, ref AppearanceChangeEvent args)
{
if (!TryComp<RotationVisualsComponent>(uid, out var rotVisuals))
if (!TryComp<RotationVisualsComponent>(uid, out var rotVisuals)
|| !Appearance.TryGetData<bool>(uid, BuckleVisuals.Buckled, out var buckled, args.Component)
|| !buckled || args.Sprite == null)
return;
if (!Appearance.TryGetData<bool>(uid, BuckleVisuals.Buckled, out var buckled, args.Component) ||
!buckled ||
args.Sprite == null)
{
_rotationVisualizerSystem.SetHorizontalAngle((uid, rotVisuals), rotVisuals.DefaultRotation);
return;
}
// Animate strapping yourself to something at a given angle
// TODO: Dump this when buckle is better
_rotationVisualizerSystem.AnimateSpriteRotation(uid, args.Sprite, rotVisuals.HorizontalRotation, 0.125f);

View file

@ -85,9 +85,10 @@ namespace Content.Client.Input
human.AddFunction(ContentKeyFunctions.Arcade2);
human.AddFunction(ContentKeyFunctions.Arcade3);
// Sunrise LieDown
human.AddFunction(Shared._Sunrise.KeyFunctions.LieDown);
// Sunrise LieDown
// Sunrise
human.AddFunction(ContentKeyFunctions.ToggleStanding);
human.AddFunction(ContentKeyFunctions.LookUp);
// Sunrise
// actions should be common (for ghosts, mobs, etc)
common.AddFunction(ContentKeyFunctions.OpenActionsMenu);

View file

@ -97,6 +97,20 @@ namespace Content.Client.Options.UI.Tabs
_deferCommands.Add(_inputManager.SaveToUserData);
}
// Sunrise
private void HandleHoldLookUp(BaseButton.ButtonToggledEventArgs args)
{
_cfg.SetCVar(CCVars.HoldLookUp, args.Pressed);
_cfg.SaveToFile();
}
private void HandleToggleAutoGetUp(BaseButton.ButtonToggledEventArgs args)
{
_cfg.SetCVar(CCVars.AutoGetUp, args.Pressed);
_cfg.SaveToFile();
}
// Sunrise
private void HandleStaticStorageUI(BaseButton.ButtonToggledEventArgs args)
{
_cfg.SetCVar(CCVars.StaticStorageUI, args.Pressed);
@ -185,9 +199,12 @@ namespace Content.Client.Options.UI.Tabs
AddButton(ContentKeyFunctions.RotateStoredItem);
AddButton(ContentKeyFunctions.SaveItemLocation);
// Sunrise LieDown
AddButton(Shared._Sunrise.KeyFunctions.LieDown);
// Sunrise LieDown
// Sunrise
AddButton(ContentKeyFunctions.ToggleStanding);
AddButton(ContentKeyFunctions.LookUp);
AddCheckBox("ui-options-function-auto-get-up", _cfg.GetCVar(CCVars.AutoGetUp), HandleToggleAutoGetUp);
AddCheckBox("ui-options-function-hold-look-up", _cfg.GetCVar(CCVars.HoldLookUp), HandleHoldLookUp);
// Sunrise
AddHeader("ui-options-header-interaction-adv");
AddButton(ContentKeyFunctions.SmartEquipBackpack);

View file

@ -0,0 +1,74 @@
using Content.Shared.ActionBlocker;
using Content.Shared.Buckle;
using Content.Shared.Rotation;
using Content.Shared.Standing;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Shared.Timing;
namespace Content.Client.Standing;
public sealed class LayingDownSystem : SharedLayingDownSystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly AnimationPlayerSystem _animation = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly SharedBuckleSystem _buckle = default!;
[Dependency] private readonly StandingStateSystem _standing = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<LayingDownComponent, MoveEvent>(OnMovementInput);
SubscribeNetworkEvent<CheckAutoGetUpEvent>(OnCheckAutoGetUp);
}
private void OnMovementInput(EntityUid uid, LayingDownComponent component, MoveEvent args)
{
if (!_timing.IsFirstTimePredicted
|| !_standing.IsDown(uid)
|| _buckle.IsBuckled(uid)
|| !_actionBlocker.CanMove(uid)
|| _animation.HasRunningAnimation(uid, "rotate")
|| !TryComp<TransformComponent>(uid, out var transform)
|| !TryComp<SpriteComponent>(uid, out var sprite)
|| !TryComp<RotationVisualsComponent>(uid, out var rotationVisuals))
return;
var rotation = transform.LocalRotation + (_eyeManager.CurrentEye.Rotation - (transform.LocalRotation - transform.WorldRotation));
if (rotation.GetDir() is Direction.SouthEast or Direction.East or Direction.NorthEast or Direction.North)
{
rotationVisuals.HorizontalRotation = Angle.FromDegrees(270);
sprite.Rotation = Angle.FromDegrees(270);
return;
}
rotationVisuals.HorizontalRotation = Angle.FromDegrees(90);
sprite.Rotation = Angle.FromDegrees(90);
}
private void OnCheckAutoGetUp(CheckAutoGetUpEvent ev, EntitySessionEventArgs args)
{
if (!_timing.IsFirstTimePredicted)
return;
var uid = GetEntity(ev.User);
if (!TryComp<TransformComponent>(uid, out var transform) || !TryComp<RotationVisualsComponent>(uid, out var rotationVisuals))
return;
var rotation = transform.LocalRotation + (_eyeManager.CurrentEye.Rotation - (transform.LocalRotation - transform.WorldRotation));
if (rotation.GetDir() is Direction.SouthEast or Direction.East or Direction.NorthEast or Direction.North)
{
rotationVisuals.HorizontalRotation = Angle.FromDegrees(270);
return;
}
rotationVisuals.HorizontalRotation = Angle.FromDegrees(90);
}
}

View file

@ -0,0 +1,128 @@
using System.Numerics;
using Content.Client.Viewport;
using Content.Shared.CCVar;
using Content.Shared.Input;
using Content.Shared.Telescope;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Client.UserInterface;
using Robust.Shared.Configuration;
using Robust.Shared.Input;
using Robust.Shared.Input.Binding;
using Robust.Shared.Timing;
namespace Content.Client.Telescope;
public sealed class TelescopeSystem : SharedTelescopeSystem
{
[Dependency] private readonly InputSystem _inputSystem = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IInputManager _input = default!;
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
private ScalingViewport? _viewport;
private bool _holdLookUp;
private bool _toggled;
public override void Initialize()
{
base.Initialize();
_cfg.OnValueChanged(CCVars.HoldLookUp,
val =>
{
var input = val ? null : InputCmdHandler.FromDelegate(_ => _toggled = !_toggled);
_input.SetInputCommand(ContentKeyFunctions.LookUp, input);
_holdLookUp = val;
_toggled = false;
},
true);
}
public override void FrameUpdate(float frameTime)
{
base.FrameUpdate(frameTime);
if (_timing.ApplyingState
|| !_timing.IsFirstTimePredicted
|| !_input.MouseScreenPosition.IsValid)
return;
var player = _player.LocalEntity;
var telescope = GetRightTelescope(player);
if (telescope == null)
{
_toggled = false;
return;
}
if (!TryComp<EyeComponent>(player, out var eye))
return;
var offset = Vector2.Zero;
if (_holdLookUp)
{
if (_inputSystem.CmdStates.GetState(ContentKeyFunctions.LookUp) != BoundKeyState.Down)
{
RaiseEvent(offset);
return;
}
}
else if (!_toggled)
{
RaiseEvent(offset);
return;
}
var mousePos = _input.MouseScreenPosition;
if (_uiManager.MouseGetControl(mousePos) as ScalingViewport is { } viewport)
_viewport = viewport;
if (_viewport == null)
return;
var centerPos = _eyeManager.WorldToScreen(eye.Eye.Position.Position + eye.Offset);
var diff = mousePos.Position - centerPos;
var len = diff.Length();
var size = _viewport.PixelSize;
var maxLength = Math.Min(size.X, size.Y) * 0.4f;
var minLength = maxLength * 0.2f;
if (len > maxLength)
{
diff *= maxLength / len;
len = maxLength;
}
var divisor = maxLength * telescope.Divisor;
if (len > minLength)
{
diff -= diff * minLength / len;
offset = new Vector2(diff.X / divisor, -diff.Y / divisor);
offset = new Angle(-eye.Rotation.Theta).RotateVec(offset);
}
RaiseEvent(offset);
}
private void RaiseEvent(Vector2 offset)
{
RaisePredictiveEvent(new EyeOffsetChangedEvent
{
Offset = offset
});
}
}

View file

@ -1,8 +0,0 @@
using Content.Shared._Sunrise.SharedLieDownPressingButtonSystem;
namespace Content.Client._Sunrise.LayDown;
public sealed class LieDownPressingButtonSystem : SharedLieDownPressingButtonSystem
{
}

View file

@ -202,6 +202,7 @@ public sealed partial class NPCCombatSystem
return;
}
_gun.SetTarget(gun, comp.Target);
_gun.AttemptShoot(uid, gunUid, gun, targetCordinates);
}
}

View file

@ -0,0 +1,28 @@
using Content.Shared.CCVar;
using Content.Shared.Standing;
using Robust.Shared.Configuration;
namespace Content.Server.Standing;
public sealed class LayingDownSystem : SharedLayingDownSystem
{
[Dependency] private readonly INetConfigurationManager _cfg = default!;
public override void Initialize()
{
base.Initialize();
SubscribeNetworkEvent<CheckAutoGetUpEvent>(OnCheckAutoGetUp);
}
private void OnCheckAutoGetUp(CheckAutoGetUpEvent ev, EntitySessionEventArgs args)
{
var uid = GetEntity(ev.User);
if (!TryComp(uid, out LayingDownComponent? layingDown))
return;
layingDown.AutoGetUp = _cfg.GetClientCVar(args.SenderSession.Channel, CCVars.AutoGetUp);
Dirty(uid, layingDown);
}
}

View file

@ -0,0 +1,5 @@
using Content.Shared.Telescope;
namespace Content.Server.Telescope;
public sealed class TelescopeSystem : SharedTelescopeSystem;

View file

@ -1,8 +0,0 @@
using Content.Shared._Sunrise.SharedLieDownPressingButtonSystem;
namespace Content.Server._Sunrise.LieDown;
public sealed class LieDownPressingButtonSystem : SharedLieDownPressingButtonSystem
{
}

View file

@ -380,7 +380,7 @@ public abstract partial class SharedBuckleSystem
_standing.Stand(buckle, force: true);
break;
case StrapPosition.Down:
_standing.Down(buckle, false, false, force: true);
_standing.Down(buckle, false, false);
break;
}

View file

@ -2333,5 +2333,20 @@ namespace Content.Shared.CCVar
/// </summary>
public static readonly CVarDef<bool> DebugPow3rDisableParallel =
CVarDef.Create("debug.pow3r_disable_parallel", true, CVar.SERVERONLY);
#region Lying Down System
public static readonly CVarDef<bool> AutoGetUp =
CVarDef.Create("rest.auto_get_up", true, CVar.CLIENT | CVar.ARCHIVE | CVar.REPLICATED);
#endregion
#region LookUp
public static readonly CVarDef<bool> HoldLookUp =
CVarDef.Create("rest.hold_look_up", true, CVar.CLIENT | CVar.ARCHIVE);
#endregion
}
}

View file

@ -61,6 +61,11 @@ namespace Content.Shared.Input
public static readonly BoundKeyFunction ZoomIn = "ZoomIn";
public static readonly BoundKeyFunction ResetZoom = "ResetZoom";
// Sunrise
public static readonly BoundKeyFunction ToggleStanding = "ToggleStanding";
public static readonly BoundKeyFunction LookUp = "LookUp";
// Sunrise
public static readonly BoundKeyFunction ArcadeUp = "ArcadeUp";
public static readonly BoundKeyFunction ArcadeDown = "ArcadeDown";
public static readonly BoundKeyFunction ArcadeLeft = "ArcadeLeft";

View file

@ -0,0 +1,26 @@
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
namespace Content.Shared.Standing;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class LayingDownComponent : Component
{
[DataField, AutoNetworkedField]
public float StandingUpTime { get; set; } = 1f;
[DataField, AutoNetworkedField]
public float SpeedModify { get; set; } = 0.4f;
[DataField, AutoNetworkedField]
public bool AutoGetUp;
}
[Serializable, NetSerializable]
public sealed class ChangeLayingDownEvent : CancellableEntityEventArgs;
[Serializable, NetSerializable]
public sealed class CheckAutoGetUpEvent(NetEntity user) : CancellableEntityEventArgs
{
public NetEntity User = user;
}

View file

@ -0,0 +1,151 @@
using Content.Shared.DoAfter;
using Content.Shared.Gravity;
using Content.Shared.Input;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Systems;
using Content.Shared.Stunnable;
using Robust.Shared.Input.Binding;
using Robust.Shared.Player;
using Robust.Shared.Serialization;
namespace Content.Shared.Standing;
public abstract class SharedLayingDownSystem : EntitySystem
{
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly StandingStateSystem _standing = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedGravitySystem _gravity = default!;
public override void Initialize()
{
CommandBinds.Builder
.Bind(ContentKeyFunctions.ToggleStanding, InputCmdHandler.FromDelegate(ToggleStanding))
.Register<SharedLayingDownSystem>();
SubscribeNetworkEvent<ChangeLayingDownEvent>(OnChangeState);
SubscribeLocalEvent<StandingStateComponent, StandingUpDoAfterEvent>(OnStandingUpDoAfter);
SubscribeLocalEvent<LayingDownComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeed);
SubscribeLocalEvent<LayingDownComponent, EntParentChangedMessage>(OnParentChanged);
}
public override void Shutdown()
{
base.Shutdown();
CommandBinds.Unregister<SharedLayingDownSystem>();
}
private void ToggleStanding(ICommonSession? session)
{
if (session is not { AttachedEntity: { Valid: true } uid } _
|| !Exists(uid)
|| !HasComp<LayingDownComponent>(session.AttachedEntity)
|| _gravity.IsWeightless(session.AttachedEntity.Value))
return;
RaiseNetworkEvent(new ChangeLayingDownEvent());
}
private void OnChangeState(ChangeLayingDownEvent ev, EntitySessionEventArgs args)
{
if (!args.SenderSession.AttachedEntity.HasValue)
return;
var uid = args.SenderSession.AttachedEntity.Value;
if (!TryComp(uid, out StandingStateComponent? standing)
|| !TryComp(uid, out LayingDownComponent? layingDown))
return;
RaiseNetworkEvent(new CheckAutoGetUpEvent(GetNetEntity(uid)));
if (HasComp<KnockedDownComponent>(uid)
|| !_mobState.IsAlive(uid))
return;
if (_standing.IsDown(uid, standing))
TryStandUp(uid, layingDown, standing);
else
TryLieDown(uid, layingDown, standing);
}
private void OnStandingUpDoAfter(EntityUid uid, StandingStateComponent component, StandingUpDoAfterEvent args)
{
if (args.Handled || args.Cancelled
|| HasComp<KnockedDownComponent>(uid)
|| _mobState.IsIncapacitated(uid)
|| !_standing.Stand(uid))
component.CurrentState = StandingState.Lying;
component.CurrentState = StandingState.Standing;
}
private void OnRefreshMovementSpeed(EntityUid uid, LayingDownComponent component, RefreshMovementSpeedModifiersEvent args)
{
if (_standing.IsDown(uid))
args.ModifySpeed(component.SpeedModify, component.SpeedModify);
else
args.ModifySpeed(1f, 1f);
}
private void OnParentChanged(EntityUid uid, LayingDownComponent component, EntParentChangedMessage args)
{
// If the entity is not on a grid, try to make it stand up to avoid issues
if (!TryComp<StandingStateComponent>(uid, out var standingState)
|| standingState.CurrentState is StandingState.Standing
|| Transform(uid).GridUid != null)
return;
_standing.Stand(uid, standingState);
}
public bool TryStandUp(EntityUid uid, LayingDownComponent? layingDown = null, StandingStateComponent? standingState = null)
{
if (!Resolve(uid, ref standingState, false)
|| !Resolve(uid, ref layingDown, false)
|| standingState.CurrentState is not StandingState.Lying
|| !_mobState.IsAlive(uid)
|| TerminatingOrDeleted(uid))
return false;
var args = new DoAfterArgs(EntityManager, uid, layingDown.StandingUpTime, new StandingUpDoAfterEvent(), uid)
{
BreakOnHandChange = false,
RequireCanInteract = false
};
if (!_doAfter.TryStartDoAfter(args))
return false;
standingState.CurrentState = StandingState.GettingUp;
return true;
}
public bool TryLieDown(EntityUid uid, LayingDownComponent? layingDown = null, StandingStateComponent? standingState = null, DropHeldItemsBehavior behavior = DropHeldItemsBehavior.NoDrop)
{
if (!Resolve(uid, ref standingState, false)
|| !Resolve(uid, ref layingDown, false)
|| standingState.CurrentState is not StandingState.Standing)
{
if (behavior == DropHeldItemsBehavior.AlwaysDrop)
RaiseLocalEvent(uid, new DropHandItemsEvent());
return false;
}
_standing.Down(uid, true, behavior != DropHeldItemsBehavior.NoDrop, standingState);
return true;
}
}
[Serializable, NetSerializable]
public sealed partial class StandingUpDoAfterEvent : SimpleDoAfterEvent;
public enum DropHeldItemsBehavior : byte
{
NoDrop,
DropIfStanding,
AlwaysDrop
}

View file

@ -1,24 +1,31 @@
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
namespace Content.Shared.Standing
namespace Content.Shared.Standing;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class StandingStateComponent : Component
{
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(StandingStateSystem))]
public sealed partial class StandingStateComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
[DataField]
public SoundSpecifier? DownSound { get; private set; } = new SoundCollectionSpecifier("BodyFall");
[DataField]
public SoundSpecifier DownSound { get; private set; } = new SoundCollectionSpecifier("BodyFall");
[DataField, AutoNetworkedField]
public bool Standing { get; set; } = true;
[DataField, AutoNetworkedField]
public StandingState CurrentState { get; set; } = StandingState.Standing;
/// <summary>
/// List of fixtures that had their collision mask changed when the entity was downed.
/// Required for re-adding the collision mask.
/// </summary>
[DataField, AutoNetworkedField]
public List<string> ChangedFixtures = new();
}
[DataField, AutoNetworkedField]
public bool Standing { get; set; } = true;
/// <summary>
/// List of fixtures that had their collision mask changed when the entity was downed.
/// Required for re-adding the collision mask.
/// </summary>
[DataField, AutoNetworkedField]
public List<string> ChangedFixtures = new();
}
public enum StandingState
{
Lying,
GettingUp,
Standing,
}

View file

@ -1,7 +1,9 @@
using Content.Shared.Buckle;
using Content.Shared.Buckle.Components;
using Content.Shared.Hands.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.Physics;
using Content.Shared.Rotation;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Systems;
@ -13,6 +15,8 @@ namespace Content.Shared.Standing
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movement = default!;
[Dependency] private readonly SharedBuckleSystem _buckle = default!;
// If StandingCollisionLayer value is ever changed to more than one layer, the logic needs to be edited.
private const int StandingCollisionLayer = (int) CollisionGroup.MidImpassable;
@ -22,13 +26,12 @@ namespace Content.Shared.Standing
if (!Resolve(uid, ref standingState, false))
return false;
return !standingState.Standing;
return standingState.CurrentState is StandingState.Lying or StandingState.GettingUp;
}
public bool Down(EntityUid uid,
bool playSound = true,
bool dropHeldItems = true,
bool force = false,
StandingStateComponent? standingState = null,
AppearanceComponent? appearance = null,
HandsComponent? hands = null)
@ -40,7 +43,7 @@ namespace Content.Shared.Standing
// Optional component.
Resolve(uid, ref appearance, ref hands, false);
if (!standingState.Standing)
if (standingState.CurrentState is StandingState.Lying or StandingState.GettingUp)
return true;
// This is just to avoid most callers doing this manually saving boilerplate
@ -48,20 +51,18 @@ namespace Content.Shared.Standing
// We do this BEFORE downing because something like buckle may be blocking downing but we want to drop hand items anyway
// and ultimately this is just to avoid boilerplate in Down callers + keep their behavior consistent.
if (dropHeldItems && hands != null)
{
RaiseLocalEvent(uid, new DropHandItemsEvent(), false);
}
if (!force)
{
var msg = new DownAttemptEvent();
RaiseLocalEvent(uid, msg, false);
if (TryComp(uid, out BuckleComponent? buckle) && buckle.Buckled && !_buckle.TryUnbuckle(uid, uid, buckleComp: buckle))
return false;
if (msg.Cancelled)
return false;
}
var msg = new DownAttemptEvent();
RaiseLocalEvent(uid, msg, false);
standingState.Standing = false;
if (msg.Cancelled)
return false;
standingState.CurrentState = StandingState.Lying;
Dirty(uid, standingState);
RaiseLocalEvent(uid, new DownedEvent(), false);
@ -87,10 +88,9 @@ namespace Content.Shared.Standing
return true;
if (playSound)
{
_audio.PlayPredicted(standingState.DownSound, uid, uid);
}
_audio.PlayPredicted(standingState.DownSound, uid, null);
_movement.RefreshMovementSpeedModifiers(uid);
return true;
}
@ -106,7 +106,9 @@ namespace Content.Shared.Standing
// Optional component.
Resolve(uid, ref appearance, false);
if (standingState.Standing)
if (standingState.CurrentState is StandingState.Standing
|| TryComp(uid, out BuckleComponent? buckle)
&& buckle.Buckled && !_buckle.TryUnbuckle(uid, uid, buckleComp: buckle))
return true;
if (!force)
@ -118,7 +120,7 @@ namespace Content.Shared.Standing
return false;
}
standingState.Standing = true;
standingState.CurrentState = StandingState.Standing;
Dirty(uid, standingState);
RaiseLocalEvent(uid, new StoodEvent(), false);
@ -133,6 +135,7 @@ namespace Content.Shared.Standing
}
}
standingState.ChangedFixtures.Clear();
_movement.RefreshMovementSpeedModifiers(uid);
return true;
}

View file

@ -16,6 +16,7 @@ using Content.Shared.StatusEffect;
using Content.Shared.Throwing;
using Content.Shared.Whitelist;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Events;
using Robust.Shared.Physics.Systems;
@ -32,6 +33,8 @@ public abstract class SharedStunSystem : EntitySystem
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
[Dependency] private readonly StandingStateSystem _standingState = default!;
[Dependency] private readonly StatusEffectsSystem _statusEffect = default!;
[Dependency] private readonly SharedLayingDownSystem _layingDown = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
/// <summary>
/// Friction modifier for knocked down players.
@ -136,12 +139,23 @@ public abstract class SharedStunSystem : EntitySystem
private void OnKnockInit(EntityUid uid, KnockedDownComponent component, ComponentInit args)
{
_standingState.Down(uid);
RaiseNetworkEvent(new CheckAutoGetUpEvent(GetNetEntity(uid)));
_layingDown.TryLieDown(uid, null, null, DropHeldItemsBehavior.DropIfStanding);
}
private void OnKnockShutdown(EntityUid uid, KnockedDownComponent component, ComponentShutdown args)
{
_standingState.Stand(uid);
if (!TryComp(uid, out StandingStateComponent? standing))
return;
if (TryComp(uid, out LayingDownComponent? layingDown))
{
if (layingDown.AutoGetUp && !_container.IsEntityInContainer(uid))
_layingDown.TryStandUp(uid, layingDown);
return;
}
_standingState.Stand(uid, standing);
}
private void OnStandAttempt(EntityUid uid, KnockedDownComponent component, StandAttemptEvent args)

View file

@ -0,0 +1,110 @@
using System.Numerics;
using Content.Shared.Camera;
using Content.Shared.Hands;
using Content.Shared.Hands.Components;
using Content.Shared.Item;
using Robust.Shared.Serialization;
namespace Content.Shared.Telescope;
public abstract class SharedTelescopeSystem : EntitySystem
{
[Dependency] private readonly SharedEyeSystem _eye = default!;
public override void Initialize()
{
base.Initialize();
SubscribeAllEvent<EyeOffsetChangedEvent>(OnEyeOffsetChanged);
SubscribeLocalEvent<TelescopeComponent, GotUnequippedHandEvent>(OnUnequip);
SubscribeLocalEvent<TelescopeComponent, HandDeselectedEvent>(OnHandDeselected);
SubscribeLocalEvent<TelescopeComponent, ComponentShutdown>(OnShutdown);
}
private void OnShutdown(Entity<TelescopeComponent> ent, ref ComponentShutdown args)
{
if (!TryComp(ent.Comp.LastEntity, out EyeComponent? eye)
|| ent.Comp.LastEntity == ent && TerminatingOrDeleted(ent))
return;
SetOffset((ent.Comp.LastEntity.Value, eye), Vector2.Zero, ent);
}
private void OnHandDeselected(Entity<TelescopeComponent> ent, ref HandDeselectedEvent args)
{
if (!TryComp(args.User, out EyeComponent? eye))
return;
SetOffset((args.User, eye), Vector2.Zero, ent);
}
private void OnUnequip(Entity<TelescopeComponent> ent, ref GotUnequippedHandEvent args)
{
if (!TryComp(args.User, out EyeComponent? eye)
|| !HasComp<ItemComponent>(ent.Owner))
return;
SetOffset((args.User, eye), Vector2.Zero, ent);
}
public TelescopeComponent? GetRightTelescope(EntityUid? ent)
{
TelescopeComponent? telescope = null;
if (TryComp<HandsComponent>(ent, out var hands)
&& hands.ActiveHandEntity.HasValue
&& TryComp<TelescopeComponent>(hands.ActiveHandEntity, out var handTelescope))
telescope = handTelescope;
else if (TryComp<TelescopeComponent>(ent, out var entityTelescope))
telescope = entityTelescope;
return telescope;
}
private void OnEyeOffsetChanged(EyeOffsetChangedEvent msg, EntitySessionEventArgs args)
{
if (args.SenderSession.AttachedEntity is not { } ent
|| !TryComp<EyeComponent>(ent, out var eye))
return;
var telescope = GetRightTelescope(ent);
if (telescope == null)
return;
var offset = Vector2.Lerp(eye.Offset, msg.Offset, telescope.LerpAmount);
SetOffset((ent, eye), offset, telescope);
}
private void SetOffset(Entity<EyeComponent> ent, Vector2 offset, TelescopeComponent telescope)
{
telescope.LastEntity = ent;
if (TryComp(ent, out CameraRecoilComponent? recoil))
{
recoil.BaseOffset = offset;
_eye.SetOffset(ent, offset + recoil.CurrentKick, ent);
}
else
{
_eye.SetOffset(ent, offset, ent);
}
}
public void SetParameters(Entity<TelescopeComponent> ent, float? divisor = null, float? lerpAmount = null)
{
var telescope = ent.Comp;
telescope.Divisor = divisor ?? telescope.Divisor;
telescope.LerpAmount = lerpAmount ?? telescope.LerpAmount;
Dirty(ent.Owner, telescope);
}
}
[Serializable, NetSerializable]
public sealed class EyeOffsetChangedEvent : EntityEventArgs
{
public Vector2 Offset;
}

View file

@ -0,0 +1,16 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Telescope;
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class TelescopeComponent : Component
{
[DataField, AutoNetworkedField]
public float Divisor = 0.1f;
[DataField, AutoNetworkedField]
public float LerpAmount = 0.1f;
[ViewVariables]
public EntityUid? LastEntity;
}

View file

@ -217,6 +217,18 @@ public abstract partial class SharedGunSystem : EntitySystem
Dirty(uid, gun);
}
// Sunrise START
/// <summary>
/// Sets the targeted entity of the gun. Should be called before attempting to shoot to avoid shooting over the target.
/// </summary>
public void SetTarget(GunComponent gun, EntityUid target)
{
gun.Target = target;
}
// Sunrise END
/// <summary>
/// Attempts to shoot at the target coordinates. Resets the shot counter after every shot.
/// </summary>

View file

@ -1,10 +0,0 @@
using Robust.Shared.Input;
namespace Content.Shared._Sunrise
{
[KeyFunctions]
public static class KeyFunctions
{
public static readonly BoundKeyFunction LieDown = "LieDown";
}
}

View file

@ -1,20 +0,0 @@
using Content.Shared.DoAfter;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
namespace Content.Shared._Sunrise.SharedLieDownPressingButtonSystem
{
// Mark for entitites which were proccessed by system so it shouldn't be used without system
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
public sealed partial class LieDownComponent : Component
{
[AutoNetworkedField]
public bool Lied { get; set; } = false;
}
}
[Serializable, NetSerializable]
public sealed partial class LieDownDoAfterEvent : SimpleDoAfterEvent
{
}

View file

@ -1,9 +0,0 @@
namespace Content.Shared._Sunrise.SharedLieDownPressingButtonSystem
{
// Mark for entitites which didn't was created via HumanoidAppearanceComponent and should be proccessing by different way
[RegisterComponent]
public sealed partial class LieDownPressingButtonComponent : Component
{
}
}

View file

@ -1,113 +0,0 @@
using Content.Shared.DoAfter;
using Robust.Shared.Player;
using Robust.Shared.Input.Binding;
using JetBrains.Annotations;
using Content.Shared.Humanoid;
using Content.Shared.Movement.Systems;
using Content.Shared.Standing;
namespace Content.Shared._Sunrise.SharedLieDownPressingButtonSystem
{
public abstract class SharedLieDownPressingButtonSystem : EntitySystem
{
[Dependency] private readonly StandingStateSystem _standing = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeed = default!;
static private Angle _defaultAngleRotation = 0;
public override void Initialize()
{
base.Initialize();
CommandBinds.Builder
.Bind(KeyFunctions.LieDown, InputCmdHandler.FromDelegate(HandlePressButtonLieDown, handle: false, outsidePrediction: false))
.Register<SharedLieDownPressingButtonSystem>();
SubscribeLocalEvent<StandingStateComponent, LieDownDoAfterEvent>(OnDoAfter);
SubscribeLocalEvent<StandingStateComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovementSpeed);
}
private void OnDoAfter(Entity<StandingStateComponent> ent, ref LieDownDoAfterEvent args)
{
if (args.Handled || args.Cancelled)
return;
if (!TryComp<StandingStateComponent>(ent, out var standingStateComponent))
return;
if (!standingStateComponent.Standing)
{
TryStand((ent, standingStateComponent));
return;
}
TryLieDown((ent, standingStateComponent));
}
private void OnRefreshMovementSpeed(Entity<StandingStateComponent> ent, ref RefreshMovementSpeedModifiersEvent args)
{
if (_standing.IsDown(ent))
args.ModifySpeed(0.4f, 0.4f);
else
args.ModifySpeed(1f, 1f);
}
private void HandlePressButtonLieDown(ICommonSession? session)
{
if (session?.AttachedEntity is var attachedEnt && attachedEnt is null)
return;
var ent = attachedEnt.Value;
var doAfterArgs = new DoAfterArgs(EntityManager, ent, 1, new LieDownDoAfterEvent(), ent, ent)
{
BreakOnDamage = true,
};
_doAfter.TryStartDoAfter(doAfterArgs);
}
[PublicAPI]
public bool TryLieDown(Entity<StandingStateComponent?> ent)
{
if (!HasComp<LieDownPressingButtonComponent>(ent) && !HasComp<HumanoidAppearanceComponent>(ent))
return false;
/*if (ent.Comp is null)
ent.Comp = AddComp<StandingStateComponent>(ent);*/
LieDown((ent, ent.Comp));
return true;
}
// Default lie down handler, for LieDownPressingButtonComponent should be wrote something different
private void LieDown(Entity<StandingStateComponent?> ent)
{
/*_rotationVisuals.SetHorizontalAngle(ent.Owner, _defaultAngleRotation);*/
_standing.Down(ent, playSound: true, dropHeldItems: false, force: true);
_movementSpeed.RefreshMovementSpeedModifiers(ent);
/*Dirty(ent);*/
}
[PublicAPI]
public bool TryStand(Entity<StandingStateComponent?> ent)
{
if (ent.Comp is null)
return false;
Stand((ent, ent.Comp));
return true;
}
private void Stand(Entity<StandingStateComponent> ent)
{
_standing.Stand(ent, standingState: ent.Comp);
_movementSpeed.RefreshMovementSpeedModifiers(ent);
/*_rotationVisuals.ResetHorizontalAngle(ent.Owner);*/
/*Dirty(ent);*/
}
}
}

View file

@ -1 +0,0 @@
ui-options-function-lie-down = Лечь на землю

View file

@ -0,0 +1,13 @@
laying-comp-lay-success-self = Вы ложитесь.
laying-comp-lay-success-other = {THE($entity)} ложится.
laying-comp-lay-fail-self = Вы не можете лечь прямо сейчас.
laying-comp-stand-success-self = Вы встаёте.
laying-comp-stand-success-other = {THE($entity)} встаёт.
laying-comp-stand-fail-self = Вы не можете встать прямо сейчас.
ui-options-function-toggle-standing = Лечь/Встать.
ui-options-function-look-up = Присмотреться/Прицелиться
ui-options-function-auto-get-up = Автоматически вставать при падении
ui-options-function-hold-look-up = Удерживать клавишу для прицеливания

View file

@ -240,6 +240,7 @@
# Sunrise-Start
- type: Carriable
- type: CanEscapeInventory
- type: LayingDown
# Sunrise-End
- type: Barotrauma
damage:

View file

@ -35,7 +35,7 @@
containers:
ballistic-ammo: !type:Container
ents: []
- type: ZoomableGun
- type: Telescope
- type: StaticPrice
price: 500

View file

@ -558,7 +558,7 @@
- type: Wieldable
- type: UseDelay
delay: 0.5
- type: ZoomableGun
- type: Telescope
- type: entity
name: S-13 «Чёрная мамба»
@ -602,7 +602,7 @@
- type: Battery
maxCharge: 3000
startingCharge: 3000
- type: entity
name: SAM-300
parent: BaseWeaponBattery
@ -681,4 +681,4 @@
- type: MultiHandedItem
- type: Battery
maxCharge: 7500
startingCharge: 7500
startingCharge: 7500

View file

@ -59,7 +59,7 @@
steps: 1
zeroVisible: true
- type: Appearance
- type: ZoomableGun
- type: Telescope
- type: UseDelay
delay: 0.5
@ -122,7 +122,7 @@
- type: Wieldable
- type: UseDelay
delay: 0.5
- type: ZoomableGun
- type: Telescope
- type: ChamberMagazineAmmoProvider
autoEject: true
boltClosed: null
@ -191,7 +191,7 @@
- type: Wieldable
- type: UseDelay
delay: 0.5
- type: ZoomableGun
- type: Telescope
- type: entity
name: M1 Garand

View file

@ -585,7 +585,12 @@ binds:
key: MouseRight
canFocus: true
# Sunrise
- function: LieDown
- function: ToggleStanding
type: State
key: R
key: R
- function: LookUp
type: State
key: MouseRight