Fraser commited on
Commit
987557b
·
1 Parent(s): 891a1e1
src/lib/components/Piclets/PicletDetail.svelte CHANGED
@@ -18,7 +18,6 @@
18
  let { instance, onClose, onDeleted }: Props = $props();
19
  let showDeleteConfirm = $state(false);
20
  let selectedTab = $state<'about' | 'stats' | 'abilities' | 'moves'>('about');
21
- let expandedMoves = $state(new Set<number>());
22
  let isSharing = $state(false);
23
 
24
  // Convert to battle definition to get enhanced ability data
@@ -59,14 +58,6 @@
59
  return '#34c759';
60
  }
61
 
62
- function toggleMoveExpanded(index: number) {
63
- if (expandedMoves.has(index)) {
64
- expandedMoves.delete(index);
65
- } else {
66
- expandedMoves.add(index);
67
- }
68
- expandedMoves = new Set(expandedMoves);
69
- }
70
 
71
  async function handleShare() {
72
  isSharing = true;
@@ -217,15 +208,10 @@
217
  <div class="content-card">
218
  <div class="moves-list">
219
  {#each instance.moves as move, index}
220
- <button
221
- class="move-item"
222
- onclick={() => toggleMoveExpanded(index)}
223
- >
224
- <MoveDisplay
225
- {move}
226
- expanded={expandedMoves.has(index)}
227
- />
228
- </button>
229
  {/each}
230
  </div>
231
  </div>
 
18
  let { instance, onClose, onDeleted }: Props = $props();
19
  let showDeleteConfirm = $state(false);
20
  let selectedTab = $state<'about' | 'stats' | 'abilities' | 'moves'>('about');
 
21
  let isSharing = $state(false);
22
 
23
  // Convert to battle definition to get enhanced ability data
 
58
  return '#34c759';
59
  }
60
 
 
 
 
 
 
 
 
 
61
 
62
  async function handleShare() {
63
  isSharing = true;
 
208
  <div class="content-card">
209
  <div class="moves-list">
210
  {#each instance.moves as move, index}
211
+ <MoveDisplay
212
+ {move}
213
+ expanded={true}
214
+ />
 
 
 
 
 
215
  {/each}
216
  </div>
217
  </div>
src/lib/db/piclets.ts CHANGED
@@ -2,7 +2,6 @@ import { db } from './index';
2
  import type { PicletInstance, Monster, BattleMove } from './schema';
3
  import { PicletType, AttackType, getTypeFromConcept } from '../types/picletTypes';
4
  import type { PicletStats } from '../types';
5
- import { Nature } from '../types';
6
 
7
  // Convert a generated Monster to a PicletInstance
8
  export async function monsterToPicletInstance(monster: Monster, level: number = 5): Promise<Omit<PicletInstance, 'id'>> {
@@ -10,98 +9,39 @@ export async function monsterToPicletInstance(monster: Monster, level: number =
10
  throw new Error('Monster must have stats to create PicletInstance');
11
  }
12
 
13
- // Check if this is a new battle-ready monster or legacy format
14
- const isBattleReady = 'baseStats' in monster.stats;
15
 
16
- let baseHp: number, baseAttack: number, baseDefense: number, baseSpeed: number;
17
- let moves: BattleMove[];
18
- let primaryType: PicletType;
19
- let tier: string;
20
 
21
- if (isBattleReady) {
22
- const stats = monster.stats as PicletStats;
23
-
24
- // Calculate base stats from battle-ready format
25
- baseHp = Math.floor(stats.baseStats.hp * 2 + 50);
26
- baseAttack = Math.floor(stats.baseStats.attack * 1.5 + 30);
27
- baseDefense = Math.floor(stats.baseStats.defense * 1.5 + 30);
28
- baseSpeed = Math.floor(stats.baseStats.speed * 1.5 + 30);
29
-
30
- // Determine primary type from battle stats
31
- const normalizedType = stats.primaryType.toLowerCase();
32
- const validType = Object.values(PicletType).find(type => type === normalizedType);
33
- primaryType = validType || getTypeFromConcept(monster.concept, monster.imageCaption);
34
-
35
- if (!validType) {
36
- console.warn(`Invalid primaryType "${stats.primaryType}" from stats, falling back to concept detection`);
37
- }
38
-
39
- // Create moves from battle-ready format
40
- moves = stats.movepool.map(move => ({
41
- name: move.name,
42
- type: move.type as unknown as AttackType,
43
- power: move.power,
44
- accuracy: move.accuracy,
45
- pp: move.pp,
46
- currentPp: move.pp,
47
- description: `${move.effects.length} effects` // Simplified description for now
48
- }));
49
-
50
- tier = stats.tier;
51
- } else {
52
- // Legacy format
53
- const legacyStats = monster.stats as any;
54
- baseHp = Math.floor(legacyStats.HP * 2 + 50);
55
- baseAttack = Math.floor(legacyStats.attack * 1.5 + 30);
56
- baseDefense = Math.floor(legacyStats.defence * 1.5 + 30);
57
- baseSpeed = Math.floor(legacyStats.speed * 1.5 + 30);
58
-
59
- // Auto-detect type for legacy monsters
60
- primaryType = getTypeFromConcept(monster.concept, monster.imageCaption);
61
-
62
- // Create legacy moves
63
- moves = [
64
- {
65
- name: legacyStats.attackActionName,
66
- type: primaryType as unknown as AttackType,
67
- power: 50,
68
- accuracy: 95,
69
- pp: 20,
70
- currentPp: 20,
71
- description: legacyStats.attackActionDescription
72
- },
73
- {
74
- name: legacyStats.buffActionName,
75
- type: AttackType.NORMAL,
76
- power: 0,
77
- accuracy: 100,
78
- pp: 15,
79
- currentPp: 15,
80
- description: legacyStats.buffActionDescription
81
- },
82
- {
83
- name: legacyStats.debuffActionName,
84
- type: AttackType.NORMAL,
85
- power: 0,
86
- accuracy: 85,
87
- pp: 15,
88
- currentPp: 15,
89
- description: legacyStats.debuffActionDescription
90
- },
91
- {
92
- name: legacyStats.specialActionName,
93
- type: primaryType as unknown as AttackType,
94
- power: 80,
95
- accuracy: 90,
96
- pp: 5,
97
- currentPp: 5,
98
- description: legacyStats.specialActionDescription
99
- }
100
- ];
101
-
102
- tier = legacyStats.tier || 'medium';
103
  }
104
 
 
 
 
 
 
 
 
 
 
 
 
105
  // Field stats are variations of regular stats
106
  const baseFieldAttack = Math.floor(baseAttack * 0.8);
107
  const baseFieldDefense = Math.floor(baseDefense * 0.8);
@@ -143,7 +83,8 @@ export async function monsterToPicletInstance(monster: Monster, level: number =
143
 
144
  // Battle
145
  moves,
146
- nature: Nature.HARDY, // Default nature
 
147
 
148
  // Roster
149
  isInRoster: false,
@@ -152,7 +93,7 @@ export async function monsterToPicletInstance(monster: Monster, level: number =
152
  // Metadata
153
  caughtAt: new Date(),
154
  bst,
155
- tier: tier, // Use tier from stats
156
  role: 'balanced', // Could be enhanced based on stat distribution
157
  variance: 0,
158
 
 
2
  import type { PicletInstance, Monster, BattleMove } from './schema';
3
  import { PicletType, AttackType, getTypeFromConcept } from '../types/picletTypes';
4
  import type { PicletStats } from '../types';
 
5
 
6
  // Convert a generated Monster to a PicletInstance
7
  export async function monsterToPicletInstance(monster: Monster, level: number = 5): Promise<Omit<PicletInstance, 'id'>> {
 
9
  throw new Error('Monster must have stats to create PicletInstance');
10
  }
11
 
12
+ // All monsters must now have the battle-ready format
13
+ const stats = monster.stats as PicletStats;
14
 
15
+ if (!stats.baseStats || !stats.specialAbility || !stats.movepool) {
16
+ throw new Error('Monster stats must be in battle-ready format with baseStats, specialAbility, and movepool');
17
+ }
 
18
 
19
+ // Calculate base stats from battle-ready format
20
+ const baseHp = Math.floor(stats.baseStats.hp * 2 + 50);
21
+ const baseAttack = Math.floor(stats.baseStats.attack * 1.5 + 30);
22
+ const baseDefense = Math.floor(stats.baseStats.defense * 1.5 + 30);
23
+ const baseSpeed = Math.floor(stats.baseStats.speed * 1.5 + 30);
24
+
25
+ // Determine primary type from battle stats
26
+ const normalizedType = stats.primaryType.toLowerCase();
27
+ const validType = Object.values(PicletType).find(type => type === normalizedType);
28
+ const primaryType = validType || getTypeFromConcept(monster.concept, monster.imageCaption);
29
+
30
+ if (!validType) {
31
+ console.warn(`Invalid primaryType "${stats.primaryType}" from stats, falling back to concept detection`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  }
33
 
34
+ // Create moves from battle-ready format
35
+ const moves: BattleMove[] = stats.movepool.map(move => ({
36
+ name: move.name,
37
+ type: move.type as unknown as AttackType,
38
+ power: move.power,
39
+ accuracy: move.accuracy,
40
+ pp: move.pp,
41
+ currentPp: move.pp,
42
+ description: `${move.effects?.length || 0} effects` // Show number of effects
43
+ }));
44
+
45
  // Field stats are variations of regular stats
46
  const baseFieldAttack = Math.floor(baseAttack * 0.8);
47
  const baseFieldDefense = Math.floor(baseDefense * 0.8);
 
83
 
84
  // Battle
85
  moves,
86
+ nature: stats.nature,
87
+ specialAbility: stats.specialAbility,
88
 
89
  // Roster
90
  isInRoster: false,
 
93
  // Metadata
94
  caughtAt: new Date(),
95
  bst,
96
+ tier: stats.tier, // Use tier from stats
97
  role: 'balanced', // Could be enhanced based on stat distribution
98
  variance: 0,
99
 
src/lib/db/schema.ts CHANGED
@@ -1,4 +1,5 @@
1
  import type { PicletType, AttackType } from '../types/picletTypes';
 
2
 
3
  // Enums
4
  export enum EncounterType {
@@ -51,6 +52,7 @@ export interface PicletInstance {
51
  // Battle
52
  moves: BattleMove[];
53
  nature: string;
 
54
 
55
  // Roster
56
  isInRoster: boolean;
@@ -133,7 +135,7 @@ export interface BattleState {
133
  capturedPiclet?: PicletInstance;
134
  }
135
 
136
- // Legacy Monster interface for backward compatibility
137
  export interface Monster {
138
  id?: number;
139
  name: string;
@@ -142,23 +144,6 @@ export interface Monster {
142
  imageCaption: string;
143
  concept: string;
144
  imagePrompt: string;
145
- stats?: {
146
- name: string;
147
- description: string;
148
- tier?: 'low' | 'medium' | 'high' | 'legendary';
149
- HP: number;
150
- defence: number;
151
- attack: number;
152
- speed: number;
153
- specialPassiveTrait: string;
154
- attackActionName: string;
155
- attackActionDescription: string;
156
- buffActionName: string;
157
- buffActionDescription: string;
158
- debuffActionName: string;
159
- debuffActionDescription: string;
160
- specialActionName: string;
161
- specialActionDescription: string;
162
- };
163
  createdAt: Date;
164
  }
 
1
  import type { PicletType, AttackType } from '../types/picletTypes';
2
+ import type { SpecialAbility } from '../battle-engine/types';
3
 
4
  // Enums
5
  export enum EncounterType {
 
52
  // Battle
53
  moves: BattleMove[];
54
  nature: string;
55
+ specialAbility: SpecialAbility;
56
 
57
  // Roster
58
  isInRoster: boolean;
 
135
  capturedPiclet?: PicletInstance;
136
  }
137
 
138
+ // Monster interface - now only supports battle-ready format
139
  export interface Monster {
140
  id?: number;
141
  name: string;
 
144
  imageCaption: string;
145
  concept: string;
146
  imagePrompt: string;
147
+ stats?: import('../types').PicletStats; // Only battle-ready format
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  createdAt: Date;
149
  }
src/lib/utils/battleConversion.ts CHANGED
@@ -22,20 +22,8 @@ export function picletInstanceToBattleDefinition(instance: PicletInstance): Picl
22
  // Convert simple moves to full battle moves
23
  const movepool: Move[] = instance.moves.map(move => convertBattleMoveToMove(move, instance.primaryType));
24
 
25
- // Create a basic special ability if none exists
26
- const specialAbility: SpecialAbility = {
27
- name: "Adaptive",
28
- description: "A basic ability that adapts to combat situations",
29
- triggers: [{
30
- event: "endOfTurn",
31
- effects: [{
32
- type: 'heal',
33
- target: 'self',
34
- amount: 'small',
35
- condition: 'ifLowHp'
36
- }]
37
- }]
38
- };
39
 
40
  // Determine tier based on BST (Base Stat Total)
41
  const bst = baseStats.hp + baseStats.attack + baseStats.defense + baseStats.speed;
 
22
  // Convert simple moves to full battle moves
23
  const movepool: Move[] = instance.moves.map(move => convertBattleMoveToMove(move, instance.primaryType));
24
 
25
+ // Use the actual special ability data from the instance
26
+ const specialAbility: SpecialAbility = instance.specialAbility;
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  // Determine tier based on BST (Base Stat Total)
29
  const bst = baseStats.hp + baseStats.attack + baseStats.defense + baseStats.speed;