const gameData = { // Characters (both player characters and enemies) characters: { // Playable characters teddy: { name: "Teddy", type: "player", backstory: "an old loyal dog with a surprisingly wise bark", goal: "to protect his friends and find tasty treats", abilities: [ { name: 'poop', damage: 8, bulletSpeed: 0.007, visual: { type: 'emoji', content: 'đŸ’©', size: 0.03 }, trailEffect: true, trailColor: "#8B4513" } ], abilityText: { bark: ["WOOF!", "ARF ARF!", "GRRR!", "BARK!", "BOW WOW!"], collision: ["*whimpers*", "*sad howl*"] }, sprites: { normal: '/static/shooter/character_images/teddy_normal.png', hit: '/static/shooter/character_images/teddy_hit.png' }, dashSpeed: 0.08, // sound: color: '#8B4513', health: 40, speed: 0.004 }, "nicky": { "type": "player", "name": "Nicky", "health": 50, "speed": 0.005, "abilities": [ { "name": "denial_shot", "damage": 10, "bulletSpeed": 0.005, "visual": { "type": "emoji", "content": "🚿", "size": 0.07 }, "trailEffect": true, "trailColor": "#ff6600", "wavy": false }], "abilityText": { "denial_shot": ["It wasn't me!", "I didn't do it!", "Messy, shower time!"] }, "sprites": { "normal": "/static/shooter/character_images/nicky_normal.png", "hit": "/static/shooter/character_images/nicky_hit.png" } }, jx: { name: "JX", type: "player", backstory: "an AI researcher with a passion for basketball", goal: "to restore balance to the sports world", abilities: [ { name: 'basketball', damage: 10, bulletSpeed: 0.006, visual: { type: 'emoji', // Can be 'emoji', 'image', or 'gif' content: '🏀', // Emoji character or URL to image/gif size: 0.04 // Optional size override }, trailEffect: true, trailColor: "#ff6600" }, ], abilityText: { basketball: ["AND ONE!", "I HAVE NO ENEMY!", "ABA DANCE!", "DID YOU KNOW?", "LIGHT WEIGHT BABY!", "YEAH BUDDY!"], collision: ["FOUL!"] }, sprites: { normal: '/static/shooter/character_images/jx_home.png', hit: '/static/shooter/character_images/jx_funny.png' }, dashSpeed: 0.1, sound: playBasketballSound, color: '#ff4500', health: 50, speed: 0.005 }, jh: { name: "JH", type: "player", backstory: "a dance afficionado with a love for food", goal: "to create harmony through food and music", abilities: [ { name: 'pizza', damage: 5, bulletSpeed: 0.007 }, { name: 'photography', damage: 12, bulletSpeed: 0.006 }, ], abilityText: { pizza: ["FRIED RICE!", "KIMCHI BOKKEUMBAP!", "JJAJANGMYEON!", "GRRRRRR!"], photography: ["CHEESE!", "PERFECT LIGHT!", "HOLD STILL!", "GET IN FRAME!"], collision: ['OUCHIE'] }, sprites: { normal: '/static/shooter/character_images/jh_bike.png', hit: '/static/shooter/character_images/jh_confused.png' }, dashSpeed: 0.1, sound: playZombieSound, color: '#00ff00', health: 50, speed: 0.005, fireRate: 500, }, bubu: { name: "Bubu", type: "player", backstory: "a legendary toddler with super cute abilities", goal: "to find all the missing pandas and sippy cups", abilities: [ { name: 'tear', damage: 15, bulletSpeed: 0.005}, { name: 'stuffedPanda', damage: 20, bulletSpeed: 0.003, wavy: true }, { name: 'sippy', damage: 10, bulletSpeed: 2 }, ], abilityText: { tear: ["WA WA!", "I'M LUA!", "BUBU DANCE!", "HELP ME!", "GO AWAY!", "EGG YOU!", "I'M BUSY!", "MARSUPIEL SUE!", "THIS IS WET!", "THAT MY BLANKET"], stuffedPanda: ["WHERE ARE MY PANDAS?", "I'M NOT A PANDA!"], sippy: ["MORE MILK!", "MY PURPLE BOTTLE!"], collision: ['WA WA!'] }, sprites: { normal: '/static/shooter/character_images/bubu.png', hit: '/static/shooter/character_images/bubu_sleep.png' }, dashSpeed: 0.1, sound: playCrySound, color: '#0000ff', health: 50, speed: 0.005 }, // Enemy characters "mop": { "type": "enemy", "name": "Mop Monster", "health": 20, "speed": 0.002, "abilities": [ { "name": "sweep", "damage": 10, "bulletSpeed": 0.005, "visual": { "type": "emoji", "content": "đŸ§č", "size": 0.04 }, "trailEffect": true, "trailColor": "#ff6600", "wavy": true }], "abilityText": { "sweep": ["I will sweep you away!", "You can't escape my cleaning powers!"] }, "sprites": { "normal": "/static/shooter/character_images/nicky/mop.png", "hit": "/static/shooter/character_images/nicky/mop_cry.png" } }, "pee": { "type": "enemy", "name": "Sentient puddle of pee", "health": 20, "speed": 0.002, "abilities": [ { "name": "splash", "damage": 10, "bulletSpeed": 0.005, "visual": { "type": "emoji", "content": "💩", "size": 0.04 }, "trailEffect": true, "trailColor": "#ff6600", "wavy": false }], "abilityText": { "sweep": ["pew pew"] }, "sprites": { "normal": "/static/shooter/character_images/nicky/pee.png", "hit": "/static/shooter/character_images/nicky/pee.png" } }, "old_lady": { "type": "boss", "name": "The Mythical Old Lady", "health": 1000, "speed": 0.003, "abilities": [ { "type": "special", "pattern": "radial", "name": "blame_shift", "damage": 10, "bulletSpeed": 0.007, "visual": { "type": "emoji", "content": "đŸ‘”", "size": 0.05 }, "trailEffect": true, "trailColor": "#ffcc00", "wavy": true }, { "type": "attack", "pattern": "targeted", "name": "truth_spray", "damage": 10, "bulletSpeed": 0.006, "visual": { "type": "emoji", "content": "🌊", "size": 0.06 }, "trailEffect": true, "trailColor": "#00ccff", "wavy": false }, { "name": "summonBots", "type": "spawn", "cooldown": 15000, "count": 3, "enemyTypes": ["pee", "mop"] } ], "abilityText": { "blame_shift": ["It was YOU all along!", "Can't blame me this time!"], "truth_spray": ["Face the truth!", "No more lies!"] }, "sprites": { "normal": "/static/shooter/character_images/nicky/old_lady.png", "hit": "/static/shooter/character_images/nicky/old_lady_surprised.png" } }, }, // Levels with consolidated information "levels": [ { "name": "The Incident", "enemyCount": 4, "hasBoss": false, "background_image_desc": "A giant tiled bathroom with glowing toilet shrines", "background": "/static/shooter/bg_images/nicky/a_giant_tiled_bathroom_with_glowing_toilet.jpeg", "weathers": [], "collectibles": [], "enemies": ["mop", "pee"], "storyBeforeLevel": [ {"type": "levelStory", "text": "It started here. Cold tile. The scent of bleach and broken trust.\nA child was asked, ‘Who peed here?’\nAnd the legend
 was born."}, {"type": "dialogue", "text": "We were here before the lady
 and after.", "character": "pee"}, {"type": "levelStory", "text": "You remember the wet floor. The stench of betrayal. The tiny voice saying: ‘It wasn’t me
 an old lady did it.’"}, {"type": "dialogue", "text": "We clean your mess
 but you can’t clean your lies.", "character": "mop"} ], "storyAfterLevel": [ {"type": "dialogue", "text": "Okay
 so I remember this place. But it wasn’t her. I mean—was it?", "character": "nicky"}, {"type": "levelStory", "text": "Doubt drips slowly. Memory leaks. And ahead lies the Grid of Denial."} ] }, { "name": "Grid of Denial", "hasBoss": false, "enemyCount": 6, "background_image_desc": "Hallways of floating memories. Portraits twist and whisper.", "background": "/static/shooter/bg_images/nicky/cartoon_style_dark_hallway_at_the_dead.jpeg", "weathers": [], "collectibles": ["lightning"], "enemies": ["mop", "pee"], "storyBeforeLevel": [ {"type": "levelStory", "text": "You tried to seal the story with stubborn silence. But questions are persistent little beasts."}, {"type": "dialogue", "text": "You said it was an old lady
 but did you believe it?", "character": "pee"}, {"type": "dialogue", "text": "You’ve asked this before. I told you the truth!", "character": "nicky"}, {"type": "dialogue", "text": "The more you deny... the deeper we dwell.", "character": "mop"} ], "storyAfterLevel": [ {"type": "levelStory", "text": "He dodged them all — the doubts, the accusations. But for how long can a lie wear the mask of conviction?"}, {"type": "dialogue", "text": "Just keep moving. Don’t look back. And definitely don’t step in that.", "character": "nicky"} ] }, { "name": "The Old Lady", "hasBoss": true, "enemyCount": 3, "background_image_desc": "a_surreal_cathedral_like_throne_room_made_entirely", "background": "/static/shooter/bg_images/nicky/a_surreal_cathedral_like_throne_room_made_entirely.jpeg", "weathers": [], "collectibles": ["lightning"], "enemies": ["pee", "mop"], "boss": ["old_lady"], "storyBeforeLevel": [ {"type": "levelStory", "text": "And then she arrived. No door opened, no footsteps sounded. But suddenly — she was there. The Old Lady."}, {"type": "dialogue", "text": "You
 you’re not real. You’re just a joke. A joke I told!", "character": "nicky"}, {"type": "dialogue", "text": "I’ve always been here. Every time you pointed fingers, every time you said my name.", "character": "old_lady"}, {"type": "dialogue", "text": "I didn’t mean it. I was just a kid...", "character": "nicky"}, {"type": "dialogue", "text": "And yet, you built me. Word by word. Denial by denial. I am your myth.", "character": "old_lady"}, {"type": "dialogue", "text": "You told the world I peed. So now, I reign.", "character": "old_lady"}, {"type": "levelStory", "text": "This was no longer a game of blame. This was a reckoning."} ], "storyAfterLevel": [ {"type": "dialogue", "text": "Set me free, little one. I was never meant to exist.", "character": "old_lady"}, {"type": "dialogue", "text": "I'm sorry", "character": "nicky"}, {"type": "levelStory", "text": "And just like that, she was gone. No more excuses. No more hiding. Just a kid, and the echo of a lie turned legend."}, {"type": "dialogue", "text": "So... anyone know a good carpet cleaner? Asking for a friend.", "character": "nicky"} ] } ], "story": { "intro": "Some truths are soaked in lies. Others
 in pee.", "finale": "And thus ended The Legend of Nicky: Bladder of Lies, Denier of Puddles. May we all remember that sometimes the old lady who peed on the floor... was inside us all along." }, "titleScreenBackground_image_desc": "urban skyline at sunrise", "settings": { "titleScreenBackground": "/static/shooter/bg_images/nicky/parody_of_game_of_throne_replace_the.jpeg", "titleScreenText": "The Legend of Nicky:
Bladder of Lies" } };