PapaSalazar-AimUrWay icon

AimUrWay

Soft aim assist for mouse and keyboard, with a damage penalty that scales to how much help you took. Tracks fish and animals only, never players. Includes an exact sensitivity converter and FOV fixes.

Last updated 4 hours ago
Total downloads 128
Total rating 1 
Categories Mods Tools
Dependency string PapaSalazar-AimUrWay-0.1.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

Aim Ur Way — How to Fish

v0.1.0 — early. Loads and patches cleanly; the assist's feel has not been tuned against live play yet.

A soft aim assist for mouse-and-keyboard players, with a damage penalty that scales to how much help you actually took — plus a sensitivity converter from other shooters.

The goal is a genuine accessibility aid that a lobby can accept, not a hidden advantage.


Host or client?

Entirely client-side. No host cooperation, and nobody else needs to install anything.

  • The assist only rotates your camera. Nothing about it is networked.
  • The damage penalty is real, not cosmetic. Damage in this game is client-authoritative: your client computes damage and tells the server to apply it (PlayerVitals.LocalHitServer.HitPlayer, and ProjectileManager stamps damage onto each projectile on the shooter's machine). So when this mod lowers your damage locally, it is lowered — there is no server-side value overriding it.

That cuts both ways, and it's worth saying plainly: because the game trusts clients on damage, this mod's honesty is a property of the mod, not something the server enforces. The penalty is real for anyone running this build.


Why this isn't an aimbot

The game already ships its own aim assist (PlayerAimAssist) — for controllers, while aiming down sights. This mod keeps that design and lifts the controller restriction. Specifically:

  1. It hooks the game's own extension point. PlayerCamera.ApplyAimAssist() already asks PlayerAimAssist.GetRotationDelta(..) for a rotation nudge each frame. That one method is the patch target, so the assist runs where the game intends and inherits its feel.
  2. It never targets players. The vanilla scan walks ItemManager.Items and takes each item's Creature, so it only ever tracks fish and animals. This mod does the same, and there is no player-targeting option — deliberately. That single property is what makes "not cheating" defensible, and it's why fighting other players is unaffected.
  3. It cannot snap. The pull is an exponential approach toward the target, hard-clamped by MaxRotationSpeed (default 90°/s). There is no instant correction anywhere in the code.
  4. You always win. The pull scales down by how fast you're turning; past ManualOverrideDegPerSec (default 140°/s) it stops entirely. A flick always beats the assist.
  5. Narrow acquisition. Default 12° half-angle, requires line of sight, capped at 60 m — the game's own numbers.
  6. It refuses to run un-penalised. If the damage-penalty patch fails to apply, the assist disables itself rather than becoming a straight advantage.

The damage penalty is proportional, not flat. The mod keeps a decaying tally of how many degrees of aiming it did versus how many you did. That ratio drives the reduction:

damage x= 1 - (MaxDamagePenalty * assistShare)

Aim manually and land the shot: no penalty. Let the assist track a target for you and shoot: the full penalty. It's applied at Attachments.Damage, the single property every shot's damage flows through, so hitscan and travelling projectiles are both covered. The shop's stat panel reads the underlying array rather than the property, so displayed weapon stats stay honest.


Sensitivity converter

This part is exact rather than eyeballed. From PlayerCamera.MouseInput:

LookInput = new Vector2(-raw.y, raw.x) * _sensitivity * SensMulti * 0.025f;
_rot += LookInput;

_rot is in degrees and raw is the Input System mouse delta in counts, so:

degrees per mouse count = sensitivity × 0.025 (at hip fire, where SensMulti == 1)

Which gives, using cm/360 as the common currency because it's independent of FOV and resolution:

$$\text{game sens} = \frac{360 \times 2.54}{\text{cm/360} \times \text{DPI} \times 0.025} = \frac{36576}{\text{cm/360} \times \text{DPI}}$$

Worked example: CS2 at 1.0 / 800 DPI is 51.95 cm/360 → this game wants 0.880. The game's default of 0.5 is about 91 cm/360 at 800 DPI, which is slow by comp standards.

Press F10 for the panel. Pick a game, enter your sensitivity and DPI, and it shows the value to use plus the cm/360 both before and after. Apply writes it via PlayerCamera.SetSensitivity.

Note the game already scales sensitivity by zoom correctly — SensMulti = _curFov / _origFov — so your ADS sensitivity stays proportional without any help. That is 360-distance matched zoom, the usual competitive choice.


Field of view

Measured in game, not guessed:

Slider range 40–140 vertical = 66–157 horizontal at 16:9
Default 74 vertical = 106.5 horizontal at 16:9

Those are the game's own limits, read off its options slider at runtime. This mod does not widen them, and the panel's FOV box clamps whatever you type to that same range.

Two things worth knowing.

Unity's fieldOfView is vertical, but every shooter quotes horizontal, so the two are never directly comparable. The panel shows both, using your actual resolution's aspect ratio. Neatly, the default 74 vertical works out at 106.5° horizontal — within a quarter of a degree of CS2's 106.26°, so the stock FOV is already CS-equivalent.

Base FOV changes your aimed sensitivity. Because SensMulti = curFov / baseFov, aiming multiplies sensitivity by AdsFov / baseFov. Raise your base FOV and your scoped aim gets slower. The panel shows the exact multiplier for whatever you're holding.

The FOV persistence bug

The options menu saves your FOV with PlayerPrefs.SetInt("FOV", …) but loads it with PlayerPrefs.GetInt("Fov", 74). PlayerPrefs keys are case sensitive, so the two never meet and your FOV reverts to 74 on every launch — quietly shifting your aimed sensitivity by up to 1.9× at the extremes of the slider.

FixFovPersistence (on by default) mirrors the saved value into the key the game actually reads, and forces it for the current session if the menu already loaded the wrong one. Verified in the registry: both FOV_h193442778 and Fov_h193443802 now hold the same value.

Caveat: the slider appears to fire its change callback on enable, so the first repair may pin the slider's serialized default rather than a value you chose. Set your FOV once through the panel's Apply FOV button to pin it deliberately — that writes both keys.

Two ways to convert

The panel gives you a straight choice:

  • Keep the same turning speed (default) — the mouse travels the same distance to spin all the way round as it did in your other game. Ignores FOV, so it's exact.
  • Adjust for the FOV difference — if the two games show different amounts of the world, this makes aiming feel the same on screen instead of turning at the same rate. Needs that game's FOV.

Most people want the first one. The second is there because if you're coming from a 103° game to a 116° one, matching raw turn speed can feel too fast even though the numbers agree.

There's a FovAdjustStrength in the config for the second mode if you already know you want the adjustment weighted toward the screen edge rather than the centre. If that sentence means nothing to you, you don't need it.

Presets

Counter-Strike 2 / CS:GO · Valorant · Apex Legends · Overwatch 2 · Team Fortress 2 · Quake

Games whose sensitivity depends on their own FOV slider (Rainbow Six Siege) or use a non-linear percentage scale (Fortnite) are deliberately absent rather than approximated. Use the cm/360 field for those — read the figure out of any online calculator and it's exact for every game ever made.

Caveat

The conversion assumes one Input System delta unit equals one mouse count — true with Windows pointer speed at the default 6/11 and "enhance pointer precision" off. If you run pointer acceleration, no converter can give you a stable answer.


Config

BepInEx/config/howtofish.aimurway.cfg. Hotkeys: F9 assist on/off, F10 converter panel.

Assist

Setting Default
Strength 0.55 Fraction of the pull to apply. 1 matches the game's controller assist
Sharpness 8 How eagerly it closes the gap. Higher is stickier
MaxRotationSpeed 90 Hard ceiling in °/s. This is what prevents snapping
ManualOverrideDegPerSec 140 Turn this fast and the assist steps aside entirely
AcquireAngle 12 Half-angle to pick up a target. Keep small
BreakAngle 35 Angle at which a locked target is dropped
MaxDistance 60 Metres. The game's own default
AssistFromHip false Vanilla is ADS-only; leaving this off stays closer to intent
AlsoAssistController false Off so it never stacks with the built-in controller assist

Fairness

Setting Default
DamagePenalty true Trade damage for aim help
MaxDamagePenalty 0.3 Largest reduction, at full assist share. 0.3 = −30%
PenaltyWindowSeconds 1.5 How long assist usage keeps counting against you

Set ShowDebugText = true under [Diagnostics] to watch the target lock, live assist share and current damage multiplier — the fastest way to tune Strength and see the penalty working.


Status and what's left

Verified: the plugin loads, binds to the game, and both Harmony patches apply (PlayerAimAssist.GetRotationDelta, Attachments.get_Damage) with no errors.

Not yet done:

  • Feel is untuned. The defaults are reasoned, not playtested. Strength and Sharpness are the two to adjust first, with ShowDebugText on.
  • Melee is uncovered. Melee has its own damage path, so the penalty doesn't apply to it. Not a problem today because the assist only helps ranged aiming.
  • No lobby-side disclosure. There's no chat announcement or host-side gate. If you play with people who care, tell them.

Design notes

Unlike the crosshair mod, this one changes behaviour, so Harmony patches are unavoidable. They're kept to two, both at stable extension points, and there's still no compile-time reference to Assembly-CSharp — everything is resolved by name at runtime, so a game update degrades to a logged warning and a disabled feature rather than a crash.