diff --git a/Content.Client/_CP14/Fishing/CP14FishingOverlay.cs b/Content.Client/_CP14/Fishing/CP14FishingOverlay.cs index 8bed514ac2..54720de5aa 100644 --- a/Content.Client/_CP14/Fishing/CP14FishingOverlay.cs +++ b/Content.Client/_CP14/Fishing/CP14FishingOverlay.cs @@ -1,6 +1,8 @@ using System.Numerics; using Content.Client.Resources; -using Content.Shared._CP14.Fishing; +using Content.Shared._CP14.Fishing.Components; +using Content.Shared._CP14.Fishing.Prototypes; +using Content.Shared._CP14.Fishing.Systems; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; @@ -12,8 +14,10 @@ namespace Content.Client._CP14.Fishing; public sealed class CP14FishingOverlay : Overlay { + [Dependency] private readonly IComponentFactory _factory = default!; [Dependency] private readonly IEntityManager _entity = default!; [Dependency] private readonly IPlayerManager _player = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly IResourceCache _resourceCache = default!; private readonly SpriteSystem _sprite; @@ -29,7 +33,7 @@ public sealed class CP14FishingOverlay : Overlay private Vector2 _backgroundOffset; private Vector2 _backgroundHandleOffset; - private float _backgroundHandleHeight; + private Vector2 _backgroundHandleSize; private Vector2 _progressOffset; private Vector2 _progressSize; @@ -61,17 +65,26 @@ public sealed class CP14FishingOverlay : Overlay _process = fishingProcess.Value.Owner; UpdateCachedStyleSheet(fishingProcess.Value.Comp.StyleSheet); - _lootTexture = _sprite.GetPrototypeIcon(fishingProcess.Value.Comp.LootProtoId).Default; + var prototype = _prototype.Index(fishingProcess.Value.Comp.LootProtoId); + var iconPath = CP14FishingIconComponent.DefaultTexturePath; + + if (prototype.Components.TryGetComponent(_factory.GetComponentName(typeof(CP14FishingIconComponent)), out var iconComponent)) + { + var comp = (CP14FishingIconComponent) iconComponent; + iconPath = comp.TexturePath; + } + + _lootTexture = _resourceCache.GetTexture(iconPath); } // Getting the position of the player we will be working from var worldPosition = _transform.GetWorldPosition(localEntity); // Calculate the shift of the player relative to the bottom of the coordinates - var playerOffset = fishingProcess.Value.Comp.PlayerPositionNormalized * _backgroundHandleHeight; - var playerHalfSize = fishingProcess.Value.Comp.PlayerHalfSizeNormalized * _backgroundHandleHeight; + var playerOffset = fishingProcess.Value.Comp.PlayerPositionNormalized * _backgroundHandleSize; + var playerHalfSize = fishingProcess.Value.Comp.PlayerHalfSizeNormalized * _backgroundHandleSize; - var lootOffset = fishingProcess.Value.Comp.LootPositionNormalized * _backgroundHandleHeight; + var lootOffset = fishingProcess.Value.Comp.LootPositionNormalized * _backgroundHandleSize + Vector2.UnitX * _backgroundHandleSize.X / 2; DrawBackground(args.WorldHandle, worldPosition - _backgroundOffset); DrawProgress(args.WorldHandle, worldPosition - _backgroundOffset + _progressOffset, _progressSize, fishingProcess.Value.Comp.Progress); @@ -114,7 +127,7 @@ public sealed class CP14FishingOverlay : Overlay private void DrawLoot(DrawingHandleWorld handle, Vector2 position) { - handle.DrawTexture(_lootTexture, position + Vector2.UnitX * 0.140625f - _lootTexture.Size / 64f); + handle.DrawTexture(_lootTexture, position - _lootTexture.Size / 64f); } private void UpdateCachedStyleSheet(CP14FishingProcessStyleSheetPrototype styleSheet) @@ -127,7 +140,7 @@ public sealed class CP14FishingOverlay : Overlay _backgroundOffset = styleSheet.Background.Offset + Vector2.UnitX * _backgroundTexture.Width / 32f; _backgroundHandleOffset = styleSheet.Background.HandleOffset; - _backgroundHandleHeight = styleSheet.Background.HandleHeight; + _backgroundHandleSize = styleSheet.Background.HandleSize; _progressOffset = styleSheet.Background.ProgressOffset; _progressSize = styleSheet.Background.ProgressSize; diff --git a/Content.Client/_CP14/Fishing/CP14FishingRodSystem.cs b/Content.Client/_CP14/Fishing/CP14FishingRodSystem.cs index d99cb78484..4a6aae96dd 100644 --- a/Content.Client/_CP14/Fishing/CP14FishingRodSystem.cs +++ b/Content.Client/_CP14/Fishing/CP14FishingRodSystem.cs @@ -1,5 +1,6 @@ using Content.Client.Hands.Systems; -using Content.Shared._CP14.Fishing.FishingRod; +using Content.Shared._CP14.Fishing.Components; +using Content.Shared._CP14.Fishing.Systems; using Robust.Client.GameObjects; using Robust.Shared.Input; using Robust.Shared.Timing; diff --git a/Content.Server/_CP14/Fishing/CP14FishingRodSystem.cs b/Content.Server/_CP14/Fishing/CP14FishingRodSystem.cs index e45db90aed..d4daa3bac3 100644 --- a/Content.Server/_CP14/Fishing/CP14FishingRodSystem.cs +++ b/Content.Server/_CP14/Fishing/CP14FishingRodSystem.cs @@ -1,4 +1,4 @@ -using Content.Shared._CP14.Fishing.FishingRod; +using Content.Shared._CP14.Fishing.Systems; namespace Content.Server._CP14.Fishing; diff --git a/Content.Shared/_CP14/Fishing/CP14FishingProcessComponent.cs b/Content.Shared/_CP14/Fishing/CP14FishingProcessComponent.cs deleted file mode 100644 index 3ea9d4fadd..0000000000 --- a/Content.Shared/_CP14/Fishing/CP14FishingProcessComponent.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System.Numerics; -using Robust.Shared.GameStates; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; -using Robust.Shared.Serialization; - -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; - - /** - * Progress - */ - - [ViewVariables, AutoNetworkedField] - 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 - { - [ViewVariables] - public float Size; - - [ViewVariables] - public float Position; - - [ViewVariables] - public float Velocity; - - [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 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/CP14FishingProcessPrototype.cs b/Content.Shared/_CP14/Fishing/CP14FishingProcessPrototype.cs deleted file mode 100644 index 31a6a9007d..0000000000 --- a/Content.Shared/_CP14/Fishing/CP14FishingProcessPrototype.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Robust.Shared.Prototypes; - -namespace Content.Shared._CP14.Fishing; - -[Prototype("CP14FishingProcess")] -public sealed class CP14FishingProcessPrototype : IPrototype -{ - [IdDataField] - public string ID { get; } = string.Empty; - - [DataField, ViewVariables] - public float Size; - - [DataField, ViewVariables] - public float Gravity; - - [DataField, ViewVariables] - public float PlayerSize; - - [DataField, ViewVariables] - public float LootSize; - - [DataField, ViewVariables] - public EntProtoId LootProtoId; -} diff --git a/Content.Shared/_CP14/Fishing/CP14FishingProcessStyleSheetPrototype.cs b/Content.Shared/_CP14/Fishing/CP14FishingProcessStyleSheetPrototype.cs deleted file mode 100644 index 7df6b294b5..0000000000 --- a/Content.Shared/_CP14/Fishing/CP14FishingProcessStyleSheetPrototype.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Numerics; -using Robust.Shared.Prototypes; - -namespace Content.Shared._CP14.Fishing; - -[Prototype("CP14FishingProcessStyleSheet")] -public sealed partial class CP14FishingProcessStyleSheetPrototype : IPrototype -{ - [IdDataField] - public string ID { get; } = string.Empty; - - [DataField, ViewVariables] - public BackgroundData Background = new(); - - [DataField, ViewVariables] - public HandleData Handle = new(); - - [DataDefinition, Serializable] - public sealed partial class BackgroundData - { - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string Texture = "/Textures/_CP14/Interface/Fishing/background.png"; - - [DataField("offset"), ViewVariables(VVAccess.ReadWrite)] - public Vector2 OffsetPixels = new(10, 0); - - [DataField("handleOffset"), ViewVariables(VVAccess.ReadWrite)] - public Vector2 HandleOffsetPixels = new(16, 4); - - [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). - /// - [ViewVariables] - public Vector2 Offset => OffsetPixels / 32f; - - /// - /// In units (pixels / 32). - /// - [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). - /// - [ViewVariables] - public float HandleHeight => HandleHeightPixels / 32f; - } - - [DataDefinition, Serializable] - public sealed partial class HandleData - { - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string TopTexture = "/Textures/_CP14/Interface/Fishing/Handle/top.png"; - - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string MiddleTexture = "/Textures/_CP14/Interface/Fishing/Handle/middle.png"; - - [DataField, ViewVariables(VVAccess.ReadWrite)] - public string BottomTexture = "/Textures/_CP14/Interface/Fishing/Handle/bottom.png"; - } -} diff --git a/Content.Shared/_CP14/Fishing/CP14FishingProcessSystem.cs b/Content.Shared/_CP14/Fishing/CP14FishingProcessSystem.cs deleted file mode 100644 index 2d4d807abf..0000000000 --- a/Content.Shared/_CP14/Fishing/CP14FishingProcessSystem.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -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; - - public override void Initialize() - { - base.Initialize(); - - _fishingRod = GetEntityQuery(); - } - - public override void Update(float frameTime) - { - base.Update(frameTime); - - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var entityUid, out var processComponent)) - { - Update((entityUid, processComponent), frameTime); - } - } - - private void Update(Entity process, float frameTime) - { - var fishingRodComponent = _fishingRod.GetComponent(process.Comp.FishingRod!.Value); - - if (fishingRodComponent.Reeling) - { - process.Comp.Player.Velocity += fishingRodComponent.Speed * frameTime; - } - else - { - process.Comp.Player.Velocity -= fishingRodComponent.Gravity * frameTime; - } - - 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) - { - process = null; - - var query = EntityQueryEnumerator(); - while (query.MoveNext(out var entityUid, out var processComponent)) - { - if (processComponent.User != userEntityUid) - continue; - - process = (entityUid, processComponent); - return true; - } - - return false; - } - - public Entity Start(ProtoId prototypeId, - Entity fishingRod, - Entity fishingPool, - EntityUid user) - { - var prototype = _prototype.Index(prototypeId); - return Start(prototype, fishingRod, fishingPool, user); - } - - public Entity Start(CP14FishingProcessPrototype prototype, - Entity fishingRod, - Entity fishingPool, - EntityUid user) - { - var entityUid = Spawn(); - var ensureComponent = EnsureComp(entityUid); - - ensureComponent.FishingRod = fishingRod; - ensureComponent.FishingPool = fishingPool; - ensureComponent.User = user; - - ensureComponent.Size = prototype.Size; - - ensureComponent.Player = new CP14FishingProcessComponent.Box(prototype.PlayerSize); - ensureComponent.Loot = new CP14FishingProcessComponent.Box(prototype.LootSize); - - ensureComponent.LootProtoId = prototype.LootProtoId; - ensureComponent.StyleSheet = _prototype.Index("Default"); - - Dirty(entityUid, ensureComponent); - - return (entityUid, ensureComponent); - } -} diff --git a/Content.Shared/_CP14/Fishing/Components/CP14FishingIconComponent.cs b/Content.Shared/_CP14/Fishing/Components/CP14FishingIconComponent.cs new file mode 100644 index 0000000000..be55333758 --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Components/CP14FishingIconComponent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Utility; + +namespace Content.Shared._CP14.Fishing.Components; + +[RegisterComponent, NetworkedComponent] +public sealed partial class CP14FishingIconComponent : Component +{ + public static readonly ResPath DefaultTexturePath = new("/Textures/_CP14/Interface/Fishing/Icons/default.png"); + + [DataField] + public ResPath TexturePath = DefaultTexturePath; +} diff --git a/Content.Shared/_CP14/Fishing/Components/CP14FishingPoolComponent.cs b/Content.Shared/_CP14/Fishing/Components/CP14FishingPoolComponent.cs new file mode 100644 index 0000000000..d39b460da6 --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Components/CP14FishingPoolComponent.cs @@ -0,0 +1,12 @@ +using Content.Shared._CP14.Fishing.Prototypes; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._CP14.Fishing.Components; + +[RegisterComponent, NetworkedComponent] +public sealed partial class CP14FishingPoolComponent : Component +{ + [DataField, ViewVariables(VVAccess.ReadWrite)] + public ProtoId LootTable = "Default"; +} diff --git a/Content.Shared/_CP14/Fishing/Components/CP14FishingProcessComponent.cs b/Content.Shared/_CP14/Fishing/Components/CP14FishingProcessComponent.cs new file mode 100644 index 0000000000..91ec7f22ce --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Components/CP14FishingProcessComponent.cs @@ -0,0 +1,64 @@ +using System.Numerics; +using Content.Shared._CP14.Fishing.Core; +using Content.Shared._CP14.Fishing.Prototypes; +using Content.Shared._CP14.Fishing.Systems; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._CP14.Fishing.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(CP14FishingProcessSystem))] +public sealed partial class CP14FishingProcessComponent : Component +{ + /** + * Boxes + */ + + [ViewVariables, AutoNetworkedField] + public Player Player; + + [ViewVariables, AutoNetworkedField] + public Fish Fish; + + /** + * Progress + */ + + [ViewVariables, AutoNetworkedField] + public float Progress; + + /** + * 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 * Fish.Position; + public Vector2 PlayerPositionNormalized => Vector2.UnitY * Player.Position; + public Vector2 PlayerHalfSizeNormalized => Vector2.UnitY * Player.HalfSize; +} diff --git a/Content.Shared/_CP14/Fishing/Components/CP14FishingRodComponent.cs b/Content.Shared/_CP14/Fishing/Components/CP14FishingRodComponent.cs new file mode 100644 index 0000000000..5c9f61f4ee --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Components/CP14FishingRodComponent.cs @@ -0,0 +1,42 @@ +using Content.Shared._CP14.Fishing.Prototypes; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared._CP14.Fishing.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class CP14FishingRodComponent : Component +{ + [ViewVariables] + public static readonly ProtoId DefaultStyle = "Default"; + + [ViewVariables] + public EntityUid? Process; + + [ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public bool Reeling; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Speed = 0.05f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Gravity = 0.075f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float MaxVelocity = 0.3f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float MinVelocity = -0.325f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Bouncing = 0.07f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Drag = 0.98f; + + [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] + public float Size = 0.25f; + + [DataField, ViewVariables(VVAccess.ReadWrite)] + public ProtoId Style = DefaultStyle; +} diff --git a/Content.Shared/_CP14/Fishing/Core/Behaviors/Behavior.cs b/Content.Shared/_CP14/Fishing/Core/Behaviors/Behavior.cs new file mode 100644 index 0000000000..aaaed81606 --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Core/Behaviors/Behavior.cs @@ -0,0 +1,16 @@ +using JetBrains.Annotations; +using Robust.Shared.Random; + +namespace Content.Shared._CP14.Fishing.Core.Behaviors; + +[ImplicitDataDefinitionForInheritors, MeansImplicitUse] +public abstract partial class Behavior +{ + [DataField] + public float Speed { get; set; } = 0.05f; + + [DataField] + public float Difficulty { get; set; } = 2f; + + public abstract float CalculateSpeed(IRobustRandom random); +} diff --git a/Content.Shared/_CP14/Fishing/Core/Behaviors/DartBehavior.cs b/Content.Shared/_CP14/Fishing/Core/Behaviors/DartBehavior.cs new file mode 100644 index 0000000000..daa57f0db4 --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Core/Behaviors/DartBehavior.cs @@ -0,0 +1,11 @@ +using Robust.Shared.Random; + +namespace Content.Shared._CP14.Fishing.Core.Behaviors; + +public sealed partial class DartBehavior : Behavior +{ + public override float CalculateSpeed(IRobustRandom random) + { + return Speed * (0.5f + random.NextFloat() * Difficulty); + } +} diff --git a/Content.Shared/_CP14/Fishing/Core/Behaviors/FloaterBehaviour.cs b/Content.Shared/_CP14/Fishing/Core/Behaviors/FloaterBehaviour.cs new file mode 100644 index 0000000000..a691a10cbc --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Core/Behaviors/FloaterBehaviour.cs @@ -0,0 +1,11 @@ +using Robust.Shared.Random; + +namespace Content.Shared._CP14.Fishing.Core.Behaviors; + +public sealed partial class FloaterBehaviour : Behavior +{ + public override float CalculateSpeed(IRobustRandom random) + { + return Speed * (0.5f + random.NextFloat() * Difficulty); + } +} diff --git a/Content.Shared/_CP14/Fishing/Core/Behaviors/MixedBehavior.cs b/Content.Shared/_CP14/Fishing/Core/Behaviors/MixedBehavior.cs new file mode 100644 index 0000000000..c3282cafe8 --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Core/Behaviors/MixedBehavior.cs @@ -0,0 +1,11 @@ +using Robust.Shared.Random; + +namespace Content.Shared._CP14.Fishing.Core.Behaviors; + +public sealed partial class MixedBehavior : Behavior +{ + public override float CalculateSpeed(IRobustRandom random) + { + return Speed * (random.NextFloat() - 0.5f); + } +} diff --git a/Content.Shared/_CP14/Fishing/Core/Behaviors/SinkerBehavior.cs b/Content.Shared/_CP14/Fishing/Core/Behaviors/SinkerBehavior.cs new file mode 100644 index 0000000000..85cf8b5aae --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Core/Behaviors/SinkerBehavior.cs @@ -0,0 +1,11 @@ +using Robust.Shared.Random; + +namespace Content.Shared._CP14.Fishing.Core.Behaviors; + +public sealed partial class SinkerBehavior : Behavior +{ + public override float CalculateSpeed(IRobustRandom random) + { + return Speed * (1.0f + random.NextFloat() * 0.5f); + } +} diff --git a/Content.Shared/_CP14/Fishing/Core/Behaviors/SmoothBehavior.cs b/Content.Shared/_CP14/Fishing/Core/Behaviors/SmoothBehavior.cs new file mode 100644 index 0000000000..c54e125a3b --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Core/Behaviors/SmoothBehavior.cs @@ -0,0 +1,11 @@ +using Robust.Shared.Random; + +namespace Content.Shared._CP14.Fishing.Core.Behaviors; + +public sealed partial class SmoothBehavior : Behavior +{ + public override float CalculateSpeed(IRobustRandom random) + { + return Speed * (0.5f + random.NextFloat() * Difficulty); + } +} diff --git a/Content.Shared/_CP14/Fishing/Core/Fish.cs b/Content.Shared/_CP14/Fishing/Core/Fish.cs new file mode 100644 index 0000000000..3b15030f64 --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Core/Fish.cs @@ -0,0 +1,48 @@ +using Content.Shared._CP14.Fishing.Core.Behaviors; +using Robust.Shared.Random; +using Robust.Shared.Serialization; +using Robust.Shared.Timing; + +namespace Content.Shared._CP14.Fishing.Core; + +[Serializable, NetSerializable] +public sealed class Fish +{ + private const float MaxPosition = 1f; + private const float MinPosition = 0f; + + public float Position { get; private set; } + + private readonly Behavior _behavior; + private readonly IRobustRandom _random; + private readonly IGameTiming _timing; + + private float _speed; + private TimeSpan _updateSpeedTime; + + public Fish(Behavior behavior, IRobustRandom random, IGameTiming timing) + { + _behavior = behavior; + _random = random; + _timing = timing; + } + + public void Update(float frameTime) + { + // Update speed + if (_timing.CurTime > _updateSpeedTime) + UpdateSpeed(); + + // Update position + Position += _speed * frameTime; + + // Clamp position + Position = Math.Clamp(Position, MinPosition, MaxPosition); + } + + private void UpdateSpeed() + { + _speed = _behavior.CalculateSpeed(_random); + _updateSpeedTime = _timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(1f / _behavior.Difficulty, 1f * _behavior.Difficulty)); + } +} diff --git a/Content.Shared/_CP14/Fishing/Core/Player.cs b/Content.Shared/_CP14/Fishing/Core/Player.cs new file mode 100644 index 0000000000..7a095c9930 --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Core/Player.cs @@ -0,0 +1,25 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared._CP14.Fishing.Core; + +[Serializable, NetSerializable] +public sealed class Player +{ + [ViewVariables(VVAccess.ReadWrite)] + public float Size; + + [ViewVariables(VVAccess.ReadWrite)] + public float Position; + + [ViewVariables(VVAccess.ReadWrite)] + public float Velocity; + + [ViewVariables] + public float HalfSize => Size / 2f; + + public Player(float size = 0.25f) + { + Size = size; + Position = HalfSize; + } +} diff --git a/Content.Shared/_CP14/Fishing/FishingPool/CP14FishingPoolComponent.cs b/Content.Shared/_CP14/Fishing/FishingPool/CP14FishingPoolComponent.cs deleted file mode 100644 index 977dcc9a92..0000000000 --- a/Content.Shared/_CP14/Fishing/FishingPool/CP14FishingPoolComponent.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Robust.Shared.GameStates; -using Robust.Shared.Prototypes; - -namespace Content.Shared._CP14.Fishing.FishingPool; - -[RegisterComponent, NetworkedComponent] -public sealed partial class CP14FishingPoolComponent : Component -{ - [DataField, ViewVariables(VVAccess.ReadWrite)] - public ProtoId LootTable; -} diff --git a/Content.Shared/_CP14/Fishing/FishingRod/CP14FishingRodComponent.cs b/Content.Shared/_CP14/Fishing/FishingRod/CP14FishingRodComponent.cs deleted file mode 100644 index 85f351655d..0000000000 --- a/Content.Shared/_CP14/Fishing/FishingRod/CP14FishingRodComponent.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Robust.Shared.GameStates; - -namespace Content.Shared._CP14.Fishing.FishingRod; - -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -public sealed partial class CP14FishingRodComponent : Component -{ - [ViewVariables] - public EntityUid? Process; - - [ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - public bool Reeling; - - [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] - 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/Content.Shared/_CP14/Fishing/FishingPool/CP14FishingPoolLootTablePrototype.cs b/Content.Shared/_CP14/Fishing/Prototypes/CP14FishingPoolLootTablePrototype.cs similarity index 84% rename from Content.Shared/_CP14/Fishing/FishingPool/CP14FishingPoolLootTablePrototype.cs rename to Content.Shared/_CP14/Fishing/Prototypes/CP14FishingPoolLootTablePrototype.cs index 7829496a7d..8f7c364df6 100644 --- a/Content.Shared/_CP14/Fishing/FishingPool/CP14FishingPoolLootTablePrototype.cs +++ b/Content.Shared/_CP14/Fishing/Prototypes/CP14FishingPoolLootTablePrototype.cs @@ -1,6 +1,6 @@ using Robust.Shared.Prototypes; -namespace Content.Shared._CP14.Fishing.FishingPool; +namespace Content.Shared._CP14.Fishing.Prototypes; [Prototype("CP14FishingPoolLootTable")] public sealed class CP14FishingPoolLootTablePrototype : IPrototype diff --git a/Content.Shared/_CP14/Fishing/Prototypes/CP14FishingProcessPrototype.cs b/Content.Shared/_CP14/Fishing/Prototypes/CP14FishingProcessPrototype.cs new file mode 100644 index 0000000000..c3563ed50c --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Prototypes/CP14FishingProcessPrototype.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared._CP14.Fishing.Prototypes; + +[Prototype("CP14FishingProcess")] +public sealed class CP14FishingProcessPrototype : IPrototype +{ + [IdDataField] + public string ID { get; } = string.Empty; + + [DataField, ViewVariables] + public EntProtoId LootProtoId; +} diff --git a/Content.Shared/_CP14/Fishing/Prototypes/CP14FishingProcessStyleSheetPrototype.cs b/Content.Shared/_CP14/Fishing/Prototypes/CP14FishingProcessStyleSheetPrototype.cs new file mode 100644 index 0000000000..66a1c6dadb --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Prototypes/CP14FishingProcessStyleSheetPrototype.cs @@ -0,0 +1,127 @@ +using System.Numerics; +using Robust.Shared.Prototypes; + +namespace Content.Shared._CP14.Fishing.Prototypes; + +/// +/// Represents the style sheet for the fishing process, containing UI elements like background and handle configurations. +/// +[Prototype("CP14FishingProcessStyleSheet")] +public sealed partial class CP14FishingProcessStyleSheetPrototype : IPrototype +{ + /// + /// Gets the unique identifier for this fishing process style sheet prototype. + /// + [IdDataField] + public string ID { get; } = string.Empty; + + /// + /// Background settings for the fishing process UI. + /// + [DataField, ViewVariables] + public BackgroundData Background = new(); + + /// + /// Handle settings for the fishing process UI. + /// + [DataField, ViewVariables] + public HandleData Handle = new(); + + /// + /// Contains data related to the background of the fishing process UI. + /// + [DataDefinition, Serializable] + public sealed partial class BackgroundData + { + /// + /// Path to the background texture image. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public string Texture = "/Textures/_CP14/Interface/Fishing/background.png"; + + /// + /// Offset of the background texture in pixels. + /// + [DataField("offset"), ViewVariables(VVAccess.ReadWrite)] + public Vector2 OffsetPixels = new(10, 0); + + /// + /// Offset of the handle in pixels. + /// + [DataField("handleOffset"), ViewVariables(VVAccess.ReadWrite)] + public Vector2 HandleOffsetPixels = new(16, 4); + + /// + /// Size of the handle in pixels. + /// + [DataField("handleSize"), ViewVariables(VVAccess.ReadWrite)] + public Vector2 HandleSizePixels = new(149, 0); + + /// + /// Offset of the progress bar in pixels. + /// + [DataField("progressOffset"), ViewVariables(VVAccess.ReadWrite)] + public Vector2 ProgressOffsetPixels = new(31, 3); + + /// + /// Size of the progress bar in pixels. + /// + [DataField("progressSize"), ViewVariables(VVAccess.ReadWrite)] + public Vector2 ProgressSizePixels = new(4, 144); + + /// + /// Gets the background offset in units (pixels divided by 32). + /// + [ViewVariables] + public Vector2 Offset => OffsetPixels / 32f; + + /// + /// Gets the handle offset in units (pixels divided by 32). + /// + [ViewVariables] + public Vector2 HandleOffset => HandleOffsetPixels / 32f; + + /// + /// Gets the progress bar offset in units (pixels divided by 32). + /// + [ViewVariables] + public Vector2 ProgressOffset => ProgressOffsetPixels / 32f; + + /// + /// Gets the progress bar size in units (pixels divided by 32). + /// + [ViewVariables] + public Vector2 ProgressSize => ProgressSizePixels / 32f; + + /// + /// Gets the handle size in units (pixels divided by 32). + /// + [ViewVariables] + public Vector2 HandleSize => HandleSizePixels / 32f; + } + + /// + /// Contains data related to the handle elements of the fishing process UI. + /// + [DataDefinition, Serializable] + public sealed partial class HandleData + { + /// + /// Path to the texture for the top part of the handle. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public string TopTexture = "/Textures/_CP14/Interface/Fishing/Handle/top.png"; + + /// + /// Path to the texture for the middle part of the handle. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public string MiddleTexture = "/Textures/_CP14/Interface/Fishing/Handle/middle.png"; + + /// + /// Path to the texture for the bottom part of the handle. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public string BottomTexture = "/Textures/_CP14/Interface/Fishing/Handle/bottom.png"; + } +} diff --git a/Content.Shared/_CP14/Fishing/Systems/CP14FishingPoolSystem.cs b/Content.Shared/_CP14/Fishing/Systems/CP14FishingPoolSystem.cs new file mode 100644 index 0000000000..de66415ac0 --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Systems/CP14FishingPoolSystem.cs @@ -0,0 +1,19 @@ +using Content.Shared._CP14.Fishing.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Shared._CP14.Fishing.Systems; + +public sealed class CP14FishingPoolSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + public EntProtoId GetLootPrototypeId(Entity pool) + { + var lootTable = _prototype.Index(pool.Comp.LootTable); + var loot = _random.Pick(lootTable.Prototypes); + + return loot; + } +} diff --git a/Content.Shared/_CP14/Fishing/Systems/CP14FishingProcessSystem.cs b/Content.Shared/_CP14/Fishing/Systems/CP14FishingProcessSystem.cs new file mode 100644 index 0000000000..90e37868b8 --- /dev/null +++ b/Content.Shared/_CP14/Fishing/Systems/CP14FishingProcessSystem.cs @@ -0,0 +1,162 @@ +using System.Diagnostics.CodeAnalysis; +using Content.Shared._CP14.Fishing.Components; +using Content.Shared._CP14.Fishing.Core; +using Content.Shared._CP14.Fishing.Core.Behaviors; +using Content.Shared._CP14.Fishing.Prototypes; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Shared._CP14.Fishing.Systems; + +public sealed class CP14FishingProcessSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IPrototypeManager _prototype = default!; + [Dependency] private readonly IRobustRandom _random = default!; + + [Dependency] private readonly CP14FishingPoolSystem _pool = default!; + + private EntityQuery _fishingRod; + + public override void Initialize() + { + base.Initialize(); + + _fishingRod = GetEntityQuery(); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var entityUid, out var processComponent)) + { + Update((entityUid, processComponent), frameTime); + } + } + + private void Update(Entity process, float frameTime) + { + var fishingRod = GetRod(process); + + UpdateReeling(process, fishingRod, frameTime); + UpdateVelocity(process, fishingRod); + UpdatePosition(process, frameTime); + + process.Comp.Fish.Update(frameTime); + + var collides = Collide(process.Comp.Fish, process.Comp.Player); + + var progressAdditive = collides ? 0.05f : -0.1f; + process.Comp.Progress = Math.Clamp(process.Comp.Progress + progressAdditive * frameTime, 0, 1); + } + + private void UpdateReeling(Entity process, + Entity fishingRod, + float frameTime) + { + if (fishingRod.Comp.Reeling) + { + process.Comp.Player.Velocity += fishingRod.Comp.Speed * frameTime; + return; + } + + process.Comp.Player.Velocity -= fishingRod.Comp.Gravity * frameTime; + } + + private void UpdateVelocity(Entity process, + Entity fishingRod) + { + process.Comp.Player.Velocity *= fishingRod.Comp.Drag; + process.Comp.Player.Velocity = Math.Clamp(process.Comp.Player.Velocity, + fishingRod.Comp.MinVelocity, + fishingRod.Comp.MaxVelocity); + } + + private void UpdatePosition(Entity process, + float frameTime) + { + process.Comp.Player.Position += process.Comp.Player.Velocity * frameTime; + + var halfSize = process.Comp.Player.HalfSize; + process.Comp.Player.Position = Math.Clamp(process.Comp.Player.Position, halfSize, 1 - halfSize); + } + + public bool TryGetByUser(EntityUid userEntityUid, [NotNullWhen(true)] out Entity? process) + { + process = null; + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var entityUid, out var processComponent)) + { + if (processComponent.User != userEntityUid) + continue; + + process = (entityUid, processComponent); + return true; + } + + return false; + } + + public void Finish(Entity process) + { + + } + + public Entity Start( + Entity fishingRod, + Entity fishingPool, + EntityUid user) + { + var process = CreateProcess(); + var loot = _pool.GetLootPrototypeId(fishingPool); + var style = GetStyle(fishingRod); + + // Save entities + process.Comp.FishingRod = fishingRod; + process.Comp.FishingPool = fishingPool; + process.Comp.User = user; + + process.Comp.Player = new Player(fishingRod.Comp.Size); + process.Comp.Fish = new Fish(new MixedBehavior(), _random, _timing); + + process.Comp.LootProtoId = loot; + process.Comp.StyleSheet = style; + + return process; + } + + private Entity CreateProcess() + { + var entityUid = Spawn(); + var ensureComponent = EnsureComp(entityUid); + + return (entityUid, ensureComponent); + } + + private Entity GetRod(Entity process) + { + var entityUid = process.Comp.FishingRod!.Value; + var component = _fishingRod.GetComponent(process.Comp.FishingRod!.Value); + return (entityUid, component); + } + + private CP14FishingProcessStyleSheetPrototype GetStyle(Entity fishingRod) + { + if (_prototype.TryIndex(fishingRod.Comp.Style, out var style)) + return style; + + Log.Error($"Failed to retrieve fishing rod style, {fishingRod.Comp.Style} not found. Reverting to default style."); + return _prototype.Index(CP14FishingRodComponent.DefaultStyle); + } + + private static bool Collide(Fish fish, Player player) + { + var playerMin = player.Position - player.HalfSize; + var playerMax = player.Position + player.HalfSize; + return fish.Position >= playerMin && fish.Position <= playerMax; + } +} diff --git a/Content.Shared/_CP14/Fishing/FishingRod/CP14SharedFishingRodSystem.cs b/Content.Shared/_CP14/Fishing/Systems/CP14SharedFishingRodSystem.cs similarity index 87% rename from Content.Shared/_CP14/Fishing/FishingRod/CP14SharedFishingRodSystem.cs rename to Content.Shared/_CP14/Fishing/Systems/CP14SharedFishingRodSystem.cs index 0a050dc70b..4d96e62cf2 100644 --- a/Content.Shared/_CP14/Fishing/FishingRod/CP14SharedFishingRodSystem.cs +++ b/Content.Shared/_CP14/Fishing/Systems/CP14SharedFishingRodSystem.cs @@ -1,9 +1,9 @@ -using Content.Shared._CP14.Fishing.FishingPool; +using Content.Shared._CP14.Fishing.Components; using Content.Shared.Hands.Components; using Content.Shared.Interaction; using Robust.Shared.Serialization; -namespace Content.Shared._CP14.Fishing.FishingRod; +namespace Content.Shared._CP14.Fishing.Systems; public abstract class CP14SharedFishingRodSystem : EntitySystem { @@ -43,7 +43,7 @@ public abstract class CP14SharedFishingRodSystem : EntitySystem if (!TryComp(args.Used, out var fishingRodComponent)) return; - fishingRodComponent.Process = _fishingProcess.Start("Debug", (args.Used, fishingRodComponent), entity, args.User); + fishingRodComponent.Process = _fishingProcess.Start((args.Used, fishingRodComponent), entity, args.User); } diff --git a/Resources/Prototypes/_CP14/Entities/Objects/Fishing/styleSheets.yml b/Resources/Prototypes/_CP14/Entities/Objects/Fishing/styleSheets.yml deleted file mode 100644 index 759f22d328..0000000000 --- a/Resources/Prototypes/_CP14/Entities/Objects/Fishing/styleSheets.yml +++ /dev/null @@ -1,13 +0,0 @@ -- type: CP14FishingProcessStyleSheet - id: Default - background: - texture: /Textures/_CP14/Interface/Fishing/background.png - 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 - bottomTexture: /Textures/_CP14/Interface/Fishing/Handle/bottom.png diff --git a/Resources/Prototypes/_CP14/Fishing/lootTables.yml b/Resources/Prototypes/_CP14/Fishing/lootTables.yml new file mode 100644 index 0000000000..5cf5f394fa --- /dev/null +++ b/Resources/Prototypes/_CP14/Fishing/lootTables.yml @@ -0,0 +1,4 @@ +- type: CP14FishingPoolLootTable + id: Default + prototypes: + - CP14FloorWater diff --git a/Resources/Prototypes/_CP14/Fishing/processes.yml b/Resources/Prototypes/_CP14/Fishing/processes.yml deleted file mode 100644 index 8dbfc52c9a..0000000000 --- a/Resources/Prototypes/_CP14/Fishing/processes.yml +++ /dev/null @@ -1,6 +0,0 @@ -- type: CP14FishingProcess - id: Debug - size: 10 - playerSize: 1 - lootSize: 0 - lootProtoId: CP14FloorWater diff --git a/Resources/Prototypes/_CP14/Fishing/styleSheets.yml b/Resources/Prototypes/_CP14/Fishing/styleSheets.yml new file mode 100644 index 0000000000..dcf56677a8 --- /dev/null +++ b/Resources/Prototypes/_CP14/Fishing/styleSheets.yml @@ -0,0 +1,13 @@ +- type: CP14FishingProcessStyleSheet + id: Default + background: + texture: /Textures/_CP14/Interface/Fishing/Styles/Default/background.png + offset: 10, 0 + handleOffset: 14, 5 + handleSize: 11, 141 + progressOffset: 4, 4 + progressSize: 2, 142 + handle: + topTexture: /Textures/_CP14/Interface/Fishing/Styles/Default/Handle/top.png + middleTexture: /Textures/_CP14/Interface/Fishing/Styles/Default/Handle/middle.png + bottomTexture: /Textures/_CP14/Interface/Fishing/Styles/Default/Handle/bottom.png