diff --git a/src/client/WebGLFrameBuilder.ts b/src/client/WebGLFrameBuilder.ts index e7d99cc1f..72aec8b3b 100644 --- a/src/client/WebGLFrameBuilder.ts +++ b/src/client/WebGLFrameBuilder.ts @@ -134,12 +134,9 @@ export class WebGLFrameBuilder { const spawnTile = p.state.spawnTile; if (spawnTile === undefined) continue; const isSelf = me !== null && p.smallID() === me.smallID(); - // myPlayer reads as a near-white with a faint gold/silver tint so the - // local-player ring is visually distinct from any team color; everyone - // else uses their territory tint. - const c = isSelf - ? { r: 248, g: 218, b: 140 } - : p.territoryColor().toRgb(); + // myPlayer's ring color is overridden in SpawnOverlayPass (animated + // white→gold pulse); everyone else uses their territory tint. + const c = p.territoryColor().toRgb(); centers.push({ // spawnTile tracks the player's currently-selected spawn directly — // updates the same tick the player picks a new location (faster than diff --git a/src/client/render/gl/passes/SpawnOverlayPass.ts b/src/client/render/gl/passes/SpawnOverlayPass.ts index 99f446d55..50b995c48 100644 --- a/src/client/render/gl/passes/SpawnOverlayPass.ts +++ b/src/client/render/gl/passes/SpawnOverlayPass.ts @@ -150,9 +150,17 @@ export class SpawnOverlayPass { const c = this.centers[i]; dataA[i * 4 + 0] = c.x; dataA[i * 4 + 1] = c.y; - dataA[i * 4 + 2] = c.r; - dataA[i * 4 + 3] = c.g; - dataB[i * 4 + 0] = c.b; + if (c.isSelf) { + // Self ring pulses white (1,1,1) → gold (1,0.84,0) in phase with the + // breath so one end of the pulse always contrasts with the terrain. + dataA[i * 4 + 2] = 1; + dataA[i * 4 + 3] = 1 - 0.16 * breathRadius; + dataB[i * 4 + 0] = 1 - breathRadius; + } else { + dataA[i * 4 + 2] = c.r; + dataA[i * 4 + 3] = c.g; + dataB[i * 4 + 0] = c.b; + } dataB[i * 4 + 1] = c.isSelf ? 1 : 0; dataB[i * 4 + 2] = c.isTeammate ? 1 : 0; dataB[i * 4 + 3] = 0;