feat: ajustar bloques divisores en los comandos de mina y racha para mejorar la presentación
This commit is contained in:
@@ -145,7 +145,7 @@ export const command: CommandMessage = {
|
|||||||
// Añadir metadata del área (imagen/descripcion) si existe
|
// Añadir metadata del área (imagen/descripcion) si existe
|
||||||
const metaBlocks = buildAreaMetadataBlocks(area);
|
const metaBlocks = buildAreaMetadataBlocks(area);
|
||||||
if (metaBlocks.length) {
|
if (metaBlocks.length) {
|
||||||
blocks.push(dividerBlock());
|
blocks.push(dividerBlock({ divider: false, spacing: 1 }));
|
||||||
blocks.push(...metaBlocks);
|
blocks.push(...metaBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ export const command: CommandMessage = {
|
|||||||
textBlock(
|
textBlock(
|
||||||
`## <a:0fire:1425690572945100860> Racha diaria de ${message.author.username}`
|
`## <a:0fire:1425690572945100860> Racha diaria de ${message.author.username}`
|
||||||
),
|
),
|
||||||
dividerBlock(),
|
dividerBlock({ divider: false, spacing: 1 }),
|
||||||
textBlock(
|
textBlock(
|
||||||
`**<:stats:1425689271788113991> ESTADÍSTICAS**\n` +
|
`**<:stats:1425689271788113991> ESTADÍSTICAS**\n` +
|
||||||
`<a:0fire:1425690572945100860> Racha Actual: **${streak.currentStreak}** días\n` +
|
`<a:0fire:1425690572945100860> Racha Actual: **${streak.currentStreak}** días\n` +
|
||||||
`<a:bluestargif:1425691124214927452> Mejor Racha: **${streak.longestStreak}** días\n` +
|
`<a:bluestargif:1425691124214927452> Mejor Racha: **${streak.longestStreak}** días\n` +
|
||||||
`<:events:1425691310194561106> Días Activos: **${streak.totalDaysActive}** días`
|
`<:events:1425691310194561106> Días Activos: **${streak.totalDaysActive}** días`
|
||||||
),
|
),
|
||||||
dividerBlock({ spacing: 1 }),
|
dividerBlock({ spacing: 1, divider: false }),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Mensaje de estado
|
// Mensaje de estado
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import { prisma } from '../../core/database/prisma'
|
import { prisma } from "../../core/database/prisma";
|
||||||
import { addItemByKey, adjustCoins, findItemByKey, getInventoryEntry } from '../economy/service';
|
import {
|
||||||
import type { ItemProps, InventoryState } from '../economy/types';
|
addItemByKey,
|
||||||
import type { LevelRequirements, RunMinigameOptions, RunResult, RewardsTable, MobsTable } from './types';
|
adjustCoins,
|
||||||
import type { Prisma } from '@prisma/client';
|
findItemByKey,
|
||||||
|
getInventoryEntry,
|
||||||
|
} from "../economy/service";
|
||||||
|
import type { ItemProps, InventoryState } from "../economy/types";
|
||||||
|
import type {
|
||||||
|
LevelRequirements,
|
||||||
|
RunMinigameOptions,
|
||||||
|
RunResult,
|
||||||
|
RewardsTable,
|
||||||
|
MobsTable,
|
||||||
|
} from "./types";
|
||||||
|
import type { Prisma } from "@prisma/client";
|
||||||
|
|
||||||
// Auto-select best tool from inventory by type and constraints
|
// Auto-select best tool from inventory by type and constraints
|
||||||
async function findBestToolKey(userId: string, guildId: string, toolType: string, opts?: { minTier?: number; allowedKeys?: string[] }) {
|
async function findBestToolKey(
|
||||||
const entries = await prisma.inventoryEntry.findMany({ where: { userId, guildId, quantity: { gt: 0 } }, include: { item: true } });
|
userId: string,
|
||||||
|
guildId: string,
|
||||||
|
toolType: string,
|
||||||
|
opts?: { minTier?: number; allowedKeys?: string[] }
|
||||||
|
) {
|
||||||
|
const entries = await prisma.inventoryEntry.findMany({
|
||||||
|
where: { userId, guildId, quantity: { gt: 0 } },
|
||||||
|
include: { item: true },
|
||||||
|
});
|
||||||
let best: { key: string; tier: number } | null = null;
|
let best: { key: string; tier: number } | null = null;
|
||||||
for (const e of entries) {
|
for (const e of entries) {
|
||||||
const props = parseItemProps(e.item.props);
|
const props = parseItemProps(e.item.props);
|
||||||
@@ -14,14 +33,19 @@ async function findBestToolKey(userId: string, guildId: string, toolType: string
|
|||||||
if (!t || t.type !== toolType) continue;
|
if (!t || t.type !== toolType) continue;
|
||||||
const tier = Math.max(0, t.tier ?? 0);
|
const tier = Math.max(0, t.tier ?? 0);
|
||||||
if (opts?.minTier != null && tier < opts.minTier) continue;
|
if (opts?.minTier != null && tier < opts.minTier) continue;
|
||||||
if (opts?.allowedKeys && opts.allowedKeys.length && !opts.allowedKeys.includes(e.item.key)) continue;
|
if (
|
||||||
|
opts?.allowedKeys &&
|
||||||
|
opts.allowedKeys.length &&
|
||||||
|
!opts.allowedKeys.includes(e.item.key)
|
||||||
|
)
|
||||||
|
continue;
|
||||||
if (!best || tier > best.tier) best = { key: e.item.key, tier };
|
if (!best || tier > best.tier) best = { key: e.item.key, tier };
|
||||||
}
|
}
|
||||||
return best?.key ?? null;
|
return best?.key ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseJSON<T>(v: unknown): T | null {
|
function parseJSON<T>(v: unknown): T | null {
|
||||||
if (!v || (typeof v !== 'object' && typeof v !== 'string')) return null;
|
if (!v || (typeof v !== "object" && typeof v !== "string")) return null;
|
||||||
return v as T;
|
return v as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,25 +61,39 @@ function pickWeighted<T extends { weight: number }>(arr: T[]): T | null {
|
|||||||
return arr[arr.length - 1] ?? null;
|
return arr[arr.length - 1] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ensureAreaAndLevel(guildId: string, areaKey: string, level: number) {
|
async function ensureAreaAndLevel(
|
||||||
const area = await prisma.gameArea.findFirst({ where: { key: areaKey, OR: [{ guildId }, { guildId: null }] }, orderBy: [{ guildId: 'desc' }] });
|
guildId: string,
|
||||||
if (!area) throw new Error('Área no encontrada');
|
areaKey: string,
|
||||||
const lvl = await prisma.gameAreaLevel.findFirst({ where: { areaId: area.id, level } });
|
level: number
|
||||||
if (!lvl) throw new Error('Nivel no encontrado');
|
) {
|
||||||
|
const area = await prisma.gameArea.findFirst({
|
||||||
|
where: { key: areaKey, OR: [{ guildId }, { guildId: null }] },
|
||||||
|
orderBy: [{ guildId: "desc" }],
|
||||||
|
});
|
||||||
|
if (!area) throw new Error("Área no encontrada");
|
||||||
|
const lvl = await prisma.gameAreaLevel.findFirst({
|
||||||
|
where: { areaId: area.id, level },
|
||||||
|
});
|
||||||
|
if (!lvl) throw new Error("Nivel no encontrado");
|
||||||
return { area, lvl } as const;
|
return { area, lvl } as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseItemProps(json: unknown): ItemProps {
|
function parseItemProps(json: unknown): ItemProps {
|
||||||
if (!json || typeof json !== 'object') return {};
|
if (!json || typeof json !== "object") return {};
|
||||||
return json as ItemProps;
|
return json as ItemProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseInvState(json: unknown): InventoryState {
|
function parseInvState(json: unknown): InventoryState {
|
||||||
if (!json || typeof json !== 'object') return {};
|
if (!json || typeof json !== "object") return {};
|
||||||
return json as InventoryState;
|
return json as InventoryState;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validateRequirements(userId: string, guildId: string, req?: LevelRequirements, toolKey?: string) {
|
async function validateRequirements(
|
||||||
|
userId: string,
|
||||||
|
guildId: string,
|
||||||
|
req?: LevelRequirements,
|
||||||
|
toolKey?: string
|
||||||
|
) {
|
||||||
if (!req) return { toolKeyUsed: undefined as string | undefined };
|
if (!req) return { toolKeyUsed: undefined as string | undefined };
|
||||||
const toolReq = req.tool;
|
const toolReq = req.tool;
|
||||||
if (!toolReq) return { toolKeyUsed: undefined as string | undefined };
|
if (!toolReq) return { toolKeyUsed: undefined as string | undefined };
|
||||||
@@ -64,45 +102,59 @@ async function validateRequirements(userId: string, guildId: string, req?: Level
|
|||||||
|
|
||||||
// Auto-select tool when required and not provided
|
// Auto-select tool when required and not provided
|
||||||
if (!toolKeyUsed && toolReq.required && toolReq.toolType) {
|
if (!toolKeyUsed && toolReq.required && toolReq.toolType) {
|
||||||
toolKeyUsed = await findBestToolKey(userId, guildId, toolReq.toolType, { minTier: toolReq.minTier, allowedKeys: toolReq.allowedKeys }) ?? undefined;
|
toolKeyUsed =
|
||||||
|
(await findBestToolKey(userId, guildId, toolReq.toolType, {
|
||||||
|
minTier: toolReq.minTier,
|
||||||
|
allowedKeys: toolReq.allowedKeys,
|
||||||
|
})) ?? undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// herramienta requerida
|
// herramienta requerida
|
||||||
if (toolReq.required && !toolKeyUsed) throw new Error('Se requiere una herramienta adecuada');
|
if (toolReq.required && !toolKeyUsed)
|
||||||
|
throw new Error("Se requiere una herramienta adecuada");
|
||||||
if (!toolKeyUsed) return { toolKeyUsed: undefined };
|
if (!toolKeyUsed) return { toolKeyUsed: undefined };
|
||||||
|
|
||||||
// verificar herramienta
|
// verificar herramienta
|
||||||
const toolItem = await findItemByKey(guildId, toolKeyUsed);
|
const toolItem = await findItemByKey(guildId, toolKeyUsed);
|
||||||
if (!toolItem) throw new Error('Herramienta no encontrada');
|
if (!toolItem) throw new Error("Herramienta no encontrada");
|
||||||
const { entry } = await getInventoryEntry(userId, guildId, toolKeyUsed);
|
const { entry } = await getInventoryEntry(userId, guildId, toolKeyUsed);
|
||||||
if (!entry || (entry.quantity ?? 0) <= 0) throw new Error('No tienes la herramienta');
|
if (!entry || (entry.quantity ?? 0) <= 0)
|
||||||
|
throw new Error("No tienes la herramienta");
|
||||||
|
|
||||||
const props = parseItemProps(toolItem.props);
|
const props = parseItemProps(toolItem.props);
|
||||||
const tool = props.tool;
|
const tool = props.tool;
|
||||||
if (toolReq.toolType && tool?.type !== toolReq.toolType) throw new Error('Tipo de herramienta incorrecto');
|
if (toolReq.toolType && tool?.type !== toolReq.toolType)
|
||||||
if (toolReq.minTier != null && (tool?.tier ?? 0) < toolReq.minTier) throw new Error('Tier de herramienta insuficiente');
|
throw new Error("Tipo de herramienta incorrecto");
|
||||||
if (toolReq.allowedKeys && !toolReq.allowedKeys.includes(toolKeyUsed)) throw new Error('Esta herramienta no es válida para esta área');
|
if (toolReq.minTier != null && (tool?.tier ?? 0) < toolReq.minTier)
|
||||||
|
throw new Error("Tier de herramienta insuficiente");
|
||||||
|
if (toolReq.allowedKeys && !toolReq.allowedKeys.includes(toolKeyUsed))
|
||||||
|
throw new Error("Esta herramienta no es válida para esta área");
|
||||||
|
|
||||||
return { toolKeyUsed };
|
return { toolKeyUsed };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function applyRewards(userId: string, guildId: string, rewards?: RewardsTable): Promise<RunResult['rewards']> {
|
async function applyRewards(
|
||||||
const results: RunResult['rewards'] = [];
|
userId: string,
|
||||||
if (!rewards || !Array.isArray(rewards.table) || rewards.table.length === 0) return results;
|
guildId: string,
|
||||||
|
rewards?: RewardsTable
|
||||||
|
): Promise<RunResult["rewards"]> {
|
||||||
|
const results: RunResult["rewards"] = [];
|
||||||
|
if (!rewards || !Array.isArray(rewards.table) || rewards.table.length === 0)
|
||||||
|
return results;
|
||||||
const draws = Math.max(1, rewards.draws ?? 1);
|
const draws = Math.max(1, rewards.draws ?? 1);
|
||||||
for (let i = 0; i < draws; i++) {
|
for (let i = 0; i < draws; i++) {
|
||||||
const pick = pickWeighted(rewards.table);
|
const pick = pickWeighted(rewards.table);
|
||||||
if (!pick) continue;
|
if (!pick) continue;
|
||||||
if (pick.type === 'coins') {
|
if (pick.type === "coins") {
|
||||||
const amt = Math.max(0, pick.amount);
|
const amt = Math.max(0, pick.amount);
|
||||||
if (amt > 0) {
|
if (amt > 0) {
|
||||||
await adjustCoins(userId, guildId, amt);
|
await adjustCoins(userId, guildId, amt);
|
||||||
results.push({ type: 'coins', amount: amt });
|
results.push({ type: "coins", amount: amt });
|
||||||
}
|
}
|
||||||
} else if (pick.type === 'item') {
|
} else if (pick.type === "item") {
|
||||||
const qty = Math.max(1, pick.qty);
|
const qty = Math.max(1, pick.qty);
|
||||||
await addItemByKey(userId, guildId, pick.itemKey, qty);
|
await addItemByKey(userId, guildId, pick.itemKey, qty);
|
||||||
results.push({ type: 'item', itemKey: pick.itemKey, qty });
|
results.push({ type: "item", itemKey: pick.itemKey, qty });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
@@ -110,7 +162,8 @@ async function applyRewards(userId: string, guildId: string, rewards?: RewardsTa
|
|||||||
|
|
||||||
async function sampleMobs(mobs?: MobsTable): Promise<string[]> {
|
async function sampleMobs(mobs?: MobsTable): Promise<string[]> {
|
||||||
const out: string[] = [];
|
const out: string[] = [];
|
||||||
if (!mobs || !Array.isArray(mobs.table) || mobs.table.length === 0) return out;
|
if (!mobs || !Array.isArray(mobs.table) || mobs.table.length === 0)
|
||||||
|
return out;
|
||||||
const draws = Math.max(0, mobs.draws ?? 0);
|
const draws = Math.max(0, mobs.draws ?? 0);
|
||||||
for (let i = 0; i < draws; i++) {
|
for (let i = 0; i < draws; i++) {
|
||||||
const pick = pickWeighted(mobs.table);
|
const pick = pickWeighted(mobs.table);
|
||||||
@@ -119,17 +172,36 @@ async function sampleMobs(mobs?: MobsTable): Promise<string[]> {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function reduceToolDurability(userId: string, guildId: string, toolKey: string) {
|
async function reduceToolDurability(
|
||||||
|
userId: string,
|
||||||
|
guildId: string,
|
||||||
|
toolKey: string
|
||||||
|
) {
|
||||||
const { item, entry } = await getInventoryEntry(userId, guildId, toolKey);
|
const { item, entry } = await getInventoryEntry(userId, guildId, toolKey);
|
||||||
if (!entry) return { broken: false, delta: 0 } as const;
|
if (!entry) return { broken: false, delta: 0 } as const;
|
||||||
const props = parseItemProps(item.props);
|
const props = parseItemProps(item.props);
|
||||||
const breakable = props.breakable;
|
const breakable = props.breakable;
|
||||||
const delta = Math.max(1, breakable?.durabilityPerUse ?? 1);
|
// Si el item no es breakable o la durabilidad está deshabilitada, no hacemos nada
|
||||||
|
if (!breakable || breakable.enabled === false) {
|
||||||
|
return { broken: false, delta: 0 } as const;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valores base
|
||||||
|
const maxConfigured = Math.max(1, breakable.maxDurability ?? 1);
|
||||||
|
let perUse = Math.max(1, breakable.durabilityPerUse ?? 1);
|
||||||
|
|
||||||
|
// Protección: si perUse > maxDurability asumimos configuración errónea y lo reducimos a 1
|
||||||
|
// (en lugar de romper inmediatamente el ítem). Si quieres que se rompa de un uso, define maxDurability igual a 1.
|
||||||
|
if (perUse > maxConfigured) perUse = 1;
|
||||||
|
const delta = perUse;
|
||||||
if (item.stackable) {
|
if (item.stackable) {
|
||||||
// Herramientas deberían ser no apilables; si lo son, solo decrementamos cantidad como fallback
|
// Herramientas deberían ser no apilables; si lo son, solo decrementamos cantidad como fallback
|
||||||
const consumed = Math.min(1, entry.quantity);
|
const consumed = Math.min(1, entry.quantity);
|
||||||
if (consumed > 0) {
|
if (consumed > 0) {
|
||||||
await prisma.inventoryEntry.update({ where: { userId_guildId_itemId: { userId, guildId, itemId: item.id } }, data: { quantity: { decrement: consumed } } });
|
await prisma.inventoryEntry.update({
|
||||||
|
where: { userId_guildId_itemId: { userId, guildId, itemId: item.id } },
|
||||||
|
data: { quantity: { decrement: consumed } },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return { broken: consumed > 0, delta } as const;
|
return { broken: consumed > 0, delta } as const;
|
||||||
}
|
}
|
||||||
@@ -137,7 +209,7 @@ async function reduceToolDurability(userId: string, guildId: string, toolKey: st
|
|||||||
state.instances ??= [{}];
|
state.instances ??= [{}];
|
||||||
if (state.instances.length === 0) state.instances.push({});
|
if (state.instances.length === 0) state.instances.push({});
|
||||||
const inst = state.instances[0];
|
const inst = state.instances[0];
|
||||||
const max = Math.max(1, breakable?.maxDurability ?? 1);
|
const max = maxConfigured; // ya calculado arriba
|
||||||
const current = Math.min(Math.max(0, inst.durability ?? max), max);
|
const current = Math.min(Math.max(0, inst.durability ?? max), max);
|
||||||
const next = current - delta;
|
const next = current - delta;
|
||||||
let broken = false;
|
let broken = false;
|
||||||
@@ -151,14 +223,23 @@ async function reduceToolDurability(userId: string, guildId: string, toolKey: st
|
|||||||
}
|
}
|
||||||
await prisma.inventoryEntry.update({
|
await prisma.inventoryEntry.update({
|
||||||
where: { userId_guildId_itemId: { userId, guildId, itemId: item.id } },
|
where: { userId_guildId_itemId: { userId, guildId, itemId: item.id } },
|
||||||
data: { state: state as unknown as Prisma.InputJsonValue, quantity: state.instances.length },
|
data: {
|
||||||
|
state: state as unknown as Prisma.InputJsonValue,
|
||||||
|
quantity: state.instances.length,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
return { broken, delta } as const;
|
return { broken, delta } as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { reduceToolDurability };
|
export { reduceToolDurability };
|
||||||
|
|
||||||
export async function runMinigame(userId: string, guildId: string, areaKey: string, level: number, opts?: RunMinigameOptions): Promise<RunResult> {
|
export async function runMinigame(
|
||||||
|
userId: string,
|
||||||
|
guildId: string,
|
||||||
|
areaKey: string,
|
||||||
|
level: number,
|
||||||
|
opts?: RunMinigameOptions
|
||||||
|
): Promise<RunResult> {
|
||||||
const { area, lvl } = await ensureAreaAndLevel(guildId, areaKey, level);
|
const { area, lvl } = await ensureAreaAndLevel(guildId, areaKey, level);
|
||||||
|
|
||||||
// Cooldown por área
|
// Cooldown por área
|
||||||
@@ -166,9 +247,11 @@ export async function runMinigame(userId: string, guildId: string, areaKey: stri
|
|||||||
const cdSeconds = Math.max(0, Number(areaConf.cooldownSeconds ?? 0));
|
const cdSeconds = Math.max(0, Number(areaConf.cooldownSeconds ?? 0));
|
||||||
const cdKey = `minigame:${area.key}`;
|
const cdKey = `minigame:${area.key}`;
|
||||||
if (cdSeconds > 0) {
|
if (cdSeconds > 0) {
|
||||||
const existing = await prisma.actionCooldown.findUnique({ where: { userId_guildId_key: { userId, guildId, key: cdKey } } });
|
const existing = await prisma.actionCooldown.findUnique({
|
||||||
|
where: { userId_guildId_key: { userId, guildId, key: cdKey } },
|
||||||
|
});
|
||||||
if (existing && existing.until > new Date()) {
|
if (existing && existing.until > new Date()) {
|
||||||
throw new Error('Cooldown activo para esta actividad');
|
throw new Error("Cooldown activo para esta actividad");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,17 +261,26 @@ export async function runMinigame(userId: string, guildId: string, areaKey: stri
|
|||||||
const mobs = parseJSON<MobsTable>(lvl.mobs) ?? { table: [] };
|
const mobs = parseJSON<MobsTable>(lvl.mobs) ?? { table: [] };
|
||||||
|
|
||||||
// Validar herramienta si aplica
|
// Validar herramienta si aplica
|
||||||
const reqRes = await validateRequirements(userId, guildId, requirements, opts?.toolKey);
|
const reqRes = await validateRequirements(
|
||||||
|
userId,
|
||||||
|
guildId,
|
||||||
|
requirements,
|
||||||
|
opts?.toolKey
|
||||||
|
);
|
||||||
|
|
||||||
// Aplicar recompensas y samplear mobs
|
// Aplicar recompensas y samplear mobs
|
||||||
const delivered = await applyRewards(userId, guildId, rewards);
|
const delivered = await applyRewards(userId, guildId, rewards);
|
||||||
const mobsSpawned = await sampleMobs(mobs);
|
const mobsSpawned = await sampleMobs(mobs);
|
||||||
|
|
||||||
// Reducir durabilidad de herramienta si se usó
|
// Reducir durabilidad de herramienta si se usó
|
||||||
let toolInfo: RunResult['tool'] | undefined;
|
let toolInfo: RunResult["tool"] | undefined;
|
||||||
if (reqRes.toolKeyUsed) {
|
if (reqRes.toolKeyUsed) {
|
||||||
const t = await reduceToolDurability(userId, guildId, reqRes.toolKeyUsed);
|
const t = await reduceToolDurability(userId, guildId, reqRes.toolKeyUsed);
|
||||||
toolInfo = { key: reqRes.toolKeyUsed, durabilityDelta: t.delta, broken: t.broken };
|
toolInfo = {
|
||||||
|
key: reqRes.toolKeyUsed,
|
||||||
|
durabilityDelta: t.delta,
|
||||||
|
broken: t.broken,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registrar la ejecución
|
// Registrar la ejecución
|
||||||
@@ -196,7 +288,7 @@ export async function runMinigame(userId: string, guildId: string, areaKey: stri
|
|||||||
rewards: delivered,
|
rewards: delivered,
|
||||||
mobs: mobsSpawned,
|
mobs: mobsSpawned,
|
||||||
tool: toolInfo,
|
tool: toolInfo,
|
||||||
notes: 'auto',
|
notes: "auto",
|
||||||
} as unknown as Prisma.InputJsonValue;
|
} as unknown as Prisma.InputJsonValue;
|
||||||
|
|
||||||
await prisma.minigameRun.create({
|
await prisma.minigameRun.create({
|
||||||
@@ -214,7 +306,12 @@ export async function runMinigame(userId: string, guildId: string, areaKey: stri
|
|||||||
// Progreso del jugador
|
// Progreso del jugador
|
||||||
await prisma.playerProgress.upsert({
|
await prisma.playerProgress.upsert({
|
||||||
where: { userId_guildId_areaId: { userId, guildId, areaId: area.id } },
|
where: { userId_guildId_areaId: { userId, guildId, areaId: area.id } },
|
||||||
create: { userId, guildId, areaId: area.id, highestLevel: Math.max(1, level) },
|
create: {
|
||||||
|
userId,
|
||||||
|
guildId,
|
||||||
|
areaId: area.id,
|
||||||
|
highestLevel: Math.max(1, level),
|
||||||
|
},
|
||||||
update: { highestLevel: { set: level } },
|
update: { highestLevel: { set: level } },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -223,24 +320,68 @@ export async function runMinigame(userId: string, guildId: string, areaKey: stri
|
|||||||
await prisma.actionCooldown.upsert({
|
await prisma.actionCooldown.upsert({
|
||||||
where: { userId_guildId_key: { userId, guildId, key: cdKey } },
|
where: { userId_guildId_key: { userId, guildId, key: cdKey } },
|
||||||
update: { until: new Date(Date.now() + cdSeconds * 1000) },
|
update: { until: new Date(Date.now() + cdSeconds * 1000) },
|
||||||
create: { userId, guildId, key: cdKey, until: new Date(Date.now() + cdSeconds * 1000) },
|
create: {
|
||||||
|
userId,
|
||||||
|
guildId,
|
||||||
|
key: cdKey,
|
||||||
|
until: new Date(Date.now() + cdSeconds * 1000),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return { success: true, rewards: delivered, mobs: mobsSpawned, tool: toolInfo };
|
return {
|
||||||
|
success: true,
|
||||||
|
rewards: delivered,
|
||||||
|
mobs: mobsSpawned,
|
||||||
|
tool: toolInfo,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience wrappers with auto-level (from PlayerProgress) and auto-tool selection inside validateRequirements
|
// Convenience wrappers with auto-level (from PlayerProgress) and auto-tool selection inside validateRequirements
|
||||||
export async function runMining(userId: string, guildId: string, level?: number, toolKey?: string) {
|
export async function runMining(
|
||||||
const area = await prisma.gameArea.findFirst({ where: { key: 'mine.cavern', OR: [{ guildId }, { guildId: null }] }, orderBy: [{ guildId: 'desc' }] });
|
userId: string,
|
||||||
if (!area) throw new Error('Área de mina no configurada');
|
guildId: string,
|
||||||
const lvl = level ?? (await prisma.playerProgress.findUnique({ where: { userId_guildId_areaId: { userId, guildId, areaId: area.id } } }))?.highestLevel ?? 1;
|
level?: number,
|
||||||
return runMinigame(userId, guildId, 'mine.cavern', Math.max(1, lvl), { toolKey });
|
toolKey?: string
|
||||||
|
) {
|
||||||
|
const area = await prisma.gameArea.findFirst({
|
||||||
|
where: { key: "mine.cavern", OR: [{ guildId }, { guildId: null }] },
|
||||||
|
orderBy: [{ guildId: "desc" }],
|
||||||
|
});
|
||||||
|
if (!area) throw new Error("Área de mina no configurada");
|
||||||
|
const lvl =
|
||||||
|
level ??
|
||||||
|
(
|
||||||
|
await prisma.playerProgress.findUnique({
|
||||||
|
where: { userId_guildId_areaId: { userId, guildId, areaId: area.id } },
|
||||||
|
})
|
||||||
|
)?.highestLevel ??
|
||||||
|
1;
|
||||||
|
return runMinigame(userId, guildId, "mine.cavern", Math.max(1, lvl), {
|
||||||
|
toolKey,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function runFishing(userId: string, guildId: string, level?: number, toolKey?: string) {
|
export async function runFishing(
|
||||||
const area = await prisma.gameArea.findFirst({ where: { key: 'lagoon.shore', OR: [{ guildId }, { guildId: null }] }, orderBy: [{ guildId: 'desc' }] });
|
userId: string,
|
||||||
if (!area) throw new Error('Área de laguna no configurada');
|
guildId: string,
|
||||||
const lvl = level ?? (await prisma.playerProgress.findUnique({ where: { userId_guildId_areaId: { userId, guildId, areaId: area.id } } }))?.highestLevel ?? 1;
|
level?: number,
|
||||||
return runMinigame(userId, guildId, 'lagoon.shore', Math.max(1, lvl), { toolKey });
|
toolKey?: string
|
||||||
|
) {
|
||||||
|
const area = await prisma.gameArea.findFirst({
|
||||||
|
where: { key: "lagoon.shore", OR: [{ guildId }, { guildId: null }] },
|
||||||
|
orderBy: [{ guildId: "desc" }],
|
||||||
|
});
|
||||||
|
if (!area) throw new Error("Área de laguna no configurada");
|
||||||
|
const lvl =
|
||||||
|
level ??
|
||||||
|
(
|
||||||
|
await prisma.playerProgress.findUnique({
|
||||||
|
where: { userId_guildId_areaId: { userId, guildId, areaId: area.id } },
|
||||||
|
})
|
||||||
|
)?.highestLevel ??
|
||||||
|
1;
|
||||||
|
return runMinigame(userId, guildId, "lagoon.shore", Math.max(1, lvl), {
|
||||||
|
toolKey,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user