import {buildInvoke, buildTraversal} from '@avocado/behavior'; import {Vector} from '@avocado/math'; import {World} from '@avocado/physics/matter/world'; import {Room} from '@avocado/topdown'; import {AFFINITY_FIRE} from '../common/combat/constants'; // Behaviors! const move = buildInvoke(['entity', 'moveFor'], [ buildInvoke(['global', 'randomNumber'], [0.25, 2.5, false]) ]); const stopAnimating = buildTraversal( ['entity', 'isAnimating'], false ); const firstWait = buildInvoke(['global', 'wait'], [ buildInvoke(['global', 'randomNumber'], [1, 4, false]) ]); const turn = buildTraversal( ['entity', 'direction'], buildInvoke(['global', 'randomNumber'], [0, 3]) ); const secondWait = buildInvoke(['global', 'wait'], [ buildInvoke(['global', 'randomNumber'], [0.5, 3, false]) ]); const startAnimating = buildTraversal( ['entity', 'isAnimating'], true ); // A fire. function fireJSON(position) { return { traits: { animated: { params: { animations: { idle: { jitter: 0.1, offset: [0, 0], uri: '/fire.animation.json', }, } }, }, audible: { params: { sounds: { fire: { uri: '/fire.sound.json', }, } } }, collider: { params: { isSensor: true, }, }, damaging: { params: { damagingSound: 'fire', damageSpecs: [ { affinity: AFFINITY_FIRE, lock: 0.45, power: 15, variance: 0.25, }, ], }, }, darkened: { params: { isDarkened: false, }, }, existent: { state: { name: 'Fire', }, }, layered: {}, listed: {}, physical: {}, positioned: { state: { x: position[0], y: position[1], }, }, roomed: {}, shaped: { params: { shape: { type: 'rectangle', position: [0, 0], size: [16, 16], }, }, }, visible: { params: { filter: 'bloom', }, }, }, }; } // Healing fire! function blueFireJSON(position) { const json = fireJSON(position); json.traits.animated.params.animations.idle.uri = '/blue-fire.animation.json'; json.traits.damaging.params.damageSpecs[0].power = -15; json.traits.audible.params.sounds.fire.uri = '/blue-fire.sound.json'; return json; } // A flower barrel. export function flowerBarrelJSON(position) { return { traits: { alive: { state: { maxLife: 1000, life: 1000, }, }, collider: {}, emitter: {}, existent: { state: { name: 'Flower Barrel', }, }, layered: {}, listed: {}, physical: {}, pictured: { params: { images: { initial: { offset: [0, -8], size: [32, 32], // Derive? uri: '/flower-barrel.png', }, } }, }, positioned: { state: { x: position[0], y: position[1], }, }, roomed: {}, shaped: { params: { shape: { type: 'rectangle', position: [0, 0], size: [20, 10], }, }, }, visible: {}, vulnerable: {}, }, }; } // A kitteh. function kittyJSON(position) { return { traits: { alive: {}, animated: { params: { animations: { idle: { offset: [0, -3], uri: '/kitty.animation.json', }, } }, }, audible: { params: { sounds: { deathSound: { uri: '/ded.sound.json', }, } } }, behaved: { params: { routines: { type: 'routines', routines: { initial: { type: 'routine', routine: { type: 'actions', traversals: [ move, stopAnimating, firstWait, turn, secondWait, startAnimating, ], } }, }, }, }, }, collider: {}, directional: { params: { directionCount: 4, }, state: { direction: 2, }, }, emitter: {}, existent: { state: { name: 'Kitty', }, }, visible: { state: { visibleScale: [1, 1], } }, layered: {}, listed: {}, mobile: { state: { speed: 40, }, }, physical: {}, positioned: { state: { x: position[0], y: position[1], }, }, roomed: {}, shaped: { params: { shape: { type: 'rectangle', position: [0, 0], size: [8, 4], }, }, }, vulnerable: {}, }, }; } // A MAMA kitteh. function mamaKittyJSON(position) { const storeJSON = buildTraversal( ['context', 'json'], { traits: { positioned: { state: {}, }, }, }, ); const setJSONX = buildTraversal( ['context', 'json', 'traits', 'positioned', 'state', 'x'], buildInvoke(['global', 'multiply'], [ buildTraversal(['entity', 'x']), 4 ]), ); const setJSONY = buildTraversal( ['context', 'json', 'traits', 'positioned', 'state', 'y'], buildInvoke(['global', 'multiply'], [ buildTraversal(['entity', 'y']), 4 ]), ); const spawn = buildInvoke(['entity', 'spawn'], [ 'kitteh', buildTraversal(['context', 'json']), ]); const playDeathSound = buildInvoke(['entity', 'playSound'], [ buildTraversal(['entity', 'deathSound']), ]); const squeeze = buildInvoke(['entity', 'transition'], [ { opacity: 0, visibleScaleX: .3, visibleScaleY: 3, }, 0.2, ]); const murderKitties = buildInvoke(['entity', 'killAllChildren']); const json = JSON.parse(JSON.stringify(kittyJSON(position))); const {traits} = json; traits.alive.params = { deathActions: { type: 'actions', traversals: [ playDeathSound, murderKitties, squeeze, ], }, }; traits.alive.state = { life: 500, maxLife: 500, }; traits.animated.params.animations.idle.offset = [0, -8]; traits.behaved.params.routines.routines.initial.routine.traversals.push(...[ storeJSON, setJSONX, setJSONY, spawn, ]); traits.existent.state.name = 'Mama Kitty'; traits.visible.state.visibleScale = [2, 2]; traits.shaped.params.shape.size = [16, 8]; traits.spawner = { params: { spawns: { kitteh: kittyJSON([100, 100]), }, }, state: { maxSpawns: 10, }, }; return json; } // Room. const roomTileSize = [24, 24]; const roomSize = Vector.mul([16, 16], roomTileSize); const roomJSON = { size: roomSize, layers: [ { entities: [], tiles: { size: roomTileSize, data: [ 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, ], }, tilesetUri: '/tileset.json', }, ], }; function mamaKittySpawnerJSON() { const storeJSON = buildTraversal( ['context', 'json'], { traits: { positioned: { state: {}, }, }, }, ); const setJSONX = buildTraversal( ['context', 'json', 'traits', 'positioned', 'state', 'x'], buildInvoke(['global', 'multiply'], [ buildInvoke(['global', 'randomNumber'], [100, roomSize[0] - 100]), 4 ]), ); const setJSONY = buildTraversal( ['context', 'json', 'traits', 'positioned', 'state', 'y'], buildInvoke(['global', 'multiply'], [ buildInvoke(['global', 'randomNumber'], [100, roomSize[1] - 100]), 4 ]), ); const spawn = buildInvoke(['entity', 'spawn'], [ 'mama', buildTraversal(['context', 'json']), ]); return { traits: { behaved: { params: { routines: { type: 'routines', routines: { initial: { type: 'routine', routine: { type: 'actions', traversals: [ storeJSON, setJSONX, setJSONY, spawn, ], } }, }, }, }, }, existent: { state: { name: 'Mama spawner', }, }, layered: {}, listed: {}, roomed: {}, spawner: { params: { spawns: { mama: mamaKittyJSON([0, 0]), }, }, state: { maxSpawns: 2, }, }, }, }; } for (let i = 0; i < 50; ++i) { const x = Math.floor(Math.random() * (roomSize[0] - 100)) + 50; const y = Math.floor(Math.random() * (roomSize[1] - 100)) + 50; roomJSON.layers[0].entities.push(flowerBarrelJSON([x * 4, y * 4])); } for (let i = 0; i < 5; ++i) { const x = Math.floor(Math.random() * (roomSize[0] - 100)) + 50; const y = Math.floor(Math.random() * (roomSize[1] - 100)) + 50; roomJSON.layers[0].entities.push(mamaKittySpawnerJSON()); } for (let i = 0; i < 60; ++i) { const x = Math.floor(Math.random() * (roomSize[0] - 100)) + 50; const y = Math.floor(Math.random() * (roomSize[1] - 100)) + 50; roomJSON.layers[0].entities.push(fireJSON([x * 4, y * 4])); } for (let i = 0; i < 5; ++i) { const x = Math.floor(Math.random() * (roomSize[0] - 100)) + 50; const y = Math.floor(Math.random() * (roomSize[1] - 100)) + 50; roomJSON.layers[0].entities.push(blueFireJSON([x * 4, y * 4])); } export function createRoom() { const room = new Room(); room.fromJSON(roomJSON); room.world = new World(); return room; }