Phase 4: Combat special effects
This commit is contained in:
+48
-3
@@ -684,6 +684,10 @@ function makeInitial(overrides: Partial<GameState> = {}): GameState {
|
||||
totalDamageDealt: 0,
|
||||
totalCraftsCompleted: 0,
|
||||
|
||||
// Combat special effect tracking
|
||||
comboHitCount: 0, // Hit counter for COMBO_MASTER (every 5th attack)
|
||||
floorHitCount: 0, // Hit counter for current floor (for FIRST_STRIKE)
|
||||
|
||||
// New equipment system
|
||||
equippedInstances: startingEquipment.equippedInstances,
|
||||
equipmentInstances: startingEquipment.equipmentInstances,
|
||||
@@ -1013,7 +1017,9 @@ export const useGameStore = create<GameStore>()(
|
||||
}
|
||||
|
||||
// Combat - uses cast speed and spell casting
|
||||
let { currentFloor, floorHP, floorMaxHP, maxFloorReached, signedPacts, castProgress, currentRoom } = state;
|
||||
let { currentFloor, floorHP, floorMaxHP, maxFloorReached, signedPacts, castProgress, currentRoom, comboHitCount, floorHitCount } = state;
|
||||
comboHitCount = comboHitCount || 0;
|
||||
floorHitCount = floorHitCount || 0;
|
||||
const floorElement = getFloorElement(currentFloor);
|
||||
|
||||
// Handle puzzle rooms separately
|
||||
@@ -1120,14 +1126,32 @@ export const useGameStore = create<GameStore>()(
|
||||
const effectiveArmor = Math.max(0, enemy.armor - armorPierce);
|
||||
dmg *= (1 - effectiveArmor);
|
||||
|
||||
// Increment hit counters
|
||||
comboHitCount += 1;
|
||||
floorHitCount += 1;
|
||||
|
||||
// First Strike: +15% damage on first attack each floor
|
||||
if (hasSpecial(effects, SPECIAL_EFFECTS.FIRST_STRIKE) && floorHitCount === 1) {
|
||||
dmg *= 1.15;
|
||||
log = [`⚡ First Strike! +15% damage!`, ...log.slice(0, 49)];
|
||||
}
|
||||
|
||||
// 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)];
|
||||
}
|
||||
|
||||
// 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)];
|
||||
}
|
||||
|
||||
// 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)];
|
||||
}
|
||||
|
||||
// Spell echo - chance to cast again
|
||||
@@ -1153,6 +1177,14 @@ export const useGameStore = create<GameStore>()(
|
||||
if (allDead) {
|
||||
// Floor cleared
|
||||
const wasGuardian = GUARDIANS[currentFloor];
|
||||
|
||||
// Adrenaline Rush: Defeating enemy restores 5% mana
|
||||
if (hasSpecial(effects, SPECIAL_EFFECTS.ADRENALINE_RUSH)) {
|
||||
const manaRestore = Math.floor(maxMana * 0.05);
|
||||
rawMana = Math.min(rawMana + manaRestore, maxMana);
|
||||
log = [`💚 Adrenaline Rush! Restored ${manaRestore} mana!`, ...log.slice(0, 49)];
|
||||
}
|
||||
|
||||
if (wasGuardian && !signedPacts.includes(currentFloor)) {
|
||||
signedPacts = [...signedPacts, currentFloor];
|
||||
log = [`⚔️ ${wasGuardian.name} defeated! Pact signed! (${wasGuardian.pact}x)`, ...log.slice(0, 49)];
|
||||
@@ -1175,8 +1207,9 @@ export const useGameStore = create<GameStore>()(
|
||||
floorHP = currentRoom.enemies[0]?.hp || floorMaxHP;
|
||||
maxFloorReached = Math.max(maxFloorReached, currentFloor);
|
||||
|
||||
// Reset cast progress on floor change
|
||||
// Reset cast progress and floor hit counter on floor change
|
||||
castProgress = 0;
|
||||
floorHitCount = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1445,6 +1478,8 @@ export const useGameStore = create<GameStore>()(
|
||||
castProgress,
|
||||
golemancy,
|
||||
flowSurgeEndTime,
|
||||
comboHitCount,
|
||||
floorHitCount,
|
||||
...craftingUpdates,
|
||||
});
|
||||
},
|
||||
@@ -2449,7 +2484,7 @@ export const useGameStore = create<GameStore>()(
|
||||
}),
|
||||
{
|
||||
name: 'mana-loop-storage',
|
||||
version: 2,
|
||||
version: 3,
|
||||
migrate: (persistedState: unknown, version: number) => {
|
||||
const state = persistedState as Record<string, unknown>;
|
||||
// Migration from version 0/1 to version 2 - add missing fields
|
||||
@@ -2462,6 +2497,14 @@ export const useGameStore = create<GameStore>()(
|
||||
parallelStudyTarget: state.parallelStudyTarget ?? null,
|
||||
};
|
||||
}
|
||||
// Migration to version 3 - add combo hit counters
|
||||
if (version < 3) {
|
||||
return {
|
||||
...state,
|
||||
comboHitCount: state.comboHitCount ?? 0,
|
||||
floorHitCount: state.floorHitCount ?? 0,
|
||||
};
|
||||
}
|
||||
return state;
|
||||
},
|
||||
partialize: (state) => ({
|
||||
@@ -2493,6 +2536,8 @@ export const useGameStore = create<GameStore>()(
|
||||
totalSpellsCast: state.totalSpellsCast,
|
||||
totalDamageDealt: state.totalDamageDealt,
|
||||
totalCraftsCompleted: state.totalCraftsCompleted,
|
||||
comboHitCount: state.comboHitCount,
|
||||
floorHitCount: state.floorHitCount,
|
||||
insight: state.insight,
|
||||
totalInsight: state.totalInsight,
|
||||
prestigeUpgrades: state.prestigeUpgrades,
|
||||
|
||||
Reference in New Issue
Block a user