better monster gen
Browse files
src/lib/components/MonsterGenerator/MonsterGenerator.svelte
CHANGED
@@ -46,12 +46,11 @@ Format your response as:
|
|
46 |
# Object Caption
|
47 |
{object description, also assess how rare the object is, the rarer the object the stronger the monster}
|
48 |
# Transformation Brainstorm
|
49 |
-
{
|
50 |
-
#
|
|
|
51 |
## Monster Visual Description
|
52 |
{ensure the creature uses all the unique attributes of the object}
|
53 |
-
## Monster Lore
|
54 |
-
...
|
55 |
\`\`\``;
|
56 |
|
57 |
const IMAGE_GENERATION_PROMPT = (concept: string) => `Extract ONLY the visual appearance from this monster concept and describe it in one concise sentence:
|
@@ -202,8 +201,8 @@ Focus on: colors, body shape, eyes, limbs, mouth, and key visual features. Omit
|
|
202 |
async function generateMonsterImage() {
|
203 |
state.currentStep = 'generating';
|
204 |
|
205 |
-
if (!fluxClient || !state.monsterConcept) {
|
206 |
-
throw new Error('Image generation service not available or no concept');
|
207 |
}
|
208 |
|
209 |
// Extract the visual description from the joy-caption output
|
@@ -245,9 +244,18 @@ Focus on: colors, body shape, eyes, limbs, mouth, and key visual features. Omit
|
|
245 |
throw new Error('Failed to extract visual description');
|
246 |
}
|
247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
try {
|
249 |
const output = await fluxClient.predict("/infer", [
|
250 |
-
`${state.imagePrompt}\nNow generate a Pokémon-Anime-style image of the monster in an idle pose with a white background. The monster should not be attacking or in motion. The full monster must be visible within the frame.`,
|
251 |
0, // seed
|
252 |
true, // randomizeSeed
|
253 |
1024, // width
|
@@ -309,14 +317,9 @@ Focus on: colors, body shape, eyes, limbs, mouth, and key visual features. Omit
|
|
309 |
const monsterNameMatch = state.monsterConcept.match(/^# (?!Object Caption|Transformation Brainstorm)(.+)$/m);
|
310 |
const monsterName = monsterNameMatch ? monsterNameMatch[1].trim() : 'Unknown Monster';
|
311 |
|
312 |
-
// Extract only the Monster Lore section for description
|
313 |
-
const loreMatch = state.monsterConcept.match(/## Monster Lore\s*\n([\s\S]*?)(?=##|$)/);
|
314 |
-
const monsterLore = loreMatch ? loreMatch[1].trim() : '';
|
315 |
-
|
316 |
// Debug logging
|
317 |
console.log('Extracted object description:', objectDescription);
|
318 |
console.log('Extracted monster name:', monsterName);
|
319 |
-
console.log('Extracted monster lore:', monsterLore);
|
320 |
|
321 |
// Create stats prompt - only ask for battle-related stats
|
322 |
const statsPrompt = `Based on this monster concept, generate a JSON object with battle stats and abilities:
|
@@ -355,6 +358,7 @@ The output should be formatted as a JSON instance that conforms to the JSON sche
|
|
355 |
"defence": {"type": "integer", "minimum": 0, "maximum": 100, "description": "Defensive/armor stat (0=paper thin, 100=impenetrable fortress)"},
|
356 |
"attack": {"type": "integer", "minimum": 0, "maximum": 100, "description": "Physical attack power (0=harmless, 100=devastating force)"},
|
357 |
"speed": {"type": "integer", "minimum": 0, "maximum": 100, "description": "Movement and reaction speed (0=immobile, 100=lightning fast)"},
|
|
|
358 |
"specialPassiveTraitDescription": {"type": "string", "description": "Describe a passive ability that gives this monster a unique advantage in battle"},
|
359 |
"attackActionName": {"type": "string", "description": "Name of the monster's primary damage-dealing attack (e.g., 'Flame Burst', 'Toxic Bite')"},
|
360 |
"attackActionDescription": {"type": "string", "description": "Describe how this attack damages the opponent and any special effects"},
|
@@ -365,7 +369,7 @@ The output should be formatted as a JSON instance that conforms to the JSON sche
|
|
365 |
"specialActionName": {"type": "string", "description": "Name of the monster's ultimate move (one use per battle)"},
|
366 |
"specialActionDescription": {"type": "string", "description": "Describe this powerful finishing move and its dramatic effects in battle"}
|
367 |
},
|
368 |
-
"required": ["rarity", "picletType", "height", "weight", "HP", "defence", "attack", "speed", "specialPassiveTraitDescription", "attackActionName", "attackActionDescription", "buffActionName", "buffActionDescription", "debuffActionName", "debuffActionDescription", "specialActionName", "specialActionDescription"]
|
369 |
}
|
370 |
\`\`\`
|
371 |
|
@@ -419,7 +423,7 @@ Write your response within \`\`\`json\`\`\``;
|
|
419 |
|
420 |
// Remove any extra fields not in our schema
|
421 |
const allowedFields = ['rarity', 'picletType', 'height', 'weight', 'HP', 'defence', 'attack', 'speed',
|
422 |
-
'specialPassiveTraitDescription', 'attackActionName', 'attackActionDescription',
|
423 |
'buffActionName', 'buffActionDescription', 'debuffActionName', 'debuffActionDescription',
|
424 |
'specialActionName', 'specialActionDescription', 'boostActionName', 'boostActionDescription',
|
425 |
'disparageActionName', 'disparageActionDescription'];
|
@@ -443,7 +447,7 @@ Write your response within \`\`\`json\`\`\``;
|
|
443 |
|
444 |
// Add the name, description, and tier that we extracted/mapped
|
445 |
parsedStats.name = monsterName;
|
446 |
-
parsedStats.description = monsterLore;
|
447 |
parsedStats.tier = tier;
|
448 |
|
449 |
// Ensure numeric fields are actually numbers
|
|
|
46 |
# Object Caption
|
47 |
{object description, also assess how rare the object is, the rarer the object the stronger the monster}
|
48 |
# Transformation Brainstorm
|
49 |
+
{brief thought on how to transform the object into a Pokémon-like creature}
|
50 |
+
# Monster Name
|
51 |
+
{monster name}
|
52 |
## Monster Visual Description
|
53 |
{ensure the creature uses all the unique attributes of the object}
|
|
|
|
|
54 |
\`\`\``;
|
55 |
|
56 |
const IMAGE_GENERATION_PROMPT = (concept: string) => `Extract ONLY the visual appearance from this monster concept and describe it in one concise sentence:
|
|
|
201 |
async function generateMonsterImage() {
|
202 |
state.currentStep = 'generating';
|
203 |
|
204 |
+
if (!fluxClient || !state.monsterConcept || !state.monsterStats) {
|
205 |
+
throw new Error('Image generation service not available or no concept/stats');
|
206 |
}
|
207 |
|
208 |
// Extract the visual description from the joy-caption output
|
|
|
244 |
throw new Error('Failed to extract visual description');
|
245 |
}
|
246 |
|
247 |
+
// Get tier for image quality enhancement
|
248 |
+
const tier = state.monsterStats.tier || 'medium';
|
249 |
+
const tierDescriptions = {
|
250 |
+
low: 'simple and basic design',
|
251 |
+
medium: 'detailed and well-crafted design',
|
252 |
+
high: 'highly detailed and impressive design with special effects',
|
253 |
+
legendary: 'extremely detailed and majestic design with dramatic lighting and aura effects'
|
254 |
+
};
|
255 |
+
|
256 |
try {
|
257 |
const output = await fluxClient.predict("/infer", [
|
258 |
+
`${state.imagePrompt}\nNow generate a Pokémon-Anime-style image of the monster in an idle pose with a white background. This is a ${tier} tier monster with ${tierDescriptions[tier as keyof typeof tierDescriptions]}. The monster should not be attacking or in motion. The full monster must be visible within the frame.`,
|
259 |
0, // seed
|
260 |
true, // randomizeSeed
|
261 |
1024, // width
|
|
|
317 |
const monsterNameMatch = state.monsterConcept.match(/^# (?!Object Caption|Transformation Brainstorm)(.+)$/m);
|
318 |
const monsterName = monsterNameMatch ? monsterNameMatch[1].trim() : 'Unknown Monster';
|
319 |
|
|
|
|
|
|
|
|
|
320 |
// Debug logging
|
321 |
console.log('Extracted object description:', objectDescription);
|
322 |
console.log('Extracted monster name:', monsterName);
|
|
|
323 |
|
324 |
// Create stats prompt - only ask for battle-related stats
|
325 |
const statsPrompt = `Based on this monster concept, generate a JSON object with battle stats and abilities:
|
|
|
358 |
"defence": {"type": "integer", "minimum": 0, "maximum": 100, "description": "Defensive/armor stat (0=paper thin, 100=impenetrable fortress)"},
|
359 |
"attack": {"type": "integer", "minimum": 0, "maximum": 100, "description": "Physical attack power (0=harmless, 100=devastating force)"},
|
360 |
"speed": {"type": "integer", "minimum": 0, "maximum": 100, "description": "Movement and reaction speed (0=immobile, 100=lightning fast)"},
|
361 |
+
"monsterLore": {"type": "string", "description": "Write a detailed background story for this monster including its personality, habitat, behavior, and lore (2-3 sentences)"},
|
362 |
"specialPassiveTraitDescription": {"type": "string", "description": "Describe a passive ability that gives this monster a unique advantage in battle"},
|
363 |
"attackActionName": {"type": "string", "description": "Name of the monster's primary damage-dealing attack (e.g., 'Flame Burst', 'Toxic Bite')"},
|
364 |
"attackActionDescription": {"type": "string", "description": "Describe how this attack damages the opponent and any special effects"},
|
|
|
369 |
"specialActionName": {"type": "string", "description": "Name of the monster's ultimate move (one use per battle)"},
|
370 |
"specialActionDescription": {"type": "string", "description": "Describe this powerful finishing move and its dramatic effects in battle"}
|
371 |
},
|
372 |
+
"required": ["rarity", "picletType", "height", "weight", "HP", "defence", "attack", "speed", "monsterLore", "specialPassiveTraitDescription", "attackActionName", "attackActionDescription", "buffActionName", "buffActionDescription", "debuffActionName", "debuffActionDescription", "specialActionName", "specialActionDescription"]
|
373 |
}
|
374 |
\`\`\`
|
375 |
|
|
|
423 |
|
424 |
// Remove any extra fields not in our schema
|
425 |
const allowedFields = ['rarity', 'picletType', 'height', 'weight', 'HP', 'defence', 'attack', 'speed',
|
426 |
+
'monsterLore', 'specialPassiveTraitDescription', 'attackActionName', 'attackActionDescription',
|
427 |
'buffActionName', 'buffActionDescription', 'debuffActionName', 'debuffActionDescription',
|
428 |
'specialActionName', 'specialActionDescription', 'boostActionName', 'boostActionDescription',
|
429 |
'disparageActionName', 'disparageActionDescription'];
|
|
|
447 |
|
448 |
// Add the name, description, and tier that we extracted/mapped
|
449 |
parsedStats.name = monsterName;
|
450 |
+
parsedStats.description = parsedStats.monsterLore || 'A mysterious creature with unknown origins.';
|
451 |
parsedStats.tier = tier;
|
452 |
|
453 |
// Ensure numeric fields are actually numbers
|