Skip to main content
Unofficial Guild Wars Reforged App — a fan project, not affiliated with ArenaNet or NCSoft

UR-09: the cursor is not re-tested after a mode change

A salvage or identification kit hides the cursor at once, but the targeting cursor appears only on the next pointer input. Measured gaps reach 1,795 ms.

When the player uses an item that starts a targeting mode, the client hides the cursor at once, but the targeting cursor appears only on the next pointer input — or on the client's idle hover cadence. With the pointer held still, the player sees no cursor at all for up to two seconds.

Fix: low effort, small blast radius — one call at the point where the client already handles the acknowledgement, and one extra hit-test per mode change adds no measurable cost.

Build used for the measurements below: 38797.

What we measured

We used a salvage kit and an identification kit, held the pointer still, and measured the gap between the cursor hide and the new cursor:

RunGap
1183 ms
21,266 ms
31,795 ms

The three runs used the same action on the same build. The spread is consistent with this sequence: the server round-trip completes, and the cursor decision then waits for the idle cycle.

The probe

We dispatched a synthetic mousemove pair with zero distance after the gap, and the cursor resolved at once — this is how our host works around the defect. Dispatching the same pair one frame after the click instead returned the hidden cursor.

So the client re-tests the pointer whenever something asks it to, but the mode isn't resolved until the server acknowledges the action.

Expected behaviour

After the acknowledgement that completes a mode change, run the pointer hit-test once, without waiting for pointer input or the idle cycle.

Where we think the call belongs
We didn't locate the acknowledgement handler in the module, so we won't name a function. In source, the right place is the handler that completes the mode change, next to the code that already updates cursor state.

Acceptance criteria

  • The player uses a salvage kit and holds the pointer still. The targeting cursor appears within one frame after the server acknowledgement.
  • The same result occurs for an identification kit.
  • The same result occurs when the player cancels the mode.
  • No extra hit-test runs while no mode change occurs. The idle cadence does not change.
  • The cursor does not flicker between the hide and the new cursor.

How to reproduce

Prepare

Log in. Put a salvage kit in the inventory. Put a salvageable item next to it.

Start the mode

Click the salvage kit. Do not move the mouse.

Observe

The cursor disappears. Wait. The targeting cursor appears after a delay of up to about two seconds.

Compare

Repeat the test, and move the mouse one pixel after the click. The targeting cursor appears at once.

Our workaround today

The host watches for two conditions: a click that produced no cursor event, and a hidden cursor state right after a click. In both cases it dispatches one synthetic out-and-back mousemove pair at the last click position — the physical pointer doesn't move — retrying every 150 ms for up to 2,500 ms. During that window the host holds the last visible cursor image instead of an empty cursor.

This workaround needs our native-cursor feature
The replay only works when the host can read the client's cursor state, which needs a certified client build. On a build we haven't certified, the player gets the raw defect.

A client-side hit-test after the acknowledgement retires the whole replay.

GWonMac

Play Guild Wars on your Mac. GWonMac runs ArenaNet's official client natively on Apple Silicon — free, open source, signed and notarized.

© GWonMac. All rights reserved.