"use client"; import { useMemo, useEffect } from 'react'; import { UseFormReturn } from 'react-hook-form'; import { z } from 'zod'; import { heroFormSchema } from '@/lib/validators'; import { Badge } from '@/components/ui/badge'; import { FormControl, FormField, FormItem, FormLabel, FormDescription } from '@/components/ui/form'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { ATTACK_TYPE_COST, COOLDOWN_TIERS, STAT_TIERS, TOTAL_POINTS } from '@/constants'; type FormSchemaType = z.infer; interface StatsSectionProps { form: UseFormReturn; } // Helper to find the cost (tier index) from a stat value const getStatCost = (stat: keyof typeof STAT_TIERS, value: number) => STAT_TIERS[stat].indexOf(value); export const StatsSection = ({ form }: StatsSectionProps) => { const watchedValues = form.watch(); const pointsSpent = useMemo(() => { let total = 0; const { heroHealth, heroSpeed, basicAttack } = watchedValues; // 1. Health, Speed, and Attack points total += getStatCost('Health', heroHealth); total += getStatCost('Speed', heroSpeed); let attackCost = getStatCost('Attack', basicAttack.damage); // 2. The 'Contact Tax' if (basicAttack.type === 'CONTACT') { attackCost += 1; } total += attackCost; // 3. Attack Type points total += ATTACK_TYPE_COST[basicAttack.type] || 0; // 4. Cooldown points if (basicAttack.type === 'MELEE') { total += COOLDOWN_TIERS.MELEE.find(t => t.value === basicAttack.cooldown)?.cost || 0; } else if (basicAttack.type === 'RANGED') { total += COOLDOWN_TIERS.RANGED.find(t => t.value === basicAttack.cooldown)?.cost || 0; } return total; }, [watchedValues]); // Effect to set a global form error if points are not exactly 12 useEffect(() => { if (pointsSpent !== TOTAL_POINTS) { form.setError('root.stats', { type: 'manual', message: `You must spend exactly ${TOTAL_POINTS} points. Currently spending ${pointsSpent}.` }); } else { form.clearErrors('root.stats'); } }, [pointsSpent, form]); const handleAttackTypeChange = (type: 'CONTACT' | 'MELEE' | 'RANGED') => { form.setValue('basicAttack.type', type, { shouldValidate: true }); // When changing type, reset cooldown to the cheapest valid option if (type === 'MELEE') { form.setValue('basicAttack.cooldown', COOLDOWN_TIERS.MELEE[0].value, { shouldValidate: true }); } else if (type === 'RANGED') { form.setValue('basicAttack.cooldown', COOLDOWN_TIERS.RANGED[0].value, { shouldValidate: true }); } else { // CONTACT form.setValue('basicAttack.cooldown', 0, { shouldValidate: true }); } } return (

Stats & Abilities

Points Spent: {pointsSpent} / {TOTAL_POINTS}
{form.formState.errors.root?.stats && (

{form.formState.errors.root.stats.message}

)}
{/* Tier Selectors for core stats */} ( Health ({field.value} HP) )}/> ( Speed ({field.value}x) )}/> ( Attack ({field.value} Dmg) {watchedValues.basicAttack.type === 'CONTACT' && +1 pt cost for Contact type.} )}/> {/* Attack Type & Cooldown */} ( Attack Type )}/> {watchedValues.basicAttack.type === 'MELEE' && ( <> ( Melee Cooldown )}/> ( Range (tiles) field.onChange(Number(e.target.value))} /> )}/> )} {watchedValues.basicAttack.type === 'RANGED' && ( ( Ranged Cooldown )}/> )}
); };