From a46ef87e3fb6b48a678f50af139644e0e909d279 Mon Sep 17 00:00:00 2001 From: Byroks Date: Wed, 21 Feb 2024 22:29:48 +0100 Subject: [PATCH 1/3] Button um Kampf beizutreten (#61) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: + Button um Kampf beizutreten + buttons um initiative zu verändern für Fernangriffe und Zauber Reviewed-on: https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/pulls/61 --- lang/de.json | 8 ++-- source/module/rolls/M5Roll.ts | 21 ---------- source/module/sheets/M5CharacterSheet.ts | 51 ++++++++++++++++++++++++ source/style/Character-sheet.less | 4 ++ templates/sheets/character/combat.hbs | 15 +++++-- 5 files changed, 72 insertions(+), 27 deletions(-) diff --git a/lang/de.json b/lang/de.json index 622128d..0993551 100644 --- a/lang/de.json +++ b/lang/de.json @@ -17,7 +17,11 @@ "midgard5.phase-movement": "Bewegungsphase", "midgard5.no-encounter": "Kein Kampf", "midgard5.encounter-not-started": "Kein aktiver Kampf", - "midgard5.initiative": "Initiative", + "midgard5.initiative": "Handlungsrang", + + "midgard5.combat-join": "Kampf Beitreten/Handlungsrang zurücksetzen", + "midgard5.combat-ranged": "Fernangriff", + "midgard5.combat-spell": "Zaubern (10 Sec)", "midgard5.time-duration": "Dauer", "midgard5.time-round": "Runde(n)", @@ -92,7 +96,6 @@ "midgard5.kampfkuenste": "Kampfkünste", "midgard5.combat": "Kampf", - "midgard5.actor-name": "Figur", "midgard5.level": "Grad", "midgard5.class": "Typ", @@ -260,7 +263,6 @@ "midgard5.itemsInContainers": "Gegenstände in Aufbewahrung", "midgard5.allItems": "Alle Gegenstände", - "midgard5.pw": "Prüfwurf", "midgard5.attack": "Angriff", "midgard5.damage": "Schaden", diff --git a/source/module/rolls/M5Roll.ts b/source/module/rolls/M5Roll.ts index f0b2565..9a5f316 100644 --- a/source/module/rolls/M5Roll.ts +++ b/source/module/rolls/M5Roll.ts @@ -269,27 +269,6 @@ export class M5Roll { return new M5Roll(rollData, actor, (game as Game).i18n.localize("midgard5.resistanceMind")); } - static async initativeRoll(actor: any) { - let newInitiative; // the initiative value for the combatant - - // ... - // The intnitiative value is calculated here - // ... - - let combatant = game["combat"].getCombatantByActor(actor._id); - if (!combatant) { - await game["combat"].createEmbeddedDocuments("Combatant", [{ actorId: actor._id }]); - combatant = game["combat"].getCombatantByActor(actor._id); - } - - const initiatives = { - _id: combatant._id, - initiative: actor.system.calc.attributes.gw.value, - }; - - await game["combat"].updateEmbeddedDocuments("Combatant", [initiatives]); - } - static resistanceBody(actor: any) { const rollData = actor.getRollData() as M5RollData; rollData.i = { diff --git a/source/module/sheets/M5CharacterSheet.ts b/source/module/sheets/M5CharacterSheet.ts index d2ffa4c..9faf8dd 100644 --- a/source/module/sheets/M5CharacterSheet.ts +++ b/source/module/sheets/M5CharacterSheet.ts @@ -363,6 +363,57 @@ export default class M5CharacterSheet extends ActorSheet { character.createItem((game as Game).i18n.localize("TYPES.Item.effect"), M5ItemType.EFFECT); }); + html.find(".join-combat").on("click", async (event) => { + if (!!game["combat"]) { + let combatant = game["combat"].getCombatantByActor(this.actor._id); + if (!combatant) { + await game["combat"].createEmbeddedDocuments("Combatant", [{ actorId: this.actor._id }]); + combatant = game["combat"].getCombatantByActor(this.actor._id); + } + + const initiatives = { + _id: combatant._id, + initiative: this.actor.system.calc.attributes.gw.value, + }; + + await game["combat"].updateEmbeddedDocuments("Combatant", [initiatives]); + } + }); + + html.find(".ranged-combat").on("click", async (event) => { + if (!!game["combat"]) { + let combatant = game["combat"].getCombatantByActor(this.actor._id); + if (!combatant) { + await game["combat"].createEmbeddedDocuments("Combatant", [{ actorId: this.actor._id }]); + combatant = game["combat"].getCombatantByActor(this.actor._id); + } + + const initiatives = { + _id: combatant._id, + initiative: 0.01 * this.actor.system.calc.attributes.gw.value, + }; + + await game["combat"].updateEmbeddedDocuments("Combatant", [initiatives]); + } + }); + + html.find(".spell-combat").on("click", async (event) => { + if (!!game["combat"]) { + let combatant = game["combat"].getCombatantByActor(this.actor._id); + if (!combatant) { + await game["combat"].createEmbeddedDocuments("Combatant", [{ actorId: this.actor._id }]); + combatant = game["combat"].getCombatantByActor(this.actor._id); + } + + const initiatives = { + _id: combatant._id, + initiative: 0.001 * this.actor.system.calc.attributes.gw.value, + }; + + await game["combat"].updateEmbeddedDocuments("Combatant", [initiatives]); + } + }); + // Drag & Drop const dragDrop = new DragDrop({ dragSelector: ".items-list .item", diff --git a/source/style/Character-sheet.less b/source/style/Character-sheet.less index a0047fd..68c3dcc 100644 --- a/source/style/Character-sheet.less +++ b/source/style/Character-sheet.less @@ -225,6 +225,10 @@ height: 1rem; } + .wide-button { + margin: 0.25rem 0; + } + .learn-button { padding: 0; margin: 0; diff --git a/templates/sheets/character/combat.hbs b/templates/sheets/character/combat.hbs index 800610a..080bedf 100644 --- a/templates/sheets/character/combat.hbs +++ b/templates/sheets/character/combat.hbs @@ -1,6 +1,6 @@
-
+
{{localize "midgard5.calculated-values"}}
@@ -8,8 +8,8 @@ - - + + @@ -26,6 +26,15 @@ +
+
+
{{localize "midgard5.initiative"}}
+ + + +
+
+
{{localize "midgard5.attack"}}
From 1624602407eda34f03a376040a31f39f8d70bbd9 Mon Sep 17 00:00:00 2001 From: Byroks Date: Wed, 21 Feb 2024 22:29:58 +0100 Subject: [PATCH 2/3] =?UTF-8?q?+=20Button=20f=C3=BCr=20Skills=20(#59)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: + Styling anpassung für + buttons + CreatItem funktion angepasst, man kann optionen reingeben + button um skills zu erstellen eingefügt Reviewed-on: https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/pulls/59 --- source/module/M5Base.ts | 7 +++ source/module/actors/M5Character.ts | 5 +- source/module/sheets/M5CharacterSheet.ts | 79 ++++++++++++------------ templates/sheets/character/combat.hbs | 2 +- templates/sheets/character/effects.hbs | 2 +- templates/sheets/character/gear.hbs | 20 ++---- templates/sheets/character/skills.hbs | 10 +-- templates/sheets/character/spells.hbs | 2 +- 8 files changed, 64 insertions(+), 63 deletions(-) diff --git a/source/module/M5Base.ts b/source/module/M5Base.ts index 72e3358..5773e5a 100644 --- a/source/module/M5Base.ts +++ b/source/module/M5Base.ts @@ -61,6 +61,13 @@ export enum M5ItemType { EFFECT = "effect", } +export enum M5SkillType { + INNATE = "innate", + GENERAL = "general", + LANGUAGE = "language", + COMBAT = "combat", +} + export enum M5EwResult { TBD = "", FUMBLE = "roll-ew-result-fumble", diff --git a/source/module/actors/M5Character.ts b/source/module/actors/M5Character.ts index 72335ca..2d92b36 100644 --- a/source/module/actors/M5Character.ts +++ b/source/module/actors/M5Character.ts @@ -1,5 +1,5 @@ import { M5Item } from "../items/M5Item"; -import { M5Attribute, M5CharacterCalculatedData, M5ItemMod, M5ItemType, M5ModOperation, M5ModResult, M5RollData, M5Skill, M5SkillCalculated, M5SkillLearned } from "../M5Base"; +import { M5Attribute, M5CharacterCalculatedData, M5ItemMod, M5ItemType, M5ModOperation, M5ModResult, M5RollData, M5Skill, M5SkillCalculated, M5SkillLearned, M5SkillType } from "../M5Base"; import M5ModAggregate from "./M5ModAggregate"; export class M5Character extends Actor { // constructor( @@ -523,10 +523,11 @@ export class M5Character extends Actor { }); } - createItem(itemName: string, itemType: M5ItemType): Promise { + createItem(itemName: string, itemType: M5ItemType, options?: any): Promise { const itemData = { name: itemName, type: itemType, + data: options, }; return (this as any).createEmbeddedDocuments("Item", [itemData]).then((docs) => { diff --git a/source/module/sheets/M5CharacterSheet.ts b/source/module/sheets/M5CharacterSheet.ts index 9faf8dd..2912a30 100644 --- a/source/module/sheets/M5CharacterSheet.ts +++ b/source/module/sheets/M5CharacterSheet.ts @@ -1,7 +1,7 @@ import Logger from "../../utils/Logger"; import { M5Character } from "../actors/M5Character"; import { M5Item } from "../items/M5Item"; -import { M5ItemType, M5SkillLearned, M5SkillUnlearned } from "../M5Base"; +import { M5ItemType, M5SkillLearned, M5SkillType, M5SkillUnlearned } from "../M5Base"; import { M5Roll } from "../rolls/M5Roll"; export default class M5CharacterSheet extends ActorSheet { @@ -270,11 +270,12 @@ export default class M5CharacterSheet extends ActorSheet { const context = this.actor as any; const item = context.items.get(itemId); - if (item.system.equipped === true) { - item.system.equipped = false; - } else { - item.system.equipped = true; - } + item.update({ + data: { + equipped: !item.system.equipped, + }, + }); + this.render(); }); @@ -282,14 +283,7 @@ export default class M5CharacterSheet extends ActorSheet { const data = this.actor.system; const character = this.actor as M5Character; - character.createItem((game as Game).i18n.localize("TYPES.Item.item"), M5ItemType.ITEM).then((i) => { - const item = i as any; - item.update({ - data: { - quantity: 1, - }, - }); - }); + character.createItem((game as Game).i18n.localize("TYPES.Item.item"), M5ItemType.ITEM, { quantity: 1 }); }); html.find(".add-weapon").on("click", async (event) => { @@ -317,42 +311,51 @@ export default class M5CharacterSheet extends ActorSheet { const data = this.actor.system; const character = this.actor as M5Character; - character.createItem((game as Game).i18n.localize("TYPES.Item.container"), M5ItemType.CONTAINER).then((i) => { - const item = i as any; - item.update({ - data: { - quantity: 1, - }, - }); - }); + character.createItem((game as Game).i18n.localize("TYPES.Item.container"), M5ItemType.CONTAINER, { quantity: 1 }); + }); + + html.find(".add-innate-skill").on("click", async (event) => { + const data = this.actor.system; + + const character = this.actor as M5Character; + character.createItem((game as Game).i18n.localize("TYPES.Item.innate-ability"), M5ItemType.SKILL, { type: M5SkillType.INNATE }); + }); + + html.find(".add-general-skill").on("click", async (event) => { + const data = this.actor.system; + + const character = this.actor as M5Character; + character.createItem((game as Game).i18n.localize("TYPES.Item.skill"), M5ItemType.SKILL, { type: M5SkillType.GENERAL }); + }); + + html.find(".add-combat-skill").on("click", async (event) => { + const data = this.actor.system; + + const character = this.actor as M5Character; + character.createItem((game as Game).i18n.localize("TYPES.Item.weapon-skill"), M5ItemType.SKILL, { type: M5SkillType.COMBAT }); + }); + + html.find(".add-language-skill").on("click", async (event) => { + const data = this.actor.system; + + const character = this.actor as M5Character; + character.createItem((game as Game).i18n.localize("TYPES.Item.language"), M5ItemType.SKILL, { type: M5SkillType.LANGUAGE }); }); html.find(".add-spell").on("click", async (event) => { const data = this.actor.system; const character = this.actor as M5Character; - character.createItem((game as Game).i18n.localize("TYPES.Item.spell"), M5ItemType.SPELL).then((i) => { - const item = i as any; - item.update({ - data: { - process: "none", - }, - }); - }); + character.createItem((game as Game).i18n.localize("TYPES.Item.spell"), M5ItemType.SPELL, { process: "none" }); }); html.find(".add-kampfkunst").on("click", async (event) => { const data = this.actor.system; const character = this.actor as M5Character; - character.createItem((game as Game).i18n.localize("TYPES.Item.kampfkunst"), M5ItemType.KAMPFKUNST).then((i) => { - const item = i as any; - item.update({ - data: { - type: "angriff", - variante: "anstuermen", - }, - }); + character.createItem((game as Game).i18n.localize("TYPES.Item.kampfkunst"), M5ItemType.KAMPFKUNST, { + type: "angriff", + variante: "anstuermen", }); }); diff --git a/templates/sheets/character/combat.hbs b/templates/sheets/character/combat.hbs index 080bedf..fc2447d 100644 --- a/templates/sheets/character/combat.hbs +++ b/templates/sheets/character/combat.hbs @@ -84,7 +84,7 @@
- + diff --git a/templates/sheets/character/effects.hbs b/templates/sheets/character/effects.hbs index 7af454d..d87114f 100644 --- a/templates/sheets/character/effects.hbs +++ b/templates/sheets/character/effects.hbs @@ -2,7 +2,7 @@ - + diff --git a/templates/sheets/character/gear.hbs b/templates/sheets/character/gear.hbs index 451fa02..437aae9 100644 --- a/templates/sheets/character/gear.hbs +++ b/templates/sheets/character/gear.hbs @@ -42,7 +42,7 @@ - + @@ -206,7 +206,6 @@
- {{#unless (eq (count data.calc.gear.items) 0)}}
{{localize "midgard5.gear"}}
@@ -218,7 +217,7 @@
- + @@ -256,9 +255,7 @@
{{localize "midgard5.movementRange"}} {{data.calc.stats.movement.value}}{{localize "midgard5.initiative"}}{{data.calc.attributes.gw.value}}
{{localize "midgard5.defense"}} {{data.calc.stats.defense.value}} {{localize "midgard5.kampfkunst-variante-short"}} {{localize "midgard5.ew"}}
{{localize "TYPES.Item.effect"}}
{{localize "midgard5.item-value"}}
{{localize "midgard5.item-value"}}
- {{/unless}} - {{#unless (eq (count data.calc.gear.weapons) 0)}}
@@ -269,7 +266,7 @@ {{localize "TYPES.Item.weapon"}} {{localize "midgard5.item-value"}} - + @@ -298,9 +295,7 @@
- {{/unless}} - {{#unless (eq (count data.calc.gear.defensiveWeapons) 0)}}
{{localize "midgard5.defensive-weapons"}}
@@ -310,7 +305,7 @@ {{localize "TYPES.Item.defensiveWeapon"}} {{localize "midgard5.item-value"}} - + @@ -338,9 +333,7 @@
- {{/unless}} - {{#unless (eq (count data.calc.gear.armor) 0)}}
{{localize "midgard5.armor"}}
@@ -350,7 +343,7 @@ {{localize "TYPES.Item.armor"}} {{localize "midgard5.item-value"}} - + @@ -378,8 +371,5 @@
- {{/unless}} - -
\ No newline at end of file diff --git a/templates/sheets/character/skills.hbs b/templates/sheets/character/skills.hbs index b666208..15f9c72 100644 --- a/templates/sheets/character/skills.hbs +++ b/templates/sheets/character/skills.hbs @@ -11,7 +11,7 @@ {{localize "midgard5.bonus"}} {{localize "midgard5.ew"}} - + @@ -56,7 +56,7 @@ {{localize "midgard5.ew"}} {{localize "midgard5.pp-short"}} - + @@ -66,7 +66,7 @@ {{skill.fw}} {{skill.calc.bonus}} {{skill.calc.ew}} - + {{skill.pp}} @@ -86,7 +86,7 @@ {{localize "midgard5.ew"}} {{localize "midgard5.pp-short"}} - + @@ -116,7 +116,7 @@ {{localize "midgard5.ew"}} {{localize "midgard5.pp-short"}} - + diff --git a/templates/sheets/character/spells.hbs b/templates/sheets/character/spells.hbs index ff5db64..aef25db 100644 --- a/templates/sheets/character/spells.hbs +++ b/templates/sheets/character/spells.hbs @@ -4,7 +4,7 @@ {{localize "TYPES.Item.spell"}} {{localize "midgard5.ew"}} - + From 06ef797ef213b3430864fa64135836bccd1dfcf2 Mon Sep 17 00:00:00 2001 From: Byroks Date: Wed, 21 Feb 2024 22:30:08 +0100 Subject: [PATCH 3/3] #57 Damage auf tokens (#58) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes: + Fix um Heilung anzurechnen + Finde token über Canvas Selected + möglich schaden auf mehrere token zeitlgiehc anzurechnen. Reviewed-on: https://git.byroks.de/MidgardVTT-Entwicklung/foundry-vtt-system-midgard5/pulls/58 --- source/index.ts | 88 ++++++++++++++++++-------------------- templates/chat/roll-m5.hbs | 2 +- 2 files changed, 42 insertions(+), 48 deletions(-) diff --git a/source/index.ts b/source/index.ts index f00d480..e11f94a 100644 --- a/source/index.ts +++ b/source/index.ts @@ -92,14 +92,14 @@ Hooks.once("init", async () => { Handlebars.registerHelper("count", (object: any) => { var length = 0; - for( var key in object ) { - if( object.hasOwnProperty(key) ) { + for (var key in object) { + if (object.hasOwnProperty(key)) { ++length; } } return length; }); - + // Default Sheet für Items definieren und das Standardsheet deaktivieren Items.unregisterSheet("core", ItemSheet); Items.registerSheet("midgard5", M5ItemSheet, { makeDefault: true }); @@ -124,12 +124,10 @@ Hooks.on("getChatLogEntryContext", function (html, options) { name: "LP & AP Schaden", icon: '', condition: (li) => { - // Only show this context menu if there are re-rollable dice in the message - const damageRolls = li.find(".apply-damage").length; + const damageRolls = li.find(".damage").length; // All must be true to show the reroll dialogue - // The button doesn't work for the GM right now, so we don't need to show it - return game["user"].character && damageRolls > 0; + return (game["user"].character || game["canvas"].tokens.controlled) && damageRolls > 0; }, callback: (li) => applyDamage(li, 2), }, @@ -137,12 +135,10 @@ Hooks.on("getChatLogEntryContext", function (html, options) { name: "AP Schaden", icon: '', condition: (li) => { - // Only show this context menu if there are re-rollable dice in the message - const damageRolls = li.find(".apply-damage").length; + const damageRolls = li.find(".damage").length; // All must be true to show the reroll dialogue - // The button doesn't work for the GM right now, so we don't need to show it - return game["user"].character && damageRolls > 0; + return (game["user"].character || game["canvas"].tokens.controlled) && damageRolls > 0; }, callback: (li) => applyDamage(li, 1), }, @@ -150,12 +146,10 @@ Hooks.on("getChatLogEntryContext", function (html, options) { name: "LP & AP Heilen", icon: '', condition: (li) => { - // Only show this context menu if there are re-rollable dice in the message - const damageRolls = li.find(".apply-damage").length; + const damageRolls = li.find(".heal").length; // All must be true to show the reroll dialogue - // The button doesn't work for the GM right now, so we don't need to show it - return game["user"].character && damageRolls > 0; + return (game["user"].character || game["canvas"].tokens.controlled) && damageRolls > 0; }, callback: (li) => applyDamage(li, -1), }, @@ -163,12 +157,10 @@ Hooks.on("getChatLogEntryContext", function (html, options) { name: "AP Heilen", icon: '', condition: (li) => { - // Only show this context menu if there are re-rollable dice in the message - const damageRolls = li.find(".apply-damage").length; + const damageRolls = li.find(".heal").length; // All must be true to show the reroll dialogue - // The button doesn't work for the GM right now, so we don't need to show it - return game["user"].character && damageRolls > 0; + return (game["user"].character || game["canvas"].tokens.controlled) && damageRolls > 0; }, callback: (li) => applyDamage(li, -2), } @@ -219,15 +211,6 @@ Hooks.on("updateCombat", function (combat: Combat, updateData: { round: number; } }); -function limitHeal(heal: number, current: number, max: number): number { - if (current === max) { - return 0; - } else if (heal + current > max) { - return max - current; - } - return heal; -} - Hooks.on("renderCombatTracker", (combatTracker, html, context) => { if (context.combat === null) { html.find("h3.encounter-title")[0].innerHTML = game["i18n"].localize("midgard5.no-encounter"); @@ -244,27 +227,29 @@ Hooks.once("ready", () => { }); async function applyDamage(roll, direction) { - const damageValue = Array.from(roll.find(".apply-damage") as HTMLElement[]) + console.log(roll, direction); + const damageValue = Array.from(roll.find(".apply") as HTMLElement[]) .map((x) => Math.max(0, Number(x.innerText))) .reduce((prev, curr) => prev + curr, 0); - const userId = game["user"].character.id; - const viewedSceneId = game["user"].viewedScene; - const token = game["actors"].get(userId).getDependentTokens(viewedSceneId)[0]?.delta.syntheticActor; + const controlledTokens = game["canvas"].tokens.controlled; const actor = game["user"].character; - if (token) { - switch (direction) { - case 2: - token["system"].lp.value -= Math.max(0, damageValue - token["system"].calc.stats.lpProtection.value); - case 1: - token["system"].ap.value -= Math.max(0, damageValue - token["system"].calc.stats.apProtection.value); - break; - case -1: - token["system"].lp.value += limitHeal(damageValue, token["system"].lp.value, token["system"].lp.max); - case -2: - token["system"].ap.value += limitHeal(damageValue, token["system"].ap.value, token["system"].ap.max); - } - token.render(); + if (controlledTokens) { + controlledTokens.forEach((controlledToken) => { + let token = controlledToken.document.delta.syntheticActor; + switch (direction) { + case 2: + token["system"].lp.value -= Math.max(0, damageValue - token["system"].calc.stats.lpProtection.value); + case 1: + token["system"].ap.value -= Math.max(0, damageValue - token["system"].calc.stats.apProtection.value); + break; + case -1: + token["system"].lp.value += limitHeal(damageValue, token["system"].lp.value, token["system"].lp.max); + case -2: + token["system"].ap.value += limitHeal(damageValue, token["system"].ap.value, token["system"].ap.max); + } + token.render(); + }); } else { switch (direction) { case 2: @@ -273,10 +258,19 @@ async function applyDamage(roll, direction) { actor["system"].ap.value -= Math.max(0, damageValue - actor["system"].calc.stats.apProtection.value); break; case -1: - actor["system"].lp.value += limitHeal(damageValue, token["system"].lp.value, token["system"].lp.max); + actor["system"].lp.value += limitHeal(damageValue, actor["system"].lp.value, actor["system"].lp.max); case -2: - actor["system"].ap.value += limitHeal(damageValue, token["system"].ap.value, token["system"].ap.max); + actor["system"].ap.value += limitHeal(damageValue, actor["system"].ap.value, actor["system"].ap.max); } actor.render(); } } + +function limitHeal(heal: number, current: number, max: number): number { + if (current === max) { + return 0; + } else if (heal + current > max) { + return max - current; + } + return heal; +} diff --git a/templates/chat/roll-m5.hbs b/templates/chat/roll-m5.hbs index 856e72b..0a10a2c 100644 --- a/templates/chat/roll-m5.hbs +++ b/templates/chat/roll-m5.hbs @@ -82,7 +82,7 @@ {{roll.label}} - {{roll.totalStr}} + {{roll.totalStr}} {{roll.result}}