Updated system

This commit is contained in:
Tornado Tech
2024-12-09 02:29:33 +10:00
parent a88e0ee00f
commit dbcf17bab2
31 changed files with 641 additions and 422 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -1,4 +1,4 @@
using Content.Shared._CP14.Fishing.FishingRod;
using Content.Shared._CP14.Fishing.Systems;
namespace Content.Server._CP14.Fishing;

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -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);
/// <remarks>
/// In units (<c>pixels / 32</c>).
/// </remarks>
[ViewVariables]
public Vector2 Offset => OffsetPixels / 32f;
/// <remarks>
/// In units (<c>pixels / 32</c>).
/// </remarks>
[ViewVariables]
public Vector2 HandleOffset => HandleOffsetPixels / 32f;
/// <remarks>
/// In units (<c>pixels / 32</c>).
/// </remarks>
[ViewVariables]
public Vector2 ProgressOffset => ProgressOffsetPixels / 32f;
/// <remarks>
/// In units (<c>pixels / 32</c>).
/// </remarks>
[ViewVariables]
public Vector2 ProgressSize => ProgressSizePixels / 32f;
/// <remarks>
/// In units (<c>pixels / 32</c>).
/// </remarks>
[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";
}
}

View File

@@ -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<CP14FishingRodComponent> _fishingRod;
public override void Initialize()
{
base.Initialize();
_fishingRod = GetEntityQuery<CP14FishingRodComponent>();
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<CP14FishingProcessComponent>();
while (query.MoveNext(out var entityUid, out var processComponent))
{
Update((entityUid, processComponent), frameTime);
}
}
private void Update(Entity<CP14FishingProcessComponent> 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<CP14FishingProcessComponent>? process)
{
process = null;
var query = EntityQueryEnumerator<CP14FishingProcessComponent>();
while (query.MoveNext(out var entityUid, out var processComponent))
{
if (processComponent.User != userEntityUid)
continue;
process = (entityUid, processComponent);
return true;
}
return false;
}
public Entity<CP14FishingProcessComponent> Start(ProtoId<CP14FishingProcessPrototype> prototypeId,
Entity<CP14FishingRodComponent> fishingRod,
Entity<CP14FishingPoolComponent> fishingPool,
EntityUid user)
{
var prototype = _prototype.Index(prototypeId);
return Start(prototype, fishingRod, fishingPool, user);
}
public Entity<CP14FishingProcessComponent> Start(CP14FishingProcessPrototype prototype,
Entity<CP14FishingRodComponent> fishingRod,
Entity<CP14FishingPoolComponent> fishingPool,
EntityUid user)
{
var entityUid = Spawn();
var ensureComponent = EnsureComp<CP14FishingProcessComponent>(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<CP14FishingProcessStyleSheetPrototype>("Default");
Dirty(entityUid, ensureComponent);
return (entityUid, ensureComponent);
}
}

View File

@@ -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;
}

View File

@@ -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<CP14FishingPoolLootTablePrototype> LootTable = "Default";
}

View File

@@ -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;
}

View File

