mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:20:47 +00:00
fix(render): turn nuke range circle red when launch would break alliance
Wire targetingAlly through GhostPreviewData.rangeWarning so RangeCirclePass can color the blast-radius circle red instead of white when the ghosted nuke would trigger a traitor penalty. Restores behavior lost in the canvas→WebGL migration.
This commit is contained in:
@@ -163,18 +163,13 @@ export class BuildPreviewController implements Controller {
|
||||
}
|
||||
}
|
||||
|
||||
// targetingAlly is computed above for state purposes; the renderer's
|
||||
// ghost passes derive their own "warning" visual from canBuild/canUpgrade
|
||||
// if needed. (Leave the variable here so its eslint-no-unused doesn't trip.)
|
||||
void targetingAlly;
|
||||
|
||||
this.game
|
||||
?.myPlayer()
|
||||
?.buildables(tileRef, [this.ghostUnit?.buildableUnit.type])
|
||||
.then((buildables) => {
|
||||
if (!this.ghostUnit) {
|
||||
this.pendingConfirm = null;
|
||||
this.emitGhostPreview(tileRef);
|
||||
this.emitGhostPreview(tileRef, targetingAlly);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -187,7 +182,7 @@ export class BuildPreviewController implements Controller {
|
||||
canUpgrade: false,
|
||||
});
|
||||
this.pendingConfirm = null;
|
||||
this.emitGhostPreview(tileRef);
|
||||
this.emitGhostPreview(tileRef, targetingAlly);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -201,7 +196,7 @@ export class BuildPreviewController implements Controller {
|
||||
}
|
||||
}
|
||||
|
||||
this.emitGhostPreview(tileRef);
|
||||
this.emitGhostPreview(tileRef, targetingAlly);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -211,8 +206,11 @@ export class BuildPreviewController implements Controller {
|
||||
* the ghost can't be placed. smoothLoop interpolates displayed position
|
||||
* toward the target tile each frame.
|
||||
*/
|
||||
private emitGhostPreview(tileRef: TileRef | undefined): void {
|
||||
const data = this.buildGhostPreviewData(tileRef);
|
||||
private emitGhostPreview(
|
||||
tileRef: TileRef | undefined,
|
||||
targetingAlly: boolean,
|
||||
): void {
|
||||
const data = this.buildGhostPreviewData(tileRef, targetingAlly);
|
||||
if (data === null) {
|
||||
this.lastGhostData = null;
|
||||
this.view.updateGhostPreview(null);
|
||||
@@ -302,6 +300,7 @@ export class BuildPreviewController implements Controller {
|
||||
|
||||
private buildGhostPreviewData(
|
||||
tileRef: TileRef | undefined,
|
||||
targetingAlly: boolean,
|
||||
): GhostPreviewData | null {
|
||||
if (!this.ghostUnit) return null;
|
||||
if (tileRef === undefined) return null;
|
||||
@@ -352,6 +351,7 @@ export class BuildPreviewController implements Controller {
|
||||
ownerID: myPlayer.smallID(),
|
||||
upgradeTargetTile,
|
||||
rangeRadius,
|
||||
rangeWarning: targetingAlly,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* RangeCirclePass — draws a translucent white circle showing the effective
|
||||
* range of a structure during build-mode ghost preview.
|
||||
* RangeCirclePass — draws a translucent circle showing the effective
|
||||
* range of a structure during build-mode ghost preview. White by default,
|
||||
* red when the ghost flags a warning (e.g. nuking would break an alliance).
|
||||
*
|
||||
* Single quad with circle SDF in the fragment shader.
|
||||
* Active only when a ghost preview with rangeRadius > 0 is set.
|
||||
@@ -20,10 +21,12 @@ export class RangeCirclePass {
|
||||
private uCamera: WebGLUniformLocation;
|
||||
private uCenter: WebGLUniformLocation;
|
||||
private uRadius: WebGLUniformLocation;
|
||||
private uColor: WebGLUniformLocation;
|
||||
|
||||
private centerX = 0;
|
||||
private centerY = 0;
|
||||
private radius = 0;
|
||||
private warning = false;
|
||||
|
||||
constructor(gl: WebGL2RenderingContext) {
|
||||
this.gl = gl;
|
||||
@@ -32,6 +35,7 @@ export class RangeCirclePass {
|
||||
this.uCamera = gl.getUniformLocation(this.program, "uCamera")!;
|
||||
this.uCenter = gl.getUniformLocation(this.program, "uCenter")!;
|
||||
this.uRadius = gl.getUniformLocation(this.program, "uRadius")!;
|
||||
this.uColor = gl.getUniformLocation(this.program, "uColor")!;
|
||||
|
||||
// Unit quad [0,1]
|
||||
this.vao = gl.createVertexArray()!;
|
||||
@@ -53,8 +57,10 @@ export class RangeCirclePass {
|
||||
this.centerX = data.tileX;
|
||||
this.centerY = data.tileY;
|
||||
this.radius = data.rangeRadius;
|
||||
this.warning = data.rangeWarning;
|
||||
} else {
|
||||
this.radius = 0;
|
||||
this.warning = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +72,11 @@ export class RangeCirclePass {
|
||||
gl.uniformMatrix3fv(this.uCamera, false, cameraMatrix);
|
||||
gl.uniform2f(this.uCenter, this.centerX, this.centerY);
|
||||
gl.uniform1f(this.uRadius, this.radius);
|
||||
if (this.warning) {
|
||||
gl.uniform3f(this.uColor, 1.0, 0.2, 0.2);
|
||||
} else {
|
||||
gl.uniform3f(this.uColor, 1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
gl.bindVertexArray(this.vao);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
|
||||
@@ -4,6 +4,7 @@ precision highp float;
|
||||
in vec2 vLocal; // [-1, +1]
|
||||
|
||||
uniform float uRadius;
|
||||
uniform vec3 uColor;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
@@ -23,5 +24,5 @@ void main() {
|
||||
float alpha = fill * 0.2 + stroke * 0.5;
|
||||
if (alpha < 0.001) discard;
|
||||
|
||||
fragColor = vec4(1.0, 1.0, 1.0, alpha);
|
||||
fragColor = vec4(uColor, alpha);
|
||||
}
|
||||
|
||||
@@ -166,6 +166,8 @@ export interface GhostPreviewData {
|
||||
upgradeTargetTile: number | null;
|
||||
/** Range radius in tiles for the placement circle (0 = no circle). */
|
||||
rangeRadius: number;
|
||||
/** True if placing here would carry a penalty (e.g. nuking an ally → traitor). */
|
||||
rangeWarning: boolean;
|
||||
}
|
||||
|
||||
/** Nuke trajectory preview data — Bezier control points + color thresholds. */
|
||||
|
||||
Reference in New Issue
Block a user