export const TILE_SIZE = 48; export const WORLD_WIDTH = 64; export const WORLD_HEIGHT = 64; export const TICK_RATE = 10; // server ticks per second export const MOVE_SPEED = 0.75; // tiles per tick (NPC movement speed) export const BROADCAST_EVERY_N_TICKS = 3; // state broadcast frequency export const SPRITE_FRAME_WIDTH = 48; export const SPRITE_FRAME_HEIGHT = 48; export const SPRITE_COLS = 6; export const SPRITE_ROWS = 4; // NPC needs export const HUNGER_DECAY_PER_TICK = 0.05; export const ENERGY_DECAY_PER_TICK = 0.03; export const HUNGER_THRESHOLD = 30; export const THIRST_DECAY_PER_TICK = 0.05; export const THIRST_THRESHOLD = 30; export const ENERGY_THRESHOLD = 20; export const NEED_RECOVERY_RATE = 0.5; // Sleep system export const SLEEP_ENERGY_RECOVERY_PER_TICK = 0.048; // ~80 energy over one night (~1667 ticks) export const SLEEP_HUNGER_DECAY_MULTIPLIER = 0.5; // hunger decays at half rate while sleeping export const SLEEP_WAKE_THRESHOLD = 85; // energy level where waking chance begins export const SLEEP_VOLUNTARY_ENERGY_THRESHOLD = 60; // nighttime voluntary sleep threshold export const NAP_BUFFER = 15; // energy buffer above minimum for daytime naps export const SLEEP_NIGHT_START = 0.667; // gameTime when night begins (DAY_HOURS/TOTAL_HOURS) // Productivity need export const PRODUCTIVITY_DECAY_PER_TICK = 0.02; export const PRODUCTIVITY_THRESHOLD = 40; export const PRODUCTIVITY_RECOVERY_RATE = 0.5; // Day/night cycle export const DAY_NIGHT_RATIO = 2; // day is 2x as long as night export const DAY_HOURS = 12; // game hours of daytime export const NIGHT_HOURS = DAY_HOURS / DAY_NIGHT_RATIO; // 6 hours of night export const TOTAL_HOURS = DAY_HOURS + NIGHT_HOURS; // 18 hours total cycle export const SUNSET_DURATION_HOURS = 1; // game hours for sunset transition export const SUNRISE_DURATION_HOURS = 1; // game hours for sunrise transition export const NIGHT_DARKNESS = 0.45; // max overlay opacity (0-1) // Directions (row index in spritesheet) export const Direction = { DOWN: 0, LEFT: 1, UP: 2, RIGHT: 3, }; // Accessory slot names in z-order (bottom to top rendering) export const ACCESSORY_SLOTS = [ 'bottom', 'feet', 'chest', 'arm', 'shoulder', 'waist', 'back', 'facialHair', 'haircut', 'hat', ]; // Portrait-only slots (facial features for close-up portraits) export const PORTRAIT_SLOTS = ['brows', 'eyes', 'mouths']; // Mapping from sprite accessory slot names to portrait folder names // (some folders are pluralized in the portrait assets) export const SPRITE_TO_PORTRAIT_FOLDER = { arm: 'arms', back: 'back', bottom: 'bottom', chest: 'chest', facialHair: 'facialHair', // feet: no portrait equivalent haircut: 'haircuts', hat: 'hats', shoulder: 'shoulders', waist: 'waist', }; // Social interactions export const AWARENESS_RADIUS = 5; // Manhattan distance in tiles export const FACING_DURATION = 10; // ticks (1s) export const PAUSING_DURATION = 15; // ticks (1.5s) export const EMOTING_DURATION = 20; // ticks (2s) export const SOCIAL_GLOBAL_COOLDOWN = 75; // ticks (7.5s) export const SOCIAL_PAIR_COOLDOWN = 450; // ticks (45s) export const PROPOSAL_EMOTING_DURATION = 30; // 3 seconds - longer for dramatic effect // Camera mode commands export const MAX_NPC_COUNT = 50; // Terrain types for procedural map export const Terrain = { GRASS: 0, WATER: 1, DIRT: 2, STONE: 3, }; // LPC tileset constants (32x32 tiles scaled 1.5x to match TILE_SIZE=48) export const TILESET_TILE_SIZE = 32; export const LPC_COLS = 3; // terrain tilesets are 3 cols wide (96px / 32px) export const TILESET_SCALE = TILE_SIZE / TILESET_TILE_SIZE; // 1.5 export const TREE_TILESET_COLS = 8; // treesnstone.png is 8 cols wide (256px / 32px) // Berry plant spritesheet (berries.png): 3 cols x 2 rows, 32x32 tiles // Each phase is 1 col wide, 2 rows tall (top foliage + bottom trunk) export const BERRY_COLS = 3; export const BerryPhase = { GROWING: 0, // col 0: developing berries RIPE: 1, // col 1: full red berries, ready to pick PICKED: 2, // col 2: bare plant, regrowing };