Add equipment crafting system
- Add crafting-recipes.ts with blueprint definitions and material requirements - Update crafting-slice.ts with equipment crafting functions - Add EquipmentCraftingProgress type and state - Update CraftingTab.tsx with new Craft tab for equipment crafting - Add material deletion functionality - Update store.ts with equipment crafting methods - Update page.tsx to pass new props to CraftingTab Features: - Players can craft equipment from discovered blueprints - Crafting requires materials and mana - Materials are obtained from loot drops - New Craft tab in the crafting interface - Shows blueprint details and material requirements
This commit is contained in:
@@ -47,7 +47,8 @@ import {
|
||||
type FamiliarBonuses,
|
||||
DEFAULT_FAMILIAR_BONUSES,
|
||||
} from './familiar-slice';
|
||||
import { rollLootDrops } from './data/loot-drops';
|
||||
import { rollLootDrops, LOOT_DROPS } from './data/loot-drops';
|
||||
import { CRAFTING_RECIPES, canCraftRecipe } from './data/crafting-recipes';
|
||||
|
||||
// Default empty effects for when effects aren't provided
|
||||
const DEFAULT_EFFECTS: ComputedEffects = {
|
||||
@@ -560,6 +561,9 @@ function makeInitial(overrides: Partial<GameState> = {}): GameState {
|
||||
blueprints: [],
|
||||
},
|
||||
lootDropsToday: 0,
|
||||
|
||||
// Equipment Crafting Progress
|
||||
equipmentCraftingProgress: null,
|
||||
|
||||
// Achievements
|
||||
achievements: {
|
||||
@@ -1912,6 +1916,98 @@ export const useGameStore = create<GameStore>()(
|
||||
return instance.totalCapacity - instance.usedCapacity;
|
||||
},
|
||||
|
||||
// ─── Equipment Crafting (from blueprints) ───────────────────────────────────
|
||||
|
||||
startCraftingEquipment: (blueprintId: string) => {
|
||||
const state = get();
|
||||
const recipe = CRAFTING_RECIPES[blueprintId];
|
||||
if (!recipe) return false;
|
||||
|
||||
// Check if player has the blueprint
|
||||
if (!state.lootInventory.blueprints.includes(blueprintId)) return false;
|
||||
|
||||
// Check materials and mana
|
||||
const { canCraft } = canCraftRecipe(
|
||||
recipe,
|
||||
state.lootInventory.materials,
|
||||
state.rawMana
|
||||
);
|
||||
|
||||
if (!canCraft) return false;
|
||||
|
||||
// Deduct materials
|
||||
const newMaterials = { ...state.lootInventory.materials };
|
||||
for (const [matId, amount] of Object.entries(recipe.materials)) {
|
||||
newMaterials[matId] = (newMaterials[matId] || 0) - amount;
|
||||
if (newMaterials[matId] <= 0) {
|
||||
delete newMaterials[matId];
|
||||
}
|
||||
}
|
||||
|
||||
// Start crafting progress
|
||||
set((state) => ({
|
||||
lootInventory: {
|
||||
...state.lootInventory,
|
||||
materials: newMaterials,
|
||||
},
|
||||
rawMana: state.rawMana - recipe.manaCost,
|
||||
currentAction: 'craft',
|
||||
equipmentCraftingProgress: {
|
||||
blueprintId,
|
||||
equipmentTypeId: recipe.equipmentTypeId,
|
||||
progress: 0,
|
||||
required: recipe.craftTime,
|
||||
manaSpent: recipe.manaCost,
|
||||
},
|
||||
log: [`🔨 Started crafting ${recipe.name}...`, ...state.log.slice(0, 49)],
|
||||
}));
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
cancelEquipmentCrafting: () => {
|
||||
set((state) => {
|
||||
const progress = state.equipmentCraftingProgress;
|
||||
if (!progress) return {};
|
||||
|
||||
const recipe = CRAFTING_RECIPES[progress.blueprintId];
|
||||
if (!recipe) return { currentAction: 'meditate', equipmentCraftingProgress: null };
|
||||
|
||||
// Refund 50% of mana
|
||||
const manaRefund = Math.floor(progress.manaSpent * 0.5);
|
||||
|
||||
return {
|
||||
currentAction: 'meditate',
|
||||
equipmentCraftingProgress: null,
|
||||
rawMana: state.rawMana + manaRefund,
|
||||
log: [`🚫 Crafting cancelled. Refunded ${manaRefund} mana.`, ...state.log.slice(0, 49)],
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
deleteMaterial: (materialId: string, amount: number) => {
|
||||
set((state) => {
|
||||
const currentAmount = state.lootInventory.materials[materialId] || 0;
|
||||
const newAmount = Math.max(0, currentAmount - amount);
|
||||
const newMaterials = { ...state.lootInventory.materials };
|
||||
|
||||
if (newAmount <= 0) {
|
||||
delete newMaterials[materialId];
|
||||
} else {
|
||||
newMaterials[materialId] = newAmount;
|
||||
}
|
||||
|
||||
const dropName = LOOT_DROPS[materialId]?.name || materialId;
|
||||
return {
|
||||
lootInventory: {
|
||||
...state.lootInventory,
|
||||
materials: newMaterials,
|
||||
},
|
||||
log: [`🗑️ Deleted ${amount}x ${dropName}.`, ...state.log.slice(0, 49)],
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
// ─── Floor Navigation ────────────────────────────────────────────────────────
|
||||
|
||||
setClimbDirection: (direction: 'up' | 'down') => {
|
||||
|
||||
Reference in New Issue
Block a user