diff --git a/src/components/DeathwatchRoller.jsx b/src/components/DeathwatchRoller.jsx index 26f1a03..0626fb1 100755 --- a/src/components/DeathwatchRoller.jsx +++ b/src/components/DeathwatchRoller.jsx @@ -173,13 +173,30 @@ function mapBuildEntryToWeapon(entry) { else if (clsText.includes('basic')) cls = 'basic' else if (clsText.includes('heavy')) cls = 'heavy' - // Derive modes from class heuristics + // Prefer the explicit single/semi/full RoF triplet (e.g. "-/-/6" = full-auto + // only at RoF 6, "S/3/-" = single + semi). A "-" means that mode is unavailable. let modes = [] - if (cls === 'melee') modes = ['single'] - else if (cls === 'pistol') modes = ['single','semi'] - else if (cls === 'basic') modes = ['single','semi','full'] - else if (cls === 'heavy') modes = ['full'] - else modes = ['single'] + const triplet = dmgText.match(/(?:^|[\s;(])([0-9S-]+)\s*\/\s*([0-9-]+)\s*\/\s*([0-9-]+)(?!m)/i) + // Only trust it as RoF notation if it carries an "S" or "-" marker; a bare + // numeric triplet is more likely a range (e.g. "30/60/90m"), so defer to class. + if (triplet && /[S-]/i.test(triplet[0])) { + const [single, semi, full] = [triplet[1], triplet[2], triplet[3]] + if (single !== '-') modes.push('single') + if (semi !== '-') modes.push('semi') + if (full !== '-') modes.push('full') + const fullRof = parseInt(full, 10) + const semiRof = parseInt(semi, 10) + if (Number.isFinite(fullRof)) rof = Math.max(rof, fullRof) + else if (Number.isFinite(semiRof)) rof = Math.max(rof, semiRof) + } + // Fall back to class heuristics when no triplet is present. + if (modes.length === 0) { + if (cls === 'melee') modes = ['single'] + else if (cls === 'pistol') modes = ['single','semi'] + else if (cls === 'basic') modes = ['single','semi','full'] + else if (cls === 'heavy') modes = ['full'] + else modes = ['single'] + } return { name, @@ -402,7 +419,6 @@ function DeathwatchRoller({ authedPlayer }) { const [enemiesLoading,setEnemiesLoading] = useState(false) const [enemiesError,setEnemiesError] = useState(null) const [enemyName,setEnemyName] = useState('Custom/None') - const [attackerName,setAttackerName] = useState('Custom/None') const [playerSkills, setPlayerSkills] = useState({}) const [playerCharacteristics, setPlayerCharacteristics] = useState({}) const [rollerTab, setRollerTab] = useState('combat') @@ -737,37 +753,6 @@ function DeathwatchRoller({ authedPlayer }) { else setDefenderModifier(0) } - function onSelectAttacker(name) { - setAttackerName(name) - const e = enemies.find(x=>x.name===name) - if (!e || name === "Custom/None") return - // Extract WS/BS from enemy - function findNumeric(o, keys) { - if (!o || typeof o !== "object") return undefined - for (const k of keys) { - if (typeof o[k] === "number") return o[k] - const lower = k.toLowerCase() - for (const ok of Object.keys(o)) { - if (ok.toLowerCase() === lower && typeof o[ok] === "number") return o[ok] - } - } - return undefined - } - const char = e.characteristics || (e.tabInfo && e.tabInfo.characteristics) || {} - const wsVal = findNumeric(e, ["ws", "Ws", "WS"]) ?? findNumeric(char, ["ws"]) - const bsVal = findNumeric(e, ["bs", "Bs", "BS"]) ?? findNumeric(char, ["bs"]) - if (typeof wsVal === "number") setWS(wsVal) - if (typeof bsVal === "number") setBS(bsVal) - const enemyDamage = extractDiceDamage(e.damage) - if (enemyDamage) setDamage(enemyDamage) - if (typeof e.pen === "number") setPen(e.pen) - else { - const enemyPen = extractPen(e.damage) - if (typeof enemyPen === "number") setPen(enemyPen) - } - if (e.attack) setWeaponName(e.attack) - } - function importFromJSONText(txt) { try { const arr = JSON.parse(txt) @@ -1396,12 +1381,6 @@ function DeathwatchRoller({ authedPlayer }) { TB / AR / W • {enemies.length} enemies loaded -
- - -