141 lines
4.6 KiB
JavaScript
141 lines
4.6 KiB
JavaScript
import iran from '../../data/iran.json';
|
|
import { CATEGORIES, lockedPlaces } from '../../constants/locations.js';
|
|
import { catalog, priceAt, isOpen, fa } from '../economy/gameState.js';
|
|
import { drawFullMap, drawIran } from '../world/mapRender.js';
|
|
import { formatDistance } from '../../utils/geo.js';
|
|
/**
|
|
* Runs the size canvas operation for this subsystem.
|
|
* @param {*} context - context.
|
|
* @param {*} c - c.
|
|
* @returns {*} Operation result, when applicable.
|
|
*/
|
|
export function sizeCanvas(context, c) {
|
|
const r = c.getBoundingClientRect(),
|
|
dpr = Math.min(devicePixelRatio, 2);
|
|
c.width = Math.max(1, r.width * dpr);
|
|
c.height = Math.max(1, r.height * dpr);
|
|
return dpr;
|
|
}
|
|
/**
|
|
* Runs the render map operation for this subsystem.
|
|
* @param {*} context - context.
|
|
* @returns {*} Operation result, when applicable.
|
|
*/
|
|
export function renderMap(context) {
|
|
if (!context.ui.read('map-dialog').open) return;
|
|
if (context.mapTab === 'city') {
|
|
const dpr = context.sizeCanvas(context.mapCanvas);
|
|
const pos = context.mode === 'drive' ? context.car : context.player;
|
|
drawFullMap(context.mapCanvas.getContext('2d'), context.mapAssets, context.mapView, {
|
|
dpr,
|
|
markers: context.markers(),
|
|
route: context.route?.points,
|
|
selected: context.selected,
|
|
player: {
|
|
x: pos.x,
|
|
z: pos.z,
|
|
heading: context.mode === 'drive' ? context.car.heading : context.player.heading,
|
|
},
|
|
});
|
|
} else {
|
|
const dpr = context.sizeCanvas(context.iranCanvas),
|
|
c = context.iranCanvas.getContext('2d');
|
|
c.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
drawIran(c, iran, {
|
|
width: context.iranCanvas.width / dpr,
|
|
height: context.iranCanvas.height / dpr,
|
|
t: context.elapsed,
|
|
cities: context.CITIES,
|
|
});
|
|
}
|
|
}
|
|
/**
|
|
* Runs the render machine list operation for this subsystem.
|
|
* @param {*} context - context.
|
|
* @returns {*} Operation result, when applicable.
|
|
*/
|
|
export function renderMachineList(context) {
|
|
const pos = context.mode === 'drive' ? context.car : context.player;
|
|
const visited = new Set(context.state.purchases.map((p) => p.machineId));
|
|
const items = context.activeStations().map((s) => ({
|
|
id: s.def.id,
|
|
name: s.def.name,
|
|
icon: CATEGORIES[s.def.category].icon,
|
|
category: CATEGORIES[s.def.category].label,
|
|
visited: visited.has(s.def.id),
|
|
open: isOpen(s.def, context.state.minutes),
|
|
selected: s.def.id === context.selected,
|
|
distance: formatDistance(Math.hypot(s.x - pos.x, s.z - pos.z)),
|
|
}));
|
|
context.ui.patch('machine-list', {
|
|
items: [
|
|
...items,
|
|
...lockedPlaces.map((p) => ({
|
|
...p,
|
|
id: p.name,
|
|
locked: true,
|
|
})),
|
|
],
|
|
});
|
|
}
|
|
/**
|
|
* Runs the select machine operation for this subsystem.
|
|
* @param {*} context - context.
|
|
* @param {*} id - id.
|
|
* @param {*} center - center.
|
|
* @returns {*} Operation result, when applicable.
|
|
*/
|
|
export function selectMachine(context, id, center = false) {
|
|
context.selected = id;
|
|
const s = context.stationById(id),
|
|
def = s.def;
|
|
if (center) {
|
|
context.mapView.cx = s.x;
|
|
context.mapView.cz = s.z;
|
|
context.mapView.mpp = Math.min(context.mapView.mpp, 1.4);
|
|
}
|
|
context.ui.patch('machine-detail', {
|
|
hidden: false,
|
|
});
|
|
context.ui.patch('detail-name', {
|
|
text: `${CATEGORIES[def.category].icon} ${def.name}`,
|
|
});
|
|
context.ui.patch('detail-address', {
|
|
text: `📍 ${def.address}`,
|
|
});
|
|
context.ui.patch('detail-meta', {
|
|
text: `🕒 ${context.hoursText(def)} · ${isOpen(def, context.state.minutes) ? 'الان باز است' : 'الان بسته است'} · ${def.note}`,
|
|
});
|
|
context.ui.patch('detail-products', {
|
|
text: def.products
|
|
.map((id) => `${catalog[id].icon} ${catalog[id].name} ${fa(priceAt(def, id))}`)
|
|
.join(' · '),
|
|
});
|
|
context.ui.patch('route-button', {
|
|
text: context.waypoint === id ? 'مسیر فعال است ✓' : 'مسیریابی تا اینجا',
|
|
});
|
|
context.renderMachineList();
|
|
context.renderMap();
|
|
}
|
|
/**
|
|
* Runs the open map operation for this subsystem.
|
|
* @param {*} context - context.
|
|
* @returns {*} Operation result, when applicable.
|
|
*/
|
|
export function openMap(context) {
|
|
if (context.anyDialogOpen()) return;
|
|
document.exitPointerLock?.();
|
|
context.keys.clear();
|
|
const pos = context.mode === 'drive' ? context.car : context.player;
|
|
Object.assign(context.mapView, {
|
|
cx: pos.x,
|
|
cz: pos.z,
|
|
mpp: 2.2,
|
|
});
|
|
context.ui.open('map-dialog');
|
|
context.selected ??= context.objectiveStation()?.def.id ?? null;
|
|
if (context.selected) context.selectMachine(context.selected);
|
|
context.renderMachineList();
|
|
context.renderMap();
|
|
}
|