#!/usr/bin/env python3 """ DolinaSmrti DARK SURVIVAL Asset Generator Post-Apocalyptic Slovenia Style - 9000+ Assets Cinematic 2D, Hand-drawn, Gritty, Realistic """ import os import json import time import uuid import requests from pathlib import Path from typing import List, Dict # Configuration COMFYUI_URL = "http://127.0.0.1:8000" OUTPUT_DIR = "/Users/davidkotnik/repos/novafarma/assets/images" # ============================================================================ # DARK SURVIVAL STYLE PROMPTS # ============================================================================ # Pozitivni prompt - kaj ลพelimo STYLE_PREFIX = """cinematic 2d game asset, hand-drawn dark survival style, detailed textures, weathered, post-apocalyptic, industrial decay, realistic proportions, gritty atmosphere, rust and dirt color palette, overgrown nature, concrete ruins, sharp details, serious tone, isolated on transparent background alpha channel, """ # Negativni prompt - ฤesa NOฤŒEMO NEGATIVE_PROMPT = """anime, manga, cute, bright colors, kawaii, pixelated, pixel art, voxel, 3d render, cartoonish, childish, chibi, happy, cheerful, colorful, fantasy, magical sparkles, clean, pristine, new, shiny, watermark, text, signature, blurry, low quality""" # ============================================================================ # MASTER REGISTRY - POST-APOCALYPTIC ASSETS # ============================================================================ def generate_dark_registry() -> List[Dict]: """Generate post-apocalyptic survival asset registry""" assets = [] # ======================================================================== # 1. SURVIVORS & NPCs (~150) # ======================================================================== survivors = [ # Main Characters ("kai_survivor", "male survivor, rugged, torn clothes, bandages, dirty face, survival gear, backpack, 48px sprite"), ("ana_survivor", "female survivor, practical clothing, tool belt, determined expression, weathered, 48px sprite"), ("grok_mutant", "mutated humanoid, radiation burns, torn clothing, imposing figure, 64px sprite"), # Survivor Types ("survivor_scavenger", "scavenger survivor, gas mask, heavy backpack, layered dirty clothing"), ("survivor_soldier", "ex-military survivor, tactical gear, worn camouflage, combat ready"), ("survivor_medic", "field medic, bloodstained coat, medical bag, exhausted"), ("survivor_mechanic", "mechanic survivor, oil-stained overalls, wrench, goggles"), ("survivor_farmer", "apocalypse farmer, patched clothing, improvised tools, weathered face"), ("survivor_trader", "wasteland trader, cart of goods, protective clothing, suspicious"), ("survivor_hunter", "wasteland hunter, animal pelts, crossbow, tribal markings"), ("survivor_elder", "old survivor, scars, wisdom, makeshift walking stick"), ("survivor_child", "young survivor, oversized clothes, determined, dirty"), # Hostile NPCs ("raider_basic", "raider, leather armor, spikes, aggressive, makeshift weapon"), ("raider_chief", "raider boss, intimidating armor, trophies, brutal"), ("raider_sniper", "raider sniper, camouflage, long rifle, hidden"), ("bandit_thief", "wasteland thief, dark clothing, quick, sneaky"), ("cultist_member", "apocalypse cultist, robes, strange symbols, fanatical"), ("cultist_leader", "cult leader, ornate robes, staff, commanding"), # Special NPCs ("scientist_bunker", "bunker scientist, hazmat suit, clipboard, nervous"), ("doctor_field", "wasteland doctor, surgical tools, blood-stained, tired"), ("blacksmith_wasteland", "post-apocalyptic blacksmith, forge apron, burns, strong"), ("radio_operator", "radio operator, headphones, electronics, isolated"), ] for name, prompt in survivors: assets.append({"cat": "npcs", "file": f"{name}.png", "prompt": prompt, "size": "48-64px"}) # Animation frames for direction in ["front", "back", "left", "right"]: for frame in ["idle1", "idle2", "walk1", "walk2", "walk3", "walk4"]: assets.append({ "cat": "npcs", "file": f"{name}_{direction}_{frame}.png", "prompt": f"{prompt}, {direction} facing view, {frame} animation frame", "size": "48-64px" }) # ======================================================================== # 2. MUTANTS & MONSTERS (~200) # ======================================================================== mutants = [ # Infected/Zombies ("zombie_fresh", "freshly turned zombie, recent victim, bloody, shambling"), ("zombie_rotten", "decomposed zombie, exposed bones, putrid, slow"), ("zombie_bloated", "bloated zombie, swollen, toxic gas, disgusting"), ("zombie_crawler", "legless zombie, crawling, desperate, grasping"), ("zombie_runner", "fast zombie, rage, sprinting, aggressive"), ("zombie_screamer", "screamer zombie, alerting, open mouth, loud"), ("zombie_giant", "giant zombie, massive, strong, slow, terrifying"), # Radiation Mutants ("mutant_humanoid", "mutated human, extra limbs, radiation burns, hostile"), ("mutant_beast", "mutated beast, glowing eyes, twisted body, predator"), ("mutant_dog", "mutated dog, hairless, sores, pack hunter"), ("mutant_rat_giant", "giant mutant rat, size of dog, diseased, aggressive"), ("mutant_crow", "mutant crow, large, intelligent, circling"), ("mutant_boar", "mutated boar, tusks, armored hide, charging"), ("mutant_wolf", "mutated wolf, glowing eyes, pack alpha, deadly"), ("mutant_bear", "irradiated bear, massive, unstoppable, territorial"), # Anomalies ("anomaly_shadow", "shadow anomaly, darkness incarnate, flickering, deadly"), ("anomaly_electric", "electric anomaly, crackling energy, floating, dangerous"), ("anomaly_fire", "fire anomaly, burning, spreading, destructive"), ("anomaly_acid", "acid pool anomaly, bubbling, corrosive, stationary"), # Wildlife (mutated) ("wolf_feral", "feral wolf, pack predator, aggressive, hungry"), ("bear_irradiated", "irradiated bear, glowing, massive, territorial"), ("deer_mutant", "mutated deer, extra antlers, aggressive, territorial"), ("crow_swarm", "murder of crows, ominous, circling, scavengers"), ] for name, prompt in mutants: assets.append({"cat": "mutanti", "file": f"{name}.png", "prompt": prompt}) # ======================================================================== # 3. BOSSES (~30) # ======================================================================== bosses = [ ("boss_zombie_horde_leader", "zombie horde leader, armored, commanding, massive, 128px"), ("boss_mutant_alpha", "alpha mutant, evolved, intelligent, deadly, 128px"), ("boss_raider_warlord", "raider warlord, throne of bones, brutal, 128px"), ("boss_irradiated_giant", "irradiated giant, glowing, unstoppable, 128px"), ("boss_shadow_entity", "shadow entity boss, darkness, consuming, 128px"), ("boss_machine_sentinel", "machine sentinel, military robot, corrupted, 128px"), ("boss_cult_demon", "summoned demon, cult ritual, hellfire, 128px"), ("boss_mutant_queen", "mutant queen, egg sacs, birthing horrors, 128px"), ] for name, prompt in bosses: assets.append({"cat": "bosses", "file": f"{name}.png", "prompt": prompt}) # ======================================================================== # 4. ENVIRONMENT - TERRAIN TILES (32x32) (~300) # ======================================================================== terrain = [ # Ground ("ground_concrete_cracked", "cracked concrete ground tile, weeds growing, 32x32"), ("ground_concrete_rubble", "concrete rubble tile, debris, 32x32"), ("ground_asphalt_broken", "broken asphalt road tile, potholes, 32x32"), ("ground_dirt_muddy", "muddy dirt tile, footprints, 32x32"), ("ground_dirt_dry", "dry cracked earth tile, drought, 32x32"), ("ground_grass_dead", "dead grass tile, brown, patchy, 32x32"), ("ground_grass_overgrown", "overgrown grass tile, wild, weeds, 32x32"), ("ground_snow_dirty", "dirty snow tile, ash mixed, 32x32"), ("ground_sand_radioactive", "radioactive sand tile, glowing particles, 32x32"), ("ground_metal_rusted", "rusted metal floor tile, industrial, 32x32"), ("ground_tile_broken", "broken floor tile, interior, debris, 32x32"), ("ground_wood_rotting", "rotting wooden floor tile, warped, 32x32"), # Water ("water_contaminated", "contaminated water tile, green tint, toxic, 32x32"), ("water_stagnant", "stagnant water tile, murky, mosquitoes, 32x32"), ("water_radioactive", "radioactive water tile, glowing, deadly, 32x32"), # Special ("ground_crater", "explosion crater tile, scorched, 32x32"), ("ground_toxic_spill", "toxic spill tile, chemical, warning, 32x32"), ("ground_blood_stain", "blood stained ground tile, dried, 32x32"), ] for name, prompt in terrain: assets.append({"cat": "environment", "file": f"{name}.png", "prompt": prompt}) # ======================================================================== # 5. ENVIRONMENT - OBJECTS (~400) # ======================================================================== env_objects = [ # Ruins & Structures ("ruin_wall_brick", "ruined brick wall segment, crumbling, bullet holes"), ("ruin_wall_concrete", "crumbled concrete wall, rebar exposed, graffiti"), ("ruin_pillar", "collapsed pillar, debris, overgrown"), ("ruin_doorframe", "abandoned doorframe, door missing, damaged"), ("ruin_window_frame", "broken window frame, glass shards, boarded"), ("ruin_stairs", "ruined staircase, collapsed, dangerous"), ("ruin_floor_hole", "floor hole, debris below, dangerous"), # Vehicles ("vehicle_car_rusted", "rusted abandoned car, flat tires, looted"), ("vehicle_car_burned", "burned out car wreck, skeleton, charred"), ("vehicle_truck_military", "abandoned military truck, damaged, supplies"), ("vehicle_bus_crashed", "crashed bus, on side, broken windows"), ("vehicle_motorcycle", "abandoned motorcycle, rusted, parts missing"), ("vehicle_bicycle", "rusted bicycle, bent, forgotten"), ("vehicle_helicopter_wreck", "crashed helicopter, burned, military"), ("vehicle_tank_destroyed", "destroyed tank, explosion damage, monument"), # Urban Objects ("object_streetlight_bent", "bent streetlight, not working, rusted"), ("object_mailbox_rusted", "rusted mailbox, dented, forgotten"), ("object_bench_broken", "broken park bench, weathered, wood rotting"), ("object_trash_can", "overturned trash can, garbage spilled"), ("object_dumpster", "abandoned dumpster, overflowing, rusted"), ("object_shopping_cart", "abandoned shopping cart, bent, rusted"), ("object_phone_booth", "destroyed phone booth, glass broken, graffiti"), ("object_newspaper_box", "rusted newspaper box, faded headlines"), ("object_hydrant_broken", "broken fire hydrant, leaking, rusted"), ("object_sign_stop", "bent stop sign, bullet holes, faded"), ("object_sign_warning", "radiation warning sign, faded, ominous"), # Nature (Post-Apocalyptic) ("tree_dead_large", "large dead tree, no leaves, gnarled, haunting"), ("tree_dead_small", "small dead tree, twisted, creepy"), ("tree_dying", "dying tree, few leaves, diseased, sad"), ("tree_overgrown", "overgrown tree, wild, reclaiming, nature"), ("bush_thorny", "thorny bush, overgrown, barrier, wild"), ("bush_dead", "dead bush, brown, brittle, abandoned"), ("grass_tall_wild", "tall wild grass, hiding dangers, swaying"), ("weeds_overgrown", "overgrown weeds, concrete cracks, nature reclaiming"), ("vines_climbing", "climbing vines on wall, overgrown, nature"), ("mushrooms_toxic", "toxic mushrooms, glowing, dangerous"), ("corpse_skeleton", "skeleton remains, old, clothes remnants"), ("corpse_fresh", "recent corpse, warning, scavengers nearby"), # Industrial ("barrel_toxic", "toxic waste barrel, leaking, hazard symbols"), ("barrel_oil", "rusted oil barrel, fuel source, valuable"), ("crate_wooden_damaged", "damaged wooden crate, broken open"), ("crate_military", "military supply crate, sealed, valuable"), ("pipe_large_rusted", "large rusted pipe, drainage, hiding spot"), ("tank_water_rusted", "rusted water tank, possibly full, valuable"), ("generator_broken", "broken generator, parts salvageable"), ("machinery_rusted", "rusted industrial machinery, dangerous"), ("fence_chainlink_torn", "torn chainlink fence, opening, barrier"), ("fence_barbed_wire", "barbed wire, dangerous, barrier, wound"), ("sandbag_wall", "sandbag wall, fortification, cover"), ("concrete_barrier", "concrete road barrier, defensive, cover"), ] for name, prompt in env_objects: assets.append({"cat": "environment", "file": f"{name}.png", "prompt": prompt}) # ======================================================================== # 6. BUILDINGS (~100) # ======================================================================== buildings = [ # Shelters ("shelter_makeshift", "makeshift shelter, tarps, wood, survivor camp"), ("shelter_bunker_entrance", "bunker entrance, blast door, military"), ("shelter_basement", "basement entrance, cellar door, hidden"), ("shelter_tent_military", "military tent, camouflage, supplies"), ("shelter_shack", "survivor shack, scrap materials, patched"), # Ruined Buildings ("building_house_ruined", "ruined house, collapsed roof, looted"), ("building_apartment_ruined", "ruined apartment building, floors exposed"), ("building_shop_looted", "looted shop, broken windows, empty"), ("building_hospital_abandoned", "abandoned hospital, eerie, supplies"), ("building_school_ruined", "ruined school, desks, children drawings"), ("building_church_destroyed", "destroyed church, steeple fallen, sanctuary"), ("building_factory_abandoned", "abandoned factory, machinery, industrial"), ("building_warehouse", "ruined warehouse, storage, scavenging"), ("building_gas_station", "abandoned gas station, pumps rusted"), ("building_police_station", "ransacked police station, cells, weapons"), ("building_fire_station", "abandoned fire station, truck rusted"), # Functional Structures ("workstation_forge", "wasteland forge, scrap metal, fire, crafting"), ("workstation_workbench", "survivor workbench, tools, repairs"), ("workstation_chemistry", "chemistry station, beakers, drugs, medicine"), ("workstation_cooking", "cooking station, fire pit, pot, meat"), ("storage_chest_metal", "locked metal chest, valuable, heavy"), ("storage_locker", "rusted locker, storage, secured"), ("storage_safe", "old safe, locked, valuable inside"), ("defenses_barricade", "survivor barricade, wood, metal, spikes"), ("defenses_watchtower", "makeshift watchtower, observation, defense"), ("defenses_trap_spike", "spike trap, hidden, deadly"), ("defenses_trap_bear", "bear trap, rusted, dangerous"), ] for name, prompt in buildings: assets.append({"cat": "buildings", "file": f"{name}.png", "prompt": prompt}) # ======================================================================== # 7. ITEMS & WEAPONS (~500) # ======================================================================== # Melee Weapons melee = [ ("weapon_pipe", "metal pipe weapon, rusty, blood stains"), ("weapon_crowbar", "crowbar, multi-use, worn"), ("weapon_machete", "machete, jungle knife, worn blade"), ("weapon_axe_fire", "fire axe, red, emergency, worn"), ("weapon_axe_wood", "wood chopping axe, handle worn"), ("weapon_baseball_bat", "baseball bat, nails added, brutal"), ("weapon_knife_combat", "combat knife, tactical, sharp"), ("weapon_knife_kitchen", "kitchen knife, improvised weapon"), ("weapon_hammer", "claw hammer, rusted, bloody"), ("weapon_wrench", "large wrench, heavy, blunt"), ("weapon_shovel", "sharpened shovel, improvised, deadly"), ("weapon_pickaxe", "pickaxe, mining tool, weapon"), ("weapon_sledgehammer", "sledgehammer, heavy, devastating"), ("weapon_sword_makeshift", "makeshift sword, sharpened metal"), ("weapon_spear", "wooden spear, sharpened tip, primitive"), ] for name, prompt in melee: assets.append({"cat": "items", "file": f"{name}.png", "prompt": prompt}) # Ranged Weapons ranged = [ ("weapon_pistol", "worn pistol, 9mm, reliable"), ("weapon_revolver", "old revolver, powerful, limited ammo"), ("weapon_shotgun", "pump shotgun, close range, devastating"), ("weapon_rifle_hunting", "hunting rifle, scope, accurate"), ("weapon_rifle_assault", "assault rifle, military, automatic"), ("weapon_smg", "submachine gun, compact, fast"), ("weapon_crossbow", "crossbow, silent, reusable ammo"), ("weapon_bow_makeshift", "makeshift bow, primitive, quiet"), ("weapon_molotov", "molotov cocktail, fire bomb, bottle"), ("weapon_grenade", "fragmentation grenade, military, deadly"), ("weapon_pipe_bomb", "pipe bomb, improvised explosive"), ] for name, prompt in ranged: assets.append({"cat": "items", "file": f"{name}.png", "prompt": prompt}) # Ammo ammo = [ ("ammo_9mm", "9mm ammunition box, pistol rounds"), ("ammo_shotgun", "shotgun shells, red, buckshot"), ("ammo_rifle", "rifle ammunition, .308, box"), ("ammo_arrow", "crossbow bolts, quiver, reusable"), ] for name, prompt in ammo: assets.append({"cat": "items", "file": f"{name}.png", "prompt": prompt}) # Medical medical = [ ("med_bandage", "dirty bandage, first aid, cloth"), ("med_medkit", "military first aid kit, valuable"), ("med_painkillers", "painkiller bottle, pills, relief"), ("med_antibiotics", "antibiotic pills, infection cure"), ("med_morphine", "morphine syringe, powerful, addictive"), ("med_antidote", "antidote vial, poison cure, rare"), ("med_rad_pills", "anti-radiation pills, potassium iodide"), ("med_blood_bag", "blood bag, transfusion, rare"), ("med_surgical_kit", "surgical tools, operations, sterile"), ("med_splint", "makeshift splint, broken bones"), ] for name, prompt in medical: assets.append({"cat": "items", "file": f"{name}.png", "prompt": prompt}) # Food & Water food = [ ("food_canned_beans", "canned beans, preserved, sustenance"), ("food_canned_meat", "canned meat, spam, protein"), ("food_canned_fruit", "canned fruit, sweet, valuable"), ("food_mre", "military MRE, complete meal, rare"), ("food_dried_meat", "dried meat, jerky, long lasting"), ("food_raw_meat", "raw meat, needs cooking, dangerous"), ("food_mushrooms", "foraged mushrooms, careful, poisonous risk"), ("food_berries", "wild berries, foraged, nutrition"), ("water_bottle_dirty", "dirty water bottle, needs purification"), ("water_bottle_clean", "clean water bottle, safe, valuable"), ("water_canteen", "military canteen, durable, reliable"), ("food_alcohol", "bottle of alcohol, trade good, medical"), ] for name, prompt in food: assets.append({"cat": "items", "file": f"{name}.png", "prompt": prompt}) # Crafting Materials crafting = [ ("material_scrap_metal", "scrap metal, salvage, crafting"), ("material_wood_plank", "wooden plank, building, fuel"), ("material_cloth_dirty", "dirty cloth, bandages, repairs"), ("material_duct_tape", "duct tape roll, repairs, valuable"), ("material_rope", "rope coil, climbing, binding"), ("material_wire", "electrical wire, electronics, traps"), ("material_nails", "box of nails, building, traps"), ("material_screws", "bag of screws, repairs, building"), ("material_glass", "glass shards, weapons, traps"), ("material_chemicals", "chemical compounds, crafting, dangerous"), ("material_gunpowder", "gunpowder, explosives, ammo crafting"), ("material_electronics", "salvaged electronics, components, repair"), ("material_fuel", "fuel canister, gasoline, valuable"), ("material_leather", "leather scraps, armor, repairs"), ] for name, prompt in crafting: assets.append({"cat": "items", "file": f"{name}.png", "prompt": prompt}) # Tools tools = [ ("tool_flashlight", "flashlight, batteries, darkness"), ("tool_lockpick", "lockpick set, breaking in, valuable"), ("tool_multitool", "multitool, swiss army, useful"), ("tool_binoculars", "binoculars, scouting, military"), ("tool_compass", "compass, navigation, survival"), ("tool_rope_grapple", "grappling hook, climbing, access"), ("tool_geiger_counter", "geiger counter, radiation detection"), ("tool_gas_mask", "gas mask, protection, filters"), ("tool_radio", "handheld radio, communication, batteries"), ("tool_lighter", "zippo lighter, fire starting, reliable"), ("tool_matches", "matchbox, fire starting, limited"), ("tool_flare", "flare, signaling, light source"), ] for name, prompt in tools: assets.append({"cat": "items", "file": f"{name}.png", "prompt": prompt}) # Armor/Clothing armor = [ ("armor_jacket_leather", "worn leather jacket, basic protection"), ("armor_vest_kevlar", "kevlar vest, bullet protection, worn"), ("armor_helmet_military", "military helmet, head protection"), ("armor_gas_mask", "gas mask, full face, apocalypse"), ("armor_hazmat_suit", "hazmat suit, radiation protection"), ("armor_boots_combat", "combat boots, sturdy, reliable"), ("armor_gloves_tactical", "tactical gloves, grip, protection"), ("armor_backpack_military", "military backpack, large capacity"), ("armor_backpack_civilian", "civilian backpack, worn, storage"), ] for name, prompt in armor: assets.append({"cat": "items", "file": f"{name}.png", "prompt": prompt}) # ======================================================================== # 8. UI ELEMENTS (~100) # ======================================================================== ui = [ # Health/Status ("ui_health_bar", "health bar, red, blood, gritty"), ("ui_stamina_bar", "stamina bar, yellow, exhaustion"), ("ui_hunger_bar", "hunger bar, empty stomach icon"), ("ui_thirst_bar", "thirst bar, water drop icon"), ("ui_radiation_bar", "radiation bar, hazard symbol, green glow"), # Icons ("ui_icon_infected", "infected status icon, biohazard"), ("ui_icon_bleeding", "bleeding status icon, blood drops"), ("ui_icon_poisoned", "poisoned status icon, skull"), ("ui_icon_broken_limb", "broken limb icon, bone crack"), ("ui_icon_hungry", "hungry icon, empty stomach"), ("ui_icon_thirsty", "thirsty icon, water drop empty"), ("ui_icon_cold", "cold icon, snowflake, freezing"), ("ui_icon_hot", "heat icon, sun, overheating"), # Buttons ("ui_button_inventory", "inventory button, backpack icon, gritty"), ("ui_button_map", "map button, worn paper, gritty"), ("ui_button_crafting", "crafting button, gear icon, gritty"), ("ui_button_skills", "skills button, person icon, gritty"), # Frames ("ui_frame_inventory", "inventory frame, metal, rusted edges"), ("ui_frame_dialog", "dialog frame, worn paper, dark"), ("ui_slot_item", "item slot, metal frame, worn"), ] for name, prompt in ui: assets.append({"cat": "ui", "file": f"{name}.png", "prompt": prompt}) return assets # ============================================================================ # COMFYUI WORKFLOW # ============================================================================ def create_dark_workflow(prompt_text: str, output_name: str, size: str = "512") -> dict: """Creates ComfyUI workflow optimized for dark survival style""" seed = int(time.time() * 1000) % 2147483647 # Parse size width = height = 512 if "32x32" in size or "32" in str(size): width = height = 256 # Generate larger, resize later elif "48" in str(size) or "64" in str(size): width = height = 512 elif "128" in str(size): width = height = 512 return { "1": { "class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "dreamshaper_8.safetensors"} }, "2": { "class_type": "EmptyLatentImage", "inputs": {"width": width, "height": height, "batch_size": 1} }, "3": { "class_type": "CLIPTextEncode", "inputs": {"text": STYLE_PREFIX + prompt_text, "clip": ["1", 1]} }, "4": { "class_type": "CLIPTextEncode", "inputs": {"text": NEGATIVE_PROMPT, "clip": ["1", 1]} }, "5": { "class_type": "KSampler", "inputs": { "seed": seed, "steps": 35, # More steps for detail "cfg": 8.0, # Higher CFG for more adherence to prompt "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": 1.0, "model": ["1", 0], "positive": ["3", 0], "negative": ["4", 0], "latent_image": ["2", 0] } }, "6": { "class_type": "VAEDecode", "inputs": {"samples": ["5", 0], "vae": ["1", 2]} }, "7": { "class_type": "SaveImage", "inputs": {"filename_prefix": output_name, "images": ["6", 0]} } } def queue_prompt(workflow: dict) -> str: try: response = requests.post(f"{COMFYUI_URL}/prompt", json={"prompt": workflow, "client_id": f"dark_{uuid.uuid4().hex[:8]}"}) return response.json().get("prompt_id") except: return None def wait_for_completion(prompt_id: str, timeout: int = 300) -> bool: start = time.time() while time.time() - start < timeout: try: response = requests.get(f"{COMFYUI_URL}/history/{prompt_id}") if prompt_id in response.json() and response.json()[prompt_id].get("outputs"): return True except: pass time.sleep(2) return False def download_image(prompt_id: str, output_path: Path) -> bool: try: history = requests.get(f"{COMFYUI_URL}/history/{prompt_id}").json() for node_output in history.get(prompt_id, {}).get("outputs", {}).values(): for img in node_output.get("images", []): params = {"filename": img["filename"], "subfolder": img.get("subfolder", ""), "type": "output"} response = requests.get(f"{COMFYUI_URL}/view", params=params) if response.status_code == 200: output_path.parent.mkdir(parents=True, exist_ok=True) output_path.write_bytes(response.content) return True return False except: return False def main(): print("=" * 70) print("๐Ÿ”ฅ DolinaSmrti DARK SURVIVAL Asset Generator") print(" Post-Apocalyptic Slovenia Style") print("=" * 70) # Check ComfyUI try: data = requests.get(f"{COMFYUI_URL}/system_stats", timeout=5).json() print(f"โœ… ComfyUI v{data['system']['comfyui_version']} running") except: print(f"โŒ ComfyUI not responding at {COMFYUI_URL}") print(" Start ComfyUI with: open /Applications/ComfyUI.app") return # Generate registry print("\n๐Ÿ“‹ Building Dark Survival Registry...") ASSETS = generate_dark_registry() print(f"๐Ÿ“Š Total Assets: {len(ASSETS)}") # Count existing existing = sum(1 for a in ASSETS if (Path(OUTPUT_DIR) / a["cat"] / a["file"]).exists()) print(f"โœ… Already Exist: {existing}") print(f"๐ŸŽฏ To Generate: {len(ASSETS) - existing}") print("\n๐Ÿ”ฅ Starting DARK SURVIVAL generation...\n") success, skip, fail = 0, 0, 0 for i, asset in enumerate(ASSETS, 1): output_path = Path(OUTPUT_DIR) / asset["cat"] / asset["file"] if output_path.exists(): skip += 1 continue print(f"[{i}/{len(ASSETS)}] ๐Ÿ”ฅ {asset['file']}") size = asset.get("size", "512") workflow = create_dark_workflow(asset["prompt"], asset["file"].replace(".png", ""), size) prompt_id = queue_prompt(workflow) if prompt_id and wait_for_completion(prompt_id) and download_image(prompt_id, output_path): print(f" โœ… SAVED") success += 1 else: print(f" โŒ FAILED") fail += 1 if i % 25 == 0: print(f"\n๐Ÿ“Š Progress: {success} โœ… | {skip} โญ๏ธ | {fail} โŒ\n") time.sleep(0.5) print("\n" + "=" * 70) print("๐Ÿ”ฅ DARK SURVIVAL GENERATION COMPLETE!") print(f"โœ… Successful: {success}") print(f"โญ๏ธ Skipped: {skip}") print(f"โŒ Failed: {fail}") if __name__ == "__main__": main()