feat(minigames): implement dual durability system for tools and weapons

- Introduced separation between `tool` (for gathering) and `weaponTool` (for combat) in minigames.
- Adjusted durability reduction logic to apply a 50% reduction for weapons used in combat to prevent instant breakage.
- Updated `RunResult` type to include `weaponTool` information.
- Enhanced `runMinigame` logic to handle weapon degradation during combat scenarios.
- Updated user commands to reflect both tool and weapon durability in outputs.
- Modified scheduled mob attacks to respect the new durability system.
- Added comprehensive documentation on the new dual durability feature and its implications for gameplay balance.
This commit is contained in:
2025-10-09 02:23:51 -05:00
parent 3a311c8bb6
commit 646f62d2e9
9 changed files with 916 additions and 102 deletions

View File

@@ -76,6 +76,7 @@ export const command: CommandMessage = {
)
.map((r) => r.itemKey!);
if (result.tool?.key) rewardKeys.push(result.tool.key);
if (result.weaponTool?.key) rewardKeys.push(result.weaponTool.key);
const rewardItems = await fetchItemBasics(guildId, rewardKeys);
// Actualizar stats
@@ -141,6 +142,27 @@ export const command: CommandMessage = {
})
: "—";
const weaponInfo = result.weaponTool?.key
? formatToolLabel({
key: result.weaponTool.key,
displayName: formatItemLabel(
rewardItems.get(result.weaponTool.key) ?? {
key: result.weaponTool.key,
name: null,
icon: null,
},
{ fallbackIcon: "⚔️" }
),
instancesRemaining: result.weaponTool.instancesRemaining,
broken: result.weaponTool.broken,
brokenInstance: result.weaponTool.brokenInstance,
durabilityDelta: result.weaponTool.durabilityDelta,
remaining: result.weaponTool.remaining,
max: result.weaponTool.max,
source: result.weaponTool.toolSource,
})
: null;
const combatSummary = result.combat
? combatSummaryRPG({
mobs: result.mobs.length,
@@ -165,9 +187,12 @@ export const command: CommandMessage = {
source === "global"
? "🌐 Configuración global"
: "📍 Configuración local";
const toolsLine = weaponInfo
? `**Pico:** ${toolInfo}\n**Arma (defensa):** ${weaponInfo}`
: `**Herramienta:** ${toolInfo}`;
blocks.push(
textBlock(
`**Área:** \`${area.key}\`${areaScope}\n**Nivel:** ${level}\n**Herramienta:** ${toolInfo}`
`**Área:** \`${area.key}\`${areaScope}\n**Nivel:** ${level}\n${toolsLine}`
)
);
blocks.push(dividerBlock({ divider: false, spacing: 1 }));

View File

@@ -77,6 +77,7 @@ export const command: CommandMessage = {
)
.map((r) => r.itemKey!);
if (result.tool?.key) rewardKeys.push(result.tool.key);
if (result.weaponTool?.key) rewardKeys.push(result.weaponTool.key);
const rewardItems = await fetchItemBasics(guildId, rewardKeys);
// Actualizar stats y misiones

View File

@@ -76,6 +76,7 @@ export const command: CommandMessage = {
)
.map((r) => r.itemKey!);
if (result.tool?.key) rewardKeys.push(result.tool.key);
if (result.weaponTool?.key) rewardKeys.push(result.weaponTool.key);
const rewardItems = await fetchItemBasics(guildId, rewardKeys);
// Actualizar stats y misiones
@@ -135,6 +136,27 @@ export const command: CommandMessage = {
source: result.tool.toolSource,
})
: "—";
const weaponInfo = result.weaponTool?.key
? formatToolLabel({
key: result.weaponTool.key,
displayName: formatItemLabel(
rewardItems.get(result.weaponTool.key) ?? {
key: result.weaponTool.key,
name: null,
icon: null,
},
{ fallbackIcon: "⚔️" }
),
instancesRemaining: result.weaponTool.instancesRemaining,
broken: result.weaponTool.broken,
brokenInstance: result.weaponTool.brokenInstance,
durabilityDelta: result.weaponTool.durabilityDelta,
remaining: result.weaponTool.remaining,
max: result.weaponTool.max,
source: result.weaponTool.toolSource,
})
: null;
const combatSummary = result.combat
? combatSummaryRPG({
mobs: result.mobs.length,
@@ -159,9 +181,12 @@ export const command: CommandMessage = {
source === "global"
? "🌐 Configuración global"
: "📍 Configuración local";
const toolsLine = weaponInfo
? `**Caña:** ${toolInfo}\n**Arma (defensa):** ${weaponInfo}`
: `**Herramienta:** ${toolInfo}`;
blocks.push(
textBlock(
`**Área:** \`${area.key}\`${areaScope}\n**Nivel:** ${level}\n**Herramienta:** ${toolInfo}`
`**Área:** \`${area.key}\`${areaScope}\n**Nivel:** ${level}\n${toolsLine}`
)
);
blocks.push(dividerBlock({ divider: false, spacing: 1 }));