Fraser commited on
Commit
60e0688
·
1 Parent(s): 230b475

OH GOT THE STATS AREN'T ACTUALLY STORED NOOOOOOOOO

Browse files
src/lib/db/index.ts CHANGED
@@ -39,6 +39,15 @@ export class PicletDatabase extends Dexie {
39
  gameState: '++id, lastPlayed',
40
  trainerScanProgress: 'imagePath, trainerName, status, completedAt'
41
  });
 
 
 
 
 
 
 
 
 
42
  }
43
  }
44
 
 
39
  gameState: '++id, lastPlayed',
40
  trainerScanProgress: 'imagePath, trainerName, status, completedAt'
41
  });
42
+
43
+ // Version 7: Move schema updated to include complete Move data (priority, flags, effects)
44
+ // No schema changes needed - just expanded interfaces, data will be preserved
45
+ this.version(7).stores({
46
+ picletInstances: '++id, typeId, nickname, isInRoster, rosterPosition, caughtAt',
47
+ encounters: '++id, type, createdAt',
48
+ gameState: '++id, lastPlayed',
49
+ trainerScanProgress: 'imagePath, trainerName, status, completedAt'
50
+ });
51
  }
52
  }
53
 
src/lib/db/piclets.ts CHANGED
@@ -1,7 +1,8 @@
1
  import { db } from './index';
2
  import type { PicletInstance, BattleMove } from './schema';
3
- import { PicletType, AttackType, getTypeFromConcept } from '../types/picletTypes';
4
  import type { PicletStats } from '../types';
 
5
  import { generateUnlockLevels } from '../services/unlockLevels';
6
 
7
  // Interface for generated piclet data (from PicletResult component)
