Add manual target override to skill check
Allow setting an explicit target number to roll against instead of the computed Per+training+mod. Works with no sheet skill selected (e.g. a GM-set 'roll vs 43'). Empty field keeps the auto-computed behaviour. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -466,6 +466,7 @@ function DeathwatchRoller({ authedPlayer }) {
|
||||
const [skillRollName, setSkillRollName] = useState('')
|
||||
const [skillRollModifier, setSkillRollModifier] = useState(0)
|
||||
const [manualSkillRoll, setManualSkillRoll] = useState('')
|
||||
const [skillTargetOverride, setSkillTargetOverride] = useState('')
|
||||
|
||||
// Load enemies from database API
|
||||
async function loadEnemiesFromAPI() {
|
||||
@@ -1200,6 +1201,11 @@ function DeathwatchRoller({ authedPlayer }) {
|
||||
const selectedSkillBase = characteristicValue(playerCharacteristics, selectedSkillCharacteristic, 45)
|
||||
const selectedSkillTrainingBonus = skillTrainingBonus(selectedSkill)
|
||||
const selectedSkillTarget = Math.max(1, Math.min(100, selectedSkillBase + selectedSkillTrainingBonus + (Number(skillRollModifier) || 0)))
|
||||
const skillTargetOverrideNum = parseInt(String(skillTargetOverride).trim(), 10)
|
||||
const hasSkillTargetOverride = String(skillTargetOverride).trim() !== '' && Number.isFinite(skillTargetOverrideNum)
|
||||
const effectiveSkillTarget = hasSkillTargetOverride
|
||||
? Math.max(1, Math.min(100, skillTargetOverrideNum))
|
||||
: selectedSkillTarget
|
||||
|
||||
const woundPct = maxWounds>0 ? Math.max(0, Math.min(100, (curWounds/maxWounds)*100)) : 0
|
||||
const status = curWounds<=0 ? 'Dead' : (curWounds<maxWounds ? 'Wounded' : 'Alive')
|
||||
@@ -1226,8 +1232,8 @@ function DeathwatchRoller({ authedPlayer }) {
|
||||
function rollSkillCheck() {
|
||||
setError('')
|
||||
setInfo('')
|
||||
if (!skillRollName) {
|
||||
setError('No skill selected')
|
||||
if (!skillRollName && !hasSkillTargetOverride) {
|
||||
setError('Select a skill or enter a target number')
|
||||
return
|
||||
}
|
||||
let roll
|
||||
@@ -1241,25 +1247,27 @@ function DeathwatchRoller({ authedPlayer }) {
|
||||
} else {
|
||||
roll = d100()
|
||||
}
|
||||
const dg = degrees(selectedSkillTarget, roll)
|
||||
const label = skillRollName || `Target ${effectiveSkillTarget}`
|
||||
const dg = degrees(effectiveSkillTarget, roll)
|
||||
const res = {
|
||||
id: uid(),
|
||||
ts: Date.now(),
|
||||
rollKind: 'skill',
|
||||
skillName: skillRollName,
|
||||
characteristic: selectedSkillCharacteristic,
|
||||
base: selectedSkillBase,
|
||||
training: skillTrainingLabel(selectedSkill),
|
||||
skillName: label,
|
||||
characteristic: skillRollName ? selectedSkillCharacteristic : null,
|
||||
base: skillRollName ? selectedSkillBase : null,
|
||||
training: skillRollName ? skillTrainingLabel(selectedSkill) : null,
|
||||
modifier: Number(skillRollModifier) || 0,
|
||||
target: selectedSkillTarget,
|
||||
target: effectiveSkillTarget,
|
||||
targetOverride: hasSkillTargetOverride,
|
||||
attackRoll: roll,
|
||||
success: dg.success,
|
||||
dos: dg.dos,
|
||||
dof: dg.dof,
|
||||
using: selectedSkillCharacteristic,
|
||||
using: skillRollName ? selectedSkillCharacteristic : null,
|
||||
}
|
||||
addRollResult(res)
|
||||
setInfo(`${skillRollName}: ${dg.success ? `Success (${dg.dos} DoS)` : `Fail (${dg.dof} DoF)`}`)
|
||||
setInfo(`${label}: ${dg.success ? `Success (${dg.dos} DoS)` : `Fail (${dg.dof} DoF)`}`)
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -1470,9 +1478,9 @@ function DeathwatchRoller({ authedPlayer }) {
|
||||
<div className="font-semibold">Skill Check</div>
|
||||
<div className="text-xs opacity-70">Uses this player sheet's skills and characteristics.</div>
|
||||
</div>
|
||||
<button onClick={rollSkillCheck} disabled={skillOptions.length === 0} className="rounded-xl px-4 py-2 bg-emerald-700 hover:bg-emerald-600 disabled:opacity-40">Roll Skill</button>
|
||||
<button onClick={rollSkillCheck} disabled={skillOptions.length === 0 && !hasSkillTargetOverride} className="rounded-xl px-4 py-2 bg-emerald-700 hover:bg-emerald-600 disabled:opacity-40">Roll Skill</button>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-3 items-end">
|
||||
<div className="grid grid-cols-1 md:grid-cols-5 gap-3 items-end">
|
||||
<div className="md:col-span-2">
|
||||
<label className="text-xs uppercase opacity-70">Skill</label>
|
||||
<select className="w-full rounded-xl border border-slate-600 bg-slate-800 px-3 py-2" value={skillRollName} onChange={e=>setSkillRollName(e.target.value)} disabled={skillOptions.length === 0}>
|
||||
@@ -1484,7 +1492,11 @@ function DeathwatchRoller({ authedPlayer }) {
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs uppercase opacity-70">Modifier</label>
|
||||
<input className="w-full rounded-xl border border-slate-600 bg-slate-800 px-3 py-2" type="number" value={skillRollModifier} onChange={e=>setSkillRollModifier(parseInt(e.target.value||'0', 10))} />
|
||||
<input className="w-full rounded-xl border border-slate-600 bg-slate-800 px-3 py-2" type="number" value={skillRollModifier} onChange={e=>setSkillRollModifier(parseInt(e.target.value||'0', 10))} disabled={hasSkillTargetOverride} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs uppercase opacity-70">Target</label>
|
||||
<input className="w-full rounded-xl border border-slate-600 bg-slate-800 px-3 py-2" type="number" min="1" max="100" placeholder="auto" value={skillTargetOverride} onChange={e=>setSkillTargetOverride(e.target.value)} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs uppercase opacity-70">Manual d100</label>
|
||||
@@ -1492,8 +1504,10 @@ function DeathwatchRoller({ authedPlayer }) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm opacity-85">
|
||||
Target <span className="font-semibold">{selectedSkillTarget}</span>
|
||||
{skillRollName && (
|
||||
Target <span className="font-semibold">{effectiveSkillTarget}</span>
|
||||
{hasSkillTargetOverride ? (
|
||||
<span> = manual target</span>
|
||||
) : skillRollName && (
|
||||
<span> = {selectedSkillCharacteristic} {selectedSkillBase} {selectedSkillTrainingBonus >= 0 ? '+' : ''}{selectedSkillTrainingBonus} training {Number(skillRollModifier) ? `${Number(skillRollModifier) > 0 ? '+' : ''}${Number(skillRollModifier)} mod` : '+0 mod'}</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user