feat(types): add flexible JSON types for economy layer; define item pricing, rewards, and inventory state

This commit is contained in:
2025-10-05 00:04:02 -05:00
parent a5d4e87444
commit 413868f4be

101
src/game/economy/types.ts Normal file
View File

@@ -0,0 +1,101 @@
// Tipos para la capa JSON flexible de economía.
// Estos tipos NO fuerzan el esquema en base de datos, solo sirven para dar seguridad de tipos en el código.
export type PriceItemComponent = {
itemKey?: string; // preferido para lookup
itemId?: string; // fallback directo
qty: number;
};
export type Price = {
coins?: number;
items?: PriceItemComponent[];
extra?: Record<string, unknown>;
};
export type ChestReward =
| { type: 'coins'; amount: number }
| { type: 'item'; itemKey?: string; itemId?: string; qty: number }
| { type: 'role'; roleId: string };
export type PassiveEffect = {
key: string; // p.ej. "xpBoost", "defenseUp"
value?: unknown; // libre según tu lógica
expiresAt?: string; // ISO string opcional
};
export type BreakableProps = {
enabled?: boolean;
// Para ítems no apilables, cada instancia puede tener durabilidad independiente
maxDurability?: number;
// Opcional: cuánto se reduce por uso/acción
durabilityPerUse?: number;
};
export type CraftableProps = {
enabled?: boolean;
};
export type ChestProps = {
enabled?: boolean;
// Recompensas que el bot debe otorgar al "abrir"
rewards?: ChestReward[];
// Si true, consume 1 del inventario al abrir
consumeOnOpen?: boolean;
};
export type EventCurrencyProps = {
enabled?: boolean;
eventKey?: string; // Identificador del evento
};
export type MutationPolicy = {
// Lista blanca/negra para mutaciones permitidas
allowedKeys?: string[];
deniedKeys?: string[];
};
export type ShopProps = {
purchasable?: boolean; // si puede venderse en la tienda (además de ShopOffer)
};
export type ItemProps = {
// Flags y bloques de config opcionales
breakable?: BreakableProps; // romperse
craftable?: CraftableProps; // craftear
chest?: ChestProps; // estilo cofre que al usar da roles/ítems/monedas
eventCurrency?: EventCurrencyProps; // puede actuar como moneda de evento
passiveEffects?: PassiveEffect[]; // efectos por tenerlo
mutationPolicy?: MutationPolicy; // reglas para mutaciones extra
craftingOnly?: boolean; // ítem que solo sirve para craftear (p.ej. mineral)
availableFrom?: string; // ISO para adquirir/usar si deseas sobreescribir a nivel props
availableTo?: string;
usableFrom?: string;
usableTo?: string;
shop?: ShopProps; // metadatos de tienda
// Cualquier otra extensión libre
[k: string]: unknown;
};
// Estado por entrada de inventario (InventoryEntry.state)
export type InventoryState = {
// Para ítems no apilables (stackable=false), puedes manejar varias instancias con durabilidad/expiración por unidad
instances?: Array<{
durability?: number;
expiresAt?: string; // ISO
notes?: string;
// Mutaciones aplicadas a esta instancia concreta
mutations?: string[]; // mutation keys, o ids si prefieres
}>;
// Campo libre para tus necesidades
notes?: string;
[k: string]: unknown;
};
export type OpenChestResult = {
coinsDelta: number;
itemsToAdd: Array<{ itemKey?: string; itemId?: string; qty: number }>;
rolesToGrant: string[]; // IDs de roles a otorgar
consumed: boolean; // si el ítem/cofre se consumió
};