adds Mod Info and the Current choice to SpecialAbility Sheet

pull/61/head
macniel 2025-10-24 11:05:06 +02:00
parent 3f6b4a0303
commit ae57e2f90e
8 changed files with 168 additions and 85 deletions

View File

@ -71,6 +71,19 @@ export class SpecialAbilityDataModel extends BaseItem {
} }
} }
getActiveMod(options) {
if (this.isActive(options)) {
if (this.value && this.auswahl.find(p => p.name === this.value)) {
const auswahl = this.auswahl.find(p => p.name === this.value)
return auswahl.mod
} else {
this.mod
}
} else {
return []
}
}
isActive(options) { isActive(options) {
const requirements = this.#getRequirements() const requirements = this.#getRequirements()
@ -78,88 +91,93 @@ export class SpecialAbilityDataModel extends BaseItem {
let passes = true let passes = true
let mod = 0 let mod = 0
const flatActor = foundry.utils.flattenObject(this.parent.actor.system) if (this.parent?.actor) {
for (let requirement of requirements) { const flatActor = foundry.utils.flattenObject(this.parent.actor.system)
for (let requirement of requirements) {
let targetField = null let targetField = null
if (requirement.attribute) { if (requirement.attribute) {
targetField = flatActor?.[requirement.attribute.toLocaleLowerCase()] targetField = flatActor?.[requirement.attribute.toLocaleLowerCase()]
} }
if (requirement.talent) { if (requirement.talent) {
targetField = this.parent.actor.itemTypes["Skill"].find(p => p.name.toLocaleLowerCase() === requirement.talent.toLocaleLowerCase()).taw targetField = this.parent.actor.itemTypes["Skill"].find(p => p.name.toLocaleLowerCase() === requirement.talent.toLocaleLowerCase()).taw
} }
if (requirement.minValue) { if (requirement.minValue) {
passes = requirement.minValue <= targetField passes = requirement.minValue <= targetField
if (!passes) console.log(`fails requirement ${requirement.attribute ?? requirement.talent} (${requirement.minValue} <= ${targetField})`) if (!passes) console.debug(`fails requirement ${requirement.attribute ?? requirement.talent} (${requirement.minValue} <= ${targetField})`)
} }
if (requirement.maxValue) { if (requirement.maxValue) {
passes = targetField <= requirement.maxValue passes = targetField <= requirement.maxValue
if (!passes) console.log(`fails requirement ${requirement.attribute ?? requirement.talent} (${targetField} <= ${requirement.maxValue})`) if (!passes) console.debug(`fails requirement ${requirement.attribute ?? requirement.talent} (${targetField} <= ${requirement.maxValue})`)
} }
if (requirement.sonderfertigkeit) { if (requirement.sonderfertigkeit) { // FIXME fails when it tries to self reference itself e.g. Ausweichen II has Ausweichen I as requirement
passes = this.parent.actor.itemTypes["SpecialAbility"].find(p => p.name === requirement.sonderfertigkeit) != undefined const regexp = /(\w*)\W?(\w*)?/
if (!passes) console.log(`fails requirement ${requirement.sonderfertigkeit} (not in possession)`) const [variantName, baseAbility, level] = regexp.exec(requirement.sonderfertigkeit)
}
if (requirement["compare"]) { passes = this.parent.actor.itemTypes["SpecialAbility"].find(p => p.name === baseAbility) != undefined
const {ownAttribute, operation, targetAttribute} = requirement["compare"] if (!passes) console.debug(`fails requirement ${requirement.sonderfertigkeit} (not in possession)`)
if (options.target) { }
const flatTarget = foundry.utils.flattenObject(options.target.system) if (requirement["compare"]) {
const foreignTargetField = flatTarget[targetAttribute] const {ownAttribute, operation, targetAttribute} = requirement["compare"]
const ourTargetField = flatActor[ownAttribute] if (options.target) {
switch (operation) { const flatTarget = foundry.utils.flattenObject(options.target.system)
case "lt": const foreignTargetField = flatTarget[targetAttribute]
passes = ourTargetField < foreignTargetField; const ourTargetField = flatActor[ownAttribute]
break; switch (operation) {
case "lte": case "lt":
passes = ourTargetField <= foreignTargetField; passes = ourTargetField < foreignTargetField;
break; break;
case "eq": case "lte":
passes = ourTargetField == foreignTargetField; passes = ourTargetField <= foreignTargetField;
break; break;
case "neq": case "eq":
passes = ourTargetField != foreignTargetField; passes = ourTargetField == foreignTargetField;
break; break;
case "gte": case "neq":
passes = ourTargetField >= foreignTargetField; passes = ourTargetField != foreignTargetField;
break; break;
case "gt": case "gte":
passes = ourTargetField > foreignTargetField; passes = ourTargetField >= foreignTargetField;
break; break;
case "gt":
passes = ourTargetField > foreignTargetField;
break;
}
if (!passes) {
console.debug(`fails compare requirement ${ownAttribute} ${operation} ${targetAttribute}`)
}
} else {
console.debug(`fails compare requirement as no target has been selected`)
return false // cant pass as we dont have a target
} }
if (!passes) { }
console.log(`fails compare requirement ${ownAttribute} ${operation} ${targetAttribute}`) if (!passes) {
} console.debug("fails atleast 1 requirement of ", this)
} else { break
console.log(`fails compare requirement as no target has been selected`)
return false // cant pass as we dont have a target
} }
} }
if (!passes) { if (passes) {
console.log("fails atleast 1 requirement of ", this) if (options?.weapon) {
break for (const waff of this.waffenLimit) {
} if (waff.waffe) {
} passes = options?.weapon?.name === waff.waffe ?? false
console.log(this.name, "requirements", passes) if (waff.mod) mod = waff.mod
if (passes) { if (passes)
if (options?.weapon) { break
for (const waff of this.waffenLimit) { }
if (waff.waffe) { if (waff.gruppe) {
passes = options?.weapon?.name === waff.waffe ?? false passes = options?.skill?.name === waff.gruppe ?? false
if (waff.mod) mod = waff.mod if (waff.mod) mod = waff.mod
if (passes) if (passes)
break break
} }
if (waff.gruppe) {
passes = options?.skill?.name === waff.gruppe ?? false
if (waff.mod) mod = waff.mod
if (passes)
break
} }
} }
} }
} }
console.log("return value", {passes, mod})
return {passes, mod} return {passes, mod}
} }
} }

