feat: agregar penalización por fatiga en recompensas de minijuegos; ajustar lógica de recompensas y modificar tipos para incluir modificadores

This commit is contained in:
2025-10-09 01:49:36 -05:00
parent c564b30413
commit 0b0a73d114
5 changed files with 80 additions and 12 deletions

View File

@@ -91,7 +91,7 @@ export const command: CommandMessage = {
"mine_count" "mine_count"
); );
const rewardLines = result.rewards.length let rewardLines = result.rewards.length
? result.rewards ? result.rewards
.map((r) => { .map((r) => {
if (r.type === "coins") return `• 🪙 +${r.amount}`; if (r.type === "coins") return `• 🪙 +${r.amount}`;
@@ -103,6 +103,15 @@ export const command: CommandMessage = {
}) })
.join("\n") .join("\n")
: "• —"; : "• —";
if (
result.rewardModifiers?.fatigueCoinMultiplier != null &&
result.rewardModifiers.fatigueCoinMultiplier < 1
) {
const pct = Math.round(
(1 - result.rewardModifiers.fatigueCoinMultiplier) * 100
);
rewardLines += `\n (⚠️ Fatiga -${pct}% monedas)`;
}
const mobsLines = result.mobs.length const mobsLines = result.mobs.length
? result.mobs.map((m) => `${m}`).join("\n") ? result.mobs.map((m) => `${m}`).join("\n")
: "• —"; : "• —";

View File

@@ -101,7 +101,7 @@ export const command: CommandMessage = {
"fight_count" "fight_count"
); );
const rewardLines = result.rewards.length let rewardLines = result.rewards.length
? result.rewards ? result.rewards
.map((r) => { .map((r) => {
if (r.type === "coins") return `• 🪙 +${r.amount}`; if (r.type === "coins") return `• 🪙 +${r.amount}`;
@@ -113,6 +113,15 @@ export const command: CommandMessage = {
}) })
.join("\n") .join("\n")
: "• —"; : "• —";
if (
result.rewardModifiers?.fatigueCoinMultiplier != null &&
result.rewardModifiers.fatigueCoinMultiplier < 1
) {
const pct = Math.round(
(1 - result.rewardModifiers.fatigueCoinMultiplier) * 100
);
rewardLines += `\n (⚠️ Fatiga -${pct}% monedas)`;
}
const mobsLines = result.mobs.length const mobsLines = result.mobs.length
? result.mobs.map((m) => `${m}`).join("\n") ? result.mobs.map((m) => `${m}`).join("\n")
: "• —"; : "• —";

View File

@@ -87,7 +87,7 @@ export const command: CommandMessage = {
"fish_count" "fish_count"
); );
const rewardLines = result.rewards.length let rewardLines = result.rewards.length
? result.rewards ? result.rewards
.map((r) => { .map((r) => {
if (r.type === "coins") return `• 🪙 +${r.amount}`; if (r.type === "coins") return `• 🪙 +${r.amount}`;
@@ -99,6 +99,15 @@ export const command: CommandMessage = {
}) })
.join("\n") .join("\n")
: "• —"; : "• —";
if (
result.rewardModifiers?.fatigueCoinMultiplier != null &&
result.rewardModifiers.fatigueCoinMultiplier < 1
) {
const pct = Math.round(
(1 - result.rewardModifiers.fatigueCoinMultiplier) * 100
);
rewardLines += `\n (⚠️ Fatiga -${pct}% monedas)`;
}
const mobsLines = result.mobs.length const mobsLines = result.mobs.length
? result.mobs.map((m) => `${m}`).join("\n") ? result.mobs.map((m) => `${m}`).join("\n")
: "• —"; : "• —";

View File

@@ -1,4 +1,7 @@
import { applyDeathFatigue } from "../combat/statusEffectsService"; import {
applyDeathFatigue,
getActiveStatusEffects,
} from "../combat/statusEffectsService";
import { getOrCreateWallet } from "../economy/service"; import { getOrCreateWallet } from "../economy/service";
import { prisma } from "../../core/database/prisma"; import { prisma } from "../../core/database/prisma";
import { import {
@@ -201,19 +204,42 @@ async function applyRewards(
userId: string, userId: string,
guildId: string, guildId: string,
rewards?: RewardsTable rewards?: RewardsTable
): Promise<RunResult["rewards"]> { ): Promise<{
rewards: RunResult["rewards"];
modifiers?: RunResult["rewardModifiers"];
}> {
const results: RunResult["rewards"] = []; const results: RunResult["rewards"] = [];
if (!rewards || !Array.isArray(rewards.table) || rewards.table.length === 0) if (!rewards || !Array.isArray(rewards.table) || rewards.table.length === 0)
return results; return { rewards: results };
// Detectar efecto FATIGUE activo para penalizar SOLO monedas.
let fatigueMagnitude: number | undefined;
try {
const effects = await getActiveStatusEffects(userId, guildId);
const fatigue = effects.find((e) => e.type === "FATIGUE");
if (fatigue && typeof fatigue.magnitude === "number") {
fatigueMagnitude = Math.max(0, Math.min(0.9, fatigue.magnitude));
}
} catch {
// silencioso
}
const coinMultiplier = fatigueMagnitude
? Math.max(0, 1 - fatigueMagnitude)
: 1;
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 baseAmt = Math.max(0, pick.amount);
if (amt > 0) { if (baseAmt > 0) {
await adjustCoins(userId, guildId, amt); const adjusted = Math.max(0, Math.floor(baseAmt * coinMultiplier));
results.push({ type: "coins", amount: amt }); const finalAmt = coinMultiplier < 1 && adjusted === 0 ? 1 : adjusted; // al menos 1 si había algo base
if (finalAmt > 0) {
await adjustCoins(userId, guildId, finalAmt);
results.push({ type: "coins", amount: finalAmt });
}
} }
} else if (pick.type === "item") { } else if (pick.type === "item") {
const qty = Math.max(1, pick.qty); const qty = Math.max(1, pick.qty);
@@ -221,7 +247,11 @@ async function applyRewards(
results.push({ type: "item", itemKey: pick.itemKey, qty }); results.push({ type: "item", itemKey: pick.itemKey, qty });
} }
} }
return results; const modifiers =
coinMultiplier < 1
? { fatigueCoinMultiplier: coinMultiplier, fatigueMagnitude }
: undefined;
return { rewards: results, modifiers };
} }
async function sampleMobs(mobs?: MobsTable): Promise<string[]> { async function sampleMobs(mobs?: MobsTable): Promise<string[]> {
@@ -381,7 +411,11 @@ export async function runMinigame(
); );
// Aplicar recompensas y samplear mobs // Aplicar recompensas y samplear mobs
const delivered = await applyRewards(userId, guildId, rewards); const { rewards: delivered, modifiers: rewardModifiers } = 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ó
@@ -729,6 +763,7 @@ export async function runMinigame(
mobs: mobsSpawned, mobs: mobsSpawned,
tool: toolInfo, tool: toolInfo,
combat: combatSummary, combat: combatSummary,
rewardModifiers,
notes: "auto", notes: "auto",
} as unknown as Prisma.InputJsonValue; } as unknown as Prisma.InputJsonValue;
@@ -776,6 +811,7 @@ export async function runMinigame(
mobs: mobsSpawned, mobs: mobsSpawned,
tool: toolInfo, tool: toolInfo,
combat: combatSummary, combat: combatSummary,
rewardModifiers,
}; };
} }

View File

@@ -62,6 +62,11 @@ export type RunResult = {
toolSource?: "provided" | "equipped" | "auto"; // origen de la selección toolSource?: "provided" | "equipped" | "auto"; // origen de la selección
}; };
combat?: CombatSummary; // resumen de combate si hubo mobs y se procesó combat?: CombatSummary; // resumen de combate si hubo mobs y se procesó
// Modificadores aplicados a las recompensas (ej: penalización por FATIGUE sobre monedas)
rewardModifiers?: {
fatigueCoinMultiplier?: number; // 0.85 si hay -15%
fatigueMagnitude?: number; // magnitud original del efecto
};
}; };
// --- Combate Básico --- // --- Combate Básico ---