diff --git a/Content.Client/_CP14/Fishing/CP14FishingOverlay.cs b/Content.Client/_CP14/Fishing/CP14FishingOverlay.cs index e7c6ab8e5b..8bed514ac2 100644 --- a/Content.Client/_CP14/Fishing/CP14FishingOverlay.cs +++ b/Content.Client/_CP14/Fishing/CP14FishingOverlay.cs @@ -16,6 +16,7 @@ public sealed class CP14FishingOverlay : Overlay [Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly IResourceCache _resourceCache = default!; + private readonly SpriteSystem _sprite; private readonly TransformSystem _transform; private readonly CP14FishingProcessSystem _fishingProcess; @@ -24,11 +25,15 @@ public sealed class CP14FishingOverlay : Overlay private Texture _handleMiddleTexture = default!; private Texture _handleBottomTexture = default!; + private Texture _lootTexture = default!; + private Vector2 _backgroundOffset; private Vector2 _backgroundHandleOffset; - private float _backgroundHandleHeight; + private Vector2 _progressOffset; + private Vector2 _progressSize; + private EntityUid _process = EntityUid.Invalid; public override OverlaySpace Space => OverlaySpace.WorldSpace; @@ -37,6 +42,7 @@ public sealed class CP14FishingOverlay : Overlay { IoCManager.InjectDependencies(this); + _sprite = _entity.System(); _transform = _entity.System(); _fishingProcess = _entity.System(); } @@ -54,6 +60,8 @@ public sealed class CP14FishingOverlay : Overlay { _process = fishingProcess.Value.Owner; UpdateCachedStyleSheet(fishingProcess.Value.Comp.StyleSheet); + + _lootTexture = _sprite.GetPrototypeIcon(fishingProcess.Value.Comp.LootProtoId).Default; } // Getting the position of the player we will be working from @@ -63,8 +71,12 @@ public sealed class CP14FishingOverlay : Overlay var playerOffset = fishingProcess.Value.Comp.PlayerPositionNormalized * _backgroundHandleHeight; var playerHalfSize = fishingProcess.Value.Comp.PlayerHalfSizeNormalized * _backgroundHandleHeight; + var lootOffset = fishingProcess.Value.Comp.LootPositionNormalized * _backgroundHandleHeight; + DrawBackground(args.WorldHandle, worldPosition - _backgroundOffset); + DrawProgress(args.WorldHandle, worldPosition - _backgroundOffset + _progressOffset, _progressSize, fishingProcess.Value.Comp.Progress); DrawHandle(args.WorldHandle, worldPosition - _backgroundOffset + _backgroundHandleOffset + playerOffset, playerHalfSize); + DrawLoot(args.WorldHandle, worldPosition - _backgroundOffset + _backgroundHandleOffset + lootOffset); } private void DrawBackground(DrawingHandleWorld handle, Vector2 position) @@ -72,6 +84,15 @@ public sealed class CP14FishingOverlay : Overlay handle.DrawTexture(_backgroundTexture, position); } + private void DrawProgress(DrawingHandleWorld handle, Vector2 position, Vector2 size, float progress) + { + var vectorA = position; + var vectorB = position + size with { Y = size.Y * progress }; + var box = new Box2(vectorA, vectorB); + + handle.DrawRect(box, Color.Aqua); + } + private void DrawHandle(DrawingHandleWorld handle, Vector2 position, Vector2 halfSize) { var cursor = position - halfSize; @@ -91,6 +112,11 @@ public sealed class CP14FishingOverlay : Overlay handle.DrawTexture(_handleTopTexture, cursor); } + private void DrawLoot(DrawingHandleWorld handle, Vector2 position) + { + handle.DrawTexture(_lootTexture, position + Vector2.UnitX * 0.140625f - _lootTexture.Size / 64f); + } + private void UpdateCachedStyleSheet(CP14FishingProcessStyleSheetPrototype styleSheet) { _backgroundTexture = _resourceCache.GetTexture(styleSheet.Background.Texture); @@ -99,7 +125,11 @@ public sealed class CP14FishingOverlay : Overlay _handleBottomTexture = _resourceCache.GetTexture(styleSheet.Handle.BottomTexture); _backgroundOffset = styleSheet.Background.Offset + Vector2.UnitX * _backgroundTexture.Width / 32f; + _backgroundHandleOffset = styleSheet.Background.HandleOffset; _backgroundHandleHeight = styleSheet.Background.HandleHeight; + + _progressOffset = styleSheet.Background.ProgressOffset; + _progressSize = styleSheet.Background.ProgressSize; } } diff --git a/Content.Shared/_CP14/Fishing/CP14FishingProcessComponent.cs b/Content.Shared/_CP14/Fishing/CP14FishingProcessComponent.cs index ca9e9085b5..3ea9d4fadd 100644 --- a/Content.Shared/_CP14/Fishing/CP14FishingProcessComponent.cs +++ b/Content.Shared/_CP14/Fishing/CP14FishingProcessComponent.cs @@ -1,6 +1,7 @@ using System.Numerics; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; +using Robust.Shared.Random; using Robust.Shared.Serialization; namespace Content.Shared._CP14.Fishing; @@ -8,36 +9,71 @@ namespace Content.Shared._CP14.Fishing; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(CP14FishingProcessSystem))] public sealed partial class CP14FishingProcessComponent : Component { + /** + * Boxes + */ + [ViewVariables, AutoNetworkedField] public Box Player = new(); [ViewVariables, AutoNetworkedField] public Box Loot = new(); + /** + * Physics + */ + [ViewVariables, AutoNetworkedField] public float Size = 16f; - [ViewVariables, AutoNetworkedField] - public float Gravity = 1f; + /** + * Progress + */ [ViewVariables, AutoNetworkedField] - public EntityUid? User; + public float Progress = 0; + + /** + * Saved entities + */ [ViewVariables, AutoNetworkedField] public EntityUid? FishingRod; + [ViewVariables, AutoNetworkedField] + public EntityUid? User; + [ViewVariables, AutoNetworkedField] public EntityUid? FishingPool; + /** + * Loot + */ + [ViewVariables, AutoNetworkedField] public EntProtoId LootProtoId; + /** + * Style + */ + [ViewVariables] public CP14FishingProcessStyleSheetPrototype StyleSheet; + /** + * Normalized + */ + + public Vector2 LootPositionNormalized => Vector2.UnitY * Loot.Position / Size; public Vector2 PlayerPositionNormalized => Vector2.UnitY * Player.Position / Size; public Vector2 PlayerHalfSizeNormalized => Vector2.UnitY * Player.HalfSize / Size; + /** + * Getters + */ + + public bool Collides => Box.Collide(Player, Loot); + [Serializable, NetSerializable] public sealed class Box { @@ -53,15 +89,40 @@ public sealed partial class CP14FishingProcessComponent : Component [ViewVariables] public float HalfSize => Size / 2f; + [ViewVariables] + public float MovementTimer; + public Box(float size = 2.5f, float position = 0) { Size = size; Position = position; } - public void Clamp(float worldSize) + public void ClampPosition(float worldSize) { Position = MathHelper.Clamp(Position, HalfSize, worldSize - HalfSize); } + + public void SimulateFishMovement(IRobustRandom random, float frameTime, float speed, float amplitude, float chaosFactor, float worldSize) + { + MovementTimer += frameTime; + Velocity = (float)(Math.Sin(MovementTimer * speed) * amplitude); + + if (random.NextDouble() < chaosFactor) + Velocity += (float)((random.NextDouble() * 2 - 1) * speed * chaosFactor * amplitude); + + Position += Velocity * frameTime; + } + + public static bool Collide(Box boxA, Box boxB) + { + var minA = boxA.Position - boxA.HalfSize; + var maxA = boxA.Position + boxA.HalfSize; + + var minB = boxB.Position - boxB.HalfSize; + var maxB = boxB.Position + boxB.HalfSize; + + return maxA >= minB && maxB >= minA; + } } } diff --git a/Content.Shared/_CP14/Fishing/CP14FishingProcessStyleSheetPrototype.cs b/Content.Shared/_CP14/Fishing/CP14FishingProcessStyleSheetPrototype.cs index 76d5944196..7df6b294b5 100644 --- a/Content.Shared/_CP14/Fishing/CP14FishingProcessStyleSheetPrototype.cs +++ b/Content.Shared/_CP14/Fishing/CP14FishingProcessStyleSheetPrototype.cs @@ -30,6 +30,12 @@ public sealed partial class CP14FishingProcessStyleSheetPrototype : IPrototype [DataField("handleHeight"), ViewVariables(VVAccess.ReadWrite)] public float HandleHeightPixels = 149; + [DataField("progressOffset"), ViewVariables(VVAccess.ReadWrite)] + public Vector2 ProgressOffsetPixels = new(31, 3); + + [DataField("progressSize"), ViewVariables(VVAccess.ReadWrite)] + public Vector2 ProgressSizePixels = new(4, 144); + /// /// In units (pixels / 32). /// @@ -42,6 +48,18 @@ public sealed partial class CP14FishingProcessStyleSheetPrototype : IPrototype [ViewVariables] public Vector2 HandleOffset => HandleOffsetPixels / 32f; + /// + /// In units (pixels / 32). + /// + [ViewVariables] + public Vector2 ProgressOffset => ProgressOffsetPixels / 32f; + + /// + /// In units (pixels / 32). + /// + [ViewVariables] + public Vector2 ProgressSize => ProgressSizePixels / 32f; + /// /// In units (pixels / 32). /// diff --git a/Content.Shared/_CP14/Fishing/CP14FishingProcessSystem.cs b/Content.Shared/_CP14/Fishing/CP14FishingProcessSystem.cs index 167e516a7a..2d4d807abf 100644 --- a/Content.Shared/_CP14/Fishing/CP14FishingProcessSystem.cs +++ b/Content.Shared/_CP14/Fishing/CP14FishingProcessSystem.cs @@ -2,12 +2,14 @@ using Content.Shared._CP14.Fishing.FishingPool; using Content.Shared._CP14.Fishing.FishingRod; using Robust.Shared.Prototypes; +using Robust.Shared.Random; namespace Content.Shared._CP14.Fishing; public sealed class CP14FishingProcessSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IRobustRandom _random = default!; private EntityQuery _fishingRod; @@ -34,14 +36,30 @@ public sealed class CP14FishingProcessSystem : EntitySystem var fishingRodComponent = _fishingRod.GetComponent(process.Comp.FishingRod!.Value); if (fishingRodComponent.Reeling) - process.Comp.Player.Position += fishingRodComponent.Speed * frameTime; + { + process.Comp.Player.Velocity += fishingRodComponent.Speed * frameTime; + } else - process.Comp.Player.Position -= process.Comp.Gravity * frameTime; + { + process.Comp.Player.Velocity -= fishingRodComponent.Gravity * frameTime; + } - // Simple collision with board - // TODO: bouncing - process.Comp.Player.Clamp(process.Comp.Size); - process.Comp.Loot.Clamp(process.Comp.Size); + const float drag = 0.98f; + process.Comp.Player.Velocity *= drag; + + process.Comp.Player.Velocity = Math.Clamp(process.Comp.Player.Velocity, + fishingRodComponent.MinVelocity, + fishingRodComponent.MaxVelocity); + + process.Comp.Player.Position += process.Comp.Player.Velocity * frameTime; + + process.Comp.Player.ClampPosition(process.Comp.Size); + + process.Comp.Loot.SimulateFishMovement(_random, frameTime, 0.25f, 0.95f, 0.75f, process.Comp.Size); + process.Comp.Loot.ClampPosition(process.Comp.Size); + + var progressAdditive = process.Comp.Collides ? 0.05f : -0.1f; + process.Comp.Progress = Math.Clamp(process.Comp.Progress + progressAdditive * frameTime, 0, 1); } public bool TryGetByUser(EntityUid userEntityUid, [NotNullWhen(true)] out Entity? process) @@ -83,7 +101,6 @@ public sealed class CP14FishingProcessSystem : EntitySystem ensureComponent.User = user; ensureComponent.Size = prototype.Size; - ensureComponent.Gravity = prototype.Gravity; ensureComponent.Player = new CP14FishingProcessComponent.Box(prototype.PlayerSize); ensureComponent.Loot = new CP14FishingProcessComponent.Box(prototype.LootSize); diff --git a/Content.Shared/_CP14/Fishing/FishingRod/CP14FishingRodComponent.cs b/Content.Shared/_CP14/Fishing/FishingRod/CP14FishingRodComponent.cs index 19e9b3e111..85f351655d 100644 --- a/Content.Shared/_CP14/Fishing/FishingRod/CP14FishingRodComponent.cs +++ b/Content.Shared/_CP14/Fishing/FishingRod/CP14FishingRodComponent.cs @@ -12,5 +12,17 @@ public sealed partial class CP14FishingRodComponent : Component public bool Reeling; [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public float Speed = 0.1f; + public float Speed = 0.5f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Gravity = 0.75f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float MaxVelocity = 3f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float MinVelocity = -3.25f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Bouncing = 0.7f; } diff --git a/Resources/Prototypes/_CP14/Entities/Objects/Fishing/fishingRods.yml b/Resources/Prototypes/_CP14/Entities/Objects/Fishing/fishingRods.yml index dd135a3804..7b41dddee7 100644 --- a/Resources/Prototypes/_CP14/Entities/Objects/Fishing/fishingRods.yml +++ b/Resources/Prototypes/_CP14/Entities/Objects/Fishing/fishingRods.yml @@ -13,4 +13,3 @@ sprite: _CP14/Objects/ModularTools/iron_spear.rsi state: icon - type: CP14FishingRod - speed: 1 diff --git a/Resources/Prototypes/_CP14/Entities/Objects/Fishing/styleSheets.yml b/Resources/Prototypes/_CP14/Entities/Objects/Fishing/styleSheets.yml index f89524ba40..759f22d328 100644 --- a/Resources/Prototypes/_CP14/Entities/Objects/Fishing/styleSheets.yml +++ b/Resources/Prototypes/_CP14/Entities/Objects/Fishing/styleSheets.yml @@ -5,6 +5,8 @@ offset: 10, 0 handleOffset: 16, 4 handleHeight: 141 + progressOffset: 31, 3 + progressSize: 4, 144 handle: topTexture: /Textures/_CP14/Interface/Fishing/Handle/top.png middleTexture: /Textures/_CP14/Interface/Fishing/Handle/middle.png diff --git a/Resources/Prototypes/_CP14/Fishing/processes.yml b/Resources/Prototypes/_CP14/Fishing/processes.yml index 396ce391c1..8dbfc52c9a 100644 --- a/Resources/Prototypes/_CP14/Fishing/processes.yml +++ b/Resources/Prototypes/_CP14/Fishing/processes.yml @@ -1,7 +1,6 @@ - type: CP14FishingProcess id: Debug size: 10 - gravity: 3.5 playerSize: 1 lootSize: 0 lootProtoId: CP14FloorWater