diff --git a/frontend/src/second-edition/components/HarcosFegyverSpec.tsx b/frontend/src/second-edition/components/HarcosFegyverSpec.tsx index 4053dc7..ec78547 100644 --- a/frontend/src/second-edition/components/HarcosFegyverSpec.tsx +++ b/frontend/src/second-edition/components/HarcosFegyverSpec.tsx @@ -8,21 +8,23 @@ import {AppDispatch, RootState} from "../../store"; import {characterSelector, setHarcosSpecialization} from "../domain-models/characterSlice"; function HarcosFegyverSpecializacio(props: { - szint: number + harcosSzint: number, + karakterSzint: number, }) { const { - szint + harcosSzint, + karakterSzint, } = props const dispatch = useDispatch.withTypes()() const character = useSelector.withTypes()(characterSelector) - const specialization = character.szintlepesek[szint-1].harcosFegyver || 'kard_hosszu' + const specialization = character.szintlepesek[karakterSzint-1]?.harcosFegyver || 'kard_hosszu' const existingSpecializations = character.szintlepesek.filter(x => x.harcosFegyver != null).map(x => x.harcosFegyver! as string) - const changeSpecialization = (specialization: string) => dispatch(setHarcosSpecialization({szint, fegyver: specialization})) + const changeSpecialization = (specialization: string) => dispatch(setHarcosSpecialization({szint: karakterSzint, fegyver: specialization})) const fegyver = GetFegyver(specialization) const availableFegyverek = AllowedFegyver(Osztaly2E.Harcos) - const pickableFegyverek = availableFegyverek.filter(f => f.Id === specialization || existingSpecializations.filter(x => x === f.Id).length < (szint < 9 ? 1 : 2)) + const pickableFegyverek = availableFegyverek.filter(f => f.Id === specialization || existingSpecializations.filter(x => x === f.Id).length < (harcosSzint < 9 ? 1 : 2)) return <> @@ -32,7 +34,7 @@ function HarcosFegyverSpecializacio(props: { fegyverek={pickableFegyverek} selectedId={specialization} onChange={changeSpecialization} - dataTestId={"harcos-specialization-" + szint} + dataTestId={"harcos-specialization-" + karakterSzint} /> {fegyver == null && Ismeretlen fegyver: {specialization}} diff --git a/frontend/src/second-edition/components/LevelUps.test.tsx b/frontend/src/second-edition/components/LevelUps.test.tsx new file mode 100644 index 0000000..aaebc6f --- /dev/null +++ b/frontend/src/second-edition/components/LevelUps.test.tsx @@ -0,0 +1,248 @@ +import React from "react"; +import {fireEvent, render} from "@testing-library/react"; +import {configureStore} from "@reduxjs/toolkit"; +import {Provider} from "react-redux"; +import LevelUps from "./LevelUps"; +import userReducer from "../../shared/domain-models/userSlice"; +import characterReducer, {setCharacter} from "../domain-models/characterSlice"; +import {AllowedFegyver} from "../domain-models/allowed-fegyver"; +import {Osztaly2E} from "../domain-models/osztaly2E"; +import {ChangeOsztalyAtSzint, DefaultKarakter, Karakter2E} from "../domain-models/karakter2E"; +import {LevelUp} from "../domain-models/szintlepes"; +import {GetAvailableKepzettsegek} from "../domain-models/kepzettsegek2E"; + +function applyLevelUp(karakter: Karakter2E): Karakter2E { + let next: Karakter2E | undefined; + LevelUp(karakter, updated => { + next = updated; + }); + expect(next).toBeDefined(); + return next as Karakter2E; +} + +describe("LevelUps Harcos specialization indexing", () => { + it("updates specialization on the selected character level for multiclass", async () => { + const level1Tolvaj: Karakter2E = { + ...DefaultKarakter, + szint: 1, + szintlepesek: [{ + osztaly: Osztaly2E.Tolvaj, + HProll: 6, + }], + tolvajKepzettsegek: [], + varazslatok: [], + }; + + const level2Auto = applyLevelUp(level1Tolvaj); + const karakter = ChangeOsztalyAtSzint(level2Auto, Osztaly2E.Harcos, 2); + + const store = configureStore({ + reducer: { + user: userReducer, + character2E: characterReducer, + }, + }); + store.dispatch(setCharacter(karakter)); + + const sut = render( + + store.dispatch(setCharacter(updated))} + /> + + ); + + const selector = await sut.findByTestId("harcos-specialization-2"); + + const currentSpec = karakter.szintlepesek[1]?.harcosFegyver; + const nextSpec = AllowedFegyver(Osztaly2E.Harcos) + .map(x => x.Id) + .find(id => id !== currentSpec); + + expect(nextSpec).toBeDefined(); + fireEvent.change(selector, {target: {value: nextSpec as string}}); + + const stateAfter = store.getState().character2E; + expect(stateAfter.szintlepesek[0]?.harcosFegyver).toBeUndefined(); + expect(stateAfter.szintlepesek[1]?.harcosFegyver).toBe(nextSpec); + }); + + it("does not render tulajdonsag selector at level 4 when all abilities are maxed", () => { + const maxedCharacter: Karakter2E = { + ...DefaultKarakter, + szint: 1, + tulajdonsagok: { + t_ero: 18, + t_ugy: 18, + t_egs: 18, + t_int: 18, + t_bol: 18, + t_kar: 18, + }, + szintlepesek: [{ + osztaly: Osztaly2E.Pap, + HProll: 8, + }], + tolvajKepzettsegek: [], + varazslatok: [], + }; + + const level2 = applyLevelUp(maxedCharacter); + const level3 = applyLevelUp(level2); + const level4 = applyLevelUp(level3); + + expect(level4.szintlepesek[3]?.tulajdonsagNoveles).toBeUndefined(); + + const store = configureStore({ + reducer: { + user: userReducer, + character2E: characterReducer, + }, + }); + store.dispatch(setCharacter(level4)); + + const sut = render( + + store.dispatch(setCharacter(updated))} + /> + + ); + + expect(sut.queryByTestId("tulajdonsag-4")).toBeNull(); + }); + + it("does not render kaloz krit selector when tengeresz milestone exists but krit is missing", () => { + const inconsistentTengeresz: Karakter2E = { + ...DefaultKarakter, + szint: 3, + szintlepesek: [ + { + osztaly: Osztaly2E.Tengeresz, + HProll: 10, + }, + { + osztaly: Osztaly2E.Tengeresz, + HProll: 5, + }, + { + osztaly: Osztaly2E.Tengeresz, + HProll: 7, + } + ], + tolvajKepzettsegek: [], + varazslatok: [], + }; + + const store = configureStore({ + reducer: { + user: userReducer, + character2E: characterReducer, + }, + }); + store.dispatch(setCharacter(inconsistentTengeresz)); + + const sut = render( + + store.dispatch(setCharacter(updated))} + /> + + ); + + expect(sut.queryByTestId("kaloz-krit-3")).toBeNull(); + }); + + it("shows and updates Tolvaj extra skill on multiclass Tolvaj level 5", async () => { + const multiclassTolvaj: Karakter2E = { + ...DefaultKarakter, + szint: 6, + szintlepesek: [ + { osztaly: Osztaly2E.Tolvaj, HProll: 6 }, + { osztaly: Osztaly2E.Harcos, HProll: 10 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 4 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 5 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 6 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 3, tolvajExtraKepzettseg: "k_meregkeveres" }, + ], + tolvajKepzettsegek: ["k_alcazas", "k_csapdak", "k_egyensulyozas", "k_hamisitas"], + varazslatok: [], + }; + + const store = configureStore({ + reducer: { + user: userReducer, + character2E: characterReducer, + }, + }); + store.dispatch(setCharacter(multiclassTolvaj)); + + const sut = render( + + store.dispatch(setCharacter(updated))} + /> + + ); + + const selector = await sut.findByTestId("tolvaj-extra-kepzettseg-6"); + const nextKepzettseg = GetAvailableKepzettsegek(multiclassTolvaj) + .map(x => x.Id) + .find(id => id !== multiclassTolvaj.szintlepesek[5]?.tolvajExtraKepzettseg); + + expect(nextKepzettseg).toBeDefined(); + fireEvent.change(selector, {target: {value: nextKepzettseg as string}}); + + const stateAfter = store.getState().character2E; + expect(stateAfter.szintlepesek[5]?.tolvajExtraKepzettseg).toBe(nextKepzettseg); + expect(stateAfter.szintlepesek[4]?.tolvajExtraKepzettseg).toBeUndefined(); + }); + + it("at Tolvaj level 9 selector includes class-restricted non-Tolvaj skills", async () => { + const tolvajLevel9: Karakter2E = { + ...DefaultKarakter, + szint: 9, + szintlepesek: [ + { osztaly: Osztaly2E.Tolvaj, HProll: 6 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 5 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 4 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 3 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 2, tolvajExtraKepzettseg: "k_meregkeveres" }, + { osztaly: Osztaly2E.Tolvaj, HProll: 4 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 5 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 3 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 6, tolvajExtraKepzettseg: "k_alkimia" }, + ], + tolvajKepzettsegek: ["k_alcazas", "k_csapdak", "k_egyensulyozas", "k_hamisitas"], + varazslatok: [], + }; + + const store = configureStore({ + reducer: { + user: userReducer, + character2E: characterReducer, + }, + }); + store.dispatch(setCharacter(tolvajLevel9)); + + const sut = render( + + store.dispatch(setCharacter(updated))} + /> + + ); + + const selector = await sut.findByTestId("tolvaj-extra-kepzettseg-9"); + const arcaneOption = selector.querySelector('option[value="k_csillagjoslas"]'); + expect(arcaneOption).not.toBeNull(); + + fireEvent.change(selector, {target: {value: "k_csillagjoslas"}}); + expect(store.getState().character2E.szintlepesek[8]?.tolvajExtraKepzettseg).toBe("k_csillagjoslas"); + }); +}); diff --git a/frontend/src/second-edition/components/LevelUps.tsx b/frontend/src/second-edition/components/LevelUps.tsx index 18330c5..0e60fba 100644 --- a/frontend/src/second-edition/components/LevelUps.tsx +++ b/frontend/src/second-edition/components/LevelUps.tsx @@ -41,6 +41,8 @@ function LevelUp(props: { const kalozSzint = classLevels[Osztaly2E.Tengeresz] const tolvajSzint = classLevels[Osztaly2E.Tolvaj] const szintlepes = karakter.szintlepesek[szint-1]; + const tulajdonsagNoveles = szintlepes?.tulajdonsagNoveles; + const kalozKritikus = szintlepes?.kalozKritikus; return
@@ -54,10 +56,10 @@ function LevelUp(props: { osztalySzint={classLevels[osztaly]} dataTestId={`osztaly-${szint}`} />} - {szint % 4 === 0 && + {szint % 4 === 0 && tulajdonsagNoveles != null && } @@ -69,12 +71,13 @@ function LevelUp(props: { /> {osztaly === Osztaly2E.Harcos && harcosSzint % 2 === 1 && } - {osztaly === Osztaly2E.Tengeresz && kalozSzint % 3 === 0 && + {osztaly === Osztaly2E.Tengeresz && kalozSzint % 3 === 0 && kalozKritikus != null && x.kalozKritikus)} changeKrit={changeKalozKritikus} szint={kalozSzint} @@ -82,12 +85,17 @@ function LevelUp(props: { } {osztaly === Osztaly2E.Tolvaj && (tolvajSzint === 5 || tolvajSzint === 9) - && szintlepes.tolvajExtraKepzettseg != null && + && szintlepes?.tolvajExtraKepzettseg != null &&
@@ -100,16 +108,19 @@ export function LevelUps(props: {karakter: Karakter2E, changeKarakter: (inputs: const {karakter, changeKarakter} = props; const tulajdonsagokAtSzint = (szint: number) => TulajdonsagokTotal({...karakter, szintlepesek: karakter.szintlepesek.slice(0, szint)}) + const szintlepesAt = (szint: number) => karakter.szintlepesek[szint-1]! const changeRolledHPAtSzint = (szint: number) => (newHProll: number) => { - changeKarakter({...karakter, szintlepesek: arraySetN(karakter.szintlepesek, szint-1, {...karakter.szintlepesek[szint-1], HProll: newHProll})}) + const szintlepes = szintlepesAt(szint) + changeKarakter({...karakter, szintlepesek: arraySetN(karakter.szintlepesek, szint-1, {...szintlepes, HProll: newHProll})}) console.log(karakter) } const changeTulajdonsagNovelesAtSzint = (szint: number) => { return (t: Tulajdonsag2E) => { + const szintlepes = szintlepesAt(szint) changeKarakter({...karakter, szintlepesek: arraySetN(karakter.szintlepesek, szint-1, { - ...karakter.szintlepesek[szint-1], + ...szintlepes, tulajdonsagNoveles: t }) }) @@ -118,10 +129,11 @@ export function LevelUps(props: {karakter: Karakter2E, changeKarakter: (inputs: const changeKalozKritikusAtSzint = (szint: number) => { return (krit: string) => { + const szintlepes = szintlepesAt(szint) changeKarakter({ ...karakter, szintlepesek: arraySetN(karakter.szintlepesek, szint-1, { - ...karakter.szintlepesek[szint-1], + ...szintlepes, kalozKritikus: krit }) }) @@ -130,10 +142,11 @@ export function LevelUps(props: {karakter: Karakter2E, changeKarakter: (inputs: const changeExtraTolvajKepzettseg = (szint: number) => { return (k: KepzettsegId) => { + const szintlepes = szintlepesAt(szint) changeKarakter({ ...karakter, szintlepesek: arraySetN(karakter.szintlepesek, szint-1, { - ...karakter.szintlepesek[szint-1], + ...szintlepes, tolvajExtraKepzettseg: k, }) }) @@ -144,10 +157,13 @@ export function LevelUps(props: {karakter: Karakter2E, changeKarakter: (inputs: return <> {levels.slice(1).map(szint => + { + const szintlepes = szintlepesAt(szint) + return ( changeKarakter(ChangeOsztalyAtSzint(karakter, o, szint))} changeExtraTolvajKepzettseg={changeExtraTolvajKepzettseg(szint)} /> + ) + } )} } diff --git a/frontend/src/second-edition/domain-models/karakter2E.ts b/frontend/src/second-edition/domain-models/karakter2E.ts index d16fae4..6357d36 100644 --- a/frontend/src/second-edition/domain-models/karakter2E.ts +++ b/frontend/src/second-edition/domain-models/karakter2E.ts @@ -9,6 +9,7 @@ import {AllowedFegyver} from "./allowed-fegyver"; import {BaseHP} from "./masodlagos_ertekek"; import {dAny} from "../../shared/domain-models/kockak"; import {KarakterVarazslat} from "./varazslat"; +import {GetAvailableKepzettsegek} from "./kepzettsegek2E"; export interface Karakter2E { id?: string, @@ -51,13 +52,15 @@ export const DefaultKarakter: Karakter2E = { varazslatok: [], } -function setOsztalyForSzintLepes(szintlepesek: Szintlepes[], osztaly: Osztaly2E, szint: number): Szintlepes[] { +function setOsztalyForSzintLepes(karakter: Karakter2E, osztaly: Osztaly2E, szint: number): Szintlepes[] { + const szintlepesek = karakter.szintlepesek const prev = szintlepesek.slice(0, szint-1) const current : Szintlepes = { ...szintlepesek[szint-1], osztaly, harcosFegyver: undefined, - kalozKritikus: undefined + kalozKritikus: undefined, + tolvajExtraKepzettseg: undefined, } const tail = szintlepesek.slice(szint).map(x => {return {...x}}) @@ -117,6 +120,39 @@ function setOsztalyForSzintLepes(szintlepesek: Szintlepes[], osztaly: Osztaly2E, tail[i].kalozKritikus = kalozKritAtSzint(kalozSzint) } } + + let tolvajSzint = prev.filter(x => x.osztaly === Osztaly2E.Tolvaj).length + const existingTolvajExtraKepzettsegek = szintlepesek + .map(x => x.tolvajExtraKepzettseg) + .filter(x => x != null) as KepzettsegId[] + const tolvajExtraKepzettsegAtSzint = (tSzint: number, atLevelSzintlepesek: Szintlepes[]): (KepzettsegId | undefined) => { + if (tSzint !== 5 && tSzint !== 9) { + return undefined + } + const extraIndex = tSzint === 5 ? 0 : 1 + if (existingTolvajExtraKepzettsegek.length > extraIndex) { + return existingTolvajExtraKepzettsegek[extraIndex] + } + return GetAvailableKepzettsegek({ + szintlepesek: atLevelSzintlepesek, + faj: karakter.faj, + kepzettsegek: karakter.kepzettsegek, + tolvajKepzettsegek: karakter.tolvajKepzettsegek, + }, { + ignoreClassRestrictions: tSzint === 9, + })[0]?.Id + } + + if (osztaly === Osztaly2E.Tolvaj) { + tolvajSzint++ + current.tolvajExtraKepzettseg = tolvajExtraKepzettsegAtSzint(tolvajSzint, [...prev, current]) + } + for (let i = 0; i < tail.length; i++) { + if (tail[i].osztaly === Osztaly2E.Tolvaj) { + tolvajSzint++ + tail[i].tolvajExtraKepzettseg = tolvajExtraKepzettsegAtSzint(tolvajSzint, [...prev, current, ...tail.slice(0, i+1)]) + } + } const HD = BaseHP(osztaly) if (szint === 1) { @@ -138,6 +174,6 @@ export function ChangeLvl1Osztaly(karakter: Karakter2E, osztaly: Osztaly2E): Kar export function ChangeOsztalyAtSzint(karakter: Karakter2E, osztaly: Osztaly2E, szint: number): Karakter2E { return { ...karakter, - szintlepesek: setOsztalyForSzintLepes(karakter.szintlepesek, osztaly, szint) + szintlepesek: setOsztalyForSzintLepes(karakter, osztaly, szint) } } diff --git a/frontend/src/second-edition/domain-models/kepzettsegek2E.test.ts b/frontend/src/second-edition/domain-models/kepzettsegek2E.test.ts index 30471b6..be0eb93 100644 --- a/frontend/src/second-edition/domain-models/kepzettsegek2E.test.ts +++ b/frontend/src/second-edition/domain-models/kepzettsegek2E.test.ts @@ -106,6 +106,28 @@ describe("Kepzettsegek 2E", () => { const actual = GetAvailableKepzettsegek(karakter) expect(actual).not.toContain(Kepzettsegek.k_meregkeveres) }) + + test("at Tolvaj level 9 extra skill can include class-restricted non-Tolvaj skills", () => { + const karakter = { + ...DefaultKarakter, + szintlepesek: [ + { osztaly: Osztaly2E.Tolvaj, HProll: 6, }, + { osztaly: Osztaly2E.Tolvaj, HProll: 6, }, + { osztaly: Osztaly2E.Tolvaj, HProll: 6, }, + { osztaly: Osztaly2E.Tolvaj, HProll: 6, tulajdonsagNoveles: Tulajdonsag2E.Ugyesseg }, + { osztaly: Osztaly2E.Tolvaj, HProll: 6, tolvajExtraKepzettseg: Kepzettsegek.k_meregkeveres.Id }, + { osztaly: Osztaly2E.Tolvaj, HProll: 6, }, + { osztaly: Osztaly2E.Tolvaj, HProll: 6, }, + { osztaly: Osztaly2E.Tolvaj, HProll: 6, }, + ] + } + + const restricted = GetAvailableKepzettsegek(karakter) + expect(restricted).not.toContain(Kepzettsegek.k_csillagjoslas) + + const unrestricted = GetAvailableKepzettsegek(karakter, { ignoreClassRestrictions: true }) + expect(unrestricted).toContain(Kepzettsegek.k_csillagjoslas) + }) }) test("multiclass characters get access to kepzettsegek from all classes", () => { const karakter = { diff --git a/frontend/src/second-edition/domain-models/kepzettsegek2E.ts b/frontend/src/second-edition/domain-models/kepzettsegek2E.ts index 96fa52f..37a0e93 100644 --- a/frontend/src/second-edition/domain-models/kepzettsegek2E.ts +++ b/frontend/src/second-edition/domain-models/kepzettsegek2E.ts @@ -27,9 +27,15 @@ export function GetNumberOfKepzettsegek(t_int: number, faj: Faj2E, max: number = return numberOfKepzettseg; } -export function GetAvailableKepzettsegek(karakter: Pick): Kepzettseg[] { +export function GetAvailableKepzettsegek( + karakter: Pick, + options?: { ignoreClassRestrictions?: boolean } +): Kepzettseg[] { const osztalyok = new Set(karakter.szintlepesek.map(x => x.osztaly)) - const availableKepzettsegek = availableKezpettsegListFajjal(karakter.faj, ...osztalyok) + const baseKepzettsegList = options?.ignoreClassRestrictions + ? KepzettsegLista + : availableKezpettsegListFajjal(karakter.faj, ...osztalyok) + const availableKepzettsegek = baseKepzettsegList .filter(k => !karakter.kepzettsegek.includes(k.Id)) if (!osztalyok.has(Osztaly2E.Tolvaj)) { diff --git a/frontend/src/second-edition/domain-models/szintlepes.multiclass.test.ts b/frontend/src/second-edition/domain-models/szintlepes.multiclass.test.ts new file mode 100644 index 0000000..339395c --- /dev/null +++ b/frontend/src/second-edition/domain-models/szintlepes.multiclass.test.ts @@ -0,0 +1,151 @@ +import {ChangeOsztalyAtSzint, DefaultKarakter, Karakter2E} from "./karakter2E"; +import {Osztaly2E} from "./osztaly2E"; +import {LevelUp} from "./szintlepes"; + +function applyLevelUp(karakter: Karakter2E): Karakter2E { + let next: Karakter2E | undefined; + LevelUp(karakter, updated => { + next = updated; + }); + expect(next).toBeDefined(); + return next as Karakter2E; +} + +function level1Tolvaj(): Karakter2E { + return { + ...DefaultKarakter, + szint: 1, + szintlepesek: [{ + osztaly: Osztaly2E.Tolvaj, + HProll: 6, + }], + tolvajKepzettsegek: [], + varazslatok: [], + }; +} + +describe("Harcos specialization in multiclass level-ups", () => { + it("adds a specialization when first Harcos level is gained at character level 2", () => { + const afterLevel2 = applyLevelUp(level1Tolvaj()); + const multiclassed = ChangeOsztalyAtSzint(afterLevel2, Osztaly2E.Harcos, 2); + + const secondLevel = multiclassed.szintlepesek[1]; + expect(secondLevel?.osztaly).toBe(Osztaly2E.Harcos); + expect(secondLevel?.harcosFegyver).toBeDefined(); + }); + + it("does not add a specialization on even Harcos class level", () => { + const afterLevel2 = applyLevelUp(level1Tolvaj()); + const multiclassed = ChangeOsztalyAtSzint(afterLevel2, Osztaly2E.Harcos, 2); + const afterLevel3 = applyLevelUp(multiclassed); + + const thirdLevel = afterLevel3.szintlepesek[2]; + expect(thirdLevel?.osztaly).toBe(Osztaly2E.Harcos); + expect(thirdLevel?.harcosFegyver).toBeUndefined(); + }); + + it("adds the next specialization on odd Harcos class level after multiclass", () => { + const afterLevel2 = applyLevelUp(level1Tolvaj()); + const multiclassed = ChangeOsztalyAtSzint(afterLevel2, Osztaly2E.Harcos, 2); + const afterLevel3 = applyLevelUp(multiclassed); + const afterLevel4 = applyLevelUp(afterLevel3); + + const firstHarcosSpec = multiclassed.szintlepesek[1]?.harcosFegyver; + const thirdHarcosLevelSpec = afterLevel4.szintlepesek[3]?.harcosFegyver; + + expect(firstHarcosSpec).toBeDefined(); + expect(thirdHarcosLevelSpec).toBeDefined(); + expect(thirdHarcosLevelSpec).not.toBe(firstHarcosSpec); + }); +}); + +describe("Tolvaj extra skill in multiclass level-ups", () => { + it("adds extra skill when Tolvaj class reaches level 5 at higher character level", () => { + const karakter: Karakter2E = { + ...DefaultKarakter, + szint: 5, + szintlepesek: [ + { osztaly: Osztaly2E.Tolvaj, HProll: 6 }, + { osztaly: Osztaly2E.Harcos, HProll: 10 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 4 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 5 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 3 }, + ], + tolvajKepzettsegek: ["k_alcazas", "k_csapdak", "k_egyensulyozas", "k_hamisitas"], + varazslatok: [], + }; + + const afterLevel6 = applyLevelUp(karakter); + const sixthLevel = afterLevel6.szintlepesek[5]; + + expect(sixthLevel?.osztaly).toBe(Osztaly2E.Tolvaj); + expect(sixthLevel?.tolvajExtraKepzettseg).toBeDefined(); + }); + + it("recomputes missing extra skill when class change makes current level Tolvaj level 5", () => { + const karakter: Karakter2E = { + ...DefaultKarakter, + szint: 5, + szintlepesek: [ + { osztaly: Osztaly2E.Tolvaj, HProll: 6 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 5 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 4 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 3 }, + { osztaly: Osztaly2E.Harcos, HProll: 8 }, + ], + tolvajKepzettsegek: ["k_alcazas", "k_csapdak", "k_egyensulyozas", "k_hamisitas"], + varazslatok: [], + }; + + const changed = ChangeOsztalyAtSzint(karakter, Osztaly2E.Tolvaj, 5); + const fifthLevel = changed.szintlepesek[4]; + + expect(fifthLevel?.osztaly).toBe(Osztaly2E.Tolvaj); + expect(fifthLevel?.tolvajExtraKepzettseg).toBeDefined(); + }); + + it("at Tolvaj class level 9 LevelUp can auto-pick a class-restricted non-Tolvaj skill", () => { + const karakter: Karakter2E = { + ...DefaultKarakter, + szint: 8, + szintlepesek: [ + { osztaly: Osztaly2E.Tolvaj, HProll: 6 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 5 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 4 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 3 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 2, tolvajExtraKepzettseg: "k_meregkeveres" }, + { osztaly: Osztaly2E.Tolvaj, HProll: 4 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 5 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 3 }, + ], + tolvajKepzettsegek: ["k_alcazas", "k_csapdak", "k_egyensulyozas", "k_hamisitas"], + varazslatok: [], + }; + + const afterLevel9 = applyLevelUp(karakter); + expect(afterLevel9.szintlepesek[8]?.tolvajExtraKepzettseg).toBe("k_alkimia"); + }); + + it("at Tolvaj class level 9 class-change recomputation can set non-Tolvaj restricted skill", () => { + const karakter: Karakter2E = { + ...DefaultKarakter, + szint: 9, + szintlepesek: [ + { osztaly: Osztaly2E.Tolvaj, HProll: 6 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 5 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 4 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 3 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 2, tolvajExtraKepzettseg: "k_meregkeveres" }, + { osztaly: Osztaly2E.Tolvaj, HProll: 4 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 5 }, + { osztaly: Osztaly2E.Tolvaj, HProll: 3 }, + { osztaly: Osztaly2E.Harcos, HProll: 8 }, + ], + tolvajKepzettsegek: ["k_alcazas", "k_csapdak", "k_egyensulyozas", "k_hamisitas"], + varazslatok: [], + }; + + const changed = ChangeOsztalyAtSzint(karakter, Osztaly2E.Tolvaj, 9); + expect(changed.szintlepesek[8]?.tolvajExtraKepzettseg).toBe("k_alkimia"); + }); +}); diff --git a/frontend/src/second-edition/domain-models/szintlepes.ts b/frontend/src/second-edition/domain-models/szintlepes.ts index db2cb43..a37ebd5 100644 --- a/frontend/src/second-edition/domain-models/szintlepes.ts +++ b/frontend/src/second-edition/domain-models/szintlepes.ts @@ -67,7 +67,9 @@ export function LevelUp(karakter: Karakter2E, changeKarakter: (input: Karakter2E if (autoPickedOsztaly === Osztaly2E.Tolvaj){ const tolvajSzint = 1 + karakter.szintlepesek.filter(x => x.osztaly === Osztaly2E.Tolvaj).length if (tolvajSzint === 5 || tolvajSzint === 9) { - const availableKepzettsegek = GetAvailableKepzettsegek(karakter) + const availableKepzettsegek = GetAvailableKepzettsegek(karakter, { + ignoreClassRestrictions: tolvajSzint === 9, + }) szintlepes.tolvajExtraKepzettseg = availableKepzettsegek[0].Id; } } diff --git a/frontend/src/second-edition/pages/CreateCharacter2E.tsx b/frontend/src/second-edition/pages/CreateCharacter2E.tsx index cd86149..8a53151 100644 --- a/frontend/src/second-edition/pages/CreateCharacter2E.tsx +++ b/frontend/src/second-edition/pages/CreateCharacter2E.tsx @@ -109,7 +109,7 @@ function CreateCharacter2E(props: {

Tanult

- {karakter.szintlepesek[0].osztaly === Osztaly2E.Harcos && } + {karakter.szintlepesek[0].osztaly === Osztaly2E.Harcos && }
{/* 1. szinten */}