Browse Source

cleaning up excessive objects, adding more enemies, cleaning up enemies

main
Stephanie Gredell 4 months ago
parent
commit
6e13dd36c2
  1. 0
      assets/avatars/codegirl.png
  2. 61
      src/data/enemies.js
  3. 24
      src/data/maps.js
  4. 7
      src/engine/battle.js
  5. 54
      src/ui/render.js

0
assets/avatars/merge_conflict_enemy.png → assets/avatars/codegirl.png

Before

Width:  |  Height:  |  Size: 400 KiB

After

Width:  |  Height:  |  Size: 400 KiB

61
src/data/enemies.js

@ -1,64 +1,49 @@
export const ENEMIES = { export const ENEMIES = {
chat_gremlin: { old_man_judo: {
id: "chat_gremlin", name: "Old Man Judo", maxHp: 40, id: "old_man_judo", name: "Old Man Judo", maxHp: 40,
avatar: "assets/avatars/13.png", // Young person with cap avatar: "assets/avatars/13.png", // Young person with cap
background: "assets/backgrounds/terrace.png", background: "assets/backgrounds/terrace.png",
ai: (turn) => turn % 3 === 0 ? { type: "block", value: 6 } : { type: "attack", value: turn % 2 === 0 ? 7 : 8 } ai: (turn) => turn % 3 === 0 ? { type: "block", value: 6 } : { type: "attack", value: turn % 2 === 0 ? 7 : 8 }
}, },
type_checker: { beastco: {
id: "type_checker", name: "Type Checker", maxHp: 45, id: "beastco", name: "Beastco", maxHp: 35,
avatar: "assets/avatars/type_checker.png", // Scholar/mage with glasses
background: "assets/backgrounds/castle.png",
ai: (turn) => (turn % 3 === 0) ? { type: "debuff", value: 1 } : { type: "attack", value: 8 },
onDebuff: (ctx) => ctx.applyWeak(ctx.player, 1)
},
js_blob: {
id: "js_blob", name: "JS Blob", maxHp: 60,
avatar: "assets/avatars/js_blob.png", // Mysterious hooded figure
background: "assets/backgrounds/dead forest.png",
ai: (turn) => (turn % 2 === 0) ? { type: "attack", value: 12 } : { type: "block", value: 6 },
onBlock: (ctx, val) => ctx.enemy.block += val
},
infinite_loop: {
id: "infinite_loop", name: "Beastco", maxHp: 35,
avatar: "assets/avatars/2.png", // Dizzy/confused character avatar: "assets/avatars/2.png", // Dizzy/confused character
background: "assets/backgrounds/throne room.png", background: "assets/backgrounds/throne room.png",
ai: (turn) => ({ type: "attack", value: 4 }), ai: (turn) => ({ type: "attack", value: 4 }),
}, },
merge_conflict_enemy: { codegirl: {
id: "merge_conflict_enemy", name: "Codegirl", maxHp: 50, id: "codegirl", name: "Codegirl", maxHp: 50,
avatar: "assets/avatars/merge_conflict_enemy.png", // Warrior with conflicted expression avatar: "assets/avatars/codegirl.png", // Warrior with conflicted expression
background: "assets/backgrounds/terrace.png", // Repeat background background: "assets/backgrounds/terrace.png", // Repeat background
ai: (turn) => turn <= 4 ? { type: "attack", value: 8 } : { type: "debuff", value: 1 }, ai: (turn) => turn <= 4 ? { type: "attack", value: 8 } : { type: "debuff", value: 1 },
onDebuff: (ctx) => { onDebuff: (ctx) => {
ctx.enemy.hp = Math.min(ctx.enemy.maxHp, ctx.enemy.hp + 8); ctx.enemy.hp = Math.min(ctx.enemy.maxHp, ctx.enemy.hp + 8);
ctx.log("Codegirl resolves the merge conflict and heals 8 HP!"); ctx.log("Codegirl resolves the merge conflict and heals 8 HP!");
} }
}, },
bug_404: { nightshadedude: {
id: "bug_404", name: "404 Bug", maxHp: 45, id: "nightshadedude", name: "Nightshadedude", maxHp: 85,
avatar: "assets/avatars/bug_404.png", // Elusive character
background: "assets/backgrounds/castle.png", // Repeat background
ai: (turn) => ({ type: "attack", value: 10 }),
},
elite_ts_demon: {
id: "elite_ts_demon", name: "Nightshadedude", maxHp: 85,
avatar: "assets/avatars/11.png", // Powerful demon/witch avatar: "assets/avatars/11.png", // Powerful demon/witch
background: "assets/backgrounds/dead forest.png", // Repeat background background: "assets/backgrounds/dead forest.png", // Repeat background
ai: (turn) => turn % 3 === 1 ? { type: "debuff", value: 1 } : { type: "attack", value: 14 }, ai: (turn) => turn % 3 === 1 ? { type: "debuff", value: 1 } : { type: "attack", value: 14 },
onDebuff: (ctx) => ctx.applyVulnerable(ctx.player, 1) onDebuff: (ctx) => ctx.applyVulnerable(ctx.player, 1)
}, },
elite_refactor: { defyusall: {
id: "elite_refactor", name: "Refactor Dragon (Elite)", maxHp: 90, id: "defyusall", name: "Defyusall", maxHp: 65,
avatar: "assets/avatars/elite_refactor.png", // Regal/noble character avatar: "assets/avatars/bug_404.png", // Elusive character
background: "assets/backgrounds/throne room.png", // Repeat background background: "assets/backgrounds/castle.png",
ai: (turn) => ({ type: "attack", value: 10 + Math.floor(turn * 1.5) }) ai: (turn) => turn % 3 === 0 ? { type: "block", value: 8 } : { type: "attack", value: 10 },
},
lithium: {
id: "lithium", name: "Lithium", maxHp: 55,
avatar: "assets/avatars/type_checker.png", // Scholar/mage with glasses
background: "assets/backgrounds/dead forest.png",
ai: (turn) => (turn % 2 === 0) ? { type: "debuff", value: 1 } : { type: "attack", value: 12 },
onDebuff: (ctx) => ctx.applyWeak(ctx.player, 1)
}, },
boss_birthday_bug: { teej: {
id: "boss_birthday_bug", name: "Teej", maxHp: 120, id: "teej", name: "Teej", maxHp: 120,
avatar: "assets/avatars/boss_birthday_bug.png", // Demanding/angry character avatar: "assets/avatars/boss_birthday_bug.png", // Demanding/angry character
background: "assets/backgrounds/throne room.png", // Repeat background - fitting for boss background: "assets/backgrounds/throne room.png", // Repeat background - fitting for boss
ai: (turn) => { ai: (turn) => {

24
src/data/maps.js

@ -3,16 +3,20 @@ export const MAPS = {
act1: { act1: {
id: "act1", name: "Birthday Spire — Act I", id: "act1", name: "Birthday Spire — Act I",
nodes: [ nodes: [
{ id: "n1", kind: "start", next: ["n2", "n3"] }, { id: "n1", kind: "start", next: ["n2", "n3"], x: 500, y: 760 },
{ id: "n2", kind: "battle", enemy: "chat_gremlin", next: ["n4"] }, { id: "n2", kind: "battle", enemy: "old_man_judo", next: ["n4"], x: 350, y: 695 },
{ id: "n3", kind: "event", next: ["n4"] }, { id: "n3", kind: "event", next: ["n4"], x: 650, y: 695 },
{ id: "n4", kind: "battle", enemy: "infinite_loop", next: ["n5", "n6"] }, { id: "n4", kind: "battle", enemy: "beastco", next: ["n5", "n6"], x: 500, y: 600 },
{ id: "n5", kind: "rest", next: ["n7"] }, { id: "n5", kind: "rest", next: ["n7"], x: 350, y: 525 },
{ id: "n6", kind: "shop", next: ["n7"] }, { id: "n6", kind: "shop", next: ["n7"], x: 650, y: 525 },
{ id: "n7", kind: "battle", enemy: "merge_conflict_enemy", next: ["n8"] }, { id: "n7", kind: "battle", enemy: "codegirl", next: ["n8"], x: 500, y: 460 },
{ id: "n8", kind: "elite", enemy: "elite_ts_demon", next: ["n9"] }, { id: "n8", kind: "battle", enemy: "defyusall", next: ["n9", "n10"], x: 500, y: 395 },
{ id: "n9", kind: "rest", next: ["n10"] }, { id: "n9", kind: "rest", next: ["n11"], x: 350, y: 330 },
{ id: "n10", kind: "boss", enemy: "boss_birthday_bug", next: [] }, { id: "n10", kind: "shop", next: ["n11"], x: 650, y: 330 },
{ id: "n11", kind: "battle", enemy: "lithium", next: ["n12"], x: 500, y: 280 },
{ id: "n12", kind: "elite", enemy: "nightshadedude", next: ["n13"], x: 500, y: 205 },
{ id: "n13", kind: "rest", next: ["n14"], x: 500, y: 125 },
{ id: "n14", kind: "boss", enemy: "teej", next: [], x: 500, y: 40 },
] ]
} }
}; };

7
src/engine/battle.js

@ -125,13 +125,6 @@ export function enemyTurn(ctx) {
} }
function applyDamage(ctx, target, raw, label) { function applyDamage(ctx, target, raw, label) {
if (target === ctx.enemy && ctx.enemy.id === "bug_404" && ctx.enemy.turn % 3 === 0) {
ctx.log(`${ctx.enemy.name} phases out and dodges your attack completely!`);
return;
}
let dmg = raw; let dmg = raw;
for (const r of ctx.relicStates) { for (const r of ctx.relicStates) {
if (r.hooks?.onDamageTaken && target === ctx.player) dmg = r.hooks.onDamageTaken(ctx, dmg); if (r.hooks?.onDamageTaken && target === ctx.player) dmg = r.hooks.onDamageTaken(ctx, dmg);

54
src/ui/render.js

@ -496,26 +496,18 @@ May this birthday bring joy in each moment you’ve got. </em></p>
<svg class="spire-paths" viewBox="0 0 1000 800" preserveAspectRatio="xMidYMid meet"> <svg class="spire-paths" viewBox="0 0 1000 800" preserveAspectRatio="xMidYMid meet">
${(() => { ${(() => {
// Use positions directly from the map data
const nodePositions = { const getNodePos = (nodeId) => {
'n1': { x: 500, y: 720 }, // Start at bottom center - moved up slightly const node = m.nodes.find(n => n.id === nodeId);
'n2': { x: 350, y: 650 }, // Battle - left branch - moved right and up return node ? { x: node.x, y: node.y } : null;
'n3': { x: 650, y: 650 }, // Event - right branch - moved left and up
'n4': { x: 500, y: 540 }, // Battle - converge - moved up slightly
'n5': { x: 350, y: 400 }, // Rest - left
'n6': { x: 650, y: 400 }, // Shop - right
'n7': { x: 500, y: 300 }, // Battle - converge
'n8': { x: 500, y: 130 }, // Elite
'n9': { x: 500, y: 70 }, // Rest
'n10': { x: 500, y: 20 } // Boss at top
}; };
return m.nodes.map(node => { return m.nodes.map(node => {
if (!node.next || node.next.length === 0) return ''; if (!node.next || node.next.length === 0) return '';
return node.next.map(nextId => { return node.next.map(nextId => {
const fromPos = nodePositions[node.id]; const fromPos = { x: node.x, y: node.y };
const toPos = nodePositions[nextId]; const toPos = getNodePos(nextId);
if (!fromPos || !toPos) return ''; if (!fromPos || !toPos) return '';
const isActivePath = (node.id === currentId && nextIds.includes(nextId)) || const isActivePath = (node.id === currentId && nextIds.includes(nextId)) ||
@ -534,19 +526,7 @@ May this birthday bring joy in each moment you’ve got. </em></p>
<div class="spire-nodes"> <div class="spire-nodes">
${(() => { ${(() => {
// Use positions directly from map data
const nodePositions = {
'n1': { x: 500, y: 720 },
'n2': { x: 360, y: 650 },
'n3': { x: 630, y: 650 },
'n4': { x: 500, y: 540 },
'n5': { x: 360, y: 400 },
'n6': { x: 630, y: 400 },
'n7': { x: 500, y: 300 },
'n8': { x: 500, y: 210 },
'n9': { x: 500, y: 120 },
'n10': { x: 500, y: 40 }
};
return m.nodes.map(n => { return m.nodes.map(n => {
const isNext = nextIds.includes(n.id); const isNext = nextIds.includes(n.id);
@ -554,8 +534,8 @@ May this birthday bring joy in each moment you’ve got. </em></p>
const isCompleted = root.completedNodes.includes(n.id); const isCompleted = root.completedNodes.includes(n.id);
const locked = (!isNext && !isCurrent && !isCompleted); const locked = (!isNext && !isCurrent && !isCompleted);
const pos = nodePositions[n.id]; const pos = { x: n.x, y: n.y };
if (!pos) return ''; if (!pos.x || !pos.y) return '';
const leftPercent = (pos.x / 1000) * 100; const leftPercent = (pos.x / 1000) * 100;
const topPercent = (pos.y / 800) * 100; const topPercent = (pos.y / 800) * 100;
@ -1232,15 +1212,13 @@ function getEnemyArt(enemyId, ENEMIES = null) {
function getEnemyFallbackEmoji(enemyId) { function getEnemyFallbackEmoji(enemyId) {
const arts = { const arts = {
chat_gremlin: '👹', old_man_judo: '👹',
type_checker: '🤖', beastco: '🌀',
js_blob: '🟢', codegirl: '⚔',
infinite_loop: '🌀', defyusall: '🚫',
merge_conflict_enemy: '⚔', lithium: '⚡',
bug_404: '❌', nightshadedude: '😈',
elite_ts_demon: '😈', teej: '🎂👾'
elite_refactor: '🐉',
boss_birthday_bug: '🎂👾'
}; };
return arts[enemyId] || '👾'; return arts[enemyId] || '👾';
} }

Loading…
Cancel
Save