Conversation
Github returns "body": null for a release published with no description text, which made Glaze fail the whole releases-array parse and silently broke the update check (the 8.30 release triggered this). Make the JSON body field std::optional in both the exe installer and the in-game dll updater, and have the release workflow extract the version's notes from history.md into the release body (with a non-empty fallback) so the API never returns a null body again. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The download-button version scanned releases?per_page=30 and filtered out drafts, but the build token has push access so GitHub returns the repo's 154 draft releases first, crowding every published release out of the page. The filtered list came back empty and the site silently served a stale fallback version. Use /releases/latest instead, which excludes drafts and prereleases by definition and tracks future releases without a config bump. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drive the shown condition through one eased 0..1 intensity: hold the current condition until it fades out, then swap and fade the new one back in, so a weather change reads as a brief lull rather than a hard pop. The same intensity rides the particle draw alpha, the ambient dimming, and newly spawned splash tints. Reset (loading/world map) starts the new condition from clear. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Skill icons and other dat images could stay blank for a session: - AcquireMapping matched only a handle literally named "Gw.dat" via a MAX_PATH buffer, so renamed/-dat-relocated archives and deep (>260 char) install paths were dropped. Match any ".dat" handle (MapDat's 3ANa magic still confirms it) using a length-sized path buffer, and record the bound path for diagnostics. - A decode that ran before the client's Gw.dat was mapped cached a null texture forever. Track pending/attempts and re-decode until a mapped-archive attempt settles the result. - Surface a one-time chat warning when the handle scan itself is blocked (usually AV/anti-cheat), plus log lines to make reports diagnosable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… update The loader's Windows Defender exception prompt reappears on every launch until the exclusion is actually added, which nags users who can't or won't elevate. Swap the Yes/No message box for a TaskDialog carrying a "Don't ask again until GWToolbox is updated" checkbox; when ticked, record the current build in HKCU\\Software\\GWToolbox and skip the prompt while that version runs, re-prompting automatically after an update. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…checkbox feat(defender): mute Windows Security prompt until next update
…loop The native reader parsed the on-disk MFT once, so files the client streamed in mid-session (a partial/streaming Gw.dat) stayed invisible and their icons blank. Make the reader pick them up, and move the work off the render thread. - GwDatArchive: guard the index with a shared_mutex so ReadFile is callable from any thread; on a miss, re-map the (grown) dat and re-parse the MFT, throttled and non-destructively (swap only on success). Factored the parse into AcquireMappingInto + ParseFrom; ReadRaw does the shared-locked lookup. - GwDatTextureModule: run the dat read + re-parse + ATEX/dye/greyscale decode on a Resources worker thread, uploading only via MakeTextureFromArgb on the DX thread. Retry a mapped-but-missing file over a ~60s window so a streamed file is caught. SaveTextureFromFileIdToFile (pure CPU) also moves to a worker. Needs an in-game validation pass: rests on the client flushing streamed files to the on-disk MFT within the retry window (not empirically measured). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Retrying missing-file decodes (up to the ~60s window) plus the occasional re-parse could crowd the shared 20-worker pool that also serves curl and wiki-image downloads. Give the dat module its own single worker thread that serialises reads/decodes (and the archive re-parse); the GPU upload still hops to the DX thread. Started in Initialize, stopped+joined in Terminate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keep dat-file concerns (mapping, MFT parse/re-parse, the dedicated worker thread) in GwDatArchive and leave only texture concerns (decode to ARGB, GPU upload, caching, retry window) in GwDatTextureModule. The archive now owns StartWorker/StopWorker/EnqueueTask; the texture module submits its decode task to it and drives its lifecycle from Initialize/Terminate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Conform the dat reader/texture module to the single-line comment guideline and trim repetition: factor the three loaders' find-or-create into a GetOrCreate helper, and use memcmp(kDatMagic) for the archive magic check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The world-map path/line overlay inlined its own world->screen transform and dropped the world_map_scale factor, so it only aligned when fully zoomed in. Route the line and navmesh blocks through the shared CalculateViewportPos helper instead, and make that helper animation-correct: derive a per-frame pixels-per-world-coord scale from the live visible rect (top_left..bottom_right, which the client re-derives every frame from the animating zoom) and the world-map frame's on-screen size, falling back to the rest-state factor until the client populates the rect. With projection now correct at every zoom level, drop the five "Map is animating" early-returns so quest/boss/area/portal overlays track the zoom animation too, and scale the boss capture icon smoothly (std::lerp 16->32) instead of snapping between two sizes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cross-map route was rendered only on the world map: QuestModule tags its world-coord tail segments draw_on_mission_map/minimap=false, and both the mission map and compass render their lines in game coords, which can't place other maps' positions. - Mission map: draw the world-coord route tails in an ImGui overlay via the existing WorldMapCoordsToMissionMapScreenPos, clipped to the widget, so the whole continent route shows (incl. the stretch past the nearest portal that the game-coord lines don't reach). Honors the existing mission-map toggle. - Compass: project world-coord tails back into current-map game space with WorldMapWidget::WorldMapToGamePos and feed the existing game-coord vertex path, so the route continues off toward the next map. Honors the minimap toggle. Also fix the mission-map pmap drop-shadow: the -100 VIEW-space offset lands in raw pixels under the mission map's game->px view (vs a small offset in the compass's zoomed space), so it was huge and didn't scale with zoom. Make the offset a MinimapRenderContext field (compass keeps the -100 default) and set it on the mission map from a small game-unit value scaled into pixels, so it stays subtle and tracks the mission-map zoom. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a dedicated Party Statistics page covering the skill-usage tracking, the display/print options, and that Ctrl+LeftClick (and /skillstats) output goes to team chat as text — nothing is saved to disk. Register it in the sidebar nav and point the /skillstats command link at it instead of the unrelated Party Window page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rename the agent instruction file to AGENTS.md so non-Claude agent models pick it up too; CLAUDE.md becomes a one-line pointer (@AGENTS.md import) so Claude Code still loads it. Tighten the existing sections to cut context tokens, and add an 'Answering feature questions' section: check whether a feature is documented (site/src/content/docs or the live https://www.gwtoolbox.com/docs/) before/while explaining it, and link the relevant page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
beam_width -> kBeamWidth = 35, z_lift -> kZLift = 5. Drops both sliders; render_max_distance and fog_factor remain configurable.
Replace magic 0x4/0x1400/0x83 literals with a SoundFlags enum. Values are cross-checked against the game's native sound dispatcher: several (Looping, NoHandle, Streaming, Positional) are confirmed straight from the binary rather than just inferred from toolbox call sites. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…maps Route builds re-evaluate their edge graph from scratch on every recompute, so a map that's permanently unreadable this session (missing pathfinding data on a partial/streaming dat install, or never visited/StoC-resolved) re-triggered the same DAT read attempt and re-logged the same error on every single route query. Cache both failure modes per map/file_id so each is only logged once. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Per AGENTS.md: comments explain why, one concise line, no prose blocks. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Per AGENTS.md: comments explain why, one concise line, no prose blocks. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Minimap: unify agent colors/sizes into the Custom Agents list
docs: add missing /noexecheck launch option
Get-MpPreference's ExclusionPath entries carry an inconsistent trailing separator versus our canonicalized folder path, so the prefix-match in ListCoversPath never matched and Toolbox kept nagging to add an exclusion that was already there. Also stop skipping verification for non-admin runs (Get-MpPreference doesn't require admin), so a real failure to add the exclusion is no longer silently reported as success. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…g-slash Fix repeated Defender exclusion prompt on already-excluded folders
The Launch button's height was hardcoded to match the character combo box's requested height, but Windows fixes a combo box's closed-state height from its font metrics regardless of what's passed to CreateWindowW, so they only lined up at some font sizes/DPI settings. The button now reads back the combo box's actual rendered rect and matches it exactly. Also opts the launcher into Per-Monitor-V2 DPI awareness (with a fallback for older Windows) and scales every hardcoded child-control layout constant by the real monitor DPI, so scaled displays get accurate layout instead of blurry bitmap-stretching.
Previously every failure (no GW process, wrong game, RVA/pattern error, antivirus-blocked memory, no valid character) popped its own MessageBoxW with bespoke Yes/No/Retry logic scattered across main.cpp. Now InjectWindow::AskInjectProcess always shows the single launcher window: on success it's the existing character selector, on failure it's a pink error box in the same slot with a Retry button that re-scans in place. The antivirus-blocked case gets a troubleshooting-guide link button, and the admin-restart button is reused across states via the same bottom-row slot. main.cpp's ~70-line reply-branch chain collapses to a single Cancel check. As a side effect, /quiet mode now actually suppresses all UI on error instead of still popping message boxes.
…k apply Replaces the blocking pre-launch MessageBox update prompts (one for the exe, one for the dll, each with their own Yes/No/Retry popups) with a status row in the launcher window, to the left of Settings. It shows "Checking..." while a background Github releases fetch runs (non-blocking - character selection or error display above it is unaffected), then "Updates available!" with an Update button if either the exe or dll is stale. Clicking Update reuses the existing DownloadWindow progress-bar dialog to install whichever of the two need it in one pass, with no extra popups. The exe replacement goes through the same rename-swap dance as before (Windows won't let a running exe be overwritten) but no longer force-restarts the launcher - the new exe just takes effect next launch, while the dll is live immediately for the injection about to happen. Also fixes a latent bug: AsyncRestClient asserts it isn't mid-request when destroyed, so UpdateChecker now aborts a still-pending check if the user launches before it finishes.
…for non-installed exe Opening the diagnostic log file at the top of WinMain used to show a blocking MessageBoxW and abort the entire launch (return 0) on failure. Since this happens before any install/Defender work, a fresh exe sitting in a CFA-protected folder (Documents, Desktop, ...) could never even get past this point on first run. Now it's non-fatal: falls back to %TEMP%, logging a PathDiagnoseWritability diagnosis of the original failure, and if even that fails, just continues without file logging - it was never load-bearing for functionality. Also closes a gap in the pre-injection Controlled Folder Access check: it only ever CFA-allowed the *installed* copy of GWToolbox.exe, not whichever copy is actually running. A freshly-downloaded, not-yet-installed exe (e.g. run with /noinstall) never got itself added to the allow-list. Now both paths are added, mirroring what Install() already does.
UpdateChecker::ApplyUpdates() went straight to downloading and writing the exe/dll with no readiness check first, unlike Install() which explicitly grants exceptions before it writes. The pre-injection check in main.cpp can't cover this either, since clicking Update happens entirely inside InjectWindow, before that check ever runs. The write here is also done by the launcher exe itself (replacing its own .exe and/or the dll), not by Gw.exe, so the CFA-allowed-apps entry needed is for GWToolbox.exe. Call EnsureDefenderReadiness() first, CFA-allowing whichever exe path(s) are about to be replaced (or the running exe for a dll-only update), so a real permissions gap now surfaces as the existing "Add Windows Security exceptions?" prompt instead of a dead-end write error.
Dying in first-person then resurrecting could leave the camera's pitch_to_go NaN (the death-orbit -> follow-cam transition clamps pitch against the wrong limits and pushes it out of its valid [-1,1] range). The NaN eases into pitch and then the eye position, and the game's terrain line-of-sight ray-march (Gw.exe @0x0070eb40) only exits on an ordered float compare, so a NaN coordinate makes it loop forever and the render thread hangs until you die again. Hook the per-frame camera-eye read (Gw.exe @0x004f7b80, asserts "*fov != 0.0f") and clamp pitch/pitch_to_go back into [-1,1] (NaN -> 0), sanitizing a NaN eye position, before the renderer and ray-march consume the camera. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add an Enabled checkbox per weather condition, shown as [Disabled] in the collapsed header when off. Disabled conditions are excluded from manual toggling, automatic weather rolls, and the /weather chat command. Fog now defaults to disabled since it's quite invasive to gameplay, which lets the Weather module itself default to enabled.
Member
Author
|
@claude please update history.md with all the changes in this PR that aren't listed under 8.31 release section yet. |
|
Claude finished @henderkes's task in 8m 12s —— View job • Updating history.md for 8.31 release
Added 13 new entries to the New features added:
Fixes/minor added:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.