Fix Bug 8: Replace direct setState calls with proper store actions in debug components
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 2m8s

- SkillDebug.tsx: Use useSkillStore.getState().incrementSkillLevel() and setSkillLevel() instead of direct setState
- ElementDebug.tsx: Use getState() for consistency
- AttunementDebug.tsx: When unlocking Enchanter, also unlock transference element
- GameStateDebug.tsx: Use proper store actions (debugSetFloor, resetFloorHP, debugSetTime) and fix Switch component usage
This commit is contained in:
2026-05-07 13:17:22 +02:00
parent 7851d8c7cb
commit 32a86c3e62
5 changed files with 114 additions and 149 deletions
+4
View File
@@ -459,11 +459,15 @@ Mana-Loop/
├── Caddyfile ├── Caddyfile
├── Dockerfile ├── Dockerfile
├── README.md ├── README.md
├── add_debugname.py
├── bun.lock ├── bun.lock
├── bunfig.toml ├── bunfig.toml
├── components.json ├── components.json
├── docker-compose.yml ├── docker-compose.yml
├── eslint.config.mjs ├── eslint.config.mjs
├── fix_remaining.py
├── fix_tabs.py
├── fix_tabs2.py
├── next.config.ts ├── next.config.ts
├── package-lock.json ├── package-lock.json
├── package.json ├── package.json
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Sparkles, Unlock } from 'lucide-react'; import { Sparkles, Unlock } from 'lucide-react';
import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements'; import { ATTUNEMENTS_DEF } from '@/lib/game/data/attunements';
import { useAttunementStore } from '@/lib/game/stores'; import { useAttunementStore } from '@/lib/game/stores';
import { useManaStore } from '@/lib/game/stores';
export function AttunementDebug() { export function AttunementDebug() {
const attunements = useAttunementStore((s) => s.attunements); const attunements = useAttunementStore((s) => s.attunements);
@@ -14,6 +15,10 @@ export function AttunementDebug() {
const handleUnlockAttunement = (id: string) => { const handleUnlockAttunement = (id: string) => {
if (debugUnlockAttunement) { if (debugUnlockAttunement) {
debugUnlockAttunement(id); debugUnlockAttunement(id);
// When unlocking Enchanter, also unlock the transference element
if (id === 'enchanter') {
useManaStore.getState().unlockElement('transference', 500);
}
} }
}; };
+4 -5
View File
@@ -8,16 +8,15 @@ import { ELEMENTS } from '@/lib/game/constants';
export function ElementDebug() { export function ElementDebug() {
const elements = useManaStore((s) => s.elements); const elements = useManaStore((s) => s.elements);
const unlockElement = useManaStore((s) => s.unlockElement);
const addElementMana = useManaStore((s) => s.addElementMana);
const handleUnlockElement = (element: string) => { const handleUnlockElement = (element: string) => {
unlockElement(element, 500); useManaStore.getState().unlockElement(element, 500);
}; };
const handleAddElementalMana = (element: string, amount: number) => { const handleAddElementalMana = (element: string, amount: number) => {
if (addElementMana) { const elem = elements?.[element];
addElementMana(element, amount, 100); if (elem?.unlocked) {
useManaStore.getState().addElementMana(element, amount, elem.max);
} }
}; };
+8 -7
View File
@@ -29,8 +29,9 @@ export function GameStateDebug() {
// Get actions from stores // Get actions from stores
const resetGame = useGameStore((s) => s.resetGame); const resetGame = useGameStore((s) => s.resetGame);
const setFloor = useCombatStore((s) => s.debugSetFloor); const debugSetFloor = useCombatStore((s) => s.debugSetFloor);
const resetHP = useCombatStore((s) => s.resetFloorHP); const resetFloorHP = useCombatStore((s) => s.resetFloorHP);
const debugSetTime = useCombatStore((s) => s.debugSetTime);
const handleReset = () => { const handleReset = () => {
if (confirmReset) { if (confirmReset) {
@@ -186,13 +187,13 @@ export function GameStateDebug() {
<Button size="sm" variant="outline" onClick={() => useGameStore.setState({ day: 1, hour: 0 })}> <Button size="sm" variant="outline" onClick={() => useGameStore.setState({ day: 1, hour: 0 })}>
Day 1 Day 1
</Button> </Button>
<Button size="sm" variant="outline" onClick={() => setTime?.(10, 0)}> <Button size="sm" variant="outline" onClick={() => debugSetTime?.(10, 0)}>
Day 10 Day 10
</Button> </Button>
<Button size="sm" variant="outline" onClick={() => setTime?.(20, 0)}> <Button size="sm" variant="outline" onClick={() => debugSetTime?.(20, 0)}>
Day 20 Day 20
</Button> </Button>
<Button size="sm" variant="outline" onClick={() => setTime?.(30, 0)}> <Button size="sm" variant="outline" onClick={() => debugSetTime?.(30, 0)}>
Day 30 Day 30
</Button> </Button>
</div> </div>
@@ -250,14 +251,14 @@ export function GameStateDebug() {
<Button <Button
size="sm" size="sm"
variant="outline" variant="outline"
onClick={() => setFloor?.(100)} onClick={() => debugSetFloor?.(100)}
> >
Skip to Floor 100 Skip to Floor 100
</Button> </Button>
<Button <Button
size="sm" size="sm"
variant="outline" variant="outline"
onClick={() => resetHP?.()} onClick={() => resetFloorHP?.()}
> >
Reset Floor HP Reset Floor HP
</Button> </Button>
+93 -137
View File
@@ -5,12 +5,54 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import { BookOpen } from 'lucide-react'; import { BookOpen } from 'lucide-react';
import { useSkillStore } from '@/lib/game/stores'; import { useSkillStore } from '@/lib/game/stores';
import { useManaStore } from '@/lib/game/stores';
export function SkillDebug() { export function SkillDebug() {
const skills = useSkillStore((s) => s.skills); const skills = useSkillStore((s) => s.skills);
const setSkills = useSkillStore.setState;
const setGameState = useSkillStore.setState; const incrementSkillLevel = (skillId: string) => {
useSkillStore.getState().incrementSkillLevel(skillId);
};
const setSkillLevel = (skillId: string, level: number) => {
useSkillStore.getState().setSkillLevel(skillId, level);
};
const unlockAllEffects = () => {
const effectIds = [
'spell_manaBolt', 'spell_manaStrike', 'spell_fireball', 'spell_emberShot',
'spell_waterJet', 'spell_iceShard', 'spell_gust', 'spell_windSlash',
'spell_stoneBullet', 'spell_rockSpike', 'spell_lightLance', 'spell_radiance',
'spell_shadowBolt', 'spell_darkPulse', 'spell_drain',
'spell_inferno', 'spell_flameWave', 'spell_tidalWave', 'spell_iceStorm',
'spell_hurricane', 'spell_windBlade', 'spell_earthquake', 'spell_stoneBarrage',
'spell_solarFlare', 'spell_divineSmite', 'spell_voidRift', 'spell_shadowStorm',
'spell_pyroclasm', 'spell_tsunami', 'spell_meteorStrike',
'spell_spark', 'spell_lightningBolt', 'spell_chainLightning',
'spell_stormCall', 'spell_thunderStrike',
'spell_metalShard', 'spell_ironFist', 'spell_steelTempest', 'spell_furnaceBlast',
'spell_sandBlast', 'spell_sandstorm', 'spell_desertWind', 'spell_duneCollapse',
'mana_cap_50', 'mana_cap_100', 'mana_regen_1', 'mana_regen_2', 'mana_regen_5',
'click_mana_1', 'click_mana_3',
'damage_5', 'damage_10', 'damage_pct_10', 'crit_5', 'attack_speed_10',
'meditate_10', 'study_10', 'insight_5',
'spell_echo_10', 'guardian_dmg_10', 'overpower_80',
'weapon_mana_cap_20', 'weapon_mana_cap_50', 'weapon_mana_cap_100',
'weapon_mana_regen_1', 'weapon_mana_regen_2', 'weapon_mana_regen_5',
'sword_fire', 'sword_frost', 'sword_lightning', 'sword_void'
];
useManaStore.setState((prev: any) => {
const currentEffects = prev.unlockedEffects || [];
const newEffects = [...currentEffects];
effectIds.forEach(id => {
if (!newEffects.includes(id)) {
newEffects.push(id);
}
});
return { ...prev, unlockedEffects: newEffects };
});
};
return ( return (
<Card className="bg-gray-900/80 border-gray-700 md:col-span-2"> <Card className="bg-gray-900/80 border-gray-700 md:col-span-2">
<CardHeader className="pb-2"> <CardHeader className="pb-2">
@@ -30,13 +72,12 @@ export function SkillDebug() {
variant="outline" variant="outline"
onClick={() => { onClick={() => {
// Level up all enchanting skills by 1 // Level up all enchanting skills by 1
setSkills((prev) => { const enchantSkills = ['enchanting', 'efficientEnchant', 'enchantSpeed', 'essenceRefining'];
const enchantSkills = ['enchanting', 'efficientEnchant', 'enchantSpeed', 'essenceRefining']; enchantSkills.forEach(skillId => {
const newSkills = { ...prev.skills }; const currentLevel = skills[skillId] || 0;
enchantSkills.forEach(skillId => { if (currentLevel < 10) {
newSkills[skillId] = Math.min((newSkills[skillId] || 0) + 1, 10); incrementSkillLevel(skillId);
}); }
return { ...prev, skills: newSkills };
}); });
}} }}
> >
@@ -47,13 +88,9 @@ export function SkillDebug() {
variant="outline" variant="outline"
onClick={() => { onClick={() => {
// Max all enchanting skills // Max all enchanting skills
setSkills((prev) => { const enchantSkills = ['enchanting', 'efficientEnchant', 'enchantSpeed', 'essenceRefining'];
const enchantSkills = ['enchanting', 'efficientEnchant', 'enchantSpeed', 'essenceRefining']; enchantSkills.forEach(skillId => {
const newSkills = { ...prev.skills }; setSkillLevel(skillId, 10);
enchantSkills.forEach(skillId => {
newSkills[skillId] = 10;
});
return { ...prev, skills: newSkills };
}); });
}} }}
> >
@@ -71,12 +108,11 @@ export function SkillDebug() {
variant="outline" variant="outline"
onClick={() => { onClick={() => {
const manaSkills = ['manaWell', 'manaFlow', 'manaOverflow', 'fireManaCap', 'waterManaCap', 'airManaCap', 'earthManaCap', 'lightManaCap', 'darkManaCap', 'deathManaCap', 'metalManaCap', 'sandManaCap', 'lightningManaCap', 'transferenceManaCap']; const manaSkills = ['manaWell', 'manaFlow', 'manaOverflow', 'fireManaCap', 'waterManaCap', 'airManaCap', 'earthManaCap', 'lightManaCap', 'darkManaCap', 'deathManaCap', 'metalManaCap', 'sandManaCap', 'lightningManaCap', 'transferenceManaCap'];
setSkills((prev) => { manaSkills.forEach(skillId => {
const newSkills = { ...prev.skills }; const currentLevel = skills[skillId] || 0;
manaSkills.forEach(skillId => { if (currentLevel < 10) {
newSkills[skillId] = Math.min((newSkills[skillId] || 0) + 1, 10); incrementSkillLevel(skillId);
}); }
return { ...prev, skills: newSkills };
}); });
}} }}
> >
@@ -87,12 +123,8 @@ export function SkillDebug() {
variant="outline" variant="outline"
onClick={() => { onClick={() => {
const manaSkills = ['manaWell', 'manaFlow', 'manaOverflow', 'fireManaCap', 'waterManaCap', 'airManaCap', 'earthManaCap', 'lightManaCap', 'darkManaCap', 'deathManaCap', 'metalManaCap', 'sandManaCap', 'lightningManaCap', 'transferenceManaCap']; const manaSkills = ['manaWell', 'manaFlow', 'manaOverflow', 'fireManaCap', 'waterManaCap', 'airManaCap', 'earthManaCap', 'lightManaCap', 'darkManaCap', 'deathManaCap', 'metalManaCap', 'sandManaCap', 'lightningManaCap', 'transferenceManaCap'];
setSkills((prev) => { manaSkills.forEach(skillId => {
const newSkills = { ...prev.skills }; setSkillLevel(skillId, 10);
manaSkills.forEach(skillId => {
newSkills[skillId] = 10;
});
return { ...prev, skills: newSkills };
}); });
}} }}
> >
@@ -110,12 +142,11 @@ export function SkillDebug() {
variant="outline" variant="outline"
onClick={() => { onClick={() => {
const studySkills = ['quickLearner', 'focusedMind', 'meditation', 'knowledgeRetention']; const studySkills = ['quickLearner', 'focusedMind', 'meditation', 'knowledgeRetention'];
setSkills((prev) => { studySkills.forEach(skillId => {
const newSkills = { ...prev.skills }; const currentLevel = skills[skillId] || 0;
studySkills.forEach(skillId => { if (currentLevel < 10) {
newSkills[skillId] = Math.min((newSkills[skillId] || 0) + 1, 10); incrementSkillLevel(skillId);
}); }
return { ...prev, skills: newSkills };
}); });
}} }}
> >
@@ -126,12 +157,8 @@ export function SkillDebug() {
variant="outline" variant="outline"
onClick={() => { onClick={() => {
const studySkills = ['quickLearner', 'focusedMind', 'meditation', 'knowledgeRetention']; const studySkills = ['quickLearner', 'focusedMind', 'meditation', 'knowledgeRetention'];
setSkills((prev) => { studySkills.forEach(skillId => {
const newSkills = { ...prev.skills }; setSkillLevel(skillId, 10);
studySkills.forEach(skillId => {
newSkills[skillId] = 10;
});
return { ...prev, skills: newSkills };
}); });
}} }}
> >
@@ -149,12 +176,11 @@ export function SkillDebug() {
variant="outline" variant="outline"
onClick={() => { onClick={() => {
const craftSkills = ['effCrafting', 'fieldRepair', 'elemCrafting']; const craftSkills = ['effCrafting', 'fieldRepair', 'elemCrafting'];
setSkills((prev) => { craftSkills.forEach(skillId => {
const newSkills = { ...prev.skills }; const currentLevel = skills[skillId] || 0;
craftSkills.forEach(skillId => { if (currentLevel < 10) {
newSkills[skillId] = Math.min((newSkills[skillId] || 0) + 1, 10); incrementSkillLevel(skillId);
}); }
return { ...prev, skills: newSkills };
}); });
}} }}
> >
@@ -165,12 +191,8 @@ export function SkillDebug() {
variant="outline" variant="outline"
onClick={() => { onClick={() => {
const craftSkills = ['effCrafting', 'fieldRepair', 'elemCrafting']; const craftSkills = ['effCrafting', 'fieldRepair', 'elemCrafting'];
setSkills((prev) => { craftSkills.forEach(skillId => {
const newSkills = { ...prev.skills }; setSkillLevel(skillId, 10);
craftSkills.forEach(skillId => {
newSkills[skillId] = 10;
});
return { ...prev, skills: newSkills };
}); });
}} }}
> >
@@ -187,22 +209,18 @@ export function SkillDebug() {
size="sm" size="sm"
variant="outline" variant="outline"
onClick={() => { onClick={() => {
setSkills((prev) => { const researchSkills = [
const researchSkills = [ 'researchManaSpells', 'researchFireSpells', 'researchWaterSpells',
'researchManaSpells', 'researchFireSpells', 'researchWaterSpells', 'researchAirSpells', 'researchEarthSpells', 'researchLightSpells',
'researchAirSpells', 'researchEarthSpells', 'researchLightSpells', 'researchDarkSpells', 'researchLifeDeathSpells',
'researchDarkSpells', 'researchLifeDeathSpells', 'researchAdvancedFire', 'researchAdvancedWater', 'researchAdvancedAir',
'researchAdvancedFire', 'researchAdvancedWater', 'researchAdvancedAir', 'researchAdvancedEarth', 'researchAdvancedLight', 'researchAdvancedDark',
'researchAdvancedEarth', 'researchAdvancedLight', 'researchAdvancedDark', 'researchMasterFire', 'researchMasterWater', 'researchMasterEarth',
'researchMasterFire', 'researchMasterWater', 'researchMasterEarth', 'researchDamageEffects', 'researchCombatEffects', 'researchManaEffects',
'researchDamageEffects', 'researchCombatEffects', 'researchManaEffects', 'researchAdvancedManaEffects', 'researchUtilityEffects'
'researchAdvancedManaEffects', 'researchUtilityEffects' ];
]; researchSkills.forEach(skillId => {
const newSkills = { ...prev.skills }; setSkillLevel(skillId, 1);
researchSkills.forEach(skillId => {
newSkills[skillId] = 1;
});
return { ...prev, skills: newSkills };
}); });
}} }}
> >
@@ -212,37 +230,7 @@ export function SkillDebug() {
size="sm" size="sm"
variant="outline" variant="outline"
onClick={() => { onClick={() => {
setGameState((prev: any) => { unlockAllEffects();
const effectIds = [
'spell_manaBolt', 'spell_manaStrike', 'spell_fireball', 'spell_emberShot',
'spell_waterJet', 'spell_iceShard', 'spell_gust', 'spell_windSlash',
'spell_stoneBullet', 'spell_rockSpike', 'spell_lightLance', 'spell_radiance',
'spell_shadowBolt', 'spell_darkPulse', 'spell_drain',
'spell_inferno', 'spell_flameWave', 'spell_tidalWave', 'spell_iceStorm',
'spell_hurricane', 'spell_windBlade', 'spell_earthquake', 'spell_stoneBarrage',
'spell_solarFlare', 'spell_divineSmite', 'spell_voidRift', 'spell_shadowStorm',
'spell_pyroclasm', 'spell_tsunami', 'spell_meteorStrike',
'spell_spark', 'spell_lightningBolt', 'spell_chainLightning',
'spell_stormCall', 'spell_thunderStrike',
'spell_metalShard', 'spell_ironFist', 'spell_steelTempest', 'spell_furnaceBlast',
'spell_sandBlast', 'spell_sandstorm', 'spell_desertWind', 'spell_duneCollapse',
'mana_cap_50', 'mana_cap_100', 'mana_regen_1', 'mana_regen_2', 'mana_regen_5',
'click_mana_1', 'click_mana_3',
'damage_5', 'damage_10', 'damage_pct_10', 'crit_5', 'attack_speed_10',
'meditate_10', 'study_10', 'insight_5',
'spell_echo_10', 'guardian_dmg_10', 'overpower_80',
'weapon_mana_cap_20', 'weapon_mana_cap_50', 'weapon_mana_cap_100',
'weapon_mana_regen_1', 'weapon_mana_regen_2', 'weapon_mana_regen_5',
'sword_fire', 'sword_frost', 'sword_lightning', 'sword_void'
];
const currentEffects = prev.unlockedEffects || [];
effectIds.forEach(id => {
if (!currentEffects.includes(id)) {
currentEffects.push(id);
}
});
return { ...prev, unlockedEffects: currentEffects };
});
}} }}
> >
Unlock All Effects Unlock All Effects
@@ -257,44 +245,12 @@ export function SkillDebug() {
size="sm" size="sm"
className="bg-purple-600 hover:bg-purple-700" className="bg-purple-600 hover:bg-purple-700"
onClick={() => { onClick={() => {
setSkills((prev) => { // Max all skills to level 10
const allEffectIds = [ Object.keys(skills).forEach(skillId => {
'spell_manaBolt', 'spell_manaStrike', 'spell_fireball', 'spell_emberShot', setSkillLevel(skillId, 10);
'spell_waterJet', 'spell_iceShard', 'spell_gust', 'spell_windSlash',
'spell_stoneBullet', 'spell_rockSpike', 'spell_lightLance', 'spell_radiance',
'spell_shadowBolt', 'spell_darkPulse', 'spell_drain',
'mana_cap_50', 'mana_cap_100', 'mana_regen_1', 'mana_regen_2', 'mana_regen_5',
'click_mana_1', 'click_mana_3', 'damage_5', 'damage_10', 'damage_pct_10',
'crit_5', 'attack_speed_10', 'meditate_10', 'study_10', 'insight_5',
'spell_echo_10', 'guardian_dmg_10', 'overpower_80'
];
const newSkills = { ...prev.skills };
Object.keys(newSkills).forEach(skillId => {
if ((newSkills[skillId] || 0) < 10) {
newSkills[skillId] = 10;
}
});
return { ...prev, skills: newSkills };
});
setGameState((prev: any) => {
const allEffectIds = [
'spell_manaBolt', 'spell_manaStrike', 'spell_fireball', 'spell_emberShot',
'spell_waterJet', 'spell_iceShard', 'spell_gust', 'spell_windSlash',
'spell_stoneBullet', 'spell_rockSpike', 'spell_lightLance', 'spell_radiance',
'spell_shadowBolt', 'spell_darkPulse', 'spell_drain',
'mana_cap_50', 'mana_cap_100', 'mana_regen_1', 'mana_regen_2', 'mana_regen_5',
'click_mana_1', 'click_mana_3', 'damage_5', 'damage_10', 'damage_pct_10',
'crit_5', 'attack_speed_10', 'meditate_10', 'study_10', 'insight_5',
'spell_echo_10', 'guardian_dmg_10', 'overpower_80'
];
const currentEffects = prev.unlockedEffects || [];
allEffectIds.forEach(id => {
if (!currentEffects.includes(id)) {
currentEffects.push(id);
}
});
return { ...prev, unlockedEffects: currentEffects };
}); });
// Unlock all effects
unlockAllEffects();
}} }}
> >
🚀 Max Everything 🚀 Max Everything