Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cf4401fa3 | ||
|
|
69e96b6610 | ||
|
|
87b54ac3ef | ||
|
|
08c0059ca5 | ||
|
|
bc615d05fa | ||
|
|
da0bdf453e | ||
|
|
dfef6d4092 | ||
|
|
5ffaa062fc | ||
|
|
14b47a5381 | ||
|
|
d213d179dc | ||
|
|
42708d54e8 | ||
|
|
386a62ef55 | ||
|
|
babbafffef | ||
|
|
3eb623120a | ||
|
|
d2f9b6891e | ||
|
|
a00fa80607 | ||
|
|
95d031c7a8 | ||
|
|
cb0696f662 | ||
|
|
db5d5b62aa | ||
|
|
6b322be3f4 | ||
|
|
48b17be458 | ||
|
|
7d7d62f950 | ||
|
|
fa03e5152b | ||
|
|
a823d89344 | ||
|
|
47eb508dd4 | ||
|
|
1cc496ad77 | ||
|
|
e0cb2bf235 | ||
|
|
8a22706ad2 | ||
|
|
0cb0a2f3ea | ||
|
|
fc56afa28e | ||
|
|
768fda1752 | ||
|
|
694333a1cb | ||
|
|
b54f58c9ce | ||
|
|
6a9e84f126 | ||
|
|
84b160b50d | ||
|
|
78568ded55 | ||
|
|
b59fde880d | ||
|
|
7969c5f526 | ||
|
|
ca5a164f7f | ||
|
|
45ae96724e | ||
|
|
7f987a7682 | ||
|
|
d88d985575 | ||
|
|
9f8a24bd68 | ||
|
|
4e629efe12 | ||
|
|
e542dd390b | ||
|
|
a517a92488 | ||
|
|
30da4f3a02 | ||
|
|
931a28fbfe | ||
|
|
4350506e09 | ||
|
|
68577737fc | ||
|
|
30f71e31cd |
32
CHANGELOG.md
32
CHANGELOG.md
@@ -1,5 +1,37 @@
|
||||
# Changelog
|
||||
|
||||
## 1.2.1 - Praised be Firefox
|
||||
- Fix dice swap on firefox that overflowed on the top and bottom of the RnK dialog
|
||||
- Fix new items list on firefox who deformed the sheets
|
||||
|
||||
## 1.2.0 - Roll n Keep
|
||||
- Added Roll n Keep 1st iteration !
|
||||
- Ability to Keep, Discard, Re-roll and Swap:
|
||||
- Keep: Keep the die for the next step, if it's an explosive one, automatically roll a new die
|
||||
- Discard: Self explain, do not keep this die for the next step.
|
||||
- Re-roll: Replace this die by a new roll (Usually Advantage & Disadvantage stuff). When a reroll is selected, all the dice in the current step will be tag as keep by default.
|
||||
- Swap (Face): Set a desired face for this die (Some weird techniques stuff)
|
||||
- Usage:
|
||||
- All these actions are done by drag and drop a die result into a target action
|
||||
- A colored icon symbolize the choice made on the dice
|
||||
- You can always change choices for the current step until you clic next
|
||||
- Please note all dice without choice will be discarded for the next step
|
||||
- The GM has the ability to undo choices by left-clicking in the status headers
|
||||
- Limitation: The roll need to only have L5R dice in it (no mixed regular + L5R)
|
||||
- Fix image's behavior on create for all items sub classes
|
||||
- Click on rings in the PC/PNC sheet now open the DicePicker with the selected ring
|
||||
- Added a booster for loading compendium's core items (speed up 20Q)
|
||||
- Added confirm dialog on item's deletion (Hold "ctrl" on the click, if you want to bypass it)
|
||||
- Added "Sleep" & "Scene End" buttons in "GM ToolBox" (old "difficulty" box)
|
||||
- Token's bar:
|
||||
- The strife bar is now displayed in red if the actor is compromised
|
||||
- Added an option, off by default, to reverse the fatigue's token bar (thanks to Jzrzmy)
|
||||
- Added an option, on by default, to set the TN to 1 when the encounter type is selected (Intrigue, Duel, Skirmish or Mass battle)
|
||||
- Split Techniques & Items by category in actor sheet (pc & npc) for better readability
|
||||
- Armor & Weapon added in the conflict tab now set the "equipped" property by default
|
||||
- Added Tabs on NPC sheets
|
||||
- New styles for dice results
|
||||
|
||||
## 1.1.2 - One Compendium to bring them all
|
||||
- Added compendiums (Thanks to Stéfano Fara for the English version !) Partial for French as PoW and CR are not translated yet
|
||||
- Shadowlands
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
},
|
||||
{
|
||||
"id": "Robes of Judgment",
|
||||
"name": "Robes of Judgment (WIP)",
|
||||
"name": "Robes de jugement",
|
||||
"description": "",
|
||||
"book_reference": "Les Royaumes Célestes p.97"
|
||||
},
|
||||
|
||||
@@ -4,7 +4,16 @@
|
||||
"Maintainers": ["Team L5R"]
|
||||
},
|
||||
"SETTINGS": {
|
||||
"None": "No option"
|
||||
"None": "No option",
|
||||
"ReverseFatigueBar": "Reverse token fatigue bar",
|
||||
"RollNKeep": {
|
||||
"DeleteOldMessage": "RnK Delete previous chat message",
|
||||
"DeleteOldMessageHint": "Choose to keep or delete the previous message for a RnK series"
|
||||
},
|
||||
"Initiative": {
|
||||
"SetTn1OnTypeChange": "Set TN to 1 on encounter change",
|
||||
"SetTn1OnTypeChangeHint": "Set the TN to 1 when the encounter type is selected (Intrigue, Duel, Skirmish or Mass battle)"
|
||||
}
|
||||
},
|
||||
"ACTOR": {
|
||||
"TypeCharacter": "Player Character",
|
||||
@@ -21,10 +30,9 @@
|
||||
},
|
||||
"l5r5e": {
|
||||
"global": {
|
||||
"ok": "OK",
|
||||
"add": "Add",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"delete_confirm": "Are you sure you want to delete '{name}' ?",
|
||||
"drop_here": "Drop here",
|
||||
"edge_translation_disclaimer": ""
|
||||
},
|
||||
@@ -83,14 +91,19 @@
|
||||
"difficulty_hidden": "TN ???",
|
||||
"dicepicker": "Dice Picker",
|
||||
"void_point_used": "Void point used",
|
||||
"assistance_used": "Skill assistance used",
|
||||
"roll_n_keep": "Roll & Keep",
|
||||
"initiative_roll": "Initiative roll"
|
||||
"initiative_roll": "Initiative roll",
|
||||
"success_text": "Success!",
|
||||
"bonus_text": "bonus successes",
|
||||
"fail_text": "Fail!"
|
||||
},
|
||||
"dicepicker": {
|
||||
"difficulty_title": "Difficulty",
|
||||
"difficulty_hidden_label": "Hide TN",
|
||||
"use_void_point_label": "Spend a",
|
||||
"void_point_tooltip": "Void point",
|
||||
"skill_assistance_label": "Assistance",
|
||||
"roll_label": "Roll",
|
||||
"bt_add_macro": "Add a macro"
|
||||
},
|
||||
@@ -98,10 +111,19 @@
|
||||
"title": "L5R Roll & Keep",
|
||||
"discard_drop_here": "Discard",
|
||||
"reroll_drop_here": "Re-roll",
|
||||
"reroll_chat": "Re-rolled dice",
|
||||
"swap_drop_here": "Swap",
|
||||
"keep_drop_here": "Keep",
|
||||
"keep_chat": "New roll from an exploding die",
|
||||
"bt_validate": "Finalize"
|
||||
"bt_validate": "Finalize this step",
|
||||
"undo": "[GM] Undo the last step choices"
|
||||
},
|
||||
"gm_toolbox": {
|
||||
"title": "GM ToolBox",
|
||||
"difficulty_hidden": "Change difficulty visibility",
|
||||
"difficulty": "Change difficulty (right: add, left: subtract, middle: TN 2)",
|
||||
"sleep": "Comfortable rest for all characters (Remove Water x2 fatigue)",
|
||||
"sleep_info": "The characters had a good night's sleep.",
|
||||
"scene_end": "End of scene (Conflict and Fatigue half reset for all characters)",
|
||||
"scene_end_info": "The tension of the scene finally drops."
|
||||
},
|
||||
"max": "Max",
|
||||
"current": "Current",
|
||||
|
||||
@@ -4,7 +4,16 @@
|
||||
"Maintainers": ["Team L5R"]
|
||||
},
|
||||
"SETTINGS": {
|
||||
"None": "Sin opción"
|
||||
"None": "Sin opción",
|
||||
"ReverseFatigueBar": "Invertir la barra de fatiga de los token",
|
||||
"RollNKeep": {
|
||||
"DeleteOldMessage": "RnK Delete previous chat message",
|
||||
"DeleteOldMessageHint": "Choose to keep or delete the previous message for a RnK series"
|
||||
},
|
||||
"Initiative": {
|
||||
"SetTn1OnTypeChange": "Set TN to 1 on encounter change",
|
||||
"SetTn1OnTypeChangeHint": "Set the TN to 1 when the encounter type is selected (Intrigue, Duel, Skirmish or Mass battle)"
|
||||
}
|
||||
},
|
||||
"ACTOR": {
|
||||
"TypeCharacter": "Personaje jugador",
|
||||
@@ -21,10 +30,9 @@
|
||||
},
|
||||
"l5r5e": {
|
||||
"global": {
|
||||
"ok": "OK",
|
||||
"add": "Añadir",
|
||||
"edit": "Editar",
|
||||
"delete": "Borrar",
|
||||
"delete_confirm": "Are you sure you want to delete '{name}' ?",
|
||||
"drop_here": "Dejar caer aquí",
|
||||
"edge_translation_disclaimer": "Edge Studio nos da su permiso para ofrecer este módulo a la comunidad, pero tanto los textos así como los códigos que lo constituyen no tienen su aprobación explícita."
|
||||
},
|
||||
@@ -83,14 +91,19 @@
|
||||
"difficulty_hidden": "NO ???",
|
||||
"dicepicker": "Dice Picker",
|
||||
"void_point_used": "Punto de vacío utilizado",
|
||||
"assistance_used": "Skill assistance used",
|
||||
"roll_n_keep": "Tirar y guardar",
|
||||
"initiative_roll": "Tirada de Iniciativa"
|
||||
"initiative_roll": "Tirada de Iniciativa",
|
||||
"success_text": "Éxitos!",
|
||||
"bonus_text": "bonus successes",
|
||||
"fail_text": "Fail!"
|
||||
},
|
||||
"dicepicker": {
|
||||
"difficulty_title": "Dificultad",
|
||||
"difficulty_hidden_label": "Ocultar NO",
|
||||
"use_void_point_label": "Gasta un",
|
||||
"void_point_tooltip": "Punto de vacío",
|
||||
"skill_assistance_label": "Assistance",
|
||||
"roll_label": "Tirar",
|
||||
"bt_add_macro": "Añadir una macro"
|
||||
},
|
||||
@@ -98,10 +111,19 @@
|
||||
"title": "L5R Roll & Keep",
|
||||
"discard_drop_here": "Descartar",
|
||||
"reroll_drop_here": "Relanzar",
|
||||
"reroll_chat": "Dados relanzados",
|
||||
"swap_drop_here": "Swap",
|
||||
"keep_drop_here": "Guardar",
|
||||
"keep_chat": "Nueva tirada de un dado relanzable",
|
||||
"bt_validate": "Finalizar"
|
||||
"bt_validate": "Finalizar",
|
||||
"undo": "[GM] Undo the last step choices"
|
||||
},
|
||||
"gm_toolbox": {
|
||||
"title": "GM ToolBox",
|
||||
"difficulty_hidden": "Change difficulty visibility",
|
||||
"difficulty": "Change difficulty (right: add, left: subtract, middle: TN 2)",
|
||||
"sleep": "Comfortable rest for all characters (Remove Water x2 fatigue)",
|
||||
"sleep_info": "The characters had a good night's sleep.",
|
||||
"scene_end": "End of scene (Conflict and Fatigue half reset for all characters)",
|
||||
"scene_end_info": "The tension of the scene finally drops."
|
||||
},
|
||||
"max": "Máx",
|
||||
"current": "Actuales",
|
||||
|
||||
@@ -4,7 +4,16 @@
|
||||
"Maintainers": ["Team L5R"]
|
||||
},
|
||||
"SETTINGS": {
|
||||
"None": "Aucune option"
|
||||
"None": "Aucune option",
|
||||
"ReverseFatigueBar": "Inverser la barre de fatigue des token",
|
||||
"RollNKeep": {
|
||||
"DeleteOldMessage": "RnK Supprime le précédent message du chat",
|
||||
"DeleteOldMessageHint": "Si coché, on supprime le message précédent pour la série de jets via le RnK"
|
||||
},
|
||||
"Initiative": {
|
||||
"SetTn1OnTypeChange": "ND 1 à la sélection du type de rencontre",
|
||||
"SetTn1OnTypeChangeHint": "Met le ND à 1 lorsqu'on modifie le type de rencontre (Intrigue, Duel, Escarmouche ou Bataille rangée)"
|
||||
}
|
||||
},
|
||||
"ACTOR": {
|
||||
"TypeCharacter": "Personnage Joueur",
|
||||
@@ -21,10 +30,9 @@
|
||||
},
|
||||
"l5r5e": {
|
||||
"global": {
|
||||
"ok": "OK",
|
||||
"add": "Ajouter",
|
||||
"edit": "Modifier",
|
||||
"delete": "Supprimer",
|
||||
"delete_confirm": "Etes-vous sûr de vouloir supprimer '{name}' ?",
|
||||
"drop_here": "Déposez ici",
|
||||
"edge_translation_disclaimer": ""
|
||||
},
|
||||
@@ -83,25 +91,39 @@
|
||||
"difficulty_hidden": "ND ???",
|
||||
"dicepicker": "Dice Picker",
|
||||
"void_point_used": "Point de vide utilisé",
|
||||
"assistance_used": "Assistance de compétence utilisée",
|
||||
"roll_n_keep": "Roll & Keep",
|
||||
"initiative_roll": "Jet d'initiative"
|
||||
"initiative_roll": "Jet d'initiative",
|
||||
"success_text": "Succès !",
|
||||
"bonus_text": "succès bonus",
|
||||
"fail_text": "Échec !"
|
||||
},
|
||||
"dicepicker": {
|
||||
"difficulty_title": "Difficulté",
|
||||
"difficulty_hidden_label": "ND Caché",
|
||||
"use_void_point_label": "Dépenser un",
|
||||
"void_point_tooltip": "Point de Vide",
|
||||
"skill_assistance_label": "Assistance",
|
||||
"roll_label": "Lancer",
|
||||
"bt_add_macro": "Ajouter une macro"
|
||||
},
|
||||
"roll_n_keep": {
|
||||
"title": "L5R Roll & Keep",
|
||||
"discard_drop_here": "Discard",
|
||||
"reroll_drop_here": "Re-roll",
|
||||
"reroll_chat": "Re-rolled dice",
|
||||
"keep_drop_here": "Keep",
|
||||
"keep_chat": "New roll from a exploding dice",
|
||||
"bt_validate": "Finalize"
|
||||
"discard_drop_here": "Abandonner",
|
||||
"reroll_drop_here": "Relancer",
|
||||
"swap_drop_here": "Modifier",
|
||||
"keep_drop_here": "Garder",
|
||||
"bt_validate": "Finaliser cette étape",
|
||||
"undo": "[GM] Annuler les choix de la dernière étape"
|
||||
},
|
||||
"gm_toolbox": {
|
||||
"title": "GM ToolBox",
|
||||
"difficulty_hidden": "Modifier la visibilité de la difficulté",
|
||||
"difficulty": "Modifier la difficulté (droite: ajout, gauche: soustraction, milieu: ND 2)",
|
||||
"sleep": "Repos confortable pour tous les personnages (Enlève Eau x2 de fatigue)",
|
||||
"sleep_info": "Les personnages ont passé une bonne nuit de sommeil.",
|
||||
"scene_end": "Fin de scène (Conflit et Fatigue à moitié pour tous les personnages dont la valeur dépasse ce seuil)",
|
||||
"scene_end_info": "La tension de la scène retombe enfin"
|
||||
},
|
||||
"max": "Max",
|
||||
"current": "Actuel",
|
||||
|
||||
@@ -32,14 +32,14 @@
|
||||
{"_id":"L5RCoreShu000032","name":"Regal Bearing","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"4","bought_at_rank":0,"ring":"water","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.220"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000033","name":"Well of Desire","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"water","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.221"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000034","name":"Shallow Waters","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"water","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.220"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000035","name":"Lady Shinjo’s Speed (Unicorn)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"2","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.222"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000036","name":"Lady Doji’s Decree (Crane)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"2","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.222"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000035","name":"Lady Shinjo’s Speed (Unicorn)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"2","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.222"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/clans/unicorn.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000036","name":"Lady Doji’s Decree (Crane)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"2","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.222"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/clans/crane.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000037","name":"Courtier’s Resolve","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.222"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000038","name":"A Samurai’s Fate","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"4","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.222"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000039","name":"Lord Bayushi’s Whispers (Scorpion)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"2","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.223"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000040","name":"Lord Togashi’s Insight (Dragon)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"2","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.223"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000039","name":"Lord Bayushi’s Whispers (Scorpion)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"2","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.223"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/clans/scorpion.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000040","name":"Lord Togashi’s Insight (Dragon)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"2","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.223"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/clans/dragon.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000041","name":"Rouse the Soul","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"5","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.223"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000042","name":"Lord Akodo’s Roar (Lion)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"2","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.223"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000042","name":"Lord Akodo’s Roar (Lion)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"2","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.223"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/clans/lion.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000043","name":"All Arts Are One","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"3","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Core Rulebook p.222"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000044","name":"Hidden in Smoke","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"4","bought_at_rank":0,"ring":"air","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Court of Stones p.117"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000045","name":"Assess Strengths","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"air","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Court of Stones p.117"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
@@ -52,7 +52,7 @@
|
||||
{"_id":"L5RCoreShu000052","name":"Fun and Games","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"water","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Court of Stones p.119"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000053","name":"Foreseen Need","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"4","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Court of Stones p.119"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000054","name":"Spin the Web (Kolat)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"3","bought_at_rank":0,"ring":"air","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Emerald Empire p.248"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000055","name":"Awe of Heaven (Imperial)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"4","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Emerald Empire p.248"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000055","name":"Awe of Heaven (Imperial)","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"4","bought_at_rank":0,"ring":"void","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Emerald Empire p.248"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/clans/imperial.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000056","name":"Look Out","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"3","bought_at_rank":0,"ring":"earth","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Path of Waves p.92"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000057","name":"Bellow of Resolve","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"earth","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Path of Waves p.92"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
{"_id":"L5RCoreShu000058","name":"Ruse of the Moon's Reflection","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"5","bought_at_rank":0,"ring":"air","technique_type":"shuji","xp_cost":"3","description":"","book_reference":"Path of Waves p.93"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/shuji.svg","effects":[]}
|
||||
|
||||
@@ -12,7 +12,9 @@ export class ActorL5r5e extends Actor {
|
||||
// }
|
||||
|
||||
// Replace default image
|
||||
data.img = `${CONFIG.l5r5e.paths.assets}icons/actors/${data.type}.svg`;
|
||||
if (data.img === undefined) {
|
||||
data.img = `${CONFIG.l5r5e.paths.assets}icons/actors/${data.type}.svg`;
|
||||
}
|
||||
|
||||
// Some tweak on actors token
|
||||
data.token = data.token || {};
|
||||
|
||||
@@ -27,9 +27,81 @@ export class BaseSheetL5r5e extends ActorSheet {
|
||||
sheetData.data.stances = CONFIG.l5r5e.stances;
|
||||
sheetData.data.techniquesList = CONFIG.l5r5e.techniques;
|
||||
|
||||
// Sort Items by name
|
||||
sheetData.items.sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
|
||||
// Split Techniques by types
|
||||
sheetData.data.splitTechniquesList = this._splitTechniques(sheetData);
|
||||
|
||||
// Split Items by types
|
||||
sheetData.data.splitItemsList = this._splitItems(sheetData);
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split Techniques by types for better readability
|
||||
* @private
|
||||
*/
|
||||
_splitTechniques(sheetData) {
|
||||
const out = {};
|
||||
|
||||
// Build the list order
|
||||
[...CONFIG.l5r5e.techniques, ...CONFIG.l5r5e.techniques_school].forEach((tech) => {
|
||||
out[tech] = [];
|
||||
});
|
||||
|
||||
// Add tech the character knows
|
||||
sheetData.items.forEach((item) => {
|
||||
if (item.type === "technique") {
|
||||
out[item.data.technique_type].push(item);
|
||||
}
|
||||
});
|
||||
|
||||
// Remove unused techs
|
||||
Object.keys(out).forEach((tech) => {
|
||||
if (
|
||||
out[tech].length < 1 &&
|
||||
!sheetData.data.techniques[tech] &&
|
||||
!CONFIG.l5r5e.techniques_school.includes(tech)
|
||||
) {
|
||||
delete out[tech];
|
||||
}
|
||||
});
|
||||
|
||||
// Manage school add button
|
||||
sheetData.data.techniques["school_ability"] = out["school_ability"].length === 0;
|
||||
sheetData.data.techniques["mastery_ability"] = out["mastery_ability"].length === 0;
|
||||
|
||||
// Always display "school_ability", but display "mastery_ability" only if rank >= 5
|
||||
if (sheetData.data.identity?.school_rank < 5 && out["mastery_ability"].length === 0) {
|
||||
delete out["mastery_ability"];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split Items by types for better readability
|
||||
* @private
|
||||
*/
|
||||
_splitItems(sheetData) {
|
||||
const out = {
|
||||
weapon: [],
|
||||
armor: [],
|
||||
item: [],
|
||||
};
|
||||
|
||||
sheetData.items.forEach((item) => {
|
||||
if (["item", "armor", "weapon"].includes(item.type)) {
|
||||
out[item.type].push(item);
|
||||
}
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a light sheet if in "limited" state
|
||||
* @override
|
||||
@@ -71,6 +143,7 @@ export class BaseSheetL5r5e extends ActorSheet {
|
||||
|
||||
/**
|
||||
* Handle dropped data on the Actor sheet
|
||||
* @param {Event} event
|
||||
*/
|
||||
async _onDrop(event) {
|
||||
// *** Everything below here is only needed if the sheet is editable ***
|
||||
@@ -185,6 +258,7 @@ export class BaseSheetL5r5e extends ActorSheet {
|
||||
}
|
||||
|
||||
new game.l5r5e.DicePickerDialog({
|
||||
ringId: li.data("ring") || null,
|
||||
skillId: skillId,
|
||||
skillCatId: li.data("skillcat") || null,
|
||||
isInitiativeRoll: li.data("initiative") || false,
|
||||
@@ -207,28 +281,12 @@ export class BaseSheetL5r5e extends ActorSheet {
|
||||
});
|
||||
|
||||
// Equipped / Readied
|
||||
html.find(".equip-readied-control").on("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this._switchEquipReadied(event);
|
||||
});
|
||||
html.find(".equip-readied-control").on("click", this._switchEquipReadied.bind(this));
|
||||
|
||||
// *** Items : add, edit, delete ***
|
||||
html.find(".item-add").on("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this._addSubItem(event);
|
||||
});
|
||||
html.find(`.item-edit`).on("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this._editSubItem(event);
|
||||
});
|
||||
html.find(`.item-delete`).on("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this._deleteSubItem(event);
|
||||
});
|
||||
html.find(".item-add").on("click", this._addSubItem.bind(this));
|
||||
html.find(`.item-edit`).on("click", this._editSubItem.bind(this));
|
||||
html.find(`.item-delete`).on("click", this._deleteSubItem.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,9 +305,13 @@ export class BaseSheetL5r5e extends ActorSheet {
|
||||
|
||||
/**
|
||||
* Add a generic item with sub type
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
async _addSubItem(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const type = $(event.currentTarget).data("item-type");
|
||||
const titles = {
|
||||
item: "l5r5e.items.title_new",
|
||||
@@ -262,7 +324,7 @@ export class BaseSheetL5r5e extends ActorSheet {
|
||||
const created = await this.actor.createEmbeddedEntity("OwnedItem", {
|
||||
name: game.i18n.localize(titles[type]),
|
||||
type: type,
|
||||
img: "icons/svg/mystery-man.svg",
|
||||
img: `${CONFIG.l5r5e.paths.assets}icons/items/${type}.svg`,
|
||||
});
|
||||
const item = this.actor.getOwnedItem(created._id);
|
||||
|
||||
@@ -272,14 +334,37 @@ export class BaseSheetL5r5e extends ActorSheet {
|
||||
item.data.data.bought_at_rank = this.actor.data.data.identity.school_rank;
|
||||
}
|
||||
|
||||
switch (item.data.type) {
|
||||
case "armor": // no break
|
||||
case "weapon":
|
||||
if ($(event.currentTarget).data("item-eqquiped")) {
|
||||
item.data.data.equipped = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case "technique": {
|
||||
// If technique, select the current type
|
||||
const techType = $(event.currentTarget).data("tech-type");
|
||||
if ([...CONFIG.l5r5e.techniques, ...CONFIG.l5r5e.techniques_school].includes(techType)) {
|
||||
item.data.data.technique_type = techType;
|
||||
item.data.img = `${CONFIG.l5r5e.paths.assets}/icons/techs/${techType}.svg`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
item.sheet.render(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a generic item with sub type
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
_editSubItem(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const itemId = $(event.currentTarget).data("item-id");
|
||||
const item = this.actor.getOwnedItem(itemId);
|
||||
item.sheet.render(true);
|
||||
@@ -287,9 +372,13 @@ export class BaseSheetL5r5e extends ActorSheet {
|
||||
|
||||
/**
|
||||
* Delete a generic item with sub type
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
_deleteSubItem(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const itemId = $(event.currentTarget).data("item-id");
|
||||
|
||||
// Remove 1 qty if possible
|
||||
@@ -298,32 +387,48 @@ export class BaseSheetL5r5e extends ActorSheet {
|
||||
return;
|
||||
}
|
||||
|
||||
// Specific advancements, remove 1 to selected ring/skill
|
||||
if (tmpItem.type === "advancement") {
|
||||
const actor = duplicate(this.actor.data.data);
|
||||
const itmData = tmpItem.data.data;
|
||||
if (itmData.advancement_type === "ring") {
|
||||
// Ring
|
||||
actor.rings[itmData.ring] = Math.max(1, actor.rings[itmData.ring] - 1);
|
||||
} else {
|
||||
// Skill
|
||||
const skillCatId = CONFIG.l5r5e.skills.get(itmData.skill);
|
||||
if (skillCatId) {
|
||||
actor.skills[skillCatId][itmData.skill] = Math.max(0, actor.skills[skillCatId][itmData.skill] - 1);
|
||||
const callback = async () => {
|
||||
// Specific advancements, remove 1 to selected ring/skill
|
||||
if (tmpItem.type === "advancement") {
|
||||
const actor = duplicate(this.actor.data.data);
|
||||
const itmData = tmpItem.data.data;
|
||||
if (itmData.advancement_type === "ring") {
|
||||
// Ring
|
||||
actor.rings[itmData.ring] = Math.max(1, actor.rings[itmData.ring] - 1);
|
||||
} else {
|
||||
// Skill
|
||||
const skillCatId = CONFIG.l5r5e.skills.get(itmData.skill);
|
||||
if (skillCatId) {
|
||||
actor.skills[skillCatId][itmData.skill] = Math.max(
|
||||
0,
|
||||
actor.skills[skillCatId][itmData.skill] - 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Update Actor
|
||||
this.actor.update({
|
||||
data: diffObject(this.actor.data.data, actor),
|
||||
});
|
||||
}
|
||||
|
||||
// Update Actor
|
||||
this.actor.update({
|
||||
data: diffObject(this.actor.data.data, actor),
|
||||
});
|
||||
return this.actor.deleteOwnedItem(itemId);
|
||||
};
|
||||
|
||||
// Holing Ctrl = without confirm
|
||||
if (event.ctrlKey) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
return this.actor.deleteOwnedItem(itemId);
|
||||
game.l5r5e.HelpersL5r5e.confirmDeleteDialog(
|
||||
game.i18n.format("l5r5e.global.delete_confirm", { name: tmpItem.name }),
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch "in_curriculum"
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
_switchSubItemCurriculum(event) {
|
||||
@@ -358,9 +463,13 @@ export class BaseSheetL5r5e extends ActorSheet {
|
||||
|
||||
/**
|
||||
* Switch Readied state on a weapon
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
_switchEquipReadied(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const type = $(event.currentTarget).data("type");
|
||||
if (!["equipped", "readied"].includes(type)) {
|
||||
return;
|
||||
|
||||
@@ -49,11 +49,6 @@ export class CharacterSheetL5r5e extends BaseSheetL5r5e {
|
||||
// Split Money
|
||||
sheetData.data.money = this._zeniToMoney(this.actor.data.data.zeni);
|
||||
|
||||
// Sort Items by name
|
||||
sheetData.items.sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
|
||||
// split advancements list by rank, and calculate xp spent
|
||||
this._prepareAdvancement(sheetData);
|
||||
sheetData.data.xp_saved = Math.floor(parseInt(sheetData.data.xp_total) - parseInt(sheetData.data.xp_spent));
|
||||
|
||||
@@ -208,6 +208,7 @@ export class TwentyQuestionsDialog extends FormApplication {
|
||||
html.find("#generate").on("click", async (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$(event.currentTarget).prop("disabled", true);
|
||||
await this.object.toActor(this.actor, flattenObject(this.cache));
|
||||
await this.close({ submit: true, force: true });
|
||||
});
|
||||
|
||||
@@ -41,7 +41,7 @@ export class CombatL5r5e extends Combat {
|
||||
|
||||
// Get score for each combatant
|
||||
const updatedCombatants = [];
|
||||
ids.forEach((combatantId) => {
|
||||
for (const combatantId of ids) {
|
||||
const combatant = game.combat.combatants.find((c) => c._id === combatantId);
|
||||
|
||||
// Skip if combatant already have a initiative value
|
||||
@@ -77,33 +77,49 @@ export class CombatL5r5e extends Combat {
|
||||
formula = createFormula.join("+");
|
||||
}
|
||||
|
||||
const roll = new game.l5r5e.RollL5r5e(formula);
|
||||
roll.actor = combatant.actor;
|
||||
roll.l5r5e.stance = data.stance;
|
||||
roll.l5r5e.skillId = skillId;
|
||||
roll.l5r5e.skillCatId = skillCat;
|
||||
roll.l5r5e.summary.difficulty =
|
||||
messageOptions.difficulty !== undefined ? messageOptions.difficulty : cfg.difficulty;
|
||||
roll.l5r5e.summary.difficultyHidden =
|
||||
messageOptions.difficultyHidden !== undefined
|
||||
? messageOptions.difficultyHidden
|
||||
: cfg.difficultyHidden;
|
||||
roll.l5r5e.summary.voidPointUsed = !!messageOptions.useVoidPoint;
|
||||
let roll;
|
||||
let rnkMessage;
|
||||
const flavor =
|
||||
game.i18n.localize("l5r5e.chatdices.initiative_roll") +
|
||||
" (" +
|
||||
game.i18n.localize(`l5r5e.conflict.initiative.prepared_${isPrepared}`) +
|
||||
")";
|
||||
|
||||
roll.roll();
|
||||
roll.toMessage({
|
||||
flavor:
|
||||
game.i18n.localize("l5r5e.chatdices.initiative_roll") +
|
||||
" (" +
|
||||
game.i18n.localize(`l5r5e.conflict.initiative.prepared_${isPrepared}`) +
|
||||
")",
|
||||
});
|
||||
if (messageOptions.rnkRoll instanceof game.l5r5e.RollL5r5e && ids.length === 1) {
|
||||
// Specific RnK
|
||||
roll = messageOptions.rnkRoll;
|
||||
rnkMessage = await roll.toMessage({ flavor });
|
||||
} else {
|
||||
// Regular
|
||||
roll = new game.l5r5e.RollL5r5e(formula);
|
||||
roll.actor = combatant.actor;
|
||||
roll.l5r5e.isInitiativeRoll = true;
|
||||
roll.l5r5e.stance = data.stance;
|
||||
roll.l5r5e.skillId = skillId;
|
||||
roll.l5r5e.skillCatId = skillCat;
|
||||
roll.l5r5e.difficulty =
|
||||
messageOptions.difficulty !== undefined ? messageOptions.difficulty : cfg.difficulty;
|
||||
roll.l5r5e.difficultyHidden =
|
||||
messageOptions.difficultyHidden !== undefined
|
||||
? messageOptions.difficultyHidden
|
||||
: cfg.difficultyHidden;
|
||||
roll.l5r5e.voidPointUsed = !!messageOptions.useVoidPoint;
|
||||
roll.l5r5e.skillAssistance = messageOptions.skillAssistance || 0;
|
||||
|
||||
roll.roll();
|
||||
rnkMessage = await roll.toMessage({ flavor });
|
||||
}
|
||||
|
||||
// Ugly but work... i need the new message
|
||||
if (ids.length === 1) {
|
||||
combatant.actor.rnkMessage = rnkMessage;
|
||||
}
|
||||
|
||||
// if the character succeeded on their Initiative check, they add 1 to their base initiative value,
|
||||
// plus an additional amount equal to their bonus successes.
|
||||
const successes = Math.min(roll.l5r5e.summary.ringsUsed, roll.l5r5e.summary.success);
|
||||
if (successes >= roll.l5r5e.summary.difficulty) {
|
||||
initiative = initiative + 1 + Math.max(successes - roll.l5r5e.summary.difficulty, 0);
|
||||
const successes = roll.l5r5e.summary.totalSuccess;
|
||||
if (successes >= roll.l5r5e.difficulty) {
|
||||
initiative = initiative + 1 + Math.max(successes - roll.l5r5e.difficulty, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +127,7 @@ export class CombatL5r5e extends Combat {
|
||||
_id: combatant._id,
|
||||
initiative: initiative,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Update all combatants at once
|
||||
await this.updateEmbeddedEntity("Combatant", updatedCombatants);
|
||||
|
||||
@@ -27,14 +27,15 @@ export class DicePickerDialog extends FormApplication {
|
||||
skill: {
|
||||
id: "",
|
||||
value: 0,
|
||||
default_value: 0,
|
||||
defaultValue: 0,
|
||||
cat: "",
|
||||
name: "",
|
||||
assistance: 0,
|
||||
},
|
||||
difficulty: {
|
||||
value: 2,
|
||||
hidden: false,
|
||||
add_void_point: false,
|
||||
addVoidPoint: false,
|
||||
},
|
||||
useVoidPoint: false,
|
||||
isInitiativeRoll: false,
|
||||
@@ -50,8 +51,6 @@ export class DicePickerDialog extends FormApplication {
|
||||
classes: ["l5r5e", "dice-picker-dialog"],
|
||||
template: CONFIG.l5r5e.paths.templates + "dice/dice-picker-dialog.html",
|
||||
title: "L5R Dice Roller",
|
||||
width: 660,
|
||||
height: 460,
|
||||
actor: null,
|
||||
ringId: null,
|
||||
skillId: "",
|
||||
@@ -184,6 +183,7 @@ export class DicePickerDialog extends FormApplication {
|
||||
}
|
||||
|
||||
this.object.skill = {
|
||||
...this.object.skill,
|
||||
id: skillId.toLowerCase().trim(),
|
||||
value: 0,
|
||||
cat: "",
|
||||
@@ -215,13 +215,13 @@ export class DicePickerDialog extends FormApplication {
|
||||
switch (this._actor.data.type) {
|
||||
case "character":
|
||||
this.object.skill.value = this._actor.data.data.skills[skillCatId]?.[this.object.skill.id] || 0;
|
||||
this.object.skill.default_value = this.object.skill.value;
|
||||
this.object.skill.defaultValue = this.object.skill.value;
|
||||
break;
|
||||
|
||||
case "npc":
|
||||
// Skill value is in categories for npc
|
||||
this.object.skill.value = this._actor.data.data.skills[skillCatId] || 0;
|
||||
this.object.skill.default_value = this.object.skill.value;
|
||||
this.object.skill.defaultValue = this.object.skill.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -249,7 +249,7 @@ export class DicePickerDialog extends FormApplication {
|
||||
isHidden = true;
|
||||
}
|
||||
this.object.difficulty.hidden = !!isHidden;
|
||||
this.object.difficulty.add_void_point = this.object.difficulty.hidden;
|
||||
this.object.difficulty.addVoidPoint = this.object.difficulty.hidden;
|
||||
this._updateVoidPointUsage();
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ export class DicePickerDialog extends FormApplication {
|
||||
actor: this._actor,
|
||||
actorIsPc: !this._actor || this._actor.data?.type === "character",
|
||||
canUseVoidPoint:
|
||||
this.object.difficulty.add_void_point || !this._actor || this._actor.data.data.void_points.value > 0,
|
||||
this.object.difficulty.addVoidPoint || !this._actor || this._actor.data.data.void_points.value > 0,
|
||||
disableSubmit: this.object.skill.value < 1 && this.object.ring.value < 1,
|
||||
difficultyHiddenIsLock: this._difficultyHiddenIsLock,
|
||||
};
|
||||
@@ -323,11 +323,27 @@ export class DicePickerDialog extends FormApplication {
|
||||
this.render(false);
|
||||
});
|
||||
|
||||
// Skill assistance
|
||||
html.find(".assistance").on("click", async (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const assistanceAdd = $(event.currentTarget).data("value");
|
||||
if (this.object.skill.assistance > 0 || assistanceAdd > 0) {
|
||||
this._quantityChange("skill", assistanceAdd);
|
||||
}
|
||||
this.object.skill.assistance = Math.max(
|
||||
Math.min(parseInt(this.object.skill.assistance) + assistanceAdd, 9),
|
||||
0
|
||||
);
|
||||
this.render(false);
|
||||
});
|
||||
|
||||
// Click on the Default Skill Dice
|
||||
html.find("#skill_default_value").on("click", async (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.object.skill.value = this.object.skill.default_value;
|
||||
this.object.skill.value = this.object.skill.defaultValue;
|
||||
this.object.skill.assistance = 0;
|
||||
this.render(false);
|
||||
});
|
||||
|
||||
@@ -345,7 +361,7 @@ export class DicePickerDialog extends FormApplication {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.object.difficulty.hidden = !this.object.difficulty.hidden;
|
||||
this.object.difficulty.add_void_point = this.object.difficulty.hidden;
|
||||
this.object.difficulty.addVoidPoint = this.object.difficulty.hidden;
|
||||
this._updateVoidPointUsage();
|
||||
this.render(false);
|
||||
});
|
||||
@@ -354,7 +370,7 @@ export class DicePickerDialog extends FormApplication {
|
||||
html.find("#diff_add_void_point").on("click", async (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.object.difficulty.add_void_point = !this.object.difficulty.add_void_point;
|
||||
this.object.difficulty.addVoidPoint = !this.object.difficulty.addVoidPoint;
|
||||
this._updateVoidPointUsage();
|
||||
this.render(false);
|
||||
});
|
||||
@@ -391,7 +407,7 @@ export class DicePickerDialog extends FormApplication {
|
||||
}
|
||||
|
||||
// If hidden add 1 void pt
|
||||
if (this.object.difficulty.add_void_point) {
|
||||
if (this.object.difficulty.addVoidPoint) {
|
||||
actorData.void_points.value = Math.min(actorData.void_points.value + 1, actorData.void_points.max);
|
||||
}
|
||||
|
||||
@@ -415,9 +431,10 @@ export class DicePickerDialog extends FormApplication {
|
||||
formula.push(`${this.object.skill.value}ds`);
|
||||
}
|
||||
|
||||
let message;
|
||||
if (this.object.isInitiativeRoll) {
|
||||
// Initiative roll
|
||||
this._actor.rollInitiative({
|
||||
await this._actor.rollInitiative({
|
||||
initiativeOptions: {
|
||||
formula: formula.join("+"),
|
||||
// updateTurn: true,
|
||||
@@ -426,9 +443,13 @@ export class DicePickerDialog extends FormApplication {
|
||||
difficulty: this.object.difficulty.value,
|
||||
difficultyHidden: this.object.difficulty.hidden,
|
||||
useVoidPoint: this.object.useVoidPoint,
|
||||
skillAssistance: this.object.skill.assistance,
|
||||
},
|
||||
},
|
||||
});
|
||||
// Adhesive tape to get the messageId :/
|
||||
message = this._actor.rnkMessage;
|
||||
delete this._actor.rnkMessage;
|
||||
} else {
|
||||
// Regular roll, so let's roll !
|
||||
const roll = await new game.l5r5e.RollL5r5e(formula.join("+"));
|
||||
@@ -437,12 +458,17 @@ export class DicePickerDialog extends FormApplication {
|
||||
roll.l5r5e.stance = this.object.ring.id;
|
||||
roll.l5r5e.skillId = this.object.skill.id;
|
||||
roll.l5r5e.skillCatId = this.object.skill.cat;
|
||||
roll.l5r5e.summary.difficulty = this.object.difficulty.value;
|
||||
roll.l5r5e.summary.difficultyHidden = this.object.difficulty.hidden;
|
||||
roll.l5r5e.summary.voidPointUsed = this.object.useVoidPoint;
|
||||
roll.l5r5e.difficulty = this.object.difficulty.value;
|
||||
roll.l5r5e.difficultyHidden = this.object.difficulty.hidden;
|
||||
roll.l5r5e.voidPointUsed = this.object.useVoidPoint;
|
||||
roll.l5r5e.skillAssistance = this.object.skill.assistance;
|
||||
|
||||
await roll.roll();
|
||||
await roll.toMessage();
|
||||
message = await roll.toMessage();
|
||||
}
|
||||
|
||||
if (message) {
|
||||
new game.l5r5e.RollnKeepDialog(message._id).render(true);
|
||||
}
|
||||
|
||||
return this.close();
|
||||
@@ -463,7 +489,7 @@ export class DicePickerDialog extends FormApplication {
|
||||
_updateVoidPointUsage() {
|
||||
if (
|
||||
this.object.useVoidPoint &&
|
||||
!this.object.difficulty.add_void_point &&
|
||||
!this.object.difficulty.addVoidPoint &&
|
||||
!!this._actor &&
|
||||
this._actor.data.data.void_points.value < 1
|
||||
) {
|
||||
|
||||
@@ -18,8 +18,8 @@ export class AbilityDie extends L5rBaseDie {
|
||||
8: { success: 1, explosive: 0, opportunity: 0, strife: 0, image: "skill_s" },
|
||||
9: { success: 1, explosive: 0, opportunity: 0, strife: 0, image: "skill_s" },
|
||||
10: { success: 1, explosive: 0, opportunity: 1, strife: 0, image: "skill_so" },
|
||||
11: { success: 1, explosive: 1, opportunity: 0, strife: 1, image: "skill_et" },
|
||||
12: { success: 1, explosive: 1, opportunity: 0, strife: 0, image: "skill_e" },
|
||||
11: { success: 0, explosive: 1, opportunity: 0, strife: 1, image: "skill_et" },
|
||||
12: { success: 0, explosive: 1, opportunity: 0, strife: 0, image: "skill_e" },
|
||||
};
|
||||
|
||||
/** @override */
|
||||
|
||||
@@ -14,6 +14,14 @@ export class L5rBaseDie extends DiceTerm {
|
||||
this.l5r5e = { success: 0, explosive: 0, opportunity: 0, strife: 0 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the total number of success + explosives
|
||||
* @returns {number}
|
||||
*/
|
||||
get totalSuccess() {
|
||||
return this.l5r5e.success + this.l5r5e.explosive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a standardized representation for the displayed formula associated with this DiceTerm
|
||||
* @override
|
||||
@@ -64,13 +72,7 @@ export class L5rBaseDie extends DiceTerm {
|
||||
this._evaluateModifiers();
|
||||
|
||||
// Combine all results
|
||||
this.l5r5e = { success: 0, explosive: 0, opportunity: 0, strife: 0 };
|
||||
this.results.forEach((term) => {
|
||||
const face = this.constructor.FACES[term.result];
|
||||
["success", "explosive", "opportunity", "strife"].forEach((props) => {
|
||||
this.l5r5e[props] += parseInt(face[props]);
|
||||
});
|
||||
});
|
||||
this.l5rSummary();
|
||||
|
||||
// Return the evaluated term
|
||||
this._evaluated = true;
|
||||
@@ -79,24 +81,36 @@ export class L5rBaseDie extends DiceTerm {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarise the total of success, strife... for L5R dices for the current Die
|
||||
*/
|
||||
l5rSummary() {
|
||||
this.l5r5e = { success: 0, explosive: 0, opportunity: 0, strife: 0 };
|
||||
this.results.forEach((term) => {
|
||||
const face = this.constructor.FACES[term.result];
|
||||
["success", "explosive", "opportunity", "strife"].forEach((props) => {
|
||||
this.l5r5e[props] += parseInt(face[props]);
|
||||
});
|
||||
if (face.explosive) {
|
||||
term.exploded = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll the DiceTerm by mapping a random uniform draw against the faces of the dice term
|
||||
* @override
|
||||
*/
|
||||
roll(options) {
|
||||
const roll = super.roll(options);
|
||||
|
||||
//roll.l5r5e = this.l5r5e;
|
||||
|
||||
return roll;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static fromData(data) {
|
||||
const roll = super.fromData(data);
|
||||
|
||||
roll.l5r5e = data.l5r5e;
|
||||
|
||||
return roll;
|
||||
}
|
||||
|
||||
@@ -106,9 +120,7 @@ export class L5rBaseDie extends DiceTerm {
|
||||
*/
|
||||
toJSON() {
|
||||
const json = super.toJSON();
|
||||
|
||||
json.l5r5e = this.l5r5e;
|
||||
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export class RingDie extends L5rBaseDie {
|
||||
3: { success: 0, explosive: 0, opportunity: 1, strife: 0, image: "ring_o" },
|
||||
4: { success: 1, explosive: 0, opportunity: 0, strife: 1, image: "ring_st" },
|
||||
5: { success: 1, explosive: 0, opportunity: 0, strife: 0, image: "ring_s" },
|
||||
6: { success: 1, explosive: 1, opportunity: 0, strife: 1, image: "ring_et" },
|
||||
6: { success: 0, explosive: 1, opportunity: 0, strife: 1, image: "ring_et" },
|
||||
};
|
||||
|
||||
/** @override */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* L5R Initiative Roll dialog
|
||||
* L5R GM Toolbox dialog
|
||||
* @extends {FormApplication}
|
||||
*/
|
||||
export class GmToolsDialog extends FormApplication {
|
||||
@@ -19,12 +19,9 @@ export class GmToolsDialog extends FormApplication {
|
||||
id: "l5r5e-gm-tools-dialog",
|
||||
classes: ["l5r5e", "gm-tools-dialog"],
|
||||
template: CONFIG.l5r5e.paths.templates + "dice/gm-tools-dialog.html",
|
||||
title: game.i18n.localize("l5r5e.dicepicker.difficulty_title"),
|
||||
width: 200, // ignored under 200px
|
||||
height: 130, // ignored under 50px
|
||||
scale: 0.5, // so scale /2 :D
|
||||
left: x - 470,
|
||||
top: y - 94,
|
||||
title: game.i18n.localize("l5r5e.gm_toolbox.title"),
|
||||
left: x - 512,
|
||||
top: y - 98,
|
||||
closeOnSubmit: false,
|
||||
submitOnClose: false,
|
||||
submitOnChange: true,
|
||||
@@ -37,6 +34,25 @@ export class GmToolsDialog extends FormApplication {
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
super(options);
|
||||
this._initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh data (used from socket)
|
||||
*/
|
||||
async refresh() {
|
||||
if (!game.user.isGM) {
|
||||
return;
|
||||
}
|
||||
this._initialize();
|
||||
this.render(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the values
|
||||
* @private
|
||||
*/
|
||||
_initialize() {
|
||||
this.object = {
|
||||
difficulty: game.settings.get("l5r5e", "initiative.difficulty.value"),
|
||||
difficultyHidden: game.settings.get("l5r5e", "initiative.difficulty.hidden"),
|
||||
@@ -67,6 +83,8 @@ export class GmToolsDialog extends FormApplication {
|
||||
if (!game.user.isGM) {
|
||||
return false;
|
||||
}
|
||||
this.position.width = "auto";
|
||||
this.position.height = "auto";
|
||||
return super.render(force, options);
|
||||
}
|
||||
|
||||
@@ -104,6 +122,8 @@ export class GmToolsDialog extends FormApplication {
|
||||
|
||||
// Modify difficulty hidden
|
||||
html.find(`.difficulty_hidden`).on("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.object.difficultyHidden = !this.object.difficultyHidden;
|
||||
game.settings
|
||||
.set("l5r5e", "initiative.difficulty.hidden", this.object.difficultyHidden)
|
||||
@@ -130,6 +150,13 @@ export class GmToolsDialog extends FormApplication {
|
||||
}
|
||||
game.settings.set("l5r5e", "initiative.difficulty.value", this.object.difficulty).then(() => this.submit());
|
||||
});
|
||||
|
||||
// Scene End & Sleep
|
||||
html.find(`.gm_actor_updates`).on("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this._updatesActors($(event.currentTarget).data("type"));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,15 +167,54 @@ export class GmToolsDialog extends FormApplication {
|
||||
* @override
|
||||
*/
|
||||
async _updateObject(event, formData) {
|
||||
// Notify the change to other players if they already have opened the DicePicker
|
||||
game.l5r5e.sockets.refreshAppId("l5r5e-dice-picker-dialog");
|
||||
|
||||
// If the current GM also have the DP open
|
||||
const app = Object.values(ui.windows).find((e) => e.id === "l5r5e-dice-picker-dialog");
|
||||
if (app && typeof app.refresh === "function") {
|
||||
app.refresh();
|
||||
}
|
||||
|
||||
this.render(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all actors
|
||||
* @param {string} type
|
||||
* @private
|
||||
*/
|
||||
_updatesActors(type) {
|
||||
if (!game.user.isGM) {
|
||||
return;
|
||||
}
|
||||
|
||||
game.actors.entities.forEach((actor) => {
|
||||
switch (type) {
|
||||
case "sleep":
|
||||
// Remove 'water x2' fatigue points
|
||||
actor.data.data.fatigue.value = Math.max(
|
||||
0,
|
||||
actor.data.data.fatigue.value - Math.ceil(actor.data.data.rings.water * 2)
|
||||
);
|
||||
break;
|
||||
|
||||
case "scene_end":
|
||||
// If more than half the value => roundup half conflit & fatigue
|
||||
actor.data.data.fatigue.value = Math.min(
|
||||
actor.data.data.fatigue.value,
|
||||
Math.ceil(actor.data.data.fatigue.max / 2)
|
||||
);
|
||||
actor.data.data.strife.value = Math.min(
|
||||
actor.data.data.strife.value,
|
||||
Math.ceil(actor.data.data.strife.max / 2)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
actor.update({
|
||||
data: {
|
||||
fatigue: {
|
||||
value: actor.data.data.fatigue.value,
|
||||
},
|
||||
strife: {
|
||||
value: actor.data.data.strife.value,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
ui.notifications.info(game.i18n.localize(`l5r5e.gm_toolbox.${type}_info`));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,23 +8,35 @@ export class RollnKeepDialog extends FormApplication {
|
||||
*/
|
||||
static CHOICES = {
|
||||
discard: "discard",
|
||||
face_change: "face-change",
|
||||
keep: "keep",
|
||||
nothing: null,
|
||||
reroll: "reroll",
|
||||
reserve: "reserve",
|
||||
// reserve: "reserve",
|
||||
swap: "swap",
|
||||
};
|
||||
|
||||
/**
|
||||
* The current ChatMessage where we come from
|
||||
* @param {ChatMessage} message
|
||||
*/
|
||||
message = null;
|
||||
_message = null;
|
||||
|
||||
/**
|
||||
* The current Roll
|
||||
* @param {RollL5r5e} roll
|
||||
*/
|
||||
roll = null;
|
||||
|
||||
/**
|
||||
* Payload Object
|
||||
*/
|
||||
object = {
|
||||
currentStep: 0,
|
||||
submitDisabled: false,
|
||||
swapDiceFaces: {
|
||||
rings: [],
|
||||
skills: [],
|
||||
},
|
||||
dicesList: [[]],
|
||||
};
|
||||
|
||||
@@ -38,59 +50,102 @@ export class RollnKeepDialog extends FormApplication {
|
||||
classes: ["l5r5e", "roll-n-keep-dialog"],
|
||||
template: CONFIG.l5r5e.paths.templates + "dice/roll-n-keep-dialog.html",
|
||||
title: game.i18n.localize("l5r5e.roll_n_keep.title"),
|
||||
width: 660,
|
||||
height: 660,
|
||||
closeOnSubmit: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a unique and dynamic element ID for the rendered ActorSheet application
|
||||
* Define a unique and dynamic element ID for the rendered application
|
||||
*/
|
||||
get id() {
|
||||
return `l5r5e-roll-n-keep-dialog-${this.message._id}`;
|
||||
return `l5r5e-roll-n-keep-dialog-${this._message._id}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* ChatMessage
|
||||
* @param {ChatMessage} msg
|
||||
*/
|
||||
set message(msg) {
|
||||
this._message = msg instanceof ChatMessage ? msg : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* ChatMessage
|
||||
* @returns {ChatMessage}
|
||||
*/
|
||||
get message() {
|
||||
return this._message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Roll n Keep dialog
|
||||
* @param {ChatMessage} message
|
||||
* @param {number} messageId
|
||||
* @param {FormApplicationOptions} options
|
||||
*/
|
||||
constructor(message, options = {}) {
|
||||
constructor(messageId, options = {}) {
|
||||
super({}, options);
|
||||
this.message = message;
|
||||
this._initialize();
|
||||
this.message = game.messages.get(messageId);
|
||||
this.options.editable =
|
||||
this._message?.isAuthor || this._message?._roll.l5r5e.actor?.owner || this._message?.owner || false;
|
||||
|
||||
this._initializeDiceFaces();
|
||||
this._initializeHistory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh data (used from socket)
|
||||
*/
|
||||
async refresh() {
|
||||
if (!this.message) {
|
||||
if (!this._message) {
|
||||
return;
|
||||
}
|
||||
this._initialize();
|
||||
this._initializeHistory();
|
||||
this.render(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the dialog with the message
|
||||
* Render
|
||||
* @param {boolean} force
|
||||
* @param {RenderOptions} options
|
||||
* @returns {Application}
|
||||
* @override
|
||||
*/
|
||||
render(force = null, options = {}) {
|
||||
if (!this._message) {
|
||||
return;
|
||||
}
|
||||
this.position.width = "auto";
|
||||
this.position.height = "auto";
|
||||
return super.render(force, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the dice history list
|
||||
* @private
|
||||
*/
|
||||
_initialize() {
|
||||
// Get the roll
|
||||
const roll = game.l5r5e.RollL5r5e.fromData(this.message.roll);
|
||||
_initializeHistory() {
|
||||
if (!this._message) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.clear();
|
||||
console.log(roll); // TODO TMP
|
||||
// Get the roll
|
||||
this.roll = game.l5r5e.RollL5r5e.fromData(this._message._roll);
|
||||
|
||||
// Already history
|
||||
if (Array.isArray(roll.l5r5e.history)) {
|
||||
this.object.dicesList = roll.l5r5e.history;
|
||||
if (Array.isArray(this.roll.l5r5e.history)) {
|
||||
this.object.dicesList = this.roll.l5r5e.history;
|
||||
|
||||
let currentStep = this.roll.l5r5e.history.length - 1;
|
||||
if (!this._haveChoice(currentStep, RollnKeepDialog.CHOICES.nothing)) {
|
||||
currentStep += 1;
|
||||
}
|
||||
this.object.currentStep = currentStep;
|
||||
return;
|
||||
}
|
||||
|
||||
// New
|
||||
roll.terms.forEach((term) => {
|
||||
this.object.dicesList = [[]];
|
||||
this.roll.terms.forEach((term) => {
|
||||
if (typeof term !== "object") {
|
||||
return;
|
||||
}
|
||||
@@ -98,14 +153,24 @@ export class RollnKeepDialog extends FormApplication {
|
||||
this.object.dicesList[0].push({
|
||||
type: term.constructor.name,
|
||||
face: res.result,
|
||||
explosive: term.constructor.FACES[res.result].explosive,
|
||||
img: term.constructor.getResultSrc(res.result),
|
||||
choice: RollnKeepDialog.CHOICES.nothing,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the dices faces
|
||||
* @private
|
||||
*/
|
||||
_initializeDiceFaces() {
|
||||
// All faces are unique for rings
|
||||
this.object.swapDiceFaces.rings = Object.keys(game.l5r5e.RingDie.FACES);
|
||||
|
||||
// Only unique for Skills
|
||||
this.object.swapDiceFaces.skills = [1, 3, 6, 8, 10, 11, 12];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create drag-and-drop workflow handlers for this Application
|
||||
* @return An array of DragDrop handlers
|
||||
@@ -121,6 +186,15 @@ export class RollnKeepDialog extends FormApplication {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Define whether a user is able to begin a dragstart workflow for a given drag selector
|
||||
* @param selector The candidate HTML selector for dragging
|
||||
* @return Can the current user drag this selector?
|
||||
*/
|
||||
_canDragStart(selector) {
|
||||
return this.options.editable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback actions which occur at the beginning of a drag start workflow.
|
||||
* @param {DragEvent} event The originating DragEvent
|
||||
@@ -142,20 +216,23 @@ export class RollnKeepDialog extends FormApplication {
|
||||
* @return {Object}
|
||||
*/
|
||||
getData(options = null) {
|
||||
const draggableList = [];
|
||||
this.object.dicesList.forEach((step, idx) => {
|
||||
step.forEach((die, dieNum) => {
|
||||
if (die) {
|
||||
draggableList[dieNum] = idx;
|
||||
}
|
||||
});
|
||||
});
|
||||
// Disable submit / edition
|
||||
this.options.classes = this.options.classes.filter((e) => e !== "finalized");
|
||||
this.object.submitDisabled = false;
|
||||
|
||||
if (this._checkKeepCount(this.object.currentStep)) {
|
||||
const kept = this._getKeepCount(this.object.currentStep);
|
||||
this.object.submitDisabled = kept < 1 || kept > this.roll.l5r5e.keepLimit;
|
||||
} else if (!this.object.dicesList[this.object.currentStep]) {
|
||||
this.options.editable = false;
|
||||
this.options.classes.push("finalized");
|
||||
}
|
||||
|
||||
return {
|
||||
...super.getData(options),
|
||||
cssClass: this.options.classes.join(" "),
|
||||
data: this.object,
|
||||
draggableList: draggableList,
|
||||
l5r5e: this.message._roll.l5r5e,
|
||||
l5r5e: this.roll.l5r5e,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -166,11 +243,28 @@ export class RollnKeepDialog extends FormApplication {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// GM Only, need to be before the editable check
|
||||
if (game.user.isGM && this.object.currentStep > 0) {
|
||||
// Add Context menu to rollback choices
|
||||
new ContextMenu(html, ".l5r5e.profil", [
|
||||
{
|
||||
name: game.i18n.localize("l5r5e.roll_n_keep.undo"),
|
||||
icon: '<i class="fas fa-undo"></i>',
|
||||
callback: () => this._undoLastStepChoices(),
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
// *** Everything below here is only needed if the sheet is editable ***
|
||||
if (!this.options.editable) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Finalize Button
|
||||
html.find("#finalize").on("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (this._getKeepCount() > 0) {
|
||||
if (!this.object.submitDisabled) {
|
||||
this.submit();
|
||||
}
|
||||
});
|
||||
@@ -180,6 +274,11 @@ export class RollnKeepDialog extends FormApplication {
|
||||
* Handle dropped items
|
||||
*/
|
||||
async _onDropItem(event) {
|
||||
// *** Everything below here is only needed if the sheet is editable ***
|
||||
if (!this.options.editable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const type = $(event.currentTarget).data("type");
|
||||
const json = event.dataTransfer.getData("text/plain");
|
||||
if (!json || !Object.values(RollnKeepDialog.CHOICES).some((e) => !!e && e === type)) {
|
||||
@@ -191,81 +290,361 @@ export class RollnKeepDialog extends FormApplication {
|
||||
return;
|
||||
}
|
||||
|
||||
let addNewRoll = false;
|
||||
const current = this.object.dicesList[data.step][data.die];
|
||||
current.choice = type;
|
||||
delete current.newFace;
|
||||
|
||||
// Actions p 26 : change, ignore/discard, reroll, reserve, change face
|
||||
switch (type) {
|
||||
case RollnKeepDialog.CHOICES.keep:
|
||||
if (current.explosive) {
|
||||
addNewRoll = true;
|
||||
case RollnKeepDialog.CHOICES.swap: {
|
||||
// Dice Type Ring/Skill
|
||||
const diceType = $(event.currentTarget).data("die");
|
||||
const diceNewFace = $(event.currentTarget).data("face");
|
||||
|
||||
if (current.type !== diceType || current.face === diceNewFace) {
|
||||
current.choice = RollnKeepDialog.CHOICES.nothing;
|
||||
this.render(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
current.newFace = diceNewFace;
|
||||
break;
|
||||
}
|
||||
|
||||
case RollnKeepDialog.CHOICES.reroll:
|
||||
addNewRoll = true;
|
||||
// If reroll, we need to keep all the line by default
|
||||
this._forceChoiceForDiceWithoutOne(RollnKeepDialog.CHOICES.keep);
|
||||
break;
|
||||
}
|
||||
|
||||
// New roll
|
||||
if (addNewRoll) {
|
||||
if (!this.object.dicesList[data.step + 1]) {
|
||||
this.object.dicesList[data.step + 1] = Array(this.object.dicesList[0].length).fill(null);
|
||||
}
|
||||
this.object.dicesList[data.step + 1][data.die] = await this._newRoll(current.type, type);
|
||||
current.choice = type;
|
||||
|
||||
// Little time saving : if we reach the max kept dices, discard all dices without a choice
|
||||
if (
|
||||
this._checkKeepCount(this.object.currentStep) &&
|
||||
this._getKeepCount(this.object.currentStep) === this.roll.l5r5e.keepLimit
|
||||
) {
|
||||
this._forceChoiceForDiceWithoutOne(RollnKeepDialog.CHOICES.discard);
|
||||
}
|
||||
|
||||
this.render(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll a new die avec return the result
|
||||
* @private
|
||||
*/
|
||||
async _newRoll(dieType, actionType) {
|
||||
const roll = await new game.l5r5e.RollL5r5e(dieType === "RingDie" ? "1dr" : "1ds");
|
||||
roll.actor = this.message.roll.l5r5e.actor;
|
||||
roll.l5r5e.stance = this.message.roll.l5r5e.stance;
|
||||
// roll.l5r5e.skillId = this.message.roll.l5r5e.skillId;
|
||||
// roll.l5r5e.skillCatId = this.message.roll.l5r5e.skillCatId;
|
||||
|
||||
await roll.roll();
|
||||
await roll.toMessage({
|
||||
flavor: game.i18n.localize(`l5r5e.roll_n_keep.${actionType}_chat`),
|
||||
});
|
||||
|
||||
const dice = roll.terms[0];
|
||||
const result = dice.results[0].result;
|
||||
|
||||
return {
|
||||
type: dieType,
|
||||
face: result,
|
||||
explosive: dice.constructor.FACES[result].explosive,
|
||||
img: dice.constructor.getResultSrc(result),
|
||||
choice: RollnKeepDialog.CHOICES.nothing,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current number of dices kept
|
||||
* @private
|
||||
*/
|
||||
_getKeepCount() {
|
||||
return this.object.dicesList.reduce((acc, step) => {
|
||||
return (
|
||||
acc +
|
||||
step.reduce((acc2, die) => {
|
||||
if (!!die && die.choice === RollnKeepDialog.CHOICES.keep) {
|
||||
acc2 = acc2 + 1;
|
||||
}
|
||||
return acc2;
|
||||
}, 0)
|
||||
);
|
||||
_getKeepCount(step) {
|
||||
return this.object.dicesList[step].reduce((acc, die) => {
|
||||
if (
|
||||
!!die &&
|
||||
[RollnKeepDialog.CHOICES.keep, RollnKeepDialog.CHOICES.reroll, RollnKeepDialog.CHOICES.swap].includes(
|
||||
die.choice
|
||||
)
|
||||
) {
|
||||
acc = acc + 1;
|
||||
}
|
||||
return acc;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a "_getKeepCount" is needed
|
||||
* @param {number} step
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
_checkKeepCount(step) {
|
||||
return (
|
||||
!this._haveChoice(step, RollnKeepDialog.CHOICES.reroll) &&
|
||||
(step === 0 || this._haveChoice(step - 1, RollnKeepDialog.CHOICES.reroll))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this choice exist in the current step
|
||||
* @private
|
||||
*/
|
||||
_haveChoice(currentStep, choice) {
|
||||
return (
|
||||
this.object.dicesList[currentStep] &&
|
||||
this.object.dicesList[currentStep].some((e) => !!e && e.choice === choice)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard all dices without a choice for the current step
|
||||
* @param {string} newChoice
|
||||
* @private
|
||||
*/
|
||||
_forceChoiceForDiceWithoutOne(newChoice) {
|
||||
this.object.dicesList[this.object.currentStep]
|
||||
.filter((e) => !!e)
|
||||
.map((e) => {
|
||||
if (e.choice === RollnKeepDialog.CHOICES.nothing) {
|
||||
e.choice = newChoice;
|
||||
}
|
||||
return e;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize dice array for "step" if needed
|
||||
* @param {number} step
|
||||
* @private
|
||||
*/
|
||||
_initializeDicesListStep(step) {
|
||||
if (!this.object.dicesList[step]) {
|
||||
this.object.dicesList[step] = Array(this.object.dicesList[0].length).fill(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply all choices to build the next step
|
||||
* @returns {Promise<void>}
|
||||
* @private
|
||||
*/
|
||||
async _applyChoices() {
|
||||
const nextStep = this.object.currentStep + 1;
|
||||
const haveReroll = this._haveChoice(this.object.currentStep, RollnKeepDialog.CHOICES.reroll);
|
||||
|
||||
// Foreach kept dices, apply choices
|
||||
const newRolls = {};
|
||||
this.object.dicesList[this.object.currentStep].forEach((die, idx) => {
|
||||
if (!die) {
|
||||
return;
|
||||
}
|
||||
switch (die.choice) {
|
||||
case RollnKeepDialog.CHOICES.keep:
|
||||
if (haveReroll) {
|
||||
// Reroll line add all kept into a new line
|
||||
this._initializeDicesListStep(nextStep);
|
||||
this.object.dicesList[nextStep][idx] = duplicate(
|
||||
this.object.dicesList[this.object.currentStep][idx]
|
||||
);
|
||||
this.object.dicesList[nextStep][idx].choice = RollnKeepDialog.CHOICES.nothing;
|
||||
this.object.dicesList[this.object.currentStep][idx].choice = RollnKeepDialog.CHOICES.discard;
|
||||
} else if (game.l5r5e[die.type].FACES[die.face].explosive) {
|
||||
// Exploding dice : add a new dice in the next step
|
||||
if (!newRolls[die.type]) {
|
||||
newRolls[die.type] = 0;
|
||||
}
|
||||
newRolls[die.type] += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case RollnKeepDialog.CHOICES.reroll:
|
||||
// Reroll : add a new dice in the next step
|
||||
if (!newRolls[die.type]) {
|
||||
newRolls[die.type] = 0;
|
||||
}
|
||||
newRolls[die.type] += 1;
|
||||
break;
|
||||
|
||||
case RollnKeepDialog.CHOICES.swap:
|
||||
// FaceSwap : add a new dice with selected face in next step
|
||||
this._initializeDicesListStep(nextStep);
|
||||
this.object.dicesList[nextStep][idx] = {
|
||||
type: this.object.dicesList[this.object.currentStep][idx].type,
|
||||
face: this.object.dicesList[this.object.currentStep][idx].newFace,
|
||||
choice: RollnKeepDialog.CHOICES.keep,
|
||||
};
|
||||
delete this.object.dicesList[this.object.currentStep][idx].newFace;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// If new rolls, roll and add them
|
||||
if (Object.keys(newRolls).length > 0) {
|
||||
const newRollsResults = await this._newRoll(newRolls);
|
||||
this._initializeDicesListStep(nextStep);
|
||||
this.object.dicesList[this.object.currentStep].forEach((die, idx) => {
|
||||
if (!die) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
die.choice === RollnKeepDialog.CHOICES.reroll ||
|
||||
(!haveReroll &&
|
||||
die.choice === RollnKeepDialog.CHOICES.keep &&
|
||||
game.l5r5e[die.type].FACES[die.face].explosive)
|
||||
) {
|
||||
this.object.dicesList[nextStep][idx] = newRollsResults[die.type].shift();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a array (of int or object) into a formula ring/skill
|
||||
* @param rolls
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
_arrayToFormula(rolls) {
|
||||
const formula = [];
|
||||
if (rolls["RingDie"]) {
|
||||
const rings = Array.isArray(rolls["RingDie"]) ? rolls["RingDie"].length : rolls["RingDie"];
|
||||
formula.push(rings + "dr");
|
||||
}
|
||||
if (rolls["AbilityDie"]) {
|
||||
const skills = Array.isArray(rolls["AbilityDie"]) ? rolls["AbilityDie"].length : rolls["AbilityDie"];
|
||||
formula.push(skills + "ds");
|
||||
}
|
||||
if (formula.length < 1) {
|
||||
return "";
|
||||
}
|
||||
return formula.join("+");
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll all new dice at once (better performance) and return the result
|
||||
* @private
|
||||
*/
|
||||
async _newRoll(newRolls) {
|
||||
const out = {
|
||||
RingDie: [],
|
||||
AbilityDie: [],
|
||||
};
|
||||
|
||||
const roll = await new game.l5r5e.RollL5r5e(this._arrayToFormula(newRolls));
|
||||
await roll.roll();
|
||||
|
||||
// Show DsN dice for the new roll
|
||||
if (game.dice3d !== undefined) {
|
||||
game.dice3d.showForRoll(roll, game.user, true);
|
||||
}
|
||||
|
||||
roll.terms.forEach((term) => {
|
||||
if (typeof term !== "object") {
|
||||
return;
|
||||
}
|
||||
term.results.forEach((res) => {
|
||||
out[term.constructor.name].push({
|
||||
type: term.constructor.name,
|
||||
face: res.result,
|
||||
choice: RollnKeepDialog.CHOICES.nothing,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the message roll
|
||||
* @param {boolean} forceKeep If true keep all dice regardless their choice
|
||||
* @returns {Promise<void>}
|
||||
* @private
|
||||
*/
|
||||
async _rebuildRoll(forceKeep = false) {
|
||||
// Get all kept dices + new (choice null)
|
||||
const diceList = this.object.dicesList.reduce((acc, step, stepIdx) => {
|
||||
const haveReroll = stepIdx > 0 && this._haveChoice(stepIdx - 1, RollnKeepDialog.CHOICES.reroll);
|
||||
step.forEach((die, idx) => {
|
||||
if (
|
||||
!!die &&
|
||||
(forceKeep ||
|
||||
die.choice === RollnKeepDialog.CHOICES.keep ||
|
||||
(haveReroll && die.choice === RollnKeepDialog.CHOICES.nothing))
|
||||
) {
|
||||
if (!acc[die.type]) {
|
||||
acc[die.type] = [];
|
||||
}
|
||||
// Check previous dice, to add html classes in chat
|
||||
if (stepIdx > 0 && this.object.dicesList[stepIdx - 1][idx]) {
|
||||
switch (this.object.dicesList[stepIdx - 1][idx].choice) {
|
||||
case RollnKeepDialog.CHOICES.reroll:
|
||||
die.class = "rerolled";
|
||||
break;
|
||||
case RollnKeepDialog.CHOICES.swap:
|
||||
die.class = "swapped";
|
||||
break;
|
||||
}
|
||||
}
|
||||
acc[die.type].push(die);
|
||||
}
|
||||
});
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// Re create a new roll
|
||||
const roll = await new game.l5r5e.RollL5r5e(this._arrayToFormula(diceList));
|
||||
roll.l5r5e = {
|
||||
...this.roll.l5r5e,
|
||||
summary: roll.l5r5e.summary,
|
||||
};
|
||||
|
||||
// Fill the data
|
||||
roll.evaluate();
|
||||
|
||||
// Modify results
|
||||
roll.terms.map((term) => {
|
||||
if (term instanceof game.l5r5e.L5rBaseDie) {
|
||||
term.results.map((res) => {
|
||||
const die = diceList[term.constructor.name].shift();
|
||||
res.result = die.face;
|
||||
|
||||
// add class to term result
|
||||
if (die.class) {
|
||||
res[die.class] = true;
|
||||
}
|
||||
return res;
|
||||
});
|
||||
term.l5rSummary();
|
||||
}
|
||||
return term;
|
||||
});
|
||||
|
||||
// Recompute summary
|
||||
roll.l5rSummary();
|
||||
|
||||
// Add roll & history to message
|
||||
this.roll = roll;
|
||||
this.roll.l5r5e.history = this.object.dicesList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the new roll in chat and delete the old message
|
||||
* @returns {Promise<void>}
|
||||
* @private
|
||||
*/
|
||||
async _toChatMessage() {
|
||||
// Keep old Ids
|
||||
const appOldId = this.id;
|
||||
const msgOldId = this._message._id;
|
||||
|
||||
if (this.roll.l5r5e.isInitiativeRoll) {
|
||||
await this.roll.l5r5e.actor.rollInitiative({
|
||||
rerollInitiative: true,
|
||||
initiativeOptions: {
|
||||
messageOptions: {
|
||||
rnkRoll: this.roll,
|
||||
},
|
||||
},
|
||||
});
|
||||
// Adhesive tape to get the message :/
|
||||
this.message = this.roll.l5r5e.actor.rnkMessage;
|
||||
delete this.roll.l5r5e.actor.rnkMessage;
|
||||
} else {
|
||||
// Send it to chat, switch to new message
|
||||
this.message = await this.roll.toMessage();
|
||||
}
|
||||
|
||||
// Refresh viewers
|
||||
game.l5r5e.sockets.updateMessageIdAndRefresh(appOldId, this._message._id);
|
||||
|
||||
// Delete old chat message related to this series
|
||||
if (game.settings.get("l5r5e", "rnk.deleteOldMessage")) {
|
||||
if (game.user.isGM) {
|
||||
const message = game.messages.get(msgOldId);
|
||||
if (message) {
|
||||
message.delete();
|
||||
}
|
||||
} else {
|
||||
game.l5r5e.sockets.deleteChatMessage(msgOldId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called upon form submission after form data is validated
|
||||
* @param event The initial triggering submission event
|
||||
@@ -274,32 +653,66 @@ export class RollnKeepDialog extends FormApplication {
|
||||
* @override
|
||||
*/
|
||||
async _updateObject(event, formData) {
|
||||
console.log("**** _updateObject");
|
||||
// *** Everything below here is only needed if the sheet is editable ***
|
||||
if (!this.options.editable) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify the change to other players
|
||||
// game.l5r5e.sockets.refreshAppId(this.id);
|
||||
// Discard all dices without a choice for the current step
|
||||
this._forceChoiceForDiceWithoutOne(RollnKeepDialog.CHOICES.discard);
|
||||
|
||||
// this.message._roll.l5r5e.history = {test: "yahooo"};
|
||||
// Apply all choices to build the next step
|
||||
await this._applyChoices();
|
||||
|
||||
// await message.update({
|
||||
// data: {
|
||||
// roll: roll
|
||||
// }
|
||||
// });
|
||||
// message.render(false);
|
||||
// *** Below this the current step become the next step ***
|
||||
this.object.currentStep++;
|
||||
|
||||
// console.log(roll.toJSON(), this.message);
|
||||
// Rebuild the roll
|
||||
await this._rebuildRoll(false);
|
||||
|
||||
// ui.chat.updateMessage(message);
|
||||
// ui.chat.postOne(message, false);
|
||||
// Send the new roll in chat and delete the old message
|
||||
await this._toChatMessage();
|
||||
|
||||
// if (game.user.isGM) {
|
||||
// message.delete();
|
||||
// } else {
|
||||
// game.l5r5e.sockets.deleteChatMessage(messageId);
|
||||
// }
|
||||
// If a next step exist, rerender, else close
|
||||
if (this.object.dicesList[this.object.currentStep]) {
|
||||
return this.render(false);
|
||||
}
|
||||
return this.close();
|
||||
}
|
||||
|
||||
// return this.close();
|
||||
/**
|
||||
* Undo the last step choice
|
||||
* @returns {Promise<Application|any>}
|
||||
* @private
|
||||
*/
|
||||
async _undoLastStepChoices() {
|
||||
// Find the step to work to
|
||||
this.object.currentStep = this.object.dicesList[this.object.currentStep]
|
||||
? this.object.currentStep
|
||||
: Math.max(0, this.object.currentStep - 1);
|
||||
|
||||
// If all clear, delete this step
|
||||
if (this._haveChoice(this.object.currentStep, RollnKeepDialog.CHOICES.nothing)) {
|
||||
if (this.object.currentStep === 0) {
|
||||
return;
|
||||
}
|
||||
this.object.dicesList.pop();
|
||||
this.object.dicesList = this.object.dicesList.filter((e) => !!e);
|
||||
this.object.currentStep--;
|
||||
}
|
||||
|
||||
// Clear choices
|
||||
this.object.dicesList[this.object.currentStep]
|
||||
.filter((e) => !!e)
|
||||
.map((e) => {
|
||||
e.choice = RollnKeepDialog.CHOICES.nothing;
|
||||
return e;
|
||||
});
|
||||
|
||||
this.options.editable = true;
|
||||
await this._rebuildRoll(true);
|
||||
await this._toChatMessage();
|
||||
return this.render(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,21 +722,22 @@ export class RollnKeepDialog extends FormApplication {
|
||||
*/
|
||||
static async onChatAction(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// Extract card data
|
||||
const button = $(event.currentTarget);
|
||||
button.attr("disabled", true);
|
||||
const card = button.parents(".l5r5e.item-display.dices-l5r");
|
||||
const messageId = card.parents(".chat-message").data("message-id");
|
||||
const message = game.messages.get(messageId);
|
||||
|
||||
// Validate permission to proceed with the roll n keep
|
||||
if (!message || !message._roll.l5r5e.actor.owner) {
|
||||
return;
|
||||
// Already open ? close it
|
||||
const app = Object.values(ui.windows).find((e) => e.id === `l5r5e-roll-n-keep-dialog-${messageId}`);
|
||||
if (app) {
|
||||
app.close();
|
||||
} else {
|
||||
new RollnKeepDialog(messageId).render(true);
|
||||
}
|
||||
|
||||
new RollnKeepDialog(message).render(true);
|
||||
|
||||
// Re-enable the button
|
||||
button.attr("disabled", false);
|
||||
}
|
||||
|
||||
@@ -13,15 +13,20 @@ export class RollL5r5e extends Roll {
|
||||
skillId: "",
|
||||
skillCatId: "",
|
||||
actor: null,
|
||||
difficulty: 2,
|
||||
difficultyHidden: false,
|
||||
voidPointUsed: false,
|
||||
keepLimit: null,
|
||||
isInitiativeRoll: false,
|
||||
skillAssistance: 0,
|
||||
initialFormula: null,
|
||||
dicesTypes: {
|
||||
std: false,
|
||||
l5r: false,
|
||||
},
|
||||
summary: {
|
||||
difficulty: 2,
|
||||
difficultyHidden: false,
|
||||
voidPointUsed: false,
|
||||
ringsUsed: 0,
|
||||
totalSuccess: 0,
|
||||
totalBonus: 0,
|
||||
success: 0,
|
||||
explosive: 0,
|
||||
opportunity: 0,
|
||||
@@ -40,8 +45,6 @@ export class RollL5r5e extends Roll {
|
||||
this.l5r5e.skillId = res[2];
|
||||
}
|
||||
});
|
||||
|
||||
// TODO parse difficulty stance skillId from cmd line ?
|
||||
}
|
||||
|
||||
set actor(actor) {
|
||||
@@ -68,23 +71,15 @@ export class RollL5r5e extends Roll {
|
||||
|
||||
// Roll
|
||||
super.evaluate({ minimize, maximize });
|
||||
|
||||
// Current terms - L5R Summary
|
||||
this.terms.forEach((term) => this._l5rSummary(term));
|
||||
|
||||
// Check inner L5R rolls - L5R Summary
|
||||
this._dice.forEach((term) => this._l5rSummary(term));
|
||||
|
||||
// Store final outputs
|
||||
this._rolled = true;
|
||||
this.l5r5e.dicesTypes.std = this.dice.some(
|
||||
(term) => term instanceof DiceTerm && !(term instanceof game.l5r5e.L5rBaseDie)
|
||||
); // ignore math symbols
|
||||
this.l5r5e.dicesTypes.l5r = this.dice.some((term) => term instanceof game.l5r5e.L5rBaseDie);
|
||||
this.l5r5e.summary.ringsUsed = this.dice.reduce(
|
||||
(acc, term) => (term instanceof game.l5r5e.RingDie ? acc + term.number : acc),
|
||||
0
|
||||
);
|
||||
|
||||
// Save initial formula
|
||||
if (!this.l5r5e.initialFormula) {
|
||||
this.l5r5e.initialFormula = this.formula;
|
||||
}
|
||||
|
||||
// Compute summary
|
||||
this.l5rSummary();
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -92,10 +87,54 @@ export class RollL5r5e extends Roll {
|
||||
/**
|
||||
* Summarise the total of success, strife... for L5R dices for the current roll
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
l5rSummary() {
|
||||
const summary = this.l5r5e.summary;
|
||||
|
||||
// Reset totals
|
||||
summary.success = 0;
|
||||
summary.explosive = 0;
|
||||
summary.opportunity = 0;
|
||||
summary.strife = 0;
|
||||
summary.totalSuccess = 0;
|
||||
|
||||
// Current terms - L5R Summary
|
||||
this.terms.forEach((term) => this._l5rTermSummary(term));
|
||||
|
||||
// Check inner L5R rolls - L5R Summary
|
||||
this._dice.forEach((term) => this._l5rTermSummary(term));
|
||||
|
||||
// Store final outputs
|
||||
this.l5r5e.dicesTypes.std = this.dice.some(
|
||||
(term) => term instanceof DiceTerm && !(term instanceof game.l5r5e.L5rBaseDie)
|
||||
); // ignore math symbols
|
||||
this.l5r5e.dicesTypes.l5r = this.dice.some((term) => term instanceof game.l5r5e.L5rBaseDie);
|
||||
summary.totalBonus = Math.max(0, summary.totalSuccess - this.l5r5e.difficulty);
|
||||
|
||||
if (!this.l5r5e.keepLimit) {
|
||||
// count ring die + skill assistance
|
||||
this.l5r5e.keepLimit =
|
||||
this.dice.reduce((acc, term) => (term instanceof game.l5r5e.RingDie ? acc + term.number : acc), 0) +
|
||||
Math.max(0, this.l5r5e.skillAssistance || 0);
|
||||
|
||||
// if only bulk skill dice, count the skill dice
|
||||
if (!this.l5r5e.keepLimit) {
|
||||
this.l5r5e.keepLimit = this.dice.reduce(
|
||||
(acc, term) => (term instanceof game.l5r5e.AbilityDie ? acc + term.number : acc),
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarise the total of success, strife... for L5R dices for the current term
|
||||
*
|
||||
* @param term
|
||||
* @private
|
||||
*/
|
||||
_l5rSummary(term) {
|
||||
_l5rTermSummary(term) {
|
||||
if (!(term instanceof game.l5r5e.L5rBaseDie)) {
|
||||
return;
|
||||
}
|
||||
@@ -103,6 +142,8 @@ export class RollL5r5e extends Roll {
|
||||
["success", "explosive", "opportunity", "strife"].forEach((props) => {
|
||||
this.l5r5e.summary[props] += parseInt(term.l5r5e[props]);
|
||||
});
|
||||
this.l5r5e.summary.totalSuccess += term.totalSuccess;
|
||||
|
||||
// TODO Others advantage/disadvantage
|
||||
}
|
||||
|
||||
@@ -160,8 +201,9 @@ export class RollL5r5e extends Roll {
|
||||
classes: [
|
||||
cls.name.toLowerCase(),
|
||||
"d" + term.faces,
|
||||
!isL5rDie && r.rerolled ? "rerolled" : null,
|
||||
!isL5rDie && r.exploded ? "exploded" : null,
|
||||
isL5rDie && r.swapped ? "swapped" : null,
|
||||
r.rerolled ? "rerolled" : null,
|
||||
r.exploded ? "exploded" : null,
|
||||
!isL5rDie && r.discarded ? "discarded" : null,
|
||||
!isL5rDie && r.result === 1 ? "min" : null,
|
||||
!isL5rDie && r.result === term.faces ? "max" : null,
|
||||
@@ -204,13 +246,6 @@ export class RollL5r5e extends Roll {
|
||||
this.roll();
|
||||
}
|
||||
|
||||
const canRnK = false; // TODO TMP dev in progress
|
||||
// const canRnK = !this.l5r5e.dicesTypes.std
|
||||
// && this.l5r5e.dicesTypes.l5r
|
||||
// && this.dice.length > 1
|
||||
// && this.l5r5e.actor // pb with dice with no actor
|
||||
// && this.l5r5e.actor.owner;
|
||||
|
||||
// Define chat data
|
||||
const chatData = {
|
||||
formula: isPrivate ? "???" : this._formula,
|
||||
@@ -224,13 +259,20 @@ export class RollL5r5e extends Roll {
|
||||
? {}
|
||||
: {
|
||||
...this.l5r5e,
|
||||
canRnK: canRnK,
|
||||
dices: this.dice.map((d) => {
|
||||
dices: this.dice.map((term) => {
|
||||
const isL5rDie = term instanceof game.l5r5e.L5rBaseDie;
|
||||
return {
|
||||
diceTypeL5r: d instanceof game.l5r5e.L5rBaseDie,
|
||||
rolls: d.results.map((r) => {
|
||||
diceTypeL5r: isL5rDie,
|
||||
rolls: term.results.map((r) => {
|
||||
return {
|
||||
result: d.constructor.getResultLabel(r.result),
|
||||
result: term.constructor.getResultLabel(r.result),
|
||||
classes: [
|
||||
isL5rDie && r.swapped ? "swapped" : null,
|
||||
r.rerolled ? "rerolled" : null,
|
||||
r.exploded ? "exploded" : null,
|
||||
]
|
||||
.filter((c) => !!c)
|
||||
.join(" "),
|
||||
};
|
||||
}),
|
||||
};
|
||||
@@ -294,10 +336,16 @@ export class RollL5r5e extends Roll {
|
||||
roll.l5r5e = duplicate(data.l5r5e);
|
||||
|
||||
// get real Actor object
|
||||
if (data.l5r5e.actor && !(data.l5r5e.actor instanceof game.l5r5e.ActorL5r5e)) {
|
||||
const actor = game.actors.get(data.l5r5e.actor.id);
|
||||
if (actor) {
|
||||
roll.l5r5e.actor = actor;
|
||||
if (data.l5r5e.actor) {
|
||||
if (data.l5r5e.actor instanceof game.l5r5e.ActorL5r5e) {
|
||||
// duplicate break the object, relink it
|
||||
roll.l5r5e.actor = data.l5r5e.actor;
|
||||
} else {
|
||||
// only id, get the object
|
||||
const actor = game.actors.get(data.l5r5e.actor.id);
|
||||
if (actor) {
|
||||
roll.l5r5e.actor = actor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,13 @@ export const RegisterHandlebars = function () {
|
||||
return game.i18n.localize("l5r5e.techniques." + techniqueName.toLowerCase());
|
||||
});
|
||||
|
||||
/* ------------------------------------ */
|
||||
/* Dice */
|
||||
/* ------------------------------------ */
|
||||
Handlebars.registerHelper("getDiceFaceUrl", function (diceClass, faceId) {
|
||||
return game.l5r5e[diceClass].getResultSrc(faceId);
|
||||
});
|
||||
|
||||
/* ------------------------------------ */
|
||||
/* Utility */
|
||||
/* ------------------------------------ */
|
||||
|
||||
@@ -68,6 +68,11 @@ export class HelpersL5r5e {
|
||||
*/
|
||||
static async getObjectGameOrPack(id, type, pack = null) {
|
||||
try {
|
||||
// If no pack passed, but it's a core item, we know the pack to get it
|
||||
if (!pack && id.substr(0, 7) === "L5RCore") {
|
||||
pack = HelpersL5r5e.getPackNameForCoreItem(id);
|
||||
}
|
||||
|
||||
// Named pack
|
||||
if (pack) {
|
||||
const data = await game.packs.get(pack).getEntity(id);
|
||||
@@ -184,4 +189,65 @@ export class HelpersL5r5e {
|
||||
static escapeRegExp(str) {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated pack for a core item (time saving)
|
||||
*/
|
||||
static getPackNameForCoreItem(itemId) {
|
||||
const core = new Map();
|
||||
core.set("Pro", "l5r5e.core-properties");
|
||||
core.set("Kat", "l5r5e.core-techniques-kata");
|
||||
core.set("Kih", "l5r5e.core-techniques-kiho");
|
||||
core.set("Ins", "l5r5e.core-techniques-inversion");
|
||||
core.set("Inv", "l5r5e.core-techniques-invocations");
|
||||
core.set("Rit", "l5r5e.core-techniques-rituals");
|
||||
core.set("Shu", "l5r5e.core-techniques-shuji");
|
||||
core.set("Mah", "l5r5e.core-techniques-maho");
|
||||
core.set("Nin", "l5r5e.core-techniques-ninjutsu");
|
||||
core.set("Sch", "l5r5e.core-techniques-school");
|
||||
core.set("Mas", "l5r5e.core-techniques-mastery");
|
||||
core.set("Ite", "l5r5e.core-items");
|
||||
core.set("Arm", "l5r5e.core-armors");
|
||||
core.set("Wea", "l5r5e.core-weapons");
|
||||
core.set("Dis", "l5r5e.core-peculiarities-distinctions");
|
||||
core.set("Pas", "l5r5e.core-peculiarities-passions");
|
||||
core.set("Adv", "l5r5e.core-peculiarities-adversities");
|
||||
core.set("Anx", "l5r5e.core-peculiarities-anxieties");
|
||||
return core.get(itemId.replace(/L5RCore(\w{3})\d+/gi, "$1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a confirm dialog before a deletion
|
||||
* @param {string} content
|
||||
* @param {function} callback The callback function for confirmed action
|
||||
*/
|
||||
static confirmDeleteDialog(content, callback) {
|
||||
new Dialog({
|
||||
title: game.i18n.localize("Delete"),
|
||||
content,
|
||||
buttons: {
|
||||
confirm: {
|
||||
icon: '<i class="fas fa-trash"></i>',
|
||||
label: game.i18n.localize("Yes"),
|
||||
callback,
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: game.i18n.localize("No"),
|
||||
},
|
||||
},
|
||||
}).render(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify Applications using Difficulty settings that the values was changed
|
||||
*/
|
||||
static notifyDifficultyChange() {
|
||||
["l5r5e-dice-picker-dialog", "l5r5e-gm-tools-dialog"].forEach((appId) => {
|
||||
const app = Object.values(ui.windows).find((e) => e.id === appId);
|
||||
if (app && typeof app.refresh === "function") {
|
||||
app.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,27 +122,21 @@ export default class HooksL5r5e {
|
||||
.then(() => HooksL5r5e._gmCombatBar(app, html, data));
|
||||
});
|
||||
|
||||
html.find(".prepared-control").on("click", (event) => {
|
||||
html.find(".prepared-control").on("mousedown", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
let preparedId = $(event.currentTarget).data("id");
|
||||
const preparedId = $(event.currentTarget).data("id");
|
||||
if (!Object.hasOwnProperty.call(prepared, preparedId)) {
|
||||
return;
|
||||
}
|
||||
let value = prepared[preparedId];
|
||||
switch (value) {
|
||||
case "false":
|
||||
value = "true";
|
||||
break;
|
||||
case "true":
|
||||
value = "null";
|
||||
break;
|
||||
case "null":
|
||||
value = "false";
|
||||
break;
|
||||
}
|
||||
const rev = event.which === 3;
|
||||
const nextValue = {
|
||||
false: rev ? "true" : "null",
|
||||
true: rev ? "null" : "false",
|
||||
null: rev ? "false" : "true",
|
||||
};
|
||||
game.settings
|
||||
.set("l5r5e", `initiative.prepared.${preparedId}`, value)
|
||||
.set("l5r5e", `initiative.prepared.${preparedId}`, nextValue[prepared[preparedId]])
|
||||
.then(() => HooksL5r5e._gmCombatBar(app, html, data));
|
||||
});
|
||||
}
|
||||
@@ -174,7 +168,7 @@ export default class HooksL5r5e {
|
||||
}
|
||||
|
||||
/**
|
||||
* DiceSoNice Hook
|
||||
* DiceSoNice - Add L5R DicePresets
|
||||
*/
|
||||
static diceSoNiceReady(dice3d) {
|
||||
const texturePath = `${CONFIG.l5r5e.paths.assets}dices/default/3d/`;
|
||||
@@ -218,4 +212,16 @@ export default class HooksL5r5e {
|
||||
"d12"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* DiceSoNice - Do not show 3D roll for the Roll n Keep series
|
||||
*
|
||||
* @param {string} messageId
|
||||
* @param {object} context
|
||||
*/
|
||||
static diceSoNiceRollStart(messageId, context) {
|
||||
if (context.roll.l5r5e?.history) {
|
||||
context.blind = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ export class ItemL5r5e extends Item {
|
||||
* @override
|
||||
*/
|
||||
static async create(data, options = {}) {
|
||||
data.img = `${CONFIG.l5r5e.paths.assets}icons/items/${data.type}.svg`;
|
||||
if (data.img === undefined) {
|
||||
data.img = `${CONFIG.l5r5e.paths.assets}icons/items/${data.type}.svg`;
|
||||
}
|
||||
return super.create(data, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,12 +105,7 @@ export class ItemSheetL5r5e extends ItemSheet {
|
||||
});
|
||||
|
||||
// Delete a property
|
||||
html.find(`.property-delete`).on("click", (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const li = $(event.currentTarget).parents(".property");
|
||||
this._deleteProperty(li.data("propertyId"));
|
||||
});
|
||||
html.find(`.property-delete`).on("click", this._deleteProperty.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,20 +169,37 @@ export class ItemSheetL5r5e extends ItemSheet {
|
||||
* Delete a property from the current item
|
||||
* @private
|
||||
*/
|
||||
_deleteProperty(id) {
|
||||
if (
|
||||
!Array.isArray(this.entity.data.data.properties) ||
|
||||
this.entity.data.data.properties.findIndex((p) => p.id === id) === -1
|
||||
) {
|
||||
_deleteProperty(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
if (!Array.isArray(this.entity.data.data.properties)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.entity.data.data.properties = this.entity.data.data.properties.filter((p) => p.id !== id);
|
||||
const id = $(event.currentTarget).parents(".property").data("propertyId");
|
||||
const tmpProps = this.entity.data.data.properties.find((p) => p.id === id);
|
||||
if (!tmpProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.entity.update({
|
||||
data: {
|
||||
properties: this.entity.data.data.properties,
|
||||
},
|
||||
});
|
||||
const callback = async () => {
|
||||
this.entity.data.data.properties = this.entity.data.data.properties.filter((p) => p.id !== id);
|
||||
this.entity.update({
|
||||
data: {
|
||||
properties: this.entity.data.data.properties,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Holing Ctrl = without confirm
|
||||
if (event.ctrlKey) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
game.l5r5e.HelpersL5r5e.confirmDeleteDialog(
|
||||
game.i18n.format("l5r5e.global.delete_confirm", { name: tmpProps.name }),
|
||||
callback
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +113,40 @@ Hooks.once("init", async () => {
|
||||
// Journal
|
||||
Items.unregisterSheet("core", JournalSheet);
|
||||
Items.registerSheet("l5r5e", BaseJournalSheetL5r5e, { makeDefault: true });
|
||||
|
||||
// Override the default Token _drawBar function to allow fatigue bar reversing.
|
||||
Token.prototype._drawBar = function (number, bar, data) {
|
||||
const reverseBar = data.attribute === "fatigue" && game.settings.get("l5r5e", "token.reverseFatigueBar");
|
||||
|
||||
// Bar value
|
||||
const pct = Math.clamped(Number(data.value), 0, data.max) / data.max;
|
||||
|
||||
// Modify color
|
||||
let color = number === 0 ? [pct / 1.2, 1 - pct, 0] : [0.5 * pct, 0.7 * pct, 0.5 + pct / 2];
|
||||
|
||||
// Red if compromised
|
||||
if (data.attribute === "strife" && data.value > data.max) {
|
||||
color = [1, 0.1, 0.1];
|
||||
}
|
||||
|
||||
// Enlarge the bar for large tokens
|
||||
let h = Math.max(canvas.dimensions.size / 12, 8);
|
||||
if (this.data.height >= 2) {
|
||||
h *= 1.6;
|
||||
}
|
||||
|
||||
// Draw the bar
|
||||
bar.clear()
|
||||
.beginFill(0x000000, 0.5)
|
||||
.lineStyle(2, 0x000000, 0.9)
|
||||
.drawRoundedRect(0, 0, this.w, h, 3)
|
||||
.beginFill(PIXI.utils.rgb2hex(color), 0.8)
|
||||
.lineStyle(1, 0x000000, 0.8)
|
||||
.drawRoundedRect(1, 1, (reverseBar ? 1 - pct : pct) * (this.w - 2), h - 2, 2);
|
||||
|
||||
// Set position
|
||||
bar.position.set(0, number === 0 ? this.h - h : 0);
|
||||
};
|
||||
});
|
||||
|
||||
/* ------------------------------------ */
|
||||
@@ -129,3 +163,4 @@ Hooks.on("renderSidebarTab", (app, html, data) => HooksL5r5e.renderSidebarTab(ap
|
||||
Hooks.on("renderChatMessage", (message, html, data) => HooksL5r5e.renderChatMessage(message, html, data));
|
||||
Hooks.on("renderCombatTracker", (app, html, data) => HooksL5r5e.renderCombatTracker(app, html, data));
|
||||
Hooks.on("renderCompendium", async (app, html, data) => HooksL5r5e.renderCompendium(app, html, data));
|
||||
Hooks.on("diceSoNiceRollStart", (messageId, context) => HooksL5r5e.diceSoNiceRollStart(messageId, context));
|
||||
|
||||
@@ -2,6 +2,33 @@
|
||||
* Custom system settings register
|
||||
*/
|
||||
export const RegisterSettings = function () {
|
||||
/* ------------------------------------ */
|
||||
/* User settings */
|
||||
/* ------------------------------------ */
|
||||
game.settings.register("l5r5e", "rnk.deleteOldMessage", {
|
||||
name: "SETTINGS.RollNKeep.DeleteOldMessage",
|
||||
hint: "SETTINGS.RollNKeep.DeleteOldMessageHint",
|
||||
scope: "world",
|
||||
config: true,
|
||||
default: true,
|
||||
type: Boolean,
|
||||
});
|
||||
game.settings.register("l5r5e", "initiative.setTn1OnTypeChange", {
|
||||
name: "SETTINGS.Initiative.SetTn1OnTypeChange",
|
||||
hint: "SETTINGS.Initiative.SetTn1OnTypeChangeHint",
|
||||
scope: "world",
|
||||
config: true,
|
||||
type: Boolean,
|
||||
default: true,
|
||||
});
|
||||
game.settings.register("l5r5e", "token.reverseFatigueBar", {
|
||||
name: "SETTINGS.ReverseFatigueBar",
|
||||
scope: "world",
|
||||
config: true,
|
||||
type: Boolean,
|
||||
default: false,
|
||||
});
|
||||
|
||||
/* ------------------------------------ */
|
||||
/* Update */
|
||||
/* ------------------------------------ */
|
||||
@@ -22,6 +49,7 @@ export const RegisterSettings = function () {
|
||||
config: false,
|
||||
type: Boolean,
|
||||
default: false,
|
||||
onChange: () => game.l5r5e.HelpersL5r5e.notifyDifficultyChange(),
|
||||
});
|
||||
game.settings.register("l5r5e", "initiative.difficulty.value", {
|
||||
name: "Initiative difficulty value",
|
||||
@@ -29,6 +57,7 @@ export const RegisterSettings = function () {
|
||||
config: false,
|
||||
type: Number,
|
||||
default: 2,
|
||||
onChange: () => game.l5r5e.HelpersL5r5e.notifyDifficultyChange(),
|
||||
});
|
||||
game.settings.register("l5r5e", "initiative.encounter", {
|
||||
name: "Initiative encounter type",
|
||||
@@ -36,6 +65,11 @@ export const RegisterSettings = function () {
|
||||
config: false,
|
||||
type: String,
|
||||
default: "skirmish",
|
||||
onChange: () => {
|
||||
if (game.settings.get("l5r5e", "initiative.setTn1OnTypeChange")) {
|
||||
game.settings.set("l5r5e", "initiative.difficulty.value", 1);
|
||||
}
|
||||
},
|
||||
});
|
||||
game.settings.register("l5r5e", "initiative.prepared.character", {
|
||||
name: "Initiative PC prepared or not",
|
||||
|
||||
@@ -25,6 +25,10 @@ export class SocketHandlerL5r5e {
|
||||
this._onRefreshAppId(data);
|
||||
break;
|
||||
|
||||
case "updateMessageIdAndRefresh":
|
||||
this._onUpdateMessageIdAndRefresh(data);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn(new Error("This socket event is not supported"), data);
|
||||
break;
|
||||
@@ -40,9 +44,13 @@ export class SocketHandlerL5r5e {
|
||||
});
|
||||
}
|
||||
_onDeleteChatMessage(data) {
|
||||
// Only delete the message if the user is a GM (otherwise it have no real effect)
|
||||
// Currently only used in RnK
|
||||
if (!game.user.isGM || !game.settings.get("l5r5e", "rnk.deleteOldMessage")) {
|
||||
return;
|
||||
}
|
||||
const message = game.messages.get(data.messageId);
|
||||
// only delete the message if the user is a GM and the event emitter is one of the recipients
|
||||
if (game.user.isGM && message.data["whisper"].includes(data.userId)) {
|
||||
if (message) {
|
||||
message.delete();
|
||||
}
|
||||
}
|
||||
@@ -65,4 +73,25 @@ export class SocketHandlerL5r5e {
|
||||
}
|
||||
app.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change in app message and refresh (used in RnK)
|
||||
* @param appId
|
||||
* @param msgId
|
||||
*/
|
||||
updateMessageIdAndRefresh(appId, msgId) {
|
||||
game.socket.emit(SocketHandlerL5r5e.SOCKET_NAME, {
|
||||
type: "updateMessageIdAndRefresh",
|
||||
appId,
|
||||
msgId,
|
||||
});
|
||||
}
|
||||
_onUpdateMessageIdAndRefresh(data) {
|
||||
const app = Object.values(ui.windows).find((e) => e.id === data.appId);
|
||||
if (!app || !app.message || typeof app.refresh !== "function") {
|
||||
return;
|
||||
}
|
||||
app.message = game.messages.get(data.msgId);
|
||||
app.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
@import "../scss/ui";
|
||||
|
||||
.l5r5e {
|
||||
@import "../scss/dices";
|
||||
@import "../scss/dices-chat";
|
||||
@import "../scss/sheets";
|
||||
@import "../scss/npc";
|
||||
@import "../scss/nav";
|
||||
|
||||
File diff suppressed because one or more lines are too long
73
system/styles/scss/dices-chat.scss
Normal file
73
system/styles/scss/dices-chat.scss
Normal file
@@ -0,0 +1,73 @@
|
||||
// Dice in chat
|
||||
.chat-dice {
|
||||
display: inline;
|
||||
position: relative;
|
||||
padding: 0.25rem;
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
border-radius: 0.15rem;
|
||||
padding: 0 0.1rem 0 0.15rem;
|
||||
font-size: 0.65rem;
|
||||
line-height: 1rem;
|
||||
width: 0.75rem;
|
||||
text-align: center;
|
||||
color: white;
|
||||
background: transparent;
|
||||
}
|
||||
&.rerolled {
|
||||
> img {
|
||||
border-bottom: 0 none;
|
||||
}
|
||||
&:after {
|
||||
content: "\f2f9";
|
||||
background: orangered;
|
||||
}
|
||||
}
|
||||
|
||||
&.swapped {
|
||||
> img {
|
||||
border-bottom: 0 none;
|
||||
}
|
||||
&:after {
|
||||
content: "\f337";
|
||||
background: fuchsia;
|
||||
}
|
||||
}
|
||||
|
||||
> img {
|
||||
border: 1px solid transparent;
|
||||
height: auto;
|
||||
width: calc(100% / 6 - 0.255rem);
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-profil {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
||||
.profile-img {
|
||||
margin: 0.25rem 0.25rem 0 0;
|
||||
}
|
||||
|
||||
&-stance {
|
||||
font-size: 2.5rem;
|
||||
line-height: 2.5rem;
|
||||
margin: 0.25rem;
|
||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
&-element {
|
||||
flex-wrap: wrap;
|
||||
flex-grow: 1;
|
||||
|
||||
&-skill {
|
||||
flex-grow: 3;
|
||||
}
|
||||
&:last-child {
|
||||
flex-grow: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +1,67 @@
|
||||
// -- Dices.scss
|
||||
|
||||
.dice-roll {
|
||||
.dice-formula,
|
||||
.dice-total {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border: rgba(255, 255, 255, 0.75);
|
||||
text-align: center;
|
||||
margin: 0.5rem 0;
|
||||
padding: 0.25rem 0.5rem 0.25rem 0.25rem;
|
||||
&-rnk {
|
||||
line-height: 2rem;
|
||||
i {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dice in chat
|
||||
.chat-dice > img {
|
||||
border: 1px solid transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 100%;
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
//cursor: pointer;
|
||||
//-webkit-appearance: none;
|
||||
//appearance: none;
|
||||
outline: none;
|
||||
margin: 0;
|
||||
flex: 0 0 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.chat-profil {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
||||
&-stance {
|
||||
font-size: 40px;
|
||||
position: relative;
|
||||
top: 8px;
|
||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
|
||||
button {
|
||||
&.chat-dice-rnk {
|
||||
cursor: default;
|
||||
color: $white;
|
||||
background: linear-gradient(
|
||||
$l5r5e-linear-gradient-third,
|
||||
$l5r5e-linear-gradient-third-dark,
|
||||
$l5r5e-linear-gradient-third
|
||||
);
|
||||
background-origin: padding-box;
|
||||
border-image: url("../assets/ui/macro-button.webp") 10 repeat;
|
||||
border-image-width: 0.5rem;
|
||||
border-image-outset: 0px;
|
||||
margin: 0.5rem 0 0;
|
||||
&:hover {
|
||||
background: linear-gradient(
|
||||
$l5r5e-linear-gradient-first-dark,
|
||||
$l5r5e-linear-gradient-first,
|
||||
$l5r5e-linear-gradient-first-dark
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
&-element {
|
||||
flex-wrap: wrap;
|
||||
flex-grow: 1;
|
||||
|
||||
&-skill {
|
||||
flex-grow: 3;
|
||||
.dice-result-rnk {
|
||||
background: rgba(0, 0, 255, 0.1);
|
||||
border: 1px solid rgba(55, 55, 155, 0.75);
|
||||
padding: 0.25rem;
|
||||
color: rgba(55, 55, 155, 0.75);
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
text-shadow: 0 0 0 $black;
|
||||
&.success {
|
||||
background: rgba(0, 255, 0, 0.1);
|
||||
border-color: rgba(55, 155, 55, 0.75);
|
||||
color: rgba(55, 155, 55, 0.75);
|
||||
i.i_success {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
&.unknown {
|
||||
background: rgba(121, 121, 121, 0.1);
|
||||
border-color: rgba(124, 124, 124, 0.75);
|
||||
color: rgba(91, 91, 91, 0.75);
|
||||
}
|
||||
&.fail {
|
||||
background: rgba(255, 0, 0, 0.1);
|
||||
border-color: rgba(155, 55, 55, 0.75);
|
||||
color: rgba(155, 55, 55, 0.75);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +73,8 @@
|
||||
|
||||
// Dice Picker
|
||||
.dice-picker-dialog {
|
||||
min-width: 600px;
|
||||
min-height: auto;
|
||||
// Utility
|
||||
* {
|
||||
transition: none;
|
||||
@@ -72,18 +95,26 @@
|
||||
text-align: center;
|
||||
background: none;
|
||||
border: none;
|
||||
height: calc(100% - 3rem);
|
||||
|
||||
td:first-child {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
td {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
td:last-child {
|
||||
width: 200px;
|
||||
border: 0 none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
tbody {
|
||||
tr {
|
||||
td {
|
||||
width: 250px;
|
||||
padding: 0 0.5rem;
|
||||
&:first-child,
|
||||
&:last-child {
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
&:last-child {
|
||||
td {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,17 +182,75 @@
|
||||
}
|
||||
|
||||
.roll-n-keep-dialog {
|
||||
min-width: 600px;
|
||||
max-width: 800px;
|
||||
&.finalized {
|
||||
width: auto;
|
||||
min-width: 400px;
|
||||
}
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
table {
|
||||
display: table;
|
||||
min-height: 9rem;
|
||||
border: 0 none;
|
||||
margin: 0.25rem 0;
|
||||
padding: 0;
|
||||
tbody {
|
||||
tr {
|
||||
background: transparent;
|
||||
td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rnk-ct {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
border-radius: 0.25rem;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
.rnk-center {
|
||||
flex: 350px;
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.profil {
|
||||
border-bottom: 1px solid #782e22;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.dropbox {
|
||||
min-height: 100px;
|
||||
position: relative;
|
||||
min-height: 7rem;
|
||||
|
||||
legend {
|
||||
i:last-child {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
border-radius: 0.15rem;
|
||||
padding: 0 0.1rem 0 0.15rem;
|
||||
font-size: 0.65rem;
|
||||
line-height: 1rem;
|
||||
width: 1rem;
|
||||
margin: 0.25rem;
|
||||
text-align: center;
|
||||
color: white;
|
||||
background: $l5r5e-label;
|
||||
}
|
||||
}
|
||||
|
||||
&.faces-change {
|
||||
min-height: 40px;
|
||||
margin: 0.5rem auto;
|
||||
}
|
||||
&.discards {
|
||||
border: 1px solid gray;
|
||||
}
|
||||
@@ -169,31 +258,142 @@
|
||||
border: 1px solid orangered;
|
||||
}
|
||||
&.keeps {
|
||||
flex: 100%;
|
||||
border: 1px solid green;
|
||||
}
|
||||
&.swap {
|
||||
flex: 0 0 calc(100px + 1rem);
|
||||
flex-direction: column;
|
||||
border: 1px solid fuchsia;
|
||||
}
|
||||
&.discards,
|
||||
&.rerolls {
|
||||
flex: 0 0 calc(50% - 0.5rem);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
/* Dice Marker */
|
||||
.dice-ct {
|
||||
position: relative;
|
||||
padding: 0.25rem;
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
height: 0.5rem;
|
||||
width: 2px;
|
||||
top: -0.3rem;
|
||||
right: calc(50% - 1px);
|
||||
background: $l5r5e-black-light;
|
||||
}
|
||||
&:after {
|
||||
content: "\f128";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
border-radius: 0.15rem;
|
||||
padding: 0 0.1rem 0 0.15rem;
|
||||
font-size: 0.65rem;
|
||||
line-height: 1rem;
|
||||
width: 0.65rem;
|
||||
text-align: center;
|
||||
color: white;
|
||||
background: gray;
|
||||
}
|
||||
&.discard {
|
||||
filter: opacity(0.5);
|
||||
&:after {
|
||||
content: "\f00d";
|
||||
background: gray;
|
||||
}
|
||||
}
|
||||
&.reroll {
|
||||
filter: opacity(0.5);
|
||||
&:after {
|
||||
content: "\f2f9";
|
||||
background: orangered;
|
||||
}
|
||||
}
|
||||
&.keep {
|
||||
&:after {
|
||||
content: "\f00c";
|
||||
background: green;
|
||||
}
|
||||
}
|
||||
&.swap {
|
||||
&:after {
|
||||
content: "\f337";
|
||||
background: fuchsia;
|
||||
}
|
||||
}
|
||||
}
|
||||
tr:first-child .dice-ct {
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dice {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
&.discard {
|
||||
filter: opacity(0.5);
|
||||
border: 0 none;
|
||||
}
|
||||
&.reroll {
|
||||
filter: opacity(0.5);
|
||||
border: 0 none;
|
||||
}
|
||||
&.keep {
|
||||
border: 0 none;
|
||||
}
|
||||
&.swap {
|
||||
border: 0 none;
|
||||
}
|
||||
}
|
||||
|
||||
.discard {
|
||||
filter: opacity(0.5);
|
||||
border: 3px solid gray;
|
||||
#finalize {
|
||||
width: 100%;
|
||||
margin: 0.5rem 0.25rem 0.25rem;
|
||||
}
|
||||
.reroll {
|
||||
filter: opacity(0.5);
|
||||
border: 3px solid orangered;
|
||||
.section-header {
|
||||
i {
|
||||
font-size: 0.75rem;
|
||||
margin: 0 0.25rem;
|
||||
}
|
||||
}
|
||||
.keep {
|
||||
border: 3px solid green;
|
||||
.fa-sign-in-alt {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.chat-profil {
|
||||
ul {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
li {
|
||||
&:nth-child(1),
|
||||
&:nth-child(2) {
|
||||
flex: 0 0 4rem;
|
||||
padding: 0 0.25rem 0.25rem;
|
||||
}
|
||||
&:nth-child(4) {
|
||||
flex: 0 0 4rem;
|
||||
padding: 0 0.25rem 0.25rem;
|
||||
}
|
||||
}
|
||||
.profile-img {
|
||||
width: 4rem;
|
||||
}
|
||||
.chat-profil-stance {
|
||||
font-size: 3.5rem;
|
||||
line-height: 3.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#l5r5e-gm-tools-dialog {
|
||||
bottom: 0;
|
||||
right: 0.5rem;
|
||||
//bottom: 0;
|
||||
//right: 0.5rem;
|
||||
display: flex;
|
||||
background-position: center;
|
||||
background-size: 100%;
|
||||
@@ -208,13 +408,15 @@
|
||||
border-image: url("../assets/ui/macro-button.webp") 10 repeat;
|
||||
border-image-width: 0.5rem;
|
||||
border-image-outset: 0px;
|
||||
padding: 0;
|
||||
margin: 0.5rem;
|
||||
.window-header {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid rgb(195, 165, 130);
|
||||
h4 {
|
||||
font-family: $font-primary;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.15rem;
|
||||
letter-spacing: 0.25rem;
|
||||
line-height: 2.25rem;
|
||||
color: $white-light;
|
||||
}
|
||||
}
|
||||
.window-content {
|
||||
@@ -222,22 +424,50 @@
|
||||
vertical-align: middle;
|
||||
background: transparent;
|
||||
color: $white-light;
|
||||
form {
|
||||
padding: 0;
|
||||
}
|
||||
.gm-tools-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-flow: wrap;
|
||||
a {
|
||||
font-size: 2rem;
|
||||
line-height: 2rem;
|
||||
min-height: 2rem;
|
||||
margin: 0;
|
||||
li {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-right: 1px solid #c3a582;
|
||||
cursor: url("../assets/cursors/pointer.webp"), pointer;
|
||||
i {
|
||||
font-size: 3rem;
|
||||
line-height: 4rem;
|
||||
vertical-align: middle;
|
||||
&:last-child {
|
||||
margin: 0;
|
||||
border: 0 none;
|
||||
}
|
||||
:hover {
|
||||
text-shadow: 0 0 $red;
|
||||
}
|
||||
}
|
||||
.difficulty {
|
||||
flex: 1;
|
||||
font-size: 3rem;
|
||||
.difficulty_hidden {
|
||||
.fa {
|
||||
width: 3rem;
|
||||
}
|
||||
.difficulty {
|
||||
flex: 1rem;
|
||||
width: 2rem;
|
||||
font-size: 2rem;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
}
|
||||
.fa {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
.fa-bed,
|
||||
.fa-star-half-alt {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -246,3 +476,34 @@
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dice-picker-dialog,
|
||||
.roll-n-keep-dialog {
|
||||
button {
|
||||
cursor: default;
|
||||
color: $white;
|
||||
background: linear-gradient(
|
||||
$l5r5e-linear-gradient-third,
|
||||
$l5r5e-linear-gradient-third-dark,
|
||||
$l5r5e-linear-gradient-third
|
||||
);
|
||||
background-origin: padding-box;
|
||||
border-image: url("../assets/ui/macro-button.webp") 10 repeat;
|
||||
border-image-width: 0.5rem;
|
||||
border-image-outset: 0px;
|
||||
margin: 0.5rem 0 0;
|
||||
&:hover {
|
||||
background: linear-gradient(
|
||||
$l5r5e-linear-gradient-first-dark,
|
||||
$l5r5e-linear-gradient-first,
|
||||
$l5r5e-linear-gradient-first-dark
|
||||
);
|
||||
}
|
||||
&[disabled] {
|
||||
opacity: 0.25;
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +186,7 @@ li {
|
||||
// Fieldset
|
||||
fieldset {
|
||||
flex: 1;
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
margin: 0 0.25rem;
|
||||
padding: 0.5rem;
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
width: 100%;
|
||||
line-height: 2rem;
|
||||
font-size: 0.75rem;
|
||||
margin: 0.25rem 0.25rem 0.5rem;
|
||||
margin: 0 0 0.5rem;
|
||||
text-align: center;
|
||||
li {
|
||||
flex: 1;
|
||||
@@ -133,24 +133,32 @@
|
||||
}
|
||||
}
|
||||
article {
|
||||
.weapons-content {
|
||||
flex: 1;
|
||||
}
|
||||
min-height: auto;
|
||||
display: flex;
|
||||
fieldset {
|
||||
fieldset,
|
||||
.checklist {
|
||||
flex: 0 0 calc(100% - 0.5rem);
|
||||
}
|
||||
.items-content {
|
||||
flex: 0 0 calc(100% - 0.5rem);
|
||||
margin: 1rem 0.25rem 0;
|
||||
}
|
||||
.weapons-content {
|
||||
flex: 1;
|
||||
}
|
||||
.initiative-wrapper {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
&:last-child {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
.techniques-wrapper {
|
||||
padding-left: 0.5rem;
|
||||
fieldset,
|
||||
.checklist {
|
||||
flex: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.npc-note {
|
||||
.editor {
|
||||
|
||||
@@ -17,13 +17,6 @@
|
||||
.sheet-body {
|
||||
height: calc(100% - 27rem);
|
||||
}
|
||||
.techniques-wrapper {
|
||||
fieldset {
|
||||
&:last-child {
|
||||
margin: 0 0 0 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
fieldset {
|
||||
&.advancement {
|
||||
display: block;
|
||||
@@ -501,6 +494,31 @@
|
||||
padding: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
min-height: calc(100% - 3.25rem);
|
||||
fieldset {
|
||||
h3 {
|
||||
font-size: 1.25rem;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
line-height: 2rem;
|
||||
color: $l5r5e-bold;
|
||||
border-bottom: 1px solid;
|
||||
.item-control {
|
||||
&.item-add {
|
||||
float: right;
|
||||
font-size: 0.75rem;
|
||||
line-height: 0.75rem;
|
||||
border: 1px solid;
|
||||
padding: 0.25rem;
|
||||
margin: 0.25rem;
|
||||
color: $white;
|
||||
background: $l5r5e-bold;
|
||||
&:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.tab[data-tab] {
|
||||
&.active {
|
||||
display: flex;
|
||||
@@ -517,11 +535,15 @@
|
||||
}
|
||||
}
|
||||
.techniques-wrapper {
|
||||
padding-left: 0.25rem;
|
||||
fieldset {
|
||||
margin: 0 0 0 0.25rem;
|
||||
}
|
||||
.checklist {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
font-size: 0.85rem;
|
||||
margin: 0 0 0.25rem 0.5rem;
|
||||
margin: 0 0 0.25rem 0.25rem;
|
||||
padding: 0.5rem;
|
||||
background: $l5r5e-title;
|
||||
--notchSize: 0.25rem;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "l5r5e",
|
||||
"title": "Legend of the Five Rings (5th Edition)",
|
||||
"description": "This is an authorised multilingual game system En|Fr|Es, for Legend of the Five Rings (5th Edition) by <a href='https://edge-studio.net/'>Edge Studio</a> <p> - Join the official Discord server: <a href='https://discord.gg/foundryvtt'> Official Discord</a></p><p> - Rejoignez la communauté Francophone: <a href='https://discord.gg/pPSDNJk'>Francophone Discord</a></p>",
|
||||
"version": "1.1.2",
|
||||
"version": "1.2.1",
|
||||
"minimumCoreVersion": "0.7.9",
|
||||
"compatibleCoreVersion": "0.7.9",
|
||||
"manifestPlusVersion": "1.0.0",
|
||||
@@ -185,5 +185,5 @@
|
||||
],
|
||||
"url": "https://gitlab.com/teaml5r/l5r5e",
|
||||
"manifest": "https://gitlab.com/teaml5r/l5r5e/-/raw/master/system/system.json",
|
||||
"download": "https://gitlab.com/teaml5r/l5r5e/-/jobs/artifacts/v1.1.2/raw/l5r5e.zip?job=build"
|
||||
"download": "https://gitlab.com/teaml5r/l5r5e/-/jobs/artifacts/v1.2.1/raw/l5r5e.zip?job=build"
|
||||
}
|
||||
|
||||
@@ -102,8 +102,7 @@
|
||||
"ritual": false,
|
||||
"shuji": false,
|
||||
"maho": false,
|
||||
"ninjutsu": false,
|
||||
"list": []
|
||||
"ninjutsu": false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -62,7 +62,10 @@
|
||||
<input name="data.money.zeni" type="number" value="{{actor.data.money.zeni}}" data-dtype="Number" min="0" placeholder="0"/>
|
||||
</label>
|
||||
</fieldset>
|
||||
{{> 'systems/l5r5e/templates/items/item/items.html' }}
|
||||
<fieldset class="items-wrapper">
|
||||
<legend>{{localize 'l5r5e.equipment' }}</legend>
|
||||
{{> 'systems/l5r5e/templates/items/item/items.html' }}
|
||||
</fieldset>
|
||||
</article>
|
||||
|
||||
{{!-- Experience Tab --}}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
<ul class="rings">
|
||||
<li id="earth">
|
||||
<label class="earth">
|
||||
<i class="i_earth"></i>
|
||||
<i class="i_earth dice-picker rollable" data-ring="earth"></i>
|
||||
<strong>{{ localizeRing 'earth' }}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="data.rings.earth" value="{{data.rings.earth}}" data-dtype="Number" min="1" max="9" placeholder="0"/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="air">
|
||||
<label class="air">
|
||||
<i class="i_air"></i>
|
||||
<i class="i_air dice-picker rollable" data-ring="air"></i>
|
||||
<strong>{{ localizeRing 'air' }}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="data.rings.air" value="{{data.rings.air}}" data-dtype="Number" min="1" max="9" placeholder="0"/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="water">
|
||||
<label class="water">
|
||||
<i class="i_water"></i>
|
||||
<i class="i_water dice-picker rollable" data-ring="water"></i>
|
||||
<strong>{{ localizeRing 'water' }}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="data.rings.water" value="{{data.rings.water}}" data-dtype="Number" min="1" max="9" placeholder="0"/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="fire">
|
||||
<label class="fire">
|
||||
<i class="i_fire"></i>
|
||||
<i class="i_fire dice-picker rollable" data-ring="fire"></i>
|
||||
<strong>{{ localizeRing 'fire' }}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="data.rings.fire" value="{{data.rings.fire}}" data-dtype="Number" min="1" max="9" placeholder="0"/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="void">
|
||||
<label class="void">
|
||||
<i class="i_void"></i>
|
||||
<i class="i_void dice-picker rollable" data-ring="void"></i>
|
||||
<strong>{{ localizeRing 'void' }}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="data.rings.void" value="{{data.rings.void}}" data-dtype="Number" min="1" max="9" placeholder="0"/>
|
||||
</label>
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
</label>
|
||||
{{/each}}
|
||||
</div>
|
||||
<fieldset class="section-header flexrow">
|
||||
<legend class="technique-controls">
|
||||
{{ localize 'l5r5e.techniques.title' }}
|
||||
{{#if editable}}
|
||||
<a data-item-type="technique" class="technique-control item-add" title="{{ localize 'l5r5e.global.add' }}"><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</legend>
|
||||
<ul class="item-list">
|
||||
{{#each actor.items as |item id|}}
|
||||
{{#ifCond item.type '==' 'technique'}}
|
||||
{{> 'systems/l5r5e/templates/items/technique/technique-entry.html' technique=item editable=../editable }}
|
||||
{{#each actor.data.splitTechniquesList as |list technique|}}
|
||||
<fieldset class="section-header flexrow">
|
||||
<legend class="technique-controls">
|
||||
{{localize (localize 'l5r5e.techniques.{technique}' technique=technique) }}
|
||||
{{#ifCond ../editable '&&' (lookup ../actor.data.techniques technique)}}
|
||||
<a data-item-type="technique" class="technique-control item-add" data-tech-type="{{technique}}" title="{{ localize 'l5r5e.global.add' }}"><i class="fas fa-plus"></i></a>
|
||||
{{/ifCond}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</fieldset>
|
||||
</legend>
|
||||
<ul class="item-list">
|
||||
{{#each list as |item id|}}
|
||||
{{> 'systems/l5r5e/templates/items/technique/technique-entry.html' technique=item editable=../../editable }}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</fieldset>
|
||||
{{/each}}
|
||||
</div>
|
||||
@@ -20,20 +20,31 @@
|
||||
</header>
|
||||
{{!-- Sheet Body --}}
|
||||
<section class="sheet-body">
|
||||
<article>
|
||||
{{!-- Skills No Tab --}}
|
||||
{{> 'systems/l5r5e/templates/actors/npc/skill.html' }}
|
||||
{{> 'systems/l5r5e/templates/actors/npc/conflict.html' }}
|
||||
</article>
|
||||
<article>
|
||||
{{!-- Sheet Tab Navigation --}}
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item" data-tab="skills">{{ localize 'l5r5e.skills.title' }}</a>
|
||||
<a class="item" data-tab="conflict">{{ localize 'l5r5e.conflict.title' }}</a>
|
||||
<a class="item" data-tab="inventory">{{ localize 'l5r5e.inventory' }}</a>
|
||||
</nav>
|
||||
{{!-- Techniques Tab --}}
|
||||
<article class="tab skills" data-group="primary" data-tab="skills">
|
||||
{{> 'systems/l5r5e/templates/actors/npc/narrative.html' }}
|
||||
{{> 'systems/l5r5e/templates/actors/npc/techniques.html' }}
|
||||
</article>
|
||||
<article>
|
||||
{{!-- Conflict Tab --}}
|
||||
<article class="tab conflict" data-group="primary" data-tab="conflict">
|
||||
{{> 'systems/l5r5e/templates/actors/npc/conflict.html' }}
|
||||
{{> 'systems/l5r5e/templates/items/weapon/weapons.html' }}
|
||||
{{> 'systems/l5r5e/templates/items/armor/armors.html' }}
|
||||
{{> 'systems/l5r5e/templates/items/item/items.html' }}
|
||||
</article>
|
||||
<article>
|
||||
{{> 'systems/l5r5e/templates/actors/npc/techniques.html' }}
|
||||
{{!-- Inventory Tab --}}
|
||||
<article class="tab inventory" data-group="primary" data-tab="inventory">
|
||||
<fieldset class="items-wrapper">
|
||||
<legend>{{localize 'l5r5e.equipment' }}</legend>
|
||||
{{> 'systems/l5r5e/templates/items/item/items.html' }}
|
||||
</fieldset>
|
||||
</article>
|
||||
</section>
|
||||
</form>
|
||||
@@ -1,35 +1,35 @@
|
||||
<ul class="rings">
|
||||
<li id="earth">
|
||||
<label class="earth">
|
||||
<i class="i_earth"></i>
|
||||
<i class="i_earth dice-picker rollable" data-ring="earth"></i>
|
||||
<strong>{{ localizeRing 'earth' }}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="data.rings.earth" value="{{data.rings.earth}}" data-dtype="Number" min="1" max="9" placeholder="0"/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="air">
|
||||
<li id="air">
|
||||
<label class="air">
|
||||
<i class="i_air"></i>
|
||||
<i class="i_air dice-picker rollable" data-ring="air"></i>
|
||||
<strong>{{ localizeRing 'air' }}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="data.rings.air" value="{{data.rings.air}}" data-dtype="Number" min="1" max="9" placeholder="0"/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="water">
|
||||
<label class="water">
|
||||
<i class="i_water"></i>
|
||||
<i class="i_water dice-picker rollable" data-ring="water"></i>
|
||||
<strong>{{ localizeRing 'water' }}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="data.rings.water" value="{{data.rings.water}}" data-dtype="Number" min="1" max="9" placeholder="0"/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="fire">
|
||||
<label class="fire">
|
||||
<i class="i_fire"></i>
|
||||
<i class="i_fire dice-picker rollable" data-ring="fire"></i>
|
||||
<strong>{{ localizeRing 'fire' }}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="data.rings.fire" value="{{data.rings.fire}}" data-dtype="Number" min="1" max="9" placeholder="0"/>
|
||||
</label>
|
||||
</li>
|
||||
<li id="void">
|
||||
<label class="void">
|
||||
<i class="i_void"></i>
|
||||
<i class="i_void dice-picker rollable" data-ring="void"></i>
|
||||
<strong>{{ localizeRing 'void' }}</strong>
|
||||
<input class="centered-input select-on-focus" type="number" name="data.rings.void" value="{{data.rings.void}}" data-dtype="Number" min="1" max="9" placeholder="0"/>
|
||||
</label>
|
||||
|
||||
@@ -1,13 +1,29 @@
|
||||
<fieldset class="techniques-wrapper section-header flexrow">
|
||||
<legend class="technique-controls">
|
||||
{{ localize 'l5r5e.techniques.title' }}
|
||||
<a data-item-type="technique" class="technique-control item-add" title="{{ localize 'l5r5e.global.add' }}"><i class="fas fa-plus"></i></a>
|
||||
</legend>
|
||||
<ul class="item-list">
|
||||
{{#each actor.items as |item id|}}
|
||||
{{#ifCond item.type '==' 'technique'}}
|
||||
{{> 'systems/l5r5e/templates/items/technique/technique-entry.html' technique=item editable=../editable }}
|
||||
{{/ifCond}}
|
||||
<div class="checklist">
|
||||
<i>{{ localize 'l5r5e.techniques.type'}}</i>
|
||||
{{#each actor.data.techniquesList as |technique|}}
|
||||
<label>
|
||||
<input type="checkbox" name="data.techniques.{{technique}}" {{checked (lookup ../actor.data.techniques technique)}} />
|
||||
{{localizeTechnique technique}}
|
||||
</label>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{#each actor.data.splitTechniquesList as |list technique|}}
|
||||
<fieldset class="section-header flexrow">
|
||||
<legend class="technique-controls">
|
||||
{{localize (localize 'l5r5e.techniques.{technique}' technique=technique) }}
|
||||
{{#ifCond ../editable '&&' (lookup ../actor.data.techniques technique)}}
|
||||
<a data-item-type="technique" class="technique-control item-add" data-tech-type="{{technique}}" title="{{ localize 'l5r5e.global.add' }}"><i class="fas fa-plus"></i></a>
|
||||
{{/ifCond}}
|
||||
</legend>
|
||||
<ul class="item-list">
|
||||
{{#each list as |item id|}}
|
||||
{{> 'systems/l5r5e/templates/items/technique/technique-entry.html' technique=item editable=../../editable }}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</fieldset>
|
||||
{{/each}}
|
||||
</fieldset>
|
||||
@@ -1,17 +1,11 @@
|
||||
<div class="l5r5e dice-roll">
|
||||
{{#if isPublicRoll }}
|
||||
{{#if isPublicRoll}}
|
||||
|
||||
{{#if l5r5e.stance}}
|
||||
<div class="l5r5e profil">
|
||||
<header class="part-header flexrow chat-profil">
|
||||
<span class="chat-profil-element">
|
||||
<img class="profile-img"
|
||||
src="{{#if l5r5e.actor.img}}{{l5r5e.actor.img}}{{else}}icons/svg/mystery-man.svg{{/if}}"
|
||||
data-edit="img"
|
||||
height="40"
|
||||
width="40"
|
||||
alt="{{#if l5r5e.actor.name}}{{l5r5e.actor.name}}{{else}}mystery-man{{/if}}"
|
||||
>
|
||||
<img class="profile-img" src="{{#if l5r5e.actor.img}}{{l5r5e.actor.img}}{{else}}icons/svg/mystery-man.svg{{/if}}" data-edit="img" alt="{{#if l5r5e.actor.name}}{{l5r5e.actor.name}}{{else}}mystery-man{{/if}}" />
|
||||
</span>
|
||||
|
||||
<span class="chat-profil-element">
|
||||
@@ -27,57 +21,81 @@
|
||||
</span>
|
||||
|
||||
<span class="chat-profil-element">
|
||||
{{#if l5r5e.summary.difficultyHidden}}
|
||||
{{#if l5r5e.difficultyHidden}}
|
||||
{{localize 'l5r5e.chatdices.difficulty_hidden'}}
|
||||
{{else}}
|
||||
{{localize 'l5r5e.chatdices.difficulty'}} {{l5r5e.summary.difficulty}}
|
||||
{{localize 'l5r5e.chatdices.difficulty'}} {{l5r5e.difficulty}}
|
||||
{{/if}}
|
||||
{{#if l5r5e.summary.voidPointUsed}}
|
||||
<br><i class="i_void" title="{{localize 'l5r5e.chatdices.void_point_used'}}"></i>
|
||||
<br>
|
||||
{{#if l5r5e.voidPointUsed}}
|
||||
<i class="i_void" title="{{localize 'l5r5e.chatdices.void_point_used'}}"></i>
|
||||
{{/if}}
|
||||
{{#if l5r5e.skillAssistance}}
|
||||
<i class="i_skill" title="{{l5r5e.skillAssistance}}x {{localize 'l5r5e.chatdices.assistance_used'}}"></i>
|
||||
{{/if}}
|
||||
</span>
|
||||
</header>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="l5r5e dice-formula">{{formula}}</div>
|
||||
<div class="l5r5e dice-formula">{{#if l5r5e.initialFormula}}{{l5r5e.initialFormula}}{{else}}{{formula}}{{/if}}</div>
|
||||
|
||||
<div class="l5r5e dice-result">
|
||||
{{#if l5r5e.dicesTypes.l5r}}
|
||||
<div class="l5r5e item-display dices-l5r">
|
||||
{{!-- Dices list --}}
|
||||
{{#each l5r5e.dices}}
|
||||
{{#if this.diceTypeL5r}}
|
||||
{{#each this.rolls}}
|
||||
<span class="l5r5e chat-dice">{{{this.result}}}</span>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{#if this.diceTypeL5r}}
|
||||
{{#each this.rolls}}
|
||||
<span class="l5r5e fas chat-dice {{this.classes}}">{{{this.result}}}</span>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
|
||||
{{!-- Roll & Keep Button --}}
|
||||
{{#if l5r5e.canRnK}}
|
||||
{{^if l5r5e.dicesTypes.std}}
|
||||
<button class="l5r5e chat-dice-rnk">{{localize "l5r5e.chatdices.roll_n_keep"}}</button>
|
||||
{{/if}}
|
||||
|
||||
{{#l5r5e.summary}}
|
||||
<ul>
|
||||
<li>{{localize "l5r5e.chatdices.successes"}}: {{this.success}}</li>
|
||||
{{!-- summary symbols --}}
|
||||
<div class="l5r5e dice-total dice-total-rnk">
|
||||
{{#if success}}
|
||||
<i class="i_success" title="{{localize 'l5r5e.chatdices.successes'}}"></i>x{{success}}
|
||||
{{/if}}
|
||||
|
||||
{{#if explosive}}
|
||||
<li>{{localize "l5r5e.chatdices.explosives"}}: {{this.explosive}}</li>
|
||||
<i class="i_explosive" title="{{localize 'l5r5e.chatdices.explosives'}}"></i>x{{explosive}}
|
||||
{{/if}}
|
||||
|
||||
{{#if opportunity}}
|
||||
<li>{{localize "l5r5e.chatdices.opportunities"}}: {{this.opportunity}}</li>
|
||||
<i class="i_opportunity" title="{{localize 'l5r5e.chatdices.opportunities'}}"></i>x{{opportunity}}
|
||||
{{/if}}
|
||||
|
||||
{{#if strife}}
|
||||
<li>{{localize "l5r5e.chatdices.strife"}}: {{this.strife}}</li>
|
||||
<i class="i_strife" title="{{localize 'l5r5e.chatdices.strife'}}"></i>x{{strife}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{{!-- Result text --}}
|
||||
{{#if ../l5r5e.difficultyHidden}}
|
||||
<div class="l5r5e dice-result-rnk unknown">
|
||||
{{totalSuccess}} {{localize 'l5r5e.chatdices.successes'}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="l5r5e dice-result-rnk {{#ifCond totalSuccess '>=' ../l5r5e.difficulty}}success{{else}}fail{{/ifCond}}">
|
||||
{{#ifCond totalSuccess '>=' ../l5r5e.difficulty}}
|
||||
{{localize "l5r5e.chatdices.success_text"}} <i title="{{totalBonus}} {{localize 'l5r5e.chatdices.successes'}}">({{totalBonus}} {{localize "l5r5e.chatdices.bonus_text"}})</i>
|
||||
{{else}}
|
||||
{{localize "l5r5e.chatdices.fail_text"}}
|
||||
{{/ifCond}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/l5r5e.summary}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{!-- Regular dices --}}
|
||||
{{#if l5r5e.dicesTypes.std}}
|
||||
<div class="l5r5e dices-std">
|
||||
{{#each results}}
|
||||
@@ -90,7 +108,6 @@
|
||||
{{{tooltip}}}
|
||||
<h4 class="l5r5e dice-total dice-total-std">{{total}}</h4>
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
|
||||
{{/if}}
|
||||
|
||||
@@ -3,28 +3,16 @@
|
||||
{{!-- First line--}}
|
||||
<tr>
|
||||
<td class="profil center">
|
||||
<img class="profile-img"
|
||||
src="{{#if actor.img}}{{actor.img}}{{else}}icons/svg/mystery-man.svg{{/if}}"
|
||||
data-edit="img"
|
||||
height="200"
|
||||
width="200"
|
||||
alt="{{#if actor.name}}{{actor.name}}{{else}}mystery-man{{/if}}"
|
||||
>
|
||||
<img class="profile-img" src="{{#if actor.img}}{{actor.img}}{{else}}icons/svg/mystery-man.svg{{/if}}" data-edit="img" alt="{{#if actor.name}}{{actor.name}}{{else}}mystery-man{{/if}}" />
|
||||
</td>
|
||||
<td class="rings center">
|
||||
<td class="center">
|
||||
<ul class="rings">
|
||||
{{#each ringsList}}
|
||||
<li id="{{this.id}}">
|
||||
<label class="attribute-label {{this.id}} centered-input ring-selection pointer-choice {{#ifCond ../data.ring.id '==' this.id}}ring-selected{{/ifCond}}">
|
||||
<i class="i_{{this.id}}"></i>
|
||||
<strong>{{this.label}}</strong>
|
||||
<input class="centered-input approach_{{this.id}}"
|
||||
type="text"
|
||||
name="approach"
|
||||
data-ringid="{{this.id}}"
|
||||
value="{{this.value}}"
|
||||
readonly="readonly"
|
||||
/>
|
||||
<input class="centered-input approach_{{this.id}}" type="text" name="approach" data-ringid="{{this.id}}" value="{{this.value}}" readonly="readonly" />
|
||||
</label>
|
||||
</li>
|
||||
{{/each}}
|
||||
@@ -32,33 +20,19 @@
|
||||
</td>
|
||||
<td class="skill">
|
||||
{{#if data.skill.name}}
|
||||
<div>
|
||||
<label>{{localizeSkill data.skill.cat 'title'}}</label>
|
||||
</div>
|
||||
|
||||
{{#if actorIsPc}}
|
||||
<div>
|
||||
<label>{{data.skill.name}}</label>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div>
|
||||
<label id="stance_label">{{localizeSkill data.skill.cat data.ring.id}}</label>
|
||||
</div>
|
||||
<div id="skill_default_value" class="dice-container pointer-choice">
|
||||
<img src="systems/l5r5e/assets/dices/default/skill_blank.svg" alt="1">
|
||||
<div class="dice-value">
|
||||
<span class="dice-skill" type="text" name="skill_{{data.skill.name}}">{{data.skill.default_value}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<label id="stance_label">{{localizeSkill data.skill.cat data.ring.id}}</label>
|
||||
<div id="skill_default_value" class="dice-container pointer-choice">
|
||||
<img src="systems/l5r5e/assets/dices/default/skill_blank.svg" alt="1">
|
||||
<div class="dice-value">
|
||||
<span class="dice-skill" type="text" name="skill_{{data.skill.name}}">{{data.skill.defaultValue}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<img class="profile-img"
|
||||
src="systems/l5r5e/assets/imgs/noskill.webp"
|
||||
data-edit="img"
|
||||
height="200"
|
||||
width="200"
|
||||
alt="no skill selected"
|
||||
>
|
||||
<img class="profile-img" src="systems/l5r5e/assets/imgs/noskill.webp" data-edit="img" alt="no skill selected" />
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -81,7 +55,7 @@
|
||||
<td>
|
||||
{{#if data.difficulty.hidden}}
|
||||
<label>
|
||||
<input type="checkbox" id="diff_add_void_point" name="difficulty.add_void_point" value="1" {{checked data.difficulty.add_void_point}}>
|
||||
<input type="checkbox" id="diff_add_void_point" name="difficulty.addVoidPoint" value="1" {{checked data.difficulty.addVoidPoint}} />
|
||||
+1 <i class="i_void" title="{{localize 'l5r5e.dicepicker.void_point_tooltip'}}"></i>
|
||||
</label>
|
||||
{{else}}
|
||||
@@ -92,9 +66,9 @@
|
||||
|
||||
<div class="third">
|
||||
<div class="dice-container">
|
||||
<img src="systems/l5r5e/assets/dices/default/3d/blank.png" alt="1">
|
||||
<img src="systems/l5r5e/assets/dices/default/3d/blank.png" alt="1" />
|
||||
<div class="dice-value">
|
||||
<input class="input-dice" type="text" name="difficulty.value" value="{{data.difficulty.value}}" readonly="readonly">
|
||||
<input class="input-dice" type="text" name="difficulty.value" value="{{data.difficulty.value}}" readonly="readonly" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -113,9 +87,9 @@
|
||||
|
||||
<div class="third">
|
||||
<div class="dice-container">
|
||||
<img src="systems/l5r5e/assets/dices/default/ring_blank.svg" alt="1">
|
||||
<img src="systems/l5r5e/assets/dices/default/ring_blank.svg" alt="1" />
|
||||
<div class="dice-value">
|
||||
<input class="input-dice input-dice-ring" type="text" name="ring.value" value="{{data.ring.value}}" readonly="readonly">
|
||||
<input class="input-dice input-dice-ring" type="text" name="ring.value" value="{{data.ring.value}}" readonly="readonly" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -132,9 +106,9 @@
|
||||
|
||||
<div class="third">
|
||||
<div class="dice-container">
|
||||
<img src="systems/l5r5e/assets/dices/default/skill_blank.svg" alt="1">
|
||||
<img src="systems/l5r5e/assets/dices/default/skill_blank.svg" alt="1" />
|
||||
<div class="dice-value">
|
||||
<input class="input-dice input-dice-skill" type="text" name="skill.value" value="{{data.skill.value}}" readonly="readonly">
|
||||
<input class="input-dice input-dice-skill" type="text" name="skill.value" value="{{data.skill.value}}" readonly="readonly" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -150,7 +124,7 @@
|
||||
<td>
|
||||
{{^if difficultyHiddenIsLock}}
|
||||
<label>
|
||||
<input type="checkbox" id="diff_hidden" name="difficulty.hidden" value="1" {{checked data.difficulty.hidden}}>
|
||||
<input type="checkbox" id="diff_hidden" name="difficulty.hidden" value="1" {{checked data.difficulty.hidden}} />
|
||||
{{localize 'l5r5e.dicepicker.difficulty_hidden_label'}}
|
||||
</label>
|
||||
{{/if}}
|
||||
@@ -158,18 +132,35 @@
|
||||
<td>
|
||||
{{#if canUseVoidPoint}}
|
||||
<label>
|
||||
<input type="checkbox" id="use_void_point" name="useVoidPoint" value="1" {{checked data.useVoidPoint}}>
|
||||
<input type="checkbox" id="use_void_point" name="useVoidPoint" value="1" {{checked data.useVoidPoint}} />
|
||||
{{localize 'l5r5e.dicepicker.use_void_point_label'}} <i class="i_void" title="{{localize 'l5r5e.dicepicker.void_point_tooltip'}}"></i>
|
||||
</label>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td>
|
||||
<div class="third">
|
||||
<i class="assistance pointer-choice fa fa-minus-square" data-item="assistance" data-value="-1"></i>
|
||||
</div>
|
||||
|
||||
<div class="third">
|
||||
<i class="i_skill"></i> {{localize 'l5r5e.dicepicker.skill_assistance_label'}}
|
||||
<div class="dice-container">
|
||||
<img src="systems/l5r5e/assets/dices/default/3d/blank.png" alt="1" />
|
||||
<div class="dice-value">
|
||||
<input class="input-dice" type="text" name="skill.assistance" value="{{data.skill.assistance}}" readonly="readonly" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="third">
|
||||
<i class="assistance pointer-choice fa fa-plus-square" data-item="assistance" data-value="1"></i>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<button name="roll" type="submit" {{#if disableSubmit}}disabled{{/if}}>{{localize 'l5r5e.dicepicker.roll_label'}} <i class='fas fa-arrow-circle-right'></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<div class="form-group">
|
||||
<button name="roll" type="submit" {{#if disableSubmit}}disabled{{/if}}>{{localize 'l5r5e.dicepicker.roll_label'}} <i class='fas fa-arrow-circle-right'></i></button>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
@@ -1,6 +1,14 @@
|
||||
<form class="l5r5e gm-tools-dialog" autocomplete="off">
|
||||
<p class="gm-tools-container">
|
||||
<a class="difficulty_hidden"><i class="fa fa-eye{{#if data.difficultyHidden}}-slash{{/if}}"></i></a>
|
||||
<strong class="difficulty">{{data.difficulty}}</strong>
|
||||
</p>
|
||||
</form>
|
||||
<ul class="gm-tools-container">
|
||||
<li class="difficulty_hidden" title="{{localize 'l5r5e.gm_toolbox.difficulty_hidden'}}">
|
||||
<i class="fa fa-eye{{#if data.difficultyHidden}}-slash{{/if}}"></i>
|
||||
<strong class="difficulty" title="{{localize 'l5r5e.gm_toolbox.difficulty'}}">{{data.difficulty}}</strong>
|
||||
</li>
|
||||
<li class="gm_actor_updates sleep" data-type="sleep" title="{{localize 'l5r5e.gm_toolbox.sleep'}}">
|
||||
<i class="fa fa-bed"></i>
|
||||
</li>
|
||||
<li class="gm_actor_updates scene_end" data-type="scene_end" title="{{localize 'l5r5e.gm_toolbox.scene_end'}}">
|
||||
<i class="fas fa-star-half-alt"></i>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
@@ -1,90 +1,130 @@
|
||||
<form class="l5r5e roll-n-keep-dialog" autocomplete="off">
|
||||
|
||||
<form class="{{cssClass}}" autocomplete="off">
|
||||
{{!-- Profil --}}
|
||||
<div class="l5r5e profil">
|
||||
<header class="part-header flexrow chat-profil">
|
||||
<span class="chat-profil-element">
|
||||
<img class="profile-img"
|
||||
src="{{#if l5r5e.actor.img}}{{l5r5e.actor.img}}{{else}}icons/svg/mystery-man.svg{{/if}}"
|
||||
data-edit="img"
|
||||
height="40"
|
||||
width="40"
|
||||
alt="{{#if l5r5e.actor.name}}{{l5r5e.actor.name}}{{else}}mystery-man{{/if}}"
|
||||
>
|
||||
</span>
|
||||
|
||||
<span class="chat-profil-element">
|
||||
<header class="l5r5e profil part-header flexrow chat-profil">
|
||||
<ul>
|
||||
<li class="chat-profil-element">
|
||||
<img class="profile-img" src="{{#if l5r5e.actor.img}}{{l5r5e.actor.img}}{{else}}icons/svg/mystery-man.svg{{/if}}" data-edit="img" alt="{{#if l5r5e.actor.name}}{{l5r5e.actor.name}}{{else}}mystery-man{{/if}}" />
|
||||
</li>
|
||||
<li class="chat-profil-element">
|
||||
<i class="chat-profil-stance {{l5r5e.stance}} i_{{l5r5e.stance}}" title="{{localizeRing l5r5e.stance}}"></i>
|
||||
</span>
|
||||
|
||||
<span class="chat-profil-element-skill">
|
||||
</li>
|
||||
<li class="chat-profil-element-skill">
|
||||
{{#if l5r5e.skillId}}
|
||||
{{localizeSkillId l5r5e.skillId}}
|
||||
{{else}}
|
||||
{{#if l5r5e.skillCatId}}{{localizeSkill l5r5e.skillCatId 'title'}}{{/if}}
|
||||
{{/if}}
|
||||
</span>
|
||||
|
||||
<span class="chat-profil-element">
|
||||
{{#if l5r5e.summary.difficultyHidden}}
|
||||
</li>
|
||||
<li class="chat-profil-element">
|
||||
{{#if l5r5e.difficultyHidden}}
|
||||
{{localize 'l5r5e.chatdices.difficulty_hidden'}}
|
||||
{{else}}
|
||||
{{localize 'l5r5e.chatdices.difficulty'}} {{l5r5e.summary.difficulty}}
|
||||
{{localize 'l5r5e.chatdices.difficulty'}} {{l5r5e.difficulty}}
|
||||
{{/if}}
|
||||
{{#if l5r5e.summary.voidPointUsed}}
|
||||
<br><i class="i_void" title="{{localize 'l5r5e.chatdices.void_point_used'}}"></i>
|
||||
<br />
|
||||
{{#if l5r5e.voidPointUsed}}
|
||||
<i class="i_void" title="{{localize 'l5r5e.chatdices.void_point_used'}}"></i>
|
||||
{{/if}}
|
||||
</span>
|
||||
</header>
|
||||
</div>
|
||||
{{#if l5r5e.skillAssistance}}
|
||||
<i class="i_skill" title="{{l5r5e.skillAssistance}}x {{localize 'l5r5e.chatdices.assistance_used'}}"></i>
|
||||
{{/if}}
|
||||
</li>
|
||||
</ul>
|
||||
</header>
|
||||
<section class="rnk-ct">
|
||||
{{!-- Body --}}
|
||||
{{#if options.editable}}
|
||||
{{!-- Face Rings --}}
|
||||
<fieldset class="dropbox swap">
|
||||
<legend class="section-header">
|
||||
<i class="fa fa-sign-in-alt" aria-hidden="true"></i> {{localize 'l5r5e.roll_n_keep.swap_drop_here'}} <i class="fa fa-arrows-alt-h"></i>
|
||||
</legend>
|
||||
|
||||
{{!-- Discard & ReRoll --}}
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
{{#each data.swapDiceFaces.rings}}
|
||||
<div class="dice dropbox faces-change" data-type="swap" data-face="{{this}}" data-die="RingDie">
|
||||
<img src="{{getDiceFaceUrl 'RingDie' this}}" alt="{{this}}" />
|
||||
</div>
|
||||
{{/each}}
|
||||
</fieldset>
|
||||
{{!-- Center --}}
|
||||
<article class="rnk-center">
|
||||
{{!-- Discard & ReRoll --}}
|
||||
<fieldset class="dropbox discards" data-type="discard">
|
||||
<legend class="section-header"><i class="fa fa-arrow-down" aria-hidden="true"></i> {{ localize 'l5r5e.roll_n_keep.discard_drop_here' }}</legend>
|
||||
<legend class="section-header">
|
||||
<i class="fa fa-sign-in-alt" aria-hidden="true"></i> {{localize 'l5r5e.roll_n_keep.discard_drop_here'}} <i class="fa fa-times"></i>
|
||||
</legend>
|
||||
</fieldset>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<fieldset class="dropbox rerolls" data-type="reroll">
|
||||
<legend class="section-header"><i class="fa fa-arrow-down" aria-hidden="true"></i> {{ localize 'l5r5e.roll_n_keep.reroll_drop_here' }}</legend>
|
||||
<legend class="section-header">
|
||||
<i class="fa fa-sign-in-alt" aria-hidden="true"></i> {{localize 'l5r5e.roll_n_keep.reroll_drop_here'}} <i class="fa fa-redo-alt"></i>
|
||||
</legend>
|
||||
</fieldset>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{{!-- DiceList history --}}
|
||||
<table>
|
||||
{{#each data.dicesList as |item idxStep|}}
|
||||
<tr>
|
||||
{{#each item as |dice idxDie|}}
|
||||
<td>
|
||||
<div class="dice {{this.choice}} {{#ifCond (lookup ../../draggableList idxDie) '==' idxStep }}draggable{{/ifCond}}" data-step="{{idxStep}}" data-die="{{idxDie}}">
|
||||
{{#if this.img}}
|
||||
<img src="{{this.img}}" alt="{{idxStep}}_{{idxDie}}" />
|
||||
{{/if}}
|
||||
</div>
|
||||
</td>
|
||||
{{/each}}
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
|
||||
{{!-- Keep --}}
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
{{!-- DiceList history --}}
|
||||
<table>
|
||||
{{#each data.dicesList as |item idxStep|}}
|
||||
<tr>
|
||||
{{#each item as |dice idxDie|}}
|
||||
<td>
|
||||
{{#if dice.face}}
|
||||
{{#if dice.newFace}}
|
||||
<span class="fas dice-ct {{dice.choice}}">
|
||||
<img class="dice {{dice.choice}}{{#ifCond ../../data.currentStep '==' idxStep}} draggable{{/ifCond}}" data-step="{{idxStep}}" data-die="{{idxDie}}" src="{{getDiceFaceUrl dice.type dice.newFace}}" alt="{{idxStep}}_{{idxDie}}" />
|
||||
</span>
|
||||
{{else}}
|
||||
<span class="fas dice-ct {{dice.choice}}">
|
||||
<img class="dice {{dice.choice}}{{#ifCond ../../data.currentStep '==' idxStep}} draggable{{/ifCond}}" data-step="{{idxStep}}" data-die="{{idxDie}}" src="{{getDiceFaceUrl dice.type dice.face}}" alt="{{idxStep}}_{{idxDie}}" />
|
||||
</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</td>
|
||||
{{/each}}
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
{{!-- Keep --}}
|
||||
<fieldset class="dropbox keeps" data-type="keep">
|
||||
<legend class="section-header"><i class="fa fa-arrow-down" aria-hidden="true"></i> {{ localize 'l5r5e.roll_n_keep.keep_drop_here' }}</legend>
|
||||
<legend class="section-header">
|
||||
<i class="fa fa-sign-in-alt" aria-hidden="true"></i> {{localize 'l5r5e.roll_n_keep.keep_drop_here'}} <i class="fa fa-check"></i>
|
||||
</legend>
|
||||
</fieldset>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<button id="finalize" name="finalize" type="button">{{ localize 'l5r5e.roll_n_keep.bt_validate' }} <i class='fas fa-arrow-circle-right'></i></button>
|
||||
|
||||
</article>
|
||||
{{!-- Face Skills --}}
|
||||
<fieldset class="dropbox swap">
|
||||
<legend class="section-header">
|
||||
<i class="fa fa-sign-in-alt" aria-hidden="true"></i> {{localize 'l5r5e.roll_n_keep.swap_drop_here'}} <i class="fa fa-arrows-alt-h"></i>
|
||||
</legend>
|
||||
{{#each data.swapDiceFaces.skills}}
|
||||
<div class="dice dropbox faces-change" data-type="swap" data-face="{{this}}" data-die="AbilityDie">
|
||||
<img src="{{getDiceFaceUrl 'AbilityDie' this}}" alt="{{this}}" />
|
||||
</div>
|
||||
{{/each}}
|
||||
</fieldset>
|
||||
<button id="finalize" name="finalize" type="button" {{#if data.submitDisabled}}disabled{{/if}}>
|
||||
{{ localize 'l5r5e.roll_n_keep.bt_validate' }} <i class="fas fa-arrow-circle-right"></i>
|
||||
</button>
|
||||
{{else}}
|
||||
<table>
|
||||
{{!-- Non editable DiceList history --}}
|
||||
{{#each data.dicesList as |item idxStep|}}
|
||||
<tr>
|
||||
{{#each item as |dice idxDie|}}
|
||||
<td>
|
||||
{{#if dice.face}}
|
||||
{{#if dice.newFace}}
|
||||
<span class="fas dice-ct {{dice.choice}}">
|
||||
<img class="dice {{dice.choice}}" src="{{getDiceFaceUrl dice.type dice.newFace}}" alt="{{idxStep}}_{{idxDie}}" />
|
||||
</span>
|
||||
{{else}}
|
||||
<span class="fas dice-ct {{dice.choice}}">
|
||||
<img class="dice {{dice.choice}}" src="{{getDiceFaceUrl dice.type dice.face}}" alt="{{idxStep}}_{{idxDie}}" />
|
||||
</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</td>
|
||||
{{/each}}
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
{{/if}}
|
||||
</section>
|
||||
</form>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<li class="item-name">{{ advancement.name }}</li>
|
||||
{{#if editable}}
|
||||
<li data-item-id="{{advancement._id}}" class="item-control item-edit" title="{{localize 'l5r5e.global.edit'}}"><i class="fas fa-edit"></i></li>
|
||||
<li data-item-id="{{advancement._id}}" class="item-control item-delete" title="{{localize 'l5r5e.global.delete'}}"><i class="fas fa-trash"></i></li>
|
||||
<li data-item-id="{{advancement._id}}" class="item-control item-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
{{#if advancement.data.description}}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</li>
|
||||
{{#if editable}}
|
||||
<li data-item-id="{{item._id}}" class="item-edit" title="{{localize 'l5r5e.global.edit'}}"><i class="fas fa-edit"></i></li>
|
||||
<li data-item-id="{{item._id}}" class="item-delete" title="{{localize 'l5r5e.global.delete'}}"><i class="fas fa-trash"></i></li>
|
||||
<li data-item-id="{{item._id}}" class="item-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
<ul class="item-properties">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<fieldset class="armors-content">
|
||||
<legend class="section-header">
|
||||
{{ localize 'l5r5e.armors.title' }}
|
||||
{{localize 'l5r5e.armors.title'}}
|
||||
{{#if editable}}
|
||||
<a data-item-type="armor" class="armor-control item-add" title="{{ localize 'l5r5e.global.add'}}"><i class="fas fa-plus"></i></a>
|
||||
<a data-item-type="armor" data-item-eqquiped="true" class="armor-control item-add" title="{{localize 'l5r5e.global.add'}}"><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</legend>
|
||||
<ul class="item-list">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{{#if editable}}
|
||||
<li data-item-id="{{item._id}}" data-type="equipped" class="item-equip equip-readied-control" title="{{localize 'l5r5e.armors.equipped'}}"><i class="fas {{#if item.data.equipped}}fa-tshirt{{else}}fa-weight-hanging{{/if}}"></i></li>
|
||||
<li data-item-id="{{item._id}}" class="item-edit" title="{{localize 'l5r5e.global.edit'}}"><i class="fas fa-edit"></i></li>
|
||||
<li data-item-id="{{item._id}}" class="item-delete" title="{{localize 'l5r5e.global.delete'}}"><i class="fas fa-trash"></i></li>
|
||||
<li data-item-id="{{item._id}}" class="item-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
<ul class="item-properties">
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<fieldset class="items-content">
|
||||
<legend>
|
||||
{{ localize 'l5r5e.equipment' }}
|
||||
{{#if editable}}
|
||||
<a data-item-type="item" class="item-control item-add" title="{{ localize 'l5r5e.global.add'}}"><i class="fas fa-plus"></i></a>
|
||||
{{#each data.splitItemsList as |cat type|}}
|
||||
<h3>
|
||||
{{localize (localize 'l5r5e.{type}s.title' type=type) }}
|
||||
{{#if ../editable}}
|
||||
<a data-item-type="{{type}}" class="item-control item-add" title="{{ localize 'l5r5e.global.add'}}"><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</legend>
|
||||
</h3>
|
||||
<ul class="item-list">
|
||||
{{#each actor.items as |item id|}}
|
||||
{{#ifCond '["item", "armor", "weapon"]' 'includes' item.type}}
|
||||
{{> 'systems/l5r5e/templates/items/item/item-entry.html' item=item id=id editable=../editable }}
|
||||
{{/ifCond}}
|
||||
{{#each cat as |item id|}}
|
||||
{{> 'systems/l5r5e/templates/items/item/item-entry.html' item=item id=id editable=../../editable }}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</fieldset>
|
||||
{{/each}}
|
||||
@@ -4,7 +4,7 @@
|
||||
<li class="item-name">{{ peculiarity.name }}</li>
|
||||
{{#if editable}}
|
||||
<li data-item-id="{{peculiarity._id}}" class="item-control item-edit" title="{{localize 'l5r5e.global.edit'}}"><i class="fas fa-edit"></i></li>
|
||||
<li data-item-id="{{peculiarity._id}}" class="item-control item-delete" title="{{localize 'l5r5e.global.delete'}}"><i class="fas fa-trash"></i></li>
|
||||
<li data-item-id="{{peculiarity._id}}" class="item-control item-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
{{#if peculiarity.data.types}}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<li class="item-img"><img src="{{item.img}}" title="{{item.name}}" width="32px" height="32px"/></li>
|
||||
<li class="item-name">{{ item.name }}</li>
|
||||
{{#if editable}}
|
||||
<li class="property-delete" title="{{localize 'l5r5e.global.delete'}}"><i class="fas fa-trash"></i></li>
|
||||
<li class="property-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
{{#if item.data.data.description}}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<li class="item-name">{{ technique.name }}</li>
|
||||
{{#if editable}}
|
||||
<li data-item-id="{{technique._id}}" class="item-control item-edit" title="{{localize 'l5r5e.global.edit'}}"><i class="fas fa-edit"></i></li>
|
||||
<li data-item-id="{{technique._id}}" class="item-control item-delete" title="{{localize 'l5r5e.global.delete'}}"><i class="fas fa-trash"></i></li>
|
||||
<li data-item-id="{{technique._id}}" class="item-control item-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
{{#if technique.data.description}}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</li>
|
||||
{{#if editable}}
|
||||
<li data-item-id="{{item._id}}" class="item-edit" title="{{localize 'l5r5e.global.edit'}}"><i class="fas fa-edit"></i></li>
|
||||
<li data-item-id="{{item._id}}" class="item-delete" title="{{localize 'l5r5e.global.delete'}}"><i class="fas fa-trash"></i></li>
|
||||
<li data-item-id="{{item._id}}" class="item-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
<ul class="item-properties">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<fieldset class="weapons-content">
|
||||
<legend class="section-header">
|
||||
{{ localize 'l5r5e.weapons.title' }}
|
||||
{{localize 'l5r5e.weapons.title'}}
|
||||
{{#if editable}}
|
||||
<a data-item-type="weapon" class="weapon-control item-add" title="{{ localize 'l5r5e.global.add'}}"><i class="fas fa-plus"></i></a>
|
||||
<a data-item-type="weapon" data-item-eqquiped="true" class="weapon-control item-add" title="{{localize 'l5r5e.global.add'}}"><i class="fas fa-plus"></i></a>
|
||||
{{/if}}
|
||||
</legend>
|
||||
<ul class="item-list">
|
||||
|
||||
Reference in New Issue
Block a user