Fix Spire Mode floor rendering and swarm floors (Tasks 5 & 6)

- Added enemy naming system with getEnemyName() function
- Updated EnemyState type to include name field
- Updated generateSwarmEnemies() and generateFloorState() to assign enemy names
- Fixed SpireTab.tsx (both versions) to display:
  - Floor type (Combat/Swarm/Speed/Guardian/Puzzle) with icons
  - Named enemies based on element and floor tier
  - Special floor properties (armor %, dodge chance)
  - Multiple enemies for swarm floors with individual HP bars
- Added ROOM_TYPE_LABELS to constants for display
- Verified floor type generation logic works correctly
- Build succeeds with npm run build
This commit is contained in:
Refactoring Agent
2026-04-28 13:36:16 +02:00
parent 7056dc04d6
commit 8aacc2c88e
61 changed files with 239 additions and 4651 deletions
+9
View File
@@ -26,3 +26,12 @@ export { PRESTIGE_DEF } from './prestige';
export type { RoomType } from './rooms';
export { PUZZLE_ROOM_INTERVAL, SWARM_ROOM_CHANCE, SPEED_ROOM_CHANCE, PUZZLE_ROOM_CHANCE } from './rooms';
export { PUZZLE_ROOMS, SWARM_CONFIG, SPEED_ROOM_CONFIG, FLOOR_ARMOR_CONFIG } from './rooms';
// Room type display labels
export const ROOM_TYPE_LABELS: Record<string, { label: string; icon: string; color: string }> = {
combat: { label: 'Combat', icon: '⚔️', color: '#EF4444' },
swarm: { label: 'Swarm', icon: '🐝', color: '#F59E0B' },
speed: { label: 'Speed', icon: '💨', color: '#3B82F6' },
guardian: { label: 'Guardian', icon: '🛡️', color: '#EF4444' },
puzzle: { label: 'Puzzle', icon: '🧩', color: '#8B5CF6' },
};
+61 -1
View File
@@ -1269,6 +1269,19 @@ export const useGameStore = create<GameStore>()(
const puzzle = PUZZLE_ROOMS[currentRoom.puzzleId || ''];
log = [`🧩 ${puzzle?.name || 'Puzzle'} solved! Proceeding to floor ${currentFloor + 1}.`, ...log.slice(0, 49)];
// Log puzzle solved to activity log
activityLog = addActivityLogEntry(state, 'puzzle_solved',
`🧩 ${puzzle?.name || 'Puzzle'} solved!`,
{ floor: currentFloor }
);
// Log floor transition to activity log
const newFloorElem = getFloorElement(currentFloor + 1);
activityLog = addActivityLogEntry(state, 'floor_transition',
`⬆️ Advanced to floor ${currentFloor + 1} (${newFloorElem})`,
{ floor: currentFloor + 1 }
);
currentFloor = currentFloor + 1;
if (currentFloor > 100) currentFloor = 100;
currentRoom = generateFloorState(currentFloor);
@@ -1392,24 +1405,40 @@ export const useGameStore = create<GameStore>()(
if (hasSpecial(effects, SPECIAL_EFFECTS.FIRST_STRIKE) && floorHitCount === 1) {
dmg *= 1.15;
log = [`⚡ First Strike! +15% damage!`, ...log.slice(0, 49)];
activityLog = addActivityLogEntry(state, 'special_effect',
`⚡ First Strike! +15% damage!`,
{ effectName: 'First Strike', floor: currentFloor }
);
}
// Combo Master: Every 5th attack deals 3x damage
if (hasSpecial(effects, SPECIAL_EFFECTS.COMBO_MASTER) && comboHitCount % 5 === 0) {
dmg *= 3;
log = [`🌀 Combo Master! Triple damage!`, ...log.slice(0, 49)];
activityLog = addActivityLogEntry(state, 'special_effect',
`🌀 Combo Master! Triple damage!`,
{ effectName: 'Combo Master', floor: currentFloor }
);
}
// Executioner: +100% damage to enemies below 25% HP
if (hasSpecial(effects, SPECIAL_EFFECTS.EXECUTIONER) && enemy.hp / enemy.maxHP < 0.25) {
dmg *= 2;
log = [`💀 Executioner! Double damage!`, ...log.slice(0, 49)];
activityLog = addActivityLogEntry(state, 'special_effect',
`💀 Executioner! Double damage!`,
{ effectName: 'Executioner', floor: currentFloor }
);
}
// Berserker: +50% damage when below 50% mana
if (hasSpecial(effects, SPECIAL_EFFECTS.BERSERKER) && rawMana < maxMana * 0.5) {
dmg *= 1.5;
log = [`🔥 Berserker! +50% damage!`, ...log.slice(0, 49)];
activityLog = addActivityLogEntry(state, 'special_effect',
`🔥 Berserker! +50% damage!`,
{ effectName: 'Berserker', floor: currentFloor }
);
}
// EXOTIC_MASTERY: +20% damage with exotic elements
@@ -1418,6 +1447,10 @@ export const useGameStore = create<GameStore>()(
if (elemDef?.cat === 'exotic') {
dmg *= 1.2;
log = [`🌟 Exotic Mastery! +20% damage!`, ...log.slice(0, 49)];
activityLog = addActivityLogEntry(state, 'special_effect',
`🌟 Exotic Mastery! +20% damage!`,
{ effectName: 'Exotic Mastery', spellName: spellDef.name, floor: currentFloor }
);
}
}
@@ -1426,6 +1459,10 @@ export const useGameStore = create<GameStore>()(
if (Math.random() < echoChance) {
dmg *= 2;
log = [`✨ Spell Echo! Double damage!`, ...log.slice(0, 49)];
activityLog = addActivityLogEntry(state, 'special_effect',
`✨ Spell Echo! Double damage!`,
{ effectName: 'Spell Echo', spellName: spellDef.name, floor: currentFloor }
);
}
// Apply damage to enemy
@@ -1734,7 +1771,14 @@ export const useGameStore = create<GameStore>()(
damage *= (1 - effectiveArmor);
// Apply damage
enemy.hp = Math.max(0, enemy.hp - Math.floor(damage));
const golemDmgDealt = Math.floor(damage);
enemy.hp = Math.max(0, enemy.hp - golemDmgDealt);
// Log golem damage to activity log
activityLog = addActivityLogEntry(state, 'golem_attack',
`🗿 ${golemDef.name || summonedGolem.golemId} dealt ${golemDmgDealt} damage`,
{ damage: golemDmgDealt, enemyName: 'enemy', floor: currentFloor, spellName: golemDef.name }
);
}
// Update currentRoom with damaged enemies
@@ -1754,6 +1798,11 @@ export const useGameStore = create<GameStore>()(
if (wasGuardian && !signedPacts.includes(currentFloor)) {
signedPacts = [...signedPacts, currentFloor];
log = [`⚔️ ${wasGuardian.name} defeated by golems! Pact signed! (${wasGuardian.pact}x)`, ...log.slice(0, 49)];
// Log guardian defeated to activity log
activityLog = addActivityLogEntry(state, 'enemy_defeated',
`⚔️ ${wasGuardian.name} defeated by golems! Pact signed! (${wasGuardian.pact}x)`,
{ enemyName: wasGuardian.name, floor: currentFloor }
);
} else if (!wasGuardian) {
const roomTypeName = currentRoom.roomType === 'swarm' ? 'Swarm'
: currentRoom.roomType === 'speed' ? 'Speed floor'
@@ -1761,6 +1810,11 @@ export const useGameStore = create<GameStore>()(
: 'Floor';
if (currentFloor % 5 === 0 || currentRoom.roomType !== 'combat') {
log = [`🗿 ${roomTypeName} ${currentFloor} cleared by golems!`, ...log.slice(0, 49)];
// Log floor cleared to activity log
activityLog = addActivityLogEntry(state, 'floor_cleared',
`🗿 ${roomTypeName} ${currentFloor} cleared by golems!`,
{ floor: currentFloor }
);
}
}
@@ -3045,6 +3099,12 @@ export const useGameStore = create<GameStore>()(
golemancy: state.golemancy,
// Conversion drains tracking
conversionDrains: state.conversionDrains,
// Spire Mode state
clearedFloors: state.clearedFloors,
climbDirection: state.climbDirection,
isDescending: state.isDescending,
// Activity Log (for Spire Mode UI)
activityLog: state.activityLog,
}),
}
)
+36
View File
@@ -5,12 +5,40 @@ import type { ElementState } from './elements';
import type { SpellState } from './spells';
import type { EquipmentInstance, EnchantmentDesign, DesignProgress, PreparationProgress, ApplicationProgress, EquipmentCraftingProgress, EquipmentDef, BlueprintDef, LootInventory, EquipmentSpellState } from './equipment';
// ─── Activity Log Types ─────────────────────────────────────────────────
export type ActivityEventType =
| 'damage_dealt'
| 'enemy_defeated'
| 'floor_cleared'
| 'floor_transition'
| 'special_effect'
| 'dodge'
| 'armor_proc'
| 'spell_cast'
| 'golem_attack'
| 'puzzle_solved';
export interface ActivityLogEntry {
id: string; // Unique ID for React key
timestamp: number; // Game time (day + hour) when event occurred
eventType: ActivityEventType; // Type of combat event
message: string; // Human-readable message
details?: {
damage?: number;
enemyName?: string;
floor?: number;
spellName?: string;
effectName?: string;
};
}
// ─── Room and Enemy Types ─────────────────────────────────────────────────────
export type RoomType = 'combat' | 'puzzle' | 'swarm' | 'speed' | 'guardian';
export interface EnemyState {
id: string;
name: string; // Display name for the enemy
hp: number;
maxHP: number;
armor: number; // Damage reduction (0-1)
@@ -213,11 +241,19 @@ export interface GameState {
// Log
log: string[];
// Activity Log (for Spire Mode UI)
activityLog: ActivityLogEntry[];
// Loop insight (earned at end of current loop)
loopInsight: number;
// Spire Mode - simplified UI for climbing
spireMode: boolean;
// Spire climbing state
clearedFloors: Record<number, boolean>; // Track cleared floors for respawning
climbDirection: 'up' | 'down' | null; // Current climb direction
isDescending: boolean; // True when actively descending (prevents spam)
}
// ─── Action Types for Store ─────────────────────────────────────────────
+3 -1
View File
@@ -52,5 +52,7 @@ export type {
SummonedGolem,
GolemancyState,
GameState,
GameActionType
GameActionType,
ActivityEventType,
ActivityLogEntry,
} from './game';