Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
REPOPathfinder
BepInEx plugin for R.E.P.O. Renders an in-world NavMesh dot trail to the current extraction or truck. Cached corners + player projection keep dots stable as you move. F4 toggle, F5 Auto/Truck, F6 IMGUI customize panel (color/size/flow/spacing).
By MentalizePez
| Last updated | an hour ago |
| Total downloads | 4 |
| Total rating | 1 |
| Categories | Tools AI Generated |
| Dependency string | MentalizePez-REPOPathfinder-0.7.2 |
| Dependants | 0 other packages depend on this package |
This mod requires the following mods to function
BepInEx-BepInExPack
BepInEx pack for Mono Unity games. Preconfigured and ready to use.
Preferred version: 5.4.2100README
REPOPathfinder
A BepInEx plugin for R.E.P.O. that renders an in-world dot trail along the NavMesh path to the current extraction point — or back to the truck once all extractions are complete. It mirrors the same target-selection logic the in-map "backtrack" dots use, projected into world space so you can follow it without opening the map.
Hotkeys (configurable, all default to F-keys):
- F4 — toggle the trail on / off.
- F5 — switch the destination between Auto (game-driven: current extraction, or truck when all are complete) and Truck (forces the truck regardless of extraction state, for going back to charge items mid-run). Choice persists.
- F6 — open the customization panel: RGBA color sliders, hex input, color presets, and live sliders for dot size / flow speed / spacing. Edits write back to the BepInEx config so they persist across sessions.
What the DLL actually does
On plugin Awake(), it:
- Reads its config. A standard BepInEx config file (
BepInEx/config/isaia.repopathfinder.cfg) defines all hotkeys, dot visuals, animation tunables, and the path-recompute threshold. A[Internal] ConfigVersionkey migrates stale defaults from prior versions in place — values that exactly match a previous default get overwritten with the current default; user-customized values are left alone. - Creates a
DontDestroyOnLoadGameObject. Adds twoMonoBehaviours to it:PathfinderManager(path / animation / rendering) andPathfinderCustomizeUI(the F6 IMGUI overlay). - Installs Harmony input-blocking patches.
InputBlockeris gated on a single staticBlockInputflag flipped by the customize UI; it is inert when the menu is closed. While the menu is open, the following are short-circuited so cursor movement doesn't drive the camera and clicks don't fire weapons:- Legacy:
UnityEngine.Input.GetAxis,GetAxisRaw,GetMouseButton,GetMouseButtonDown,GetMouseButtonUp— return0f/false. - New:
UnityEngine.InputSystem.InputAction.ReadValue<T>()forVector2,float, andVector3— returndefault(T). Bound dynamically via reflection, so the plugin still loads if the new InputSystem assembly is absent. Input.GetKey/GetKeyDown/GetKeyUpare deliberately not patched, so F4 / F5 / F6 keep working.
- Legacy:
Path computation
The path is cached in world space, not recomputed every frame:
- Target resolution. Auto mode:
RoundDirector.allExtractionPointsCompleted(read by reflection) →LevelGenerator.LevelPathTruck.transform.position; otherwiseRoundDirector.extractionPointCurrent.transform.position. Truck mode: alwaysLevelPathTruck. Identity is theExtractionPointreference or the literal string"truck". - Recompute trigger. A new path is computed only when:
- There is no cached path yet,
- The target identity changed (different extraction, or Auto↔Truck flip),
- The player has drifted further than
OffPathRecomputeThresholdMeters(default3.0) from the cached polyline (closest-point-on-line-segment over each cached segment), or - A scene change invalidated the cache.
- Compute & cache.
NavMesh.CalculatePath(playerNavmeshPos, targetPos, AllAreas, path)is called once. The corners and prefix arc-distances are stored; the displayed dots reference these stable world-space points for as long as the cache lives.playerNavmeshPosisPlayerAvatar.LastNavmeshPosition(read by reflection — internal field). - Each frame. The player is projected onto the cached polyline to produce a
playerArcscalar; that's the trail's "back end". Walking forward changes onlyplayerArc; the cached corners are untouched, so dot world positions stay stable regardless of how the player moves.
Animation & rendering
- A pool of
MaxDots(default 30) sphere primitives, colliders stripped, sharing one material with per-dot color set viaMaterialPropertyBlock. - A single shared
_animOffset∈ [0, spacing) advances byFlowSpeedm/s. When it crossesspacingthe circular pool pointer_frontPooldecrements, which makes every sphere's slot index increment by 1 simultaneously. Spacing stays perfectly even regardless of howavailableLength = totalLength - playerArcchanges. - The single sphere whose slot wraps from
MaxDots-1to0per cycle has its smoothing flag cleared in the same step, so it snaps to its new position at the player end of the trail instead of being lerped across the room. - World position per dot:
CachedPointAtDistance(playerArc + slot*spacing + animOffset), plusGroundOffseton Y. The result is exponentially smoothed toward the displayed position with ratePositionSmoothRate(default251/s) for the rare cases where the path is re-cached. - Alpha fade per dot:
min(SmoothStep(0..fadeZone, d), SmoothStep(0..fadeZone, endpoint-d))whered = slot*spacing + animOffset,endpoint = min(availableLength, MaxDots*spacing),fadeZone = spacing * FadeZoneFraction. Hides the wrap and the path's own ends behind alpha-0 transitions. - Material shader is resolved at runtime via
Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard")._ZWrite0 andSrcAlpha/OneMinusSrcAlphablend are set if the chosen shader exposes those properties; render queue is3500.
Customization UI
PathfinderCustomizeUI (default F6) is a draggable GUILayout.Window:
- RGBA sliders (0–255 readout),
#RRGGBBAAtext field with Apply, preview swatch over a white underlay so transparency is obvious, eight color presets. - Sliders for
DotScale,FlowSpeedMetersPerSec,SpacingMeters. - Reset Visuals writes each of the above ConfigEntries back to its
DefaultValue. Close dismisses the panel. - All edits go straight to the BepInEx ConfigEntries.
PathfinderManagersubscribes toDotColorHex.SettingChangedso the cached_baseColorrefreshes the moment a slider moves; size / flow / spacing are read from config every frame and update for free. - On open: cached
Cursor.lockStateandCursor.visibleare saved, then forced toNone/trueso the cursor is interactable. On close: the saved values are restored.InputBlocker.BlockInputis flipped in lockstep with visibility.
Install
Thunderstore Mod Manager: click Install. Manual: drop REPOPathfinder.dll into <profile>/BepInEx/plugins/REPOPathfinder/. Requires BepInEx-BepInExPack.
Compatibility
- Client-side. The plugin is purely local: it reads
PlayerController.instance.playerAvatarScript,RoundDirector.instance, andLevelGenerator.Instanceto compute its own path and renders its own GameObjects. No RPCs, no Photon traffic. Each player can install independently; nothing about the plugin requires the host or other clients to have it. - No Harmony patches on REPO code. Harmony prefixes target only
UnityEngine.Input(legacy) andUnityEngine.InputSystem.InputAction.ReadValue<T>()(new). REPO's own classes are read via reflection (forinternalfields) but are never patched. - No NavMesh modifications. The plugin calls
NavMesh.CalculatePathfor itself; it does not bake or alter the game's NavMesh.
Changelog
0.7.2
- Ported the InputBlocker pattern from REPOBlacklist so dragging customize-panel sliders no longer rotates the camera or fires weapons. Harmony prefixes on legacy
Input.*axis / mouse-button reads and onInputAction.ReadValue<Vector2/float/Vector3>()(bound via reflection);GetKey*deliberately untouched so hotkeys still work.
0.7.1
- Fixed long-path "conveyor belt" rubber-banding: when
activeCount == MaxDots, the wrapping dot's slot transitionedMaxDots-1 → 0while staying inside the visible branch, so the smoothing lerp animated it across the entire trail length. The frontPool decrement now also clears_wasVisiblefor the pool index that just wrapped, forcing a snap.
0.7.0
- Added the F6 customization UI: RGBA sliders, hex input, eight color presets, dot-size / flow-speed / spacing sliders, Reset Visuals, all live-bound to the BepInEx ConfigEntries.
PathfinderManagersubscribes toDotColorHex.SettingChangedand refreshes its cached_baseColorimmediately, so dragging color sliders updates world dots on the same frame.
0.6.0
- Added F5 destination toggle: Auto (game-driven extraction → truck) and Truck (force truck regardless of extraction state). Mode is persisted as a
PathfinderTargetModeConfigEntry. Cache invalidated on toggle so the trail re-orients on the next frame.
0.5.0
- Replaced per-frame recompute with a cached path + per-frame player projection. Path is recomputed only on target identity change or when the player drifts more than
OffPathRecomputeThresholdMetersfrom the cached polyline. Walking forward / backward along the path no longer translates dot world positions at all — the dots are nailed to absolute world coordinates; only their visibility shifts as the player walks past them. RecalcIntervalSecondsis now deprecated and ignored.
0.4.0
- Added per-dot exponential-decay smoothing on world positions (
PositionSmoothRate, default 25)._wasVisibleflags reset on every path recompute and on hidden→visible transitions so wraps still snap rather than draw a curved interpolation across geometry.
0.3.0
- Replaced per-dot independent
d %= trailExtentwrap with a shared_animOffsetplus circular pool pointer_frontPool. Spacing now stays perfectly even regardless of howavailableLengthchanges; previously a moving modulo divisor could shake dots off the spacing grid. - Added config-version migration: stale
DotColorHex/DotScaledefaults from 0.1 / 0.2 are overwritten with the new defaults; user-customized values are preserved.
0.2.0
- Added continuous flow animation:
_animOffsetadvances every frame and the trail recycles continuously instead of populating-then-disappearing in waves. - Switched per-dot color updates to a single shared material plus
MaterialPropertyBlockfor alpha fade. - Smaller / more translucent default dot visuals.
0.1.0
- Initial implementation: F4 toggle, NavMesh path computation from
PlayerAvatar.LastNavmeshPositiontoRoundDirector.extractionPointCurrent(orLevelGenerator.LevelPathTruckwhen all extractions are complete), primitive sphere pool withSprites/Defaultmaterial at render queue 3500.