feat: wire up stuck-weapon follow-up for impale/slash specials
Add POST /api/combat/stuck-weapon-removal endpoint supporting three removal types: attacker (weapon skill roll), self (STR+CON roll), and first-aid (First Aid skill roll). After a special hit with damage through, the attack result UI shows a stuck-weapon card with buttons for each removal option.
This commit is contained in:
@@ -421,6 +421,41 @@ app.post('/api/combat/attack', (req, res) => {
|
||||
res.json({ combatState: dbApi.combat.get(), result });
|
||||
});
|
||||
|
||||
app.post('/api/combat/stuck-weapon-removal', (req, res) => {
|
||||
const { attackerCombatantId, defenderCombatantId, weaponName, kind, removalType, firstAidSkillPercent } = req.body || {};
|
||||
const current = dbApi.combat.get();
|
||||
if (!current) return res.status(400).json({ error: 'No active combat' });
|
||||
const state = current.state;
|
||||
const attacker = (state.combatants || []).find((c) => c.id === attackerCombatantId);
|
||||
const defender = (state.combatants || []).find((c) => c.id === defenderCombatantId);
|
||||
if (!attacker || !defender) return res.status(400).json({ error: 'Unknown attacker or defender combatant id' });
|
||||
if (kind !== 'impale' && kind !== 'slash') return res.status(400).json({ error: 'kind must be impale or slash' });
|
||||
|
||||
let result;
|
||||
if (removalType === 'attacker') {
|
||||
const weaponEntry = attacker.weapons.find((w) => w.weapon_name.toLowerCase() === (weaponName || '').toLowerCase());
|
||||
if (!weaponEntry) return res.status(400).json({ error: `Attacker has no weapon named "${weaponName}"` });
|
||||
result = rq3.attemptWeaponRemoval(weaponEntry.skill_percent, kind);
|
||||
result.removalType = 'attacker';
|
||||
} else if (removalType === 'self') {
|
||||
result = { success: rq3.removeStuckWeaponFromSelf(defender.str + defender.con), weaponBreaks: false, removalType: 'self' };
|
||||
} else if (removalType === 'first-aid') {
|
||||
const pct = Number(firstAidSkillPercent) || 0;
|
||||
result = { success: rq3.removeStuckWeaponWithFirstAid(pct), weaponBreaks: false, removalType: 'first-aid' };
|
||||
} else {
|
||||
return res.status(400).json({ error: 'removalType must be attacker, self, or first-aid' });
|
||||
}
|
||||
|
||||
const outcome = result.weaponBreaks ? 'weapon breaks' : result.success ? 'weapon removed' : 'weapon stays stuck';
|
||||
dbApi.log.append({
|
||||
type: 'combat',
|
||||
summary: `Stuck-weapon removal (${removalType}, ${kind}): ${outcome}`,
|
||||
details: result,
|
||||
});
|
||||
|
||||
res.json({ combatState: dbApi.combat.get(), result });
|
||||
});
|
||||
|
||||
app.post('/api/combat/cast-spell', (req, res) => {
|
||||
const { casterCombatantId, targetCombatantId, mechanicId, mpSpent } = req.body || {};
|
||||
const current = dbApi.combat.get();
|
||||
|
||||
Reference in New Issue
Block a user