View File

@ -28,7 +28,7 @@ export default {
actorData.itemTypes.SpecialAbility.forEach((item) => { actorData.itemTypes.SpecialAbility.forEach((item) => {
context.specialAbilities.push({ context.specialAbilities.push({
id: item._id, id: item._id,
name: item.name, name: item.system.value ? item.system.value : item.name,
}); });
} }
); );

View File

@ -4,7 +4,7 @@ export class SpecialAbilitySheet extends HandlebarsApplicationMixin(DocumentShee
/** @inheritDoc */ /** @inheritDoc */
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
position: {width: 520, height: 480}, position: {width: 520, height: 600},
classes: ['dsa41', 'sheet', 'item', 'specialability'], classes: ['dsa41', 'sheet', 'item', 'specialability'],
tag: 'form', tag: 'form',
form: { form: {
@ -57,6 +57,20 @@ export class SpecialAbilitySheet extends HandlebarsApplicationMixin(DocumentShee
context.flags = specialabilityData.flags; context.flags = specialabilityData.flags;
context.text = specialabilityData.system.text; context.text = specialabilityData.system.text;
context.aktionsText = specialabilityData.system.aktionsText; context.aktionsText = specialabilityData.system.aktionsText;
context.hasChoices = context.system.auswahl.length > 0;
context.choices = {}
context.value = context.system.value
context.system.auswahl.forEach(a => {
context.choices[a.name] = a.name
})
context.isActive = this.document.system.isActive()?.passes
context.mod = this.document.system.getActiveMod()?.map(mod => {
return {
name: mod.name,
value: mod.value > 0 ? "+" + mod.value : mod.value,
}
})
context.hasModality = context.system.value != null
return context; return context;
} }

View File

@ -321,7 +321,7 @@ export class XmlImport {
#getAttributeJson(attributes, name) { #getAttributeJson(attributes, name) {
let attribute = this.#filterAttribute(attributes, name) let attribute = this.#filterAttribute(attributes, name)
return { return {
start: parseInt(attribute.startwert), start: parseInt(attribute.value),
aktuell: parseInt(attribute.value), aktuell: parseInt(attribute.value),
mod: parseInt(attribute.mod), mod: parseInt(attribute.mod),
} }
@ -564,10 +564,21 @@ export class XmlImport {
} }
specialAbilities.forEach((specialAbility) => { specialAbilities.forEach((specialAbility) => {
const compendiumOfSF = game.packs.get('DSA_4-1.sonderfertigkeiten'); const compendiumOfSF = game.packs.get('DSA_4-1.sonderfertigkeiten');
const sfId = compendiumOfSF?.index.find(sf => sf.name === specialAbility.name) const regexp = /(\w*)\W?(\w*)?/
const [variantName, baseAbility, level] = regexp.exec(specialAbility.name)
const sfId = compendiumOfSF?.index.find(sf => sf.name === baseAbility)
if (sfId) { if (sfId) {
compendiumOfSF.getDocument(sfId._id).then(sf => actor.createEmbeddedDocuments('Item', [sf])) if (variantName) {
console.log(baseAbility + " to be imported as " + variantName) // TODO if baseAbility already imported, adjust its level instead of adding a new embeddedDocument
}
compendiumOfSF.getDocument(sfId._id).then(sf => {
actor.createEmbeddedDocuments('Item', [sf]).then(_ => {
actor.itemTypes["SpecialAbility"].find(p => p.name === baseAbility).update({
"system.value": variantName
})
})
})
} else { } else {
actor.createEmbeddedDocuments('Item', [ actor.createEmbeddedDocuments('Item', [
new SpecialAbility({ new SpecialAbility({

View File

@ -0,0 +1,19 @@
.row {
display: flex;
flex-direction: row;
gap: 8px;
> * {
flex: 1;
}
}
.column {
display: flex;
flex-direction: column;
gap: 8px;
> * {
flex: 1;
}
}

View File

@ -6,6 +6,7 @@
@use "molecules/lists"; @use "molecules/lists";
@use "molecules/attributes"; @use "molecules/attributes";
@use "molecules/sidebar-elements"; @use "molecules/sidebar-elements";
@use "molecules/rows-and-columns";
@use "molecules/tabs"; @use "molecules/tabs";
@use "molecules/paperdoll"; @use "molecules/paperdoll";

View File

@ -1,11 +1,11 @@
<section class="tab {{tabs.advantage.id}} {{tabs.advantage.cssClass}}" <section class="tab {{tabs.advantage.id}} {{tabs.advantage.cssClass}}"
data-tab="{{tabs.advantage.id}}" data-tab="{{tabs.advantage.id}}"
data-group="{{tabs.advantage.group}}"> data-group="{{tabs.advantage.group}}">
<div> <div class="row">
<label>Name</label> <div>
<input name="system.name" value="{{system.name}}"/> <label>Name</label>
<input type="text" name="system.name" value="{{system.name}}"/>
</div> </div>
{{#if hasModality}} {{#if hasModality}}
<div> <div>
<label for="{{this._id}}.choice">Auswahl</label> <label for="{{this._id}}.choice">Auswahl</label>
@ -18,6 +18,7 @@
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}
</div>
<div class="body"> <div class="body">
<label>Beschreibung</label> <label>Beschreibung</label>
<prose-mirror <prose-mirror

View File

@ -2,10 +2,24 @@
data-tab="{{tabs.specialability.id}}" data-tab="{{tabs.specialability.id}}"
data-group="{{tabs.specialability.group}}"> data-group="{{tabs.specialability.group}}">
<div> <div>
<div class="row">
<div> <div>
<label>Name</label> <label>Name</label>
<input name="system.name" value="{{system.name}}"/> <input type="text" name="system.name" value="{{system.name}}"/>
</div>
{{#if hasModality}}
<div>
<label for="{{this._id}}.choice">Auswahl</label>
{{#if hasChoices}}
<select id="{{this._id}}.choice" name="system.value">
{{selectOptions choices selected=system.value inverted=true}}
</select>
{{else}}
<input id="{{this._id}}.choice" name="system.value" value="{{system.value}}"/>
{{/if}}
</div>
{{/if}}
</div> </div>
<div class="body"> <div class="body">
<label>Aktionstext</label> <label>Aktionstext</label>
@ -29,7 +43,12 @@
{{{text}}} {{{text}}}
</prose-mirror> </prose-mirror>
</div> </div>
<div class="mods">
{{#each mod}}
<span>{{this.name}} {{this.value}}</span>
{{/each}}
</div>
</div> </div>
</div> </section>