Exact source used by this build. SHA-256: c8e47dc418a4df470623ab42d6b1d7b9d0f1394b09f1dae1bc91a606a4984b7d.

1 import { z } from "zod";
2 import { SeasonSchema } from "../seasons/schema";
3 import { WeatherSchema } from "../weather/schema";
4 import { WaterTagSchema } from "../maps/schema";
5 export { WaterTagSchema } from "../maps/schema";
6 
7 const id = z.string().min(1);
8 const count = z.number().int().nonnegative();
9 const positive = z.number().positive();
10 const probability = z.number().min(0).max(1);
11 const quality = z.enum(["regular", "silver", "gold", "iridium"]);
12 export const FishBehaviorSchema = z.enum(["mixed", "smooth", "sinker", "floater", "dart"]);
13 export const RodSchema = z.object({
14   id, itemId: id, name: id, description: id, icon: id, price: count, requiredLevel: count.max(10),
15   baitSlots: count.max(1), tackleSlots: count.max(1), training: z.boolean(),
16 });
17 export const BaitSchema = z.object({
18   id, itemId: id, name: id, description: id, icon: id, price: count, requiredLevel: count.max(10),
19   biteTimeMultiplier: positive.max(1), barSizeBonus: count, crabQuality: quality,
20 });
21 export const TackleSchema = z.object({
22   id, itemId: id, name: id, description: id, icon: id, barSizeBonus: count,
23   biteTimeMultiplier: positive, catchDrainMultiplier: positive, bounceMultiplier: z.number().nonnegative(),
24   treasureChanceBonus: probability, qualityBonus: count.max(3),
25 });
26 export const FishSchema = z.object({
27   id: z.string().regex(/^fish_\d{2}$/), itemId: id, name: z.literal("TBD"), description: z.literal("TBD"), icon: id,
28   difficulty: z.number().int().min(15).max(110), behavior: FishBehaviorSchema,
29   minSize: positive, maxSize: positive, basePrice: count, legendary: z.boolean(), requiredLevel: count.max(10), requiredDepth: count.max(5),
30   seasons: z.array(SeasonSchema).min(1), weather: z.array(WeatherSchema).min(1),
31   timeWindows: z.array(z.object({ startMinute: count.min(360).max(1559), endMinute: count.min(361).max(1560) })
32     .refine((window) => window.endMinute > window.startMinute, "Fish time window must increase")).min(1),
33 }).refine((fish) => fish.maxSize >= fish.minSize, "Fish size range must increase")
34   .refine((fish) => fish.legendary || fish.difficulty <= 95, "Only legendary fish exceed difficulty 95");
35 export const CrabCreatureSchema = z.object({
36   id: z.string().regex(/^crab_\d{2}$/), itemId: id, name: z.literal("TBD"), description: z.literal("TBD"), icon: id,
37   minSize: positive, maxSize: positive, basePrice: count, weight: positive,
38 }).refine((creature) => creature.maxSize >= creature.minSize, "Crab creature size range must increase");
39 export const FishingTableSchema = z.object({
40   areaId: id, waterTag: WaterTagSchema, fishIds: z.array(id).min(1), crabCreatureIds: z.array(id).min(1), trashChance: probability,
41 });
42 export const FishingWaterSchema = z.object({
43   areaId: id, waterTag: WaterTagSchema, x: count, y: count, width: count.positive(), height: count.positive(), manifestKey: id,
44   /** Map-local GIDs allow different habitats in one area without overlapping coordinate masks. */
45   waterTileIds: z.array(count.positive()).min(1).optional(),
46 });
47 const IngredientSchema = z.object({ itemId: id, quantity: count.positive() });
48 export const CrabPotSchema = z.object({
49   itemId: id, recipeId: id, recipeItemId: id, icon: id, recipeIcon: id,
50   requiredLevel: count.max(10), price: count, ingredients: z.array(IngredientSchema).min(1),
51   trapperIngredients: z.array(IngredientSchema).min(1), trashChance: probability, xp: count,
52 });
53 export const FishingMechanicsSchema = z.object({
54   energyBase: positive, energyPerLevel: z.number().nonnegative(), chargeMaxMs: positive,
55   castBaseDistance: positive, castLevelInterval: positive, castLevelBonus: z.number().nonnegative(),
56   castLevelThresholds: z.array(count.positive()).refine((values) => values.every((value, index) => index === 0 || value > values[index - 1]!), "Cast level thresholds must strictly increase"),
57   castHorizontalBonus: z.number().nonnegative(),
58   biteMinMs: positive, biteMaxMs: positive, biteLevelReductionMs: z.number().nonnegative(),
59   biteFirstMultiplier: positive, biteFloorMs: positive, biteWindowMs: positive,
60   shallowBiteDepthPenalty: z.number().nonnegative(), shallowBiteDistancePenalty: z.number().nonnegative(), shallowBiteDistanceThreshold: positive,
61   barTrackHeight: positive, barBaseHeight: positive, barPerLevel: positive, trainingBarLevel: count.max(10),
62   trainingMaxDifficulty: count, physicsStepMs: positive, gravity: positive, liftAcceleration: positive, bounce: probability,
63   catchInitial: probability, catchFillPerFrame: positive.max(1), catchDrainPerFrame: positive.max(1),
64   treasureChance: probability, treasureFillPerFrame: positive.max(1), treasureDrainPerFrame: positive.max(1), treasureDelayMs: count,
65   depthMax: count.positive(), xpQualityFactor: positive, xpDifficultyDivisor: positive,
66   xpTreasureMultiplier: positive, xpPerfectMultiplier: positive, xpLegendaryMultiplier: positive, trashXp: count,
67 }).refine((value) => value.biteMinMs < value.biteMaxMs, "Bite bounds must increase")
68   .refine((value) => value.barBaseHeight + value.barPerLevel * 10 < value.barTrackHeight, "Fishing bar must fit track");
69 export const FishingSchema = z.object({
70   rods: z.array(RodSchema).min(1), baits: z.array(BaitSchema), tackles: z.array(TackleSchema),
71   fish: z.array(FishSchema).min(1), crabCreatures: z.array(CrabCreatureSchema).min(1),
72   tables: z.array(FishingTableSchema).min(1), waters: z.array(FishingWaterSchema), waterTileIds: z.array(count.positive()).min(1), shopIds: z.array(id).min(1),
73   trash: z.array(z.object({ itemId: id, weight: positive, icon: id })).min(1),
74   treasure: z.array(z.object({ itemId: id, weight: positive, minQuantity: count.positive(), maxQuantity: count.positive(), icon: id })
75     .refine((entry) => entry.maxQuantity >= entry.minQuantity, "Treasure quantity range must increase")).min(1),
76   crabPot: CrabPotSchema, mechanics: FishingMechanicsSchema,
77   visuals: z.object({ bobber: id, bite: id, bar: id, fish: id, treasure: id, water: id }),
78 });
79 export type FishingContent = z.infer<typeof FishingSchema>;
80 export type FishingRod = z.infer<typeof RodSchema>;
81 export type FishingBait = z.infer<typeof BaitSchema>;
82 export type FishingTackle = z.infer<typeof TackleSchema>;
83 export type FishDefinition = z.infer<typeof FishSchema>;
84 export type CrabCreature = z.infer<typeof CrabCreatureSchema>;
85 export type FishingTable = z.infer<typeof FishingTableSchema>;
86 export type FishingWater = z.infer<typeof FishingWaterSchema>;
87 export type WaterTag = z.infer<typeof WaterTagSchema>;
88 export type FishBehavior = z.infer<typeof FishBehaviorSchema>;
89