import {importCharacter} from "../xml-import/xml-import.mjs"; import {LiturgyData} from "../data/miracle/liturgydata.mjs"; import {Zonenruestung, Zonenwunde} from "../data/Trefferzone.js"; export class Character extends Actor { import() { let input = document.createElement('input') input.type = 'file' input.accept = '.xml' input.onchange = e => { importCharacter(this.id, e.target.files[0]) } input.click() } /** * @override * Augment the actor source data with additional dynamic data. Typically, * you'll want to handle most of your calculated/derived data in this step. * Data calculated in this step should generally not exist in template.json * (such as ability modifiers rather than ability scores) and should be * available both inside and outside of character sheets (such as if an actor * is queried and has a roll executed directly from it). */ prepareDerivedData() { if (this.type === "character") { const actorData = this; const systemData = actorData.system; 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; 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 = 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.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 if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { systemData.rs = { brust: 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.brust = 0; systemData.wunden.bauch = 0; systemData.wunden.armlinks = 0; systemData.wunden.armrechts = 0; systemData.wunden.beinlinks = 0; systemData.wunden.beinrechts = 0; } systemData.ws = ko / 2; // map current set to RS and BE const ausruestung = systemData.heldenausruestung[systemData.setEquipped]; if (ausruestung) { if (ausruestung.brust) { systemData.be += systemData.parent.items.get(ausruestung.brust).system.armorHandicap ?? 0 if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) { systemData.rs.brust = 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.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.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.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.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.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.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 } } } systemData.kap.max = 0; // evaluate deities for KaP const deities = systemData.parent.items.filter(p => p.type === "Blessing") deities?.forEach((deity) => { if (LiturgyData.alverans.includes(deity.system.gottheit)) { systemData.kap.max = 24; } else if (systemData.kap.max === 0) { systemData.kap.max += 12; } }, 0) } } /** * Augment the basic Item data model with additional dynamic data. */ prepareData() { super.prepareData(); this.prepareEmbeddedDocuments(); } getRollData() { const data = super.getRollData(); if (this.type !== 'character' && this.type !== 'creature') return; if (data.attribute) { for (let [k, v] of Object.entries(data.attribute)) { data[k] = foundry.utils.deepClone(v); } } // move sonderfertigkeiten into data, if it isn't in data the actor doesn't have that sonderfertigkeit data.sf = {} if (data.sonderfertigkeiten) { data.sonderfertigkeiten.forEach(sf => { data.sf[sf.name] = sf.auswahl; }) delete data.sonderfertigkeiten; } return data; } /** * * @param amount * @param zone either null or one of * @returns {Promise} */ async takeDamage(amount = null, zone = null) { this.prepareDerivedData() const playWithZoneArmor = game.settings.get("DSA_4-1", "optional_ruestungzonen") const playWithWoundZones = game.settings.get("DSA_4-1", "optional_trefferzonen") const previousLeP = this.system.lep.aktuell; if (amount == null) { // TODO show Dialog for entering damage amount (TP) } let armorReduction = 0 let setEquipped = this.system.setEquipped let woundThreshold = this.system.ws if (playWithZoneArmor) { const armorId = this.system.heldenausruestung[setEquipped][Zonenruestung[zone]] const zoneArmor = await this.items.find(p => p._id === armorId) if (!zoneArmor) { return console.error(`zone "${zone}" is not a valid value`) } armorReduction = zoneArmor.system.armorValue ?? 0 } else { armorReduction = this.system.rs } let damage = amount - armorReduction let wounds = damage / woundThreshold let wound = null if (playWithWoundZones) { wound = await game.packs.get("DSA_4-1.Wounds").index.find(p => p.name === Zonenwunde[zone]) if (!wound) { return console.error(`Wunden Dokument zu "${zone}" konnten nicht gefunden werden`) } } else { wound = await game.packs.get("DSA_4-1.Wounds").index.find(p => p.name === Wunde) if (!wound) { return console.error(`Wunden Dokument zu "${Wunde}" konnten nicht gefunden werden`) } } // TODO this doesnt work yet, wound documents wont get expanded for (let i = 0; i < wounds; i++) { await this.createEmbeddedDocuments('Item', [wound]) } await this.update({system: {lep: {aktuell: previousLeP - damage}}}) } }