Compare commits
16 Commits
v1.12.0
...
dev_skills
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87fd300a22 | ||
|
|
fe2aa5dd25 | ||
|
|
6f7b00328e | ||
|
|
67b7601fa1 | ||
|
|
87096ab286 | ||
|
|
273531f522 | ||
|
|
c1bf9644f8 | ||
|
|
1b68d33bd2 | ||
|
|
a24e775001 | ||
|
|
823b883d4e | ||
|
|
12c8a70f60 | ||
|
|
1d42d2970d | ||
|
|
0b3816587b | ||
|
|
710afd9804 | ||
|
|
1ec9e65ca5 | ||
|
|
5fbb34d882 |
@@ -1,6 +1,10 @@
|
||||
# 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`).
|
||||
|
||||
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -22,6 +22,11 @@
|
||||
"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": {
|
||||
@@ -31,6 +36,7 @@
|
||||
"army": "Army"
|
||||
},
|
||||
"Item": {
|
||||
"skill": "Skill",
|
||||
"item": "Item",
|
||||
"armor": "Armor",
|
||||
"weapon": "Weapon",
|
||||
@@ -285,6 +291,7 @@
|
||||
"skills": {
|
||||
"title": "Skills",
|
||||
"label": "Skill",
|
||||
"category": "Category",
|
||||
"artisan": {
|
||||
"title": "Artisan",
|
||||
"aesthetics": "Aesthetics",
|
||||
|
||||
@@ -285,6 +285,7 @@
|
||||
"skills": {
|
||||
"title": "Habilidades",
|
||||
"label": "Habilidad",
|
||||
"category": "Categoría",
|
||||
"artisan": {
|
||||
"title": "Artesanales",
|
||||
"aesthetics": "Estética",
|
||||
|
||||
@@ -22,6 +22,11 @@
|
||||
"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": {
|
||||
@@ -31,6 +36,7 @@
|
||||
"army": "Armée"
|
||||
},
|
||||
"Item": {
|
||||
"skill": "Compétence",
|
||||
"item": "Objet",
|
||||
"armor": "Armure",
|
||||
"weapon": "Arme",
|
||||
@@ -285,6 +291,7 @@
|
||||
"skills": {
|
||||
"title": "Compétences",
|
||||
"label": "Compétence",
|
||||
"category": "Catégorie",
|
||||
"artisan": {
|
||||
"title": "Artisanales",
|
||||
"aesthetics": "Esthétique",
|
||||
|
||||
@@ -285,6 +285,7 @@
|
||||
"skills": {
|
||||
"title": "Abilità",
|
||||
"label": "Abilità",
|
||||
"category": "Categoria",
|
||||
"artisan": {
|
||||
"title": "Artigiane",
|
||||
"aesthetics": "Estetica",
|
||||
|
||||
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":[]}
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`,
|
||||
|
||||
@@ -7,6 +7,22 @@ export const RegisterSettings = function () {
|
||||
/* ------------------------------------ */
|
||||
/* 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",
|
||||
|
||||
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
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -933,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,8 +7,8 @@
|
||||
"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.11.0/raw/l5r5e.zip?job=build",
|
||||
"version": "1.11.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"
|
||||
@@ -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>
|
||||
@@ -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