Compare commits
27 Commits
v1.10.0
...
dev_skills
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87fd300a22 | ||
|
|
fe2aa5dd25 | ||
|
|
6f7b00328e | ||
|
|
9a46cfb842 | ||
|
|
0658a6cbc4 | ||
|
|
c2cf927557 | ||
|
|
8817f390e4 | ||
|
|
b993914dcb | ||
|
|
9fa30444aa | ||
|
|
d607abe45d | ||
|
|
6e534d5bf3 | ||
|
|
848a54fa1e | ||
|
|
7740aed299 | ||
|
|
c1adae132b | ||
|
|
67b7601fa1 | ||
|
|
87096ab286 | ||
|
|
273531f522 | ||
|
|
c1bf9644f8 | ||
|
|
1b68d33bd2 | ||
|
|
a24e775001 | ||
|
|
823b883d4e | ||
|
|
12c8a70f60 | ||
|
|
1d42d2970d | ||
|
|
0b3816587b | ||
|
|
710afd9804 | ||
|
|
1ec9e65ca5 | ||
|
|
5fbb34d882 |
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,6 +1,22 @@
|
||||
# Changelog
|
||||
Date format : day/month/year
|
||||
|
||||
## 2.0.0 - xx/xx/2024 - Skill list
|
||||
- Skills are now items, this can break things update with caution. Save before upgrading !
|
||||
- Added a new dialog settings to configure default skills list.
|
||||
|
||||
## 1.11.0 - 13/12/2023 - Little fixes
|
||||
- 20Q :
|
||||
- Starting techniques now have a limit of 6 techniques instead of 5 (see Celestial Realms : `Moshi Sun Sentinel School`).
|
||||
- Enable dropping on the 'drop here' label for 20Q (thk to Litasa !34).
|
||||
- Compendiums : Added masteries and abilities from Deathly Turns.
|
||||
|
||||
## 1.10.1 - 22/08/2023 - Litasa's fixes
|
||||
All these changes are thanks to Litasa.
|
||||
- Roll-n-Keep dialog now waits for the DiceSoNice animation to finish before displaying the result when re-rolling or exploding dice (!28).
|
||||
- Adding the ability to have a different name for the custom-compendium (needed to disable the system embedded ones).
|
||||
- Fixes some CSS issues when the font size is not the default (#50, #51 and #52).
|
||||
|
||||
## 1.10.0 - 11/06/2023 - FoundryVTT v11 Compatibility
|
||||
__! Be certain to carefully back up any critical user data before installing this update !__
|
||||
- Updated the System to FoundryVTT v11.
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
# Copyright (c) CC BY-NC-SA 4.0 2020 - 2021 This System is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
|
||||
# Copyright (c) CC BY-NC-SA 4.0 2020 - 2023 This System is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
|
||||
|
||||
By exercising the Licensed Rights (link below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
|
||||
|
||||
https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
|
||||
|
||||
# Copyright (c) 2018 - 2021 Fantasy Flight Games. Legend of the Five Rings est TM de Fantasy Flight Games.
|
||||
# Copyright (c) 2018 - 2023 Fantasy Flight Games. Legend of the Five Rings est TM de Fantasy Flight Games.
|
||||
|
||||
All images, texts and contents are the property of their creator / legal owner.
|
||||
|
||||
|
||||
# Copyright (c) 2020 - 2021 Foundry Network
|
||||
# Copyright (c) 2020 - 2023 Foundry Network
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
26
system/assets/icons/items/skill.svg
Normal file
26
system/assets/icons/items/skill.svg
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.1.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="239.5px" height="239.5px" viewBox="0 0 239.5 239.5" style="enable-background:new 0 0 239.5 239.5;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFCC;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M173.2,103.1c0.8-4.9,1.4-9.8,1.4-14.9c0-48.2-39.1-87.3-87.3-87.3C39.1,0.9,0,40,0,88.2s39.1,87.3,87.3,87.3
|
||||
c5.7,0,11.3-0.6,16.7-1.6c0-0.1,0-0.2,0-0.3c0-7.6,1.2-14.9,3.5-21.7c-6.4,2-13.1,3.1-20.1,3.1c-36.8,0-66.7-29.9-66.7-66.7
|
||||
s29.9-66.7,66.7-66.7s66.7,29.9,66.7,66.7c0,6.5-1,12.9-2.8,18.8C158.2,104.6,165.5,103.2,173.2,103.1z"/>
|
||||
<path class="st0" d="M87.3,26.8c-33.8,0-61.4,27.5-61.4,61.4c0,33.8,27.5,61.4,61.4,61.4c8,0,15.7-1.6,22.7-4.4
|
||||
c6.9-15.6,19.3-28.2,34.7-35.4c2.5-6.7,4-13.9,4-21.5C148.6,54.3,121.1,26.8,87.3,26.8z M110.6,101.7c0,5.4-4.4,9.8-9.8,9.8H73.7
|
||||
c-5.4,0-9.8-4.4-9.8-9.8v-27c0-5.4,4.4-9.8,9.8-9.8h27.1c5.4,0,9.8,4.4,9.8,9.8V101.7z"/>
|
||||
<path class="st0" d="M174.4,108.4c-0.8,0-1.6,0.1-2.4,0.1c-8.2,0.3-16,2-23.1,5.1c-1.3,0.5-2.5,1.2-3.8,1.8
|
||||
c-1.4,0.7-2.8,1.5-4.2,2.3c-9.5,5.7-17.5,13.8-23.1,23.5c-0.8,1.4-1.5,2.8-2.2,4.3c-0.6,1.2-1.2,2.5-1.7,3.8
|
||||
c-2.9,7.2-4.6,15-4.7,23.2c0,0.3,0,0.7,0,1c0,35.9,29.2,65.1,65.1,65.1s65.1-29.2,65.1-65.1C239.5,137.6,210.3,108.4,174.4,108.4z
|
||||
M174.4,226c-28.9,0-52.4-23.5-52.4-52.4c0-1.8,0.1-3.6,0.3-5.4c2.5-24.2,21.6-43.6,45.7-46.6c2.1-0.3,4.3-0.4,6.5-0.4
|
||||
c28.9,0,52.4,23.5,52.4,52.4C226.9,202.4,203.3,226,174.4,226z"/>
|
||||
<path class="st0" d="M174.4,126.5c-3.2,0-6.2,0.3-9.2,0.9c-18.9,3.8-33.7,18.9-37.1,37.9c-0.5,2.7-0.8,5.4-0.8,8.2
|
||||
c0,26,21.1,47.1,47.1,47.1s47.1-21.1,47.1-47.1S200.4,126.5,174.4,126.5z M192.6,184c0,4.2-3.4,7.6-7.6,7.6h-21
|
||||
c-4.2,0-7.6-3.4-7.6-7.6v-21c0-4.2,3.4-7.6,7.6-7.6h21c4.2,0,7.6,3.4,7.6,7.6V184z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
153
system/babele/fr/l5r5e.core-skills.json
Normal file
153
system/babele/fr/l5r5e.core-skills.json
Normal file
@@ -0,0 +1,153 @@
|
||||
{
|
||||
"label": "Compétences",
|
||||
"mapping": {
|
||||
"description": "system.description",
|
||||
"book_reference": "system.book_reference"
|
||||
},
|
||||
"entries": [
|
||||
{
|
||||
"id": "Composition",
|
||||
"name": "Composition",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.146"
|
||||
},
|
||||
{
|
||||
"id": "Aesthetics",
|
||||
"name": "Esthétique",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.146"
|
||||
},
|
||||
{
|
||||
"id": "Smithing",
|
||||
"name": "Forge",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.149"
|
||||
},
|
||||
{
|
||||
"id": "Design",
|
||||
"name": "Stylisme",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.147"
|
||||
},
|
||||
{
|
||||
"id": "Martial Arts [Melee]",
|
||||
"name": "Arts martiaux (corps à corps)",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.162"
|
||||
},
|
||||
{
|
||||
"id": "Martial Arts [Ranged]",
|
||||
"name": "Arts martiaux (distance)",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.163"
|
||||
},
|
||||
{
|
||||
"id": "Martial Arts [Unarmed]",
|
||||
"name": "Arts martiaux (mains nues)",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.164"
|
||||
},
|
||||
{
|
||||
"id": "Fitness",
|
||||
"name": "Forme",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.162"
|
||||
},
|
||||
{
|
||||
"id": "Meditation",
|
||||
"name": "Méditation",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.164"
|
||||
},
|
||||
{
|
||||
"id": "Tactics",
|
||||
"name": "Tactique",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.165"
|
||||
},
|
||||
{
|
||||
"id": "Commerce",
|
||||
"name": "Commerce",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.167"
|
||||
},
|
||||
{
|
||||
"id": "Skulduggery",
|
||||
"name": "Magouilles",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.168"
|
||||
},
|
||||
{
|
||||
"id": "Seafaring",
|
||||
"name": "Navigation",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.168"
|
||||
},
|
||||
{
|
||||
"id": "Survival",
|
||||
"name": "Survie",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.169"
|
||||
},
|
||||
{
|
||||
"id": "Labor",
|
||||
"name": "Travail manuel",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.167"
|
||||
},
|
||||
{
|
||||
"id": "Culture",
|
||||
"name": "Culture",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.156"
|
||||
},
|
||||
{
|
||||
"id": "Government",
|
||||
"name": "Gouvernement",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.156"
|
||||
},
|
||||
{
|
||||
"id": "Medicine",
|
||||
"name": "Médecine",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.157"
|
||||
},
|
||||
{
|
||||
"id": "Sentiment",
|
||||
"name": "Sentiments",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.158"
|
||||
},
|
||||
{
|
||||
"id": "Theology",
|
||||
"name": "Théologie",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.158"
|
||||
},
|
||||
{
|
||||
"id": "Command",
|
||||
"name": "Commandement",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.151"
|
||||
},
|
||||
{
|
||||
"id": "Courtesy",
|
||||
"name": "Courtoisie",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.152"
|
||||
},
|
||||
{
|
||||
"id": "Games",
|
||||
"name": "Jeux",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.153"
|
||||
},
|
||||
{
|
||||
"id": "Performance",
|
||||
"name": "Représentations",
|
||||
"description": "",
|
||||
"book_reference": "Livre de Règles p.154"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -592,6 +592,18 @@
|
||||
"name": "Born to Survive (WIP)",
|
||||
"description": "",
|
||||
"book_reference": "Décret de la nature"
|
||||
},
|
||||
{
|
||||
"id": "Hunter of the Supernatural",
|
||||
"name": "Hunter of the Supernatural (WIP)",
|
||||
"description": "",
|
||||
"book_reference": "Celestial Realms - Deathly Turns"
|
||||
},
|
||||
{
|
||||
"id": "An Arrow Loosed",
|
||||
"name": "An Arrow Loosed (WIP)",
|
||||
"description": "",
|
||||
"book_reference": "Celestial Realms - Deathly Turns"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -592,6 +592,18 @@
|
||||
"name": "Evolution of the Wilds (WIP)",
|
||||
"description": "",
|
||||
"book_reference": "Décret de la nature"
|
||||
},
|
||||
{
|
||||
"id": "Mazoku's Authority",
|
||||
"name": "Mazoku's Authority (WIP)",
|
||||
"description": "",
|
||||
"book_reference": "Celestial Realms - Deathly Turns"
|
||||
},
|
||||
{
|
||||
"id": "Effortless Aim",
|
||||
"name": "Effortless Aim (WIP)",
|
||||
"description": "",
|
||||
"book_reference": "Celestial Realms - Deathly Turns"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -17,6 +17,16 @@
|
||||
"CustomTechniques": {
|
||||
"Title": "Use custom techniques",
|
||||
"Hint": "Add 'Specificity' technique type to serve as a catch-all."
|
||||
},
|
||||
"CustomCompendiumName": {
|
||||
"Title": "Custom Compendium Name",
|
||||
"Hint": "For advanced users that want to change the name of the custom compendiums (Used to disables the embedded ones).",
|
||||
"Notification": "Unable set Custom Compendium: '{name}'. Is it activated and registered with Babele?"
|
||||
},
|
||||
"DefaultSkillsList": {
|
||||
"Title": "Skills",
|
||||
"Label": "Set Default Skills",
|
||||
"Hint": "Set default skills list for new characters."
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
@@ -26,6 +36,7 @@
|
||||
"army": "Army"
|
||||
},
|
||||
"Item": {
|
||||
"skill": "Skill",
|
||||
"item": "Item",
|
||||
"armor": "Armor",
|
||||
"weapon": "Weapon",
|
||||
@@ -280,6 +291,7 @@
|
||||
"skills": {
|
||||
"title": "Skills",
|
||||
"label": "Skill",
|
||||
"category": "Category",
|
||||
"artisan": {
|
||||
"title": "Artisan",
|
||||
"aesthetics": "Aesthetics",
|
||||
@@ -475,7 +487,7 @@
|
||||
"honor": "Honor",
|
||||
"access": "Technique types available",
|
||||
"school_ability": "School ability",
|
||||
"starting_techniques": "Starting techniques (2-5)",
|
||||
"starting_techniques": "Starting techniques (2-6)",
|
||||
"outfit": "Starting outfit",
|
||||
"q4": "4. How does your character stand out within their school? (p. 88)",
|
||||
"q4_pow": "4. What gets your character in and out of trouble? (p. 60)"
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
"CustomTechniques": {
|
||||
"Title": "Use custom techniques",
|
||||
"Hint": "Add 'Specificity' technique type to serve as a catch-all."
|
||||
},
|
||||
"CustomCompendiumName": {
|
||||
"Title": "Custom Compendium Name",
|
||||
"Hint": "For advanced users that want to change the name of the custom compendiums (Used to disables the embedded ones).",
|
||||
"Notification": "Unable set Custom Compendium: '{name}'. Is it activated and registered with Babele?"
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
@@ -280,6 +285,7 @@
|
||||
"skills": {
|
||||
"title": "Habilidades",
|
||||
"label": "Habilidad",
|
||||
"category": "Categoría",
|
||||
"artisan": {
|
||||
"title": "Artesanales",
|
||||
"aesthetics": "Estética",
|
||||
@@ -475,7 +481,7 @@
|
||||
"honor": "Honor",
|
||||
"access": "Tipos de técnicas disponibles",
|
||||
"school_ability": "Capacidad de escuela",
|
||||
"starting_techniques": "Técnicas iniciales (2-5)",
|
||||
"starting_techniques": "Técnicas iniciales (2-6)",
|
||||
"outfit": "Equipo inicial",
|
||||
"q4": "4. ¿De qué manera destaca tu personaje dentro de su escuela? (p. 88)",
|
||||
"q4_pow": "4. What gets your character in and out of trouble? (p. 60)"
|
||||
|
||||
@@ -17,6 +17,16 @@
|
||||
"CustomTechniques": {
|
||||
"Title": "Utiliser les techniques personnalisées",
|
||||
"Hint": "Ajoute un type de technique 'Particularités' pour servir de fourre-tout."
|
||||
},
|
||||
"CustomCompendiumName": {
|
||||
"Title": "Nom du CustomCompendium",
|
||||
"Hint": "Pour les utilisateurs avancés qui souhaitent modifier le nom du compendium personnalisé (utilisé pour désactiver ceux intégrés).",
|
||||
"Notification": "Impossible de définir le compendium personnalisé : '{name}'. Est-il activé et enregistré auprès de Babele ?"
|
||||
},
|
||||
"DefaultSkillsList": {
|
||||
"Title": "Compétences",
|
||||
"Label": "Définir les compétences par défaut",
|
||||
"Hint": "Définie la liste des compétences par défaut pour les nouveaux personnages."
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
@@ -26,6 +36,7 @@
|
||||
"army": "Armée"
|
||||
},
|
||||
"Item": {
|
||||
"skill": "Compétence",
|
||||
"item": "Objet",
|
||||
"armor": "Armure",
|
||||
"weapon": "Arme",
|
||||
@@ -280,6 +291,7 @@
|
||||
"skills": {
|
||||
"title": "Compétences",
|
||||
"label": "Compétence",
|
||||
"category": "Catégorie",
|
||||
"artisan": {
|
||||
"title": "Artisanales",
|
||||
"aesthetics": "Esthétique",
|
||||
@@ -475,7 +487,7 @@
|
||||
"honor": "Honneur",
|
||||
"access": "Types de techniques accessibles",
|
||||
"school_ability": "Capacité d'école",
|
||||
"starting_techniques": "Techniques de départ (2-5)",
|
||||
"starting_techniques": "Techniques de départ (2-6)",
|
||||
"outfit": "Équipement de départ",
|
||||
"q4": "4. De quelle manière votre personnage se démarque-t-il au sein de son école ? (p. 88)",
|
||||
"q4_pow": "4. Qu'est-ce qui attire des ennuis à votre personnage dans ou l'en sort ? (p. 60)"
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
"CustomTechniques": {
|
||||
"Title": "Usa tecniche custom",
|
||||
"Hint": "Aggiunge il tipo 'Speciale' come termine generale."
|
||||
},
|
||||
"CustomCompendiumName": {
|
||||
"Title": "Custom Compendium Name",
|
||||
"Hint": "For advanced users that want to change the name of the custom compendiums (Used to disables the embedded ones).",
|
||||
"Notification": "Unable set Custom Compendium: '{name}'. Is it activated and registered with Babele?"
|
||||
}
|
||||
},
|
||||
"TYPES": {
|
||||
@@ -280,6 +285,7 @@
|
||||
"skills": {
|
||||
"title": "Abilità",
|
||||
"label": "Abilità",
|
||||
"category": "Categoria",
|
||||
"artisan": {
|
||||
"title": "Artigiane",
|
||||
"aesthetics": "Estetica",
|
||||
@@ -475,7 +481,7 @@
|
||||
"honor": "Onore",
|
||||
"access": "Tecniche Disponibili",
|
||||
"school_ability": "Abilità di Scuola",
|
||||
"starting_techniques": "Tecniche di Partenza (2-5)",
|
||||
"starting_techniques": "Tecniche di Partenza (2-6)",
|
||||
"outfit": "Dotazione di Partenza",
|
||||
"q4": "4. Come si distingue il personaggio all’interno della sua scuola? (p. 88)",
|
||||
"q4_pow": "4. Che cosa mette nei guai il personaggio, e che cosa lo tira fuori dai guai? (p. 60)"
|
||||
|
||||
24
system/packs/core-skills.db
Normal file
24
system/packs/core-skills.db
Normal file
@@ -0,0 +1,24 @@
|
||||
{"_id":"L5RCoreSkl000001","name":"Composition","permission":{"default":0},"type":"skill","data":{"category":"artisan","description":"","book_reference":"Core Rulebook p.146","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"composition"}},"img":"icons/sundries/scrolls/scroll-symbol-circle-white.webp","effects":[]}
|
||||
{"_id":"L5RCoreSkl000002","name":"Aesthetics","permission":{"default":0},"type":"skill","data":{"category":"artisan","description":"","book_reference":"Core Rulebook p.146","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"aesthetics"}},"img":"systems/l5r5e/assets/icons/techs/kiho.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000003","name":"Smithing","permission":{"default":0},"type":"skill","data":{"category":"artisan","description":"","book_reference":"Core Rulebook p.149","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"smithing"}},"img":"systems/l5r5e/assets/icons/items/item_pattern.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000004","name":"Design","permission":{"default":0},"type":"skill","data":{"category":"artisan","description":"","book_reference":"Core Rulebook p.147","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"design"}},"img":"systems/l5r5e/assets/icons/items/keikogi.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000005","name":"Martial Arts [Melee]","permission":{"default":0},"type":"skill","data":{"category":"martial","description":"","book_reference":"Core Rulebook p.162","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"melee"}},"img":"systems/l5r5e/assets/icons/weapons/katana.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000006","name":"Martial Arts [Ranged]","permission":{"default":0},"type":"skill","data":{"category":"martial","description":"","book_reference":"Core Rulebook p.163","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"ranged"}},"img":"systems/l5r5e/assets/icons/weapons/crossbow.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000007","name":"Martial Arts [Unarmed]","permission":{"default":0},"type":"skill","data":{"category":"martial","description":"","book_reference":"Core Rulebook p.164","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"unarmed"}},"img":"systems/l5r5e/assets/icons/weapons/unarmed.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000008","name":"Fitness","permission":{"default":0},"type":"skill","data":{"category":"martial","description":"","book_reference":"Core Rulebook p.162","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"fitness"}},"img":"icons/skills/melee/maneuver-daggers-paired-orange.webp","effects":[]}
|
||||
{"_id":"L5RCoreSkl000009","name":"Meditation","permission":{"default":0},"type":"skill","data":{"category":"martial","description":"","book_reference":"Core Rulebook p.164","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"meditation"}},"img":"systems/l5r5e/assets/icons/techs/ritual.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000010","name":"Tactics","permission":{"default":0},"type":"skill","data":{"category":"martial","description":"","book_reference":"Core Rulebook p.165","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"tactics"}},"img":"systems/l5r5e/assets/icons/items/armor.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000011","name":"Commerce","permission":{"default":0},"type":"skill","data":{"category":"trade","description":"","book_reference":"Core Rulebook p.167","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"commerce"}},"img":"icons/skills/trades/baking-bread-rolls-green.webp","effects":[]}
|
||||
{"_id":"L5RCoreSkl000012","name":"Skulduggery","permission":{"default":0},"type":"skill","data":{"category":"trade","description":"","book_reference":"Core Rulebook p.168","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"skulduggery"}},"img":"icons/skills/social/intimidation-impressing.webp","effects":[]}
|
||||
{"_id":"L5RCoreSkl000013","name":"Seafaring","permission":{"default":0},"type":"skill","data":{"category":"trade","description":"","book_reference":"Core Rulebook p.168","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"seafaring"}},"img":"icons/skills/trades/profession-sailing-ship.webp","effects":[]}
|
||||
{"_id":"L5RCoreSkl000014","name":"Survival","permission":{"default":0},"type":"skill","data":{"category":"trade","description":"","book_reference":"Core Rulebook p.169","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"survival"}},"img":"icons/environment/wilderness/camp-improvised.webp","effects":[]}
|
||||
{"_id":"L5RCoreSkl000015","name":"Labor","permission":{"default":0},"type":"skill","data":{"category":"trade","description":"","book_reference":"Core Rulebook p.167","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"labor"}},"img":"icons/tools/hand/hammer-and-nail.webp","effects":[]}
|
||||
{"_id":"L5RCoreSkl000016","name":"Culture","permission":{"default":0},"type":"skill","data":{"category":"scholar","description":"","book_reference":"Core Rulebook p.156","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"culture"}},"img":"icons/sundries/documents/document-sealed-signatures-red.webp","effects":[]}
|
||||
{"_id":"L5RCoreSkl000017","name":"Government","permission":{"default":0},"type":"skill","data":{"category":"scholar","description":"","book_reference":"Core Rulebook p.156","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"government"}},"img":"systems/l5r5e/assets/icons/items/army_fortification.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000018","name":"Medicine","permission":{"default":0},"type":"skill","data":{"category":"scholar","description":"","book_reference":"Core Rulebook p.157","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"medicine"}},"img":"icons/tools/laboratory/bowl-liquid-pink-yellow-green.webp","effects":[]}
|
||||
{"_id":"L5RCoreSkl000019","name":"Sentiment","permission":{"default":0},"type":"skill","data":{"category":"scholar","description":"","book_reference":"Core Rulebook p.158","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"sentiment"}},"img":"systems/l5r5e/assets/icons/actors/traditional-japanese-woman.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000020","name":"Theology","permission":{"default":0},"type":"skill","data":{"category":"scholar","description":"","book_reference":"Core Rulebook p.158","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"theology"}},"img":"systems/l5r5e/assets/icons/items/blessed.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000021","name":"Command","permission":{"default":0},"type":"skill","data":{"category":"social","description":"","book_reference":"Core Rulebook p.151","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"command"}},"img":"systems/l5r5e/assets/icons/items/army_cohort.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000022","name":"Courtesy","permission":{"default":0},"type":"skill","data":{"category":"social","description":"","book_reference":"Core Rulebook p.152","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"courtesy"}},"img":"systems/l5r5e/assets/icons/social.svg","effects":[]}
|
||||
{"_id":"L5RCoreSkl000023","name":"Games","permission":{"default":0},"type":"skill","data":{"category":"social","description":"","book_reference":"Core Rulebook p.153","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"games"}},"img":"icons/sundries/gaming/dice-runed-tan.webp","effects":[]}
|
||||
{"_id":"L5RCoreSkl000024","name":"Performance","permission":{"default":0},"type":"skill","data":{"category":"social","description":"","book_reference":"Core Rulebook p.154","rank":0,"modifier":0},"sort":100001,"flags":{"l5r5e":{"skillCoreId":"performance"}},"img":"icons/environment/people/group.webp","effects":[]}
|
||||
@@ -96,3 +96,5 @@
|
||||
{"_id":"L5RCoreMas000096","name":"Reflexive Strike","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"6","bought_at_rank":0,"ring":"void","skill":"","difficulty":"","technique_type":"mastery_ability","xp_cost":"0","description":"","book_reference":"Writ of the Wild p.99"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/mastery_ability.svg","effects":[]}
|
||||
{"_id":"L5RCoreMas000097","name":"A Master of Study","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"6","bought_at_rank":0,"ring":"void","skill":"","difficulty":"","technique_type":"mastery_ability","xp_cost":"0","description":"","book_reference":"Writ of the Wild p.100"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/mastery_ability.svg","effects":[]}
|
||||
{"_id":"L5RCoreMas000098","name":"Born to Survive","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"6","bought_at_rank":0,"ring":"void","skill":"","difficulty":"","technique_type":"mastery_ability","xp_cost":"0","description":"","book_reference":"Writ of the Wild p.101"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/mastery_ability.svg","effects":[]}
|
||||
{"_id":"L5RCoreMas000099","name":"Hunter of the Supernatural","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"6","bought_at_rank":0,"ring":"void","skill":"","difficulty":"","technique_type":"mastery_ability","xp_cost":"0","description":"","book_reference":"Celestial Realms - Deathly Turns p.24"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/mastery_ability.svg","effects":[]}
|
||||
{"_id":"L5RCoreMas000100","name":"An Arrow Loosed","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"6","bought_at_rank":0,"ring":"void","skill":"","difficulty":"","technique_type":"mastery_ability","xp_cost":"0","description":"","book_reference":"Celestial Realms - Deathly Turns p.25"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/mastery_ability.svg","effects":[]}
|
||||
|
||||
@@ -96,3 +96,5 @@
|
||||
{"_id":"L5RCoreSch000096","name":"Keen Senses","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"void","skill":"","difficulty":"","technique_type":"school_ability","xp_cost":"0","description":"","book_reference":"Writ of the Wild p.99"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/school_ability.svg","effects":[]}
|
||||
{"_id":"L5RCoreSch000097","name":"Mind of Calm","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"void","skill":"","difficulty":"","technique_type":"school_ability","xp_cost":"0","description":"","book_reference":"Writ of the Wild p.100"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/school_ability.svg","effects":[]}
|
||||
{"_id":"L5RCoreSch000098","name":"Evolution of the Wilds","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"void","skill":"","difficulty":"","technique_type":"school_ability","xp_cost":"0","description":"","book_reference":"Writ of the Wild p.101"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/school_ability.svg","effects":[]}
|
||||
{"_id":"L5RCoreSch000099","name":"Mazoku's Authority","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"void","skill":"","difficulty":"","technique_type":"school_ability","xp_cost":"0","description":"","book_reference":"Celestial Realms - Deathly Turns p.24"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/school_ability.svg","effects":[]}
|
||||
{"_id":"L5RCoreSch000100","name":"Effortless Aim","permission":{"default":0},"type":"technique","data":{"in_curriculum":false,"xp_used":0,"rank":"1","bought_at_rank":0,"ring":"void","skill":"","difficulty":"","technique_type":"school_ability","xp_cost":"0","description":"","book_reference":"Celestial Realms - Deathly Turns p.25"},"sort":100001,"flags":{},"img":"systems/l5r5e/assets/icons/techs/school_ability.svg","effects":[]}
|
||||
|
||||
@@ -16,66 +16,92 @@ export class ActorL5r5e extends Actor {
|
||||
docData.img = `${CONFIG.l5r5e.paths.assets}icons/actors/${docData.type}.svg`;
|
||||
}
|
||||
|
||||
// Some tweak on actors prototypeToken
|
||||
docData.prototypeToken = docData.prototypeToken || {};
|
||||
switch (docData.type) {
|
||||
case "character":
|
||||
foundry.utils.mergeObject(
|
||||
docData.prototypeToken,
|
||||
{
|
||||
// vision: true,
|
||||
// dimSight: 30,
|
||||
// brightSight: 0,
|
||||
actorLink: true,
|
||||
disposition: 1, // friendly
|
||||
bar1: {
|
||||
attribute: "fatigue",
|
||||
},
|
||||
bar2: {
|
||||
attribute: "strife",
|
||||
},
|
||||
},
|
||||
{ overwrite: false }
|
||||
);
|
||||
break;
|
||||
// Only for new actors (New actor has no items, duplicates does)
|
||||
if (!docData.items) {
|
||||
// Some tweak on actors prototypeToken
|
||||
docData.prototypeToken = docData.prototypeToken || {};
|
||||
switch (docData.type) {
|
||||
case "character":
|
||||
// Load skills from core compendiums (only for pc character)
|
||||
docData.items = [];
|
||||
await ActorL5r5e.addSkillsFromDefaultList(docData);
|
||||
|
||||
case "npc":
|
||||
foundry.utils.mergeObject(
|
||||
docData.prototypeToken,
|
||||
{
|
||||
actorLink: true,
|
||||
disposition: 0, // neutral
|
||||
bar1: {
|
||||
attribute: "fatigue",
|
||||
// Set token properties
|
||||
foundry.utils.mergeObject(
|
||||
docData.prototypeToken,
|
||||
{
|
||||
// vision: true,
|
||||
// dimSight: 30,
|
||||
// brightSight: 0,
|
||||
actorLink: true,
|
||||
disposition: 1, // friendly
|
||||
bar1: {
|
||||
attribute: "fatigue",
|
||||
},
|
||||
bar2: {
|
||||
attribute: "strife",
|
||||
},
|
||||
},
|
||||
bar2: {
|
||||
attribute: "strife",
|
||||
},
|
||||
},
|
||||
{ overwrite: false }
|
||||
);
|
||||
break;
|
||||
{ overwrite: false }
|
||||
);
|
||||
break;
|
||||
|
||||
case "army":
|
||||
foundry.utils.mergeObject(
|
||||
docData.prototypeToken,
|
||||
{
|
||||
actorLink: true,
|
||||
disposition: 0, // neutral
|
||||
bar1: {
|
||||
attribute: "battle_readiness.casualties_strength",
|
||||
case "npc":
|
||||
foundry.utils.mergeObject(
|
||||
docData.prototypeToken,
|
||||
{
|
||||
actorLink: true,
|
||||
disposition: 0, // neutral
|
||||
bar1: {
|
||||
attribute: "fatigue",
|
||||
},
|
||||
bar2: {
|
||||
attribute: "strife",
|
||||
},
|
||||
},
|
||||
bar2: {
|
||||
attribute: "battle_readiness.panic_discipline",
|
||||
{ overwrite: false }
|
||||
);
|
||||
break;
|
||||
|
||||
case "army":
|
||||
foundry.utils.mergeObject(
|
||||
docData.prototypeToken,
|
||||
{
|
||||
actorLink: true,
|
||||
disposition: 0, // neutral
|
||||
bar1: {
|
||||
attribute: "battle_readiness.casualties_strength",
|
||||
},
|
||||
bar2: {
|
||||
attribute: "battle_readiness.panic_discipline",
|
||||
},
|
||||
},
|
||||
},
|
||||
{ overwrite: false }
|
||||
);
|
||||
break;
|
||||
{ overwrite: false }
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
await super.create(docData, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all the skills from compendiums to "items"
|
||||
*/
|
||||
static async addSkillsFromDefaultList(docData) {
|
||||
console.log(`L5R5E | Adding default skills to ${docData.name}`);
|
||||
|
||||
const skillList = await game.l5r5e.HelpersL5r5e.getSkillsItemsList();
|
||||
|
||||
skillList.forEach(item => {
|
||||
// Get the json data and replace the object id/rank
|
||||
const tmpData = item.toObject();
|
||||
tmpData._id = foundry.utils.randomID();
|
||||
tmpData.system.rank = 0;
|
||||
docData.items.push(tmpData);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Entity-specific actions that should occur when the Entity is updated
|
||||
* @override
|
||||
@@ -94,7 +120,7 @@ export class ActorL5r5e extends Actor {
|
||||
context.pack = this.pack;
|
||||
|
||||
// NPC switch between types : Linked actor for Adversary, unlinked for Minion
|
||||
if (!!docData["system.type"] && this.type === "npc" && docData["system.type"] !== this.system.type) {
|
||||
if (!!docData["system.type"] && this.isNpc && docData["system.type"] !== this.system.type) {
|
||||
docData["prototypeToken.actorLink"] = docData["system.type"] === "adversary";
|
||||
}
|
||||
|
||||
@@ -197,38 +223,51 @@ export class ActorL5r5e extends Actor {
|
||||
* @private
|
||||
*/
|
||||
async _updateActorFromAdvancement(item, isAdd) {
|
||||
if (item && item.type === "advancement") {
|
||||
const actor = foundry.utils.duplicate(this.system);
|
||||
const itemData = item.system;
|
||||
if (itemData.advancement_type === "ring") {
|
||||
// Ring
|
||||
if (isAdd) {
|
||||
actor.rings[itemData.ring] = Math.min(9, actor.rings[itemData.ring] + 1);
|
||||
} else {
|
||||
actor.rings[itemData.ring] = Math.max(1, actor.rings[itemData.ring] - 1);
|
||||
}
|
||||
if (!item || item.type !== "advancement") {
|
||||
return;
|
||||
}
|
||||
|
||||
const actorSystem = foundry.utils.duplicate(this.system);
|
||||
const itemData = item.system;
|
||||
if (itemData.advancement_type === "ring") {
|
||||
// Ring
|
||||
if (isAdd) {
|
||||
actorSystem.rings[itemData.ring] = Math.min(9, actorSystem.rings[itemData.ring] + 1);
|
||||
} else {
|
||||
// Skill
|
||||
const skillCatId = CONFIG.l5r5e.skills.get(itemData.skill);
|
||||
if (skillCatId) {
|
||||
if (isAdd) {
|
||||
actor.skills[skillCatId][itemData.skill] = Math.min(
|
||||
9,
|
||||
actor.skills[skillCatId][itemData.skill] + 1
|
||||
);
|
||||
} else {
|
||||
actor.skills[skillCatId][itemData.skill] = Math.max(
|
||||
0,
|
||||
actor.skills[skillCatId][itemData.skill] - 1
|
||||
);
|
||||
}
|
||||
}
|
||||
actorSystem.rings[itemData.ring] = Math.max(1, actorSystem.rings[itemData.ring] - 1);
|
||||
}
|
||||
|
||||
// Update Actor
|
||||
await this.update({
|
||||
system: foundry.utils.diffObject(this.system, actor),
|
||||
system: foundry.utils.diffObject(this.system, actorSystem),
|
||||
});
|
||||
|
||||
} else {
|
||||
// Skill
|
||||
let skillItem = await fromUuid(itemData.skill); // Skill itemUuid
|
||||
if (!skillItem) {
|
||||
console.warn("L5R5E | Unknown skill item uuid", itemData.skill);
|
||||
return;
|
||||
}
|
||||
// Out of actor item ?
|
||||
if (!skillItem.actor || skillItem.actor._id !== this._id) {
|
||||
const checkItem = this.items.getName(skillItem.name);
|
||||
if (checkItem) {
|
||||
skillItem = checkItem;
|
||||
} else {
|
||||
throw new Error(`Unable to find "${skillItem.name}" on this actor`);
|
||||
}
|
||||
}
|
||||
|
||||
const newRank = isAdd
|
||||
? Math.min(9, skillItem.system.rank + 1)
|
||||
: Math.max(0, skillItem.system.rank - 1);
|
||||
if (skillItem.system.rank === newRank) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update Item
|
||||
await skillItem.update({ "system.rank": newRank });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,12 +300,20 @@ export class ActorL5r5e extends Actor {
|
||||
return this.type === "character";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this actor is a NPC
|
||||
* @return {boolean}
|
||||
*/
|
||||
get isNpc() {
|
||||
return this.type === "npc";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this actor is an Adversary
|
||||
* @return {boolean}
|
||||
*/
|
||||
get isAdversary() {
|
||||
return this.type === "npc" && this.system.type === "adversary";
|
||||
return this.isNpc && this.system.type === "adversary";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,7 +321,7 @@ export class ActorL5r5e extends Actor {
|
||||
* @return {boolean}
|
||||
*/
|
||||
get isMinion() {
|
||||
return this.type === "npc" && this.system.type === "minion";
|
||||
return this.isNpc && this.system.type === "minion";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,7 +417,7 @@ export class ActorL5r5e extends Actor {
|
||||
if (!this.isCharacterType) {
|
||||
return null;
|
||||
}
|
||||
return this.type === "npc" ? this.system.conflict_rank.social : this.system.identity.school_rank;
|
||||
return this.isNpc ? this.system.conflict_rank.social : this.system.identity.school_rank;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -381,6 +428,6 @@ export class ActorL5r5e extends Actor {
|
||||
if (!this.isCharacterType) {
|
||||
return null;
|
||||
}
|
||||
return this.type === "npc" ? this.system.conflict_rank.martial : this.system.identity.school_rank;
|
||||
return this.isNpc ? this.system.conflict_rank.martial : this.system.identity.school_rank;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,141 +133,151 @@ export class BaseCharacterSheetL5r5e extends BaseSheetL5r5e {
|
||||
* @param {DragEvent} event
|
||||
*/
|
||||
async _onDrop(event) {
|
||||
// *** Everything below here is only needed if the sheet is editable ***
|
||||
if (!this.isEditable || this.actor.system.soft_locked) {
|
||||
console.log("L5R5E | BCS | This sheet is not editable");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check item type and subtype
|
||||
const item = await game.l5r5e.HelpersL5r5e.getDragnDropTargetObject(event);
|
||||
if (!item || !["Item", "JournalEntry"].includes(item.documentName) || item.type === "property") {
|
||||
console.log(`L5R5E | BCS | Wrong subtype ${item?.type}`, item);
|
||||
return;
|
||||
}
|
||||
|
||||
// Specific curriculum journal drop
|
||||
if (item.documentName === "JournalEntry") {
|
||||
// npc does not have this
|
||||
if (!this.actor.system.identity?.school_curriculum_journal) {
|
||||
console.log("L5R5E | BCS | NPC won't go to school :'(");
|
||||
return;
|
||||
}
|
||||
this.actor.system.identity.school_curriculum_journal = {
|
||||
id: item._id,
|
||||
name: item.name,
|
||||
pack: item.pack || null,
|
||||
};
|
||||
await this.actor.update({
|
||||
system: {
|
||||
identity: {
|
||||
school_curriculum_journal: this.actor.system.identity.school_curriculum_journal,
|
||||
},
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Dropped an item with same "id" as one owned
|
||||
if (this.actor.items) {
|
||||
// Exit if we already owned exactly this id (drag a personal item on our own sheet)
|
||||
if (
|
||||
this.actor.items.some((embedItem) => {
|
||||
// Search in children
|
||||
if (embedItem.items instanceof Map && embedItem.items.has(item._id)) {
|
||||
return true;
|
||||
}
|
||||
return embedItem._id === item._id;
|
||||
})
|
||||
) {
|
||||
console.log("L5R5E | BCS | This element has been ignored because it already exists in this actor", item.uuid);
|
||||
try {
|
||||
// *** Everything below here is only needed if the sheet is editable ***
|
||||
if (!this.isEditable || this.actor.system.soft_locked) {
|
||||
console.log("L5R5E | BCS | This sheet is not editable");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add quantity instead if they have (id is different so use type and name)
|
||||
if (item.system.quantity) {
|
||||
const tmpItem = this.actor.items.find(
|
||||
(embedItem) => embedItem.name === item.name && embedItem.type === item.type
|
||||
);
|
||||
if (tmpItem && this._modifyQuantity(tmpItem.id, 1)) {
|
||||
// Check item type and subtype
|
||||
const item = await game.l5r5e.HelpersL5r5e.getDragnDropTargetObject(event);
|
||||
if (!item || !["Item", "JournalEntry"].includes(item.documentName) || item.type === "property") {
|
||||
console.log(`L5R5E | BCS | Wrong subtype ${item?.type}`, item);
|
||||
return;
|
||||
}
|
||||
|
||||
// Specific curriculum journal drop
|
||||
if (item.documentName === "JournalEntry") {
|
||||
// npc does not have this
|
||||
if (!this.actor.system.identity?.school_curriculum_journal) {
|
||||
console.log("L5R5E | BCS | NPC won't go to school :'(");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can add the item - Foundry override cause props
|
||||
const allowed = Hooks.call("dropActorSheetData", this.actor, this, item);
|
||||
if (allowed === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
let itemData = item.toObject(true);
|
||||
|
||||
// Item subtype specific
|
||||
switch (itemData.type) {
|
||||
case "army_cohort":
|
||||
case "army_fortification":
|
||||
console.warn("L5R5E | BCS | Army items are not allowed", item?.type, item);
|
||||
this.actor.system.identity.school_curriculum_journal = {
|
||||
id: item._id,
|
||||
name: item.name,
|
||||
pack: item.pack || null,
|
||||
};
|
||||
await this.actor.update({
|
||||
system: {
|
||||
identity: {
|
||||
school_curriculum_journal: this.actor.system.identity.school_curriculum_journal,
|
||||
},
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
case "advancement":
|
||||
// Specific advancements, remove 1 to selected ring/skill
|
||||
await this.actor.addBonus(item);
|
||||
break;
|
||||
|
||||
case "title":
|
||||
// Generate new Ids for the embed items
|
||||
await item.generateNewIdsForAllEmbedItems();
|
||||
|
||||
// Add embed advancements bonus
|
||||
for (let [embedId, embedItem] of item.system.items) {
|
||||
if (embedItem.type === "advancement") {
|
||||
await this.actor.addBonus(embedItem);
|
||||
}
|
||||
// Dropped an item with same "id" as one owned
|
||||
if (this.actor.items) {
|
||||
// Exit if we already owned exactly this id (drag a personal item on our own sheet)
|
||||
if (
|
||||
this.actor.items.some((embedItem) => {
|
||||
// Search in children
|
||||
if (embedItem.items instanceof Map && embedItem.items.has(item._id)) {
|
||||
return true;
|
||||
}
|
||||
return embedItem._id === item._id;
|
||||
})
|
||||
) {
|
||||
console.log("L5R5E | BCS | This element has been ignored because it already exists in this actor", item.uuid);
|
||||
return;
|
||||
}
|
||||
|
||||
// refresh data
|
||||
itemData = item.toObject(true);
|
||||
break;
|
||||
|
||||
case "technique":
|
||||
// School_ability and mastery_ability, allow only 1 per type
|
||||
if (CONFIG.l5r5e.techniques.get(itemData.system.technique_type)?.type === "school") {
|
||||
if (
|
||||
Array.from(this.actor.items).some((e) => {
|
||||
return e.type === "technique" && e.system.technique_type === itemData.system.technique_type;
|
||||
})
|
||||
) {
|
||||
ui.notifications.info(game.i18n.localize("l5r5e.techniques.only_one"));
|
||||
// Add quantity instead if they have (id is different so use type and name)
|
||||
if (item.system.quantity) {
|
||||
const tmpItem = this.actor.items.find(
|
||||
(embedItem) => embedItem.name === item.name && embedItem.type === item.type
|
||||
);
|
||||
if (tmpItem && this._modifyQuantity(tmpItem.id, 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No cost for schools
|
||||
itemData.system.xp_cost = 0;
|
||||
itemData.system.xp_used = 0;
|
||||
itemData.system.in_curriculum = true;
|
||||
} else {
|
||||
// Check if technique is allowed for this character
|
||||
// if (!game.user.isGM && !this.actor.system.techniques[itemData.system.technique_type]) {
|
||||
// ui.notifications.info(game.i18n.localize("l5r5e.techniques.not_allowed"));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Verify cost
|
||||
itemData.system.xp_cost =
|
||||
itemData.system.xp_cost > 0 ? itemData.system.xp_cost : CONFIG.l5r5e.xp.techniqueCost;
|
||||
itemData.system.xp_used = itemData.system.xp_cost;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Modify the bought at rank to the current actor rank
|
||||
if (itemData.system.bought_at_rank !== undefined && this.actor.system.identity?.school_rank) {
|
||||
itemData.system.bought_at_rank = this.actor.system.identity.school_rank;
|
||||
}
|
||||
// Can add the item - Foundry override cause props
|
||||
const allowed = Hooks.call("dropActorSheetData", this.actor, this, item);
|
||||
if (allowed === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally create the embed
|
||||
return this.actor.createEmbeddedDocuments("Item", [itemData]);
|
||||
let itemData = item.toObject(true);
|
||||
|
||||
// Item subtype specific
|
||||
switch (itemData.type) {
|
||||
case "army_cohort":
|
||||
case "army_fortification":
|
||||
console.warn("L5R5E | BCS | Army items are not allowed", item?.type, item);
|
||||
return;
|
||||
|
||||
case "advancement":
|
||||
// Specific advancements, add x to selected ring/skill
|
||||
await this.actor.addBonus(item);
|
||||
break;
|
||||
|
||||
case "title":
|
||||
// Generate new Ids for the embed items
|
||||
await item.generateNewIdsForAllEmbedItems();
|
||||
|
||||
// Add embed advancements bonus
|
||||
for (let [embedId, embedItem] of item.system.items) {
|
||||
if (embedItem.type === "advancement") {
|
||||
await this.actor.addBonus(embedItem);
|
||||
}
|
||||
}
|
||||
|
||||
// refresh data
|
||||
itemData = item.toObject(true);
|
||||
break;
|
||||
|
||||
case "skill":
|
||||
itemData.system.rank = 0;
|
||||
itemData.system.modifier = 0;
|
||||
break;
|
||||
|
||||
case "technique":
|
||||
// School_ability and mastery_ability, allow only 1 per type
|
||||
if (CONFIG.l5r5e.techniques.get(itemData.system.technique_type)?.type === "school") {
|
||||
if (
|
||||
Array.from(this.actor.items).some((e) => {
|
||||
return e.type === "technique" && e.system.technique_type === itemData.system.technique_type;
|
||||
})
|
||||
) {
|
||||
ui.notifications.info(game.i18n.localize("l5r5e.techniques.only_one"));
|
||||
return;
|
||||
}
|
||||
|
||||
// No cost for schools
|
||||
itemData.system.xp_cost = 0;
|
||||
itemData.system.xp_used = 0;
|
||||
itemData.system.in_curriculum = true;
|
||||
} else {
|
||||
// Check if technique is allowed for this character
|
||||
// if (!game.user.isGM && !this.actor.system.techniques[itemData.system.technique_type]) {
|
||||
// ui.notifications.info(game.i18n.localize("l5r5e.techniques.not_allowed"));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Verify cost
|
||||
itemData.system.xp_cost =
|
||||
itemData.system.xp_cost > 0 ? itemData.system.xp_cost : CONFIG.l5r5e.xp.techniqueCost;
|
||||
itemData.system.xp_used = itemData.system.xp_cost;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Modify the bought at rank to the current actor rank
|
||||
if (itemData.system.bought_at_rank !== undefined && this.actor.system.identity?.school_rank) {
|
||||
itemData.system.bought_at_rank = this.actor.system.identity.school_rank;
|
||||
}
|
||||
|
||||
// Finally create the embed
|
||||
return this.actor.createEmbeddedDocuments("Item", [itemData]);
|
||||
|
||||
} catch (ex) {
|
||||
console.warn("L5R5E |", ex.message);
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
|
||||
@@ -98,7 +98,7 @@ export class CharacterGeneratorDialog extends FormApplication {
|
||||
}));
|
||||
return {
|
||||
...(await super.getData(options)),
|
||||
isNpc: this.actor.type === "npc",
|
||||
isNpc: this.actor.isNpc,
|
||||
clanList: [{ id: "random", label: game.i18n.localize("l5r5e.global.random") }, ...clans],
|
||||
genderList: [
|
||||
{ id: "random", label: game.i18n.localize("l5r5e.global.random") },
|
||||
|
||||
@@ -292,7 +292,7 @@ export class CharacterGenerator {
|
||||
}
|
||||
) {
|
||||
const actorDatas = actor.system;
|
||||
const isNpc = actor.type === "npc";
|
||||
const isNpc = actor.isNpc;
|
||||
|
||||
// Need to set some required values
|
||||
this.data.age = actorDatas.identity.age || CharacterGenerator.genAge(this.data.avgRingsValue);
|
||||
|
||||
@@ -47,8 +47,11 @@ export class CharacterSheetL5r5e extends BaseCharacterSheetL5r5e {
|
||||
// Min rank = 1
|
||||
this.actor.system.identity.school_rank = Math.max(1, this.actor.system.identity.school_rank);
|
||||
|
||||
// Split Skills
|
||||
sheetData.data.skillCategories = game.l5r5e.HelpersL5r5e.splitSkillByCategory(sheetData.items);
|
||||
|
||||
// Split Money
|
||||
sheetData.data.system.money = this._zeniToMoney(this.actor.system.zeni);
|
||||
sheetData.data.money = this._zeniToMoney(this.actor.system.zeni);
|
||||
|
||||
// Split school advancements by rank, and calculate xp spent and add it to total
|
||||
this._prepareSchoolAdvancement(sheetData);
|
||||
@@ -180,6 +183,12 @@ export class CharacterSheetL5r5e extends BaseCharacterSheetL5r5e {
|
||||
* @param formData
|
||||
*/
|
||||
_updateObject(event, formData) {
|
||||
// Update items ranks
|
||||
const formDataObj = foundry.utils.expandObject(formData);
|
||||
if (formDataObj.skillsValues) {
|
||||
this._updateItemsRank(foundry.utils.expandObject(formDataObj.skillsValues));
|
||||
}
|
||||
|
||||
// Clan tag trim if autocomplete in school name
|
||||
if (
|
||||
formData["autoCompleteListName"] === "system.identity.school" &&
|
||||
@@ -194,16 +203,12 @@ export class CharacterSheetL5r5e extends BaseCharacterSheetL5r5e {
|
||||
}
|
||||
|
||||
// Store money in Zeni
|
||||
if (formData["system.money.koku"] || formData["system.money.bu"] || formData["system.money.zeni"]) {
|
||||
if (formData["money.koku"] || formData["money.bu"] || formData["money.zeni"]) {
|
||||
formData["system.zeni"] = this._moneyToZeni(
|
||||
formData["system.money.koku"] || 0,
|
||||
formData["system.money.bu"] || 0,
|
||||
formData["system.money.zeni"] || 0
|
||||
formData["money.koku"] || 0,
|
||||
formData["money.bu"] || 0,
|
||||
formData["money.zeni"] || 0
|
||||
);
|
||||
// Remove fake money object
|
||||
delete formData["system.money.koku"];
|
||||
delete formData["system.money.bu"];
|
||||
delete formData["system.money.zeni"];
|
||||
}
|
||||
|
||||
// Save computed values
|
||||
@@ -219,6 +224,20 @@ export class CharacterSheetL5r5e extends BaseCharacterSheetL5r5e {
|
||||
return super._updateObject(event, formData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update embedded items ranks
|
||||
* @param {Object<String:String>} itemsValues items new values "ids: rank"
|
||||
*/
|
||||
_updateItemsRank(itemsValues) {
|
||||
Object.entries(itemsValues).forEach(([key, rank]) => {
|
||||
const item = this.actor.items.get(key);
|
||||
if (!item || item.system.rank === rank) {
|
||||
return;
|
||||
}
|
||||
item.update({ "system.rank": rank });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a sum in Zeni to Zeni, Bu and Koku
|
||||
* @param {number} zeni
|
||||
|
||||
@@ -251,7 +251,7 @@ export class TwentyQuestionsDialog extends FormApplication {
|
||||
if (!["item", "technique", "peculiarity", "bond"].includes(type)) {
|
||||
return;
|
||||
}
|
||||
const stepKey = $(event.target).data("step");
|
||||
const stepKey = $(event.currentTarget).data("step");
|
||||
if (!stepKey) {
|
||||
console.warn("L5R5E | 20Q | Event stepKey is undefined");
|
||||
return;
|
||||
|
||||
@@ -32,7 +32,7 @@ export class CombatL5r5e extends Combat {
|
||||
const skillId = messageOptions.skillId
|
||||
? messageOptions.skillId
|
||||
: CONFIG.l5r5e.initiativeSkills[game.settings.get(CONFIG.l5r5e.namespace, "initiative-encounter")];
|
||||
const skillCat = CONFIG.l5r5e.skills.get(skillId);
|
||||
const skillCat = CONFIG.l5r5e.skills.get(skillId); // TODO refacto with skill items
|
||||
|
||||
// Get score for each combatant
|
||||
const networkActors = [];
|
||||
@@ -199,6 +199,6 @@ export class CombatL5r5e extends Combat {
|
||||
* @private
|
||||
*/
|
||||
static _getWeightByActorType(actor) {
|
||||
return actor.type === "npc" ? (actor.type === "minion" ? 3 : 2) : 1;
|
||||
return actor.isNpc ? (actor.type === "minion" ? 3 : 2) : 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export const L5R5E = {
|
||||
money: [50, 10],
|
||||
stances: ["earth", "air", "water", "fire", "void"],
|
||||
roles: ["artisan", "bushi", "courtier", "monk", "sage", "shinobi", "shugenja"],
|
||||
skillCategories: ["artisan", "martial", "scholar", "social", "trade"],
|
||||
xp: {
|
||||
costPerRank: [0, 20, 24, 32, 44, 60],
|
||||
bondCostPerRank: [0, 3, 4, 6, 8, 10],
|
||||
@@ -46,6 +47,7 @@ L5R5E.techniques.set("title_ability", { type: "title", displayInTypes: false });
|
||||
L5R5E.techniques.set("specificity", { type: "custom", displayInTypes: false });
|
||||
|
||||
// *** SkillId - CategoryId ***
|
||||
// Hardcoded skills are still required for compatibility (migration & olds worlds)
|
||||
L5R5E.skills = new Map();
|
||||
L5R5E.skills.set("aesthetics", "artisan");
|
||||
L5R5E.skills.set("composition", "artisan");
|
||||
|
||||
@@ -110,7 +110,7 @@ export class DicePickerDialog extends FormApplication {
|
||||
* ex: new game.l5r5e.DicePickerDialog({skillId: 'aesthetics', ringId: 'water', actor: game.user.character}).render(true);
|
||||
*
|
||||
* Options :
|
||||
* actor {Actor} Any `Actor` object instance. Ex : `game.user.character`, `canvas.tokens.controlled[0].actor`
|
||||
* actor {ActorL5r5e} Any `Actor` object instance. Ex : `game.user.character`, `canvas.tokens.controlled[0].actor`
|
||||
* actorId {string} This is the `id` not the `uuid` of an actor. Ex : "AbYgKrNwWeAxa9jT"
|
||||
* actorName {string} Careful this is case-sensitive. Ex : "Isawa Aki"
|
||||
* difficulty {number} `1` to `9`
|
||||
@@ -271,19 +271,21 @@ export class DicePickerDialog extends FormApplication {
|
||||
if (!skillsList) {
|
||||
return;
|
||||
}
|
||||
this.object.skill.list = this.parseSkillsList(skillsList);
|
||||
if (this.object.skill.list.length > 0) {
|
||||
// Set 1st skill
|
||||
if (this.useCategory) {
|
||||
this.skillCatId = this.object.skill.list[0].id;
|
||||
} else {
|
||||
this.skillId = this.object.skill.list[0].id;
|
||||
this.parseSkillsList(skillsList).then((list) => {
|
||||
this.object.skill.list = list;
|
||||
if (this.object.skill.list.length > 0) {
|
||||
// Set 1st skill
|
||||
if (this.useCategory) {
|
||||
this.skillCatId = this.object.skill.list[0].id;
|
||||
} else {
|
||||
this.skillId = this.object.skill.list[0].id;
|
||||
}
|
||||
// Remove the list if only one item
|
||||
if (this.object.skill.list.length === 1) {
|
||||
this.object.skill.list = null;
|
||||
}
|
||||
}
|
||||
// Remove the list if only one item
|
||||
if (this.object.skill.list.length === 1) {
|
||||
this.object.skill.list = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,7 +305,7 @@ export class DicePickerDialog extends FormApplication {
|
||||
name: "",
|
||||
};
|
||||
|
||||
this.skillCatId = CONFIG.l5r5e.skills.get(skillId);
|
||||
this.skillCatId = CONFIG.l5r5e.skills.get(skillId); // TODO refacto with skill items
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,7 +384,7 @@ export class DicePickerDialog extends FormApplication {
|
||||
* @return {boolean}
|
||||
*/
|
||||
get useCategory() {
|
||||
return !!this._actor && this._actor.type === "npc";
|
||||
return !!this._actor && this._actor.isNpc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -830,10 +832,10 @@ export class DicePickerDialog extends FormApplication {
|
||||
* NPC : shrink to category names
|
||||
*
|
||||
* @param {string} skillList
|
||||
* @return {string[]}
|
||||
* @returns {Promise<{id: *, label: string}[]>}
|
||||
*/
|
||||
parseSkillsList(skillList) {
|
||||
const categories = game.l5r5e.HelpersL5r5e.getCategoriesSkillsList();
|
||||
async parseSkillsList(skillList) {
|
||||
const categories = await game.l5r5e.HelpersL5r5e.getCategoriesSkillsList();
|
||||
|
||||
// Sanitize and uniques values
|
||||
const unqSkillList = new Set();
|
||||
|
||||
@@ -535,7 +535,7 @@ export class RollnKeepDialog extends FormApplication {
|
||||
|
||||
// Show DsN dice for the new roll
|
||||
if (game.dice3d !== undefined) {
|
||||
game.dice3d.showForRoll(
|
||||
await game.dice3d.showForRoll(
|
||||
roll,
|
||||
game.user,
|
||||
true,
|
||||
|
||||
@@ -113,7 +113,7 @@ export class GmMonitor extends FormApplication {
|
||||
|
||||
} else {
|
||||
// If empty add pc with owner
|
||||
actors = game.actors.filter((actor) => actor.type === "character" && actor.hasPlayerOwnerActive);
|
||||
actors = game.actors.filter((actor) => actor.isCharacter && actor.hasPlayerOwnerActive);
|
||||
this._saveActorsIds();
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,12 @@ export const RegisterHandlebars = function () {
|
||||
return objects.join("");
|
||||
});
|
||||
|
||||
// Make the sum of values
|
||||
Handlebars.registerHelper('sum', function(...nb) {
|
||||
nb.pop(); // remove this function call
|
||||
return nb.reduce((acc, n) => acc + Number(n ?? 0), 0);
|
||||
});
|
||||
|
||||
// Add a setter
|
||||
Handlebars.registerHelper("setVar", function (varName, varValue, options) {
|
||||
options.data.root[varName] = varValue;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
export class HelpersL5r5e {
|
||||
/**
|
||||
* Get Rings/Element for List / Select
|
||||
* @param {Actor|null} actor
|
||||
* @param {ActorL5r5e|null} actor
|
||||
* @return {{id: string, label: *, value}[]}
|
||||
*/
|
||||
static getRingsList(actor = null) {
|
||||
@@ -15,12 +15,83 @@ export class HelpersL5r5e {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default skill list for settings
|
||||
* @returns {string[]}
|
||||
*/
|
||||
static getDefaultSkillsUuidFromPack() {
|
||||
return Array.from({length: 24}, (_, i) => "Compendium.l5r5e.core-skills.L5RCoreSkl" + ('' +(i + 1)).padStart(6, "0"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the skill items list for this actor or from the default (settings)
|
||||
* @param {ActorL5r5e} actor If actor provided, get the skills preferably from it
|
||||
* @returns {Promise<Item[]>}
|
||||
*/
|
||||
static async getSkillsItemsList(actor = null) {
|
||||
const skillList = [];
|
||||
|
||||
// If actor provided, get the skills preferably from it
|
||||
if (actor instanceof Actor && actor?.isCharacter) {
|
||||
actor.items
|
||||
.filter(item => item.type === "skill")
|
||||
.forEach(item => skillList.push(item))
|
||||
}
|
||||
|
||||
// Get the default list from settings
|
||||
let defaultList = game.settings.get(CONFIG.l5r5e.namespace, "defaultSkillsList") || [];
|
||||
|
||||
// If empty, refill with default values
|
||||
if (foundry.utils.isEmpty(defaultList)) {
|
||||
defaultList = HelpersL5r5e.getDefaultSkillsUuidFromPack();
|
||||
await game.settings.set(CONFIG.l5r5e.namespace, "defaultSkillsList", defaultList);
|
||||
}
|
||||
|
||||
defaultList = await Promise.all(defaultList.map(async uuid => await fromUuid(uuid)));
|
||||
|
||||
|
||||
// Merge the two list by name
|
||||
const namesList = skillList.map(item => item.name);
|
||||
defaultList.forEach(item => {
|
||||
if (item && !namesList.includes(item.name)) {
|
||||
skillList.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
return skillList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split Skills item by categories, and sort them alphabetically
|
||||
* @param {Item[]} itemsList
|
||||
* @return {{catName: Item[]}}
|
||||
*/
|
||||
static splitSkillByCategory(itemsList) {
|
||||
const skill = CONFIG.l5r5e.skillCategories.reduce((acc,curr) => (acc[curr] = [], acc), {});
|
||||
|
||||
itemsList.forEach((item) => {
|
||||
if (item.type === "skill") {
|
||||
const cat = item.system.category ?? "artisan";
|
||||
skill[cat].push(item);
|
||||
}
|
||||
});
|
||||
|
||||
// Sort Items by name
|
||||
Object.values(skill).forEach(section => {
|
||||
section.sort((a, b) => a.name.localeCompare(b.name));
|
||||
});
|
||||
|
||||
return skill;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Skills for List / Select with groups
|
||||
* @param {boolean} useGroup
|
||||
* @return {{cat: any, id: any, label: *}[]}
|
||||
*/
|
||||
static getSkillsList(useGroup = false) {
|
||||
console.warn('@deprecated hardcoded skills - helpers.getSkillsList() - Use getSkillsItemsList() + splitSkillByCategory() instead'); // TODO @deprecated hardcoded skills
|
||||
|
||||
if (!useGroup) {
|
||||
return Array.from(CONFIG.l5r5e.skills).map(([id, cat]) => ({
|
||||
id: id,
|
||||
@@ -45,17 +116,25 @@ export class HelpersL5r5e {
|
||||
|
||||
/**
|
||||
* Return Categories and Skill names in it
|
||||
* @return {Map}
|
||||
* @param {ActorL5r5e} actor If actor provided, get the skills preferably from it
|
||||
* @returns {Promise<Map>}
|
||||
*/
|
||||
static getCategoriesSkillsList() {
|
||||
return Array.from(CONFIG.l5r5e.skills).reduce((acc, [id, cat]) => {
|
||||
static async getCategoriesSkillsList(actor = null) {
|
||||
const skillList = await HelpersL5r5e.getSkillsItemsList(actor);
|
||||
const acc = new Map();
|
||||
|
||||
skillList.forEach((item) => {
|
||||
const id = item.name;
|
||||
const cat = item.system.category;
|
||||
|
||||
if (acc.has(cat)) {
|
||||
acc.set(cat, [...acc.get(cat), id]);
|
||||
} else {
|
||||
acc.set(cat, [id]);
|
||||
}
|
||||
return acc;
|
||||
}, new Map());
|
||||
});
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,6 +376,8 @@ export class HelpersL5r5e {
|
||||
static getPackNameForCoreItem(documentId) {
|
||||
const core = new Map();
|
||||
|
||||
core.set("Skl", "l5r5e.core-skills");
|
||||
|
||||
core.set("Arm", "l5r5e.core-armors");
|
||||
core.set("Bon", "l5r5e.core-bonds");
|
||||
core.set("Boo", "l5r5e.core-celestial-implement-boons");
|
||||
@@ -442,8 +523,8 @@ export class HelpersL5r5e {
|
||||
|
||||
/**
|
||||
* Subscribe to common events from the sheet.
|
||||
* @param {jQuery} html HTML content of the sheet.
|
||||
* @param {Actor} actor Actor Object
|
||||
* @param {jQuery} html HTML content of the sheet.
|
||||
* @param {ActorL5r5e} actor Actor Object
|
||||
*/
|
||||
static commonListeners(html, actor = null) {
|
||||
// Toggle
|
||||
@@ -567,12 +648,15 @@ export class HelpersL5r5e {
|
||||
static async getEmbedItemByEvent(event, actor) {
|
||||
const current = $(event.currentTarget);
|
||||
const itemId = current.data("item-id");
|
||||
const itemUuid = current.data("item-uuid");
|
||||
const propertyId = current.data("property-id");
|
||||
const itemParentId = current.data("item-parent-id");
|
||||
|
||||
let item;
|
||||
if (propertyId) {
|
||||
item = await HelpersL5r5e.getObjectGameOrPack({ id: propertyId, type: "Item" });
|
||||
} else if (itemUuid) {
|
||||
item = await fromUuid(itemUuid);
|
||||
} else if (itemParentId) {
|
||||
// Embed Item
|
||||
let parentItem;
|
||||
@@ -739,7 +823,7 @@ export class HelpersL5r5e {
|
||||
* @return {Promise<{RollTableDraw}>} The drawn results
|
||||
*/
|
||||
static async drawManyFromPack(pack, tableName, retrieve = 5, opt = { rollMode: "selfroll" }) {
|
||||
const comp = await game.packs.get(pack);
|
||||
const comp = game.packs.get(pack);
|
||||
if (!comp) {
|
||||
console.log(`L5R5E | Helpers | Pack not found[${pack}]`);
|
||||
return;
|
||||
@@ -754,6 +838,23 @@ export class HelpersL5r5e {
|
||||
return await table.drawMany(retrieve, opt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all compendium data from his id
|
||||
*
|
||||
* @param {String} compendium
|
||||
* @param {Function} filter
|
||||
* @returns {Promise<Item[]>}
|
||||
*/
|
||||
static async loadCompendium(compendium, filter = item => true) {
|
||||
const pack = game.packs.get(compendium);
|
||||
if (!pack) {
|
||||
console.log(`L5R5E | Pack not found[${compendium}]`);
|
||||
return;
|
||||
}
|
||||
const data = (await pack.getDocuments()) ?? [];
|
||||
return data.filter(filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the string simplified for comparaison
|
||||
* @param {string} str
|
||||
|
||||
@@ -6,7 +6,7 @@ export default class HooksL5r5e {
|
||||
// Enable embed Babele compendiums only if custom compendium is not found or disabled
|
||||
if (
|
||||
typeof Babele !== "undefined" &&
|
||||
Babele.get().modules.every((module) => module.module !== "l5r5e-custom-compendiums")
|
||||
Babele.get().modules.every((module) => module.module !== game.settings.get(CONFIG.l5r5e.namespace, "custom-compendium-name"))
|
||||
) {
|
||||
Babele.get().setSystemTranslationsDir("babele"); // Since Babele v2.0.7
|
||||
}
|
||||
@@ -28,6 +28,14 @@ export default class HooksL5r5e {
|
||||
game.l5r5e.migrations.migrateWorld({ force: false }).then();
|
||||
}
|
||||
|
||||
// Prepare values are sometimes null
|
||||
["character", "adversary", "minion"].forEach(preparedId => {
|
||||
const prepVal = game.settings.get(CONFIG.l5r5e.namespace, `initiative-prepared-${preparedId}`);
|
||||
if (prepVal === null || prepVal === "null") {
|
||||
game.settings.set(CONFIG.l5r5e.namespace, `initiative-prepared-${preparedId}`, "actor");
|
||||
}
|
||||
});
|
||||
|
||||
// For some reasons, not always really ready, so wait a little
|
||||
await new Promise((r) => setTimeout(r, 2000));
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ export class ItemL5r5e extends Item {
|
||||
|
||||
/**
|
||||
* Return the linked Actor instance if any (current or embed)
|
||||
* @return {Actor|null}
|
||||
* @return {ActorL5r5e|null}
|
||||
*/
|
||||
get actor() {
|
||||
return super.actor || game.actors.get(this.system.parent_id?.actor_id) || null;
|
||||
@@ -58,7 +58,11 @@ export class ItemL5r5e extends Item {
|
||||
*/
|
||||
static async create(data, context = {}) {
|
||||
if (data.img === undefined) {
|
||||
data.img = `${CONFIG.l5r5e.paths.assets}icons/items/${data.type}.svg`;
|
||||
if (data.type === 'technique') {
|
||||
data.img = `${CONFIG.l5r5e.paths.assets}icons/techs/kata.svg`;
|
||||
} else {
|
||||
data.img = `${CONFIG.l5r5e.paths.assets}icons/items/${data.type}.svg`;
|
||||
}
|
||||
}
|
||||
return super.create(data, context);
|
||||
}
|
||||
@@ -235,7 +239,11 @@ export class ItemL5r5e extends Item {
|
||||
if (addBonusToActor) {
|
||||
const actor = this.actor;
|
||||
if (item instanceof Item && actor instanceof Actor) {
|
||||
actor.addBonus(item);
|
||||
try {
|
||||
await actor.addBonus(item);
|
||||
} catch (ex) {
|
||||
console.warn("L5R5E |", ex.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
|
||||
const sheetData = await super.getData(options);
|
||||
|
||||
sheetData.data.subTypesList = AdvancementSheetL5r5e.types;
|
||||
sheetData.data.skillsList = game.l5r5e.HelpersL5r5e.getSkillsList(true);
|
||||
sheetData.data.skillsList = game.l5r5e.HelpersL5r5e.splitSkillByCategory(await game.l5r5e.HelpersL5r5e.getSkillsItemsList(this.actor));
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
@@ -82,33 +82,45 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
|
||||
let name = this.object.name;
|
||||
let img = this.object.img;
|
||||
|
||||
const getLocalItemByUuid = async (uuid) => {
|
||||
const item = await fromUuid(uuid);
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
if (item?.actor?._id === this.actor._id) {
|
||||
return item;
|
||||
}
|
||||
return this.items.getName(item.name);
|
||||
}
|
||||
const skillItemNew = newChoice.skill ? (await getLocalItemByUuid(newChoice.skill)) : null;
|
||||
const skillItemOld = oldChoice.skill ? (await getLocalItemByUuid(oldChoice.skill)) : null;
|
||||
|
||||
// Modify image to reflect choice
|
||||
if (newChoice.ring) {
|
||||
name = game.i18n.localize(`l5r5e.rings.${newChoice.ring}`) + "+1";
|
||||
img = `systems/l5r5e/assets/icons/rings/${newChoice.ring}.svg`;
|
||||
} else if (newChoice.skill) {
|
||||
name =
|
||||
game.i18n.localize(`l5r5e.skills.${CONFIG.l5r5e.skills.get(newChoice.skill)}.${newChoice.skill}`) +
|
||||
"+1";
|
||||
|
||||
} else if (newChoice.skill && skillItemNew) {
|
||||
name = skillItemNew.name +"+1";
|
||||
img = `systems/l5r5e/assets/dices/default/skill_blank.svg`;
|
||||
}
|
||||
|
||||
// Object embed in actor ?
|
||||
const actor = this.document.actor;
|
||||
if (actor) {
|
||||
if (newChoice.skill && !skillItemNew.actor) {
|
||||
ui.notifications.warn(`Unable to find "${skillItemNew?.name}" on this actor`);
|
||||
return;
|
||||
}
|
||||
|
||||
const actorData = foundry.utils.duplicate(actor.system);
|
||||
let skillCatId = null;
|
||||
|
||||
// Old choices
|
||||
if (oldChoice.ring) {
|
||||
actorData.rings[oldChoice.ring] = Math.max(1, actorData.rings[oldChoice.ring] - 1);
|
||||
}
|
||||
if (oldChoice.skill) {
|
||||
skillCatId = CONFIG.l5r5e.skills.get(oldChoice.skill);
|
||||
actorData.skills[skillCatId][oldChoice.skill] = Math.max(
|
||||
0,
|
||||
actorData.skills[skillCatId][oldChoice.skill] - 1
|
||||
);
|
||||
if (oldChoice.skill && skillItemOld) {
|
||||
await skillItemOld.update({ "system.rank": Math.max(0, skillItemOld.system.rank - 1) });
|
||||
}
|
||||
|
||||
// new choices
|
||||
@@ -119,15 +131,11 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
|
||||
game.i18n.localize(`l5r5e.rings.${newChoice.ring}`) +
|
||||
` +1 (${actorData.rings[newChoice.ring] - 1} -> ${actorData.rings[newChoice.ring]})`;
|
||||
}
|
||||
if (newChoice.skill) {
|
||||
skillCatId = CONFIG.l5r5e.skills.get(newChoice.skill);
|
||||
actorData.skills[skillCatId][newChoice.skill] = actorData.skills[skillCatId][newChoice.skill] + 1;
|
||||
xp_used = actorData.skills[skillCatId][newChoice.skill] * CONFIG.l5r5e.xp.skillCostMultiplier;
|
||||
name =
|
||||
game.i18n.localize(`l5r5e.skills.${skillCatId}.${newChoice.skill}`) +
|
||||
` +1 (${actorData.skills[skillCatId][newChoice.skill] - 1} -> ${
|
||||
actorData.skills[skillCatId][newChoice.skill]
|
||||
})`;
|
||||
if (newChoice.skill && skillItemNew) {
|
||||
const newRank = Math.min(9, skillItemNew.system.rank + 1);
|
||||
await skillItemNew.update({ "system.rank": newRank });
|
||||
xp_used = newRank * CONFIG.l5r5e.xp.skillCostMultiplier;
|
||||
name = `${skillItemNew.name} +1 (${newRank - 1} -> ${newRank})`;
|
||||
}
|
||||
|
||||
// Update Actor
|
||||
@@ -141,7 +149,7 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
|
||||
name: name,
|
||||
img: img,
|
||||
system: {
|
||||
xp_used: xp_used,
|
||||
xp_used,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
28
system/scripts/items/skill-sheet.js
Normal file
28
system/scripts/items/skill-sheet.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import { ItemSheetL5r5e } from "./item-sheet.js";
|
||||
|
||||
/**
|
||||
* @extends {ItemSheet}
|
||||
*/
|
||||
export class SkillSheetL5r5e extends ItemSheetL5r5e {
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["l5r5e", "sheet", "skill"],
|
||||
template: CONFIG.l5r5e.paths.templates + "items/skill/skill-sheet.html",
|
||||
width: 520,
|
||||
height: 480,
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Object|Promise}
|
||||
*/
|
||||
async getData(options = {}) {
|
||||
const sheetData = await super.getData(options);
|
||||
|
||||
sheetData.data.SkillCategoriesList = CONFIG.l5r5e.skillCategories;
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ export class TechniqueSheetL5r5e extends ItemSheetL5r5e {
|
||||
// Sanitize Difficulty and Skill list
|
||||
sheetData.data.system.difficulty = TechniqueSheetL5r5e.formatDifficulty(sheetData.data.system.difficulty);
|
||||
sheetData.data.system.skill = TechniqueSheetL5r5e.translateSkillsList(
|
||||
TechniqueSheetL5r5e.formatSkillList(sheetData.data.system.skill.split(",")),
|
||||
await TechniqueSheetL5r5e.formatSkillList(sheetData.data.system.skill.split(",")),
|
||||
false
|
||||
).join(", ");
|
||||
|
||||
@@ -54,9 +54,9 @@ export class TechniqueSheetL5r5e extends ItemSheetL5r5e {
|
||||
|
||||
// Sanitize Difficulty and Skill list
|
||||
formData["system.difficulty"] = TechniqueSheetL5r5e.formatDifficulty(formData["system.difficulty"]);
|
||||
formData["system.skill"] = TechniqueSheetL5r5e.formatSkillList(
|
||||
formData["system.skill"] = (await TechniqueSheetL5r5e.formatSkillList(
|
||||
TechniqueSheetL5r5e.translateSkillsList(formData["system.skill"].split(","), true)
|
||||
).join(",");
|
||||
)).join(",");
|
||||
|
||||
return super._updateObject(event, formData);
|
||||
}
|
||||
@@ -143,13 +143,13 @@ export class TechniqueSheetL5r5e extends ItemSheetL5r5e {
|
||||
/**
|
||||
* Sanitize the technique skill list
|
||||
* @param {string[]} skillList
|
||||
* @return {string[]}
|
||||
* @returns {Promise<string|*[]>}
|
||||
*/
|
||||
static formatSkillList(skillList) {
|
||||
static async formatSkillList(skillList) {
|
||||
if (!skillList) {
|
||||
return "";
|
||||
}
|
||||
const categories = game.l5r5e.HelpersL5r5e.getCategoriesSkillsList();
|
||||
const categories = await game.l5r5e.HelpersL5r5e.getCategoriesSkillsList(this.actor);
|
||||
|
||||
// List categories
|
||||
const unqCatList = new Set();
|
||||
@@ -160,18 +160,6 @@ export class TechniqueSheetL5r5e extends ItemSheetL5r5e {
|
||||
}
|
||||
});
|
||||
|
||||
// List skill (not include in cat)
|
||||
const unqSkillList = new Set();
|
||||
skillList.forEach((s) => {
|
||||
s = s?.trim();
|
||||
if (!!s && CONFIG.l5r5e.skills.has(s)) {
|
||||
const cat = CONFIG.l5r5e.skills.get(s);
|
||||
if (!unqCatList.has(cat)) {
|
||||
unqSkillList.add(s);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return [...unqCatList, ...unqSkillList];
|
||||
return [...unqCatList];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ export class WeaponSheetL5r5e extends ItemSheetL5r5e {
|
||||
|
||||
async getData(options = {}) {
|
||||
const sheetData = await super.getData(options);
|
||||
const categories = await game.l5r5e.HelpersL5r5e.getCategoriesSkillsList(this.actor);
|
||||
console.log(categories);
|
||||
|
||||
// Martial skills only
|
||||
sheetData.data.skills = Array.from(CONFIG.l5r5e.skills)
|
||||
|
||||
@@ -23,6 +23,7 @@ import { CombatL5r5e } from "./combat.js";
|
||||
// Items
|
||||
import { ItemL5r5e } from "./item.js";
|
||||
import { ItemSheetL5r5e } from "./items/item-sheet.js";
|
||||
import { SkillSheetL5r5e } from "./items/skill-sheet.js";
|
||||
import { ArmorSheetL5r5e } from "./items/armor-sheet.js";
|
||||
import { WeaponSheetL5r5e } from "./items/weapon-sheet.js";
|
||||
import { TechniqueSheetL5r5e } from "./items/technique-sheet.js";
|
||||
@@ -43,6 +44,7 @@ import { MigrationL5r5e } from "./migration.js";
|
||||
import { GmToolbox } from "./gm/gm-toolbox.js";
|
||||
import { GmMonitor } from "./gm/gm-monitor.js";
|
||||
import { Storage } from "./storage.js";
|
||||
import { DefaultSkillsDialogL5r5e } from "./settings/default-skills-dialog.js";
|
||||
|
||||
/* ------------------------------------ */
|
||||
/* Initialize system */
|
||||
@@ -92,6 +94,7 @@ Hooks.once("init", async () => {
|
||||
GmToolbox,
|
||||
GmMonitor,
|
||||
HelpDialog,
|
||||
DefaultSkillsDialogL5r5e,
|
||||
storage: new Storage(),
|
||||
sockets: new SocketHandlerL5r5e(),
|
||||
migrations: MigrationL5r5e,
|
||||
@@ -132,6 +135,11 @@ Hooks.once("init", async () => {
|
||||
label: "TYPES.Item.item",
|
||||
makeDefault: true,
|
||||
});
|
||||
Items.registerSheet(L5R5E.namespace, SkillSheetL5r5e, {
|
||||
types: ["skill"],
|
||||
label: "ITEM.TypeSkill",
|
||||
makeDefault: true,
|
||||
});
|
||||
Items.registerSheet(L5R5E.namespace, ArmorSheetL5r5e, {
|
||||
types: ["armor"],
|
||||
label: "TYPES.Item.armor",
|
||||
|
||||
@@ -6,7 +6,7 @@ export class MigrationL5r5e {
|
||||
* Minimum Version needed for migration stuff to trigger
|
||||
* @type {string}
|
||||
*/
|
||||
static NEEDED_VERSION = "1.3.0";
|
||||
static NEEDED_VERSION = "2.0.0";
|
||||
|
||||
/**
|
||||
* Return true if the version need some updates
|
||||
@@ -28,6 +28,11 @@ export class MigrationL5r5e {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for translation to load
|
||||
if (!options.force && typeof Babele !== "undefined") {
|
||||
await new Promise((r) => setTimeout(r, 5000));
|
||||
}
|
||||
|
||||
// if (MigrationL5r5e.needUpdate("1.3.0")) {
|
||||
// ChatMessage.create({"content": "<strong>L5R5E v1.3.0 :</strong><br>"});
|
||||
// }
|
||||
@@ -42,7 +47,7 @@ export class MigrationL5r5e {
|
||||
// Migrate World Actors
|
||||
for (let actor of game.actors.contents) {
|
||||
try {
|
||||
const updateData = MigrationL5r5e._migrateActorData(actor, options);
|
||||
const updateData = await MigrationL5r5e._migrateActorData(actor, options);
|
||||
if (!foundry.utils.isEmpty(updateData)) {
|
||||
console.log(`L5R5E | Migration | Migrating Actor document ${actor.name}[${actor._id}]`);
|
||||
await actor.update(updateData);
|
||||
@@ -225,7 +230,7 @@ export class MigrationL5r5e {
|
||||
* @param options
|
||||
* @return {Object} The updateData to apply
|
||||
*/
|
||||
static _migrateActorData(actor, options = { force: false }) {
|
||||
static async _migrateActorData(actor, options = { force: false }) {
|
||||
const updateData = {};
|
||||
const system = actor.system;
|
||||
|
||||
@@ -243,7 +248,7 @@ export class MigrationL5r5e {
|
||||
}
|
||||
|
||||
// NPC are now without autostats, we need to save the value
|
||||
if (actor.type === "npc") {
|
||||
if (actor.isNpc) {
|
||||
if (system.endurance < 1) {
|
||||
updateData["system.endurance"] = (Number(system.rings.earth) + Number(system.rings.fire)) * 2;
|
||||
updateData["system.composure"] = (Number(system.rings.earth) + Number(system.rings.water)) * 2;
|
||||
@@ -264,7 +269,7 @@ export class MigrationL5r5e {
|
||||
}
|
||||
|
||||
// NPC have now more than a Strength and a Weakness
|
||||
if (actor.type === "npc" && system.rings_affinities?.strength) {
|
||||
if (actor.isNpc && system.rings_affinities?.strength) {
|
||||
const aff = system.rings_affinities;
|
||||
updateData["system.rings_affinities." + aff.strength.ring] = aff.strength.value;
|
||||
updateData["system.rings_affinities." + aff.weakness.ring] = aff.weakness.value;
|
||||
@@ -276,6 +281,29 @@ export class MigrationL5r5e {
|
||||
}
|
||||
// ***** End of 1.3.0 *****
|
||||
|
||||
// ***** Start of 2.0.0 *****
|
||||
if (options?.force || MigrationL5r5e.needUpdate("2.0.0")) {
|
||||
// Only PC : Convert fixed skills to items list
|
||||
if (actor.isCharacter && Array.from(actor.items).every(i => i.type !== "skill")) {
|
||||
// Add skills items
|
||||
const update = {items: [], name: actor.name};
|
||||
await game.l5r5e.ActorL5r5e.addSkillsFromDefaultList(update);
|
||||
|
||||
// Set actor value
|
||||
update.items.forEach(item => {
|
||||
const skillId = item.flags?.l5r5e?.skillCoreId;
|
||||
const skillCatId = CONFIG.l5r5e.skills.get(skillId);
|
||||
const skillValue = system.skills[skillCatId][skillId];
|
||||
if (skillCatId && skillValue > 0) {
|
||||
item.system.rank = skillValue;
|
||||
}
|
||||
});
|
||||
|
||||
updateData.items = update.items;
|
||||
}
|
||||
}
|
||||
// ***** End of 2.0.0 *****
|
||||
|
||||
return updateData;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ export const PreloadTemplates = async function () {
|
||||
`${tpl}actors/character/narrative.html`,
|
||||
`${tpl}actors/character/rings.html`,
|
||||
`${tpl}actors/character/effects.html`,
|
||||
`${tpl}actors/character/skill.html`,
|
||||
`${tpl}actors/character/social.html`,
|
||||
`${tpl}actors/character/stance.html`,
|
||||
`${tpl}actors/character/techniques.html`,
|
||||
@@ -59,6 +58,9 @@ export const PreloadTemplates = async function () {
|
||||
`${tpl}items/property/properties.html`,
|
||||
`${tpl}items/property/property-entry.html`,
|
||||
`${tpl}items/property/property-sheet.html`,
|
||||
`${tpl}items/skill/skill-entry.html`,
|
||||
`${tpl}items/skill/skill-sheet.html`,
|
||||
`${tpl}items/skill/skill-text.html`,
|
||||
`${tpl}items/signature-scroll/signature-scroll-entry.html`,
|
||||
`${tpl}items/signature-scroll/signature-scroll-sheet.html`,
|
||||
`${tpl}items/signature-scroll/signature-scroll-text.html`,
|
||||
|
||||
@@ -2,9 +2,27 @@
|
||||
* Custom system settings register
|
||||
*/
|
||||
export const RegisterSettings = function () {
|
||||
const isBabeleRegistered = (typeof Babele !== "undefined");
|
||||
|
||||
/* ------------------------------------ */
|
||||
/* User settings */
|
||||
/* ------------------------------------ */
|
||||
game.settings.registerMenu(CONFIG.l5r5e.namespace, "defaultSkillsListMenu", {
|
||||
name: "SETTINGS.DefaultSkillsList.Title",
|
||||
label: "SETTINGS.DefaultSkillsList.Label",
|
||||
hint: "SETTINGS.DefaultSkillsList.Hint",
|
||||
icon: "fas fa-bars",
|
||||
type: game.l5r5e.DefaultSkillsDialogL5r5e,
|
||||
restricted: true, // GameMaster only
|
||||
});
|
||||
game.settings.register(CONFIG.l5r5e.namespace, "defaultSkillsList", {
|
||||
name: "System Migration Version",
|
||||
scope: "world",
|
||||
config: false,
|
||||
type: Array,
|
||||
default: game.l5r5e.HelpersL5r5e.getDefaultSkillsUuidFromPack(),
|
||||
});
|
||||
|
||||
game.settings.register(CONFIG.l5r5e.namespace, "rnk-deleteOldMessage", {
|
||||
name: "SETTINGS.RollNKeep.DeleteOldMessage",
|
||||
hint: "SETTINGS.RollNKeep.DeleteOldMessageHint",
|
||||
@@ -36,6 +54,20 @@ export const RegisterSettings = function () {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
});
|
||||
game.settings.register(CONFIG.l5r5e.namespace, "custom-compendium-name", {
|
||||
name: "SETTINGS.CustomCompendiumName.Title",
|
||||
hint: "SETTINGS.CustomCompendiumName.Hint",
|
||||
scope: "world",
|
||||
config: isBabeleRegistered,
|
||||
requiresReload: true,
|
||||
type: String,
|
||||
default: "l5r5e-custom-compendiums",
|
||||
onChange: (name) => {
|
||||
if (!Babele.get().modules.find((module) => module.module === name)) {
|
||||
ui.notifications.warn(game.i18n.format("SETTINGS.CustomCompendiumName.Notification", { name }), { permanent: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* ------------------------------------ */
|
||||
/* Update */
|
||||
|
||||
148
system/scripts/settings/default-skills-dialog.js
Normal file
148
system/scripts/settings/default-skills-dialog.js
Normal file
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* L5R Settings dialog for default skills list
|
||||
* @extends {FormApplication}
|
||||
*/
|
||||
export class DefaultSkillsDialogL5r5e extends FormApplication {
|
||||
/**
|
||||
* Key for skills list in Settings
|
||||
* @type {string}
|
||||
*/
|
||||
static skillsLisKey = "defaultSkillsList";
|
||||
|
||||
/**
|
||||
* Assign the default options
|
||||
* @override
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
id: "l5r5e-settings-default-skills-dialog",
|
||||
classes: ["l5r5e", "settings", "default-skills"],
|
||||
template: CONFIG.l5r5e.paths.templates + "settings/default-skills-dialog.html",
|
||||
title: game.i18n.localize("SETTINGS.DefaultSkillsList.Label"),
|
||||
width: 500,
|
||||
height: 680,
|
||||
resizable: true,
|
||||
closeOnSubmit: false,
|
||||
submitOnClose: false,
|
||||
submitOnChange: false,
|
||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent non GM to render this windows
|
||||
* @override
|
||||
*/
|
||||
render(force = false, options = {}) {
|
||||
if (!this.isEditable) {
|
||||
console.log("L5R5E | You don't have the rights to display this application");
|
||||
return false;
|
||||
}
|
||||
return super.render(force, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the Form Application currently editable?
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isEditable() {
|
||||
return game.user.isGM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct and return the data object used to render the HTML template for this form application.
|
||||
* @param options
|
||||
* @return {Object}
|
||||
*/
|
||||
async getData(options = null) {
|
||||
// Transform skills uuids to items by categories
|
||||
let skillList = await game.l5r5e.HelpersL5r5e.getSkillsItemsList();
|
||||
skillList = game.l5r5e.HelpersL5r5e.splitSkillByCategory(skillList);
|
||||
|
||||
return {
|
||||
...(await super.getData(options)),
|
||||
skillList,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dropped data on the Actor sheet
|
||||
* @param {DragEvent} event
|
||||
*/
|
||||
async _onDrop(event) {
|
||||
// *** Everything below here is only needed if the sheet is editable ***
|
||||
if (!this.isEditable) {
|
||||
console.log("L5R5E | This sheet is not editable");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check item type and subtype
|
||||
const item = await game.l5r5e.HelpersL5r5e.getDragnDropTargetObject(event);
|
||||
if (!item || item.documentName !== "Item" || item?.type !== "skill") {
|
||||
console.log(`L5R5E | Item dropped must be a Skill Item : ${item?.type}`, item);
|
||||
return;
|
||||
}
|
||||
|
||||
// EmbedItem actor item ?
|
||||
if (item.uuid.startsWith('Actor.')) {
|
||||
console.log("L5R5E | This element has been ignored because it's a EmbedItem actor item", item.uuid);
|
||||
return;
|
||||
}
|
||||
|
||||
const skillListUuids = game.settings.get(CONFIG.l5r5e.namespace, DefaultSkillsDialogL5r5e.skillsLisKey) || [];
|
||||
|
||||
// Dropped an item with same "id" as one owned
|
||||
if (skillListUuids.some((embedItem) => embedItem.uuid === item.uuid)) {
|
||||
console.log("L5R5E | This element has been ignored because it already exists", item.uuid);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the uuid and save
|
||||
skillListUuids.push(item.uuid);
|
||||
await game.settings.set(CONFIG.l5r5e.namespace, DefaultSkillsDialogL5r5e.skillsLisKey, skillListUuids);
|
||||
|
||||
// Refresh
|
||||
this.render(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to events from the sheet.
|
||||
* @param {jQuery} html HTML content of the sheet.
|
||||
*/
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Commons
|
||||
game.l5r5e.HelpersL5r5e.commonListeners(html);
|
||||
|
||||
// *** Everything below here is only needed if the sheet is editable ***
|
||||
if (!this.isEditable) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete an item
|
||||
html.find(`.item-delete`).on("click", this._removeSkill.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item from it's uuid
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
async _removeSkill(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const itemUuid = $(event.currentTarget).data("item-uuid");
|
||||
if (!itemUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove and save
|
||||
const skillListUuids = game.settings.get(CONFIG.l5r5e.namespace, DefaultSkillsDialogL5r5e.skillsLisKey) || [];
|
||||
await game.settings.set(CONFIG.l5r5e.namespace, DefaultSkillsDialogL5r5e.skillsLisKey, skillListUuids.filter((uuid) => uuid !== itemUuid));
|
||||
|
||||
// Refresh
|
||||
this.render(false);
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -118,7 +118,7 @@
|
||||
|
||||
// Dice Picker
|
||||
.dice-picker-dialog {
|
||||
min-width: 600px;
|
||||
min-width: 35rem;
|
||||
min-height: auto;
|
||||
// Utility
|
||||
* {
|
||||
@@ -225,6 +225,7 @@
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: large;
|
||||
padding: 0;
|
||||
|
||||
&-ring {
|
||||
color: #f0f0e0;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
.item {
|
||||
.item-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.item-img {
|
||||
flex: 0 0 32px;
|
||||
padding-right: 0.25rem;
|
||||
@@ -110,6 +112,7 @@
|
||||
&.peculiarity,
|
||||
&.property,
|
||||
&.signature-scroll,
|
||||
&.skill,
|
||||
&.technique,
|
||||
&.title,
|
||||
&.weapon {
|
||||
@@ -356,6 +359,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
&.skill {
|
||||
article {
|
||||
&.attributes {
|
||||
height: 4rem;
|
||||
}
|
||||
&.infos {
|
||||
height: calc(100% - 5rem);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.weapon {
|
||||
article {
|
||||
&.attributes {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/** Sheets **/
|
||||
&.sheet {
|
||||
min-width: 600px;
|
||||
min-width: 37rem;
|
||||
|
||||
label {
|
||||
&:hover {
|
||||
text-shadow: 0 0 2px $red;
|
||||
}
|
||||
}
|
||||
|
||||
.l5r-buttons-bar {
|
||||
display: flex;
|
||||
flex: 0 0 100%;
|
||||
@@ -21,6 +23,7 @@
|
||||
margin: 0 0 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&.actor {
|
||||
.sheet-header {
|
||||
h1 {
|
||||
@@ -44,11 +47,13 @@
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.sheet-body {
|
||||
flex: 0 0 100%;
|
||||
align-items: flex-start;
|
||||
@@ -84,6 +89,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section,
|
||||
article {
|
||||
&.tab[data-tab] {
|
||||
@@ -93,6 +99,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sheet-header {
|
||||
flex: 0 0 100%;
|
||||
align-items: flex-start;
|
||||
@@ -575,6 +582,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
article {
|
||||
background: $l5r5e-white-light;
|
||||
padding: 0.5rem;
|
||||
@@ -740,6 +748,7 @@
|
||||
flex: 0 0 calc(50% - 0.5rem);
|
||||
}
|
||||
}
|
||||
|
||||
.xp,
|
||||
.money-wrapper {
|
||||
flex: 100%;
|
||||
@@ -758,6 +767,7 @@
|
||||
line-height: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
font-size: 0.85rem;
|
||||
color: $black-light;
|
||||
@@ -824,6 +834,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.inventory {
|
||||
.items-wrapper {
|
||||
h3 {
|
||||
@@ -918,6 +929,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nav {
|
||||
&.sheet-tabs {
|
||||
flex: 100%;
|
||||
|
||||
@@ -41,29 +41,63 @@
|
||||
);
|
||||
}
|
||||
ul {
|
||||
flex: 50%;
|
||||
padding: 0.25rem 0.5rem 0.25rem 0;
|
||||
flex: 100%;
|
||||
padding: 0 0.15rem;
|
||||
li {
|
||||
text-align: left;
|
||||
line-height: 2rem;
|
||||
margin: 0.25rem 0;
|
||||
&.skill {
|
||||
text-align: right;
|
||||
span {
|
||||
color: $l5r5e-black;
|
||||
&[data-skill="melee"],
|
||||
&[data-skill="ranged"],
|
||||
&[data-skill="unarmed"] {
|
||||
float: left;
|
||||
line-height: 1rem;
|
||||
width: calc(100% - 2rem);
|
||||
}
|
||||
}
|
||||
&.skill-category-skills-list {
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
object-fit: contain;
|
||||
object-position: 50% 0;
|
||||
border: none;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
input {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.item-header {
|
||||
flex: 4;
|
||||
align-items: center;
|
||||
|
||||
h4 {
|
||||
margin: 0;
|
||||
}
|
||||
.item-img {
|
||||
height: 32px;
|
||||
margin: 0;
|
||||
flex: 0 0 32px;
|
||||
}
|
||||
.item-rank {
|
||||
flex: 0 0 32px;
|
||||
text-align: center;
|
||||
}
|
||||
.item-edit,
|
||||
.item-delete {
|
||||
text-align: center;
|
||||
line-height: 1rem;
|
||||
font-size: 0.75rem;
|
||||
flex: 0 0 1rem;
|
||||
padding: 0 0.1rem;
|
||||
color: $black-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.skill-category-ring-actions {
|
||||
padding: 0.25rem 0 0.25rem 0.5rem;
|
||||
border-top: 1px dashed $l5r5e-title;
|
||||
border-left: 1px solid $l5r5e-title;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-content: center;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
}
|
||||
input {
|
||||
|
||||
@@ -32,8 +32,7 @@ button {
|
||||
overflow: initial;
|
||||
height: calc(100% - 1.1rem);
|
||||
top: 0.2rem;
|
||||
width: 320px;
|
||||
min-width: 40px;
|
||||
min-width: 20rem;
|
||||
letter-spacing: 0.1rem;
|
||||
position: relative;
|
||||
margin-right: 0.5rem;
|
||||
@@ -172,6 +171,9 @@ button {
|
||||
}
|
||||
}
|
||||
&.collapsed {
|
||||
min-width: 0;
|
||||
width: 3rem !important;
|
||||
|
||||
#sidebar-tabs {
|
||||
> .item {
|
||||
&.active {
|
||||
@@ -931,6 +933,41 @@ button {
|
||||
}
|
||||
}
|
||||
|
||||
#l5r5e-settings-default-skills-dialog {
|
||||
.item-header {
|
||||
align-items: center;
|
||||
|
||||
.item-img {
|
||||
flex: 0 0 32px;
|
||||
padding-right: 0.25rem;
|
||||
|
||||
img {
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.item-name {
|
||||
flex: 1;
|
||||
font-size: 1rem;
|
||||
line-height: 1rem;
|
||||
color: $l5r5e-bold;
|
||||
}
|
||||
|
||||
.item-source {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item-delete {
|
||||
text-align: center;
|
||||
line-height: 1rem;
|
||||
font-size: 0.75rem;
|
||||
flex: 0 0 1rem;
|
||||
padding: 0 0.1rem;
|
||||
color: $black-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.autocomplete-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
"changelog": "https://gitlab.com/teaml5r/l5r5e/-/blob/master/CHANGELOG.md",
|
||||
"license": "https://gitlab.com/teaml5r/l5r5e/-/blob/master/LICENSE.md",
|
||||
"manifest": "https://gitlab.com/teaml5r/l5r5e/-/raw/master/system/system.json",
|
||||
"download": "https://gitlab.com/teaml5r/l5r5e/-/jobs/artifacts/v1.10.0/raw/l5r5e.zip?job=build",
|
||||
"version": "1.10.0",
|
||||
"download": "https://gitlab.com/teaml5r/l5r5e/-/jobs/artifacts/v2.0.0/raw/l5r5e.zip?job=build",
|
||||
"version": "2.0.0",
|
||||
"compatibility": {
|
||||
"minimum": 11,
|
||||
"verified": "11.301"
|
||||
"verified": "11"
|
||||
},
|
||||
"manifestPlusVersion": "1.2.0",
|
||||
"socket": true,
|
||||
@@ -50,6 +50,7 @@
|
||||
"color": "#019806",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"core-skills",
|
||||
"core-peculiarities-distinctions",
|
||||
"core-peculiarities-passions",
|
||||
"core-peculiarities-adversities",
|
||||
@@ -115,6 +116,13 @@
|
||||
}
|
||||
],
|
||||
"packs": [
|
||||
{
|
||||
"name": "core-skills",
|
||||
"label": "Skills",
|
||||
"path": "packs/core-skills.db",
|
||||
"type": "Item",
|
||||
"system": "l5r5e"
|
||||
},
|
||||
{
|
||||
"name": "core-properties",
|
||||
"label": "Properties",
|
||||
|
||||
@@ -194,7 +194,8 @@
|
||||
"signature_scroll",
|
||||
"item_pattern",
|
||||
"army_cohort",
|
||||
"army_fortification"
|
||||
"army_fortification",
|
||||
"skill"
|
||||
],
|
||||
"templates": {
|
||||
"basics": {
|
||||
@@ -220,6 +221,12 @@
|
||||
"properties": []
|
||||
}
|
||||
},
|
||||
"skill": {
|
||||
"templates": ["basics"],
|
||||
"category": "artisan",
|
||||
"rank": 0,
|
||||
"modifier": 0
|
||||
},
|
||||
"item": {
|
||||
"templates": ["basics", "item"]
|
||||
},
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
{{!-- items list --}}
|
||||
<h2>{{localize 'l5r5e.sheets.equipment'}}</h2>
|
||||
<ul>
|
||||
<li>{{localize 'l5r5e.money.title'}} : {{data.system.money.koku}} {{localize 'l5r5e.money.koku'}} / {{data.system.money.bu}} {{localize 'l5r5e.money.bu'}} / {{data.system.money.zeni}} {{localize 'l5r5e.money.zeni'}}</li>
|
||||
<li>{{localize 'l5r5e.money.title'}} : {{data.money.koku}} {{localize 'l5r5e.money.koku'}} / {{data.money.bu}} {{localize 'l5r5e.money.bu'}} / {{data.money.zeni}} {{localize 'l5r5e.money.zeni'}}</li>
|
||||
{{#each data.splitItemsList as |cat type|}}
|
||||
<li>
|
||||
<strong>{{localize (localize 'l5r5e.{type}s.title' type=type)}} ({{cat.length}})</strong>
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
{{!-- Skills Tab --}}
|
||||
<article class="tab skills" data-group="primary" data-tab="skills">
|
||||
<ul class="skills-wrapper">
|
||||
{{#each data.system.skills as |category id|}} {{>
|
||||
'systems/l5r5e/templates/actors/character/category.html' category=category categoryId=id data=../data}}
|
||||
{{#each data.skillCategories as |itemsInCategory id|}}
|
||||
{{> 'systems/l5r5e/templates/actors/character/category.html' itemsInCategory=itemsInCategory categoryId=id data=../data}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{> 'systems/l5r5e/templates/actors/character/techniques.html'}}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<li class="skill-category-wrapper skill-category-content">
|
||||
<h4 class="section-header toggle-on-click" data-toggle="toggle-skill-category-{{categoryId}}">{{localizeSkill categoryId 'title'}}</h4>
|
||||
<ul class="skill-category-skills-list toggle-skill-category-{{categoryId}} {{#ifCond data.storeInfos 'includes' (concat 'toggle-skill-category-' categoryId)}}toggle-hidden{{/ifCond}}">
|
||||
{{#each category as |skill id|}}
|
||||
{{> 'systems/l5r5e/templates/actors/character/skill.html' categoryId=../categoryId skill=skill skillId=id data=../data}}
|
||||
{{#each itemsInCategory as |skill|}}
|
||||
{{> 'systems/l5r5e/templates/items/skill/skill-entry.html' skill=skill data=../data}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
<ul class="skill-category-ring-actions toggle-skill-category-{{categoryId}} {{#ifCond data.storeInfos 'includes' (concat 'toggle-skill-category-' categoryId)}}toggle-hidden{{/ifCond}}">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<legend class="section-header">{{localize 'l5r5e.money.title'}}</legend>
|
||||
<label>
|
||||
{{localize 'l5r5e.money.koku'}}
|
||||
<input name="system.money.koku" type="number" value="{{data.system.money.koku}}" data-dtype="Number" min="0" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
<input name="money.koku" type="number" value="{{data.money.koku}}" data-dtype="Number" min="0" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
<span class="money-buttons">
|
||||
<i class="money-control pointer-choice fa fa-plus-square" data-type="koku" data-value="1"></i>
|
||||
<i class="money-control pointer-choice fa fa-minus-square" data-type="koku" data-value="-1"></i>
|
||||
@@ -10,7 +10,7 @@
|
||||
</label>
|
||||
<label>
|
||||
{{localize 'l5r5e.money.bu'}}
|
||||
<input name="system.money.bu" type="number" value="{{data.system.money.bu}}" data-dtype="Number" min="0" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
<input name="money.bu" type="number" value="{{data.money.bu}}" data-dtype="Number" min="0" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
<span class="money-buttons">
|
||||
<i class="money-control pointer-choice fa fa-plus-square" data-type="bu" data-value="1"></i>
|
||||
<i class="money-control pointer-choice fa fa-minus-square" data-type="bu" data-value="-1"></i>
|
||||
@@ -18,7 +18,7 @@
|
||||
</label>
|
||||
<label>
|
||||
{{localize 'l5r5e.money.zeni'}}
|
||||
<input name="system.money.zeni" type="number" value="{{data.system.money.zeni}}" data-dtype="Number" min="0" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
<input name="money.zeni" type="number" value="{{data.money.zeni}}" data-dtype="Number" min="0" placeholder="0" {{^if data.editable_not_soft_locked}}disabled{{/if}}/>
|
||||
<span class="money-buttons">
|
||||
<i class="money-control pointer-choice fa fa-plus-square" data-type="zeni" data-value="1"></i>
|
||||
<i class="money-control pointer-choice fa fa-minus-square" data-type="zeni" data-value="-1"></i>
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<li class="skill skill-wrapper">
|
||||
<label class="skill-content">
|
||||
<span class="dice-picker attribute-label rollable" data-skill="{{skillId}}">{{localizeSkill categoryId skillId}}</span>
|
||||
<input
|
||||
class="centered-input select-on-focus"
|
||||
type="number"
|
||||
name="system.skills.{{categoryId}}.{{skillId}}"
|
||||
value="{{skill}}"
|
||||
data-dtype="Number"
|
||||
min="0"
|
||||
max="9"
|
||||
placeholder="0"
|
||||
{{^if data.editable_not_soft_locked}}disabled{{/if}}
|
||||
/>
|
||||
</label>
|
||||
</li>
|
||||
@@ -258,7 +258,7 @@
|
||||
{{localize 'l5r5e.twenty_questions.part2.school_ability'}}
|
||||
{{> 'systems/l5r5e/templates/actors/character/twenty-questions-item.html' itemsList=cache.step3.school_ability stepName='step3.school_ability' itemType='techniques' hideDndAt=1}}
|
||||
{{localize 'l5r5e.twenty_questions.part2.starting_techniques'}}
|
||||
{{> 'systems/l5r5e/templates/actors/character/twenty-questions-item.html' itemsList=cache.step3.techniques stepName='step3.techniques' itemType='techniques' hideDndAt=5}}
|
||||
{{> 'systems/l5r5e/templates/actors/character/twenty-questions-item.html' itemsList=cache.step3.techniques stepName='step3.techniques' itemType='techniques' hideDndAt=6}}
|
||||
</td>
|
||||
<td class="fifty">
|
||||
{{localize 'l5r5e.twenty_questions.part2.outfit'}}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{{#each data.skillsList as |skills catId|}}
|
||||
<optgroup label="{{localizeSkill catId 'title'}}">
|
||||
{{#each skills as |obj|}}
|
||||
<option value="{{obj.id}}">{{obj.label}}</option>
|
||||
<option value="{{obj.uuid}}">{{obj.name}}</option>
|
||||
{{/each}}
|
||||
</optgroup>
|
||||
{{/each}}
|
||||
|
||||
26
system/templates/items/skill/skill-entry.html
Normal file
26
system/templates/items/skill/skill-entry.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<li class="item skill flexcol" data-item-id="{{skill.id}}">
|
||||
<ul class="item-header skill-controls flexrow">
|
||||
<li class="item-img"><img src="{{skill.img}}" title="{{skill.name}}" width="32px" height="32px"/></li>
|
||||
<li class="item-name dice-picker attribute-label rollable l5r5e-tooltip" data-item-id="{{skill._id}}" data-skill="{{skill._id}}">{{skill.name}}</li>
|
||||
<li class="item-rank">
|
||||
{{#if data.editable_not_soft_locked}}
|
||||
<input
|
||||
class="centered-input select-on-focus"
|
||||
type="number"
|
||||
name="skillsValues.{{skill._id}}"
|
||||
value="{{skill.system.rank}}"
|
||||
data-dtype="Number"
|
||||
min="0"
|
||||
max="9"
|
||||
placeholder="0"
|
||||
/>
|
||||
{{else}}
|
||||
{{sum skill.system.rank skill.system.modifier}}
|
||||
{{/if}}
|
||||
</li>
|
||||
{{#if data.editable_not_soft_locked}}
|
||||
<li data-item-id="{{skill._id}}" class="item-control item-edit" title="{{localize 'l5r5e.global.edit'}}"><i class="fas fa-edit"></i></li>
|
||||
<li data-item-id="{{skill._id}}" class="item-control item-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</li>
|
||||
27
system/templates/items/skill/skill-sheet.html
Normal file
27
system/templates/items/skill/skill-sheet.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<form class="{{cssClass}}" autocomplete="off">
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
|
||||
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
|
||||
</header>
|
||||
{{!-- Sheet Body --}}
|
||||
<section class="sheet-body">
|
||||
{{!-- Attributes Tab --}}
|
||||
<article class="attributes" data-group="primary" data-tab="attributes">
|
||||
<label class="attribute">
|
||||
{{localize 'l5r5e.skills.category'}}
|
||||
<select name="system.category">
|
||||
{{#select data.system.category}}
|
||||
{{#each data.SkillCategoriesList as |id|}}
|
||||
<option value="{{id}}">{{localizeSkill id 'title'}}</option>
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</label>
|
||||
<label class="attribute">
|
||||
{{localize 'l5r5e.sheets.rank'}}
|
||||
<input class="select-on-focus" type="number" name="system.rank" value="{{data.system.rank}}" data-dtype="Number" min="0" placeholder="0"/>
|
||||
</label>
|
||||
</article>
|
||||
{{> 'systems/l5r5e/templates/items/item/item-infos.html'}}
|
||||
</section>
|
||||
</form>
|
||||
18
system/templates/items/skill/skill-text.html
Normal file
18
system/templates/items/skill/skill-text.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<div class="{{cssClass}}" data-actor-id="{{actor._id}}" data-item-id="{{data._id}}">
|
||||
<header class="card-header">
|
||||
<h2 class="item-name"><img src="{{data.img}}" title="{{data.name}}" /> {{data.name}}</h2>
|
||||
</header>
|
||||
<section class="sheet-body">
|
||||
<ul>
|
||||
<li>
|
||||
<strong>{{localize 'l5r5e.skills.category'}}</strong> : {{localizeSkill data.system.category 'title'}}
|
||||
</li>
|
||||
<li>
|
||||
<strong>{{localize 'l5r5e.sheets.rank'}}</strong> : {{data.system.rank}}{{#if data.system.modifier}} ({{data.system.modifier}}){{/if}}
|
||||
</li>
|
||||
</ul>
|
||||
{{!--item-infos--}}
|
||||
<p><strong>{{localize 'l5r5e.sheets.description'}}</strong> : {{{data.enrichedHtml.description}}}</p>
|
||||
<p><strong>{{localize 'l5r5e.sheets.book_reference'}}</strong> : {{data.system.book_reference}}</p>
|
||||
</section>
|
||||
</div>
|
||||
19
system/templates/settings/default-skills-dialog.html
Normal file
19
system/templates/settings/default-skills-dialog.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<form autocomplete="off">
|
||||
{{#each skillList as |category name|}}
|
||||
<h2>{{localizeSkill name 'title'}}</h2>
|
||||
<div class="form-group">
|
||||
<ul>
|
||||
{{#each category as |skill|}}
|
||||
<li class="item skill flexcol">
|
||||
<ul class="item-header skill-controls flexrow">
|
||||
<li class="item-img"><img src="{{skill.img}}" title="{{skill.name}}" width="32px" height="32px"/></li>
|
||||
<li class="item-name attribute-label l5r5e-tooltip" data-item-uuid="{{skill.uuid}}">{{skill.name}}</li>
|
||||
<li class="item-source">{{#if skill.pack}}{{skill.pack}}{{else}}world{{/if}}</li>
|
||||
<li data-item-uuid="{{skill.uuid}}" class="item-control item-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
|
||||
</ul>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/each}}
|
||||
</form>
|
||||
Reference in New Issue
Block a user