From 83cf10495e68dc9cb6ab73360299da0ae71ff488 Mon Sep 17 00:00:00 2001 From: Jacob Babor Date: Sat, 27 Jun 2026 04:20:40 -0500 Subject: [PATCH] Add RED4ext release packaging --- .gitignore | 1 + README.md | 221 ++++++++++++++++------------- docs/compaction-handoff.md | 9 ++ packaging/EdgeWeightGPS-README.txt | 25 ++++ tools/install_red4ext_shim.sh | 4 + tools/package_red4ext_mod.sh | 24 ++++ 6 files changed, 188 insertions(+), 96 deletions(-) create mode 100644 packaging/EdgeWeightGPS-README.txt create mode 100755 tools/package_red4ext_mod.sh diff --git a/.gitignore b/.gitignore index 868c171..6c7337d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ __pycache__/ /work/ /work-*.txt /build/ +/dist/ /vendor/ /scratch/ diff --git a/README.md b/README.md index dbcadf5..31505b7 100644 --- a/README.md +++ b/README.md @@ -1,108 +1,137 @@ -# 2077 Edge Weight Mod +# EdgeWeightGPS -Experimental Cyberpunk 2077 GPS route-weighting mod tooling. +Cyberpunk 2077 RED4ext plugin that improves player GPS routing by penalizing +short-segment churn in the native GPS solver. The current validated default +pushes the GPS toward smoother, higher-momentum driving corridors without +globally forcing every route onto highways. -## Feasibility +## Current Status -Cyberpunk exposes a native `gamegpsGPSSystem`, but the current public RTTI dump does -not expose script-callable methods for replacing or overriding the GPS planner. The -useful surfaces are generated traffic resources: +Working prototype, validated in-game. -- `worldTrafficPersistentResource.data.lanes` -- `worldTrafficLanePersistent.length` -- `worldTrafficLanePersistent.maxSpeed` -- `worldTrafficLanePersistent.flags` -- `worldTrafficLanePersistent.playerGPSInfo` -- `worldTrafficPersistentLaneConnectionsResource.data` -- `worldTrafficConnectivityOutLane.exitProbabilityCompressed` -- `worldTrafficConnectivityOutLane.isSharpAngle` -- `worldTrafficLanePersistentFlags.Highway` -- `worldTrafficLanePersistentFlags.GPSOnly` +- Route scoring patch: enabled. +- Live tuning file: enabled. +- Current default fixed-edge penalty: `80.0`. +- Highway multiplier: neutral `1.0`; the earlier highway-speed/class + experiments are not part of the playable default. -The in-game GPS path is computed natively over generated traffic graph data. A -full replacement planner would require native hooks or patching the game -executable. A feasible REDmod-style mod has to patch generated graph resources -and test which fields the native planner actually consumes. - -## Current Implementation - -Current active work is a RED4ext shim under `red4ext/EdgeWeightGPS`. It has -confirmed the world-map GPS route path runs through the native async traffic -route pipeline, not the script-facing `RunGPSQuery`/`UpdateGPSQuery` helpers. -The shim can log the query lifecycle, async traffic result handoff, and route -postprocess stages. - -A later spatial edge-cost prototype hooked the native local GPS edge-cost -callback at `0x44f838` and successfully changed thousands of candidate edge -costs in live route-producer calls. A controlled in-game inversion test still -produced byte-identical final `GPSQueryResultFetch` route records before and -after flipping highway weights from nearly free to extremely expensive. Treat -that hook as a useful local-search diagnostic, not the final player GPS -weighting surface. - -An experimental traffic candidate scorer hook at RVA `0x8d46cc` proved the game -does consult traffic lane flags while selecting route/projection candidates: -highway, road, and pavement flags were visible live and the hook changed their -scores. That detour currently crashes during load, so it is disabled by default -in source and disabled in the local game install as `EdgeWeightGPS.dll.disabled`. -It should be treated as evidence and an RE lead, not a playable mod. - -The older data-only tooling remains in the repo for reference: - -This repo currently contains WolvenKit-export patchers: - -```bash -python3 tools/patch_traffic_lanes.py exported-json-dir patched-json-dir -python3 tools/patch_lane_connections.py all.traffic_persistent.json all.lane_connections.json patched.lane_connections.json -``` - -`patch_traffic_lanes.py` recursively scans WolvenKit JSON exports for `lanes` -arrays that look like `worldTrafficLanePersistent` data and applies configurable -speed weighting: - -- highways get boosted toward a preferred GPS speed in the game's lane scale -- regular roads keep a moderate speed floor -- pavement, crosswalk, and disabled traffic lanes are left alone -- optional non-highway speed caps can make highways more attractive - -In-game testing disproved `maxSpeed` as the main GPS routing lever: even highway -speed `120` did not change GPS routes, although freeway traffic visibly moved -faster. Treat speed patches as traffic simulation experiments, not route -weighting. - -`patch_lane_connections.py` patches `all.lane_connections` by raising -highway-enter/stay edge probabilities and lowering competing non-highway exits. -That candidate loaded in game, but live testing did not show a GPS routing -change. - -After patching, deserialize the JSON back into CR2W and pack the resulting -resources into an archive. - -The toolbox now has WolvenKit CLI installed: - -```bash -toolbox run --container 2077 bash -lc '$HOME/.dotnet/tools/cp77tools --help' -``` - -See [docs/tooling.md](docs/tooling.md) for the end-to-end archive build flow. -See [docs/traffic-system-debrief.md](docs/traffic-system-debrief.md) for the -detailed feasibility and traffic graph notes. - -## Status - -A conservative speed archive, an aggressive speed archive, and a connection -probability archive were built from the local Flatpak Steam Phantom Liberty -install. All `zz_edge` archives are currently disabled in the game folder. - -The RED4ext plugin is also currently disabled for normal play: +The active package is a RED4ext plugin only: ```text -Cyberpunk 2077/red4ext/plugins/EdgeWeightGPS/EdgeWeightGPS.dll.disabled +red4ext/plugins/EdgeWeightGPS/EdgeWeightGPS.dll +red4ext/plugins/EdgeWeightGPS/momentum_weights.bin +red4ext/plugins/EdgeWeightGPS/solver_weights.bin ``` +## What It Patches + +Reverse engineering found the player GPS route search loop around the native +solver relaxation cluster. The useful patch surface is not the script-facing +`RunGPSQuery`/`UpdateGPSQuery` helpers and not the generated traffic +`maxSpeed` fields. The playable hook patches the two ordinary adjacency +expansion sites feeding the native relax/update routine at `0x40ba58`. + +The plugin adds a nonnegative fixed cost to ordinary edge expansion. In +practice, this makes many tiny street segments and repeated 90-degree +stair-steps less attractive, while still allowing local roads when they are the +right path. + +## Validation Summary + +The default `80.0` penalty was selected after live A/B testing: + +- `0.0`: vanilla behavior; visibly stair-stepped in highlighted routes. +- `40.0`: partial improvement, but still missed useful smoother corridors. +- `80.0`: best observed result; selected smoother high-speed corridors and + passed drive testing. +- `160.0`: too high; caused bad hairpins/local access and one fallback-style + route. + +Drive validation at `80.0`: + +- The Dogtown route used a smoother highway corridor and drove cleanly at high + speed. +- Live minimap recalculation still worked after a deliberate detour. +- Claire/Westbrook route also drove cleanly; one blind hill/ramp surprise was + driver unfamiliarity, not a route failure. + +See [docs/gps-momentum-field-tests.md](docs/gps-momentum-field-tests.md) for +the detailed test notes, screenshots, and log references. + +## Build + +Build in the Fedora toolbox: + +```bash +toolbox run -c 2077 ./tools/build_red4ext_shim.sh +``` + +This writes: + ```text -Cyberpunk 2077/archive/pc/mod/zz_edge_weight_gps_highway_probability.archive.disabled +build/red4ext/EdgeWeightGPS-mingw64/EdgeWeightGPS.dll ``` -Build outputs are ignored by git. Experimental archives and RED4ext DLL builds -should be enabled one at a time and tested from a cold boot. +## Install Locally + +Only install while the game is cold. + +```bash +toolbox run -c 2077 ./tools/install_red4ext_shim.sh +``` + +The install script builds the DLL, installs it into the Flatpak Steam Cyberpunk +2077 folder, and writes the validated defaults: + +- `momentum_weights.bin = 80.0` +- `solver_weights.bin = 1.0` + +Override the game directory with `CYBERPUNK2077_GAME_DIR` if needed. + +## Package + +Create a redistributable RED4ext zip: + +```bash +toolbox run -c 2077 ./tools/package_red4ext_mod.sh +``` + +The package is written under `dist/` and contains the `red4ext/` folder layout +expected by the game. + +## Live Tuning + +`momentum_weights.bin` is a single little-endian float32 and is hot-reloaded +every 500 ms while the game is running. + +Useful presets: + +```bash +python3 tools/write_momentum_weights.py vanilla # 0.0 +python3 tools/write_momentum_weights.py default # 80.0 +python3 tools/write_momentum_weights.py overstrong # 160.0, known too high +``` + +`solver_weights.bin` is still present for older highway multiplier experiments, +but the playable default keeps it neutral: + +```bash +python3 tools/write_solver_weights.py vanilla # 1.0 +``` + +## Repository Notes + +This repository also contains older experiments and reverse-engineering tools: + +- REDmod/archive traffic resource patchers. +- Traffic lane and connection probability patchers. +- Static disassembly helpers. +- RED4ext logging probes. + +Those tools are retained because they explain the route-finding system and +document failed approaches, but they are not part of the current playable +package. The important debriefs are: + +- [docs/traffic-system-debrief.md](docs/traffic-system-debrief.md) +- [docs/red4ext-logging-shim.md](docs/red4ext-logging-shim.md) +- [docs/gps-routing-research.md](docs/gps-routing-research.md) diff --git a/docs/compaction-handoff.md b/docs/compaction-handoff.md index cc49a85..a7bf42e 100644 --- a/docs/compaction-handoff.md +++ b/docs/compaction-handoff.md @@ -21,6 +21,15 @@ Current date/time context: 2026-06-27, local timezone America/Chicago. recalculation worked after a detour, and the Claire route drove cleanly aside from a driver-unfamiliarity ramp/hill surprise. - Updated detailed notes in `docs/gps-momentum-field-tests.md`. +- The rebuilt source-default-80 DLL was installed while the game was cold at + about `04:17` local. Installed defaults were rewritten: + `momentum_weights.bin = 80.0`, `solver_weights.bin = 1.0`. +- Added release packaging: + `toolbox run -c 2077 ./tools/package_red4ext_mod.sh`. + Verified package: + `dist/EdgeWeightGPS-red4ext-20260627-041942.zip`, containing + `red4ext/plugins/EdgeWeightGPS/EdgeWeightGPS.dll`, + `momentum_weights.bin = 80.0`, and `solver_weights.bin = 1.0`. ## 2026-06-27 Live Momentum Knob Installed diff --git a/packaging/EdgeWeightGPS-README.txt b/packaging/EdgeWeightGPS-README.txt new file mode 100644 index 0000000..6a5a79a --- /dev/null +++ b/packaging/EdgeWeightGPS-README.txt @@ -0,0 +1,25 @@ +EdgeWeightGPS RED4ext package + +Install: +Copy the red4ext folder from this package into the Cyberpunk 2077 game folder. +The final layout should include: + + Cyberpunk 2077/red4ext/plugins/EdgeWeightGPS/EdgeWeightGPS.dll + Cyberpunk 2077/red4ext/plugins/EdgeWeightGPS/momentum_weights.bin + Cyberpunk 2077/red4ext/plugins/EdgeWeightGPS/solver_weights.bin + +Default tuning: + momentum_weights.bin = 80.0 fixed ordinary-edge penalty + solver_weights.bin = 1.0 neutral highway multiplier + +Notes: +The plugin changes player GPS route scoring by adding a fixed cost to ordinary +edge expansion in the native GPS solver. This favors smoother routes with fewer +short-segment stair-steps and was validated in-game on long highway routes, +City Center routes, and local Watson/Westbrook routes. + +Tuning: +momentum_weights.bin is a single little-endian float32 and is hot-reloaded while +the game is running. Set it to 0.0 to disable the fixed-edge penalty. Values +around 80.0 are the current validated default. 160.0 was tested and is too high: +it can trigger bad hairpins or fallback-style routing. diff --git a/tools/install_red4ext_shim.sh b/tools/install_red4ext_shim.sh index d3952dc..00e448a 100755 --- a/tools/install_red4ext_shim.sh +++ b/tools/install_red4ext_shim.sh @@ -8,5 +8,9 @@ plugin_out="$game_dir/red4ext/plugins/EdgeWeightGPS" dll_path="$("$repo_root/tools/build_red4ext_shim.sh" | tail -n 1)" mkdir -p "$plugin_out" install -m 0644 "$dll_path" "$plugin_out/EdgeWeightGPS.dll" +install -m 0644 "$repo_root/presets/momentum/default.bin" "$plugin_out/momentum_weights.bin" +install -m 0644 "$repo_root/presets/solver_weights/vanilla.bin" "$plugin_out/solver_weights.bin" printf 'Installed %s\n' "$plugin_out/EdgeWeightGPS.dll" +printf 'Installed %s\n' "$plugin_out/momentum_weights.bin" +printf 'Installed %s\n' "$plugin_out/solver_weights.bin" diff --git a/tools/package_red4ext_mod.sh b/tools/package_red4ext_mod.sh new file mode 100755 index 0000000..6f3b964 --- /dev/null +++ b/tools/package_red4ext_mod.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +timestamp="$(date +%Y%m%d-%H%M%S)" +staging="$repo_root/build/package/EdgeWeightGPS-$timestamp" +dist_dir="$repo_root/dist" +zip_path="$dist_dir/EdgeWeightGPS-red4ext-$timestamp.zip" + +dll_path="$("$repo_root/tools/build_red4ext_shim.sh" | tail -n 1)" +plugin_out="$staging/red4ext/plugins/EdgeWeightGPS" + +mkdir -p "$plugin_out" "$dist_dir" +install -m 0644 "$dll_path" "$plugin_out/EdgeWeightGPS.dll" +install -m 0644 "$repo_root/presets/momentum/default.bin" "$plugin_out/momentum_weights.bin" +install -m 0644 "$repo_root/presets/solver_weights/vanilla.bin" "$plugin_out/solver_weights.bin" +install -m 0644 "$repo_root/packaging/EdgeWeightGPS-README.txt" "$plugin_out/README.txt" + +( + cd "$staging" + python3 -m zipfile -c "$zip_path" red4ext +) + +printf '%s\n' "$zip_path"