Character Creation with Default Values is no longer possible (got to be but its not scope of MVP anyway).
Skills either from Compendia or Imported Entries can now be uniquely added to a Character. This approach will help us later with adding other Elements like Advantages (these need a "uniqueness" Attribute), Spells (always unique), Miracles (also always unique), Equipmentpull/47/head
parent
32031eb548
commit
1afdd483e6
|
|
@ -72,7 +72,7 @@ Hooks.once("init", () => {
|
|||
})
|
||||
|
||||
Hooks.on('dropActorSheetData', (actor, sheet, data) => {
|
||||
CharacterSheet.onDroppedData(actor, sheet, data);
|
||||
return CharacterSheet.onDroppedData(actor, sheet, data);
|
||||
} )
|
||||
|
||||
Hooks.once("ready", async function() {
|
||||
|
|
@ -112,4 +112,4 @@ function rollItemMacro(itemName) {
|
|||
|
||||
// Trigger the item roll
|
||||
return item.roll();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,12 @@
|
|||
import {Skill} from "../documents/skill.mjs";
|
||||
import {SkillDataModel} from "./skill.mjs";
|
||||
|
||||
const {
|
||||
SchemaField, NumberField, StringField, EmbeddedDocumentField, DocumentIdField, ArrayField, ForeignDocumentField
|
||||
} = foundry.data.fields;
|
||||
|
||||
/**
|
||||
* @extends {Map<string, Set<VornachteileDataModel>>}
|
||||
*/
|
||||
class SkillMap extends Map {
|
||||
/** @inheritDoc */
|
||||
get(key, { type }={}) {
|
||||
const result = super.get(key);
|
||||
if ( !result?.size || !type ) return result;
|
||||
return result.filter(i => i.type === type);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @inheritDoc */
|
||||
set(key, value) {
|
||||
if ( !this.has(key) ) super.set(key, new Set());
|
||||
this.get(key).add(value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
|
||||
|
||||
|
||||
/**
|
||||
* Mapping of item identifiers to the items.
|
||||
* @type {SkillMap<string, Set<VornachteileDataModel>>}
|
||||
*/
|
||||
skills = this.skills
|
||||
|
||||
|
||||
|
||||
static defineSchema() {
|
||||
return {
|
||||
name: new StringField(),
|
||||
|
|
@ -143,11 +114,7 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
|
|||
auswahlen: new ArrayField(new StringField()),
|
||||
})),
|
||||
|
||||
talente: new ArrayField(new SchemaField({
|
||||
talent: new DocumentIdField(Item),
|
||||
taw: new NumberField({integer: true, required: true}),
|
||||
})
|
||||
),
|
||||
talente: new ArrayField(new DocumentIdField(Item)),
|
||||
zauber: new ArrayField(new SchemaField({
|
||||
talent: new DocumentIdField(),
|
||||
zfw: new NumberField({integer: true, required: true}),
|
||||
|
|
@ -171,106 +138,8 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
|
|||
super._initialize(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds base skills according to the BRW to the given actor
|
||||
* @param actor
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async #createBaseSkills(actor) {
|
||||
const compendiumOfSkills = await game.packs.get('DSA_4-1.talente-brw');
|
||||
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 = []
|
||||
|
||||
const mappedCompendiumItems = talentsByName.map( talentName => {
|
||||
const talent = compendiumOfSkills.index.find( skill => skill.name === talentName)
|
||||
return talent._id
|
||||
})
|
||||
|
||||
for (const talentId of mappedCompendiumItems) {
|
||||
const talent = await compendiumOfSkills.getDocument(talentId);
|
||||
try {
|
||||
const embeddedDocument = (await thisCharacter.createEmbeddedDocuments('Item', [talent]))[0]
|
||||
if (embeddedDocument.type === "Skill") {
|
||||
if (talent) {
|
||||
talente.push({
|
||||
taw: 0,
|
||||
talent: embeddedDocument.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`${talentId} not found in items`)
|
||||
}
|
||||
}
|
||||
await actor.update({system: { talente: talente}})
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attributes of the given actor to their default values
|
||||
* @param actor
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async #setBaseAttributes(actor) {
|
||||
const startEigenschaften = {
|
||||
"mu": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"kl": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"in": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"ch": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"ff": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"ge": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"ko": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"kk": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
}
|
||||
}
|
||||
|
||||
await actor.update({system: {attribute: startEigenschaften}})
|
||||
}
|
||||
|
||||
async _onCreate(data, options, userId) {
|
||||
const thisCharacter = await game.actors.getName(data.name);
|
||||
|
||||
await this.#createBaseSkills(thisCharacter)
|
||||
await this.#setBaseAttributes(thisCharacter)
|
||||
|
||||
super._onCreate(data, options, userId);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export class SkillDataModel extends BaseItem {
|
|||
return {
|
||||
name: new StringField({ required: true }),
|
||||
gruppe: new StringField({ required: true }),
|
||||
taw: new NumberField({ integer: true, initial: 0 }),
|
||||
probe: new ArrayField(new StringField(), { exact: 3 }), // References one of the eight attributes by name
|
||||
voraussetzung: new SchemaField({
|
||||
talent: new StringField({ model: SkillDataModel }),
|
||||
|
|
@ -15,7 +16,7 @@ export class SkillDataModel extends BaseItem {
|
|||
}), // Required skills at a given level
|
||||
talent: new HTMLField({ required: true }),
|
||||
behinderung: new NumberField({ required: false}), // BE-X
|
||||
komplexität: new NumberField({ required: false }), // In case of languages
|
||||
komplexität: new NumberField({ required: false }), // In case of languages
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
|
@ -86,5 +87,4 @@ export class SkillDataModel extends BaseItem {
|
|||
patzer: patzerCounter === countToPatzer,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,4 +41,103 @@ export class Character extends Actor {
|
|||
}
|
||||
|
||||
|
||||
}
|
||||
async addSkillFromCompendiumByNameToActor(talentName, actor) {
|
||||
const compendiumOfSkills = game.packs.get('DSA_4-1.talente-brw');
|
||||
const talentId = compendiumOfSkills.index.find( skill => skill.name === talentName)
|
||||
let talentObject = {}
|
||||
const talent = await compendiumOfSkills.getDocument(talentId);
|
||||
try {
|
||||
const embeddedDocument = (await actor.createEmbeddedDocuments('Item', [talent]))[0]
|
||||
if (embeddedDocument.type === "Skill") {
|
||||
if (talent) {
|
||||
talentObject = {
|
||||
taw: 0,
|
||||
talent: embeddedDocument.id,
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`${talentName} not found in items`, error)
|
||||
}
|
||||
await actor.update({system: { talente: talentObject, ...actor.system.talente}})
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds base skills according to the BRW to the given actor
|
||||
* @param actor
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async #createBaseSkills(actor) {
|
||||
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 => {
|
||||
|
||||
this.addSkillFromCompendiumByNameToActor(
|
||||
talentName,
|
||||
)
|
||||
})
|
||||
|
||||
await actor.update({system: { talente: talente}})
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attributes of the given actor to their default values
|
||||
* @param actor
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async #setBaseAttributes(actor) {
|
||||
const startEigenschaften = {
|
||||
"mu": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"kl": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"in": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"ch": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"ff": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"ge": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"ko": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
},
|
||||
"kk": {
|
||||
start: 10,
|
||||
aktuell: 10,
|
||||
mod: 0
|
||||
}
|
||||
}
|
||||
|
||||
await actor.update({system: {attribute: startEigenschaften}})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,25 +39,15 @@ export class CharacterSheet extends ActorSheet {
|
|||
}
|
||||
|
||||
#addSkillsToContext(context) {
|
||||
const actorSkills = {}
|
||||
const actorData = context.data;
|
||||
context.skills = {};
|
||||
context.flatSkills = [];
|
||||
|
||||
Object.values(actorData.items).forEach( (item) => {
|
||||
Object.values(actorData.items).forEach( (item, index) => {
|
||||
if (item.type === "Skill") {
|
||||
actorSkills[item._id] = item;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if ( context.system.talente?.length >= 0) {
|
||||
context.system.talente.forEach( ( { taw, talent }, index) => {
|
||||
if (actorSkills[talent]) {
|
||||
const talentObjekt = actorSkills[talent];
|
||||
if (talentObjekt.type === 'Skill') {
|
||||
const talentGruppe = talentObjekt.system.gruppe;
|
||||
const eigenschaften = Object.values(talentObjekt.system.probe);
|
||||
const talentGruppe = item.system.gruppe;
|
||||
const eigenschaften = Object.values(item.system.probe);
|
||||
const werte = [
|
||||
{name: eigenschaften[0], value: this.prepareEigenschaftRoll(actorData, eigenschaften[0])},
|
||||
{name: eigenschaften[1], value: this.prepareEigenschaftRoll(actorData, eigenschaften[1])},
|
||||
|
|
@ -69,9 +59,9 @@ export class CharacterSheet extends ActorSheet {
|
|||
const obj = {
|
||||
type: "talent",
|
||||
gruppe: talentGruppe,
|
||||
name: talentObjekt.name,
|
||||
taw: "" + taw,
|
||||
tawPath: `system.talente.${index}.taw`,
|
||||
name: item.name,
|
||||
taw: "" + item.system.taw,
|
||||
tawPath: `system.items.${index}.taw`,
|
||||
werte,
|
||||
rollEigenschaft1: werte[0].value,
|
||||
rollEigenschaft2: werte[1].value,
|
||||
|
|
@ -84,9 +74,8 @@ export class CharacterSheet extends ActorSheet {
|
|||
context.skills[talentGruppe].push(obj);
|
||||
context.flatSkills.push(obj);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#addAdvantagesToContext(context) {
|
||||
|
|
@ -298,88 +287,40 @@ export class CharacterSheet extends ActorSheet {
|
|||
|
||||
}
|
||||
|
||||
async #handleDroppedSkill(actor, data) {
|
||||
let alreadyInSet = false;
|
||||
let previousTaw = 0;
|
||||
const id = foundry.utils.parseUuid(data.uuid).id;
|
||||
|
||||
const item = (await actor.createEmbeddedDocuments('Item', [await game.items.get(id)]))[0]
|
||||
|
||||
actor.system.talente.forEach(({taw, talent}) => {
|
||||
if (talent) {
|
||||
if (talent._id === item._id) {
|
||||
alreadyInSet = talent;
|
||||
previousTaw = taw;
|
||||
}
|
||||
#handleDroppedSkill(actor, skill) {
|
||||
const array = Array.from(actor.items);
|
||||
for ( let i = 0; i < array.length; i++ ) {
|
||||
if (array[i].name === skill.name) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
const myContent = `TaW: <input id="taw" type="number" value="${previousTaw}" />`;
|
||||
new Dialog({
|
||||
title: `Talent ${item.name} ${alreadyInSet?'ersetzen':'hinzufügen'}`,
|
||||
content: myContent,
|
||||
buttons: {
|
||||
button1: {
|
||||
label: "hinzufügen",
|
||||
callback: (html) => myCallback(html),
|
||||
icon: `<i class="fas fa-check"></i>`
|
||||
}
|
||||
}
|
||||
}).render(true);
|
||||
|
||||
async function myCallback(html) {
|
||||
const taw = html.find("input#taw").val();
|
||||
|
||||
let index = actor.system.talente.findIndex( predicate => predicate.talent && predicate.talent._id === alreadyInSet._id )
|
||||
let sorted = [];
|
||||
if (alreadyInSet) {
|
||||
actor.system.talente[index].taw = taw;
|
||||
sorted = actor.system.talente;
|
||||
|
||||
} else {
|
||||
const newItem = {
|
||||
taw: taw,
|
||||
talent: {_id: item._id, name: item.name}
|
||||
}
|
||||
console.log(newItem, await game.items.get(item._id))
|
||||
sorted = [newItem, ...actor.system.talente].sort((a, b) => {
|
||||
|
||||
return a.talent.name.localeCompare(b.talent.name)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const serialised = sorted.map(({taw, talent}) => {
|
||||
return {
|
||||
taw: taw,
|
||||
talent: talent._id
|
||||
}
|
||||
});
|
||||
|
||||
await actor.update({
|
||||
system: {
|
||||
talente: [
|
||||
|
||||
...serialised
|
||||
]
|
||||
}
|
||||
});
|
||||
ui.notifications.info(`Talent ${item.name} auf TaW ${taw} hinzugefügt`);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static getElementByName(collection, id) {
|
||||
const array = Array.from(collection);
|
||||
for (const element of array) {
|
||||
if (element._id === id) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static onDroppedData(actor, characterSheet, data) {
|
||||
const item = game.items.get(foundry.utils.parseUuid(data.uuid).id)
|
||||
|
||||
switch (item.type) {
|
||||
const uuid = foundry.utils.parseUuid(data.uuid);
|
||||
const collection = uuid.collection.index ?? uuid.collection;
|
||||
const document = CharacterSheet.getElementByName(collection, uuid.id);
|
||||
const {
|
||||
name,
|
||||
type
|
||||
} = document
|
||||
console.log(name, type)
|
||||
switch (type) {
|
||||
case "Skill":
|
||||
characterSheet.#handleDroppedSkill(actor, data);
|
||||
return characterSheet.#handleDroppedSkill(actor, document); // on false cancel this whole operation
|
||||
default:
|
||||
console.log(item, item.type);
|
||||
return false;
|
||||
}
|
||||
|
||||
// maybe dont
|
||||
actor.items.clear()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,22 @@ function calculateBirthdate(json) {
|
|||
return `${day}. ${month} ${year} BF`
|
||||
}
|
||||
|
||||
function mapSkills(rawJson) {
|
||||
let talents = []
|
||||
for (let talent in held.talentliste.talent) {
|
||||
talent = held.talentliste.talent[talent]
|
||||
let talentItem = game.items.getName(talent.name)
|
||||
if (talentItem) {
|
||||
let talentJson = {
|
||||
talent: talentItem,
|
||||
taw: talent.value,
|
||||
}
|
||||
talents.push(talentJson)
|
||||
}
|
||||
}
|
||||
return talents
|
||||
}
|
||||
|
||||
/**
|
||||
* parses a json into a fitting character-json
|
||||
* @param rawJson the json parsed from the Helden-Software XML
|
||||
|
|
@ -248,19 +264,8 @@ function mapRawJson(rawJson) {
|
|||
}
|
||||
json.sonderfertigkeiten = specialAbilities
|
||||
json.liturgien = liturgies
|
||||
let talents = []
|
||||
for (let talent in held.talentliste.talent) {
|
||||
talent = held.talentliste.talent[talent]
|
||||
let talentItem = game.items.getName(talent.name)
|
||||
if (talentItem) {
|
||||
let talentJson = {
|
||||
talent: talentItem,
|
||||
taw: talent.value,
|
||||
}
|
||||
talents.push(talentJson)
|
||||
}
|
||||
}
|
||||
json.talente = talents
|
||||
|
||||
json.talente = mapSkills(rawJson)
|
||||
let spells = []
|
||||
/*for (let spell in held.zauberliste.zauber) {
|
||||
spell = held.zauberliste.zauber[spell]
|
||||
|
|
@ -337,4 +342,4 @@ Hooks.on("getActorContextOptions", (application, menuItems) => {
|
|||
actor.import()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue