70 lines
2.4 KiB
TypeScript
70 lines
2.4 KiB
TypeScript
import type { AppliedEvent, TripEvent } from "@deadhead/sim";
|
||
import { z } from "zod";
|
||
// Local, not from ./entities: entities imports this file.
|
||
const idSchema = z.string().min(1);
|
||
const timeSchema = z.number().int().nonnegative();
|
||
|
||
const credits = z.number().int();
|
||
|
||
/** One option's pre-rolled outcome (decision 0.5.143). */
|
||
const eventOutcomeSchema = z.object({
|
||
delayMs: z.number().int(),
|
||
hullLoss: z.number().nonnegative(),
|
||
payLoss: credits.nonnegative(),
|
||
fee: credits.nonnegative(),
|
||
bonus: credits.nonnegative(),
|
||
xpBonusPct: z.number().nonnegative(),
|
||
extraFuelFu: z.number().nonnegative(),
|
||
});
|
||
|
||
/** A trip's event as rolled at dispatch (decisions 0.5.143–0.5.145). */
|
||
export const savedTripEventSchema = z.object({
|
||
eventId: idSchema,
|
||
kind: z.enum(["automatic", "radio"]),
|
||
good: z.boolean(),
|
||
fireAt: timeSchema,
|
||
windowEndsAt: timeSchema,
|
||
options: z.array(z.object({ id: idSchema, available: z.boolean(), outcome: eventOutcomeSchema })),
|
||
defaultOptionId: idSchema,
|
||
});
|
||
|
||
/** What the event changed once its option applied. */
|
||
export const appliedEventSchema = z.object({
|
||
eventId: idSchema,
|
||
optionId: idSchema,
|
||
answered: z.boolean(),
|
||
arrivalAt: timeSchema,
|
||
hullLoss: z.number().nonnegative(),
|
||
payLoss: credits.nonnegative(),
|
||
fee: credits.nonnegative(),
|
||
bonus: credits.nonnegative(),
|
||
priorityLost: credits.nonnegative(),
|
||
xpBonusPct: z.number().nonnegative(),
|
||
extraFuelFu: z.number().nonnegative(),
|
||
});
|
||
|
||
/**
|
||
* A radio call waiting for the player (decision 0.5.144): fired, not yet
|
||
* answered, window still open. The options' outcomes stay hidden: the player
|
||
* chooses on what each option might do (content), not on what it will.
|
||
*/
|
||
export const radioCallSchema = z.object({
|
||
dispatchId: idSchema,
|
||
shipId: idSchema.nullable(),
|
||
pilotId: idSchema,
|
||
eventId: idSchema,
|
||
fireAt: timeSchema,
|
||
windowEndsAt: timeSchema,
|
||
options: z.array(z.object({ id: idSchema, available: z.boolean() })),
|
||
defaultOptionId: idSchema,
|
||
/** Flown by an Independent pilot's own choice (CR-021). */
|
||
independent: z.boolean(),
|
||
});
|
||
export type RadioCall = z.infer<typeof radioCallSchema>;
|
||
|
||
// The saved shapes are the sim's own: a change on either side fails the build.
|
||
type Same<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
|
||
const _sameEvent: Same<z.infer<typeof savedTripEventSchema>, TripEvent> = true;
|
||
const _sameApplied: Same<z.infer<typeof appliedEventSchema>, AppliedEvent> = true;
|
||
void [_sameEvent, _sameApplied];
|