347 lines
7.8 KiB
TypeScript
Executable File
347 lines
7.8 KiB
TypeScript
Executable File
// ─── Loot Drop Definitions ─────────────────────────────────────────────────────
|
|
|
|
import type { LootDrop } from '../types/game';
|
|
|
|
export const LOOT_DROPS: Record<string, LootDrop> = {
|
|
// ─── Materials (used for crafting) ───
|
|
manaCrystalDust: {
|
|
id: 'manaCrystalDust',
|
|
name: 'Mana Crystal Dust',
|
|
rarity: 'common',
|
|
type: 'material',
|
|
minFloor: 1,
|
|
dropChance: 0.15,
|
|
},
|
|
arcaneShard: {
|
|
id: 'arcaneShard',
|
|
name: 'Arcane Shard',
|
|
rarity: 'uncommon',
|
|
type: 'material',
|
|
minFloor: 10,
|
|
dropChance: 0.10,
|
|
},
|
|
earthShard: {
|
|
id: 'earthShard',
|
|
name: 'Earth Attuned Shard',
|
|
rarity: 'uncommon',
|
|
type: 'material',
|
|
minFloor: 10,
|
|
dropChance: 0.08,
|
|
},
|
|
metalShard: {
|
|
id: 'metalShard',
|
|
name: 'Metal Attuned Shard',
|
|
rarity: 'rare',
|
|
type: 'material',
|
|
minFloor: 20,
|
|
dropChance: 0.06,
|
|
},
|
|
crystalShard: {
|
|
id: 'crystalShard',
|
|
name: 'Crystal Attuned Shard',
|
|
rarity: 'rare',
|
|
type: 'material',
|
|
minFloor: 30,
|
|
dropChance: 0.05,
|
|
},
|
|
sandShard: {
|
|
id: 'sandShard',
|
|
name: 'Sand Attuned Shard',
|
|
rarity: 'uncommon',
|
|
type: 'material',
|
|
minFloor: 15,
|
|
dropChance: 0.07,
|
|
},
|
|
manaCrystal: {
|
|
id: 'manaCrystal',
|
|
name: 'Mana Crystal',
|
|
rarity: 'uncommon',
|
|
type: 'material',
|
|
minFloor: 5,
|
|
dropChance: 0.10,
|
|
},
|
|
fireCrystal: {
|
|
id: 'fireCrystal',
|
|
name: 'Fire Attuned Crystal',
|
|
rarity: 'rare',
|
|
type: 'material',
|
|
minFloor: 15,
|
|
dropChance: 0.06,
|
|
},
|
|
waterCrystal: {
|
|
id: 'waterCrystal',
|
|
name: 'Water Attuned Crystal',
|
|
rarity: 'rare',
|
|
type: 'material',
|
|
minFloor: 15,
|
|
dropChance: 0.06,
|
|
},
|
|
airCrystal: {
|
|
id: 'airCrystal',
|
|
name: 'Air Attuned Crystal',
|
|
rarity: 'rare',
|
|
type: 'material',
|
|
minFloor: 15,
|
|
dropChance: 0.06,
|
|
},
|
|
earthCrystal: {
|
|
id: 'earthCrystal',
|
|
name: 'Earth Attuned Crystal',
|
|
rarity: 'rare',
|
|
type: 'material',
|
|
minFloor: 15,
|
|
dropChance: 0.06,
|
|
},
|
|
lightCrystal: {
|
|
id: 'lightCrystal',
|
|
name: 'Light Attuned Crystal',
|
|
rarity: 'rare',
|
|
type: 'material',
|
|
minFloor: 25,
|
|
dropChance: 0.05,
|
|
},
|
|
darkCrystal: {
|
|
id: 'darkCrystal',
|
|
name: 'Dark Attuned Crystal',
|
|
rarity: 'rare',
|
|
type: 'material',
|
|
minFloor: 25,
|
|
dropChance: 0.05,
|
|
},
|
|
metalCrystal: {
|
|
id: 'metalCrystal',
|
|
name: 'Metal Attuned Crystal',
|
|
rarity: 'rare',
|
|
type: 'material',
|
|
minFloor: 30,
|
|
dropChance: 0.05,
|
|
},
|
|
crystalCrystal: {
|
|
id: 'crystalCrystal',
|
|
name: 'Crystal Attuned Crystal',
|
|
rarity: 'epic',
|
|
type: 'material',
|
|
minFloor: 40,
|
|
dropChance: 0.03,
|
|
},
|
|
elementalCore: {
|
|
id: 'elementalCore',
|
|
name: 'Elemental Core',
|
|
rarity: 'rare',
|
|
type: 'material',
|
|
minFloor: 25,
|
|
dropChance: 0.08,
|
|
},
|
|
voidEssence: {
|
|
id: 'voidEssence',
|
|
name: 'Void Essence',
|
|
rarity: 'epic',
|
|
type: 'material',
|
|
minFloor: 50,
|
|
dropChance: 0.05,
|
|
guardianOnly: true,
|
|
},
|
|
celestialFragment: {
|
|
id: 'celestialFragment',
|
|
name: 'Celestial Fragment',
|
|
rarity: 'legendary',
|
|
type: 'material',
|
|
minFloor: 75,
|
|
dropChance: 0.02,
|
|
guardianOnly: true,
|
|
},
|
|
|
|
// ─── Elemental Essence (grants elemental mana) ───
|
|
fireEssenceDrop: {
|
|
id: 'fireEssenceDrop',
|
|
name: 'Fire Essence',
|
|
rarity: 'uncommon',
|
|
type: 'essence',
|
|
minFloor: 5,
|
|
dropChance: 0.12,
|
|
amount: { min: 5, max: 15 },
|
|
},
|
|
waterEssenceDrop: {
|
|
id: 'waterEssenceDrop',
|
|
name: 'Water Essence',
|
|
rarity: 'uncommon',
|
|
type: 'essence',
|
|
minFloor: 5,
|
|
dropChance: 0.12,
|
|
amount: { min: 5, max: 15 },
|
|
},
|
|
airEssenceDrop: {
|
|
id: 'airEssenceDrop',
|
|
name: 'Air Essence',
|
|
rarity: 'uncommon',
|
|
type: 'essence',
|
|
minFloor: 5,
|
|
dropChance: 0.12,
|
|
amount: { min: 5, max: 15 },
|
|
},
|
|
earthEssenceDrop: {
|
|
id: 'earthEssenceDrop',
|
|
name: 'Earth Essence',
|
|
rarity: 'uncommon',
|
|
type: 'essence',
|
|
minFloor: 5,
|
|
dropChance: 0.12,
|
|
amount: { min: 5, max: 15 },
|
|
},
|
|
lightEssenceDrop: {
|
|
id: 'lightEssenceDrop',
|
|
name: 'Light Essence',
|
|
rarity: 'rare',
|
|
type: 'essence',
|
|
minFloor: 20,
|
|
dropChance: 0.08,
|
|
amount: { min: 3, max: 10 },
|
|
},
|
|
darkEssenceDrop: {
|
|
id: 'darkEssenceDrop',
|
|
name: 'Dark Essence',
|
|
rarity: 'rare',
|
|
type: 'essence',
|
|
minFloor: 20,
|
|
dropChance: 0.08,
|
|
amount: { min: 3, max: 10 },
|
|
},
|
|
vitalityEssenceDrop: {
|
|
id: 'vitalityEssenceDrop',
|
|
name: 'Vitality Essence',
|
|
rarity: 'epic',
|
|
type: 'essence',
|
|
minFloor: 40,
|
|
dropChance: 0.05,
|
|
amount: { min: 2, max: 8 },
|
|
},
|
|
deathEssenceDrop: {
|
|
id: 'deathEssenceDrop',
|
|
name: 'Death Essence',
|
|
rarity: 'epic',
|
|
type: 'essence',
|
|
minFloor: 40,
|
|
dropChance: 0.05,
|
|
amount: { min: 2, max: 8 },
|
|
},
|
|
|
|
// ─── Raw Mana Drops ───
|
|
manaOrb: {
|
|
id: 'manaOrb',
|
|
name: 'Mana Orb',
|
|
rarity: 'common',
|
|
type: 'gold', // Uses gold type but gives raw mana
|
|
minFloor: 1,
|
|
dropChance: 0.20,
|
|
amount: { min: 10, max: 50 },
|
|
},
|
|
greaterManaOrb: {
|
|
id: 'greaterManaOrb',
|
|
name: 'Greater Mana Orb',
|
|
rarity: 'uncommon',
|
|
type: 'gold',
|
|
minFloor: 15,
|
|
dropChance: 0.10,
|
|
amount: { min: 50, max: 150 },
|
|
},
|
|
supremeManaOrb: {
|
|
id: 'supremeManaOrb',
|
|
name: 'Supreme Mana Orb',
|
|
rarity: 'rare',
|
|
type: 'gold',
|
|
minFloor: 35,
|
|
dropChance: 0.05,
|
|
amount: { min: 100, max: 500 },
|
|
},
|
|
|
|
// ─── Equipment Blueprints ───
|
|
staffBlueprint: {
|
|
id: 'staffBlueprint',
|
|
name: 'Staff Blueprint',
|
|
rarity: 'uncommon',
|
|
type: 'blueprint',
|
|
minFloor: 10,
|
|
dropChance: 0.03,
|
|
},
|
|
wandBlueprint: {
|
|
id: 'wandBlueprint',
|
|
name: 'Wand Blueprint',
|
|
rarity: 'rare',
|
|
type: 'blueprint',
|
|
minFloor: 20,
|
|
dropChance: 0.02,
|
|
},
|
|
robeBlueprint: {
|
|
id: 'robeBlueprint',
|
|
name: 'Mage Robe Blueprint',
|
|
rarity: 'rare',
|
|
type: 'blueprint',
|
|
minFloor: 25,
|
|
dropChance: 0.02,
|
|
},
|
|
artifactBlueprint: {
|
|
id: 'artifactBlueprint',
|
|
name: 'Artifact Blueprint',
|
|
rarity: 'legendary',
|
|
type: 'blueprint',
|
|
minFloor: 60,
|
|
dropChance: 0.01,
|
|
guardianOnly: true,
|
|
},
|
|
};
|
|
|
|
// Rarity colors for UI
|
|
export const LOOT_RARITY_COLORS: Record<string, { color: string; glow: string }> = {
|
|
common: { color: '#9CA3AF', glow: '#9CA3AF40' },
|
|
uncommon: { color: '#22C55E', glow: '#22C55E40' },
|
|
rare: { color: '#3B82F6', glow: '#3B82F640' },
|
|
epic: { color: '#A855F7', glow: '#A855F740' },
|
|
legendary: { color: '#F59E0B', glow: '#F59E0B60' },
|
|
};
|
|
|
|
// Get loot drops available at a given floor
|
|
export function getAvailableDrops(floor: number, isGuardian: boolean): LootDrop[] {
|
|
return Object.values(LOOT_DROPS).filter(drop => {
|
|
if (drop.minFloor > floor) return false;
|
|
if (drop.guardianOnly && !isGuardian) return false;
|
|
return true;
|
|
});
|
|
}
|
|
|
|
// Roll for loot drops
|
|
export function rollLootDrops(
|
|
floor: number,
|
|
isGuardian: boolean,
|
|
luckBonus: number = 0
|
|
): Array<{ drop: LootDrop; amount: number }> {
|
|
const available = getAvailableDrops(floor, isGuardian);
|
|
const drops: Array<{ drop: LootDrop; amount: number }> = [];
|
|
|
|
for (const drop of available) {
|
|
// Calculate adjusted drop chance
|
|
let chance = drop.dropChance;
|
|
chance *= (1 + luckBonus); // Apply luck bonus
|
|
|
|
// Guardian floors have 2x drop rate
|
|
if (isGuardian) chance *= 2;
|
|
|
|
// Cap at 50% for any single drop
|
|
chance = Math.min(0.5, chance);
|
|
|
|
if (Math.random() < chance) {
|
|
let amount = 1;
|
|
|
|
// For gold/essence types, roll amount
|
|
if (drop.amount) {
|
|
amount = Math.floor(
|
|
Math.random() * (drop.amount.max - drop.amount.min + 1) + drop.amount.min
|
|
);
|
|
}
|
|
|
|
drops.push({ drop, amount });
|
|
}
|
|
}
|
|
|
|
return drops;
|
|
}
|