Compare commits

...

3 Commits

Author SHA1 Message Date
Jendrik b21ba191d8 re-added import of characters
Pull Request Check / testing (pull_request) Successful in 20s Details
2025-09-27 23:18:17 +02:00
Jendrik c758fcc3e4 Merge branch 'refs/heads/main' into feature/xml-import
# Conflicts:
#	src/main.mjs
#	src/module/data/character.mjs
2025-09-27 22:19:35 +02:00
macniel cfb7abc803 Adds Binding example a of one-to-many relation between a Character and multiple Skills (#15)
Erweitert das PlayerCharacterDataModel um zwei Arrays welche andere eine Ansammlung von DocumentTypes entgegennehmen können. Diese können dann in dem characterSheet.mjs ausgewertet werden (von den verknüpften Dokumenten muss jeweils der Konstruktor aufgerufen werden) und dann via context injection im Template angezeigt werden.

Um aktuell via Developer Konsole in Foundry Felder hinzuzufügen wird folgendes benutzt:

```javascript
game.actors.getName(<Name des Akteurs>).update({"system": {"talente": [ game.items.getName(<Name des Talents>)/*, ...weitere Talente */ ]}})
```

Dies können wir für Basis Talente nutzen wenn ein Charakter angelegt wird.

Co-authored-by: macniel <yuna.baehr@proton.me>
Reviewed-on: #15
2025-09-27 21:59:47 +02:00
10 changed files with 2018 additions and 51 deletions

8
.idea/.gitignore vendored 100644
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

1855
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@
"@foundryvtt/foundryvtt-cli": "^3.0.0", "@foundryvtt/foundryvtt-cli": "^3.0.0",
"cb": "^0.1.1", "cb": "^0.1.1",
"del": "^8.0.1", "del": "^8.0.1",
"fvtt-types": "npm:@league-of-foundry-developers/foundry-vtt-types@^13.346.0-beta.20250812191140",
"gulp": "^5.0.1", "gulp": "^5.0.1",
"gulp-replace": "^1.1.4", "gulp-replace": "^1.1.4",
"gulp-sass": "^6.0.1", "gulp-sass": "^6.0.1",

View File

@ -1,10 +1,10 @@
import {SkillSheet} from "./module/sheets/skillSheet.mjs";
import {SpellSheet} from "./module/sheets/spellSheet.mjs";
import {SkillDataModel} from "./module/data/skill.mjs";
import {SpellDataModel} from "./module/data/spell.mjs";
import {Character} from "./module/documents/character.mjs";
import {PlayerCharacterDataModel} from "./module/data/character.mjs"; import {PlayerCharacterDataModel} from "./module/data/character.mjs";
import {CharacterSheet} from "./module/Sheet/CharacterSheet.mjs"; import { SkillSheet } from "./module/sheets/skillSheet.mjs";
import { SpellSheet } from "./module/sheets/spellSheet.mjs";
import { SkillDataModel } from "./module/data/skill.mjs";
import { SpellDataModel } from "./module/data/spell.mjs";
import { Character } from "./module/documents/character.mjs";
import { CharacterSheet } from "./module/sheets/characterSheet.mjs";
Hooks.once("init", () => { Hooks.once("init", () => {
@ -21,13 +21,14 @@ Hooks.once("init", () => {
spell: SpellDataModel spell: SpellDataModel
} }
foundry.documents.collections.Actors.registerSheet("dsa41.character", CharacterSheet, {
types: ["character"],
makeDefault: true
});
console.log("DSA 4.1 is ready for development!") console.log("DSA 4.1 is ready for development!")
Actors.registerSheet('dsa41.character', CharacterSheet, {
types: ["character"],
makeDefault: true,
label: 'DSA41.CharacterLabels.Item'
})
// Register sheet application classes // Register sheet application classes
Items.registerSheet('dsa41.skill', SkillSheet, { Items.registerSheet('dsa41.skill', SkillSheet, {
types: ["Skill"], types: ["Skill"],

View File

@ -1,8 +1,8 @@
import { Skill } from "./Items/skill.mjs"; import {SkillDataModel} from "./skill.mjs";
import { Spell } from "./Items/spell.mjs"; import {SpellDataModel} from "./spell.mjs";
const { const {
SchemaField, NumberField, StringField, ArrayField, BooleanField, EmbeddedCollectionField, SchemaField, NumberField, StringField, ArrayField, BooleanField, ForeignDocumentField
} = foundry.data.fields; } = foundry.data.fields;
export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel { export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
@ -113,8 +113,9 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
name: new StringField(), name: new StringField(),
auswahlen: new ArrayField(new StringField()), auswahlen: new ArrayField(new StringField()),
})), })),
talente: new EmbeddedCollectionField( { model: Skill }),
zauber: new EmbeddedCollectionField( { model: Spell }), talente: new ArrayField ( new ForeignDocumentField(Item) ),
zauber: new ArrayField ( new ForeignDocumentField(Item) ),
liturgien: new ArrayField(new SchemaField({ liturgien: new ArrayField(new SchemaField({
name: new StringField(), name: new StringField(),
})), })),
@ -126,8 +127,12 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
notizen: new ArrayField(new SchemaField({ notizen: new ArrayField(new SchemaField({
key: new StringField(), key: new StringField(),
notiz: new StringField(), notiz: new StringField(),
})) })),
} }
} }
_initialize(options) {
super._initialize(options);
}
} }

