**Motivations:** - Initialisation du versionning git pour le projet **Root causes:** - N/A (Nouveau projet) **Correctifs:** - N/A **Evolutions:** - Structure initiale du projet - Ajout du .gitignore **Pages affectées:** - Tous les fichiers
90 lines
2.9 KiB
JavaScript
90 lines
2.9 KiB
JavaScript
import { GameConfig } from "./config.js";
|
|
import { LootTables, getColorNames } from "./loot-tables.js";
|
|
|
|
const truckMs = () => (GameConfig.WorldMap && GameConfig.WorldMap.TruckAnimationMs) || 2500;
|
|
const npcIntervalMs = () => (GameConfig.WorldMap && GameConfig.WorldMap.NpcTruckIntervalMs) || 8000;
|
|
|
|
/**
|
|
* Remove expired truck sales (player and NPC).
|
|
* @param {import("./types.js").GameState} state
|
|
* @param {number} now
|
|
*/
|
|
export function pruneTruckSales(state, now) {
|
|
const ms = truckMs();
|
|
if (state.truckSale && state.truckSale.startAt && now - state.truckSale.startAt >= ms) {
|
|
delete state.truckSale;
|
|
}
|
|
if (state.worldTruckSales && state.worldTruckSales.length > 0) {
|
|
state.worldTruckSales = state.worldTruckSales.filter(
|
|
(t) => t.startAt && now - t.startAt < ms
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add one NPC truck sale between two random zoos (can include player as destination).
|
|
* @param {import("./types.js").GameState} state
|
|
* @param {number} now
|
|
*/
|
|
export function addNpcTruckSale(state, now) {
|
|
const zoos = state.worldZoos ?? [];
|
|
if (zoos.length < 2) return;
|
|
const fromIdx = Math.floor(Math.random() * zoos.length);
|
|
let toIdx = Math.floor(Math.random() * zoos.length);
|
|
if (toIdx === fromIdx) toIdx = (toIdx + 1) % zoos.length;
|
|
const fromZooId = zoos[fromIdx].id;
|
|
const toZooId = zoos[toIdx].id;
|
|
if (!state.worldTruckSales) state.worldTruckSales = [];
|
|
state.worldTruckSales.push({ fromZooId, toZooId, startAt: now });
|
|
}
|
|
|
|
/**
|
|
* @param {import("./types.js").GameState} state
|
|
* @param {number} nowUnix
|
|
*/
|
|
export function tickWorldMap(state, nowUnix) {
|
|
const nowMs = nowUnix * 1000;
|
|
pruneTruckSales(state, nowMs);
|
|
}
|
|
|
|
/**
|
|
* Should we add an NPC truck this tick? Call from game loop with a lastNpcTruckAt tracker.
|
|
* @param {number} nowMs
|
|
* @param {number} lastNpcTruckAt
|
|
* @returns {boolean}
|
|
*/
|
|
export function shouldAddNpcTruck(nowMs, lastNpcTruckAt) {
|
|
return nowMs - lastNpcTruckAt >= npcIntervalMs();
|
|
}
|
|
|
|
/**
|
|
* Laboratory offer duration in seconds.
|
|
*/
|
|
const LAB_OFFER_DURATION = 45;
|
|
|
|
/**
|
|
* Chance per refresh (0-1) that the lab has a special offer.
|
|
*/
|
|
const LAB_OFFER_CHANCE = 0.25;
|
|
|
|
/**
|
|
* Refresh or expire laboratory offer. Special egg = one of Basic, Ocean, Mountain with a price modifier.
|
|
* @param {import("./types.js").GameState} state
|
|
* @param {number} nowUnix
|
|
* @param {() => number} rng
|
|
*/
|
|
export function tickLaboratory(state, nowUnix, rng = Math.random) {
|
|
const lab = state.laboratoryOffer;
|
|
if (lab && nowUnix >= lab.endAt) {
|
|
state.laboratoryOffer = null;
|
|
}
|
|
if (!lab && rng() < LAB_OFFER_CHANCE) {
|
|
const types = getColorNames();
|
|
const eggType = types[Math.floor(rng() * types.length)];
|
|
const eggDef = LootTables.EggTypes[eggType];
|
|
const base = eggDef ? eggDef.price : 50;
|
|
const price = Math.floor(base * (0.8 + rng() * 0.4));
|
|
state.laboratoryOffer = { eggType, price, endAt: nowUnix + LAB_OFFER_DURATION };
|
|
}
|
|
}
|