@@ -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<CP14FishingProcessStyleSheetPrototype> 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<CP14FishingProcessStyleSheetPrototype> Style = DefaultStyle;
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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<CP14FishingPoolLootTablePrototype> LootTable;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -0,0 +1,127 @@
using System.Numerics;
using Robust.Shared.Prototypes;
namespace Content.Shared._CP14.Fishing.Prototypes;
/// <summary>
/// Represents the style sheet for the fishing process, containing UI elements like background and handle configurations.
/// </summary>
[Prototype("CP14FishingProcessStyleSheet")]
public sealed partial class CP14FishingProcessStyleSheetPrototype : IPrototype
{
/// <summary>
/// Gets the unique identifier for this fishing process style sheet prototype.
/// </summary>
[IdDataField]
public string ID { get; } = string.Empty;
/// <summary>
/// Background settings for the fishing process UI.
/// </summary>
[DataField, ViewVariables]
public BackgroundData Background = new();
/// <summary>
/// Handle settings for the fishing process UI.
/// </summary>
[DataField, ViewVariables]
public HandleData Handle = new();
/// <summary>
/// Contains data related to the background of the fishing process UI.
/// </summary>
[DataDefinition, Serializable]
public sealed partial class BackgroundData
{
/// <summary>
/// Path to the background texture image.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public string Texture = "/Textures/_CP14/Interface/Fishing/background.png";
/// <summary>
/// Offset of the background texture in pixels.
/// </summary>
[DataField("offset"), ViewVariables(VVAccess.ReadWrite)]
public Vector2 OffsetPixels = new(10, 0);
/// <summary>
/// Offset of the handle in pixels.
/// </summary>
[DataField("handleOffset"), ViewVariables(VVAccess.ReadWrite)]
public Vector2 HandleOffsetPixels = new(16, 4);
/// <summary>
/// Size of the handle in pixels.
/// </summary>
[DataField("handleSize"), ViewVariables(VVAccess.ReadWrite)]
public Vector2 HandleSizePixels = new(149, 0);
/// <summary>
/// Offset of the progress bar in pixels.
/// </summary>
[DataField("progressOffset"), ViewVariables(VVAccess.ReadWrite)]
public Vector2 ProgressOffsetPixels = new(31, 3);
/// <summary>
/// Size of the progress bar in pixels.
/// </summary>
[DataField("progressSize"), ViewVariables(VVAccess.ReadWrite)]
public Vector2 ProgressSizePixels = new(4, 144);
/// <summary>
/// Gets the background offset in units (pixels divided by 32).
/// </summary>
[ViewVariables]
public Vector2 Offset => OffsetPixels / 32f;
/// <summary>
/// Gets the handle offset in units (pixels divided by 32).
/// </summary>
[ViewVariables]
public Vector2 HandleOffset => HandleOffsetPixels / 32f;
/// <summary>
/// Gets the progress bar offset in units (pixels divided by 32).
/// </summary>
[ViewVariables]
public Vector2 ProgressOffset => ProgressOffsetPixels / 32f;
/// <summary>
/// Gets the progress bar size in units (pixels divided by 32).
/// </summary>
[ViewVariables]
public Vector2 ProgressSize => ProgressSizePixels / 32f;
/// <summary>
/// Gets the handle size in units (pixels divided by 32).
/// </summary>
[ViewVariables]
public Vector2 HandleSize => HandleSizePixels / 32f;
}
/// <summary>
/// Contains data related to the handle elements of the fishing process UI.
/// </summary>
[DataDefinition, Serializable]
public sealed partial class HandleData
{
/// <summary>
/// Path to the texture for the top part of the handle.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public string TopTexture = "/Textures/_CP14/Interface/Fishing/Handle/top.png";
/// <summary>
/// Path to the texture for the middle part of the handle.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public string MiddleTexture = "/Textures/_CP14/Interface/Fishing/Handle/middle.png";
/// <summary>
/// Path to the texture for the bottom part of the handle.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
public string BottomTexture = "/Textures/_CP14/Interface/Fishing/Handle/bottom.png";
}
}

View File

@@ -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<CP14FishingPoolComponent> pool)
{
var lootTable = _prototype.Index(pool.Comp.LootTable);
var loot = _random.Pick(lootTable.Prototypes);
return loot;
}
}

View File

@@ -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<CP14FishingRodComponent> _fishingRod;
public override void Initialize()
{
base.Initialize();
_fishingRod = GetEntityQuery<CP14FishingRodComponent>();
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<CP14FishingProcessComponent>();
while (query.MoveNext(out var entityUid, out var processComponent))
{
Update((entityUid, processComponent), frameTime);
}
}
private void Update(Entity<CP14FishingProcessComponent> 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<CP14FishingProcessComponent> process,
Entity<CP14FishingRodComponent> 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<CP14FishingProcessComponent> process,
Entity<CP14FishingRodComponent> 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<CP14FishingProcessComponent> 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<CP14FishingProcessComponent>? process)
{
process = null;
var query = EntityQueryEnumerator<CP14FishingProcessComponent>();
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<CP14FishingProcessComponent?> process)
{
}
public Entity<CP14FishingProcessComponent> Start(
Entity<CP14FishingRodComponent> fishingRod,
Entity<CP14FishingPoolComponent> 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<CP14FishingProcessComponent> CreateProcess()
{
var entityUid = Spawn();
var ensureComponent = EnsureComp<CP14FishingProcessComponent>(entityUid);
return (entityUid, ensureComponent);
}
private Entity<CP14FishingRodComponent> GetRod(Entity<CP14FishingProcessComponent> process)
{
var entityUid = process.Comp.FishingRod!.Value;
var component = _fishingRod.GetComponent(process.Comp.FishingRod!.Value);
return (entityUid, component);
}
private CP14FishingProcessStyleSheetPrototype GetStyle(Entity<CP14FishingRodComponent> 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;
}
}

View File

@@ -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<CP14FishingRodComponent>(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);
}

View File

@@ -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

View File

@@ -0,0 +1,4 @@
- type: CP14FishingPoolLootTable
id: Default
prototypes:
- CP14FloorWater

View File

@@ -1,6 +0,0 @@
- type: CP14FishingProcess
id: Debug
size: 10
playerSize: 1
lootSize: 0
lootProtoId: CP14FloorWater

View File

@@ -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