PapaSalazar-DynamicCrosshair icon

DynamicCrosshair

Crosshair that marks where your gun is really pointing and traces its live spread cone, including bullet drop and muzzle parallax. Client-side, no patches.

Last updated 2 hours ago
Total downloads 15
Total rating 1 
Categories Mods
Dependency string PapaSalazar-DynamicCrosshair-1.0.0
Dependants 0 other packages depend on this package

This mod requires the following mods to function

BepInEx-BepInExPack-5.4.2305 icon
BepInEx-BepInExPack

BepInEx pack for Mono Unity games. Preconfigured and ready to use.

Preferred version: 5.4.2305

README

Dynamic Crosshair — How to Fish

by PapaSalazar

A client-side crosshair that shows where your gun is actually pointing and traces the real spread cone the game will use for your next shot.

How to Fish ships no crosshair. The guns are held off to the side of the camera and their muzzles are driven by a physics recoil rig, so the barrel is almost never pointing at the middle of your screen. This mod stops you guessing: it reads the weapon's own numbers every frame, re-runs the game's own shot maths, and draws the result.

  • Point of aim — a dot at the exact spot the muzzle is looking at, not the screen centre.
  • Spread outline — the boundary of the cone your pellets can land in, traced from the game's live _spread value.
  • Bullet drop — weapons whose projectiles travel and fall are simulated with the game's own integrator, so the crosshair sits where the shot lands, not where the barrel points.
  • Blocked-barrel warning — when you press the muzzle into a wall, crate or teammate, How to Fish silently resolves the shot at that obstruction instead of downrange. The crosshair turns red and snaps to the impact point.

No Harmony patches, no network traffic, no writes to game state. It reads and it draws.


Install

With a mod manager (recommended)

Search for DynamicCrosshair in Thunderstore Mod Manager or r2modman and install. BepInEx comes along as a dependency.

By hand

  1. Install BepInEx 5.4.23.5 (win_x64) into the folder containing How to Fish.exe, then launch the game once so it creates its folders.
  2. Drop DynamicCrosshair.dll into How to Fish/BepInEx/plugins/.
  3. Launch. The config file appears at BepInEx/config/howtofish.dynamiccrosshair.cfg.

Press F8 in game to toggle the crosshair off and on.


Configuration

Edit BepInEx/config/howtofish.dynamiccrosshair.cfg (restart the game to apply).

Shape

Two independent settings: one for the spread cone, one for the point of aim. Set either to None if you only want the other.

SpreadStyle
None Do not draw the cone
Ring Continuous outline (default)
DashedRing Broken outline — reads better over busy scenery
Ticks Four marks standing outward on the boundary
Brackets Four short arcs, like brackets around the target
CenterStyle
None Do not mark the point of aim
Dot Filled disc
HollowDot Small open circle — readable on light and dark backgrounds
Plus Four arms with a centre gap (default) — never covers what you are shooting
Cross Four diagonal arms with a centre gap
Diamond Small open diamond

Size

Sizes are authored for 1080p and scaled to your screen height, so the crosshair looks the same at 1440p and 4K instead of shrinking to a few specks.

Setting Default What it does
ScaleWithResolution true Scale all sizes by screen height. Off = exact pixels
ReferenceHeight 1080 Height the sizes below are authored against
Thickness 2 Line thickness of the spread outline
OutlineWidth 1.5 Dark edge width per side. This is the main visibility control — raise it before anything else. 0 disables
CenterSize 3 Radius of Dot, HollowDot, Diamond
CenterGap 3 Empty space in the middle of Plus / Cross
CenterArmLength 8 Arm length for Plus / Cross
TickLength 9 Mark length for Ticks
Segments 40 Points used to trace the outline
DashCount 12 Dashes in DashedRing
BracketArcDegrees 34 How much of the boundary each Brackets arc covers
MinRadiusPixels 3 Smallest the outline may get. Weapons with no spread show only the centre marker, since a ring there would imply spread that does not exist
MaxRadiusPixels 900 Safety clamp

Colours

All values are RRGGBBAA hex — the last two digits are opacity.

Setting Default What it does
Color 5CFFC8FF Spread outline
CenterColor FFFFFFFF Point-of-aim marker. Keeping this a different colour from the outline is the single easiest way to make the exact aim point pop
BlockedColor FF4040FF Used when the barrel is obstructed
OutlineColor 000000C8 Dark edge drawn behind everything

