Files
novafarma/scripts/generate_assets_dark.py
David Kotnik 349aa917db Dolina Smrti V6.0 - Dark Survival style pivot
MAJOR CHANGES:
- Complete art style change from anime/cute to Dark Survival
- Deleted all anime-style assets (229 files)
- New post-apocalyptic visual style: gritty, realistic, weathered

NEW ASSETS (in progress):
- kai_markovic.png + 18 animation frames (front/back/left idle/walk/work)
- Dark Survival style with pink-green dreadlocks, plugs, piercings

NEW SCRIPTS:
- generate_v6_final.py: Main V6.0 generator (413 assets registry)
- generate_assets_dark.py: Dark Survival style generator
- generate_assets_full.py: Full registry generator

REGISTRY (413 assets):
- npcs: 117 (Kai, Gronk, Viktor + animations)
- environment: 104 (18 biomes with tiles)
- items: 94 (weapons, medical, food, tools)
- buildings: 29, ui: 28, mutanti: 21, zivali: 12, bosses: 8

Style specs:
- Cinematic 2D, hand-drawn, post-apocalyptic
- Transparent backgrounds (alpha channel)
- NO anime/pixel art/voxel (negative prompt enforced)
- 32x32 tiles, 48-64px characters, 128px bosses
2025-12-28 23:18:30 +01:00

635 lines
30 KiB
Python

#!/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()