Manage selective fire

This commit is contained in:
2025-06-15 00:30:24 +02:00
parent e0400793ff
commit 9e4d76298c
35 changed files with 654 additions and 122 deletions

View File

@ -170,10 +170,62 @@ i.fvtt-cthulhu-eternal {
background-position: 0%; background-position: 0%;
background-size: 100% 100%; background-size: 100% 100%;
} }
.chat-lethal-damage ul {
list-style-type: none;
padding: 0;
margin: 0;
justify-content: center;
align-items: center;
}
.chat-lethal-damage ul .result-lethal {
color: var(--color-critical-failure);
font-family: var(--font-title);
}
.chat-lethal-damage ul .result-non-lethal {
color: var(--color-failure);
font-family: var(--font-title);
}
.chat-lethal-damage ul li {
margin: 0 10px;
font-family: var(--font-primary);
font-size: calc(var(--font-size-standard) * 1.02);
}
.fvtt-cthulhu-eternal .protagonist-sheet-common label { .fvtt-cthulhu-eternal .protagonist-sheet-common label {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1); font-size: calc(var(--font-size-standard) * 1);
} }
.fvtt-cthulhu-eternal .protagonist-sheet-common .hp-unconscious {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1);
color: #b4710c;
}
.fvtt-cthulhu-eternal .protagonist-sheet-common .hp-dead {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1);
color: #b40000;
}
.fvtt-cthulhu-eternal .protagonist-sheet-common .protagonist-luck {
display: flex;
min-width: 8rem;
max-width: 8rem;
}
.fvtt-cthulhu-eternal .protagonist-sheet-common .protagonist-luck .rollable:hover,
.fvtt-cthulhu-eternal .protagonist-sheet-common .protagonist-luck .rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer;
font-size: 0.9rem;
}
.fvtt-cthulhu-eternal .protagonist-sheet-common .damage-bonus {
display: flex;
}
.fvtt-cthulhu-eternal .protagonist-sheet-common .damage-bonus label {
max-width: 5rem;
min-width: 5rem;
}
.fvtt-cthulhu-eternal .protagonist-sheet-common .damage-bonus input {
max-width: 2rem;
min-width: 2rem;
}
.fvtt-cthulhu-eternal .vehicle-sheet-common label { .fvtt-cthulhu-eternal .vehicle-sheet-common label {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1); font-size: calc(var(--font-size-standard) * 1);
@ -203,6 +255,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
overflow: scroll; overflow: scroll;
} }
.fvtt-cthulhu-eternal .protagonist-content .sheet-tabs a { .fvtt-cthulhu-eternal .protagonist-content .sheet-tabs a {
@ -250,7 +303,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .protagonist-content legend { .fvtt-cthulhu-eternal .protagonist-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -258,6 +311,38 @@ i.fvtt-cthulhu-eternal {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1); font-size: calc(var(--font-size-standard) * 1);
} }
.fvtt-cthulhu-eternal .protagonist-content .hp-unconscious {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1);
color: #b4710c;
}
.fvtt-cthulhu-eternal .protagonist-content .hp-dead {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1);
color: #b40000;
}
.fvtt-cthulhu-eternal .protagonist-content .protagonist-luck {
display: flex;
min-width: 8rem;
max-width: 8rem;
}
.fvtt-cthulhu-eternal .protagonist-content .protagonist-luck .rollable:hover,
.fvtt-cthulhu-eternal .protagonist-content .protagonist-luck .rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer;
font-size: 0.9rem;
}
.fvtt-cthulhu-eternal .protagonist-content .damage-bonus {
display: flex;
}
.fvtt-cthulhu-eternal .protagonist-content .damage-bonus label {
max-width: 5rem;
min-width: 5rem;
}
.fvtt-cthulhu-eternal .protagonist-content .damage-bonus input {
max-width: 2rem;
min-width: 2rem;
}
.fvtt-cthulhu-eternal .sheet-tabs { .fvtt-cthulhu-eternal .sheet-tabs {
background-color: var(--color-light-1); background-color: var(--color-light-1);
} }
@ -295,9 +380,6 @@ i.fvtt-cthulhu-eternal {
width: 2rem; width: 2rem;
margin-left: 4px; margin-left: 4px;
} }
.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp .damage-bonus {
font-size: calc(var(--font-size-standard) * 0.8);
}
.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp .hp-separator { .fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp .hp-separator {
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.2);
display: flex; display: flex;
@ -867,6 +949,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
overflow: scroll; overflow: scroll;
} }
.fvtt-cthulhu-eternal .vehicle-content .sheet-tabs a { .fvtt-cthulhu-eternal .vehicle-content .sheet-tabs a {
@ -914,7 +997,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .vehicle-content legend { .fvtt-cthulhu-eternal .vehicle-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -1124,6 +1207,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
overflow: scroll; overflow: scroll;
} }
.fvtt-cthulhu-eternal .creature-content .sheet-tabs a { .fvtt-cthulhu-eternal .creature-content .sheet-tabs a {
@ -1171,7 +1255,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .creature-content legend { .fvtt-cthulhu-eternal .creature-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -1782,6 +1866,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .skill-content .sheet-tabs a { .fvtt-cthulhu-eternal .skill-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -1828,7 +1913,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .skill-content legend { .fvtt-cthulhu-eternal .skill-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -1876,6 +1961,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .injury-content .sheet-tabs a { .fvtt-cthulhu-eternal .injury-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -1922,7 +2008,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .injury-content legend { .fvtt-cthulhu-eternal .injury-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -1970,6 +2056,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .weapon-content .sheet-tabs a { .fvtt-cthulhu-eternal .weapon-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -2016,7 +2103,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .weapon-content legend { .fvtt-cthulhu-eternal .weapon-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -2056,6 +2143,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .armor-content .sheet-tabs a { .fvtt-cthulhu-eternal .armor-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -2102,7 +2190,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .armor-content legend { .fvtt-cthulhu-eternal .armor-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -2142,6 +2230,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .motivation-content .sheet-tabs a { .fvtt-cthulhu-eternal .motivation-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -2188,7 +2277,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .motivation-content legend { .fvtt-cthulhu-eternal .motivation-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -2228,6 +2317,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .mentaldisorder-content .sheet-tabs a { .fvtt-cthulhu-eternal .mentaldisorder-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -2274,7 +2364,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .mentaldisorder-content legend { .fvtt-cthulhu-eternal .mentaldisorder-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -2314,6 +2404,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .bond-content .sheet-tabs a { .fvtt-cthulhu-eternal .bond-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -2360,7 +2451,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .bond-content legend { .fvtt-cthulhu-eternal .bond-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -2416,6 +2507,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .gear-content .sheet-tabs a { .fvtt-cthulhu-eternal .gear-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -2462,7 +2554,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .gear-content legend { .fvtt-cthulhu-eternal .gear-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -2502,6 +2594,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .arcane-content .sheet-tabs a { .fvtt-cthulhu-eternal .arcane-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -2548,7 +2641,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .arcane-content legend { .fvtt-cthulhu-eternal .arcane-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -2588,6 +2681,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .archetype-content .sheet-tabs a { .fvtt-cthulhu-eternal .archetype-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -2634,7 +2728,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .archetype-content legend { .fvtt-cthulhu-eternal .archetype-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -2674,6 +2768,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .ritual-content .sheet-tabs a { .fvtt-cthulhu-eternal .ritual-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -2720,7 +2815,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .ritual-content legend { .fvtt-cthulhu-eternal .ritual-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -2768,6 +2863,7 @@ i.fvtt-cthulhu-eternal {
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
} }
.fvtt-cthulhu-eternal .tome-content .sheet-tabs a { .fvtt-cthulhu-eternal .tome-content .sheet-tabs a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
@ -2814,7 +2910,7 @@ i.fvtt-cthulhu-eternal {
} }
.fvtt-cthulhu-eternal .tome-content legend { .fvtt-cthulhu-eternal .tome-content legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -2940,6 +3036,11 @@ i.fvtt-cthulhu-eternal {
margin-left: 2rem; margin-left: 2rem;
display: none; display: none;
} }
.dice-roll .intro-chat .intro-right ul .healing-roll {
font-size: calc(var(--font-size-standard) * 1);
margin-left: 2rem;
display: none;
}
.dice-roll .intro-chat .intro-right ul .roll-damage { .dice-roll .intro-chat .intro-right ul .roll-damage {
font-size: calc(var(--font-size-standard) * 1); font-size: calc(var(--font-size-standard) * 1);
margin-left: 2rem; margin-left: 2rem;

View File

@ -124,12 +124,12 @@ Hooks.once("ready", function () {
} }
preLocalizeConfig() preLocalizeConfig()
if (game.user.isGM && game.i18n.lang === 'fr' && !game.modules.find(m => m.id == "babele")) { if (game.user.isGM && game.i18n.lang === 'fr' && typeof Babele === 'undefined') {
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
whisper: [game.user.id], whisper: [game.user.id],
content: `<div ><span class=""> content: `<div ><span class="">
<strong>ATTENTION ! Français détecte, mais le module Babele n'est pas installé !<br>Installez Babele pour bénéficier de la traduction des compendiums` <strong>ATTENTION ! Français détecté, mais le module Babele n'est pas installé !<br>Installez Babele pour bénéficier de la traduction des compendiums`
}) })
} }
@ -144,12 +144,18 @@ Hooks.on("renderChatMessageHTML", (message, html, data) => {
$(html).find(".damage-roll").each((i, btn) => { $(html).find(".damage-roll").each((i, btn) => {
btn.style.display = "inline" btn.style.display = "inline"
}) })
$(html).find(".healing-roll").each((i, btn) => {
btn.style.display = "inline"
})
$(html).find(".nudge-roll").click((event) => { $(html).find(".nudge-roll").click((event) => {
CthulhuEternalUtils.nudgeRoll(message) CthulhuEternalUtils.nudgeRoll(message)
}) })
$(html).find(".damage-roll").click((event) => { $(html).find(".damage-roll").click((event) => {
CthulhuEternalUtils.damageRoll(message) CthulhuEternalUtils.damageRoll(message)
}) })
$(html).find(".healing-roll").click((event) => {
CthulhuEternalUtils.healingRoll(message)
})
} }
}) })

View File

@ -57,6 +57,12 @@
"label": "Storage" "label": "Storage"
} }
}, },
"hp": {
"label": "HP",
"stunned": {
"label": "Stun."
}
},
"biodata": { "biodata": {
"feature": { "feature": {
"label": "Feature" "label": "Feature"
@ -207,6 +213,12 @@
"RangedWeapons": "Ranged Weapons", "RangedWeapons": "Ranged Weapons",
"FirearmsBeams": "Firearms / Beam Weapons", "FirearmsBeams": "Firearms / Beam Weapons",
"FIELDS": { "FIELDS": {
"isHealing": {
"label": "Healing skill"
},
"healingFormula": {
"label": "Healing PV roll"
},
"isAdversary": { "isAdversary": {
"label": "Adversary" "label": "Adversary"
}, },
@ -278,6 +290,15 @@
"directSkillValue": { "directSkillValue": {
"label": "Direct skill value" "label": "Direct skill value"
}, },
"ammo": {
"label": "Ammo",
"value": {
"label": "Ammo value"
},
"max": {
"label": "Max ammo"
}
},
"state": { "state": {
"label": "State" "label": "State"
}, },
@ -495,9 +516,14 @@
} }
}, },
"Label": { "Label": {
"rollNudge": "Roll Nudge",
"rollDamage": "Roll Damage",
"rollHealing": "Roll Healing",
"result": "Result",
"damageMessage": "Damage to apply",
"lethalityRoll": "Lethality Roll", "lethalityRoll": "Lethality Roll",
"lethalityWounded": "The target is lethally wounded", "lethalityWounded": "The target is lethally wounded (HP = 0)",
"lethalityNotWounded": "The target is not lethally wounded", "lethalityNotWounded": "The target is not lethally wounded, apply damage",
"damageRoll": "Damage Roll", "damageRoll": "Damage Roll",
"vehicle":"Vehicle", "vehicle":"Vehicle",
"Weapon": "Weapon", "Weapon": "Weapon",
@ -622,7 +648,21 @@
"noActorFound": "No actor found", "noActorFound": "No actor found",
"skillFailed": "Skill roll failed : the skill has been ticked for progression", "skillFailed": "Skill roll failed : the skill has been ticked for progression",
"rollProgress": "Roll Progress", "rollProgress": "Roll Progress",
"skillProgress": "Skill Progress" "skillProgress": "Skill Progress",
"unconscious": "Unconscious",
"dying": "Dying",
"stunnedWarning": "The Protagonist is stunned. He cannot act until he recovers by successfully rolling a CONx5 check.",
"deadWarning": "The Protagonist is dead. He cannot act until he is revived by a successful First Aid roll.",
"unconsciousWarning": "The Protagonist is unconscious. He cannot act until he has at least 3 HP.",
"Luck": "Luck",
"titleLuck": "Luck Roll",
"healingRoll": "Healing Roll succes, the target gains",
"healingRollFailure": "Healing roll failed ! The target looses",
"killRadius": "Kill Radius",
"killRadiusInfo": "All targets within the kill radius suffer the damage",
"ammoUsed": "Ammo used",
"lethalityLethal": "Lethal !!",
"lethalityNotLethal": "Non-Lethal"
}, },
"ChatMessage": { "ChatMessage": {
"exhausted": "Your protagonist is exhausted. He loses [[/r 1d6]] Willpower Points." "exhausted": "Your protagonist is exhausted. He loses [[/r 1d6]] Willpower Points."
@ -651,7 +691,9 @@
"NoWeaponSkill": "No weapon skill found for this weapon. Check Weapon definition or available skills/era", "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", "NoWeaponType": "No weapon type found for this weapon subtype. Check Weapon definition or available skills/era",
"skillAlreadyExists": "Skill already exists", "skillAlreadyExists": "Skill already exists",
"WrongEra": "The era of the item does not match the ear of the system" "WrongEra": "The era of the item does not match the ear of the system",
"NoSelectiveFireChoices": "Not enough ammo fo Selective Fire choices for this weapon.",
"NoAmmo": "No more ammo for this weapon. "
} }
} }
} }

View File

@ -42,6 +42,12 @@
"FIELDS": { "FIELDS": {
"damageBonus": { "damageBonus": {
"label": "Bonus D." "label": "Bonus D."
},
"hp": {
"label": "HP",
"stunned": {
"label": "Etourdi"
}
}, },
"resources": { "resources": {
"permanentRating": { "permanentRating": {
@ -207,6 +213,12 @@
"RangedWeapons": "Armes de tir", "RangedWeapons": "Armes de tir",
"FirearmsBeams": "Armes à feu / à rayons", "FirearmsBeams": "Armes à feu / à rayons",
"FIELDS": { "FIELDS": {
"isHealing": {
"label": "Compétence de soin"
},
"healingFormula": {
"label": "PV soignés"
},
"isAdversary": { "isAdversary": {
"label": "Adversaire" "label": "Adversaire"
}, },
@ -272,6 +284,15 @@
"longspray": "Barrage long" "longspray": "Barrage long"
}, },
"FIELDS": { "FIELDS": {
"ammo": {
"label": "Munitions",
"value": {
"label": "Munitions (actuelles)"
},
"max": {
"label": "Munitions (max)"
}
},
"hasDirectSkill": { "hasDirectSkill": {
"label": "Compétence intégrée" "label": "Compétence intégrée"
}, },
@ -495,9 +516,14 @@
} }
}, },
"Label": { "Label": {
"rollNudge": "Modifier le jet",
"rollDamage": "Jet de dégâts",
"rollHealing": "Jet de soin",
"result": "Resultat",
"damageMessage": "Dégâts à appliquer",
"lethalityRoll": "Jet de Létalité", "lethalityRoll": "Jet de Létalité",
"lethalityWounded": "La cible est mortellement blessée", "lethalityWounded": "La cible est mortellement blessée (PV = 0)",
"lethalityNotWounded": "La cible n'est PAS mortellement blessée", "lethalityNotWounded": "La cible n'est PAS mortellement blessée, encaissement des dégâts",
"damageRoll": "Jet de dégâts", "damageRoll": "Jet de dégâts",
"vehicle":"Véhicule", "vehicle":"Véhicule",
"Weapon": "Arme", "Weapon": "Arme",
@ -559,7 +585,7 @@
"conLong": "Constitution", "conLong": "Constitution",
"chaLong": "Charisme", "chaLong": "Charisme",
"total": "Total", "total": "Total",
"skills": "Compétence", "skills": "Compétences",
"gear": "Matériel", "gear": "Matériel",
"damage": "Dégâts", "damage": "Dégâts",
"resource": "Ressource", "resource": "Ressource",
@ -622,7 +648,21 @@
"noActorFound": "Aucun protagoniste trouvé", "noActorFound": "Aucun protagoniste trouvé",
"skillFailed": "Jet de compétence échoué : la compétence a été marquée comme pouvant progresser.", "skillFailed": "Jet de compétence échoué : la compétence a été marquée comme pouvant progresser.",
"rollProgress": "Jet de progression", "rollProgress": "Jet de progression",
"skillProgress": "Progression de compétence" "skillProgress": "Progression de compétence",
"unconscious": "Inconscient",
"dying": "Mourant",
"stunnedWarning": "Votre protagoniste est étourdi. Il ne peut pas agir tant qu'il n'a pas réussi un test de CON x 5.",
"deadWarning": "Votre protagoniste est mourrant. Il mourra s'il n'est pas soigné dans les {con} minutes",
"unconsciousWarning": "Votre protagoniste est inconscient. Il ne peut pas agir tant qu'il n'a pas atteint 3 PV.",
"Luck": "Chance",
"titleLuck": "Jet de Chance",
"healingRoll": "Jet de soin, PV soignés",
"healingRollFailure": "Jet de soin échoué critique, PV perdus",
"killRadius": "Rayon de mortlalité",
"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"
}, },
"ChatMessage": { "ChatMessage": {
"exhausted": "Votre protagoniste est épuisé. Il perd [[/r 1d6]] Points de Volonté." "exhausted": "Votre protagoniste est épuisé. Il perd [[/r 1d6]] Points de Volonté."
@ -651,7 +691,9 @@
"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.", "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.", "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", "skillAlreadyExists": "La compétence existe déja",
"WrongEra": "L'époque de l'item ne correspond pas à celle du jeu en cours." "WrongEra": "L'époque de l'item ne correspond pas à celle du jeu en cours.",
"NoSelectiveFireChoices": "Aucune option de tir sélectif n'est disponible pour cette arme : pas assez de munitions.",
"NoAmmo": "Aucune munition disponible pour cette arme."
} }
} }
} }

View File

@ -199,7 +199,7 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
* corresponding value from the document's system and performs the roll. * corresponding value from the document's system and performs the roll.
*/ */
async _onRoll(event, target) { async _onRoll(event, target) {
const rollType = $(event.currentTarget).data("roll-type") let rollType = $(event.currentTarget).data("roll-type")
let item let item
let li let li
// Debug : console.log(">>>>", event, target, rollType) // Debug : console.log(">>>>", event, target, rollType)
@ -231,6 +231,12 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
item.name = game.i18n.localize("CTHULHUETERNAL.Label.SAN") item.name = game.i18n.localize("CTHULHUETERNAL.Label.SAN")
item.targetScore = item.value item.targetScore = item.value
break; break;
case "luck":
item = foundry.utils.duplicate(this.actor.system.characteristics.int)
item.name = game.i18n.localize("CTHULHUETERNAL.Label.Luck")
item.value = 10
item.targetScore = 50
break;
default: default:
throw new Error(`Unknown roll type ${rollType}`) throw new Error(`Unknown roll type ${rollType}`)
} }

View File

@ -18,4 +18,13 @@ export default class CthulhuEternalWeaponSheet extends CthulhuEternalItemSheet {
template: "systems/fvtt-cthulhu-eternal/templates/weapon.hbs", template: "systems/fvtt-cthulhu-eternal/templates/weapon.hbs",
}, },
} }
async _prepareContext() {
let context = await super._prepareContext()
context.isFireArm = this.item.system.isFireArm()
context.isRanged = this.item.system.isRanged()
return context
}
} }

View File

@ -31,7 +31,6 @@ export default class CthulhuEternalActor extends Actor {
} }
_onUpdate(changed, options, userId) { _onUpdate(changed, options, userId) {
// DEBUG : console.log("CthulhuEternalActor.update", changed, options, userId)
if (changed?.system?.wp?.exhausted) { if (changed?.system?.wp?.exhausted) {
ChatMessage.create({ ChatMessage.create({
user: userId, user: userId,

View File

@ -105,6 +105,105 @@ export default class CthulhuEternalRoll extends Roll {
$(".resource-score").text(`${rating} (${options.percentScore}%)`) $(".resource-score").text(`${rating} (${options.percentScore}%)`)
} }
static buildSelectiveFireChoices(actor, weapon) {
if (!weapon || !weapon?.system?.hasSelectiveFire) {
return {}
}
// Loop thru the selective fire choices and build the choices object when enough ammo in the weapon
let choices = {}
for (let choiceKey in SYSTEM.WEAPON_SELECTIVE_FIRE_CHOICES) {
let choice = SYSTEM.WEAPON_SELECTIVE_FIRE_CHOICES[choiceKey]
if (choice.ammoUsed > 0 && choice.ammoUsed <= weapon.system.ammo.value) {
choices[choiceKey] = choice
}
}
// If no choices available, warn the user
if (Object.keys(choices).length === 0) {
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.NoSelectiveFireChoices"))
return {}
}
return choices
}
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
}
if (weapon.system.lethality > 0) {
let lethalityRoll = new Roll("1d100")
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 = {
weapon,
wounds,
lethalScore,
isLethal,
ammoUsed,
rollResult: lethalityRoll.total,
}
let flavor = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-lethal-damage.hbs", msgData)
ChatMessage.create({
user: game.user.id,
content: flavor,
speaker: ChatMessage.getSpeaker({ actor: actor }),
}, { rollMode: options.rollMode, create: true })
return
}
// 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") {
formula += ` + ${weapon.damageBonus}`
}
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()
let msgData = {
weapon,
formula,
ammoUsed,
rollResult: damageRoll.total,
}
let flavor = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-regular-damage.hbs", msgData)
ChatMessage.create({
user: game.user.id,
content: flavor,
speaker: ChatMessage.getSpeaker({ actor: actor }),
}, { rollMode: options.rollMode, create: true })
}
/** /**
* Prompt the user with a dialog to configure and execute a roll. * Prompt the user with a dialog to configure and execute a roll.
* *
@ -124,12 +223,18 @@ export default class CthulhuEternalRoll extends Roll {
let hasModifier = true let hasModifier = true
let hasMultiplier = false let hasMultiplier = false
options.isNudge = true options.isNudge = true
let actor = game.actors.get(options.actorId)
switch (options.rollType) { switch (options.rollType) {
case "skill": case "skill":
console.log(options.rollItem) console.log(options.rollItem)
options.initialScore = options.rollItem.system.computeScore() options.initialScore = options.rollItem.system.computeScore()
break break
case "luck":
hasModifier = false
options.initialScore = 50
options.isNudge = false
break
case "san": case "san":
case "char": case "char":
options.initialScore = options.rollItem.targetScore options.initialScore = options.rollItem.targetScore
@ -146,40 +251,8 @@ export default class CthulhuEternalRoll extends Roll {
options.rollItem.enableStorage = true options.rollItem.enableStorage = true
options.isNudge = false options.isNudge = false
break break
case "damage": { case "damage":
let isLethal = false return this.processWeaponDamage(actor, options)
options.isNudge = false
if (options.rollItem.system.lethality > 0) {
let lethalityRoll = new Roll("1d100")
await lethalityRoll.evaluate()
let lethalScore = (options?.previousResultType === "successCritical") ? options.rollItem.system.lethality * 2 : options.rollItem.system.lethality
isLethal = (lethalityRoll.total <= lethalScore)
let flavor = `${options.rollItem.name} - <strong> ${game.i18n.localize("CTHULHUETERNAL.Label.lethalityRoll")} </strong> : ${lethalityRoll.total} <= ${lethalScore} => ${isLethal}`
if (isLethal) {
flavor += `<br> ${game.i18n.localize("CTHULHUETERNAL.Label.lethalityWounded")} => HP = 0`
} else {
let wounds = Math.floor(lethalityRoll.total / 10) + (lethalityRoll.total % 10)
flavor += `<br> ${game.i18n.localize("CTHULHUETERNAL.Label.lethalityNotWounded")} => HP loss = ${wounds}`
}
await lethalityRoll.toMessage({
flavor: flavor
});
return
}
let formula = options.rollItem.system.damage
if (options.rollItem.system.weaponType === "melee" || options.rollItem.system.weaponType === "unarmed") {
formula += ` + ${options.rollItem.damageBonus}`
}
if (options?.previousResultType === "successCritical") {
formula = `( ${formula} ) * 2`
}
let damageRoll = new Roll(formula)
await damageRoll.evaluate()
await damageRoll.toMessage({
flavor: `${options.rollItem.name} - ${game.i18n.localize("CTHULHUETERNAL.Label.damageRoll")}`
});
}
return
case "weapon": { case "weapon": {
let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era") let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era")
if (era !== options.rollItem.system.settings) { if (era !== options.rollItem.system.settings) {
@ -192,6 +265,11 @@ export default class CthulhuEternalRoll extends Roll {
console.log("WP Not found", era, options.rollItem.system.weaponType) console.log("WP Not found", era, options.rollItem.system.weaponType)
return return
} }
// 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 options.weapon = options.rollItem
if (options.rollItem.system.hasDirectSkill) { if (options.rollItem.system.hasDirectSkill) {
let skillName = options.rollItem.name let skillName = options.rollItem.name
@ -199,7 +277,6 @@ export default class CthulhuEternalRoll extends Roll {
options.initialScore = options.weapon.system.directSkillValue options.initialScore = options.weapon.system.directSkillValue
} else { } else {
let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType]) let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType])
let actor = game.actors.get(options.actorId)
options.rollItem = actor.items.find(i => i.type === "skill" && i.name.toLowerCase() === skillName.toLowerCase()) options.rollItem = actor.items.find(i => i.type === "skill" && i.name.toLowerCase() === skillName.toLowerCase())
if (!options.rollItem) { if (!options.rollItem) {
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.NoWeaponSkill")) ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.NoWeaponSkill"))
@ -215,7 +292,6 @@ export default class CthulhuEternalRoll extends Roll {
break break
} }
console.log("Roll options", CONFIG.Dice.rollModes);
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); //Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)])) const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); //Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
const fieldRollMode = new foundry.data.fields.StringField({ const fieldRollMode = new foundry.data.fields.StringField({
choices: rollModes, choices: rollModes,
@ -225,7 +301,7 @@ export default class CthulhuEternalRoll extends Roll {
const choiceModifier = SYSTEM.MODIFIER_CHOICES const choiceModifier = SYSTEM.MODIFIER_CHOICES
const choiceMultiplier = SYSTEM.MULTIPLIER_CHOICES const choiceMultiplier = SYSTEM.MULTIPLIER_CHOICES
const choiceSelectiveFire = SYSTEM.WEAPON_SELECTIVE_FIRE_CHOICES const choiceSelectiveFire = this.buildSelectiveFireChoices(actor, options?.weapon)
let modifier = "+0" let modifier = "+0"
let multiplier = "5" let multiplier = "5"
@ -318,6 +394,10 @@ export default class CthulhuEternalRoll extends Roll {
} }
rollData.targetScore = Math.min(Math.max(rollData.targetScore, 0), 100) rollData.targetScore = Math.min(Math.max(rollData.targetScore, 0), 100)
} }
if (!rollData.targetScore) {
rollData.targetScore = options.initialScore
rollData.modifier = "0"
}
if (Hooks.call("fvtt-cthulhu-eternal.preRoll", options, rollData) === false) return if (Hooks.call("fvtt-cthulhu-eternal.preRoll", options, rollData) === false) return
@ -390,6 +470,8 @@ export default class CthulhuEternalRoll extends Roll {
*/ */
static createTitle(type, target) { static createTitle(type, target) {
switch (type) { switch (type) {
case "luck":
return `${game.i18n.localize("CTHULHUETERNAL.Label.titleLuck")}`
case "skill": case "skill":
return `${game.i18n.localize("CTHULHUETERNAL.Label.titleSkill")}` return `${game.i18n.localize("CTHULHUETERNAL.Label.titleSkill")}`
case "weapon": case "weapon":

View File

@ -35,7 +35,9 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
schema.hp = new fields.SchemaField({ schema.hp = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }), value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
max: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }), max: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
stunned: new fields.BooleanField({ required: true, initial: false }) stunned: new fields.BooleanField({ required: true, initial: false }),
unconscious: new fields.BooleanField({ required: true, initial: false }),
dead: new fields.BooleanField({ required: true, initial: false })
}) })
schema.san = new fields.SchemaField({ schema.san = new fields.SchemaField({
@ -130,6 +132,22 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
updates[`system.damageBonus`] = dmgBonus updates[`system.damageBonus`] = dmgBonus
} }
// Unconsciousness management
if (!this.hp.unconscious && this.hp.value <= 2) {
updates[`system.hp.unconscious`] = true
}
if (this.hp.unconscious && this.hp.value > 2) {
updates[`system.hp.unconscious`] = false
}
// Dead management
if (!this.hp.dead && this.hp.value <= 0) {
updates[`system.hp.dead`] = true
}
if (this.hp.dead && this.hp.value > 0) {
updates[`system.hp.dead`] = false
}
// Sanity check // Sanity check
if (this.san.value > this.san.max) { if (this.san.value > this.san.max) {
updates[`system.san.value`] = this.san.max updates[`system.san.value`] = this.san.max
@ -165,6 +183,10 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
} }
} }
isStunned() {
return this.hp.stunned
}
isLowWP() { isLowWP() {
return this.wp.value <= 2 return this.wp.value <= 2
} }
@ -207,6 +229,32 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
* @returns {Promise<null>} - A promise that resolves to null if the roll is cancelled. * @returns {Promise<null>} - A promise that resolves to null if the roll is cancelled.
*/ */
async roll(rollType, rollItem) { async roll(rollType, rollItem) {
if (this.hp.dead ) {
// Warn with chat message
ChatMessage.create({
content: `<p>${game.i18n.format("CTHULHUETERNAL.Label.deadWarning", {con: this.characteristics.con.value} )}</p>`,
speaker: ChatMessage.getSpeaker({ actor: this.parent })
})
return null
}
if (this.hp.unconscious ) {
// Warn with chat message
ChatMessage.create({
content: `<p>${game.i18n.localize("CTHULHUETERNAL.Label.unconsciousWarning")}</p>`,
speaker: ChatMessage.getSpeaker({ actor: this.parent })
})
return null
}
if (this.hp.stunned && rollType === "skill") {
// Warn with chat message
ChatMessage.create({
content: `<p>${game.i18n.localize("CTHULHUETERNAL.Label.stunnedWarning")}</p>`,
speaker: ChatMessage.getSpeaker({ actor: this.parent })
})
return null
}
let opponentTarget let opponentTarget
const hasTarget = opponentTarget !== undefined const hasTarget = opponentTarget !== undefined

View File

@ -15,6 +15,8 @@ export default class CthulhuEternalSkill extends foundry.abstract.TypeDataModel
schema.diceEvolved = new fields.BooleanField({ required: true, initial: true }) schema.diceEvolved = new fields.BooleanField({ required: true, initial: true })
schema.rollFailed = new fields.BooleanField({ required: true, initial: false }) schema.rollFailed = new fields.BooleanField({ required: true, initial: false })
schema.isAdversary = new fields.BooleanField({ required: true, initial: false }) schema.isAdversary = new fields.BooleanField({ required: true, initial: false })
schema.isHealing = new fields.BooleanField({ required: true, initial: false })
schema.healingFormula = new fields.StringField({ required: true, initial: "1d4" })
return schema return schema
} }
@ -36,11 +38,11 @@ export default class CthulhuEternalSkill extends foundry.abstract.TypeDataModel
return `${this.base} + ${ String(this.bonus)}`; return `${this.base} + ${ String(this.bonus)}`;
} }
// Split the base value per stat : // Split the base value per stat :
let base = this.base.toLowerCase(); let base = this.base.toLowerCase();
let char = actor.system.characteristics[base]; let char = actor.system.characteristics[base];
if (!char) { if (!char) {
ui.notifications.error(`The characteristic ${base} is wrong for actor ${actor.name}`); ui.notifications.error(`The characteristic ${base} is wrong for actor ${actor.name}`);
return `${this.base } + ${ String(this.bonus)}`; return `${this.base } + ${ String(this.bonus)}`;
} }
let charValue = char.value; let charValue = char.value;

View File

@ -25,6 +25,10 @@ export default class CthulhuEternalWeapon extends foundry.abstract.TypeDataModel
schema.armorPiercing = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.armorPiercing = new fields.NumberField({ required: true, initial: 0, min: 0 })
schema.weaponSubtype = new fields.StringField({ required: true, initial: "basicfirearm", choices: SYSTEM.WEAPON_SUBTYPE }) schema.weaponSubtype = new fields.StringField({ required: true, initial: "basicfirearm", choices: SYSTEM.WEAPON_SUBTYPE })
schema.state = new fields.StringField({ required: true, initial: "pristine", choices: SYSTEM.EQUIPMENT_STATES }) schema.state = new fields.StringField({ required: true, initial: "pristine", choices: SYSTEM.EQUIPMENT_STATES })
schema.ammo = new fields.SchemaField({
value: new fields.NumberField({ ...requiredInteger, initial: 6, min: 0 }),
max: new fields.NumberField({ ...requiredInteger, initial: 6, min: 0 })
})
schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 })
@ -37,4 +41,12 @@ export default class CthulhuEternalWeapon extends foundry.abstract.TypeDataModel
get weaponCategory() { get weaponCategory() {
return game.i18n.localize(CATEGORY[this.category].label) return game.i18n.localize(CATEGORY[this.category].label)
} }
isRanged() {
return this.weaponType.includes("ranged")
}
isFireArm() {
return this.weaponType === "rangedfirearm"
}
} }

View File

@ -180,6 +180,30 @@ export default class CthulhuEternalUtils {
}); });
} }
static async healingRoll(rollMessage) {
let rollData = rollMessage.rolls[0]?.options?.rollData
let healingFormula = rollData.rollItem.system.healingFormula
let healingMsg = "CTHULHUETERNAL.Label.healingRoll"
if (rollData.resultType === "successCritical") {
healingFormula += " * 2"
}
if (rollData.resultType === "failureCritical") {
healingMsg = "CTHULHUETERNAL.Label.healingRollFailure"
}
// Now display the result in chat message
let roll = new Roll(healingFormula)
await roll.evaluate()
roll.toMessage({
speaker: ChatMessage.getSpeaker({ actor: rollData.actorId }),
flavor: `${game.i18n.localize(healingMsg)} : ${roll.total}`,
rolls: [roll],
options: {
rollData: rollData,
resultType: rollData.resultType
}
})
}
static async damageRoll(rollMessage) { static async damageRoll(rollMessage) {
let rollData = rollMessage.rolls[0]?.options?.rollData let rollData = rollMessage.rolls[0]?.options?.rollData
let actor = game.actors.get(rollData.actorId) let actor = game.actors.get(rollData.actorId)
@ -187,7 +211,9 @@ export default class CthulhuEternalUtils {
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Label.noActorFound")) ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Label.noActorFound"))
return return
} }
console.log("Damage roll data", rollData)
rollData.weapon.resultType = rollData.resultType // Keep the result type from the roll message 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
actor.system.roll("damage", rollData.weapon) actor.system.roll("damage", rollData.weapon)
} }

View File

@ -1 +1 @@
MANIFEST-000081 MANIFEST-000131

View File

@ -1,7 +1,3 @@
2025/06/12-21:40:36.466688 7f13a0ff96c0 Recovering log #79 2025/06/14-23:45:33.918294 7f78d8df86c0 Recovering log #129
2025/06/12-21:40:36.523036 7f13a0ff96c0 Delete type=3 #77 2025/06/14-23:45:34.040033 7f78d8df86c0 Delete type=3 #127
2025/06/12-21:40:36.523080 7f13a0ff96c0 Delete type=0 #79 2025/06/14-23:45:34.040084 7f78d8df86c0 Delete type=0 #129
2025/06/12-22:19:34.910570 7f139fbff6c0 Level-0 table #84: started
2025/06/12-22:19:34.910598 7f139fbff6c0 Level-0 table #84: 0 bytes OK
2025/06/12-22:19:34.968716 7f139fbff6c0 Delete type=0 #82
2025/06/12-22:19:35.027464 7f139fbff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)

View File

@ -1,7 +1,7 @@
2025/06/12-20:37:22.833913 7f13a0ff96c0 Recovering log #75 2025/06/14-13:49:17.890351 7f78d8df86c0 Recovering log #125
2025/06/12-20:37:22.843981 7f13a0ff96c0 Delete type=3 #73 2025/06/14-13:49:17.899990 7f78d8df86c0 Delete type=3 #123
2025/06/12-20:37:22.844063 7f13a0ff96c0 Delete type=0 #75 2025/06/14-13:49:17.900040 7f78d8df86c0 Delete type=0 #125
2025/06/12-20:52:48.559109 7f139fbff6c0 Level-0 table #80: started 2025/06/14-16:21:28.823932 7f78d37fe6c0 Level-0 table #130: started
2025/06/12-20:52:48.559156 7f139fbff6c0 Level-0 table #80: 0 bytes OK 2025/06/14-16:21:28.823960 7f78d37fe6c0 Level-0 table #130: 0 bytes OK
2025/06/12-20:52:48.723881 7f139fbff6c0 Delete type=0 #78 2025/06/14-16:21:28.831212 7f78d37fe6c0 Delete type=0 #128
2025/06/12-20:52:48.724064 7f139fbff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end) 2025/06/14-16:21:28.848927 7f78d37fe6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)

View File

@ -1 +1 @@
MANIFEST-000249 MANIFEST-000300

View File

@ -1,7 +1,3 @@
2025/06/12-21:40:36.410156 7f13a17fa6c0 Recovering log #247 2025/06/14-23:45:33.811724 7f78d9dfa6c0 Recovering log #298
2025/06/12-21:40:36.461712 7f13a17fa6c0 Delete type=3 #245 2025/06/14-23:45:33.914052 7f78d9dfa6c0 Delete type=3 #296
2025/06/12-21:40:36.461765 7f13a17fa6c0 Delete type=0 #247 2025/06/14-23:45:33.914134 7f78d9dfa6c0 Delete type=0 #298
2025/06/12-22:19:34.795093 7f139fbff6c0 Level-0 table #252: started
2025/06/12-22:19:34.795129 7f139fbff6c0 Level-0 table #252: 0 bytes OK
2025/06/12-22:19:34.852214 7f139fbff6c0 Delete type=0 #250
2025/06/12-22:19:35.027439 7f139fbff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)

View File

@ -1,7 +1,7 @@
2025/06/12-20:37:22.815373 7f13a1ffb6c0 Recovering log #242 2025/06/14-13:49:17.875545 7f78d95f96c0 Recovering log #294
2025/06/12-20:37:22.826434 7f13a1ffb6c0 Delete type=3 #240 2025/06/14-13:49:17.886122 7f78d95f96c0 Delete type=3 #292
2025/06/12-20:37:22.826479 7f13a1ffb6c0 Delete type=0 #242 2025/06/14-13:49:17.886173 7f78d95f96c0 Delete type=0 #294
2025/06/12-20:52:48.502299 7f139fbff6c0 Level-0 table #248: started 2025/06/14-16:21:28.817422 7f78d37fe6c0 Level-0 table #299: started
2025/06/12-20:52:48.502341 7f139fbff6c0 Level-0 table #248: 0 bytes OK 2025/06/14-16:21:28.817477 7f78d37fe6c0 Level-0 table #299: 0 bytes OK
2025/06/12-20:52:48.558859 7f139fbff6c0 Delete type=0 #246 2025/06/14-16:21:28.823801 7f78d37fe6c0 Delete type=0 #297
2025/06/12-20:52:48.724054 7f139fbff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end) 2025/06/14-16:21:28.848912 7f78d37fe6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

@ -5,4 +5,4 @@
justify-content: center; justify-content: center;
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.1); font-size: calc(var(--font-size-standard) * 1.1);
} }

View File

@ -85,3 +85,26 @@ i.fvtt-cthulhu-eternal {
background-position: 0%; background-position: 0%;
background-size: 100% 100%; background-size: 100% 100%;
} }
.chat-lethal-damage {
ul {
list-style-type: none;
padding: 0;
margin: 0;
justify-content: center;
align-items: center;
.result-lethal {
color: var(--color-critical-failure);
font-family: var(--font-title);
}
.result-non-lethal {
color: var(--color-failure);
font-family: var(--font-title);
}
li {
margin: 0 10px;
font-family: var(--font-primary);
font-size: calc(var(--font-size-standard) * 1.02);
}
}
}

View File

@ -5,10 +5,11 @@
background-image: var(--background-image-base); background-image: var(--background-image-base);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
--input-height: 1.4rem;
.sheet-tabs { .sheet-tabs {
a { a {
color: rgba(32, 31, 31, 0.8); color: rgba(32, 31, 31, 0.8);
} }
} }
@ -62,7 +63,7 @@
legend { legend {
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.1);
font-weight: bold; font-weight: bold;
letter-spacing: 1px; letter-spacing: 1px;
} }
@ -73,6 +74,38 @@
font-family: var(--font-secondary); font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1); font-size: calc(var(--font-size-standard) * 1);
} }
.hp-unconscious {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1);
color: #b4710c;
}
.hp-dead {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1);
color: #b40000;
}
.protagonist-luck {
display: flex;
min-width: 8rem;
max-width: 8rem;
.rollable:hover,
.rollable:focus {
text-shadow: 0 0 8px var(--color-shadow-primary);
cursor: pointer;
font-size: 0.9rem;
}
}
.damage-bonus {
display: flex;
label {
max-width: 5rem;
min-width: 5rem;
}
input {
max-width: 2rem;
min-width: 2rem;
}
}
} }
.vehicle-sheet-common { .vehicle-sheet-common {
@ -90,7 +123,6 @@
} }
.item-sheet-common { .item-sheet-common {
.form-fields { .form-fields {
padding-top: 4px; padding-top: 4px;
} }

View File

@ -42,9 +42,6 @@
width: 2rem; width: 2rem;
margin-left: 4px; margin-left: 4px;
} }
.damage-bonus {
font-size: calc(var(--font-size-standard) * 0.8);
}
.hp-separator { .hp-separator {
font-size: calc(var(--font-size-standard) * 1.2); font-size: calc(var(--font-size-standard) * 1.2);
display: flex; display: flex;

View File

@ -98,6 +98,11 @@
margin-left: 2rem; margin-left: 2rem;
display: none; display: none;
} }
.healing-roll {
font-size: calc(var(--font-size-standard) * 1.0);
margin-left: 2rem;
display: none;
}
.roll-damage { .roll-damage {
font-size: calc(var(--font-size-standard) * 1.0); font-size: calc(var(--font-size-standard) * 1.0);
margin-left: 2rem; margin-left: 2rem;

View File

@ -0,0 +1,31 @@
<div class="{{cssClass}}">
<div class="chat-lethal-damage">
<ul>
<li><strong>{{weapon.name}} : {{localize "CTHULHUETERNAL.Label.lethalityRoll"}}</strong></li>
<li>{{localize "CTHULHUETERNAL.Label.result"}} :{{rollResult}} ({{lethalScore}})</li>
{{#if weapon.system.selectiveFireChoice}}
<li>{{weapon.system.selectiveFireChoiceLabel}}</li>
{{/if}}
{{#if weapon.system.killRadius}}
<li>{{localize "CTHULHUETERNAL.Label.killRadius"}} : {{weapon.system.killRadius}} {{weapon.system.rangeUnit}}</li>
<li>{{localize "CTHULHUETERNAL.Label.killRadiusInfo"}}</li>
{{/if}}
{{#if ammoUsed}}
<li>{{localize "CTHULHUETERNAL.Label.ammoUsed"}}: {{ammoUsed}} / {{weapon.system.ammo.value}}</li>
{{/if}}
{{#if isLethal}}
<li class="result-lethal">{{localize "CTHULHUETERNAL.Label.lethalityLethal"}}</li>
<li class="result-lethal">{{localize "CTHULHUETERNAL.Label.lethalityWounded"}}</li>
{{else}}
<li class="result-non-lethal">{{localize "CTHULHUETERNAL.Label.lethalityNotLethal"}}</li>
<li class="result-non-lethal">{{localize "CTHULHUETERNAL.Label.lethalityNotWounded"}}: <strong>{{wounds}}</strong></li>
{{/if}}
</ul>
</div>
</div>

View File

@ -51,30 +51,54 @@
{{#if isCritical}} {{#if isCritical}}
<li class="result-critical-success">{{localize "CTHULHUETERNAL.Label.criticalSuccess"}} <li class="result-critical-success">{{localize "CTHULHUETERNAL.Label.criticalSuccess"}}
{{#if (eq rollType "weapon")}} {{#if (eq rollType "weapon")}}
<a class="damage-roll"><i class="fa-solid fa-sword"></i></a> {{#if (eq weapon.system.weaponType "rangedfirearm")}}
<a class="damage-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-gun"></i></a>
{{else}}
<a class="damage-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-sword"></i></a>
{{/if}}
{{/if}} {{/if}}
{{#if (eq rollType "skill") }}
{{#if rollItem.system.isHealing}}
<a class="healing-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollHealing"}}"><i class="fa-solid fa-heart"></i></a>
{{/if}}
{{/if}}
</li> </li>
{{else}} {{else}}
<li class="result-success"> <li class="result-success">
{{localize "CTHULHUETERNAL.Label.success"}} {{localize "CTHULHUETERNAL.Label.success"}}
{{#if isNudge}} {{#if isNudge}}
<a class="nudge-roll"><i class="fa-solid fa-circle-sort-down"></i></a> <a class="nudge-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollNudge"}}"><i class="fa-solid fa-circle-sort-down"></i></a>
{{/if}} {{/if}}
{{#if (eq rollType "weapon")}} {{#if (eq weapon.system.weaponType "rangedfirearm")}}
<a class="damage-roll"><i class="fa-solid fa-sword"></i></a> <a class="damage-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-gun"></i></a>
{{else}}
<a class="damage-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-sword"></i></a>
{{/if}}
{{#if (eq rollType "skill") }}
{{#if rollItem.system.isHealing}}
<a class="healing-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollHealing"}}"><i class="fa-solid fa-heart"></i></a>
{{/if}}
{{/if}} {{/if}}
</li> </li>
{{/if}} {{/if}}
{{/if}} {{/if}}
{{#if isFailure}} {{#if isFailure}}
{{#if isCritical}} {{#if isCritical}}
<li class="result-critical-failure">{{localize "CTHULHUETERNAL.Label.criticalFailure"}}</li> <li class="result-critical-failure">{{localize "CTHULHUETERNAL.Label.criticalFailure"}}
{{#if (eq rollType "skill") }}
{{#if rollItem.system.isHealing}}
<a class="healing-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollHealing"}}"><i class="fa-solid fa-heart"></i></a>
{{/if}}
{{/if}}
</li>
{{else}} {{else}}
<li class="result-failure"> <li class="result-failure">
{{localize "CTHULHUETERNAL.Label.failure"}} {{localize "CTHULHUETERNAL.Label.failure"}}
{{#if isNudge}} {{#if isNudge}}
<a class="nudge-roll"><i class="fa-solid fa-circle-sort-down"></i></a> <a class="nudge-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollNudge"}}"><i class="fa-solid fa-circle-sort-down"></i></a>
{{/if}} {{/if}}
</li> </li>
{{/if}} {{/if}}

View File

@ -0,0 +1,20 @@
<div class="{{cssClass}}">
<div class="chat-lethal-damage">
<ul>
<li><strong>{{weapon.name}} : {{localize "CTHULHUETERNAL.Label.damageRoll"}}</strong></li>
<li>{{localize "CTHULHUETERNAL.Label.result"}} :{{rollResult}} ({{formula}})</li>
{{#if weapon.system.killRadius}}
<li>{{localize "CTHULHUETERNAL.Label.killRadius"}} : {{weapon.system.killRadius}} {{weapon.system.rangeUnit}}</li>
<li>{{localize "CTHULHUETERNAL.Label.killRadiusInfo"}}</li>
{{/if}}
{{#if ammoUsed}}
<li>{{localize "CTHULHUETERNAL.Label.ammoUsed"}}: {{ammoUsed}} / {{weapon.system.ammo.value}}</li>
{{/if}}
<li class="result-non-lethal">{{localize "CTHULHUETERNAL.Label.damageMessage"}}: <strong>{{rollResult}}</strong></li>
</ul>
</div>
</div>

View File

@ -10,14 +10,20 @@
data-tooltip="{{actor.name}}" /> data-tooltip="{{actor.name}}" />
</div> </div>
<fieldset class="protagonist-hp"> <fieldset class="protagonist-hp">
<legend>{{localize "CTHULHUETERNAL.Label.HP"}}</legend> {{#if system.hp.dead}}
<legend class="hp-dead">{{localize "CTHULHUETERNAL.Label.HP"}} {{localize "CTHULHUETERNAL.Label.dying"}}</legend>
{{else}}
{{#if system.hp.unconscious}}
<legend class="hp-unconscious">{{localize "CTHULHUETERNAL.Label.HP"}} {{localize "CTHULHUETERNAL.Label.unconscious"}}</legend>
{{else}}
<legend>{{localize "CTHULHUETERNAL.Label.HP"}}</legend>
{{/if}}
{{/if}}
<div class="flexrow"> <div class="flexrow">
{{formField systemFields.hp.fields.value value=system.hp.value}} {{formField systemFields.hp.fields.value value=system.hp.value}}
<span class="hp-separator">/</span> <span class="hp-separator">/</span>
{{formField systemFields.hp.fields.max value=system.hp.max rootId=partId disabled=true}} {{formField systemFields.hp.fields.max value=system.hp.max rootId=partId disabled=true}}
</div> {{formField systemFields.hp.fields.stunned value=system.hp.stunned classes="stunned"}}
<div class="flexrow ">
{{formField systemFields.damageBonus value=system.damageBonus classes="damage-bonus"}}
</div> </div>
</fieldset> </fieldset>
@ -158,6 +164,17 @@
rootId=partId disabled=isPlayMode }} rootId=partId disabled=isPlayMode }}
<label class="char-text">{{mul system.characteristics.cha.value 5}}</label> <label class="char-text">{{mul system.characteristics.cha.value 5}}</label>
</div> </div>
<div class="protagonist-luck">
<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
<label class="rollable" data-roll-type="luck" data-char-id="luck"
data-tooltip="{{system.Label.Luck}}">{{localize
"CTHULHUETERNAL.Label.Luck"}} (50)</label>
</div>
<div class="damage-bonus">
{{formField systemFields.damageBonus value=system.damageBonus tooltip="Etourdi" }}
</div>
</fieldset> </fieldset>
</section> </section>

View File

@ -14,6 +14,10 @@
{{system.skillTotal}} {{system.skillTotal}}
</div> </div>
{{#if isGM}} {{#if isGM}}
{{formField systemFields.isHealing value=system.isHealing}}
{{#if system.isHealing}}
{{formField systemFields.healingFormula value=system.healingFormula}}
{{/if}}
{{formField systemFields.isAdversary value=system.isAdversary }} {{formField systemFields.isAdversary value=system.isAdversary }}
{{formField systemFields.diceEvolved value=system.diceEvolved}} {{formField systemFields.diceEvolved value=system.diceEvolved}}
@ -21,6 +25,10 @@
{{formField systemFields.rollFailed value=system.rollFailed}} {{formField systemFields.rollFailed value=system.rollFailed}}
{{/if}} {{/if}}
{{else}} {{else}}
{{formField systemFields.isHealing value=system.isHealing disabled=true}}
{{#if system.isHealing}}
{{formField systemFields.healingFormula value=system.healingFormula disabled=true}}
{{/if}}
{{formField systemFields.isAdversary value=system.isAdversary disabled=true}} {{formField systemFields.isAdversary value=system.isAdversary disabled=true}}
{{formField systemFields.diceEvolved value=system.diceEvolved disabled=true}} {{formField systemFields.diceEvolved value=system.diceEvolved disabled=true}}

View File

@ -8,7 +8,7 @@
{{formField systemFields.settings value=system.settings localize=true}} {{formField systemFields.settings value=system.settings localize=true}}
{{formField systemFields.weaponType value=system.weaponType localize=true}} {{formField systemFields.weaponType value=system.weaponType localize=true}}
{{#if (eq system.weaponType "rangedfirearm")}} {{#if (eq system.weaponType "rangedfirearm")}}
{{formField systemFields.weaponSubtype value=system.weaponSubtype localize=true}} {{formField systemFields.weaponSubtype value=system.weaponSubtype localize=true}}
{{/if}} {{/if}}
{{formField systemFields.state value=system.state localize=true}} {{formField systemFields.state value=system.state localize=true}}
@ -18,12 +18,20 @@
{{formField systemFields.directSkillValue value=system.directSkillValue }} {{formField systemFields.directSkillValue value=system.directSkillValue }}
{{/if}} {{/if}}
{{formField systemFields.hasSelectiveFire value=system.hasSelectiveFire}}
{{formField systemFields.applyDamageBonus value=system.applyDamageBonus}} {{formField systemFields.applyDamageBonus value=system.applyDamageBonus}}
{{formField systemFields.damage value=system.damage}} {{formField systemFields.damage value=system.damage}}
{{formField systemFields.baseRange value=system.baseRange}} {{#if isRanged}}
{{formField systemFields.rangeUnit value=system.rangeUnit localize=true}} {{formField systemFields.baseRange value=system.baseRange}}
{{formField systemFields.rangeUnit value=system.rangeUnit localize=true}}
{{/if}}
{{#if isFireArm}}
{{formField systemFields.hasSelectiveFire value=system.hasSelectiveFire}}
{{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.lethality value=system.lethality}}
{{formField systemFields.killRadius value=system.killRadius}} {{formField systemFields.killRadius value=system.killRadius}}