feat(economy): enhance minigame commands to track stats, quest progress, and achievements
This commit is contained in:
221
src/game/achievements/seed.ts
Normal file
221
src/game/achievements/seed.ts
Normal file
@@ -0,0 +1,221 @@
|
||||
import { prisma } from '../../core/database/prisma';
|
||||
import logger from '../../core/lib/logger';
|
||||
|
||||
/**
|
||||
* Seed de logros base
|
||||
*/
|
||||
export async function seedAchievements(guildId: string | null = null) {
|
||||
const achievements = [
|
||||
// Minería
|
||||
{
|
||||
key: 'first_mine',
|
||||
name: '⛏️ Primera Mina',
|
||||
description: 'Mina por primera vez',
|
||||
category: 'mining',
|
||||
requirements: { type: 'mine_count', value: 1 },
|
||||
rewards: { coins: 100 },
|
||||
hidden: false,
|
||||
points: 10
|
||||
},
|
||||
{
|
||||
key: 'miner_novice',
|
||||
name: '⛏️ Minero Novato',
|
||||
description: 'Mina 10 veces',
|
||||
category: 'mining',
|
||||
requirements: { type: 'mine_count', value: 10 },
|
||||
rewards: { coins: 500 },
|
||||
hidden: false,
|
||||
points: 20
|
||||
},
|
||||
{
|
||||
key: 'miner_expert',
|
||||
name: '⛏️ Minero Experto',
|
||||
description: 'Mina 50 veces',
|
||||
category: 'mining',
|
||||
requirements: { type: 'mine_count', value: 50 },
|
||||
rewards: { coins: 2500 },
|
||||
hidden: false,
|
||||
points: 50
|
||||
},
|
||||
{
|
||||
key: 'miner_master',
|
||||
name: '⛏️ Maestro Minero',
|
||||
description: 'Mina 100 veces',
|
||||
category: 'mining',
|
||||
requirements: { type: 'mine_count', value: 100 },
|
||||
rewards: { coins: 10000 },
|
||||
hidden: false,
|
||||
points: 100
|
||||
},
|
||||
|
||||
// Pesca
|
||||
{
|
||||
key: 'first_fish',
|
||||
name: '🎣 Primera Pesca',
|
||||
description: 'Pesca por primera vez',
|
||||
category: 'fishing',
|
||||
requirements: { type: 'fish_count', value: 1 },
|
||||
rewards: { coins: 100 },
|
||||
hidden: false,
|
||||
points: 10
|
||||
},
|
||||
{
|
||||
key: 'fisher_novice',
|
||||
name: '🎣 Pescador Novato',
|
||||
description: 'Pesca 10 veces',
|
||||
category: 'fishing',
|
||||
requirements: { type: 'fish_count', value: 10 },
|
||||
rewards: { coins: 500 },
|
||||
hidden: false,
|
||||
points: 20
|
||||
},
|
||||
{
|
||||
key: 'fisher_expert',
|
||||
name: '🎣 Pescador Experto',
|
||||
description: 'Pesca 50 veces',
|
||||
category: 'fishing',
|
||||
requirements: { type: 'fish_count', value: 50 },
|
||||
rewards: { coins: 2500 },
|
||||
hidden: false,
|
||||
points: 50
|
||||
},
|
||||
|
||||
// Combate
|
||||
{
|
||||
key: 'first_fight',
|
||||
name: '⚔️ Primera Pelea',
|
||||
description: 'Pelea por primera vez',
|
||||
category: 'combat',
|
||||
requirements: { type: 'fight_count', value: 1 },
|
||||
rewards: { coins: 150 },
|
||||
hidden: false,
|
||||
points: 10
|
||||
},
|
||||
{
|
||||
key: 'warrior_novice',
|
||||
name: '⚔️ Guerrero Novato',
|
||||
description: 'Pelea 10 veces',
|
||||
category: 'combat',
|
||||
requirements: { type: 'fight_count', value: 10 },
|
||||
rewards: { coins: 750 },
|
||||
hidden: false,
|
||||
points: 20
|
||||
},
|
||||
{
|
||||
key: 'mob_hunter',
|
||||
name: '👾 Cazador de Monstruos',
|
||||
description: 'Derrota 50 mobs',
|
||||
category: 'combat',
|
||||
requirements: { type: 'mob_defeat_count', value: 50 },
|
||||
rewards: { coins: 3000 },
|
||||
hidden: false,
|
||||
points: 50
|
||||
},
|
||||
{
|
||||
key: 'mob_slayer',
|
||||
name: '👾 Asesino de Monstruos',
|
||||
description: 'Derrota 200 mobs',
|
||||
category: 'combat',
|
||||
requirements: { type: 'mob_defeat_count', value: 200 },
|
||||
rewards: { coins: 15000 },
|
||||
hidden: false,
|
||||
points: 100
|
||||
},
|
||||
|
||||
// Economía
|
||||
{
|
||||
key: 'first_coins',
|
||||
name: '💰 Primeras Monedas',
|
||||
description: 'Gana 1,000 monedas en total',
|
||||
category: 'economy',
|
||||
requirements: { type: 'coins_earned', value: 1000 },
|
||||
rewards: { coins: 200 },
|
||||
hidden: false,
|
||||
points: 10
|
||||
},
|
||||
{
|
||||
key: 'wealthy',
|
||||
name: '💰 Acaudalado',
|
||||
description: 'Gana 10,000 monedas en total',
|
||||
category: 'economy',
|
||||
requirements: { type: 'coins_earned', value: 10000 },
|
||||
rewards: { coins: 2000 },
|
||||
hidden: false,
|
||||
points: 30
|
||||
},
|
||||
{
|
||||
key: 'millionaire',
|
||||
name: '💰 Millonario',
|
||||
description: 'Gana 100,000 monedas en total',
|
||||
category: 'economy',
|
||||
requirements: { type: 'coins_earned', value: 100000 },
|
||||
rewards: { coins: 25000 },
|
||||
hidden: false,
|
||||
points: 100
|
||||
},
|
||||
|
||||
// Crafteo
|
||||
{
|
||||
key: 'first_craft',
|
||||
name: '🛠️ Primer Crafteo',
|
||||
description: 'Craftea tu primer item',
|
||||
category: 'crafting',
|
||||
requirements: { type: 'craft_count', value: 1 },
|
||||
rewards: { coins: 100 },
|
||||
hidden: false,
|
||||
points: 10
|
||||
},
|
||||
{
|
||||
key: 'crafter_expert',
|
||||
name: '🛠️ Artesano Experto',
|
||||
description: 'Craftea 50 items',
|
||||
category: 'crafting',
|
||||
requirements: { type: 'craft_count', value: 50 },
|
||||
rewards: { coins: 5000 },
|
||||
hidden: false,
|
||||
points: 50
|
||||
},
|
||||
{
|
||||
key: 'master_crafter',
|
||||
name: '🛠️ Maestro Artesano',
|
||||
description: 'Craftea 200 items',
|
||||
category: 'crafting',
|
||||
requirements: { type: 'craft_count', value: 200 },
|
||||
rewards: { coins: 20000 },
|
||||
hidden: false,
|
||||
points: 100
|
||||
}
|
||||
];
|
||||
|
||||
let created = 0;
|
||||
for (const ach of achievements) {
|
||||
const existing = await prisma.achievement.findUnique({
|
||||
where: { guildId_key: { guildId: guildId || '', key: ach.key } }
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
await prisma.achievement.create({
|
||||
data: { ...ach, guildId: guildId || undefined }
|
||||
});
|
||||
created++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Seeded ${created} achievements for guild ${guildId || 'global'}`);
|
||||
return created;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ejecutar si es llamado directamente
|
||||
*/
|
||||
if (require.main === module) {
|
||||
seedAchievements(null)
|
||||
.then(count => {
|
||||
console.log(`✅ ${count} achievements seeded`);
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('❌ Error seeding achievements:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export async function checkAchievements(
|
||||
}
|
||||
});
|
||||
|
||||
const newUnlocks = [];
|
||||
const newUnlocks: any[] = [];
|
||||
const stats = await getOrCreatePlayerStats(userId, guildId);
|
||||
|
||||
for (const achievement of achievements) {
|
||||
@@ -118,7 +118,7 @@ export async function checkAchievements(
|
||||
|
||||
return newUnlocks;
|
||||
} catch (error) {
|
||||
logger.error(`Error checking achievements for ${userId}:`, error);
|
||||
console.error(`Error checking achievements for ${userId}:`, error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,15 +16,11 @@ export async function updateQuestProgress(
|
||||
const quests = await prisma.quest.findMany({
|
||||
where: {
|
||||
OR: [{ guildId }, { guildId: null }],
|
||||
active: true,
|
||||
OR: [
|
||||
{ endAt: null },
|
||||
{ endAt: { gte: new Date() } }
|
||||
]
|
||||
active: true
|
||||
}
|
||||
});
|
||||
|
||||
const updates = [];
|
||||
const updates: any[] = [];
|
||||
|
||||
for (const quest of quests) {
|
||||
const req = quest.requirements as any;
|
||||
@@ -94,7 +90,7 @@ export async function updateQuestProgress(
|
||||
|
||||
return updates;
|
||||
} catch (error) {
|
||||
logger.error(`Error updating quest progress for ${userId}:`, error);
|
||||
console.error(`Error updating quest progress for ${userId}:`, error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -144,7 +140,7 @@ export async function claimQuestReward(
|
||||
|
||||
return { quest: progress.quest, rewards };
|
||||
} catch (error) {
|
||||
logger.error(`Error claiming quest reward for ${userId}:`, error);
|
||||
console.error(`Error claiming quest reward for ${userId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -156,11 +152,7 @@ export async function getPlayerQuests(userId: string, guildId: string) {
|
||||
const quests = await prisma.quest.findMany({
|
||||
where: {
|
||||
OR: [{ guildId }, { guildId: null }],
|
||||
active: true,
|
||||
OR: [
|
||||
{ endAt: null },
|
||||
{ endAt: { gte: new Date() } }
|
||||
]
|
||||
active: true
|
||||
},
|
||||
orderBy: [
|
||||
{ type: 'asc' },
|
||||
@@ -272,10 +264,10 @@ export async function generateDailyQuests(guildId: string) {
|
||||
});
|
||||
}
|
||||
|
||||
logger.info(`Generated ${selectedTemplates.length} daily quests for guild ${guildId}`);
|
||||
console.log(`Generated ${selectedTemplates.length} daily quests for guild ${guildId}`);
|
||||
return selectedTemplates.length;
|
||||
} catch (error) {
|
||||
logger.error(`Error generating daily quests for ${guildId}:`, error);
|
||||
console.error(`Error generating daily quests for ${guildId}:`, error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -295,6 +287,6 @@ export async function cleanExpiredQuests(guildId: string) {
|
||||
}
|
||||
});
|
||||
|
||||
logger.info(`Deactivated ${result.count} expired quests for guild ${guildId}`);
|
||||
console.log(`Deactivated ${result.count} expired quests for guild ${guildId}`);
|
||||
return result.count;
|
||||
}
|
||||
|
||||
@@ -52,15 +52,15 @@ export async function giveRewards(
|
||||
guildId,
|
||||
action: 'reward_given',
|
||||
target: source,
|
||||
details: rewards
|
||||
details: rewards as any
|
||||
}
|
||||
}).catch(() => {}); // Silencioso si falla el log
|
||||
|
||||
logger.info(`Rewards given to ${userId} in ${guildId} from ${source}:`, rewards);
|
||||
console.log(`Rewards given to ${userId} in ${guildId} from ${source}:`, rewards);
|
||||
|
||||
return results;
|
||||
} catch (error) {
|
||||
logger.error(`Error giving rewards to ${userId} in ${guildId}:`, error);
|
||||
console.error(`Error giving rewards to ${userId} in ${guildId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ export async function updateStats(
|
||||
|
||||
return stats;
|
||||
} catch (error) {
|
||||
logger.error(`Error updating stats for ${userId} in ${guildId}:`, error);
|
||||
console.error(`Error updating stats for ${userId} in ${guildId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ export async function updateStreak(userId: string, guildId: string) {
|
||||
daysIncreased: daysDiff === 1
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error(`Error updating streak for ${userId}:`, error);
|
||||
console.error(`Error updating streak for ${userId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user