clibuddy 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/adventure/adventureUI.d.ts +24 -0
  4. package/dist/adventure/adventureUI.js +290 -0
  5. package/dist/adventure/adventures.d.ts +4 -0
  6. package/dist/adventure/adventures.js +206 -0
  7. package/dist/adventure/biomes.d.ts +30 -0
  8. package/dist/adventure/biomes.js +80 -0
  9. package/dist/adventure/combat/combat.d.ts +14 -0
  10. package/dist/adventure/combat/combat.js +638 -0
  11. package/dist/adventure/combat/combatUI.d.ts +5 -0
  12. package/dist/adventure/combat/combatUI.js +116 -0
  13. package/dist/adventure/combat/conditions.d.ts +20 -0
  14. package/dist/adventure/combat/conditions.js +111 -0
  15. package/dist/adventure/combat/enemies.d.ts +4 -0
  16. package/dist/adventure/combat/enemies.js +430 -0
  17. package/dist/adventure/combat/gear.d.ts +3 -0
  18. package/dist/adventure/combat/gear.js +199 -0
  19. package/dist/adventure/combat/skills.d.ts +6 -0
  20. package/dist/adventure/combat/skills.js +197 -0
  21. package/dist/adventure/combat.d.ts +31 -0
  22. package/dist/adventure/combat.js +732 -0
  23. package/dist/adventure/combatUI.d.ts +5 -0
  24. package/dist/adventure/combatUI.js +116 -0
  25. package/dist/adventure/endless.d.ts +18 -0
  26. package/dist/adventure/endless.js +154 -0
  27. package/dist/adventure/enemies.d.ts +4 -0
  28. package/dist/adventure/enemies.js +320 -0
  29. package/dist/adventure/engine.d.ts +20 -0
  30. package/dist/adventure/engine.js +137 -0
  31. package/dist/adventure/gear.d.ts +3 -0
  32. package/dist/adventure/gear.js +149 -0
  33. package/dist/adventure/generation/biomes.d.ts +30 -0
  34. package/dist/adventure/generation/biomes.js +102 -0
  35. package/dist/adventure/generation/endless.d.ts +18 -0
  36. package/dist/adventure/generation/endless.js +154 -0
  37. package/dist/adventure/generation/generator.d.ts +9 -0
  38. package/dist/adventure/generation/generator.js +245 -0
  39. package/dist/adventure/generation/templates.d.ts +25 -0
  40. package/dist/adventure/generation/templates.js +228 -0
  41. package/dist/adventure/generator.d.ts +9 -0
  42. package/dist/adventure/generator.js +245 -0
  43. package/dist/adventure/skills.d.ts +6 -0
  44. package/dist/adventure/skills.js +197 -0
  45. package/dist/adventure/templates.d.ts +25 -0
  46. package/dist/adventure/templates.js +228 -0
  47. package/dist/adventure/types.d.ts +236 -0
  48. package/dist/adventure/types.js +97 -0
  49. package/dist/app/state.d.ts +49 -0
  50. package/dist/app/state.js +51 -0
  51. package/dist/buddy/activities.d.ts +16 -0
  52. package/dist/buddy/activities.js +90 -0
  53. package/dist/buddy/decay.d.ts +3 -0
  54. package/dist/buddy/decay.js +45 -0
  55. package/dist/buddy/leveling.d.ts +11 -0
  56. package/dist/buddy/leveling.js +25 -0
  57. package/dist/buddy/roll.d.ts +4 -0
  58. package/dist/buddy/roll.js +61 -0
  59. package/dist/buddy/species.d.ts +4 -0
  60. package/dist/buddy/species.js +592 -0
  61. package/dist/buddy/titles.d.ts +17 -0
  62. package/dist/buddy/titles.js +89 -0
  63. package/dist/buddy/types.d.ts +92 -0
  64. package/dist/buddy/types.js +21 -0
  65. package/dist/commands/actions.d.ts +2 -0
  66. package/dist/commands/actions.js +141 -0
  67. package/dist/commands/admin.d.ts +2 -0
  68. package/dist/commands/admin.js +202 -0
  69. package/dist/commands/registry.d.ts +25 -0
  70. package/dist/commands/registry.js +31 -0
  71. package/dist/commands/social.d.ts +2 -0
  72. package/dist/commands/social.js +92 -0
  73. package/dist/dialogue/engine.d.ts +7 -0
  74. package/dist/dialogue/engine.js +68 -0
  75. package/dist/dialogue/lines.d.ts +26 -0
  76. package/dist/dialogue/lines.js +294 -0
  77. package/dist/events/engine.d.ts +20 -0
  78. package/dist/events/engine.js +51 -0
  79. package/dist/events/events.d.ts +13 -0
  80. package/dist/events/events.js +149 -0
  81. package/dist/index.d.ts +10 -0
  82. package/dist/index.js +1665 -0
  83. package/dist/inventory/finding.d.ts +11 -0
  84. package/dist/inventory/finding.js +99 -0
  85. package/dist/inventory/items.d.ts +31 -0
  86. package/dist/inventory/items.js +63 -0
  87. package/dist/minigames/copycat.d.ts +2 -0
  88. package/dist/minigames/copycat.js +153 -0
  89. package/dist/minigames/fetch.d.ts +2 -0
  90. package/dist/minigames/fetch.js +179 -0
  91. package/dist/minigames/moodmatch.d.ts +2 -0
  92. package/dist/minigames/moodmatch.js +144 -0
  93. package/dist/minigames/quickpaws.d.ts +2 -0
  94. package/dist/minigames/quickpaws.js +142 -0
  95. package/dist/minigames/registry.d.ts +5 -0
  96. package/dist/minigames/registry.js +16 -0
  97. package/dist/minigames/rpsplus.d.ts +2 -0
  98. package/dist/minigames/rpsplus.js +168 -0
  99. package/dist/minigames/treasurehunt.d.ts +2 -0
  100. package/dist/minigames/treasurehunt.js +146 -0
  101. package/dist/minigames/types.d.ts +30 -0
  102. package/dist/minigames/types.js +69 -0
  103. package/dist/rendering/commandPalette.d.ts +16 -0
  104. package/dist/rendering/commandPalette.js +77 -0
  105. package/dist/rendering/display.d.ts +9 -0
  106. package/dist/rendering/display.js +231 -0
  107. package/dist/rendering/inventoryUI.d.ts +14 -0
  108. package/dist/rendering/inventoryUI.js +99 -0
  109. package/dist/rendering/items.d.ts +7 -0
  110. package/dist/rendering/items.js +34 -0
  111. package/dist/rendering/listUtils.d.ts +3 -0
  112. package/dist/rendering/listUtils.js +24 -0
  113. package/dist/rendering/minigameUI.d.ts +11 -0
  114. package/dist/rendering/minigameUI.js +37 -0
  115. package/dist/rendering/overlayUI.d.ts +24 -0
  116. package/dist/rendering/overlayUI.js +184 -0
  117. package/dist/rendering/scene.d.ts +8 -0
  118. package/dist/rendering/scene.js +87 -0
  119. package/dist/rendering/screen.d.ts +43 -0
  120. package/dist/rendering/screen.js +97 -0
  121. package/dist/sound/sound.d.ts +11 -0
  122. package/dist/sound/sound.js +55 -0
  123. package/dist/state/save.d.ts +5 -0
  124. package/dist/state/save.js +100 -0
  125. package/dist/state/settings.d.ts +7 -0
  126. package/dist/state/settings.js +81 -0
  127. package/dist/story/mainStory.d.ts +4 -0
  128. package/dist/story/mainStory.js +3111 -0
  129. package/dist/story/npcs.d.ts +17 -0
  130. package/dist/story/npcs.js +137 -0
  131. package/dist/story/progress.d.ts +26 -0
  132. package/dist/story/progress.js +168 -0
  133. package/dist/story/seasonal.d.ts +6 -0
  134. package/dist/story/seasonal.js +96 -0
  135. package/dist/story/shop.d.ts +7 -0
  136. package/dist/story/shop.js +26 -0
  137. package/dist/story/sideQuests.d.ts +4 -0
  138. package/dist/story/sideQuests.js +151 -0
  139. package/dist/story/types.d.ts +61 -0
  140. package/dist/story/types.js +36 -0
  141. package/dist/updates.d.ts +23 -0
  142. package/dist/updates.js +142 -0
  143. package/package.json +53 -0
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateNarrativeText = generateNarrativeText;
4
+ exports.generateNarrativeTitle = generateNarrativeTitle;
5
+ exports.generateChoiceLabels = generateChoiceLabels;
6
+ exports.generateCombatText = generateCombatText;
7
+ exports.generateCombatTitle = generateCombatTitle;
8
+ exports.generateTreasureText = generateTreasureText;
9
+ exports.generateRestText = generateRestText;
10
+ exports.generateEvent = generateEvent;
11
+ exports.generateBuddyLine = generateBuddyLine;
12
+ exports.generateBossText = generateBossText;
13
+ exports.generateHiddenRoomText = generateHiddenRoomText;
14
+ function pick(arr) {
15
+ return arr[Math.floor(Math.random() * arr.length)];
16
+ }
17
+ // ─── Narrative Room Templates ────────────────────────────────
18
+ function generateNarrativeText(biome) {
19
+ const templates = [
20
+ [`The ${pick(biome.adjectives)} ${pick(biome.nouns)} stretches before you.`, `Two paths diverge ahead — ${pick(biome.directions)} and ${pick(biome.directions)}.`],
21
+ [`You reach a ${pick(biome.landmarks)}. The air feels ${pick(biome.adjectives)}.`, `Something rustles in ${pick(biome.hidingSpots)}.`],
22
+ [`The path narrows as you enter a ${pick(biome.adjectives)} ${pick(biome.nouns)}.`, `You can go ${pick(biome.directions)} or ${pick(biome.directions)}.`],
23
+ [`A ${pick(biome.landmarks)} marks a crossroads.`, `The ${pick(biome.nouns)} feels ${pick(biome.adjectives)} here.`],
24
+ [`Your footsteps echo in the ${pick(biome.adjectives)} ${pick(biome.nouns)}.`, `Ahead, the path splits around a ${pick(biome.landmarks)}.`],
25
+ [`The ${pick(biome.nouns)} opens up to reveal a ${pick(biome.landmarks)}.`, `The air is ${pick(biome.adjectives)}. Which way?`],
26
+ [`Deeper into the ${pick(biome.nouns)}, you hear sounds from ${pick(biome.hidingSpots)}.`, `The path branches — ${pick(biome.directions)} looks safe, ${pick(biome.directions)} looks... interesting.`],
27
+ [`You stand at the edge of a ${pick(biome.adjectives)} ${pick(biome.nouns)}.`, `A ${pick(biome.landmarks)} marks two possible routes.`],
28
+ [`Shadows dance across a ${pick(biome.landmarks)}.`, `The ${pick(biome.nouns)} seems to whisper. Two paths await.`],
29
+ ];
30
+ return pick(templates);
31
+ }
32
+ function generateNarrativeTitle(biome) {
33
+ const titles = [
34
+ `The ${capitalize(pick(biome.adjectives))} ${capitalize(pick(biome.nouns))}`,
35
+ `${capitalize(pick(biome.landmarks))}`,
36
+ `A Fork in the ${capitalize(pick(biome.nouns))}`,
37
+ `The ${capitalize(pick(biome.adjectives))} Path`,
38
+ ];
39
+ return pick(titles);
40
+ }
41
+ function generateChoiceLabels(biome) {
42
+ return [
43
+ `Go ${pick(biome.directions)}`,
44
+ `Head ${pick(biome.directions)}`,
45
+ ];
46
+ }
47
+ // ─── Combat Room Templates ───────────────────────────────────
48
+ function generateCombatText(biome, enemyName) {
49
+ const templates = [
50
+ [`A ${enemyName} leaps out from ${pick(biome.hidingSpots)}!`],
51
+ [`You stumble into a ${pick(biome.adjectives)} clearing. A ${enemyName} blocks the way!`],
52
+ [`Something moves in ${pick(biome.hidingSpots)}... it's a ${enemyName}!`],
53
+ [`The ${pick(biome.nouns)} grows ${pick(biome.adjectives)}. A ${enemyName} appears!`],
54
+ ];
55
+ return pick(templates);
56
+ }
57
+ function generateCombatTitle(biome) {
58
+ return `${capitalize(pick(biome.adjectives))} Encounter`;
59
+ }
60
+ // ─── Treasure Room Templates ─────────────────────────────────
61
+ function generateTreasureText(biome) {
62
+ const templates = [
63
+ [`Behind a ${pick(biome.landmarks)}, something glints...`],
64
+ [`Your buddy digs near ${pick(biome.hidingSpots)} and finds something!`],
65
+ [`Hidden in the ${pick(biome.adjectives)} ${pick(biome.nouns)}, a stash awaits!`],
66
+ [`A ${pick(biome.landmarks)} conceals a small cache of treasure.`],
67
+ ];
68
+ return pick(templates);
69
+ }
70
+ // ─── Rest Room Templates ─────────────────────────────────────
71
+ function generateRestText(biome) {
72
+ const templates = [
73
+ [`A peaceful spot near a ${pick(biome.landmarks)}. The ${pick(biome.nouns)} is quiet here.`],
74
+ [`A sheltered ${pick(biome.nouns)} offers respite. You could rest here...`],
75
+ [`The ${pick(biome.adjectives)} atmosphere fades. This feels safe.`],
76
+ ];
77
+ return pick(templates);
78
+ }
79
+ function generateEvent(biome) {
80
+ const events = [
81
+ {
82
+ text: [`A small creature peeks out from ${pick(biome.hidingSpots)}.`, `It seems to want to trade...`],
83
+ choices: [
84
+ { label: "Offer a Berry", outcome: "It hands you something shiny in return!", effect: { itemGain: pick(biome.loot.uncommon) } },
85
+ { label: "Wave and move on", outcome: "The creature waves goodbye." },
86
+ ],
87
+ },
88
+ {
89
+ text: [`You find a strange ${pick(biome.adjectives)} chest near a ${pick(biome.landmarks)}.`, `It could be a trap... or treasure.`],
90
+ choices: [
91
+ { label: "Open it carefully", outcome: "Inside — a useful item!", effect: { itemGain: pick(biome.loot.rare) } },
92
+ { label: "Leave it alone", outcome: "Better safe than sorry. You move on." },
93
+ { label: "Kick it open", outcome: "A puff of gas! You feel woozy.", effect: { hp: -10 } },
94
+ ],
95
+ },
96
+ {
97
+ text: [`A warm glow emanates from a ${pick(biome.landmarks)}.`, `It feels... magical.`],
98
+ choices: [
99
+ { label: "Touch the glow", outcome: "A warm feeling washes over you!", effect: { hp: 15, happiness: 5 } },
100
+ { label: "Back away cautiously", outcome: "The glow fades. Nothing happens." },
101
+ ],
102
+ },
103
+ {
104
+ text: [`A weary traveler rests by the path.`, `"Care to share some food? I'll make it worth your while."`],
105
+ choices: [
106
+ { label: "Share some food", outcome: "\"Thank you! Take this.\"", effect: { itemGain: pick(biome.loot.uncommon) } },
107
+ { label: "Apologize and decline", outcome: "The traveler nods and rests." },
108
+ ],
109
+ },
110
+ {
111
+ text: [`A wise-looking creature sits near a ${pick(biome.landmarks)}.`, `"Answer my riddle and I'll reward you!"`],
112
+ choices: [
113
+ { label: "Accept the riddle", outcome: "You answer wisely! A reward appears.", effect: { itemGain: pick(biome.loot.rare) } },
114
+ { label: "Politely refuse", outcome: "The creature nods knowingly." },
115
+ ],
116
+ },
117
+ {
118
+ text: [`A small animal is trapped under a ${pick(biome.adjectives)} rock near ${pick(biome.hidingSpots)}.`, `It whimpers for help...`],
119
+ choices: [
120
+ { label: "Help free it", outcome: "It scurries free! It drops something as thanks.", effect: { itemGain: pick(biome.loot.uncommon), happiness: 5 } },
121
+ { label: "It might be a trap...", outcome: "You move on cautiously." },
122
+ ],
123
+ },
124
+ {
125
+ text: [`A glowing rune is etched into a ${pick(biome.landmarks)}.`, `It pulses with ${pick(biome.adjectives)} energy.`],
126
+ choices: [
127
+ { label: "Touch the rune", outcome: "Power surges through you!", effect: { hp: 20 } },
128
+ { label: "Study it from afar", outcome: "You learn something, but feel nothing change." },
129
+ { label: "Smash it", outcome: "The rune explodes! Ow!", effect: { hp: -15 } },
130
+ ],
131
+ },
132
+ {
133
+ text: [`Someone left a campfire burning near ${pick(biome.hidingSpots)}.`, `There's a pack nearby...`],
134
+ choices: [
135
+ { label: "Warm up and rest", outcome: "The warmth is soothing.", effect: { hp: 10, happiness: 5 } },
136
+ { label: "Search the pack", outcome: "You find something useful!", effect: { itemGain: pick(biome.loot.uncommon) } },
137
+ { label: "Leave it — not yours", outcome: "You move on with a clear conscience." },
138
+ ],
139
+ },
140
+ ];
141
+ return pick(events);
142
+ }
143
+ // ─── Buddy Dialogue Templates ────────────────────────────────
144
+ const SPECIES_ADVENTURE_LINES = {
145
+ rabbit: [
146
+ "My ears are twitching... something's nearby!", "I can hop right over this!",
147
+ "This place smells like carrots... no wait, danger.", "Want me to scout ahead? I'm fast!",
148
+ "*nose wiggles* I sense trouble...", "I could dig us an escape route!",
149
+ "My lucky foot says... this way!",
150
+ ],
151
+ cat: [
152
+ "I sense prey ahead.", "*sniffs the air* Interesting...", "I'll lead. Stay behind me.",
153
+ "*tail flicks* Something moved.", "I've hunted worse than this.",
154
+ "Do NOT touch me right now. I'm focused.", "This reminds me of my afternoon prowl.",
155
+ ],
156
+ frog: [
157
+ "Ribbit! I mean... let's go!", "The moisture here is nice.", "*tongue flick* Just checking.",
158
+ "I can sense vibrations... something big!", "Hop hop hop! Keep up!",
159
+ "If it gets wet, that's MY territory.", "My skin is tingling... that's either danger or humidity.",
160
+ ],
161
+ owl: [
162
+ "I can see far ahead from here.", "Hoo goes there?", "Knowledge awaits in every corner.",
163
+ "I've read about places like this...", "*head rotates* Scanning for threats.",
164
+ "Logically, the left path is safer.", "My wisdom says proceed with caution.",
165
+ ],
166
+ fox: [
167
+ "I smell adventure!", "My instincts say... this way!", "Stay sharp, I'll sniff out danger.",
168
+ "There's a shortcut here, I can feel it!", "Trust the nose!",
169
+ "*tail swish* I've got a plan.", "Foxes always find the best paths.",
170
+ ],
171
+ phoenix: [
172
+ "My flames light the way!", "*feathers glow* I feel strong here.", "Even if we fall, we rise again!",
173
+ "The fire within me burns brighter here!", "Nothing can stop eternal flame!",
174
+ "I sense ancient power nearby...", "*sparks fly from wings* Let's GO!",
175
+ ],
176
+ dragon: [
177
+ "I smell treasure nearby!", "*tiny roar* I'm not scared!", "My scales will protect us!",
178
+ "Is that gold? I think I smell gold!", "*puffs smoke confidently*",
179
+ "I'm basically a fortress. With legs.", "Anything that glows is mine. That's the rule.",
180
+ ],
181
+ };
182
+ const GENERIC_BUDDY_LINES = [
183
+ "Which way should we go?",
184
+ "This looks interesting...",
185
+ "Stay close!",
186
+ "I've got a good feeling about this!",
187
+ "Let's be careful here...",
188
+ "Ooh, what's over there?",
189
+ "I wonder what we'll find!",
190
+ "This is exciting!",
191
+ "I trust your instincts!",
192
+ "Lead the way, I've got your back!",
193
+ "Something tells me this will be worth it.",
194
+ ];
195
+ function generateBuddyLine(speciesId, biome) {
196
+ // 50% species-specific, 50% generic
197
+ if (Math.random() < 0.5) {
198
+ const speciesLines = SPECIES_ADVENTURE_LINES[speciesId];
199
+ if (speciesLines)
200
+ return pick(speciesLines);
201
+ }
202
+ // Comfort bonus line
203
+ if (biome.comfortSpecies.includes(speciesId) && Math.random() < 0.3) {
204
+ return "I feel right at home here!";
205
+ }
206
+ return pick(GENERIC_BUDDY_LINES);
207
+ }
208
+ // ─── Boss Room Templates ─────────────────────────────────────
209
+ function generateBossText(biome, bossName) {
210
+ const templates = [
211
+ [`The ${pick(biome.nouns)} trembles. Something massive approaches...`, `${bossName} emerges!`],
212
+ [`A deafening sound echoes through the ${pick(biome.nouns)}.`, `${bossName} blocks your path — there's no going back!`],
213
+ [`The air grows heavy. ${bossName} rises from ${pick(biome.hidingSpots)}!`],
214
+ ];
215
+ return pick(templates);
216
+ }
217
+ // ─── Hidden Room Templates ───────────────────────────────────
218
+ function generateHiddenRoomText(biome, speciesId) {
219
+ const speciesName = speciesId.charAt(0).toUpperCase() + speciesId.slice(1);
220
+ return [
221
+ `Your ${speciesName} senses notice something others would miss...`,
222
+ `A hidden passage reveals itself in the ${pick(biome.adjectives)} ${pick(biome.nouns)}!`,
223
+ ];
224
+ }
225
+ function capitalize(s) {
226
+ return s.charAt(0).toUpperCase() + s.slice(1);
227
+ }
228
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1,236 @@
1
+ export type Element = "fire" | "water" | "nature" | "light" | "shadow" | "neutral";
2
+ export declare function getElementMultiplier(atkElement: Element, defElement: Element): {
3
+ multiplier: number;
4
+ label: string;
5
+ };
6
+ export declare const ELEMENT_ICONS: Record<Element, string>;
7
+ export declare const SPECIES_ELEMENTS: Record<string, Element>;
8
+ export interface CombatStats {
9
+ maxHp: number;
10
+ hp: number;
11
+ atk: number;
12
+ def: number;
13
+ spd: number;
14
+ dodgeChance: number;
15
+ }
16
+ export type AIBehavior = "aggressive" | "defensive" | "tactical" | "berserker" | "evasive";
17
+ export interface EnemyDef {
18
+ id: string;
19
+ name: string;
20
+ element: Element;
21
+ aiBehavior: AIBehavior;
22
+ art: string[];
23
+ encounterLine: string;
24
+ attackLine: string;
25
+ defeatLine: string;
26
+ defendLine?: string;
27
+ baseHp: number;
28
+ baseAtk: number;
29
+ baseDef: number;
30
+ baseSpd: number;
31
+ baseDodge?: number;
32
+ xpReward: number;
33
+ dropChance: number;
34
+ dropPool: string[];
35
+ isBoss?: boolean;
36
+ specialMove?: {
37
+ name: string;
38
+ line: string;
39
+ damageMultiplier: number;
40
+ chance: number;
41
+ };
42
+ /** Boss phase 2 special (triggers at HP < 50%) */
43
+ phase2Move?: {
44
+ name: string;
45
+ line: string;
46
+ damageMultiplier: number;
47
+ chance: number;
48
+ };
49
+ /** Boss enrage at HP < 25%: +atkBonus% ATK, uses special every other turn */
50
+ enrageAtkBonus?: number;
51
+ }
52
+ export type SkillEffect = {
53
+ type: "damage";
54
+ multiplier: number;
55
+ ignoreDefense?: boolean;
56
+ } | {
57
+ type: "buff";
58
+ stat: "atk" | "def" | "dodge" | "crit";
59
+ amount: number;
60
+ turns: number;
61
+ } | {
62
+ type: "debuff";
63
+ stat: "atk" | "def";
64
+ amount: number;
65
+ turns: number;
66
+ } | {
67
+ type: "poison";
68
+ damagePerTurn: number;
69
+ turns: number;
70
+ } | {
71
+ type: "stun";
72
+ turns: number;
73
+ } | {
74
+ type: "revive";
75
+ hpPercent: number;
76
+ } | {
77
+ type: "skip_enemy_turn";
78
+ };
79
+ export interface SkillDef {
80
+ id: string;
81
+ name: string;
82
+ description: string;
83
+ speciesId: string;
84
+ levelRequired: number;
85
+ energyCost: number;
86
+ element?: Element;
87
+ effect: SkillEffect;
88
+ useLine: string;
89
+ }
90
+ export type RoomType = "narrative" | "combat" | "treasure" | "rest" | "event" | "boss";
91
+ export interface RoomChoice {
92
+ label: string;
93
+ nextRoomId: string;
94
+ }
95
+ export interface RoomCondition {
96
+ type: "species" | "level" | "item";
97
+ value: string | number;
98
+ }
99
+ export interface RoomDef {
100
+ id: string;
101
+ type: RoomType;
102
+ title: string;
103
+ text: string[];
104
+ buddyLine: string;
105
+ nextRoomId?: string;
106
+ choices?: RoomChoice[];
107
+ enemyId?: string;
108
+ lootPool?: string[];
109
+ healAmount?: number;
110
+ condition?: RoomCondition;
111
+ npcsPresent?: string[];
112
+ eventChoices?: {
113
+ label: string;
114
+ outcome: string;
115
+ nextRoomId?: string;
116
+ effect?: Partial<{
117
+ hp: number;
118
+ hunger: number;
119
+ happiness: number;
120
+ itemGain: string;
121
+ }>;
122
+ }[];
123
+ }
124
+ export interface AdventureDef {
125
+ id: string;
126
+ name: string;
127
+ description: string;
128
+ difficulty: "easy" | "medium" | "hard" | "boss" | number;
129
+ levelRequired: number;
130
+ energyCost: number;
131
+ hungerCost: number;
132
+ rooms: RoomDef[];
133
+ roomMap: Map<string, RoomDef>;
134
+ startRoomId: string;
135
+ completionXp: number;
136
+ isScene?: boolean;
137
+ hideRoomCounter?: boolean;
138
+ }
139
+ export type StatType = "atk" | "def" | "crit" | "dodge" | "spd" | "stun" | "poison";
140
+ export interface StatusEffect {
141
+ stat: StatType;
142
+ amount: number;
143
+ turnsLeft: number;
144
+ }
145
+ export type StatusCondition = {
146
+ type: "burn";
147
+ damagePerTurn: number;
148
+ turnsLeft: number;
149
+ } | {
150
+ type: "poison";
151
+ damagePerTurn: number;
152
+ turnsLeft: number;
153
+ } | {
154
+ type: "freeze";
155
+ turnsLeft: number;
156
+ } | {
157
+ type: "stun";
158
+ turnsLeft: number;
159
+ } | {
160
+ type: "charm";
161
+ turnsLeft: number;
162
+ } | {
163
+ type: "blind";
164
+ turnsLeft: number;
165
+ } | {
166
+ type: "regen";
167
+ healPerTurn: number;
168
+ turnsLeft: number;
169
+ } | {
170
+ type: "shield";
171
+ amount: number;
172
+ } | {
173
+ type: "buff";
174
+ stat: StatType;
175
+ amount: number;
176
+ turnsLeft: number;
177
+ } | {
178
+ type: "debuff";
179
+ stat: StatType;
180
+ amount: number;
181
+ turnsLeft: number;
182
+ };
183
+ /** Elements immune to certain conditions */
184
+ export declare const CONDITION_IMMUNITIES: Record<string, Element[]>;
185
+ /** Check if an element is immune to a condition type */
186
+ export declare function isImmune(conditionType: string, element: Element): boolean;
187
+ export interface CombatState {
188
+ phase: "player_turn" | "player_animate" | "enemy_turn" | "enemy_animate" | "victory" | "defeat" | "fled";
189
+ playerStats: CombatStats;
190
+ enemyStats: CombatStats;
191
+ enemy: EnemyDef;
192
+ combatEnergy: number;
193
+ maxCombatEnergy: number;
194
+ playerEffects: StatusEffect[];
195
+ enemyEffects: StatusEffect[];
196
+ playerConditions: StatusCondition[];
197
+ enemyConditions: StatusCondition[];
198
+ isDefending: boolean;
199
+ turnCount: number;
200
+ log: string[];
201
+ ticksInPhase: number;
202
+ damageTakenThisBattle: number;
203
+ usedRevive: boolean;
204
+ morale: number;
205
+ playerElement: Element;
206
+ enemyElement: Element;
207
+ equippedGearIds: string[];
208
+ lastSkillUsed?: string;
209
+ comboTriggeredThisBattle: number;
210
+ }
211
+ export interface AdventureState {
212
+ active: boolean;
213
+ adventureId: string;
214
+ currentRoomId: string;
215
+ roomsVisited: string[];
216
+ phase: "room" | "combat" | "result";
217
+ combat?: CombatState;
218
+ morale: number;
219
+ textPage: number;
220
+ textFullyShown: boolean;
221
+ lootCollected: string[];
222
+ xpEarned: number;
223
+ battlesWon: number;
224
+ battlesLost: number;
225
+ battlesFled: number;
226
+ damageTaken: number;
227
+ buddyReaction: string;
228
+ }
229
+ export declare function createInactiveAdventure(): AdventureState;
230
+ /** Build a roomMap from a rooms array for fast ID lookup */
231
+ export declare function buildRoomMap(rooms: RoomDef[]): Map<string, RoomDef>;
232
+ /** Get a room by ID from an adventure */
233
+ export declare function getRoom(adventure: AdventureDef, roomId: string): RoomDef | undefined;
234
+ /** Get room index for display purposes (how many rooms visited) */
235
+ export declare function getRoomProgress(state: AdventureState): number;
236
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONDITION_IMMUNITIES = exports.SPECIES_ELEMENTS = exports.ELEMENT_ICONS = void 0;
4
+ exports.getElementMultiplier = getElementMultiplier;
5
+ exports.isImmune = isImmune;
6
+ exports.createInactiveAdventure = createInactiveAdventure;
7
+ exports.buildRoomMap = buildRoomMap;
8
+ exports.getRoom = getRoom;
9
+ exports.getRoomProgress = getRoomProgress;
10
+ // Fire > Nature > Water > Fire, Light <> Shadow
11
+ const ELEMENT_CHART = {
12
+ fire: ["nature"],
13
+ water: ["fire"],
14
+ nature: ["water"],
15
+ light: ["shadow"],
16
+ shadow: ["light"],
17
+ neutral: [],
18
+ };
19
+ const ELEMENT_WEAK = {
20
+ fire: ["water"],
21
+ water: ["nature"],
22
+ nature: ["fire"],
23
+ light: ["shadow"],
24
+ shadow: ["light"],
25
+ neutral: [],
26
+ };
27
+ function getElementMultiplier(atkElement, defElement) {
28
+ if (atkElement === "neutral" || defElement === "neutral")
29
+ return { multiplier: 1.0, label: "" };
30
+ if (ELEMENT_CHART[atkElement]?.includes(defElement))
31
+ return { multiplier: 1.5, label: "Super effective!" };
32
+ if (ELEMENT_WEAK[atkElement]?.includes(defElement))
33
+ return { multiplier: 0.6, label: "Not very effective..." };
34
+ return { multiplier: 1.0, label: "" };
35
+ }
36
+ exports.ELEMENT_ICONS = {
37
+ fire: "🔥",
38
+ water: "💧",
39
+ nature: "🌿",
40
+ light: "✨",
41
+ shadow: "🌑",
42
+ neutral: "⚪",
43
+ };
44
+ exports.SPECIES_ELEMENTS = {
45
+ rabbit: "nature",
46
+ cat: "shadow",
47
+ frog: "water",
48
+ owl: "light",
49
+ fox: "nature",
50
+ phoenix: "fire",
51
+ dragon: "fire",
52
+ };
53
+ /** Elements immune to certain conditions */
54
+ exports.CONDITION_IMMUNITIES = {
55
+ burn: ["fire"],
56
+ freeze: ["water"],
57
+ };
58
+ /** Check if an element is immune to a condition type */
59
+ function isImmune(conditionType, element) {
60
+ return exports.CONDITION_IMMUNITIES[conditionType]?.includes(element) ?? false;
61
+ }
62
+ function createInactiveAdventure() {
63
+ return {
64
+ active: false,
65
+ adventureId: "",
66
+ currentRoomId: "",
67
+ roomsVisited: [],
68
+ phase: "room",
69
+ morale: 50,
70
+ textPage: 0,
71
+ textFullyShown: false,
72
+ lootCollected: [],
73
+ xpEarned: 0,
74
+ battlesWon: 0,
75
+ battlesLost: 0,
76
+ battlesFled: 0,
77
+ damageTaken: 0,
78
+ buddyReaction: "",
79
+ };
80
+ }
81
+ /** Build a roomMap from a rooms array for fast ID lookup */
82
+ function buildRoomMap(rooms) {
83
+ const map = new Map();
84
+ for (const room of rooms) {
85
+ map.set(room.id, room);
86
+ }
87
+ return map;
88
+ }
89
+ /** Get a room by ID from an adventure */
90
+ function getRoom(adventure, roomId) {
91
+ return adventure.roomMap.get(roomId);
92
+ }
93
+ /** Get room index for display purposes (how many rooms visited) */
94
+ function getRoomProgress(state) {
95
+ return state.roomsVisited.length;
96
+ }
97
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Centralized app state — all mutable state lives here.
3
+ * Accessed and mutated from index.ts handlers.
4
+ * This consolidates the 29 global `let` variables into one object.
5
+ */
6
+ import { BuddyState } from "../buddy/types";
7
+ import { AdventureDef, AdventureState } from "../adventure/types";
8
+ import { ActiveEvent } from "../events/engine";
9
+ import { InventoryUIState } from "../rendering/inventoryUI";
10
+ import { OverlayState } from "../rendering/overlayUI";
11
+ import { MinigameMenuState } from "../rendering/minigameUI";
12
+ import { AdventureMenuState } from "../adventure/adventureUI";
13
+ import { MiniGameState } from "../minigames/types";
14
+ import { PaletteState } from "../rendering/commandPalette";
15
+ import { Screen } from "../rendering/screen";
16
+ export interface AppState {
17
+ screen: Screen;
18
+ buddyState: BuddyState | null;
19
+ appPhase: "roll-wait" | "rolling" | "reveal" | "naming" | "playing";
20
+ animFrame: number;
21
+ animTimer: ReturnType<typeof setInterval> | null;
22
+ decayTimer: ReturnType<typeof setInterval> | null;
23
+ feedbackMessage: string | undefined;
24
+ feedbackTimeout: ReturnType<typeof setTimeout> | null;
25
+ dialogueMessage: string | undefined;
26
+ dialogueSource: string | undefined;
27
+ dialogueTimeout: ReturnType<typeof setTimeout> | null;
28
+ dialogueTick: number;
29
+ activeEvent: ActiveEvent | null;
30
+ petSequence: string[] | null;
31
+ petTick: number;
32
+ inventoryUI: InventoryUIState;
33
+ overlay: OverlayState;
34
+ minigameMenu: MinigameMenuState;
35
+ adventureMenu: AdventureMenuState;
36
+ palette: PaletteState;
37
+ activeMiniGame: MiniGameState;
38
+ activeAdventure: AdventureState;
39
+ currentAdventureDef: AdventureDef | null;
40
+ endlessDepth: number;
41
+ isEndlessMode: boolean;
42
+ showingSkillMenu: boolean;
43
+ inputBuffer: string;
44
+ pendingCommand: string | null;
45
+ argsBuffer: string;
46
+ nameBuffer: string;
47
+ }
48
+ export declare function createInitialState(): AppState;
49
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ /**
3
+ * Centralized app state — all mutable state lives here.
4
+ * Accessed and mutated from index.ts handlers.
5
+ * This consolidates the 29 global `let` variables into one object.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.createInitialState = createInitialState;
9
+ const types_1 = require("../adventure/types");
10
+ const inventoryUI_1 = require("../rendering/inventoryUI");
11
+ const overlayUI_1 = require("../rendering/overlayUI");
12
+ const minigameUI_1 = require("../rendering/minigameUI");
13
+ const adventureUI_1 = require("../adventure/adventureUI");
14
+ const types_2 = require("../minigames/types");
15
+ const commandPalette_1 = require("../rendering/commandPalette");
16
+ const screen_1 = require("../rendering/screen");
17
+ function createInitialState() {
18
+ return {
19
+ screen: new screen_1.Screen(),
20
+ buddyState: null,
21
+ appPhase: "roll-wait",
22
+ animFrame: 0,
23
+ animTimer: null,
24
+ decayTimer: null,
25
+ feedbackMessage: undefined,
26
+ feedbackTimeout: null,
27
+ dialogueMessage: undefined,
28
+ dialogueSource: undefined,
29
+ dialogueTimeout: null,
30
+ dialogueTick: 0,
31
+ activeEvent: null,
32
+ petSequence: null,
33
+ petTick: 0,
34
+ inventoryUI: (0, inventoryUI_1.createInventoryUI)(),
35
+ overlay: (0, overlayUI_1.createOverlay)(),
36
+ minigameMenu: (0, minigameUI_1.createMinigameMenu)(),
37
+ adventureMenu: (0, adventureUI_1.createAdventureMenu)(),
38
+ palette: (0, commandPalette_1.createPalette)(),
39
+ activeMiniGame: (0, types_2.createInactiveGame)(),
40
+ activeAdventure: (0, types_1.createInactiveAdventure)(),
41
+ currentAdventureDef: null,
42
+ endlessDepth: 0,
43
+ isEndlessMode: false,
44
+ showingSkillMenu: false,
45
+ inputBuffer: "",
46
+ pendingCommand: null,
47
+ argsBuffer: "",
48
+ nameBuffer: "",
49
+ };
50
+ }
51
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1,16 @@
1
+ import { ActivityType, ActivityState, BuddyState, BuddyStats } from "./types";
2
+ /** Build an ActivityState for the given activity type based on current stats */
3
+ /** Build an ActivityState. Pass statOverrides to use custom stat deltas (e.g. from inventory items). */
4
+ export declare function startActivity(state: BuddyState, type: Exclude<ActivityType, "idle">, statOverrides?: Partial<BuddyStats>): ActivityState;
5
+ /**
6
+ * Apply activity progress using linear interpolation.
7
+ * Returns updated state. Clears activity and awards XP when complete.
8
+ */
9
+ export declare function applyActivityProgress(state: BuddyState): BuddyState;
10
+ /** Check if the current activity blocks a new action */
11
+ export declare function isActivityBlocked(currentActivity: ActivityType | undefined, attempted: Exclude<ActivityType, "idle">): boolean;
12
+ /** Returns seconds remaining for the current activity */
13
+ export declare function activityTimeRemaining(activity: ActivityState): number;
14
+ /** Format remaining time as "1:42" or "8s" */
15
+ export declare function formatTimeRemaining(activity: ActivityState): string;
16
+ //# sourceMappingURL=activities.d.ts.map