Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7dc2492c96 | |||
| 2c25820152 | |||
| 6ad8226265 | |||
| 68a0d03740 | |||
| 8d9cc1045c | |||
| 4af277d8a2 | |||
| bc9f397755 | |||
| 264a5c7a4c | |||
| 4edbc9b618 |
6
LICENSE
6
LICENSE
@@ -0,0 +1,6 @@
|
|||||||
|
Code license :
|
||||||
|
|
||||||
|
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
|
||||||
|
|
||||||
|
This license requires that reusers give credit to the creator. It allows reusers to distribute, remix, adapt, and build upon the material in any medium or format, for noncommercial purposes only. If others modify or adapt the material, they must license the modified material under identical terms.
|
||||||
|
|
||||||
|
|||||||
389
compendiums/fr/fvtt-cthulhu-eternal.weapons.json
Normal file
389
compendiums/fr/fvtt-cthulhu-eternal.weapons.json
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
{
|
||||||
|
"label": "Armes",
|
||||||
|
"folders": {
|
||||||
|
"Automatic and Heavy Weapons": "Automatiques et armes lourdes",
|
||||||
|
"Firearms": "Armes à feu",
|
||||||
|
"Melee Weapons": "Armes de mêlée",
|
||||||
|
"Ranged Weapons": "Armes à distance",
|
||||||
|
"Ranged weapons": "Armes à distance",
|
||||||
|
"Thermal Weapons": "Armes thermiques",
|
||||||
|
"Weapons - Age Of Revolutions": "Armes - Âge des Révolutions",
|
||||||
|
"Weapons - Age Of Sails": "Armes - Âge de la Voile",
|
||||||
|
"Weapons - Classical Era": "Armes - Époque Classique",
|
||||||
|
"Weapons - Cold War": "Armes - Guerre Froide",
|
||||||
|
"Weapons - Future": "Armes - Futur",
|
||||||
|
"Weapons - Jazz": "Armes - Jazz/Années folles",
|
||||||
|
"Weapons - Medieval": "Armes - Médiévales",
|
||||||
|
"Weapons - Modern": "Armes - Modernes",
|
||||||
|
"Weapons - Post Apocalyptic": "Armes - Post-apocalyptiques",
|
||||||
|
"Weapons - Victorian": "Armes - Victoriennes",
|
||||||
|
"Weapons - World War I": "Armes - Première Guerre mondiale",
|
||||||
|
"Weapons - World War II": "Armes - Seconde Guerre mondiale"
|
||||||
|
},
|
||||||
|
"mapping": {
|
||||||
|
"rangeUnit": {
|
||||||
|
"path": "system.rangeUnit",
|
||||||
|
"converter": "translateRangeUnit"
|
||||||
|
},
|
||||||
|
"baseRange": {
|
||||||
|
"path": "system.baseRange",
|
||||||
|
"converter": "translateRange"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"entries": {
|
||||||
|
"Anti-tank rifle": {
|
||||||
|
"name": "Arme antichar"
|
||||||
|
},
|
||||||
|
"Assault rifle": {
|
||||||
|
"name": "Fusil d'assaut"
|
||||||
|
},
|
||||||
|
"Axe": {
|
||||||
|
"name": "Hache"
|
||||||
|
},
|
||||||
|
"Bare hands and feet": {
|
||||||
|
"name": "Mains et pieds nus"
|
||||||
|
},
|
||||||
|
"Baseball Bat": {
|
||||||
|
"name": "Batte de baseball"
|
||||||
|
},
|
||||||
|
"Baseball bat": {
|
||||||
|
"name": "Batte de baseball"
|
||||||
|
},
|
||||||
|
"Battle laser": {
|
||||||
|
"name": "Laser de combat"
|
||||||
|
},
|
||||||
|
"Battle rifle": {
|
||||||
|
"name": "Fusil de combat"
|
||||||
|
},
|
||||||
|
"Bayonet": {
|
||||||
|
"name": "Baïonnette"
|
||||||
|
},
|
||||||
|
"Blackjack": {
|
||||||
|
"name": "Blackjack"
|
||||||
|
},
|
||||||
|
"Blunderbuss Pistol": {
|
||||||
|
"name": "Pistolet tromblon"
|
||||||
|
},
|
||||||
|
"Bow": {
|
||||||
|
"name": "Arc"
|
||||||
|
},
|
||||||
|
"Brass knuckles": {
|
||||||
|
"name": "Poings américains"
|
||||||
|
},
|
||||||
|
"Broad sword": {
|
||||||
|
"name": "Épée large"
|
||||||
|
},
|
||||||
|
"Buffalo Rifle": {
|
||||||
|
"name": "Fusil Buffalo"
|
||||||
|
},
|
||||||
|
"Cane Gun": {
|
||||||
|
"name": "Pistolet canne"
|
||||||
|
},
|
||||||
|
"Cannon Barrel Pistol": {
|
||||||
|
"name": "Pistolet canon"
|
||||||
|
},
|
||||||
|
"Carbine": {
|
||||||
|
"name": "Carabine"
|
||||||
|
},
|
||||||
|
"Cavalry lance": {
|
||||||
|
"name": "Lance de cavalerie"
|
||||||
|
},
|
||||||
|
"Cavalry sabre": {
|
||||||
|
"name": "Sabre de cavalerie"
|
||||||
|
},
|
||||||
|
"Ceramic Grenade": {
|
||||||
|
"name": "Grenade en céramique"
|
||||||
|
},
|
||||||
|
"Chainsaw": {
|
||||||
|
"name": "Tronçonneuse"
|
||||||
|
},
|
||||||
|
"Claymore": {
|
||||||
|
"name": "Claymore"
|
||||||
|
},
|
||||||
|
"Club": {
|
||||||
|
"name": "Gourdin"
|
||||||
|
},
|
||||||
|
"Combat knife": {
|
||||||
|
"name": "Couteau de combat"
|
||||||
|
},
|
||||||
|
"Cosh": {
|
||||||
|
"name": "Matraque"
|
||||||
|
},
|
||||||
|
"Cricket bat": {
|
||||||
|
"name": "Batte de cricket"
|
||||||
|
},
|
||||||
|
"Crossbow": {
|
||||||
|
"name": "Arbalète"
|
||||||
|
},
|
||||||
|
"Cutlass": {
|
||||||
|
"name": "Coutelas"
|
||||||
|
},
|
||||||
|
"Dagger": {
|
||||||
|
"name": "Dague"
|
||||||
|
},
|
||||||
|
"Derringer": {
|
||||||
|
"name": "Derringer"
|
||||||
|
},
|
||||||
|
"Dueling Pistol": {
|
||||||
|
"name": "Pistolet de duel"
|
||||||
|
},
|
||||||
|
"Dutch (long) Pistol": {
|
||||||
|
"name": "Pistolet néerlandais (long)"
|
||||||
|
},
|
||||||
|
"Elephant Gun": {
|
||||||
|
"name": "Fusil à éléphant"
|
||||||
|
},
|
||||||
|
"Flintlock Pistol": {
|
||||||
|
"name": "Pistolet à silex"
|
||||||
|
},
|
||||||
|
"Fowling Piece": {
|
||||||
|
"name": "Fusil de chasse"
|
||||||
|
},
|
||||||
|
"Garotte": {
|
||||||
|
"name": "Garrot"
|
||||||
|
},
|
||||||
|
"Gatling Gun": {
|
||||||
|
"name": "Gatling Gun"
|
||||||
|
},
|
||||||
|
"Guntō": {
|
||||||
|
"name": "Guntō"
|
||||||
|
},
|
||||||
|
"Hand Grenade": {
|
||||||
|
"name": "Grenade à main"
|
||||||
|
},
|
||||||
|
"Hand grenade": {
|
||||||
|
"name": "Grenade à main"
|
||||||
|
},
|
||||||
|
"Hatchet": {
|
||||||
|
"name": "Hachette"
|
||||||
|
},
|
||||||
|
"Heavy Pistol": {
|
||||||
|
"name": "Pistolet lourd"
|
||||||
|
},
|
||||||
|
"Heavy Spear": {
|
||||||
|
"name": "Lance lourde"
|
||||||
|
},
|
||||||
|
"Heavy axe": {
|
||||||
|
"name": "Hache lourde"
|
||||||
|
},
|
||||||
|
"Heavy hammer": {
|
||||||
|
"name": "Marteau lourd"
|
||||||
|
},
|
||||||
|
"Heavy pistol": {
|
||||||
|
"name": "Pistolet gros calibre"
|
||||||
|
},
|
||||||
|
"Heavy spear": {
|
||||||
|
"name": "Lance lourde"
|
||||||
|
},
|
||||||
|
"Incendiary Grenade": {
|
||||||
|
"name": "Grenade incendiaire"
|
||||||
|
},
|
||||||
|
"Javelin": {
|
||||||
|
"name": "Javelot"
|
||||||
|
},
|
||||||
|
"Katana": {
|
||||||
|
"name": "Katana"
|
||||||
|
},
|
||||||
|
"Knife": {
|
||||||
|
"name": "Couteau"
|
||||||
|
},
|
||||||
|
"Large Caliber Pistol": {
|
||||||
|
"name": "Pistolet gros calibre"
|
||||||
|
},
|
||||||
|
"Large sword": {
|
||||||
|
"name": "Grande épée"
|
||||||
|
},
|
||||||
|
"Laser carbine": {
|
||||||
|
"name": "Carabine laser"
|
||||||
|
},
|
||||||
|
"Life preserver": {
|
||||||
|
"name": "Gilet de sauvetage"
|
||||||
|
},
|
||||||
|
"Light Spear": {
|
||||||
|
"name": "Lance légère"
|
||||||
|
},
|
||||||
|
"Light axe": {
|
||||||
|
"name": "Hache légère"
|
||||||
|
},
|
||||||
|
"Light spear": {
|
||||||
|
"name": "Lance légère"
|
||||||
|
},
|
||||||
|
"Long spear": {
|
||||||
|
"name": "Lance longue"
|
||||||
|
},
|
||||||
|
"Long sword": {
|
||||||
|
"name": "Epée longue"
|
||||||
|
},
|
||||||
|
"Longrifle": {
|
||||||
|
"name": "Fusil long"
|
||||||
|
},
|
||||||
|
"Mace": {
|
||||||
|
"name": "Masse"
|
||||||
|
},
|
||||||
|
"Machete": {
|
||||||
|
"name": "Machette"
|
||||||
|
},
|
||||||
|
"Maxim": {
|
||||||
|
"name": "Maxime"
|
||||||
|
},
|
||||||
|
"Medium Pistol": {
|
||||||
|
"name": "Pistolet moyen"
|
||||||
|
},
|
||||||
|
"Musket": {
|
||||||
|
"name": "Mousquet"
|
||||||
|
},
|
||||||
|
"Nightstick": {
|
||||||
|
"name": "Matraque"
|
||||||
|
},
|
||||||
|
"Oil": {
|
||||||
|
"name": "Huile"
|
||||||
|
},
|
||||||
|
"Ordinary knife": {
|
||||||
|
"name": "Couteau ordinaire"
|
||||||
|
},
|
||||||
|
"Plasma rifle": {
|
||||||
|
"name": "Fusil à plasma"
|
||||||
|
},
|
||||||
|
"Polearm": {
|
||||||
|
"name": "Arme d'hast"
|
||||||
|
},
|
||||||
|
"Power sword": {
|
||||||
|
"name": "Epée énergétique"
|
||||||
|
},
|
||||||
|
"Rapier": {
|
||||||
|
"name": "Rapière"
|
||||||
|
},
|
||||||
|
"Rifle": {
|
||||||
|
"name": "Fusil"
|
||||||
|
},
|
||||||
|
"Sabre": {
|
||||||
|
"name": "Sabre"
|
||||||
|
},
|
||||||
|
"Scimitar": {
|
||||||
|
"name": "Cimeterre"
|
||||||
|
},
|
||||||
|
"Seax": {
|
||||||
|
"name": "Seax"
|
||||||
|
},
|
||||||
|
"Shield bash": {
|
||||||
|
"name": "Coup de bouclier"
|
||||||
|
},
|
||||||
|
"Shiv": {
|
||||||
|
"name": "Shiv"
|
||||||
|
},
|
||||||
|
"Short spear": {
|
||||||
|
"name": "Lance courte"
|
||||||
|
},
|
||||||
|
"Short sword": {
|
||||||
|
"name": "Epée courte"
|
||||||
|
},
|
||||||
|
"Shotgun": {
|
||||||
|
"name": "Shotgun"
|
||||||
|
},
|
||||||
|
"Shuriken": {
|
||||||
|
"name": "Shuriken"
|
||||||
|
},
|
||||||
|
"Sickle": {
|
||||||
|
"name": "Faucille"
|
||||||
|
},
|
||||||
|
"Sling": {
|
||||||
|
"name": "Fronde"
|
||||||
|
},
|
||||||
|
"Small-caliber pistol": {
|
||||||
|
"name": "Pistolet de petit calibre"
|
||||||
|
},
|
||||||
|
"Small‐caliber pistol": {
|
||||||
|
"name": "Pistolet de petit calibre"
|
||||||
|
},
|
||||||
|
"Staff": {
|
||||||
|
"name": "Bâton"
|
||||||
|
},
|
||||||
|
"Steel-toe boot": {
|
||||||
|
"name": "Botte à embout en acier"
|
||||||
|
},
|
||||||
|
"Steel‐toe boot": {
|
||||||
|
"name": "Botte à embout en acier"
|
||||||
|
},
|
||||||
|
"Submachine gun": {
|
||||||
|
"name": "Pistolet-mitrailleur"
|
||||||
|
},
|
||||||
|
"Sulphur soaked cloth": {
|
||||||
|
"name": "Tissu imbibé de soufre"
|
||||||
|
},
|
||||||
|
"Switchblade": {
|
||||||
|
"name": "Couteau à cran d'arrêt"
|
||||||
|
},
|
||||||
|
"Sword cane": {
|
||||||
|
"name": "Canne épée"
|
||||||
|
},
|
||||||
|
"Taser": {
|
||||||
|
"name": "Taser"
|
||||||
|
},
|
||||||
|
"Thompson": {
|
||||||
|
"name": "Thompson"
|
||||||
|
},
|
||||||
|
"Thrown Axe": {
|
||||||
|
"name": "Hache de lancer"
|
||||||
|
},
|
||||||
|
"Thrown Hand Grenade": {
|
||||||
|
"name": "Grenade à main de lancer"
|
||||||
|
},
|
||||||
|
"Thrown Heavy Spear": {
|
||||||
|
"name": "Lance lourde lancée"
|
||||||
|
},
|
||||||
|
"Thrown Knife": {
|
||||||
|
"name": "Couteau de lancer"
|
||||||
|
},
|
||||||
|
"Thrown Light Spear": {
|
||||||
|
"name": "Lance légère lancée"
|
||||||
|
},
|
||||||
|
"Thrown Long Spear": {
|
||||||
|
"name": "Lance longue lancée"
|
||||||
|
},
|
||||||
|
"Thrown Net": {
|
||||||
|
"name": "Filet"
|
||||||
|
},
|
||||||
|
"Thrown Rock": {
|
||||||
|
"name": "Pierre lancée"
|
||||||
|
},
|
||||||
|
"Thrown Short Spear": {
|
||||||
|
"name": "Lance courte lancée"
|
||||||
|
},
|
||||||
|
"Thrown Spear": {
|
||||||
|
"name": "Lance lancée"
|
||||||
|
},
|
||||||
|
"Thrown Spear, Heavy": {
|
||||||
|
"name": "Lance lancée, lourde"
|
||||||
|
},
|
||||||
|
"Thrown Spear, Light": {
|
||||||
|
"name": "Lance lancée, légère"
|
||||||
|
},
|
||||||
|
"Tomahawk": {
|
||||||
|
"name": "Tomahawk"
|
||||||
|
},
|
||||||
|
"Trident": {
|
||||||
|
"name": "Trident"
|
||||||
|
},
|
||||||
|
"Two-Handed sword": {
|
||||||
|
"name": "Epée à deux mains"
|
||||||
|
},
|
||||||
|
"Two-handed sword": {
|
||||||
|
"name": "Epée à deux mains"
|
||||||
|
},
|
||||||
|
"Very heavy sniper laser": {
|
||||||
|
"name": "Laser lourd de sniper"
|
||||||
|
},
|
||||||
|
"Very heavy sniper rifle": {
|
||||||
|
"name": "Fusil lourd de sniper"
|
||||||
|
},
|
||||||
|
"Very large pistol": {
|
||||||
|
"name": "Pistolet très gros calibre"
|
||||||
|
},
|
||||||
|
"WW1 Machinegun": {
|
||||||
|
"name": "Mitrailleuse de la Première Guerre mondiale"
|
||||||
|
},
|
||||||
|
"War club": {
|
||||||
|
"name": "Massue de guerre"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -232,6 +232,32 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.02);
|
font-size: calc(var(--font-size-standard) * 1.02);
|
||||||
}
|
}
|
||||||
|
.chat-san-request ul .combatants-grid,
|
||||||
|
.chat-lethal-damage ul .combatants-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
gap: 4px;
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
.chat-san-request ul .combatants-grid button.apply-wounds-btn,
|
||||||
|
.chat-lethal-damage ul .combatants-grid button.apply-wounds-btn {
|
||||||
|
font-family: var(--font-primary);
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.7);
|
||||||
|
border: 1px solid #4b4a44;
|
||||||
|
padding: 4px 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
background-color: #f0f0e0;
|
||||||
|
color: #1c1c1c;
|
||||||
|
}
|
||||||
|
.chat-san-request ul .combatants-grid button.apply-wounds-btn:hover,
|
||||||
|
.chat-lethal-damage ul .combatants-grid button.apply-wounds-btn:hover {
|
||||||
|
background-color: #d5d5c5;
|
||||||
|
border-color: #2d2d2a;
|
||||||
|
}
|
||||||
.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);
|
||||||
@@ -3041,6 +3067,9 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-size: calc(var(--font-size-standard) * 2);
|
font-size: calc(var(--font-size-standard) * 2);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
}
|
}
|
||||||
|
.li-apply-wounds {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.dice-roll {
|
.dice-roll {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
@@ -3084,21 +3113,6 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1);
|
font-size: calc(var(--font-size-standard) * 1);
|
||||||
}
|
}
|
||||||
.dice-roll .intro-chat .intro-right ul .nudge-roll {
|
|
||||||
font-size: calc(var(--font-size-standard) * 1);
|
|
||||||
margin-left: 2rem;
|
|
||||||
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 {
|
|
||||||
font-size: calc(var(--font-size-standard) * 1);
|
|
||||||
margin-left: 2rem;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.dice-roll .intro-chat .intro-right ul .result-success {
|
.dice-roll .intro-chat .intro-right ul .result-success {
|
||||||
color: var(--color-success);
|
color: var(--color-success);
|
||||||
font-family: var(--font-title);
|
font-family: var(--font-title);
|
||||||
@@ -3133,3 +3147,197 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-size: calc(var(--font-size-standard) * 1.2);
|
font-size: calc(var(--font-size-standard) * 1.2);
|
||||||
text-shadow: 0 0 10px var(--color-shadow-primary);
|
text-shadow: 0 0 10px var(--color-shadow-primary);
|
||||||
}
|
}
|
||||||
|
.dice-roll .chat-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.375rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
border-top: 1px solid var(--color-border-light-primary);
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.dice-roll .chat-actions .chat-action-button {
|
||||||
|
display: inline-flex !important;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
background: var(--color-dark-6);
|
||||||
|
color: var(--color-light-1);
|
||||||
|
border: 1px solid var(--color-border-light-primary);
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
text-decoration: none;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
.dice-roll .chat-actions .chat-action-button:hover {
|
||||||
|
background: var(--color-dark-5);
|
||||||
|
border-color: var(--color-border-dark);
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
.dice-roll .chat-actions .chat-action-button i {
|
||||||
|
font-size: 1rem !important;
|
||||||
|
line-height: 1;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.dice-roll .chat-actions .nudge-roll,
|
||||||
|
.dice-roll .chat-actions .damage-roll,
|
||||||
|
.dice-roll .chat-actions .healing-roll,
|
||||||
|
.dice-roll .chat-actions .opposed-roll {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.opposed-roll-result {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 5px;
|
||||||
|
font-family: var(--font-primary);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .opposed-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
padding-bottom: 0.2rem;
|
||||||
|
border-bottom: 1px solid var(--color-border-light-primary);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .opposed-header h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-family: var(--font-title);
|
||||||
|
font-size: calc(var(--font-size-standard) * 1);
|
||||||
|
color: var(--color-dark-1);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .opposed-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.15rem;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
.opposed-roll-result .opposed-winner,
|
||||||
|
.opposed-roll-result .opposed-loser {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.3rem 0.4rem;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.opposed-roll-result .opposed-winner {
|
||||||
|
background: rgba(34, 139, 34, 0.1);
|
||||||
|
border: 2px solid var(--color-success);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .opposed-loser {
|
||||||
|
background: rgba(220, 20, 60, 0.1);
|
||||||
|
border: 2px solid var(--color-failure);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .character-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
.opposed-roll-result .character-info img {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid var(--color-border-light-primary);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .character-info .character-name {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.15rem;
|
||||||
|
}
|
||||||
|
.opposed-roll-result .character-info .character-name strong {
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.75);
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--color-dark-2);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .character-info .character-name .winner-name {
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.95);
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--color-success);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .character-info .character-name .loser-name {
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.95);
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--color-failure);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .roll-result {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.3rem;
|
||||||
|
}
|
||||||
|
.opposed-roll-result .roll-result .roll-value {
|
||||||
|
font-size: calc(var(--font-size-standard) * 1.2);
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: var(--font-title);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .roll-result .critical-badge {
|
||||||
|
padding: 0.15rem 0.3rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.7);
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
background: var(--color-critical-success);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.opposed-roll-result .winner-result .roll-value {
|
||||||
|
color: var(--color-success);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .loser-result .roll-value {
|
||||||
|
color: var(--color-failure);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .versus-separator {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.3rem;
|
||||||
|
padding: 0;
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.85);
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--color-dark-2);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .versus-separator i {
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.9);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .chat-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.375rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
border-top: 1px solid var(--color-border-light-primary);
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
}
|
||||||
|
.opposed-roll-result .chat-actions .chat-action-button {
|
||||||
|
display: inline-flex !important;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
background: var(--color-dark-6);
|
||||||
|
color: var(--color-light-1);
|
||||||
|
border: 1px solid var(--color-border-light-primary);
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
text-decoration: none;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
.opposed-roll-result .chat-actions .chat-action-button:hover {
|
||||||
|
background: var(--color-dark-5);
|
||||||
|
border-color: var(--color-border-dark);
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
.opposed-roll-result .chat-actions .chat-action-button i {
|
||||||
|
font-size: 1rem !important;
|
||||||
|
line-height: 1;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import * as applications from "./module/applications/_module.mjs"
|
|||||||
import { handleSocketEvent } from "./module/socket.mjs"
|
import { handleSocketEvent } from "./module/socket.mjs"
|
||||||
import CthulhuEternalUtils from "./module/utils.mjs"
|
import CthulhuEternalUtils from "./module/utils.mjs"
|
||||||
|
|
||||||
|
import { SystemManager } from './module/applications/hud/system-manager.js'
|
||||||
|
import { MODULE, REQUIRED_CORE_MODULE_VERSION } from './module/applications/hud/constants.js'
|
||||||
|
|
||||||
export class ClassCounter { static printHello() { console.log("Hello") } static sendJsonPostRequest(e, s) { const t = { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify(s) }; return fetch(e, t).then((e => { if (!e.ok) throw new Error("La requête a échoué avec le statut " + e.status); return e.json() })).catch((e => { throw console.error("Erreur envoi de la requête:", e), e })) } static registerUsageCount(e = game.system.id, s = {}) { if (game.user.isGM) { game.settings.register(e, "world-key", { name: "Unique world key", scope: "world", config: !1, default: "", type: String }); let t = game.settings.get(e, "world-key"); null != t && "" != t && "NONE" != t && "none" != t.toLowerCase() || (t = foundry.utils.randomID(32), game.settings.set(e, "world-key", t)); let a = { name: e, system: game.system.id, worldKey: t, version: game.system.version, language: game.settings.get("core", "language"), remoteAddr: game.data.addresses.remote, nbInstalledModules: game.modules.size, nbActiveModules: game.modules.filter((e => e.active)).length, nbPacks: game.world.packs.size, nbUsers: game.users.size, nbScenes: game.scenes.size, nbActors: game.actors.size, nbPlaylist: game.playlists.size, nbTables: game.tables.size, nbCards: game.cards.size, optionsData: s, foundryVersion: `${game.release.generation}.${game.release.build}` }; this.sendJsonPostRequest("https://www.uberwald.me/fvtt_appcount/count_post.php", a) } } }
|
export class ClassCounter { static printHello() { console.log("Hello") } static sendJsonPostRequest(e, s) { const t = { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify(s) }; return fetch(e, t).then((e => { if (!e.ok) throw new Error("La requête a échoué avec le statut " + e.status); return e.json() })).catch((e => { throw console.error("Erreur envoi de la requête:", e), e })) } static registerUsageCount(e = game.system.id, s = {}) { if (game.user.isGM) { game.settings.register(e, "world-key", { name: "Unique world key", scope: "world", config: !1, default: "", type: String }); let t = game.settings.get(e, "world-key"); null != t && "" != t && "NONE" != t && "none" != t.toLowerCase() || (t = foundry.utils.randomID(32), game.settings.set(e, "world-key", t)); let a = { name: e, system: game.system.id, worldKey: t, version: game.system.version, language: game.settings.get("core", "language"), remoteAddr: game.data.addresses.remote, nbInstalledModules: game.modules.size, nbActiveModules: game.modules.filter((e => e.active)).length, nbPacks: game.world.packs.size, nbUsers: game.users.size, nbScenes: game.scenes.size, nbActors: game.actors.size, nbPlaylist: game.playlists.size, nbTables: game.tables.size, nbCards: game.cards.size, optionsData: s, foundryVersion: `${game.release.generation}.${game.release.build}` }; this.sendJsonPostRequest("https://www.uberwald.me/fvtt_appcount/count_post.php", a) } } }
|
||||||
|
|
||||||
Hooks.once("init", function () {
|
Hooks.once("init", function () {
|
||||||
@@ -29,6 +32,12 @@ Hooks.once("init", function () {
|
|||||||
models,
|
models,
|
||||||
documents,
|
documents,
|
||||||
}
|
}
|
||||||
|
// Set an initiative formula for the system
|
||||||
|
CONFIG.Combat.initiative = {
|
||||||
|
formula: "@characteristics.dex.value",
|
||||||
|
decimals: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
CONFIG.Actor.documentClass = documents.CthulhuEternalActor
|
CONFIG.Actor.documentClass = documents.CthulhuEternalActor
|
||||||
CONFIG.Actor.dataModels = {
|
CONFIG.Actor.dataModels = {
|
||||||
@@ -93,13 +102,14 @@ Hooks.once("init", function () {
|
|||||||
CthulhuEternalUtils.registerSettings()
|
CthulhuEternalUtils.registerSettings()
|
||||||
CthulhuEternalUtils.registerHandlebarsHelpers()
|
CthulhuEternalUtils.registerHandlebarsHelpers()
|
||||||
CthulhuEternalUtils.setupCSSRootVariables()
|
CthulhuEternalUtils.setupCSSRootVariables()
|
||||||
|
CONFIG.debug.hooks = false;
|
||||||
|
|
||||||
console.info("CTHULHU ETERNAL | System Initialized")
|
console.info("CTHULHU ETERNAL | System Initialized")
|
||||||
})
|
})
|
||||||
|
|
||||||
Hooks.once('babele.init', (babele) => {
|
Hooks.once('babele.init', (babele) => {
|
||||||
babele.setSystemTranslationsDir("compendiums");
|
babele.setSystemTranslationsDir("compendiums");
|
||||||
|
CthulhuEternalUtils.registerBabeleTranslations(babele);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,9 +145,22 @@ Hooks.once("ready", function () {
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
Hooks.on('tokenActionHudCoreApiReady', async () => {
|
||||||
|
/**
|
||||||
|
* Return the SystemManager and requiredCoreModuleVersion to Token Action HUD Core
|
||||||
|
*/
|
||||||
|
let module = {} // game.modules.get(MODULE.ID)
|
||||||
|
module.api = {
|
||||||
|
requiredCoreModuleVersion: REQUIRED_CORE_MODULE_VERSION,
|
||||||
|
SystemManager
|
||||||
|
}
|
||||||
|
Hooks.call('tokenActionHudSystemReady', module)
|
||||||
|
})
|
||||||
|
|
||||||
Hooks.on("renderChatMessageHTML", (message, html, data) => {
|
Hooks.on("renderChatMessageHTML", (message, html, data) => {
|
||||||
// Affichage des boutons de jet de dés uniquement pour les joueurs
|
// Affichage des boutons de jet de dés uniquement pour les joueurs
|
||||||
if (message.author.id === game.user.id) {
|
if (message.author.id === game.user.id || game.user.isGM) {
|
||||||
$(html).find(".nudge-roll").each((i, btn) => {
|
$(html).find(".nudge-roll").each((i, btn) => {
|
||||||
btn.style.display = "inline"
|
btn.style.display = "inline"
|
||||||
})
|
})
|
||||||
@@ -147,6 +170,11 @@ Hooks.on("renderChatMessageHTML", (message, html, data) => {
|
|||||||
$(html).find(".healing-roll").each((i, btn) => {
|
$(html).find(".healing-roll").each((i, btn) => {
|
||||||
btn.style.display = "inline"
|
btn.style.display = "inline"
|
||||||
})
|
})
|
||||||
|
if (game.user.isGM) {
|
||||||
|
$(html).find(".opposed-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)
|
||||||
})
|
})
|
||||||
@@ -163,7 +191,38 @@ Hooks.on("renderChatMessageHTML", (message, html, data) => {
|
|||||||
$(html).find(".san-type").click((event) => {
|
$(html).find(".san-type").click((event) => {
|
||||||
CthulhuEternalUtils.applySANType(message, event)
|
CthulhuEternalUtils.applySANType(message, event)
|
||||||
})
|
})
|
||||||
|
$(html).find(".opposed-roll").click((event) => {
|
||||||
|
CthulhuEternalUtils.opposedRollManagement(message, event)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
if (game.user.isGM) {
|
||||||
|
$(html).find(".li-apply-wounds").each((i, btn) => {
|
||||||
|
btn.style.display = "block"
|
||||||
|
})
|
||||||
|
$(html).find(".apply-wounds-btn").click((event) => {
|
||||||
|
CthulhuEternalUtils.applyWounds(message, event)
|
||||||
|
})
|
||||||
|
$(html).find(".apply-wounds-btn").hover(
|
||||||
|
function (event) {
|
||||||
|
// Mouse enter - select the token
|
||||||
|
let combatantId = $(this).data("combatant-id")
|
||||||
|
if (combatantId && game.combat) {
|
||||||
|
let combatant = game.combat.combatants.get(combatantId)
|
||||||
|
if (combatant?.token) {
|
||||||
|
let token = canvas.tokens.get(combatant.token.id)
|
||||||
|
if (token) {
|
||||||
|
token.control({ releaseOthers: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function (event) {
|
||||||
|
// Mouse leave - release selection
|
||||||
|
canvas.tokens.releaseAll()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
61
lang/en.json
61
lang/en.json
@@ -59,6 +59,12 @@
|
|||||||
},
|
},
|
||||||
"hp": {
|
"hp": {
|
||||||
"label": "HP",
|
"label": "HP",
|
||||||
|
"value": {
|
||||||
|
"label": "Current"
|
||||||
|
},
|
||||||
|
"max": {
|
||||||
|
"label": "Max"
|
||||||
|
},
|
||||||
"stunned": {
|
"stunned": {
|
||||||
"label": "Stun."
|
"label": "Stun."
|
||||||
}
|
}
|
||||||
@@ -126,6 +132,18 @@
|
|||||||
"damageBonus": {
|
"damageBonus": {
|
||||||
"label": "Dmg.Bonus"
|
"label": "Dmg.Bonus"
|
||||||
},
|
},
|
||||||
|
"hp": {
|
||||||
|
"label": "HP",
|
||||||
|
"value": {
|
||||||
|
"label": "Current"
|
||||||
|
},
|
||||||
|
"max": {
|
||||||
|
"label": "Max"
|
||||||
|
},
|
||||||
|
"stunned": {
|
||||||
|
"label": "Stun."
|
||||||
|
}
|
||||||
|
},
|
||||||
"resources": {
|
"resources": {
|
||||||
"permanentRating": {
|
"permanentRating": {
|
||||||
"label": "Permanent Rating"
|
"label": "Permanent Rating"
|
||||||
@@ -205,6 +223,7 @@
|
|||||||
"Struggle": "Struggle"
|
"Struggle": "Struggle"
|
||||||
},
|
},
|
||||||
"Skill": {
|
"Skill": {
|
||||||
|
"DodgeName": "Dodge",
|
||||||
"Unnatural": "Unnatural",
|
"Unnatural": "Unnatural",
|
||||||
"Melee": "Melee Weapons",
|
"Melee": "Melee Weapons",
|
||||||
"Firearms": "Firearms",
|
"Firearms": "Firearms",
|
||||||
@@ -552,10 +571,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Label": {
|
"Label": {
|
||||||
|
"noTarget": "No target selected",
|
||||||
|
"noDefenseRoll": "No defense roll available",
|
||||||
|
"opposedRoll": "Opposed Roll",
|
||||||
|
"Target": "Target",
|
||||||
|
"feet": "feet",
|
||||||
|
"feets": "feet",
|
||||||
|
"yard": "yard",
|
||||||
|
"Yard": "Yard",
|
||||||
|
"yards": "yards",
|
||||||
|
"Feet": "Feet",
|
||||||
|
"Yards": "Yards",
|
||||||
"sanLoss5": "You suffered a SAN loss of 5+ ({value}) : you suffer a temporary insanity (Flee, Submit, Struggle or understanding the Unnatural).",
|
"sanLoss5": "You suffered a SAN loss of 5+ ({value}) : you suffer a temporary insanity (Flee, Submit, Struggle or understanding the Unnatural).",
|
||||||
"sanViolenceReset": "The violence SAN loss count has been reset.",
|
"sanViolenceReset": "The violence SAN loss count has been reset.",
|
||||||
"sanHelplessnessReset": "The helplessness SAN loss count has been reset.",
|
"sanHelplessnessReset": "The helplessness SAN loss count has been reset.",
|
||||||
"sanLoss": "You suffer a SAN loss",
|
"sanLoss": "You suffer a SAN loss",
|
||||||
|
"noSanLoss": "No SAN loss",
|
||||||
|
"sanLossInfo": "Select the SAN loss using the buttons below.",
|
||||||
"selectSANType": "Select the type of SAN loss with the buttons below.",
|
"selectSANType": "Select the type of SAN loss with the buttons below.",
|
||||||
"Violence" : "Violence",
|
"Violence" : "Violence",
|
||||||
"Helplessness": "Helplessness",
|
"Helplessness": "Helplessness",
|
||||||
@@ -711,9 +743,11 @@
|
|||||||
"skillProgress": "Skill Progress",
|
"skillProgress": "Skill Progress",
|
||||||
"unconscious": "Unconscious",
|
"unconscious": "Unconscious",
|
||||||
"dying": "Dying",
|
"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.",
|
"unconsciousWarning": "The Protagonist is unconscious. He cannot act until he has at least 3 HP.",
|
||||||
|
"luck": "Luck",
|
||||||
|
"Other": "Other",
|
||||||
|
"Skills": "Skills",
|
||||||
|
"WP": "WP",
|
||||||
"Luck": "Luck",
|
"Luck": "Luck",
|
||||||
"titleLuck": "Luck Roll",
|
"titleLuck": "Luck Roll",
|
||||||
"healingRoll": "Healing Roll succes, the target gains",
|
"healingRoll": "Healing Roll succes, the target gains",
|
||||||
@@ -730,7 +764,20 @@
|
|||||||
"visibility": "Visibility",
|
"visibility": "Visibility",
|
||||||
"rangedRange": "Range",
|
"rangedRange": "Range",
|
||||||
"aimingLastRound": "Aiming Last Round (+20)",
|
"aimingLastRound": "Aiming Last Round (+20)",
|
||||||
"aimingWithSight": "Aiming with Sight (+20)"
|
"aimingWithSight": "Aiming with Sight (+20)",
|
||||||
|
"applyWounds": "Apply To",
|
||||||
|
"opposedRollWinner": "Opposed Roll Winner",
|
||||||
|
"opposedRollResult": "Opposed Roll Result",
|
||||||
|
"defeats": "defeats",
|
||||||
|
"critical": "Critical",
|
||||||
|
"other": "Other",
|
||||||
|
"str": "STR",
|
||||||
|
"dex": "DEX",
|
||||||
|
"int": "INT",
|
||||||
|
"pow": "POW",
|
||||||
|
"con": "CON",
|
||||||
|
"cha": "CHA",
|
||||||
|
"Damage": "Damage"
|
||||||
},
|
},
|
||||||
"ChatMessage": {
|
"ChatMessage": {
|
||||||
"exhausted": "Your protagonist is exhausted. He loses [[/r 1d6]] Willpower Points."
|
"exhausted": "Your protagonist is exhausted. He loses [[/r 1d6]] Willpower Points."
|
||||||
@@ -755,8 +802,12 @@
|
|||||||
"rollDamage": "Roll Damage"
|
"rollDamage": "Roll Damage"
|
||||||
},
|
},
|
||||||
"Chat": {
|
"Chat": {
|
||||||
|
"noArmor": "No armor absorbed damage.",
|
||||||
|
"armorAbsorbed": "Armor absorbed {armor} damage.",
|
||||||
|
"woundsApplied": "Wounds applied to {name}: {effectiveWounds} (armor absorbed : {armorText})"
|
||||||
},
|
},
|
||||||
"Notifications": {
|
"Notifications": {
|
||||||
|
"AttackNoTarget": "No target selected for the attack, please select one target to get automations.",
|
||||||
"NoWeaponSkill": "No weapon skill found for this weapon. Check Weapon definition or available skills/era",
|
"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",
|
||||||
@@ -765,7 +816,9 @@
|
|||||||
"NoAmmo": "No more ammo for this weapon. ",
|
"NoAmmo": "No more ammo for this weapon. ",
|
||||||
"noRollDataFound": "No roll data found",
|
"noRollDataFound": "No roll data found",
|
||||||
"noActorFound": "No actor found for this item.",
|
"noActorFound": "No actor found for this item.",
|
||||||
"noSanLossFound": "No SAN loss value found."
|
"noSanLossFound": "No SAN loss value found.",
|
||||||
|
"opposedRollFirstStored": "First opposed roll stored. Perform and store the second roll to resolve the opposed roll.",
|
||||||
|
"opposedRollSecondStored": "Second opposed roll stored. The opposed roll is now being resolved."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
43
lang/fr.json
43
lang/fr.json
@@ -217,6 +217,7 @@
|
|||||||
"Struggle": "Lutter"
|
"Struggle": "Lutter"
|
||||||
},
|
},
|
||||||
"Skill": {
|
"Skill": {
|
||||||
|
"DodgeName": "Esquive",
|
||||||
"Unnatural": "Inconcevable",
|
"Unnatural": "Inconcevable",
|
||||||
"Melee": "Armes de mêlée",
|
"Melee": "Armes de mêlée",
|
||||||
"Firearms": "Armes à feu",
|
"Firearms": "Armes à feu",
|
||||||
@@ -564,6 +565,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Label": {
|
"Label": {
|
||||||
|
"noTarget": "Aucune cible sélectionnée",
|
||||||
|
"noDefenseRoll": "Aucun jet de défense existant",
|
||||||
|
"opposedRoll": "Jet opposé",
|
||||||
|
"Target": "Cible",
|
||||||
|
"feet": "pieds (ie 30cm)",
|
||||||
|
"feets": "pieds (ie 30cm)",
|
||||||
|
"yard": "mètres",
|
||||||
|
"Yard": "mètres",
|
||||||
|
"yards": "mètres",
|
||||||
|
"Feet": "Pieds",
|
||||||
|
"Yards": "Mètres",
|
||||||
"sanLoss5": "Perte de SAN de 5+ ({value}) : vous souffrez d'une folie temporaire (Fuite, Soumission, Lutte ou compréhension de l'Inconcevable).",
|
"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é.",
|
"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é.",
|
"sanHelplessnessReset": "Le décompte des pertes de SAN d'impuissance a été réinitialisé.",
|
||||||
@@ -606,7 +618,7 @@
|
|||||||
"Unarmed": "Désarmé",
|
"Unarmed": "Désarmé",
|
||||||
"Cured": "Soigné",
|
"Cured": "Soigné",
|
||||||
"Uncured": "Non soigné",
|
"Uncured": "Non soigné",
|
||||||
"nudgedRoll": "Modifier le jeu",
|
"nudgedRoll": "Jet modifié : ",
|
||||||
"selectNewValue": "Sélectionner une nouvelle valeur",
|
"selectNewValue": "Sélectionner une nouvelle valeur",
|
||||||
"wpCost": "Cout en PVO",
|
"wpCost": "Cout en PVO",
|
||||||
"Hand": "A portée de main",
|
"Hand": "A portée de main",
|
||||||
@@ -728,7 +740,10 @@
|
|||||||
"stunnedWarning": "Votre protagoniste est étourdi. Il ne peut pas agir tant qu'il n'a pas réussi un test de CON x 5.",
|
"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",
|
"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.",
|
"unconsciousWarning": "Votre protagoniste est inconscient. Il ne peut pas agir tant qu'il n'a pas atteint 3 PV.",
|
||||||
"Luck": "Chance",
|
"luck": "Chance",
|
||||||
|
"Other": "Autre",
|
||||||
|
"Skills": "Compétences",
|
||||||
|
"WP": "PVO",
|
||||||
"titleLuck": "Jet de Chance",
|
"titleLuck": "Jet de Chance",
|
||||||
"healingRoll": "Jet de soin, PV soignés",
|
"healingRoll": "Jet de soin, PV soignés",
|
||||||
"healingRollFailure": "Jet de soin échoué critique, PV perdus",
|
"healingRollFailure": "Jet de soin échoué critique, PV perdus",
|
||||||
@@ -744,7 +759,21 @@
|
|||||||
"visibility": "Visibilité",
|
"visibility": "Visibilité",
|
||||||
"rangedRange": "Portée",
|
"rangedRange": "Portée",
|
||||||
"aimingLastRound": "Visée lors du dernier round (+20)",
|
"aimingLastRound": "Visée lors du dernier round (+20)",
|
||||||
"aimingWithSight": "Visée avec lunette (+20)"
|
"aimingWithSight": "Visée avec lunette (+20)",
|
||||||
|
"applyWounds": "Appliquer à",
|
||||||
|
"opposedRollWinner": "Gagnant du jet opposé",
|
||||||
|
"opposedRollResult": "Résultat du jet opposé",
|
||||||
|
"defeats": "Défait",
|
||||||
|
"critical": "Critique",
|
||||||
|
"other": "Autre",
|
||||||
|
"str": "FOR",
|
||||||
|
"dex": "DEX",
|
||||||
|
"int": "INT",
|
||||||
|
"pow": "POU",
|
||||||
|
"con": "CON",
|
||||||
|
"cha": "CHA",
|
||||||
|
"Luck": "Chance",
|
||||||
|
"Damage": "Dégâts"
|
||||||
},
|
},
|
||||||
"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é."
|
||||||
@@ -769,8 +798,12 @@
|
|||||||
"rollDamage": "Lancer les dégâts"
|
"rollDamage": "Lancer les dégâts"
|
||||||
},
|
},
|
||||||
"Chat": {
|
"Chat": {
|
||||||
|
"armorAbsorbed": "L'armure a absorbé {armor} points de dégâts.",
|
||||||
|
"noArmor": "Pas d'armure.",
|
||||||
|
"woundsApplied": "Blessures appliquées à {name} : {effectiveWounds} (armure absorbée : {armorText})"
|
||||||
},
|
},
|
||||||
"Notifications": {
|
"Notifications": {
|
||||||
|
"AttackNoTarget": "Aucune cible n'a été sélectionnée pour cette attaque, veuillez sélectionner une cible pour bénéficier des automatisations.",
|
||||||
"NoWeaponSkill": "Aucune compétence associée n'a été trouvé pour cette arme. Vérifier la définition de l'arme ainsi que l'époque configurée.",
|
"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",
|
||||||
@@ -779,7 +812,9 @@
|
|||||||
"NoAmmo": "Aucune munition disponible pour cette arme.",
|
"NoAmmo": "Aucune munition disponible pour cette arme.",
|
||||||
"noRollDataFound": "Aucune donnée de jet trouvée.",
|
"noRollDataFound": "Aucune donnée de jet trouvée.",
|
||||||
"noActorFound": "Aucun protagoniste trouvé.",
|
"noActorFound": "Aucun protagoniste trouvé.",
|
||||||
"noSanLossFound": "Aucune valeur de perte de SAN trouvée."
|
"noSanLossFound": "Aucune valeur de perte de SAN trouvée.",
|
||||||
|
"opposedRollFirstStored": "Premier jet opposé enregistré. Effectuez et enregistrez le deuxième jet pour résoudre le jet opposé.",
|
||||||
|
"opposedRollSecondStored": "Deuxième jet opposé enregistré. Le jet opposé est maintenant en cours de résolution."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// System Module Imports
|
// System Module Imports
|
||||||
import { Utils } from './utils.js'
|
import { Utils } from './utils.js'
|
||||||
import { SYSTEM } from "../../config/system.mjs"
|
import { SYSTEM } from "../../config/system.mjs"
|
||||||
|
import CthulhuEternalUtils from '../../utils.mjs'
|
||||||
|
|
||||||
export let ActionHandler = null
|
export let ActionHandler = null
|
||||||
|
|
||||||
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||||
@@ -38,7 +40,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
#buildCharacterActions() {
|
#buildCharacterActions() {
|
||||||
this.buildAttributes()
|
this.buildCharacteristics()
|
||||||
this.buildOther()
|
this.buildOther()
|
||||||
this.buildLuck()
|
this.buildLuck()
|
||||||
this.buildSkills()
|
this.buildSkills()
|
||||||
@@ -49,17 +51,17 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
return game.settings.get('token-action-hud-core', 'tooltips') === 'none'
|
return game.settings.get('token-action-hud-core', 'tooltips') === 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
async buildAttributes() {
|
async buildCharacteristics() {
|
||||||
const actions = []
|
const actions = []
|
||||||
for (const key in this.actor.system.characteristics) {
|
for (const key in this.actor.system.characteristics) {
|
||||||
const encodedValue = [coreModule.api.Utils.i18n('attributes'), key].join(this.delimiter)
|
const encodedValue = ['characteristics', key].join(this.delimiter)
|
||||||
const tooltip = {
|
const tooltip = {
|
||||||
content: String(this.actor.system.characteristics[key].value * 5),
|
content: String(this.actor.system.characteristics[key].value * 5),
|
||||||
class: 'tah-system-tooltip',
|
class: 'tah-system-tooltip',
|
||||||
direction: 'LEFT'
|
direction: 'LEFT'
|
||||||
}
|
}
|
||||||
actions.push({
|
actions.push({
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.' + key),
|
name: coreModule.api.Utils.i18n(`CTHULHUETERNAL.Label.${key}`),
|
||||||
id: key,
|
id: key,
|
||||||
info1: this.#showValue() ? { text: tooltip.content } : null,
|
info1: this.#showValue() ? { text: tooltip.content } : null,
|
||||||
tooltip,
|
tooltip,
|
||||||
@@ -67,7 +69,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
await this.addActions(actions, {
|
await this.addActions(actions, {
|
||||||
id: 'attributes',
|
id: 'characteristics',
|
||||||
type: 'system'
|
type: 'system'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -80,79 +82,83 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
direction: 'LEFT'
|
direction: 'LEFT'
|
||||||
}
|
}
|
||||||
actions.push({
|
actions.push({
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Luck'),
|
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.luck'),
|
||||||
id: 'luck',
|
id: 'luck',
|
||||||
info1: this.#showValue() ? { text: '50' } : null,
|
info1: this.#showValue() ? { text: '50' } : null,
|
||||||
tooltip,
|
tooltip,
|
||||||
encodedValue: ['attributes', 'luck'].join(this.delimiter)
|
encodedValue: ['characteristics', 'luck'].join(this.delimiter)
|
||||||
})
|
})
|
||||||
await this.addActions(actions, { id: 'luck', type: 'system' })
|
await this.addActions(actions, { id: 'luck', type: 'system' })
|
||||||
}
|
}
|
||||||
|
|
||||||
async buildOther() {
|
async buildOther() {
|
||||||
if (typeof this.actor.system.sanity.value !== 'undefined') {
|
if (typeof this.actor.system?.san?.value !== 'undefined') {
|
||||||
const actions = []
|
const actions = []
|
||||||
const groupData = {
|
const groupData = {
|
||||||
id: 'other_sanity',
|
id: 'other_san',
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.SAN'),
|
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.SAN'),
|
||||||
type: 'system'
|
type: 'system'
|
||||||
}
|
}
|
||||||
this.addGroup(groupData, { id: 'other', type: 'system' }, true)
|
this.addGroup(groupData, { id: 'other', type: 'system' }, true)
|
||||||
const tooltip = {
|
const tooltip = {
|
||||||
content: String(this.actor.system.san.value + '/' + this.actor.system.san.max),
|
content: `${this.actor.system.san.value}/${this.actor.system.san.max}`,
|
||||||
class: 'tah-system-tooltip',
|
class: 'tah-system-tooltip',
|
||||||
direction: 'LEFT'
|
direction: 'LEFT'
|
||||||
}
|
}
|
||||||
actions.push({
|
actions.push({
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.SAN'),
|
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.SAN'),
|
||||||
id: 'sanity',
|
id: 'san',
|
||||||
info1: this.#showValue() ? { text: tooltip.content } : null,
|
info1: this.#showValue() ? { text: tooltip.content } : null,
|
||||||
tooltip,
|
tooltip,
|
||||||
encodedValue: ['attributes', 'sanity'].join(this.delimiter)
|
encodedValue: ['characteristics', 'san'].join(this.delimiter)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '+',
|
name: '+',
|
||||||
id: 'sanity_add',
|
id: 'san_add',
|
||||||
encodedValue: ['attributes', 'sanity_add'].join(this.delimiter)
|
tooltip,
|
||||||
|
encodedValue: ['characteristics', 'san_add'].join(this.delimiter)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '-',
|
name: '-',
|
||||||
id: 'sanity_subtract',
|
id: 'san_subtract',
|
||||||
encodedValue: ['attributes', 'sanity_subtract'].join(this.delimiter)
|
tooltip,
|
||||||
|
encodedValue: ['characteristics', 'san_subtract'].join(this.delimiter)
|
||||||
})
|
})
|
||||||
await this.addActions(actions, { id: 'other_sanity', type: 'system' })
|
await this.addActions(actions, { id: 'other_san', type: 'system' })
|
||||||
}
|
}
|
||||||
if (typeof this.actor.system.hp.value !== 'undefined') {
|
if (typeof this.actor.system.hp.value !== 'undefined') {
|
||||||
const actions = []
|
const actions = []
|
||||||
const groupData = {
|
const groupData = {
|
||||||
id: 'other_health',
|
id: 'other_hp',
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.HP'),
|
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.HP'),
|
||||||
type: 'system'
|
type: 'system'
|
||||||
}
|
}
|
||||||
this.addGroup(groupData, { id: 'other', type: 'system' }, true)
|
this.addGroup(groupData, { id: 'other', type: 'system' }, true)
|
||||||
const tooltip = {
|
const tooltip = {
|
||||||
content: String(this.actor.system.hp.value + '/' + this.actor.system.hp.max),
|
content: `${this.actor.system.hp.value}/${this.actor.system.hp.max}`,
|
||||||
class: 'tah-system-tooltip',
|
class: 'tah-system-tooltip',
|
||||||
direction: 'LEFT'
|
direction: 'LEFT'
|
||||||
}
|
}
|
||||||
actions.push({
|
actions.push({
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.HP'),
|
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.HP'),
|
||||||
id: 'health',
|
id: 'hp',
|
||||||
info1: this.#showValue() ? { text: tooltip.content } : null,
|
info1: this.#showValue() ? { text: tooltip.content } : null,
|
||||||
tooltip,
|
tooltip,
|
||||||
encodedValue: ['attributes', 'health'].join(this.delimiter)
|
encodedValue: ['characteristics', 'hp'].join(this.delimiter)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '+',
|
name: '+',
|
||||||
id: 'health_add',
|
id: 'hp_add',
|
||||||
encodedValue: ['attributes', 'health_add'].join(this.delimiter)
|
tooltip,
|
||||||
|
encodedValue: ['characteristics', 'hp_add'].join(this.delimiter)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '-',
|
name: '-',
|
||||||
id: 'health_subtract',
|
id: 'hp_subtract',
|
||||||
encodedValue: ['attributes', 'health_subtract'].join(this.delimiter)
|
tooltip,
|
||||||
|
encodedValue: ['characteristics', 'hp_subtract'].join(this.delimiter)
|
||||||
})
|
})
|
||||||
await this.addActions(actions, { id: 'other_health', type: 'system' })
|
await this.addActions(actions, { id: 'other_hp', type: 'system' })
|
||||||
}
|
}
|
||||||
if (typeof this.actor.system.wp.value !== 'undefined') {
|
if (typeof this.actor.system.wp.value !== 'undefined') {
|
||||||
const actions = []
|
const actions = []
|
||||||
@@ -163,7 +169,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
}
|
}
|
||||||
this.addGroup(groupData, { id: 'other', type: 'system' }, true)
|
this.addGroup(groupData, { id: 'other', type: 'system' }, true)
|
||||||
const tooltip = {
|
const tooltip = {
|
||||||
content: String(this.actor.system.wp.value + '/' + this.actor.system.wp.max),
|
content: `${this.actor.system.wp.value}/${this.actor.system.wp.max}`,
|
||||||
class: 'tah-system-tooltip',
|
class: 'tah-system-tooltip',
|
||||||
direction: 'LEFT'
|
direction: 'LEFT'
|
||||||
}
|
}
|
||||||
@@ -172,17 +178,19 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
id: 'wp',
|
id: 'wp',
|
||||||
info1: this.#showValue() ? { text: tooltip.content } : null,
|
info1: this.#showValue() ? { text: tooltip.content } : null,
|
||||||
tooltip,
|
tooltip,
|
||||||
encodedValue: ['attributes', 'wp'].join(this.delimiter)
|
encodedValue: ['characteristics', 'wp'].join(this.delimiter)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '+',
|
name: '+',
|
||||||
id: 'wp_add',
|
id: 'wp_add',
|
||||||
encodedValue: ['attributes', 'wp_add'].join(this.delimiter)
|
tooltip,
|
||||||
|
encodedValue: ['characteristics', 'wp_add'].join(this.delimiter)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '-',
|
name: '-',
|
||||||
id: 'wp_subtract',
|
id: 'wp_subtract',
|
||||||
encodedValue: ['attributes', 'wp_subtract'].join(this.delimiter)
|
tooltip,
|
||||||
|
encodedValue: ['characteristics', 'wp_subtract'].join(this.delimiter)
|
||||||
})
|
})
|
||||||
await this.addActions(actions, { id: 'other_wp', type: 'system' })
|
await this.addActions(actions, { id: 'other_wp', type: 'system' })
|
||||||
}
|
}
|
||||||
@@ -190,19 +198,23 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
|
|
||||||
async buildSkills() {
|
async buildSkills() {
|
||||||
const actions = []
|
const actions = []
|
||||||
let actorSkills = this.actor.items.filter(item => item.type === 'skill')
|
// Build alpha sorted skill list
|
||||||
for (const skill in actorSkills) {
|
let skills = this.actor.items.filter(i => i.type === 'skill')
|
||||||
if (skill.system.computeScore() > 0) {
|
skills = skills.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
console.log('Building skills actions for skills:', skills)
|
||||||
|
for (const skill of skills) {
|
||||||
|
console.log('Processing skill item:', skill)
|
||||||
|
if (skill.system.skillTotal > 0) {
|
||||||
const tooltip = {
|
const tooltip = {
|
||||||
content: String(skill.skill.system.computeScore()),
|
content: String(skill.system.skillTotal),
|
||||||
direction: 'LEFT'
|
direction: 'LEFT'
|
||||||
}
|
}
|
||||||
actions.push({
|
actions.push({
|
||||||
name: skill.name,
|
name: `${skill.name} (${skill.system.skillTotal})`,
|
||||||
id: skill.id,
|
id: skill.id,
|
||||||
info1: this.#showValue() ? { text: tooltip.content } : null,
|
info1: this.#showValue() ? { text: tooltip.content } : null,
|
||||||
tooltip,
|
tooltip,
|
||||||
encodedValue: ['skills', s].join(this.delimiter)
|
encodedValue: ['skills', skill.id].join(this.delimiter)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,62 +222,55 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async buildEquipment() {
|
async buildEquipment() {
|
||||||
let weapons = this.actor.items.filter(item => item.type === 'weapon')
|
let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era")
|
||||||
let skills = this.actor.items.filter(item => item.type === 'skill')
|
|
||||||
for (const item of weapons) {
|
// const rituals = []
|
||||||
|
for (const item of this.actor.items) {
|
||||||
// Push the weapon name as a new group
|
// Push the weapon name as a new group
|
||||||
const groupData = {
|
const groupData = {
|
||||||
id: 'weapons_' + item._id,
|
id: `weapons_${item._id}`,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
type: 'system'
|
type: 'system'
|
||||||
}
|
}
|
||||||
if (!SYSTEM.WEAPON_SKILL_MAPPING[era] || !SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType]) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType])
|
|
||||||
let skill = skills.find(skill => skill.name.toLowerCase() === skillName.toLowerCase())
|
|
||||||
this.addGroup(groupData, { id: 'weapons', type: 'system' }, true)
|
this.addGroup(groupData, { id: 'weapons', type: 'system' }, true)
|
||||||
if (item.type === 'weapon') {
|
if (item.type === 'weapon') {
|
||||||
const weapons = []
|
let skill = CthulhuEternalUtils.getWeaponSkill(this.actor, item, era)
|
||||||
|
item.skillTotal = skill ? skill.system.skillTotal : 0
|
||||||
|
let weapons = []
|
||||||
const tooltip = {
|
const tooltip = {
|
||||||
content: String(skill.system.computeScore()),
|
content: String(item.skillTotal),
|
||||||
direction: 'LEFT'
|
direction: 'LEFT'
|
||||||
}
|
}
|
||||||
|
console.log('Weapon skill total for', item.name, 'is', item.skillTotal, item._id)
|
||||||
weapons.push({
|
weapons.push({
|
||||||
name: skill.name,
|
name: `${item.name} (${item.skillTotal})`,
|
||||||
id: skill._id,
|
id: `weapon_${item._id}`,
|
||||||
info1: this.#showValue() ? { text: tooltip.content } : null,
|
info1: this.#showValue() ? { text: tooltip.content } : null,
|
||||||
encodedValue: ['weapons', item._id].join(this.delimiter),
|
encodedValue: ['weapons', item._id].join(this.delimiter),
|
||||||
tooltip
|
tooltip
|
||||||
})
|
})
|
||||||
|
let damage = ''
|
||||||
|
if (item.system.lethality > 0) {
|
||||||
|
damage = `L:${item.system.lethality}%`
|
||||||
|
} else {
|
||||||
|
damage = item.system.damage
|
||||||
|
}
|
||||||
const damageTooltip = {
|
const damageTooltip = {
|
||||||
content: String(item.system.damage),
|
content: String(damage),
|
||||||
direction: 'LEFT'
|
direction: 'LEFT'
|
||||||
}
|
}
|
||||||
if (item.system.damage !== '') {
|
if (item.system.damage !== '') {
|
||||||
weapons.push({
|
weapons.push({
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Damage'),
|
name: `${coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Damage')} (${damage})`,
|
||||||
id: item._id,
|
id: `damage_${item._id}`,
|
||||||
info1: this.#showValue() ? { text: damageTooltip.content } : null,
|
info1: this.#showValue() ? { text: damageTooltip.content } : null,
|
||||||
encodedValue: ['damage', item._id].join(this.delimiter),
|
encodedValue: ['damage', item._id].join(this.delimiter),
|
||||||
tooltip: damageTooltip
|
tooltip: damageTooltip
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (item.system.isLethal) {
|
console.log('Adding weapon actions for', item.name, weapons)
|
||||||
const lethalityTooltip = {
|
|
||||||
content: String(item.system.lethality),
|
|
||||||
direction: 'LEFT'
|
|
||||||
}
|
|
||||||
weapons.push({
|
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Lethality'),
|
|
||||||
id: item._id,
|
|
||||||
info1: this.#showValue() ? { text: lethalityTooltip.content } : null,
|
|
||||||
encodedValue: ['lethality', item._id].join(this.delimiter),
|
|
||||||
tooltip: lethalityTooltip
|
|
||||||
})
|
|
||||||
}
|
|
||||||
await this.addActions(weapons, {
|
await this.addActions(weapons, {
|
||||||
id: 'weapons_' + item._id,
|
id: `weapons_${item._id}`,
|
||||||
type: 'system'
|
type: 'system'
|
||||||
})
|
})
|
||||||
}/* else if (item.type === 'ritual') {
|
}/* else if (item.type === 'ritual') {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* Module-based constants
|
* Module-based constants
|
||||||
*/
|
*/
|
||||||
export const SYSTEM = {
|
export const MODULE = {
|
||||||
ID: 'fvtt-cthulhu-eternal'
|
ID: 'token-action-hud-cthulhu-eternal'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,18 +21,19 @@ export const REQUIRED_CORE_MODULE_VERSION = '2.0'
|
|||||||
* Action types
|
* Action types
|
||||||
*/
|
*/
|
||||||
export const ACTION_TYPE = {
|
export const ACTION_TYPE = {
|
||||||
attributes: 'CTHULHUETERNAL.Label.Characteristics',
|
characteristics: 'CTHULHUETERNAL.Label.characteristics',
|
||||||
skills: 'CTHULHUETERNAL.Label.Skill',
|
skills: 'CTHULHUETERNAL.Label.Skills',
|
||||||
equipment: 'CTHULHUETERNAL.Label.Gear'
|
equipment: 'CTHULHUETERNAL.Label.gear'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Groups
|
* Groups
|
||||||
*/
|
*/
|
||||||
export const GROUP = {
|
export const GROUP = {
|
||||||
attributes: { id: 'attributes', name: 'CTHULHUETERNAL.Label.Characteristics', type: 'system' },
|
characteristics: { id: 'characteristics', name: 'CTHULHUETERNAL.Label.characteristics', type: 'system' },
|
||||||
luck: { id: 'luck', name: 'CTHULHUETERNAL.Label.Luck', type: 'system'},
|
luck: { id: 'luck', name: 'CTHULHUETERNAL.Label.luck', type: 'system' },
|
||||||
|
other: { id: 'other', name: 'CTHULHUETERNAL.Label.other', type: 'system' },
|
||||||
skills: { id: 'skills', name: 'CTHULHUETERNAL.Label.Skills', type: 'system' },
|
skills: { id: 'skills', name: 'CTHULHUETERNAL.Label.Skills', type: 'system' },
|
||||||
weapons: { id: 'weapons', name: 'CTHULHUETERNAL.Label.Weapons', type: 'system' },
|
weapons: { id: 'weapons', name: 'CTHULHUETERNAL.Label.weapons', type: 'system' },
|
||||||
rituals: { id: 'rituals', name: 'CTHULHUETERNAL.Label.Rituals', type: 'system' }
|
rituals: { id: 'rituals', name: 'CTHULHUETERNAL.Label.rituals', type: 'system' }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
{
|
{
|
||||||
nestId: 'statistics',
|
nestId: 'statistics',
|
||||||
id: 'statistics',
|
id: 'statistics',
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Characteristics'),
|
name: game.i18n.localize('CTHULHUETERNAL.Label.characteristics'),
|
||||||
groups: [
|
groups: [
|
||||||
{ ...groups.attributes, nestId: 'statistics_attributes' },
|
{ ...groups.characteristics, nestId: 'statistics_characteristics' },
|
||||||
{ ...groups.other, nestId: 'statistics_other' },
|
{ ...groups.other, nestId: 'statistics_other' },
|
||||||
{ ...groups.luck, nestId: 'statistics_luck' }
|
{ ...groups.luck, nestId: 'statistics_luck' }
|
||||||
]
|
]
|
||||||
@@ -27,17 +27,15 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
{
|
{
|
||||||
nestId: 'skills',
|
nestId: 'skills',
|
||||||
id: 'skills',
|
id: 'skills',
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Skills'),
|
name: game.i18n.localize('CTHULHUETERNAL.Label.skills'),
|
||||||
groups: [
|
groups: [
|
||||||
{ ...groups.skills, nestId: 'skills_skills' },
|
{ ...groups.skills, nestId: 'skills_skills' }
|
||||||
{ ...groups.typedSkills, nestId: 'skills_typed' },
|
|
||||||
{ ...groups.specialTraining, nestId: 'skills_special' }
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
nestId: 'equipment',
|
nestId: 'equipment',
|
||||||
id: 'equipment',
|
id: 'equipment',
|
||||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Gear'),
|
name: game.i18n.localize('CTHULHUETERNAL.Label.gear'),
|
||||||
groups: [
|
groups: [
|
||||||
{ ...groups.weapons, nestId: 'equipment_weapons' },
|
{ ...groups.weapons, nestId: 'equipment_weapons' },
|
||||||
{ ...groups.rituals, nestId: 'equipment_rituals' }
|
{ ...groups.rituals, nestId: 'equipment_rituals' }
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
import { SYSTEM } from "../../config/system.mjs"
|
import { SYSTEM } from "../../config/system.mjs"
|
||||||
import CthulhuEternalRoll from '../../documents/roll.mjs'
|
|
||||||
|
|
||||||
export let RollHandler = null
|
export let RollHandler = null
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
async handleActionClick(event, encodedValue) {
|
async handleActionClick(event, encodedValue) {
|
||||||
const [actionTypeId, actionId] = encodedValue.split('|')
|
const [actionTypeId, actionId] = encodedValue.split('|')
|
||||||
|
|
||||||
const knownCharacters = ['character']
|
const knownCharacters = ['protagonist', 'creature']
|
||||||
|
|
||||||
// If single actor is selected
|
// If single actor is selected
|
||||||
if (this.actor) {
|
if (this.actor) {
|
||||||
@@ -66,9 +66,10 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
* @param {string} actionId The actionId
|
* @param {string} actionId The actionId
|
||||||
*/
|
*/
|
||||||
async #handleAction(event, actor, token, actionTypeId, actionId) {
|
async #handleAction(event, actor, token, actionTypeId, actionId) {
|
||||||
|
console.log('Handling action', actionId, 'of type', actionTypeId, 'for actor', actor.name)
|
||||||
switch (actionTypeId) {
|
switch (actionTypeId) {
|
||||||
case 'attributes':
|
case 'characteristics':
|
||||||
await this.#handleAttributesAction(event, actor, actionId)
|
await this.#handleCharacteristicsAction(event, actor, actionId)
|
||||||
break
|
break
|
||||||
case 'skills':
|
case 'skills':
|
||||||
await this.#handleSkillsAction(event, actor, actionId)
|
await this.#handleSkillsAction(event, actor, actionId)
|
||||||
@@ -82,12 +83,6 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
case 'lethality':
|
case 'lethality':
|
||||||
await this.#handleLethalityAction(event, actor, actionId)
|
await this.#handleLethalityAction(event, actor, actionId)
|
||||||
break
|
break
|
||||||
case 'specialTraining':
|
|
||||||
await this.#handleSpecialTrainingAction(event, actor, actionId)
|
|
||||||
break
|
|
||||||
case 'typedSkills':
|
|
||||||
await this.#handleCustomTypedAction(event, actor, actionId)
|
|
||||||
break
|
|
||||||
/* case 'rituals':
|
/* case 'rituals':
|
||||||
await this.#handleRitualsAction(event, actor, actionId)
|
await this.#handleRitualsAction(event, actor, actionId)
|
||||||
break */
|
break */
|
||||||
@@ -98,18 +93,20 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle Attribute action
|
* Handle Characteristic action
|
||||||
* @private
|
* @private
|
||||||
* @param {object} event The event
|
* @param {object} event The event
|
||||||
* @param {object} actor The actor
|
* @param {object} actor The actor
|
||||||
* @param {string} actionId The action id
|
* @param {string} actionId The action id
|
||||||
*/
|
*/
|
||||||
async #handleAttributesAction (event, actor, actionId) {
|
async #handleCharacteristicsAction(event, actor, actionId) {
|
||||||
let rollType
|
let rollType
|
||||||
if (actionId === 'wp' || actionId === 'health') return
|
if (actionId === 'wp' || actionId === 'hp') return
|
||||||
|
|
||||||
if (actionId.includes('_add') || actionId.includes('_subtract')) {
|
if (actionId.includes('_add') || actionId.includes('_subtract')) {
|
||||||
const attr = actionId.split('_')[0]
|
const attr = actionId.split('_')[0]
|
||||||
const action = actionId.split('_')[1]
|
const action = actionId.split('_')[1]
|
||||||
|
console.log('Updating', attr, 'with action', action)
|
||||||
const update = {}
|
const update = {}
|
||||||
update.system = {}
|
update.system = {}
|
||||||
update.system[attr] = {}
|
update.system[attr] = {}
|
||||||
@@ -117,21 +114,23 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
if (update.system[attr].value > this.actor.system[attr].max || update.system[attr].value < this.actor.system[attr].min) return
|
if (update.system[attr].value > this.actor.system[attr].max || update.system[attr].value < this.actor.system[attr].min) return
|
||||||
return await this.actor.update(update)
|
return await this.actor.update(update)
|
||||||
}
|
}
|
||||||
if (actionId === 'sanity') {
|
if (actionId === 'san') {
|
||||||
rollType = actionId
|
let item = foundry.utils.duplicate(actor.system.san)
|
||||||
|
item.name = game.i18n.localize("CTHULHUETERNAL.Label.SAN")
|
||||||
|
item.targetScore = item.value
|
||||||
|
await actor.system.roll('san', item)
|
||||||
} else if (actionId === 'luck') {
|
} else if (actionId === 'luck') {
|
||||||
rollType = actionId
|
let item = foundry.utils.duplicate(actor.system.characteristics.int)
|
||||||
|
item.name = game.i18n.localize("CTHULHUETERNAL.Label.Luck")
|
||||||
|
item.value = 10
|
||||||
|
item.targetScore = 50
|
||||||
|
await actor.system.roll('luck', item)
|
||||||
} else {
|
} else {
|
||||||
rollType = 'stat'
|
let item = foundry.utils.duplicate(actor.system.characteristics[actionId])
|
||||||
|
item.name = game.i18n.localize(`CTHULHUETERNAL.Label.${actionId}Long`)
|
||||||
|
item.targetScore = item.value * 5
|
||||||
|
await actor.system.roll('char', item)
|
||||||
}
|
}
|
||||||
const options = {
|
|
||||||
actor: this.actor,
|
|
||||||
rollType,
|
|
||||||
key: actionId
|
|
||||||
}
|
|
||||||
|
|
||||||
const roll = new DGPercentileRoll('1D100', {}, options)
|
|
||||||
return await this.actor.sheet.processRoll(event, roll)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,63 +141,11 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
* @param {string} actionId The action id
|
* @param {string} actionId The action id
|
||||||
*/
|
*/
|
||||||
async #handleSkillsAction(event, actor, actionId) {
|
async #handleSkillsAction(event, actor, actionId) {
|
||||||
const options = {
|
const skill = actor.items.find(i => i.type === 'skill' && i.id === actionId)
|
||||||
actor: this.actor,
|
if (!skill) return ui.notifications.warn(`Skill not found for action id '${actionId}'`)
|
||||||
rollType: 'skill',
|
await actor.system.roll('skill', skill)
|
||||||
key: actionId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const skill = this.actor.system.skills[actionId]
|
|
||||||
if (!skill) return ui.notifications.warn('Bad skill name in HUD.')
|
|
||||||
|
|
||||||
const roll = new DGPercentileRoll('1D100', {}, options)
|
|
||||||
await this.actor.sheet.processRoll(event, roll)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle Typed/Custom skills action
|
|
||||||
* @private
|
|
||||||
* @param {object} event The event
|
|
||||||
* @param {object} actor The actor
|
|
||||||
* @param {string} actionId The action id
|
|
||||||
*/
|
|
||||||
async #handleCustomTypedAction (event, actor, actionId) {
|
|
||||||
const options = {
|
|
||||||
actor: this.actor,
|
|
||||||
rollType: 'skill',
|
|
||||||
key: actionId
|
|
||||||
}
|
|
||||||
const roll = new DGPercentileRoll('1D100', {}, options)
|
|
||||||
await this.actor.sheet.processRoll(event, roll)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle SoecialTraining action
|
|
||||||
* @private
|
|
||||||
* @param {object} event The event
|
|
||||||
* @param {object} actor The actor
|
|
||||||
* @param {string} actionId The action id
|
|
||||||
*/
|
|
||||||
async #handleSpecialTrainingAction (event, actor, actionId) {
|
|
||||||
const attr = this.actor.system.specialTraining.find(a => a.name === actionId).attribute
|
|
||||||
let target = 0
|
|
||||||
if (DG.statistics.includes(attr)) {
|
|
||||||
target = this.actor.system.statistics[attr].x5
|
|
||||||
} else if (DG.skills.includes(attr)) {
|
|
||||||
target = this.actor.system.skills[attr].proficiency
|
|
||||||
} else {
|
|
||||||
target = this.actor.system.typedSkills[attr].proficiency
|
|
||||||
}
|
|
||||||
const options = {
|
|
||||||
actor: this.actor,
|
|
||||||
rollType: 'special-training',
|
|
||||||
key: attr,
|
|
||||||
specialTrainingName: actionId,
|
|
||||||
target
|
|
||||||
}
|
|
||||||
const roll = new DGPercentileRoll('1D100', {}, options)
|
|
||||||
await this.actor.sheet.processRoll(event, roll)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle Weapon action
|
* Handle Weapon action
|
||||||
@@ -208,15 +155,10 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
* @param {string} actionId The action id
|
* @param {string} actionId The action id
|
||||||
*/
|
*/
|
||||||
async #handleWeaponsAction(event, actor, actionId) {
|
async #handleWeaponsAction(event, actor, actionId) {
|
||||||
const item = this.actor.items.get(actionId)
|
let weapon = actor.items.find(i => i.type === 'weapon' && i.id === actionId)
|
||||||
const options = {
|
weapon.damageFormula = weapon.system.damage
|
||||||
actor: this.actor,
|
weapon.damageBonus = actor.system.damageBonus
|
||||||
rollType: 'weapon',
|
await actor.system.roll('weapon', weapon)
|
||||||
key: item.system.skill,
|
|
||||||
item
|
|
||||||
}
|
|
||||||
const roll = new DGPercentileRoll('1D100', {}, options)
|
|
||||||
await this.actor.sheet.processRoll(event, roll)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -227,21 +169,10 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
* @param {string} actionId The action id
|
* @param {string} actionId The action id
|
||||||
*/
|
*/
|
||||||
async #handleDamageAction(event, actor, actionId) {
|
async #handleDamageAction(event, actor, actionId) {
|
||||||
const item = this.actor.items.get(actionId)
|
let weapon = actor.items.find(i => i.type === 'weapon' && i.id === actionId)
|
||||||
if (item.system.lethality > 0 && event.ctrlKey) {
|
weapon.damageFormula = weapon.system.damage
|
||||||
// Toggle on/off lethality
|
weapon.damageBonus = actor.system.damageBonus
|
||||||
const isLethal = !item.system.isLethal
|
await actor.system.roll('damage', weapon)
|
||||||
await item.update({ 'system.isLethal': isLethal })
|
|
||||||
} else {
|
|
||||||
const options = {
|
|
||||||
actor: this.actor,
|
|
||||||
rollType: 'damage',
|
|
||||||
key: item.system.damage,
|
|
||||||
item
|
|
||||||
}
|
|
||||||
const roll = new DGDamageRoll(item.system.damage, {}, options)
|
|
||||||
await this.actor.sheet.processRoll(event, roll)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -263,8 +194,9 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
key: item.system.lethality,
|
key: item.system.lethality,
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
|
/* TOFIX
|
||||||
const roll = new DGLethalityRoll(item.system.damage, {}, options)
|
const roll = new DGLethalityRoll(item.system.damage, {}, options)
|
||||||
await this.actor.sheet.processRoll(event, roll)
|
await this.actor.sheet.processRoll(event, roll)*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
module/applications/hud/settings.js
Normal file
9
module/applications/hud/settings.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { MODULE } from './constants.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register module settings
|
||||||
|
* Called by Token Action HUD Core to register Token Action HUD system module settings
|
||||||
|
* @param {function} coreUpdate Token Action HUD Core update function
|
||||||
|
*/
|
||||||
|
export function register (coreUpdate) {
|
||||||
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
// System Module Imports
|
// System Module Imports
|
||||||
import { ActionHandler } from './action-handler.js'
|
import { ActionHandler } from './action-handler.js'
|
||||||
import { RollHandler as Core } from './roll-handler.js'
|
import { RollHandler as Core } from './roll-handler.js'
|
||||||
import { SYSTEM } from './constants.js'
|
import { MODULE } from './constants.js'
|
||||||
import { DEFAULTS } from './defaults.js'
|
import { DEFAULTS } from './defaults.js'
|
||||||
|
import * as systemSettings from './settings.js'
|
||||||
|
|
||||||
export let SystemManager = null
|
export let SystemManager = null
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
* @param {function} coreUpdate The Token Action HUD Core update function
|
* @param {function} coreUpdate The Token Action HUD Core update function
|
||||||
*/
|
*/
|
||||||
registerSettings(coreUpdate) {
|
registerSettings(coreUpdate) {
|
||||||
/*systemSettings.register(coreUpdate)*/
|
systemSettings.register(coreUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,7 +83,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
template: {
|
template: {
|
||||||
class: 'tah-style-template-style', // The class to add to first DIV element
|
class: 'tah-style-template-style', // The class to add to first DIV element
|
||||||
file: 'tah-template-style', // The file without the css extension
|
file: 'tah-template-style', // The file without the css extension
|
||||||
moduleId: SYSTEM.ID, // The module ID
|
moduleId: MODULE.ID, // The module ID
|
||||||
name: 'Template Style' // The name to display in the Token Action HUD Core 'Style' module setting
|
name: 'Template Style' // The name to display in the Token Action HUD Core 'Style' module setting
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,7 @@
|
|||||||
import { SYSTEM } from './constants.js'
|
import { MODULE } from './constants.js'
|
||||||
|
|
||||||
export let Utils = null
|
export let Utils = null
|
||||||
|
|
||||||
function registerHUD() {
|
|
||||||
Hooks.on('tokenActionHudCoreApiReady', async () => {
|
|
||||||
/**
|
|
||||||
* Return the SystemManager and requiredCoreModuleVersion to Token Action HUD Core
|
|
||||||
*/
|
|
||||||
const module = game.system
|
|
||||||
module.api = {
|
|
||||||
requiredCoreModuleVersion: "2.0",
|
|
||||||
SystemManager
|
|
||||||
}
|
|
||||||
Hooks.call('tokenActionHudSystemReady', module)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||||
/**
|
/**
|
||||||
* Utility functions
|
* Utility functions
|
||||||
@@ -31,7 +16,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
static getSetting(key, defaultValue = null) {
|
static getSetting(key, defaultValue = null) {
|
||||||
let value = defaultValue ?? null
|
let value = defaultValue ?? null
|
||||||
try {
|
try {
|
||||||
value = game.settings.get(SYSTEM.ID, key)
|
value = game.settings.get(MODULE.ID, key)
|
||||||
} catch {
|
} catch {
|
||||||
coreModule.api.Logger.debug(`Setting '${key}' not found`)
|
coreModule.api.Logger.debug(`Setting '${key}' not found`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export default class CthulhuEternalItemSheet extends HandlebarsApplicationMixin(
|
|||||||
dragover: this._onDragOver.bind(this),
|
dragover: this._onDragOver.bind(this),
|
||||||
drop: this._onDrop.bind(this),
|
drop: this._onDrop.bind(this),
|
||||||
}
|
}
|
||||||
return new DragDrop(d)
|
return new foundry.applications.ux.DragDrop.implementation(d)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,10 +98,20 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
|
|||||||
switch (partId) {
|
switch (partId) {
|
||||||
case "main":
|
case "main":
|
||||||
break
|
break
|
||||||
case "skills":
|
case "skills": {
|
||||||
context.tab = context.tabs.skills
|
context.tab = context.tabs.skills
|
||||||
context.skills = doc.itemTypes.skill
|
let tmpSkills = doc.itemTypes.skill
|
||||||
context.skills.sort((a, b) => a.name.localeCompare(b.name))
|
tmpSkills.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
const nbCols = 3;
|
||||||
|
const nbRows = Math.ceil(tmpSkills.length / nbCols);
|
||||||
|
let skillsColumns = Array.from({ length: nbRows }, (_, rowIdx) =>
|
||||||
|
Array.from({ length: nbCols }, (_, colIdx) => tmpSkills[rowIdx + colIdx * nbRows]).filter(Boolean)
|
||||||
|
);
|
||||||
|
// Merge skillsColumns in a single flat array
|
||||||
|
skillsColumns = skillsColumns.flat().filter(Boolean);
|
||||||
|
//DEBUG : console.log("Skills columns:", skillsColumns);
|
||||||
|
context.skills = skillsColumns
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case "equipment":
|
case "equipment":
|
||||||
context.tab = context.tabs.equipment
|
context.tab = context.tabs.equipment
|
||||||
|
|||||||
@@ -77,6 +77,96 @@ export const RESOURCE_RATING = {
|
|||||||
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichModern" },
|
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichModern" },
|
||||||
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichModern" }
|
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichModern" }
|
||||||
},
|
},
|
||||||
|
future: {
|
||||||
|
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
||||||
|
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 20000, assets: "CTHULHUETERNAL.Resource.PoorModern" },
|
||||||
|
8: { name: "Average", description: "CTHULHUETERNAL.Resource.Average", income: 50000, assets: "CTHULHUETERNAL.Resource.AverageModern" },
|
||||||
|
12: { name: "Above Average", description: "CTHULHUETERNAL.Resource.AboveAverage", income: 100000, assets: "CTHULHUETERNAL.Resource.AboveAverageModern" },
|
||||||
|
16: { name: "Well Off", description: "CTHULHUETERNAL.Resource.WellOff", income: 150000, assets: "CTHULHUETERNAL.Resource.WellOffModern" },
|
||||||
|
18: { name: "Rich", description: "CTHULHUETERNAL.Resource.Rich", income: 20000, assets: "CTHULHUETERNAL.Resource.RichModern" },
|
||||||
|
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichModern" },
|
||||||
|
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichModern" }
|
||||||
|
},
|
||||||
|
coldwar: {
|
||||||
|
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
||||||
|
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 20000, assets: "CTHULHUETERNAL.Resource.PoorColdWar" },
|
||||||
|
8: { name: "Average", description: "CTHULHUETERNAL.Resource.Average", income: 50000, assets: "CTHULHUETERNAL.Resource.AverageColdWar" },
|
||||||
|
12: { name: "Above Average", description: "CTHULHUETERNAL.Resource.AboveAverage", income: 100000, assets: "CTHULHUETERNAL.Resource.AboveAverageColdWar" },
|
||||||
|
16: { name: "Well Off", description: "CTHULHUETERNAL.Resource.WellOff", income: 150000, assets: "CTHULHUETERNAL.Resource.WellOffColdWar" },
|
||||||
|
18: { name: "Rich", description: "CTHULHUETERNAL.Resource.Rich", income: 200000, assets: "CTHULHUETERNAL.Resource.RichColdWar" },
|
||||||
|
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichColdWar" },
|
||||||
|
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichColdWar" }
|
||||||
|
},
|
||||||
|
ww1: {
|
||||||
|
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
||||||
|
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 20000, assets: "CTHULHUETERNAL.Resource.PoorColdWar" },
|
||||||
|
8: { name: "Average", description: "CTHULHUETERNAL.Resource.Average", income: 50000, assets: "CTHULHUETERNAL.Resource.AverageColdWar" },
|
||||||
|
12: { name: "Above Average", description: "CTHULHUETERNAL.Resource.AboveAverage", income: 100000, assets: "CTHULHUETERNAL.Resource.AboveAverageColdWar" },
|
||||||
|
16: { name: "Well Off", description: "CTHULHUETERNAL.Resource.WellOff", income: 150000, assets: "CTHULHUETERNAL.Resource.WellOffColdWar" },
|
||||||
|
18: { name: "Rich", description: "CTHULHUETERNAL.Resource.Rich", income: 200000, assets: "CTHULHUETERNAL.Resource.RichColdWar" },
|
||||||
|
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichColdWar" },
|
||||||
|
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichColdWar" }
|
||||||
|
},
|
||||||
|
ww2: {
|
||||||
|
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
||||||
|
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 20000, assets: "CTHULHUETERNAL.Resource.PoorColdWar" },
|
||||||
|
8: { name: "Average", description: "CTHULHUETERNAL.Resource.Average", income: 50000, assets: "CTHULHUETERNAL.Resource.AverageColdWar" },
|
||||||
|
12: { name: "Above Average", description: "CTHULHUETERNAL.Resource.AboveAverage", income: 100000, assets: "CTHULHUETERNAL.Resource.AboveAverageColdWar" },
|
||||||
|
16: { name: "Well Off", description: "CTHULHUETERNAL.Resource.WellOff", income: 150000, assets: "CTHULHUETERNAL.Resource.WellOffColdWar" },
|
||||||
|
18: { name: "Rich", description: "CTHULHUETERNAL.Resource.Rich", income: 200000, assets: "CTHULHUETERNAL.Resource.RichColdWar" },
|
||||||
|
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichColdWar" },
|
||||||
|
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichColdWar" }
|
||||||
|
},
|
||||||
|
medieval: {
|
||||||
|
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
||||||
|
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 20000, assets: "CTHULHUETERNAL.Resource.PoorColdWar" },
|
||||||
|
8: { name: "Average", description: "CTHULHUETERNAL.Resource.Average", income: 50000, assets: "CTHULHUETERNAL.Resource.AverageColdWar" },
|
||||||
|
12: { name: "Above Average", description: "CTHULHUETERNAL.Resource.AboveAverage", income: 100000, assets: "CTHULHUETERNAL.Resource.AboveAverageColdWar" },
|
||||||
|
16: { name: "Well Off", description: "CTHULHUETERNAL.Resource.WellOff", income: 150000, assets: "CTHULHUETERNAL.Resource.WellOffColdWar" },
|
||||||
|
18: { name: "Rich", description: "CTHULHUETERNAL.Resource.Rich", income: 200000, assets: "CTHULHUETERNAL.Resource.RichColdWar" },
|
||||||
|
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichColdWar" },
|
||||||
|
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichColdWar" }
|
||||||
|
},
|
||||||
|
revolution: {
|
||||||
|
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
||||||
|
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 20000, assets: "CTHULHUETERNAL.Resource.PoorColdWar" },
|
||||||
|
8: { name: "Average", description: "CTHULHUETERNAL.Resource.Average", income: 50000, assets: "CTHULHUETERNAL.Resource.AverageColdWar" },
|
||||||
|
12: { name: "Above Average", description: "CTHULHUETERNAL.Resource.AboveAverage", income: 100000, assets: "CTHULHUETERNAL.Resource.AboveAverageColdWar" },
|
||||||
|
16: { name: "Well Off", description: "CTHULHUETERNAL.Resource.WellOff", income: 150000, assets: "CTHULHUETERNAL.Resource.WellOffColdWar" },
|
||||||
|
18: { name: "Rich", description: "CTHULHUETERNAL.Resource.Rich", income: 200000, assets: "CTHULHUETERNAL.Resource.RichColdWar" },
|
||||||
|
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichColdWar" },
|
||||||
|
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichColdWar" }
|
||||||
|
},
|
||||||
|
ageofsail: {
|
||||||
|
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
||||||
|
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 20000, assets: "CTHULHUETERNAL.Resource.PoorColdWar" },
|
||||||
|
8: { name: "Average", description: "CTHULHUETERNAL.Resource.Average", income: 50000, assets: "CTHULHUETERNAL.Resource.AverageColdWar" },
|
||||||
|
12: { name: "Above Average", description: "CTHULHUETERNAL.Resource.AboveAverage", income: 100000, assets: "CTHULHUETERNAL.Resource.AboveAverageColdWar" },
|
||||||
|
16: { name: "Well Off", description: "CTHULHUETERNAL.Resource.WellOff", income: 150000, assets: "CTHULHUETERNAL.Resource.WellOffColdWar" },
|
||||||
|
18: { name: "Rich", description: "CTHULHUETERNAL.Resource.Rich", income: 200000, assets: "CTHULHUETERNAL.Resource.RichColdWar" },
|
||||||
|
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichColdWar" },
|
||||||
|
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichColdWar" }
|
||||||
|
},
|
||||||
|
classical: {
|
||||||
|
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
||||||
|
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 20000, assets: "CTHULHUETERNAL.Resource.PoorColdWar" },
|
||||||
|
8: { name: "Average", description: "CTHULHUETERNAL.Resource.Average", income: 50000, assets: "CTHULHUETERNAL.Resource.AverageColdWar" },
|
||||||
|
12: { name: "Above Average", description: "CTHULHUETERNAL.Resource.AboveAverage", income: 100000, assets: "CTHULHUETERNAL.Resource.AboveAverageColdWar" },
|
||||||
|
16: { name: "Well Off", description: "CTHULHUETERNAL.Resource.WellOff", income: 150000, assets: "CTHULHUETERNAL.Resource.WellOffColdWar" },
|
||||||
|
18: { name: "Rich", description: "CTHULHUETERNAL.Resource.Rich", income: 200000, assets: "CTHULHUETERNAL.Resource.RichColdWar" },
|
||||||
|
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichColdWar" },
|
||||||
|
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichColdWar" }
|
||||||
|
},
|
||||||
|
postapo: {
|
||||||
|
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
||||||
|
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 20000, assets: "CTHULHUETERNAL.Resource.PoorColdWar" },
|
||||||
|
8: { name: "Average", description: "CTHULHUETERNAL.Resource.Average", income: 50000, assets: "CTHULHUETERNAL.Resource.AverageColdWar" },
|
||||||
|
12: { name: "Above Average", description: "CTHULHUETERNAL.Resource.AboveAverage", income: 100000, assets: "CTHULHUETERNAL.Resource.AboveAverageColdWar" },
|
||||||
|
16: { name: "Well Off", description: "CTHULHUETERNAL.Resource.WellOff", income: 150000, assets: "CTHULHUETERNAL.Resource.WellOffColdWar" },
|
||||||
|
18: { name: "Rich", description: "CTHULHUETERNAL.Resource.Rich", income: 200000, assets: "CTHULHUETERNAL.Resource.RichColdWar" },
|
||||||
|
19: { name: "Very Rich", description: "CTHULHUETERNAL.Resource.VeryRich", income: 500000, assets: "CTHULHUETERNAL.Resource.VeryRichColdWar" },
|
||||||
|
20: { name: "Super Rich", description: "CTHULHUETERNAL.Resource.SuperRich", income: 1000000, assets: "CTHULHUETERNAL.Resource.SuperRichColdWar" }
|
||||||
|
},
|
||||||
victorian: {
|
victorian: {
|
||||||
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
0: { name: "Penury", description: "CTHULHUETERNAL.Resource.Penury", income: 0, assets: "CTHULHUETERNAL.Resource.NoAssets" },
|
||||||
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 30, assets: "CTHULHUETERNAL.Resource.PoorVictorian" },
|
4: { name: "Poor", description: "CTHULHUETERNAL.Resource.Poor", income: 30, assets: "CTHULHUETERNAL.Resource.PoorVictorian" },
|
||||||
|
|||||||
@@ -23,8 +23,10 @@ export default class CthulhuEternalActor extends Actor {
|
|||||||
data.items.push(skill.toObject())
|
data.items.push(skill.toObject())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.items.push({ type:"weapon", img: "systems/fvtt-cthulhu-eternal/assets/icons/icon_fist.svg",
|
data.items.push({
|
||||||
name: game.i18n.localize("CTHULHUETERNAL.Label.Unarmed"), system: { damage: "1d4-1", weaponType: "unarmed" } })
|
type: "weapon", img: "systems/fvtt-cthulhu-eternal/assets/icons/icon_fist.svg",
|
||||||
|
name: game.i18n.localize("CTHULHUETERNAL.Label.Unarmed"), system: { damage: "1d4-1", weaponType: "unarmed", applyDamageBonus: true }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.create(data, options);
|
return super.create(data, options);
|
||||||
@@ -43,6 +45,44 @@ export default class CthulhuEternalActor extends Actor {
|
|||||||
return super._onUpdate(changed, options, userId)
|
return super._onUpdate(changed, options, userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setLastDefenseRoll(rollData) {
|
||||||
|
this.setFlag("fvtt-cthulhu-eternal", "last-defense-roll", rollData)
|
||||||
|
}
|
||||||
|
|
||||||
|
getLastDefenseRoll() {
|
||||||
|
return this.getFlag("fvtt-cthulhu-eternal", "last-defense-roll")
|
||||||
|
}
|
||||||
|
|
||||||
|
applyWounds(woundData) {
|
||||||
|
// Get available armor
|
||||||
|
let armors = this.items.filter(i => i.type === "armor" && i.system.equipped)
|
||||||
|
let totalArmor = 0
|
||||||
|
for (let armor of armors) {
|
||||||
|
totalArmor += armor.system.protection
|
||||||
|
}
|
||||||
|
let effectiveWounds = Math.max(woundData.rollResult - totalArmor, 0)
|
||||||
|
if (woundData.isLethal) {
|
||||||
|
effectiveWounds = this.system.hp.value // Killed!
|
||||||
|
}
|
||||||
|
// Apply armor reduction
|
||||||
|
let hp = Math.max(this.system.hp.value - effectiveWounds, 0)
|
||||||
|
if (this.system.hp.value !== hp) {
|
||||||
|
this.update({ "system.hp.value": hp })
|
||||||
|
}
|
||||||
|
console.log("Applying wounds", { woundData, totalArmor, effectiveWounds })
|
||||||
|
// Chat message for GM only
|
||||||
|
if (game.user.isGM) {
|
||||||
|
let armorText = totalArmor > 0 ? game.i18n.format("CTHULHUETERNAL.Chat.armorAbsorbed", { armor: totalArmor }) : game.i18n.localize("CTHULHUETERNAL.Chat.noArmor")
|
||||||
|
ChatMessage.create({
|
||||||
|
user: game.user.id,
|
||||||
|
speaker: { alias: this.name },
|
||||||
|
rollMode: "gmroll",
|
||||||
|
content: game.i18n.format("CTHULHUETERNAL.Chat.woundsApplied", { name: this.name, effectiveWounds, armorText }),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async createEmbeddedDocuments(embeddedName, data, operation) {
|
async createEmbeddedDocuments(embeddedName, data, operation) {
|
||||||
let newData = []
|
let newData = []
|
||||||
if (embeddedName === "Item") {
|
if (embeddedName === "Item") {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
import { SYSTEM } from "../config/system.mjs"
|
import { SYSTEM } from "../config/system.mjs"
|
||||||
|
import CthulhuEternalUtils from "../utils.mjs"
|
||||||
|
|
||||||
export default class CthulhuEternalRoll extends Roll {
|
export default class CthulhuEternalRoll extends Roll {
|
||||||
/**
|
/**
|
||||||
@@ -128,51 +129,48 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
static async processWeaponDamage(actor, options) {
|
static async processWeaponDamage(actor, options) {
|
||||||
let isLethal = false
|
let isLethal = false
|
||||||
let weapon = options.rollItem
|
let weapon = options.rollItem
|
||||||
let ammoUsed = weapon.system.weaponType.includes("ranged") ? 1 : 0 // Default ammo used for melee weapons is 0
|
|
||||||
options.isNudge = false
|
options.isNudge = false
|
||||||
|
|
||||||
// Selective fire management
|
// Selective fire management
|
||||||
if (weapon.system.hasSelectiveFire && weapon.selectiveFireChoice) {
|
if (weapon.system.hasSelectiveFire && weapon.selectiveFireChoice) {
|
||||||
let choice = SYSTEM.WEAPON_SELECTIVE_FIRE_CHOICES[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.selectiveFireChoiceLabel = choice.label // Store the choice in the weapon
|
||||||
weapon.system.lethality = choice.lethality // Override lethality
|
weapon.system.lethality = choice.lethality // Override lethality
|
||||||
weapon.system.killRadius = choice.killRadius // Override kill radius
|
weapon.system.killRadius = choice.killRadius // Override kill radius
|
||||||
ammoUsed = choice.ammoUsed // Override ammo used
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ammoUsed = Number(ammoUsed)
|
let combatants = []
|
||||||
|
if (game?.combat?.combatants) {
|
||||||
|
for (let c of game.combat.combatants) {
|
||||||
|
if (c.actorid !== actor.id) {
|
||||||
|
combatants.push({ id: c.id, name: c.name })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (weapon.system.lethality > 0) {
|
if (weapon.system.lethality > 0) {
|
||||||
let lethalityRoll = new Roll("1d100")
|
let lethalityRoll = new Roll("1d100")
|
||||||
await lethalityRoll.evaluate()
|
await lethalityRoll.evaluate()
|
||||||
let lethalScore = (options?.previousResultType === "successCritical") ? weapon.system.lethality * 2 : weapon.system.lethality
|
let lethalScore = (options?.previousResultType === "successCritical") ? weapon.system.lethality * 2 : weapon.system.lethality
|
||||||
isLethal = (lethalityRoll.total <= lethalScore)
|
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 wounds = Math.floor(lethalityRoll.total / 10) + (lethalityRoll.total % 10)
|
||||||
let msgData = {
|
let msgData = {
|
||||||
|
actorId: actor.id,
|
||||||
weapon,
|
weapon,
|
||||||
wounds,
|
wounds,
|
||||||
lethalScore,
|
lethalScore,
|
||||||
isLethal,
|
isLethal,
|
||||||
ammoUsed,
|
ammoUsed: weapon?.ammoUsed || 0,
|
||||||
rollResult: lethalityRoll.total,
|
rollResult: lethalityRoll.total,
|
||||||
|
combatants: combatants
|
||||||
}
|
}
|
||||||
let flavor = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-lethal-damage.hbs", msgData)
|
let flavor = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-lethal-damage.hbs", msgData)
|
||||||
ChatMessage.create({
|
let msg = await ChatMessage.create({
|
||||||
user: game.user.id,
|
user: game.user.id,
|
||||||
content: flavor,
|
content: flavor,
|
||||||
speaker: ChatMessage.getSpeaker({ actor: actor }),
|
speaker: ChatMessage.getSpeaker({ actor: actor }),
|
||||||
}, { rollMode: options.rollMode, create: true })
|
}, { rollMode: options.rollMode, create: true })
|
||||||
|
await msg.setFlag("fvtt-cthulhu-eternal", "woundData", msgData)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,27 +182,24 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
if (options?.previousResultType === "successCritical") {
|
if (options?.previousResultType === "successCritical") {
|
||||||
formula = `( ${formula} ) * 2`
|
formula = `( ${formula} ) * 2`
|
||||||
}
|
}
|
||||||
if (ammoUsed > 0) {
|
|
||||||
await actor.updateEmbeddedDocuments("Item", [{
|
|
||||||
_id: weapon._id,
|
|
||||||
"system.ammo.value": Math.max(0, weapon.system.ammo.value - ammoUsed)
|
|
||||||
}])
|
|
||||||
}
|
|
||||||
console.log("Weapon damage formula", formula, weapon, ammoUsed)
|
|
||||||
let damageRoll = new Roll(formula)
|
let damageRoll = new Roll(formula)
|
||||||
await damageRoll.evaluate()
|
await damageRoll.evaluate()
|
||||||
let msgData = {
|
let msgData = {
|
||||||
|
actorId: actor.id,
|
||||||
weapon,
|
weapon,
|
||||||
formula,
|
formula,
|
||||||
ammoUsed,
|
ammoUsed: weapon?.ammoUsed || 0,
|
||||||
rollResult: damageRoll.total,
|
rollResult: damageRoll.total,
|
||||||
|
combatants: combatants
|
||||||
}
|
}
|
||||||
let flavor = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-regular-damage.hbs", msgData)
|
let flavor = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-regular-damage.hbs", msgData)
|
||||||
ChatMessage.create({
|
let msg = await ChatMessage.create({
|
||||||
user: game.user.id,
|
user: game.user.id,
|
||||||
content: flavor,
|
content: flavor,
|
||||||
speaker: ChatMessage.getSpeaker({ actor: actor }),
|
speaker: ChatMessage.getSpeaker({ actor: actor }),
|
||||||
}, { rollMode: options.rollMode, create: true })
|
}, { rollMode: options.rollMode, create: true })
|
||||||
|
await msg.setFlag("fvtt-cthulhu-eternal", "woundData", msgData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -215,11 +210,32 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
modifier += SYSTEM.WEAPON_VISIBILITY[rollData.visibilityChoice]?.modifier || 0
|
modifier += SYSTEM.WEAPON_VISIBILITY[rollData.visibilityChoice]?.modifier || 0
|
||||||
modifier += SYSTEM.WEAPON_ATTACKER_STATE[rollData.attackerStateChoice]?.modifier || 0
|
modifier += SYSTEM.WEAPON_ATTACKER_STATE[rollData.attackerStateChoice]?.modifier || 0
|
||||||
modifier += SYSTEM.WEAPON_TARGET_SIZE[rollData.targetSizeChoice]?.modifier || 0
|
modifier += SYSTEM.WEAPON_TARGET_SIZE[rollData.targetSizeChoice]?.modifier || 0
|
||||||
modifier += (rollData.aimingLastRound) ? 20 : 0
|
modifier += (rollData.aimingLastRoundFlag) ? 20 : 0
|
||||||
modifier += (rollData.aimingWithSight) ? 20 : 0
|
modifier += (rollData.aimingWithSightFlag) ? 20 : 0
|
||||||
return modifier
|
return modifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async processAmmoUsed(actor, weapon) {
|
||||||
|
let ammoUsed = weapon.system.weaponType.includes("ranged") ? 1 : 0 // Default ammo used for melee weapons is 0
|
||||||
|
// Selective fire management
|
||||||
|
if (weapon.system.hasSelectiveFire && weapon.selectiveFireChoice) {
|
||||||
|
let choice = SYSTEM.WEAPON_SELECTIVE_FIRE_CHOICES[weapon.selectiveFireChoice]
|
||||||
|
if (choice.ammoUsed > weapon.system.ammo.value) {
|
||||||
|
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.NoAmmo"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ammoUsed = choice.ammoUsed // Override ammo used
|
||||||
|
}
|
||||||
|
ammoUsed = Number(ammoUsed)
|
||||||
|
if (ammoUsed > 0) {
|
||||||
|
await actor.updateEmbeddedDocuments("Item", [{
|
||||||
|
_id: weapon._id,
|
||||||
|
"system.ammo.value": Math.max(0, weapon.system.ammo.value - ammoUsed)
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
weapon.ammoUsed = ammoUsed
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prompt the user with a dialog to configure and execute a roll.
|
* Prompt the user with a dialog to configure and execute a roll.
|
||||||
*
|
*
|
||||||
@@ -241,9 +257,10 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
options.isNudge = true
|
options.isNudge = true
|
||||||
let actor = game.actors.get(options.actorId)
|
let actor = game.actors.get(options.actorId)
|
||||||
|
|
||||||
|
let target = CthulhuEternalUtils.getTarget()
|
||||||
|
|
||||||
switch (options.rollType) {
|
switch (options.rollType) {
|
||||||
case "skill":
|
case "skill":
|
||||||
console.log(options.rollItem)
|
|
||||||
options.initialScore = options.rollItem.system.computeScore()
|
options.initialScore = options.rollItem.system.computeScore()
|
||||||
break
|
break
|
||||||
case "luck":
|
case "luck":
|
||||||
@@ -281,26 +298,19 @@ 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
|
||||||
}
|
}
|
||||||
|
/*if (!target) {
|
||||||
|
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.AttackNoTarget"))
|
||||||
|
}*/
|
||||||
// Check if the weapon has enouth ammo in case of a firearm
|
// Check if the weapon has enouth ammo in case of a firearm
|
||||||
if (options.rollItem.system.isFireArm() && options.rollItem.system.ammo.value <= 0) {
|
if (options.rollItem.system.isFireArm() && options.rollItem.system.ammo.value <= 0) {
|
||||||
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.NoAmmo"))
|
ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.NoAmmo"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
options.weapon = options.rollItem
|
options.weapon = options.rollItem
|
||||||
if (options.rollItem.system.hasDirectSkill) {
|
|
||||||
let skillName = options.rollItem.name
|
options.rollItem = CthulhuEternalUtils.getWeaponSkill(actor, options.rollItem, era)
|
||||||
options.rollItem = { type: "skill", name: skillName, system: { base: 0, bonus: options.weapon.system.directSkillValue } }
|
options.initialScore = options.rollItem.system.skillTotal
|
||||||
options.initialScore = options.weapon.system.directSkillValue
|
console.log("WEAPON", era, options.rollItem)
|
||||||
} else {
|
|
||||||
let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType])
|
|
||||||
options.rollItem = actor.items.find(i => i.type === "skill" && i.name.toLowerCase() === skillName.toLowerCase())
|
|
||||||
if (!options.rollItem) {
|
|
||||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.NoWeaponSkill"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
options.initialScore = options.rollItem.system.computeScore()
|
|
||||||
console.log("WEAPON", skillName, era, options.rollItem)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@@ -353,10 +363,11 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
visibilityChoice: "clear",
|
visibilityChoice: "clear",
|
||||||
attackerStateChoice: "normal",
|
attackerStateChoice: "normal",
|
||||||
targetSizeChoice: "normal",
|
targetSizeChoice: "normal",
|
||||||
aimingLastRound: false,
|
aimingLastRoundFlag: false,
|
||||||
aimingWithSight: false,
|
aimingWithSightFlag: false,
|
||||||
modifier,
|
modifier,
|
||||||
formula,
|
formula,
|
||||||
|
targetName: target?.name,
|
||||||
hasTarget: options.hasTarget,
|
hasTarget: options.hasTarget,
|
||||||
hasModifier,
|
hasModifier,
|
||||||
hasMultiplier,
|
hasMultiplier,
|
||||||
@@ -402,6 +413,14 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
options.multiplier = Number(event.target.value)
|
options.multiplier = Number(event.target.value)
|
||||||
this.updateResourceDialog(options)
|
this.updateResourceDialog(options)
|
||||||
})
|
})
|
||||||
|
$(".aimingLastRound").change(event => {
|
||||||
|
options.aimingLastRoundFlag = event.target.checked
|
||||||
|
this.updateResourceDialog(options)
|
||||||
|
})
|
||||||
|
$(".aimingWithSight").change(event => {
|
||||||
|
options.aimingWithSightFlag = event.target.checked
|
||||||
|
this.updateResourceDialog(options)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -409,10 +428,14 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
if (rollContext === null) return
|
if (rollContext === null) return
|
||||||
|
|
||||||
let rollData = foundry.utils.mergeObject(foundry.utils.duplicate(options), rollContext)
|
let rollData = foundry.utils.mergeObject(foundry.utils.duplicate(options), rollContext)
|
||||||
|
// If we have a target, get its data
|
||||||
|
rollData.targetId = target?.id
|
||||||
|
rollData.targetName = target?.name
|
||||||
rollData.rollMode = rollContext.visibility
|
rollData.rollMode = rollContext.visibility
|
||||||
|
|
||||||
// Update target score
|
// Update target score
|
||||||
console.log("Rolldata", rollData, options)
|
console.log("Rolldata", rollData)
|
||||||
|
|
||||||
if (options.rollType === "resource") {
|
if (options.rollType === "resource") {
|
||||||
rollData.targetScore = options.initialScore * Number(rollContext.multiplier)
|
rollData.targetScore = options.initialScore * Number(rollContext.multiplier)
|
||||||
} else {
|
} else {
|
||||||
@@ -432,6 +455,10 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
rollData.modifier = "0"
|
rollData.modifier = "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.rollType === "weapon") {
|
||||||
|
await this.processAmmoUsed(actor, rollData.weapon)
|
||||||
|
}
|
||||||
|
|
||||||
if (Hooks.call("fvtt-cthulhu-eternal.preRoll", options, rollData) === false) return
|
if (Hooks.call("fvtt-cthulhu-eternal.preRoll", options, rollData) === false) return
|
||||||
|
|
||||||
const roll = new this(formula, options.data, rollData)
|
const roll = new this(formula, options.data, rollData)
|
||||||
@@ -492,7 +519,66 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
this.options.isLowWP = rollData.isLowWP
|
this.options.isLowWP = rollData.isLowWP
|
||||||
this.options.isZeroWP = rollData.isZeroWP
|
this.options.isZeroWP = rollData.isZeroWP
|
||||||
this.options.isExhausted = rollData.isExhausted
|
this.options.isExhausted = rollData.isExhausted
|
||||||
|
rollData.isSuccess = this.options.isSuccess
|
||||||
|
rollData.isFailure = this.options.isFailure
|
||||||
|
rollData.isCritical = this.options.isCritical
|
||||||
|
rollData.resultType = resultType
|
||||||
|
rollData.rollResult = this.total
|
||||||
|
rollData.total = this.total
|
||||||
this.options.rollData = foundry.utils.duplicate(rollData)
|
this.options.rollData = foundry.utils.duplicate(rollData)
|
||||||
|
|
||||||
|
// Keep track of the last defense roll for the actor
|
||||||
|
if (game.combat && (rollData?.weapon?.system.type === "melee" || (rollData?.rollItem.type === "skill" && rollData?.rollItem.name?.toLowerCase().includes(game.i18n.localize("CTHULHUETERNAL.Skill.dodgeName").toLowerCase())))) {
|
||||||
|
let actor = game.actors.get(options.actorId)
|
||||||
|
rollData.round = game.combat.round
|
||||||
|
actor.setLastDefenseRoll(foundry.utils.duplicate(rollData))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game.combat && rollData?.weapon) { // An attack roll
|
||||||
|
rollData.isAttackRoll = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now check if we have a target for the current roll, and if the target has done its defense roll this round
|
||||||
|
if (rollData.targetId) {
|
||||||
|
let token = game.scenes.current.tokens.get(rollData.targetId)
|
||||||
|
let defender = token.actor
|
||||||
|
let lastDefenseRoll = defender?.getLastDefenseRoll()
|
||||||
|
// Now compare opposition
|
||||||
|
this.compareRolls(rollData, lastDefenseRoll)
|
||||||
|
rollData.defenseRoll = lastDefenseRoll
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
compareRolls(attackRoll, defenseRoll) {
|
||||||
|
if (!defenseRoll || defenseRoll.round !== game?.combat?.round) {
|
||||||
|
// ui.notifications.info(game.i18n.localize("CTHULHUETERNAL.Notifications.NoDefenseRoll"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (attackRoll.isFailure) {
|
||||||
|
attackRoll.attackSucess = false
|
||||||
|
}
|
||||||
|
if (attackRoll.isSuccess && defenseRoll.isFailure) {
|
||||||
|
attackRoll.attackSucess = true
|
||||||
|
}
|
||||||
|
if (attackRoll.isSuccess && defenseRoll.isSuccess) {
|
||||||
|
if (attackRoll.isCritical && !defenseRoll.isCritical) {
|
||||||
|
attackRoll.attackSucess = true
|
||||||
|
}
|
||||||
|
else if (!attackRoll.isCritical && defenseRoll.isCritical) {
|
||||||
|
attackRoll.attackSucess = false
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Both are normal success, compare the roll results
|
||||||
|
if (attackRoll.total >= defenseRoll.total) {
|
||||||
|
// Attack successful
|
||||||
|
attackRoll.attackSucess = true
|
||||||
|
} else {
|
||||||
|
// Defense successful
|
||||||
|
attackRoll.attackSucess = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -590,7 +676,7 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
* @returns {Promise} - A promise that resolves when the message is created.
|
* @returns {Promise} - A promise that resolves when the message is created.
|
||||||
*/
|
*/
|
||||||
async toMessage(messageData = {}, { rollMode, create = true } = {}) {
|
async toMessage(messageData = {}, { rollMode, create = true } = {}) {
|
||||||
super.toMessage(
|
let rollMsg = await super.toMessage(
|
||||||
{
|
{
|
||||||
isFailure: this.resultType === "failure",
|
isFailure: this.resultType === "failure",
|
||||||
actingCharName: this.actorName,
|
actingCharName: this.actorName,
|
||||||
@@ -601,10 +687,11 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
},
|
},
|
||||||
{ rollMode: rollMode },
|
{ rollMode: rollMode },
|
||||||
)
|
)
|
||||||
|
|
||||||
// Manage the skill evolution if the roll is a failure
|
|
||||||
let rollData = this.options.rollData || this.options
|
let rollData = this.options.rollData || this.options
|
||||||
let rollItem = this.options.rollItem
|
let rollItem = this.options.rollItem
|
||||||
|
await rollMsg.setFlag("fvtt-cthulhu-eternal", "rollData", rollData)
|
||||||
|
|
||||||
|
// Manage the skill evolution if the roll is a failure
|
||||||
if (rollData.resultType.includes("failure") && rollItem.type === "skill") {
|
if (rollData.resultType.includes("failure") && rollItem.type === "skill") {
|
||||||
// Is the skill able to progress
|
// Is the skill able to progress
|
||||||
if (rollItem.system.diceEvolved && !rollItem.system.rollFailed) {
|
if (rollItem.system.diceEvolved && !rollItem.system.rollFailed) {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
|
|||||||
insanity: new fields.StringField({ required: true, nullable: false, initial: "none", choices: SYSTEM.INSANITY }),
|
insanity: new fields.StringField({ required: true, nullable: false, initial: "none", choices: SYSTEM.INSANITY }),
|
||||||
})
|
})
|
||||||
|
|
||||||
schema.damageBonus = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
schema.damageBonus = new fields.NumberField({ ...requiredInteger, initial: 0, min: -2 })
|
||||||
|
|
||||||
schema.resources = new fields.SchemaField({
|
schema.resources = new fields.SchemaField({
|
||||||
value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), // Unused but kept for compatibility
|
value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }), // Unused but kept for compatibility
|
||||||
@@ -127,9 +127,11 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
|
|||||||
dmgBonus = -2
|
dmgBonus = -2
|
||||||
} else if (this.characteristics.str.value <= 8) {
|
} else if (this.characteristics.str.value <= 8) {
|
||||||
dmgBonus = -1
|
dmgBonus = -1
|
||||||
|
} else if (this.characteristics.str.value <= 12) {
|
||||||
|
dmgBonus = 0
|
||||||
} else if (this.characteristics.str.value <= 16) {
|
} else if (this.characteristics.str.value <= 16) {
|
||||||
dmgBonus = 1
|
dmgBonus = 1
|
||||||
} else if (this.characteristics.str.value <= 20) {
|
} else if (this.characteristics.str.value <= 40) {
|
||||||
dmgBonus = 2
|
dmgBonus = 2
|
||||||
}
|
}
|
||||||
if (this.damageBonus !== dmgBonus) {
|
if (this.damageBonus !== dmgBonus) {
|
||||||
@@ -140,13 +142,16 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
|
|||||||
if (!this.san.breakingPointReached && this.san.value <= this.san.breakingPoint) {
|
if (!this.san.breakingPointReached && this.san.value <= this.san.breakingPoint) {
|
||||||
updates[`system.san.breakingPointReached`] = true
|
updates[`system.san.breakingPointReached`] = true
|
||||||
this.san.breakingPointReached = true // Force local update to true
|
this.san.breakingPointReached = true // Force local update to true
|
||||||
|
let w = game.users.find(u => u.character?.name === this.parent?.name)
|
||||||
|
if (w) {
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
content: `<p>${game.i18n.format("CTHULHUETERNAL.Label.breakingPointReached", { bp: this.san.breakingPoint, san: this.san.value })}</p>`,
|
content: `<p>${game.i18n.format("CTHULHUETERNAL.Label.breakingPointReached", { bp: this.san.breakingPoint, san: this.san.value })}</p>`,
|
||||||
speaker: ChatMessage.getSpeaker({ actor: this.parent }),
|
speaker: ChatMessage.getSpeaker({ actor: this.parent }),
|
||||||
// Get the user id of the actor owner
|
// Get the user id of the actor owner
|
||||||
whisper: [game.users.find(u => u.character?.name === this.parent?.name).id ]
|
whisper: [w.id]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Unconsciousness management
|
// Unconsciousness management
|
||||||
if (!this.hp.unconscious && this.hp.value <= 2) {
|
if (!this.hp.unconscious && this.hp.value <= 2) {
|
||||||
|
|||||||
259
module/utils.mjs
259
module/utils.mjs
@@ -16,6 +16,14 @@ export default class CthulhuEternalUtils {
|
|||||||
config: true,
|
config: true,
|
||||||
onChange: _ => window.location.reload()
|
onChange: _ => window.location.reload()
|
||||||
});
|
});
|
||||||
|
game.settings.register("fvtt-cthulhu-eternal", "roll-opposed-store", {
|
||||||
|
name: "Roll Opposed Store",
|
||||||
|
hint: "Whether to store opposed roll results for later use",
|
||||||
|
default: { roll1: null, roll2: null },
|
||||||
|
scope: "world",
|
||||||
|
type: Object,
|
||||||
|
config: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static async loadCompendiumData(compendium) {
|
static async loadCompendiumData(compendium) {
|
||||||
@@ -180,6 +188,53 @@ export default class CthulhuEternalUtils {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static removeChatMessageId(messageId) {
|
||||||
|
if (messageId) {
|
||||||
|
game.messages.get(messageId)?.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static findChatMessageId(current) {
|
||||||
|
return HawkmoonUtility.getChatMessageId(HawkmoonUtility.findChatMessage(current));
|
||||||
|
}
|
||||||
|
|
||||||
|
static getChatMessageId(node) {
|
||||||
|
return node?.attributes.getNamedItem('data-message-id')?.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static findChatMessage(current) {
|
||||||
|
return HawkmoonUtility.findNodeMatching(current, it => it.classList.contains('chat-message') && it.attributes.getNamedItem('data-message-id'))
|
||||||
|
}
|
||||||
|
|
||||||
|
static findNodeMatching(current, predicate) {
|
||||||
|
if (current) {
|
||||||
|
if (predicate(current)) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
return HawkmoonUtility.findNodeMatching(current.parentElement, predicate);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static getWeaponSkill(actor, weapon, era) {
|
||||||
|
let skill
|
||||||
|
if (weapon.system.hasDirectSkill) {
|
||||||
|
let skillName = weapon.name
|
||||||
|
skill = { type: "skill", name: skillName, system: { base: 0, bonus: weapon.system.directSkillValue, skillTotal: weapon.system.directSkillValue } }
|
||||||
|
} else {
|
||||||
|
let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][weapon.system.weaponType])
|
||||||
|
skill = actor.items.find(i => i.type === "skill" && i.name.toLowerCase() === skillName.toLowerCase())
|
||||||
|
if (!skill) {
|
||||||
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.NoWeaponSkill"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return skill
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
static async applySANType(rollMessage, event) {
|
static async applySANType(rollMessage, event) {
|
||||||
let rollData = rollMessage.getFlag("fvtt-cthulhu-eternal", "rollData")
|
let rollData = rollMessage.getFlag("fvtt-cthulhu-eternal", "rollData")
|
||||||
if (!rollData) {
|
if (!rollData) {
|
||||||
@@ -248,13 +303,179 @@ export default class CthulhuEternalUtils {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async opposedRollManagement(rollMessage, event) {
|
||||||
|
let rollData = rollMessage.getFlag("fvtt-cthulhu-eternal", "rollData")
|
||||||
|
if (!rollData) {
|
||||||
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noRollDataFound"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the store
|
||||||
|
let store = game.settings.get("fvtt-cthulhu-eternal", "roll-opposed-store")
|
||||||
|
if (!store.roll1) {
|
||||||
|
store.roll1 = {
|
||||||
|
rollData: rollData,
|
||||||
|
messageId: rollMessage.id
|
||||||
|
}
|
||||||
|
await game.settings.set("fvtt-cthulhu-eternal", "roll-opposed-store", store)
|
||||||
|
ui.notifications.info(game.i18n.localize("CTHULHUETERNAL.Notifications.opposedRollFirstStored"))
|
||||||
|
}
|
||||||
|
else if (!store.roll2) {
|
||||||
|
store.roll2 = {
|
||||||
|
rollData: rollData,
|
||||||
|
messageId: rollMessage.id
|
||||||
|
}
|
||||||
|
await game.settings.set("fvtt-cthulhu-eternal", "roll-opposed-store", store)
|
||||||
|
ui.notifications.info(game.i18n.localize("CTHULHUETERNAL.Notifications.opposedRollSecondStored"))
|
||||||
|
// Now perform the opposed roll resolution
|
||||||
|
await this.resolveOpposedRolls(store.roll1, store.roll2)
|
||||||
|
// Clear the store
|
||||||
|
store.roll1 = null
|
||||||
|
store.roll2 = null
|
||||||
|
await game.settings.set("fvtt-cthulhu-eternal", "roll-opposed-store", store)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.opposedRollStoreFull"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async resolveOpposedRolls(roll1, roll2) {
|
||||||
|
// Get actors
|
||||||
|
let actor1 = game.actors.get(roll1.rollData.actorId)
|
||||||
|
let actor2 = game.actors.get(roll2.rollData.actorId)
|
||||||
|
if (!actor1 || !actor2) {
|
||||||
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noActorFound"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Determine winner
|
||||||
|
let winner = null
|
||||||
|
let loser = null
|
||||||
|
// If there critical success/failure, apply them first (remark : this d100 results)
|
||||||
|
roll1.rollData.rollCompare = roll1.rollData.rollResult
|
||||||
|
roll2.rollData.rollCompare = roll2.rollData.rollResult
|
||||||
|
if (roll1.rollData.resultType === "successCritical") {
|
||||||
|
roll1.rollData.rollCompare = -roll1.rollData.rollResult
|
||||||
|
}
|
||||||
|
if (roll2.rollData.resultType === "failureCritical") {
|
||||||
|
roll2.rollData.rollCompare = 100 + roll2.rollData.rollResult
|
||||||
|
}
|
||||||
|
if (roll2.rollData.resultType === "successCritical") {
|
||||||
|
roll2.rollData.rollCompare = -roll2.rollData.rollResult
|
||||||
|
}
|
||||||
|
if (roll1.rollData.resultType === "failureCritical") {
|
||||||
|
roll1.rollData.rollCompare = roll1.rollData.rollResult * 2
|
||||||
|
}
|
||||||
|
if (roll1.rollData.isSuccess && roll2.rollData.isFailure) {
|
||||||
|
winner = { actor: actor1, rollData: roll1.rollData, messageId: roll1.messageId }
|
||||||
|
loser = { actor: actor2, rollData: roll2.rollData, messageId: roll2.messageId }
|
||||||
|
}
|
||||||
|
else if (roll2.rollData.isSuccess && roll1.rollData.isFailure) {
|
||||||
|
winner = { actor: actor2, rollData: roll2.rollData, messageId: roll2.messageId }
|
||||||
|
loser = { actor: actor1, rollData: roll1.rollData, messageId: roll1.messageId }
|
||||||
|
}
|
||||||
|
else if (roll1.rollData.rollCompare < roll2.rollData.rollCompare) {
|
||||||
|
winner = { actor: actor1, rollData: roll1.rollData, messageId: roll1.messageId }
|
||||||
|
loser = { actor: actor2, rollData: roll2.rollData, messageId: roll2.messageId }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
winner = { actor: actor2, rollData: roll2.rollData, messageId: roll2.messageId }
|
||||||
|
loser = { actor: actor1, rollData: roll1.rollData, messageId: roll1.messageId }
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Opposed roll result", winner, loser)
|
||||||
|
|
||||||
|
// Check if winner was attacking with a weapon that can apply damage
|
||||||
|
let canApplyDamage = winner && winner.rollData?.weapon && winner.rollData.weapon.system
|
||||||
|
|
||||||
|
// Prepare data for the template
|
||||||
|
let msgData = {
|
||||||
|
winner: {
|
||||||
|
actor: {
|
||||||
|
name: winner.actor.name,
|
||||||
|
img: winner.actor.img
|
||||||
|
},
|
||||||
|
rollData: {
|
||||||
|
rollResult: winner.rollData.rollResult || winner.rollData.total,
|
||||||
|
isCritical: winner.rollData.isCritical,
|
||||||
|
weapon: winner.rollData.weapon
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loser: {
|
||||||
|
actor: {
|
||||||
|
name: loser.actor.name,
|
||||||
|
img: loser.actor.img
|
||||||
|
},
|
||||||
|
rollData: {
|
||||||
|
rollResult: loser.rollData.rollResult || loser.rollData.total,
|
||||||
|
isCritical: loser.rollData.isCritical
|
||||||
|
}
|
||||||
|
},
|
||||||
|
canApplyDamage: canApplyDamage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the template
|
||||||
|
let content = await foundry.applications.handlebars.renderTemplate(
|
||||||
|
"systems/fvtt-cthulhu-eternal/templates/chat-opposed-result.hbs",
|
||||||
|
msgData
|
||||||
|
)
|
||||||
|
|
||||||
|
// Display the result in chat
|
||||||
|
let chatMsg = await ChatMessage.create({
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: winner.actor.id }),
|
||||||
|
content: content
|
||||||
|
})
|
||||||
|
|
||||||
|
// Store the winner's roll data for damage roll if applicable
|
||||||
|
if (canApplyDamage) {
|
||||||
|
await chatMsg.setFlag("fvtt-cthulhu-eternal", "rollData", winner.rollData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static translateRangeUnit(range) {
|
||||||
|
if (typeof range === 'string') {
|
||||||
|
return game.i18n.localize(`CTHULHUETERNAL.Label.${range}`)
|
||||||
|
} else if (typeof range === 'number') {
|
||||||
|
return range
|
||||||
|
} else {
|
||||||
|
console.warn("CTHULHU ETERNAL | translateRange called with an unknown type", range)
|
||||||
|
return range
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static translateRange(range) {
|
||||||
|
// If the range is a string, replace STR with FOR
|
||||||
|
if (typeof range === 'string') {
|
||||||
|
return range.replace(/STR/g, "FOR").replace(/str/g, "for")
|
||||||
|
}
|
||||||
|
return range
|
||||||
|
}
|
||||||
|
|
||||||
|
static async registerBabeleTranslations(babele) {
|
||||||
|
babele.registerConverters({
|
||||||
|
'translateRangeUnit': (originalValue) => {
|
||||||
|
return CthulhuEternalUtils.translateRangeUnit(originalValue)
|
||||||
|
},
|
||||||
|
'translateRange': (originalValue) => {
|
||||||
|
return CthulhuEternalUtils.translateRange(originalValue)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
static async damageRoll(rollMessage, formula = null) {
|
static async damageRoll(rollMessage, formula = null) {
|
||||||
let rollData = rollMessage.rolls[0]?.options?.rollData
|
let rollData = rollMessage.rolls[0]?.options?.rollData
|
||||||
|
if (!rollData) {
|
||||||
|
rollData = rollMessage.getFlag("fvtt-cthulhu-eternal", "rollData")
|
||||||
|
}
|
||||||
|
if (!rollData) {
|
||||||
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Label.noRollDataFound"))
|
||||||
|
return
|
||||||
|
}
|
||||||
let actor = game.actors.get(rollData.actorId)
|
let actor = game.actors.get(rollData.actorId)
|
||||||
if (!actor) {
|
if (!actor) {
|
||||||
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)
|
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
|
rollData.weapon.selectiveFireChoice = rollData.selectiveFireChoice // Keep the selected fire choice from the roll message
|
||||||
@@ -327,6 +548,10 @@ export default class CthulhuEternalUtils {
|
|||||||
roll.toMessage()
|
roll.toMessage()
|
||||||
|
|
||||||
actor.system.modifyWP(-dialogContext.wpCost)
|
actor.system.modifyWP(-dialogContext.wpCost)
|
||||||
|
|
||||||
|
// Delete the initial roll message
|
||||||
|
await rollMessage.delete()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static setupCSSRootVariables() {
|
static setupCSSRootVariables() {
|
||||||
@@ -345,4 +570,38 @@ export default class CthulhuEternalUtils {
|
|||||||
document.documentElement.style.setProperty('--background-image-base', `linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8)), url("../assets/ui/${era}_background_main.webp")`);
|
document.documentElement.style.setProperty('--background-image-base', `linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8)), url("../assets/ui/${era}_background_main.webp")`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getTarget() {
|
||||||
|
if (game.user.targets && game.user.targets.size === 1) {
|
||||||
|
for (let target of game.user.targets) {
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
static applyWounds(message, event) {
|
||||||
|
let woundData = message.getFlag("fvtt-cthulhu-eternal", "woundData")
|
||||||
|
if (!woundData) {
|
||||||
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noRollDataFound"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let actor = game.actors.get(woundData.actorId)
|
||||||
|
if (!actor) {
|
||||||
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noActorFound"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log("Applying wounds", woundData)
|
||||||
|
// Remove the chat message
|
||||||
|
this.removeChatMessageId(message.id)
|
||||||
|
|
||||||
|
// Get the targetted actorId from the button's data attribute
|
||||||
|
let targetCombatantId = event.currentTarget.dataset.combatantId
|
||||||
|
let combatant = game.combat.combatants.get(targetCombatantId)
|
||||||
|
let targetActor = combatant.token?.actor || game.actors.get(combatant.actorId)
|
||||||
|
if (!targetActor) {
|
||||||
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noTargetActorFound") + targetCombatantId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
targetActor.applyWounds(woundData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
MANIFEST-000217
|
MANIFEST-000273
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
2025/07/14-21:08:15.948300 7f3fa67fc6c0 Recovering log #215
|
2025/11/21-23:23:35.521610 7f21eeffd6c0 Recovering log #271
|
||||||
2025/07/14-21:08:15.959041 7f3fa67fc6c0 Delete type=3 #213
|
2025/11/21-23:23:35.612353 7f21eeffd6c0 Delete type=3 #269
|
||||||
2025/07/14-21:08:15.959103 7f3fa67fc6c0 Delete type=0 #215
|
2025/11/21-23:23:35.612430 7f21eeffd6c0 Delete type=0 #271
|
||||||
2025/07/14-21:36:01.776546 7f3fa57fa6c0 Level-0 table #220: started
|
2025/11/21-23:35:34.796894 7f21ed7fa6c0 Level-0 table #276: started
|
||||||
2025/07/14-21:36:01.776599 7f3fa57fa6c0 Level-0 table #220: 0 bytes OK
|
2025/11/21-23:35:34.796917 7f21ed7fa6c0 Level-0 table #276: 0 bytes OK
|
||||||
2025/07/14-21:36:01.836135 7f3fa57fa6c0 Delete type=0 #218
|
2025/11/21-23:35:34.806397 7f21ed7fa6c0 Delete type=0 #274
|
||||||
2025/07/14-21:36:02.071353 7f3fa57fa6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
|
2025/11/21-23:35:34.806600 7f21ed7fa6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
2025/07/14-10:18:19.443254 7f3fa77fe6c0 Recovering log #211
|
2025/11/12-23:48:30.686758 7f4781ffb6c0 Recovering log #267
|
||||||
2025/07/14-10:18:19.474975 7f3fa77fe6c0 Delete type=3 #209
|
2025/11/12-23:48:30.697449 7f4781ffb6c0 Delete type=3 #265
|
||||||
2025/07/14-10:18:19.475128 7f3fa77fe6c0 Delete type=0 #211
|
2025/11/12-23:48:30.697507 7f4781ffb6c0 Delete type=0 #267
|
||||||
2025/07/14-20:48:52.882063 7f3fa57fa6c0 Level-0 table #216: started
|
2025/11/13-13:58:42.410831 7f4780bff6c0 Level-0 table #272: started
|
||||||
2025/07/14-20:48:52.882164 7f3fa57fa6c0 Level-0 table #216: 0 bytes OK
|
2025/11/13-13:58:42.410865 7f4780bff6c0 Level-0 table #272: 0 bytes OK
|
||||||
2025/07/14-20:48:52.889652 7f3fa57fa6c0 Delete type=0 #214
|
2025/11/13-13:58:42.417362 7f4780bff6c0 Delete type=0 #270
|
||||||
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)
|
2025/11/13-13:58:42.434870 7f4780bff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
BIN
packs-system/rituals/MANIFEST-000273
Normal file
BIN
packs-system/rituals/MANIFEST-000273
Normal file
Binary file not shown.
0
packs-system/skills/000444.log
Normal file
0
packs-system/skills/000444.log
Normal file
@@ -1 +1 @@
|
|||||||
MANIFEST-000386
|
MANIFEST-000442
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
2025/07/14-21:08:15.916959 7f3fa5ffb6c0 Recovering log #384
|
2025/11/21-23:23:35.280848 7f21edffb6c0 Recovering log #440
|
||||||
2025/07/14-21:08:15.927715 7f3fa5ffb6c0 Delete type=3 #382
|
2025/11/21-23:23:35.368467 7f21edffb6c0 Delete type=3 #438
|
||||||
2025/07/14-21:08:15.927846 7f3fa5ffb6c0 Delete type=0 #384
|
2025/11/21-23:23:35.368552 7f21edffb6c0 Delete type=0 #440
|
||||||
2025/07/14-21:36:01.925671 7f3fa57fa6c0 Level-0 table #389: started
|
2025/11/21-23:35:34.777225 7f21ed7fa6c0 Level-0 table #445: started
|
||||||
2025/07/14-21:36:01.925708 7f3fa57fa6c0 Level-0 table #389: 0 bytes OK
|
2025/11/21-23:35:34.777275 7f21ed7fa6c0 Level-0 table #445: 0 bytes OK
|
||||||
2025/07/14-21:36:01.980506 7f3fa57fa6c0 Delete type=0 #387
|
2025/11/21-23:35:34.786357 7f21ed7fa6c0 Delete type=0 #443
|
||||||
2025/07/14-21:36:02.071389 7f3fa57fa6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
|
2025/11/21-23:35:34.806576 7f21ed7fa6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
2025/07/14-10:18:19.359761 7f3fa67fc6c0 Recovering log #380
|
2025/11/12-23:48:30.659183 7f47817fa6c0 Recovering log #436
|
||||||
2025/07/14-10:18:19.394536 7f3fa67fc6c0 Delete type=3 #378
|
2025/11/12-23:48:30.670042 7f47817fa6c0 Delete type=3 #434
|
||||||
2025/07/14-10:18:19.394680 7f3fa67fc6c0 Delete type=0 #380
|
2025/11/12-23:48:30.670124 7f47817fa6c0 Delete type=0 #436
|
||||||
2025/07/14-20:48:52.889840 7f3fa57fa6c0 Level-0 table #385: started
|
2025/11/13-13:58:42.417482 7f4780bff6c0 Level-0 table #441: started
|
||||||
2025/07/14-20:48:52.889882 7f3fa57fa6c0 Level-0 table #385: 0 bytes OK
|
2025/11/13-13:58:42.417509 7f4780bff6c0 Level-0 table #441: 0 bytes OK
|
||||||
2025/07/14-20:48:52.896159 7f3fa57fa6c0 Delete type=0 #383
|
2025/11/13-13:58:42.423396 7f4780bff6c0 Delete type=0 #439
|
||||||
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)
|
2025/11/13-13:58:42.434882 7f4780bff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
BIN
packs-system/skills/MANIFEST-000442
Normal file
BIN
packs-system/skills/MANIFEST-000442
Normal file
Binary file not shown.
0
packs-system/skills/lost/000392.log
Normal file
0
packs-system/skills/lost/000392.log
Normal file
0
packs-system/skills/lost/000409.log
Normal file
0
packs-system/skills/lost/000409.log
Normal file
0
packs-system/weapons/000090.log
Normal file
0
packs-system/weapons/000090.log
Normal file
@@ -1 +1 @@
|
|||||||
MANIFEST-000031
|
MANIFEST-000088
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
2025/07/14-21:08:15.933872 7f3fa6ffd6c0 Recovering log #29
|
2025/11/21-23:23:35.396467 7f21ef7fe6c0 Recovering log #86
|
||||||
2025/07/14-21:08:15.943722 7f3fa6ffd6c0 Delete type=3 #27
|
2025/11/21-23:23:35.502570 7f21ef7fe6c0 Delete type=3 #84
|
||||||
2025/07/14-21:08:15.943845 7f3fa6ffd6c0 Delete type=0 #29
|
2025/11/21-23:23:35.502631 7f21ef7fe6c0 Delete type=0 #86
|
||||||
2025/07/14-21:36:01.980637 7f3fa57fa6c0 Level-0 table #34: started
|
2025/11/21-23:35:34.786516 7f21ed7fa6c0 Level-0 table #91: started
|
||||||
2025/07/14-21:36:02.012185 7f3fa57fa6c0 Level-0 table #34: 24252 bytes OK
|
2025/11/21-23:35:34.786543 7f21ed7fa6c0 Level-0 table #91: 0 bytes OK
|
||||||
2025/07/14-21:36:02.071125 7f3fa57fa6c0 Delete type=0 #32
|
2025/11/21-23:35:34.796797 7f21ed7fa6c0 Delete type=0 #89
|
||||||
2025/07/14-21:36:02.071403 7f3fa57fa6c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)
|
2025/11/21-23:35:34.806589 7f21ed7fa6c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)
|
||||||
2025/07/14-21:36:02.071441 7f3fa57fa6c0 Manual compaction at level-1 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at '!items!qb4c1wfPZFcGiEuV' @ 472 : 1
|
|
||||||
2025/07/14-21:36:02.071451 7f3fa57fa6c0 Compacting 1@1 + 1@2 files
|
|
||||||
2025/07/14-21:36:02.101879 7f3fa57fa6c0 Generated table #35@1: 362 keys, 93592 bytes
|
|
||||||
2025/07/14-21:36:02.101908 7f3fa57fa6c0 Compacted 1@1 + 1@2 files => 93592 bytes
|
|
||||||
2025/07/14-21:36:02.154064 7f3fa57fa6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
|
|
||||||
2025/07/14-21:36:02.154296 7f3fa57fa6c0 Delete type=2 #14
|
|
||||||
2025/07/14-21:36:02.154743 7f3fa57fa6c0 Delete type=2 #34
|
|
||||||
2025/07/14-21:36:02.372014 7f3fa57fa6c0 Manual compaction at level-1 from '!items!qb4c1wfPZFcGiEuV' @ 472 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
2025/07/14-10:18:19.404246 7f3fa5ffb6c0 Recovering log #25
|
2025/11/12-23:48:30.674156 7f4781ffb6c0 Recovering log #82
|
||||||
2025/07/14-10:18:19.435628 7f3fa5ffb6c0 Delete type=3 #23
|
2025/11/12-23:48:30.683495 7f4781ffb6c0 Delete type=3 #80
|
||||||
2025/07/14-10:18:19.435765 7f3fa5ffb6c0 Delete type=0 #25
|
2025/11/12-23:48:30.683546 7f4781ffb6c0 Delete type=0 #82
|
||||||
2025/07/14-20:48:52.908846 7f3fa57fa6c0 Level-0 table #30: started
|
2025/11/13-13:58:42.404378 7f4780bff6c0 Level-0 table #87: started
|
||||||
2025/07/14-20:48:52.908888 7f3fa57fa6c0 Level-0 table #30: 0 bytes OK
|
2025/11/13-13:58:42.404437 7f4780bff6c0 Level-0 table #87: 0 bytes OK
|
||||||
2025/07/14-20:48:52.915004 7f3fa57fa6c0 Delete type=0 #28
|
2025/11/13-13:58:42.410719 7f4780bff6c0 Delete type=0 #85
|
||||||
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/11/13-13:58:42.434856 7f4780bff6c0 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)
|
|
||||||
|
|||||||
Binary file not shown.
BIN
packs-system/weapons/MANIFEST-000088
Normal file
BIN
packs-system/weapons/MANIFEST-000088
Normal file
Binary file not shown.
0
packs-system/weapons/lost/000038.log
Normal file
0
packs-system/weapons/lost/000038.log
Normal file
0
packs-system/weapons/lost/000055.log
Normal file
0
packs-system/weapons/lost/000055.log
Normal file
@@ -111,8 +111,8 @@ i.fvtt-cthulhu-eternal {
|
|||||||
padding: 2px 2px;
|
padding: 2px 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 0.3s;
|
transition: background-color 0.3s;
|
||||||
min-width: 6.0rem;
|
min-width: 6rem;
|
||||||
max-width: 6.0rem;
|
max-width: 6rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.san-loose-buttons {
|
.san-loose-buttons {
|
||||||
@@ -128,8 +128,8 @@ i.fvtt-cthulhu-eternal {
|
|||||||
padding: 2px 2px;
|
padding: 2px 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 0.3s;
|
transition: background-color 0.3s;
|
||||||
min-width: 3.0rem;
|
min-width: 3rem;
|
||||||
max-width: 3.0rem;
|
max-width: 3rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.result-non-lethal {
|
.result-non-lethal {
|
||||||
@@ -141,5 +141,28 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.02);
|
font-size: calc(var(--font-size-standard) * 1.02);
|
||||||
}
|
}
|
||||||
|
.combatants-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
gap: 4px;
|
||||||
|
margin: 8px 0;
|
||||||
|
button.apply-wounds-btn {
|
||||||
|
font-family: var(--font-primary);
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.7);
|
||||||
|
border: 1px solid #4b4a44;
|
||||||
|
padding: 4px 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
background-color: #f0f0e0;
|
||||||
|
color: #1c1c1c;
|
||||||
|
&:hover {
|
||||||
|
background-color: #d5d5c5;
|
||||||
|
border-color: #2d2d2a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
244
styles/roll.less
244
styles/roll.less
@@ -53,6 +53,10 @@
|
|||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.li-apply-wounds {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
&.dice-roll {
|
&.dice-roll {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
@@ -91,22 +95,7 @@
|
|||||||
li {
|
li {
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.0);
|
font-size: calc(var(--font-size-standard) * 1);
|
||||||
}
|
|
||||||
.nudge-roll {
|
|
||||||
font-size: calc(var(--font-size-standard) * 1.0);
|
|
||||||
margin-left: 2rem;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.healing-roll {
|
|
||||||
font-size: calc(var(--font-size-standard) * 1.0);
|
|
||||||
margin-left: 2rem;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.roll-damage {
|
|
||||||
font-size: calc(var(--font-size-standard) * 1.0);
|
|
||||||
margin-left: 2rem;
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
.result-success {
|
.result-success {
|
||||||
color: var(--color-success);
|
color: var(--color-success);
|
||||||
@@ -145,4 +134,227 @@
|
|||||||
font-size: calc(var(--font-size-standard) * 1.2);
|
font-size: calc(var(--font-size-standard) * 1.2);
|
||||||
text-shadow: 0 0 10px var(--color-shadow-primary);
|
text-shadow: 0 0 10px var(--color-shadow-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.375rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
border-top: 1px solid var(--color-border-light-primary);
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.chat-action-button {
|
||||||
|
display: inline-flex !important;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
background: var(--color-dark-6);
|
||||||
|
color: var(--color-light-1);
|
||||||
|
border: 1px solid var(--color-border-light-primary);
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
text-decoration: none;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--color-dark-5);
|
||||||
|
border-color: var(--color-border-dark);
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 1rem !important;
|
||||||
|
line-height: 1;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nudge-roll,
|
||||||
|
.damage-roll,
|
||||||
|
.healing-roll,
|
||||||
|
.opposed-roll {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opposed-roll-result {
|
||||||
|
padding: 0.5rem;
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 5px;
|
||||||
|
font-family: var(--font-primary);
|
||||||
|
|
||||||
|
.opposed-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
padding-bottom: 0.2rem;
|
||||||
|
border-bottom: 1px solid var(--color-border-light-primary);
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-family: var(--font-title);
|
||||||
|
font-size: calc(var(--font-size-standard) * 1);
|
||||||
|
color: var(--color-dark-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opposed-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.15rem;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opposed-winner,
|
||||||
|
.opposed-loser {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.3rem 0.4rem;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opposed-winner {
|
||||||
|
background: rgba(34, 139, 34, 0.1);
|
||||||
|
border: 2px solid var(--color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.opposed-loser {
|
||||||
|
background: rgba(220, 20, 60, 0.1);
|
||||||
|
border: 2px solid var(--color-failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
.character-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid var(--color-border-light-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.character-name {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.15rem;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.75);
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--color-dark-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.winner-name {
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.95);
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loser-name {
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.95);
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--color-failure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.roll-result {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.3rem;
|
||||||
|
|
||||||
|
.roll-value {
|
||||||
|
font-size: calc(var(--font-size-standard) * 1.2);
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: var(--font-title);
|
||||||
|
}
|
||||||
|
|
||||||
|
.critical-badge {
|
||||||
|
padding: 0.15rem 0.3rem;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.7);
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
background: var(--color-critical-success);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.winner-result .roll-value {
|
||||||
|
color: var(--color-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loser-result .roll-value {
|
||||||
|
color: var(--color-failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
.versus-separator {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.3rem;
|
||||||
|
padding: 0;
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.85);
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--color-dark-2);
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.375rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
border-top: 1px solid var(--color-border-light-primary);
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
|
||||||
|
.chat-action-button {
|
||||||
|
display: inline-flex !important;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
background: var(--color-dark-6);
|
||||||
|
color: var(--color-light-1);
|
||||||
|
border: 1px solid var(--color-border-light-primary);
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
text-decoration: none;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--color-dark-5);
|
||||||
|
border-color: var(--color-border-dark);
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 1rem !important;
|
||||||
|
line-height: 1;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"download": "#{DOWNLOAD}#",
|
"download": "#{DOWNLOAD}#",
|
||||||
"url": "https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal",
|
"url": "https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal",
|
||||||
"license": "LICENSE",
|
"license": "LICENSE",
|
||||||
"version": "13.0.1",
|
"version": "13.0.2",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Uberwald",
|
"name": "Uberwald",
|
||||||
|
|||||||
@@ -21,12 +21,20 @@
|
|||||||
<li>{{localize "CTHULHUETERNAL.Label.ammoUsed"}}: {{ammoUsed}} / {{weapon.system.ammo.value}}</li>
|
<li>{{localize "CTHULHUETERNAL.Label.ammoUsed"}}: {{ammoUsed}} / {{weapon.system.ammo.value}}</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
<li class="li-apply-wounds">
|
||||||
|
<button type="button" class="apply-wounds">{{localize "CTHULHUETERNAL.Label.applyWounds"}}</button>
|
||||||
|
<select name="combatant" class="roll-skill-modifier">
|
||||||
|
{{selectOptions combatants valueAttr="id" labelAttr="name"}}
|
||||||
|
</select>
|
||||||
|
</li>
|
||||||
|
|
||||||
{{#if isLethal}}
|
{{#if isLethal}}
|
||||||
<li class="result-lethal">{{localize "CTHULHUETERNAL.Label.lethalityLethal"}}</li>
|
<li class="result-lethal">{{localize "CTHULHUETERNAL.Label.lethalityLethal"}}</li>
|
||||||
<li class="result-lethal">{{localize "CTHULHUETERNAL.Label.lethalityWounded"}}</li>
|
<li class="result-lethal">{{localize "CTHULHUETERNAL.Label.lethalityWounded"}}</li>
|
||||||
{{else}}
|
{{else}}
|
||||||
<li class="result-non-lethal">{{localize "CTHULHUETERNAL.Label.lethalityNotLethal"}}</li>
|
<li class="result-non-lethal">{{localize "CTHULHUETERNAL.Label.lethalityNotLethal"}}</li>
|
||||||
<li class="result-non-lethal">{{localize "CTHULHUETERNAL.Label.lethalityNotWounded"}}: <strong>{{wounds}}</strong></li>
|
<li class="result-non-lethal">{{localize "CTHULHUETERNAL.Label.lethalityNotWounded"}}: <strong>{{wounds}}</strong>
|
||||||
|
</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -6,20 +6,28 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="intro-right">
|
<div class="intro-right">
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><strong>{{actingCharName}}</strong></li>
|
||||||
{{#if (eq rollType "char")}}
|
{{#if (eq rollType "char")}}
|
||||||
<li><strong>{{localize "CTHULHUETERNAL.Label.charRoll"}}</strong></li>
|
<li><strong>{{localize "CTHULHUETERNAL.Label.charRoll"}}</strong></li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if (eq rollType "skill")}}
|
{{#if (eq rollType "skill")}}
|
||||||
<li><strong>{{localize "CTHULHUETERNAL.Label.skillRoll"}}</strong></li>
|
<li><strong>{{localize
|
||||||
|
"CTHULHUETERNAL.Label.skillRoll"
|
||||||
|
}}</strong></li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isNudgedRoll}}
|
{{#if isNudgedRoll}}
|
||||||
<li><strong>{{localize "CTHULHUETERNAL.Label.nudgedRoll"}} : {{wpCost}} {{localize "CTHULHUETERNAL.Label.WPSpent"}}</strong></li>
|
<li><strong>{{localize "CTHULHUETERNAL.Label.nudgedRoll"}}
|
||||||
|
:
|
||||||
|
{{wpCost}}
|
||||||
|
{{localize "CTHULHUETERNAL.Label.WPSpent"}}</strong></li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if weapon}}
|
{{#if weapon}}
|
||||||
<li><strong>{{localize "CTHULHUETERNAL.Label.Weapon"}} : {{weapon.name}}</strong></li>
|
<li><strong>{{localize "CTHULHUETERNAL.Label.Weapon"}}
|
||||||
|
:
|
||||||
|
{{weapon.name}}</strong></li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if (eq rollType "resource")}}
|
{{#if (eq rollType "resource")}}
|
||||||
@@ -29,95 +37,101 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isZeroWP}}
|
{{#if isZeroWP}}
|
||||||
<li class="red-warning">{{localize "CTHULHUETERNAL.Label.ZeroWP"}}</li>
|
<li class="red-warning">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.ZeroWP"
|
||||||
|
}}</li>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if isLowWP}}
|
{{#if isLowWP}}
|
||||||
<li class="orange-warning">{{localize "CTHULHUETERNAL.Label.LowWP"}} : -20%</li>
|
<li class="orange-warning">{{localize "CTHULHUETERNAL.Label.LowWP"}}
|
||||||
|
: -20%</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isExhausted}}
|
{{#if isExhausted}}
|
||||||
<li class="orange-warning">{{localize "CTHULHUETERNAL.Label.Exhausted"}} : -20%</li>
|
<li class="orange-warning">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.Exhausted"
|
||||||
|
}}
|
||||||
|
: -20%</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if (eq rollType "resource")}}
|
{{#if (eq rollType "resource")}}
|
||||||
<li>{{localize "CTHULHUETERNAL.Label.multiplier"}} : {{multiplier}}</li>
|
<li>{{localize "CTHULHUETERNAL.Label.multiplier"}}
|
||||||
|
:
|
||||||
|
{{multiplier}}</li>
|
||||||
{{else}}
|
{{else}}
|
||||||
<li>{{localize "CTHULHUETERNAL.Label.modifier"}} : {{totalModifier}}%</li>
|
<li>{{localize "CTHULHUETERNAL.Label.modifier"}}
|
||||||
|
:
|
||||||
|
{{totalModifier}}%</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<li>{{localize "CTHULHUETERNAL.Label.targetScore"}} : {{targetScore}}%</li>
|
<li>{{localize "CTHULHUETERNAL.Label.targetScore"}}
|
||||||
|
:
|
||||||
|
{{targetScore}}%</li>
|
||||||
|
|
||||||
{{#if isSuccess}}
|
{{#if isSuccess}}
|
||||||
{{#if isCritical}}
|
{{#if isCritical}}
|
||||||
<li class="result-critical-success">{{localize "CTHULHUETERNAL.Label.criticalSuccess"}}
|
<li class="result-critical-success">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.criticalSuccess"
|
||||||
|
}}
|
||||||
</li>
|
</li>
|
||||||
{{else}}
|
{{else}}
|
||||||
<li class="result-success">
|
<li class="result-success">
|
||||||
{{localize "CTHULHUETERNAL.Label.success"}}
|
{{localize "CTHULHUETERNAL.Label.success"}}
|
||||||
{{#if isNudge}}
|
|
||||||
<a class="nudge-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollNudge"}}"><i class="fa-solid fa-circle-sort-down"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq rollType "weapon")}}
|
|
||||||
<li>
|
|
||||||
{{#if (eq weapon.system.weaponType "rangedfirearm")}}
|
|
||||||
{{#if weapon.system.hasDamageDistance}}
|
|
||||||
{{#each weapon.system.damageDistance as |damageDistance|}}
|
|
||||||
{{#if (gt damageDistance.distance 0)}}
|
|
||||||
<a class="damage-roll" data-item-id="{{weapon.id}}" data-action="roll" data-roll-type="damage"
|
|
||||||
data-roll-value="{{damageDistance.damage}}" >
|
|
||||||
<i class="fa-solid fa-gun"></i>
|
|
||||||
<span class="damage-distance">{{damageDistance.distance}}:{{damageDistance.damage}} </span>
|
|
||||||
</a>
|
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
|
||||||
{{else}}
|
|
||||||
<a class="damage-roll" data-roll-value="{{weapon.system.damage}}" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-gun"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
{{else}}
|
|
||||||
<a class="damage-roll" data-roll-value="{{weapon.system.damage}}" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-sword"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
</li>
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq rollType "skill") }}
|
|
||||||
{{#if rollItem.system.isHealing}}
|
|
||||||
<li>
|
|
||||||
<a class="healing-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollHealing"}}"><i class="fa-solid fa-heart"></i></a>
|
|
||||||
</li>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
</li>
|
|
||||||
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isFailure}}
|
{{#if isFailure}}
|
||||||
{{#if isCritical}}
|
{{#if isCritical}}
|
||||||
<li class="result-critical-failure">{{localize "CTHULHUETERNAL.Label.criticalFailure"}}
|
<li class="result-critical-failure">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.criticalFailure"
|
||||||
|
}}
|
||||||
</li>
|
</li>
|
||||||
{{else}}
|
{{else}}
|
||||||
<li class="result-failure">
|
<li class="result-failure">
|
||||||
{{localize "CTHULHUETERNAL.Label.failure"}}
|
{{localize "CTHULHUETERNAL.Label.failure"}}
|
||||||
</li>
|
</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isNudge}}
|
|
||||||
<li>
|
|
||||||
<a class="nudge-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollNudge"}}"><i class="fa-solid fa-circle-sort-down"></i></a>
|
|
||||||
</li>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
<!-- {{#if isAttackRoll}}
|
||||||
|
{{#if defenseRoll}}
|
||||||
|
<li>{{localize "CTHULHUETERNAL.Label.defenseRoll"}}</li>
|
||||||
|
{{#if attackSuccess}}
|
||||||
|
<li class="result-success">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.attackSuccess"
|
||||||
|
}}</li>
|
||||||
|
{{else}}
|
||||||
|
<li class="result-failure">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.attackFailure"
|
||||||
|
}}</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
{{#if targetId}}
|
||||||
|
<li class="orange-warning">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.noDefenseRoll"
|
||||||
|
}}</li>
|
||||||
|
{{else}}
|
||||||
|
<li class="orange-warning">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.noTarget"
|
||||||
|
}}</li>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}} -->
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if isDamage}}
|
{{#if isDamage}}
|
||||||
<div>
|
<div>
|
||||||
{{#if (and isGM hasTarget)}}
|
{{#if (and isGM hasTarget)}}
|
||||||
{{{localize "CTHULHUETERNAL.Roll.displayArmor" targetName=targetName targetArmor=targetArmor
|
{{{localize
|
||||||
realDamage=realDamage}}}
|
"CTHULHUETERNAL.Roll.displayArmor"
|
||||||
|
targetName=targetName
|
||||||
|
targetArmor=targetArmor
|
||||||
|
realDamage=realDamage
|
||||||
|
}}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@@ -128,4 +142,86 @@
|
|||||||
{{{tooltip}}}
|
{{{tooltip}}}
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
|
{{! Zone d'actions regroupées }}
|
||||||
|
<div class="chat-actions">
|
||||||
|
{{#if isSuccess}}
|
||||||
|
{{#if isNudge}}
|
||||||
|
<a
|
||||||
|
class="nudge-roll chat-action-button"
|
||||||
|
data-tooltip="{{localize 'CTHULHUETERNAL.Label.rollNudge'}}"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-circle-sort-down"></i>
|
||||||
|
</a>
|
||||||
|
{{/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)}}
|
||||||
|
<a
|
||||||
|
class="damage-roll chat-action-button"
|
||||||
|
data-item-id="{{weapon.id}}"
|
||||||
|
data-action="roll"
|
||||||
|
data-roll-type="damage"
|
||||||
|
data-roll-value="{{damageDistance.damage}}"
|
||||||
|
data-tooltip="{{localize
|
||||||
|
'CTHULHUETERNAL.Label.rollDamage'
|
||||||
|
}} ({{damageDistance.distance}}m : {{damageDistance.damage}})"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-gun"></i>
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
<a
|
||||||
|
class="damage-roll chat-action-button"
|
||||||
|
data-roll-value="{{weapon.system.damage}}"
|
||||||
|
data-tooltip="{{localize 'CTHULHUETERNAL.Label.rollDamage'}}"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-gun"></i>
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
<a
|
||||||
|
class="damage-roll chat-action-button"
|
||||||
|
data-roll-value="{{weapon.system.damage}}"
|
||||||
|
data-tooltip="{{localize 'CTHULHUETERNAL.Label.rollDamage'}}"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-sword"></i>
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if (eq rollType "skill")}}
|
||||||
|
{{#if rollItem.system.isHealing}}
|
||||||
|
<a
|
||||||
|
class="healing-roll chat-action-button"
|
||||||
|
data-tooltip="{{localize 'CTHULHUETERNAL.Label.rollHealing'}}"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-heart"></i>
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isFailure}}
|
||||||
|
{{#if isNudge}}
|
||||||
|
<a
|
||||||
|
class="nudge-roll chat-action-button"
|
||||||
|
data-tooltip="{{localize 'CTHULHUETERNAL.Label.rollNudge'}}"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-circle-sort-down"></i>
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<a
|
||||||
|
class="opposed-roll chat-action-button"
|
||||||
|
data-tooltip="{{localize 'CTHULHUETERNAL.Label.opposedRoll'}}"
|
||||||
|
>
|
||||||
|
<i class="fa-duotone fa-light fa-arrows-to-line"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
64
templates/chat-opposed-result.hbs
Normal file
64
templates/chat-opposed-result.hbs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{{! Template for opposed roll result }}
|
||||||
|
<div class="cthulhu-eternal-roll opposed-roll-result">
|
||||||
|
<div class="opposed-header">
|
||||||
|
<h3>{{localize "CTHULHUETERNAL.Label.opposedRollResult"}}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="opposed-content">
|
||||||
|
<div class="opposed-winner">
|
||||||
|
<div class="character-info">
|
||||||
|
<img src="{{winner.actor.img}}" alt="{{winner.actor.name}}" />
|
||||||
|
<div class="character-name">
|
||||||
|
<strong>{{localize "CTHULHUETERNAL.Label.opposedRollWinner"}}</strong>
|
||||||
|
<span class="winner-name">{{winner.actor.name}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="roll-result winner-result">
|
||||||
|
<span class="roll-value">{{winner.rollData.rollResult}}</span>
|
||||||
|
{{#if winner.rollData.isCritical}}
|
||||||
|
<span class="critical-badge">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.critical"
|
||||||
|
}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="versus-separator">
|
||||||
|
<i class="fas fa-swords"></i>
|
||||||
|
<span>{{localize "CTHULHUETERNAL.Label.defeats"}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="opposed-loser">
|
||||||
|
<div class="character-info">
|
||||||
|
<img src="{{loser.actor.img}}" alt="{{loser.actor.name}}" />
|
||||||
|
<div class="character-name">
|
||||||
|
<span class="loser-name">{{loser.actor.name}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="roll-result loser-result">
|
||||||
|
<span class="roll-value">{{loser.rollData.rollResult}}</span>
|
||||||
|
{{#if loser.rollData.isCritical}}
|
||||||
|
<span class="critical-badge">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.critical"
|
||||||
|
}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if canApplyDamage}}
|
||||||
|
<div class="chat-actions">
|
||||||
|
<a
|
||||||
|
class="damage-roll chat-action-button"
|
||||||
|
data-roll-value="{{winner.rollData.weapon.system.damage}}"
|
||||||
|
data-tooltip="{{localize 'CTHULHUETERNAL.Label.rollDamage'}}"
|
||||||
|
>
|
||||||
|
{{#if (eq winner.rollData.weapon.system.weaponType "rangedfirearm")}}
|
||||||
|
<i class="fa-solid fa-gun"></i>
|
||||||
|
{{else}}
|
||||||
|
<i class="fa-solid fa-sword"></i>
|
||||||
|
{{/if}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
@@ -1,22 +1,59 @@
|
|||||||
<div class="{{cssClass}}">
|
<div class="{{cssClass}}">
|
||||||
<div class="chat-lethal-damage">
|
<div class="chat-lethal-damage">
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>{{weapon.name}} : {{localize "CTHULHUETERNAL.Label.damageRoll"}}</strong></li>
|
<li><strong>{{weapon.name}}
|
||||||
<li>{{localize "CTHULHUETERNAL.Label.result"}} :{{rollResult}} ({{formula}})</li>
|
:
|
||||||
|
{{localize "CTHULHUETERNAL.Label.damageRoll"}}</strong></li>
|
||||||
|
<li>{{localize "CTHULHUETERNAL.Label.result"}}
|
||||||
|
:{{rollResult}}
|
||||||
|
({{formula}})</li>
|
||||||
|
|
||||||
{{#if (gt weapon.system.killRadius 0)}}
|
{{#if (gt weapon.system.killRadius 0)}}
|
||||||
<li>{{localize "CTHULHUETERNAL.Label.killRadius"}} : {{weapon.system.killRadius}} {{weapon.system.rangeUnit}}</li>
|
<li>{{localize "CTHULHUETERNAL.Label.killRadius"}}
|
||||||
|
:
|
||||||
|
{{weapon.system.killRadius}}
|
||||||
|
{{weapon.system.rangeUnit}}</li>
|
||||||
<li>{{localize "CTHULHUETERNAL.Label.killRadiusInfo"}}</li>
|
<li>{{localize "CTHULHUETERNAL.Label.killRadiusInfo"}}</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if (gt weapon.system.armorPiercing 0)}}
|
{{#if (gt weapon.system.armorPiercing 0)}}
|
||||||
<li>{{localize "CTHULHUETERNAL.Label.armorPiercing"}} : {{weapon.system.armorPiercing}}</li>
|
<li>{{localize "CTHULHUETERNAL.Label.armorPiercing"}}
|
||||||
|
:
|
||||||
|
{{weapon.system.armorPiercing}}</li>
|
||||||
|
{{/if}}
|
||||||
|
{{#if (gt weapon.system.penetration 0)}}
|
||||||
|
<li>{{localize "CTHULHUETERNAL.Label.penetration"}}
|
||||||
|
:
|
||||||
|
{{weapon.system.penetration}}</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if ammoUsed}}
|
{{#if ammoUsed}}
|
||||||
<li>{{localize "CTHULHUETERNAL.Label.ammoUsed"}}: {{ammoUsed}} / {{weapon.system.ammo.value}}</li>
|
<li>{{localize "CTHULHUETERNAL.Label.ammoUsed"}}:
|
||||||
|
{{ammoUsed}}
|
||||||
|
/
|
||||||
|
{{weapon.system.ammo.value}}</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<li class="result-non-lethal">{{localize "CTHULHUETERNAL.Label.damageMessage"}}: <strong>{{rollResult}}</strong></li>
|
|
||||||
|
<li class="li-apply-wounds">
|
||||||
|
<div>{{localize "CTHULHUETERNAL.Label.applyWounds"}}</div>
|
||||||
|
<div class="combatants-grid">
|
||||||
|
{{#each combatants}}
|
||||||
|
<button
|
||||||
|
class="apply-wounds-btn"
|
||||||
|
data-combatant-id="{{this.id}}"
|
||||||
|
title="{{this.name}}"
|
||||||
|
>
|
||||||
|
{{this.name}}
|
||||||
|
</button>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="result-non-lethal">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.damageMessage"
|
||||||
|
}}:
|
||||||
|
<strong>{{rollResult}}</strong>
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|||||||
@@ -9,25 +9,62 @@
|
|||||||
|
|
||||||
{{#if (eq rollType "resource")}}
|
{{#if (eq rollType "resource")}}
|
||||||
<legend>{{localize "CTHULHUETERNAL.Label.resourceRating"}}</legend>
|
<legend>{{localize "CTHULHUETERNAL.Label.resourceRating"}}</legend>
|
||||||
<div class="dialog-skill">{{rollItem.name}} : <span class="resource-score">{{initialScore}} ({{mul initialScore 5}}%)</span></div>
|
<div class="dialog-skill">{{rollItem.name}}
|
||||||
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Hand"}} : {{rollItem.hand}} <input type="checkbox" data-action="selectHand" {{checked rollItem.enableHand}}></div>
|
:
|
||||||
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Stowed"}} : {{rollItem.stowed}} <input type="checkbox" data-action="selectStowed" {{checked rollItem.enableStowed}}></div>
|
<span class="resource-score">{{initialScore}}
|
||||||
|
({{mul initialScore 5}}%)</span></div>
|
||||||
|
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Hand"}}
|
||||||
|
:
|
||||||
|
{{rollItem.hand}}
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
data-action="selectHand"
|
||||||
|
{{checked rollItem.enableHand}}
|
||||||
|
/></div>
|
||||||
|
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Stowed"}}
|
||||||
|
:
|
||||||
|
{{rollItem.stowed}}
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
data-action="selectStowed"
|
||||||
|
{{checked rollItem.enableStowed}}
|
||||||
|
/></div>
|
||||||
<div class="dialog-skill">
|
<div class="dialog-skill">
|
||||||
{{localize "CTHULHUETERNAL.Label.Storage"}} : {{rollItem.storage}}
|
{{localize "CTHULHUETERNAL.Label.Storage"}}
|
||||||
<input type="checkbox" data-action="selectStorage" {{checked rollItem.enableStorage}}>
|
:
|
||||||
|
{{rollItem.storage}}
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
data-action="selectStorage"
|
||||||
|
{{checked rollItem.enableStorage}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="dialog-skill">{{rollItem.name}} : {{initialScore}}%</div>
|
<div class="dialog-skill">{{rollItem.name}} : {{initialScore}}%</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if weapon}}
|
{{#if weapon}}
|
||||||
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Weapon"}} : {{weapon.name}}</div>
|
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Weapon"}}
|
||||||
|
:
|
||||||
|
{{weapon.name}}</div>
|
||||||
|
|
||||||
|
{{#if targetName}}
|
||||||
|
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Target"}}
|
||||||
|
:
|
||||||
|
{{targetName}}</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if (eq weapon.system.weaponType "melee")}}
|
{{#if (eq weapon.system.weaponType "melee")}}
|
||||||
<div class="dialog-skill">
|
<div class="dialog-skill">
|
||||||
{{localize "CTHULHUETERNAL.Label.targetMove"}}
|
{{localize "CTHULHUETERNAL.Label.targetMove"}}
|
||||||
<select name="meleeTargetMoveChoice" class="roll-skill-modifier">
|
<select name="meleeTargetMoveChoice" class="roll-skill-modifier">
|
||||||
{{selectOptions choiceMeleeTargetMove localize=true selected=meleeTargetMoveChoice valueAttr="id" labelAttr="label"}}
|
{{selectOptions
|
||||||
|
choiceMeleeTargetMove
|
||||||
|
localize=true
|
||||||
|
selected=meleeTargetMoveChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@@ -35,24 +72,44 @@
|
|||||||
<div class="dialog-skill">
|
<div class="dialog-skill">
|
||||||
{{localize "CTHULHUETERNAL.Label.rangedRange"}}
|
{{localize "CTHULHUETERNAL.Label.rangedRange"}}
|
||||||
<select name="rangedRangeChoice" class="roll-skill-modifier">
|
<select name="rangedRangeChoice" class="roll-skill-modifier">
|
||||||
{{selectOptions choiceRangedRange localize=true selected=rangedRangeChoice valueAttr="id" labelAttr="label"}}
|
{{selectOptions
|
||||||
|
choiceRangedRange
|
||||||
|
localize=true
|
||||||
|
selected=rangedRangeChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="dialog-skill">
|
<div class="dialog-skill">
|
||||||
{{localize "CTHULHUETERNAL.Label.targetMove"}}
|
{{localize "CTHULHUETERNAL.Label.targetMove"}}
|
||||||
<select name="rangedTargetMoveChoice" class="roll-skill-modifier">
|
<select name="rangedTargetMoveChoice" class="roll-skill-modifier">
|
||||||
{{selectOptions choiceRangedTargetMove localize=true selected=rangedTargetMoveChoice valueAttr="id" labelAttr="label"}}
|
{{selectOptions
|
||||||
|
choiceRangedTargetMove
|
||||||
|
localize=true
|
||||||
|
selected=rangedTargetMoveChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dialog-skill">
|
<div class="dialog-skill">
|
||||||
{{localize "CTHULHUETERNAL.Label.aimingLastRound"}}
|
{{localize "CTHULHUETERNAL.Label.aimingLastRound"}}
|
||||||
<input type="checkbox" name="aimingLastRound">
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="aimingLastRound"
|
||||||
|
name="aimingLastRound"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{{#if weapon.system.hasSight}}
|
{{#if weapon.system.hasSight}}
|
||||||
<div class="dialog-skill">
|
<div class="dialog-skill">
|
||||||
{{localize "CTHULHUETERNAL.Label.aimingWithSight"}}
|
{{localize "CTHULHUETERNAL.Label.aimingWithSight"}}
|
||||||
<input type="checkbox" name="aimingWithSight">
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="aimingWithSight"
|
||||||
|
name="aimingWithSight"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
@@ -61,26 +118,50 @@
|
|||||||
<div class="dialog-skill">
|
<div class="dialog-skill">
|
||||||
{{localize "CTHULHUETERNAL.Label.visibility"}}
|
{{localize "CTHULHUETERNAL.Label.visibility"}}
|
||||||
<select name="visibilityChoice" class="roll-skill-modifier">
|
<select name="visibilityChoice" class="roll-skill-modifier">
|
||||||
{{selectOptions choiceVisibility localize=true selected=visibilityChoice valueAttr="id" labelAttr="label"}}
|
{{selectOptions
|
||||||
|
choiceVisibility
|
||||||
|
localize=true
|
||||||
|
selected=visibilityChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="dialog-skill">
|
<div class="dialog-skill">
|
||||||
{{localize "CTHULHUETERNAL.Label.attackerState"}}
|
{{localize "CTHULHUETERNAL.Label.attackerState"}}
|
||||||
<select name="attackerStateChoice" class="roll-skill-modifier">
|
<select name="attackerStateChoice" class="roll-skill-modifier">
|
||||||
{{selectOptions choiceAttackerState localize=true selected=attackerStateChoice valueAttr="id" labelAttr="label"}}
|
{{selectOptions
|
||||||
|
choiceAttackerState
|
||||||
|
localize=true
|
||||||
|
selected=attackerStateChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="dialog-skill">
|
<div class="dialog-skill">
|
||||||
{{localize "CTHULHUETERNAL.Label.targetSize"}}
|
{{localize "CTHULHUETERNAL.Label.targetSize"}}
|
||||||
<select name="targetSizeChoice" class="roll-skill-modifier">
|
<select name="targetSizeChoice" class="roll-skill-modifier">
|
||||||
{{selectOptions choiceTargetSize localize=true selected=targetSizeChoice valueAttr="id" labelAttr="label"}}
|
{{selectOptions
|
||||||
|
choiceTargetSize
|
||||||
|
localize=true
|
||||||
|
selected=targetSizeChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if weapon.system.hasSelectiveFire}}
|
{{#if weapon.system.hasSelectiveFire}}
|
||||||
<div class="dialog-skill">Selective Fire :
|
<div class="dialog-skill">Selective Fire :
|
||||||
<select name="selectiveFireChoice" class="roll-skill-modifier">
|
<select name="selectiveFireChoice" class="roll-skill-modifier">
|
||||||
{{selectOptions choiceSelectiveFire localize=true selected=selectiveFireChoice valueAttr="id" labelAttr="label"}}
|
{{selectOptions
|
||||||
|
choiceSelectiveFire
|
||||||
|
localize=true
|
||||||
|
selected=selectiveFireChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@@ -88,20 +169,27 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isZeroWP}}
|
{{#if isZeroWP}}
|
||||||
<div class="dialog-skill red-warning">{{localize "CTHULHUETERNAL.Label.ZeroWP"}}</div>
|
<div class="dialog-skill red-warning">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.ZeroWP"
|
||||||
|
}}</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if isLowWP}}
|
{{#if isLowWP}}
|
||||||
<div class="dialog-skill orange-warning">{{localize "CTHULHUETERNAL.Label.LowWP"}} : -20%</div>
|
<div class="dialog-skill orange-warning">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.LowWP"
|
||||||
|
}}
|
||||||
|
: -20%</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isExhausted}}
|
{{#if isExhausted}}
|
||||||
<div class="dialog-skill orange-warning">{{localize "CTHULHUETERNAL.Label.Exhausted"}} : -20%</div>
|
<div class="dialog-skill orange-warning">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.Exhausted"
|
||||||
|
}}
|
||||||
|
: -20%</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
</fieldSet>
|
</fieldSet>
|
||||||
|
|
||||||
|
|
||||||
{{#if hasModifier}}
|
{{#if hasModifier}}
|
||||||
<fieldSet class="dialog-modifier">
|
<fieldSet class="dialog-modifier">
|
||||||
<legend>{{localize "CTHULHUETERNAL.Label.modifier"}}</legend>
|
<legend>{{localize "CTHULHUETERNAL.Label.modifier"}}</legend>
|
||||||
@@ -114,7 +202,10 @@
|
|||||||
{{#if hasMultiplier}}
|
{{#if hasMultiplier}}
|
||||||
<fieldSet class="dialog-modifier">
|
<fieldSet class="dialog-modifier">
|
||||||
<legend>{{localize "CTHULHUETERNAL.Label.multiplier"}}</legend>
|
<legend>{{localize "CTHULHUETERNAL.Label.multiplier"}}</legend>
|
||||||
<select name="multiplier" class="roll-skill-modifier roll-skill-multiplier">
|
<select
|
||||||
|
name="multiplier"
|
||||||
|
class="roll-skill-modifier roll-skill-multiplier"
|
||||||
|
>
|
||||||
{{selectOptions choiceMultiplier selected=multiplier}}
|
{{selectOptions choiceMultiplier selected=multiplier}}
|
||||||
</select>
|
</select>
|
||||||
</fieldSet>
|
</fieldSet>
|
||||||
|
|||||||
Reference in New Issue
Block a user