diff --git a/gulpfile.mjs b/gulpfile.mjs index 9bf1cc29..0c1c432d 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -45,13 +45,14 @@ const convert = function (from, to, ofType) { readdirSync(SOURCE).forEach(file => { let originalSource = JSON.parse(readFileSync(join(SOURCE, file), {encoding: "utf8"})); let id = randomID(); + let targetSource = { _id: id, _key: "!items!" + id, type: TYPE, img: originalSource.image, name: originalSource.name.trim(), - system: {...originalSource} + system: {...originalSource}, } delete targetSource.system.image; let target = JSON.stringify(targetSource, null, 2); @@ -101,6 +102,7 @@ async function prepareDB() { convert("./src/packs/_source/munition", "./src/packs/__source/munition", "Equipment"); convert("./src/packs/_source/ruestzeug", "./src/packs/__source/ruestzeug", "Equipment"); convert("./src/packs/_source/liturgien-und-segnungen", "./src/packs/__source/liturgien", "Liturgy"); + convert("./src/packs/_source/wunden", "./src/packs/__source/wunden", "ActiveEffect"); } catch (err) { console.error(err); diff --git a/src/main.mjs b/src/main.mjs index 6355cf2a..13cc781c 100644 --- a/src/main.mjs +++ b/src/main.mjs @@ -127,6 +127,54 @@ Hooks.once("init", () => { label: 'DSA41.ActiveEffectLabels.ActiveFfect' }) + game.settings.register('DSA_4-1', 'optional_trefferzonen', { + name: "Optional: Trefferzonen", + hint: "Ersetzt das Wundensystem aus dem BRW durch das Trefferzonensystem aus WdH", + scope: "world", + config: true, + type: Boolean, + default: false, + onChange: value => { + }, + requiresReload: true + }) + + game.settings.register('DSA_4-1', 'optional_ruestungzonen', { + name: "Optional: Zonenrüstung", + hint: "Ersetzt das Rüstungssystem aus dem BRW durch das Zonenrüstungssystem aus WdH", + scope: "world", + config: true, + type: Boolean, + default: false, + onChange: value => { + }, + requiresReload: true + }) + + game.settings.register('DSA_4-1', 'optional_ausdauer', { + name: "Optional: Ausdauerregeln", + hint: "Aktiviert Regeln für das Spiel mit Ausdauer", + scope: "world", + config: true, + type: Boolean, + default: false, + onChange: value => { + }, + requiresReload: true + }) + + game.settings.register('DSA_4-1', 'optional_distanzklassen', { + name: "Optional: Distanzklassen", + hint: "Aktiviert Regeln für das Spiel mit Distanzklassen", + scope: "world", + config: true, + type: Boolean, + default: false, + onChange: value => { + }, + requiresReload: true + }) + return preloadHandlebarsTemplates(); }) diff --git a/src/module/data/activeeffect.mjs b/src/module/data/activeeffect.mjs index 929cb489..e5257eca 100644 --- a/src/module/data/activeeffect.mjs +++ b/src/module/data/activeeffect.mjs @@ -1,6 +1,6 @@ import BaseItem from "./base-item.mjs"; -const {ArrayField, NumberField, StringField, HTMLField} = foundry.data.fields; +const {ArrayField, BooleanField, NumberField, AnyField, StringField, HTMLField} = foundry.data.fields; export class ActiveEffectDataModel extends BaseItem { @@ -8,6 +8,8 @@ export class ActiveEffectDataModel extends BaseItem { return { name: new StringField({required: true}), notes: new HTMLField(), + unique: new BooleanField({initial: false}), + effects: new AnyField() } /* @@ -33,12 +35,13 @@ export class ActiveEffectDataModel extends BaseItem { _onCreate(data, options, userId) { super._onCreate(data, options, userId); - if (this.parent.getEmbeddedCollection("ActiveEffect").contents.length === 0) { + console.log(data); + if (this.parent.getEmbeddedCollection("ActiveEffect").contents.length === 0) { this.parent.createEmbeddedDocuments("ActiveEffect", [{ name: data.name, - changes: [], + changes: data.system.effects, duration: {}, icon: this.img, }]); diff --git a/src/module/data/character.mjs b/src/module/data/character.mjs index 1c257cab..693c7fb5 100644 --- a/src/module/data/character.mjs +++ b/src/module/data/character.mjs @@ -55,6 +55,10 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { aktuell: new NumberField({required: true, integer: true, initial: 0}), mod: new NumberField({required: true, integer: true}), }), + gs: new SchemaField({ + aktuell: new NumberField({required: true, integer: true, initial: 0}), + mod: new NumberField({required: true, integer: true}), + }), attribute: new SchemaField({ mu: new SchemaField({ start: new NumberField({required: true, integer: true}), @@ -125,7 +129,18 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { key: new StringField(), notiz: new StringField(), })), - + wunden: new SchemaField({ + aktuell: new NumberField({required: true, integer: true}), // only with DSA_4-1.optional_trefferzonen = false + max: new NumberField({required: true, integer: true}), // only with DSA_4-1.optional_trefferzonen = false + mod: new NumberField({required: true, integer: true}), // only with DSA_4-1.optional_trefferzonen = false + armlinks: new NumberField({required: true, integer: true, initial: 0}), + armrechts: new NumberField({required: true, integer: true, initial: 0}), + beinlinks: new NumberField({required: true, integer: true, initial: 0}), + beinrechts: new NumberField({required: true, integer: true, initial: 0}), + bauch: new NumberField({required: true, integer: true, initial: 0}), + torso: new NumberField({required: true, integer: true, initial: 0}), + kopf: new NumberField({required: true, integer: true, initial: 0}), + }), heldenausruestung: new ArrayField( new SchemaField({ links: new DocumentIdField(), diff --git a/src/module/documents/character.mjs b/src/module/documents/character.mjs index 4393b264..c6e5ce3d 100644 --- a/src/module/documents/character.mjs +++ b/src/module/documents/character.mjs @@ -28,63 +28,167 @@ export class Character extends Actor { const actorData = this; const systemData = actorData.system; - const mu = systemData.attribute.mu.aktuell + systemData.attribute.mu.mod; - const kl = systemData.attribute.kl.aktuell + systemData.attribute.kl.mod; - const _in = systemData.attribute.in.aktuell + systemData.attribute.in.mod; - const ch = systemData.attribute.ch.aktuell + systemData.attribute.ch.mod; + systemData.attribute.mu.aktuell = systemData.attribute.mu.start + systemData.attribute.mu.mod; + systemData.attribute.kl.aktuell = systemData.attribute.kl.start + systemData.attribute.kl.mod; + systemData.attribute.in.aktuell = systemData.attribute.in.start + systemData.attribute.in.mod; + systemData.attribute.ch.aktuell = systemData.attribute.ch.start + systemData.attribute.ch.mod; - const ff = systemData.attribute.ff.aktuell + systemData.attribute.ff.mod; - const ge = systemData.attribute.ge.aktuell + systemData.attribute.ge.mod; - const ko = systemData.attribute.kk.aktuell + systemData.attribute.ko.mod; - const kk = systemData.attribute.kk.aktuell + systemData.attribute.kk.mod; + systemData.attribute.ff.aktuell = systemData.attribute.ff.start + systemData.attribute.ff.mod; + systemData.attribute.ge.aktuell = systemData.attribute.ge.start + systemData.attribute.ge.mod; + systemData.attribute.ko.aktuell = systemData.attribute.ko.start + systemData.attribute.ko.mod; + systemData.attribute.kk.aktuell = systemData.attribute.kk.start + systemData.attribute.kk.mod; + const mu = systemData.attribute.mu.aktuell; + const kl = systemData.attribute.kl.aktuell; + const _in = systemData.attribute.in.aktuell; + const ch = systemData.attribute.ch.aktuell; + const ff = systemData.attribute.ff.aktuell; + const ge = systemData.attribute.ge.aktuell; + const ko = systemData.attribute.ko.aktuell; + const kk = systemData.attribute.kk.aktuell; systemData.lep.max = Math.round((ko + ko + kk) / 2) + systemData.lep.mod; systemData.aup.max = Math.round((mu + ko + ge) / 2) + systemData.aup.mod; systemData.asp.max = Math.round((mu + _in + ch) / 2) + systemData.asp.mod; - systemData.at = Math.round((mu + ge + kk) / 5); - systemData.pa = Math.round((_in + ge + kk) / 5); - systemData.fk = Math.round((_in + ff + kk) / 5); + systemData.at = systemData.at ?? {links: {}, rechts: {}} + systemData.at.links = systemData.at.links ?? { + aktuell: 0, + mods: 0 + } + systemData.at.rechts = systemData.at.rechts ?? { + aktuell: 0, + mods: 0 + } + systemData.at.basis = Math.round((mu + ge + kk) / 5) + systemData.at.aktuell = systemData.at.basis + (systemData.at.mod ?? 0); + systemData.at.links.aktuell = systemData.at.basis + (systemData.at.links.mod ?? 0); + systemData.at.rechts.aktuell = systemData.at.basis + (systemData.at.rechts.mod ?? 0); + systemData.pa = systemData.pa ?? {links: {}, rechts: {}} + systemData.pa.links = systemData.pa.links ?? { + aktuell: 0, + mods: 0 + } + systemData.pa.rechts = systemData.pa.rechts ?? { + aktuell: 0, + mods: 0 + } + systemData.pa.basis = Math.round((_in + ge + kk) / 5); + systemData.pa.aktuell = systemData.pa.basis + (systemData.pa.mod ?? 0); + systemData.pa.links.aktuell = systemData.pa.basis + (systemData.pa.links.mod ?? 0); + systemData.pa.rechts.aktuell = systemData.pa.basis + (systemData.pa.links.mod ?? 0); + systemData.fk = systemData.fk ?? { + aktuell: 0, + mods: 0 + } + systemData.fk.basis = Math.round((_in + ff + kk) / 5); + systemData.fk.aktuell = systemData.fk.basis + (systemData.fk.mod ?? 0); - systemData.ini.aktuell = Math.round((mu + mu + _in + ge) / 5) + systemData.ini.mod; - systemData.mr.aktuell = Math.round((mu + kl + ko) / 5) + systemData.mr.mod; + systemData.ini.basis = Math.round((mu + mu + _in + ge) / 5) + systemData.ini.aktuell = systemData.ini.basis + (systemData.ini.mod ?? 0); + systemData.mr.basis = Math.round((mu + kl + ko) / 5) + systemData.mr.aktuell = systemData.mr.basis + (systemData.mr.mod ?? 0); + systemData.gs.basis = 6; + systemData.gs.aktuell = systemData.gs.basis + (systemData.gs.mod ?? 0); // TOOD: get GS from species - systemData.rs = 0; + + if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { + systemData.rs = { + torso: 0, + bauch: 0, + armlinks: 0, + armrechts: 0, + beinlinks: 0, + beinrechts: 0, + kopf: 0, + }; // only with DSA_4-1.optional_trefferzonen = true + } else { + systemData.rs = 0; // only with DSA_4-1.optional_trefferzonen = false + } systemData.be = 0; + + // half KO is the maximum a character can sustain wounds before collapsing + systemData.wunden.max = ko / 2; + if (game.settings.get("DSA_4-1", "optional_trefferzonen")) { + systemData.wunden.kopf = 0; + systemData.wunden.torso = 0; + systemData.wunden.bauch = 0; + systemData.wunden.armlinks = 0; + systemData.wunden.armrechts = 0; + systemData.wunden.beinlinks = 0; + systemData.wunden.beinrechts = 0; + } + + // map current set to RS and BE const ausruestung = systemData.heldenausruestung[systemData.setEquipped]; if (ausruestung) { if (ausruestung.brust) { - systemData.rs += systemData.parent.items.get(ausruestung.brust).system.armorValue ?? 0 systemData.be += systemData.parent.items.get(ausruestung.brust).system.armorHandicap ?? 0 + if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { + systemData.rs.torso = systemData.parent.items.get(ausruestung.brust).system.armorValue ?? 0 + } else { + systemData.rs += systemData.parent.items.get(ausruestung.brust).system.armorValue ?? 0 + } } if (ausruestung.bauch) { - systemData.rs += systemData.parent.items.get(ausruestung.bauch).system.armorValue ?? 0 systemData.be += systemData.parent.items.get(ausruestung.bauch).system.armorHandicap ?? 0 + if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { + systemData.rs.bauch = systemData.parent.items.get(ausruestung.bauch).system.armorValue ?? 0 + } else { + systemData.rs += systemData.parent.items.get(ausruestung.bauch).system.armorValue ?? 0 + } } if (ausruestung.ruecken) { - systemData.rs += systemData.parent.items.get(ausruestung.ruecken).system.armorValue ?? 0 systemData.be += systemData.parent.items.get(ausruestung.ruecken).system.armorHandicap ?? 0 + if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { + // ruecken is not a valid trefferzone + } else { + systemData.rs += systemData.parent.items.get(ausruestung.ruecken).system.armorValue ?? 0 + } } if (ausruestung.armlinks) { - systemData.rs += systemData.parent.items.get(ausruestung.armlinks).system.armorValue ?? 0 systemData.be += systemData.parent.items.get(ausruestung.armlinks).system.armorHandicap ?? 0 + if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { + systemData.rs.armlinks = systemData.parent.items.get(ausruestung.armlinks).system.armorValue ?? 0 + } else { + systemData.rs += systemData.parent.items.get(ausruestung.armlinks).system.armorValue ?? 0 + } } if (ausruestung.armrechts) { - systemData.rs += systemData.parent.items.get(ausruestung.armrechts).system.armorValue ?? 0 systemData.be += systemData.parent.items.get(ausruestung.armrechts).system.armorHandicap ?? 0 + if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { + systemData.rs.armrechts = systemData.parent.items.get(ausruestung.armrechts).system.armorValue ?? 0 + } else { + systemData.rs += systemData.parent.items.get(ausruestung.armrechts).system.armorValue ?? 0 + } } if (ausruestung.beinlinks) { - systemData.rs += systemData.parent.items.get(ausruestung.beinlinks).system.armorValue ?? 0 systemData.be += systemData.parent.items.get(ausruestung.beinlinks).system.armorHandicap ?? 0 + if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { + systemData.rs.beinlinks = systemData.parent.items.get(ausruestung.beinlinks).system.armorValue ?? 0 + } else { + systemData.rs += systemData.parent.items.get(ausruestung.beinlinks).system.armorValue ?? 0 + } } if (ausruestung.beinrechts) { - systemData.rs += systemData.parent.items.get(ausruestung.beinrechts).system.armorValue ?? 0 systemData.be += systemData.parent.items.get(ausruestung.beinrechts).system.armorHandicap ?? 0 + if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { + systemData.rs.beinrechts = systemData.parent.items.get(ausruestung.beinrechts).system.armorValue ?? 0 + } else { + systemData.rs += systemData.parent.items.get(ausruestung.beinrechts).system.armorValue ?? 0 + } + } + if (ausruestung.kopf) { + systemData.be += systemData.parent.items.get(ausruestung.kopf).system.armorHandicap ?? 0 + if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { + systemData.rs.kopf = systemData.parent.items.get(ausruestung.kopf).system.armorValue ?? 0 + } else { + systemData.rs += systemData.parent.items.get(ausruestung.kopf).system.armorValue ?? 0 + } } } diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 7cdef543..5e143b4f 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -125,6 +125,19 @@ export class CharacterSheet extends ActorSheet { context.name = context.derived.name ?? actorData.name; context.effects = actorData.effects ?? []; + context.maxWounds = actorData.system.wunden.max ?? 3; + context.wounds = actorData.system.wunden.aktuell ?? 0; + context.woundsFilled = []; + for (let i = 1; i <= context.maxWounds; i++) { + context.woundsFilled[i] = i <= context.wounds + } + + context.zonenruestung = game.settings.get("DSA_4-1", "optional_ruestungzonen") + context.trefferzonen = game.settings.get("DSA_4-1", "optional_trefferzonen") + context.ausdauer = game.settings.get("DSA_4-1", "optional_ausdauer") + + + this.#addEffectsToContext(context) this.#addSkillsToContext(context) this.#addAdvantagesToContext(context) this.#addSpecialAbilitiesToContext(context) @@ -137,6 +150,43 @@ export class CharacterSheet extends ActorSheet { return context; } + #addEffectsToContext(context) { + const actorData = context.data; + + context.isGM = game.user.isGM + context.effects = []; + Object.values(actorData.items).forEach((item, index) => { + if (item.type === "ActiveEffect") { + const effect = item.effects[0]; + const conditions = [] + + if (effect) { + effect.changes.forEach(change => { + if (change.key.indexOf("wunden") === -1) { + const key = change.key + .replace(/system\./g, "") + .replace(/\.mod/g, "") + .replace(/attribute./g, "") + .replace(/.links/g, "(Links)") + .replace(/.rechts/g, "(Rechts)") + const value = Number(change.value) > 0 ? "+" + change.value : change.value; + conditions.push( + `${key}${value}` + ) + } + }) + } + + context.effects.push({ + name: item.name, + conditions: conditions.join(" "), + id: item._id, + actor: actorData._id + }); + } + }) + } + #addSpellsToContext(context) { const actorData = context.data; context.spells = []; @@ -189,56 +239,60 @@ export class CharacterSheet extends ActorSheet { "ff": await this.#getModsOfAttribute('system.attribute.ff.mod'), "ge": await this.#getModsOfAttribute('system.attribute.ge.mod'), "ko": await this.#getModsOfAttribute('system.attribute.ko.mod'), - "kk": await this.#getModsOfAttribute('system.attribute.kk.mod') + "kk": await this.#getModsOfAttribute('system.attribute.kk.mod'), + "at": await this.#getModsOfAttribute('system.at.mod'), + "pa": await this.#getModsOfAttribute('system.pa.mod'), + "fk": await this.#getModsOfAttribute('system.fk.mod'), + } context.attributes = [ { eigenschaft: "mu", name: "MU", tooltip: "Mut", - wert: (context.derived.attribute.mu.aktuell + context.derived.attribute.mu.mod) ?? 0, + wert: context.derived.attribute.mu.aktuell ?? 0, }, { eigenschaft: "kl", name: "KL", tooltip: "Klugheit", - wert: (context.derived.attribute.kl.aktuell + context.derived.attribute.kl.mod) ?? 0, + wert: context.derived.attribute.kl.aktuell ?? 0, }, { eigenschaft: "in", name: "IN", tooltip: "Intuition", - wert: (context.derived.attribute.in.aktuell + context.derived.attribute.in.mod) ?? 0, + wert: context.derived.attribute.in.aktuell ?? 0, }, { eigenschaft: "ch", name: "CH", tooltip: "Charisma", - wert: (context.derived.attribute.ch.aktuell + context.derived.attribute.ch.mod) ?? 0, + wert: context.derived.attribute.ch.aktuell ?? 0, }, { eigenschaft: "ff", name: "FF", tooltip: "Fingerfertigkeit", - wert: (context.derived.attribute.ff.aktuell + context.derived.attribute.ff.mod) ?? 0, + wert: context.derived.attribute.ff.aktuell ?? 0, }, { eigenschaft: "ge", name: "GE", tooltip: "Geschicklichkeit", - wert: (context.derived.attribute.ge.aktuell + context.derived.attribute.ge.mod) ?? 0, + wert: context.derived.attribute.ge.aktuell ?? 0, }, { eigenschaft: "ko", name: "KO", tooltip: "Konstitution", - wert: (context.derived.attribute.ko.aktuell + context.derived.attribute.ko.mod) ?? 0, + wert: context.derived.attribute.ko.aktuell ?? 0, }, { eigenschaft: "kk", name: "KK", tooltip: "Körperkraft", - wert: (context.derived.attribute.kk.aktuell + context.derived.attribute.kk.mod) ?? 0, + wert: context.derived.attribute.kk.aktuell ?? 0, }, ]; @@ -329,8 +383,8 @@ export class CharacterSheet extends ActorSheet { context.attacks.push({ name: obj.name, using: fernkampf.name, - atroll: `1d20 + ${this.object.system.fk + obj.system.at}`, - at: `1w20 + ${this.object.system.fk + obj.system.at}`, + atroll: `1d20 + ${this.object.system.fk.aktuell + obj.system.at}`, + at: `1w20 + ${this.object.system.fk.aktuell + obj.system.at}`, iniroll: `(${context.inidice})d6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`, ini: `${context.inidice}w6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`, }) @@ -343,10 +397,10 @@ export class CharacterSheet extends ActorSheet { context.attacks.push({ name: obj.name, using: links.name, - atroll: `1d20 + ${this.object.system.at + obj.system.at + links.system.attackModifier}`, - at: `1w20 + ${this.object.system.at + obj.system.at + links.system.attackModifier}`, - paroll: `1d20 + ${this.object.system.pa + obj.system.pa + links.system.parryModifier}`, - pa: `1w20 + ${this.object.system.pa + obj.system.pa + links.system.parryModifier}`, + atroll: `1d20 + ${this.object.system.at.links.aktuell + obj.system.at + links.system.attackModifier}`, + at: `1w20 + ${this.object.system.at.links.aktuell + obj.system.at + links.system.attackModifier}`, + paroll: `1d20 + ${this.object.system.pa.links.aktuell + obj.system.pa + links.system.parryModifier}`, + pa: `1w20 + ${this.object.system.pa.links.aktuell + obj.system.pa + links.system.parryModifier}`, iniroll: `(${context.inidice})d6 + ${context.inivalue + links.system.iniModifier ?? 0}`, ini: `${context.inidice}w6 + ${context.inivalue + links.system.iniModifier ?? 0}`, }) @@ -360,10 +414,10 @@ export class CharacterSheet extends ActorSheet { context.attacks.push({ name: obj.name, using: rechts.name, - atroll: `1d20 + ${this.object.system.at + obj.system.at + rechts.system.attackModifier}`, - at: `1w20 + ${this.object.system.at + obj.system.at + rechts.system.attackModifier}`, - paroll: `1d20 + ${this.object.system.pa + obj.system.pa + rechts.system.parryModifier}`, - pa: `1w20 + ${this.object.system.pa + obj.system.pa + rechts.system.parryModifier}`, + atroll: `1d20 + ${this.object.system.at.rechts.aktuell + obj.system.at + rechts.system.attackModifier}`, + at: `1w20 + ${this.object.system.at.rechts.aktuell + obj.system.at + rechts.system.attackModifier}`, + paroll: `1d20 + ${this.object.system.pa.rechts.aktuell + obj.system.pa + rechts.system.parryModifier}`, + pa: `1w20 + ${this.object.system.pa.rechts.aktuell + obj.system.pa + rechts.system.parryModifier}`, iniroll: `(${context.inidice})d6 + ${context.inivalue + rechts.system.iniModifier ?? 0}`, ini: `${context.inidice}w6 + ${context.inivalue + rechts.system.iniModifier ?? 0}`, }) @@ -753,10 +807,7 @@ export class CharacterSheet extends ActorSheet { const array = Array.from(actor.items); for (let i = 0; i < array.length; i++) { if (array[i].name === activeEffect.name) { - // replace active effect - actor.deleteEmbeddedDocuments('Item', [array[i].id]).then(() => { - console.log("await") - }) + // replace active effect if its unique return true; } @@ -792,6 +843,13 @@ export class CharacterSheet extends ActorSheet { this.object.update({"system.setEquipped": id}) }) + html.on('click', '[data-operation="removeEffect"]', (evt) => { + const {actorId, effectId} = evt.currentTarget.dataset; + if (game.user.isGM) { + this.object.items.get(effectId).delete(); + } + }) + html.on('click', '.talent.rollable', (evt) => { this._onTalentRoll(evt); }); @@ -911,6 +969,16 @@ export class CharacterSheet extends ActorSheet { } ]); + html.on('click', '[data-operation="addWounds"]', async (evt) => { + const {value} = evt.currentTarget.dataset + this.object.update({"system.wunden.aktuell": value}) + }) + + html.on('click', '[data-operation="reduceWounds"]', async (evt) => { + const {value} = evt.currentTarget.dataset + this.object.update({"system.wunden.aktuell": value}) + }) + html.on('click', '.liturgy.rollable', async (evt) => { evt.stopPropagation(); @@ -963,7 +1031,6 @@ export class CharacterSheet extends ActorSheet { }) - } #handleDroppedEquipment(actor, equipment) { diff --git a/src/module/sheets/groupSheet.mjs b/src/module/sheets/groupSheet.mjs index 6536d933..ac411279 100644 --- a/src/module/sheets/groupSheet.mjs +++ b/src/module/sheets/groupSheet.mjs @@ -30,10 +30,10 @@ export class GroupSheet extends ActorSheet { // update group const settings = {...group.system.settings} character.items.filter((i) => i.type === "Advantage").forEach((advantage) => { - settings[this.#stringToKeyFieldName(advantage.name)] = false + settings[sheet.#stringToKeyFieldName(advantage.name)] = false }) character.items.filter((i) => i.type === "Skill").forEach((skill) => { - settings[this.#stringToKeyFieldName(skill.name)] = false + settings[sheet.#stringToKeyFieldName(skill.name)] = false }), await group.update({ system: { diff --git a/src/packs/_source/wunden/arm-r-wunde.json b/src/packs/_source/wunden/arm-r-wunde.json new file mode 100644 index 00000000..436be843 --- /dev/null +++ b/src/packs/_source/wunden/arm-r-wunde.json @@ -0,0 +1,44 @@ +{ + "name": "Wunde Rechter Arm", + "notes": "Nur für das Spiel mit Trefferzonen gedacht.
Eine Waffe oder andere Auswirkung hat eine Wunde am rechten Arm verursacht", + "unique": false, + "image": "icons/skills/wounds/bone-broken-knee-beam.webp", + "effects": [ + { + "key": "system.wunden.armrechts", + "mode": 2, + "value": "1", + "priority": 10 + }, + { + "key": "system.attribute.at.rechts.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.atribute.pa.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.pa.rechts.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.attribute.kk.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.attribute.ff.mod", + "mode": 2, + "value": "-2", + "priority": 10 + } + ] +} \ No newline at end of file diff --git a/src/packs/_source/wunden/arm-wunde.json b/src/packs/_source/wunden/arm-wunde.json new file mode 100644 index 00000000..1c3b6d4e --- /dev/null +++ b/src/packs/_source/wunden/arm-wunde.json @@ -0,0 +1,44 @@ +{ + "name": "Wunde Linker Arm", + "notes": "Nur für das Spiel mit Trefferzonen gedacht.
Eine Waffe oder andere Auswirkung hat eine Wunde am linken Arm verursacht", + "unique": false, + "image": "icons/skills/wounds/bone-broken-knee-beam.webp", + "effects": [ + { + "key": "system.wunden.armlinks", + "mode": 2, + "value": "1", + "priority": 10 + }, + { + "key": "system.pa.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.at.links.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.pa.links.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.attribute.kk.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.attribute.ff.mod", + "mode": 2, + "value": "-2", + "priority": 10 + } + ] +} \ No newline at end of file diff --git a/src/packs/_source/wunden/bauch-wunde.json b/src/packs/_source/wunden/bauch-wunde.json new file mode 100644 index 00000000..543ffbad --- /dev/null +++ b/src/packs/_source/wunden/bauch-wunde.json @@ -0,0 +1,44 @@ +{ + "name": "Bauchwunde", + "notes": "Nur für das Spiel mit Trefferzonen gedacht.
Eine Waffe oder andere Auswirkung hat eine Wunde am Bauch verursacht", + "unique": false, + "image": "icons/skills/wounds/bone-broken-knee-beam.webp", + "effects": [ + { + "key": "system.wunden.bauch", + "mode": 2, + "value": "1", + "priority": 10 + }, + { + "key": "system.at.mod", + "mode": 2, + "value": "-1", + "priority": 10 + }, + { + "key": "system.pa.mod", + "mode": 2, + "value": "-1", + "priority": 10 + }, + { + "key": "system.attribute.ko.mod", + "mode": 2, + "value": "-1", + "priority": 10 + }, + { + "key": "system.attribute.kk.mod", + "mode": 2, + "value": "-1", + "priority": 10 + }, + { + "key": "system.gs.mod", + "mode": 2, + "value": "-1", + "priority": 10 + } + ] +} \ No newline at end of file diff --git a/src/packs/_source/wunden/bein-r-wunde.json b/src/packs/_source/wunden/bein-r-wunde.json new file mode 100644 index 00000000..fceba306 --- /dev/null +++ b/src/packs/_source/wunden/bein-r-wunde.json @@ -0,0 +1,44 @@ +{ + "name": "Wunde Rechtes Bein", + "notes": "Nur für das Spiel mit Trefferzonen gedacht.
Eine Waffe oder andere Auswirkung hat eine Wunde am rechten Bein verursacht", + "unique": false, + "image": "icons/skills/wounds/bone-broken-knee-beam.webp", + "effects": [ + { + "key": "system.wunden.beinrechts", + "mode": 2, + "value": "1", + "priority": 10 + }, + { + "key": "system.at.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.pa.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.attribute.ge.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.ini.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.gs.mod", + "mode": 2, + "value": "-1", + "priority": 10 + } + ] +} \ No newline at end of file diff --git a/src/packs/_source/wunden/bein-wunde.json b/src/packs/_source/wunden/bein-wunde.json new file mode 100644 index 00000000..1e46dd41 --- /dev/null +++ b/src/packs/_source/wunden/bein-wunde.json @@ -0,0 +1,44 @@ +{ + "name": "Wunde Linkes Bein", + "notes": "Nur für das Spiel mit Trefferzonen gedacht.
Eine Waffe oder andere Auswirkung hat eine Wunde am linken Bein verursacht", + "unique": false, + "image": "icons/skills/wounds/bone-broken-knee-beam.webp", + "effects": [ + { + "key": "system.wunden.beinlinks", + "mode": 2, + "value": "1", + "priority": 10 + }, + { + "key": "system.at.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.pa.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.attribute.ge.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.ini.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.gs.mod", + "mode": 2, + "value": "-1", + "priority": 10 + } + ] +} \ No newline at end of file diff --git a/src/packs/_source/wunden/kopf-wunde.json b/src/packs/_source/wunden/kopf-wunde.json new file mode 100644 index 00000000..dbee3d04 --- /dev/null +++ b/src/packs/_source/wunden/kopf-wunde.json @@ -0,0 +1,38 @@ +{ + "name": "Kopfwunde", + "notes": "Nur für das Spiel mit Trefferzonen gedacht.
Eine Waffe oder andere Auswirkung hat eine Wunde am Kopf verursacht", + "unique": false, + "image": "icons/skills/wounds/bone-broken-knee-beam.webp", + "effects": [ + { + "key": "system.wunden.kopf", + "mode": 2, + "value": "1", + "priority": 10 + }, + { + "key": "system.attribute.mu.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.attribute.kl.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.attribute.in.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.ini.mod", + "mode": 2, + "value": "-2", + "priority": 10 + } + ] +} \ No newline at end of file diff --git a/src/packs/_source/wunden/torso-wunde.json b/src/packs/_source/wunden/torso-wunde.json new file mode 100644 index 00000000..cd319e1f --- /dev/null +++ b/src/packs/_source/wunden/torso-wunde.json @@ -0,0 +1,38 @@ +{ + "name": "Brustwunde", + "notes": "Nur für das Spiel mit Trefferzonen gedacht.
Eine Waffe oder andere Auswirkung hat eine Wunde an der Brust verursacht", + "unique": false, + "image": "icons/skills/wounds/bone-broken-knee-beam.webp", + "effects": [ + { + "key": "system.wunden.torso", + "mode": 2, + "value": "1", + "priority": 10 + }, + { + "key": "system.attribute.kk.mod", + "mode": 2, + "value": "-1", + "priority": 10 + }, + { + "key": "system.attribute.ko.mod", + "mode": 2, + "value": "-1", + "priority": 10 + }, + { + "key": "system.at.mod", + "mode": 2, + "value": "-1", + "priority": 10 + }, + { + "key": "system.pa.mod", + "mode": 2, + "value": "-1", + "priority": 10 + } + ] +} \ No newline at end of file diff --git a/src/packs/_source/wunden/wunde.json b/src/packs/_source/wunden/wunde.json new file mode 100644 index 00000000..0f6ff0cb --- /dev/null +++ b/src/packs/_source/wunden/wunde.json @@ -0,0 +1,50 @@ +{ + "name": "Wunde", + "notes": "Nur für das Spiel ohne Trefferzonen gedacht.
Eine Waffe oder andere Auswirkung hat eine Wunde verursacht", + "unique": false, + "image": "icons/skills/wounds/bone-broken-knee-beam.webp", + "effects": [ + { + "key": "system.wunden", + "mode": 2, + "value": "1", + "priority": 10 + }, + { + "key": "system.at.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.pa.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.fk.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.ini.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.attribute.ge.mod", + "mode": 2, + "value": "-2", + "priority": 10 + }, + { + "key": "system.gs.mod", + "mode": 2, + "value": "-1", + "priority": 10 + } + ] +} \ No newline at end of file diff --git a/src/style/_character-sheet.scss b/src/style/_character-sheet.scss index 6a671515..a95fe207 100644 --- a/src/style/_character-sheet.scss +++ b/src/style/_character-sheet.scss @@ -240,10 +240,9 @@ } .backpack.active { - padding: 8px; display: grid; grid-template-columns: 1fr 320px; - grid-template-rows: 64px 1fr; + grid-template-rows: 74px 1fr; gap: 10px; height: 100%; grid-template-areas: @@ -284,8 +283,194 @@ } - .tab.combat { + .tab.combat.active { + display: grid; + + grid-template-columns: 1fr 320px; + grid-template-rows: 32px 32px 1fr; + grid-template-areas: "res res" "wounds wounds" "actions actions"; + gap: 10px; + + .tab-resources { + grid-area: res; + } + + .wounds { + position: relative; + height: 24px; + display: flex; + margin-bottom: 8px; + padding-left: 130px; + grid-area: wounds; + + label { + position: absolute; + left: 0; + top: 0; + line-height: 24px; + width: 120px; + bottom: 0; + vertical-align: middle; + text-align: right; + height: 24px; + display: inline-block; + z-index: 2; + } + + .filled-segment { + border: 1px solid black; + background-image: url('../assets/gradient.png'); + background-size: 24px 100%; + position: relative; + flex: 1; + text-align: center; + vertical-align: middle; + line-height: 24px; + color: white; + text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3); + background-color: rgba(255, 0, 0, 0.8); + background-blend-mode: multiply; + + } + + .empty-segment { + border: 1px solid black; + background-image: url('../assets/gradient.png'); + background-size: 32px 100%; + position: relative; + flex: 1; + text-align: center; + vertical-align: middle; + line-height: 24px; + color: gold; + text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3); + background-color: rgba(0, 0, 0, 0.8); + background-blend-mode: multiply; + + } + + } + + .actions { + grid-area: actions; + } + + &.zones { + grid-template-areas: "res res" "wounds wounds" "actions paperdoll"; + + .paperdoll { + grid-area: paperdoll; + + div { + position: relative; + margin-left: 9px; + margin-top: 42px; + + .wound { + position: absolute; + width: 32px; + height: 32px; + border-radius: 16px; + border: 1px solid black; + background-color: rgba(0, 0, 0, 0.5); + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); + line-height: 32px; + vertical-align: middle; + text-align: center; + color: red; + + + &.armlinks { + top: 146px; + left: 210px; + } + + &.armrechts { + top: 146px; + left: 60px; + } + + &.beinlinks { + top: 346px; + left: 210px; + } + + &.beinrechts { + top: 346px; + left: 60px; + } + + &.bauch { + top: 166px; + left: 136px; + } + + &.kopf { + top: 6px; + left: 136px + } + + &.torso { + top: 86px; + left: 110px; + } + + } + + .armor { + position: absolute; + width: 32px; + height: 32px; + border-radius: 0 0 16px 16px; + line-height: 32px; + vertical-align: middle; + text-align: center; + border: 1px solid silver; + background-color: rgba(0, 0, 0, 0.5); + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); + color: silver; + + &.armlinks { + top: 180px; + left: 210px; + } + + &.armrechts { + top: 180px; + left: 60px; + } + + &.beinlinks { + top: 380px; + left: 210px; + } + + &.beinrechts { + top: 380px; + left: 60px; + } + + &.bauch { + top: 200px; + left: 136px; + } + + &.kopf { + top: 40px; + left: 136px + } + + &.torso { + top: 120px; + left: 110px; + } + } + } + + } + + } } @@ -434,23 +619,23 @@ & > div { - height: 48px; + height: 32px; position: relative; label { width: 80px; - line-height: 48px; + line-height: 32px; vertical-align: middle; } input { display: inline-block; width: 40px; - height: 48px; + height: 32px; } span.inline { - line-height: 48px; + line-height: 32px; vertical-align: middle; width: 40px; text-align: center; diff --git a/src/system.json b/src/system.json index bf0f5b45..64166527 100644 --- a/src/system.json +++ b/src/system.json @@ -84,6 +84,14 @@ "type": "Item", "path": "packs/munition", "private": false + }, + { + "name": "Wounds", + "label": "Trefferzonen Wunden", + "system": "DSA_4-1", + "type": "Item", + "path": "packs/wunden", + "private": false } ], "languages": [ diff --git a/src/templates/actor/actor-character-sheet.hbs b/src/templates/actor/actor-character-sheet.hbs index dcc03e78..1929a542 100644 --- a/src/templates/actor/actor-character-sheet.hbs +++ b/src/templates/actor/actor-character-sheet.hbs @@ -22,9 +22,11 @@ + {{#if ausdauer}} + {{/if}} {{#if this.hasLiturgies}} +
+ + +
+ {{#each this.mods.at}} + {{this.value}} + {{/each}} +
+
+
+ + +
+ {{#each this.mods.pa}} + {{this.value}} + {{/each}} +
+
+
+ + +
+ {{#each this.mods.fk}} + {{this.value}} + {{/each}} +
+
@@ -218,21 +247,27 @@
+ {{#if ausdauer}}
+ {{/if}} + {{#if hasSpells}}
-
+ {{/if}} + {{#if hasLiturgies}} +
+ {{/if}}

Vor- und Nachteile

@@ -252,7 +287,8 @@
-
+
@@ -268,16 +304,20 @@ von
+ {{#if ausdauer}}
von
-
+ {{/if}} + {{#if (not zonenruestung)}} +
{{derived.rs}}
+ {{/if}}
{{derived.be}} @@ -285,13 +325,64 @@
+ {{#if (not trefferzonen)}} +
+ + {{#each this.woundsFilled}} + {{#if this}} +
{{@index}}
+ {{else}} +
{{@index}}
+ {{/if}} + {{/each}} +
+ {{/if}} +
+

Aktionen im Kampf

{{#each this.actions}} {{> "systems/DSA_4-1/templates/ui/partial-action-button.hbs" this}} {{/each}}
+ {{#if (or trefferzonen zonenruestung)}} +
+

{{#if (and trefferzonen zonenruestung)}}Trefferzonen{{/if}}{{#if + (and trefferzonen (not zonenruestung))}}Wunden{{/if}}{{#if + (and (not trefferzonen) zonenruestung)}}Rüstung{{/if}}

+
+ + + + {{#if trefferzonen}} + {{derived.wunden.kopf}} + {{derived.wunden.torso}} + {{derived.wunden.armlinks}} + {{derived.wunden.armrechts}} + {{derived.wunden.bauch}} + {{derived.wunden.beinlinks}} + {{derived.wunden.beinrechts}} + {{/if}} + {{#if zonenruestung}} + {{derived.rs.kopf}} + {{derived.rs.torso}} + {{derived.rs.armlinks}} + {{derived.rs.armrechts}} + {{derived.rs.bauch}} + {{derived.rs.beinlinks}} + {{derived.rs.beinrechts}} + {{/if}} +
+
+ {{/if}} +
@@ -687,10 +778,29 @@
{{/if}} - {{#if this.hasPets}} -
+
+ + + + + + + + {{#each this.effects}} + + + + + + {{/each}} + +
EffektVeränderungen
+ {{this.name}} + {{this.conditions}}{{#if ../isGM}} + {{/if}}
- {{/if}} +