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 }) {