Files
org_web/assets/scripts/pages/princess-lima-v2-maps.js
gitea-actions 6066f486de
All checks were successful
Build Org Website / build (push) Successful in 1m2s
Refine Princess Lima for v2 presentation
2026-07-30 15:00:45 +01:00

83 lines
3.7 KiB
JavaScript

(function (root) {
"use strict";
const Data = root.PrincessLimaV2Data;
const Systems = root.PrincessLimaV2Systems;
function properties(object) {
return Systems.propertyMap(object);
}
function objects(map, layerName) {
const layer = map.getObjectLayer(layerName);
return layer ? layer.objects : [];
}
function build(scene, regionId, state) {
const map = scene.make.tilemap({ key: `map-${regionId}` });
const tileset = map.addTilesetImage("Princess Lima World", "world-tiles", 32, 32, 0, 0);
if (!tileset) throw new Error(`Tileset could not be attached for ${regionId}`);
const tileLayers = [
["Base terrain", 0, 1], ["Terrain variation", 2, 0.62], ["Paths", 3, 1],
["Water", 4, 0.94], ["Cliffs and buildings", 8, 1], ["Props", 12, 1],
["Objects behind actors", 20, 1], ["Actor layer", 100, 1],
["Objects above actors", 9000, 1], ["Shadows", 8800, 0.42], ["Lighting", 8900, 0.34]
].map(([name, depth, alpha]) => {
const layer = map.createLayer(name, tileset, 0, 0);
if (layer) layer.setDepth(depth).setAlpha(alpha);
return layer;
}).filter(Boolean);
const collisions = scene.physics.add.staticGroup();
objects(map, "Collision").forEach((object) => {
const blocker = scene.add.rectangle(object.x + object.width / 2, object.y + object.height / 2, object.width, object.height, 0x000000, 0);
scene.physics.add.existing(blocker, true);
collisions.add(blocker);
});
const bounds = { width: map.widthInPixels, height: map.heightInPixels };
const resolved = Boolean(state.flags[`${regionId}_resolved`]);
const tint = resolved ? 0xffffff : {
village: 0xd9c1a8, forest: 0xb7cfba, ruins: 0xaabdc4, mountain: 0xc7d8e6,
camp: 0xd8c09c, fortressExterior: 0xb7a7c2, fortressInterior: 0xa996af,
bossArena: 0xa17ca8, chamber: 0xfff1cc
}[regionId] || 0xffffff;
tileLayers.forEach((layer) => layer.setTint(tint));
const ambience = createAmbience(scene, regionId, bounds, state);
return {
map, tileset, tileLayers, collisions, bounds, ambience,
spawns: Object.fromEntries(objects(map, "Named safe spawns").map((object) => [object.name, { x: object.x, y: object.y }])),
npcs: objects(map, "Dialogue triggers"),
enemies: objects(map, "Enemy zones"),
interactions: objects(map, "Interaction zones").concat(objects(map, "Optional secrets")),
transitions: objects(map, "Scene transitions"),
cameraZones: objects(map, "Camera zones")
};
}
function createAmbience(scene, regionId, bounds, state) {
const container = scene.add.container(0, 0).setDepth(8700);
if (!state.settings.particles || state.settings.effectsQuality === "minimal") return container;
const colors = {
village: 0xffa75e, forest: 0xb9f39a, ruins: 0x6dd7df, mountain: 0xe8f5ff,
camp: 0xffc16b, fortressExterior: 0x9d6fb4, fortressInterior: 0x9d6fb4,
bossArena: 0xd968c2, chamber: 0xffe3a3
};
const count = state.settings.effectsQuality === "reduced" ? 10 : 24;
for (let index = 0; index < count; index += 1) {
const mote = scene.add.circle(
(index * 149 + 71) % bounds.width,
(index * 83 + 37) % bounds.height,
index % 3 + 1,
colors[regionId] || 0xffffff,
0.12 + (index % 4) * 0.07
);
container.add(mote);
if (!state.settings.reducedMotion) scene.tweens.add({
targets: mote, y: mote.y - 32 - (index % 5) * 8, x: mote.x + ((index % 3) - 1) * 18,
alpha: { from: mote.alpha, to: 0.03 }, duration: 2600 + index * 97, yoyo: true, repeat: -1,
ease: "Sine.InOut"
});
}
return container;
}
root.PrincessLimaV2Maps = Object.freeze({ build, objects, properties });
}(typeof globalThis !== "undefined" ? globalThis : this));