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:
@@ -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")
|
||||||
: "• —";
|
: "• —";
|
||||||
|
|||||||
@@ -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")
|
||||||
: "• —";
|
: "• —";
|
||||||
|
|||||||
@@ -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")
|
||||||
: "• —";
|
: "• —";
|
||||||
|
|||||||
@@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 ---
|
||||||
|
|||||||
Reference in New Issue
Block a user