diff --git a/Content.Common.Data/_Shitcode/Weapons/Misc/PhysicsGunBlacklistComponent.cs b/Content.Common.Data/_Shitcode/Weapons/Misc/PhysicsGunBlacklistComponent.cs new file mode 100644 index 00000000000..5b7d3f021d9 --- /dev/null +++ b/Content.Common.Data/_Shitcode/Weapons/Misc/PhysicsGunBlacklistComponent.cs @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2024 Piras314 +// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Misandry +// SPDX-FileCopyrightText: 2025 gus +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +namespace Content.Common.Data._Shitcode.Weapons.Misc; + +/// +/// Marks an entity as unable to be tether or force gunned +/// +[RegisterComponent] +public sealed partial class PhysicsGunBlacklistComponent : Component +{ +} diff --git a/Content.Module.Client/_Goobstation/Fishing/FishingSystem.cs b/Content.Module.Client/_Goobstation/Fishing/FishingSystem.cs new file mode 100644 index 00000000000..e5dbef13f54 --- /dev/null +++ b/Content.Module.Client/_Goobstation/Fishing/FishingSystem.cs @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: 2025 Aidenkrz +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +using Content.Goobstation.Client.Fishing.Overlays; +using Content.Goobstation.Shared.Fishing.Components; +using Content.Goobstation.Shared.Fishing.Systems; +using Robust.Client.Graphics; +using Robust.Client.Player; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; + +namespace Content.Goobstation.Client.Fishing; + +public sealed class FishingSystem : SharedFishingSystem +{ + [Dependency] private readonly IOverlayManager _overlay = default!; + [Dependency] private readonly IPlayerManager _player = default!; + + public override void Initialize() + { + base.Initialize(); + _overlay.AddOverlay(new FishingOverlay(EntityManager, _player)); + } + + public override void Shutdown() + { + base.Shutdown(); + _overlay.RemoveOverlay(); + } + + // Does nothing on client, because can't spawn entities in prediction + protected override void SetupFishingFloat(Entity fishingRod, EntityUid player, EntityCoordinates target) {} + + // Does nothing on client, because can't delete entities in prediction + protected override void ThrowFishReward(EntProtoId fishId, EntityUid fishSpot, EntityUid target) {} + + // Does nothing on client, because NUKE ALL PREDICTION!!!! (UseInHands event sometimes gets declined on Server side, and it desyncs, so we can't predict that sadly. + protected override void CalculateFightingTimings(Entity fisher, ActiveFishingSpotComponent activeSpotComp) {} +} diff --git a/Content.Module.Client/_Goobstation/Fishing/Overlays/FishingOverlay.cs b/Content.Module.Client/_Goobstation/Fishing/Overlays/FishingOverlay.cs new file mode 100644 index 00000000000..9905173baf0 --- /dev/null +++ b/Content.Module.Client/_Goobstation/Fishing/Overlays/FishingOverlay.cs @@ -0,0 +1,137 @@ +// SPDX-FileCopyrightText: 2025 Aidenkrz +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +using System.Numerics; +using Content.Client.UserInterface.Systems; +using Content.Goobstation.Shared.Fishing.Components; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Shared.Enums; +using Robust.Client.Player; +using Robust.Shared.Utility; + +namespace Content.Goobstation.Client.Fishing.Overlays; + +public sealed class FishingOverlay : Overlay +{ + private readonly IEntityManager _entManager; + private readonly IPlayerManager _player; + private readonly SharedTransformSystem _transform; + private readonly ProgressColorSystem _progressColor; + + private readonly Texture _barTexture; + + // Fractional positions for progress bar fill (relative to texture height/width) + private const float StartYFraction = 0.09375f; // 3/32 + private const float EndYFraction = 0.90625f; // 29/32 + private const float BarWidthFraction = 0.2f; // 2/10 + + // Apply a custom scale factor to reduce the size of the progress bar + // We dont want to do this because muh pixel consistency, but i'll keep it here as an option + private const float BarScale = 1f; + + public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV; + + public FishingOverlay(IEntityManager entManager, IPlayerManager player) + { + _entManager = entManager; + _player = player; + _transform = _entManager.EntitySysManager.GetEntitySystem(); + _progressColor = _entManager.System(); + + // Load the progress bar texture + var sprite = new SpriteSpecifier.Rsi(new("/Textures/_Goobstation/Interface/Misc/fish_bar.rsi"), "icon"); + _barTexture = _entManager.EntitySysManager.GetEntitySystem().Frame0(sprite); + } + + protected override void Draw(in OverlayDrawArgs args) + { + var handle = args.WorldHandle; + var rotation = args.Viewport.Eye?.Rotation ?? Angle.Zero; + var xformQuery = _entManager.GetEntityQuery(); + + const float scale = 1f; + var scaleMatrix = Matrix3Helpers.CreateScale(new Vector2(scale, scale)); + var rotationMatrix = Matrix3Helpers.CreateRotation(-rotation); + + // Define bounds for culling entities outside the viewport + var bounds = args.WorldAABB.Enlarged(5f); + var localEnt = _player.LocalSession?.AttachedEntity; + + // Calculate the size of the texture in world units + var textureSize = new Vector2(_barTexture.Width, _barTexture.Height) / EyeManager.PixelsPerMeter; + + var scaledTextureSize = textureSize * BarScale; + + // Define the progress bar's width as a fraction of the texture width + var barWidth = scaledTextureSize.X * BarWidthFraction; + + // Iterate through all entities with ActiveFisherComponent + var enumerator = _entManager.AllEntityQueryEnumerator(); + while (enumerator.MoveNext(out var uid, out var comp, out var sprite, out var xform)) + { + // Skip if the entity is not on the current map, has invalid progress, or is not the local player + if (xform.MapID != args.MapId || + comp.TotalProgress == null || + comp.TotalProgress < 0 || + uid != localEnt) + continue; + + // Get the world position of the entity + var worldPosition = _transform.GetWorldPosition(xform, xformQuery); + if (!bounds.Contains(worldPosition)) + continue; + + // Set up the transformation matrix for rendering + var worldMatrix = Matrix3Helpers.CreateTranslation(worldPosition); + var scaledWorld = Matrix3x2.Multiply(scaleMatrix, worldMatrix); + var matty = Matrix3x2.Multiply(rotationMatrix, scaledWorld); + handle.SetTransform(matty); + + // Calculate the position of the progress bar relative to the entity + var position = new Vector2( + sprite.Bounds.Width / 2f, + -scaledTextureSize.Y / 2f // Center vertically + ); + + // Draw the background texture at the scaled size + handle.DrawTextureRect(_barTexture, new Box2(position, position + scaledTextureSize)); + + // Calculate progress and clamp it to [0, 1] + var progress = Math.Clamp(comp.TotalProgress.Value, 0f, 1f); + + // Calculate the fill height based on progress + var startYPixel = scaledTextureSize.Y * StartYFraction; + var endYPixel = scaledTextureSize.Y * EndYFraction; + var yProgress = (endYPixel - startYPixel) * progress + startYPixel; + + // Define the fill box with the correct width and height + var box = new Box2( + new Vector2((scaledTextureSize.X - barWidth) / 2f, startYPixel), + new Vector2((scaledTextureSize.X + barWidth) / 2f, yProgress) + ); + + // Translate the box to the correct position + box = box.Translated(position); + + // Draw the progress fill + var color = GetProgressColor(progress); + handle.DrawRect(box, color); + } + + // Reset the shader and transform + handle.UseShader(null); + handle.SetTransform(Matrix3x2.Identity); + } + + /// + /// Gets the color for the progress bar based on the progress value. + /// + public Color GetProgressColor(float progress, float alpha = 1f) + { + return _progressColor.GetProgressColor(progress).WithAlpha(alpha); + } +} diff --git a/Content.Module.Server/_Goobstation/Fishing/FishingSystem.cs b/Content.Module.Server/_Goobstation/Fishing/FishingSystem.cs new file mode 100644 index 00000000000..8b117b80743 --- /dev/null +++ b/Content.Module.Server/_Goobstation/Fishing/FishingSystem.cs @@ -0,0 +1,167 @@ +// SPDX-FileCopyrightText: 2025 Aidenkrz +// SPDX-FileCopyrightText: 2025 Aviu00 <93730715+Aviu00@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Aviu00 +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Rouden <149893554+Roudenn@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +using System.Linq; +using System.Numerics; +using Content.Goobstation.Shared.Fishing.Components; +using Content.Goobstation.Shared.Fishing.Systems; +using Content.Shared.EntityTable; +using Content.Shared.Interaction.Events; +using Content.Shared.Item; +using Content.Shared.Movement.Pulling.Components; +using Content.Shared.Physics; +using Robust.Server.GameObjects; +using Robust.Shared.Map; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Events; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Goobstation.Server.Fishing; + +public sealed class FishingSystem : SharedFishingSystem +{ + // Here we calculate the start of fishing, because apparently StartCollideEvent + // works janky on clientside so we can't predict when fishing starts. + [Dependency] private readonly IComponentFactory _compFactory = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly PhysicsSystem _physics = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnFloatCollide); + SubscribeLocalEvent(OnFishingInteract); + } + + #region Event handling + + private void OnFloatCollide(Entity ent, ref StartCollideEvent args) + { + // TODO: make it so this can collide with any unacnchored objects (items, mobs, etc) but not the player casting it (get parent of rod?) + // Fishing spot logic + var attachedEnt = args.OtherEntity; + + if (HasComp(attachedEnt)) + return; + + if (!FishSpotQuery.TryComp(attachedEnt, out var spotComp)) + { + if (args.OtherBody.BodyType == BodyType.Static) + return; + + Anchor(ent, attachedEnt); + return; + } + + // Anchor fishing float on an entity + Anchor(ent, attachedEnt); + + // Currently we don't support multiple loots from this + var fish = spotComp.FishList.GetSpawns(_random.GetRandom(), EntityManager, _proto, new EntityTableContext()).First(); + + // Get fish difficulty + _proto.Index(fish).TryGetComponent(out FishComponent? fishComp, _compFactory); + + // Assign things that depend on the fish + var activeFishSpot = EnsureComp(attachedEnt); + activeFishSpot.Fish = fish; + activeFishSpot.FishDifficulty = fishComp?.FishDifficulty ?? FishComponent.DefaultDifficulty; + + // Assign things that depend on the spot + var time = spotComp.FishDefaultTimer + _random.NextFloat(-spotComp.FishTimerVariety, spotComp.FishTimerVariety); + activeFishSpot.FishingStartTime = Timing.CurTime + TimeSpan.FromSeconds(time); + activeFishSpot.AttachedFishingLure = ent; + + // Declares war on prediction + Dirty(attachedEnt, activeFishSpot); + Dirty(ent); + } + + private void OnFishingInteract(EntityUid uid, FishingRodComponent component, UseInHandEvent args) + { + if (!FisherQuery.TryComp(args.User, out var fisherComp) || fisherComp.TotalProgress == null || args.Handled || !Timing.IsFirstTimePredicted) + return; + + fisherComp.TotalProgress += fisherComp.ProgressPerUse * component.Efficiency; + Dirty(args.User, fisherComp); // That's a bit evil, but we want to keep numbers real. + + args.Handled = true; + } + + private void Anchor(Entity ent, EntityUid attachedEnt) + { + var spotPosition = Xform.GetWorldPosition(attachedEnt); + Xform.SetWorldPosition(ent, spotPosition); + Xform.SetParent(ent, attachedEnt); + _physics.SetLinearVelocity(ent, Vector2.Zero); + _physics.SetAngularVelocity(ent, 0f); + ent.Comp.AttachedEntity = attachedEnt; + RemComp(ent); + RemComp(ent); + } + + #endregion + + protected override void SetupFishingFloat(Entity fishingRod, EntityUid player, EntityCoordinates target) + { + var (uid, component) = fishingRod; + var targetCoords = Xform.ToMapCoordinates(target); + var playerCoords = Xform.GetMapCoordinates(Transform(player)); + + var fishFloat = Spawn(component.FloatPrototype, playerCoords); + component.FishingLure = fishFloat; + Dirty(uid, component); + + // Calculate throw direction + var direction = targetCoords.Position - playerCoords.Position; + if (direction == Vector2.Zero) + direction = Vector2.UnitX; // If the user somehow manages to click directly in the center of themself, just toss it to the right i guess. + + // Yeet + Throwing.TryThrow(fishFloat, direction, 15f, player, 2f, null, true); + + // Set up lure component + var fishLureComp = EnsureComp(fishFloat); + fishLureComp.FishingRod = uid; + Dirty(fishFloat, fishLureComp); + + // Rope visuals + var visuals = EnsureComp(fishFloat); + visuals.Sprite = component.RopeSprite; + visuals.OffsetA = component.RopeLureOffset; + visuals.OffsetB = component.RopeUserOffset; + visuals.Target = uid; + } + + protected override void ThrowFishReward(EntProtoId fishId, EntityUid fishSpot, EntityUid target) + { + var position = Transform(fishSpot).Coordinates; + var fish = Spawn(fishId, position); + // Throw da fish back to the player because it looks funny + var direction = Xform.GetWorldPosition(target) - Xform.GetWorldPosition(fish); + var length = direction.Length(); + var distance = Math.Clamp(length, 0.5f, 15f); + direction *= distance / length; + + Throwing.TryThrow(fish, direction, 7f); + } + + protected override void CalculateFightingTimings(Entity fisher, ActiveFishingSpotComponent activeSpotComp) + { + if (Timing.CurTime < fisher.Comp.NextStruggle) + return; + + fisher.Comp.NextStruggle = Timing.CurTime + TimeSpan.FromSeconds(_random.NextFloat(0.06f, 0.18f)); + fisher.Comp.TotalProgress -= activeSpotComp.FishDifficulty; + Dirty(fisher); + } +} diff --git a/Content.Module.Shared/_Goobstation/Fishing/Components/ActiveFisherComponent.cs b/Content.Module.Shared/_Goobstation/Fishing/Components/ActiveFisherComponent.cs new file mode 100644 index 00000000000..32074deb890 --- /dev/null +++ b/Content.Module.Shared/_Goobstation/Fishing/Components/ActiveFisherComponent.cs @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2025 Aidenkrz +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +using Robust.Shared.GameStates; + +namespace Content.Goobstation.Shared.Fishing.Components; + +/// +/// Applied to players that are pulling fish out from water +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class ActiveFisherComponent : Component +{ + [DataField, AutoNetworkedField] + public TimeSpan? NextStruggle; + + [DataField, AutoNetworkedField] + public float? TotalProgress; + + [DataField, AutoNetworkedField] + public float ProgressPerUse = 0.05f; + + [DataField, AutoNetworkedField] + public EntityUid FishingRod; +} diff --git a/Content.Module.Shared/_Goobstation/Fishing/Components/ActiveFishingSpotComponent.cs b/Content.Module.Shared/_Goobstation/Fishing/Components/ActiveFishingSpotComponent.cs new file mode 100644 index 00000000000..c338ddd8a7e --- /dev/null +++ b/Content.Module.Shared/_Goobstation/Fishing/Components/ActiveFishingSpotComponent.cs @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Goobstation.Shared.Fishing.Components; + +/// +/// Dynamic component, that is assigned to active fishing spots that are currently waiting for da fish. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class ActiveFishingSpotComponent : Component +{ + [ViewVariables, AutoNetworkedField] + public EntityUid? AttachedFishingLure; + + [DataField, AutoNetworkedField] + public TimeSpan? FishingStartTime; + + /// + /// If true, someone is pulling fish out of this spot. + /// + [DataField, AutoNetworkedField] + public bool IsActive; + + [DataField, AutoNetworkedField] + public float FishDifficulty; + + /// + /// Fish that we're currently trying to catch + /// + [DataField] + public EntProtoId? Fish; // not networked because useless for client +} diff --git a/Content.Module.Shared/_Goobstation/Fishing/Components/FishComponent.cs b/Content.Module.Shared/_Goobstation/Fishing/Components/FishComponent.cs new file mode 100644 index 00000000000..6f325d1f56b --- /dev/null +++ b/Content.Module.Shared/_Goobstation/Fishing/Components/FishComponent.cs @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +namespace Content.Goobstation.Shared.Fishing.Components; + +/// +/// The fish itself! +/// +[RegisterComponent] +public sealed partial class FishComponent : Component +{ + public const float DefaultDifficulty = 0.021f; + + [DataField("difficulty")] + public float FishDifficulty = DefaultDifficulty; +} diff --git a/Content.Module.Shared/_Goobstation/Fishing/Components/FishingLureComponent.cs b/Content.Module.Shared/_Goobstation/Fishing/Components/FishingLureComponent.cs new file mode 100644 index 00000000000..8969e237955 --- /dev/null +++ b/Content.Module.Shared/_Goobstation/Fishing/Components/FishingLureComponent.cs @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: 2025 Aidenkrz +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +using Robust.Shared.GameStates; + +namespace Content.Goobstation.Shared.Fishing.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class FishingLureComponent : Component +{ + [DataField, AutoNetworkedField] + public EntityUid FishingRod; + + [DataField, AutoNetworkedField] + public EntityUid? AttachedEntity; + + [ViewVariables] + public TimeSpan NextUpdate; + + [DataField] + public float UpdateInterval = 1f; +} diff --git a/Content.Module.Shared/_Goobstation/Fishing/Components/FishingRodComponent.cs b/Content.Module.Shared/_Goobstation/Fishing/Components/FishingRodComponent.cs new file mode 100644 index 00000000000..9641be49ed6 --- /dev/null +++ b/Content.Module.Shared/_Goobstation/Fishing/Components/FishingRodComponent.cs @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Aidenkrz +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Rouden <149893554+Roudenn@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +using Robust.Shared.Prototypes; +using Robust.Shared.GameStates; +using Robust.Shared.Utility; +using System.Numerics; + +namespace Content.Goobstation.Shared.Fishing.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class FishingRodComponent : Component +{ + /// + /// Higher value will make every interact more productive. + /// + [DataField] + public float Efficiency = 1f; + + /// + /// At what progress fishing starts. + /// + [DataField] + public float StartingProgress = 0.33f; + + /// + /// How many seconds we wait until fish starts to fight with us + /// + [DataField] + public float StartingStruggleTime = 0.3f; + + /// + /// If lure moves bigger than this distance away from the rod, + /// it will force it to reel instantly. + /// + [DataField] + public float BreakOnDistance = 8f; + + [DataField] + public EntProtoId FloatPrototype = "FishingLure"; + + [DataField] + public SpriteSpecifier RopeSprite = + new SpriteSpecifier.Rsi(new ResPath("_Goobstation/Objects/Specific/Fishing/fishing_lure.rsi"), "rope"); + + [DataField, ViewVariables] + public Vector2 RopeUserOffset = new (0f, 0f); + + [DataField, ViewVariables] + public Vector2 RopeLureOffset = new (0f, 0f); + + [DataField, AutoNetworkedField] + public EntityUid? FishingLure; + + [DataField] + public EntProtoId ThrowLureActionId = "ActionStartFishing"; + + [DataField, AutoNetworkedField] + public EntityUid? ThrowLureActionEntity; + + [DataField] + public EntProtoId PullLureActionId = "ActionStopFishing"; + + [DataField, AutoNetworkedField] + public EntityUid? PullLureActionEntity; +} diff --git a/Content.Module.Shared/_Goobstation/Fishing/Components/FishingSpotComponent.cs b/Content.Module.Shared/_Goobstation/Fishing/Components/FishingSpotComponent.cs new file mode 100644 index 00000000000..2e8447a0922 --- /dev/null +++ b/Content.Module.Shared/_Goobstation/Fishing/Components/FishingSpotComponent.cs @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +using Content.Shared.EntityTable.EntitySelectors; + +namespace Content.Goobstation.Shared.Fishing.Components; + +[RegisterComponent] +public sealed partial class FishingSpotComponent : Component +{ + /// + /// All possible fishes to catch here + /// + [DataField(required: true)] + public EntityTableSelector FishList; + + /// + /// Default time for fish to occur + /// + [DataField] + public float FishDefaultTimer; + + /// + /// Variety number that FishDefaultTimer can go up or down to randomly + /// + [DataField] + public float FishTimerVariety; +} diff --git a/Content.Module.Shared/_Goobstation/Fishing/Events/FishingEvents.cs b/Content.Module.Shared/_Goobstation/Fishing/Events/FishingEvents.cs new file mode 100644 index 00000000000..bdc558f3b1b --- /dev/null +++ b/Content.Module.Shared/_Goobstation/Fishing/Events/FishingEvents.cs @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2025 Aidenkrz +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +using Content.Shared.Actions; +using Robust.Shared.Serialization; + +namespace Content.Goobstation.Shared.Fishing.Events; + +public sealed partial class ThrowFishingLureActionEvent : WorldTargetActionEvent; + +public sealed partial class PullFishingLureActionEvent : InstantActionEvent; + +[Serializable, NetSerializable] +public sealed class ActiveFishingSpotComponentState : ComponentState +{ + public readonly float FishDifficulty; + public bool IsActive; + public TimeSpan? FishingStartTime; + public NetEntity? AttachedFishingLure; + + public ActiveFishingSpotComponentState(float fishDifficulty, bool isActive, TimeSpan? fishingStartTime, NetEntity? attachedFishingLure) + { + FishDifficulty = fishDifficulty; + IsActive = isActive; + FishingStartTime = fishingStartTime; + AttachedFishingLure = attachedFishingLure; + } +} diff --git a/Content.Module.Shared/_Goobstation/Fishing/Systems/SharedFishingSystem.cs b/Content.Module.Shared/_Goobstation/Fishing/Systems/SharedFishingSystem.cs new file mode 100644 index 00000000000..203152a253f --- /dev/null +++ b/Content.Module.Shared/_Goobstation/Fishing/Systems/SharedFishingSystem.cs @@ -0,0 +1,390 @@ +// SPDX-FileCopyrightText: 2025 Aidenkrz +// SPDX-FileCopyrightText: 2025 Aviu00 +// SPDX-FileCopyrightText: 2025 GoobBot +// SPDX-FileCopyrightText: 2025 Rouden <149893554+Roudenn@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Roudenn +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +using Content.Goobstation.Shared.Fishing.Components; +using Content.Goobstation.Shared.Fishing.Events; +using Content.Shared.Actions; +using Content.Shared.Hands.EntitySystems; +using Content.Shared.Popups; +using Content.Shared.Throwing; +using Robust.Shared.Map; +using Robust.Shared.Network; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Goobstation.Shared.Fishing.Systems; + +/// +/// This handles... da fish +/// +public abstract class SharedFishingSystem : EntitySystem +{ + [Dependency] protected readonly IGameTiming Timing = default!; + [Dependency] protected readonly INetManager Net = default!; + [Dependency] protected readonly ThrowingSystem Throwing = default!; + [Dependency] protected readonly SharedTransformSystem Xform = default!; + [Dependency] private readonly SharedActionsSystem _actions = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly SharedHandsSystem _hands = default!; + + protected EntityQuery FisherQuery; + protected EntityQuery ActiveFishSpotQuery; + protected EntityQuery FishSpotQuery; + protected EntityQuery FishRodQuery; + protected EntityQuery FishLureQuery; + + public override void Initialize() + { + base.Initialize(); + + FisherQuery = GetEntityQuery(); + ActiveFishSpotQuery = GetEntityQuery(); + FishSpotQuery = GetEntityQuery(); + FishRodQuery = GetEntityQuery(); + FishLureQuery = GetEntityQuery(); + + SubscribeLocalEvent(OnFishingRodInit); + SubscribeLocalEvent(OnGetActions); + SubscribeLocalEvent(OnThrowFloat); + SubscribeLocalEvent(OnPullFloat); + SubscribeLocalEvent(OnRodParentChanged); + + SubscribeLocalEvent(OnRodTerminating); + SubscribeLocalEvent(OnLureTerminating); + SubscribeLocalEvent(OnSpotTerminating); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + UpdateFishing(); + } + + private void UpdateFishing() + { + if (!Timing.IsFirstTimePredicted) + return; + + var currentTime = Timing.CurTime; + var activeFishers = EntityQueryEnumerator(); + while (activeFishers.MoveNext(out var fisher, out var fisherComp)) + { + // Get fishing rod, then float, then spot... ReCurse. + if (TerminatingOrDeleted(fisherComp.FishingRod) || + !FishRodQuery.TryComp(fisherComp.FishingRod, out var fishingRodComp) || + TerminatingOrDeleted(fishingRodComp.FishingLure) || + !FishLureQuery.TryComp(fishingRodComp.FishingLure, out var fishingFloatComp) || + TerminatingOrDeleted(fishingFloatComp.AttachedEntity) || + !ActiveFishSpotQuery.TryComp(fishingFloatComp.AttachedEntity, out var activeSpotComp)) + continue; + + var fishRod = fisherComp.FishingRod; + var fishSpot = fishingFloatComp.AttachedEntity.Value; + + fisherComp.TotalProgress ??= fishingRodComp.StartingProgress; + fisherComp.NextStruggle ??= Timing.CurTime + TimeSpan.FromSeconds(fishingRodComp.StartingStruggleTime); + + // Fish fighting logic + CalculateFightingTimings((fisher, fisherComp), activeSpotComp); + + switch (fisherComp.TotalProgress) + { + case < 0f: + // It's over + _popup.PopupEntity(Loc.GetString("fishing-progress-fail"), fisher, fisher); + StopFishing((fishRod, fishingRodComp), fisher); + continue; + + case >= 1f: + if (activeSpotComp.Fish != null) + { + ThrowFishReward(activeSpotComp.Fish.Value, fishSpot, fisher); + _popup.PopupEntity(Loc.GetString("fishing-progress-success"), fisher, fisher); + } + + StopFishing((fishRod, fishingRodComp), fisher); + break; + } + } + + var fishingSpots = EntityQueryEnumerator(); + while (fishingSpots.MoveNext(out var activeSpotComp)) + { + if (currentTime < activeSpotComp.FishingStartTime || activeSpotComp.IsActive || activeSpotComp.FishingStartTime == null) + continue; + + // Trigger start of the fishing process + if (TerminatingOrDeleted(activeSpotComp.AttachedFishingLure)) + continue; + + // Get fishing lure, then rod, then player... ReCurse. + if (!FishLureQuery.TryComp(activeSpotComp.AttachedFishingLure, out var fishingFloatComp) || + TerminatingOrDeleted(fishingFloatComp.FishingRod) || + !FishRodQuery.TryComp(fishingFloatComp.FishingRod, out var fishRodComp)) + continue; + + var fishRod = fishingFloatComp.FishingRod; + + if (TerminatingOrDeleted(fishingFloatComp.FishingRod)) + continue; + + var fisher = Transform(fishingFloatComp.FishingRod).ParentUid; + + if (!Exists(fisher) || TerminatingOrDeleted(fisher)) + continue; + + var activeFisher = EnsureComp(fisher); + activeFisher.FishingRod = fishRod; + activeFisher.ProgressPerUse *= fishRodComp.Efficiency; + activeFisher.TotalProgress = fishRodComp.StartingProgress; + activeFisher.NextStruggle = Timing.CurTime + TimeSpan.FromSeconds(fishRodComp.StartingStruggleTime); // Compensate ping for 0.3 seconds + + // Predicted because it works like 99.9% of the time anyway. + _popup.PopupPredicted(Loc.GetString("fishing-progress-start"), fisher, fisher); + activeSpotComp.IsActive = true; + } + + var fishingLures = EntityQueryEnumerator(); + while (fishingLures.MoveNext(out var fishingLure, out var lureComp, out var xform)) + { + if (lureComp.NextUpdate > Timing.CurTime) + continue; + + lureComp.NextUpdate = Timing.CurTime + TimeSpan.FromSeconds(lureComp.UpdateInterval); + + if (TerminatingOrDeleted(lureComp.FishingRod) || + !FishRodQuery.TryComp(lureComp.FishingRod, out var fishingRodComp)) + continue; + + var lurePos = Xform.GetMapCoordinates(fishingLure, xform); + var rodPos = Xform.GetMapCoordinates(lureComp.FishingRod); + var distance = lurePos.Position - rodPos.Position; + var fisher = Transform(lureComp.FishingRod).ParentUid; + + if (!Exists(fisher) || TerminatingOrDeleted(fisher) || + distance.Length() > fishingRodComp.BreakOnDistance || + lurePos.MapId != rodPos.MapId || + !_hands.IsHolding(fisher, lureComp.FishingRod) || + !HasComp(fisher)) + { + var rod = (lureComp.FishingRod, fishingRodComp); + StopFishing(rod, fisher); + ToggleFishingActions(rod, fisher, false); + } + } + } + + /// + /// if AddPulling is true, we ADD Pulling action and REMOVE Throwing action. + /// Basically true if we start, and false if we end. + /// + private void ToggleFishingActions(Entity ent, EntityUid fisher, bool addPulling) + { + if (TerminatingOrDeleted(ent) || !Exists(fisher) || TerminatingOrDeleted(fisher)) + return; + + if (addPulling) + { + _actions.RemoveAction(ent.Comp.ThrowLureActionEntity); + _actions.AddAction(fisher, ref ent.Comp.PullLureActionEntity, ent.Comp.PullLureActionId, ent); + } + else + { + _actions.RemoveAction(ent.Comp.PullLureActionEntity); + _actions.AddAction(fisher, ref ent.Comp.ThrowLureActionEntity, ent.Comp.ThrowLureActionId, ent); + } + } + + protected abstract void CalculateFightingTimings(Entity fisher, ActiveFishingSpotComponent activeSpotComp); + + /// + /// Server-side only, sets up fishing float and throws it + /// + protected abstract void SetupFishingFloat(Entity fishingRod, EntityUid player, EntityCoordinates target); + + /// + /// Server-side only, spawns a fish and throws it to our player! + /// + protected abstract void ThrowFishReward(EntProtoId fishId, EntityUid fishSpot, EntityUid target); + + /// + /// Reels the fishing rod back and stops fishing progress if arguments are passed to it. + /// + private void StopFishing( + Entity fishingRod, + EntityUid? fisher) + { + var nullOrDeleted = + fishingRod.Comp.FishingLure == null || TerminatingOrDeleted(fishingRod.Comp.FishingLure.Value); + + if (!nullOrDeleted && FishLureQuery.TryComp(fishingRod.Comp.FishingLure, out var lureComp) && + !TerminatingOrDeleted(lureComp.AttachedEntity) && + ActiveFishSpotQuery.TryComp(lureComp.AttachedEntity, out var activeSpotComp)) + RemCompDeferred(lureComp.AttachedEntity.Value, activeSpotComp); + + if (!nullOrDeleted && Net.IsServer) + QueueDel(fishingRod.Comp.FishingLure); + + if (Exists(fisher) && !TerminatingOrDeleted(fisher) && FisherQuery.TryComp(fisher, out var fisherComp)) + { + RemCompDeferred(fisher.Value, fisherComp); + + ToggleFishingActions(fishingRod, fisher.Value, false); + } + + fishingRod.Comp.FishingLure = null; + } + + #region Terminating Events + + private void OnRodTerminating(Entity ent, ref EntityTerminatingEvent args) + { + TryStopFishing(ent); + } + + private void OnLureTerminating(Entity ent, ref EntityTerminatingEvent args) + { + TryStopFishing(ent); + } + + private void OnSpotTerminating(Entity ent, ref EntityTerminatingEvent args) + { + TryStopFishing(ent); + } + + #endregion + + #region Deletion Helpers + + /// + /// Stops fishing by taking only the Fishing rod as an argument. + /// + private void TryStopFishing(Entity rod) + { + var player = Transform(rod).ParentUid; + StopFishing(rod, player); + } + + /// + /// Stops fishing by taking only the Fishing lure as an argument. + /// + private void TryStopFishing(Entity lure) + { + if (!FishRodQuery.TryComp(lure.Comp.FishingRod, out var rodComp)) + return; + + TryStopFishing((lure.Comp.FishingRod, rodComp)); + } + + /// + /// Stops fishing by taking only the Active spot as an argument. + /// + private void TryStopFishing(Entity spot) + { + if (!FishLureQuery.TryComp(spot.Comp.AttachedFishingLure, out var lureComp)) + return; + + if (!FishRodQuery.TryComp(lureComp.FishingRod, out var rodComp)) + return; + + TryStopFishing((lureComp.FishingRod, rodComp)); + } + + #endregion + + #region Event Handling + + private void OnThrowFloat(Entity ent, ref ThrowFishingLureActionEvent args) + { + if (args.Handled || !Timing.IsFirstTimePredicted) + return; + + var player = args.Performer; + + if (ent.Comp.FishingLure != null || !Xform.IsValid(args.Target)) + { + args.Handled = true; + return; + } + + SetupFishingFloat(ent, player, args.Target); + ToggleFishingActions(ent, player, true); + args.Handled = true; + } + + private void OnPullFloat(Entity ent, ref PullFishingLureActionEvent args) + { + if (args.Handled || !Timing.IsFirstTimePredicted) + return; + + var player = args.Performer; + var (uid, component) = ent; + + if (component.FishingLure == null) + { + ToggleFishingActions(ent, player, true); + args.Handled = true; + return; + } + + _popup.PopupPredicted(Loc.GetString("fishing-rod-remove-lure", ("ent", Name(uid))), uid, uid); + + if (!FishLureQuery.TryComp(component.FishingLure, out var lureComp)) + return; + + if (lureComp.AttachedEntity != null && Exists(lureComp.AttachedEntity)) + { + // TODO: so this kinda just lets you pull anything right up to you, it should instead just apply an impulse in your direction modfiied by the weight of the player vs the object + // Also we need to autoreel/snap the line if the player gets too far away + // Also we should probably PVS override the lure if the rod is in PVS, and vice versa to stop the joint visuals from popping in/out + var attachedEnt = lureComp.AttachedEntity.Value; + var targetCoords = Xform.GetMapCoordinates(Transform(attachedEnt)); + var playerCoords = Xform.GetMapCoordinates(Transform(player)); + var rand = new Random((int) Timing.CurTick.Value); // evil random prediction hack + + // Calculate throw direction + var direction = (playerCoords.Position - targetCoords.Position) * rand.NextFloat(0.2f, 0.85f); + + // Yeet + Throwing.TryThrow(attachedEnt, direction, 4f, player); + } + + StopFishing(ent, player); + ToggleFishingActions(ent, player, false); + args.Handled = true; + } + + private void OnFishingRodInit(Entity ent, ref MapInitEvent args) + { + _actions.AddAction(ent, ref ent.Comp.ThrowLureActionEntity, ent.Comp.ThrowLureActionId); + } + + private void OnRodParentChanged(Entity ent, ref EntParentChangedMessage args) + { + if (TerminatingOrDeleted(ent) || !Exists(args.Transform.ParentUid)) + return; + + // Anything that is an active fisher should be fine. + if (!FisherQuery.HasComp(args.Transform.ParentUid)) + { + StopFishing(ent, args.OldParent); + } + } + + private void OnGetActions(Entity ent, ref GetItemActionsEvent args) + { + if (ent.Comp.FishingLure == null) + args.AddAction(ref ent.Comp.ThrowLureActionEntity, ent.Comp.ThrowLureActionId); + else + args.AddAction(ref ent.Comp.PullLureActionEntity, ent.Comp.PullLureActionId); + } + + #endregion +} diff --git a/Content.Shared/Weapons/Misc/SharedTetherGunSystem.cs b/Content.Shared/Weapons/Misc/SharedTetherGunSystem.cs index 0f6baf06f25..7db63a4412b 100644 --- a/Content.Shared/Weapons/Misc/SharedTetherGunSystem.cs +++ b/Content.Shared/Weapons/Misc/SharedTetherGunSystem.cs @@ -1,4 +1,19 @@ +// SPDX-FileCopyrightText: 2023 DrSmugleaf +// SPDX-FileCopyrightText: 2023 Pieter-Jan Briers +// SPDX-FileCopyrightText: 2024 Kara +// SPDX-FileCopyrightText: 2024 Nemanja <98561806+EmoGarbage404@users.noreply.github.com> +// SPDX-FileCopyrightText: 2024 Piras314 +// SPDX-FileCopyrightText: 2024 Tayrtahn +// SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Misandry +// SPDX-FileCopyrightText: 2025 TemporalOroboros +// SPDX-FileCopyrightText: 2025 gus +// SPDX-FileCopyrightText: 2025 metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> +// +// SPDX-License-Identifier: AGPL-3.0-or-later + using System.Diagnostics.CodeAnalysis; +using Content.Common.Data._Shitcode.Weapons.Misc; using Content.Shared.ActionBlocker; using Content.Shared.Buckle.Components; using Content.Shared.Hands.Components; @@ -178,7 +193,8 @@ protected virtual bool CanTether(EntityUid uid, BaseForceGunComponent component, return false; if (physics.BodyType == BodyType.Static && !component.CanUnanchor || - _container.IsEntityInContainer(target)) + _container.IsEntityInContainer(target) + || HasComp(target) && !component.CanUnanchor) // Goob-GunBlacklist return false; if (physics.Mass > component.MassLimit) diff --git a/LEGAL.md b/LEGAL.md index edbb549ed1a..e25dbbf6a73 100644 --- a/LEGAL.md +++ b/LEGAL.md @@ -52,9 +52,9 @@ | Библиотеки /
Пространства имён | Проект | Исходный репозиторий | Исходная лицензия | |-------------------------------------|-------|-----------------------|----------| -| `Content.SIS.*` / `_SIS` | Skill Issue Station | https://github.com/Shegare/SIS-14 | AGPL-3.0-or-later | -| `_Goobstation` | Goob Station 14 | https://github.com/Goob-Station/Goob-Station | AGPL-3.0-or-later | -| `_EinsteinEngines` | Einstein Engines | https://github.com/Simple-Station/Einstein-Engines | AGPL-3.0-or-later | +| `Content.SIS.*`
`_SIS` | Skill Issue Station | https://github.com/Shegare/SIS-14 | AGPL-3.0-or-later | +| `_Goobstation`
`_Shitcode` | Goob Station 14 | https://github.com/Goob-Station/Goob-Station | AGPL-3.0-or-later | +| `_EinsteinEngines` | Einstein Engines | https://github.com/Simple-Station/Einstein-Engines | AGPL-3.0-or-later | | `Axolotl` | Space Axolotl | https://github.com/space-axolotl-14/space-axolotl-14 | MIT | Дополнительные репозитории с портированным кодом (без пространств имён): diff --git a/Resources/Audio/_Goobstation/Items/Fishing/attributions.yml b/Resources/Audio/_Goobstation/Items/Fishing/attributions.yml new file mode 100644 index 00000000000..5abc9cf749c --- /dev/null +++ b/Resources/Audio/_Goobstation/Items/Fishing/attributions.yml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2025 Aidenkrz +# SPDX-FileCopyrightText: 2025 GoobBot +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +- files: ["fishing_rod_cast.ogg"] + license: "CC-BY-NC-SA-4.0" + copyright: "Taken from Goon at commit 0c11a46275f493f295d6d05d1aa5fad1d935efb4" + source: "https://github.com/goonstation/goonstation/blob/master/sound/items/fishing_rod_cast.ogg" + +- files: ["fishing_rod_reel.ogg"] + license: "CC-BY-NC-SA-4.0" + copyright: "Taken from Goon at commit 0c11a46275f493f295d6d05d1aa5fad1d935efb4" + source: "https://github.com/goonstation/goonstation/blob/master/sound/items/fishing_rod_cast.ogg" diff --git a/Resources/Audio/_Goobstation/Items/Fishing/fishing_rod_cast.ogg b/Resources/Audio/_Goobstation/Items/Fishing/fishing_rod_cast.ogg new file mode 100644 index 00000000000..9ae49abb50f Binary files /dev/null and b/Resources/Audio/_Goobstation/Items/Fishing/fishing_rod_cast.ogg differ diff --git a/Resources/Audio/_Goobstation/Items/Fishing/fishing_rod_reel.ogg b/Resources/Audio/_Goobstation/Items/Fishing/fishing_rod_reel.ogg new file mode 100644 index 00000000000..95c543b8f7a Binary files /dev/null and b/Resources/Audio/_Goobstation/Items/Fishing/fishing_rod_reel.ogg differ diff --git a/Resources/Locale/ru-RU/_Goobstation/fishing/fishing.ftl b/Resources/Locale/ru-RU/_Goobstation/fishing/fishing.ftl new file mode 100644 index 00000000000..e13cdd92a11 --- /dev/null +++ b/Resources/Locale/ru-RU/_Goobstation/fishing/fishing.ftl @@ -0,0 +1,10 @@ +fishing-rod-remove-lure = { $ent } сматывает леску +fishing-progress-success = Вы вытащили что-то из воды! +fishing-progress-fail = Вы упустили добычу... +fishing-progress-lost-rod = Вы потеряли контроль над { $ent }! +fishing-progress-start = Вы чувствуете, как что-то цепляется за приманку! + +action-fishing-stop = Смотать удочку +action-fishing-stop-desc = Смотайте удочку, чтобы вытащить объект, который к ней прицепился, или прекратить рыбалку. +action-fishing-start = Забросить приманку +action-fishing-start-desc = Забросьте приманку с удочки, чтобы поймать что-нибудь! diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/actions/fishing.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/actions/fishing.ftl new file mode 100644 index 00000000000..53e755f9957 --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/actions/fishing.ftl @@ -0,0 +1,4 @@ +ent-ActionStartFishing = Забросить приманку + .desc = Забросьте приманку с удочки, чтобы что-нибудь поймать! +ent-ActionStopFishing = Смотать удочку + .desc = Смотайте удочку, чтобы вытащить объект, к которому она прикреплена, или прекратить рыбалку. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/catalog/fills/crates/service.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/catalog/fills/crates/service.ftl new file mode 100644 index 00000000000..3d1517d6a08 --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/catalog/fills/crates/service.ftl @@ -0,0 +1,2 @@ +ent-CrateFishingGoodies = ящик рыболовных принадлежностей + .desc = Пара удочек, плюшевый мишка и шляпа. Всё, что нужно, чтобы поймать всю рыбу на станции! diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/entities/objects/specific/fishing/fish.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/entities/objects/specific/fishing/fish.ftl new file mode 100644 index 00000000000..b33ccb4b803 --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/entities/objects/specific/fishing/fish.ftl @@ -0,0 +1,42 @@ +ent-BaseFish = рыба + .desc = Водное существо из бескрайнего моря... Или унитаза. +ent-BaseFishRare = редкая рыба + .desc = Водное существо из бескрайнего моря... Или унитаза. +ent-FishAlien = инопланетная рыба + .desc = Выглядит довольно... Похитительно. +ent-FishAngler = рыба-удильщик + .desc = Самая страшная вещь в мире, после бинглов. +ent-FishBass = окунь + .desc = Вероятно, самая обычная рыба из существующих. Если только вы не используете её как бас-гитару. +ent-FishBingle = рыба бингл + .desc = бингл +ent-FishBlob = рыба-капля + .desc = К сожалению, это не биологическая угроза 5-го уровня. +ent-FishBlueFintuna = синепёрый тунец + .desc = Он смотрит прямо на вас... +ent-FishBoyFisher = бойфишер + .desc = Вы ведь любите целовать рыб, не так ли? +ent-FishCat = сом + .desc = Как ни странно, он совсем не похож на кота. И не мяукает. +ent-FishTropicalClown = клоун рыба-клоун + .desc = Это определённо какая-то шутка. +ent-FishNukeDisk = рыба ядерный диск + .desc = Эм, вообще-то, засовывать рыбу в ядерное взрывное устройство — плохая идея. +ent-FishGib = рыба гибстик + .desc = Моё лицо, когда я открываю подарок и получаю гибстик: +ent-FishMutant = рыба-мутант + .desc = Аномальная рыба, которая выглядит так, будто съела ядерные отходы. +ent-FishNuker = рыба ядерный оперативник + .desc = Хищник рыбы ядерного диска. +ent-FishPuffer = рыба-ёж + .desc = Она ядовита... во многих смыслах. +ent-FishSilver = серебряная рыба + .desc = На самом деле содержит серебро. +ent-FishTropicalSun = тропическая солнечная рыба + .desc = Она, наверное, слишком долго смотрела на солнце...? +ent-FishToxic = рыба токсичных отходов + .desc = Глядя на эту рыбу, вы понимаете, насколько плохой идеей было разрешить сброс ядерных отходов в реки. +ent-FishTropical = рыба-клоун + .desc = Эта рыба постоянно что-то ищет... А может, кого-то? +ent-FishIan = рыба Иан + .desc = Водный Иан из морских глубин. diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/entities/objects/specific/fishing/fishingspots.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/entities/objects/specific/fishing/fishingspots.ftl new file mode 100644 index 00000000000..2d514486c6b --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/entities/objects/specific/fishing/fishingspots.ftl @@ -0,0 +1,4 @@ +ent-BaseFishingSpot = подозрительные волны + .desc = Здесь что-то плавает... +ent-FishingSpotWater = { ent-BaseFishingSpot } + .desc = { ent-BaseFishingSpot.desc } diff --git a/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/entities/objects/tools/fishing_rods.ftl b/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/entities/objects/tools/fishing_rods.ftl new file mode 100644 index 00000000000..719a94c3250 --- /dev/null +++ b/Resources/Locale/ru-RU/ss14-ru/prototypes/_goobstation/entities/objects/tools/fishing_rods.ftl @@ -0,0 +1,13 @@ +ent-FishingRod = удочка + .desc = Время отправиться на рыбалку! +ent-FishingRodGoon = удочка + .desc = Время отправиться на рыбалку! + .suffix = Неуклюжая +ent-FishingRodMakeshift = самодельная удочка + .desc = Наверное, будет сложно поймать рыбу с её помощью. +ent-FishingRodGolden = золотая удочка + .desc = Наконец-то вы поймали 250 рыб. Вот ваш трофей. +ent-FishingLure = рыболовная приманка + .desc = рыба, иди сюда +ent-FishingLureMakeshift = рыболовная приманка + .desc = рыба, иди сюда diff --git a/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml b/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml index 79fc6f4ad9c..622a38bc9e6 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/toilet.yml @@ -1,3 +1,98 @@ +# SPDX-FileCopyrightText: 2021 Alex Evgrashin +# SPDX-FileCopyrightText: 2021 Metal Gear Sloth +# SPDX-FileCopyrightText: 2021 Paul Ritter +# SPDX-FileCopyrightText: 2021 Swept +# SPDX-FileCopyrightText: 2021 Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com> +# SPDX-FileCopyrightText: 2021 Vera Aguilera Puerto +# SPDX-FileCopyrightText: 2021 Ygg01 +# SPDX-FileCopyrightText: 2022 Morb <14136326+Morb0@users.noreply.github.com> +# SPDX-FileCopyrightText: 2022 Peptide90 <78795277+Peptide90@users.noreply.github.com> +# SPDX-FileCopyrightText: 2022 wrexbe <81056464+wrexbe@users.noreply.github.com> +# SPDX-FileCopyrightText: 2023 AJCM-git <60196617+AJCM-git@users.noreply.github.com> +# SPDX-FileCopyrightText: 2023 Nairod <110078045+Nairodian@users.noreply.github.com> +# SPDX-FileCopyrightText: 2023 TNE <38938720+JustTNE@users.noreply.github.com> +# SPDX-FileCopyrightText: 2023 Topy +# SPDX-FileCopyrightText: 2024 Aiden +# SPDX-FileCopyrightText: 2024 Alzore <140123969+Blackern5000@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Brandon Hu <103440971+Brandon-Huu@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 CaasGit <87243814+CaasGit@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Chief-Engineer <119664036+Chief-Engineer@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Cojoke <83733158+Cojoke-dot@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 DrSmugleaf <10968691+DrSmugleaf@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 DrSmugleaf +# SPDX-FileCopyrightText: 2024 Ed <96445749+TheShuEd@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Emisse <99158783+Emisse@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 EmoGarbage404 +# SPDX-FileCopyrightText: 2024 Eoin Mcloughlin +# SPDX-FileCopyrightText: 2024 Errant <35878406+Errant-4@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Flareguy <78941145+Flareguy@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Hrosts <35345601+Hrosts@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Ian +# SPDX-FileCopyrightText: 2024 Ilya246 <57039557+Ilya246@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Joel Zimmerman +# SPDX-FileCopyrightText: 2024 JustCone <141039037+JustCone14@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Killerqu00 <47712032+Killerqu00@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Ko4ergaPunk <62609550+Ko4ergaPunk@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Kukutis96513 <146854220+Kukutis96513@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Lye <128915833+Lyroth001@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 MerrytheManokit <167581110+MerrytheManokit@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Mervill +# SPDX-FileCopyrightText: 2024 MilenVolf <63782763+MilenVolf@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 MureixloI <132683811+MureixloI@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 NakataRin <45946146+NakataRin@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Nemanja <98561806+EmoGarbage404@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Nim <128169402+Nimfar11@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 OrangeMoronage9622 +# SPDX-FileCopyrightText: 2024 PJBot +# SPDX-FileCopyrightText: 2024 Pieter-Jan Briers +# SPDX-FileCopyrightText: 2024 Plykiya <58439124+Plykiya@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Preston Smith <92108534+thetolbean@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Psychpsyo <60073468+Psychpsyo@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Repo <47093363+Titian3@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 RiceMar1244 <138547931+RiceMar1244@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Simon <63975668+Simyon264@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Stalen <33173619+stalengd@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 TakoDragon <69509841+BackeTako@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Thomas <87614336+Aeshus@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 TsjipTsjip <19798667+TsjipTsjip@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 TurboTracker <130304754+TurboTrackerss14@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Ubaser <134914314+UbaserB@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Unkn0wn_Gh0st +# SPDX-FileCopyrightText: 2024 Vasilis +# SPDX-FileCopyrightText: 2024 Vigers Ray <60344369+VigersRay@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 beck-thompson <107373427+beck-thompson@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 brainfood1183 <113240905+brainfood1183@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 deathride58 +# SPDX-FileCopyrightText: 2024 deltanedas <39013340+deltanedas@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 deltanedas <@deltanedas:kde.org> +# SPDX-FileCopyrightText: 2024 dffdff2423 +# SPDX-FileCopyrightText: 2024 eoineoineoin +# SPDX-FileCopyrightText: 2024 foboscheshir <156405958+foboscheshir@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 lzk <124214523+lzk228@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 metalgearsloth +# SPDX-FileCopyrightText: 2024 nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 plykiya +# SPDX-FileCopyrightText: 2024 saintmuntzer <47153094+saintmuntzer@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 shamp <140359015+shampunj@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 strO0pwafel <153459934+strO0pwafel@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 stroopwafel +# SPDX-FileCopyrightText: 2024 themias <89101928+themias@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 to4no_fix <156101927+chavonadelal@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 voidnull000 <18663194+voidnull000@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# SPDX-FileCopyrightText: 2025 SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 slarticodefast <161409025+slarticodefast@users.noreply.github.com> +# +# SPDX-License-Identifier: AGPL-3.0-or-later + - type: entity abstract: true parent: [ DisposalUnitBase, SeatBase ] @@ -61,6 +156,18 @@ - MachineMask layer: - None + # Goob-Start + fishing: + shape: + !type:PhysShapeCircle + radius: 0.4 + layer: + - ItemMask + mask: + - HighImpassable + density: 1000 + hard: false + # Goob-End - type: PlungerUse - type: Appearance - type: SecretStash @@ -89,12 +196,19 @@ maxVol: 100 tank: maxVol: 500 - - type: SolutionRegeneration - solution: tank - generated: - reagents: - - ReagentId: Water - Quantity: 1 + # Goob-Start + #- type: SolutionRegeneration # Goobstation - laggy, also who uses toilets? + # solution: tank + # generated: + # reagents: + # - ReagentId: Water + # Quantity: 1 + - type: FishingSpot + fishList: !type:NestedSelector + tableId: ToiletFishingLootTable + fishDefaultTimer: 45.0 + fishTimerVariety: 15.0 + # Goob-End - type: DrainableSolution solution: tank - type: ReagentTank diff --git a/Resources/Prototypes/Entities/Tiles/lava.yml b/Resources/Prototypes/Entities/Tiles/lava.yml index 84907318de0..951f2c8c4ba 100644 --- a/Resources/Prototypes/Entities/Tiles/lava.yml +++ b/Resources/Prototypes/Entities/Tiles/lava.yml @@ -1,3 +1,35 @@ +# SPDX-FileCopyrightText: 2023 Kara +# SPDX-FileCopyrightText: 2023 lzk <124214523+lzk228@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Adeinitas <147965189+adeinitas@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Flareguy <78941145+Flareguy@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Timemaster99 <57200767+Timemaster99@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 VMSolidus +# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 Aidenkrz +# SPDX-FileCopyrightText: 2025 Aineias1 +# SPDX-FileCopyrightText: 2025 DoutorWhite +# SPDX-FileCopyrightText: 2025 FaDeOkno <143940725+FaDeOkno@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 McBosserson <148172569+McBosserson@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 Milon +# SPDX-FileCopyrightText: 2025 Piras314 +# SPDX-FileCopyrightText: 2025 Rouden <149893554+Roudenn@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 Roudenn +# SPDX-FileCopyrightText: 2025 TheBorzoiMustConsume <197824988+TheBorzoiMustConsume@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 Unlumination <144041835+Unlumy@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 deltanedas <39013340+deltanedas@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 deltanedas <@deltanedas:kde.org> +# SPDX-FileCopyrightText: 2025 gluesniffler <159397573+gluesniffler@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 gluesniffler +# SPDX-FileCopyrightText: 2025 metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 username <113782077+whateverusername0@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 whateverusername0 +# +# SPDX-License-Identifier: AGPL-3.0-or-later + - type: entity id: FloorLavaEntity name: lava @@ -21,6 +53,13 @@ multiplier: 3.75 multiplierOnExisting: 0.75 - !type:Ignite + # Goob-Start + - type: FishingSpot + fishList: !type:NestedSelector + tableId: LavaFishingLootTable + fishDefaultTimer: 25.0 + fishTimerVariety: 15.0 + # Goob-End - type: Transform anchored: true - type: SyncSprite @@ -53,6 +92,18 @@ - ItemMask density: 1000 hard: false + # Goob-Start + fishing: + shape: + !type:PhysShapeCircle + radius: 0.4 + layer: + - ItemMask + mask: + - HighImpassable + density: 1000 + hard: false + # Goob-End - type: Tag tags: - HideContextMenu diff --git a/Resources/Prototypes/Entities/Tiles/liquid_plasma.yml b/Resources/Prototypes/Entities/Tiles/liquid_plasma.yml index 8d1881375bb..f5454bdd231 100644 --- a/Resources/Prototypes/Entities/Tiles/liquid_plasma.yml +++ b/Resources/Prototypes/Entities/Tiles/liquid_plasma.yml @@ -1,3 +1,20 @@ +# SPDX-FileCopyrightText: 2023 Kara +# SPDX-FileCopyrightText: 2023 lzk <124214523+lzk228@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Adeinitas <147965189+adeinitas@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Flareguy <78941145+Flareguy@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Timemaster99 <57200767+Timemaster99@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 VMSolidus +# SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 DoutorWhite +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# SPDX-FileCopyrightText: 2025 metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> +# +# SPDX-License-Identifier: AGPL-3.0-or-later + - type: entity id: FloorLiquidPlasmaEntity name: liquid plasma @@ -21,6 +38,13 @@ multiplier: 3.75 multiplierOnExisting: 0.75 - !type:Ignite + # Goob-Start + - type: FishingSpot + fishList: !type:NestedSelector + tableId: PlasmaFishingLootTable + fishDefaultTimer: 25.0 + fishTimerVariety: 15.0 + # Goob-End - type: Transform anchored: true - type: SyncSprite @@ -51,6 +75,18 @@ - ItemMask density: 1000 hard: false + # Goob-Start + fishing: + shape: + !type:PhysShapeCircle + radius: 0.4 + layer: + - ItemMask + mask: + - HighImpassable + density: 1000 + hard: false + # Goob-End - type: Tag tags: - HideContextMenu diff --git a/Resources/Prototypes/Entities/Tiles/water.yml b/Resources/Prototypes/Entities/Tiles/water.yml index a4478b5e583..efb7d861f81 100644 --- a/Resources/Prototypes/Entities/Tiles/water.yml +++ b/Resources/Prototypes/Entities/Tiles/water.yml @@ -1,3 +1,17 @@ +# SPDX-FileCopyrightText: 2023 AJCM-git <60196617+AJCM-git@users.noreply.github.com> +# SPDX-FileCopyrightText: 2023 Kara +# SPDX-FileCopyrightText: 2023 lzk <124214523+lzk228@users.noreply.github.com> +# SPDX-FileCopyrightText: 2023 metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Aiden +# SPDX-FileCopyrightText: 2024 Ed <96445749+TheShuEd@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 Froffy025 <78222136+Froffy025@users.noreply.github.com> +# SPDX-FileCopyrightText: 2024 justdie12 <125140938+justdie12@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# +# SPDX-License-Identifier: AGPL-3.0-or-later + - type: entity id: FloorWaterEntity name: water @@ -24,12 +38,14 @@ reagents: - ReagentId: Water Quantity: 9999999 - - type: SolutionRegeneration - solution: tank - generated: - reagents: - - ReagentId: Water - Quantity: 100 + # Goob-Start + #- type: SolutionRegeneration # Goob: laggy as shit + # solution: tank + # generated: + # reagents: + # - ReagentId: Water + # Quantity: 100 + # Goob-End - type: DrainableSolution solution: pool - type: SpeedModifierContacts @@ -49,6 +65,18 @@ - ItemMask density: 1000 hard: false + # Goob-Start + fishing: + shape: + !type:PhysShapeCircle + radius: 0.4 + layer: + - ItemMask + mask: + - HighImpassable + density: 1000 + hard: false + # Goob-End - type: FootstepModifier footstepSoundCollection: collection: FootstepWater @@ -63,3 +91,10 @@ - type: TileEntityEffect effects: - !type:Extinguish + # Goob-Start + - type: FishingSpot + fishList: !type:NestedSelector + tableId: WaterFishingLootTable + fishDefaultTimer: 25.0 + fishTimerVariety: 15.0 + # Goob-End diff --git a/Resources/Prototypes/_Goobstation/Actions/fishing.yml b/Resources/Prototypes/_Goobstation/Actions/fishing.yml new file mode 100644 index 00000000000..0bd25c92041 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Actions/fishing.yml @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2025 Aidenkrz +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +- type: entity + parent: BaseAction + id: ActionStartFishing + name: Throw fishing lure + description: Throw lure from the fishing rod to catch something! + components: + - type: Action + icon: + sprite: _Goobstation/Objects/Specific/Fishing/fishing_lure.rsi + state: icon + sound: + path: /Audio/_Goobstation/Items/Fishing/fishing_rod_cast.ogg + itemIconStyle: BigAction + useDelay: 2.5 + - type: TargetAction + range: 15 + checkCanAccess: false + - type: WorldTargetAction + event: !type:ThrowFishingLureActionEvent + +- type: entity + parent: BaseAction + id: ActionStopFishing + name: Reel fishing rod + description: Reel your fishing rod to pull an object that it attached to, or stop fishing. + components: + - type: Action + icon: + sprite: _Goobstation/Objects/Specific/Fishing/goon_rod.rsi + state: icon + sound: + path: /Audio/_Goobstation/Items/Fishing/fishing_rod_reel.ogg + itemIconStyle: NoItem + - type: InstantAction + event: !type:PullFishingLureActionEvent diff --git a/Resources/Prototypes/_Goobstation/Catalog/Cargo/cargo_service.yml b/Resources/Prototypes/_Goobstation/Catalog/Cargo/cargo_service.yml new file mode 100644 index 00000000000..55e21b98617 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Catalog/Cargo/cargo_service.yml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +- type: cargoProduct + id: FishingGoodies + icon: + sprite: _Goobstation/Objects/Specific/Fishing/fishing_rod.rsi + state: icon + product: CrateFishingGoodies + cost: 1000 + category: cargoproduct-category-name-service + group: market diff --git a/Resources/Prototypes/_Goobstation/Catalog/Fills/Crates/service.yml b/Resources/Prototypes/_Goobstation/Catalog/Fills/Crates/service.yml new file mode 100644 index 00000000000..f7815231d71 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Catalog/Fills/Crates/service.yml @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +- type: entity + id: CrateFishingGoodies + parent: CratePlastic + name: fishing goodies crate + description: A couple of fishing rods, a bear, and a hat. Everything you need to catch all fish on the station! + components: + - type: StorageFill + contents: + - id: FishingRod + - id: FishingRodGoon + - id: ClothingHeadFishCap + - id: DrinkBeerBottleFull diff --git a/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Fishing/fish.yml b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Fishing/fish.yml new file mode 100644 index 00000000000..9598411a702 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Fishing/fish.yml @@ -0,0 +1,301 @@ +# SPDX-FileCopyrightText: 2025 Evige +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Rouden <149893554+Roudenn@users.noreply.github.com> +# SPDX-FileCopyrightText: 2025 Roudenn +# SPDX-FileCopyrightText: 2026 Skill Issue Station contributors +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +- type: entity + id: BaseFish + parent: [SimpleMobBase, BaseItem] + abstract: true + name: fish + description: Water-born creature from the infinite sea... Or toilet. + components: + - type: Fish + difficulty: 0.029 + - type: StaticPrice + price: 250 + - type: MobThresholds + thresholds: + 0: Alive + 1: Critical + 5: Dead + - type: MovementSpeedModifier + baseWalkSpeed: 0.1 + baseSprintSpeed: 0.1 + - type: PassiveDamage + allowedStates: + - Alive + damageCap: 20 + damage: + types: + Asphyxiation: 1 + - type: Respirator + damage: + types: + Asphyxiation: 1.0 + damageRecovery: + types: + Asphyxiation: 0 + - type: Butcherable + spawned: + - id: FoodMeatFish + amount: 2 + - type: Bloodstream + bloodReferenceSolution: + reagents: + - ReagentId: Blood + Quantity: 20 + - type: ZombieImmune + +- type: entity + id: BaseFishRare + parent: BaseFish + abstract: true + name: rare fish + description: Water-born creature from the infinite sea... Or toilet. + components: + - type: Fish + difficulty: 0.038 + - type: StaticPrice + price: 750 + +- type: entity + id: FishAlien + parent: BaseFishRare + name: alien fish + description: Looks pretty... Abductory. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: alien + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishAngler + parent: BaseFish + name: angler fish + description: Scariest thing in existence, after bingles. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: angler + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishBass + parent: BaseFish + name: bass fish + description: Probably the most normal fish in existence. Unless you use it as bass guitar. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: bass + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishBingle + parent: BaseFishRare + name: bingle fish + description: bingle + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: bingle + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishBlob + parent: BaseFish + name: blob fish + description: Unfortuantly, this is not a 5th level bio-hazard threat. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: blob + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishBlueFintuna + parent: BaseFish + name: blue fintuna + description: It's looking straight to you... + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: blue_fintuna + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishBoyFisher + parent: BaseFishRare + name: boy fisher + description: You like kissing fish, don't you? + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: boy_fisher + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishCat + parent: BaseFish + name: cat fish + description: Ironically this looks nothing like a cat. And it doesn't meow. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: catfish + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishTropicalClown + parent: BaseFish + name: clown clown fish + description: That is almost certanly some kind of joke. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: clown + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + - type: Bloodstream + bloodReferenceSolution: + reagents: + - ReagentId: Laughter + Quantity: 20 + +- type: entity + id: FishNukeDisk + parent: BaseFishRare + name: nuke disk fish + description: Erm, Actually, it's a bad idea trying to fit a fish inside a nuclear explosion device. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: disk + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishGib + parent: BaseFishRare + name: gib stick fish + description: "My face when i open a present and get gibstick:" + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: gib + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishMutant + parent: BaseFishRare + name: mutant fish + description: Anomalous fish that looks like it ate some nuclear waste. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: mutant + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishNuker + parent: BaseFishRare + name: nuclear operative fish + description: Predator of the nuke disk fish. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: nuker + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishPuffer + parent: BaseFish + name: puffer fish + description: It is poisonous... in many ways. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: pufferfish + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishSilver + parent: BaseFish + name: silver fish + description: Actually contains silver. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: silverfish + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishTropicalSun + parent: BaseFish + name: tropical sun fish + description: It probably looked at the sun for too long...? + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: sun_tropical + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishToxic + parent: BaseFishRare + name: toxic waste fish + description: "Looking at this fish, you understand how much it was a bad idea to allow nuclear waste to be dumped into rivers." + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: toxic + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + +- type: entity + id: FishTropical + parent: BaseFish + name: clown fish + description: This fish is always searching for something... Or maybe someone? + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: tropical + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + - type: Bloodstream + bloodReferenceSolution: + reagents: + - ReagentId: Laughter + Quantity: 10 + +- type: entity + id: FishIan + parent: BaseFishRare + name: ian fish + description: Water-born ian from the sea. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi + state: ian + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fish.rsi diff --git a/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Fishing/fishingspots.yml b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Fishing/fishingspots.yml new file mode 100644 index 00000000000..d2d5c94dedb --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Fishing/fishingspots.yml @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2025 Aidenkrz +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +- type: entity + id: BaseFishingSpot + abstract: true + name: suspicious waves + description: Something is floating here... + placement: + mode: SnapgridCenter + components: + - type: FishingSpot + fishList: !type:NestedSelector + tableId: WaterFishingLootTable + fishDefaultTimer: 25.0 + fishTimerVariety: 15.0 + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeAabb + bounds: "-0.25,-0.25,0.25,0.25" + layer: + - ItemMask + mask: + - HighImpassable + density: 1000 + hard: false + - type: Transform + anchored: true + noRot: true + - type: Clickable + - type: InteractionOutline + - type: PhysicsGunBlacklist + # TODO: change visuals when it's active + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fishing_spot.rsi + state: water + - type: Icon + sprite: _Goobstation/Objects/Specific/Fishing/fishing_spot.rsi + state: water + +- type: entity + id: FishingSpotWater + parent: BaseFishingSpot diff --git a/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Fishing/loot_tables.yml b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Fishing/loot_tables.yml new file mode 100644 index 00000000000..f46e12fec53 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Fishing/loot_tables.yml @@ -0,0 +1,109 @@ +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +# This should be on every other fishing table +- type: entityTable + id: BasicFishingLootTable + table: !type:GroupSelector + children: + # 75% chance of scrap of some kind + - !type:GroupSelector + weight: 75 + children: + - !type:NestedSelector + tableId: SalvageScrapLowValue + weight: 65 + - !type:NestedSelector + tableId: SalvageScrapHighValue + weight: 35 + # 15% chance of some trash + - !type:NestedSelector + tableId: GenericTrashItems + weight: 15 + # 10% chance of low-value treasure or maintenance tools + - !type:GroupSelector + weight: 10 + children: + - !type:NestedSelector + tableId: SalvageTreasureCommon + - !type:NestedSelector + tableId: MaintToolsTable + +# All types of the rare and unique fishes +- type: entityTable + id: RareFishTable + table: !type:GroupSelector + children: + - id: FishAlien + - id: FishBingle + - id: FishBoyFisher + - id: FishNukeDisk + - id: FishGib + - id: FishMutant + - id: FishNuker + - id: FishToxic + - id: FishIan + +# Fish from water +- type: entityTable + id: WaterFishTable + table: !type:GroupSelector + children: + - id: FishAngler + - id: FishBass + - id: FishBlob + - id: FishBlueFintuna + - id: FishCat + - id: FishTropicalClown + - id: FishPuffer + - id: FishSilver + - id: FishTropicalSun + - id: FishTropical + +# Items from Water +- type: entityTable + id: WaterFishingLootTable + table: !type:GroupSelector + children: + - !type:NestedSelector + tableId: BasicFishingLootTable + weight: 70 + - !type:NestedSelector + tableId: WaterFishTable + weight: 20 + - !type:NestedSelector + tableId: RareFishTable + weight: 10 + +# Items from Lava +- type: entityTable + id: LavaFishingLootTable + table: !type:GroupSelector + children: + # TODO: lava/plasma fish + - !type:NestedSelector + tableId: BasicFishingLootTable + +# Items from Plasma +- type: entityTable + id: PlasmaFishingLootTable + table: !type:GroupSelector + children: + # TODO: lava/plasma fish + - !type:NestedSelector + tableId: BasicFishingLootTable + +# Items from Toilets +- type: entityTable + id: ToiletFishingLootTable + table: !type:GroupSelector + children: + # like water but no rare fishes + - !type:NestedSelector + tableId: BasicFishingLootTable + weight: 80 + - !type:NestedSelector + tableId: WaterFishTable + weight: 20 diff --git a/Resources/Prototypes/_Goobstation/Entities/Objects/Tools/fishing_rods.yml b/Resources/Prototypes/_Goobstation/Entities/Objects/Tools/fishing_rods.yml new file mode 100644 index 00000000000..aa4a6d9f650 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Entities/Objects/Tools/fishing_rods.yml @@ -0,0 +1,117 @@ +# SPDX-FileCopyrightText: 2025 Aidenkrz +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Basic rod +- type: entity + id: FishingRod + parent: BaseItem + name: fishing rod + description: It's time to go fishing! + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/fishing_rod.rsi + state: icon + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fishing_rod.rsi + size: Normal + - type: UseDelay # Just for visuals and to prevent autoclickers + delay: 0.08 # 12,5 CPS at max + - type: MeleeWeapon + wideAnimationRotation: 45 + attackRate: 1.0 + damage: + types: + Piercing: 4 + - type: FishingRod + +# Variation of a normal rod +- type: entity + id: FishingRodGoon + suffix: Goon + parent: FishingRod + name: fishing rod + description: It's time to go fishing! + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/goon_rod.rsi + state: icon + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/goon_rod.rsi + size: Normal + +# Makeshift rod +- type: entity + id: FishingRodMakeshift + parent: FishingRod + name: makeshift fishing rod + description: Probably would be hard to catch a fish using that. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi + state: icon + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi + size: Normal + - type: FishingRod + floatPrototype: FishingLureMakeshift + efficiency: 0.8 + - type: Construction + graph: FishingRodMakeshift + node: makeshiftRod + +# Golden rod +- type: entity + id: FishingRodGolden + parent: FishingRod + name: golden fishing rod + description: Finally, you caught 250 fishes. Here's your trophey. + components: + - type: Sprite + sprite: _Goobstation/Objects/Specific/Fishing/golden_rod.rsi + state: icon + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/golden_rod.rsi + size: Normal + - type: FishingRod + efficiency: 1.3 + - type: MeleeWeapon + wideAnimationRotation: 45 + attackRate: 1.0 + damage: + types: + Piercing: 10 + +# Normal fishing lure +- type: entity + id: FishingLure + parent: BaseItem + name: fishing lure + description: fish come here + categories: [ HideSpawnMenu ] + components: + - type: Sprite + noRot: true + sprite: _Goobstation/Objects/Specific/Fishing/fishing_lure.rsi + state: icon + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/fishing_lure.rsi + size: Normal + - type: FishingLure + +- type: entity + id: FishingLureMakeshift + parent: FishingLure + name: fishing lure + description: fish come here + categories: [ HideSpawnMenu ] + components: + - type: Sprite + noRot: true + sprite: _Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi + state: icon + - type: Item + sprite: _Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi + size: Normal diff --git a/Resources/Prototypes/_Goobstation/Recipes/Construction/Graphs/misc/makeshift_rod.yml b/Resources/Prototypes/_Goobstation/Recipes/Construction/Graphs/misc/makeshift_rod.yml new file mode 100644 index 00000000000..dd159637c45 --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Recipes/Construction/Graphs/misc/makeshift_rod.yml @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# SPDX-FileCopyrightText: 2026 Skill Issue Station contributors +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +- type: constructionGraph + id: FishingRodMakeshift + start: start + graph: + - node: start + edges: + - to: makeshiftRod + steps: + - material: Cloth + amount: 3 + doAfter: 2 + - material: WoodPlank + amount: 5 + doAfter: 2 + - node: makeshiftRod + entity: FishingRodMakeshift diff --git a/Resources/Prototypes/_Goobstation/Recipes/Construction/misc.yml b/Resources/Prototypes/_Goobstation/Recipes/Construction/misc.yml new file mode 100644 index 00000000000..eba5de9d0ea --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Recipes/Construction/misc.yml @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2025 GoobBot +# SPDX-FileCopyrightText: 2025 Roudenn +# SPDX-FileCopyrightText: 2026 Skill Issue Station contributors +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +- type: construction + id: FishingRodMakeshift + graph: FishingRodMakeshift + startNode: start + targetNode: makeshiftRod + category: construction-category-misc + objectType: Item diff --git a/Resources/Textures/_Goobstation/Interface/Misc/fish_bar.rsi/icon.png b/Resources/Textures/_Goobstation/Interface/Misc/fish_bar.rsi/icon.png new file mode 100644 index 00000000000..17535a5ca01 Binary files /dev/null and b/Resources/Textures/_Goobstation/Interface/Misc/fish_bar.rsi/icon.png differ diff --git a/Resources/Textures/_Goobstation/Interface/Misc/fish_bar.rsi/meta.json b/Resources/Textures/_Goobstation/Interface/Misc/fish_bar.rsi/meta.json new file mode 100644 index 00000000000..dd4481e8221 --- /dev/null +++ b/Resources/Textures/_Goobstation/Interface/Misc/fish_bar.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "size": { + "x": 8, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "https://github.com/tgstation/tgstation/blob/886ca0f8dddf83ecaf10c92ff106172722352192/icons/effects/progessbar.dmi, resized and edited by rouden_ (discord)", + "states": [ + { + "name": "icon" + } + ] +} diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/alien.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/alien.png new file mode 100644 index 00000000000..1bf96770135 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/alien.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/angler.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/angler.png new file mode 100644 index 00000000000..a04b0447d21 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/angler.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/bass.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/bass.png new file mode 100644 index 00000000000..eb8618fb2d4 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/bass.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/bingle.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/bingle.png new file mode 100644 index 00000000000..c7817a1dd5a Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/bingle.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/blob.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/blob.png new file mode 100644 index 00000000000..e3161045e7c Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/blob.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/blue_fintuna.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/blue_fintuna.png new file mode 100644 index 00000000000..78f40ebaa80 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/blue_fintuna.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/boy_fisher.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/boy_fisher.png new file mode 100644 index 00000000000..afdfb01b351 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/boy_fisher.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/catfish.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/catfish.png new file mode 100644 index 00000000000..2f0e1a6135b Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/catfish.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/clown.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/clown.png new file mode 100644 index 00000000000..879229450bd Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/clown.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/disk.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/disk.png new file mode 100644 index 00000000000..c606d18bdca Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/disk.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/gib.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/gib.png new file mode 100644 index 00000000000..5371fc77dce Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/gib.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/ian.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/ian.png new file mode 100644 index 00000000000..1de536567f6 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/ian.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/meta.json b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/meta.json new file mode 100644 index 00000000000..c54652d4dd2 --- /dev/null +++ b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/meta.json @@ -0,0 +1,95 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "bingle, boy_fisher, gib, disk, nuker, pufferfish by arraydeess (discord), clown, tropical, mutant, alien, bluefintuna, blob, toxic by imasleeping (discord), ian fish by latibulate_ (discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "alien" + }, + { + "name": "angler" + }, + { + "name": "bass" + }, + { + "name": "bingle" + }, + { + "name": "blob" + }, + { + "name": "blue_fintuna" + }, + { + "name": "boy_fisher", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "catfish" + }, + { + "name": "clown" + }, + { + "name": "disk", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "gib", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "mutant" + }, + { + "name": "nuker" + }, + { + "name": "pufferfish" + }, + { + "name": "silverfish" + }, + { + "name": "sun_tropical" + }, + { + "name": "toxic" + }, + { + "name": "tropical" + }, + { + "name": "ian" + } + ] +} diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/mutant.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/mutant.png new file mode 100644 index 00000000000..1f32e3a3de5 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/mutant.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/nuker.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/nuker.png new file mode 100644 index 00000000000..8943a90d6b2 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/nuker.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/pufferfish.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/pufferfish.png new file mode 100644 index 00000000000..1b413334211 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/pufferfish.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/silverfish.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/silverfish.png new file mode 100644 index 00000000000..b103088c8c7 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/silverfish.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/sun_tropical.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/sun_tropical.png new file mode 100644 index 00000000000..2cee2eafc90 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/sun_tropical.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/toxic.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/toxic.png new file mode 100644 index 00000000000..1679f0f548a Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/toxic.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/tropical.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/tropical.png new file mode 100644 index 00000000000..78f138983c2 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fish.rsi/tropical.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_lure.rsi/icon.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_lure.rsi/icon.png new file mode 100644 index 00000000000..5d731573e18 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_lure.rsi/icon.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_lure.rsi/meta.json b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_lure.rsi/meta.json new file mode 100644 index 00000000000..8f15d477121 --- /dev/null +++ b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_lure.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Sprites by arraydeess (discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "rope" + } + ] +} diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_lure.rsi/rope.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_lure.rsi/rope.png new file mode 100644 index 00000000000..2cbc11a08c8 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_lure.rsi/rope.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/icon-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/icon-active.png new file mode 100644 index 00000000000..835af5a280f Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/icon-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/icon.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/icon.png new file mode 100644 index 00000000000..1738ec1c1ee Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/icon.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-left-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-left-active.png new file mode 100644 index 00000000000..b250960daae Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-left-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-left.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-left.png new file mode 100644 index 00000000000..de26c62d813 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-left.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-right-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-right-active.png new file mode 100644 index 00000000000..8349d576e7e Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-right-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-right.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-right.png new file mode 100644 index 00000000000..55aebb4f9bd Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/inhand-right.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/meta.json b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/meta.json new file mode 100644 index 00000000000..979f05fa920 --- /dev/null +++ b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_rod.rsi/meta.json @@ -0,0 +1,33 @@ +{ + "version": 1, + "license": "CC-BY-NC-SA-3.0", + "copyright": "Goonstation, taken at commit 39ddf6bbd54c9f27fe49f5cea1a3119738b09596", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-left-active", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "inhand-right-active", + "directions": 4 + }, + { + "name": "icon" + }, + { + "name": "icon-active" + } + ] +} diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_spot.rsi/meta.json b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_spot.rsi/meta.json new file mode 100644 index 00000000000..ead6c5ee9c4 --- /dev/null +++ b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_spot.rsi/meta.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "water by Rouge2t7 on Discord", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "water", + "delays": [ + [ + 0.25, + 0.25, + 0.25 + ] + ] + } + ] +} diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_spot.rsi/water.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_spot.rsi/water.png new file mode 100644 index 00000000000..1d9528ddadc Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/fishing_spot.rsi/water.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/icon-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/icon-active.png new file mode 100644 index 00000000000..e0c654e374b Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/icon-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/icon.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/icon.png new file mode 100644 index 00000000000..85d6e3a8f06 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/icon.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-left-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-left-active.png new file mode 100644 index 00000000000..fe7a0f1c5a9 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-left-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-left.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-left.png new file mode 100644 index 00000000000..00db0a51c75 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-left.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-right-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-right-active.png new file mode 100644 index 00000000000..07b0a660fd5 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-right-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-right.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-right.png new file mode 100644 index 00000000000..76285aa01d0 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/inhand-right.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/meta.json b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/meta.json new file mode 100644 index 00000000000..10bfa9bbcae --- /dev/null +++ b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/golden_rod.rsi/meta.json @@ -0,0 +1,33 @@ +{ + "version": 1, + "license": "CC-BY-NC-SA-3.0", + "copyright": "Goonstation, taken at commit 39ddf6bbd54c9f27fe49f5cea1a3119738b09596, modified by rouden_ (discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-left-active", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "inhand-right-active", + "directions": 4 + }, + { + "name": "icon" + }, + { + "name": "icon-active" + } + ] +} diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/icon-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/icon-active.png new file mode 100644 index 00000000000..b05d89453bf Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/icon-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/icon.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/icon.png new file mode 100644 index 00000000000..7a014e6f889 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/icon.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-left-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-left-active.png new file mode 100644 index 00000000000..b250960daae Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-left-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-left.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-left.png new file mode 100644 index 00000000000..de26c62d813 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-left.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-right-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-right-active.png new file mode 100644 index 00000000000..8349d576e7e Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-right-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-right.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-right.png new file mode 100644 index 00000000000..55aebb4f9bd Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/inhand-right.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/meta.json b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/meta.json new file mode 100644 index 00000000000..979f05fa920 --- /dev/null +++ b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/goon_rod.rsi/meta.json @@ -0,0 +1,33 @@ +{ + "version": 1, + "license": "CC-BY-NC-SA-3.0", + "copyright": "Goonstation, taken at commit 39ddf6bbd54c9f27fe49f5cea1a3119738b09596", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-left-active", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "inhand-right-active", + "directions": 4 + }, + { + "name": "icon" + }, + { + "name": "icon-active" + } + ] +} diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi/icon.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi/icon.png new file mode 100644 index 00000000000..042c32df9f0 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi/icon.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi/meta.json b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi/meta.json new file mode 100644 index 00000000000..8f15d477121 --- /dev/null +++ b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi/meta.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Sprites by arraydeess (discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "rope" + } + ] +} diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi/rope.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi/rope.png new file mode 100644 index 00000000000..2662f7bfdc7 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_lure.rsi/rope.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/icon-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/icon-active.png new file mode 100644 index 00000000000..e2a38566c6c Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/icon-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/icon.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/icon.png new file mode 100644 index 00000000000..e4cac4c84e5 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/icon.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-left-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-left-active.png new file mode 100644 index 00000000000..e95e2a1b5fe Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-left-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-left.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-left.png new file mode 100644 index 00000000000..232d17a9510 Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-left.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-right-active.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-right-active.png new file mode 100644 index 00000000000..2fb4cd3bd1a Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-right-active.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-right.png b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-right.png new file mode 100644 index 00000000000..d70d19811ee Binary files /dev/null and b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/inhand-right.png differ diff --git a/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/meta.json b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/meta.json new file mode 100644 index 00000000000..fbeab60e076 --- /dev/null +++ b/Resources/Textures/_Goobstation/Objects/Specific/Fishing/makeshift_rod.rsi/meta.json @@ -0,0 +1,33 @@ +{ + "version": 1, + "license": "CC-BY-NC-SA-3.0", + "copyright": "Sprites by arraydeess (discord) and rouden_ (discord)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-left-active", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "inhand-right-active", + "directions": 4 + }, + { + "name": "icon" + }, + { + "name": "icon-active" + } + ] +}