diff --git a/src/10th/Roster.jsx b/src/10th/Roster.jsx index a007fad..850e5cc 100644 --- a/src/10th/Roster.jsx +++ b/src/10th/Roster.jsx @@ -3,10 +3,16 @@ import factionBackground from "../assets/factionBackground.png"; import keywordsBackground from "../assets/keywordsBackground.png"; import cardBackground from "../assets/cardBackground.png"; import dgBackground from "../assets/dgBackground.png"; +import tauBackground from "../assets/tauBackground.png"; +import tyranidBackground from "../assets/tyranidBackground.png"; +import mechanicusBackground from "../assets/mechanicusBackground.png"; +import orkBackground from "../assets/orkBackground.png"; +import necronBackground from "../assets/necronBackground.png"; import { Arrow, wavyLine } from "../assets/icons"; import { Weapons, hasDifferentProfiles } from "./Weapons"; import { useIndexedDB } from "../helpers/useIndexedDB"; // New hook for IndexedDB import { ImgEditor } from "./ImgEditor"; +import { trySettingLocalStorage } from "../helpers/useLocalStorage"; export const Roster = ({ roster, onePerPage, colorUserChoice }) => { if (!roster) { @@ -249,10 +255,7 @@ const Unit = ({ paddingBottom: 4, background: "linear-gradient(90deg, rgba(20,21,25,1) 0%, rgba(48,57,62,1) 45%, rgba(73,74,79,1) 100%)", - backgroundImage: - catalog === "Chaos - Death Guard" - ? `url(${dgBackground})` - : `url(${factionBackground})`, + backgroundImage: `url(${backgrounds[catalog] ? backgrounds[catalog] : factionBackground})`, backgroundSize: "cover", color: "#fff", position: "relative", @@ -371,7 +374,7 @@ const Unit = ({ top: 0, height: "100%", bottom: 0, - width: "50%", + width: "60%", zIndex: 100, overflow: "hidden", }} @@ -437,6 +440,9 @@ const Unit = ({ reader.onload = function (ev) { setImage(ev.target.result); setBgRemoved(false); + // reset position of the image + trySettingLocalStorage(`positionX_${name}`, 0, () => {}); + trySettingLocalStorage(`positionY_${name}`, 0, () => {}); }.bind(this); reader.readAsDataURL(e.target.files[0]); } @@ -569,6 +575,15 @@ const Unit = ({ ); }; +const backgrounds = { + "Imperium - Adeptus Mechanicus": mechanicusBackground, + "Chaos - Death Guard": dgBackground, + "Xenos - T'au Empire": tauBackground, + "Xenos - Tyranids": tyranidBackground, + "Xenos - Orks": orkBackground, + "Xenos - Necrons": necronBackground, +}; + const checkAbilitiesForInvul = (abilitiesMap, name) => { const abilities = [...(abilitiesMap?.keys?.() || [])]; for (let ability of abilities) { @@ -583,7 +598,9 @@ const checkAbilitiesForInvul = (abilitiesMap, name) => { continue; } } - switch (abilitiesMap.get(ability)?.trim()?.toLowerCase().replace(".", "")) { + switch ( + abilitiesMap.get(ability)?.trim()?.toLowerCase().replaceAll(".", "") + ) { case "2+": if (ability?.toLowerCase().includes("invulnerable save")) return "2+"; break; @@ -662,15 +679,15 @@ const checkAbilitiesForInvul = (abilitiesMap, name) => { case "this model has a 6+ invulnerable save against ranged weapons": return "6+*"; - case "this model has a 2+ invulnerable save. you cannot re-roll invulnerable saving throws made for this model": + case "this model has a 2+ invulnerable save you cannot re-roll invulnerable saving throws made for this model": return "2+*"; - case "this model has a 3+ invulnerable save. you cannot re-roll invulnerable saving throws made for this model": + case "this model has a 3+ invulnerable save you cannot re-roll invulnerable saving throws made for this model": return "3+*"; - case "this model has a 4+ invulnerable save. you cannot re-roll invulnerable saving throws made for this model": + case "this model has a 4+ invulnerable save you cannot re-roll invulnerable saving throws made for this model": return "4+*"; - case "this model has a 5+ invulnerable save. you cannot re-roll invulnerable saving throws made for this model": + case "this model has a 5+ invulnerable save you cannot re-roll invulnerable saving throws made for this model": return "5+*"; - case "this model has a 6+ invulnerable save. you cannot re-roll invulnerable saving throws made for this model": + case "this model has a 6+ invulnerable save you cannot re-roll invulnerable saving throws made for this model": return "6+*"; } } @@ -696,14 +713,17 @@ const ModelStats = ({ modelStat, index, showName, abilities }) => { {showName && (
-
{name}
+ {name}
)} @@ -749,6 +769,9 @@ const InvulRow = ({ hasInvul }) => { }; const FactionIcon = ({ catalog }) => { + if (!factionIcons[catalog]) { + console.log(catalog); + } return (
), + "Xenos - Necrons": ( + + + + + + + ), + "Xenos - T'au Empire": ( + + + + + + ), }; const Keywords = ({ keywords }) => { @@ -972,7 +1020,7 @@ const Rules = ({ rules }) => { const removeInvulnsWithoutSpecialRules = (abilities) => { const filteredAbilities = new Map(); for (let [key, value] of abilities) { - switch (value?.trim()?.toLowerCase().replace(".", "")) { + switch (value?.trim()?.toLowerCase().replaceAll(".", "")) { case "2+": if (!key?.toLowerCase().includes("invulnerable save")) filteredAbilities.set(key, value); @@ -1048,10 +1096,13 @@ const boldKeywords = [ "heretic astartes", "adeptus astartes", "adeptus mechanicus", + "halo override", "adeptus custodes", "adeptus sororitas", "tyranids", + "termagants", "orks", + "necrons", ]; const weaponKeywords = [ @@ -1064,43 +1115,47 @@ const weaponKeywords = [ "indirect fire", "sustained hits 1", "sustained hits 2", + "sustained hits x", "devastating wounds", + "precision", + "ignores cover", ]; const Abilities = ({ abilities }) => { if (!abilities) return null; - const filteredAbilities = removeInvulnsWithoutSpecialRules(abilities); + let filteredAbilities = removeInvulnsWithoutSpecialRules(abilities); - let keys = [...filteredAbilities.keys()]; + // sort abilites so that "Leader" is always at the bottom, "Supreme Commander" also bottom but before "Leader", same for any invulnerable save + let abilitiesForEnd = new Map(); + for (let [key, value] of filteredAbilities) { + if (key.toLowerCase().includes("invulnerable save")) { + filteredAbilities.delete(key); + abilitiesForEnd.set(key, value); + } + if (key.toLowerCase().includes("damaged: ")) { + filteredAbilities.delete(key); + abilitiesForEnd.set(key, value); + } + } + if (filteredAbilities.has("Supreme Commander")) { + const supremeCommander = filteredAbilities.get("Supreme Commander"); + filteredAbilities.delete("Supreme Commander"); + abilitiesForEnd.set("Supreme Commander", supremeCommander); + } + if (filteredAbilities.has("Leader")) { + const leader = filteredAbilities.get("Leader"); + filteredAbilities.delete("Leader"); + abilitiesForEnd.set("Leader", leader); + } + filteredAbilities = new Map([...filteredAbilities, ...abilitiesForEnd]); const replacedAbilities = new Map(); // in the value of the filtered abilites, make certain keywords bold for (let [key, value] of filteredAbilities) { - let newValue = value; - for (let keyword of boldKeywords) { - newValue = newValue.replace( - new RegExp(`\\b${keyword}\\b`, "gi"), - `${keyword.toUpperCase()}`, - ); - } - - // weaponKeywords could be with [] or without - for (let keyword of weaponKeywords) { - newValue = newValue.replace( - new RegExp(`\\[${keyword}\\]`, "gi"), - `[${keyword.toUpperCase()}]`, - ); - if (keyword !== "assault") { - newValue = newValue.replace( - new RegExp(`\\b${keyword}\\b`, "gi"), - `${keyword.toUpperCase()}`, - ); - } - } - - replacedAbilities.set(key, newValue); + replacedAbilities.set(key, makeKeywordsBold(value)); } + let keys = [...filteredAbilities.keys()]; return (
{ ); }; +const makeKeywordsBold = (text) => { + let newValue = text; + for (let keyword of boldKeywords) { + newValue = newValue.replace( + new RegExp(`\\b${keyword}\\b`, "gi"), + `${keyword.toUpperCase()}`, + ); + } + + // weaponKeywords could be with [] or without + for (let keyword of weaponKeywords) { + newValue = newValue.replace( + new RegExp(`\\[${keyword}\\]`, "gi"), + `[${keyword.toUpperCase()}]`, + ); + if (keyword !== "assault") { + // replace without [] only if it is not "assault" and not already replaced + newValue = newValue.replace( + new RegExp(`(?[${keyword.toUpperCase()}]`, + ); + } + } + // replace two newlines with one but only if there are two newlines in a row + return newValue.replace(/\n\n+/g, "\n\n"); +}; + const Characteristic = ({ title, characteristic, index }) => { return (
{ lineHeight: 1.4, }} > - {rule}: {rules.get(rule)} + {rule}:{" "} +
))}
diff --git a/src/assets/cardBackground.png b/src/assets/cardBackground.png index 6fa894d..6058b10 100644 Binary files a/src/assets/cardBackground.png and b/src/assets/cardBackground.png differ diff --git a/src/assets/dgBackground.png b/src/assets/dgBackground.png index fc61584..c136c62 100644 Binary files a/src/assets/dgBackground.png and b/src/assets/dgBackground.png differ diff --git a/src/assets/mechanicusBackground.png b/src/assets/mechanicusBackground.png new file mode 100644 index 0000000..13cf3dd Binary files /dev/null and b/src/assets/mechanicusBackground.png differ diff --git a/src/assets/meleeIcon.png b/src/assets/meleeIcon.png index 521d2e7..7a1304e 100644 Binary files a/src/assets/meleeIcon.png and b/src/assets/meleeIcon.png differ diff --git a/src/assets/necronBackground.png b/src/assets/necronBackground.png new file mode 100644 index 0000000..3553c49 Binary files /dev/null and b/src/assets/necronBackground.png differ diff --git a/src/assets/orkBackground.png b/src/assets/orkBackground.png new file mode 100644 index 0000000..1195f6e Binary files /dev/null and b/src/assets/orkBackground.png differ diff --git a/src/assets/rangedIcon.png b/src/assets/rangedIcon.png index c8d43ad..3127a42 100644 Binary files a/src/assets/rangedIcon.png and b/src/assets/rangedIcon.png differ diff --git a/src/assets/tauBackground.png b/src/assets/tauBackground.png new file mode 100644 index 0000000..bacd825 Binary files /dev/null and b/src/assets/tauBackground.png differ diff --git a/src/assets/tyranidBackground.png b/src/assets/tyranidBackground.png new file mode 100644 index 0000000..708dd74 Binary files /dev/null and b/src/assets/tyranidBackground.png differ diff --git a/src/helpers/useLocalStorage.js b/src/helpers/useLocalStorage.js index af667df..fe43ba8 100644 --- a/src/helpers/useLocalStorage.js +++ b/src/helpers/useLocalStorage.js @@ -42,12 +42,12 @@ export function useLocalStorage(key, initValue) { return [state, setState]; } -const trySettingLocalStorage = (key, value, setState) => { +export const trySettingLocalStorage = (key, value, setState) => { try { localStorage.setItem(key, value); window.dispatchEvent(new Event("storage")); } catch (e) { console.error(e); - setState(value); + setState?.(value); } };