Round direction to nearest heading and simplify here distance phrasing
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
// Maintainer-controlled web client version.
|
// Maintainer-controlled web client version.
|
||||||
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
||||||
window.CHGRID_WEB_VERSION = "2026.02.21 R89";
|
window.CHGRID_WEB_VERSION = "2026.02.21 R90";
|
||||||
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
|
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
|
||||||
window.CHGRID_TIME_ZONE = "America/Detroit";
|
window.CHGRID_TIME_ZONE = "America/Detroit";
|
||||||
|
|||||||
@@ -670,6 +670,13 @@ function squareWord(distance: number): string {
|
|||||||
return distance === 1 ? 'square' : 'squares';
|
return distance === 1 ? 'square' : 'squares';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function distanceDirectionPhrase(px: number, py: number, tx: number, ty: number): string {
|
||||||
|
const distance = Math.round(Math.hypot(tx - px, ty - py));
|
||||||
|
const direction = getDirection(px, py, tx, ty);
|
||||||
|
if (direction === 'here') return 'here';
|
||||||
|
return `${distance} ${squareWord(distance)} ${direction}`;
|
||||||
|
}
|
||||||
|
|
||||||
function persistPlayerPosition(): void {
|
function persistPlayerPosition(): void {
|
||||||
try {
|
try {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@@ -1216,9 +1223,8 @@ function handleNormalModeInput(code: string, shiftKey: boolean): void {
|
|||||||
state.mode = 'listItems';
|
state.mode = 'listItems';
|
||||||
const first = state.items.get(state.sortedItemIds[0]);
|
const first = state.items.get(state.sortedItemIds[0]);
|
||||||
if (first) {
|
if (first) {
|
||||||
const distance = Math.round(Math.hypot(first.x - state.player.x, first.y - state.player.y));
|
|
||||||
updateStatus(
|
updateStatus(
|
||||||
`List: ${itemLabel(first)}, ${distance} ${squareWord(distance)} ${getDirection(state.player.x, state.player.y, first.x, first.y)}, ${first.x}, ${first.y}`,
|
`List: ${itemLabel(first)}, ${distanceDirectionPhrase(state.player.x, state.player.y, first.x, first.y)}, ${first.x}, ${first.y}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
audio.sfxUiBlip();
|
audio.sfxUiBlip();
|
||||||
@@ -1233,9 +1239,8 @@ function handleNormalModeInput(code: string, shiftKey: boolean): void {
|
|||||||
const item = state.items.get(nearest.itemId);
|
const item = state.items.get(nearest.itemId);
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
audio.sfxLocate({ x: item.x - state.player.x, y: item.y - state.player.y });
|
audio.sfxLocate({ x: item.x - state.player.x, y: item.y - state.player.y });
|
||||||
const roundedDistance = Math.round(nearest.distance);
|
|
||||||
updateStatus(
|
updateStatus(
|
||||||
`${itemLabel(item)}, ${roundedDistance} ${squareWord(roundedDistance)} ${getDirection(state.player.x, state.player.y, item.x, item.y)}, ${item.x}, ${item.y}`,
|
`${itemLabel(item)}, ${distanceDirectionPhrase(state.player.x, state.player.y, item.x, item.y)}, ${item.x}, ${item.y}`,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1336,9 +1341,8 @@ function handleNormalModeInput(code: string, shiftKey: boolean): void {
|
|||||||
state.mode = 'listUsers';
|
state.mode = 'listUsers';
|
||||||
const first = state.peers.get(state.sortedPeerIds[0]);
|
const first = state.peers.get(state.sortedPeerIds[0]);
|
||||||
if (first) {
|
if (first) {
|
||||||
const distance = Math.round(Math.hypot(first.x - state.player.x, first.y - state.player.y));
|
|
||||||
updateStatus(
|
updateStatus(
|
||||||
`List: ${first.nickname}, ${distance} ${squareWord(distance)} ${getDirection(state.player.x, state.player.y, first.x, first.y)}, ${first.x}, ${first.y}`,
|
`List: ${first.nickname}, ${distanceDirectionPhrase(state.player.x, state.player.y, first.x, first.y)}, ${first.x}, ${first.y}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
audio.sfxUiBlip();
|
audio.sfxUiBlip();
|
||||||
@@ -1354,9 +1358,8 @@ function handleNormalModeInput(code: string, shiftKey: boolean): void {
|
|||||||
const peer = state.peers.get(nearest.peerId);
|
const peer = state.peers.get(nearest.peerId);
|
||||||
if (!peer) return;
|
if (!peer) return;
|
||||||
audio.sfxLocate({ x: peer.x - state.player.x, y: peer.y - state.player.y });
|
audio.sfxLocate({ x: peer.x - state.player.x, y: peer.y - state.player.y });
|
||||||
const roundedDistance = Math.round(nearest.distance);
|
|
||||||
updateStatus(
|
updateStatus(
|
||||||
`${peer.nickname}, ${roundedDistance} ${squareWord(roundedDistance)} ${getDirection(state.player.x, state.player.y, peer.x, peer.y)}, ${peer.x}, ${peer.y}`,
|
`${peer.nickname}, ${distanceDirectionPhrase(state.player.x, state.player.y, peer.x, peer.y)}, ${peer.x}, ${peer.y}`,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1484,9 +1487,8 @@ function handleListModeInput(code: string, key: string): void {
|
|||||||
: (state.listIndex - 1 + state.sortedPeerIds.length) % state.sortedPeerIds.length;
|
: (state.listIndex - 1 + state.sortedPeerIds.length) % state.sortedPeerIds.length;
|
||||||
const peer = state.peers.get(state.sortedPeerIds[state.listIndex]);
|
const peer = state.peers.get(state.sortedPeerIds[state.listIndex]);
|
||||||
if (!peer) return;
|
if (!peer) return;
|
||||||
const distance = Math.round(Math.hypot(peer.x - state.player.x, peer.y - state.player.y));
|
|
||||||
updateStatus(
|
updateStatus(
|
||||||
`${peer.nickname}, ${distance} ${squareWord(distance)} ${getDirection(state.player.x, state.player.y, peer.x, peer.y)}, ${peer.x}, ${peer.y}`,
|
`${peer.nickname}, ${distanceDirectionPhrase(state.player.x, state.player.y, peer.x, peer.y)}, ${peer.x}, ${peer.y}`,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1500,9 +1502,8 @@ function handleListModeInput(code: string, key: string): void {
|
|||||||
state.listIndex = nextByInitial;
|
state.listIndex = nextByInitial;
|
||||||
const peer = state.peers.get(state.sortedPeerIds[state.listIndex]);
|
const peer = state.peers.get(state.sortedPeerIds[state.listIndex]);
|
||||||
if (!peer) return;
|
if (!peer) return;
|
||||||
const distance = Math.round(Math.hypot(peer.x - state.player.x, peer.y - state.player.y));
|
|
||||||
updateStatus(
|
updateStatus(
|
||||||
`${peer.nickname}, ${distance} ${squareWord(distance)} ${getDirection(state.player.x, state.player.y, peer.x, peer.y)}, ${peer.x}, ${peer.y}`,
|
`${peer.nickname}, ${distanceDirectionPhrase(state.player.x, state.player.y, peer.x, peer.y)}, ${peer.x}, ${peer.y}`,
|
||||||
);
|
);
|
||||||
audio.sfxUiBlip();
|
audio.sfxUiBlip();
|
||||||
return;
|
return;
|
||||||
@@ -1540,9 +1541,8 @@ function handleListItemsModeInput(code: string, key: string): void {
|
|||||||
: (state.itemListIndex - 1 + state.sortedItemIds.length) % state.sortedItemIds.length;
|
: (state.itemListIndex - 1 + state.sortedItemIds.length) % state.sortedItemIds.length;
|
||||||
const item = state.items.get(state.sortedItemIds[state.itemListIndex]);
|
const item = state.items.get(state.sortedItemIds[state.itemListIndex]);
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
const distance = Math.round(Math.hypot(item.x - state.player.x, item.y - state.player.y));
|
|
||||||
updateStatus(
|
updateStatus(
|
||||||
`${itemLabel(item)}, ${distance} ${squareWord(distance)} ${getDirection(state.player.x, state.player.y, item.x, item.y)}, ${item.x}, ${item.y}`,
|
`${itemLabel(item)}, ${distanceDirectionPhrase(state.player.x, state.player.y, item.x, item.y)}, ${item.x}, ${item.y}`,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1559,9 +1559,8 @@ function handleListItemsModeInput(code: string, key: string): void {
|
|||||||
state.itemListIndex = nextByInitial;
|
state.itemListIndex = nextByInitial;
|
||||||
const item = state.items.get(state.sortedItemIds[state.itemListIndex]);
|
const item = state.items.get(state.sortedItemIds[state.itemListIndex]);
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
const distance = Math.round(Math.hypot(item.x - state.player.x, item.y - state.player.y));
|
|
||||||
updateStatus(
|
updateStatus(
|
||||||
`${itemLabel(item)}, ${distance} ${squareWord(distance)} ${getDirection(state.player.x, state.player.y, item.x, item.y)}, ${item.x}, ${item.y}`,
|
`${itemLabel(item)}, ${distanceDirectionPhrase(state.player.x, state.player.y, item.x, item.y)}, ${item.x}, ${item.y}`,
|
||||||
);
|
);
|
||||||
audio.sfxUiBlip();
|
audio.sfxUiBlip();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -133,13 +133,14 @@ export function getDirection(px: number, py: number, tx: number, ty: number): st
|
|||||||
const dx = tx - px;
|
const dx = tx - px;
|
||||||
const dy = ty - py;
|
const dy = ty - py;
|
||||||
if (dx === 0 && dy === 0) return 'here';
|
if (dx === 0 && dy === 0) return 'here';
|
||||||
let vDir = '';
|
if (dx === 0) return dy > 0 ? 'directly north' : 'directly south';
|
||||||
let hDir = '';
|
if (dy === 0) return dx > 0 ? 'directly east' : 'directly west';
|
||||||
if (dy > 0) vDir = 'north';
|
|
||||||
if (dy < 0) vDir = 'south';
|
const octants = ['east', 'northeast', 'north', 'northwest', 'west', 'southwest', 'south', 'southeast'] as const;
|
||||||
if (dx > 0) hDir = 'east';
|
const step = Math.PI / 4;
|
||||||
if (dx < 0) hDir = 'west';
|
const rawIndex = Math.round(Math.atan2(dy, dx) / step);
|
||||||
return `${vDir} ${hDir}`.trim();
|
const index = ((rawIndex % octants.length) + octants.length) % octants.length;
|
||||||
|
return octants[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNearestItem(state: GameState): { itemId: string | null; distance: number } {
|
export function getNearestItem(state: GameState): { itemId: string | null; distance: number } {
|
||||||
|
|||||||
Reference in New Issue
Block a user