Update fight options
All checks were successful
Release Creation / build (release) Successful in 53s

This commit is contained in:
2025-11-11 19:56:33 +01:00
parent 8d9cc1045c
commit 68a0d03740
30 changed files with 406 additions and 213 deletions

View File

@@ -205,6 +205,7 @@
"Struggle": "Struggle"
},
"Skill": {
"DodgeName": "Dodge",
"Unnatural": "Unnatural",
"Melee": "Melee Weapons",
"Firearms": "Firearms",
@@ -552,6 +553,10 @@
}
},
"Label": {
"noTarget": "No target selected",
"noDefenseRoll": "No defense roll available",
"opposedRoll": "Opposed Roll",
"Target": "Target",
"sanLoss5": "You suffered a SAN loss of 5+ ({value}) : you suffer a temporary insanity (Flee, Submit, Struggle or understanding the Unnatural).",
"sanViolenceReset": "The violence SAN loss count has been reset.",
"sanHelplessnessReset": "The helplessness SAN loss count has been reset.",
@@ -761,6 +766,7 @@
"woundsApplied": "Wounds applied to {name}: {effectiveWounds} (armor absorbed : {armorText})"
},
"Notifications": {
"AttackNoTarget": "No target selected for the attack, please select one target to get automations.",
"NoWeaponSkill": "No weapon skill found for this weapon. Check Weapon definition or available skills/era",
"NoWeaponType": "No weapon type found for this weapon subtype. Check Weapon definition or available skills/era",
"skillAlreadyExists": "Skill already exists",

View File

@@ -217,6 +217,7 @@
"Struggle": "Lutter"
},
"Skill": {
"DodgeName": "Esquive",
"Unnatural": "Inconcevable",
"Melee": "Armes de mêlée",
"Firearms": "Armes à feu",
@@ -564,6 +565,10 @@
}
},
"Label": {
"noTarget": "Aucune cible sélectionnée",
"noDefenseRoll": "Aucun jet de défense existant",
"opposedRoll": "Jet opposé",
"Target": "Cible",
"feet": "pieds (ie 30cm)",
"feets": "pieds (ie 30cm)",
"yard": "mètres",
@@ -782,6 +787,7 @@
"woundsApplied": "Blessures appliquées à {name} : {effectiveWounds} (armure absorbée : {armorText})"
},
"Notifications": {
"AttackNoTarget": "Aucune cible n'a été sélectionnée pour cette attaque, veuillez sélectionner une cible pour bénéficier des automatisations.",
"NoWeaponSkill": "Aucune compétence associée n'a été trouvé pour cette arme. Vérifier la définition de l'arme ainsi que l'époque configurée.",
"NoWeaponType": "Aucun type d'arme trouvé pour ce sous-type. Vérifier la définition de l'arme ainsi que l'époque configurée.",
"skillAlreadyExists": "La compétence existe déja",

View File

@@ -25,7 +25,7 @@ export default class CthulhuEternalActor extends Actor {
}
data.items.push({
type: "weapon", img: "systems/fvtt-cthulhu-eternal/assets/icons/icon_fist.svg",
name: game.i18n.localize("CTHULHUETERNAL.Label.Unarmed"), system: { damage: "1d4-1", weaponType: "unarmed" }
name: game.i18n.localize("CTHULHUETERNAL.Label.Unarmed"), system: { damage: "1d4-1", weaponType: "unarmed", applyDamageBonus: true }
})
}
@@ -45,8 +45,15 @@ export default class CthulhuEternalActor extends Actor {
return super._onUpdate(changed, options, userId)
}
setLastDefenseRoll(rollData) {
this.setFlag("fvtt-cthulhu-eternal", "last-defense-roll", rollData)
}
getLastDefenseRoll() {
return this.getFlag("fvtt-cthulhu-eternal", "last-defense-roll")
}
applyWounds(woundData) {
let updates = {}
// Get available armor
let armors = this.items.filter(i => i.type === "armor" && i.system.equipped)
let totalArmor = 0
@@ -60,10 +67,7 @@ export default class CthulhuEternalActor extends Actor {
// Apply armor reduction
let hp = Math.max(this.system.hp.value - effectiveWounds, 0)
if (this.system.hp.value !== hp) {
updates[`system.hp.value`] = hp
}
if (Object.keys(updates).length > 0) {
this.update(updates)
this.update({ "system.hp.value": hp })
}
// Chat message for GM only
if (game.user.isGM) {

View File

@@ -1,5 +1,6 @@
import { SYSTEM } from "../config/system.mjs"
import CthulhuEternalUtils from "../utils.mjs"
export default class CthulhuEternalRoll extends Roll {
/**
@@ -128,29 +129,21 @@ export default class CthulhuEternalRoll extends Roll {
static async processWeaponDamage(actor, options) {
let isLethal = false
let weapon = options.rollItem
let ammoUsed = weapon.system.weaponType.includes("ranged") ? 1 : 0 // Default ammo used for melee weapons is 0
options.isNudge = false
// Selective fire management
if (weapon.system.hasSelectiveFire && weapon.selectiveFireChoice) {
let choice = SYSTEM.WEAPON_SELECTIVE_FIRE_CHOICES[weapon.selectiveFireChoice]
if (choice.ammoUsed > weapon.system.ammo.value) {
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.NoAmmo"))
return
}
weapon.system.selectiveFireChoiceLabel = choice.label // Store the choice in the weapon
weapon.system.lethality = choice.lethality // Override lethality
weapon.system.killRadius = choice.killRadius // Override kill radius
ammoUsed = choice.ammoUsed // Override ammo used
}
ammoUsed = Number(ammoUsed)
let combatants = []
if (game?.combat?.combatants) {
for (let c of game.combat.combatants) {
if (c.actor.id !== actor.id) {
combatants.push({ id: c.actor.id, name: c.name })
combatants.push({ id: c.id, name: c.name })
}
}
}
@@ -160,12 +153,6 @@ export default class CthulhuEternalRoll extends Roll {
await lethalityRoll.evaluate()
let lethalScore = (options?.previousResultType === "successCritical") ? weapon.system.lethality * 2 : weapon.system.lethality
isLethal = (lethalityRoll.total <= lethalScore)
if (ammoUsed > 0) {
await actor.updateEmbeddedDocuments("Item", [{
_id: weapon._id,
"system.ammo.value": Math.max(0, weapon.system.ammo.value - ammoUsed)
}])
}
let wounds = Math.floor(lethalityRoll.total / 10) + (lethalityRoll.total % 10)
let msgData = {
actorId: actor.id,
@@ -173,7 +160,7 @@ export default class CthulhuEternalRoll extends Roll {
wounds,
lethalScore,
isLethal,
ammoUsed,
ammoUsed: weapon?.ammoUsed || 0,
rollResult: lethalityRoll.total,
combatants: combatants
}
@@ -195,12 +182,6 @@ export default class CthulhuEternalRoll extends Roll {
if (options?.previousResultType === "successCritical") {
formula = `( ${formula} ) * 2`
}
if (ammoUsed > 0) {
await actor.updateEmbeddedDocuments("Item", [{
_id: weapon._id,
"system.ammo.value": Math.max(0, weapon.system.ammo.value - ammoUsed)
}])
}
let damageRoll = new Roll(formula)
await damageRoll.evaluate()
@@ -208,7 +189,7 @@ export default class CthulhuEternalRoll extends Roll {
actorId: actor.id,
weapon,
formula,
ammoUsed,
ammoUsed: weapon?.ammoUsed || 0,
rollResult: damageRoll.total,
combatants: combatants
}
@@ -234,6 +215,27 @@ export default class CthulhuEternalRoll extends Roll {
return modifier
}
static async processAmmoUsed(actor, weapon) {
let ammoUsed = weapon.system.weaponType.includes("ranged") ? 1 : 0 // Default ammo used for melee weapons is 0
// Selective fire management
if (weapon.system.hasSelectiveFire && weapon.selectiveFireChoice) {
let choice = SYSTEM.WEAPON_SELECTIVE_FIRE_CHOICES[weapon.selectiveFireChoice]
if (choice.ammoUsed > weapon.system.ammo.value) {
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.NoAmmo"))
return
}
ammoUsed = choice.ammoUsed // Override ammo used
}
ammoUsed = Number(ammoUsed)
if (ammoUsed > 0) {
await actor.updateEmbeddedDocuments("Item", [{
_id: weapon._id,
"system.ammo.value": Math.max(0, weapon.system.ammo.value - ammoUsed)
}])
}
weapon.ammoUsed = ammoUsed
}
/**
* Prompt the user with a dialog to configure and execute a roll.
*
@@ -255,9 +257,10 @@ export default class CthulhuEternalRoll extends Roll {
options.isNudge = true
let actor = game.actors.get(options.actorId)
let target = CthulhuEternalUtils.getTarget()
switch (options.rollType) {
case "skill":
console.log(options.rollItem)
options.initialScore = options.rollItem.system.computeScore()
break
case "luck":
@@ -295,12 +298,16 @@ export default class CthulhuEternalRoll extends Roll {
console.log("WP Not found", era, options.rollItem.system.weaponType)
return
}
if (!target) {
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.AttackNoTarget"))
}
// Check if the weapon has enouth ammo in case of a firearm
if (options.rollItem.system.isFireArm() && options.rollItem.system.ammo.value <= 0) {
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.NoAmmo"))
return
}
options.weapon = options.rollItem
if (options.rollItem.system.hasDirectSkill) {
let skillName = options.rollItem.name
options.rollItem = { type: "skill", name: skillName, system: { base: 0, bonus: options.weapon.system.directSkillValue } }
@@ -371,6 +378,7 @@ export default class CthulhuEternalRoll extends Roll {
aimingWithSight: false,
modifier,
formula,
targetName: target?.name,
hasTarget: options.hasTarget,
hasModifier,
hasMultiplier,
@@ -423,10 +431,14 @@ export default class CthulhuEternalRoll extends Roll {
if (rollContext === null) return
let rollData = foundry.utils.mergeObject(foundry.utils.duplicate(options), rollContext)
// If we have a target, get its data
rollData.targetId = target?.id
rollData.targetName = target?.name
rollData.rollMode = rollContext.visibility
// Update target score
console.log("Rolldata", rollData, options)
console.log("Rolldata", rollData)
if (options.rollType === "resource") {
rollData.targetScore = options.initialScore * Number(rollContext.multiplier)
} else {
@@ -446,6 +458,10 @@ export default class CthulhuEternalRoll extends Roll {
rollData.modifier = "0"
}
if (options.rollType === "weapon") {
await this.processAmmoUsed(actor, rollData.weapon)
}
if (Hooks.call("fvtt-cthulhu-eternal.preRoll", options, rollData) === false) return
const roll = new this(formula, options.data, rollData)
@@ -506,7 +522,64 @@ export default class CthulhuEternalRoll extends Roll {
this.options.isLowWP = rollData.isLowWP
this.options.isZeroWP = rollData.isZeroWP
this.options.isExhausted = rollData.isExhausted
rollData.isSuccess = this.options.isSuccess
rollData.isFailure = this.options.isFailure
rollData.isCritical = this.options.isCritical
rollData.resultType = resultType
this.options.rollData = foundry.utils.duplicate(rollData)
// Keep track of the last defense roll for the actor
if (game.combat && (rollData?.weapon?.system.type === "melee" || (rollData?.rollItem.type === "skill" && rollData?.rollItem.name?.toLowerCase().includes(game.i18n.localize("CTHULHUETERNAL.Skill.dodgeName").toLowerCase())))) {
let actor = game.actors.get(options.actorId)
rollData.round = game.combat.round
actor.setLastDefenseRoll(foundry.utils.duplicate(rollData))
}
if (game.combat && rollData?.weapon) { // An attack roll
rollData.isAttackRoll = true
}
// Now check if we have a target for the current roll, and if the target has done its defense roll this round
if (rollData.targetId) {
let token = game.scenes.current.tokens.get(rollData.targetId)
let defender = token.actor
let lastDefenseRoll = defender?.getLastDefenseRoll()
// Now compare opposition
this.compareRolls(rollData, lastDefenseRoll)
rollData.defenseRoll = lastDefenseRoll
}
}
compareRolls(attackRoll, defenseRoll) {
if (!defenseRoll || defenseRoll.round !== game?.combat?.round) {
ui.notifications.info(game.i18n.localize("CTHULHUETERNAL.Notifications.NoDefenseRoll"))
return
}
if (attackRoll.isFailure) {
attackRoll.attackSucess = false
}
if (attackRoll.isSuccess && defenseRoll.isFailure) {
attackRoll.attackSucess = true
}
if (attackRoll.isSuccess && defenseRoll.isSuccess) {
if (attackRoll.isCritical && !defenseRoll.isCritical) {
attackRoll.attackSucess = true
}
else if (!attackRoll.isCritical && defenseRoll.isCritical) {
attackRoll.attackSucess = false
}
else {
// Both are normal success, compare the roll results
if (attackRoll.total >= defenseRoll.total) {
// Attack successful
attackRoll.attackSucess = true
} else {
// Defense successful
attackRoll.attackSucess = false
}
}
}
}
/**

View File

@@ -375,6 +375,15 @@ export default class CthulhuEternalUtils {
document.documentElement.style.setProperty('--background-image-base', `linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8)), url("../assets/ui/${era}_background_main.webp")`);
}
static getTarget() {
if (game.user.targets && game.user.targets.size === 1) {
for (let target of game.user.targets) {
return target
}
}
return undefined;
}
static applyWounds(message, event) {
let woundData = message.getFlag("fvtt-cthulhu-eternal", "woundData")
if (!woundData) {
@@ -387,10 +396,11 @@ export default class CthulhuEternalUtils {
return
}
// Get the targetted actorId from the HTML select event
let targetActorId = event.target.value
let targetActor = game.actors.get(targetActorId)
let targetCombatantId = event.target.value
let combatant = game.combat.combatants.get(targetCombatantId)
let targetActor = combatant.token?.actor || game.actors.get(combatant.actorId)
if (!targetActor) {
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noTargetActorFound") + targetActorId)
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noTargetActorFound") + targetCombatantId)
return
}
targetActor.applyWounds(woundData)

Binary file not shown.

View File

View File

@@ -1 +1 @@
MANIFEST-000249
MANIFEST-000261

View File

@@ -1,7 +1,7 @@
2025/10/01-10:24:47.689741 7fc4987f86c0 Recovering log #246
2025/10/01-10:24:47.787870 7fc4987f86c0 Delete type=3 #244
2025/10/01-10:24:47.787986 7fc4987f86c0 Delete type=0 #246
2025/10/01-11:24:12.555415 7fc497ff76c0 Level-0 table #252: started
2025/10/01-11:24:12.555461 7fc497ff76c0 Level-0 table #252: 0 bytes OK
2025/10/01-11:24:12.565317 7fc497ff76c0 Delete type=0 #250
2025/10/01-11:24:12.577205 7fc497ff76c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
2025/10/08-22:08:44.664871 7f77151f96c0 Recovering log #259
2025/10/08-22:08:44.675676 7f77151f96c0 Delete type=3 #257
2025/10/08-22:08:44.675773 7f77151f96c0 Delete type=0 #259
2025/10/08-23:43:02.763720 7f770f3ff6c0 Level-0 table #264: started
2025/10/08-23:43:02.763751 7f770f3ff6c0 Level-0 table #264: 0 bytes OK
2025/10/08-23:43:02.770330 7f770f3ff6c0 Delete type=0 #262
2025/10/08-23:43:02.770574 7f770f3ff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)

View File

@@ -1,11 +1,7 @@
2025/10/01-09:23:25.493413 7fc499ffb6c0 Delete type=3 #1
2025/10/01-09:24:30.037985 7fc497ff76c0 Level-0 table #247: started
2025/10/01-09:24:30.038031 7fc497ff76c0 Level-0 table #247: 0 bytes OK
2025/10/01-09:24:30.044462 7fc497ff76c0 Delete type=0 #245
2025/10/01-09:24:30.069660 7fc497ff76c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at '!items!zVFfp3o0G0Zg3Ia4' @ 52 : 1
2025/10/01-09:24:30.069672 7fc497ff76c0 Compacting 1@0 + 0@1 files
2025/10/01-09:24:30.073695 7fc497ff76c0 Generated table #248@0: 26 keys, 60964 bytes
2025/10/01-09:24:30.073722 7fc497ff76c0 Compacted 1@0 + 0@1 files => 60964 bytes
2025/10/01-09:24:30.080151 7fc497ff76c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/10/01-09:24:30.080234 7fc497ff76c0 Delete type=2 #242
2025/10/01-09:24:30.086925 7fc497ff76c0 Manual compaction at level-0 from '!items!zVFfp3o0G0Zg3Ia4' @ 52 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
2025/10/01-17:34:00.770173 7fc4987f86c0 Recovering log #255
2025/10/01-17:34:00.786532 7fc4987f86c0 Delete type=3 #253
2025/10/01-17:34:00.786591 7fc4987f86c0 Delete type=0 #255
2025/10/01-20:52:25.677932 7fc497ff76c0 Level-0 table #260: started
2025/10/01-20:52:25.677997 7fc497ff76c0 Level-0 table #260: 0 bytes OK
2025/10/01-20:52:26.027584 7fc497ff76c0 Delete type=0 #258
2025/10/01-20:52:26.508239 7fc497ff76c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)

Binary file not shown.

View File

Binary file not shown.

View File

View File

@@ -1 +1 @@
MANIFEST-000418
MANIFEST-000430

View File

@@ -1,7 +1,7 @@
2025/10/01-10:24:47.499257 7fc4997fa6c0 Recovering log #415
2025/10/01-10:24:47.596647 7fc4997fa6c0 Delete type=3 #413
2025/10/01-10:24:47.596724 7fc4997fa6c0 Delete type=0 #415
2025/10/01-11:24:12.545465 7fc497ff76c0 Level-0 table #421: started
2025/10/01-11:24:12.545499 7fc497ff76c0 Level-0 table #421: 0 bytes OK
2025/10/01-11:24:12.555310 7fc497ff76c0 Delete type=0 #419
2025/10/01-11:24:12.577192 7fc497ff76c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
2025/10/08-22:08:44.633139 7f77159fa6c0 Recovering log #428
2025/10/08-22:08:44.643368 7f77159fa6c0 Delete type=3 #426
2025/10/08-22:08:44.643480 7f77159fa6c0 Delete type=0 #428
2025/10/08-23:43:02.756716 7f770f3ff6c0 Level-0 table #433: started
2025/10/08-23:43:02.756789 7f770f3ff6c0 Level-0 table #433: 0 bytes OK
2025/10/08-23:43:02.763557 7f770f3ff6c0 Delete type=0 #431
2025/10/08-23:43:02.770557 7f770f3ff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)

View File

@@ -1,11 +1,7 @@
2025/10/01-09:23:25.444068 7fc499ffb6c0 Delete type=3 #1
2025/10/01-09:24:30.024822 7fc497ff76c0 Level-0 table #416: started
2025/10/01-09:24:30.024870 7fc497ff76c0 Level-0 table #416: 0 bytes OK
2025/10/01-09:24:30.030665 7fc497ff76c0 Delete type=0 #414
2025/10/01-09:24:30.044587 7fc497ff76c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at '!items!zvoUByzWSWZ87fxA' @ 1281 : 1
2025/10/01-09:24:30.044598 7fc497ff76c0 Compacting 1@0 + 0@1 files
2025/10/01-09:24:30.051264 7fc497ff76c0 Generated table #417@0: 556 keys, 320457 bytes
2025/10/01-09:24:30.051285 7fc497ff76c0 Compacted 1@0 + 0@1 files => 320457 bytes
2025/10/01-09:24:30.058278 7fc497ff76c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/10/01-09:24:30.058439 7fc497ff76c0 Delete type=2 #411
2025/10/01-09:24:30.086897 7fc497ff76c0 Manual compaction at level-0 from '!items!zvoUByzWSWZ87fxA' @ 1281 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
2025/10/01-17:34:00.727436 7fc499ffb6c0 Recovering log #424
2025/10/01-17:34:00.744993 7fc499ffb6c0 Delete type=3 #422
2025/10/01-17:34:00.745065 7fc499ffb6c0 Delete type=0 #424
2025/10/01-20:52:26.571766 7fc497ff76c0 Level-0 table #429: started
2025/10/01-20:52:26.571816 7fc497ff76c0 Level-0 table #429: 0 bytes OK
2025/10/01-20:52:26.607301 7fc497ff76c0 Delete type=0 #427
2025/10/01-20:52:26.607477 7fc497ff76c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)

Binary file not shown.

View File

Binary file not shown.

View File

View File

@@ -1 +1 @@
MANIFEST-000064
MANIFEST-000076

View File

@@ -1,7 +1,7 @@
2025/10/01-10:24:47.601344 7fc499ffb6c0 Recovering log #61
2025/10/01-10:24:47.686801 7fc499ffb6c0 Delete type=3 #59
2025/10/01-10:24:47.686869 7fc499ffb6c0 Delete type=0 #61
2025/10/01-11:24:12.535658 7fc497ff76c0 Level-0 table #67: started
2025/10/01-11:24:12.535725 7fc497ff76c0 Level-0 table #67: 0 bytes OK
2025/10/01-11:24:12.545352 7fc497ff76c0 Delete type=0 #65
2025/10/01-11:24:12.577171 7fc497ff76c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)
2025/10/08-22:08:44.648914 7f770ffff6c0 Recovering log #74
2025/10/08-22:08:44.660220 7f770ffff6c0 Delete type=3 #72
2025/10/08-22:08:44.660388 7f770ffff6c0 Delete type=0 #74
2025/10/08-23:43:02.832863 7f770f3ff6c0 Level-0 table #79: started
2025/10/08-23:43:02.832918 7f770f3ff6c0 Level-0 table #79: 0 bytes OK
2025/10/08-23:43:02.839997 7f770f3ff6c0 Delete type=0 #77
2025/10/08-23:43:02.852551 7f770f3ff6c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)

View File

@@ -1,11 +1,7 @@
2025/10/01-09:23:25.469063 7fc499ffb6c0 Delete type=3 #1
2025/10/01-09:24:30.030754 7fc497ff76c0 Level-0 table #62: started
2025/10/01-09:24:30.030783 7fc497ff76c0 Level-0 table #62: 0 bytes OK
2025/10/01-09:24:30.037809 7fc497ff76c0 Delete type=0 #60
2025/10/01-09:24:30.058634 7fc497ff76c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at '!items!zyxA9DhO36t5OBDv' @ 55 : 1
2025/10/01-09:24:30.058646 7fc497ff76c0 Compacting 1@0 + 0@1 files
2025/10/01-09:24:30.063565 7fc497ff76c0 Generated table #63@0: 362 keys, 93592 bytes
2025/10/01-09:24:30.063591 7fc497ff76c0 Compacted 1@0 + 0@1 files => 93592 bytes
2025/10/01-09:24:30.069446 7fc497ff76c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/10/01-09:24:30.069529 7fc497ff76c0 Delete type=2 #57
2025/10/01-09:24:30.086915 7fc497ff76c0 Manual compaction at level-0 from '!items!zyxA9DhO36t5OBDv' @ 55 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)
2025/10/01-17:34:00.750882 7fc4997fa6c0 Recovering log #70
2025/10/01-17:34:00.765634 7fc4997fa6c0 Delete type=3 #68
2025/10/01-17:34:00.765703 7fc4997fa6c0 Delete type=0 #70
2025/10/01-20:52:26.472838 7fc497ff76c0 Level-0 table #75: started
2025/10/01-20:52:26.472892 7fc497ff76c0 Level-0 table #75: 0 bytes OK
2025/10/01-20:52:26.508046 7fc497ff76c0 Delete type=0 #73
2025/10/01-20:52:26.508280 7fc497ff76c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)

Binary file not shown.

View File

View File

@@ -6,7 +6,7 @@
"download": "#{DOWNLOAD}#",
"url": "https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal",
"license": "LICENSE",
"version": "13.0.1",
"version": "13.0.2",
"authors": [
{
"name": "Uberwald",

View File

@@ -7,125 +7,218 @@
<div class="intro-right">
<ul>
{{#if (eq rollType "char")}}
<li><strong>{{localize "CTHULHUETERNAL.Label.charRoll"}}</strong></li>
<li><strong>{{localize "CTHULHUETERNAL.Label.charRoll"}}</strong></li>
{{/if}}
{{#if (eq rollType "skill")}}
<li><strong>{{localize "CTHULHUETERNAL.Label.skillRoll"}}</strong></li>
<li><strong>{{localize
"CTHULHUETERNAL.Label.skillRoll"
}}</strong></li>
{{/if}}
{{#if isNudgedRoll}}
<li><strong>{{localize "CTHULHUETERNAL.Label.nudgedRoll"}} : {{wpCost}} {{localize "CTHULHUETERNAL.Label.WPSpent"}}</strong></li>
<li><strong>{{localize "CTHULHUETERNAL.Label.nudgedRoll"}}
:
{{wpCost}}
{{localize "CTHULHUETERNAL.Label.WPSpent"}}</strong></li>
{{/if}}
{{#if weapon}}
<li><strong>{{localize "CTHULHUETERNAL.Label.Weapon"}} : {{weapon.name}}</strong></li>
<li><strong>{{localize "CTHULHUETERNAL.Label.Weapon"}}
:
{{weapon.name}}</strong></li>
{{/if}}
{{#if (eq rollType "resource")}}
<li><strong>{{rollItem.name}} : {{initialScore}}</strong></li>
<li><strong>{{rollItem.name}} : {{initialScore}}</strong></li>
{{else}}
<li><strong>{{rollItem.name}} : {{initialScore}}%</strong></li>
<li><strong>{{rollItem.name}} : {{initialScore}}%</strong></li>
{{/if}}
{{#if isZeroWP}}
<li class="red-warning">{{localize "CTHULHUETERNAL.Label.ZeroWP"}}</li>
<li class="red-warning">{{localize
"CTHULHUETERNAL.Label.ZeroWP"
}}</li>
{{else}}
{{#if isLowWP}}
<li class="orange-warning">{{localize "CTHULHUETERNAL.Label.LowWP"}} : -20%</li>
{{/if}}
{{#if isLowWP}}
<li class="orange-warning">{{localize "CTHULHUETERNAL.Label.LowWP"}}
: -20%</li>
{{/if}}
{{/if}}
{{#if isExhausted}}
<li class="orange-warning">{{localize "CTHULHUETERNAL.Label.Exhausted"}} : -20%</li>
<li class="orange-warning">{{localize
"CTHULHUETERNAL.Label.Exhausted"
}}
: -20%</li>
{{/if}}
{{#if (eq rollType "resource")}}
<li>{{localize "CTHULHUETERNAL.Label.multiplier"}} : {{multiplier}}</li>
{{#if (eq rollType "resource")}}
<li>{{localize "CTHULHUETERNAL.Label.multiplier"}}
:
{{multiplier}}</li>
{{else}}
<li>{{localize "CTHULHUETERNAL.Label.modifier"}} : {{totalModifier}}%</li>
<li>{{localize "CTHULHUETERNAL.Label.modifier"}}
:
{{totalModifier}}%</li>
{{/if}}
<li>{{localize "CTHULHUETERNAL.Label.targetScore"}} : {{targetScore}}%</li>
<li>{{localize "CTHULHUETERNAL.Label.targetScore"}}
:
{{targetScore}}%</li>
{{#if isSuccess}}
{{#if isCritical}}
<li class="result-critical-success">{{localize "CTHULHUETERNAL.Label.criticalSuccess"}}
<li class="result-critical-success">{{localize
"CTHULHUETERNAL.Label.criticalSuccess"
}}
</li>
{{else}}
<li class="result-success">
{{localize "CTHULHUETERNAL.Label.success"}}
{{#if isNudge}}
<a class="nudge-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollNudge"}}"><i class="fa-solid fa-circle-sort-down"></i></a>
{{/if}}
<li class="result-success">
{{localize "CTHULHUETERNAL.Label.success"}}
{{#if isNudge}}
<a
class="nudge-roll"
data-tooltip="{{localize ' CTHULHUETERNAL.Label.rollNudge'}}"
><i class="fa-solid fa-circle-sort-down"></i></a>
{{/if}}
</li>
</li>
{{/if}}
{{#if (eq rollType "weapon")}}
<li>
{{#if (eq rollType "weapon")}}
<li>
{{#if (eq weapon.system.weaponType "rangedfirearm")}}
{{#if weapon.system.hasDamageDistance}}
{{#each weapon.system.damageDistance as |damageDistance|}}
{{#if (gt damageDistance.distance 0)}}
<a class="damage-roll" data-item-id="{{weapon.id}}" data-action="roll" data-roll-type="damage"
data-roll-value="{{damageDistance.damage}}" >
<i class="fa-solid fa-gun"></i>
<span class="damage-distance">{{damageDistance.distance}}:{{damageDistance.damage}}&nbsp;&nbsp;</span>
</a>
<a
class="damage-roll"
data-item-id="{{weapon.id}}"
data-action="roll"
data-roll-type="damage"
data-roll-value="{{damageDistance.damage}}"
>
<i class="fa-solid fa-gun"></i>
<span
class="damage-distance"
>{{damageDistance.distance}}:{{damageDistance.damage}}&nbsp;&nbsp;</span>
</a>
{{/if}}
{{/each}}
{{else}}
<a class="damage-roll" data-roll-value="{{weapon.system.damage}}" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-gun"></i></a>
<a
class="damage-roll"
data-roll-value="{{weapon.system.damage}}"
data-tooltip="{{localize
'
CTHULHUETERNAL.Label.rollDamage'
}}"
><i class="fa-solid fa-gun"></i></a>
{{/if}}
{{else}}
<a class="damage-roll" data-roll-value="{{weapon.system.damage}}" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-sword"></i></a>
<a
class="damage-roll"
data-roll-value="{{weapon.system.damage}}"
data-tooltip="{{localize
'
CTHULHUETERNAL.Label.rollDamage'
}}"
><i class="fa-solid fa-sword"></i></a>
{{/if}}
</li>
{{/if}}
{{#if (eq rollType "skill")}}
{{#if rollItem.system.isHealing}}
<li>
<a
class="healing-roll"
data-tooltip="{{localize
' CTHULHUETERNAL.Label.rollHealing'
}}"
><i class="fa-solid fa-heart"></i></a>
</li>
{{/if}}
{{#if (eq rollType "skill") }}
{{#if rollItem.system.isHealing}}
<li>
<a class="healing-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollHealing"}}"><i class="fa-solid fa-heart"></i></a>
</li>
{{/if}}
{{/if}}
</li>
{{/if}}
{{/if}}
{{#if isFailure}}
{{#if isCritical}}
<li class="result-critical-failure">{{localize "CTHULHUETERNAL.Label.criticalFailure"}}
<li class="result-critical-failure">{{localize
"CTHULHUETERNAL.Label.criticalFailure"
}}
</li>
{{else}}
<li class="result-failure">
{{localize "CTHULHUETERNAL.Label.failure"}}
</li>
<li class="result-failure">
{{localize "CTHULHUETERNAL.Label.failure"}}
</li>
{{/if}}
{{#if isNudge}}
<li>
<a class="nudge-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollNudge"}}"><i class="fa-solid fa-circle-sort-down"></i></a>
</li>
<li>
<a
class="nudge-roll"
data-tooltip="{{localize 'CTHULHUETERNAL.Label.rollNudge'}}"
><i class="fa-solid fa-circle-sort-down"></i></a>
</li>
{{/if}}
{{/if}}
{{#if isAttackRoll}}
{{#if defenseRoll}}
<li>{{localize "CTHULHUETERNAL.Label.defenseRoll"}}</li>
{{#if attackSuccess}}
<li class="result-success">{{localize
"CTHULHUETERNAL.Label.attackSuccess"
}}</li>
{{else}}
<li class="result-failure">{{localize
"CTHULHUETERNAL.Label.attackFailure"
}}</li>
{{/if}}
{{else}}
{{#if targetId}}
<li class="orange-warning">{{localize
"CTHULHUETERNAL.Label.noDefenseRoll"
}}</li>
<a
class="opposed-roll"
data-tooltip="{{localize 'CTHULHUETERNAL.Label.opposedRoll'}}"
>
<i class="fa-duotone fa-light fa-arrows-to-line"></i></a>
{{else}}
<li class="orange-warning">{{localize
"CTHULHUETERNAL.Label.noTarget"
}}</li>
<a
class="opposed-roll"
data-tooltip="{{localize 'CTHULHUETERNAL.Label.opposedRoll'}}"
>
<i class="fa-duotone fa-light fa-arrows-to-line"></i></a>
{{/if}}
{{/if}}
{{/if}}
</ul>
</div>
</div>
{{#if isDamage}}
<div>
{{#if (and isGM hasTarget)}}
{{{localize "CTHULHUETERNAL.Roll.displayArmor" targetName=targetName targetArmor=targetArmor
realDamage=realDamage}}}
{{/if}}
</div>
<div>
{{#if (and isGM hasTarget)}}
{{{localize
"CTHULHUETERNAL.Roll.displayArmor"
targetName=targetName
targetArmor=targetArmor
realDamage=realDamage
}}}
{{/if}}
</div>
{{/if}}
{{#unless isPrivate}}
<div class="dice-result">
<h4 class="dice-total">{{total}}</h4>
<div class="dice-formula">{{formula}}</div>
{{{tooltip}}}
</div>
<div class="dice-result">
<h4 class="dice-total">{{total}}</h4>
<div class="dice-formula">{{formula}}</div>
{{{tooltip}}}
</div>
{{/unless}}
</div>

View File

@@ -23,6 +23,7 @@
<li class="li-apply-wounds">
{{localize "CTHULHUETERNAL.Label.applyWounds"}}
<select name="combatant" class="li-apply-wounds-select">
<option value="none"></option>
{{selectOptions combatants valueAttr="id" labelAttr="name"}}
</select>
</li>

View File

@@ -9,9 +9,12 @@
{{#if (eq rollType "resource")}}
<legend>{{localize "CTHULHUETERNAL.Label.resourceRating"}}</legend>
<div class="dialog-skill">{{rollItem.name}} : <span class="resource-score">{{initialScore}} ({{mul initialScore 5}}%)</span></div>
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Hand"}} : {{rollItem.hand}} <input type="checkbox" data-action="selectHand" {{checked rollItem.enableHand}}></div>
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Stowed"}} : {{rollItem.stowed}} <input type="checkbox" data-action="selectStowed" {{checked rollItem.enableStowed}}></div>
<div class="dialog-skill">{{rollItem.name}} : <span class="resource-score">{{initialScore}} ({{mul initialScore
5}}%)</span></div>
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Hand"}} : {{rollItem.hand}} <input type="checkbox"
data-action="selectHand" {{checked rollItem.enableHand}}></div>
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Stowed"}} : {{rollItem.stowed}} <input type="checkbox"
data-action="selectStowed" {{checked rollItem.enableStowed}}></div>
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.Storage"}} : {{rollItem.storage}}
<input type="checkbox" data-action="selectStorage" {{checked rollItem.enableStorage}}>
@@ -23,76 +26,85 @@
{{#if weapon}}
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Weapon"}} : {{weapon.name}}</div>
{{#if (eq weapon.system.weaponType "melee")}}
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.targetMove"}}
<select name="meleeTargetMoveChoice" class="roll-skill-modifier">
{{selectOptions choiceMeleeTargetMove localize=true selected=meleeTargetMoveChoice valueAttr="id" labelAttr="label"}}
</select>
</div>
{{/if}}
{{#if isRangedWeapon}}
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.rangedRange"}}
<select name="rangedRangeChoice" class="roll-skill-modifier">
{{selectOptions choiceRangedRange localize=true selected=rangedRangeChoice valueAttr="id" labelAttr="label"}}
</select>
</div>
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.targetMove"}}
<select name="rangedTargetMoveChoice" class="roll-skill-modifier">
{{selectOptions choiceRangedTargetMove localize=true selected=rangedTargetMoveChoice valueAttr="id" labelAttr="label"}}
</select>
</div>
{{#if targetName}}
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Target"}} : {{targetName}}</div>
{{/if}}
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.aimingLastRound"}}
<input type="checkbox" name="aimingLastRound">
</div>
{{#if weapon.system.hasSight}}
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.aimingWithSight"}}
<input type="checkbox" name="aimingWithSight">
</div>
{{/if}}
{{/if}}
{{#if (eq weapon.system.weaponType "melee")}}
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.targetMove"}}
<select name="meleeTargetMoveChoice" class="roll-skill-modifier">
{{selectOptions choiceMeleeTargetMove localize=true selected=meleeTargetMoveChoice valueAttr="id"
labelAttr="label"}}
</select>
</div>
{{/if}}
{{#if isRangedWeapon}}
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.rangedRange"}}
<select name="rangedRangeChoice" class="roll-skill-modifier">
{{selectOptions choiceRangedRange localize=true selected=rangedRangeChoice valueAttr="id" labelAttr="label"}}
</select>
</div>
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.targetMove"}}
<select name="rangedTargetMoveChoice" class="roll-skill-modifier">
{{selectOptions choiceRangedTargetMove localize=true selected=rangedTargetMoveChoice valueAttr="id"
labelAttr="label"}}
</select>
</div>
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.visibility"}}
<select name="visibilityChoice" class="roll-skill-modifier">
{{selectOptions choiceVisibility localize=true selected=visibilityChoice valueAttr="id" labelAttr="label"}}
</select>
</div>
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.attackerState"}}
<select name="attackerStateChoice" class="roll-skill-modifier">
{{selectOptions choiceAttackerState localize=true selected=attackerStateChoice valueAttr="id" labelAttr="label"}}
</select>
</div>
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.targetSize"}}
<select name="targetSizeChoice" class="roll-skill-modifier">
{{selectOptions choiceTargetSize localize=true selected=targetSizeChoice valueAttr="id" labelAttr="label"}}
</select>
</div>
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.aimingLastRound"}}
<input type="checkbox" name="aimingLastRound">
</div>
{{#if weapon.system.hasSight}}
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.aimingWithSight"}}
<input type="checkbox" name="aimingWithSight">
</div>
{{/if}}
{{#if weapon.system.hasSelectiveFire}}
<div class="dialog-skill">Selective Fire :
<select name="selectiveFireChoice" class="roll-skill-modifier">
{{selectOptions choiceSelectiveFire localize=true selected=selectiveFireChoice valueAttr="id" labelAttr="label"}}
</select>
</div>
{{/if}}
{{/if}}
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.visibility"}}
<select name="visibilityChoice" class="roll-skill-modifier">
{{selectOptions choiceVisibility localize=true selected=visibilityChoice valueAttr="id" labelAttr="label"}}
</select>
</div>
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.attackerState"}}
<select name="attackerStateChoice" class="roll-skill-modifier">
{{selectOptions choiceAttackerState localize=true selected=attackerStateChoice valueAttr="id"
labelAttr="label"}}
</select>
</div>
<div class="dialog-skill">
{{localize "CTHULHUETERNAL.Label.targetSize"}}
<select name="targetSizeChoice" class="roll-skill-modifier">
{{selectOptions choiceTargetSize localize=true selected=targetSizeChoice valueAttr="id" labelAttr="label"}}
</select>
</div>
{{#if weapon.system.hasSelectiveFire}}
<div class="dialog-skill">Selective Fire :
<select name="selectiveFireChoice" class="roll-skill-modifier">
{{selectOptions choiceSelectiveFire localize=true selected=selectiveFireChoice valueAttr="id"
labelAttr="label"}}
</select>
</div>
{{/if}}
{{/if}}
{{#if isZeroWP}}
<div class="dialog-skill red-warning">{{localize "CTHULHUETERNAL.Label.ZeroWP"}}</div>
{{else}}
{{#if isLowWP}}
<div class="dialog-skill orange-warning">{{localize "CTHULHUETERNAL.Label.LowWP"}} : -20%</div>
{{/if}}
{{#if isLowWP}}
<div class="dialog-skill orange-warning">{{localize "CTHULHUETERNAL.Label.LowWP"}} : -20%</div>
{{/if}}
{{/if}}
{{#if isExhausted}}