From 109682b415f9fe0e9005ea2b149e285e74663b3f Mon Sep 17 00:00:00 2001 From: macniel Date: Sun, 28 Sep 2025 12:19:21 +0200 Subject: [PATCH] feature/rollable-character-talents (#38) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hinterlegt bei den Talenten nun die Würfel mechanik. Fügt bei dieser auch hinzu, dass die Schwelle zum Patzer (Tollpatsch,...) reduziert werden könne, sodass Patzerschwelle, Meisterliche schwelle in anzahl und Wert angepasst werden kann. Basistalente werden nun beim anlegen des Actors hinzugefügt, diese müssen entsprechend bereits aus dem Kompendium importiert sein. **Das muss aber besser und automatischer gehen können.** Co-authored-by: macniel Reviewed-on: https://git.macniel.online/macniel/foundry-dsa41-game/pulls/38 --- src/module/data/character.mjs | 48 ++++++++++- src/module/documents/skill.mjs | 3 +- src/module/documents/spell.mjs | 4 +- src/module/sheets/characterSheet.mjs | 86 +++++++++++++++++-- .../körperlich/sich-verstecken.json | 2 +- src/templates/actor/actor-character-sheet.hbs | 3 +- 6 files changed, 131 insertions(+), 15 deletions(-) diff --git a/src/module/data/character.mjs b/src/module/data/character.mjs index 6351e88b..bd77fa8e 100644 --- a/src/module/data/character.mjs +++ b/src/module/data/character.mjs @@ -43,7 +43,8 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { so: new NumberField({ required: true, integer: true }), gilde: new StringField(), }), - talente: new ArrayField ( new ForeignDocumentField(Item) ), + talente: new ArrayField ( new SchemaField( + {taw: new NumberField(), talent: new ForeignDocumentField(Item) })), zauber: new ArrayField ( new ForeignDocumentField(Item) ), } } @@ -52,4 +53,49 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { super._initialize(options); } + _onCreate(data, options, userId) { + // prepare base talents + const talentsByName = [ + "Athletik", "Klettern", "Körperbeherrschung", "Schleichen", "Schwimmen", "Selbstbeherrschung", "Sich Verstecken", "Singen", "Sinnenschärfe", "Tanzen", "Zechen", + "Menschenkenntnis", "Überreden", + "Fährtensuchen", "Orientierung", "Wildnisleben", + "Götter/Kulte", "Rechnen", "Sagen/Legenden", + "Heilkunde: Wunden", "Holzbearbeitung", "Kochen", "Lederverarbeitung", "Malen/Zeichnen", "Schneidern" + ] + + const talente = [] + + talentsByName.forEach( talentName => { + const talent = game.items.getName(talentName); + console.log(talent); + if (talent) { + talente.push({ + taw: 0, + talent + }) + } else { + console.error(`${talentName} not found in items`) + } + }) + + // push base talents + game.actors.getName(data.name).update({system: {talente}}) + + const startEigenschaften = { + "mu": 10, + "kl": 10, + "in": 10, + "ch": 10, + "ff": 10, + "ge": 10, + "ko": 10, + "kk": 10, + } + + game.actors.getName(data.name).update({system: {attribute: startEigenschaften}}) + super._onCreate(data, options, userId); + + + } + } \ No newline at end of file diff --git a/src/module/documents/skill.mjs b/src/module/documents/skill.mjs index ead10ed7..99b1992b 100644 --- a/src/module/documents/skill.mjs +++ b/src/module/documents/skill.mjs @@ -1,6 +1,5 @@ -import { BaseItem } from "./base-item.mjs"; -export class Skill extends BaseItem { +export class Skill extends Item { /** * Augment the basic Item data model with additional dynamic data. */ diff --git a/src/module/documents/spell.mjs b/src/module/documents/spell.mjs index f382a84c..05d34b42 100644 --- a/src/module/documents/spell.mjs +++ b/src/module/documents/spell.mjs @@ -1,6 +1,4 @@ -import { BaseItem } from "./base-item.mjs"; - -export class Spell extends BaseItem { +export class Spell extends Item { /** * Augment the basic Item data model with additional dynamic data. */ diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs index 41df263a..30a15498 100644 --- a/src/module/sheets/characterSheet.mjs +++ b/src/module/sheets/characterSheet.mjs @@ -80,11 +80,17 @@ export class CharacterSheet extends ActorSheet { context.skills = []; if ( context.system.talente?.length >= 0) { context.system.talente.forEach(talent => { - const tempTalent = talent(); - console.log(tempTalent.system.probe); + console.log(talent); + const taw = talent.taw; + const talentObjekt = game.items.get(talent.talent); + const eigenschaften = Object.values(talentObjekt.system.probe); context.skills.push({ - talentName: tempTalent.name, - probe: `ROLLDATA(${Object.values(tempTalent.system.probe).join("/")})` + talentName: talentObjekt.name, + taw: taw, + rollEigenschaft1: this.prepareEigenschaftRoll(actorData, eigenschaften[0]), + rollEigenschaft2: this.prepareEigenschaftRoll(actorData, eigenschaften[1]), + rollEigenschaft3: this.prepareEigenschaftRoll(actorData, eigenschaften[2]), + probe: `(${eigenschaften.join("/")})` }); }) @@ -94,13 +100,74 @@ export class CharacterSheet extends ActorSheet { return context; } - _onRoll(event) { + prepareEigenschaftRoll(actorData, name) { + return actorData.system.attribute[name.toLowerCase()] + } + + async _onTalentRoll(event) { event.preventDefault(); const dataset = event.currentTarget.dataset; console.log(dataset) + if (dataset.rolleigenschaft1) { + let roll1 = new Roll("3d20", this.actor.getRollData()); + + let evaluated1 = (await roll1.evaluate()) + + const dsaDieRollEvaluated = this._evaluateRoll(evaluated1.terms[0].results, { + taw: dataset.taw, + werte: [dataset.rolleigenschaft1, dataset.rolleigenschaft2, dataset.rolleigenschaft3], + }) + + if (dsaDieRollEvaluated.tap >= 0) { // erfolg + evaluated1.toMessage({ + speaker: ChatMessage.getSpeaker({actor: this.actor}), + flavor: ` ${dsaDieRollEvaluated.meisterlich?'Meisterlich geschafft':'Geschafft'} mit ${dsaDieRollEvaluated.tap} Punkten übrig`, + rollMode: game.settings.get('core', 'rollMode'), + }) + } else { // misserfolg + evaluated1.toMessage({ + speaker: ChatMessage.getSpeaker({actor: this.actor}), + flavor: ` ${dsaDieRollEvaluated.meisterlich?'Gepatzt':''} mit ${Math.abs(dsaDieRollEvaluated.tap)} Punkten daneben`, + rollMode: game.settings.get('core', 'rollMode'), + }) + } + + + } + } + + _evaluateRoll(rolledDice, { taw, lowerThreshold = 1, upperThreshold = 20, countToMeisterlich = 3, countToPatzer = 3, werte = [] } ) { + let tap = taw; + let meisterlichCounter = 0; + let patzerCounter = 0; + let failCounter = 0; + + rolledDice.forEach( (rolledDie, index) => { + if (tap < 0 && rolledDie.result > werte[index]) { + tap -= rolledDie.result - werte[index]; + if (tap <0) { // konnte nicht vollständig ausgeglichen werden + failCounter++; + } + } else if (rolledDie.result > werte[index]) { // taw ist bereits aufgebraucht und wert kann nicht ausgeglichen werden + tap -= rolledDie.result - werte[index]; + failCounter++; + } + if (rolledDie.result <= lowerThreshold) meisterlichCounter++; + if (rolledDie.result > upperThreshold) patzerCounter++; + }) + + return { + tap, + meisterlich: meisterlichCounter === countToMeisterlich, + patzer: patzerCounter === countToPatzer, + } + } + + _onAttributeRoll(event) { + event.preventDefault(); + const dataset = event.currentTarget.dataset; if (dataset.roll) { let label = dataset.label ? `[Attribut] ${dataset.label}` : ''; - console.log(this.actor.getRollData()); let roll = new Roll(dataset.roll, this.actor.getRollData()); roll.toMessage({ speaker: ChatMessage.getSpeaker({ actor: this.actor }), @@ -116,7 +183,12 @@ export class CharacterSheet extends ActorSheet { html.on('click', '.attribut.rollable', (evt) => { console.log(evt); - this._onRoll(evt); + this._onAttributeRoll(evt); + }); + + html.on('click', '.talent.rollable', (evt) => { + console.log(evt); + this._onTalentRoll(evt); }); // Everything below here is only needed if the sheet is editable diff --git a/src/packs/_source/talente-brw/körperlich/sich-verstecken.json b/src/packs/_source/talente-brw/körperlich/sich-verstecken.json index adc9d8de..8fce89fa 100644 --- a/src/packs/_source/talente-brw/körperlich/sich-verstecken.json +++ b/src/packs/_source/talente-brw/körperlich/sich-verstecken.json @@ -2,7 +2,7 @@ "_id": "o1nYjhmMP0Zzlcw6", "_key": "!items!o1nYjhmMP0Zzlcw6", "type": "Skill", - "name": "Sich verstecken", + "name": "Sich Verstecken", "system": { "gruppe": "Körperlich", "probe": [ diff --git a/src/templates/actor/actor-character-sheet.hbs b/src/templates/actor/actor-character-sheet.hbs index 768b7267..cacc3ffc 100644 --- a/src/templates/actor/actor-character-sheet.hbs +++ b/src/templates/actor/actor-character-sheet.hbs @@ -46,9 +46,10 @@
    {{#each skills}} -
  • +
  • {{this.talentName}} {{this.probe}} + TAW: {{this.taw}}
  • {{/each}}