View File

@ -1,9 +1,22 @@
export class Character extends Item { import {importCharacter} from "../xml-import/xml-import.mjs";
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()
}
/** /**
* Augment the basic Item data model with additional dynamic data. * Augment the basic Item data model with additional dynamic data.
*/ */
prepareData() { prepareData() {
super.prepareData(); super.prepareData();
this.prepareEmbeddedDocuments();
} }
} }

View File

@ -0,0 +1,62 @@
export class CharacterSheet extends ActorSheet {
/**@override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ['dsa41', 'sheet', 'actor', 'character'],
width: 520,
height: 480,
tabs: [
{
navSelector: '.sheet-tabs',
contentSelector: '.sheet-body',
initial: 'description',
},
],
});
}
/** @override */
get template() {
return `systems/DSA_4-1/templates/actor/actor-character-sheet.hbs`;
}
/** @override */
getData() {
// Retrieve the data structure from the base sheet. You can inspect or log
// the context variable to see the structure, but some key properties for
// sheets are the actor object, the data object, whether or not it's
// editable, the items array, and the effects array.
const context = super.getData();
// Use a safe clone of the actor data for further operations.
const actorData = context.data;
// Add the actor's data to context.data for easier access, as well as flags.
context.system = actorData.system;
context.flags = actorData.flags;
context.skills = [];
if ( context.system.talente?.length >= 0) {
context.system.talente.forEach(talent => {
const tempTalent = talent();
console.log(tempTalent.system.probe);
context.skills.push({
talentName: tempTalent.name,
probe: `ROLLDATA(${Object.values(tempTalent.system.probe).join("/")})`
});
})
}
console.log(context);
return context;
}
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) return;
}
}

View File

@ -73,7 +73,21 @@
], ],
"documentTypes": { "documentTypes": {
"Actor": { "Actor": {
"character": {} "character": {
"numberFields": [
"groesse", "alter", "gewicht"
],
"stringFields": [
"name"
],
"schemaFields": [
"attribute", "meta"
],
"arrayFields": [
"talente",
"zauber"
]
}
}, },
"Item": { "Item": {
"Skill": { "Skill": {

View File

@ -0,0 +1,45 @@
<form class="{{cssClass}} {{actor.type}} flexcol" autocomplete="off">
{{!-- Sheet Header --}}
<header class="sheet-header">
{{!-- Header stuff goes here --}}
<img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="100" width="100"/>
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name"/></h1>
</div>
</header>
{{!-- Sheet Tab Navigation --}}
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item" data-tab="overview">Übersicht</a>
<a class="item" data-tab="skills">Talente</a>
</nav>
{{!-- Sheet Body --}}
<section class="sheet-body">
<div class="tab description" data-group="primary" data-tab="description">
<div><label>Spezies
<input type="text" name="system.meta.spezies.value" value="{{system.meta.spezies}}"/>
</label>
</div>
<div><label>Kultur<input type="text" name="system.meta.kultur.value" value="{{system.meta.kultur}}"/></label>
</div>
<div><label>Profession<input type="text" name="system.meta.profession.value"
value="{{system.meta.profession}}"/></label>
</div>
<div><label>Geschlecht<input type="text" name="system.meta.geschlecht.value"
value="{{system.meta.geschlecht}}"/></label>
</div>
</div>
<div class="tab skills" data-group="primary" data-tab="skills">
<ul>
{{#each skills}}
<li><div>
<b>{{this.talentName}}</b>
{{this.probe}}
</div></li>
{{/each}}
</ul>
</div>
</section>
</form>

View File

@ -1,27 +0,0 @@
<form class="{{cssClass}} {{actor.type}} flexcol" autocomplete="off">
{{!-- Sheet Header --}}
<header class="sheet-header">
{{!-- Header stuff goes here --}}
<img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="100" width="100"/>
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name"/></h1>
</div>
</header>
{{!-- Sheet Tab Navigation --}}
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item" data-tab="overview">Übersicht</a>
<a class="item" data-tab="skills">Talente</a>
</nav>
{{!-- Sheet Body --}}
<section class="sheet-body">
<div class="tab description" data-group="primary" data-tab="description">
<input type="text" name="system.meta.spezies.value" value="{{system.meta.spezies.value}}" />
<input type="text" name="system.meta.kultur.value" value="{{system.meta.kultur.value}}" />
<input type="text" name="system.meta.profession.value" value="{{system.meta.profession.value}}" />
<input type="text" name="system.meta.geschlecht.value" value="{{system.meta.geschlecht.value}}" />
</div>
</section>
</form>