Merge remote-tracking branch 'origin/main' into feature/spells

pull/53/head
macniel 2025-10-05 16:01:09 +02:00
commit 02c7f5ad9b
4 changed files with 293 additions and 0 deletions

View File

@ -0,0 +1,31 @@
const {
SchemaField, NumberField, StringField, HTMLField, ArrayField
} = foundry.data.fields;
export class CreatureDataModel extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
ini: new SchemaField({
aktuell: new NumberField(),
wuerfel: new NumberField(),
}),
lep: new SchemaField({
max: new NumberField(),
aktuell: new NumberField(),
}),
mr: new NumberField(),
rs: new NumberField(),
attacks: new ArrayField(
new SchemaField({
at: new NumberField(),
pa: new NumberField(),
tp: new StringField(),
name: new StringField(),
}), {min: 0}),
description: new HTMLField()
}
}
}

View File

@ -0,0 +1,28 @@
export class Creature extends Actor {
/**
* Augment the basic Item data model with additional dynamic data.
*/
prepareData() {
super.prepareData();
this.prepareEmbeddedDocuments();
}
getRollData() {
const data = super.getRollData();
console.log(this.type)
if (this.type !== 'character' && this.type !== 'creature') return;
// Copy the ability scores to the top level, so that rolls can use
// formulas like `@str.mod + 4`.
if (data.attribute) {
for (let [k, v] of Object.entries(data.attribute)) {
data[k] = foundry.utils.deepClone(v);
}
}
return data;
}
}

View File

@ -0,0 +1,97 @@
export class CreatureSheet extends foundry.appv1.sheets.ActorSheet {
/**@override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ['dsa41', 'sheet', 'actor', 'creature'],
width: 520,
height: 480,
tabs: [
{
navSelector: '.sheet-tabs',
contentSelector: '.sheet-body',
initial: 'meta',
},
],
});
}
/** @override */
get template() {
return `systems/DSA_4-1/templates/actor/actor-creature-sheet.hbs`;
}
/** @override */
getData() {
const context = super.getData();
const actorData = context.data;
context.attacks = [];
actorData.system.attacks.forEach((attack, index) => {
context.attacks.push({
namepath: `system.attacks.${index}.name`,
name: attack.name,
atpath: `system.attacks.${index}.at`,
at: attack.at,
papath: `system.attacks.${index}.pa`,
pa: attack.pa,
tppath: `system.attacks.${index}.tp`,
tp: attack.tp,
index: index,
})
})
return context;
}
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) return;
html.on('click', '.remove-attack', async (evt) => {
const {index} = evt.target.dataset;
let sans = Array.from(this.object.system.attacks);
sans.splice(index, 1);
await this.object.update({'system.attacks': sans})
})
html.on('click', '.attacks-die.die', async (evt) => {
const {rollType, rollName, roll} = evt.currentTarget.dataset;
let r = new Roll(roll, this.actor.getRollData());
const label = `${rollType} (${rollName})`
await r.toMessage({
speaker: ChatMessage.getSpeaker({actor: this.object}),
flavor: label,
rollMode: game.settings.get('core', 'rollMode'),
});
})
html.on('click', '.editor .add-attack', async (evt) => {
const name = evt.target.parentElement.querySelector('#attack_name').value
const at = evt.target.parentElement.querySelector('#attack_at').value
const pa = evt.target.parentElement.querySelector('#attack_pa').value
const tp = evt.target.parentElement.querySelector('#attack_tp').value
const newAttack = {
name,
at,
pa,
tp
}
await this.object.update({'system.attacks': [...this.object.system.attacks, newAttack]})
evt.target.parentElement.querySelector('#attack_name').value = ""
evt.target.parentElement.querySelector('#attack_at').value = ""
evt.target.parentElement.querySelector('#attack_pa').value = ""
evt.target.parentElement.querySelector('#attack_tp').value = ""
})
}
}

View File

