diff --git a/compendiums/fr/fvtt-cthulhu-eternal.skills.json b/compendiums/fr/fvtt-cthulhu-eternal.skills.json index fc578ab..7b3c68d 100644 --- a/compendiums/fr/fvtt-cthulhu-eternal.skills.json +++ b/compendiums/fr/fvtt-cthulhu-eternal.skills.json @@ -20,7 +20,7 @@ "entries": { "Pilot (Type)": { "name": "Pilotage (Type)", - "description": "" + "description": "

Piloter, naviguer et diriger des véhicules nautiques ou aériens. Utilisez cette compétence pour assurer la sécurité d'un navire en cas de danger, par exemple lors d'une tempête ou d'une poursuite dangereuse. Chaque type de véhicule requiert une compétence distincte : Avion, Drone, Hélicoptère, Dirigeable, Petite embarcation, Navire, etc.

" }, "Anthropology": { "name": "Anthropologie", diff --git a/css/fvtt-cthulhu-eternal.css b/css/fvtt-cthulhu-eternal.css index 427ccfa..3f6a743 100644 --- a/css/fvtt-cthulhu-eternal.css +++ b/css/fvtt-cthulhu-eternal.css @@ -183,6 +183,25 @@ i.fvtt-cthulhu-eternal { color: var(--color-critical-failure); font-family: var(--font-title); } +.chat-san-request ul .san-type-buttons, +.chat-lethal-damage ul .san-type-buttons { + display: flex; + justify-content: center; + align-items: center; + margin: 10px 0; +} +.chat-san-request ul .san-type-buttons button, +.chat-lethal-damage ul .san-type-buttons button { + margin: 0 2px; + font-family: var(--font-primary); + font-size: calc(var(--font-size-standard) * 0.9); + border: none; + padding: 2px 2px; + cursor: pointer; + transition: background-color 0.3s; + min-width: 6rem; + max-width: 6rem; +} .chat-san-request ul .san-loose-buttons, .chat-lethal-damage ul .san-loose-buttons { display: flex; @@ -804,7 +823,7 @@ i.fvtt-cthulhu-eternal { } .fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons { display: grid; - grid-template-columns: repeat(2, 1fr); + grid-template-columns: repeat(1, 1fr); gap: 4px; } .fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon { @@ -824,10 +843,24 @@ i.fvtt-cthulhu-eternal { min-width: 1.8rem; max-width: 1.8rem; } -.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .damage { +.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .range { min-width: 6rem; max-width: 6rem; } +.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .ammo { + min-width: 4rem; + max-width: 4rem; +} +.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .lethality { + display: flex; + min-width: 3.2rem; + max-width: 3.2rem; +} +.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .damage { + display: flex; + min-width: 12rem; + max-width: 12rem; +} .fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .name { min-width: 10rem; max-width: 10rem; @@ -2153,6 +2186,24 @@ i.fvtt-cthulhu-eternal { margin-top: 8px; background-color: var(--color-light-1); } +.fvtt-cthulhu-eternal .weapon-content fieldset input { + max-width: 5rem; + min-width: 5rem; +} +.fvtt-cthulhu-eternal .weapon-content fieldset select { + max-width: 14rem; + min-width: 14rem; +} +.fvtt-cthulhu-eternal .weapon-content fieldset input[type="checkbox"] { + max-width: 1.5rem; + min-width: 1.5rem; +} +.fvtt-cthulhu-eternal .weapon-content fieldset .flexrow > *:not(:first-child) { + margin-left: 1rem; +} +.fvtt-cthulhu-eternal .weapon-content fieldset .damage-distance { + margin-left: 2rem; +} .fvtt-cthulhu-eternal .weapon-content label { flex: 10%; } diff --git a/cthulhu-eternal.mjs b/cthulhu-eternal.mjs index 1d4cd52..2912868 100644 --- a/cthulhu-eternal.mjs +++ b/cthulhu-eternal.mjs @@ -151,7 +151,8 @@ Hooks.on("renderChatMessageHTML", (message, html, data) => { CthulhuEternalUtils.nudgeRoll(message) }) $(html).find(".damage-roll").click((event) => { - CthulhuEternalUtils.damageRoll(message) + let formula = $(event.currentTarget).data("roll-value") + CthulhuEternalUtils.damageRoll(message, formula) }) $(html).find(".healing-roll").click((event) => { CthulhuEternalUtils.healingRoll(message) diff --git a/lang/en.json b/lang/en.json index 99ff463..73e5d5f 100644 --- a/lang/en.json +++ b/lang/en.json @@ -212,6 +212,7 @@ "UnarmedCombat": "Unarmed Combat", "RangedWeapons": "Ranged Weapons", "FirearmsBeams": "Firearms / Beam Weapons", + "MilitaryTrainingExplosive": "Military Training (Explosives)", "FIELDS": { "isHealing": { "label": "Healing skill" @@ -268,7 +269,8 @@ "rangedprimitive": "Ranged Primitive", "rangedthrown": "Ranged Thrown", "rangedfirearm": "Ranged Firearm", - "unarmed": "Unarmed" + "unarmed": "Unarmed", + "rangedexplosive": "Explosive" }, "WeaponSubtype": { "basicfirearm": "Basic Firearm", @@ -283,7 +285,41 @@ "shortspray": "Short Spray", "longspray": "Long Spray" }, + "Target": { + "Normal": "Normal", + "Stationary": "Stationary", + "MovingRange": "Moving or on the ground", + "MovingFast": "Moving Fast (ie running)", + "MovingVeryFast": "Moving Very Fast", + "HalfCovered": "Half Covered", + "Covered": "Full Covered" + }, + "Range": { + "PointBlank": "Point Blank", + "Normal": "Normal", + "Range2x": "Up to Range x2", + "Range5x": "Up to Range x5" + }, + "Visibility": { + "Clear": "Clear", + "Obscured": "Obscured", + "Darkness": "Darkness" + }, + "Attacker": { + "Normal": "Normal", + "Irritated": "Irritated/Annoyed", + "Corrosive": "Deeply Annoyed" + }, "FIELDS": { + "hasDamageDistance": { + "label": "Is damage distance based?" + }, + "hasSight": { + "label": "Has sight" + }, + "isStunning": { + "label": "Is Stunning" + }, "hasDirectSkill": { "label": "Has direct skill" }, @@ -526,11 +562,14 @@ "Unnatural": "Unnatural", "sanLossViolence": "You suffered a SAN loss due to violence : violence progress path has evolved.", "sanLossHelplessness": "You suffered a SAN loss due to helplessness : helplessness progress path has evolved.", + "SANLossUnnatural": "You suffered a SAN loss due to unnatural : you may gain an Unnatural skill, check with the GM.", + "SANLossNone": "You suffered a SAN loss, but no special consequences apply.", "adaptedToViolence": "You are now : Adapted to Violence.", "adaptedToViolenceShort": "Adapted to Violence", "adaptedToHelplessness": "You are now : Adapted to Helplessness.", "adaptedToHelplessnessShort": "Adapted to Helplessness", - "SANTest": "You just rolled a SAN test : please select the SAN loss with the buttons below.", + "SANTestSuccess": "You just rolled a SAN test with success, but you may still loose SAN points. Select the value of SAN loss with the buttons below.", + "SANTestFailure": "You just rolled a SAN test with failure, you loose SAN points. Select the value of SAN loss with the buttons below.", "breakingPointReached": "Your SAN has reached your Breaking Point : you suffer a disorder (to be discussed with the GM). Reset the BP to its new value.", "rollNudge": "Roll Nudge", "rollDamage": "Roll Damage", @@ -613,6 +652,11 @@ "biography": "Biography", "notes": "Notes", "weapons": "Weapons", + "melee": "Melee", + "Lethality": "Lethality", + "baseRange": "Base Range", + "Ammo": "Ammo", + "armorPiercing": "Armor Piercing", "HP": "HP", "SAN": "SAN", "current": "Current", @@ -678,7 +722,15 @@ "killRadiusInfo": "All targets within the kill radius suffer the damage", "ammoUsed": "Ammo used", "lethalityLethal": "Lethal !!", - "lethalityNotLethal": "Non-Lethal" + "lethalityNotLethal": "Non-Lethal", + "WPSpent": "WP Spent", + "targetMove": "Target Move", + "attackerState": "Attacker State", + "targetSize": "Target Size", + "visibility": "Visibility", + "rangedRange": "Range", + "aimingLastRound": "Aiming Last Round (+20)", + "aimingWithSight": "Aiming with Sight (+20)" }, "ChatMessage": { "exhausted": "Your protagonist is exhausted. He loses [[/r 1d6]] Willpower Points." @@ -699,7 +751,8 @@ "Tooltip": { "sanBP": ">5 SAN lost in one roll, temporary insanity. If SAN less reaches BP = a Disorder unconscious Breaking and AND reset BP.", "setBP": "Set the current Breaking Point based on the current SAN value", - "addBond": "Add a new Bond" + "addBond": "Add a new Bond", + "rollDamage": "Roll Damage" }, "Chat": { }, diff --git a/lang/fr.json b/lang/fr.json index bf23b2a..06483c0 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -224,6 +224,7 @@ "UnarmedCombat": "Combat à mains nues", "RangedWeapons": "Armes de tir", "FirearmsBeams": "Armes à feu / à rayons", + "MilitaryTrainingExplosive": "Entraînement militaire (Explosifs)", "FIELDS": { "isHealing": { "label": "Compétence de soin" @@ -280,7 +281,8 @@ "rangedprimitive": "A distance - Primitive", "rangedthrown": "A distance - Lancer", "rangedfirearm": "A distance - Arme à feu", - "unarmed": "Non armé" + "unarmed": "Non armé", + "rangedexplosive": "Explosif" }, "WeaponSubtype": { "basicfirearm": "Arme à feu de base", @@ -295,7 +297,41 @@ "shortspray": "Barrage court", "longspray": "Barrage long" }, + "Target": { + "Normal": "Normal", + "Stationary": "Immobile (+20)", + "MovingRange": "En mouvement ou au sol (-20)", + "MovingFast": "En mouvement rapide (ie course) (-20)", + "MovingVeryFast": "En mouvement très rapide (ie véhicule) (-40)", + "HalfCovered": "A moitié couvert (-20)", + "Covered": "A Couvert (-40)" + }, + "Range": { + "PointBlank": "Bout portant (+20)", + "Normal": "Normal", + "Range2x": "de portée à portée x2 (-20)", + "Range5x": "de portéex2 à portée x5 (-40)" + }, + "Visibility": { + "Clear": "Normale", + "Obscured": "Obscurci (-20)", + "Darkness": "Obscurité (-40)" + }, + "Attacker": { + "Normal": "Normal", + "Irritated": "Irrité/Gêné (-20)", + "Corrosive": "Fortement gêné (-40)" + }, "FIELDS": { + "hasDamageDistance": { + "label": "Dégâts basés sur la distance ?" + }, + "hasSight": { + "label": "Lunette de visée" + }, + "isStunning": { + "label": "Etourdissante" + }, "ammo": { "label": "Munitions", "value": { @@ -531,17 +567,20 @@ "sanLoss5": "Perte de SAN de 5+ ({value}) : vous souffrez d'une folie temporaire (Fuite, Soumission, Lutte ou compréhension de l'Inconcevable).", "sanViolenceReset": "Le décompte des pertes de SAN de violence a été réinitialisé.", "sanHelplessnessReset": "Le décompte des pertes de SAN d'impuissance a été réinitialisé.", - "sanLoss": "Perte de SAN", + "sanLoss": "Vous venez de perdre des points de SAN", "noSanLoss": "Aucune perte de SAN", "sanLossInfo": "Sélectionnez la perte de SAN à l'aide des boutons ci-dessous.", - "selectSANType": "Sélectionnez le type de perte de SAN à l'aide des boutons ci-dessous.", + "selectSANType": "Sélectionnez maintenant le type SAN perdue à l'aide des boutons ci-dessous.", "sanLossViolence": "Vous avez subi une perte de SAN due à la violence : le chemin de progression de la violence a évolué.", "sanLossHelplessness": "Vous avez subi une perte de SAN due à l'impuissance : le chemin de progression de l'impuissance a évolué.", + "SANLossUnnatural": "Vous avez subi une perte de SAN due à l'inconcevable : vous pouvez peut-être faire progresser la compétence Inconcevable, vérifiez avec le MJ.", + "SANLossNone": "Vous avez subi une perte de SAN, mais aucune conséquence spéciale n'est appliquée.", "adaptedToViolence": "Vous êtes maintenant : Habitué à la violence", "adaptedToViolenceShort": "Habitué à la violence", "adaptedToHelplessness": "Vous êtes maintenant : Habitué à l'impuissance", "adaptedToHelplessnessShort": "Habitué à l'impuissance", - "SANTest": "Vous venez de faire un jet de SAN : selectionnez la perte de SAN à l'aide des boutons ci-dessous.", + "SANTestSuccess": "Vous venez de réussir votre jet de SAN, mais vous pouvez toujours perdre des points de SAN. Sélectionnez la valeur à l'aide des boutons ci-dessous.", + "SANTestFailure": "Vous venez d'échouer votre test de SAN, vous perdez des points de SAN. Sélectionnez la valeur à l'aide des boutons ci-dessous.", "breakingPointReached": "Vous avez atteint votre Point de Rupture (PR) : vous souffrez d'un trouble mental. Vous devez re-initialiser votre PR à l'aide du bouton disponible dans la section SAN de la fiche de PJ.", "Violence" : "Violence", "Helplessness": "Impuissance", @@ -627,6 +666,11 @@ "biography": "Biographie", "notes": "Notes", "weapons": "Armes", + "melee": "Mêlée", + "Lethality": "Létalité", + "baseRange": "Portée de base", + "Ammo": "Munitions", + "armorPiercing": "Pénétration d'armure", "HP": "PV", "SAN": "SAN", "current": "Actuel", @@ -692,7 +736,15 @@ "killRadiusInfo": "Si la cible est dans le rayon de mortalité, elle subit les dommages.", "ammoUsed": "Munitions utilisées", "lethalityLethal": "Létal !!", - "lethalityNotLethal": "Non létal" + "lethalityNotLethal": "Non létal", + "WPSpent": "PVO dépensés", + "targetMove": "Mouvement de la cible", + "attackerState": "Etat de l'attaquant", + "targetSize": "Taille de la cible", + "visibility": "Visibilité", + "rangedRange": "Portée", + "aimingLastRound": "Visée lors du dernier round (+20)", + "aimingWithSight": "Visée avec lunette (+20)" }, "ChatMessage": { "exhausted": "Votre protagoniste est épuisé. Il perd [[/r 1d6]] Points de Volonté." @@ -713,7 +765,8 @@ "Tooltip": { "sanBP": "Perte de 5+ SAN en 1 jet : folie temporaire. SI la SAN atteint le PR : trouble mental, perte de conscience et reset du PR.", "setBP": "Positionner le Point de Rupture à la valeur courant de la SAN", - "addBond": "Ajouter une Attache" + "addBond": "Ajouter une Attache", + "rollDamage": "Lancer les dégâts" }, "Chat": { }, diff --git a/macro_roll.js b/macro_roll.js new file mode 100644 index 0000000..2e864be --- /dev/null +++ b/macro_roll.js @@ -0,0 +1,19 @@ +let nb = 10000 +let sum = 0 +let results = [] +for (let i = 0; i < nb; i++) { + let r = new Roll("1d100") + await r.evaluate() + sum += r.total + results.push(r.total) +} + +let mean = sum / nb +let variance = results.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) / nb +let stddev = Math.sqrt(variance) + +console.log("Average : ", mean) +console.log("Standard deviation : ", stddev) +console.log("Coefficient of variation : ", stddev / mean ) +console.log("Min : ", Math.min(...results)) +console.log("Max : ", Math.max(...results)) \ No newline at end of file diff --git a/module/applications/sheets/protagonist-sheet.mjs b/module/applications/sheets/protagonist-sheet.mjs index 1eeebcb..e3c7ad4 100644 --- a/module/applications/sheets/protagonist-sheet.mjs +++ b/module/applications/sheets/protagonist-sheet.mjs @@ -225,6 +225,7 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS case "damage": li = $(event.currentTarget).parents(".item"); item = this.actor.items.get(li.data("item-id")); + item.damageFormula = $(event.currentTarget).data("roll-value") || item.system.damage item.damageBonus = this.actor.system.damageBonus break case "san": diff --git a/module/config/system.mjs b/module/config/system.mjs index bc36cd8..3acc9b1 100644 --- a/module/config/system.mjs +++ b/module/config/system.mjs @@ -154,7 +154,8 @@ export const WEAPON_SKILL_MAPPING = { "rangedprimitive": "CTHULHUETERNAL.Skill.Firearms", "rangedthrown": "CTHULHUETERNAL.Skill.Athletics", "rangedfirearm": "CTHULHUETERNAL.Skill.Firearms", - "unarmed": "CTHULHUETERNAL.Skill.UnarmedCombat" + "unarmed": "CTHULHUETERNAL.Skill.UnarmedCombat", + "rangedexplosive": "CTHULHUETERNAL.Skill.MilitaryTrainingExplosive" }, victorian: { "melee": "CTHULHUETERNAL.Skill.Melee", @@ -245,6 +246,45 @@ export const WEAPON_SELECTIVE_FIRE_CHOICES = { "longspray": { id: "longspray", label: "CTHULHUETERNAL.Weapon.SelectiveFire.longspray", ammoUsed: 20, lethality: 10, killRadius: 3}, } +// Melee stuff +export const WEAPON_MELEE_TARGET_MOVE = { + "normal": { id: "normal", label: "CTHULHUETERNAL.Weapon.Target.Normal", modifier: 0 }, + "stationary": { id: "stationary", label: "CTHULHUETERNAL.Weapon.Target.Stationary", modifier: 20 }, + "movingfast": { id: "movingfast", label: "CTHULHUETERNAL.Weapon.Target.MovingFast", modifier: -20 }, + "movingveryfast": { id: "movingveryfast", label: "CTHULHUETERNAL.Weapon.Target.MovingVeryFast", modifier: -40 }, +} +// Ranged stuff +export const WEAPON_RANGED_RANGE = { + "pointblank": { id: "pointblank", label: "CTHULHUETERNAL.Weapon.Range.PointBlank", modifier: +20 }, + "normal": { id: "normal", label: "CTHULHUETERNAL.Weapon.Range.Normal", modifier: 0 }, + "range2x": { id: "range2x", label: "CTHULHUETERNAL.Weapon.Range.Range2x", modifier: -20 }, + "range5x": { id: "range5x", label: "CTHULHUETERNAL.Weapon.Range.Range5x", modifier: -40 } +} +export const WEAPON_RANGED_TARGET_MOVE = { + "normal": { id: "normal", label: "CTHULHUETERNAL.Weapon.Target.Normal", modifier: 0 }, + "stationary": { id: "stationary", label: "CTHULHUETERNAL.Weapon.Target.Stationary", modifier: 20 }, + "movingfast": { id: "movingfast", label: "CTHULHUETERNAL.Weapon.Target.MovingRange", modifier: -20 }, + "movingveryfast": { id: "movingveryfast", label: "CTHULHUETERNAL.Weapon.Target.MovingVeryFast", modifier: -40 }, +} + +// Common stuff +export const WEAPON_ATTACKER_STATE = { + "normal": { id: "normal", label: "CTHULHUETERNAL.Weapon.Target.Normal", modifier: 0 }, + "irritated": { id: "irritated", label: "CTHULHUETERNAL.Weapon.Attacker.Irritated", modifier: -20 }, + "corrosive": { id: "corrosive", label: "CTHULHUETERNAL.Weapon.Attacker.Corrosive", modifier: -40 }, +} +export const WEAPON_TARGET_SIZE = { + "normal": { id: "normal", label: "CTHULHUETERNAL.Weapon.Target.Normal", modifier: 0 }, + "halfcovered": { id: "halfcovered", label: "CTHULHUETERNAL.Weapon.Target.HalfCovered", modifier: -20 }, + "covered": { id: "covered", label: "CTHULHUETERNAL.Weapon.Target.Covered", modifier: -40 }, +} +export const WEAPON_VISIBILITY = { + "clear": { id: "clear", label: "CTHULHUETERNAL.Weapon.Visibility.Clear", modifier: 0 }, + "obscured": { id: "obscured", label: "CTHULHUETERNAL.Weapon.Visibility.Obscured", modifier: -20 }, + "darkness": { id: "darkness", label: "CTHULHUETERNAL.Weapon.Visibility.Darkness", modifier: -40 }, +} + + export const RITUAL_TYPES = { "simple": "CTHULHUETERNAL.Ritual.Simple", "difficult": "CTHULHUETERNAL.Ritual.Difficult", @@ -277,5 +317,11 @@ export const SYSTEM = { MULTIPLIER_CHOICES, ASCII, DAMAGE_BONUS, - RITUAL_TYPES + RITUAL_TYPES, + WEAPON_MELEE_TARGET_MOVE, + WEAPON_RANGED_RANGE, + WEAPON_RANGED_TARGET_MOVE, + WEAPON_ATTACKER_STATE, + WEAPON_TARGET_SIZE, + WEAPON_VISIBILITY } diff --git a/module/config/weapon.mjs b/module/config/weapon.mjs index 26fbbfa..a5060b2 100644 --- a/module/config/weapon.mjs +++ b/module/config/weapon.mjs @@ -3,7 +3,8 @@ export const WEAPON_TYPE = { "rangedprimitive": "CTHULHUETERNAL.Weapon.WeaponType.rangedprimitive", "rangedthrown": "CTHULHUETERNAL.Weapon.WeaponType.rangedthrown", "rangedfirearm": "CTHULHUETERNAL.Weapon.WeaponType.rangedfirearm", - "unarmed": "CTHULHUETERNAL.Weapon.WeaponType.unarmed" + "unarmed": "CTHULHUETERNAL.Weapon.WeaponType.unarmed", + "rangedexplosive": "CTHULHUETERNAL.Weapon.WeaponType.rangedexplosive", } export const WEAPON_SUBTYPE = { diff --git a/module/documents/roll.mjs b/module/documents/roll.mjs index c7c726d..aac278a 100644 --- a/module/documents/roll.mjs +++ b/module/documents/roll.mjs @@ -106,7 +106,7 @@ export default class CthulhuEternalRoll extends Roll { } static buildSelectiveFireChoices(actor, weapon) { - if (!weapon || !weapon?.system?.hasSelectiveFire) { + if (!weapon?.system?.hasSelectiveFire) { return {} } // Loop thru the selective fire choices and build the choices object when enough ammo in the weapon @@ -144,6 +144,8 @@ export default class CthulhuEternalRoll extends Roll { ammoUsed = choice.ammoUsed // Override ammo used } + ammoUsed = Number(ammoUsed) + if (weapon.system.lethality > 0) { let lethalityRoll = new Roll("1d100") await lethalityRoll.evaluate() @@ -175,8 +177,8 @@ export default class CthulhuEternalRoll extends Roll { } // If the weapon is not lethal, we can proceed with the regular damage roll - let formula = weapon.system.damage - if (weapon.system.weaponType === "melee" || weapon.system.weaponType === "unarmed") { + let formula = weapon?.damageFormula || weapon.system.damage || "0" + if (weapon.system.applyDamageBonus) { formula += ` + ${actor.system?.damageBonus}` } if (options?.previousResultType === "successCritical") { @@ -205,6 +207,19 @@ export default class CthulhuEternalRoll extends Roll { }, { rollMode: options.rollMode, create: true }) } + + static computeWeaponModifiers(rollData) { + let modifier = SYSTEM.WEAPON_MELEE_TARGET_MOVE[rollData.meleeTargetMoveChoice]?.modifier || 0 + modifier += SYSTEM.WEAPON_RANGED_RANGE[rollData.rangedRangeChoice]?.modifier || 0 + modifier += SYSTEM.WEAPON_RANGED_TARGET_MOVE[rollData.rangedTargetMoveChoice]?.modifier || 0 + modifier += SYSTEM.WEAPON_VISIBILITY[rollData.visibilityChoice]?.modifier || 0 + modifier += SYSTEM.WEAPON_ATTACKER_STATE[rollData.attackerStateChoice]?.modifier || 0 + modifier += SYSTEM.WEAPON_TARGET_SIZE[rollData.targetSizeChoice]?.modifier || 0 + modifier += (rollData.aimingLastRound) ? 20 : 0 + modifier += (rollData.aimingWithSight) ? 20 : 0 + return modifier + } + /** * Prompt the user with a dialog to configure and execute a roll. * @@ -311,6 +326,7 @@ export default class CthulhuEternalRoll extends Roll { rollType: options.rollType, rollItem: foundry.utils.duplicate(options.rollItem), // Object only, no class weapon: options?.weapon, + isRangedWeapon: options?.weapon?.system?.isRanged(), initialScore: options.initialScore, targetScore: options.initialScore, isLowWP: options.isLowWP, @@ -324,12 +340,26 @@ export default class CthulhuEternalRoll extends Roll { choiceModifier, choiceMultiplier, choiceSelectiveFire, + choiceMeleeTargetMove: SYSTEM.WEAPON_MELEE_TARGET_MOVE, + choiceRangedRange: SYSTEM.WEAPON_RANGED_RANGE, + choiceRangedTargetMove: SYSTEM.WEAPON_RANGED_TARGET_MOVE, + choiceVisibility: SYSTEM.WEAPON_VISIBILITY, + choiceAttackerState: SYSTEM.WEAPON_ATTACKER_STATE, + choiceTargetSize: SYSTEM.WEAPON_TARGET_SIZE, + selectiveFireChoice: "shortburst", + meleeTargetMoveChoice: "normal", + rangedRangeChoice: "normal", + rangedTargetMoveChoice: "normal", + visibilityChoice: "clear", + attackerStateChoice: "normal", + targetSizeChoice: "normal", + aimingLastRound: false, + aimingWithSight: false, + modifier, formula, hasTarget: options.hasTarget, hasModifier, hasMultiplier, - modifier, - selectiveFireChoice: "shortburst", multiplier } const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/roll-dialog.hbs", dialogContext) @@ -386,7 +416,9 @@ export default class CthulhuEternalRoll extends Roll { if (options.rollType === "resource") { rollData.targetScore = options.initialScore * Number(rollContext.multiplier) } else { - rollData.targetScore = Math.min(Math.max(options.initialScore + Number(rollData.modifier), 0), 100) + let totalModifier = this.computeWeaponModifiers(rollData) + Number(rollData.modifier) + rollData.totalModifier = Math.min(totalModifier, 40) + rollData.targetScore = Math.min(Math.max(options.initialScore + Number(rollData.totalModifier), 0), 100) if (rollData.isLowWP || rollData.isExhausted) { rollData.targetScore -= 20 } @@ -395,7 +427,7 @@ export default class CthulhuEternalRoll extends Roll { } rollData.targetScore = Math.min(Math.max(rollData.targetScore, 0), 100) } - if (!rollData.targetScore) { + if (rollData.targetScore === undefined || rollData.targetScore === null) { rollData.targetScore = options.initialScore rollData.modifier = "0" } @@ -456,6 +488,7 @@ export default class CthulhuEternalRoll extends Roll { this.options.isCritical = resultType === "successCritical" || resultType === "failureCritical" } rollData.resultType = resultType + this.options.isLowWP = rollData.isLowWP this.options.isZeroWP = rollData.isZeroWP this.options.isExhausted = rollData.isExhausted @@ -601,12 +634,14 @@ export default class CthulhuEternalRoll extends Roll { rollItem: rollItem, rollData: rollData } + // Get array of gamemaster ID let msg = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-san-request.hbs", msgData) let chatMsg = await ChatMessage.create({ user: game.user.id, content: msg, - speaker: ChatMessage.getSpeaker({ actor: rollData.actor }) - }, { rollMode: rollData.rollMode, create: true }) + speaker: ChatMessage.getSpeaker({ actor: rollData.actor }), + whisper: game.users.filter(u => u.isGM).map(u => u.id), + }) await chatMsg.setFlag("fvtt-cthulhu-eternal", "rollData", rollData) } } diff --git a/module/models/protagonist.mjs b/module/models/protagonist.mjs index 5c53a74..3be2484 100644 --- a/module/models/protagonist.mjs +++ b/module/models/protagonist.mjs @@ -90,6 +90,10 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData prepareDerivedData() { super.prepareDerivedData(); + if (!game.user.isGM ) { + return + } + let updates = {} if (this.wp.max !== this.characteristics.pow.value) { updates[`system.wp.max`] = this.characteristics.pow.value @@ -123,8 +127,6 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData dmgBonus = -2 } else if (this.characteristics.str.value <= 8) { dmgBonus = -1 - } else if (this.characteristics.str.value <= 12) { - dmgBonus = 0 } else if (this.characteristics.str.value <= 16) { dmgBonus = 1 } else if (this.characteristics.str.value <= 20) { @@ -137,9 +139,12 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData // BP (Breaking Point) management if (!this.san.breakingPointReached && this.san.value <= this.san.breakingPoint) { updates[`system.san.breakingPointReached`] = true + this.san.breakingPointReached = true // Force local update to true ChatMessage.create({ content: `

${game.i18n.format("CTHULHUETERNAL.Label.breakingPointReached", { bp: this.san.breakingPoint, san: this.san.value })}

`, - speaker: ChatMessage.getSpeaker({ actor: this.parent }) + speaker: ChatMessage.getSpeaker({ actor: this.parent }), + // Get the user id of the actor owner + whisper: [game.users.find(u => u.character?.name === this.parent?.name).id ] }) } @@ -195,10 +200,6 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData } async applySANConsequences(rollData) { - // If sanType is "non", do nothing - if (rollData.sanType === "none") { - return - } let msgData = { sanType: rollData.sanType, sanLoss: rollData.sanLoss, @@ -265,14 +266,21 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData updates[`system.san.helplessness`] = [false, false, false] msgData.adaptedToHelplessness = true } + } else if (rollData.sanType === "unnatural" ) { + template = "systems/fvtt-cthulhu-eternal/templates/chat-san-loss-unnatural.hbs" + } else { + template = "systems/fvtt-cthulhu-eternal/templates/chat-san-loss-none.hbs" } + console.log("CthulhuEternalProtagonist.applySANConsequences", rollData, updates, template) let content = await foundry.applications.handlebars.renderTemplate(template, msgData) let msg = await ChatMessage.create({ content: content, - speaker: ChatMessage.getSpeaker({ actor: this.parent }) + speaker: ChatMessage.getSpeaker({ actor: this.parent }), + whisper: game.users.filter(u => u.isGM).map(u => u.id), }) - msg.setFlag("fvtt-cthulhu-eternal", "rollData", msgData) + await msg.setFlag("fvtt-cthulhu-eternal", "rollData", msgData) + if (Object.keys(updates).length > 0) { this.parent.update(updates) } @@ -284,12 +292,14 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData let san = Math.max(Math.min(this.san.value + rollData.sanLoss, this.san.max), 0) if (this.san.value !== san) { updates[`system.san.value`] = san + rollData.sanValue = san const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-san-type-request.hbs", rollData) let msg = await ChatMessage.create({ content: content, - speaker: ChatMessage.getSpeaker({ actor: this.parent }) + speaker: ChatMessage.getSpeaker({ actor: this.parent }), + whisper: game.users.filter(u => u.isGM).map(u => u.id) }) - msg.setFlag("fvtt-cthulhu-eternal", "rollData", rollData) + await msg.setFlag("fvtt-cthulhu-eternal", "rollData", rollData) } if (Object.keys(updates).length > 0) { this.parent.update(updates) diff --git a/module/models/weapon.mjs b/module/models/weapon.mjs index a6709a6..ab55b36 100644 --- a/module/models/weapon.mjs +++ b/module/models/weapon.mjs @@ -13,12 +13,23 @@ export default class CthulhuEternalWeapon extends foundry.abstract.TypeDataModel schema.weaponType = new fields.StringField({ required: true, initial: "melee", choices: SYSTEM.WEAPON_TYPE }) schema.hasDirectSkill = new fields.BooleanField({ required: true, initial: false }) - schema.directSkillValue = new fields.NumberField({ required: true, initial: 0, min: 0, max:99 }) + schema.directSkillValue = new fields.NumberField({ required: true, initial: 0, min: 0, max: 99 }) + + schema.hasDamageDistance = new fields.BooleanField({ required: true, initial: false }) + schema.damageDistance = new fields.SchemaField(Array.fromRange(6, 1).reduce((damageDistance, i) => { + damageDistance[`dist${i}`] = new fields.SchemaField({ + damage: new fields.StringField({ required: true, initial: "1d6" }), + distance: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) + }) + return damageDistance + }, {})); schema.hasSelectiveFire = new fields.BooleanField({ required: true, initial: false }) - schema.damage = new fields.StringField({required: true, initial: "1d6"}) + schema.hasSight = new fields.BooleanField({ required: true, initial: false }) + schema.isStunning = new fields.BooleanField({ required: true, initial: false }) + schema.damage = new fields.StringField({ required: true, initial: "1d6" }) schema.applyDamageBonus = new fields.BooleanField({ required: true, initial: false }) - schema.baseRange = new fields.StringField({required: true, initial: ""}) + schema.baseRange = new fields.StringField({ required: true, initial: "" }) schema.rangeUnit = new fields.StringField({ required: true, initial: "yard", choices: SYSTEM.WEAPON_RANGE_UNIT }) schema.lethality = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.killRadius = new fields.NumberField({ required: true, initial: 0, min: 0 }) @@ -43,7 +54,8 @@ export default class CthulhuEternalWeapon extends foundry.abstract.TypeDataModel } isRanged() { - return this.weaponType.includes("ranged") + console.log("isRanged", this.weaponType, this) + return this.weaponType.match("ranged") } isFireArm() { diff --git a/module/utils.mjs b/module/utils.mjs index 5963bcf..b7a7833 100644 --- a/module/utils.mjs +++ b/module/utils.mjs @@ -196,11 +196,6 @@ export default class CthulhuEternalUtils { ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noSanTypeFound")) return } - // If the sanType is "none", we don't apply any SAN processing - if (sanType === "none") { - ui.notifications.info(game.i18n.localize("CTHULHUETERNAL.Notifications.noSanLossApplied")) - return - } rollData.sanType = sanType await actor.system.applySANConsequences(rollData) // Delete the roll message @@ -253,7 +248,7 @@ export default class CthulhuEternalUtils { }) } - static async damageRoll(rollMessage) { + static async damageRoll(rollMessage, formula = null) { let rollData = rollMessage.rolls[0]?.options?.rollData let actor = game.actors.get(rollData.actorId) if (!actor) { @@ -263,6 +258,7 @@ export default class CthulhuEternalUtils { console.log("Damage roll data", rollData) rollData.weapon.resultType = rollData.resultType // Keep the result type from the roll message rollData.weapon.selectiveFireChoice = rollData.selectiveFireChoice // Keep the selected fire choice from the roll message + rollData.weapon.damageFormula = formula || rollData.weapon.system.damage actor.system.roll("damage", rollData.weapon) } diff --git a/packs-system/rituals/000173.log b/packs-system/rituals/000218.log similarity index 100% rename from packs-system/rituals/000173.log rename to packs-system/rituals/000218.log diff --git a/packs-system/rituals/CURRENT b/packs-system/rituals/CURRENT index 91e41f4..9aabe0c 100644 --- a/packs-system/rituals/CURRENT +++ b/packs-system/rituals/CURRENT @@ -1 +1 @@ -MANIFEST-000171 +MANIFEST-000217 diff --git a/packs-system/rituals/LOG b/packs-system/rituals/LOG index e163bbe..cc9592c 100644 --- a/packs-system/rituals/LOG +++ b/packs-system/rituals/LOG @@ -1,7 +1,3 @@ -2025/07/09-17:04:59.082095 7f2a0effd6c0 Recovering log #169 -2025/07/09-17:04:59.092675 7f2a0effd6c0 Delete type=3 #167 -2025/07/09-17:04:59.092780 7f2a0effd6c0 Delete type=0 #169 -2025/07/09-17:18:46.206680 7f276ffff6c0 Level-0 table #174: started -2025/07/09-17:18:46.206717 7f276ffff6c0 Level-0 table #174: 0 bytes OK -2025/07/09-17:18:46.235941 7f276ffff6c0 Delete type=0 #172 -2025/07/09-17:18:46.287862 7f276ffff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end) +2025/07/14-21:08:15.948300 7f3fa67fc6c0 Recovering log #215 +2025/07/14-21:08:15.959041 7f3fa67fc6c0 Delete type=3 #213 +2025/07/14-21:08:15.959103 7f3fa67fc6c0 Delete type=0 #215 diff --git a/packs-system/rituals/LOG.old b/packs-system/rituals/LOG.old index 05e4dad..3a6458c 100644 --- a/packs-system/rituals/LOG.old +++ b/packs-system/rituals/LOG.old @@ -1,7 +1,7 @@ -2025/06/29-22:25:29.091880 7fda6d9f96c0 Recovering log #165 -2025/06/29-22:25:29.103184 7fda6d9f96c0 Delete type=3 #163 -2025/06/29-22:25:29.103305 7fda6d9f96c0 Delete type=0 #165 -2025/06/29-22:26:56.370766 7fda5bbff6c0 Level-0 table #170: started -2025/06/29-22:26:56.370832 7fda5bbff6c0 Level-0 table #170: 0 bytes OK -2025/06/29-22:26:56.379673 7fda5bbff6c0 Delete type=0 #168 -2025/06/29-22:26:56.380010 7fda5bbff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end) +2025/07/14-10:18:19.443254 7f3fa77fe6c0 Recovering log #211 +2025/07/14-10:18:19.474975 7f3fa77fe6c0 Delete type=3 #209 +2025/07/14-10:18:19.475128 7f3fa77fe6c0 Delete type=0 #211 +2025/07/14-20:48:52.882063 7f3fa57fa6c0 Level-0 table #216: started +2025/07/14-20:48:52.882164 7f3fa57fa6c0 Level-0 table #216: 0 bytes OK +2025/07/14-20:48:52.889652 7f3fa57fa6c0 Delete type=0 #214 +2025/07/14-20:48:52.915102 7f3fa57fa6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end) diff --git a/packs-system/rituals/MANIFEST-000171 b/packs-system/rituals/MANIFEST-000217 similarity index 73% rename from packs-system/rituals/MANIFEST-000171 rename to packs-system/rituals/MANIFEST-000217 index 66c5cfa..6431ccb 100644 Binary files a/packs-system/rituals/MANIFEST-000171 and b/packs-system/rituals/MANIFEST-000217 differ diff --git a/packs-system/skills/000342.log b/packs-system/skills/000387.log similarity index 100% rename from packs-system/skills/000342.log rename to packs-system/skills/000387.log diff --git a/packs-system/skills/CURRENT b/packs-system/skills/CURRENT index 757ec85..0884887 100644 --- a/packs-system/skills/CURRENT +++ b/packs-system/skills/CURRENT @@ -1 +1 @@ -MANIFEST-000340 +MANIFEST-000386 diff --git a/packs-system/skills/LOG b/packs-system/skills/LOG index 5d2a756..4e8fe04 100644 --- a/packs-system/skills/LOG +++ b/packs-system/skills/LOG @@ -1,7 +1,3 @@ -2025/07/09-17:04:59.062504 7f2a0dffb6c0 Recovering log #338 -2025/07/09-17:04:59.072990 7f2a0dffb6c0 Delete type=3 #336 -2025/07/09-17:04:59.073130 7f2a0dffb6c0 Delete type=0 #338 -2025/07/09-17:18:46.236069 7f276ffff6c0 Level-0 table #343: started -2025/07/09-17:18:46.236095 7f276ffff6c0 Level-0 table #343: 0 bytes OK -2025/07/09-17:18:46.287671 7f276ffff6c0 Delete type=0 #341 -2025/07/09-17:18:46.287875 7f276ffff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end) +2025/07/14-21:08:15.916959 7f3fa5ffb6c0 Recovering log #384 +2025/07/14-21:08:15.927715 7f3fa5ffb6c0 Delete type=3 #382 +2025/07/14-21:08:15.927846 7f3fa5ffb6c0 Delete type=0 #384 diff --git a/packs-system/skills/LOG.old b/packs-system/skills/LOG.old index 4f901d0..ddad229 100644 --- a/packs-system/skills/LOG.old +++ b/packs-system/skills/LOG.old @@ -1,7 +1,7 @@ -2025/06/29-22:25:29.069935 7fda6d1f86c0 Recovering log #334 -2025/06/29-22:25:29.081064 7fda6d1f86c0 Delete type=3 #332 -2025/06/29-22:25:29.081192 7fda6d1f86c0 Delete type=0 #334 -2025/06/29-22:26:56.360514 7fda5bbff6c0 Level-0 table #339: started -2025/06/29-22:26:56.360577 7fda5bbff6c0 Level-0 table #339: 0 bytes OK -2025/06/29-22:26:56.370559 7fda5bbff6c0 Delete type=0 #337 -2025/06/29-22:26:56.379992 7fda5bbff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end) +2025/07/14-10:18:19.359761 7f3fa67fc6c0 Recovering log #380 +2025/07/14-10:18:19.394536 7f3fa67fc6c0 Delete type=3 #378 +2025/07/14-10:18:19.394680 7f3fa67fc6c0 Delete type=0 #380 +2025/07/14-20:48:52.889840 7f3fa57fa6c0 Level-0 table #385: started +2025/07/14-20:48:52.889882 7f3fa57fa6c0 Level-0 table #385: 0 bytes OK +2025/07/14-20:48:52.896159 7f3fa57fa6c0 Delete type=0 #383 +2025/07/14-20:48:52.915114 7f3fa57fa6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end) diff --git a/packs-system/skills/MANIFEST-000340 b/packs-system/skills/MANIFEST-000386 similarity index 71% rename from packs-system/skills/MANIFEST-000340 rename to packs-system/skills/MANIFEST-000386 index 3016009..5c2b1ff 100644 Binary files a/packs-system/skills/MANIFEST-000340 and b/packs-system/skills/MANIFEST-000386 differ diff --git a/packs-system/weapons/000014.ldb b/packs-system/weapons/000014.ldb new file mode 100644 index 0000000..bec309b Binary files /dev/null and b/packs-system/weapons/000014.ldb differ diff --git a/packs-system/weapons/000032.log b/packs-system/weapons/000032.log new file mode 100644 index 0000000..07cba19 Binary files /dev/null and b/packs-system/weapons/000032.log differ diff --git a/packs-system/weapons/CURRENT b/packs-system/weapons/CURRENT new file mode 100644 index 0000000..d95f027 --- /dev/null +++ b/packs-system/weapons/CURRENT @@ -0,0 +1 @@ +MANIFEST-000031 diff --git a/packs-system/weapons/LOCK b/packs-system/weapons/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/packs-system/weapons/LOG b/packs-system/weapons/LOG new file mode 100644 index 0000000..af4b43d --- /dev/null +++ b/packs-system/weapons/LOG @@ -0,0 +1,3 @@ +2025/07/14-21:08:15.933872 7f3fa6ffd6c0 Recovering log #29 +2025/07/14-21:08:15.943722 7f3fa6ffd6c0 Delete type=3 #27 +2025/07/14-21:08:15.943845 7f3fa6ffd6c0 Delete type=0 #29 diff --git a/packs-system/weapons/LOG.old b/packs-system/weapons/LOG.old new file mode 100644 index 0000000..1fdda04 --- /dev/null +++ b/packs-system/weapons/LOG.old @@ -0,0 +1,8 @@ +2025/07/14-10:18:19.404246 7f3fa5ffb6c0 Recovering log #25 +2025/07/14-10:18:19.435628 7f3fa5ffb6c0 Delete type=3 #23 +2025/07/14-10:18:19.435765 7f3fa5ffb6c0 Delete type=0 #25 +2025/07/14-20:48:52.908846 7f3fa57fa6c0 Level-0 table #30: started +2025/07/14-20:48:52.908888 7f3fa57fa6c0 Level-0 table #30: 0 bytes OK +2025/07/14-20:48:52.915004 7f3fa57fa6c0 Delete type=0 #28 +2025/07/14-20:48:52.915133 7f3fa57fa6c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end) +2025/07/14-20:48:52.928670 7f3fa57fa6c0 Manual compaction at level-1 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end) diff --git a/packs-system/weapons/MANIFEST-000031 b/packs-system/weapons/MANIFEST-000031 new file mode 100644 index 0000000..51b9aba Binary files /dev/null and b/packs-system/weapons/MANIFEST-000031 differ diff --git a/styles/global.less b/styles/global.less index c21a984..3dcd0d8 100644 --- a/styles/global.less +++ b/styles/global.less @@ -98,6 +98,23 @@ i.fvtt-cthulhu-eternal { color: var(--color-critical-failure); font-family: var(--font-title); } + .san-type-buttons { + display: flex; + justify-content: center; + align-items: center; + margin: 10px 0; + button { + margin: 0 2px; + font-family: var(--font-primary); + font-size: calc(var(--font-size-standard) * 0.9); + border: none; + padding: 2px 2px; + cursor: pointer; + transition: background-color 0.3s; + min-width: 6.0rem; + max-width: 6.0rem; + } + } .san-loose-buttons { display: flex; justify-content: center; diff --git a/styles/protagonist.less b/styles/protagonist.less index 2b162f3..55cbc4d 100644 --- a/styles/protagonist.less +++ b/styles/protagonist.less @@ -478,7 +478,7 @@ } .weapons { display: grid; - grid-template-columns: repeat(2, 1fr); + grid-template-columns: repeat(1, 1fr); gap: 4px; .weapon { display: flex; @@ -496,10 +496,24 @@ min-width: 1.8rem; max-width: 1.8rem; } - .damage { + .range { min-width: 6rem; max-width: 6rem; } + .ammo { + min-width: 4rem; + max-width: 4rem; + } + .lethality { + display: flex; + min-width: 3.2rem; + max-width: 3.2rem; + } + .damage { + display: flex; + min-width: 12rem; + max-width: 12rem; + } .name { min-width: 10rem; max-width: 10rem; diff --git a/styles/weapon.less b/styles/weapon.less index 06d9f8d..205ccc5 100644 --- a/styles/weapon.less +++ b/styles/weapon.less @@ -14,6 +14,24 @@ fieldset { margin-top: 8px; background-color: var(--color-light-1); + input { + max-width: 5rem; + min-width: 5rem; + } + select { + max-width: 14rem; + min-width: 14rem; + } + input[type="checkbox"] { + max-width: 1.5rem; + min-width: 1.5rem; + } + .flexrow > *:not(:first-child) { + margin-left: 1rem; + } + .damage-distance { + margin-left: 2rem; + } } label { diff --git a/system.json b/system.json index 431185c..481aeb8 100644 --- a/system.json +++ b/system.json @@ -152,6 +152,18 @@ }, "flags": {} }, + { + "name": "weapons", + "label": "Weapons", + "system": "fvtt-cthulhu-eternal", + "path": "packs-system/weapons", + "type": "Item", + "ownership": { + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" + }, + "flags": {} + }, { "name": "rituals", "label": "Rituals", diff --git a/templates/chat-lethal-damage.hbs b/templates/chat-lethal-damage.hbs index 51620c9..9309545 100644 --- a/templates/chat-lethal-damage.hbs +++ b/templates/chat-lethal-damage.hbs @@ -8,11 +8,15 @@ {{#if weapon.system.selectiveFireChoice}}
  • {{weapon.system.selectiveFireChoiceLabel}}
  • {{/if}} - {{#if weapon.system.killRadius}} + {{#if (gt weapon.system.killRadius 0)}}
  • {{localize "CTHULHUETERNAL.Label.killRadius"}} : {{weapon.system.killRadius}} {{weapon.system.rangeUnit}}
  • {{localize "CTHULHUETERNAL.Label.killRadiusInfo"}}
  • {{/if}} + {{#if (gt weapon.system.armorPiercing 0)}} +
  • {{localize "CTHULHUETERNAL.Label.armorPiercing"}} : {{weapon.system.armorPiercing}}
  • + {{/if}} + {{#if ammoUsed}}
  • {{localize "CTHULHUETERNAL.Label.ammoUsed"}}: {{ammoUsed}} / {{weapon.system.ammo.value}}
  • {{/if}} diff --git a/templates/chat-message.hbs b/templates/chat-message.hbs index 369718f..9f1d595 100644 --- a/templates/chat-message.hbs +++ b/templates/chat-message.hbs @@ -15,7 +15,7 @@ {{/if}} {{#if isNudgedRoll}} -
  • {{localize "CTHULHUETERNAL.Label.nudgedRoll"}} : {{wpCost}} WP spent
  • +
  • {{localize "CTHULHUETERNAL.Label.nudgedRoll"}} : {{wpCost}} {{localize "CTHULHUETERNAL.Label.WPSpent"}}
  • {{/if}} {{#if weapon}} @@ -43,26 +43,13 @@ {{#if (eq rollType "resource")}}
  • {{localize "CTHULHUETERNAL.Label.multiplier"}} : {{multiplier}}
  • {{else}} -
  • {{localize "CTHULHUETERNAL.Label.modifier"}} : {{modifier}}%
  • +
  • {{localize "CTHULHUETERNAL.Label.modifier"}} : {{totalModifier}}%
  • {{/if}}
  • {{localize "CTHULHUETERNAL.Label.targetScore"}} : {{targetScore}}%
  • {{#if isSuccess}} {{#if isCritical}}
  • {{localize "CTHULHUETERNAL.Label.criticalSuccess"}} - {{#if (eq rollType "weapon")}} - {{#if (eq weapon.system.weaponType "rangedfirearm")}} - - {{else}} - - {{/if}} - {{/if}} - {{#if (eq rollType "skill") }} - {{#if rollItem.system.isHealing}} - - {{/if}} - {{/if}} -
  • {{else}}
  • @@ -70,38 +57,58 @@ {{#if isNudge}} {{/if}} - {{#if (eq weapon.system.weaponType "rangedfirearm")}} - + +
  • + {{/if}} + {{#if (eq rollType "weapon")}} +
  • + {{#if (eq weapon.system.weaponType "rangedfirearm")}} + {{#if weapon.system.hasDamageDistance}} + {{#each weapon.system.damageDistance as |damageDistance|}} + {{#if (gt damageDistance.distance 0)}} + + + {{damageDistance.distance}}:{{damageDistance.damage}}   + + {{/if}} + {{/each}} {{else}} - + {{/if}} + {{else}} + + {{/if}} +
  • + {{/if}} {{#if (eq rollType "skill") }} {{#if rollItem.system.isHealing}} +
  • +
  • {{/if}} {{/if}} - {{/if}} {{/if}} {{#if isFailure}} - {{#if isCritical}} -
  • {{localize "CTHULHUETERNAL.Label.criticalFailure"}} - {{#if (eq rollType "skill") }} - {{#if rollItem.system.isHealing}} - - {{/if}} - {{/if}} + {{#if isCritical}} +
  • {{localize "CTHULHUETERNAL.Label.criticalFailure"}} +
  • + {{else}} +
  • + {{localize "CTHULHUETERNAL.Label.failure"}}
  • - {{else}} -
  • - {{localize "CTHULHUETERNAL.Label.failure"}} - {{#if isNudge}} - {{/if}} -
  • - {{/if}} + + {{#if isNudge}} +
  • + +
  • + {{/if}} + + {{/if}} diff --git a/templates/chat-regular-damage.hbs b/templates/chat-regular-damage.hbs index 354c17e..7c7cba3 100644 --- a/templates/chat-regular-damage.hbs +++ b/templates/chat-regular-damage.hbs @@ -4,11 +4,15 @@
  • {{weapon.name}} : {{localize "CTHULHUETERNAL.Label.damageRoll"}}
  • {{localize "CTHULHUETERNAL.Label.result"}} :{{rollResult}} ({{formula}})
  • - {{#if weapon.system.killRadius}} + {{#if (gt weapon.system.killRadius 0)}}
  • {{localize "CTHULHUETERNAL.Label.killRadius"}} : {{weapon.system.killRadius}} {{weapon.system.rangeUnit}}
  • {{localize "CTHULHUETERNAL.Label.killRadiusInfo"}}
  • {{/if}} + {{#if (gt weapon.system.armorPiercing 0)}} +
  • {{localize "CTHULHUETERNAL.Label.armorPiercing"}} : {{weapon.system.armorPiercing}}
  • + {{/if}} + {{#if ammoUsed}}
  • {{localize "CTHULHUETERNAL.Label.ammoUsed"}}: {{ammoUsed}} / {{weapon.system.ammo.value}}
  • {{/if}} diff --git a/templates/chat-san-loss-none.hbs b/templates/chat-san-loss-none.hbs new file mode 100644 index 0000000..e86e01c --- /dev/null +++ b/templates/chat-san-loss-none.hbs @@ -0,0 +1,8 @@ +
    +
    +
      +
    • {{localize "CTHULHUETERNAL.Label.SANLossNone"}}
    • +
    + +
    +
    \ No newline at end of file diff --git a/templates/chat-san-loss-unnatural.hbs b/templates/chat-san-loss-unnatural.hbs new file mode 100644 index 0000000..0f1bdb3 --- /dev/null +++ b/templates/chat-san-loss-unnatural.hbs @@ -0,0 +1,8 @@ +
    +
    +
      +
    • {{localize "CTHULHUETERNAL.Label.SANLossUnnatural"}}
    • +
    + +
    +
    \ No newline at end of file diff --git a/templates/chat-san-request.hbs b/templates/chat-san-request.hbs index 872841b..247e6dc 100644 --- a/templates/chat-san-request.hbs +++ b/templates/chat-san-request.hbs @@ -1,7 +1,11 @@
      -
    • {{localize "CTHULHUETERNAL.Label.SANTest"}}
    • + {{#if rollData.isSuccess}} +
    • {{localize "CTHULHUETERNAL.Label.SANTestSuccess"}}
    • + {{else}} +
    • {{localize "CTHULHUETERNAL.Label.SANTestFailure"}}
    • + {{/if}}
    • diff --git a/templates/protagonist-equipment.hbs b/templates/protagonist-equipment.hbs index 046fe9d..fb87e7b 100644 --- a/templates/protagonist-equipment.hbs +++ b/templates/protagonist-equipment.hbs @@ -16,11 +16,64 @@ {{item.name}}
    - - - {{localize "CTHULHUETERNAL.Label.damageShort"}} : - {{item.system.damage}} +
    + {{#if (eq system.lethality 0)}} + + + {{#if item.system.hasDamageDistance}} + {{#each item.system.damageDistance as |damageDistance|}} + {{#if (gt damageDistance.distance 0)}} + + {{damageDistance.distance}}:{{damageDistance.damage}}   + + {{/if}} + {{/each}} + {{else}} + + {{item.system.damage}} + + {{/if}} + {{else}} + N/A + {{/if}} +
    + + {{#if (gt system.baseRange 0)}} + {{item.system.baseRange}} {{item.system.rangeUnit}} + {{else}} + {{localize "CTHULHUETERNAL.Label.melee"}} + {{/if}} + + {{#if (gt system.lethality 0)}} + + + {{item.system.lethality}}% + + {{else}} + - + {{/if}} + + {{#if (gt system.killRadius 0)}} + {{item.system.killRadius}} + {{else}} + - + {{/if}} + + {{#if (gt system.armorPiercing 0)}} + {{item.system.armorPiercing}} + {{else}} + - + {{/if}} + + {{#if (eq system.weaponType "rangedfirearm")}} + {{item.system.ammo.value}}/{{item.system.ammo.max}} + {{else}} + N/A + {{/if}} +
    diff --git a/templates/roll-dialog.hbs b/templates/roll-dialog.hbs index d356f21..d8fb685 100644 --- a/templates/roll-dialog.hbs +++ b/templates/roll-dialog.hbs @@ -12,28 +12,87 @@
    {{rollItem.name}} : {{initialScore}} ({{mul initialScore 5}}%)
    {{localize "CTHULHUETERNAL.Label.Hand"}} : {{rollItem.hand}}
    {{localize "CTHULHUETERNAL.Label.Stowed"}} : {{rollItem.stowed}}
    -
    {{localize "CTHULHUETERNAL.Label.Storage"}} : {{rollItem.storage}}
    +
    + {{localize "CTHULHUETERNAL.Label.Storage"}} : {{rollItem.storage}} + +
    {{else}}
    {{rollItem.name}} : {{initialScore}}%
    {{/if}} {{#if weapon}}
    {{localize "CTHULHUETERNAL.Label.Weapon"}} : {{weapon.name}}
    + + {{#if (eq weapon.system.weaponType "melee")}} +
    + {{localize "CTHULHUETERNAL.Label.targetMove"}} + +
    + {{/if}} + {{#if isRangedWeapon}} +
    + {{localize "CTHULHUETERNAL.Label.rangedRange"}} + +
    +
    + {{localize "CTHULHUETERNAL.Label.targetMove"}} + +
    + +
    + {{localize "CTHULHUETERNAL.Label.aimingLastRound"}} + +
    + {{#if weapon.system.hasSight}} +
    + {{localize "CTHULHUETERNAL.Label.aimingWithSight"}} + +
    + {{/if}} + + {{/if}} + +
    + {{localize "CTHULHUETERNAL.Label.visibility"}} + +
    +
    + {{localize "CTHULHUETERNAL.Label.attackerState"}} + +
    +
    + {{localize "CTHULHUETERNAL.Label.targetSize"}} + +
    + {{#if weapon.system.hasSelectiveFire}}
    Selective Fire :
    {{/if}} + {{/if}} {{#if isZeroWP}}
    {{localize "CTHULHUETERNAL.Label.ZeroWP"}}
    {{else}} - {{#if isLowWP}} -
    {{localize "CTHULHUETERNAL.Label.LowWP"}} : -20%
    - {{/if}} + {{#if isLowWP}} +
    {{localize "CTHULHUETERNAL.Label.LowWP"}} : -20%
    + {{/if}} {{/if}} {{#if isExhausted}} diff --git a/templates/weapon.hbs b/templates/weapon.hbs index 100fc62..82fe4d0 100644 --- a/templates/weapon.hbs +++ b/templates/weapon.hbs @@ -12,32 +12,60 @@ {{/if}} {{formField systemFields.state value=system.state localize=true}} + {{formField systemFields.isStunning value=system.isStunning localize=true}} +
    {{formField systemFields.hasDirectSkill value=system.hasDirectSkill }} {{#if system.hasDirectSkill}} {{formField systemFields.directSkillValue value=system.directSkillValue }} {{/if}} +
    - {{formField systemFields.applyDamageBonus value=system.applyDamageBonus}} - {{formField systemFields.damage value=system.damage}} +
    + {{formField systemFields.hasDamageDistance value=system.hasDamageDistance localize=true}} +
    - {{#if isRanged}} - {{formField systemFields.baseRange value=system.baseRange}} - {{formField systemFields.rangeUnit value=system.rangeUnit localize=true}} + {{#if system.hasDamageDistance}} + {{#each system.damageDistance as |damageDistance idx|}} +
    + + +
    + {{/each}} + {{else}} +
    + {{formField systemFields.damage value=system.damage}} + {{formField systemFields.applyDamageBonus value=system.applyDamageBonus}} +
    + {{#if isRanged}} +
    + {{formField systemFields.baseRange value=system.baseRange}} + {{formField systemFields.rangeUnit value=system.rangeUnit localize=true}} +
    + {{/if}} {{/if}} {{#if isFireArm}} +
    {{formField systemFields.hasSelectiveFire value=system.hasSelectiveFire}} + {{formField systemFields.hasSight value=system.hasSight}} +
    +
    {{formField systemFields.ammo.fields.value value=system.ammo.value}} {{formField systemFields.ammo.fields.max value=system.ammo.max}} +
    {{/if}} - {{formField systemFields.lethality value=system.lethality}} - {{formField systemFields.killRadius value=system.killRadius}} +
    + {{formField systemFields.lethality value=system.lethality}} + {{formField systemFields.killRadius value=system.killRadius}} +
    +
    {{formField systemFields.armorPiercing value=system.armorPiercing}} - {{formField systemFields.resourceLevel value=system.resourceLevel}} +
    +