-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* FollowCamera * fix follow distance * one more shit * Fixes and polishing --------- Co-authored-by: JerryImMouse <[email protected]>
- Loading branch information
1 parent
9807371
commit 50cd154
Showing
24 changed files
with
540 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// License granted by JerryImMouse to Corvax Forge. | ||
// Non-exclusive, non-transferable, perpetual license to use, distribute, and modify. | ||
// All other rights reserved by JerryImMouse. | ||
using System.Numerics; | ||
using Content.Shared._NC.CameraFollow.Components; | ||
using Content.Shared._NC.CameraFollow.Events; | ||
using Content.Shared._NC.FollowDistance.Components; | ||
using Robust.Client.GameObjects; | ||
using Robust.Client.Graphics; | ||
using Robust.Client.Input; | ||
using Robust.Client.Player; | ||
using Robust.Shared.Timing; | ||
|
||
namespace Content.Client._NC.CameraFollow; | ||
|
||
/// <summary> | ||
/// Use to make camera follow for player's mouse, uses Lerp() func. to follow player's mouse | ||
/// </summary> | ||
public sealed class CameraFollowSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly IInputManager _input = default!; | ||
[Dependency] private readonly IPlayerManager _player = default!; | ||
[Dependency] private readonly IGameTiming _timing = default!; | ||
[Dependency] private readonly IEyeManager _manager = default!; | ||
[Dependency] private readonly TransformSystem _transform = default!; | ||
|
||
public override void FrameUpdate(float frameTime) | ||
{ | ||
base.FrameUpdate(frameTime); | ||
|
||
// Check if mouse position is valid | ||
if (!_timing.IsFirstTimePredicted || !_input.MouseScreenPosition.IsValid) | ||
return; | ||
|
||
var player = _player.LocalSession?.AttachedEntity; | ||
|
||
if (player == null || !TryComp<CameraFollowComponent>(player, out var followComponent)) | ||
return; | ||
if (!TryComp<EyeComponent>(player, out var eye) || !followComponent.Enabled) | ||
return; | ||
|
||
// Get player map position and eye offset | ||
var xform = Transform(player.Value); | ||
var playerPos = _transform.GetMapCoordinates(xform).Position; | ||
var eyeOffset = new Vector2(eye.Offset.X, eye.Offset.Y); | ||
|
||
// Get mouse position on map | ||
var coords = _input.MouseScreenPosition; | ||
var mapPos = _manager.ScreenToMap(coords); | ||
|
||
// Get currentLerpProgress and difference between player position and mouse position | ||
float currentLerpTime = 0; | ||
currentLerpTime += frameTime; | ||
if (currentLerpTime > followComponent.LerpTime) | ||
{ | ||
currentLerpTime = followComponent.LerpTime; | ||
} | ||
|
||
// Counts diff between player and mouse position | ||
// Counts our progress through lerp, don't touch it please, idk how it works. | ||
var lerpProgress = currentLerpTime / followComponent.LerpTime; | ||
var diff = new Vector2(mapPos.X, mapPos.Y) - playerPos; | ||
|
||
// Checks if player pointed his mouse on UI | ||
if (mapPos is { X: 0, Y: 0 }) | ||
return; | ||
|
||
var offset = followComponent.Offset; | ||
// If eye offset is higher than max distance lerp offset to max distance and apply "back strength" | ||
// TODO: Prob need to change the multiplication of lerpProgress to 4f, because this can cause the camera to jerk around | ||
|
||
|
||
if (Math.Abs(eyeOffset.X) >= Math.Abs(followComponent.MaxDistance.X) || | ||
Math.Abs(eyeOffset.Y) >= Math.Abs(followComponent.MaxDistance.Y)) | ||
{ | ||
offset = Vector2.Lerp(offset, followComponent.MaxDistance, lerpProgress * followComponent.BackStrength); | ||
} | ||
// Just lerp to calculated offset position | ||
offset = Vector2.Lerp(offset, diff, lerpProgress); | ||
|
||
RaisePredictiveEvent(new ChangeCamOffsetEvent | ||
{ | ||
Offset = offset | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System.Numerics; | ||
using Content.Shared.Movement.Systems; | ||
|
||
namespace Content.Shared.Camera; | ||
|
||
/// <summary> | ||
/// Raised directed by-ref when <see cref="SharedContentEyeSystem.UpdateEyeOffset"/> is called. | ||
/// Should be subscribed to by any systems that want to modify an entity's eye offset, | ||
/// so that they do not override each other. | ||
/// </summary> | ||
/// <param name="Offset"> | ||
/// The total offset to apply. | ||
/// </param> | ||
/// <remarks> | ||
/// Note that in most cases <see cref="Offset"/> should be incremented or decremented by subscribers, not set. | ||
/// Otherwise, any offsets applied by previous subscribing systems will be overridden. | ||
/// </remarks> | ||
[ByRefEvent] | ||
public record struct GetEyeOffsetEvent(Vector2 Offset); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
Content.Shared/_NC/CameraFollow/Components/CameraFollowComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// License granted by JerryImMouse to Corvax Forge. | ||
// Non-exclusive, non-transferable, perpetual license to use, distribute, and modify. | ||
// All other rights reserved by JerryImMouse. | ||
using System.Numerics; | ||
using Content.Shared.Actions; | ||
using Content.Shared._NC.CameraFollow.EntitySystems; | ||
using Robust.Shared.GameStates; | ||
using Robust.Shared.Prototypes; | ||
using Robust.Shared.Serialization; | ||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; | ||
|
||
namespace Content.Shared._NC.CameraFollow.Components; | ||
/// <summary> | ||
/// Component to set eye offset to make camera follow player's mouse | ||
/// </summary> | ||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] | ||
public sealed partial class CameraFollowComponent : Component | ||
{ | ||
// TODO: Probably need to remove max distance cause it doesn't influence on max distance lol | ||
[DataField, AutoNetworkedField] | ||
public Vector2 MaxDistance = new(0.0001f, 0.0001f); | ||
|
||
[DataField, AutoNetworkedField] | ||
public Vector2 DefaultMaxDistance = new(0.0001f, 0.0001f); | ||
|
||
[DataField, AutoNetworkedField] | ||
public Vector2 Offset; | ||
|
||
[DataField("lerpTime")] | ||
public float LerpTime = 1f; | ||
|
||
// Max distance controller btw | ||
// I think its broken cause it looks weird | ||
[DataField("backStrength"), AutoNetworkedField] | ||
public float BackStrength = 10f; | ||
|
||
[DataField("defaultBackStrength")] | ||
public float DefaultBackStrength = 10f; | ||
|
||
[DataField("action", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))] | ||
public string Action = "ActionToggleCamera"; | ||
|
||
// Action entity to remove it from player on component remove | ||
public EntityUid? ActionEntity; | ||
|
||
[DataField, AutoNetworkedField] | ||
public bool Enabled = false; | ||
|
||
} |
55 changes: 55 additions & 0 deletions
55
Content.Shared/_NC/CameraFollow/EntitySystems/CameraActionsSystem.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// License granted by JerryImMouse to Corvax Forge. | ||
// Non-exclusive, non-transferable, perpetual license to use, distribute, and modify. | ||
// All other rights reserved by JerryImMouse. | ||
using System.Numerics; | ||
using Content.Shared._NC.CameraFollow.Components; | ||
using Content.Shared._NC.CameraFollow.Events; | ||
using Content.Shared.Bed.Sleep; | ||
using Content.Shared.Stunnable; | ||
|
||
namespace Content.Shared._NC.CameraFollow.EntitySystems; | ||
|
||
public sealed class CameraActionsSystem : EntitySystem | ||
{ | ||
[Dependency] private readonly SharedEyeSystem _eye = default!; | ||
|
||
public override void Initialize() | ||
{ | ||
base.Initialize(); | ||
|
||
SubscribeLocalEvent<CameraFollowComponent, ToggleCameraEvent>(OnToggleCamera); | ||
SubscribeLocalEvent<CameraFollowComponent, SleepStateChangedEvent>(OnSleeping); | ||
} | ||
|
||
private void OnSleeping(Entity<CameraFollowComponent> ent, ref SleepStateChangedEvent args) | ||
{ | ||
SetCameraEnabled(ent, false); | ||
Dirty(ent); | ||
} | ||
|
||
private void OnToggleCamera(EntityUid uid, CameraFollowComponent component, ToggleCameraEvent args) | ||
{ | ||
if (HasComp<SleepingComponent>(uid) || HasComp<StunnedComponent>(uid)) // Check if entity is sleeping right now(when sleeping entity has a shader without shadows, it can cause wallhacking) | ||
{ | ||
args.Handled = true; | ||
return; | ||
} | ||
|
||
SetCameraEnabled((uid,component), !component.Enabled); | ||
Dirty(uid, component); | ||
args.Handled = true; | ||
} | ||
|
||
|
||
/// <summary> | ||
/// Sets the enabled state of the camera on server and client side | ||
/// </summary> | ||
/// <param name="component">CameraFollowComponent</param> | ||
/// <param name="enabled">Enabled boolean value</param> | ||
private void SetCameraEnabled(Entity<CameraFollowComponent> component, bool enabled) | ||
{ | ||
component.Comp.Enabled = enabled; | ||
component.Comp.Offset = new Vector2(0, 0); | ||
_eye.SetOffset(component, component.Comp.Offset); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
Content.Shared/_NC/CameraFollow/Events/ToggleCameraEvent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// License granted by JerryImMouse to Corvax Forge. | ||
// Non-exclusive, non-transferable, perpetual license to use, distribute, and modify. | ||
// All other rights reserved by JerryImMouse. | ||
using System.Numerics; | ||
using Content.Shared.Actions; | ||
using Robust.Shared.Serialization; | ||
|
||
namespace Content.Shared._NC.CameraFollow.Events; | ||
|
||
/// <summary> | ||
/// Turns on/off the camera following the player's mouse position. | ||
/// </summary> | ||
public sealed partial class ToggleCameraEvent : InstantActionEvent | ||
{ | ||
} | ||
|
||
[Serializable, NetSerializable] | ||
public sealed partial class ChangeCamOffsetEvent : EntityEventArgs | ||
{ | ||
public Vector2 Offset = Vector2.Zero; | ||
} |
33 changes: 33 additions & 0 deletions
33
Content.Shared/_NC/FollowDistance/Components/FollowDistanceComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// License granted by JerryImMouse to Corvax Forge. | ||
// Non-exclusive, non-transferable, perpetual license to use, distribute, and modify. | ||
// All other rights reserved by JerryImMouse. | ||
using System.Numerics; | ||
using Robust.Shared.Serialization; | ||
|
||
namespace Content.Shared._NC.FollowDistance.Components; | ||
|
||
/// <summary> | ||
/// Component to set new values for <see cref="CameraFollow"/> | ||
/// </summary> | ||
[RegisterComponent] | ||
public sealed partial class FollowDistanceComponent : Component | ||
{ | ||
// Probably don't touch this field in your prototype, this can cause unpredictable behavior | ||
// But you can try... | ||
[DataField("maxDistance"), ViewVariables(VVAccess.ReadWrite)] | ||
public Vector2 MaxDistance = new(0.0001f, 0.0001f); | ||
|
||
// Change this field in your prototype to set max distance, the lower the value, the more the player will be able to see. | ||
// DON'T SET THIS TO 0, it will cause max distance wouldn't work and player will be able to look all over the map. | ||
// If you want to set a value lower than 1, use float values, but never 0 and less. | ||
[DataField("backStrength"), ViewVariables(VVAccess.ReadWrite)] | ||
public float BackStrength = 4f; | ||
|
||
// This fields for default player's max distance and back strength | ||
// This will set automatically on player pickup entity with FollowDistanceComponent | ||
[DataField, ViewVariables(VVAccess.ReadOnly)] | ||
public Vector2 DefaultMaxDistance = new Vector2(0.0001f, 0.0001f); | ||
|
||
[DataField, ViewVariables(VVAccess.ReadOnly)] | ||
public float DefaultBackStrength = 4f; | ||
} |
Oops, something went wrong.