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