fiirst
This commit is contained in:
parent
ba055a7f13
commit
a322158f43
20 changed files with 3383 additions and 0 deletions
155
src/core/state.js
Normal file
155
src/core/state.js
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
import { STARTING_CASH, TURN_SECONDS, BUILD_COSTS, FACILITY_PRICES, GRID } from './config.js';
|
||||
import { randomBetween } from './utils.js';
|
||||
|
||||
export function newTurnStats() {
|
||||
return {
|
||||
mixerCount: 0,
|
||||
truckFemale: 0,
|
||||
truckMale: 0,
|
||||
trashCount: 0,
|
||||
poopSpawned: 0,
|
||||
poopTruck: 0,
|
||||
poopTrash: 0,
|
||||
poopMixer: 0,
|
||||
autoSorted: 0,
|
||||
revenue: 0,
|
||||
penalty: 0,
|
||||
profit: 0,
|
||||
pendingTruckRevenue: 0,
|
||||
explosionDamage: 0,
|
||||
correct: 0,
|
||||
mistakes: 0,
|
||||
contractBonus: 0,
|
||||
contractResult: null
|
||||
};
|
||||
}
|
||||
|
||||
export function newTotalStats() {
|
||||
return {
|
||||
turnsCompleted: 0,
|
||||
processed: 0,
|
||||
correct: 0,
|
||||
mistakes: 0,
|
||||
revenue: 0,
|
||||
penalty: 0,
|
||||
profit: 0,
|
||||
maxCash: STARTING_CASH,
|
||||
autoSorted: 0,
|
||||
poopTruck: 0,
|
||||
poopTrash: 0,
|
||||
poopMixer: 0,
|
||||
explosionDamage: 0,
|
||||
contractBonus: 0,
|
||||
contractSuccess: 0,
|
||||
contractFailed: 0
|
||||
};
|
||||
}
|
||||
|
||||
export function createGame() {
|
||||
return {
|
||||
phase: 'title',
|
||||
cash: STARTING_CASH,
|
||||
turn: 1,
|
||||
timeLeft: TURN_SECONDS,
|
||||
lastTimestamp: 0,
|
||||
nextId: 10,
|
||||
buildTool: null,
|
||||
buildSession: 0,
|
||||
undoStack: [],
|
||||
redoStack: [],
|
||||
selected: null,
|
||||
multiSelected: [],
|
||||
selectionBox: null,
|
||||
groupDrag: null,
|
||||
pan: null,
|
||||
view: { x: 0, y: 0 },
|
||||
debug: false,
|
||||
chicks: [],
|
||||
effects: [],
|
||||
floatingTexts: [],
|
||||
shake: { time: 0, strength: 0 },
|
||||
truckCargo: [],
|
||||
conveyorTiles: new Set(),
|
||||
conveyorMeta: new Map(),
|
||||
eggFarms: [],
|
||||
scanners: [],
|
||||
facilities: {},
|
||||
branchCounters: new Map(),
|
||||
mixerHalfTimer: 0,
|
||||
congestion: new Map(),
|
||||
lastExplodedComponent: new Map(),
|
||||
contractOffer: null,
|
||||
contractActive: null,
|
||||
stats: newTurnStats(),
|
||||
lastResult: null,
|
||||
totals: newTotalStats()
|
||||
};
|
||||
}
|
||||
|
||||
export function getSpawnRange(farm) {
|
||||
const ranges = [[1.95, 4.35], [1.55, 3.45], [1.25, 2.80], [1.05, 2.35]];
|
||||
return ranges[(farm?.level || 1) - 1] || ranges[0];
|
||||
}
|
||||
|
||||
export function nextSpawnDelay(farm) {
|
||||
const [min, max] = getSpawnRange(farm);
|
||||
return randomBetween(min, max);
|
||||
}
|
||||
|
||||
function facilityBodyForEntry(id, entry, side) {
|
||||
const sizes = {
|
||||
mixer: { w: 164, h: 126, name: 'Mixer', price: FACILITY_PRICES.mixer },
|
||||
trash: { w: 180, h: 100, name: 'Waste Shredder', price: FACILITY_PRICES.trash },
|
||||
truck: { w: 176, h: 138, name: 'Truck', price: FACILITY_PRICES.truck }
|
||||
};
|
||||
const g = { left: GRID.x, right: GRID.x + GRID.cols * GRID.cell, top: GRID.y, bottom: GRID.y + GRID.rows * GRID.cell };
|
||||
const c = { x: GRID.x + entry.col * GRID.cell + GRID.cell / 2, y: GRID.y + entry.row * GRID.cell + GRID.cell / 2 };
|
||||
const spec = sizes[id];
|
||||
let x = c.x - spec.w / 2;
|
||||
let y = c.y - spec.h / 2;
|
||||
if (side === 'left') { x = g.left - spec.w - 18; y = c.y - spec.h / 2; }
|
||||
else if (side === 'right') { x = g.right + 18; y = c.y - spec.h / 2; }
|
||||
else if (side === 'bottom') { x = c.x - spec.w / 2; y = g.bottom + 18; }
|
||||
else if (side === 'top') { x = c.x - spec.w / 2; y = g.top - spec.h - 18; }
|
||||
return { type: 'facility', id, name: spec.name, x, y, w: spec.w, h: spec.h, level: 1, price: spec.price, entry: { ...entry }, side };
|
||||
}
|
||||
|
||||
export function defaultFacilities() {
|
||||
return {
|
||||
// Machine bodies sit outside the build grid. Only these receiver cells sit on the grid edge.
|
||||
mixer: facilityBodyForEntry('mixer', { col: 0, row: 6 }, 'left'),
|
||||
trash: facilityBodyForEntry('trash', { col: 16, row: 12 }, 'bottom'),
|
||||
truck: facilityBodyForEntry('truck', { col: 21, row: 7 }, 'right')
|
||||
};
|
||||
}
|
||||
|
||||
export function resetLayout(game) {
|
||||
game.conveyorTiles.clear();
|
||||
game.conveyorMeta.clear();
|
||||
const initial = [
|
||||
// Egg Farm -> S1 top input. The approach lane is long enough to read the flow.
|
||||
[4, 1], [4, 2], [4, 3], [4, 4], [4, 5],
|
||||
// S1 left output -> Mixer receiver on the left grid edge.
|
||||
[3, 6], [2, 6], [1, 6], [0, 6],
|
||||
// S1 right output -> S2 top input. This avoids touching S2's waste output lane.
|
||||
[5, 6], [6, 6], [7, 6], [8, 6], [9, 6], [10, 6], [11, 6], [12, 6], [13, 6], [14, 6],
|
||||
[14, 5], [15, 5], [16, 5], [17, 5], [17, 6],
|
||||
// S2 left output -> Waste Shredder receiver on bottom grid edge.
|
||||
[16, 7], [16, 8], [16, 9], [16, 10], [16, 11], [16, 12],
|
||||
// S2 right output -> Truck receiver on the right grid edge.
|
||||
[18, 7], [19, 7], [20, 7], [21, 7]
|
||||
]; for (const [col, row] of initial) {
|
||||
const k = `${col},${row}`;
|
||||
game.conveyorTiles.add(k);
|
||||
game.conveyorMeta.set(k, { price: BUILD_COSTS.conveyor, builtSession: null });
|
||||
}
|
||||
game.facilities = defaultFacilities();
|
||||
game.scanners = [
|
||||
{ type: 'scanner', id: 1, kind: 'manual', slot: 0, role: 0, col: 4, row: 6, level: 1, queue: [], cooldown: 0, price: BUILD_COSTS.manualScanner, builtSession: null, autoMode: 'standard' },
|
||||
{ type: 'scanner', id: 2, kind: 'manual', slot: 1, role: 1, col: 17, row: 7, level: 1, queue: [], cooldown: 0, price: BUILD_COSTS.manualScanner, builtSession: null, autoMode: 'standard' }
|
||||
];
|
||||
const farm = { type: 'eggFarm', id: 1, col: 4, row: 0, level: 1, nextSpawn: 2, lastInterval: 2, spawnCounter: 0, price: BUILD_COSTS.eggFarm, builtSession: null };
|
||||
farm.nextSpawn = nextSpawnDelay(farm);
|
||||
farm.lastInterval = farm.nextSpawn;
|
||||
game.eggFarms = [farm];
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue