Browse Source

think this is the final gameplay commit

main
Stephanie Gredell 4 months ago
parent
commit
16650df85b
  1. BIN
      assets/sounds/played-card.mp3
  2. BIN
      assets/sounds/would-you-like-to-play.mp3
  3. 5
      src/data/cards.js
  4. 53
      src/data/enemies.js
  5. 28
      src/data/maps.js
  6. 2
      src/main.js
  7. 3
      src/ui/render.js

BIN
assets/sounds/played-card.mp3

Binary file not shown.

BIN
assets/sounds/would-you-like-to-play.mp3

Binary file not shown.

5
src/data/cards.js

@ -1,5 +1,3 @@
export const CARDS = { export const CARDS = {
strike: { strike: {
id: "strike", name: "Strike", cost: 1, type: "attack", text: "Deal 6.", target: "enemy", id: "strike", name: "Strike", cost: 1, type: "attack", text: "Deal 6.", target: "enemy",
@ -158,7 +156,6 @@ export const CARDS = {
id: "code_review", name: "Code Review", cost: 1, type: "skill", text: "Look at top 3 cards. Put 1 in hand, rest on bottom of deck.", id: "code_review", name: "Code Review", cost: 1, type: "skill", text: "Look at top 3 cards. Put 1 in hand, rest on bottom of deck.",
art: "Monk_24.png", art: "Monk_24.png",
effect: (ctx) => { effect: (ctx) => {
ctx.draw(1); ctx.draw(1);
ctx.log("Code review reveals useful insights. You draw a card."); ctx.log("Code review reveals useful insights. You draw a card.");
} }
@ -338,7 +335,7 @@ export const CARDS = {
export const STARTER_DECK = [ export const STARTER_DECK = [
"strike", "strike", "defend", "defend", "strike", "strike", "defend", "defend",
"segfault", "coffee_rush", "skill_issue", "git_commit", "segfault", "coffee_rush", "skill_issue", "git_commit",
"stack_trace", "raw_dog" "stack_trace", "stack_trace"
]; ];
export const CARD_POOL = [ export const CARD_POOL = [

53
src/data/enemies.js

@ -22,8 +22,15 @@ export const ENEMIES = {
ctx.log("Codegirl resolves the merge conflict and heals 8 HP!"); ctx.log("Codegirl resolves the merge conflict and heals 8 HP!");
} }
}, },
lowkeyabu: {
id: "lowkeyabu", name: "LowKeyAbu", maxHp: 85,
avatar: "assets/avatars/7.png", // Powerful demon/witch
background: "assets/backgrounds/castle.png", // Repeat background
ai: (turn) => turn % 3 === 1 ? { type: "debuff", value: 1 } : { type: "attack", value: 10 },
onDebuff: (ctx) => ctx.applyVulnerable(ctx.player, 1)
},
nightshadedude: { nightshadedude: {
id: "nightshadedude", name: "Nightshadedude", maxHp: 85, id: "nightshadedude", name: "Nightshadedude", maxHp: 120,
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 },
@ -57,28 +64,28 @@ export const ENEMIES = {
}, },
// ACT 2 ENEMIES - Harder versions // ACT 2 ENEMIES - Harder versions
senior_dev: { teej: {
id: "senior_dev", name: "Senior Dev", maxHp: 65, id: "teej", name: "Teej", maxHp: 65,
avatar: "assets/avatars/elite_ts_demon.png", avatar: "assets/avatars/elite_ts_demon.png",
background: "assets/backgrounds/castle.png", background: "assets/backgrounds/castle.png",
ai: (turn) => turn % 3 === 0 ? { type: "debuff", value: 2 } : { type: "attack", value: turn % 2 === 0 ? 12 : 14 }, ai: (turn) => turn % 3 === 0 ? { type: "debuff", value: 2 } : { type: "attack", value: turn % 2 === 0 ? 12 : 14 },
onDebuff: (ctx) => ctx.applyWeak(ctx.player, 2) onDebuff: (ctx) => ctx.applyWeak(ctx.player, 2)
}, },
tech_lead: { begin: {
id: "tech_lead", name: "Tech Lead", maxHp: 80, id: "begin", name: "Begin", maxHp: 80,
avatar: "assets/avatars/infinite_loop.png", avatar: "assets/avatars/infinite_loop.png",
background: "assets/backgrounds/dead forest.png", background: "assets/backgrounds/dead forest.png",
ai: (turn) => (turn % 2 === 0) ? { type: "attack", value: 16 } : { type: "block", value: 12 } ai: (turn) => (turn % 2 === 0) ? { type: "attack", value: 16 } : { type: "block", value: 12 }
}, },
code_reviewer: { adam: {
id: "code_reviewer", name: "Code Reviewer", maxHp: 70, id: "adam", name: "Adam", maxHp: 70,
avatar: "assets/avatars/chat_gremlin.png", avatar: "assets/avatars/chat_gremlin.png",
background: "assets/backgrounds/terrace.png", background: "assets/backgrounds/terrace.png",
ai: (turn) => turn % 4 === 0 ? { type: "debuff", value: 1 } : { type: "attack", value: 13 }, ai: (turn) => turn % 4 === 0 ? { type: "debuff", value: 1 } : { type: "attack", value: 13 },
onDebuff: (ctx) => { ctx.applyVulnerable(ctx.player, 1); ctx.log("Code Reviewer finds bugs in your logic!"); } onDebuff: (ctx) => { ctx.applyVulnerable(ctx.player, 1); ctx.log("Adam finds bugs in your logic!"); }
}, },
scrum_master: { david: {
id: "scrum_master", name: "Scrum Master", maxHp: 90, id: "david", name: "David", maxHp: 90,
avatar: "assets/avatars/js_blob.png", avatar: "assets/avatars/js_blob.png",
background: "assets/backgrounds/castle.png", background: "assets/backgrounds/castle.png",
ai: (turn) => { ai: (turn) => {
@ -87,10 +94,10 @@ export const ENEMIES = {
if (cyc === 1) return { type: "attack", value: 11 }; if (cyc === 1) return { type: "attack", value: 11 };
return { type: "debuff", value: 1 }; return { type: "debuff", value: 1 };
}, },
onDebuff: (ctx) => { ctx.flags.nextTurnEnergyPenalty = (ctx.flags.nextTurnEnergyPenalty || 0) + 1; ctx.log("Scrum Master schedules another meeting! Lose 1 energy next turn."); } onDebuff: (ctx) => { ctx.flags.nextTurnEnergyPenalty = (ctx.flags.nextTurnEnergyPenalty || 0) + 1; ctx.log("David schedules another meeting! Lose 1 energy next turn."); }
}, },
architect: { dax: {
id: "architect", name: "The Architect", maxHp: 150, id: "dax", name: "Dax", maxHp: 150,
avatar: "assets/avatars/bug_404.png", avatar: "assets/avatars/bug_404.png",
background: "assets/backgrounds/throne room.png", background: "assets/backgrounds/throne room.png",
ai: (turn) => { ai: (turn) => {
@ -101,7 +108,23 @@ export const ENEMIES = {
if (cyc === 4) return { type: "attack", value: 30 }; if (cyc === 4) return { type: "attack", value: 30 };
return { type: "attack", value: 20 }; return { type: "attack", value: 20 };
}, },
onDebuff: (ctx) => { ctx.applyWeak(ctx.player, 2); ctx.applyVulnerable(ctx.player, 1); ctx.log("The Architect redesigns your entire approach!"); }, onDebuff: (ctx) => { ctx.applyWeak(ctx.player, 2); ctx.applyVulnerable(ctx.player, 1); ctx.log("Dax redesigns your entire approach!"); },
onBlock: (ctx) => { ctx.enemy.hp = Math.min(ctx.enemy.maxHp, ctx.enemy.hp + 12); ctx.log("The Architect refactors and optimizes, healing 12 HP!"); } onBlock: (ctx) => { ctx.enemy.hp = Math.min(ctx.enemy.maxHp, ctx.enemy.hp + 12); ctx.log("Dax refactors and optimizes, healing 12 HP!"); }
},
taylor: {
id: "taylor", name: "Taylor Otwell", maxHp: 150,
avatar: "assets/avatars/bug_404.png",
background: "assets/backgrounds/throne room.png",
ai: (turn) => {
const cyc = turn % 5;
if (cyc === 1) return { type: "debuff", value: 2 };
if (cyc === 2) return { type: "attack", value: 25 };
if (cyc === 3) return { type: "block", value: 15 };
if (cyc === 4) return { type: "attack", value: 30 };
return { type: "attack", value: 20 };
},
onDebuff: (ctx) => { ctx.applyWeak(ctx.player, 2); ctx.applyVulnerable(ctx.player, 1); ctx.log("Taylor redesigns your entire approach!"); },
onBlock: (ctx) => { ctx.enemy.hp = Math.min(ctx.enemy.maxHp, ctx.enemy.hp + 12); ctx.log("Taylor refactors and optimizes, healing 12 HP!"); }
} }
}; };

28
src/data/maps.js

@ -14,27 +14,27 @@ export const MAPS = {
{ id: "n9", kind: "rest", next: ["n11"], x: 350, y: 330 }, { id: "n9", kind: "rest", next: ["n11"], x: 350, y: 330 },
{ id: "n10", kind: "shop", next: ["n11"], x: 650, y: 330 }, { id: "n10", kind: "shop", next: ["n11"], x: 650, y: 330 },
{ id: "n11", kind: "battle", enemy: "lithium", next: ["n12"], x: 500, y: 280 }, { 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: "n12", kind: "elite", enemy: "lowkeyabu", next: ["n13"], x: 500, y: 205 },
{ id: "n13", kind: "rest", next: ["n14"], x: 500, y: 125 }, { id: "n13", kind: "rest", next: ["n14"], x: 500, y: 125 },
{ id: "n14", kind: "boss", enemy: "teej", next: [], x: 500, y: 40 }, { id: "n14", kind: "boss", enemy: "nightshadedude", next: [], x: 500, y: 40 },
] ]
}, },
act2: { act2: {
id: "act2", name: "Birthday Spire — Act II: The Corporate Ladder", id: "act2", name: "Birthday Spire — Act II: The Corporate Ladder",
nodes: [ nodes: [
{ id: "a2n1", kind: "start", next: ["a2n2", "a2n3"], x: 500, y: 760 }, { id: "a2n1", kind: "start", next: ["a2n2", "a2n3"], x: 500, y: 760 },
{ id: "a2n2", kind: "battle", enemy: "senior_dev", next: ["a2n4", "a2n5"], x: 400, y: 680 }, { id: "a2n2", kind: "battle", enemy: "teej", next: ["a2n5"], x: 300, y: 695 },
{ id: "a2n3", kind: "event", next: ["a2n5"], x: 600, y: 680 }, { id: "a2n3", kind: "event", next: ["a2n5"], x: 650, y: 695 },
{ id: "a2n4", kind: "shop", next: ["a2n6"], x: 300, y: 600 }, { id: "a2n5", kind: "battle", enemy: "begin", next: ["a2n4", "a2n7"], x: 500, y: 600 },
{ id: "a2n5", kind: "battle", enemy: "tech_lead", next: ["a2n6", "a2n7"], x: 500, y: 600 }, { id: "a2n4", kind: "shop", next: ["a2n6"], x: 350, y: 525 },
{ id: "a2n6", kind: "battle", enemy: "code_reviewer", next: ["a2n8"], x: 400, y: 520 }, { id: "a2n7", kind: "rest", next: ["a2n6"], x: 650, y: 525 },
{ id: "a2n7", kind: "rest", next: ["a2n8"], x: 600, y: 520 }, { id: "a2n6", kind: "battle", enemy: "adam", next: ["a2n8"], x: 500, y: 460 },
{ id: "a2n8", kind: "battle", enemy: "scrum_master", next: ["a2n9", "a2n10"], x: 500, y: 440 }, { id: "a2n8", kind: "battle", enemy: "david", next: ["a2n9", "a2n10"], x: 500, y: 360 },
{ id: "a2n9", kind: "event", next: ["a2n11"], x: 350, y: 360 }, { id: "a2n9", kind: "rest", next: ["a2n11"], x: 350, y: 320 },
{ id: "a2n10", kind: "shop", next: ["a2n11"], x: 650, y: 360 }, { id: "a2n10", kind: "shop", next: ["a2n11"], x: 650, y: 320 },
{ id: "a2n11", kind: "elite", enemy: "senior_dev", next: ["a2n12"], x: 500, y: 280 }, { id: "a2n11", kind: "elite", enemy: "dax", next: ["a2n12"], x: 500, y: 250 },
{ id: "a2n12", kind: "rest", next: ["a2n13"], x: 500, y: 200 }, { id: "a2n12", kind: "rest", next: ["a2n13"], x: 500, y: 140 },
{ id: "a2n13", kind: "boss", enemy: "architect", next: [], x: 500, y: 120 }, { id: "a2n13", kind: "boss", enemy: "taylor", next: [], x: 500, y: 40 },
] ]
} }
}; };

2
src/main.js

@ -116,7 +116,6 @@ const root = {
} }
} }
else { else {
this.save(); this.save();
this.afterNode(); this.afterNode();
} }
@ -142,7 +141,6 @@ const root = {
async selectStartingRelic(relicId) { async selectStartingRelic(relicId) {
attachRelics(this, [relicId]); attachRelics(this, [relicId]);
this.log(`Selected starting relic: ${relicId}`);
this.save(); this.save();
await renderMap(this); await renderMap(this);
}, },

3
src/ui/render.js

@ -4,7 +4,7 @@ function playSound(soundFile) {
try { try {
const audio = new Audio(`assets/sounds/${soundFile}`); const audio = new Audio(`assets/sounds/${soundFile}`);
audio.volume = 0.3; audio.volume = 0.3;
audio.play().catch(e => { }); // Silently fail if no audio audio.play().catch(e => { console.log(e) }); // Silently fail if no audio
} catch (e) { } catch (e) {
// Silently fail if audio not available // Silently fail if audio not available
} }
@ -251,6 +251,7 @@ export async function renderBattle(root) {
const index = parseInt(btn.dataset.play, 10); const index = parseInt(btn.dataset.play, 10);
const card = p.hand[index]; const card = p.hand[index];
if (p.energy >= card.cost) { if (p.energy >= card.cost) {
playSound('played-card.mp3')
root.play(index); root.play(index);
// Clear selection when card is played via mouse // Clear selection when card is played via mouse
root.selectedCardIndex = null; root.selectedCardIndex = null;

Loading…
Cancel
Save