(function (root) { "use strict"; const Data = root.PrincessLimaData; const TILE = 32; const REGION_ROW = Object.freeze({ village: 0, forest: 1, ruins: 2, mountain: 3, camp: 4, fortressExterior: 5, fortressInterior: 6, bossArena: 7, chamber: 8 }); const ART = Object.freeze({ village: { paths: [[1, 10, 38, 4], [17, 7, 6, 15], [3, 16, 34, 3]], decor: [["garden", 1120, 575], ["cart", 955, 350], ["smoke", 180, 62], ["forge", 520, 250], ["flowers", 785, 610]] }, forest: { paths: [[1, 9, 37, 4], [8, 4, 4, 16], [16, 8, 4, 14], [24, 3, 4, 16], [31, 2, 5, 19]], decor: [["stream", 1040, 300], ["bridge", 1030, 375], ["log", 760, 500], ["flowers", 520, 110], ["mushrooms", 1010, 610]] }, ruins: { paths: [[3, 16, 33, 4], [15, 4, 5, 13], [25, 4, 5, 13]], decor: [["mosaic", 575, 350], ["statue", 230, 190], ["statue", 930, 190], ["arch", 570, 115], ["rubble", 1080, 520]] }, mountain: { paths: [[1, 16, 38, 4], [11, 5, 5, 13], [23, 5, 5, 13], [31, 10, 6, 9]], decor: [["ice", 560, 580], ["pine", 110, 160], ["pine", 1140, 150], ["icicles", 630, 70], ["cave", 1080, 335]] }, camp: { paths: [[1, 16, 38, 4], [17, 5, 6, 14], [5, 10, 30, 4]], decor: [["fire", 640, 345], ["crates", 1120, 570], ["training", 210, 385], ["lookout", 1120, 150], ["banner", 640, 55]] }, fortressExterior: { paths: [[1, 17, 38, 4], [18, 4, 5, 17], [10, 9, 20, 5]], decor: [["moat", 640, 625], ["stairs", 640, 465], ["banner", 640, 120], ["siege", 220, 620], ["siege", 1060, 620]] }, fortressInterior: { paths: [[18, 2, 5, 20], [5, 14, 30, 5], [7, 5, 27, 5]], decor: [["carpet", 640, 360], ["torch", 225, 230], ["torch", 1055, 230], ["crates", 1000, 610], ["banner", 640, 80]] }, bossArena: { paths: [[5, 3, 30, 18]], decor: [["throne", 640, 90], ["rune", 640, 360], ["brazier", 330, 155], ["brazier", 950, 155], ["chains", 640, 45]] }, chamber: { paths: [[4, 3, 32, 18]], decor: [["carpet", 640, 410], ["bed", 1000, 230], ["flowers", 220, 210], ["fountain", 300, 560], ["table", 985, 515]] } }); function tileIndex(regionId, kind) { return REGION_ROW[regionId] * 4 + kind; } function createTilemap(scene, regionId) { const config = ART[regionId]; const rows = Math.ceil(Data.HEIGHT / TILE); const columns = Math.ceil(Data.WIDTH / TILE); const base = tileIndex(regionId, 0); const detail = tileIndex(regionId, 1); const path = tileIndex(regionId, 2); const data = Array.from({ length: rows }, (_, y) => Array.from({ length: columns }, (_, x) => ((x * 7 + y * 11) % 13 === 0 ? detail : base))); config.paths.forEach(([left, top, width, height]) => { for (let y = top; y < Math.min(rows, top + height); y += 1) { for (let x = left; x < Math.min(columns, left + width); x += 1) data[y][x] = path; } }); const map = scene.make.tilemap({ data, tileWidth: TILE, tileHeight: TILE }); const tiles = map.addTilesetImage("lima-world-tiles", "lima-world-tiles", TILE, TILE, 0, 0); const layer = map.createLayer(0, tiles, 0, 0).setDepth(0); return { map, layer }; } function drawObstacle(scene, regionId, shape) { const frame = tileIndex(regionId, shape.kind === "water" || shape.kind === "chasm" ? 3 : 1); if (shape.shape === "circle") { const color = Phaser.Display.Color.HexStringToColor(Data.MAPS[regionId].palette[2]).color; const edge = Phaser.Display.Color.HexStringToColor(Data.MAPS[regionId].palette[3]).color; const object = scene.add.circle(shape.x, shape.y, shape.radius, color, 0.98).setStrokeStyle(5, edge).setDepth(8); scene.add.circle(shape.x - shape.radius * 0.22, shape.y - shape.radius * 0.28, Math.max(4, shape.radius * 0.18), 0xffffff, 0.18).setDepth(9); return object; } const object = scene.add.tileSprite( shape.x + shape.width / 2, shape.y + shape.height / 2, shape.width, shape.height, "lima-world-tiles", frame ).setDepth(8); const graphics = scene.add.graphics().setDepth(9); const outline = Phaser.Display.Color.HexStringToColor(Data.MAPS[regionId].palette[3]).color; graphics.lineStyle(3, outline, 0.95).strokeRect(shape.x, shape.y, shape.width, shape.height); addSilhouette(scene, shape); return object; } function addSilhouette(scene, shape) { const x = shape.x; const y = shape.y; const width = shape.width; const height = shape.height; const ink = 0x0b0d13; if (shape.kind === "house" || shape.kind === "tent") { scene.add.triangle(x + width / 2, y + 6, 4, Math.min(50, height * 0.35), width / 2, 0, width - 4, Math.min(50, height * 0.35), 0x3e2430, 0.92).setDepth(10); scene.add.rectangle(x + width / 2, y + height - 14, Math.min(34, width * 0.2), 28, ink, 0.85).setDepth(10); } else if (shape.kind === "trees") { for (let py = y + 18; py < y + height; py += 44) { scene.add.circle(x + width / 2 + ((py / 44) % 2 ? -12 : 12), py, 22, 0x173f2b, 0.96).setStrokeStyle(2, 0x82a957).setDepth(10); } } else if (/wall|cell|fence|barricade|cage/.test(shape.kind || "")) { for (let px = x + 8; px < x + width; px += 18) scene.add.rectangle(px, y + height / 2, 5, height - 5, ink, 0.32).setDepth(10); } else if (shape.kind === "cliff") { for (let py = y + 14; py < y + height; py += 34) scene.add.triangle(x + width - 12, py, 0, 0, 22, 8, 4, 22, 0xdce6ee, 0.5).setDepth(10); } } function drawDecor(scene, regionId) { ART[regionId].decor.forEach(([type, x, y], index) => { const depth = y + 5; if (["flowers", "mushrooms"].includes(type)) { const colors = type === "flowers" ? [0xffd26b, 0xd6759e, 0xf6f1cf] : [0xd95c69, 0xf0c66c]; colors.forEach((color, offset) => scene.add.circle(x + offset * 10, y + (offset % 2) * 5, 4, color).setDepth(depth)); } else if (["fire", "torch", "brazier"].includes(type)) { scene.add.circle(x, y, type === "fire" ? 18 : 10, 0xff9d3d, 0.92).setStrokeStyle(3, 0xffe18b).setDepth(depth); scene.add.rectangle(x, y + 15, type === "fire" ? 34 : 8, 7, 0x5b3324).setDepth(depth - 1); } else if (["stream", "ice", "moat"].includes(type)) { scene.add.ellipse(x, y, type === "moat" ? 420 : 150, type === "moat" ? 38 : 64, type === "ice" ? 0x9dd9e8 : 0x28758b, 0.72).setStrokeStyle(3, 0xb7eff1).setDepth(3); } else if (["bridge", "stairs", "carpet"].includes(type)) { scene.add.rectangle(x, y, type === "carpet" ? 100 : 130, type === "stairs" ? 48 : 40, type === "carpet" ? 0x7f2940 : 0x9a7548, 0.95).setStrokeStyle(3, 0xe0bd75).setDepth(depth); } else if (["pine", "smoke", "statue", "arch", "lookout", "throne", "fountain"].includes(type)) { const color = { pine: 0x275437, smoke: 0x70737c, statue: 0x8f9990, arch: 0x767d72, lookout: 0x68452d, throne: 0x613152, fountain: 0x4c99b5 }[type]; scene.add.triangle(x, y, 0, 42, 26, 0, 52, 42, color, 0.94).setStrokeStyle(2, 0xe4c779).setDepth(depth); } else { const color = ["rune", "chains"].includes(type) ? 0x8c4aa0 : 0x73513a; scene.add.rectangle(x, y, 48 + index % 2 * 16, 30, color, 0.88).setStrokeStyle(2, 0xd1ac66).setDepth(depth); } }); } function render(scene, regionId, obstacles, dynamicObstacles, unlockedRoutes) { createTilemap(scene, regionId); scene.add.image(Data.WIDTH / 2, Data.HEIGHT / 2, "lima-region-atlas", REGION_ROW[regionId]) .setDisplaySize(Data.WIDTH, Data.HEIGHT) .setAlpha(regionId === "chamber" ? 0.52 : 0.42) .setDepth(1); obstacles.forEach((shape) => drawObstacle(scene, regionId, shape)); (dynamicObstacles || []).forEach((shape) => { if (!unlockedRoutes.includes(shape.opensWith)) drawObstacle(scene, regionId, shape); else if (shape.id === "bridge") { scene.add.tileSprite(shape.x + shape.width / 2, shape.y + shape.height / 2, shape.width, 70, "lima-world-tiles", tileIndex(regionId, 2)).setDepth(7); } }); drawDecor(scene, regionId); } const api = Object.freeze({ ART, REGION_ROW, createTilemap, drawObstacle, render, tileIndex }); if (typeof module === "object" && module.exports) module.exports = api; root.PrincessLimaMaps = api; }(typeof globalThis !== "undefined" ? globalThis : this));