Refactor large files into modular components
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m9s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m9s
- Refactored page.tsx (613→252 lines) with GameOverScreen and LeftPanel extracted - Refactored StatsTab.tsx (584→92 lines) with section components - Refactored SkillsTab.tsx (434→54 lines) with sub-components - Created modular structure for GameContext, LootInventory, and other components - All extracted components organized into feature directories
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
// ─── Room Generation Functions ────────────────────────────────────────────────
|
||||
// Extracted from store.ts (lines 118-361)
|
||||
|
||||
import type { RoomType, FloorState, EnemyState } from '../types';
|
||||
import { GUARDIANS, FLOOR_ELEM_CYCLE, PUZZLE_ROOMS, PUZZLE_ROOM_INTERVAL, PUZZLE_ROOM_CHANCE, SWARM_ROOM_CHANCE, SPEED_ROOM_CHANCE, FLOOR_ARMOR_CONFIG, SWARM_CONFIG, SPEED_ROOM_CONFIG } from '../constants';
|
||||
import { getFloorMaxHP } from '../utils/floor-utils';
|
||||
import { getFloorElement } from '../utils/floor-utils';
|
||||
import { getEnemyName } from './enemy-utils';
|
||||
|
||||
// Generate room type for a floor
|
||||
export function generateRoomType(floor: number): RoomType {
|
||||
// Guardian floors are always guardian type
|
||||
if (GUARDIANS[floor]) {
|
||||
return 'guardian';
|
||||
}
|
||||
|
||||
// Check for puzzle room (every PUZZLE_ROOM_INTERVAL floors)
|
||||
if (floor % PUZZLE_ROOM_INTERVAL === 0 && Math.random() < PUZZLE_ROOM_CHANCE) {
|
||||
return 'puzzle';
|
||||
}
|
||||
|
||||
// Check for swarm room
|
||||
if (Math.random() < SWARM_ROOM_CHANCE) {
|
||||
return 'swarm';
|
||||
}
|
||||
|
||||
// Check for speed room
|
||||
if (Math.random() < SPEED_ROOM_CHANCE) {
|
||||
return 'speed';
|
||||
}
|
||||
|
||||
// Default to combat
|
||||
return 'combat';
|
||||
}
|
||||
|
||||
// Get armor for a non-guardian floor
|
||||
export function getFloorArmor(floor: number): number {
|
||||
if (GUARDIANS[floor]) {
|
||||
return GUARDIANS[floor].armor || 0;
|
||||
}
|
||||
|
||||
// Armor becomes more common on higher floors
|
||||
if (floor < 10) return 0;
|
||||
|
||||
const armorChance = Math.min(FLOOR_ARMOR_CONFIG.maxArmorChance,
|
||||
FLOOR_ARMOR_CONFIG.baseChance + (floor - 10) * FLOOR_ARMOR_CONFIG.chancePerFloor);
|
||||
|
||||
if (Math.random() > armorChance) return 0;
|
||||
|
||||
// Scale armor with floor
|
||||
const armorRange = FLOOR_ARMOR_CONFIG.maxArmor - FLOOR_ARMOR_CONFIG.minArmor;
|
||||
const floorProgress = Math.min(1, (floor - 10) / 90);
|
||||
return FLOOR_ARMOR_CONFIG.minArmor + armorRange * floorProgress * Math.random();
|
||||
}
|
||||
|
||||
// Get dodge chance for a speed room
|
||||
export function getDodgeChance(floor: number): number {
|
||||
return Math.min(
|
||||
SPEED_ROOM_CONFIG.maxDodge,
|
||||
SPEED_ROOM_CONFIG.baseDodgeChance + floor * SPEED_ROOM_CONFIG.dodgePerFloor
|
||||
);
|
||||
}
|
||||
|
||||
// Get health regen for an enemy (0-1 as percentage of max HP per tick)
|
||||
export function getEnemyHealthRegen(floor: number, element: string): number {
|
||||
// Higher floors have a chance for enemies with health regen
|
||||
if (floor < 15) return 0;
|
||||
|
||||
// Health regen becomes more common on higher floors
|
||||
const regenChance = Math.min(0.3, (floor - 15) * 0.005); // Max 30% chance
|
||||
if (Math.random() > regenChance) return 0;
|
||||
|
||||
// Scale regen with floor (0.5% to 3% of max HP per tick)
|
||||
const floorProgress = Math.min(1, (floor - 15) / 85);
|
||||
return 0.005 + floorProgress * 0.025;
|
||||
}
|
||||
|
||||
// Get barrier for an enemy (0-1 as percentage of max HP)
|
||||
export function getEnemyBarrier(floor: number, element: string): number {
|
||||
// Barrier appears on higher floors, more common with certain elements
|
||||
if (floor < 20) return 0;
|
||||
|
||||
// Barrier chance based on element - light/water/earth more likely
|
||||
const barrierElements = ['light', 'water', 'earth'];
|
||||
const baseChance = barrierElements.includes(element) ? 0.15 : 0.08;
|
||||
const floorBonus = Math.min(0.25, (floor - 20) * 0.003); // Max 25% additional chance
|
||||
const barrierChance = Math.min(0.4, baseChance + floorBonus);
|
||||
|
||||
if (Math.random() > barrierChance) return 0;
|
||||
|
||||
// Barrier is 10% to 30% of max HP
|
||||
const floorProgress = Math.min(1, (floor - 20) / 80);
|
||||
return 0.1 + floorProgress * 0.2;
|
||||
}
|
||||
|
||||
// Generate enemies for a swarm room
|
||||
export function generateSwarmEnemies(floor: number): EnemyState[] {
|
||||
const baseHP = getFloorMaxHP(floor);
|
||||
const element = getFloorElement(floor);
|
||||
const numEnemies = SWARM_CONFIG.minEnemies +
|
||||
Math.floor(Math.random() * (SWARM_CONFIG.maxEnemies - SWARM_CONFIG.minEnemies + 1));
|
||||
|
||||
const enemies: EnemyState[] = [];
|
||||
for (let i = 0; i < numEnemies; i++) {
|
||||
const enemyName = getEnemyName(element, floor);
|
||||
enemies.push({
|
||||
id: `enemy_${i}`,
|
||||
name: enemyName,
|
||||
hp: Math.floor(baseHP * SWARM_CONFIG.hpMultiplier),
|
||||
maxHP: Math.floor(baseHP * SWARM_CONFIG.hpMultiplier),
|
||||
armor: SWARM_CONFIG.armorBase + Math.floor(floor / 10) * SWARM_CONFIG.armorPerFloor,
|
||||
dodgeChance: 0,
|
||||
healthRegen: getEnemyHealthRegen(floor, element),
|
||||
barrier: getEnemyBarrier(floor, element),
|
||||
element,
|
||||
});
|
||||
}
|
||||
return enemies;
|
||||
}
|
||||
|
||||
// Generate initial floor state
|
||||
export function generateFloorState(floor: number): FloorState {
|
||||
const roomType = generateRoomType(floor);
|
||||
const element = getFloorElement(floor);
|
||||
const baseHP = getFloorMaxHP(floor);
|
||||
const guardian = GUARDIANS[floor];
|
||||
|
||||
switch (roomType) {
|
||||
case 'guardian':
|
||||
return {
|
||||
roomType: 'guardian',
|
||||
enemies: [{
|
||||
id: 'guardian',
|
||||
name: guardian.name,
|
||||
hp: guardian.hp,
|
||||
maxHP: guardian.hp,
|
||||
armor: guardian.armor || 0,
|
||||
dodgeChance: 0,
|
||||
healthRegen: 0.01, // Guardians have 1% HP regen per tick
|
||||
barrier: 0,
|
||||
element: guardian.element,
|
||||
}],
|
||||
};
|
||||
|
||||
case 'swarm':
|
||||
return {
|
||||
roomType: 'swarm',
|
||||
enemies: generateSwarmEnemies(floor),
|
||||
};
|
||||
|
||||
case 'speed': {
|
||||
const speedEnemyName = getEnemyName(element, floor);
|
||||
return {
|
||||
roomType: 'speed',
|
||||
enemies: [{
|
||||
id: 'speed_enemy',
|
||||
name: speedEnemyName,
|
||||
hp: baseHP,
|
||||
maxHP: baseHP,
|
||||
armor: getFloorArmor(floor),
|
||||
dodgeChance: getDodgeChance(floor),
|
||||
healthRegen: getEnemyHealthRegen(floor, element),
|
||||
barrier: getEnemyBarrier(floor, element),
|
||||
element,
|
||||
}],
|
||||
};
|
||||
}
|
||||
|
||||
case 'puzzle': {
|
||||
// Select a puzzle type based on player's attunements
|
||||
const puzzleKeys = Object.keys(PUZZLE_ROOMS);
|
||||
const selectedPuzzle = puzzleKeys[Math.floor(Math.random() * puzzleKeys.length)];
|
||||
const puzzle = PUZZLE_ROOMS[selectedPuzzle];
|
||||
return {
|
||||
roomType: 'puzzle',
|
||||
enemies: [],
|
||||
puzzleProgress: 0,
|
||||
puzzleRequired: 1,
|
||||
puzzleId: selectedPuzzle,
|
||||
puzzleAttunements: puzzle.attunements,
|
||||
};
|
||||
}
|
||||
|
||||
default: // combat
|
||||
const combatEnemyName = getEnemyName(element, floor);
|
||||
return {
|
||||
roomType: 'combat',
|
||||
enemies: [{
|
||||
id: 'enemy',
|
||||
name: combatEnemyName,
|
||||
hp: baseHP,
|
||||
maxHP: baseHP,
|
||||
armor: getFloorArmor(floor),
|
||||
dodgeChance: 0,
|
||||
healthRegen: getEnemyHealthRegen(floor, element),
|
||||
barrier: getEnemyBarrier(floor, element),
|
||||
element,
|
||||
}],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Get puzzle progress speed based on attunements
|
||||
export function getPuzzleProgressSpeed(
|
||||
puzzleId: string,
|
||||
attunements: Record<string, any>
|
||||
): number {
|
||||
const puzzle = PUZZLE_ROOMS[puzzleId];
|
||||
if (!puzzle) return 0.02; // Default slow progress
|
||||
|
||||
let speed = puzzle.baseProgressPerTick;
|
||||
|
||||
// Add bonus for each relevant attunement level
|
||||
for (const attId of puzzle.attunements) {
|
||||
const attState = attunements[attId];
|
||||
if (attState?.active) {
|
||||
speed += puzzle.attunementBonus * (attState.level || 1);
|
||||
}
|
||||
}
|
||||
|
||||
return speed;
|
||||
}
|
||||
Reference in New Issue
Block a user