Behaviour

Setting Default What it does
HideWhileAiming false Hide once you are aiming down the weapon's own sights
HideWithSniperScope true Hide behind the full-screen scope overlay, where it only adds clutter
ShowBlockedIndicator true Recolour and relocate the crosshair when the muzzle is obstructed
ConformToGeometry false Trace every outline point against the world so the cone wraps around corners and angled surfaces. Nicer looking; costs one cast per segment per frame
MaxSimulationSteps 250 Physics ticks simulated for projectiles that travel and drop
MaxRange 400 How far to follow a shot before drawing the crosshair at that distance

Diagnostics

Setting Default What it does
ShowDebugText false On-screen readout of live spread, pellet count, delivery type, range and on-screen radius
LogBindingDetails true Lists every game field the mod attached to at startup. Leave this on — it is the fastest way to see what a game update changed
DumpWeaponTable false Once in game, log every weapon's id, spread, pellet count, speed and gravity, plus the id of every other item. Handy for checking weapons you are not holding, and for bug reports
TestPattern false Draws a fixed ring at screen centre everywhere, including the main menu

Can't see it? Try these

How to Fish is a bright, high-contrast game — pale sand, bright sky, white water. A thin crosshair disappears into it. In rough order of effectiveness:

  1. Raise OutlineWidth to 23. The dark edge behind the crosshair does more for legibility than any colour change.
  2. Use a contrasting CenterColor. Magenta FF00FFFF or yellow FFE800FF cut through sand and sea in a way white and cyan do not.
  3. Switch CenterStyle to Plus or Cross. Four arms cover far more pixels than a dot while the centre gap keeps your target visible.
  4. Raise Thickness to 2.53 and CenterArmLength to 1012.
  5. Check ScaleWithResolution is true. If it is off on a 1440p or 4K screen, every size is being taken as literal pixels and will look tiny.

Ready-made combinations:

Maximum visibility

SpreadStyle = Ring
CenterStyle = Plus
Thickness = 2.8
OutlineWidth = 2.5
CenterArmLength = 11
CenterColor = FF00FFFF

Minimal — point of aim only

SpreadStyle = None
CenterStyle = HollowDot
CenterSize = 3.5

Shooter-familiar — four ticks that track the spread

SpreadStyle = Ticks
CenterStyle = Dot
TickLength = 11

Clean brackets

SpreadStyle = Brackets
CenterStyle = Diamond
BracketArcDegrees = 28

What "dynamic" actually means here

Worth being precise, because it affects how much you should trust the ring.

In the current game build, Weapon._spread is a constant per weapon — a cone half-angle in degrees, set on each weapon prefab. It is not a bloom value that grows while you spray. So the ring is not going to pulse when you fire.

And there are only five guns, of which exactly one has any spread at all:

Weapon Item ID Spread Pellets Speed Gravity
Pistol 66 1 350 0
Smg 69 1 350 0
Assault Rifle 54 1 900 0
Shotgun 68 25 100 0
Sniper Rifle 70 1 1000 0

So be clear on what you are getting: the spread ring only ever appears on the shotgun. On the other four the crosshair is a point-of-aim marker, which is still the part that matters most — the barrel does not point at your screen centre, and that offset is large up close. Measured on the pistol: about 130 px off centre at 5 m, converging to nothing by 400 m.

No gun uses ProjectileGravity either, so the bullet-drop simulation is currently inert for player weapons. It is kept because it costs nothing when gravity is zero and it means an arced weapon added in a future update works on day one, with no mod change.

What genuinely changes frame to frame, and what this mod tracks:

  • Where the cone points. The muzzle transform is driven by a ConfigurableJoint recoil rig plus sway, sprint offsets and the aim-down-sights position. It moves constantly, and it does not point at your screen centre.
  • How big the cone looks. Aiming down sights changes the camera FOV, so the same angular spread covers a different number of pixels.
  • Where the cone lands. For weapons with ProjectileGravity, distance changes the drop, so the whole crosshair moves down as your target gets further away.
  • Which muzzle is used. Barrel attachments swap the fire point, so fitting a suppressor moves your point of aim.
  • The scoped-weapon override. Past 90% zoom, a weapon with a sniper scope fires from the camera instead of the barrel. The crosshair follows that switch.

