Various initiative fixes + shield management messages
All checks were successful
Release Creation / build (release) Successful in 46s
All checks were successful
Release Creation / build (release) Successful in 46s
This commit is contained in:
@@ -100,6 +100,14 @@ export class LethalFantasyCombat extends Combat {
|
||||
return this.turns = turns;
|
||||
}
|
||||
|
||||
async startCombat() {
|
||||
this._playCombatSound("startEncounter")
|
||||
const updateData = { round: 0, turn: 0 }
|
||||
Hooks.callAll("combatStart", this, updateData)
|
||||
await this.update(updateData)
|
||||
return this
|
||||
}
|
||||
|
||||
async rollInitiative(ids, options) {
|
||||
console.log("%%%%%%%%% Roll Initiative", ids, options);
|
||||
|
||||
@@ -110,13 +118,12 @@ export class LethalFantasyCombat extends Combat {
|
||||
let updates = [];
|
||||
for (let cId of ids) {
|
||||
const c = this.combatants.get(cId);
|
||||
let user = game.users.find(u => u.active && u.character && u.character.id === c.actor.id);
|
||||
if (user?.hasPlayerOwner) {
|
||||
const playerOwner = game.users.find(u => u.active && !u.isGM && u.character?.id === c.actor.id);
|
||||
if (game.user.isGM && playerOwner) {
|
||||
console.log("Rolling initiative for", c.actor.name);
|
||||
game.socket.emit(`system.${SYSTEM.id}`, { type: "rollInitiative", actorId: c.actor.id, combatId: this.id, combatantId: c.id });
|
||||
game.socket.emit(`system.${SYSTEM.id}`, { type: "rollInitiative", userId: playerOwner.id, actorId: c.actor.id, combatId: this.id, combatantId: c.id });
|
||||
} else {
|
||||
user = game.users.find(u => u.active && u.isGM);
|
||||
c.actor.system.rollInitiative(this.id, c.id);
|
||||
await c.actor.system.rollInitiative(this.id, c.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,12 +203,11 @@ export class LethalFantasyCombat extends Combat {
|
||||
|
||||
for (let c of this.combatants) {
|
||||
if (nextRound >= c.initiative) {
|
||||
let user = game.users.find(u => u.active && u.character && u.character.id === c.actor.id);
|
||||
if (user?.hasPlayerOwner) {
|
||||
game.socket.emit(`system.${SYSTEM.id}`, { type: "rollProgressionDice", progressionCount: c.system.progressionCount + 1, actorId: c.actor.id, combatId: this.id, combatantId: c.id });
|
||||
const playerOwner = game.users.find(u => u.active && !u.isGM && u.character?.id === c.actor.id);
|
||||
if (game.user.isGM && playerOwner) {
|
||||
game.socket.emit(`system.${SYSTEM.id}`, { type: "rollProgressionDice", userId: playerOwner.id, progressionCount: c.system.progressionCount + 1, actorId: c.actor.id, combatId: this.id, combatantId: c.id });
|
||||
} else {
|
||||
user = game.users.find(u => u.active && u.isGM);
|
||||
c.actor.system.rollProgressionDice(this.id, c.id);
|
||||
await c.actor.system.rollProgressionDice(this.id, c.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ export default class LethalFantasyActor extends Actor {
|
||||
}
|
||||
|
||||
/* *************************************************/
|
||||
async prepareRoll(rollType, rollKey, rollDice, defenderId, defenderTokenId) {
|
||||
async prepareRoll(rollType, rollKey, rollDice, defenderId, defenderTokenId, extraShieldDr = 0) {
|
||||
console.log("Preparing roll", rollType, rollKey, rollDice, defenderId)
|
||||
let rollTarget
|
||||
switch (rollType) {
|
||||
@@ -268,7 +268,7 @@ export default class LethalFantasyActor extends Actor {
|
||||
rollTarget.magicUser = this.system.biodata.magicUser
|
||||
rollTarget.actorModifiers = foundry.utils.duplicate(this.system.modifiers)
|
||||
rollTarget.actorLevel = this.system.biodata.level
|
||||
await this.system.roll(rollType, rollTarget, defenderId, defenderTokenId)
|
||||
await this.system.roll(rollType, rollTarget, defenderId, defenderTokenId, extraShieldDr)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -346,58 +346,73 @@ export default class LethalFantasyRoll extends Roll {
|
||||
favor: "none",
|
||||
targetName
|
||||
}
|
||||
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-dialog.hbs", dialogContext)
|
||||
let rollContext
|
||||
if (options.rollContext) {
|
||||
rollContext = foundry.utils.duplicate(options.rollContext)
|
||||
hasGrantedDice = !!rollContext.hasGrantedDice
|
||||
pointBlank = !!rollContext.pointBlank
|
||||
beyondSkill = !!rollContext.beyondSkill
|
||||
letItFly = !!rollContext.letItFly
|
||||
saveSpell = !!rollContext.saveSpell
|
||||
rollContext.visibility ||= rollContext.rollMode || game.settings.get("core", "rollMode")
|
||||
rollContext.modifier ||= modifier
|
||||
rollContext.favor ||= "none"
|
||||
rollContext.changeDice ||= `${dice}`
|
||||
rollContext.attackerAim ||= "0"
|
||||
} else {
|
||||
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-dialog.hbs", dialogContext)
|
||||
|
||||
let position = game.user.getFlag(SYSTEM.id, "roll-dialog-pos") || { top: -1, left: -1 }
|
||||
const label = game.i18n.localize("LETHALFANTASY.Roll.roll")
|
||||
const rollContext = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: "Roll dialog" },
|
||||
classes: ["lethalfantasy"],
|
||||
content,
|
||||
position,
|
||||
buttons: [
|
||||
{
|
||||
label: label,
|
||||
callback: (event, button, dialog) => {
|
||||
console.log("Roll context", event, button, dialog)
|
||||
let position = dialog.position
|
||||
game.user.setFlag(SYSTEM.id, "roll-dialog-pos", foundry.utils.duplicate(position))
|
||||
const output = Array.from(button.form.elements).reduce((obj, input) => {
|
||||
if (input.name) obj[input.name] = input.value
|
||||
return obj
|
||||
}, {})
|
||||
return output
|
||||
let position = game.user.getFlag(SYSTEM.id, "roll-dialog-pos") || { top: -1, left: -1 }
|
||||
const label = game.i18n.localize("LETHALFANTASY.Roll.roll")
|
||||
rollContext = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: "Roll dialog" },
|
||||
classes: ["lethalfantasy"],
|
||||
content,
|
||||
position,
|
||||
buttons: [
|
||||
{
|
||||
label: label,
|
||||
callback: (event, button, dialog) => {
|
||||
console.log("Roll context", event, button, dialog)
|
||||
let position = dialog.position
|
||||
game.user.setFlag(SYSTEM.id, "roll-dialog-pos", foundry.utils.duplicate(position))
|
||||
const output = Array.from(button.form.elements).reduce((obj, input) => {
|
||||
if (input.name) obj[input.name] = input.value
|
||||
return obj
|
||||
}, {})
|
||||
return output
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
actions: {
|
||||
"selectGranted": (event, button, dialog) => {
|
||||
hasGrantedDice = event.target.checked
|
||||
},
|
||||
"selectBeyondSkill": (event, button, dialog) => {
|
||||
beyondSkill = button.checked
|
||||
},
|
||||
"selectPointBlank": (event, button, dialog) => {
|
||||
pointBlank = button.checked
|
||||
},
|
||||
"selectLetItFly": (event, button, dialog) => {
|
||||
letItFly = button.checked
|
||||
},
|
||||
"saveSpellCheck": (event, button, dialog) => {
|
||||
saveSpell = button.checked
|
||||
},
|
||||
"gotoToken": (event, button, dialog) => {
|
||||
let tokenId = $(button).data("tokenId")
|
||||
let token = canvas.tokens?.get(tokenId)
|
||||
if (token) {
|
||||
canvas.animatePan({ x: token.x, y: token.y, duration: 200 })
|
||||
canvas.tokens.releaseAll();
|
||||
token.control({ releaseOthers: true });
|
||||
],
|
||||
actions: {
|
||||
"selectGranted": (event, button, dialog) => {
|
||||
hasGrantedDice = event.target.checked
|
||||
},
|
||||
"selectBeyondSkill": (event, button, dialog) => {
|
||||
beyondSkill = button.checked
|
||||
},
|
||||
"selectPointBlank": (event, button, dialog) => {
|
||||
pointBlank = button.checked
|
||||
},
|
||||
"selectLetItFly": (event, button, dialog) => {
|
||||
letItFly = button.checked
|
||||
},
|
||||
"saveSpellCheck": (event, button, dialog) => {
|
||||
saveSpell = button.checked
|
||||
},
|
||||
"gotoToken": (event, button, dialog) => {
|
||||
let tokenId = $(button).data("tokenId")
|
||||
let token = canvas.tokens?.get(tokenId)
|
||||
if (token) {
|
||||
canvas.animatePan({ x: token.x, y: token.y, duration: 200 })
|
||||
canvas.tokens.releaseAll()
|
||||
token.control({ releaseOthers: true })
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
rejectClose: false // Click on Close button will not launch an error
|
||||
})
|
||||
},
|
||||
rejectClose: false // Click on Close button will not launch an error
|
||||
})
|
||||
}
|
||||
|
||||
// If the user cancels the dialog, exit
|
||||
if (rollContext === null) return
|
||||
@@ -547,6 +562,10 @@ export default class LethalFantasyRoll extends Roll {
|
||||
rollFavor = null
|
||||
}
|
||||
|
||||
if (options.forceNoD30) {
|
||||
hasD30 = false
|
||||
}
|
||||
|
||||
if (hasD30) {
|
||||
let rollD30 = await new Roll("1D30").evaluate()
|
||||
if (game?.dice3d) {
|
||||
@@ -621,6 +640,7 @@ export default class LethalFantasyRoll extends Roll {
|
||||
rollBase.options.rollData = foundry.utils.duplicate(rollData)
|
||||
rollBase.options.defenderId = options.defenderId
|
||||
rollBase.options.defenderTokenId = options.defenderTokenId
|
||||
rollBase.options.extraShieldDr = options.extraShieldDr || 0
|
||||
|
||||
/**
|
||||
* A hook event that fires after the roll has been made.
|
||||
@@ -1296,7 +1316,7 @@ export default class LethalFantasyRoll extends Roll {
|
||||
* @returns {Promise} - A promise that resolves when the message is created.
|
||||
*/
|
||||
async toMessage(messageData = {}, { rollMode, create = true } = {}) {
|
||||
super.toMessage(
|
||||
return await super.toMessage(
|
||||
{
|
||||
isSave: this.isSave,
|
||||
isChallenge: this.isChallenge,
|
||||
@@ -1313,7 +1333,7 @@ export default class LethalFantasyRoll extends Roll {
|
||||
rollData: this.rollData,
|
||||
...messageData,
|
||||
},
|
||||
{ rollMode: rollMode },
|
||||
{ rollMode, create },
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
|
||||
* @param {"="|"+"|"++"|"-"|"--"} rollAdvantage If there is an avantage (+), a disadvantage (-), a double advantage (++), a double disadvantage (--) or a normal roll (=).
|
||||
* @returns {Promise<null>} - A promise that resolves to null if the roll is cancelled.
|
||||
*/
|
||||
async roll(rollType, rollTarget, defenderId, defenderTokenId) {
|
||||
async roll(rollType, rollTarget, defenderId, defenderTokenId, extraShieldDr = 0) {
|
||||
const hasTarget = false
|
||||
let roll = await LethalFantasyRoll.prompt({
|
||||
rollType,
|
||||
@@ -285,7 +285,8 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
|
||||
hasTarget,
|
||||
target: false,
|
||||
defenderId,
|
||||
defenderTokenId
|
||||
defenderTokenId,
|
||||
extraShieldDr
|
||||
})
|
||||
if (!roll) return null
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
||||
* @param {"="|"+"|"++"|"-"|"--"} rollAdvantage If there is an avantage (+), a disadvantage (-), a double advantage (++), a double disadvantage (--) or a normal roll (=).
|
||||
* @returns {Promise<null>} - A promise that resolves to null if the roll is cancelled.
|
||||
*/
|
||||
async roll(rollType, rollTarget, defenderId = undefined, defenderTokenId = undefined) {
|
||||
async roll(rollType, rollTarget, defenderId = undefined, defenderTokenId = undefined, extraShieldDr = 0) {
|
||||
const hasTarget = false
|
||||
let roll = await LethalFantasyRoll.prompt({
|
||||
rollType,
|
||||
@@ -152,14 +152,15 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
||||
hasTarget,
|
||||
target: false,
|
||||
defenderId,
|
||||
defenderTokenId
|
||||
defenderTokenId,
|
||||
extraShieldDr
|
||||
})
|
||||
if (!roll) return null
|
||||
|
||||
await roll.toMessage({}, { rollMode: roll.options.rollMode })
|
||||
}
|
||||
|
||||
async prepareMonsterRoll(rollType, rollKey, rollDice = undefined, tokenId = undefined, damageModifier = undefined, defenderId = undefined, defenderTokenId = undefined) {
|
||||
async prepareMonsterRoll(rollType, rollKey, rollDice = undefined, tokenId = undefined, damageModifier = undefined, defenderId = undefined, defenderTokenId = undefined, extraShieldDr = 0) {
|
||||
let rollTarget
|
||||
switch (rollType) {
|
||||
case "monster-attack":
|
||||
@@ -255,7 +256,7 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
||||
if (rollTarget) {
|
||||
rollTarget.tokenId = tokenId
|
||||
console.log(rollTarget)
|
||||
await this.roll(rollType, rollTarget, defenderId, defenderTokenId)
|
||||
await this.roll(rollType, rollTarget, defenderId, defenderTokenId, extraShieldDr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
136
module/utils.mjs
136
module/utils.mjs
@@ -124,10 +124,12 @@ export default class LethalFantasyUtils {
|
||||
}
|
||||
break
|
||||
case "rollInitiative":
|
||||
if (msg.userId && msg.userId !== game.user.id) break
|
||||
actor = game.actors.get(msg.actorId)
|
||||
actor.system.rollInitiative(msg.combatId, msg.combatantId)
|
||||
break
|
||||
case "rollProgressionDice":
|
||||
if (msg.userId && msg.userId !== game.user.id) break
|
||||
actor = game.actors.get(msg.actorId)
|
||||
actor.system.rollProgressionDice(msg.combatId, msg.combatantId, msg.rollProgressionCount)
|
||||
break
|
||||
@@ -190,6 +192,9 @@ export default class LethalFantasyUtils {
|
||||
const attackWeaponId = msg.attackWeaponId
|
||||
const attackRollType = msg.attackRollType
|
||||
const attackRollKey = msg.attackRollKey
|
||||
const attackD30result = msg.attackD30result
|
||||
const attackD30message = msg.attackD30message
|
||||
const attackRerollContext = msg.attackRerollContext
|
||||
const combatantId = msg.combatantId
|
||||
const tokenId = msg.tokenId
|
||||
|
||||
@@ -289,6 +294,9 @@ export default class LethalFantasyUtils {
|
||||
attackWeaponId,
|
||||
attackRollType,
|
||||
attackRollKey,
|
||||
attackD30result,
|
||||
attackD30message,
|
||||
attackRerollContext,
|
||||
defenderId: defender.id,
|
||||
defenderTokenId
|
||||
}
|
||||
@@ -358,6 +366,9 @@ export default class LethalFantasyUtils {
|
||||
attackWeaponId,
|
||||
attackRollType,
|
||||
attackRollKey,
|
||||
attackD30result,
|
||||
attackD30message,
|
||||
attackRerollContext,
|
||||
defenderId: defender.id,
|
||||
defenderTokenId
|
||||
}
|
||||
@@ -368,6 +379,114 @@ export default class LethalFantasyUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static hasD30Reroll(d30Message) {
|
||||
return /mulligan|re-?roll/i.test(d30Message || "")
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCombatBonusDiceChoices() {
|
||||
return ["1d4", "1d6", "1d8", "1d10", "1d12", "1d20", "1d20e"]
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getShieldReactionData(actor) {
|
||||
if (!actor) return null
|
||||
if (actor.type === "monster") {
|
||||
const formula = actor.system.combat?.shieldDefenseDice
|
||||
const damageReduction = actor.getShieldDR()
|
||||
if (!formula || damageReduction <= 0) return null
|
||||
return {
|
||||
label: game.i18n.localize("LETHALFANTASY.Label.shieldDefenseDice"),
|
||||
formula,
|
||||
damageReduction
|
||||
}
|
||||
}
|
||||
|
||||
const equippedShields = actor.items.filter(item => item.type === "shield" && item.system.equipped)
|
||||
if (equippedShields.length === 0) return null
|
||||
|
||||
const shield = equippedShields[0]
|
||||
return {
|
||||
label: shield.name,
|
||||
formula: shield.system.defense,
|
||||
damageReduction: actor.getShieldDR(),
|
||||
shieldId: shield.id
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async promptCombatBonusDie(actorName, sideLabel, currentRoll, opposingRoll) {
|
||||
const choices = this.getCombatBonusDiceChoices()
|
||||
const optionsHtml = choices.map(choice => `<option value="${choice}">${choice.toUpperCase()}</option>`).join("")
|
||||
const content = `
|
||||
<div class="grit-luck-dialog">
|
||||
<div class="combat-status">
|
||||
<p><strong>${actorName}</strong> currently has <strong>${currentRoll}</strong></p>
|
||||
<p>Opposing ${sideLabel} roll: <strong>${opposingRoll}</strong></p>
|
||||
</div>
|
||||
<div class="weapon-selection">
|
||||
<label for="bonus-die">Choose a bonus die:</label>
|
||||
<select id="bonus-die" name="bonusDie" style="width: 100%; margin-top: 8px;">
|
||||
${optionsHtml}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
|
||||
return await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: "Add Bonus Die" },
|
||||
classes: ["lethalfantasy"],
|
||||
content,
|
||||
buttons: [
|
||||
{
|
||||
label: "Roll Bonus Die",
|
||||
icon: "fa-solid fa-dice",
|
||||
callback: (event, button, dialog) => button.form.elements.bonusDie.value
|
||||
},
|
||||
{
|
||||
label: "Cancel",
|
||||
icon: "fa-solid fa-xmark",
|
||||
callback: () => null
|
||||
}
|
||||
],
|
||||
rejectClose: false
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async rollBonusDie(formula, actor, messageContent) {
|
||||
const roll = new Roll(formula)
|
||||
await roll.evaluate()
|
||||
if (game?.dice3d) {
|
||||
await game.dice3d.showForRoll(roll, game.user, true)
|
||||
}
|
||||
if (messageContent) {
|
||||
await ChatMessage.create({
|
||||
content: messageContent(roll.total, formula),
|
||||
speaker: ChatMessage.getSpeaker({ actor })
|
||||
})
|
||||
}
|
||||
return roll.total
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async rerollConfiguredRoll(rerollContext = {}) {
|
||||
const RollClass = CONFIG.Dice.rolls.find(r => r.name === "LethalFantasyRoll")
|
||||
if (typeof RollClass?.prompt !== "function") {
|
||||
ui.notifications.error("Lethal Fantasy roll class not available for reroll")
|
||||
return null
|
||||
}
|
||||
|
||||
return await RollClass.prompt({
|
||||
...foundry.utils.duplicate(rerollContext),
|
||||
rollContext: foundry.utils.duplicate(rerollContext.rollContext || {}),
|
||||
forceNoD30: true,
|
||||
hasTarget: false,
|
||||
target: false
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async offerGritLuckBonus(defender, attackRoll, currentDefenseRoll, attackerName, defenderName) {
|
||||
let totalBonus = 0
|
||||
@@ -538,7 +657,8 @@ export default class LethalFantasyUtils {
|
||||
/* -------------------------------------------- */
|
||||
static async compareAttackDefense(data) {
|
||||
console.log("compareAttackDefense called with:", data)
|
||||
const isAttackWin = data.attackRoll > data.defenseRoll
|
||||
const outcome = data.outcome || (data.attackRoll > data.defenseRoll ? "hit" : "miss")
|
||||
const isAttackWin = outcome !== "miss"
|
||||
console.log("isAttackWin:", isAttackWin, "attackRoll:", data.attackRoll, "defenseRoll:", data.defenseRoll)
|
||||
|
||||
let damageButton = ""
|
||||
@@ -548,10 +668,10 @@ export default class LethalFantasyUtils {
|
||||
if (data.attackRollType === "weapon-attack") {
|
||||
damageButton = `
|
||||
<div class="attack-result-damage">
|
||||
<button class="roll-damage-btn" data-attacker-id="${data.attackerId}" data-defender-id="${data.defenderId}" data-defender-token-id="${data.defenderTokenId || ""}" data-weapon-id="${data.attackWeaponId}" data-damage-type="small">
|
||||
<button class="roll-damage-btn" data-attacker-id="${data.attackerId}" data-defender-id="${data.defenderId}" data-defender-token-id="${data.defenderTokenId || ""}" data-extra-shield-dr="${data.shieldDamageReduction || 0}" data-weapon-id="${data.attackWeaponId}" data-damage-type="small">
|
||||
<i class="fa-solid fa-dice-d6"></i> Damage (Small)
|
||||
</button>
|
||||
<button class="roll-damage-btn" data-attacker-id="${data.attackerId}" data-defender-id="${data.defenderId}" data-defender-token-id="${data.defenderTokenId || ""}" data-weapon-id="${data.attackWeaponId}" data-damage-type="medium">
|
||||
<button class="roll-damage-btn" data-attacker-id="${data.attackerId}" data-defender-id="${data.defenderId}" data-defender-token-id="${data.defenderTokenId || ""}" data-extra-shield-dr="${data.shieldDamageReduction || 0}" data-weapon-id="${data.attackWeaponId}" data-damage-type="medium">
|
||||
<i class="fa-solid fa-dice-d20"></i> Damage (Medium)
|
||||
</button>
|
||||
</div>
|
||||
@@ -559,7 +679,7 @@ export default class LethalFantasyUtils {
|
||||
} else if (data.attackRollType === "monster-attack") {
|
||||
damageButton = `
|
||||
<div class="attack-result-damage">
|
||||
<button class="roll-damage-btn" data-attacker-id="${data.attackerId}" data-defender-id="${data.defenderId}" data-defender-token-id="${data.defenderTokenId || ""}" data-attack-key="${data.attackRollKey}" data-damage-type="monster">
|
||||
<button class="roll-damage-btn" data-attacker-id="${data.attackerId}" data-defender-id="${data.defenderId}" data-defender-token-id="${data.defenderTokenId || ""}" data-extra-shield-dr="${data.shieldDamageReduction || 0}" data-attack-key="${data.attackRollKey}" data-damage-type="monster">
|
||||
<i class="fa-solid fa-burst"></i> Damage
|
||||
</button>
|
||||
</div>
|
||||
@@ -588,9 +708,11 @@ export default class LethalFantasyUtils {
|
||||
</div>
|
||||
</div>
|
||||
<div class="combat-result-text">
|
||||
${isAttackWin ?
|
||||
`<i class="fa-solid fa-circle-check"></i> <strong>${data.attackerName}</strong> hits <strong>${data.defenderName}</strong>!` :
|
||||
`<i class="fa-solid fa-shield-halved"></i> <strong>${data.defenderName}</strong> parries the attack!`
|
||||
${outcome === "shielded-hit"
|
||||
? `<i class="fa-solid fa-shield"></i> <strong>${data.attackerName}</strong> still hits <strong>${data.defenderName}</strong>, but shield DR <strong>${data.shieldDamageReduction || 0}</strong> reduces the damage.`
|
||||
: isAttackWin
|
||||
? `<i class="fa-solid fa-circle-check"></i> <strong>${data.attackerName}</strong> hits <strong>${data.defenderName}</strong>!`
|
||||
: `<i class="fa-solid fa-shield-halved"></i> <strong>${data.defenderName}</strong> parries the attack!`
|
||||
}
|
||||
</div>
|
||||
${damageButton}
|
||||
|
||||
Reference in New Issue
Block a user