From 12e6412a9ff5f12e987adaecc91b91458e047270 Mon Sep 17 00:00:00 2001 From: Byroks Date: Sat, 23 Mar 2024 19:17:54 +0100 Subject: [PATCH 1/3] #70-classes-as-items (#92) Co-authored-by: LeFrique Reviewed-on: https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/pulls/92 --- lang/de.json | 27 ++- source/module/actors/M5Character.ts | 47 ++--- source/module/items/M5Item.ts | 17 +- source/module/sheets/M5CharacterSheet.ts | 8 + source/module/sheets/M5ItemSheet.ts | 7 + source/style/Character-sheet.less | 23 +++ source/style/item-sheet.less | 9 +- source/template.json | 204 ++++++++++++++++++--- templates/sheets/character/base_values.hbs | 2 +- templates/sheets/character/main.hbs | 21 ++- templates/sheets/item/class.hbs | 109 +++++++++++ 11 files changed, 399 insertions(+), 75 deletions(-) create mode 100644 templates/sheets/item/class.hbs diff --git a/lang/de.json b/lang/de.json index efd3e95..4ed4493 100644 --- a/lang/de.json +++ b/lang/de.json @@ -278,29 +278,36 @@ "midgard5.damage": "Schaden", "midgard5.spell-process-none": "Ohne", + "midgard5.spell-process-artefakte": "Artefakte", "midgard5.spell-process-beherrschen": "Beherrschen", "midgard5.spell-process-bewegen": "Bewegen", - "midgard5.spell-process-blutzauber": "Blutmagie", + "midgard5.spell-process-beschwoeren": "Beschwören", + "midgard5.spell-process-blutmagie": "Blutmagie", "midgard5.spell-process-chaoswunder": "Chaoswunder", + "midgard5.spell-process-dweomer": "Dweomer", "midgard5.spell-process-erkennen": "Erkennen", "midgard5.spell-process-erschaffen": "Erschaffen", + "midgard5.spell-process-erhaltung": "Erhaltung", "midgard5.spell-process-formen": "Formen", "midgard5.spell-process-finstere_magie": "Finstere Magie", - "midgard5.spell-process-veraendern": "Verändern", - "midgard5.spell-process-zerstoeren": "Zerstören", - "midgard5.spell-process-wundertat": "Wundertat", - "midgard5.spell-process-dweomer": "Dweomer", - "midgard5.spell-process-wilder_Dweomer": "Wilder Dweomer", - "midgard5.spell-process-zauberlied": "Zauberlied", - "midgard5.spell-process-salz": "Salz", - "midgard5.spell-process-thaumagraphie": "Thaumagraphie", - "midgard5.spell-process-beschwoeren": "Beschwören", + "midgard5.spell-process-kampfverse": "Kampfverse", + "midgard5.spell-process-namensmagie": "Namensmagie", "midgard5.spell-process-nekromantie": "Nekromantie", + "midgard5.spell-process-runenstaebe": "Runenstäbe", "midgard5.spell-process-thaumatherapie": "Thaumatherapie", + "midgard5.spell-process-veraendern": "Verändern", + "midgard5.spell-process-vigilsignien": "Vigilsignien", + "midgard5.spell-process-wundertat": "Wundertat", + "midgard5.spell-process-wilder_Dweomer": "Wilder Dweomer", + "midgard5.spell-process-zerstoeren": "Zerstören", + "midgard5.spell-process-zauberlied": "Zauberlieder", + "midgard5.spell-process-zaubersalz": "Zaubersalze", "midgard5.spell-process-zaubermittel": "Zaubermittel", "midgard5.spell-process-zauberschutz": "Zauberschutz", "midgard5.spell-process-zauberrunen": "Zauberrunen", "midgard5.spell-process-zaubersiegel": "Zaubersiegel", + "midgard5.spell-process-zaubertaenze": "Zaubertänze", + "midgard5.spell-process-zauberblaetter": "Zauberblätter", "midgard5.spell-type-gedanke": "Gedanke", "midgard5.spell-type-geste": "Geste", diff --git a/source/module/actors/M5Character.ts b/source/module/actors/M5Character.ts index 0f07a15..8c6e8bb 100644 --- a/source/module/actors/M5Character.ts +++ b/source/module/actors/M5Character.ts @@ -1,18 +1,5 @@ import { M5Item } from "../items/M5Item"; -import { - M5Attribute, - M5CharacterCalculatedData, - M5ItemMod, - M5ItemType, - M5ModOperation, - M5ModResult, - M5ModType, - M5RollData, - M5Skill, - M5SkillCalculated, - M5SkillLearned, - M5SkillType, -} from "../M5Base"; +import { M5Attribute, M5CharacterCalculatedData, M5ItemMod, M5ItemType, M5ModOperation, M5ModResult, M5RollData, M5Skill, M5SkillCalculated } from "../M5Base"; import M5ModAggregate from "./M5ModAggregate"; export class M5Character extends Actor { // constructor( @@ -94,6 +81,7 @@ export class M5Character extends Actor { containers?: boolean; kampfkuenste?: boolean; encumbrance?: boolean; + class?: boolean; } = {} ): M5CharacterCalculatedData { let ret: M5CharacterCalculatedData = { @@ -194,12 +182,8 @@ export class M5Character extends Actor { ret.stats.attackBonus = this.modResult(ret.attributes.gs.bonus); ret.stats.defenseBonus = this.modResult(ret.attributes.gw.bonus); ret.stats.movement = this.modResult(data.movement); - ret.stats.resistanceMind = this.modResult( - (data.info.magicUsing ? 2 : 0) + ret.stats.defense.value + (data.info.race === "Mensch" ? ret.attributes.in.bonus : this.raceBonus(data.info.race)) - ); - ret.stats.resistanceBody = this.modResult( - (data.info.magicUsing ? 2 : 1) + ret.stats.defense.value + (data.info.race === "Mensch" ? ret.attributes.ko.bonus : this.raceBonus(data.info.race)) - ); + ret.stats.resistanceMind = this.modResult(ret.stats.defense.value + (data.info.race === "Mensch" ? ret.attributes.in.bonus : this.raceBonus(data.info.race))); + ret.stats.resistanceBody = this.modResult(ret.stats.defense.value + (data.info.race === "Mensch" ? ret.attributes.ko.bonus : this.raceBonus(data.info.race))); ret.stats.spellCasting = this.modResult((data.info.magicUsing ? M5Character.spellCastingFromLevel(ret.level) : 3) + ret.attributes.zt.bonus); ret.stats.brawl = this.modResult(Math.floor((ret.attributes.st.value + ret.attributes.gw.value) / 20)); ret.stats.brawlFw = ret.stats.brawl.value + ret.stats.attackBonus.value + (data.info.race === "Zwerg" ? 1 : 0); @@ -223,7 +207,7 @@ export class M5Character extends Actor { const aggregate = new M5ModAggregate(data, ret); context.items - ?.filter((item) => (item.type === "item" || item.type === "effect" || item.type === "armor" || item.type === "container") && item.system.equipped) + ?.filter((item) => (item.type === "item" || item.type === "effect" || item.type === "armor" || item.type === "container" || item.type === "class") && item.system.equipped) .forEach((item) => { const mods = item.system.mods; //console.log("Actor item mods", mods) @@ -499,6 +483,25 @@ export class M5Character extends Actor { //} } + if (!skip?.class) { + context.items + ?.filter((item) => item.type === "class") + .sort((a, b) => b?.system.magicUsing - a?.system.magicUsing) + .forEach((item, index) => { + if (index !== 0) { + item.system.equipped = false; + } else { + item.system.equipped = true; + data.info.magicUsing = item.system.magicUsing; + } + + if (typeof data.info.class === "string") { + data.info.class = {}; + } + data.info.class[item.id] = item.name; + }); + } + if (!skip?.effects) { context.items ?.filter((item) => item.type === "effect") @@ -565,7 +568,7 @@ export class M5Character extends Actor { type: item.system.type, castDuration: item.system.castDuration || 0, ap: item.system.ap || 0, - range: item.system.range|| 0, + range: item.system.range || 0, effectTarget: item.system.effectTarget, effectArea: item.system.effectArea, effectDuration: item.system.effectDuration || 0, diff --git a/source/module/items/M5Item.ts b/source/module/items/M5Item.ts index 85c6e9b..c4eb60c 100644 --- a/source/module/items/M5Item.ts +++ b/source/module/items/M5Item.ts @@ -18,7 +18,7 @@ export class M5Item extends Item { calc.containers = null; if (actor) { - const actorCalc = actor.derivedData({ containers: false, items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true }); + const actorCalc = actor.derivedData({ containers: false, items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true, class: true }); if (actorCalc) { calc.containers = actorCalc.gear.containers; } @@ -47,12 +47,14 @@ export class M5Item extends Item { if (character) { const actorCalc = character.derivedData({ + containers: true, skills: true, items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true, + class: true, }); if (actorCalc?.skillMods && Object.keys(actorCalc.skillMods).indexOf(itemId) !== -1) { pairs = pairs.concat(actorCalc.skillMods[itemId]); @@ -89,7 +91,7 @@ export class M5Item extends Item { calc.containers = null; if (actor) { - const actorCalc = character.derivedData({ items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true }); + const actorCalc = character.derivedData({ items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true, class: true }); if (actorCalc) { calc.ew += actorCalc.stats.attackBonus.value; calc.combatSkills = actorCalc.skills.combat; @@ -124,7 +126,7 @@ export class M5Item extends Item { calc.containers = null; if (actor) { - const actorCalc = character.derivedData({ items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true }); + const actorCalc = character.derivedData({ items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true, class: true }); if (actorCalc) { calc.ew += actorCalc.stats.defense.value + actorCalc.stats.defenseBonus.value; calc.combatSkills = actorCalc.skills.combat; @@ -157,7 +159,7 @@ export class M5Item extends Item { itemData.mods[5] = { type: "stat", id: "apProtection", operation: "set", value: itemData.apProtection }; calc.containers = null; if (actor) { - const actorCalc = actor.derivedData({ items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true }); + const actorCalc = actor.derivedData({ items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true, class: true }); if (actorCalc) { calc.containers = actorCalc.gear.containers; } @@ -171,7 +173,7 @@ export class M5Item extends Item { } else if (itemType === "spell") { calc.fw = 0; if (actor) { - const actorCalc = character.derivedData({ items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true }); + const actorCalc = character.derivedData({ containers: true, items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true, class: true }); if (actorCalc) { calc.ew = actorCalc.stats.spellCasting.value; } @@ -183,7 +185,7 @@ export class M5Item extends Item { calc.generalSkills = null; if (actor) { - const actorCalc = character.derivedData({ items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true }); + const actorCalc = character.derivedData({ containers: true, items: true, spells: true, effects: true, kampfkuenste: true, encumbrance: true, class: true }); if (actorCalc) { calc.generalSkills = actorCalc.skills.general; } @@ -197,6 +199,9 @@ export class M5Item extends Item { itemData.rolls.formulas[0].label = skill.name; } } + } else if (itemType === "class") { + itemData.mods[0] = { type: "stat", id: "resistanceBody", operation: "add", value: itemData.resistanceBody }; + itemData.mods[1] = { type: "stat", id: "resistanceMind", operation: "add", value: itemData.resistanceMind }; } if (itemData?.mods) { calc.mods = {}; diff --git a/source/module/sheets/M5CharacterSheet.ts b/source/module/sheets/M5CharacterSheet.ts index 454a7ab..7cbc2ff 100644 --- a/source/module/sheets/M5CharacterSheet.ts +++ b/source/module/sheets/M5CharacterSheet.ts @@ -433,6 +433,14 @@ export default class M5CharacterSheet extends ActorSheet { } }); + html.find(".class-item-edit").on("click", async (event) => { + this.actor.items.find((x) => x.type === "class").sheet.render(true); + }); + + html.find(".class-item-delete").on("click", async (event) => { + this.actor.items.find((x) => x.type === "class").delete(); + }); + // Drag & Drop const dragDrop = new DragDrop({ dragSelector: ".items-list .item", diff --git a/source/module/sheets/M5ItemSheet.ts b/source/module/sheets/M5ItemSheet.ts index 1274a50..1403e2b 100644 --- a/source/module/sheets/M5ItemSheet.ts +++ b/source/module/sheets/M5ItemSheet.ts @@ -7,6 +7,13 @@ export class M5ItemSheet extends ItemSheet { width: 640, height: 480, classes: ["midgard5", "sheet", "item"], + tabs: [ + { + navSelector: ".sheet-navigation", + contentSelector: ".sheet-content", + initial: "base_values", + }, + ], }); } diff --git a/source/style/Character-sheet.less b/source/style/Character-sheet.less index 68c3dcc..898b404 100644 --- a/source/style/Character-sheet.less +++ b/source/style/Character-sheet.less @@ -365,4 +365,27 @@ } } } + + .chip { + display: inline-block; + padding: 0 25px; + height: 35px; + font-size: 16px; + line-height: 35px; + border-radius: 25px; + background-color: #f1f1f1; + } + + .closebtn { + padding-left: 10px; + color: #888; + font-weight: bold; + float: right; + font-size: 20px; + cursor: pointer; + } + + .closebtn:hover { + color: #000; + } } diff --git a/source/style/item-sheet.less b/source/style/item-sheet.less index 57133d6..fc1faf6 100644 --- a/source/style/item-sheet.less +++ b/source/style/item-sheet.less @@ -1,6 +1,6 @@ // main: midgard5.less -.midgard5.sheet.item { +.midgard5.sheet.item { form { display: flex; flex-direction: column; @@ -15,10 +15,11 @@ } .item-img { height: 64px; - width: 64px; + width: 64px; } - td, th { + td, + th { padding: 0 0.5rem 0 0.5rem; &.center { @@ -40,7 +41,7 @@ .col-create { width: 3rem; text-align: center; - + button { background: rgba(255, 255, 255, 0.5); } diff --git a/source/template.json b/source/template.json index ddf875d..23483b4 100644 --- a/source/template.json +++ b/source/template.json @@ -6,7 +6,7 @@ "info": { "description": "", "background": "", - "class": "", + "class": {}, "race": "", "magicUsing": false, "showAllItems": false, @@ -140,12 +140,11 @@ "wahrsagen": { "fw": 0, "attribute": "zt", "initial": 8, "pp": 0 }, "wasserkampf": { "fw": 0, "attribute": "gw", "initial": 8, "pp": 0 }, "zauberkunde": { "fw": 0, "attribute": "in", "initial": 8, "pp": 0 } - } + } } }, "gear": { - "gear": { - } + "gear": {} } }, "character": { @@ -154,7 +153,7 @@ } }, "Item": { - "types": ["skill", "weapon", "defensiveWeapon", "armor", "spell", "kampfkunst", "item", "effect", "container"], + "types": ["skill", "weapon", "defensiveWeapon", "armor", "spell", "kampfkunst", "item", "effect", "container", "class"], "templates": { "itemDescription": { "description": "" @@ -207,11 +206,11 @@ "equipped": false }, "valuable": { - "valuable": false, + "valuable": false, "item-wealth": true }, "hoarded": { - "hoarded": false, + "hoarded": false, "inHoard": true }, "physical": { @@ -231,29 +230,36 @@ "spellSelection": { "spellProcessSelection": { "none": "midgard5.spell-process-none", + "artefakte": "midgard5.spell-process-artefakte", "beherrschen": "midgard5.spell-process-beherrschen", "bewegen": "midgard5.spell-process-bewegen", - "blutzauber": "midgard5.spell-process-blutzauber", + "beschwoeren": "midgard5.spell-process-beschwoeren", + "blutmagie": "midgard5.spell-process-blutmagie", "chaoswunder": "midgard5.spell-process-chaoswunder", + "dweomer": "midgard5.spell-process-dweomer", + "erhaltung": "midgard5.spell-process-erhaltung", "erkennen": "midgard5.spell-process-erkennen", "erschaffen": "midgard5.spell-process-erschaffen", "formen": "midgard5.spell-process-formen", "finstere_magie": "midgard5.spell-process-finstere_magie", - "veraendern": "midgard5.spell-process-veraendern", - "zerstoeren": "midgard5.spell-process-zerstoeren", - "wundertat": "midgard5.spell-process-wundertat", - "dweomer": "midgard5.spell-process-dweomer", - "wilder_dweomer": "midgard5.spell-process-wilder_dweomer", - "zauberlied": "midgard5.spell-process-zauberlied", - "salz": "midgard5.spell-process-salz", - "thaumagraphie": "midgard5.spell-process-thaumagraphie", - "beschwoeren": "midgard5.spell-process-beschwoeren", + "kampfverse": "midgard5.spell-process-kampfverse", + "namensmagie": "midgard5.spell-process-namensmagie", "nekromantie": "midgard5.spell-process-nekromantie", - "thaumatherapie": "midgard5.spell-process-thaumatherapie", + "runenstaebe": "midgard5.spell-process-zauberrunen", + "thaumatherapie": "midgard5.spell-process-runenstaebe", + "veraendern": "midgard5.spell-process-veraendern", + "vigilsignien": "midgard5.spell-process-vigilsignien", + "wilder_dweomer": "midgard5.spell-process-wilder_dweomer", + "wundertat": "midgard5.spell-process-wundertat", + "zauberblaetter": "midgard5.spell-process-zauberblaetter", + "zauberlied": "midgard5.spell-process-zauberlied", "zaubermittel": "midgard5.spell-process-zaubermittel", - "zauberschutz": "midgard5.spell-process-zauberschutz", "zauberrunen": "midgard5.spell-process-zauberrunen", - "zaubersiegel": "midgard5.spell-process-siegel" + "zaubersalz": "midgard5.spell-process-zaubersalz", + "zauberschutz": "midgard5.spell-process-zauberschutz", + "zaubersiegel": "midgard5.spell-process-zaubersiegel", + "zaubertaenze": "midgard5.spell-process-zaubertaenze", + "zerstoeren": "midgard5.spell-process-zerstoeren" }, "spellTypeSelection": { "gedanke": "midgard5.spell-type-gedanke", @@ -289,7 +295,7 @@ "fechten": "midgard5.kampfkunst-variante-fechten", "schusstechnik": "midgard5.kampfkunst-variante-schusstechnik", "finten": "midgard5.kampfkunst-variante-finten", - "geistestechnik": "midgard5.kampfkunst-variante-geistestechnik", + "geistestechnik": "midgard5.kampfkunst-variante-geistestechnik", "verteidigung": "midgard5.kampfkunst-variante-verteidigung" }, "kidoVarianteSelection": { @@ -325,7 +331,7 @@ "calc": {} }, "item": { - "templates": ["itemDescription", "equippable", "physical","valuable","hoarded"], + "templates": ["itemDescription", "equippable", "physical", "valuable", "hoarded"], "rolls": { "formulas": {}, "output": "" @@ -352,7 +358,7 @@ "calc": {} }, "weapon": { - "templates": ["itemDescription", "stats", "equippable", "physical","valuable","hoarded"], + "templates": ["itemDescription", "stats", "equippable", "physical", "valuable", "hoarded"], "special": false, "ranged": false, "valuable": false, @@ -377,7 +383,7 @@ "calc": {} }, "defensiveWeapon": { - "templates": ["itemDescription", "stats", "equippable", "physical","valuable","hoarded"], + "templates": ["itemDescription", "stats", "equippable", "physical", "valuable", "hoarded"], "special": false, "valuable": false, "hoarded": false, @@ -395,7 +401,7 @@ "calc": {} }, "armor": { - "templates": ["itemDescription", "stats", "equippable", "attributeMod", "physical","valuable","hoarded"], + "templates": ["itemDescription", "stats", "equippable", "attributeMod", "physical", "valuable", "hoarded"], "lpProtection": 0, "apProtection": 0, "valuable": false, @@ -459,6 +465,154 @@ "output": "" }, "calc": {} + }, + "class": { + "templates": ["itemDescription"], + "magicUsing": false, + "equipped": true, + "resistanceBody": 1, + "resistanceMind": 0, + "calc": {}, + "mods": {}, + "lernKostenAllgemein": { + "alltag": 20, + "freiland": 20, + "halbwelt": 20, + "kampf": 20, + "koerper": 20, + "sozial": 20, + "unterwelt": 20, + "waffen": 20, + "wissen": 20 + }, + "lernKostenZauber": { + "beherrschen": { + "kosten": 0, + "pp": 0 + }, + "bewegen": { + "kosten": 0, + "pp": 0 + }, + "erkennen": { + "kosten": 0, + "pp": 0 + }, + "erschaffen": { + "kosten": 0, + "pp": 0 + }, + "formen": { + "kosten": 0, + "pp": 0 + }, + "veraendern": { + "kosten": 0, + "pp": 0 + }, + "zerstoeren": { + "kosten": 0, + "pp": 0 + }, + "wundertat": { + "kosten": 0, + "pp": 0 + }, + "dweomer": { + "kosten": 0, + "pp": 0 + }, + "zauberlied": { + "kosten": 0, + "pp": 0 + }, + "kampfverse": { + "kosten": 0, + "pp": 0 + }, + "zaubertaenze": { + "kosten": 0, + "pp": 0 + }, + "zaubersalz": { + "kosten": 0, + "pp": 0 + }, + "runenstaebe": { + "kosten": 0, + "pp": 0 + }, + "zaubersiegel": { + "kosten": 0, + "pp": 0 + }, + "zauberrunen": { + "kosten": 0, + "pp": 0 + }, + "thaumagraphie": { + "kosten": 0, + "pp": 0 + }, + "erhaltung": { + "kosten": 0, + "pp": 0 + }, + "zaubermittel": { + "kosten": 0, + "pp": 0 + }, + "zauberschutz": { + "kosten": 0, + "pp": 0 + }, + "zauberblaetter": { + "kosten": 0, + "pp": 0 + }, + "vigilsignien": { + "kosten": 0, + "pp": 0 + }, + "artefakte": { + "kosten": 0, + "pp": 0 + }, + "chaoswunder": { + "kosten": 0, + "pp": 0 + }, + "wilder_dweomer": { + "kosten": 0, + "pp": 0 + }, + "nekromantie": { + "kosten": 0, + "pp": 0 + }, + "finstere_magie": { + "kosten": 0, + "pp": 0 + }, + "blutmagie": { + "kosten": 0, + "pp": 0 + }, + "beschwoeren": { + "kosten": 0, + "pp": 0 + }, + "namensmagie": { + "kosten": 0, + "pp": 0 + } + }, + "lernKostenKamptechnik": { + "kampfkunst": 90, + "fechtkunst": 90, + "schiesskunst": 90, + "kido": 90 + } } } } diff --git a/templates/sheets/character/base_values.hbs b/templates/sheets/character/base_values.hbs index b7b9556..b3bfae8 100644 --- a/templates/sheets/character/base_values.hbs +++ b/templates/sheets/character/base_values.hbs @@ -63,7 +63,7 @@ {{localize "midgard5.magicUsing"}} - + {{localize "midgard5.movementRange"}} diff --git a/templates/sheets/character/main.hbs b/templates/sheets/character/main.hbs index 1039fc3..d5cef81 100644 --- a/templates/sheets/character/main.hbs +++ b/templates/sheets/character/main.hbs @@ -15,7 +15,14 @@ {{localize "midgard5.class"}} - + + {{#each data.info.class as |class id|}} +
+ {{class}} + +
+ {{/each}} + {{localize "midgard5.level"}} {{data.calc.level}} @@ -132,26 +139,26 @@ {{> "systems/midgard5/templates/sheets/character/base_values.hbs"}} -
+
{{> "systems/midgard5/templates/sheets/character/skills.hbs"}}
-
+
{{> "systems/midgard5/templates/sheets/character/gear.hbs"}}
-
+
{{> "systems/midgard5/templates/sheets/character/combat.hbs"}}
-
+
{{> "systems/midgard5/templates/sheets/character/spells.hbs"}}
-
+
{{> "systems/midgard5/templates/sheets/character/effects.hbs"}}
-
+
{{> "systems/midgard5/templates/sheets/character/description.hbs"}}
diff --git a/templates/sheets/item/class.hbs b/templates/sheets/item/class.hbs new file mode 100644 index 0000000..e12e040 --- /dev/null +++ b/templates/sheets/item/class.hbs @@ -0,0 +1,109 @@ +
+
+ +