@ -0,0 +1,137 @@
<form class="{{cssClass}} {{actor.type}}" autocomplete="off">
{{!-- Sheet Header --}}
<header class="sheet-header">
{{!-- Header stuff goes here --}}
<img src="{{actor.img}}" data-edit="img" title="{{actor.name}}"/>
<input type="text" name="name" value="{{actor.name}}" placeholder="Name"/>
</header>
{{!-- Sheet Tab Navigation --}}
<nav class="sheet-tabs tabs" style="flex: 0" data-group="primary">
<a class="item" data-tab="meta">Kopfdaten</a>
<a class="item" data-tab="attacks">Attacken</a>
<a class="item" data-tab="description">Beschreibung</a>
</nav>
{{!-- Sheet Body --}}
<section class="sheet-body" style="flex: 1">
<div class="tab meta" data-group="primary" data-tab="meta">
<div>
<div class="input">
<label for="system.lep.aktuell">Lebenspunkte</label>
<input type="text" name="system.lep.aktuell"
value="{{actor.system.lep.aktuell}}"/>
</div>
<div class="input">
<label for="system.rs">Rüstungsschutz</label>
<input type="text" name="system.rs"
value="{{actor.system.rs}}"/>
</div>
<div class="input">
<label for="system.mr">Magieresistenz</label>
<input type="text" name="system.mr"
value="{{actor.system.mr}}"/>
</div>
<div class="input compound">
<label>Initiative</label>
<div class="inline-label">
<input type="number" name="system.ini.wuerfel"
value="{{actor.system.ini.wuerfel}}"/>
<span class="inline">w6 + </span>
</div>
<input type="number" name="system.ini.aktuell"
value="{{actor.system.ini.aktuell}}"/>
</div>
</div>
</div>
<div class="tab attacks" data-group="primary" data-tab="attacks">
<table class="attacks-table">
<thead>
<tr>
<th>Name</th>
<th>Attacke</th>
<th>Parade</th>
<th>Schaden</th>
<th></th>
</tr>
</thead>
<tbody>
{{#each this.attacks}}
<tr>
<td>
<input type="text" name="{{this.namepath}}"
value="{{this.name}}"/>
</td>
<td class="rollable tablecell">
<div class="attacks-die die rollable attack" data-actor="{{actor.name}}"
data-roll-type="attack" data-roll-name="{{this.name}}" data-roll="1d20<{{this.at}}cs">
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }}
</div>
<input type="text" name="{{this.atpath}}"
value="{{this.at}}"/>
</td>
<td class="rollable tablecell">
<div class="attacks-die die" data-roll-type="parry" data-roll-name="{{this.name}}"
data-roll="1d20 + {{this.pa}}">
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }}
</div>
<input type="text" name="{{this.papath}}"
value="{{this.pa}}"/>
</td>
<td class="rollable tablecell">
<div class="attacks-die die" data-roll-type="damage" data-roll-name="{{this.name}}"
data-roll="{{this.tp}}">
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }}
</div>
<input type="text" name="{{this.tppath}}"
value="{{this.tp}}"/>
</td>
<td>
<button class="button-inline remove-attack" data-index="{{this.index}}"><i
class="fa-solid fa-trash"></i></button>
</td>
</tr>
{{/each}}
</tbody>
<tfoot class="editor">
<tr>
<th colspan="5">Attacke hinzufügen</th>
</tr>
<tr>
<td>
<input type="text" id="attack_name"/>
</td>
<td>
<input type="text" id="attack_at" placeholder="8"/>
</td>
<td>
<input type="text" id="attack_pa" placeholer="12"/>
</td>
<td>
<input type="text" id="attack_tp" placeholder="1d6+3"/>
</td>
<td>
<button class="button-inline add-attack"><i class="fa-solid fa-plus"></i></button>
</td>
</tr>
</tfoot>
</table>
</div>
<div class="tab description" data-group="primary" data-tab="description">
{{editor system.description target="system.description" button=true owner=owner editable=editable}}
</div>
</section>
</form>