diff --git a/TODO.md b/TODO.md index bc64f0a..a8a9b73 100644 --- a/TODO.md +++ b/TODO.md @@ -1,10 +1,10 @@ # TODO -- [ ] Add react-router - [ ] Add redux -- [ ] Prevent reducing talent points on a row when it is a dependency for points already spent in the next row - [ ] Prevent reducing talent points on a talent that is a requirement for another talent with points in it - [ ] Talent tooltips -- [ ] Change class - [ ] Generate URL for chosen talents -- [ ] Responsive on mobile \ No newline at end of file +- [ ] Responsive on mobile +- [ ] Pretty ClassPicker +- [x] Add react-router +- [x] Prevent reducing talent points on a row when it is a dependency for points already spent in the next row \ No newline at end of file diff --git a/src/components/TalentSlot.tsx b/src/components/TalentSlot.tsx index 152f3c2..6707bbe 100644 --- a/src/components/TalentSlot.tsx +++ b/src/components/TalentSlot.tsx @@ -68,4 +68,4 @@ export const TalentSlot: FC = (props) => { TalentSlot.defaultProps = defaultProps -// ;(TalentSlot as any).whyDidYouRender = true \ No newline at end of file +;(TalentSlot as any).whyDidYouRender = true \ No newline at end of file diff --git a/src/data/talents.ts b/src/data/talents.ts index f1dc5b5..3cabed2 100644 --- a/src/data/talents.ts +++ b/src/data/talents.ts @@ -3744,9 +3744,14 @@ export const talentsBySpec: Root = { } } -export const talentToSpec: {[key: number]: number} = {} +export const talentsById: {[key: number]: TalentData} = {} +export const talentsBySpecArray: {[key: number]: TalentData[]} = {} +export const talentToSpec: {[key: number]: number} = {} + for (let specId in talentsBySpec) { for (let talentId in talentsBySpec[specId]) { + talentsById[talentId] = talentsBySpec[specId][talentId] + talentsBySpecArray[specId] = Object.values(talentsBySpec[specId]) talentToSpec[talentId] = parseInt(specId, 10) } } diff --git a/src/lib/tree.ts b/src/lib/tree.ts index 1f247de..e7e28fb 100644 --- a/src/lib/tree.ts +++ b/src/lib/tree.ts @@ -1,7 +1,8 @@ import { List, Map, fromJS } from 'immutable' -import { talentsBySpec, talentToSpec } from '../data/talents'; +import { talentsBySpec, talentToSpec, talentsById } from '../data/talents'; export const MAX_POINTS = 51 +export const MAX_ROWS = 7 /** * Returns the overall points spent in the tree. @@ -36,13 +37,18 @@ export function calcMeetsRequirements(talent: TalentData, known: Map, talent: TalentData): Map => { const currentPoints = known.get(talent.id, 0) - // Support for specific Talent dependency requirement. - if (talent.requires.length > 0 && !calcMeetsRequirements(talent, known)) { + // Reached the max rank? + if (currentPoints >= talent.ranks.length) { + return known + } + + // Spend a maximum of 51 points + if (calcAvailablePoints(known) === 0) { return known } - // Spend a maximum of 51 points - if (calcAvailablePoints(known) === 0) { + // Support for specific Talent dependency requirement. + if (talent.requires.length > 0 && !calcMeetsRequirements(talent, known)) { return known } @@ -52,11 +58,6 @@ export const addTalentPoint = (known: Map, talent: TalentData): if (requiredPoints > pointsInSpec) { return known } - - // Reached the max rank? - if (currentPoints >= talent.ranks.length) { - return known - } return known.set(talent.id, currentPoints + 1) } @@ -66,13 +67,41 @@ export const addTalentPoint = (known: Map, talent: TalentData): */ export const removeTalentPoint = (known: Map, talent: TalentData): Map => { const currentPoints = known.get(talent.id, 0) - - // TODO: We should prevent reducing talent points on a row when it is a dependency for points already spent in the next row. + const specId = talentToSpec[talent.id] - // Already no points for this talent + // No points to reduce for this talent if (currentPoints === 0) { return known } + + let highestRow = 0 + let cumulativePointsPerRow = {} + known.forEach((points, talentId) => { + const t = talentsBySpec[specId][talentId] + if (t) { + highestRow = t.row > highestRow ? t.row : highestRow + for (let row = t.row; row < MAX_ROWS; row++) { + cumulativePointsPerRow[row] = (cumulativePointsPerRow[row] || 0) + points + } + } + }) + + // Check if removing this talent would not break the requirements for talents spent in later rows + const pointsUntilHighestRow = cumulativePointsPerRow[highestRow - 1] + const targetPointsHighestRow = highestRow * 5 + if (talent.row < highestRow && pointsUntilHighestRow - 1 < targetPointsHighestRow) { + return known + } + + // TODO: Prevent if another talent depends on this + // const isDependency = known.reduce((prev, current, key) => { + // if (prev) return prev + // const t = talentsBySpec[specId][key] + // if (t.requires.length === 0) { + // return false + // } + // t.requires.map((d) => d.id === talent.id ? d : undefined) + // }, false) return currentPoints === 1 ? known.remove(talent.id)