@@ -36,28 +37,49 @@ export async function generatedDataToPicletInstance(data: GeneratedPicletData, l
36
  const baseSpeed = Math.floor(stats.baseStats.speed * 1.5 + 30);
37
 
38
  // Determine primary type from battle stats
39
- const normalizedType = stats.primaryType.toLowerCase();
40
- const validType = Object.values(PicletType).find(type => type === normalizedType);
41
- const primaryType = validType || getTypeFromConcept(data.concept, data.imageCaption);
42
 
43
- if (!validType) {
44
  console.warn(`Invalid primaryType "${stats.primaryType}" from stats, falling back to concept detection`);
45
  }
46
 
47
- // Create moves from battle-ready format (without unlock levels initially)
 
 
 
 
 
 
 
 
 
 
 
 
48
  const baseMoves: BattleMove[] = stats.movepool.map(move => ({
49
  name: move.name,
50
- type: move.type as unknown as AttackType,
51
  power: move.power,
52
  accuracy: move.accuracy,
53
  pp: move.pp,
 
 
 
54
  currentPp: move.pp,
55
- description: move.description,
56
  unlockLevel: 1 // Temporary, will be set below
57
  }));
58
 
59
  // Generate unlock levels for moves and special ability
60
- const { movesWithUnlocks, abilityUnlockLevel } = generateUnlockLevels(baseMoves, stats.specialAbility);
 
 
 
 
 
 
 
61
  const moves = movesWithUnlocks;
62
 
63
  // Field stats are variations of regular stats
@@ -90,9 +112,9 @@ export async function generatedDataToPicletInstance(data: GeneratedPicletData, l
90
  return {
91
  // Type Info
92
  typeId: data.name.toLowerCase().replace(/\s+/g, '-'),
93
- nickname: data.name,
94
  primaryType: primaryType,
95
- secondaryType: undefined,
96
 
97
  // Current Stats
98
  currentHp: maxHp,
@@ -116,7 +138,7 @@ export async function generatedDataToPicletInstance(data: GeneratedPicletData, l
116
  // Battle
117
  moves,
118
  nature: stats.nature,
119
- specialAbility: stats.specialAbility,
120
  specialAbilityUnlockLevel: abilityUnlockLevel,
121
 
122
  // Roster
 
1
  import { db } from './index';
2
  import type { PicletInstance, BattleMove } from './schema';
3
+ import { PicletType, getTypeFromConcept } from '../types/picletTypes';
4
  import type { PicletStats } from '../types';
5
+ import type { Move as BattleEngineMove } from '../battle-engine/types';
6
  import { generateUnlockLevels } from '../services/unlockLevels';
7
 
8
  // Interface for generated piclet data (from PicletResult component)
 
37
  const baseSpeed = Math.floor(stats.baseStats.speed * 1.5 + 30);
38
 
39
  // Determine primary type from battle stats
40
+ const normalizedPrimaryType = stats.primaryType.toLowerCase();
41
+ const validPrimaryType = Object.values(PicletType).find(type => type === normalizedPrimaryType);
42
+ const primaryType = validPrimaryType || getTypeFromConcept(data.concept, data.imageCaption);
43
 
44
+ if (!validPrimaryType) {
45
  console.warn(`Invalid primaryType "${stats.primaryType}" from stats, falling back to concept detection`);
46
  }
47
 
48
+ // Handle secondary type
49
+ let secondaryType: PicletType | undefined = undefined;
50
+ if (stats.secondaryType && stats.secondaryType !== null) {
51
+ const normalizedSecondaryType = stats.secondaryType.toLowerCase();
52
+ const validSecondaryType = Object.values(PicletType).find(type => type === normalizedSecondaryType);
53
+ secondaryType = validSecondaryType;
54
+ if (!validSecondaryType) {
55
+ console.warn(`Invalid secondaryType "${stats.secondaryType}" from stats, ignoring`);
56
+ }
57
+ }
58
+
59
+ // Create moves from battle-ready format preserving all data
60
+ // Convert from PicletStats.BattleMove (loose types) to schema.BattleMove (strict types)
61
  const baseMoves: BattleMove[] = stats.movepool.map(move => ({
62
  name: move.name,
63
+ type: move.type as any, // Type conversion from string union to AttackType enum
64
  power: move.power,
65
  accuracy: move.accuracy,
66
  pp: move.pp,
67
+ priority: move.priority,
68
+ flags: move.flags as any, // Type conversion from string[] to MoveFlag[]
69
+ effects: move.effects as any, // Type conversion between BattleEffect types
70
  currentPp: move.pp,
 
71
  unlockLevel: 1 // Temporary, will be set below
72
  }));
73
 
74
  // Generate unlock levels for moves and special ability
75
+ // Convert from PicletStats.SpecialAbility to battle-engine.SpecialAbility
76
+ const convertedSpecialAbility = {
77
+ name: stats.specialAbility.name,
78
+ description: stats.specialAbility.description,
79
+ effects: stats.specialAbility.effects as any,
80
+ triggers: stats.specialAbility.triggers as any
81
+ };
82
+ const { movesWithUnlocks, abilityUnlockLevel } = generateUnlockLevels(baseMoves, convertedSpecialAbility);
83
  const moves = movesWithUnlocks;
84
 
85
  // Field stats are variations of regular stats
 
112
  return {
113
  // Type Info
114
  typeId: data.name.toLowerCase().replace(/\s+/g, '-'),
115
+ nickname: stats.name || data.name, // Use stats.name if available, fallback to data.name
116
  primaryType: primaryType,
117
+ secondaryType: secondaryType,
118
 
119
  // Current Stats
120
  currentHp: maxHp,
 
138
  // Battle
139
  moves,
140
  nature: stats.nature,
141
+ specialAbility: convertedSpecialAbility,
142
  specialAbilityUnlockLevel: abilityUnlockLevel,
143
 
144
  // Roster
src/lib/db/schema.ts CHANGED
@@ -1,5 +1,5 @@
1
  import type { PicletType, AttackType } from '../types/picletTypes';
2
- import type { SpecialAbility } from '../battle-engine/types';
3
 
4
  // Enums
5
  export enum EncounterType {
@@ -10,15 +10,9 @@ export enum EncounterType {
10
  FIRST_PICLET = 'firstPiclet'
11
  }
12
 
13
- // Battle Move embedded object
14
- export interface BattleMove {
15
- name: string;
16
- type: AttackType;
17
- power: number;
18
- accuracy: number;
19
- pp: number;
20
  currentPp: number;
21
- description: string;
22
  unlockLevel: number; // Level at which this move is unlocked
23
  }
24
 
 
1
  import type { PicletType, AttackType } from '../types/picletTypes';
2
+ import type { SpecialAbility, Move } from '../battle-engine/types';
3
 
4
  // Enums
5
  export enum EncounterType {
 
10
  FIRST_PICLET = 'firstPiclet'
11
  }
12
 
13
+ // Battle Move with unlock level - extends the complete Move interface
14
+ export interface BattleMove extends Move {
 
 
 
 
 
15
  currentPp: number;
 
16
  unlockLevel: number; // Level at which this move is unlocked
17
  }
18
 
src/lib/utils/battleConversion.ts CHANGED
@@ -2,10 +2,10 @@
2
  * Conversion utilities for transforming database types to battle engine types
3
  */
4
 
5
- import type { PicletInstance, BattleMove } from '$lib/db/schema';
6
  import type { PicletDefinition, Move, BaseStats, SpecialAbility } from '$lib/battle-engine/types';
7
- import type { PicletStats, BattleEffect, AbilityTrigger } from '$lib/types';
8
- import { PicletType, AttackType } from '$lib/types/picletTypes';
9
  import { recalculatePicletStats } from '$lib/services/levelingService';
10
  import { getUnlockedMoves, isSpecialAbilityUnlocked } from '$lib/services/unlockLevels';
11
 
@@ -25,17 +25,35 @@ export function picletInstanceToBattleDefinition(instance: PicletInstance): Picl
25
  speed: updatedInstance.speed // Includes level scaling and nature modifiers
26
  };
27
 
28
- // Only include unlocked moves
29
  const unlockedMoves = getUnlockedMoves(instance.moves, updatedInstance.level);
30
- const movepool: Move[] = unlockedMoves.map(move => convertBattleMoveToMove(move, instance.primaryType));
 
 
 
 
 
 
 
 
 
31
 
32
  // Ensure at least one move is available (first move should always be unlocked at level 1)
33
  if (movepool.length === 0) {
34
  console.warn(`Piclet ${instance.nickname} has no unlocked moves at level ${updatedInstance.level}!`);
35
  // Emergency fallback - unlock first move
36
  if (instance.moves.length > 0) {
37
- const firstMove = convertBattleMoveToMove(instance.moves[0], instance.primaryType);
38
- movepool.push(firstMove);
 
 
 
 
 
 
 
 
 
39
  }
40
  }
41
 
@@ -53,7 +71,6 @@ export function picletInstanceToBattleDefinition(instance: PicletInstance): Picl
53
  specialAbility = {
54
  name: "Locked Ability",
55
  description: `Unlocks at level ${instance.specialAbilityUnlockLevel}`,
56
- trigger: "onBattleStart" as any,
57
  effects: []
58
  };
59
  }
@@ -74,47 +91,11 @@ export function picletInstanceToBattleDefinition(instance: PicletInstance): Picl
74
  secondaryType: instance.secondaryType,
75
  baseStats,
76
  nature: instance.nature,
77
- specialAbility,
78
  movepool
79
  };
80
  }
81
 
82
- /**
83
- * Convert BattleMove to full Move for battle engine
84
- */
85
- function convertBattleMoveToMove(battleMove: BattleMove, primaryType: PicletType): Move {
86
- // Create basic effects based on move properties
87
- const effects: any[] = [];
88
-
89
- if (battleMove.power > 0) {
90
- effects.push({
91
- type: 'damage',
92
- target: 'opponent',
93
- amount: battleMove.power >= 80 ? 'strong' :
94
- battleMove.power >= 60 ? 'normal' : 'weak'
95
- });
96
- }
97
-
98
- // Add status or stat effects for non-damaging moves
99
- if (battleMove.power === 0) {
100
- effects.push({
101
- type: 'modifyStats',
102
- target: 'self',
103
- stats: { attack: 'increase' }
104
- });
105
- }
106
-
107
- return {
108
- name: battleMove.name,
109
- type: battleMove.type,
110
- power: battleMove.power,
111
- accuracy: battleMove.accuracy,
112
- pp: battleMove.pp,
113
- priority: 0,
114
- flags: battleMove.power > 0 && battleMove.name.toLowerCase().includes('tackle') ? ['contact'] : [],
115
- effects
116
- };
117
- }
118
 
119
 
120
  /**
@@ -144,12 +125,12 @@ export function picletStatsToBattleDefinition(stats: PicletStats, name: string,
144
  name: stats.name || name,
145
  description: stats.description || concept,
146
  tier: stats.tier,
147
- primaryType: stats.primaryType,
148
- secondaryType: stats.secondaryType || undefined,
149
  baseStats: stats.baseStats,
150
  nature: stats.nature,
151
- specialAbility: stats.specialAbility,
152
- movepool: stats.movepool
153
  };
154
  }
155
 
 
2
  * Conversion utilities for transforming database types to battle engine types
3
  */
4
 
5
+ import type { PicletInstance } from '$lib/db/schema';
6
  import type { PicletDefinition, Move, BaseStats, SpecialAbility } from '$lib/battle-engine/types';
7
+ import type { PicletStats } from '$lib/types';
8
+ import { PicletType } from '$lib/types/picletTypes';
9
  import { recalculatePicletStats } from '$lib/services/levelingService';
10
  import { getUnlockedMoves, isSpecialAbilityUnlocked } from '$lib/services/unlockLevels';
11
 
 
25
  speed: updatedInstance.speed // Includes level scaling and nature modifiers
26
  };
27
 
28
+ // Only include unlocked moves - BattleMove now contains complete Move data
29
  const unlockedMoves = getUnlockedMoves(instance.moves, updatedInstance.level);
30
+ const movepool: Move[] = unlockedMoves.map(move => ({
31
+ name: move.name,
32
+ type: move.type,
33
+ power: move.power,
34
+ accuracy: move.accuracy,
35
+ pp: move.pp,
36
+ priority: move.priority,
37
+ flags: move.flags,
38
+ effects: move.effects
39
+ }));
40
 
41
  // Ensure at least one move is available (first move should always be unlocked at level 1)
42
  if (movepool.length === 0) {
43
  console.warn(`Piclet ${instance.nickname} has no unlocked moves at level ${updatedInstance.level}!`);
44
  // Emergency fallback - unlock first move
45
  if (instance.moves.length > 0) {
46
+ const firstMove = instance.moves[0];
47
+ movepool.push({
48
+ name: firstMove.name,
49
+ type: firstMove.type,
50
+ power: firstMove.power,
51
+ accuracy: firstMove.accuracy,
52
+ pp: firstMove.pp,
53
+ priority: firstMove.priority,
54
+ flags: firstMove.flags,
55
+ effects: firstMove.effects
56
+ });
57
  }
58
  }
59
 
 
71
  specialAbility = {
72
  name: "Locked Ability",
73
  description: `Unlocks at level ${instance.specialAbilityUnlockLevel}`,
 
74
  effects: []
75
  };
76
  }
 
91
  secondaryType: instance.secondaryType,
92
  baseStats,
93
  nature: instance.nature,
94
+ specialAbility: specialAbility!,
95
  movepool
96
  };
97
  }
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
 
101
  /**
 
125
  name: stats.name || name,
126
  description: stats.description || concept,
127
  tier: stats.tier,
128
+ primaryType: stats.primaryType as PicletType,
129
+ secondaryType: stats.secondaryType as PicletType || undefined,
130
  baseStats: stats.baseStats,
131
  nature: stats.nature,
132
+ specialAbility: stats.specialAbility as any,
133
+ movepool: stats.movepool as any
134
  };
135
  }
136