Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 709e69fac8 | |||
| e26db56585 | |||
| bb6a6248f2 | |||
| 7dc2492c96 | |||
| 2c25820152 | |||
| 6ad8226265 | |||
| 68a0d03740 | |||
| 8d9cc1045c | |||
| 4af277d8a2 | |||
| bc9f397755 | |||
| 264a5c7a4c | |||
| 4edbc9b618 | |||
| 47c2aea941 | |||
| cdefecdeba | |||
| 61b8da8ccf |
@@ -0,0 +1 @@
|
|||||||
|
packs/** filter=lfs diff=lfs merge=lfs -text
|
||||||
@@ -60,4 +60,4 @@ jobs:
|
|||||||
manifest: 'https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal/releases/download/latest/system.json'
|
manifest: 'https://www.uberwald.me/gitea/public/fvtt-cthulhu-eternal/releases/download/latest/system.json'
|
||||||
notes: 'https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-cthulhu-eternal.zip'
|
notes: 'https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-cthulhu-eternal.zip'
|
||||||
compatibility-minimum: '13'
|
compatibility-minimum: '13'
|
||||||
compatibility-verified: '13'
|
compatibility-verified: '14'
|
||||||
@@ -5,4 +5,6 @@ styles/*.css
|
|||||||
|
|
||||||
# Node Modules
|
# Node Modules
|
||||||
node_modules/
|
node_modules/
|
||||||
|
.github/
|
||||||
|
.history/
|
||||||
|
|
||||||
|
|||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"CTHULHUETERNAL"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
"entries": {
|
"entries": {
|
||||||
"Pilot (Type)": {
|
"Pilot (Type)": {
|
||||||
"name": "Pilotage (Type)",
|
"name": "Pilotage (Type)",
|
||||||
"description": "<pPiloter, naviguer et diriger des véhicules nautiques ou aériens. Utilisez cette compétence pour assurer la sécurité d'un navire en cas de danger, par exemple lors d'une tempête ou d'une poursuite dangereuse. Chaque type de véhicule requiert une compétence distincte : Avion, Drone, Hélicoptère, Dirigeable, Petite embarcation, Navire, etc.</p>"
|
"description": "<p>Piloter, naviguer et diriger des véhicules nautiques ou aériens. Utilisez cette compétence pour assurer la sécurité d'un navire en cas de danger, par exemple lors d'une tempête ou d'une poursuite dangereuse. Chaque type de véhicule requiert une compétence distincte : Avion, Drone, Hélicoptère, Dirigeable, Petite embarcation, Navire, etc.</p>"
|
||||||
},
|
},
|
||||||
"Anthropology": {
|
"Anthropology": {
|
||||||
"name": "Anthropologie",
|
"name": "Anthropologie",
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+331
-81
@@ -183,6 +183,25 @@ i.fvtt-cthulhu-eternal {
|
|||||||
color: var(--color-critical-failure);
|
color: var(--color-critical-failure);
|
||||||
font-family: var(--font-title);
|
font-family: var(--font-title);
|
||||||
}
|
}
|
||||||
|
.chat-san-request ul .san-type-buttons,
|
||||||
|
.chat-lethal-damage ul .san-type-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.chat-san-request ul .san-type-buttons button,
|
||||||
|
.chat-lethal-damage ul .san-type-buttons button {
|
||||||
|
margin: 0 2px;
|
||||||
|
font-family: var(--font-primary);
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.9);
|
||||||
|
border: none;
|
||||||
|
padding: 2px 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
min-width: 6rem;
|
||||||
|
max-width: 6rem;
|
||||||
|
}
|
||||||
.chat-san-request ul .san-loose-buttons,
|
.chat-san-request ul .san-loose-buttons,
|
||||||
.chat-lethal-damage ul .san-loose-buttons {
|
.chat-lethal-damage ul .san-loose-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -213,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);
|
||||||
@@ -275,9 +320,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
@@ -400,7 +443,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp input {
|
.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp input {
|
||||||
flex: none;
|
flex: none;
|
||||||
width: 2rem;
|
width: 4rem;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp .hp-separator {
|
.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp .hp-separator {
|
||||||
@@ -634,6 +677,12 @@ i.fvtt-cthulhu-eternal {
|
|||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
.fvtt-cthulhu-eternal .empty-state {
|
||||||
|
color: var(--color-text-light-6);
|
||||||
|
font-style: italic;
|
||||||
|
padding: 0.5rem 0.25rem;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
.fvtt-cthulhu-eternal .tab.protagonist-skills .main-div .skills .skill {
|
.fvtt-cthulhu-eternal .tab.protagonist-skills .main-div .skills .skill {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -806,7 +855,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons {
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(1, 1fr);
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon {
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon {
|
||||||
@@ -826,10 +875,24 @@ i.fvtt-cthulhu-eternal {
|
|||||||
min-width: 1.8rem;
|
min-width: 1.8rem;
|
||||||
max-width: 1.8rem;
|
max-width: 1.8rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .damage {
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .range {
|
||||||
min-width: 6rem;
|
min-width: 6rem;
|
||||||
max-width: 6rem;
|
max-width: 6rem;
|
||||||
}
|
}
|
||||||
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .ammo {
|
||||||
|
min-width: 4rem;
|
||||||
|
max-width: 4rem;
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .lethality {
|
||||||
|
display: flex;
|
||||||
|
min-width: 3.2rem;
|
||||||
|
max-width: 3.2rem;
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .damage {
|
||||||
|
display: flex;
|
||||||
|
min-width: 12rem;
|
||||||
|
max-width: 12rem;
|
||||||
|
}
|
||||||
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .name {
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .weapons .weapon .name {
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
max-width: 10rem;
|
max-width: 10rem;
|
||||||
@@ -861,6 +924,20 @@ i.fvtt-cthulhu-eternal {
|
|||||||
min-width: 1.8rem;
|
min-width: 1.8rem;
|
||||||
max-width: 1.8rem;
|
max-width: 1.8rem;
|
||||||
}
|
}
|
||||||
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .armors .armor .equipped-toggle {
|
||||||
|
font-size: 1rem;
|
||||||
|
min-width: 1.4rem;
|
||||||
|
max-width: 1.4rem;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #888;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .armors .armor .equipped-toggle.active {
|
||||||
|
color: #4caf50;
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .armors .armor .equipped-toggle:hover {
|
||||||
|
color: #2196f3;
|
||||||
|
}
|
||||||
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .armors .armor .protection {
|
.fvtt-cthulhu-eternal .tab.protagonist-equipment .main-div .armors .armor .protection {
|
||||||
min-width: 5rem;
|
min-width: 5rem;
|
||||||
max-width: 5rem;
|
max-width: 5rem;
|
||||||
@@ -977,9 +1054,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
@@ -1235,9 +1310,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
@@ -1297,6 +1370,25 @@ i.fvtt-cthulhu-eternal {
|
|||||||
.fvtt-cthulhu-eternal .sheet-tabs {
|
.fvtt-cthulhu-eternal .sheet-tabs {
|
||||||
background-color: var(--color-light-1);
|
background-color: var(--color-light-1);
|
||||||
}
|
}
|
||||||
|
.fvtt-cthulhu-eternal .creature-hp {
|
||||||
|
gap: 2px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .creature-hp .form-fields input {
|
||||||
|
flex: none;
|
||||||
|
min-width: 4rem;
|
||||||
|
max-width: 4rem;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .creature-hp .damage-bonus {
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.8);
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .creature-hp .hp-separator {
|
||||||
|
font-size: calc(var(--font-size-standard) * 1.2);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
.fvtt-cthulhu-eternal .creature-main {
|
.fvtt-cthulhu-eternal .creature-main {
|
||||||
background-color: var(--color-light-1);
|
background-color: var(--color-light-1);
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1322,24 +1414,6 @@ i.fvtt-cthulhu-eternal {
|
|||||||
width: auto;
|
width: auto;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-hp {
|
|
||||||
gap: 2px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-hp input {
|
|
||||||
flex: none;
|
|
||||||
width: 2rem;
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-hp .damage-bonus {
|
|
||||||
font-size: calc(var(--font-size-standard) * 0.8);
|
|
||||||
}
|
|
||||||
.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-hp .hp-separator {
|
|
||||||
font-size: calc(var(--font-size-standard) * 1.2);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-dv .form-fields,
|
.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-dv .form-fields,
|
||||||
.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-dmax .form-fields {
|
.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-dmax .form-fields {
|
||||||
flex: none;
|
flex: none;
|
||||||
@@ -1894,9 +1968,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .skill-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .skill-content .sheet-tabs a {
|
||||||
@@ -1989,9 +2061,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .injury-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .injury-content .sheet-tabs a {
|
||||||
@@ -2084,9 +2154,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .weapon-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .weapon-content .sheet-tabs a {
|
||||||
@@ -2164,6 +2232,24 @@ i.fvtt-cthulhu-eternal {
|
|||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
background-color: var(--color-light-1);
|
background-color: var(--color-light-1);
|
||||||
}
|
}
|
||||||
|
.fvtt-cthulhu-eternal .weapon-content fieldset input {
|
||||||
|
max-width: 5rem;
|
||||||
|
min-width: 5rem;
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .weapon-content fieldset select {
|
||||||
|
max-width: 14rem;
|
||||||
|
min-width: 14rem;
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .weapon-content fieldset input[type="checkbox"] {
|
||||||
|
max-width: 1.5rem;
|
||||||
|
min-width: 1.5rem;
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .weapon-content fieldset .flexrow > *:not(:first-child) {
|
||||||
|
margin-left: 1rem;
|
||||||
|
}
|
||||||
|
.fvtt-cthulhu-eternal .weapon-content fieldset .damage-distance {
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
.fvtt-cthulhu-eternal .weapon-content label {
|
.fvtt-cthulhu-eternal .weapon-content label {
|
||||||
flex: 10%;
|
flex: 10%;
|
||||||
}
|
}
|
||||||
@@ -2171,9 +2257,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .armor-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .armor-content .sheet-tabs a {
|
||||||
@@ -2258,9 +2342,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .motivation-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .motivation-content .sheet-tabs a {
|
||||||
@@ -2345,9 +2427,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .mentaldisorder-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .mentaldisorder-content .sheet-tabs a {
|
||||||
@@ -2432,9 +2512,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .bond-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .bond-content .sheet-tabs a {
|
||||||
@@ -2535,9 +2613,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .gear-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .gear-content .sheet-tabs a {
|
||||||
@@ -2622,9 +2698,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .arcane-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .arcane-content .sheet-tabs a {
|
||||||
@@ -2709,9 +2783,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .archetype-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .archetype-content .sheet-tabs a {
|
||||||
@@ -2796,9 +2868,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .ritual-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .ritual-content .sheet-tabs a {
|
||||||
@@ -2891,9 +2961,7 @@ i.fvtt-cthulhu-eternal {
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
}
|
}
|
||||||
.fvtt-cthulhu-eternal .tome-content .sheet-tabs a {
|
.fvtt-cthulhu-eternal .tome-content .sheet-tabs a {
|
||||||
@@ -3019,6 +3087,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;
|
||||||
}
|
}
|
||||||
@@ -3062,21 +3133,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);
|
||||||
@@ -3111,3 +3167,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;
|
||||||
|
}
|
||||||
|
|||||||
+69
-3
@@ -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,22 +170,65 @@ 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"
|
||||||
})
|
})
|
||||||
|
$(html).find(".worn-weapon-check").each((i, btn) => {
|
||||||
|
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)
|
||||||
})
|
})
|
||||||
$(html).find(".damage-roll").click((event) => {
|
$(html).find(".damage-roll").click((event) => {
|
||||||
CthulhuEternalUtils.damageRoll(message)
|
let formula = $(event.currentTarget).data("roll-value")
|
||||||
|
CthulhuEternalUtils.damageRoll(message, formula)
|
||||||
})
|
})
|
||||||
$(html).find(".healing-roll").click((event) => {
|
$(html).find(".healing-roll").click((event) => {
|
||||||
CthulhuEternalUtils.healingRoll(message)
|
CthulhuEternalUtils.healingRoll(message)
|
||||||
})
|
})
|
||||||
|
$(html).find(".worn-weapon-check").click((event) => {
|
||||||
|
CthulhuEternalUtils.wornWeaponCheck(message)
|
||||||
|
})
|
||||||
$(html).find(".san-loose").click((event) => {
|
$(html).find(".san-loose").click((event) => {
|
||||||
CthulhuEternalUtils.applySANLoss(message, event)
|
CthulhuEternalUtils.applySANLoss(message, event)
|
||||||
})
|
})
|
||||||
$(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()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+130
-7
@@ -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",
|
||||||
@@ -212,6 +231,7 @@
|
|||||||
"UnarmedCombat": "Unarmed Combat",
|
"UnarmedCombat": "Unarmed Combat",
|
||||||
"RangedWeapons": "Ranged Weapons",
|
"RangedWeapons": "Ranged Weapons",
|
||||||
"FirearmsBeams": "Firearms / Beam Weapons",
|
"FirearmsBeams": "Firearms / Beam Weapons",
|
||||||
|
"MilitaryTrainingExplosive": "Military Training (Explosives)",
|
||||||
"FIELDS": {
|
"FIELDS": {
|
||||||
"isHealing": {
|
"isHealing": {
|
||||||
"label": "Healing skill"
|
"label": "Healing skill"
|
||||||
@@ -268,7 +288,8 @@
|
|||||||
"rangedprimitive": "Ranged Primitive",
|
"rangedprimitive": "Ranged Primitive",
|
||||||
"rangedthrown": "Ranged Thrown",
|
"rangedthrown": "Ranged Thrown",
|
||||||
"rangedfirearm": "Ranged Firearm",
|
"rangedfirearm": "Ranged Firearm",
|
||||||
"unarmed": "Unarmed"
|
"unarmed": "Unarmed",
|
||||||
|
"rangedexplosive": "Explosive"
|
||||||
},
|
},
|
||||||
"WeaponSubtype": {
|
"WeaponSubtype": {
|
||||||
"basicfirearm": "Basic Firearm",
|
"basicfirearm": "Basic Firearm",
|
||||||
@@ -283,7 +304,41 @@
|
|||||||
"shortspray": "Short Spray",
|
"shortspray": "Short Spray",
|
||||||
"longspray": "Long Spray"
|
"longspray": "Long Spray"
|
||||||
},
|
},
|
||||||
|
"Target": {
|
||||||
|
"Normal": "Normal",
|
||||||
|
"Stationary": "Stationary",
|
||||||
|
"MovingRange": "Moving or on the ground",
|
||||||
|
"MovingFast": "Moving Fast (ie running)",
|
||||||
|
"MovingVeryFast": "Moving Very Fast",
|
||||||
|
"HalfCovered": "Half Covered",
|
||||||
|
"Covered": "Full Covered"
|
||||||
|
},
|
||||||
|
"Range": {
|
||||||
|
"PointBlank": "Point Blank",
|
||||||
|
"Normal": "Normal",
|
||||||
|
"Range2x": "Up to Range x2",
|
||||||
|
"Range5x": "Up to Range x5"
|
||||||
|
},
|
||||||
|
"Visibility": {
|
||||||
|
"Clear": "Clear",
|
||||||
|
"Obscured": "Obscured",
|
||||||
|
"Darkness": "Darkness"
|
||||||
|
},
|
||||||
|
"Attacker": {
|
||||||
|
"Normal": "Normal",
|
||||||
|
"Irritated": "Irritated/Annoyed",
|
||||||
|
"Corrosive": "Deeply Annoyed"
|
||||||
|
},
|
||||||
"FIELDS": {
|
"FIELDS": {
|
||||||
|
"hasDamageDistance": {
|
||||||
|
"label": "Is damage distance based?"
|
||||||
|
},
|
||||||
|
"hasSight": {
|
||||||
|
"label": "Has sight"
|
||||||
|
},
|
||||||
|
"isStunning": {
|
||||||
|
"label": "Is Stunning"
|
||||||
|
},
|
||||||
"hasDirectSkill": {
|
"hasDirectSkill": {
|
||||||
"label": "Has direct skill"
|
"label": "Has direct skill"
|
||||||
},
|
},
|
||||||
@@ -516,25 +571,47 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Label": {
|
"Label": {
|
||||||
|
"JunkWeapon": "This weapon is in 'Junk' state, -20% applied. Critical failure on a roll of 96-100",
|
||||||
|
"WornWeapon": "This weapon is 'Worn', a Luck roll will be performed.",
|
||||||
|
"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",
|
||||||
"Unnatural": "Unnatural",
|
"Unnatural": "Unnatural",
|
||||||
"sanLossViolence": "You suffered a SAN loss due to violence : violence progress path has evolved.",
|
"sanLossViolence": "You suffered a SAN loss due to violence : violence progress path has evolved.",
|
||||||
"sanLossHelplessness": "You suffered a SAN loss due to helplessness : helplessness progress path has evolved.",
|
"sanLossHelplessness": "You suffered a SAN loss due to helplessness : helplessness progress path has evolved.",
|
||||||
|
"SANLossUnnatural": "You suffered a SAN loss due to unnatural : you may gain an Unnatural skill, check with the GM.",
|
||||||
|
"SANLossNone": "You suffered a SAN loss, but no special consequences apply.",
|
||||||
"adaptedToViolence": "You are now : Adapted to Violence.",
|
"adaptedToViolence": "You are now : Adapted to Violence.",
|
||||||
"adaptedToViolenceShort": "Adapted to Violence",
|
"adaptedToViolenceShort": "Adapted to Violence",
|
||||||
"adaptedToHelplessness": "You are now : Adapted to Helplessness.",
|
"adaptedToHelplessness": "You are now : Adapted to Helplessness.",
|
||||||
"adaptedToHelplessnessShort": "Adapted to Helplessness",
|
"adaptedToHelplessnessShort": "Adapted to Helplessness",
|
||||||
"SANTest": "You just rolled a SAN test : please select the SAN loss with the buttons below.",
|
"SANTestSuccess": "You just rolled a SAN test with success, but you may still loose SAN points. Select the value of SAN loss with the buttons below.",
|
||||||
|
"SANTestFailure": "You just rolled a SAN test with failure, you loose SAN points. Select the value of SAN loss with the buttons below.",
|
||||||
"breakingPointReached": "Your SAN has reached your Breaking Point : you suffer a disorder (to be discussed with the GM). Reset the BP to its new value.",
|
"breakingPointReached": "Your SAN has reached your Breaking Point : you suffer a disorder (to be discussed with the GM). Reset the BP to its new value.",
|
||||||
"rollNudge": "Roll Nudge",
|
"rollNudge": "Roll Nudge",
|
||||||
"rollDamage": "Roll Damage",
|
"rollDamage": "Roll Damage",
|
||||||
"rollHealing": "Roll Healing",
|
"rollHealing": "Roll Healing",
|
||||||
|
"wornWeaponCheck": "Check Weapon Condition",
|
||||||
|
"wornWeaponCheckTitle": "Worn Weapon Condition Check",
|
||||||
|
"wornWeaponCheckSuccess": "{weapon}: Luck roll succeeded ({roll}/50) - Weapon remains worn.",
|
||||||
|
"wornWeaponCheckFailure": "{weapon}: Luck roll failed ({roll}/50) - Weapon became junk!",
|
||||||
"result": "Result",
|
"result": "Result",
|
||||||
"damageMessage": "Damage to apply",
|
"damageMessage": "Damage to apply",
|
||||||
"lethalityRoll": "Lethality Roll",
|
"lethalityRoll": "Lethality Roll",
|
||||||
@@ -546,6 +623,7 @@
|
|||||||
"ZeroWP": "Zero WP : Automatic failure (ie 0%)",
|
"ZeroWP": "Zero WP : Automatic failure (ie 0%)",
|
||||||
"LowWP": "Low WP",
|
"LowWP": "Low WP",
|
||||||
"Exhausted": "Exhausted",
|
"Exhausted": "Exhausted",
|
||||||
|
"wornWeaponWarning": "Worn weapon: Don't forget to make the luck roll after the attack!",
|
||||||
"creature": "Creature",
|
"creature": "Creature",
|
||||||
"Rituals": "Rituals",
|
"Rituals": "Rituals",
|
||||||
"Tomes": "Tomes",
|
"Tomes": "Tomes",
|
||||||
@@ -613,6 +691,11 @@
|
|||||||
"biography": "Biography",
|
"biography": "Biography",
|
||||||
"notes": "Notes",
|
"notes": "Notes",
|
||||||
"weapons": "Weapons",
|
"weapons": "Weapons",
|
||||||
|
"melee": "Melee",
|
||||||
|
"Lethality": "Lethality",
|
||||||
|
"baseRange": "Base Range",
|
||||||
|
"Ammo": "Ammo",
|
||||||
|
"armorPiercing": "Armor Piercing",
|
||||||
"HP": "HP",
|
"HP": "HP",
|
||||||
"SAN": "SAN",
|
"SAN": "SAN",
|
||||||
"current": "Current",
|
"current": "Current",
|
||||||
@@ -651,6 +734,8 @@
|
|||||||
"newMentalDisorder": "New Mental Disorder",
|
"newMentalDisorder": "New Mental Disorder",
|
||||||
"newWeapon": "New Weapon",
|
"newWeapon": "New Weapon",
|
||||||
"newArmor": "New Armor",
|
"newArmor": "New Armor",
|
||||||
|
"equipped": "Equipped (click to unequip)",
|
||||||
|
"unequipped": "Not equipped (click to equip)",
|
||||||
"newInjury": "New Injury",
|
"newInjury": "New Injury",
|
||||||
"newGear": "New Gear",
|
"newGear": "New Gear",
|
||||||
"newArcane": "New Arcane",
|
"newArcane": "New Arcane",
|
||||||
@@ -667,9 +752,17 @@
|
|||||||
"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.",
|
||||||
|
"stunnedWarning": "The Protagonist is stunned. He cannot act until he succeeds at a CON × 5 test.",
|
||||||
|
"deadWarning": "The Protagonist is dying. He will die if not treated within {con} minutes.",
|
||||||
|
"noSkills": "No skills. Add skills to this character.",
|
||||||
|
"noWeapons": "No weapons. Add weapons in edit mode.",
|
||||||
|
"noArmors": "No armor. Add armor in edit mode.",
|
||||||
|
"noGears": "No gear. Add gear in edit mode.",
|
||||||
|
"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",
|
||||||
@@ -678,7 +771,28 @@
|
|||||||
"killRadiusInfo": "All targets within the kill radius suffer the damage",
|
"killRadiusInfo": "All targets within the kill radius suffer the damage",
|
||||||
"ammoUsed": "Ammo used",
|
"ammoUsed": "Ammo used",
|
||||||
"lethalityLethal": "Lethal !!",
|
"lethalityLethal": "Lethal !!",
|
||||||
"lethalityNotLethal": "Non-Lethal"
|
"lethalityNotLethal": "Non-Lethal",
|
||||||
|
"WPSpent": "WP Spent",
|
||||||
|
"targetMove": "Target Move",
|
||||||
|
"attackerState": "Attacker State",
|
||||||
|
"targetSize": "Target Size",
|
||||||
|
"visibility": "Visibility",
|
||||||
|
"rangedRange": "Range",
|
||||||
|
"aimingLastRound": "Aiming Last Round (+20)",
|
||||||
|
"aimingWithSight": "Aiming with Sight (+20)",
|
||||||
|
"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."
|
||||||
@@ -699,20 +813,29 @@
|
|||||||
"Tooltip": {
|
"Tooltip": {
|
||||||
"sanBP": ">5 SAN lost in one roll, temporary insanity. If SAN less reaches BP = a Disorder unconscious Breaking and AND reset BP.",
|
"sanBP": ">5 SAN lost in one roll, temporary insanity. If SAN less reaches BP = a Disorder unconscious Breaking and AND reset BP.",
|
||||||
"setBP": "Set the current Breaking Point based on the current SAN value",
|
"setBP": "Set the current Breaking Point based on the current SAN value",
|
||||||
"addBond": "Add a new Bond"
|
"addBond": "Add a new Bond",
|
||||||
|
"rollDamage": "Roll Damage"
|
||||||
},
|
},
|
||||||
"Chat": {
|
"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",
|
||||||
"WrongEra": "The era of the item does not match the ear of the system",
|
"WrongEra": "The era of the item does not match the ear of the system",
|
||||||
"NoSelectiveFireChoices": "Not enough ammo fo Selective Fire choices for this weapon.",
|
"NoSelectiveFireChoices": "Not enough ammo fo Selective Fire choices for this weapon.",
|
||||||
"NoAmmo": "No more ammo for this weapon. ",
|
"NoAmmo": "No more ammo for this weapon. ",
|
||||||
|
"WeaponBecameJunk": "Weapon {weapon} became junk!",
|
||||||
|
"noWeaponFound": "No weapon found.",
|
||||||
"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."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+112
-11
@@ -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",
|
||||||
@@ -224,6 +225,7 @@
|
|||||||
"UnarmedCombat": "Combat à mains nues",
|
"UnarmedCombat": "Combat à mains nues",
|
||||||
"RangedWeapons": "Armes de tir",
|
"RangedWeapons": "Armes de tir",
|
||||||
"FirearmsBeams": "Armes à feu / à rayons",
|
"FirearmsBeams": "Armes à feu / à rayons",
|
||||||
|
"MilitaryTrainingExplosive": "Entraînement militaire (Explosifs)",
|
||||||
"FIELDS": {
|
"FIELDS": {
|
||||||
"isHealing": {
|
"isHealing": {
|
||||||
"label": "Compétence de soin"
|
"label": "Compétence de soin"
|
||||||
@@ -280,7 +282,8 @@
|
|||||||
"rangedprimitive": "A distance - Primitive",
|
"rangedprimitive": "A distance - Primitive",
|
||||||
"rangedthrown": "A distance - Lancer",
|
"rangedthrown": "A distance - Lancer",
|
||||||
"rangedfirearm": "A distance - Arme à feu",
|
"rangedfirearm": "A distance - Arme à feu",
|
||||||
"unarmed": "Non armé"
|
"unarmed": "Non armé",
|
||||||
|
"rangedexplosive": "Explosif"
|
||||||
},
|
},
|
||||||
"WeaponSubtype": {
|
"WeaponSubtype": {
|
||||||
"basicfirearm": "Arme à feu de base",
|
"basicfirearm": "Arme à feu de base",
|
||||||
@@ -295,7 +298,41 @@
|
|||||||
"shortspray": "Barrage court",
|
"shortspray": "Barrage court",
|
||||||
"longspray": "Barrage long"
|
"longspray": "Barrage long"
|
||||||
},
|
},
|
||||||
|
"Target": {
|
||||||
|
"Normal": "Normal",
|
||||||
|
"Stationary": "Immobile (+20)",
|
||||||
|
"MovingRange": "En mouvement ou au sol (-20)",
|
||||||
|
"MovingFast": "En mouvement rapide (ie course) (-20)",
|
||||||
|
"MovingVeryFast": "En mouvement très rapide (ie véhicule) (-40)",
|
||||||
|
"HalfCovered": "A moitié couvert (-20)",
|
||||||
|
"Covered": "A Couvert (-40)"
|
||||||
|
},
|
||||||
|
"Range": {
|
||||||
|
"PointBlank": "Bout portant (+20)",
|
||||||
|
"Normal": "Normal",
|
||||||
|
"Range2x": "de portée à portée x2 (-20)",
|
||||||
|
"Range5x": "de portéex2 à portée x5 (-40)"
|
||||||
|
},
|
||||||
|
"Visibility": {
|
||||||
|
"Clear": "Normale",
|
||||||
|
"Obscured": "Obscurci (-20)",
|
||||||
|
"Darkness": "Obscurité (-40)"
|
||||||
|
},
|
||||||
|
"Attacker": {
|
||||||
|
"Normal": "Normal",
|
||||||
|
"Irritated": "Irrité/Gêné (-20)",
|
||||||
|
"Corrosive": "Fortement gêné (-40)"
|
||||||
|
},
|
||||||
"FIELDS": {
|
"FIELDS": {
|
||||||
|
"hasDamageDistance": {
|
||||||
|
"label": "Dégâts basés sur la distance ?"
|
||||||
|
},
|
||||||
|
"hasSight": {
|
||||||
|
"label": "Lunette de visée"
|
||||||
|
},
|
||||||
|
"isStunning": {
|
||||||
|
"label": "Etourdissante"
|
||||||
|
},
|
||||||
"ammo": {
|
"ammo": {
|
||||||
"label": "Munitions",
|
"label": "Munitions",
|
||||||
"value": {
|
"value": {
|
||||||
@@ -528,20 +565,36 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Label": {
|
"Label": {
|
||||||
|
"JunkWeapon": "Cette arme est 'Défectueuse'', -20% appliqué. Échec critique sur un jet de 96-100",
|
||||||
|
"WornWeapon": "Cette arme est 'Usée', un jet de Chance sera effectué.",
|
||||||
|
"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é.",
|
||||||
"sanLoss": "Perte de SAN",
|
"sanLoss": "Vous venez de perdre des points de SAN",
|
||||||
"noSanLoss": "Aucune perte de SAN",
|
"noSanLoss": "Aucune perte de SAN",
|
||||||
"sanLossInfo": "Sélectionnez la perte de SAN à l'aide des boutons ci-dessous.",
|
"sanLossInfo": "Sélectionnez la perte de SAN à l'aide des boutons ci-dessous.",
|
||||||
"selectSANType": "Sélectionnez le type de perte de SAN à l'aide des boutons ci-dessous.",
|
"selectSANType": "Sélectionnez maintenant le type SAN perdue à l'aide des boutons ci-dessous.",
|
||||||
"sanLossViolence": "Vous avez subi une perte de SAN due à la violence : le chemin de progression de la violence a évolué.",
|
"sanLossViolence": "Vous avez subi une perte de SAN due à la violence : le chemin de progression de la violence a évolué.",
|
||||||
"sanLossHelplessness": "Vous avez subi une perte de SAN due à l'impuissance : le chemin de progression de l'impuissance a évolué.",
|
"sanLossHelplessness": "Vous avez subi une perte de SAN due à l'impuissance : le chemin de progression de l'impuissance a évolué.",
|
||||||
|
"SANLossUnnatural": "Vous avez subi une perte de SAN due à l'inconcevable : vous pouvez peut-être faire progresser la compétence Inconcevable, vérifiez avec le MJ.",
|
||||||
|
"SANLossNone": "Vous avez subi une perte de SAN, mais aucune conséquence spéciale n'est appliquée.",
|
||||||
"adaptedToViolence": "Vous êtes maintenant : Habitué à la violence",
|
"adaptedToViolence": "Vous êtes maintenant : Habitué à la violence",
|
||||||
"adaptedToViolenceShort": "Habitué à la violence",
|
"adaptedToViolenceShort": "Habitué à la violence",
|
||||||
"adaptedToHelplessness": "Vous êtes maintenant : Habitué à l'impuissance",
|
"adaptedToHelplessness": "Vous êtes maintenant : Habitué à l'impuissance",
|
||||||
"adaptedToHelplessnessShort": "Habitué à l'impuissance",
|
"adaptedToHelplessnessShort": "Habitué à l'impuissance",
|
||||||
"SANTest": "Vous venez de faire un jet de SAN : selectionnez la perte de SAN à l'aide des boutons ci-dessous.",
|
"SANTestSuccess": "Vous venez de réussir votre jet de SAN, mais vous pouvez toujours perdre des points de SAN. Sélectionnez la valeur à l'aide des boutons ci-dessous.",
|
||||||
|
"SANTestFailure": "Vous venez d'échouer votre test de SAN, vous perdez des points de SAN. Sélectionnez la valeur à l'aide des boutons ci-dessous.",
|
||||||
"breakingPointReached": "Vous avez atteint votre Point de Rupture (PR) : vous souffrez d'un trouble mental. Vous devez re-initialiser votre PR à l'aide du bouton disponible dans la section SAN de la fiche de PJ.",
|
"breakingPointReached": "Vous avez atteint votre Point de Rupture (PR) : vous souffrez d'un trouble mental. Vous devez re-initialiser votre PR à l'aide du bouton disponible dans la section SAN de la fiche de PJ.",
|
||||||
"Violence" : "Violence",
|
"Violence" : "Violence",
|
||||||
"Helplessness": "Impuissance",
|
"Helplessness": "Impuissance",
|
||||||
@@ -549,6 +602,10 @@
|
|||||||
"rollNudge": "Modifier le jet",
|
"rollNudge": "Modifier le jet",
|
||||||
"rollDamage": "Jet de dégâts",
|
"rollDamage": "Jet de dégâts",
|
||||||
"rollHealing": "Jet de soin",
|
"rollHealing": "Jet de soin",
|
||||||
|
"wornWeaponCheck": "Vérifier l'état de l'arme",
|
||||||
|
"wornWeaponCheckTitle": "Vérification d'état d'arme usée",
|
||||||
|
"wornWeaponCheckSuccess": "{weapon} : Jet de chance réussi ({roll}/50) - L'arme reste usée.",
|
||||||
|
"wornWeaponCheckFailure": "{weapon} : Jet de chance échoué ({roll}/50) - L'arme devient défectueuse !",
|
||||||
"result": "Resultat",
|
"result": "Resultat",
|
||||||
"damageMessage": "Dégâts à appliquer",
|
"damageMessage": "Dégâts à appliquer",
|
||||||
"lethalityRoll": "Jet de Létalité",
|
"lethalityRoll": "Jet de Létalité",
|
||||||
@@ -559,15 +616,14 @@
|
|||||||
"Weapon": "Arme",
|
"Weapon": "Arme",
|
||||||
"ZeroWP": "PVO à 0 : Echec automatique (ie 0%)",
|
"ZeroWP": "PVO à 0 : Echec automatique (ie 0%)",
|
||||||
"LowWP": "PVO faibles",
|
"LowWP": "PVO faibles",
|
||||||
"Exhausted": "Epuisé",
|
"Exhausted": "Epuisé", "wornWeaponWarning": "Arme usée : N'oubliez pas de faire le jet de chance après l'attaque !", "creature": "Créature",
|
||||||
"creature": "Créature",
|
|
||||||
"Rituals": "Rituels",
|
"Rituals": "Rituels",
|
||||||
"Tomes": "Ouvrages",
|
"Tomes": "Ouvrages",
|
||||||
"otherBenefits": "Autres avantages",
|
"otherBenefits": "Autres avantages",
|
||||||
"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",
|
||||||
@@ -627,6 +683,11 @@
|
|||||||
"biography": "Biographie",
|
"biography": "Biographie",
|
||||||
"notes": "Notes",
|
"notes": "Notes",
|
||||||
"weapons": "Armes",
|
"weapons": "Armes",
|
||||||
|
"melee": "Mêlée",
|
||||||
|
"Lethality": "Létalité",
|
||||||
|
"baseRange": "Portée de base",
|
||||||
|
"Ammo": "Munitions",
|
||||||
|
"armorPiercing": "Pénétration d'armure",
|
||||||
"HP": "PV",
|
"HP": "PV",
|
||||||
"SAN": "SAN",
|
"SAN": "SAN",
|
||||||
"current": "Actuel",
|
"current": "Actuel",
|
||||||
@@ -665,6 +726,8 @@
|
|||||||
"newMentalDisorder": "Nouveau Trouble mental",
|
"newMentalDisorder": "Nouveau Trouble mental",
|
||||||
"newWeapon": "Nouvelle Arme",
|
"newWeapon": "Nouvelle Arme",
|
||||||
"newArmor": "Nouvelle Armure",
|
"newArmor": "Nouvelle Armure",
|
||||||
|
"equipped": "Équipée (cliquer pour déséquiper)",
|
||||||
|
"unequipped": "Non équipée (cliquer pour équiper)",
|
||||||
"newInjury": "Nouvelle Blessure",
|
"newInjury": "Nouvelle Blessure",
|
||||||
"newGear": "Nouvel Equipement",
|
"newGear": "Nouvel Equipement",
|
||||||
"newArcane": "Nouvel Arcane",
|
"newArcane": "Nouvel Arcane",
|
||||||
@@ -684,7 +747,14 @@
|
|||||||
"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",
|
"noSkills": "Aucune compétence. Ajoutez des compétences à ce personnage.",
|
||||||
|
"noWeapons": "Aucune arme. Ajoutez des armes en mode édition.",
|
||||||
|
"noArmors": "Aucune armure. Ajoutez une armure en mode édition.",
|
||||||
|
"noGears": "Aucun équipement. Ajoutez de l'équipement en mode édition.",
|
||||||
|
"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",
|
||||||
@@ -692,7 +762,29 @@
|
|||||||
"killRadiusInfo": "Si la cible est dans le rayon de mortalité, elle subit les dommages.",
|
"killRadiusInfo": "Si la cible est dans le rayon de mortalité, elle subit les dommages.",
|
||||||
"ammoUsed": "Munitions utilisées",
|
"ammoUsed": "Munitions utilisées",
|
||||||
"lethalityLethal": "Létal !!",
|
"lethalityLethal": "Létal !!",
|
||||||
"lethalityNotLethal": "Non létal"
|
"lethalityNotLethal": "Non létal",
|
||||||
|
"WPSpent": "PVO dépensés",
|
||||||
|
"targetMove": "Mouvement de la cible",
|
||||||
|
"attackerState": "Etat de l'attaquant",
|
||||||
|
"targetSize": "Taille de la cible",
|
||||||
|
"visibility": "Visibilité",
|
||||||
|
"rangedRange": "Portée",
|
||||||
|
"aimingLastRound": "Visée lors du dernier round (+20)",
|
||||||
|
"aimingWithSight": "Visée avec lunette (+20)",
|
||||||
|
"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é."
|
||||||
@@ -713,20 +805,29 @@
|
|||||||
"Tooltip": {
|
"Tooltip": {
|
||||||
"sanBP": "Perte de 5+ SAN en 1 jet : folie temporaire. SI la SAN atteint le PR : trouble mental, perte de conscience et reset du PR.",
|
"sanBP": "Perte de 5+ SAN en 1 jet : folie temporaire. SI la SAN atteint le PR : trouble mental, perte de conscience et reset du PR.",
|
||||||
"setBP": "Positionner le Point de Rupture à la valeur courant de la SAN",
|
"setBP": "Positionner le Point de Rupture à la valeur courant de la SAN",
|
||||||
"addBond": "Ajouter une Attache"
|
"addBond": "Ajouter une Attache",
|
||||||
|
"rollDamage": "Lancer les dégâts"
|
||||||
},
|
},
|
||||||
"Chat": {
|
"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",
|
||||||
"WrongEra": "L'époque de l'item ne correspond pas à celle du jeu en cours.",
|
"WrongEra": "L'époque de l'item ne correspond pas à celle du jeu en cours.",
|
||||||
"NoSelectiveFireChoices": "Aucune option de tir sélectif n'est disponible pour cette arme : pas assez de munitions.",
|
"NoSelectiveFireChoices": "Aucune option de tir sélectif n'est disponible pour cette arme : pas assez de munitions.",
|
||||||
"NoAmmo": "Aucune munition disponible pour cette arme.",
|
"NoAmmo": "Aucune munition disponible pour cette arme.",
|
||||||
|
"WeaponBecameJunk": "L'arme {weapon} est devenue défectueuse !",
|
||||||
|
"noWeaponFound": "Aucune arme trouvée.",
|
||||||
"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."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
let nb = 10000
|
||||||
|
let sum = 0
|
||||||
|
let results = []
|
||||||
|
for (let i = 0; i < nb; i++) {
|
||||||
|
let r = new Roll("1d100")
|
||||||
|
await r.evaluate()
|
||||||
|
sum += r.total
|
||||||
|
results.push(r.total)
|
||||||
|
}
|
||||||
|
|
||||||
|
let mean = sum / nb
|
||||||
|
let variance = results.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) / nb
|
||||||
|
let stddev = Math.sqrt(variance)
|
||||||
|
|
||||||
|
console.log("Average : ", mean)
|
||||||
|
console.log("Standard deviation : ", stddev)
|
||||||
|
console.log("Coefficient of variation : ", stddev / mean )
|
||||||
|
console.log("Min : ", Math.min(...results))
|
||||||
|
console.log("Max : ", Math.max(...results))
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// System Module Imports
|
// System Module Imports
|
||||||
import { Utils } from './utils.js'
|
import CthulhuEternalUtils from '../../utils.mjs'
|
||||||
import { SYSTEM } from "../../config/system.mjs"
|
|
||||||
export let ActionHandler = null
|
export let ActionHandler = null
|
||||||
|
|
||||||
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||||
@@ -15,8 +15,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
* @param {array} groupIds
|
* @param {array} groupIds
|
||||||
*/
|
*/
|
||||||
async buildSystemActions(groupIds) {
|
async buildSystemActions(groupIds) {
|
||||||
// Set actor and token variables
|
// this.actor and this.actors are provided by the base class (TAH Core v2+)
|
||||||
this.actors = (!this.actor) ? this._getActors() : [this.actor]
|
|
||||||
this.actorType = this.actor?.type
|
this.actorType = this.actor?.type
|
||||||
|
|
||||||
// Set items variable
|
// Set items variable
|
||||||
@@ -26,9 +25,11 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
this.items = items
|
this.items = items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.actor) {
|
||||||
if (this.actorType !== 'vehicle') {
|
if (this.actorType !== 'vehicle') {
|
||||||
this.#buildCharacterActions()
|
this.#buildCharacterActions()
|
||||||
} else if (!this.actor) {
|
}
|
||||||
|
} else {
|
||||||
this.#buildMultipleTokenActions()
|
this.#buildMultipleTokenActions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,7 +39,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 +50,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 +68,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
await this.addActions(actions, {
|
await this.addActions(actions, {
|
||||||
id: 'attributes',
|
id: 'characteristics',
|
||||||
type: 'system'
|
type: 'system'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -80,79 +81,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 +168,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 +177,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 +197,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))
|
||||||
|
|
||||||
|
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,76 +221,54 @@ 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')
|
|
||||||
|
const weapons = this.actor.items.filter(i => i.type === 'weapon')
|
||||||
for (const item of weapons) {
|
for (const item of weapons) {
|
||||||
// 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') {
|
let skill = CthulhuEternalUtils.getWeaponSkill(this.actor, item, era)
|
||||||
const weapons = []
|
item.skillTotal = skill ? skill.system.skillTotal : 0
|
||||||
|
let weaponActions = []
|
||||||
const tooltip = {
|
const tooltip = {
|
||||||
content: String(skill.system.computeScore()),
|
content: String(item.skillTotal),
|
||||||
direction: 'LEFT'
|
direction: 'LEFT'
|
||||||
}
|
}
|
||||||
weapons.push({
|
weaponActions.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({
|
weaponActions.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) {
|
await this.addActions(weaponActions, {
|
||||||
const lethalityTooltip = {
|
id: `weapons_${item._id}`,
|
||||||
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, {
|
|
||||||
id: 'weapons_' + item._id,
|
|
||||||
type: 'system'
|
type: 'system'
|
||||||
})
|
})
|
||||||
}/* else if (item.type === 'ritual') {
|
|
||||||
rituals.push({
|
|
||||||
name: item.name,
|
|
||||||
id: item._id,
|
|
||||||
encodedValue: ['rituals', item.name].join(this.delimiter)
|
|
||||||
})
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* await this.addActions(rituals, {
|
|
||||||
id: 'rituals',
|
|
||||||
type: 'system'
|
|
||||||
}) */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,24 +15,25 @@ export const CORE_MODULE = {
|
|||||||
/**
|
/**
|
||||||
* Core module version required by the system module
|
* Core module version required by the system module
|
||||||
*/
|
*/
|
||||||
export const REQUIRED_CORE_MODULE_VERSION = '2.0'
|
export const REQUIRED_CORE_MODULE_VERSION = '2'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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,6 +1,3 @@
|
|||||||
import { SYSTEM } from "../../config/system.mjs"
|
|
||||||
import CthulhuEternalRoll from '../../documents/roll.mjs'
|
|
||||||
|
|
||||||
export let RollHandler = null
|
export let RollHandler = null
|
||||||
|
|
||||||
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||||
@@ -18,7 +15,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) {
|
||||||
@@ -67,8 +64,8 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
*/
|
*/
|
||||||
async #handleAction(event, actor, token, actionTypeId, actionId) {
|
async #handleAction(event, actor, token, actionTypeId, actionId) {
|
||||||
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 +79,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,40 +89,42 @@ 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
|
if (actionId === 'wp' || actionId === 'hp') return
|
||||||
if (actionId === 'wp' || actionId === 'health') 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]
|
||||||
const update = {}
|
const update = {}
|
||||||
update.system = {}
|
update.system = {}
|
||||||
update.system[attr] = {}
|
update.system[attr] = {}
|
||||||
update.system[attr].value = action === 'add' ? this.actor.system[attr].value + 1 : this.actor.system[attr].value - 1
|
update.system[attr].value = action === 'add' ? actor.system[attr].value + 1 : actor.system[attr].value - 1
|
||||||
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 > actor.system[attr].max || update.system[attr].value < actor.system[attr].min) return
|
||||||
return await this.actor.update(update)
|
return await 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 +135,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 +149,11 @@ 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)
|
const weapon = actor.items.find(i => i.type === 'weapon' && i.id === actionId)
|
||||||
const options = {
|
if (!weapon) return ui.notifications.warn(`Weapon not found for action id '${actionId}'`)
|
||||||
actor: this.actor,
|
weapon.damageFormula = weapon.system.damage
|
||||||
rollType: 'weapon',
|
weapon.damageBonus = actor.system.damageBonus
|
||||||
key: item.system.skill,
|
await actor.system.roll('weapon', weapon)
|
||||||
item
|
|
||||||
}
|
|
||||||
const roll = new DGPercentileRoll('1D100', {}, options)
|
|
||||||
await this.actor.sheet.processRoll(event, roll)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -227,21 +164,11 @@ 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)
|
const weapon = actor.items.find(i => i.type === 'weapon' && i.id === actionId)
|
||||||
if (item.system.lethality > 0 && event.ctrlKey) {
|
if (!weapon) return ui.notifications.warn(`Weapon not found for action id '${actionId}'`)
|
||||||
// Toggle on/off lethality
|
weapon.damageFormula = weapon.system.damage
|
||||||
const isLethal = !item.system.isLethal
|
weapon.damageBonus = actor.system.damageBonus
|
||||||
await item.update({ 'system.isLethal': isLethal })
|
await actor.system.roll('damage', weapon)
|
||||||
} 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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -252,19 +179,20 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
* @param {string} actionId The action id
|
* @param {string} actionId The action id
|
||||||
*/
|
*/
|
||||||
async #handleLethalityAction(event, actor, actionId) {
|
async #handleLethalityAction(event, actor, actionId) {
|
||||||
const item = await this.actor.items.get(actionId)
|
const item = actor.items.get(actionId)
|
||||||
if (item.system.damage !== '' && event.ctrlKey) {
|
if (item.system.damage !== '' && event.ctrlKey) {
|
||||||
const isLethal = !item.system.isLethal
|
const isLethal = !item.system.isLethal
|
||||||
await item.update({ 'system.isLethal': isLethal })
|
await item.update({ 'system.isLethal': isLethal })
|
||||||
} else {
|
} else {
|
||||||
const options = {
|
const options = {
|
||||||
actor: this.actor,
|
actor,
|
||||||
rollType: 'lethality',
|
rollType: 'lethality',
|
||||||
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)*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,8 @@
|
|||||||
// 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 { 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 +68,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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,14 +78,8 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
|||||||
* @returns {object} The TAH system styles
|
* @returns {object} The TAH system styles
|
||||||
*/
|
*/
|
||||||
registerStyles() {
|
registerStyles() {
|
||||||
return {
|
// No system-specific styles; use the core styles only
|
||||||
template: {
|
return {}
|
||||||
class: 'tah-style-template-style', // The class to add to first DIV element
|
|
||||||
file: 'tah-template-style', // The file without the css extension
|
|
||||||
moduleId: SYSTEM.ID, // The module ID
|
|
||||||
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`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,6 @@ export default class CthulhuEternalActorSheet extends HandlebarsApplicationMixin
|
|||||||
_onDragOver(event) {}
|
_onDragOver(event) {}
|
||||||
|
|
||||||
async _onDropItem(item) {
|
async _onDropItem(item) {
|
||||||
console.log("Dropped item", item)
|
|
||||||
let itemData = item.toObject()
|
let itemData = item.toObject()
|
||||||
await this.document.createEmbeddedDocuments("Item", [itemData], { renderSheet: false })
|
await this.document.createEmbeddedDocuments("Item", [itemData], { renderSheet: false })
|
||||||
}
|
}
|
||||||
@@ -160,15 +159,12 @@ export default class CthulhuEternalActorSheet extends HandlebarsApplicationMixin
|
|||||||
}
|
}
|
||||||
|
|
||||||
static #onUpdateCheckboxArray(event, target) {
|
static #onUpdateCheckboxArray(event, target) {
|
||||||
console.log("Update checkbox array", event, target)
|
|
||||||
let arrayName = target.dataset.name
|
let arrayName = target.dataset.name
|
||||||
let arrayIdx = Number(target.dataset.index)
|
let arrayIdx = Number(target.dataset.index)
|
||||||
let dataPath = `system.san.${arrayName}`
|
let dataPath = `system.san.${arrayName}`
|
||||||
let tab = foundry.utils.duplicate(this.document.system.san[arrayName])
|
let tab = foundry.utils.duplicate(this.document.system.san[arrayName])
|
||||||
tab[arrayIdx] = target.checked
|
tab[arrayIdx] = target.checked
|
||||||
this.actor.update( { [dataPath]: tab } )
|
this.actor.update( { [dataPath]: tab } )
|
||||||
// Dump
|
|
||||||
console.log("Array name", arrayName, arrayIdx, target.checked, dataPath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setBP: CthulhuEternalProtagonistSheet.#onSetBP,
|
setBP: CthulhuEternalProtagonistSheet.#onSetBP,
|
||||||
|
toggleEquipped: CthulhuEternalProtagonistSheet.#onToggleEquipped,
|
||||||
createGear: CthulhuEternalProtagonistSheet.#onCreateGear,
|
createGear: CthulhuEternalProtagonistSheet.#onCreateGear,
|
||||||
createArmor: CthulhuEternalProtagonistSheet.#onCreateArmor,
|
createArmor: CthulhuEternalProtagonistSheet.#onCreateArmor,
|
||||||
createWeapon: CthulhuEternalProtagonistSheet.#onCreateWeapon,
|
createWeapon: CthulhuEternalProtagonistSheet.#onCreateWeapon,
|
||||||
@@ -98,10 +99,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
|
||||||
@@ -145,6 +156,12 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
|
|||||||
this.document.system.setBP()
|
this.document.system.setBP()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static #onToggleEquipped(event, target) {
|
||||||
|
const itemId = target.dataset.itemId
|
||||||
|
const item = this.document.items.get(itemId)
|
||||||
|
if (item) item.update({ "system.equipped": !item.system.equipped })
|
||||||
|
}
|
||||||
|
|
||||||
static #onCreateGear(event, target) {
|
static #onCreateGear(event, target) {
|
||||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newGear"), type: "gear" }])
|
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newGear"), type: "gear" }])
|
||||||
}
|
}
|
||||||
@@ -225,6 +242,7 @@ export default class CthulhuEternalProtagonistSheet extends CthulhuEternalActorS
|
|||||||
case "damage":
|
case "damage":
|
||||||
li = $(event.currentTarget).parents(".item");
|
li = $(event.currentTarget).parents(".item");
|
||||||
item = this.actor.items.get(li.data("item-id"));
|
item = this.actor.items.get(li.data("item-id"));
|
||||||
|
item.damageFormula = $(event.currentTarget).data("roll-value") || item.system.damage
|
||||||
item.damageBonus = this.actor.system.damageBonus
|
item.damageBonus = this.actor.system.damageBonus
|
||||||
break
|
break
|
||||||
case "san":
|
case "san":
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ export default class CthulhuEternalSkillSheet extends CthulhuEternalItemSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async #onRollProgress(event, target) {
|
static async #onRollProgress(event, target) {
|
||||||
console.log("Rolling progress for skill", this, event, target)
|
|
||||||
if (this.actor) {
|
if (this.actor) {
|
||||||
const roll = await new Roll("1d4").evaluate()
|
const roll = await new Roll("1d4").evaluate()
|
||||||
if (roll) {
|
if (roll) {
|
||||||
@@ -41,7 +40,7 @@ export default class CthulhuEternalSkillSheet extends CthulhuEternalItemSheet {
|
|||||||
user: game.user.id,
|
user: game.user.id,
|
||||||
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
||||||
content: `<div class="progress-roll">${game.i18n.localize("CTHULHUETERNAL.Label.skillProgress")} - ${this.document.name} +${roll.total}</div>`,
|
content: `<div class="progress-roll">${game.i18n.localize("CTHULHUETERNAL.Label.skillProgress")} - ${this.document.name} +${roll.total}</div>`,
|
||||||
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
|
type: CONST.CHAT_MESSAGE_STYLES.ROLL,
|
||||||
roll: roll,
|
roll: roll,
|
||||||
};
|
};
|
||||||
await ChatMessage.create(chatData);
|
await ChatMessage.create(chatData);
|
||||||
|
|||||||
+139
-3
@@ -46,7 +46,7 @@ export const ERA_CSS = {
|
|||||||
modern: { primaryFont: "Georama", secondaryFont: "Georama", titleFont: "Georama", baseFontSize: "1.0rem", titleFontSize: "1.2rem", imgFilter: "brightness(0) saturate(100%) invert(92%) sepia(11%) saturate(1214%) hue-rotate(51deg) brightness(93%) contrast(86%)" },
|
modern: { primaryFont: "Georama", secondaryFont: "Georama", titleFont: "Georama", baseFontSize: "1.0rem", titleFontSize: "1.2rem", imgFilter: "brightness(0) saturate(100%) invert(92%) sepia(11%) saturate(1214%) hue-rotate(51deg) brightness(93%) contrast(86%)" },
|
||||||
future: { primaryFont: "Georama", secondaryFont: "Georama", titleFont: "Seabreed", baseFontSize: "1.0rem", titleFontSize: "2.0rem", imgFilter: "invert(90%) sepia(6%) saturate(1818%) hue-rotate(152deg) brightness(91%) contrast(91%)" },
|
future: { primaryFont: "Georama", secondaryFont: "Georama", titleFont: "Seabreed", baseFontSize: "1.0rem", titleFontSize: "2.0rem", imgFilter: "invert(90%) sepia(6%) saturate(1818%) hue-rotate(152deg) brightness(91%) contrast(91%)" },
|
||||||
victorian: { primaryFont: "Volkhov", secondaryFont: "Volkhov", titleFont: "Excelsior", baseFontSize: "1.0rem", titleFontSize: "1.2rem", imgFilter: "brightness(0) saturate(100%) invert(100%) sepia(59%) saturate(1894%) hue-rotate(337deg) brightness(88%) contrast(98%)" },
|
victorian: { primaryFont: "Volkhov", secondaryFont: "Volkhov", titleFont: "Excelsior", baseFontSize: "1.0rem", titleFontSize: "1.2rem", imgFilter: "brightness(0) saturate(100%) invert(100%) sepia(59%) saturate(1894%) hue-rotate(337deg) brightness(88%) contrast(98%)" },
|
||||||
coldwar: { primaryFont: "Georama", secondaryFont: "Georama", titleFont: "TopSecret", baseFontSize: "1.0rem", titleFontSize: "1.2rem",imgFilter: "brightness(0) saturate(100%) invert(81%) sepia(14%) saturate(2508%) hue-rotate(202deg) brightness(99%) contrast(105%)"},
|
coldwar: { primaryFont: "Georama", secondaryFont: "Georama", titleFont: "TopSecret", baseFontSize: "0.9rem", titleFontSize: "1.2rem", imgFilter: "brightness(0) saturate(100%) invert(81%) sepia(14%) saturate(2508%) hue-rotate(202deg) brightness(99%) contrast(105%)" },
|
||||||
revolution: { primaryFont: "IMFell", secondaryFont: "IMFell", titleFont: "Dominican", baseFontSize: "1.0rem", titleFontSize: "1.3rem", imgFilter: "brightness(0) saturate(100%) invert(81%) sepia(25%) saturate(386%) hue-rotate(7deg) brightness(101%) contrast(84%)" },
|
revolution: { primaryFont: "IMFell", secondaryFont: "IMFell", titleFont: "Dominican", baseFontSize: "1.0rem", titleFontSize: "1.3rem", imgFilter: "brightness(0) saturate(100%) invert(81%) sepia(25%) saturate(386%) hue-rotate(7deg) brightness(101%) contrast(84%)" },
|
||||||
medieval: { primaryFont: "Skranji", secondaryFont: "UncialAntiqua", titleFont: "Luminari", baseFontSize: "0.9rem", titleFontSize: "1.2rem", imgFilter: "brightness(0) saturate(100%) invert(93%) sepia(46%) saturate(354%) hue-rotate(321deg) brightness(93%) contrast(87%)" },
|
medieval: { primaryFont: "Skranji", secondaryFont: "UncialAntiqua", titleFont: "Luminari", baseFontSize: "0.9rem", titleFontSize: "1.2rem", imgFilter: "brightness(0) saturate(100%) invert(93%) sepia(46%) saturate(354%) hue-rotate(321deg) brightness(93%) contrast(87%)" },
|
||||||
ww2: { primaryFont: "SairaStencilOne", secondaryFont: "SairaStencilOne", titleFont: "Armalite", baseFontSize: "0.9rem", titleFontSize: "1.2rem", imgFilter: "filter: invert(44%) sepia(8%) saturate(2657%) hue-rotate(40deg) brightness(96%) contrast(75%)" },
|
ww2: { primaryFont: "SairaStencilOne", secondaryFont: "SairaStencilOne", titleFont: "Armalite", baseFontSize: "0.9rem", titleFontSize: "1.2rem", imgFilter: "filter: invert(44%) sepia(8%) saturate(2657%) hue-rotate(40deg) brightness(96%) contrast(75%)" },
|
||||||
@@ -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" },
|
||||||
@@ -154,7 +244,8 @@ export const WEAPON_SKILL_MAPPING = {
|
|||||||
"rangedprimitive": "CTHULHUETERNAL.Skill.Firearms",
|
"rangedprimitive": "CTHULHUETERNAL.Skill.Firearms",
|
||||||
"rangedthrown": "CTHULHUETERNAL.Skill.Athletics",
|
"rangedthrown": "CTHULHUETERNAL.Skill.Athletics",
|
||||||
"rangedfirearm": "CTHULHUETERNAL.Skill.Firearms",
|
"rangedfirearm": "CTHULHUETERNAL.Skill.Firearms",
|
||||||
"unarmed": "CTHULHUETERNAL.Skill.UnarmedCombat"
|
"unarmed": "CTHULHUETERNAL.Skill.UnarmedCombat",
|
||||||
|
"rangedexplosive": "CTHULHUETERNAL.Skill.MilitaryTrainingExplosive"
|
||||||
},
|
},
|
||||||
victorian: {
|
victorian: {
|
||||||
"melee": "CTHULHUETERNAL.Skill.Melee",
|
"melee": "CTHULHUETERNAL.Skill.Melee",
|
||||||
@@ -245,6 +336,45 @@ export const WEAPON_SELECTIVE_FIRE_CHOICES = {
|
|||||||
"longspray": { id: "longspray", label: "CTHULHUETERNAL.Weapon.SelectiveFire.longspray", ammoUsed: 20, lethality: 10, killRadius: 3 },
|
"longspray": { id: "longspray", label: "CTHULHUETERNAL.Weapon.SelectiveFire.longspray", ammoUsed: 20, lethality: 10, killRadius: 3 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Melee stuff
|
||||||
|
export const WEAPON_MELEE_TARGET_MOVE = {
|
||||||
|
"normal": { id: "normal", label: "CTHULHUETERNAL.Weapon.Target.Normal", modifier: 0 },
|
||||||
|
"stationary": { id: "stationary", label: "CTHULHUETERNAL.Weapon.Target.Stationary", modifier: 20 },
|
||||||
|
"movingfast": { id: "movingfast", label: "CTHULHUETERNAL.Weapon.Target.MovingFast", modifier: -20 },
|
||||||
|
"movingveryfast": { id: "movingveryfast", label: "CTHULHUETERNAL.Weapon.Target.MovingVeryFast", modifier: -40 },
|
||||||
|
}
|
||||||
|
// Ranged stuff
|
||||||
|
export const WEAPON_RANGED_RANGE = {
|
||||||
|
"pointblank": { id: "pointblank", label: "CTHULHUETERNAL.Weapon.Range.PointBlank", modifier: +20 },
|
||||||
|
"normal": { id: "normal", label: "CTHULHUETERNAL.Weapon.Range.Normal", modifier: 0 },
|
||||||
|
"range2x": { id: "range2x", label: "CTHULHUETERNAL.Weapon.Range.Range2x", modifier: -20 },
|
||||||
|
"range5x": { id: "range5x", label: "CTHULHUETERNAL.Weapon.Range.Range5x", modifier: -40 }
|
||||||
|
}
|
||||||
|
export const WEAPON_RANGED_TARGET_MOVE = {
|
||||||
|
"normal": { id: "normal", label: "CTHULHUETERNAL.Weapon.Target.Normal", modifier: 0 },
|
||||||
|
"stationary": { id: "stationary", label: "CTHULHUETERNAL.Weapon.Target.Stationary", modifier: 20 },
|
||||||
|
"movingfast": { id: "movingfast", label: "CTHULHUETERNAL.Weapon.Target.MovingRange", modifier: -20 },
|
||||||
|
"movingveryfast": { id: "movingveryfast", label: "CTHULHUETERNAL.Weapon.Target.MovingVeryFast", modifier: -40 },
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common stuff
|
||||||
|
export const WEAPON_ATTACKER_STATE = {
|
||||||
|
"normal": { id: "normal", label: "CTHULHUETERNAL.Weapon.Target.Normal", modifier: 0 },
|
||||||
|
"irritated": { id: "irritated", label: "CTHULHUETERNAL.Weapon.Attacker.Irritated", modifier: -20 },
|
||||||
|
"corrosive": { id: "corrosive", label: "CTHULHUETERNAL.Weapon.Attacker.Corrosive", modifier: -40 },
|
||||||
|
}
|
||||||
|
export const WEAPON_TARGET_SIZE = {
|
||||||
|
"normal": { id: "normal", label: "CTHULHUETERNAL.Weapon.Target.Normal", modifier: 0 },
|
||||||
|
"halfcovered": { id: "halfcovered", label: "CTHULHUETERNAL.Weapon.Target.HalfCovered", modifier: -20 },
|
||||||
|
"covered": { id: "covered", label: "CTHULHUETERNAL.Weapon.Target.Covered", modifier: -40 },
|
||||||
|
}
|
||||||
|
export const WEAPON_VISIBILITY = {
|
||||||
|
"clear": { id: "clear", label: "CTHULHUETERNAL.Weapon.Visibility.Clear", modifier: 0 },
|
||||||
|
"obscured": { id: "obscured", label: "CTHULHUETERNAL.Weapon.Visibility.Obscured", modifier: -20 },
|
||||||
|
"darkness": { id: "darkness", label: "CTHULHUETERNAL.Weapon.Visibility.Darkness", modifier: -40 },
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export const RITUAL_TYPES = {
|
export const RITUAL_TYPES = {
|
||||||
"simple": "CTHULHUETERNAL.Ritual.Simple",
|
"simple": "CTHULHUETERNAL.Ritual.Simple",
|
||||||
"difficult": "CTHULHUETERNAL.Ritual.Difficult",
|
"difficult": "CTHULHUETERNAL.Ritual.Difficult",
|
||||||
@@ -277,5 +407,11 @@ export const SYSTEM = {
|
|||||||
MULTIPLIER_CHOICES,
|
MULTIPLIER_CHOICES,
|
||||||
ASCII,
|
ASCII,
|
||||||
DAMAGE_BONUS,
|
DAMAGE_BONUS,
|
||||||
RITUAL_TYPES
|
RITUAL_TYPES,
|
||||||
|
WEAPON_MELEE_TARGET_MOVE,
|
||||||
|
WEAPON_RANGED_RANGE,
|
||||||
|
WEAPON_RANGED_TARGET_MOVE,
|
||||||
|
WEAPON_ATTACKER_STATE,
|
||||||
|
WEAPON_TARGET_SIZE,
|
||||||
|
WEAPON_VISIBILITY
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ export const WEAPON_TYPE = {
|
|||||||
"rangedprimitive": "CTHULHUETERNAL.Weapon.WeaponType.rangedprimitive",
|
"rangedprimitive": "CTHULHUETERNAL.Weapon.WeaponType.rangedprimitive",
|
||||||
"rangedthrown": "CTHULHUETERNAL.Weapon.WeaponType.rangedthrown",
|
"rangedthrown": "CTHULHUETERNAL.Weapon.WeaponType.rangedthrown",
|
||||||
"rangedfirearm": "CTHULHUETERNAL.Weapon.WeaponType.rangedfirearm",
|
"rangedfirearm": "CTHULHUETERNAL.Weapon.WeaponType.rangedfirearm",
|
||||||
"unarmed": "CTHULHUETERNAL.Weapon.WeaponType.unarmed"
|
"unarmed": "CTHULHUETERNAL.Weapon.WeaponType.unarmed",
|
||||||
|
"rangedexplosive": "CTHULHUETERNAL.Weapon.WeaponType.rangedexplosive",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WEAPON_SUBTYPE = {
|
export const WEAPON_SUBTYPE = {
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -40,9 +42,52 @@ export default class CthulhuEternalActor extends Actor {
|
|||||||
type: CONST.CHAT_MESSAGE_STYLES.OTHER
|
type: CONST.CHAT_MESSAGE_STYLES.OTHER
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if (this.type === "protagonist" && changed?.system?.hp !== undefined) {
|
||||||
|
const hp = this.system.hp
|
||||||
|
this.toggleStatusEffect("dead", { active: !!hp.dead })
|
||||||
|
this.toggleStatusEffect("unconscious", { active: !!hp.unconscious && !hp.dead })
|
||||||
|
this.toggleStatusEffect("stun", { active: !!hp.stunned && !hp.dead && !hp.unconscious })
|
||||||
|
}
|
||||||
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 })
|
||||||
|
}
|
||||||
|
// 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") {
|
||||||
|
|||||||
+193
-60
@@ -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 {
|
||||||
/**
|
/**
|
||||||
@@ -106,7 +107,7 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static buildSelectiveFireChoices(actor, weapon) {
|
static buildSelectiveFireChoices(actor, weapon) {
|
||||||
if (!weapon || !weapon?.system?.hasSelectiveFire) {
|
if (!weapon?.system?.hasSelectiveFire) {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
// Loop thru the selective fire choices and build the choices object when enough ammo in the weapon
|
// Loop thru the selective fire choices and build the choices object when enough ammo in the weapon
|
||||||
@@ -128,20 +129,23 @@ 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
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
@@ -149,59 +153,87 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the weapon is not lethal, we can proceed with the regular damage roll
|
// If the weapon is not lethal, we can proceed with the regular damage roll
|
||||||
let formula = weapon.system.damage
|
let formula = weapon?.damageFormula || weapon.system.damage || "0"
|
||||||
if (weapon.system.weaponType === "melee" || weapon.system.weaponType === "unarmed") {
|
if (weapon.system.applyDamageBonus) {
|
||||||
formula += ` + ${weapon.damageBonus}`
|
formula += ` + ${actor.system?.damageBonus}`
|
||||||
}
|
}
|
||||||
if (options?.previousResultType === "successCritical") {
|
if (options?.previousResultType === "successCritical") {
|
||||||
formula = `( ${formula} ) * 2`
|
formula = `( ${formula} ) * 2`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let damageRoll = new Roll(formula)
|
||||||
|
await damageRoll.evaluate()
|
||||||
|
let msgData = {
|
||||||
|
actorId: actor.id,
|
||||||
|
weapon,
|
||||||
|
formula,
|
||||||
|
ammoUsed: weapon?.ammoUsed || 0,
|
||||||
|
rollResult: damageRoll.total,
|
||||||
|
combatants: combatants
|
||||||
|
}
|
||||||
|
let flavor = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-regular-damage.hbs", msgData)
|
||||||
|
let msg = await ChatMessage.create({
|
||||||
|
user: game.user.id,
|
||||||
|
content: flavor,
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: actor }),
|
||||||
|
}, { rollMode: options.rollMode, create: true })
|
||||||
|
await msg.setFlag("fvtt-cthulhu-eternal", "woundData", msgData)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static computeWeaponModifiers(rollData) {
|
||||||
|
let modifier = SYSTEM.WEAPON_MELEE_TARGET_MOVE[rollData.meleeTargetMoveChoice]?.modifier || 0
|
||||||
|
modifier += SYSTEM.WEAPON_RANGED_RANGE[rollData.rangedRangeChoice]?.modifier || 0
|
||||||
|
modifier += SYSTEM.WEAPON_RANGED_TARGET_MOVE[rollData.rangedTargetMoveChoice]?.modifier || 0
|
||||||
|
modifier += SYSTEM.WEAPON_VISIBILITY[rollData.visibilityChoice]?.modifier || 0
|
||||||
|
modifier += SYSTEM.WEAPON_ATTACKER_STATE[rollData.attackerStateChoice]?.modifier || 0
|
||||||
|
modifier += SYSTEM.WEAPON_TARGET_SIZE[rollData.targetSizeChoice]?.modifier || 0
|
||||||
|
modifier += (rollData.aimingLastRoundFlag) ? 20 : 0
|
||||||
|
modifier += (rollData.aimingWithSightFlag) ? 20 : 0
|
||||||
|
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) {
|
if (ammoUsed > 0) {
|
||||||
await actor.updateEmbeddedDocuments("Item", [{
|
await actor.updateEmbeddedDocuments("Item", [{
|
||||||
_id: weapon._id,
|
_id: weapon._id,
|
||||||
"system.ammo.value": Math.max(0, weapon.system.ammo.value - ammoUsed)
|
"system.ammo.value": Math.max(0, weapon.system.ammo.value - ammoUsed)
|
||||||
}])
|
}])
|
||||||
}
|
}
|
||||||
let damageRoll = new Roll(formula)
|
weapon.ammoUsed = ammoUsed
|
||||||
await damageRoll.evaluate()
|
|
||||||
let msgData = {
|
|
||||||
weapon,
|
|
||||||
formula,
|
|
||||||
ammoUsed,
|
|
||||||
rollResult: damageRoll.total,
|
|
||||||
}
|
|
||||||
let flavor = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-regular-damage.hbs", msgData)
|
|
||||||
ChatMessage.create({
|
|
||||||
user: game.user.id,
|
|
||||||
content: flavor,
|
|
||||||
speaker: ChatMessage.getSpeaker({ actor: actor }),
|
|
||||||
}, { rollMode: options.rollMode, create: true })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -225,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":
|
||||||
@@ -257,33 +290,30 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era")
|
let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era")
|
||||||
if (era !== options.rollItem.system.settings) {
|
if (era !== options.rollItem.system.settings) {
|
||||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.WrongEra"))
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.WrongEra"))
|
||||||
console.log("WP Wrong Era", era, options.rollItem.system.weaponType)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!SYSTEM.WEAPON_SKILL_MAPPING[era]?.[options.rollItem.system.weaponType]) {
|
if (!SYSTEM.WEAPON_SKILL_MAPPING[era]?.[options.rollItem.system.weaponType]) {
|
||||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.NoWeaponType"))
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.NoWeaponType"))
|
||||||
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
|
if (options.weapon.system.state === "junk") {
|
||||||
} else {
|
options.isJunk = true
|
||||||
let skillName = game.i18n.localize(SYSTEM.WEAPON_SKILL_MAPPING[era][options.rollItem.system.weaponType])
|
options.initialScore = Math.max(0, options.initialScore - 20) // -20% for junk weapons
|
||||||
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()
|
if (options.weapon.system.state === "worn") {
|
||||||
console.log("WEAPON", skillName, era, options.rollItem)
|
options.isWorn = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@@ -310,10 +340,13 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
rollType: options.rollType,
|
rollType: options.rollType,
|
||||||
rollItem: foundry.utils.duplicate(options.rollItem), // Object only, no class
|
rollItem: foundry.utils.duplicate(options.rollItem), // Object only, no class
|
||||||
weapon: options?.weapon,
|
weapon: options?.weapon,
|
||||||
|
isRangedWeapon: options?.weapon?.system?.isRanged(),
|
||||||
initialScore: options.initialScore,
|
initialScore: options.initialScore,
|
||||||
targetScore: options.initialScore,
|
targetScore: options.initialScore,
|
||||||
isLowWP: options.isLowWP,
|
isLowWP: options.isLowWP,
|
||||||
isZeroWP: options.isZeroWP,
|
isZeroWP: options.isZeroWP,
|
||||||
|
isJunk: options.isJunk,
|
||||||
|
isWorn: options.isWorn,
|
||||||
isExhausted: options.isExhausted,
|
isExhausted: options.isExhausted,
|
||||||
enableHand: options.rollItem.enableHand,
|
enableHand: options.rollItem.enableHand,
|
||||||
enableStowed: options.rollItem.enableStowed,
|
enableStowed: options.rollItem.enableStowed,
|
||||||
@@ -323,12 +356,27 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
choiceModifier,
|
choiceModifier,
|
||||||
choiceMultiplier,
|
choiceMultiplier,
|
||||||
choiceSelectiveFire,
|
choiceSelectiveFire,
|
||||||
|
choiceMeleeTargetMove: SYSTEM.WEAPON_MELEE_TARGET_MOVE,
|
||||||
|
choiceRangedRange: SYSTEM.WEAPON_RANGED_RANGE,
|
||||||
|
choiceRangedTargetMove: SYSTEM.WEAPON_RANGED_TARGET_MOVE,
|
||||||
|
choiceVisibility: SYSTEM.WEAPON_VISIBILITY,
|
||||||
|
choiceAttackerState: SYSTEM.WEAPON_ATTACKER_STATE,
|
||||||
|
choiceTargetSize: SYSTEM.WEAPON_TARGET_SIZE,
|
||||||
|
selectiveFireChoice: "shortburst",
|
||||||
|
meleeTargetMoveChoice: "normal",
|
||||||
|
rangedRangeChoice: "normal",
|
||||||
|
rangedTargetMoveChoice: "normal",
|
||||||
|
visibilityChoice: "clear",
|
||||||
|
attackerStateChoice: "normal",
|
||||||
|
targetSizeChoice: "normal",
|
||||||
|
aimingLastRoundFlag: false,
|
||||||
|
aimingWithSightFlag: false,
|
||||||
|
modifier,
|
||||||
formula,
|
formula,
|
||||||
|
targetName: target?.name,
|
||||||
hasTarget: options.hasTarget,
|
hasTarget: options.hasTarget,
|
||||||
hasModifier,
|
hasModifier,
|
||||||
hasMultiplier,
|
hasMultiplier,
|
||||||
modifier,
|
|
||||||
selectiveFireChoice: "shortburst",
|
|
||||||
multiplier
|
multiplier
|
||||||
}
|
}
|
||||||
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/roll-dialog.hbs", dialogContext)
|
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/roll-dialog.hbs", dialogContext)
|
||||||
@@ -371,6 +419,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)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -378,14 +434,18 @@ 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)
|
|
||||||
if (options.rollType === "resource") {
|
if (options.rollType === "resource") {
|
||||||
rollData.targetScore = options.initialScore * Number(rollContext.multiplier)
|
rollData.targetScore = options.initialScore * Number(rollContext.multiplier)
|
||||||
} else {
|
} else {
|
||||||
rollData.targetScore = Math.min(Math.max(options.initialScore + Number(rollData.modifier), 0), 100)
|
let totalModifier = this.computeWeaponModifiers(rollData) + Number(rollData.modifier)
|
||||||
|
rollData.totalModifier = Math.min(totalModifier, 40)
|
||||||
|
rollData.targetScore = Math.min(Math.max(options.initialScore + Number(rollData.totalModifier), 0), 100)
|
||||||
if (rollData.isLowWP || rollData.isExhausted) {
|
if (rollData.isLowWP || rollData.isExhausted) {
|
||||||
rollData.targetScore -= 20
|
rollData.targetScore -= 20
|
||||||
}
|
}
|
||||||
@@ -394,24 +454,29 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
}
|
}
|
||||||
rollData.targetScore = Math.min(Math.max(rollData.targetScore, 0), 100)
|
rollData.targetScore = Math.min(Math.max(rollData.targetScore, 0), 100)
|
||||||
}
|
}
|
||||||
if (!rollData.targetScore) {
|
if (rollData.targetScore === undefined || rollData.targetScore === null) {
|
||||||
rollData.targetScore = options.initialScore
|
rollData.targetScore = options.initialScore
|
||||||
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)
|
||||||
await roll.evaluate()
|
await roll.evaluate()
|
||||||
|
|
||||||
roll.displayRollResult(roll, options, rollData)
|
await roll.displayRollResult(roll, options, rollData)
|
||||||
|
|
||||||
if (Hooks.call("fvtt-cthulhu-eternal.Roll", options, rollData, roll) === false) return
|
if (Hooks.call("fvtt-cthulhu-eternal.Roll", options, rollData, roll) === false) return
|
||||||
|
|
||||||
|
|
||||||
return roll
|
return roll
|
||||||
}
|
}
|
||||||
|
|
||||||
displayRollResult(formula, options, rollData) {
|
async displayRollResult(formula, options, rollData) {
|
||||||
|
|
||||||
// Compute the result quality
|
// Compute the result quality
|
||||||
let resultType = "failure"
|
let resultType = "failure"
|
||||||
@@ -429,6 +494,11 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
resultType = "failureCritical"
|
resultType = "failureCritical"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rollData.weapon?.system?.state === "junk" && this.total > 95) {
|
||||||
|
this.options.isDestroyed = true
|
||||||
|
rollData.isDestroyed = true
|
||||||
|
resultType = "failureCritical"
|
||||||
|
}
|
||||||
// As per the rules, a roll of 100 is always a failure, even if the target is above 100
|
// As per the rules, a roll of 100 is always a failure, even if the target is above 100
|
||||||
if (this.total === 100) {
|
if (this.total === 100) {
|
||||||
resultType = "failureCritical"
|
resultType = "failureCritical"
|
||||||
@@ -455,10 +525,70 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
this.options.isCritical = resultType === "successCritical" || resultType === "failureCritical"
|
this.options.isCritical = resultType === "successCritical" || resultType === "failureCritical"
|
||||||
}
|
}
|
||||||
rollData.resultType = resultType
|
rollData.resultType = resultType
|
||||||
|
|
||||||
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -556,7 +686,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,
|
||||||
@@ -567,10 +697,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) {
|
||||||
@@ -600,12 +731,14 @@ export default class CthulhuEternalRoll extends Roll {
|
|||||||
rollItem: rollItem,
|
rollItem: rollItem,
|
||||||
rollData: rollData
|
rollData: rollData
|
||||||
}
|
}
|
||||||
|
// Get array of gamemaster ID
|
||||||
let msg = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-san-request.hbs", msgData)
|
let msg = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-san-request.hbs", msgData)
|
||||||
let chatMsg = await ChatMessage.create({
|
let chatMsg = await ChatMessage.create({
|
||||||
user: game.user.id,
|
user: game.user.id,
|
||||||
content: msg,
|
content: msg,
|
||||||
speaker: ChatMessage.getSpeaker({ actor: rollData.actor })
|
speaker: ChatMessage.getSpeaker({ actor: rollData.actor }),
|
||||||
}, { rollMode: rollData.rollMode, create: true })
|
whisper: game.users.filter(u => u.isGM).map(u => u.id),
|
||||||
|
})
|
||||||
await chatMsg.setFlag("fvtt-cthulhu-eternal", "rollData", rollData)
|
await chatMsg.setFlag("fvtt-cthulhu-eternal", "rollData", rollData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export default class CthulhuEternalArmor extends foundry.abstract.TypeDataModel
|
|||||||
|
|
||||||
schema.protection = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
schema.protection = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||||
schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 })
|
schema.resourceLevel = new fields.NumberField({ required: true, initial: 0, min: 0 })
|
||||||
|
schema.equipped = new fields.BooleanField({ required: true, initial: false })
|
||||||
|
|
||||||
return schema
|
return schema
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -90,6 +90,10 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
|
|||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
super.prepareDerivedData();
|
super.prepareDerivedData();
|
||||||
|
|
||||||
|
if (!game.user.isGM) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let updates = {}
|
let updates = {}
|
||||||
if (this.wp.max !== this.characteristics.pow.value) {
|
if (this.wp.max !== this.characteristics.pow.value) {
|
||||||
updates[`system.wp.max`] = this.characteristics.pow.value
|
updates[`system.wp.max`] = this.characteristics.pow.value
|
||||||
@@ -127,7 +131,7 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
|
|||||||
dmgBonus = 0
|
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) {
|
||||||
@@ -137,11 +141,17 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
|
|||||||
// BP (Breaking Point) management
|
// BP (Breaking Point) management
|
||||||
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
|
||||||
|
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
|
||||||
|
whisper: [w.id]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Unconsciousness management
|
// Unconsciousness management
|
||||||
if (!this.hp.unconscious && this.hp.value <= 2) {
|
if (!this.hp.unconscious && this.hp.value <= 2) {
|
||||||
@@ -195,10 +205,6 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
|
|||||||
}
|
}
|
||||||
|
|
||||||
async applySANConsequences(rollData) {
|
async applySANConsequences(rollData) {
|
||||||
// If sanType is "non", do nothing
|
|
||||||
if (rollData.sanType === "none") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let msgData = {
|
let msgData = {
|
||||||
sanType: rollData.sanType,
|
sanType: rollData.sanType,
|
||||||
sanLoss: rollData.sanLoss,
|
sanLoss: rollData.sanLoss,
|
||||||
@@ -265,14 +271,20 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
|
|||||||
updates[`system.san.helplessness`] = [false, false, false]
|
updates[`system.san.helplessness`] = [false, false, false]
|
||||||
msgData.adaptedToHelplessness = true
|
msgData.adaptedToHelplessness = true
|
||||||
}
|
}
|
||||||
|
} else if (rollData.sanType === "unnatural") {
|
||||||
|
template = "systems/fvtt-cthulhu-eternal/templates/chat-san-loss-unnatural.hbs"
|
||||||
|
} else {
|
||||||
|
template = "systems/fvtt-cthulhu-eternal/templates/chat-san-loss-none.hbs"
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = await foundry.applications.handlebars.renderTemplate(template, msgData)
|
let content = await foundry.applications.handlebars.renderTemplate(template, msgData)
|
||||||
let msg = await ChatMessage.create({
|
let msg = await ChatMessage.create({
|
||||||
content: content,
|
content: content,
|
||||||
speaker: ChatMessage.getSpeaker({ actor: this.parent })
|
speaker: ChatMessage.getSpeaker({ actor: this.parent }),
|
||||||
|
whisper: game.users.filter(u => u.isGM).map(u => u.id),
|
||||||
})
|
})
|
||||||
msg.setFlag("fvtt-cthulhu-eternal", "rollData", msgData)
|
await msg.setFlag("fvtt-cthulhu-eternal", "rollData", msgData)
|
||||||
|
|
||||||
if (Object.keys(updates).length > 0) {
|
if (Object.keys(updates).length > 0) {
|
||||||
this.parent.update(updates)
|
this.parent.update(updates)
|
||||||
}
|
}
|
||||||
@@ -284,12 +296,14 @@ export default class CthulhuEternalProtagonist extends foundry.abstract.TypeData
|
|||||||
let san = Math.max(Math.min(this.san.value + rollData.sanLoss, this.san.max), 0)
|
let san = Math.max(Math.min(this.san.value + rollData.sanLoss, this.san.max), 0)
|
||||||
if (this.san.value !== san) {
|
if (this.san.value !== san) {
|
||||||
updates[`system.san.value`] = san
|
updates[`system.san.value`] = san
|
||||||
|
rollData.sanValue = san
|
||||||
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-san-type-request.hbs", rollData)
|
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/chat-san-type-request.hbs", rollData)
|
||||||
let msg = await ChatMessage.create({
|
let msg = await ChatMessage.create({
|
||||||
content: content,
|
content: content,
|
||||||
speaker: ChatMessage.getSpeaker({ actor: this.parent })
|
speaker: ChatMessage.getSpeaker({ actor: this.parent }),
|
||||||
|
whisper: game.users.filter(u => u.isGM).map(u => u.id)
|
||||||
})
|
})
|
||||||
msg.setFlag("fvtt-cthulhu-eternal", "rollData", rollData)
|
await msg.setFlag("fvtt-cthulhu-eternal", "rollData", rollData)
|
||||||
}
|
}
|
||||||
if (Object.keys(updates).length > 0) {
|
if (Object.keys(updates).length > 0) {
|
||||||
this.parent.update(updates)
|
this.parent.update(updates)
|
||||||
|
|||||||
@@ -15,7 +15,18 @@ export default class CthulhuEternalWeapon extends foundry.abstract.TypeDataModel
|
|||||||
schema.hasDirectSkill = new fields.BooleanField({ required: true, initial: false })
|
schema.hasDirectSkill = new fields.BooleanField({ required: true, initial: false })
|
||||||
schema.directSkillValue = new fields.NumberField({ required: true, initial: 0, min: 0, max: 99 })
|
schema.directSkillValue = new fields.NumberField({ required: true, initial: 0, min: 0, max: 99 })
|
||||||
|
|
||||||
|
schema.hasDamageDistance = new fields.BooleanField({ required: true, initial: false })
|
||||||
|
schema.damageDistance = new fields.SchemaField(Array.fromRange(6, 1).reduce((damageDistance, i) => {
|
||||||
|
damageDistance[`dist${i}`] = new fields.SchemaField({
|
||||||
|
damage: new fields.StringField({ required: true, initial: "1d6" }),
|
||||||
|
distance: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||||
|
})
|
||||||
|
return damageDistance
|
||||||
|
}, {}));
|
||||||
|
|
||||||
schema.hasSelectiveFire = new fields.BooleanField({ required: true, initial: false })
|
schema.hasSelectiveFire = new fields.BooleanField({ required: true, initial: false })
|
||||||
|
schema.hasSight = new fields.BooleanField({ required: true, initial: false })
|
||||||
|
schema.isStunning = new fields.BooleanField({ required: true, initial: false })
|
||||||
schema.damage = new fields.StringField({ required: true, initial: "1d6" })
|
schema.damage = new fields.StringField({ required: true, initial: "1d6" })
|
||||||
schema.applyDamageBonus = new fields.BooleanField({ required: true, initial: false })
|
schema.applyDamageBonus = new fields.BooleanField({ required: true, initial: false })
|
||||||
schema.baseRange = new fields.StringField({ required: true, initial: "" })
|
schema.baseRange = new fields.StringField({ required: true, initial: "" })
|
||||||
@@ -43,7 +54,7 @@ export default class CthulhuEternalWeapon extends foundry.abstract.TypeDataModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
isRanged() {
|
isRanged() {
|
||||||
return this.weaponType.includes("ranged")
|
return this.weaponType.match("ranged")
|
||||||
}
|
}
|
||||||
|
|
||||||
isFireArm() {
|
isFireArm() {
|
||||||
|
|||||||
+318
-12
@@ -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) {
|
||||||
@@ -110,9 +118,6 @@ export default class CthulhuEternalUtils {
|
|||||||
return Object.keys(obj).length;
|
return Object.keys(obj).length;
|
||||||
})
|
})
|
||||||
|
|
||||||
Handlebars.registerHelper('isEnabled', function (configKey) {
|
|
||||||
return game.settings.get("bol", configKey);
|
|
||||||
})
|
|
||||||
Handlebars.registerHelper('split', function (str, separator, keep) {
|
Handlebars.registerHelper('split', function (str, separator, keep) {
|
||||||
return str.split(separator)[keep];
|
return str.split(separator)[keep];
|
||||||
})
|
})
|
||||||
@@ -156,7 +161,6 @@ export default class CthulhuEternalUtils {
|
|||||||
return eval(expr);
|
return eval(expr);
|
||||||
})
|
})
|
||||||
Handlebars.registerHelper('isOwnerOrGM', function (actor) {
|
Handlebars.registerHelper('isOwnerOrGM', function (actor) {
|
||||||
console.log("Testing actor", actor.isOwner, game.userId)
|
|
||||||
return actor.isOwner || game.isGM;
|
return actor.isOwner || game.isGM;
|
||||||
})
|
})
|
||||||
Handlebars.registerHelper('upperFirst', function (text) {
|
Handlebars.registerHelper('upperFirst', function (text) {
|
||||||
@@ -180,6 +184,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) {
|
||||||
@@ -196,11 +247,6 @@ export default class CthulhuEternalUtils {
|
|||||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noSanTypeFound"))
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Notifications.noSanTypeFound"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// If the sanType is "none", we don't apply any SAN processing
|
|
||||||
if (sanType === "none") {
|
|
||||||
ui.notifications.info(game.i18n.localize("CTHULHUETERNAL.Notifications.noSanLossApplied"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rollData.sanType = sanType
|
rollData.sanType = sanType
|
||||||
await actor.system.applySANConsequences(rollData)
|
await actor.system.applySANConsequences(rollData)
|
||||||
// Delete the roll message
|
// Delete the roll message
|
||||||
@@ -253,19 +299,243 @@ export default class CthulhuEternalUtils {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static async damageRoll(rollMessage) {
|
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 }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
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)
|
|
||||||
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
|
||||||
|
rollData.weapon.damageFormula = formula || rollData.weapon.system.damage
|
||||||
actor.system.roll("damage", rollData.weapon)
|
actor.system.roll("damage", rollData.weapon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async wornWeaponCheck(rollMessage) {
|
||||||
|
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)
|
||||||
|
if (!actor) {
|
||||||
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Label.noActorFound"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let weapon = rollData.weapon
|
||||||
|
if (!weapon) {
|
||||||
|
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Label.noWeaponFound"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lance un jet de chance (50%)
|
||||||
|
let luckRoll = new Roll("1d100")
|
||||||
|
await luckRoll.evaluate()
|
||||||
|
|
||||||
|
let isSuccess = luckRoll.total <= 50
|
||||||
|
let resultMsg = ""
|
||||||
|
|
||||||
|
if (isSuccess) {
|
||||||
|
// Succès - l'arme reste worn
|
||||||
|
resultMsg = game.i18n.format("CTHULHUETERNAL.Label.wornWeaponCheckSuccess", {
|
||||||
|
weapon: weapon.name,
|
||||||
|
roll: luckRoll.total
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Échec - l'arme devient junk
|
||||||
|
resultMsg = game.i18n.format("CTHULHUETERNAL.Label.wornWeaponCheckFailure", {
|
||||||
|
weapon: weapon.name,
|
||||||
|
roll: luckRoll.total
|
||||||
|
})
|
||||||
|
|
||||||
|
// Mettre à jour l'état de l'arme
|
||||||
|
await actor.updateEmbeddedDocuments("Item", [{
|
||||||
|
_id: weapon._id,
|
||||||
|
"system.state": "junk"
|
||||||
|
}])
|
||||||
|
|
||||||
|
ui.notifications.warn(game.i18n.format("CTHULHUETERNAL.Notifications.WeaponBecameJunk", { weapon: weapon.name }))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Créer un message de chat avec le résultat
|
||||||
|
await ChatMessage.create({
|
||||||
|
user: game.user.id,
|
||||||
|
content: `<div class="cthulhu-eternal-roll">
|
||||||
|
<h4>${game.i18n.localize("CTHULHUETERNAL.Label.wornWeaponCheckTitle")}</h4>
|
||||||
|
<p>${resultMsg}</p>
|
||||||
|
</div>`,
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: actor }),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
static async nudgeRoll(rollMessage) {
|
static async nudgeRoll(rollMessage) {
|
||||||
|
|
||||||
let dialogContext = rollMessage.rolls[0]?.options
|
let dialogContext = rollMessage.rolls[0]?.options
|
||||||
@@ -278,7 +548,6 @@ export default class CthulhuEternalUtils {
|
|||||||
|
|
||||||
// Build options table for the select operator between minValue and maxValue
|
// Build options table for the select operator between minValue and maxValue
|
||||||
dialogContext.nudgeOptions = Array.from({ length: dialogContext.maxValue - dialogContext.minValue + 1 }, (_, i) => dialogContext.minValue + i)
|
dialogContext.nudgeOptions = Array.from({ length: dialogContext.maxValue - dialogContext.minValue + 1 }, (_, i) => dialogContext.minValue + i)
|
||||||
console.log(dialogContext)
|
|
||||||
|
|
||||||
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/nudge-dialog.hbs", dialogContext)
|
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-cthulhu-eternal/templates/nudge-dialog.hbs", dialogContext)
|
||||||
|
|
||||||
@@ -331,6 +600,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() {
|
||||||
@@ -349,4 +622,37 @@ 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
|
||||||
|
}
|
||||||
|
// 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-000167
|
MANIFEST-000293
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
2025/06/29-22:25:29.091880 7fda6d9f96c0 Recovering log #165
|
2026/04/28-23:36:37.192093 7f5797fff6c0 Delete type=3 #1
|
||||||
2025/06/29-22:25:29.103184 7fda6d9f96c0 Delete type=3 #163
|
2026/04/28-23:37:29.068330 7f57977fe6c0 Level-0 table #296: started
|
||||||
2025/06/29-22:25:29.103305 7fda6d9f96c0 Delete type=0 #165
|
2026/04/28-23:37:29.068358 7f57977fe6c0 Level-0 table #296: 0 bytes OK
|
||||||
2025/06/29-22:26:56.370766 7fda5bbff6c0 Level-0 table #170: started
|
2026/04/28-23:37:29.074817 7f57977fe6c0 Delete type=0 #294
|
||||||
2025/06/29-22:26:56.370832 7fda5bbff6c0 Level-0 table #170: 0 bytes OK
|
2026/04/28-23:37:29.106904 7f57977fe6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at '!items!zVFfp3o0G0Zg3Ia4' @ 52 : 1
|
||||||
2025/06/29-22:26:56.379673 7fda5bbff6c0 Delete type=0 #168
|
2026/04/28-23:37:29.106913 7f57977fe6c0 Compacting 1@0 + 0@1 files
|
||||||
2025/06/29-22:26:56.380010 7fda5bbff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
|
2026/04/28-23:37:29.111066 7f57977fe6c0 Generated table #297@0: 26 keys, 60964 bytes
|
||||||
|
2026/04/28-23:37:29.111082 7f57977fe6c0 Compacted 1@0 + 0@1 files => 60964 bytes
|
||||||
|
2026/04/28-23:37:29.117095 7f57977fe6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
||||||
|
2026/04/28-23:37:29.117212 7f57977fe6c0 Delete type=2 #248
|
||||||
|
2026/04/28-23:37:29.117383 7f57977fe6c0 Manual compaction at level-0 from '!items!zVFfp3o0G0Zg3Ia4' @ 52 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
2025/06/29-22:24:52.674663 7fda6c9f76c0 Recovering log #161
|
2026/04/28-23:36:37.170404 7f5797fff6c0 Log #291: 0 ops saved to Table #292 OK
|
||||||
2025/06/29-22:24:52.733389 7fda6c9f76c0 Delete type=3 #159
|
2026/04/28-23:36:37.170516 7f5797fff6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-cthulhu-eternal/packs-system/rituals/000291.log: OK
|
||||||
2025/06/29-22:24:52.733531 7fda6c9f76c0 Delete type=0 #161
|
2026/04/28-23:36:37.171708 7f5797fff6c0 Table #248: 26 entries OK
|
||||||
2025/06/29-22:25:23.612345 7fda5bbff6c0 Level-0 table #166: started
|
2026/04/28-23:36:37.175280 7f5797fff6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-cthulhu-eternal/packs-system/rituals; recovered 1 files; 60964 bytes. Some data may have been lost. ****
|
||||||
2025/06/29-22:25:23.612406 7fda5bbff6c0 Level-0 table #166: 0 bytes OK
|
|
||||||
2025/06/29-22:25:23.683484 7fda5bbff6c0 Delete type=0 #164
|
|
||||||
2025/06/29-22:25:23.834365 7fda5bbff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000336
|
MANIFEST-000462
|
||||||
|
|||||||
+11
-7
@@ -1,7 +1,11 @@
|
|||||||
2025/06/29-22:25:29.069935 7fda6d1f86c0 Recovering log #334
|
2026/04/28-23:36:37.131149 7f57a57ee6c0 Delete type=3 #1
|
||||||
2025/06/29-22:25:29.081064 7fda6d1f86c0 Delete type=3 #332
|
2026/04/28-23:37:29.054894 7f57977fe6c0 Level-0 table #465: started
|
||||||
2025/06/29-22:25:29.081192 7fda6d1f86c0 Delete type=0 #334
|
2026/04/28-23:37:29.054961 7f57977fe6c0 Level-0 table #465: 0 bytes OK
|
||||||
2025/06/29-22:26:56.360514 7fda5bbff6c0 Level-0 table #339: started
|
2026/04/28-23:37:29.061529 7f57977fe6c0 Delete type=0 #463
|
||||||
2025/06/29-22:26:56.360577 7fda5bbff6c0 Level-0 table #339: 0 bytes OK
|
2026/04/28-23:37:29.081738 7f57977fe6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at '!items!zvoUByzWSWZ87fxA' @ 1281 : 1
|
||||||
2025/06/29-22:26:56.370559 7fda5bbff6c0 Delete type=0 #337
|
2026/04/28-23:37:29.081748 7f57977fe6c0 Compacting 1@0 + 0@1 files
|
||||||
2025/06/29-22:26:56.379992 7fda5bbff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
|
2026/04/28-23:37:29.088487 7f57977fe6c0 Generated table #466@0: 556 keys, 320457 bytes
|
||||||
|
2026/04/28-23:37:29.088505 7f57977fe6c0 Compacted 1@0 + 0@1 files => 320457 bytes
|
||||||
|
2026/04/28-23:37:29.094678 7f57977fe6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
||||||
|
2026/04/28-23:37:29.094831 7f57977fe6c0 Delete type=2 #417
|
||||||
|
2026/04/28-23:37:29.117360 7f57977fe6c0 Manual compaction at level-0 from '!items!zvoUByzWSWZ87fxA' @ 1281 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
2025/06/29-22:24:52.606734 7fda6d9f96c0 Recovering log #330
|
2026/04/28-23:36:36.935963 7f57a57ee6c0 Log #460: 0 ops saved to Table #461 OK
|
||||||
2025/06/29-22:24:52.662677 7fda6d9f96c0 Delete type=3 #328
|
2026/04/28-23:36:36.936025 7f57a57ee6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-cthulhu-eternal/packs-system/skills/000460.log: OK
|
||||||
2025/06/29-22:24:52.662873 7fda6d9f96c0 Delete type=0 #330
|
2026/04/28-23:36:36.942723 7f57a57ee6c0 Table #417: 556 entries OK
|
||||||
2025/06/29-22:25:23.549590 7fda5bbff6c0 Level-0 table #335: started
|
2026/04/28-23:36:36.946588 7f57a57ee6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-cthulhu-eternal/packs-system/skills; recovered 1 files; 320457 bytes. Some data may have been lost. ****
|
||||||
2025/06/29-22:25:23.549651 7fda5bbff6c0 Level-0 table #335: 0 bytes OK
|
|
||||||
2025/06/29-22:25:23.612061 7fda5bbff6c0 Delete type=0 #333
|
|
||||||
2025/06/29-22:25:23.834320 7fda5bbff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
MANIFEST-000108
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
2026/04/28-23:36:37.166060 7f57a4fed6c0 Delete type=3 #1
|
||||||
|
2026/04/28-23:37:29.061681 7f57977fe6c0 Level-0 table #111: started
|
||||||
|
2026/04/28-23:37:29.061722 7f57977fe6c0 Level-0 table #111: 0 bytes OK
|
||||||
|
2026/04/28-23:37:29.068229 7f57977fe6c0 Delete type=0 #109
|
||||||
|
2026/04/28-23:37:29.095030 7f57977fe6c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at '!items!zyxA9DhO36t5OBDv' @ 55 : 1
|
||||||
|
2026/04/28-23:37:29.095044 7f57977fe6c0 Compacting 1@0 + 0@1 files
|
||||||
|
2026/04/28-23:37:29.100652 7f57977fe6c0 Generated table #112@0: 362 keys, 93592 bytes
|
||||||
|
2026/04/28-23:37:29.100675 7f57977fe6c0 Compacted 1@0 + 0@1 files => 93592 bytes
|
||||||
|
2026/04/28-23:37:29.106685 7f57977fe6c0 compacted to: files[ 0 1 0 0 0 0 0 ]
|
||||||
|
2026/04/28-23:37:29.106785 7f57977fe6c0 Delete type=2 #63
|
||||||
|
2026/04/28-23:37:29.117373 7f57977fe6c0 Manual compaction at level-0 from '!items!zyxA9DhO36t5OBDv' @ 55 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
2026/04/28-23:36:37.136506 7f57a4fed6c0 Log #106: 0 ops saved to Table #107 OK
|
||||||
|
2026/04/28-23:36:37.136625 7f57a4fed6c0 Archiving /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-cthulhu-eternal/packs-system/weapons/000106.log: OK
|
||||||
|
2026/04/28-23:36:37.141991 7f57a4fed6c0 Table #63: 362 entries OK
|
||||||
|
2026/04/28-23:36:37.145196 7f57a4fed6c0 **** Repaired leveldb /home/morr/foundry/foundrydata-dev/Data/systems/fvtt-cthulhu-eternal/packs-system/weapons; recovered 1 files; 93592 bytes. Some data may have been lost. ****
|
||||||
Binary file not shown.
+22
-19
@@ -8,6 +8,28 @@
|
|||||||
background-color: var(--color-light-1);
|
background-color: var(--color-light-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.creature-hp {
|
||||||
|
gap: 2px;
|
||||||
|
align-items: center;
|
||||||
|
.form-fields {
|
||||||
|
input {
|
||||||
|
flex: none;
|
||||||
|
min-width: 4rem;
|
||||||
|
max-width: 4rem;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.damage-bonus {
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.8);
|
||||||
|
}
|
||||||
|
.hp-separator {
|
||||||
|
font-size: calc(var(--font-size-standard) * 1.2);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.creature-main {
|
.creature-main {
|
||||||
background-color: var(--color-light-1);
|
background-color: var(--color-light-1);
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -34,25 +56,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.creature-hp {
|
|
||||||
gap: 2px;
|
|
||||||
align-items: center;
|
|
||||||
input {
|
|
||||||
flex: none;
|
|
||||||
width: 2rem;
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
.damage-bonus {
|
|
||||||
font-size: calc(var(--font-size-standard) * 0.8);
|
|
||||||
}
|
|
||||||
.hp-separator {
|
|
||||||
font-size: calc(var(--font-size-standard) * 1.2);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.creature-dv,
|
.creature-dv,
|
||||||
.creature-dmax {
|
.creature-dmax {
|
||||||
.form-fields {
|
.form-fields {
|
||||||
|
|||||||
+42
-2
@@ -98,6 +98,23 @@ i.fvtt-cthulhu-eternal {
|
|||||||
color: var(--color-critical-failure);
|
color: var(--color-critical-failure);
|
||||||
font-family: var(--font-title);
|
font-family: var(--font-title);
|
||||||
}
|
}
|
||||||
|
.san-type-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin: 10px 0;
|
||||||
|
button {
|
||||||
|
margin: 0 2px;
|
||||||
|
font-family: var(--font-primary);
|
||||||
|
font-size: calc(var(--font-size-standard) * 0.9);
|
||||||
|
border: none;
|
||||||
|
padding: 2px 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
min-width: 6rem;
|
||||||
|
max-width: 6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
.san-loose-buttons {
|
.san-loose-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -111,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 {
|
||||||
@@ -124,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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -2,9 +2,7 @@
|
|||||||
font-family: var(--font-primary);
|
font-family: var(--font-primary);
|
||||||
font-size: calc(var(--font-size-standard) * 1.05);
|
font-size: calc(var(--font-size-standard) * 1.05);
|
||||||
color: var(--color-dark-1);
|
color: var(--color-dark-1);
|
||||||
background-image: var(--background-image-base);
|
background: var(--color-light-1);
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
--input-height: 1.4rem;
|
--input-height: 1.4rem;
|
||||||
|
|
||||||
.sheet-tabs {
|
.sheet-tabs {
|
||||||
|
|||||||
+17
-3
@@ -39,7 +39,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
input {
|
input {
|
||||||
flex: none;
|
flex: none;
|
||||||
width: 2rem;
|
width: 4rem;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
.hp-separator {
|
.hp-separator {
|
||||||
@@ -478,7 +478,7 @@
|
|||||||
}
|
}
|
||||||
.weapons {
|
.weapons {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(1, 1fr);
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
.weapon {
|
.weapon {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -496,10 +496,24 @@
|
|||||||
min-width: 1.8rem;
|
min-width: 1.8rem;
|
||||||
max-width: 1.8rem;
|
max-width: 1.8rem;
|
||||||
}
|
}
|
||||||
.damage {
|
.range {
|
||||||
min-width: 6rem;
|
min-width: 6rem;
|
||||||
max-width: 6rem;
|
max-width: 6rem;
|
||||||
}
|
}
|
||||||
|
.ammo {
|
||||||
|
min-width: 4rem;
|
||||||
|
max-width: 4rem;
|
||||||
|
}
|
||||||
|
.lethality {
|
||||||
|
display: flex;
|
||||||
|
min-width: 3.2rem;
|
||||||
|
max-width: 3.2rem;
|
||||||
|
}
|
||||||
|
.damage {
|
||||||
|
display: flex;
|
||||||
|
min-width: 12rem;
|
||||||
|
max-width: 12rem;
|
||||||
|
}
|
||||||
.name {
|
.name {
|
||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
max-width: 10rem;
|
max-width: 10rem;
|
||||||
|
|||||||
+228
-16
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,24 @@
|
|||||||
fieldset {
|
fieldset {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
background-color: var(--color-light-1);
|
background-color: var(--color-light-1);
|
||||||
|
input {
|
||||||
|
max-width: 5rem;
|
||||||
|
min-width: 5rem;
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
max-width: 14rem;
|
||||||
|
min-width: 14rem;
|
||||||
|
}
|
||||||
|
input[type="checkbox"] {
|
||||||
|
max-width: 1.5rem;
|
||||||
|
min-width: 1.5rem;
|
||||||
|
}
|
||||||
|
.flexrow > *:not(:first-child) {
|
||||||
|
margin-left: 1rem;
|
||||||
|
}
|
||||||
|
.damage-distance {
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
|
|||||||
+14
-2
@@ -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",
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
},
|
},
|
||||||
"compatibility": {
|
"compatibility": {
|
||||||
"minimum": "13",
|
"minimum": "13",
|
||||||
"verified": "13"
|
"verified": "14"
|
||||||
},
|
},
|
||||||
"esmodules": [
|
"esmodules": [
|
||||||
"cthulhu-eternal.mjs"
|
"cthulhu-eternal.mjs"
|
||||||
@@ -152,6 +152,18 @@
|
|||||||
},
|
},
|
||||||
"flags": {}
|
"flags": {}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "weapons",
|
||||||
|
"label": "Weapons",
|
||||||
|
"system": "fvtt-cthulhu-eternal",
|
||||||
|
"path": "packs-system/weapons",
|
||||||
|
"type": "Item",
|
||||||
|
"ownership": {
|
||||||
|
"PLAYER": "OBSERVER",
|
||||||
|
"ASSISTANT": "OWNER"
|
||||||
|
},
|
||||||
|
"flags": {}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "rituals",
|
"name": "rituals",
|
||||||
"label": "Rituals",
|
"label": "Rituals",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
{{formField systemFields.settings value=system.settings localize=true}}
|
{{formField systemFields.settings value=system.settings localize=true}}
|
||||||
{{formField systemFields.protection value=system.protection}}
|
{{formField systemFields.protection value=system.protection}}
|
||||||
{{formField systemFields.resourceLevel value=system.resourceLevel}}
|
{{formField systemFields.resourceLevel value=system.resourceLevel}}
|
||||||
|
{{formField systemFields.equipped value=system.equipped}}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,21 +8,33 @@
|
|||||||
{{#if weapon.system.selectiveFireChoice}}
|
{{#if weapon.system.selectiveFireChoice}}
|
||||||
<li>{{weapon.system.selectiveFireChoiceLabel}}</li>
|
<li>{{weapon.system.selectiveFireChoiceLabel}}</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if weapon.system.killRadius}}
|
{{#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)}}
|
||||||
|
<li>{{localize "CTHULHUETERNAL.Label.armorPiercing"}} : {{weapon.system.armorPiercing}}</li>
|
||||||
|
{{/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="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>
|
||||||
|
|||||||
+170
-48
@@ -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}} WP spent</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,88 +37,108 @@
|
|||||||
{{/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 isWorn}}
|
||||||
|
<li class="orange-warning"><i
|
||||||
|
class="fa-solid fa-triangle-exclamation"
|
||||||
|
></i>
|
||||||
|
{{localize "CTHULHUETERNAL.Label.wornWeaponWarning"}}</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"}} : {{modifier}}%</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
|
||||||
{{#if (eq rollType "weapon")}}
|
"CTHULHUETERNAL.Label.criticalSuccess"
|
||||||
{{#if (eq weapon.system.weaponType "rangedfirearm")}}
|
}}
|
||||||
<a class="damage-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-gun"></i></a>
|
|
||||||
{{else}}
|
|
||||||
<a class="damage-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-sword"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq rollType "skill") }}
|
|
||||||
{{#if rollItem.system.isHealing}}
|
|
||||||
<a class="healing-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollHealing"}}"><i class="fa-solid fa-heart"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
{{else}}
|
{{else}}
|
||||||
<li class="result-success">
|
<li class="result-success">
|
||||||
{{localize "CTHULHUETERNAL.Label.success"}}
|
{{localize "CTHULHUETERNAL.Label.success"}}
|
||||||
{{#if isNudge}}
|
|
||||||
<a class="nudge-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollNudge"}}"><i class="fa-solid fa-circle-sort-down"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq weapon.system.weaponType "rangedfirearm")}}
|
|
||||||
<a class="damage-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-gun"></i></a>
|
|
||||||
{{else}}
|
|
||||||
<a class="damage-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollDamage"}}"><i class="fa-solid fa-sword"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq rollType "skill") }}
|
|
||||||
{{#if rollItem.system.isHealing}}
|
|
||||||
<a class="healing-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollHealing"}}"><i class="fa-solid fa-heart"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
</li>
|
</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{/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
|
||||||
{{#if (eq rollType "skill") }}
|
"CTHULHUETERNAL.Label.criticalFailure"
|
||||||
{{#if rollItem.system.isHealing}}
|
}}
|
||||||
<a class="healing-roll" data-tooltip="{{localize "CTHULHUETERNAL.Label.rollHealing"}}"><i class="fa-solid fa-heart"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
</li>
|
</li>
|
||||||
{{else}}
|
{{else}}
|
||||||
<li class="result-failure">
|
<li class="result-failure">
|
||||||
{{localize "CTHULHUETERNAL.Label.failure"}}
|
{{localize "CTHULHUETERNAL.Label.failure"}}
|
||||||
{{#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}}
|
{{/if}}
|
||||||
|
|
||||||
|
<!-- {{#if isAttackRoll}}
|
||||||
|
{{#if defenseRoll}}
|
||||||
|
<li>{{localize "CTHULHUETERNAL.Label.defenseRoll"}}</li>
|
||||||
|
{{#if attackSuccess}}
|
||||||
|
<li class="result-success">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.attackSuccess"
|
||||||
|
}}</li>
|
||||||
|
{{else}}
|
||||||
|
<li class="result-failure">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.attackFailure"
|
||||||
|
}}</li>
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
{{#if targetId}}
|
||||||
|
<li class="orange-warning">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.noDefenseRoll"
|
||||||
|
}}</li>
|
||||||
|
{{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}}
|
||||||
@@ -121,4 +149,98 @@
|
|||||||
{{{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 (eq rollType "weapon")}}
|
||||||
|
{{#if isWorn}}
|
||||||
|
<a
|
||||||
|
class="worn-weapon-check chat-action-button"
|
||||||
|
data-weapon-id="{{weapon.id}}"
|
||||||
|
data-tooltip="{{localize 'CTHULHUETERNAL.Label.wornWeaponCheck'}}"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-dice"></i>
|
||||||
|
</a>
|
||||||
|
{{/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>
|
||||||
@@ -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,18 +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 weapon.system.killRadius}}
|
{{#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 ammoUsed}}
|
{{#if (gt weapon.system.armorPiercing 0)}}
|
||||||
<li>{{localize "CTHULHUETERNAL.Label.ammoUsed"}}: {{ammoUsed}} / {{weapon.system.ammo.value}}</li>
|
<li>{{localize "CTHULHUETERNAL.Label.armorPiercing"}}
|
||||||
|
:
|
||||||
|
{{weapon.system.armorPiercing}}</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<li class="result-non-lethal">{{localize "CTHULHUETERNAL.Label.damageMessage"}}: <strong>{{rollResult}}</strong></li>
|
{{#if (gt weapon.system.penetration 0)}}
|
||||||
|
<li>{{localize "CTHULHUETERNAL.Label.penetration"}}
|
||||||
|
:
|
||||||
|
{{weapon.system.penetration}}</li>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if ammoUsed}}
|
||||||
|
<li>{{localize "CTHULHUETERNAL.Label.ammoUsed"}}:
|
||||||
|
{{ammoUsed}}
|
||||||
|
/
|
||||||
|
{{weapon.system.ammo.value}}</li>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<div class="{{cssClass}}">
|
||||||
|
<div class="chat-san-request">
|
||||||
|
<ul>
|
||||||
|
<li><strong>{{localize "CTHULHUETERNAL.Label.SANLossNone"}}</strong></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<div class="{{cssClass}}">
|
||||||
|
<div class="chat-san-request">
|
||||||
|
<ul>
|
||||||
|
<li><strong>{{localize "CTHULHUETERNAL.Label.SANLossUnnatural"}}</strong></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
<div class="{{cssClass}}">
|
<div class="{{cssClass}}">
|
||||||
<div class="chat-san-request">
|
<div class="chat-san-request">
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>{{localize "CTHULHUETERNAL.Label.SANTest"}}</strong></li>
|
{{#if rollData.isSuccess}}
|
||||||
|
<li><strong>{{localize "CTHULHUETERNAL.Label.SANTestSuccess"}}</strong></li>
|
||||||
|
{{else}}
|
||||||
|
<li><strong>{{localize "CTHULHUETERNAL.Label.SANTestFailure"}}</strong></li>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<li class="san-loose-buttons">
|
<li class="san-loose-buttons">
|
||||||
<button class="san-loose" data-san-value="0">0</button>
|
<button class="san-loose" data-san-value="0">0</button>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend>
|
<legend>{{localize "CTHULHUETERNAL.Label.description"}}</legend>
|
||||||
{{formInput systemFields.description enriched=enrichedDescriptionw value=system.description name="system.description" toggled=true}}
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
@@ -9,18 +9,71 @@
|
|||||||
{{#each weapons as |item|}}
|
{{#each weapons as |item|}}
|
||||||
{{!log 'weapon' this}}
|
{{!log 'weapon' this}}
|
||||||
<div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
|
<div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
|
||||||
|
<!-- content -->
|
||||||
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
||||||
<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
|
<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
|
||||||
<div class="name rollable" data-roll-type="weapon" data-tooltip="{{{item.system.description}}}">
|
<div class="name rollable" data-roll-type="weapon" data-tooltip="{{{item.system.description}}}">
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="damage" data-tooltip="{{localize 'CTHULHUETERNAL.Tooltip.rollDamage'}}">
|
||||||
|
{{#if (eq system.lethality 0)}}
|
||||||
<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
|
<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
|
||||||
<a class="damage rollable" data-item-id="{{item.id}}" data-action="roll" data-roll-type="damage"
|
|
||||||
|
{{#if item.system.hasDamageDistance}}
|
||||||
|
{{#each item.system.damageDistance as |damageDistance|}}
|
||||||
|
{{#if (gt damageDistance.distance 0)}}
|
||||||
|
<a class="rollable" data-item-id="{{item.id}}" data-action="roll" data-roll-type="damage"
|
||||||
|
data-roll-value="{{damageDistance.damage}}" >
|
||||||
|
<span class="damage-distance">{{damageDistance.distance}}:{{damageDistance.damage}} </span>
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
<a class="rollable" data-item-id="{{item.id}}" data-action="roll" data-roll-type="damage"
|
||||||
data-roll-value="{{item.system.damage}}" >
|
data-roll-value="{{item.system.damage}}" >
|
||||||
{{localize "CTHULHUETERNAL.Label.damageShort"}} :
|
{{item.system.damage}}
|
||||||
{{item.system.damage}}</a>
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
N/A
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if (gt system.baseRange 0)}}
|
||||||
|
<span class="range" data-tooltip="CTHULHUETERNAL.Label.baseRange">{{item.system.baseRange}} {{item.system.rangeUnit}}</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="range">{{localize "CTHULHUETERNAL.Label.melee"}}</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if (gt system.lethality 0)}}
|
||||||
|
<a class="lethality rollable" data-item-id="{{item.id}}" data-action="roll" data-roll-type="damage"
|
||||||
|
data-tooltip="CTHULHUETERNAL.Label.Lethality" >
|
||||||
|
<img src="systems/fvtt-cthulhu-eternal/assets/ui/d100.svg" class="d100" />
|
||||||
|
{{item.system.lethality}}%
|
||||||
|
</a>
|
||||||
|
{{else}}
|
||||||
|
<span class="lethality" data-tooltip="CTHULHUETERNAL.Label.Lethality">-</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if (gt system.killRadius 0)}}
|
||||||
|
<span class="lethality" data-tooltip="CTHULHUETERNAL.Label.killRadius" >{{item.system.killRadius}}</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="lethality" data-tooltip="CTHULHUETERNAL.Label.killRadius">-</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if (gt system.armorPiercing 0)}}
|
||||||
|
<span class="lethality" data-tooltip="CTHULHUETERNAL.Label.armorPiercing" >{{item.system.armorPiercing}}</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="lethality" data-tooltip="CTHULHUETERNAL.Label.armorPiercing">-</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if (eq system.weaponType "rangedfirearm")}}
|
||||||
|
<span class="ammo" data-tooltip="CTHULHUETERNAL.Label.Ammo" >{{item.system.ammo.value}}/{{item.system.ammo.max}}</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="ammo" data-tooltip="CTHULHUETERNAL.Label.Ammo">N/A</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
||||||
@@ -28,6 +81,8 @@
|
|||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="empty-state">{{localize "CTHULHUETERNAL.Label.noWeapons"}}</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
@@ -46,6 +101,13 @@
|
|||||||
{{item.name}}
|
{{item.name}}
|
||||||
</div>
|
</div>
|
||||||
<span class="protection">{{localize "CTHULHUETERNAL.Label.armor"}} : {{item.system.protection}}</span>
|
<span class="protection">{{localize "CTHULHUETERNAL.Label.armor"}} : {{item.system.protection}}</span>
|
||||||
|
<a class="equipped-toggle {{#if item.system.equipped}}active{{/if}}"
|
||||||
|
data-action="toggleEquipped"
|
||||||
|
data-item-id="{{item.id}}"
|
||||||
|
data-item-uuid="{{item.uuid}}"
|
||||||
|
data-tooltip="{{#if item.system.equipped}}{{localize 'CTHULHUETERNAL.Label.equipped'}}{{else}}{{localize 'CTHULHUETERNAL.Label.unequipped'}}{{/if}}">
|
||||||
|
<i class="fas {{#if item.system.equipped}}fa-shield-halved{{else}}fa-shield{{/if}}"></i>
|
||||||
|
</a>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
<a data-tooltip="{{localize 'CTHULHUETERNAL.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
|
||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
|
||||||
@@ -53,6 +115,8 @@
|
|||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="empty-state">{{localize "CTHULHUETERNAL.Label.noArmors"}}</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
@@ -77,6 +141,8 @@
|
|||||||
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="empty-state">{{localize "CTHULHUETERNAL.Label.noGears"}}</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
<a data-tooltip="{{localize 'CTHULHUETERNAL.Delete'}}" data-action="delete" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="empty-state">{{localize "CTHULHUETERNAL.Label.noSkills"}}</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|||||||
+174
-14
@@ -9,40 +9,197 @@
|
|||||||
|
|
||||||
{{#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}}
|
||||||
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Storage"}} : {{rollItem.storage}} <input type="checkbox" data-action="selectStorage" {{checked rollItem.enableStorage}}></div>
|
({{mul initialScore 5}}%)</span></div>
|
||||||
|
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Hand"}}
|
||||||
|
:
|
||||||
|
{{rollItem.hand}}
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
data-action="selectHand"
|
||||||
|
{{checked rollItem.enableHand}}
|
||||||
|
/></div>
|
||||||
|
<div class="dialog-skill">{{localize "CTHULHUETERNAL.Label.Stowed"}}
|
||||||
|
:
|
||||||
|
{{rollItem.stowed}}
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
data-action="selectStowed"
|
||||||
|
{{checked rollItem.enableStowed}}
|
||||||
|
/></div>
|
||||||
|
<div class="dialog-skill">
|
||||||
|
{{localize "CTHULHUETERNAL.Label.Storage"}}
|
||||||
|
:
|
||||||
|
{{rollItem.storage}}
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
data-action="selectStorage"
|
||||||
|
{{checked rollItem.enableStorage}}
|
||||||
|
/>
|
||||||
|
</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>
|
{{#if isJunk}}
|
||||||
{{#if weapon.system.hasSelectiveFire}}
|
<div class="dialog-skill red-warning">{{localize
|
||||||
<div class="dialog-skill">Selective Fire :
|
"CTHULHUETERNAL.Label.JunkWeapon"
|
||||||
<select name="selectiveFireChoice" class="roll-skill-modifier">
|
}}</div>
|
||||||
{{selectOptions choiceSelectiveFire localize=true selected=selectiveFireChoice nameAttr="id" labelAttr="label"}}
|
{{/if}}
|
||||||
|
{{#if isWorn}}
|
||||||
|
<div class="dialog-skill orange-warning">{{localize
|
||||||
|
"CTHULHUETERNAL.Label.WornWeapon"
|
||||||
|
}}</div>
|
||||||
|
{{/if}}
|
||||||
|
<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")}}
|
||||||
|
<div class="dialog-skill">
|
||||||
|
{{localize "CTHULHUETERNAL.Label.targetMove"}}
|
||||||
|
<select name="meleeTargetMoveChoice" class="roll-skill-modifier">
|
||||||
|
{{selectOptions
|
||||||
|
choiceMeleeTargetMove
|
||||||
|
localize=true
|
||||||
|
selected=meleeTargetMoveChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#if isRangedWeapon}}
|
||||||
|
<div class="dialog-skill">
|
||||||
|
{{localize "CTHULHUETERNAL.Label.rangedRange"}}
|
||||||
|
<select name="rangedRangeChoice" class="roll-skill-modifier">
|
||||||
|
{{selectOptions
|
||||||
|
choiceRangedRange
|
||||||
|
localize=true
|
||||||
|
selected=rangedRangeChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-skill">
|
||||||
|
{{localize "CTHULHUETERNAL.Label.targetMove"}}
|
||||||
|
<select name="rangedTargetMoveChoice" class="roll-skill-modifier">
|
||||||
|
{{selectOptions
|
||||||
|
choiceRangedTargetMove
|
||||||
|
localize=true
|
||||||
|
selected=rangedTargetMoveChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dialog-skill">
|
||||||
|
{{localize "CTHULHUETERNAL.Label.aimingLastRound"}}
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="aimingLastRound"
|
||||||
|
name="aimingLastRound"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{{#if weapon.system.hasSight}}
|
||||||
|
<div class="dialog-skill">
|
||||||
|
{{localize "CTHULHUETERNAL.Label.aimingWithSight"}}
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="aimingWithSight"
|
||||||
|
name="aimingWithSight"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="dialog-skill">
|
||||||
|
{{localize "CTHULHUETERNAL.Label.visibility"}}
|
||||||
|
<select name="visibilityChoice" class="roll-skill-modifier">
|
||||||
|
{{selectOptions
|
||||||
|
choiceVisibility
|
||||||
|
localize=true
|
||||||
|
selected=visibilityChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-skill">
|
||||||
|
{{localize "CTHULHUETERNAL.Label.attackerState"}}
|
||||||
|
<select name="attackerStateChoice" class="roll-skill-modifier">
|
||||||
|
{{selectOptions
|
||||||
|
choiceAttackerState
|
||||||
|
localize=true
|
||||||
|
selected=attackerStateChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-skill">
|
||||||
|
{{localize "CTHULHUETERNAL.Label.targetSize"}}
|
||||||
|
<select name="targetSizeChoice" class="roll-skill-modifier">
|
||||||
|
{{selectOptions
|
||||||
|
choiceTargetSize
|
||||||
|
localize=true
|
||||||
|
selected=targetSizeChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if weapon.system.hasSelectiveFire}}
|
||||||
|
<div class="dialog-skill">Selective Fire :
|
||||||
|
<select name="selectiveFireChoice" class="roll-skill-modifier">
|
||||||
|
{{selectOptions
|
||||||
|
choiceSelectiveFire
|
||||||
|
localize=true
|
||||||
|
selected=selectiveFireChoice
|
||||||
|
valueAttr="id"
|
||||||
|
labelAttr="label"
|
||||||
|
}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#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>
|
||||||
@@ -55,7 +212,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>
|
||||||
|
|||||||
+31
-3
@@ -12,32 +12,60 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{formField systemFields.state value=system.state localize=true}}
|
{{formField systemFields.state value=system.state localize=true}}
|
||||||
|
{{formField systemFields.isStunning value=system.isStunning localize=true}}
|
||||||
|
|
||||||
|
<div class="flexrow">
|
||||||
{{formField systemFields.hasDirectSkill value=system.hasDirectSkill }}
|
{{formField systemFields.hasDirectSkill value=system.hasDirectSkill }}
|
||||||
{{#if system.hasDirectSkill}}
|
{{#if system.hasDirectSkill}}
|
||||||
{{formField systemFields.directSkillValue value=system.directSkillValue }}
|
{{formField systemFields.directSkillValue value=system.directSkillValue }}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
{{formField systemFields.applyDamageBonus value=system.applyDamageBonus}}
|
<div class="flexrow">
|
||||||
|
{{formField systemFields.hasDamageDistance value=system.hasDamageDistance localize=true}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if system.hasDamageDistance}}
|
||||||
|
{{#each system.damageDistance as |damageDistance idx|}}
|
||||||
|
<div class="flexrow">
|
||||||
|
<label class="damage-distance">Distance</label><input type="number" name="system.damageDistance.{{idx}}.distance" value="{{damageDistance.distance}}" min="0" />
|
||||||
|
<label>Damage</label><input type="text" name="system.damageDistance.{{idx}}.damage" value="{{damageDistance.damage}}" />
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
<div class="flexrow">
|
||||||
{{formField systemFields.damage value=system.damage}}
|
{{formField systemFields.damage value=system.damage}}
|
||||||
|
{{formField systemFields.applyDamageBonus value=system.applyDamageBonus}}
|
||||||
|
</div>
|
||||||
{{#if isRanged}}
|
{{#if isRanged}}
|
||||||
|
<div class="flexrow">
|
||||||
{{formField systemFields.baseRange value=system.baseRange}}
|
{{formField systemFields.baseRange value=system.baseRange}}
|
||||||
{{formField systemFields.rangeUnit value=system.rangeUnit localize=true}}
|
{{formField systemFields.rangeUnit value=system.rangeUnit localize=true}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isFireArm}}
|
{{#if isFireArm}}
|
||||||
|
<div class="flexrow">
|
||||||
{{formField systemFields.hasSelectiveFire value=system.hasSelectiveFire}}
|
{{formField systemFields.hasSelectiveFire value=system.hasSelectiveFire}}
|
||||||
|
{{formField systemFields.hasSight value=system.hasSight}}
|
||||||
|
</div>
|
||||||
|
<div class="flexrow">
|
||||||
{{formField systemFields.ammo.fields.value value=system.ammo.value}}
|
{{formField systemFields.ammo.fields.value value=system.ammo.value}}
|
||||||
{{formField systemFields.ammo.fields.max value=system.ammo.max}}
|
{{formField systemFields.ammo.fields.max value=system.ammo.max}}
|
||||||
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="flexrow">
|
||||||
{{formField systemFields.lethality value=system.lethality}}
|
{{formField systemFields.lethality value=system.lethality}}
|
||||||
{{formField systemFields.killRadius value=system.killRadius}}
|
{{formField systemFields.killRadius value=system.killRadius}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flexrow">
|
||||||
{{formField systemFields.armorPiercing value=system.armorPiercing}}
|
{{formField systemFields.armorPiercing value=system.armorPiercing}}
|
||||||
|
|
||||||
{{formField systemFields.resourceLevel value=system.resourceLevel}}
|
{{formField systemFields.resourceLevel value=system.resourceLevel}}
|
||||||
|
</div>
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
|||||||
Reference in New Issue
Block a user