From c827693e727f5cad4e93fc2b239630bcf16635e4 Mon Sep 17 00:00:00 2001 From: mstein Date: Wed, 13 Jul 2022 02:44:14 +0200 Subject: [PATCH] Adds mod calculation --- lang/de.json | 2 +- source/PreloadTemplates.ts | 1 + source/index.ts | 11 +- source/module/M5Base.ts | 111 ++++++++------ source/module/actors/M5Character.ts | 96 ++++++++---- source/module/actors/M5ModAggregate.ts | 164 +++++++++++++++++++++ source/module/items/M5Item.ts | 110 ++++++++------ source/module/sheets/M5CharacterSheet.ts | 7 + source/style/Character-sheet.less | 67 +++++++++ source/template.json | 2 +- templates/sheets/character/attribute.hbs | 13 ++ templates/sheets/character/base_values.hbs | 27 ++++ templates/sheets/character/gear.hbs | 15 ++ templates/sheets/item/item.hbs | 1 + templates/sheets/item/mod.hbs | 1 + 15 files changed, 497 insertions(+), 131 deletions(-) create mode 100644 source/module/actors/M5ModAggregate.ts create mode 100644 templates/sheets/character/attribute.hbs diff --git a/lang/de.json b/lang/de.json index b2ce85a..128e485 100644 --- a/lang/de.json +++ b/lang/de.json @@ -1,5 +1,5 @@ { - "ACTOR.TypeCharacter": "Spielfigur", + "ACTOR.TypeCharacter": "Charakter", "ACTOR.TypeNpc": "Kreatur / Nichtspielerfigur", "ACTOR.TypeVehicle": "Transportmittel / Pferd etc.", diff --git a/source/PreloadTemplates.ts b/source/PreloadTemplates.ts index 56ed6dd..143e60e 100644 --- a/source/PreloadTemplates.ts +++ b/source/PreloadTemplates.ts @@ -6,6 +6,7 @@ const preloadTemplates = async (): Promise[]> = // const templates = [ rootPath + "actor/actor-sheet.hbs" ] // This would map to our local folder of /Assets/Templates/Actor/actor-sheet.hbs const templates: Array = [ + "sheets/character/attribute.hbs", "sheets/character/base_values.hbs", "sheets/character/skills.hbs", "sheets/character/gear.hbs", diff --git a/source/index.ts b/source/index.ts index 5d9465f..1eec7ed 100644 --- a/source/index.ts +++ b/source/index.ts @@ -20,12 +20,11 @@ Hooks.once("init", async () => { return values.map(val => val.toString()).join(join) }) - // static concat(...values) { - // const options = values.pop(); - // const join = options.hash?.join || ""; - // return new Handlebars.SafeString(values.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({ diff --git a/source/module/M5Base.ts b/source/module/M5Base.ts index aac02da..83ee9de 100644 --- a/source/module/M5Base.ts +++ b/source/module/M5Base.ts @@ -1,48 +1,4 @@ -export interface M5CharacterCalculatedData { - level: number - attributes: { - st: { value: number, bonus: number } - gs: { value: number, bonus: number } - gw: { value: number, bonus: number } - ko: { value: number, bonus: number } - in: { value: number, bonus: number } - zt: { value: number, bonus: number } - au: { value: number, bonus: number } - pa: { value: number, bonus: number } - wk: { value: number, bonus: number } - } - stats: { - armor: number - defense: number - damageBonus: number - attackBonus: number - defenseBonus: number - movementBonus: number - resistanceMind: number - resistanceBody: number - spellCasting: number - brawl: number - brawlEw: number - poisonResistance: number - enduranceBonus: number - } - skills: { - innate: {} - general: {} - combat: {} - language: {} - custom: {} - } - gear: { - weapons: {} - defensiveWeapons: {} - armor: {} - items: {} - } - spells: {} -} - export interface M5Skill { fw: number attribute: string @@ -144,6 +100,73 @@ export interface M5ItemMod { value: number } +export interface M5ModPair { + mod: M5ItemMod + source: string +} + +export interface M5ModSource { + item: string + operation: M5ModOperation + value: number +} + +export interface M5ModResult { + mods: Array + value: number +} + +export interface M5AttributeCalculated extends M5ModResult { + bonus: number +} + +export interface M5CharacterCalculatedData { + level: number + attributes: { + st: M5AttributeCalculated + gs: M5AttributeCalculated + gw: M5AttributeCalculated + ko: M5AttributeCalculated + in: M5AttributeCalculated + zt: M5AttributeCalculated + au: M5AttributeCalculated + pa: M5AttributeCalculated + wk: M5AttributeCalculated + } + stats: { + lp: M5ModResult + ap: M5ModResult + armor: number + defense: M5ModResult + damageBonus: M5ModResult + attackBonus: M5ModResult + defenseBonus: M5ModResult + movementBonus: M5ModResult + resistanceMind: M5ModResult + resistanceBody: M5ModResult + spellCasting: M5ModResult + brawl: M5ModResult + brawlEw: number + poisonResistance: M5ModResult + enduranceBonus: number + } + skillMods: {} + skills: { + innate: {} + general: {} + combat: {} + language: {} + custom: {} + } + gear: { + weapons: {} + defensiveWeapons: {} + armor: {} + items: {} + } + spells: {} +} + export function enumKeys(obj: O): K[] { return Object.keys(obj).filter(k => Number.isNaN(+k)) as K[] } diff --git a/source/module/actors/M5Character.ts b/source/module/actors/M5Character.ts index 529ae2e..594dbb4 100644 --- a/source/module/actors/M5Character.ts +++ b/source/module/actors/M5Character.ts @@ -1,5 +1,6 @@ import { M5Item } from "../items/M5Item" -import { M5Attribute, M5CharacterCalculatedData, M5RollData, M5Skill, M5SkillCalculated, M5SkillLearned } from "../M5Base" +import { M5Attribute, M5CharacterCalculatedData, M5ItemMod, M5ModOperation, M5ModResult, M5RollData, M5Skill, M5SkillCalculated, M5SkillLearned } from "../M5Base" +import M5ModAggregate from "./M5ModAggregate" export class M5Character extends Actor { @@ -28,35 +29,38 @@ export class M5Character extends Actor { return -2 } - derivedData(skip: { skills?: boolean, weapons?: boolean, defensiveWeapons?: boolean, armor?: boolean, items?: boolean, spells?: boolean } = {} ): M5CharacterCalculatedData { + derivedData(skip: { mods?: boolean, skills?: boolean, weapons?: boolean, defensiveWeapons?: boolean, armor?: boolean, items?: boolean, spells?: boolean } = {} ): M5CharacterCalculatedData { let ret: M5CharacterCalculatedData = { level: 0, attributes: { - st: { value: 0, bonus: 0 }, - gs: { value: 0, bonus: 0 }, - gw: { value: 0, bonus: 0 }, - ko: { value: 0, bonus: 0 }, - in: { value: 0, bonus: 0 }, - zt: { value: 0, bonus: 0 }, - au: { value: 0, bonus: 0 }, - pa: { value: 0, bonus: 0 }, - wk: { value: 0, bonus: 0 } + st: { value: 0, bonus: 0, mods: [] }, + gs: { value: 0, bonus: 0, mods: [] }, + gw: { value: 0, bonus: 0, mods: [] }, + ko: { value: 0, bonus: 0, mods: [] }, + in: { value: 0, bonus: 0, mods: [] }, + zt: { value: 0, bonus: 0, mods: [] }, + au: { value: 0, bonus: 0, mods: [] }, + pa: { value: 0, bonus: 0, mods: [] }, + wk: { value: 0, bonus: 0, mods: [] } }, stats: { + lp: { value: 0, mods: [] }, + ap: { value: 0, mods: [] }, armor: 0, - defense: 0, - damageBonus: 0, - attackBonus: 0, - defenseBonus: 0, - movementBonus: 0, - resistanceMind: 0, - resistanceBody: 0, - spellCasting: 0, - brawl: 0, + defense: { value: 0, mods: [] }, + damageBonus: { value: 0, mods: [] }, + attackBonus: { value: 0, mods: [] }, + defenseBonus: { value: 0, mods: [] }, + movementBonus: { value: 0, mods: [] }, + resistanceMind: { value: 0, mods: [] }, + resistanceBody: { value: 0, mods: [] }, + spellCasting: { value: 0, mods: [] }, + brawl: { value: 0, mods: [] }, brawlEw: 0, - poisonResistance: 0, + poisonResistance: { value: 0, mods: [] }, enduranceBonus: 0 }, + skillMods: {}, skills: { innate: {}, general: {}, @@ -103,20 +107,37 @@ export class M5Character extends Actor { ret.attributes.pa.bonus = M5Character.attributeBonus(data.attributes.pa) ret.attributes.wk.bonus = M5Character.attributeBonus(data.attributes.wk) + ret.stats.lp = this.modResult(data.lp) + ret.stats.ap = this.modResult(data.ap) ret.stats.armor = 0 - ret.stats.defense = M5Character.defenseFromLevel(ret.level) - ret.stats.damageBonus = Math.floor(ret.attributes.st.value/20) + Math.floor(ret.attributes.gs.value/30) - 3 - ret.stats.attackBonus = ret.attributes.gs.bonus - ret.stats.defenseBonus = ret.attributes.gw.bonus - ret.stats.movementBonus = 0 - ret.stats.resistanceMind = ret.stats.defense - ret.stats.resistanceBody = ret.stats.defense + 1 - ret.stats.spellCasting = (data.info.magicUsing ? M5Character.spellCastingFromLevel(ret.level) : 3) + ret.attributes.zt.bonus - ret.stats.brawl = Math.floor((ret.attributes.st.value + ret.attributes.gw.value) / 20) - ret.stats.brawlEw = ret.stats.brawl + ret.stats.attackBonus - ret.stats.poisonResistance = 30 + Math.floor(ret.attributes.ko.value / 2) + ret.stats.defense = this.modResult(M5Character.defenseFromLevel(ret.level)) + ret.stats.damageBonus = this.modResult(Math.floor(ret.attributes.st.value/20) + Math.floor(ret.attributes.gs.value/30) - 3) + ret.stats.attackBonus = this.modResult(ret.attributes.gs.bonus) + ret.stats.defenseBonus = this.modResult(ret.attributes.gw.bonus) + ret.stats.movementBonus = this.modResult(0) + ret.stats.resistanceMind = this.modResult(ret.stats.defense.value) + ret.stats.resistanceBody = this.modResult(ret.stats.defense.value + 1) + 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.brawlEw = ret.stats.brawl.value + ret.stats.attackBonus.value + ret.stats.poisonResistance = this.modResult(30 + Math.floor(ret.attributes.ko.value / 2)) ret.stats.enduranceBonus = Math.floor(ret.attributes.ko.value/10) + Math.floor(ret.attributes.st.value/20) + if (!skip.mods) { + const aggregate = new M5ModAggregate(data, ret) + + context.items?.filter(item => item.data.type === "item").forEach(item => { + const mods = item.data.data.mods + console.log("Actor item mods", mods) + Object.keys(mods).forEach(modIndex => { + const mod = mods[modIndex] as M5ItemMod + aggregate.push(mod, item.data.name) + }) + }) + + ret.skillMods = aggregate.calculate() + } + if (!skip.items) { context.items?.filter(item => item.data.type === "item").forEach(item => { item.prepareDerivedData() @@ -306,4 +327,15 @@ export class M5Character extends Actor { return (this as any).getEmbeddedDocument("Item", itemId) } + private modResult(value: number): M5ModResult { + return { + value: value, + mods: [{ + item: (game as Game).i18n.localize("ACTOR.TypeCharacter"), + operation: M5ModOperation.SET, + value: value + }] + } + } + } diff --git a/source/module/actors/M5ModAggregate.ts b/source/module/actors/M5ModAggregate.ts new file mode 100644 index 0000000..da053f8 --- /dev/null +++ b/source/module/actors/M5ModAggregate.ts @@ -0,0 +1,164 @@ +import { M5Attribute, M5AttributeCalculated, M5Attributes, M5CharacterCalculatedData, M5ItemMod, M5ModOperation, M5ModResult, M5ModSource, M5ModType, M5Stats, M5ModPair } from "../M5Base" + +export default class M5ModAggregate { + private attributes = new Map>() + private stats = new Map>() + private skills = new Map>() + + constructor(public data: any, public calc: M5CharacterCalculatedData) { + const characterString = (game as Game).i18n.localize("ACTOR.TypeCharacter") + + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.ST, operation: M5ModOperation.SET, value: data.attributes.st.value }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.GS, operation: M5ModOperation.SET, value: data.attributes.gs.value }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.GW, operation: M5ModOperation.SET, value: data.attributes.gw.value }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.KO, operation: M5ModOperation.SET, value: data.attributes.ko.value }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.IN, operation: M5ModOperation.SET, value: data.attributes.in.value }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.ZT, operation: M5ModOperation.SET, value: data.attributes.zt.value }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.AU, operation: M5ModOperation.SET, value: data.attributes.au.value }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.PA, operation: M5ModOperation.SET, value: data.attributes.pa.value }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.WK, operation: M5ModOperation.SET, value: data.attributes.wk.value }, characterString) + + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.ST, operation: M5ModOperation.ADD_100, value: data.attributes.st.bonus }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.GS, operation: M5ModOperation.ADD_100, value: data.attributes.gs.bonus }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.GW, operation: M5ModOperation.ADD_100, value: data.attributes.gw.bonus }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.KO, operation: M5ModOperation.ADD_100, value: data.attributes.ko.bonus }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.IN, operation: M5ModOperation.ADD_100, value: data.attributes.in.bonus }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.ZT, operation: M5ModOperation.ADD_100, value: data.attributes.zt.bonus }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.AU, operation: M5ModOperation.ADD_100, value: data.attributes.au.bonus }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.PA, operation: M5ModOperation.ADD_100, value: data.attributes.pa.bonus }, characterString) + this.push({ type: M5ModType.ATTRIBUTE, id: M5Attributes.WK, operation: M5ModOperation.ADD_100, value: data.attributes.wk.bonus }, characterString) + + this.push({ type: M5ModType.STAT, id: M5Stats.DEFENSE, operation: M5ModOperation.SET, value: calc.stats.defense.value }, characterString) + this.push({ type: M5ModType.STAT, id: M5Stats.ATTACK, operation: M5ModOperation.SET, value: calc.stats.attackBonus.value }, characterString) + this.push({ type: M5ModType.STAT, id: M5Stats.DAMAGE, operation: M5ModOperation.SET, value: calc.stats.damageBonus.value }, characterString) + this.push({ type: M5ModType.STAT, id: M5Stats.MOVEMENT, operation: M5ModOperation.SET, value: calc.stats.movementBonus.value }, characterString) + this.push({ type: M5ModType.STAT, id: M5Stats.RESISTANCE_MIND, operation: M5ModOperation.SET, value: calc.stats.resistanceMind.value }, characterString) + this.push({ type: M5ModType.STAT, id: M5Stats.RESISTANCE_BODY, operation: M5ModOperation.SET, value: calc.stats.resistanceBody.value }, characterString) + this.push({ type: M5ModType.STAT, id: M5Stats.SPELL_CASTING, operation: M5ModOperation.SET, value: calc.stats.spellCasting.value }, characterString) + this.push({ type: M5ModType.STAT, id: M5Stats.BRAWL, operation: M5ModOperation.SET, value: calc.stats.brawl.value }, characterString) + this.push({ type: M5ModType.STAT, id: M5Stats.POISON_RESISTANCE, operation: M5ModOperation.SET, value: calc.stats.poisonResistance.value }, characterString) + this.push({ type: M5ModType.STAT, id: M5Stats.LP, operation: M5ModOperation.SET, value: calc.stats.lp.value }, characterString) + this.push({ type: M5ModType.STAT, id: M5Stats.AP, operation: M5ModOperation.SET, value: calc.stats.ap.value }, characterString) + } + + push(mod: M5ItemMod, source: string) { + if (!mod?.id || mod.id === "") + return + + let map: Map> = null + if (mod.type === M5ModType.ATTRIBUTE) + map = this.attributes + else if (mod.type === M5ModType.STAT) + map = this.stats + else if (mod.type === M5ModType.SKILL) + map = this.skills + + if (map) { + const pair: M5ModPair = { + mod: mod, + source: source + } + + let key = mod.id + if (mod.type === M5ModType.ATTRIBUTE) + key = (mod.id + "").toLowerCase() + else if (mod.type === M5ModType.STAT) + key = (mod.id + "").toLowerCase() + + if (map.has(key)) + map.get(key).push(pair) + else + map.set(key, [pair]) + } + } + + calculate() { + const calc = this.calc + + this.attributes.forEach((pairs, id) => { + const res = M5ModAggregate.processPairs(pairs) + calc.attributes[id] = { + value: res.value, + bonus: M5ModAggregate.attributeBonus(res.value), + mods: res.mods + } as M5AttributeCalculated + //console.log("calc.attributes." + id, calc.attributes[id]) + }) + + this.stats.forEach((pairs, id) => { + const res = M5ModAggregate.processPairs(pairs) + calc.stats[id] = res + }) + + const ret = {} + this.skills.forEach((pairs, id) => { + ret[id] = pairs + }) + + return ret + } + + static pairAsSource(pair: M5ModPair): M5ModSource { + return { + operation: pair.mod.operation, + value: pair.mod.value, + item: pair.source + } + } + + static processPairs(arr: Array): M5ModResult { + let ret: M5ModResult = { + mods: [], + value: 0 + } + + let mods = arr.filter(pair => pair.mod.operation === M5ModOperation.FIXED).sort((a, b) => b.mod.value - a.mod.value) + let pair = mods.length === 0 ? null : mods[0] + + if (pair) { + ret.mods.push(this.pairAsSource(pair)) + ret.value = pair.mod.value + } else { + mods = arr.filter(pair => pair.mod.operation === M5ModOperation.SET).sort((a, b) => b.mod.value - a.mod.value) + if (mods.length !== 0) { + ret.mods.push(this.pairAsSource(mods[0])) + ret.value = mods[0].mod.value + } + + mods = arr.filter(pair => pair.mod.operation === M5ModOperation.ADD_100) + if (mods.length !== 0) { + ret.mods = ret.mods.concat(mods.map(this.pairAsSource)) + const bonus = mods.map(p => p.mod.value).reduce((a, b) => a + b, 0) + ret.value = Math.min(100, Math.max(0, ret.value + bonus)) + } + + mods = arr.filter(pair => pair.mod.operation === M5ModOperation.ADD) + if (mods.length !== 0) { + ret.mods = ret.mods.concat(mods.map(this.pairAsSource)) + const bonus = mods.map(p => p.mod.value).reduce((a, b) => a + b, 0) + ret.value = Math.max(0, ret.value + bonus) + } + } + + return ret + } + + static attributeMinMax(attribute: M5Attribute) { + return Math.min(100, Math.max(0, attribute.value + attribute.bonus)) + } + + static attributeBonus(value: number) { + if (value > 95) + return 2 + if (value > 80) + return 1 + if (value > 20) + return 0 + if (value > 5) + return -1 + return -2 + } + + //static modToString(mod: M5ItemMod): string { } + +} diff --git a/source/module/items/M5Item.ts b/source/module/items/M5Item.ts index 212c53f..521d3bf 100644 --- a/source/module/items/M5Item.ts +++ b/source/module/items/M5Item.ts @@ -1,7 +1,6 @@ -import { ItemData } from "@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/module.mjs" -import { ConstructorDataType } from "@league-of-foundry-developers/foundry-vtt-types/src/types/helperTypes" import { M5Character } from "../actors/M5Character" -import { enumKeys, M5Attributes, M5ItemMod, M5ModType, M5RollData, M5RollResult, M5Skill, M5Stats } from "../M5Base" +import M5ModAggregate from "../actors/M5ModAggregate" +import { enumKeys, M5Attributes, M5ModOperation, M5ModPair, M5ModType, M5RollData, M5RollResult, M5Stats } from "../M5Base" import { M5Roll } from "../rolls/M5Roll" export class M5Item extends Item { @@ -14,15 +13,48 @@ export class M5Item extends Item { const calc = context.data.calc if (context.type === "skill") { + calc.fw = context.data.fw calc.bonus = 0 - if (context.data?.attribute && context.data?.attribute !== "" && character) { - const attribute = character.attribute(context.data.attribute) - if (attribute) - calc.bonus += M5Character.attributeBonus(attribute) + let pairs: Array = [{ + source: context.name, + mod: { + type: M5ModType.SKILL, + id: context._id, + operation: M5ModOperation.SET, + value: context.data.fw + } + }] + + if (character) { + const actorCalc = character.derivedData({ skills: true, weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true }) + if (actorCalc?.skillMods && Object.keys(actorCalc.skillMods).indexOf(context._id) !== -1) { + pairs = pairs.concat(actorCalc.skillMods[context._id]) + } + + if (context.data?.attribute && context.data?.attribute !== "") { + pairs.push({ + source: context.name, + mod: { + type: M5ModType.SKILL, + id: context._id, + operation: M5ModOperation.ADD, + value: actorCalc.attributes[context.data.attribute].bonus + } + }) + } } - calc.ew = context.data.fw + calc.bonus + const res = M5ModAggregate.processPairs(pairs) + res.mods.forEach(mod => { + if ([M5ModOperation.SET, M5ModOperation.FIXED].includes(mod.operation)) + calc.fw = mod.value + else + calc.bonus += mod.value + }) + + calc.ew = calc.fw + calc.bonus + calc.sources = res.mods } else if (context.type === "weapon") { calc.fw = 0 calc.bonus = 0 @@ -57,7 +89,7 @@ export class M5Item extends Item { if (actor) { const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true }) if (actorCalc) { - calc.ew += actorCalc.stats.defense + actorCalc.stats.defenseBonus + calc.ew += actorCalc.stats.defense.value + actorCalc.stats.defenseBonus.value calc.combatSkills = actorCalc.skills.combat } @@ -79,43 +111,6 @@ export class M5Item extends Item { calc.ew += actorCalc.stats.spellCasting } } - } else if (context.type === "mod") { - const parent = (this as any).parent - const actor = parent?.actor - const character = actor as M5Character - - calc.ids = {} - - switch (context.data.type as M5ModType) { - case M5ModType.ATTRIBUTE: { - for (const key of enumKeys(M5Attributes)) { - const val = M5Attributes[key] - calc.ids[key] = (game as Game).i18n.localize(`midgard5.actor-${val}-long`) - } - break - } - case M5ModType.STAT: { - for (const key of enumKeys(M5Stats)) { - const val = M5Stats[key] - calc.ids[key] = (game as Game).i18n.localize(`midgard5.mod-stat-${val}`) - } - break - } - case M5ModType.SKILL: { - if (character) { - const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true }) - if (actorCalc) { - let category = (game as Game).i18n.localize("midgard5.innate-ability") - Object.keys(actorCalc.skills.innate).forEach(skillId => { - const skill = character.getItem(skillId) - if (skill) - calc.ids[skillId] = `${category}: ${skill.data.name}` - }) - } - } - break - } - } } else if (context.type === "item") { calc.mods = {} Object.keys(context.data?.mods).forEach(key => { @@ -140,7 +135,28 @@ export class M5Item extends Item { if (character) { const actorCalc = character.derivedData({ weapons: true, defensiveWeapons: true, armor: true, items: true, spells: true }) if (actorCalc) { - let category = (game as Game).i18n.localize("midgard5.innate-ability") + let category = (game as Game).i18n.localize("midgard5.skill") + Object.keys(actorCalc.skills.general).forEach(skillId => { + const skill = character.getItem(skillId) + if (skill) + modCalc[skillId] = `${category}: ${skill.data.name}` + }) + + category = (game as Game).i18n.localize("midgard5.language") + Object.keys(actorCalc.skills.language).forEach(skillId => { + const skill = character.getItem(skillId) + if (skill) + modCalc[skillId] = `${category}: ${skill.data.name}` + }) + + category = (game as Game).i18n.localize("midgard5.weapon-skill") + Object.keys(actorCalc.skills.combat).forEach(skillId => { + const skill = character.getItem(skillId) + if (skill) + modCalc[skillId] = `${category}: ${skill.data.name}` + }) + + category = (game as Game).i18n.localize("midgard5.innate-ability") Object.keys(actorCalc.skills.innate).forEach(skillId => { const skill = character.getItem(skillId) if (skill) diff --git a/source/module/sheets/M5CharacterSheet.ts b/source/module/sheets/M5CharacterSheet.ts index 8213fad..d9520c9 100644 --- a/source/module/sheets/M5CharacterSheet.ts +++ b/source/module/sheets/M5CharacterSheet.ts @@ -35,6 +35,13 @@ export default class M5CharacterSheet extends ActorSheet { }) } + override setPosition(options = {}) { + const position = super.setPosition(options) + const fillerWidth = this.element.find(".attributes .filler:first").width() + this.element.find(".attributes .attribute-filler-fixed").width(fillerWidth) + return position; + } + override activateListeners(html: JQuery) { super.activateListeners(html) diff --git a/source/style/Character-sheet.less b/source/style/Character-sheet.less index 1cc57d2..e3f29c7 100644 --- a/source/style/Character-sheet.less +++ b/source/style/Character-sheet.less @@ -1,4 +1,6 @@ // main: midgard5.less +@borderGroove: 2px groove #eeede0; +@attributeBorderColor: rgba(0, 0, 0, 0.5); .midgard5 { .flexrow { @@ -83,4 +85,69 @@ color:rgb(93, 93, 93); font-style: italic; } + + .filler { + flex: 1 1 auto; + } + + .attributes { + display: flex; + flex-direction: row; + margin-bottom: 0.5rem; + + .attribute { + flex: 0 0 7rem; + margin: 0; + border: 1px solid @attributeBorderColor; + //border-bottom: none; + border-radius: 10; + + display: flex; + flex-direction: column; + + .attribute-header { + display: flex; + align-items: center; + text-align: center; + justify-content: center; + + font-weight: bold; + background-color: @attributeBorderColor; + color:rgba(255, 255, 255, 1); + + //font-size: 1.0rem; + height: 2.5rem; + } + + .attribute-main { + padding: 0.2rem; + + .attribute-main-value { + text-align: center; + vertical-align: middle; + font-size: 2rem; + } + + .attribute-main-bonus { + text-align: center; + vertical-align: middle; + font-size: 1rem; + } + } + + .attribute-footer { + display: flex; + flex-direction: row; + gap: 0.3rem; + padding: 0.3rem; + background-color: @attributeBorderColor; + + input { + flex-grow: 1; + text-align: center; + background-color: rgba(255, 255, 255, 0.8); + } + } + } + } } \ No newline at end of file diff --git a/source/template.json b/source/template.json index 133d4af..fef1056 100644 --- a/source/template.json +++ b/source/template.json @@ -216,7 +216,7 @@ "rolls": { "formulas": { "0": { - "formula": "1d20 + @i.fw + @i.calc.bonus", + "formula": "1d20 + @i.calc.fw + @i.calc.bonus", "type": "ew", "label": "EW", "enabled": true diff --git a/templates/sheets/character/attribute.hbs b/templates/sheets/character/attribute.hbs new file mode 100644 index 0000000..7c05dfe --- /dev/null +++ b/templates/sheets/character/attribute.hbs @@ -0,0 +1,13 @@ +
+
{{localize (m5concat "midgard5.actor-" attributeId "-long")}}
+ +
+
{{calc.value}}
+
{{calc.bonus}}
+
+ + +
\ No newline at end of file diff --git a/templates/sheets/character/base_values.hbs b/templates/sheets/character/base_values.hbs index 9136b52..4f5a581 100644 --- a/templates/sheets/character/base_values.hbs +++ b/templates/sheets/character/base_values.hbs @@ -29,6 +29,32 @@

Leiteigenschaften

+ +
+ {{> "systems/midgard5/templates/sheets/character/attribute.hbs" attributeId="st" attribute=data.attributes.st calc=data.calc.attributes.st}} +
+ {{> "systems/midgard5/templates/sheets/character/attribute.hbs" attributeId="gs" attribute=data.attributes.gs calc=data.calc.attributes.gs}} +
+ {{> "systems/midgard5/templates/sheets/character/attribute.hbs" attributeId="gw" attribute=data.attributes.gw calc=data.calc.attributes.gw}} +
+ {{> "systems/midgard5/templates/sheets/character/attribute.hbs" attributeId="ko" attribute=data.attributes.ko calc=data.calc.attributes.ko}} +
+ {{> "systems/midgard5/templates/sheets/character/attribute.hbs" attributeId="in" attribute=data.attributes.in calc=data.calc.attributes.in}} +
+ +
+
+ {{> "systems/midgard5/templates/sheets/character/attribute.hbs" attributeId="zt" attribute=data.attributes.zt calc=data.calc.attributes.zt}} +
+ {{> "systems/midgard5/templates/sheets/character/attribute.hbs" attributeId="au" attribute=data.attributes.au calc=data.calc.attributes.au}} +
+ {{> "systems/midgard5/templates/sheets/character/attribute.hbs" attributeId="pa" attribute=data.attributes.pa calc=data.calc.attributes.pa}} +
+ {{> "systems/midgard5/templates/sheets/character/attribute.hbs" attributeId="wk" attribute=data.attributes.wk calc=data.calc.attributes.wk}} +
+
+ +

Berechnete Werte

diff --git a/templates/sheets/character/gear.hbs b/templates/sheets/character/gear.hbs index e204062..18e56b9 100644 --- a/templates/sheets/character/gear.hbs +++ b/templates/sheets/character/gear.hbs @@ -75,3 +75,18 @@ {{/each}}
+ + + + + + + + + {{#each data.calc.gear.items as |item itemId|}} + + + + {{/each}} + +
{{localize "ITEM.TypeItem"}}
{{item.label}}
diff --git a/templates/sheets/item/item.hbs b/templates/sheets/item/item.hbs index 39338a1..fb7ebc0 100644 --- a/templates/sheets/item/item.hbs +++ b/templates/sheets/item/item.hbs @@ -44,6 +44,7 @@ {{#select data.id}} + {{#each data.calc.ids as |name key|}} {{/each}}