show degrading ws and bs characteristics, show psyker spells

This commit is contained in:
NilsUeter
2023-05-07 11:53:54 +02:00
parent f2e813d5d7
commit 9134d420a5
4 changed files with 149 additions and 37 deletions
+2 -1
View File
@@ -58,7 +58,7 @@ function App() {
const rosterName = info.getAttribute("name"); const rosterName = info.getAttribute("name");
if (rosterName) { if (rosterName) {
document.title = `PrettyScribe ${rosterName}`; document.title = `FancyScribe ${rosterName}`;
} }
if (gameType == "Warhammer 40,000 9th Edition") { if (gameType == "Warhammer 40,000 9th Edition") {
@@ -90,6 +90,7 @@ function App() {
> >
<input <input
type="file" type="file"
accept=".ros,.rosz"
name="rosterUpload" name="rosterUpload"
id="rosterUpload" id="rosterUpload"
onChange={handleFileSelect} onChange={handleFileSelect}
+129 -18
View File
@@ -115,6 +115,7 @@ const Unit = ({ unit, catalog }) => {
modelStats, modelStats,
modelList, modelList,
psykers, psykers,
spells,
cost, cost,
} = unit; } = unit;
@@ -238,7 +239,8 @@ const Unit = ({ unit, catalog }) => {
{modelStats.map((model, index) => ( {modelStats.map((model, index) => (
<ModelStats <ModelStats
key={index} key={index}
modelStats={model} modelStats={modelStats}
modelStat={model}
modelList={modelList} modelList={modelList}
index={index} index={index}
showName={modelStats.length > 1} showName={modelStats.length > 1}
@@ -261,10 +263,8 @@ const Unit = ({ unit, catalog }) => {
flexDirection: "column", flexDirection: "column",
}} }}
> >
<table <Spells title="PSYCHIC" spells={spells} />
className="weapons-table" <table className="weapons-table" style={{ width: "100%" }}>
style={{ width: "100%", marginTop: 20 }}
>
<Weapons <Weapons
title="RANGED WEAPONS" title="RANGED WEAPONS"
weapons={rangedWeapons} weapons={rangedWeapons}
@@ -275,11 +275,11 @@ const Unit = ({ unit, catalog }) => {
weapons={meleeWeapons} weapons={meleeWeapons}
modelStats={modelStats} modelStats={modelStats}
/> />
<Psykers title="PSYKER" psykers={psykers} />
</table> </table>
<div style={{ flex: "1" }}></div> <div style={{ flex: "1" }}></div>
{hasDifferentProfiles && ( {hasDifferentProfiles && (
<table className="weapons-table" style={{ width: "100%" }}> <table className="weapons-table" style={{ width: "100%" }}>
<tbody>
<tr className="emptyRow noBorderTop"> <tr className="emptyRow noBorderTop">
<td style={{ width: 37, borderTop: "none" }}>{Arrow}</td> <td style={{ width: 37, borderTop: "none" }}>{Arrow}</td>
<td <td
@@ -294,6 +294,7 @@ const Unit = ({ unit, catalog }) => {
profiles to make attacks with. profiles to make attacks with.
</td> </td>
</tr> </tr>
</tbody>
</table> </table>
)} )}
<Keywords keywords={keywords} /> <Keywords keywords={keywords} />
@@ -323,6 +324,7 @@ const Unit = ({ unit, catalog }) => {
</div> </div>
<Rules rules={rules} /> <Rules rules={rules} />
<Abilities abilities={abilities.Abilities} /> <Abilities abilities={abilities.Abilities} />
<Psykers title="PSYKER" psykers={psykers} />
<Factions factions={factions} /> <Factions factions={factions} />
<FactionIcon catalog={catalog} /> <FactionIcon catalog={catalog} />
</div> </div>
@@ -333,12 +335,13 @@ const Unit = ({ unit, catalog }) => {
const ModelStats = ({ const ModelStats = ({
modelStats, modelStats,
modelStat,
index, index,
showName, showName,
showWeapons, showWeapons,
modelList, modelList,
}) => { }) => {
let { move, toughness, save, wounds, leadership, name } = modelStats; let { move, toughness, save, wounds, leadership, name, bs, ws } = modelStat;
if (!wounds) { if (!wounds) {
wounds = "/"; wounds = "/";
} }
@@ -357,6 +360,9 @@ const ModelStats = ({
modelListMatches = modelListMatches.map((model) => modelListMatches = modelListMatches.map((model) =>
model.replaceAll(name, "") model.replaceAll(name, "")
); );
const bsChange = Math.abs(parseInt(modelStats[0].bs, 10) - parseInt(bs, 10));
const wsChange = Math.abs(parseInt(modelStats[0].ws, 10) - parseInt(ws, 10));
return ( return (
<div style={{ display: "flex", gap: 16, alignItems: "center" }}> <div style={{ display: "flex", gap: 16, alignItems: "center" }}>
<Characteristic title="M" characteristic={move} index={index} /> <Characteristic title="M" characteristic={move} index={index} />
@@ -374,6 +380,13 @@ const ModelStats = ({
}} }}
> >
{name} {name}
{name.toLowerCase().includes("wounds remaining") &&
(bsChange !== 0 || wsChange !== 0) &&
` Each time this model makes an attack, subtract ${
bsChange ? `${bsChange} from the balistic skill` : ""
}${bsChange !== 0 && wsChange !== 0 ? " and " : ""}${
wsChange ? `${wsChange} from the weapon skill` : ""
}.`}
</div> </div>
)} )}
{showWeapons && ( {showWeapons && (
@@ -385,7 +398,7 @@ const ModelStats = ({
}} }}
> >
{modelListMatches.map((model, index) => ( {modelListMatches.map((model, index) => (
<div>{model}</div> <div key={model}>{model}</div>
))} ))}
</div> </div>
)} )}
@@ -578,7 +591,10 @@ const FancyBox = ({ children }) => {
const Psykers = ({ title, psykers }) => { const Psykers = ({ title, psykers }) => {
return ( return (
<> <table
className="weapons-table"
style={{ width: "100%", margin: "4px 2px" }}
>
{psykers.length > 0 && ( {psykers.length > 0 && (
<thead> <thead>
<tr <tr
@@ -587,11 +603,6 @@ const Psykers = ({ title, psykers }) => {
color: "#fff", color: "#fff",
}} }}
> >
<th style={{ width: 37 }}>
<div style={{ display: "flex" }}>
<img src={rangedIcon} />
</div>
</th>
<th style={{ textAlign: "left" }}>{title}</th> <th style={{ textAlign: "left" }}>{title}</th>
<th>Cast</th> <th>Cast</th>
<th>Deny</th> <th>Deny</th>
@@ -607,12 +618,12 @@ const Psykers = ({ title, psykers }) => {
))} ))}
{psykers.length > 0 && ( {psykers.length > 0 && (
<tr className="emptyRow"> <tr className="emptyRow">
<td style={{ width: 37, borderTop: "none" }}></td> <td style={{ width: 37 }}></td>
<td colSpan={7}></td> <td colSpan={7}></td>
</tr> </tr>
)} )}
</tbody> </tbody>
</> </table>
); );
}; };
@@ -620,8 +631,10 @@ const Psyker = ({ psyker, index }) => {
let { name, cast, deny, powers } = psyker; let { name, cast, deny, powers } = psyker;
return ( return (
<tr className={index % 2 ? "rowOtherColor" : ""}> <tr
<td style={{ borderTop: "none", backgroundColor: "#dfe0e2" }}></td> className={index % 2 ? "rowOtherColor" : ""}
style={{ fontSize: ".8em" }}
>
<td style={{ textAlign: "left" }}> <td style={{ textAlign: "left" }}>
<div <div
style={{ style={{
@@ -643,6 +656,104 @@ const Psyker = ({ psyker, index }) => {
); );
}; };
const Spells = ({ title, spells }) => {
return (
<table className="weapons-table" style={{ width: "100%", marginTop: 20 }}>
{spells.length > 0 && (
<thead>
<tr
style={{
backgroundColor: "var(--primary-color)",
color: "#fff",
}}
>
<th style={{ width: 37 }}>
<div style={{ display: "flex" }}>
<img src={rangedIcon} />
</div>
</th>
<th style={{ textAlign: "left" }}>{title}</th>
<th>RANGE</th>
<th>WARP CHARGE</th>
</tr>
</thead>
)}
<tbody>
{spells.map((spell, index) => (
<Spell
key={spell.name}
spell={spell}
index={index}
className={getSpellClassNames(spells, index)}
/>
))}
{spells.length > 0 && (
<tr className="emptyRow">
<td style={{ width: 37, borderTop: "none" }}></td>
<td colSpan={7}></td>
</tr>
)}
</tbody>
</table>
);
};
const Spell = ({ spell, index, className }) => {
let { name, range, manifest, details } = spell;
return (
<>
<tr className={className}>
<td style={{ borderTop: "none", backgroundColor: "#dfe0e2" }}></td>
<td style={{ textAlign: "left" }}>
<div
style={{
display: "flex",
alignItems: "center",
flexWrap: "wrap",
gap: "0 4px",
}}
>
{name}
</div>
</td>
<td>{range}</td>
<td>{manifest}</td>
</tr>
<tr className={className + " noBorderTop"}>
<td style={{ backgroundColor: "#dfe0e2" }}></td>
<td
colSpan="7"
style={{
textAlign: "left",
fontSize: "0.8em",
paddingTop: 0,
paddingBottom: 1,
lineHeight: 1.4,
}}
>
{details}
</td>
</tr>
</>
);
};
const getSpellClassNames = (spells, index) => {
let differentColor = false;
for (let i = 1; i <= index; i++) {
let { name } = spells[i];
if (name !== spells[i - 1].name) {
differentColor = !differentColor;
}
}
const classes = [];
if (differentColor) classes.push("rowOtherColor");
if (index === 0) classes.push("noBorderTop");
if (index > 0 && spells[index].name === spells[index - 1].name)
classes.push("noBorderTop");
return classes.join(" ");
};
const ForceRules = ({ rules }) => { const ForceRules = ({ rules }) => {
return ( return (
<div <div
+3 -3
View File
@@ -97,7 +97,7 @@ const Weapon = ({ weapon, modelStats, isMelee, className }) => {
type = "Plague Weapon"; type = "Plague Weapon";
} }
} }
if ( /* if (
abilities?.includes( abilities?.includes(
"Each time an attack made with this weapon targets an enemy within half range, that attack has a Damage characteristic of D6+2." "Each time an attack made with this weapon targets an enemy within half range, that attack has a Damage characteristic of D6+2."
) || ) ||
@@ -119,7 +119,7 @@ const Weapon = ({ weapon, modelStats, isMelee, className }) => {
} else { } else {
type = "Melta 2"; type = "Melta 2";
} }
} } */
if ( if (
abilities?.includes( abilities?.includes(
@@ -251,7 +251,7 @@ const Weapon = ({ weapon, modelStats, isMelee, className }) => {
<td>{damage}</td> <td>{damage}</td>
</tr> </tr>
{abilities && abilities !== "-" && ( {abilities && abilities !== "-" && (
<tr className={className + " " + "noBorderTop"}> <tr className={className + " noBorderTop"}>
<td style={{ backgroundColor: "#dfe0e2" }}></td> <td style={{ backgroundColor: "#dfe0e2" }}></td>
<td <td
colSpan="7" colSpan="7"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

After

Width:  |  Height:  |  Size: 278 KiB