/* ========================================================= * REPRTERRA WEB — entities.js * Factories & shared helpers for buildings/units/dinos. * ========================================================= */ 'use strict'; window.RTS = window.RTS || {}; RTS.entities = (function () { const U = RTS.util; let nextId = 1; const E = {}; E.resetIds = () => { nextId = 1; }; // after loading a save, keep new ids above everything deserialized E.setIdFloor = (n) => { if (n >= nextId) nextId = n + 1; }; // ---------- footprint ---------- // returns [x0,y0] of top-left tile for a building centered at cx,cy E.footOrigin = function (cx, cy, size) { return [Math.round(cx - size / 2), Math.round(cy - size / 2)]; }; // ---------- buildings ---------- E.makeBuilding = function (defId, cx, cy, opts) { const C = RTS.CONFIG; const def = C.BUILDINGS[defId]; const instant = opts && opts.instant; const b = { kind: 'building', id: nextId++, defId, name: def.name, size: def.size, x: Math.round(cx), y: Math.round(cy), // center tile coords hp: instant ? def.hp : def.hp * 0.15, maxHp: def.hp, done: !!instant, progress: instant ? 1 : 0, buildTime: instant ? 0 : 2.5 + def.size * 2.5, workersNeed: def.workers || 0, workers: 0, powered: true, active: true, // production on/off cool: 0, // tower fire cooldown trainQ: [], // barracks queue [{t, unit}] trainT: 0, rallyX: null, rallyY: null, burnT: 0, }; return b; }; // ---------- human units ---------- E.makeUnit = function (unitId, x, y) { const C = RTS.CONFIG; const def = C.UNITS[unitId]; const simSt = (RTS.sim && RTS.sim.state) ? RTS.sim.state() : null; const armorLvl = (simSt && simSt.upgrades) ? simSt.upgrades.armor || 0 : 0; const hp = def.hp * (1 + 0.25 * armorLvl); return { kind: 'unit', id: nextId++, unitId, name: def.name, x, y, hp, maxHp: hp, speed: def.speed, cool: 0, path: null, pathI: 0, tx: null, ty: null, // move goal attackMove: false, targetId: 0, // focused enemy selected: false, facing: U.rng() * Math.PI * 2, animT: U.rng() * 10, dead: false, }; }; // ---------- dinosaurs ---------- E.makeDino = function (dinoId, x, y, mode, home) { const C = RTS.CONFIG; const def = C.DINOS[dinoId]; const rng = U.rng; return { kind: 'dino', id: nextId++, dinoId, name: def.name, x, y, hp: def.hp, maxHp: def.hp, dmg: def.dmg, rof: def.rof, speed: def.speed * rng.range(0.9, 1.12), r: def.r, flying: !!def.flying, amphibious: !!def.amphibious, ranged: def.ranged || 0, bldMult: def.bldMult || 1, bounty: def.bounty, scale: def.scale, color: def.color, mode: mode || 'wave', // 'roam' | 'wave' | 'final' homeX: home ? home.x : x, homeY: home ? home.y : y, targetId: 0, targetType: '', path: null, pathI: 0, repathT: 0, stuckT: 0, lastDist: Infinity, cool: 0, facing: rng() * Math.PI * 2, animT: rng() * 10, wanderT: 0, wx: x, wy: y, aggro: !!(mode === 'wave'), dead: false, hitFlash: 0, }; }; // ---------- projectiles ---------- E.makeProj = function (type, x, y, tx, ty, opts) { return { kind: 'proj', id: nextId++, type, // 'bullet' | 'shell' | 'spit' x, y, z: opts && opts.z != null ? opts.z : 8, tx, ty, speed: opts && opts.speed || 14, dmg: opts && opts.dmg || 5, aoe: opts && opts.aoe || 0, air: !!(opts && opts.air), fromPlayer: !(opts && opts.enemy), color: opts && opts.color || '#ffd76a', trail: [], arc: opts && opts.arc || 0, // lob height for shells/spits t: 0, total: 1, }; }; return E; })();