The value is read fresh every frame rather than cached, so if a future update turns _spread into a real dynamic bloom, this crosshair starts breathing with it on its own — no mod update needed.

The outline is sampled using the game's own expression, Quaternion.Euler(v * _spread) * forward with |v| == 1, rather than approximated with a circle. That matters because the game applies its Euler angles on world axes, which makes the cone slightly orientation-dependent. Sampling the real expression reproduces that instead of hiding it.


Why this should survive game updates

Most mods break on update because they hard-reference the game's assembly or patch a method whose signature moved. This one does neither.

  1. No compile-time reference to Assembly-CSharp. The mod only links against BepInEx and stock Unity modules. A changed game assembly cannot produce a TypeLoadException, because there is nothing to load.
  2. No Harmony patches. Nothing is hooked, so there is no signature to match, no patch to fail, and no conflict with other mods.
  3. Name-tolerant binding. Every field is looked up by a list of likely names; if none match, the mod searches the declaring type for a member of the right type whose name contains the relevant keyword. _spread becoming _bulletSpread still binds, with a warning telling you it happened.
  4. Independent feature degradation. Only six members are essential. Everything else — bullet drop, the blocked-barrel check, scope handling, water clamping — fails on its own, logs one warning, and leaves the rest working.
  5. It switches itself off rather than misbehaving. After 30 consecutive read failures the mod disables itself and says so once. It will never spam your log or tank your frame rate.

If a future update does break something, LogBindingDetails prints exactly which member could not be found, which is usually a one-line fix.


Troubleshooting

No crosshair at all. Set TestPattern = true and restart. A ring at screen centre means the overlay works and the problem is reading the weapon — check BepInEx/LogOutput.log. No ring means something else is covering the overlay; try raising sortingOrder by rebuilding, or check for a conflicting UI mod.

It only appears with a gun out. Correct. Fishing rods and melee weapons have no spread cone.

Nothing in the log. BepInEx is not loading. Confirm winhttp.dll and doorstop_config.ini sit next to How to Fish.exe, and that you used the win_x64 build.

Frame rate dip with a bow or harpoon. Those projectiles are simulated tick by tick. Lower MaxSimulationSteps, or MaxRange, or turn off ConformToGeometry.


Multiplayer

Entirely client-side and read-only: no RPCs, no synced state, and no data read about other players. Nothing to desync and nothing another client can detect.

That said, it is an aiming aid in a game that has friendly fire and a PvP-capable lobby. The game already sells a laser-sight attachment that does something similar at short range, so this is not far outside its own design — but it is worth checking with whoever is hosting before using it in a competitive lobby.


Building from source

Requires the .NET SDK (8 or newer). No NuGet packages; references come from your game install.

dotnet build -c Release

If your Steam library is not on C:, point the build at it:

dotnet build -c Release -p:GameDir="D:\SteamLibrary\steamapps\common\How to Fish\How to Fish"

build.ps1 builds, copies the DLL into your game's plugin folder and produces a Thunderstore-ready zip in dist/:

powershell -ExecutionPolicy Bypass -File build.ps1

validate-package.ps1 checks that zip against Thunderstore's manifest rules — required files, name and version format, description length, dependency strings, icon dimensions — and queries the community to confirm the name and version are not already taken:

powershell -ExecutionPolicy Bypass -File validate-package.ps1

The project targets netstandard2.1, because Unity 6's own assemblies do and anything lower fails to reference them.

Test save

tools/make-test-save.ps1 writes a save containing all five guns, one per hotbar slot, so you can cycle 1–5 and check the crosshair against every weapon in the game:

powershell -ExecutionPolicy Bypass -File tools\make-test-save.ps1

It reads your SteamID from your newest existing save (saves are keyed by it), leaves your own saves untouched, and creates a separate one called CrosshairTest. Weapons get default attachments, because Sight, BarrelAttachment and AmmoType are indexes into per-weapon lists and an out-of-range value would throw inside the game — buy attachments in game instead. Use -Name, -Money and -SteamId to override.


Verified against

How to Fish 1.0.4 (Steam app 4001890, build 24860529)
Unity 6000.4.4 (Mono backend)
BepInEx 5.4.23.5 win_x64

Licence

MIT. See LICENSE.