From 7b8b8d784cee83aa329f4950f3d0eb0d68ab1782 Mon Sep 17 00:00:00 2001 From: HuskyHsu Date: Wed, 17 Jan 2024 00:41:04 +0800 Subject: [PATCH] feat: add custom calc stat value --- src/pages/Pokemon/components/Statistic.tsx | 274 +++++++++++++++++++-- src/types/Pokemon.ts | 10 + 2 files changed, 260 insertions(+), 24 deletions(-) diff --git a/src/pages/Pokemon/components/Statistic.tsx b/src/pages/Pokemon/components/Statistic.tsx index 954af5a72..130ab0f9e 100644 --- a/src/pages/Pokemon/components/Statistic.tsx +++ b/src/pages/Pokemon/components/Statistic.tsx @@ -2,7 +2,7 @@ import { useState } from 'react'; import clsx from 'clsx'; import { RadarChart } from './RadarChart'; -import { FillType, FullPokemon } from '@/types/Pokemon'; +import { FillType, FullPokemon, BasePoint } from '@/types/Pokemon'; import { SubTitleSlide } from '@/newComponents/common'; type Props = { @@ -27,19 +27,103 @@ function calStatistic( return nature === 'up' ? Math.floor(value * 1.1) : Math.floor(value * 0.9); } +function updateBase(prev: BasePoint, key: string, value: number): BasePoint { + if (Number.isNaN(value)) { + value = 0; + } + + if (value < 0) { + value = 0; + } + + if (value > 252) { + value = 252; + } + + const preTotal = prev.Hp + prev.Atk + prev.Def + prev.SpA + prev.SpD + prev.Spe; + + if (preTotal - prev[key as keyof typeof prev] + value > 510) { + value = 510 - preTotal + prev[key as keyof typeof prev]; + } + + const newBase = { + ...prev, + [key as keyof typeof prev]: value, + }; + + return { + ...newBase, + Total: newBase.Hp + newBase.Atk + newBase.Def + newBase.SpA + newBase.SpD + newBase.Spe, + }; +} + +function updateIndividual(prev: BasePoint, key: string, value: number): BasePoint { + if (Number.isNaN(value)) { + value = 0; + } + + if (value < 0) { + value = 0; + } + + if (value > 31) { + value = 31; + } + + const newBase = { + ...prev, + [key as keyof typeof prev]: value, + }; + + return newBase; +} + +function updateNature(prev: BasePoint, key: string, value: number): BasePoint { + for (let curKey in prev) { + if (curKey === key) { + prev[curKey as keyof typeof prev] = prev[curKey as keyof typeof prev] === value ? 0 : value; + } else { + if (value > 0 && prev[curKey as keyof typeof prev] > 0) { + prev[curKey as keyof typeof prev] = 0; + } else if (value < 0 && prev[curKey as keyof typeof prev] < 0) { + prev[curKey as keyof typeof prev] = 0; + } + } + } + + return { ...prev }; +} + export function Statistic({ pokemon }: Props) { const [lv, setLv] = useState(75); - const [targetSpe, setTargetSpe] = useState( - calStatistic(pokemon.baseStats[5], 31, 0, lv, false, undefined) - 1 - ); + const [customBase, setCustomBase] = useState({ + Hp: 0, + Atk: 0, + Def: 0, + SpA: 0, + SpD: 0, + Spe: 0, + Total: 0, + }); + const [customIndividual, setcustomIndividual] = useState({ + Hp: 31, + Atk: 31, + Def: 31, + SpA: 31, + SpD: 31, + Spe: 31, + Total: 0, + }); - const speEv = Array(253) - .fill(0) - .map((_, i) => i) - .map((ev) => { - return calStatistic(pokemon.baseStats[5], 31, ev, lv, false, undefined); - }) - .findIndex((val) => val > targetSpe); + const [nature, setNature] = useState({ + Hp: 0, + Atk: 0, + Def: 0, + SpA: 0, + SpD: 0, + Spe: 0, + Total: 0, + }); const cases = [ { name: '最高', individual: 31, base: 252, nature: 'up' }, @@ -104,21 +188,163 @@ export function Statistic({ pokemon }: Props) { ))} ))} + + 自訂 + {['Hp', 'Atk', 'Def', 'SpA', 'SpD', 'Spe'].map((key, i) => { + return ( + + {calStatistic( + pokemon.baseStats[i], + customIndividual[key as keyof typeof customIndividual], + customBase[key as keyof typeof customBase], + lv, + i === 0, + nature[key as keyof typeof nature] === 0 + ? undefined + : nature[key as keyof typeof nature] > 0 + ? 'up' + : 'down' + )} + + ); + })} + - setTargetSpe(parseInt(e.target.value))} - /> -

- 若對手的速度{targetSpe} ,需要{speEv}點速度努力值才能先攻 - (同等級下,我方個體值滿,且無性格影響下) -

+
+ + + + + + {['Hp', '攻擊', '防禦', '特攻', '特防', '速度'].map((type) => ( + + ))} + + + + + + + + + {['Hp', 'Atk', 'Def', 'SpA', 'SpD', 'Spe'].map((key) => { + return ( + + ); + })} + + + + + + + {['Hp', 'Atk', 'Def', 'SpA', 'SpD', 'Spe'].map((key) => { + return ( + + ); + })} + + + + + + + ); + })} + + + + + + + ); + })} + + +
+ {} + + {type} +
個體值
+ { + ['Hp', 'Atk', 'Def', 'SpA', 'SpD', 'Spe'].filter((key) => { + return customIndividual[key as keyof typeof customIndividual] === 31; + }).length + } + v + + { + setcustomIndividual((prev) => { + return updateIndividual(prev, key, Number(e.target.value)); + }); + }} + /> +
努力值
{customBase.Total} + { + setCustomBase((prev) => { + return updateBase(prev, key, Number(e.target.value)); + }); + }} + /> +
性格⇧
+ + {['Atk', 'Def', 'SpA', 'SpD', 'Spe'].map((key) => { + const value = nature[key as keyof typeof nature] > 0 ? '+' : ''; + return ( + + { + setNature((prev) => { + return updateNature(prev, key, 1); + }); + }} + /> +
性格⇩
+ + {['Atk', 'Def', 'SpA', 'SpD', 'Spe'].map((key) => { + const value = nature[key as keyof typeof nature] < 0 ? '-' : ''; + return ( + + { + setNature((prev) => { + return updateNature(prev, key, -1); + }); + }} + /> +
+
  • 最高:個體值最大、努力值滿、性格⇧
  • diff --git a/src/types/Pokemon.ts b/src/types/Pokemon.ts index 43e25c3f4..45e6c5137 100644 --- a/src/types/Pokemon.ts +++ b/src/types/Pokemon.ts @@ -48,6 +48,16 @@ export enum EVIndex { Spe = 5, } +export type BasePoint = { + Hp: number; + Atk: number; + Def: number; + SpA: number; + SpD: number; + Spe: number; + Total: number; +}; + export enum EVName { 'HP' = 'HP', 'Atk' = '攻擊',