+
+ + +
+ +
+ + + + + + + + + + + + + + +
+
+ + + + +
+
{{localize "midgard5.resistanceMind"}}{{localize "midgard5.resistanceBody"}}
+ +
+ +
+ + + + + + +
+
+ {{#each data.lernKostenAllgemein as |wert name|}} + + + + + {{/each}} +
+
+
+ +
+ + + + + + +
+
+ {{#each data.lernKostenKamptechnik as |wert name|}} + + + + + {{/each}} +
+
+
+ +
+ + + + + + +
+
+ + {{#each data.lernKostenZauber as |wert name|}} + + + + + {{/each}} +
+
+
+ +
+ {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + +
+ +
+ +
\ No newline at end of file From 3a58485d27ada9ff569bfea3b6647454119dc34c Mon Sep 17 00:00:00 2001 From: Byroks Date: Sun, 24 Mar 2024 15:06:30 +0100 Subject: [PATCH 2/3] #90 Clean Spell Button funktioniert nicht (#94) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: + hinzufügen von roll funktion für Zauberwert Reviewed-on: https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/pulls/94 Reviewed-by: Le-Frique --- source/module/rolls/M5Roll.ts | 17 +++++++++++++++++ source/module/sheets/M5CharacterSheet.ts | 5 +++++ templates/sheets/character/spells.hbs | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/source/module/rolls/M5Roll.ts b/source/module/rolls/M5Roll.ts index 9a5f316..a7ad922 100644 --- a/source/module/rolls/M5Roll.ts +++ b/source/module/rolls/M5Roll.ts @@ -212,6 +212,23 @@ export class M5Roll { return new M5Roll(rollData, actor, (game as Game).i18n.localize("midgard5.perception")); } + static cleanSpell(actor: any) { + const rollData = actor.getRollData() as M5RollData; + + rollData.rolls["0"] = { + formula: "1d20 + @c.calc.stats.spellCasting.value", + enabled: true, + label: (game as Game).i18n.localize("midgard5.spellCasting"), + result: "", + total: 0, + totalStr: "", + dice: {}, + css: "", + } as M5RollResult; + + return new M5Roll(rollData, actor, (game as Game).i18n.localize("midgard5.spellCasting")); + } + static drinking(actor: any) { const rollData = actor.getRollData() as M5RollData; diff --git a/source/module/sheets/M5CharacterSheet.ts b/source/module/sheets/M5CharacterSheet.ts index 7cbc2ff..d34d69c 100644 --- a/source/module/sheets/M5CharacterSheet.ts +++ b/source/module/sheets/M5CharacterSheet.ts @@ -247,6 +247,11 @@ export default class M5CharacterSheet extends ActorSheet { await roll.toMessage(); }); + html.find(".roll-cleanSpell-button").on("click", async (event) => { + const roll = M5Roll.cleanSpell(this.actor); + await roll.toMessage(); + }); + html.find(".roll-perception-button").on("click", async (event) => { const roll = M5Roll.perception(this.actor); await roll.toMessage(); diff --git a/templates/sheets/character/spells.hbs b/templates/sheets/character/spells.hbs index df236c5..9fbd500 100644 --- a/templates/sheets/character/spells.hbs +++ b/templates/sheets/character/spells.hbs @@ -8,7 +8,7 @@ {{localize "midgard5.spellCasting"}} {{data.calc.stats.spellCasting.value}} - From 046d5f02864722b9b23d302edde1dd9d1c4428c4 Mon Sep 17 00:00:00 2001 From: Byroks Date: Sun, 24 Mar 2024 15:09:08 +0100 Subject: [PATCH 3/3] #91 Automatische Praxispunkte (#93) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: + implementation von Automatischen Praxispunkten + Hinzufügen von System Settings zur abschaltung von Automatischen Praxispunkten + Aufräumen von Helpers und settings in eigene Dateien Co-authored-by: LeFrique Reviewed-on: https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/pulls/93 --- lang/de.json | 8 ++- source/helpers.ts | 110 ++++++++++++++++++++++++++++++++ source/index.ts | 107 ++----------------------------- source/module/M5Base.ts | 2 +- source/module/items/M5Item.ts | 2 +- source/module/rolls/M5Roll.ts | 46 ++++++++++++- source/settings.ts | 16 +++++ source/template.json | 6 +- templates/sheets/item/class.hbs | 2 +- 9 files changed, 192 insertions(+), 107 deletions(-) create mode 100644 source/helpers.ts create mode 100644 source/settings.ts diff --git a/lang/de.json b/lang/de.json index 4ed4493..d6aff9d 100644 --- a/lang/de.json +++ b/lang/de.json @@ -181,7 +181,11 @@ "midgard5.meditieren": "Meditieren", "midgard5.menschenkenntnis": "Menschenkenntnis", "midgard5.meucheln": "Meucheln", - "midgard5.musizieren": "Musizieren", + "midgard5.musizierenFloete": "Musizieren (Flöten)", + "midgard5.musizierenBlas": "Musizieren (Blasinstrumente)", + "midgard5.musizierenRythmus": "Musizieren (Rythmusinstrumente)", + "midgard5.musizierenStreich": "Musizieren (Streichinstrumente)", + "midgard5.musizierenZupf": "Musizieren (Zupfinstrumente)", "midgard5.naturkunde": "Naturkunde", "midgard5.ninjutsu": "NinJutsu", "midgard5.orakelkunst": "Orakelkunst", @@ -298,7 +302,7 @@ "midgard5.spell-process-veraendern": "Verändern", "midgard5.spell-process-vigilsignien": "Vigilsignien", "midgard5.spell-process-wundertat": "Wundertat", - "midgard5.spell-process-wilder_Dweomer": "Wilder Dweomer", + "midgard5.spell-process-wilder_dweomer": "Wilder Dweomer", "midgard5.spell-process-zerstoeren": "Zerstören", "midgard5.spell-process-zauberlied": "Zauberlieder", "midgard5.spell-process-zaubersalz": "Zaubersalze", diff --git a/source/helpers.ts b/source/helpers.ts new file mode 100644 index 0000000..f0c0572 --- /dev/null +++ b/source/helpers.ts @@ -0,0 +1,110 @@ +/* global Handlebars, game, TextEditor, WOD5E */ + +import { M5Skill } from "./module/M5Base"; +import { M5Character } from "./module/actors/M5Character"; + +/** + * Define any helpers necessary for working with Handlebars + * @return {Promise} + */ +export const loadHelpers = async function () { + Handlebars.registerHelper("times", (n: number, block) => { + var accum = ""; + for (let i = 0; i < n; ++i) accum += block.fn(i); + return accum; + }); + + Handlebars.registerHelper("array", (arr: any[], index: number) => { + return arr[index]; + }); + + Handlebars.registerHelper("m5concat", (...values) => { + const options = values.pop(); + const join = options.hash?.join || ""; + //return new Handlebars.SafeString(values.join(join)); + return values.map((val) => val.toString()).join(join); + }); + + Handlebars.registerHelper("add", (...values) => { + const options = values.pop(); + return values.reduce((prev, cur) => prev + cur); + }); + + Handlebars.registerHelper("localizeMidgard", (str: string) => { + const template = Handlebars.compile("{{localize value}}"); + return template({ + value: "midgard5." + str, + }); + }); + + Handlebars.registerHelper("skillBonus", (actorId: string, skill: M5Skill) => { + const actor = (game as Game).actors.get(actorId) as M5Character; + return actor.skillBonus(skill).toString(); + }); + + Handlebars.registerHelper("skillEw", (actorId: string, skill: M5Skill) => { + const actor = (game as Game).actors.get(actorId) as M5Character; + return actor.skillEw(skill).toString(); + }); + + Handlebars.registerHelper("skill", (skillId: string) => { + return (game as Game).items.get(skillId); + }); + + Handlebars.registerHelper("itemValue", (id: string, path: string) => { + let obj = (game as Game).items.get(id); + path.split(".").forEach((p) => (obj = obj[p])); + return `${obj}`; + }); + + Handlebars.registerHelper("actorItemValue", (actorId: any, itemId: string, path: string, token?: boolean) => { + //console.log("actorItemValue", actorId, itemId, path) + const actor = (game as Game).actors.get(actorId); + let obj = actor.items.get(itemId)?.system; + path.split(".").forEach((p) => { + if (obj) obj = obj[p]; + }); + return `${obj}`; + }); + + Handlebars.registerHelper("icon", (relpath: string) => { + return `systems/midgard5/assets/icons/${relpath}`; + }); + + Handlebars.registerHelper("isSkillInList", (skillName: string, list: any) => { + for (let key in list) { + if (list[key]?.label?.toLowerCase() === skillName?.toLowerCase()) { + return true; + } + } + return false; + }); + + Handlebars.registerHelper("skillEwInList", (skillName: string, list: any) => { + for (let key in list) { + if (list[key]?.label?.toLowerCase() === skillName?.toLowerCase()) { + return list[key].calc.ew; + } + } + return false; + }); + + Handlebars.registerHelper("stripHtml", function (param) { + var regex = /(<([^>]+)>)/gi; + return param.replace(regex, ""); + }); + + Handlebars.registerHelper("contains", (label: string, contains: string) => { + return label.toLowerCase().includes(contains.toLowerCase()); + }); + + Handlebars.registerHelper("count", (object: any) => { + var length = 0; + for (var key in object) { + if (object.hasOwnProperty(key)) { + ++length; + } + } + return length; + }); +}; diff --git a/source/index.ts b/source/index.ts index 49f7311..2d4de52 100644 --- a/source/index.ts +++ b/source/index.ts @@ -2,112 +2,17 @@ import Logger from "./utils/Logger"; import M5CharacterSheet from "./module/sheets/M5CharacterSheet"; import preloadTemplates from "./PreloadTemplates"; import { M5Character } from "./module/actors/M5Character"; -import { M5ItemMod, M5ModOperation, M5Skill, M5TimeUnit } from "./module/M5Base"; +import { M5ModOperation, M5TimeUnit } from "./module/M5Base"; import { M5ItemSheet } from "./module/sheets/M5ItemSheet"; import { M5Item } from "./module/items/M5Item"; +import { loadHelpers } from "./helpers"; +import { loadSettings } from "./settings"; Hooks.once("init", async () => { Logger.log("M5 | Initialisierung Midgard 5"); - Handlebars.registerHelper("times", (n: number, block) => { - var accum = ""; - for (let i = 0; i < n; ++i) accum += block.fn(i); - return accum; - }); - - Handlebars.registerHelper("array", (arr: any[], index: number) => { - return arr[index]; - }); - - Handlebars.registerHelper("m5concat", (...values) => { - const options = values.pop(); - const join = options.hash?.join || ""; - //return new Handlebars.SafeString(values.join(join)); - return values.map((val) => val.toString()).join(join); - }); - - Handlebars.registerHelper("add", (...values) => { - const options = values.pop(); - return values.reduce((prev, cur) => prev + cur); - }); - - Handlebars.registerHelper("localizeMidgard", (str: string) => { - const template = Handlebars.compile("{{localize value}}"); - return template({ - value: "midgard5." + str, - }); - }); - - Handlebars.registerHelper("skillBonus", (actorId: string, skill: M5Skill) => { - const actor = (game as Game).actors.get(actorId) as M5Character; - return actor.skillBonus(skill).toString(); - }); - - Handlebars.registerHelper("skillEw", (actorId: string, skill: M5Skill) => { - const actor = (game as Game).actors.get(actorId) as M5Character; - return actor.skillEw(skill).toString(); - }); - - Handlebars.registerHelper("skill", (skillId: string) => { - return (game as Game).items.get(skillId); - }); - - Handlebars.registerHelper("itemValue", (id: string, path: string) => { - let obj = (game as Game).items.get(id); - path.split(".").forEach((p) => (obj = obj[p])); - return `${obj}`; - }); - - Handlebars.registerHelper("actorItemValue", (actorId: any, itemId: string, path: string, token?: boolean) => { - //console.log("actorItemValue", actorId, itemId, path) - const actor = (game as Game).actors.get(actorId); - let obj = actor.items.get(itemId)?.system; - path.split(".").forEach((p) => { - if (obj) obj = obj[p]; - }); - return `${obj}`; - }); - - Handlebars.registerHelper("icon", (relpath: string) => { - return `systems/midgard5/assets/icons/${relpath}`; - }); - - Handlebars.registerHelper("isSkillInList", (skillName: string, list: any) => { - for (let key in list) { - if (list[key]?.label?.toLowerCase() === skillName?.toLowerCase()) { - return true; - } - } - return false; - }); - - Handlebars.registerHelper("skillEwInList", (skillName: string, list: any) => { - for (let key in list) { - if (list[key]?.label?.toLowerCase() === skillName?.toLowerCase()) { - return list[key].calc.ew; - } - } - return false; - }); - - Handlebars.registerHelper("stripHtml", function (param) { - var regex = /(<([^>]+)>)/gi; - return param.replace(regex, ""); - }); - - Handlebars.registerHelper("contains", (label: string, contains: string) => { - return label.toLowerCase().includes(contains.toLowerCase()); - }); - - Handlebars.registerHelper("count", (object: any) => { - var length = 0; - for (var key in object) { - if (object.hasOwnProperty(key)) { - ++length; - } - } - return length; - }); + // Load settings into Foundry + loadSettings(); // Default Sheet für Items definieren und das Standardsheet deaktivieren Items.unregisterSheet("core", ItemSheet); @@ -121,6 +26,8 @@ Hooks.once("init", async () => { CONFIG.Item.documentClass = M5Item; //RegisterSettings(); await preloadTemplates(); + + loadHelpers(); }); Hooks.once("setup", () => { diff --git a/source/module/M5Base.ts b/source/module/M5Base.ts index 586b84f..004e1f1 100644 --- a/source/module/M5Base.ts +++ b/source/module/M5Base.ts @@ -29,7 +29,7 @@ export interface M5RollData { c: any; i: any; iType: string; - rolls: {}; + rolls: any; res: { label: string; }; diff --git a/source/module/items/M5Item.ts b/source/module/items/M5Item.ts index c4eb60c..72845cc 100644 --- a/source/module/items/M5Item.ts +++ b/source/module/items/M5Item.ts @@ -323,7 +323,7 @@ export class M5Item extends Item { } } - const roll = new M5Roll(rollData, this.actor, item.name); + const roll = new M5Roll(rollData, this.actor, item.name, item.id); return roll.toMessage(); } else { ChatMessage.create({ diff --git a/source/module/rolls/M5Roll.ts b/source/module/rolls/M5Roll.ts index a7ad922..aab59a2 100644 --- a/source/module/rolls/M5Roll.ts +++ b/source/module/rolls/M5Roll.ts @@ -11,7 +11,7 @@ export class M5Roll { public _total: number = 0; public pool: PoolTerm = null; - constructor(public data: M5RollData, public actor: any, public label: string) { + constructor(public data: M5RollData, public actor: any, public label: string, public id?: string) { //super(null) //this.data = rollData } @@ -88,6 +88,50 @@ export class M5Roll { }); this.data.res.label = this.label; + if ((game as Game).settings.get("midgard5", "automatedPP")) { + if ((this.data.i.type === "language" || this.data.i.type === "general") && this.data.rolls[0].dice[0] >= 16) { + this.actor.items.get(this.id).update({ + system: { + pp: this.data.i.pp + 1, + }, + }); + } else if (this.data.rolls[0].dice[0] === 20) { + if (this.data.i.type === "combat") { + // Rolling through skill + this.actor.items.get(this.id).update({ + system: { + pp: this.data.i.pp + 1, + }, + }); + } else if (this.data.iType === "weapon") { + // Rolling through Weapon Item + const skill = this.actor.items.get(this.data.i.skillId); + skill.update({ + system: { + pp: skill.system.pp + 1, + }, + }); + } else if (this.data.iType === "defensiveWeapon") { + // Rolling through defensiveWeapon Item + const skill = this.actor.items.get(this.data.i.skillId); + skill.update({ + system: { + pp: skill.system.pp + 1, + }, + }); + } else if (this.data.iType === "spell") { + // Rolling through Spell Item + const klasse = this.actor.items.find((x) => x.type === "class" && x.system.equipped); + klasse.update({ + system: { + lernKostenZauber: { + [this.data.i.process]: { pp: klasse.system.lernKostenZauber[this.data.i.process].pp + 1 }, + }, + }, + }); + } + } + } this._evaluated = true; return this; diff --git a/source/settings.ts b/source/settings.ts new file mode 100644 index 0000000..d9ba705 --- /dev/null +++ b/source/settings.ts @@ -0,0 +1,16 @@ +/* global game */ + +/** + * Define all game settings here + * @return {Promise} + */ +export const loadSettings = async function () { + (game as Game).settings.register("midgard5", "automatedPP", { + name: "Automatische Praxispunkte", + hint: "Falls aktiv, werden Praxispunkte automatisch angerechnet.", + scope: "world", + config: true, + default: true, + type: Boolean, + }); +}; diff --git a/source/template.json b/source/template.json index 23483b4..de2ef9e 100644 --- a/source/template.json +++ b/source/template.json @@ -101,7 +101,11 @@ "meditieren": { "fw": 0, "attribute": "wk", "initial": 8, "pp": 0 }, "menschenkenntnis": { "fw": 3, "attribute": "in", "initial": 8, "pp": 0 }, "meucheln": { "fw": 0, "attribute": "gs", "initial": 8, "pp": 0 }, - "musizieren": { "fw": 0, "attribute": "gs", "initial": 12, "pp": 0 }, + "musizierenFloete": { "fw": 0, "attribute": "gs", "initial": 12, "pp": 0 }, + "musizierenBlas": { "fw": 0, "attribute": "gs", "initial": 12, "pp": 0 }, + "musizierenRythmus": { "fw": 0, "attribute": "gs", "initial": 12, "pp": 0 }, + "musizierenStreich": { "fw": 0, "attribute": "gs", "initial": 12, "pp": 0 }, + "musizierenZupf": { "fw": 0, "attribute": "gs", "initial": 12, "pp": 0 }, "ninjutsu": { "fw": 0, "attribute": "gw", "initial": 8, "pp": 0 }, "naturkunde": { "fw": 0, "attribute": "in", "initial": 8, "pp": 0 }, "orakelkunst": { "fw": 0, "attribute": "in", "initial": 8, "pp": 0 }, diff --git a/templates/sheets/item/class.hbs b/templates/sheets/item/class.hbs index e12e040..6e657c0 100644 --- a/templates/sheets/item/class.hbs +++ b/templates/sheets/item/class.hbs @@ -89,7 +89,7 @@ {{#each data.lernKostenZauber as |wert name|}} - + {{/each}}