83 lines
3.7 KiB
JavaScript
Executable File
83 lines
3.7 KiB
JavaScript
Executable File
(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));
|