mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-23 22:05:24 +00:00
feat/highlight the owner of hovered naval units (#4610)
Resolves #4445 ## Description: Changes HoverHighlightController.ts to check for naval units if the mouse is not currently hovering over land. It then highlights the owner of the closest naval unit within 50px of the mouse. The activation radius feels a little to large right now, but it is consistent with the PlayerInfoOverlay functionality. Some input would be appreciated It is also currently disabled by default, not sure if this should be the case. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory ## Please put your Discord username so you can be contacted if a bug or regression is found: unne27 https://github.com/user-attachments/assets/7b8262e5-a097-44c8-b2ae-1ac336466623 <img width="534" height="901" alt="image" src="https://github.com/user-attachments/assets/50e9e126-08a6-4a24-9c26-cd4099a2603e" /> --------- Co-authored-by: unne27 <>
This commit is contained in:
@@ -9,12 +9,13 @@
|
||||
*/
|
||||
|
||||
import { EventBus } from "../../core/EventBus";
|
||||
import { UnitType } from "../../core/game/Game";
|
||||
import { Controller } from "../Controller";
|
||||
import { MouseMoveEvent } from "../InputHandler";
|
||||
import { MapRenderer } from "../render/gl";
|
||||
import { OWNER_MASK } from "../render/gl/utils/TileCodec";
|
||||
import { TransformHandler } from "../TransformHandler";
|
||||
import { GameView } from "../view";
|
||||
import { GameView, UnitView } from "../view";
|
||||
|
||||
export class HoverHighlightController implements Controller {
|
||||
private lastOwnerID = 0;
|
||||
@@ -30,16 +31,47 @@ export class HoverHighlightController implements Controller {
|
||||
this.eventBus.on(MouseMoveEvent, (e) => this.onMouseMove(e));
|
||||
}
|
||||
|
||||
private navalHighlightEnabled(): boolean {
|
||||
return this.view.getSettings().mapOverlay.navalHighlight;
|
||||
}
|
||||
|
||||
private onMouseMove(e: MouseMoveEvent): void {
|
||||
const world = this.transformHandler.screenToWorldCoordinatesFloat(e.x, e.y);
|
||||
this.view.setMouseWorldPos(world.x, world.y);
|
||||
|
||||
const cell = this.transformHandler.screenToWorldCoordinates(e.x, e.y);
|
||||
let ownerID = 0;
|
||||
if (this.game.isValidCoord(cell.x, cell.y)) {
|
||||
const ref = this.game.ref(cell.x, cell.y);
|
||||
ownerID = this.game.tileState(ref) & OWNER_MASK;
|
||||
if (!this.game.isValidCoord(cell.x, cell.y)) {
|
||||
if (this.lastOwnerID !== 0) {
|
||||
this.lastOwnerID = 0;
|
||||
this.view.setHighlightOwner(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let ownerID = 0;
|
||||
|
||||
const ref = this.game.ref(cell.x, cell.y);
|
||||
if (this.game.isLand(ref)) {
|
||||
ownerID = this.game.tileState(ref) & OWNER_MASK;
|
||||
} else if (this.navalHighlightEnabled()) {
|
||||
// Avoid square root for performance; 50 tile radius = 2500 tiles²
|
||||
let closestUnit: UnitView | null = null;
|
||||
let closestDistSquared = 2500;
|
||||
for (const u of this.game.units(
|
||||
UnitType.Warship,
|
||||
UnitType.TradeShip,
|
||||
UnitType.TransportShip,
|
||||
)) {
|
||||
const distSquared = this.game.euclideanDistSquared(ref, u.tile());
|
||||
if (distSquared < closestDistSquared) {
|
||||
closestDistSquared = distSquared;
|
||||
closestUnit = u;
|
||||
}
|
||||
}
|
||||
if (closestUnit !== null) {
|
||||
ownerID = closestUnit.owner().smallID();
|
||||
}
|
||||
}
|
||||
|
||||
if (ownerID === this.lastOwnerID) return;
|
||||
this.lastOwnerID = ownerID;
|
||||
this.view.setHighlightOwner(ownerID);
|
||||
|
||||
@@ -297,6 +297,17 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
private currentNavalHighlight(): boolean {
|
||||
return (
|
||||
this.userSettings.graphicsOverrides().mapOverlay?.navalHighlight ??
|
||||
renderDefaults.mapOverlay.navalHighlight
|
||||
);
|
||||
}
|
||||
|
||||
private onToggleNavalHighlight() {
|
||||
this.patchMapOverlay({ navalHighlight: !this.currentNavalHighlight() });
|
||||
}
|
||||
|
||||
private currentHighlightFill(): number {
|
||||
return (
|
||||
this.userSettings.graphicsOverrides().mapOverlay?.highlightFillBrighten ??
|
||||
@@ -692,6 +703,7 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
|
||||
const classicIcons = this.currentClassicIcons();
|
||||
const classicNumbers = this.currentClassicNumbers();
|
||||
const showDots = this.currentShowDots();
|
||||
const navalHighlight = this.currentNavalHighlight();
|
||||
const highlightFill = this.currentHighlightFill();
|
||||
const highlightBrighten = this.currentHighlightBrighten();
|
||||
const highlightThicken = this.currentHighlightThicken();
|
||||
@@ -1040,6 +1052,29 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
|
||||
${translateText("graphics_setting.section_map")}
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
|
||||
@click=${this.onToggleNavalHighlight}
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="font-medium">
|
||||
${translateText(
|
||||
"graphics_setting.naval_hover_highlight_label",
|
||||
)}
|
||||
</div>
|
||||
<div class="text-sm text-slate-400">
|
||||
${translateText(
|
||||
"graphics_setting.naval_hover_highlight_desc",
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-slate-400">
|
||||
${navalHighlight
|
||||
? translateText("user_setting.on")
|
||||
: translateText("user_setting.off")}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div
|
||||
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
|
||||
>
|
||||
|
||||
@@ -24,6 +24,7 @@ export const GraphicsOverridesSchema = z
|
||||
.partial(),
|
||||
mapOverlay: z
|
||||
.object({
|
||||
navalHighlight: z.boolean(),
|
||||
highlightFillBrighten: z.number(),
|
||||
highlightBrighten: z.number(),
|
||||
highlightThicken: z.number(),
|
||||
|
||||
@@ -47,6 +47,9 @@ export function applyGraphicsOverrides(
|
||||
// triggers — structures stay as full icons at every zoom level.
|
||||
settings.structure.dotsZoomThreshold = 0;
|
||||
}
|
||||
if (overrides.mapOverlay?.navalHighlight !== undefined) {
|
||||
settings.mapOverlay.navalHighlight = overrides.mapOverlay.navalHighlight;
|
||||
}
|
||||
if (overrides.mapOverlay?.highlightFillBrighten !== undefined) {
|
||||
settings.mapOverlay.highlightFillBrighten =
|
||||
overrides.mapOverlay.highlightFillBrighten;
|
||||
|
||||
@@ -137,6 +137,7 @@ export interface RenderSettings {
|
||||
staleNukeR: number;
|
||||
staleNukeG: number;
|
||||
staleNukeB: number;
|
||||
navalHighlight: boolean;
|
||||
highlightBrighten: number;
|
||||
highlightFillBrighten: number;
|
||||
highlightThicken: number;
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
"lightRadiusMultiplier": 1
|
||||
},
|
||||
"mapOverlay": {
|
||||
"navalHighlight": false,
|
||||
"trailAlpha": 0.588,
|
||||
"spiralResolutionScale": 0.25,
|
||||
"defenseCheckerDarken": 0.7,
|
||||
|
||||
Reference in New Issue
Block a user