[fe] [2e] add basic szintlepes

This commit is contained in:
2024-01-24 16:38:16 +01:00
parent 978618d1b1
commit 8f32daf337
13 changed files with 546 additions and 93 deletions
@@ -0,0 +1,88 @@
import React from "react";
import {Karakter2E} from "../domain-models/karakter2E";
import {SignedNumberToText} from "../../shared/components/Helpers";
import {Mentok, MentoTipus, MentoTipusLabel, MentokTotal} from "../domain-models/mentok";
import {BaseHP, HP} from "../domain-models/masodlagos_ertekek";
import {TamadasBonusz} from "../domain-models/tamadas_bonusz";
function MentoNovekedes(props : {tipus: MentoTipus, ujMentok: Mentok, regiMentok: Mentok}) {
const {tipus, ujMentok, regiMentok} = props
if (ujMentok[tipus] === regiMentok[tipus]) {
return null
}
return <div className='row m-2'>
<label className='col-sm-6 col-8 col-form-label'>{MentoTipusLabel(tipus)} mentő növekedés{' '}</label>
<span className='col col-form-label'>{SignedNumberToText(ujMentok[tipus] - regiMentok[tipus])}</span>
</div>;
}
function UjMento(props : {tipus: MentoTipus, ujMentok: Mentok, regiMentok: Mentok}) {
const {tipus, ujMentok, regiMentok} = props
if (ujMentok[tipus] === regiMentok[tipus]) {
return null
}
return <div className='row m-2'>
<label className='col-sm-6 col-8 col-form-label'>{MentoTipusLabel(tipus)} mentő új értéke{' '}</label>
<span className='col col-form-label'>{SignedNumberToText(ujMentok[tipus])}</span>
</div>;
}
function BasicNewLevel(props: {
karakter: Pick<Karakter2E, 'osztaly' | 'tulajdonsagok' | 'szintlepesek'>
szint: number
changeRolledHP: (hp: number) => void,
}) {
const {karakter, szint, changeRolledHP} = props
const regiMentok = MentokTotal({...karakter, szint: szint - 1})
const ujMentok = MentokTotal({...karakter, szint: szint})
const regiTB = TamadasBonusz(karakter.osztaly, szint-1)
const ujTB = TamadasBonusz(karakter.osztaly, szint)
if (regiTB.length < ujTB.length) {
regiTB.push(0)
}
const TBdiff = ujTB.map((x, i) => x - regiTB[i])
const isTBincreased = TBdiff.length > 0 && TBdiff.some(x => x > 0)
return <>
<div className='row'>
<div className='col-lg-6'>
<div className='row m-2'>
<label className='col-sm-6 col-8 col-form-label'>Plusz dobott HP (d{BaseHP(karakter.osztaly)}){' '}</label>
<div className='col-sm-2 col'>
<input
className='form-control'
maxLength={2}
type='number'
value={karakter.szintlepesek[szint-1].HProll || 1}
min={1}
max={12}
onChange={e => changeRolledHP(Number(e.target.value))} />
</div>
</div>
{ isTBincreased && <div className='row m-2'>
<label className='col-sm-6 col-8 col-form-label'>Támadás bónusz növekedés{' '}</label>
<span className='col col-form-label'>{TBdiff.map(SignedNumberToText).join(" / ")}</span>
</div>}
<MentoNovekedes tipus={'kitartas'} ujMentok={ujMentok} regiMentok={regiMentok} />
<MentoNovekedes tipus={'reflex'} ujMentok={ujMentok} regiMentok={regiMentok} />
<MentoNovekedes tipus={'akaratero'} ujMentok={ujMentok} regiMentok={regiMentok} />
</div>
<div className='col-lg-6'>
<div className='row m-2'>
<label className='col-sm-6 col-8 col-form-label'>Új HP{' '}</label>
<span className='col col-form-label'>{HP({...karakter, szintlepesek: karakter.szintlepesek.slice(0, szint-1)})}</span>
</div>
{isTBincreased && <div className='row m-2'>
<label className='col-sm-6 col-8 col-form-label'>Új Támadás bónusz{' '}</label>
<span className='col col-form-label'>{ujTB.map(SignedNumberToText).join(" / ")}</span>
</div>}
<UjMento tipus={'kitartas'} ujMentok={ujMentok} regiMentok={regiMentok} />
<UjMento tipus={'reflex'} ujMentok={ujMentok} regiMentok={regiMentok} />
<UjMento tipus={'akaratero'} ujMentok={ujMentok} regiMentok={regiMentok} />
</div>
</div>
</>
}
export default BasicNewLevel
@@ -0,0 +1,86 @@
import React from "react";
import {Fegyver} from "../domain-models/felszereles";
export function FegyverLabel(fegyver: Fegyver): string {
const flags = [] as string[]
if (fegyver.Harcos) {
flags.push("H")
}
if (fegyver.Masfelkezes) {
flags.push("1½K")
}
if (fegyver.Ketkezes) {
if (fegyver.Type === "kozelharci") {
flags.push("2K")
} else {
if (fegyver.KetkezesBonusz) {
flags.push("2KB")
} else {
flags.push("2KN")
}
}
}
if (fegyver.HarciManover) {
flags.push("+2 HM")
}
if (fegyver.Alakzat){
flags.push("AL")
}
if (fegyver.Hosszu) {
flags.push("HO")
}
if (fegyver.Kabito) {
flags.push("KO")
}
if (fegyver.LovasRoham) {
flags.push("LR")
}
if (fegyver.PancelToro) {
flags.push("PT")
}
if (fegyver.PajzsZuzo) {
flags.push("PZ")
}
if (fegyver.Rohamtoro) {
flags.push("RT")
}
// Replaced by new group "dobhato"
// if (fegyver.EroBonusz) {
// flags.push("ER")
// }
if (fegyver.Megjegyzes != null && fegyver.Megjegyzes.length > 0) {
flags.push(fegyver.Megjegyzes)
}
const serializedFlags = flags.reduce((p,c) => `${p}${c} `, '');
const sizeLabel = fegyver.Size < 1 && fegyver.Size > 0 ? ` [1/${Math.round(1 / fegyver.Size)}]` : (fegyver.Size > 1 ? ` [${fegyver.Size}]` : '');
return `${fegyver.Name}${sizeLabel} ${serializedFlags.length > 0 ? "| " + serializedFlags : ''}| ${
fegyver.DamageMultiplier > 1 ? `${fegyver.DamageMultiplier}*` : ''}${fegyver.NumberOfDamageDice}d${fegyver.DamageDice}${fegyver.DamageBonus > 0 ? ` +${fegyver.DamageBonus}` : ''} ${
fegyver.CritRangeStart < 20 ? `${fegyver.CritRangeStart}-20` : ''}x${fegyver.CritMultiplier}${
fegyver.Price > 0 ? ` | ár: ${fegyver.Price} at ` : ''}${
fegyver.Range > 10 ? ` | táv: ${fegyver.Range}` : ''}`
}
function FegyverSelector(props: {fegyverek: Fegyver[], selectedId: string, onChange: (id: string) => void}) {
const { fegyverek, selectedId, onChange } = props
return <>
<select className='col form-select' value={selectedId}
onChange={e => onChange(e.target.value)}>
<optgroup label="Közelharci">
{fegyverek.filter(f => f.Type === 'kozelharci').map(f => <option
key={f.Id} value={f.Id}>{FegyverLabel(f)}</option>)}
</optgroup>
<optgroup label="Közelharci, dobható">
{fegyverek.filter(f => f.Type === 'dobhato').map(f => <option
key={f.Id} value={f.Id}>{FegyverLabel(f)}</option>)}
</optgroup>
<optgroup label="Távolsági">
{fegyverek.filter(f => f.Type === 'lofegyver').map(f => <option
key={f.Id} value={f.Id}>{FegyverLabel(f)}</option>)}
</optgroup>
</select>
</>
}
export default FegyverSelector
@@ -5,64 +5,7 @@ import {AllowedPajzsTypes, AllowedPancelTypes} from '../domain-models/allowed-pa
import fegyverek from '../domain-models/fegyver.json'
import {arraySetN} from "../../util";
import {AllowedFegyver} from "../domain-models/allowed-fegyver";
export function FegyverLabel(fegyver: Fegyver): string {
const flags = [] as string[]
if (fegyver.Harcos) {
flags.push("H")
}
if (fegyver.Masfelkezes) {
flags.push("1½K")
}
if (fegyver.Ketkezes) {
if (fegyver.Type === "kozelharci") {
flags.push("2K")
} else {
if (fegyver.KetkezesBonusz) {
flags.push("2KB")
} else {
flags.push("2KN")
}
}
}
if (fegyver.HarciManover) {
flags.push("+2 HM")
}
if (fegyver.Alakzat){
flags.push("AL")
}
if (fegyver.Hosszu) {
flags.push("HO")
}
if (fegyver.Kabito) {
flags.push("KO")
}
if (fegyver.LovasRoham) {
flags.push("LR")
}
if (fegyver.PancelToro) {
flags.push("PT")
}
if (fegyver.PajzsZuzo) {
flags.push("PZ")
}
if (fegyver.Rohamtoro) {
flags.push("RT")
}
// if (fegyver.EroBonusz) {
// flags.push("ER")
// }
if (fegyver.Megjegyzes != null && fegyver.Megjegyzes.length > 0) {
flags.push(fegyver.Megjegyzes)
}
const serializedFlags = flags.reduce((p,c) => `${p}${c} `, '');
const sizeLabel = fegyver.Size < 1 && fegyver.Size > 0 ? ` [1/${Math.round(1 / fegyver.Size)}]` : (fegyver.Size > 1 ? ` [${fegyver.Size}]` : '');
return `${fegyver.Name}${sizeLabel} ${serializedFlags.length > 0 ? "| " + serializedFlags : ''}| ${
fegyver.DamageMultiplier > 1 ? `${fegyver.DamageMultiplier}*` : ''}${fegyver.NumberOfDamageDice}d${fegyver.DamageDice}${fegyver.DamageBonus > 0 ? ` +${fegyver.DamageBonus}` : ''} ${
fegyver.CritRangeStart < 20 ? `${fegyver.CritRangeStart}-20` : ''}x${fegyver.CritMultiplier}${
fegyver.Price > 0 ? ` | ár: ${fegyver.Price} at ` : ''}${
fegyver.Range > 10 ? ` | táv: ${fegyver.Range}` : ''}`
}
import FegyverSelector from "./FegyverSelector";
function Felszereles(props: {felszereles: KarakterFelszereles, changeFelszereles: (felszereles: KarakterFelszereles) => void, osztaly: Osztaly2E}) {
const { felszereles, changeFelszereles, osztaly } = props;
@@ -116,21 +59,7 @@ function Felszereles(props: {felszereles: KarakterFelszereles, changeFelszereles
{valasztottFegyverek.map(({idx, fegyver}) => (
<div key={`fegyver-${idx}`} className='row m-2'>
<label className='col-md-2 col-sm-3 col-form-label'>Fegyver</label>
<select className='col form-select' value={fegyver.Id}
onChange={e => changeFegyver(idx, e.target.value)}>
<optgroup label="Közelharci">
{allowedFegyverek.filter(f => f.Type === 'kozelharci').map(f => <option
key={f.Id} value={f.Id}>{FegyverLabel(f)}</option>)}
</optgroup>
<optgroup label="Közelharci, dobható">
{allowedFegyverek.filter(f => f.Type === 'dobhato').map(f => <option
key={f.Id} value={f.Id}>{FegyverLabel(f)}</option>)}
</optgroup>
<optgroup label="Távolsági">
{allowedFegyverek.filter(f => f.Type === 'lofegyver').map(f => <option
key={f.Id} value={f.Id}>{FegyverLabel(f)}</option>)}
</optgroup>
</select>
<FegyverSelector fegyverek={allowedFegyverek} selectedId={fegyver.Id} onChange={(fegyverId) => changeFegyver(idx, fegyverId)} />
<button className='col-md-2 col-sm-3 btn btn-outline-dark btn-lg ms-2' type='button'
onClick={() => changeFelszereles({
...felszereles,
@@ -0,0 +1,32 @@
import React from "react";
import {GetFegyver} from "../domain-models/felszereles";
import FegyverSelector from "./FegyverSelector";
import {AllowedFegyver} from "../domain-models/allowed-fegyver";
import {Osztaly2E} from "../domain-models/osztaly2E";
function HarcosFegyverSpecializacio(props: {
specialization: string,
existingSpecializations: (string | undefined)[],
changeSpecialization: (specialization: string) => void
szint: number
}) {
const {
specialization,
existingSpecializations,
changeSpecialization,
szint
} = props
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))
return <>
<div className='row m-2'>
<label className='col-md-2 col-sm-3 col-form-label' >Fegyver specializáció</label>
<FegyverSelector fegyverek={pickableFegyverek} selectedId={specialization} onChange={changeSpecialization} />
{fegyver == null && <span className='form-field-error'>Ismeretlen fegyver: {specialization}</span>}
</div>
</>
}
export default HarcosFegyverSpecializacio
@@ -0,0 +1,28 @@
import React from "react";
import {Osztaly2E} from "../domain-models/osztaly2E";
import {AllowedFegyver} from "../domain-models/allowed-fegyver";
import FegyverSelector from "./FegyverSelector";
function KalozKritikus(props: {
kritFegyverId: string,
existingKrits: (string | undefined)[],
changeKrit: (krit: string) => void,
szint: number
}) {
const {
kritFegyverId,
existingKrits,
changeKrit,
szint
} = props
const fegyverek = AllowedFegyver(Osztaly2E.Tengeresz).filter(f => f.Id === kritFegyverId || existingKrits.filter(x => x === f.Id).length < (szint < 9 ? 1 : 2))
return <>
<div className='row m-2'>
<label className='col-md-2 col-sm-3 col-form-label'>Kritikus</label>
<FegyverSelector fegyverek={fegyverek} selectedId={kritFegyverId} onChange={changeKrit} />
</div>
</>
}
export default KalozKritikus
@@ -0,0 +1,126 @@
import React from "react";
import {Karakter2E} from "../domain-models/karakter2E";
import BasicNewLevel from "./BasicNewLevel";
import TulajdonsagNoveles from "./TulajdonsagNoveles";
import {Tulajdonsag2E, TulajdonsagokTotal} from "../domain-models/tulajdonsag2E";
import {arraySetN} from "../../util";
import {Osztaly2E} from "../domain-models/osztaly2E";
import KalozKritikus from "./KalozKritikus";
import HarcosFegyverSpecializacio from "./HarcosFegyverSpec";
function LevelUp(props: {
szint: number,
karakter: Karakter2E,
changeTulajdonsagNoveles: (t: Tulajdonsag2E) => void,
changeRolledHP: (rolledHP: number) => void,
changeHarcosSpec: (spec: string) => void,
changeKalozKritikus: (krit: string) => void,
}) {
const {
szint,
karakter,
changeTulajdonsagNoveles,
changeRolledHP,
changeHarcosSpec,
changeKalozKritikus,
} = props
const specialization = karakter.szintlepesek[szint-1].harcosFegyver
const krit = karakter.szintlepesek[szint-1].kalozKritikus
return <div>
<div className='row mt-3'>
<h5 className='col align-self-center'>{szint}. Szint</h5>
</div>
{szint % 4 === 0
&& <TulajdonsagNoveles
tulajdonsagok={karakter.tulajdonsagok}
tulajdonsagNoveles={karakter.szintlepesek[szint-1].tulajdonsagNoveles!}
changeTulajdonsagNoveles={changeTulajdonsagNoveles}
/>}
<BasicNewLevel
szint={szint}
karakter={karakter}
changeRolledHP={changeRolledHP}
/>
{karakter.osztaly === Osztaly2E.Harcos && szint % 2 === 1 &&
<HarcosFegyverSpecializacio
specialization={specialization!}
existingSpecializations={karakter.szintlepesek.map(x => x.harcosFegyver)}
changeSpecialization={changeHarcosSpec}
szint={szint}
/>
}
{karakter.osztaly === Osztaly2E.Tengeresz && szint % 3 === 0 && !!krit &&
<KalozKritikus
kritFegyverId={krit}
existingKrits={karakter.szintlepesek.map(x => x.kalozKritikus)}
changeKrit={changeKalozKritikus}
szint={szint}
/>
}
</div>
}
export function LevelUps(props: {karakter: Karakter2E, changeKarakter: (inputs: Karakter2E) => void}){
const {karakter, changeKarakter} = props;
const tulajdonsagokAtSzint = (szint: number) => TulajdonsagokTotal({...karakter, szintlepesek: karakter.szintlepesek.slice(0, szint - 1)})
const changeRolledHPAtSzint = (szint: number) => (newHProll: number) => {
changeKarakter({...karakter, szintlepesek: arraySetN(karakter.szintlepesek, szint-2, {...karakter.szintlepesek[szint-2], HProll: newHProll})})
console.log(karakter)
}
const changeTulajdonsagNovelesAtSzint = (szint: number) => {
return (t: Tulajdonsag2E) => {
changeKarakter({...karakter,
szintlepesek: arraySetN(karakter.szintlepesek, szint-1, {
...karakter.szintlepesek[szint-1],
tulajdonsagNoveles: t
})
})
};
}
const changeHarcosSpecializacioAtSzint = (szint: number) => {
return (spec: string) => {
changeKarakter({
...karakter,
szintlepesek: arraySetN(karakter.szintlepesek, szint-1, {
...karakter.szintlepesek[szint-1],
harcosFegyver: spec
})
})
};
}
const changeKalozKritikusAtSzint = (szint: number) => {
return (krit: string) => {
changeKarakter({
...karakter,
szintlepesek: arraySetN(karakter.szintlepesek, szint-1, {
...karakter.szintlepesek[szint-1],
kalozKritikus: krit
})
})
};
}
const levels = karakter.szintlepesek.map((_, i) => i+1);
return <>
{levels.slice(1).map(szint =>
<LevelUp
key={`level-up-${szint}`}
szint={szint}
karakter={{...karakter, tulajdonsagok: tulajdonsagokAtSzint(szint)}}
changeTulajdonsagNoveles={changeTulajdonsagNovelesAtSzint(szint)}
changeRolledHP={changeRolledHPAtSzint(szint)}
changeHarcosSpec={changeHarcosSpecializacioAtSzint(szint)}
changeKalozKritikus={changeKalozKritikusAtSzint(szint)}
/>
)}
</>
}
export default LevelUps
@@ -0,0 +1,37 @@
import React from "react";
import {
KarakterTulajdonsagok,
Modifier,
Tulajdonsag2E,
TulajdonsagIDs,
TulajdonsagLabel
} from "../domain-models/tulajdonsag2E";
import {SignedNumberToText} from "../../shared/components/Helpers";
function TulajdonsagNoveles(props: {tulajdonsagok: KarakterTulajdonsagok, tulajdonsagNoveles: Tulajdonsag2E, changeTulajdonsagNoveles: (tulajdonsag: Tulajdonsag2E) => void}) {
const {tulajdonsagok, tulajdonsagNoveles, changeTulajdonsagNoveles} = props
return <>
<div className='row'>
<div className='col-lg-6'>
<div className='row m-2'>
<label className='col-sm-6 col-8 col-form-label'>Tulajdonság növelés{' '}</label>
<div className='col'>
<select className='form-select' value={tulajdonsagNoveles} onChange={(e) => changeTulajdonsagNoveles(e.target.value as Tulajdonsag2E)}>
{TulajdonsagIDs.filter(t => t === tulajdonsagNoveles || tulajdonsagok[t] < 18).map(t => (
<option value={t} key={t}>{TulajdonsagLabel(t)}</option>
))}
</select>
</div>
</div>
</div>
<div className='col-lg-6'>
<div className='row m-2'>
<label className='col-sm-6 col-8 col-form-label'>Új {TulajdonsagLabel(tulajdonsagNoveles)}{' '}</label>
<span className='col col-form-label'>{tulajdonsagok[tulajdonsagNoveles]} ({SignedNumberToText(Modifier(tulajdonsagok[tulajdonsagNoveles]))})</span>
</div>
</div>
</div>
</>
}
export default TulajdonsagNoveles