#69 fixes equipment dialog to adhere the new model and laid out controls in a pleasing manner.

main
macniel 2026-03-14 11:00:32 +01:00
parent 9dc95f7ff7
commit 1dd43451c2
8 changed files with 339 additions and 123 deletions

View File

@ -16,8 +16,11 @@ class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2) {
resizable: true, resizable: true,
}, },
actions: { actions: {
editImage: DocumentSheetV2.DEFAULT_OPTIONS.actions.editImage editImage: DocumentSheetV2.DEFAULT_OPTIONS.actions.editImage,
addToMelee: EquipmentSheet.#addToMelee,
removeFromMelee: EquipmentSheet.#removeFromMelee,
addToRanged: EquipmentSheet.#addToRanged,
removeFromRanged: EquipmentSheet.#removeFromRanged
} }
} }
@ -72,6 +75,38 @@ class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2) {
return options return options
} }
static async #addToMelee(event, target) {
const optionId = this.element.querySelector(`[data-target-field="${target.dataset.targetField}"]`).value
const meleeSkills = this.document.system.meleeSkills
if (optionId.trim() !== '' && !meleeSkills.includes(optionId)) {
meleeSkills.push(optionId)
await this.document.update({'system.meleeSkills': meleeSkills})
}
}
static async #removeFromMelee(event, target) {
const {optionId} = target.dataset
let meleeSkills = this.document.system.meleeSkills
meleeSkills = meleeSkills.toSpliced(meleeSkills.indexOf(optionId), 1)
await this.document.update({'system.meleeSkills': meleeSkills})
}
static async #addToRanged(event, target) {
const optionId = this.element.querySelector(`[data-target-field="${target.dataset.targetField}"]`).value
const rangedSkills = this.document.system.rangedSkills
if (optionId.trim() !== '' && !rangedSkills.includes(optionId)) {
rangedSkills.push(optionId)
await this.document.update({'system.rangedSkills': rangedSkills})
}
}
static async #removeFromRanged(event, target) {
const {optionId} = target.dataset
let rangedSkills = this.document.system.rangedSkills
rangedSkills = rangedSkills.toSpliced(rangedSkills.indexOf(optionId), 1)
await this.document.update({'system.rangedSkills': rangedSkills})
}
/** /**
* Handle form submission * Handle form submission
* @this {EquipmentSheet} * @this {EquipmentSheet}
@ -177,7 +212,9 @@ class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2) {
"Raufen": "Raufen" "Raufen": "Raufen"
}, },
entries: equipmentData.meleeSkills, entries: equipmentData.meleeSkills,
targetField: "meleeSkills" targetField: "meleeSkills",
removeOption: "removeFromMelee",
addOption: "addToMelee",
} }
} }
@ -193,7 +230,9 @@ class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2) {
"Bogen": "Bogen", "Bogen": "Bogen",
}, },
entries: equipmentData.rangedSkills, entries: equipmentData.rangedSkills,
targetField: "rangedSkills" targetField: "rangedSkills",
removeOption: "removeFromRanged",
addOption: "addToRanged",
} }
} }

View File

@ -0,0 +1,36 @@
.array-editor {
.array-entry {
display: flex;
gap: 4px;
.label {
flex: 1 0;
align-self: center;
}
button.remove {
flex: 0 1;
}
&:nth-child(odd) {
background-color: rgba(0, 0, 0, 0.1);
}
}
.options {
display: flex;
gap: 4px;
select {
flex: 1 0;
}
button {
height: 32px;
width: 32px;
}
}
}

View File

@ -5,91 +5,223 @@
.tab.meta.active > div { .tab.meta.active > div {
display: grid; display: grid;
grid-auto-columns: 1fr 1fr; grid-auto-columns: 1fr 1fr;
grid-template-columns: 80px auto; grid-template-columns: 80px auto;
grid-template-rows: 48px auto 48px; grid-template-rows: 48px auto 48px;
gap: 8px; gap: 8px;
grid-template-areas: grid-template-areas:
"quantity name" "quantity name"
"description description" "description description"
"bottomline bottomline"; "bottomline bottomline";
.name { .name {
grid-area: name; grid-area: name;
}
.name {
position: relative;
.img {
position: absolute;
right: 0;
bottom: 6px;
width: 24px;
height: 24px;
} }
.name { label {
position: relative; position: absolute;
left: 0;
top: 0;
right: 26px;
bottom: 0;
}
}
.img { .bottomline {
position: absolute; grid-area: bottomline;
right: 0; display: grid;
bottom: 6px; grid-template-columns: repeat(2, 1fr);
width: 24px; gap: 8px;
height: 24px;
} .named-value {
position: relative;
height: 48px;
label { label {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
right: 26px;
bottom: 0; bottom: 0;
} width: 80px;
} line-height: 24px;
vertical-align: middle;
.bottomline { input {
grid-area: bottomline;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px;
.named-value {
position: relative;
height: 48px;
label {
position: absolute; position: absolute;
left: 0; left: 80px;
top: 0; top: 0;
bottom: 0; bottom: 0;
width: 80px; right: 0;
line-height: 24px;
vertical-align: middle;
input {
position: absolute;
left: 80px;
top: 0;
bottom: 0;
right: 0;
}
} }
} }
} }
.quantity {
grid-area: quantity;
}
.description {
grid-area: description;
position: relative;
display: flex;
flex-direction: column;
label {
flex: 0;
}
.editor {
flex: 1;
}
}
} }
.quantity {
grid-area: quantity;
}
.description {
grid-area: description;
position: relative;
display: flex;
flex-direction: column;
label {
flex: 0;
}
.editor {
flex: 1;
}
}
}
.tab.melee.active > div {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 48px auto 48px 48px;
gap: 8px;
grid-template-areas:
"tp tpbonus"
"applicableSkills applicableSkills"
"initiativeMod breakFactor"
"atMod paMod";
.tp {
grid-area: tp;
}
.tp-bonus {
grid-area: tpbonus;
display: grid;
grid-template-rows: 16px 1fr;
gap: 4px;
grid-template-areas: "label label" "tp kk";
label {
grid-area: label;
text-align: center;
}
}
.applicable-skills {
grid-area: applicableSkills;
.array-editor {
display: flex;
flex-direction: column;
height: 100%;
padding-bottom: 24px;
ul {
flex: 1 0;
}
}
}
.initiative-modifier {
grid-area: initiativeMod;
}
.breakfactor {
grid-area: breakFactor;
}
.at-mod {
grid-area: atMod;
}
.pa-mod {
grid-area: paMod;
}
}
.tab.armor.active > div {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 48px auto 48px 48px;
gap: 8px;
grid-template-areas:
"head head chest chest"
"back back belly belly"
"leftArm leftArm rightArm rightArm"
"leftLeg leftLeg rightLeg rightLeg"
"totalArmor totalHandicap iniMod breakFactor"
"atMod atMod paMod paMod";
.head {
grid-area: head;
}
.chest {
grid-area: chest;
}
.back {
grid-area: back;
}
.belly {
grid-area: belly;
}
.left-arm {
grid-area: leftArm;
}
.right-arm {
grid-area: rightArm;
}
.left-leg {
grid-area: leftLeg;
}
.right-leg {
grid-area: rightLeg;
}
.total {
grid-area: totalArmor;
}
.handicap {
grid-area: totalHandicap;
}
.initiative-modifier {
grid-area: iniMod;
}
.break-factor {
grid-area: breakFactor;
}
.at-mod {
grid-area: atMod;
}
.pa-mod {
grid-area: paMod;
}
}
} }

View File

@ -11,6 +11,7 @@
@use "molecules/coins"; @use "molecules/coins";
@use "molecules/weights"; @use "molecules/weights";
@use "molecules/fieldset"; @use "molecules/fieldset";
@use "molecules/array-editor";
@use "molecules/tabs"; @use "molecules/tabs";
@use "molecules/paperdoll"; @use "molecules/paperdoll";

View File

@ -3,79 +3,81 @@
data-group="{{tabs.armor.group}}"> data-group="{{tabs.armor.group}}">
<div> <div>
<fieldset> <div class="head">
<legend>Rüstungswerte</legend> <label>Kopf
<input type="text" name="system.armorValue.kopf" value="{{system.armorValue.kopf}}"/>
<div>
<label>Gesamt Rüstungswert
<input type="text" name="system.armorValue.total" value="{{system.armorValue.total}}"/>
</label> </label>
</div> </div>
<div> <div class="chest">
<label>Brust
<input type="text" name="system.armorValue.brust" value="{{system.armorValue.brust}}"/>
</label>
</div>
<div class="back">
<label>Rücken
<input type="text" name="system.armorValue.ruecken" value="{{system.armorValue.ruecken}}"/>
</label>
</div>
<div class="belly">
<label>Bauch
<input type="text" name="system.armorValue.bauch" value="{{system.armorValue.bauch}}"/>
</label>
</div>
<div class="left-arm">
<label>Linker Arm <label>Linker Arm
<input type="text" name="system.armorValue.armlinks" value="{{system.armorValue.armlinks}}"/> <input type="text" name="system.armorValue.armlinks" value="{{system.armorValue.armlinks}}"/>
</label> </label>
</div> </div>
<div>
<div class="right-arm">
<label>Rechter Arm <label>Rechter Arm
<input type="text" name="system.armorValue.armrechts" value="{{system.armorValue.armrechts}}"/> <input type="text" name="system.armorValue.armrechts" value="{{system.armorValue.armrechts}}"/>
</label> </label>
</div> </div>
<div>
<div class="left-leg">
<label>Linkes Bein <label>Linkes Bein
<input type="text" name="system.armorValue.beinlinks" value="{{system.armorValue.beinlinks}}"/> <input type="text" name="system.armorValue.beinlinks" value="{{system.armorValue.beinlinks}}"/>
</label> </label>
</div> </div>
<div>
<div class="right-leg">
<label>Rechtes Bein <label>Rechtes Bein
<input type="text" name="system.armorValue.beinrechts" value="{{system.armorValue.beinrechts}}"/> <input type="text" name="system.armorValue.beinrechts" value="{{system.armorValue.beinrechts}}"/>
</label> </label>
</div> </div>
<div> <div class="total">
<label>Bauch <label>Rüstungswert
<input type="text" name="system.armorValue.bauch" value="{{system.armorValue.bauch}}"/> <input type="text" name="system.armorValue.total" value="{{system.armorValue.total}}"/>
</label> </label>
</div> </div>
<div>
<label>Brust
<input type="text" name="system.armorValue.brust" value="{{system.armorValue.brust}}"/>
</label>
</div>
<div>
<label>Rücken
<input type="text" name="system.armorValue.ruecken" value="{{system.armorValue.ruecken}}"/>
</label>
</div>
<div>
<label>Kopf
<input type="text" name="system.armorValue.kopf" value="{{system.armorValue.kopf}}"/>
</label>
</div>
</fieldset>
<div> <div class="handicap">
<label>Gesamt Behinderung <label>Behinderung
<input type="text" name="system.armorHandicap" value="{{system.armorHandicap}}"/> <input type="text" name="system.armorHandicap" value="{{system.armorHandicap}}"/>
</label> </label>
</div> </div>
<div> <div class="initiative-modifier">
<label>Initiative Modifaktor <label>Initiative
<input type="text" name="system.iniModifier" value="{{system.iniModifier}}"/> <input type="text" name="system.iniModifier" value="{{system.iniModifier}}"/>
</label> </label>
</div> </div>
<div> <div class="break-factor">
<label>Bruchfaktor <label>Bruchfaktor
<input type="text" name="system.breakFactor" value="{{system.breakFactor}}"/> <input type="text" name="system.breakFactor" value="{{system.breakFactor}}"/>
</label> </label>
</div> </div>
<div> <div class="at-mod">
<label>Attacke <label>Attacke
<input type="text" name="system.attackModifier" value="{{system.attackModifier}}"/> <input type="text" name="system.attackModifier" value="{{system.attackModifier}}"/>
</label> </label>
</div> </div>
<div> <div class="pa-mod">
<label>Parade <label>Parade
<input type="text" name="system.parryModifier" value="{{system.parryModifier}}"/> <input type="text" name="system.parryModifier" value="{{system.parryModifier}}"/>
</label> </label>

View File

@ -1,40 +1,38 @@
<section class="tab {{tabs.melee.id}} {{tabs.melee.cssClass}}" <section class="tab {{tabs.melee.id}} {{tabs.melee.cssClass}}"
data-tab="{{tabs.melee.id}}" data-tab="{{tabs.melee.id}}"
data-group="{{tabs.melee.group}}"> data-group="{{tabs.melee.group}}">
<div> <div class="melee">
<div> <div class="tp">
<label>TP <label>TP
<input type="text" name="system.meleeAttackDamage" value="{{system.meleeAttackDamage}}"/> <input type="text" name="system.meleeAttackDamage" value="{{system.meleeAttackDamage}}"/>
</label> </label>
</div> </div>
<div> <div class="tp-bonus">
<label>TP/KK <label>TP/KK</label>
<input name="system.meleeAttackModifier" type="number" value="{{system.meleeAttackModifier}}"/> <input name="system.meleeAttackModifier" type="number" value="{{system.meleeAttackModifier}}"/>
<input name="system.meleeAttackModifierIncrement" type="number" <input name="system.meleeAttackModifierIncrement" type="number"
value="{{system.meleeAttackModifierIncrement}}"/> value="{{system.meleeAttackModifierIncrement}}"/>
</label>
</div> </div>
<div> <div class="applicable-skills">
<label>Geführte Talente <label>Geführte Talente</label>
{{> "systems/DSA_4-1/templates/ui/partial-array-editor.hbs" this.meleeSkillsAndOptions}} {{> "systems/DSA_4-1/templates/ui/partial-array-editor.hbs" this.meleeSkillsAndOptions}}
</label>
</div> </div>
<div> <div class="initiative-modifier">
<label>Initiative <label>Initiative
<input name="system.iniModifier" type="number" value="{{system.iniModifier}}"/> <input name="system.iniModifier" type="number" value="{{system.iniModifier}}"/>
</label> </label>
</div> </div>
<div> <div class="breakfactor">
<label>Bruchfaktor <label>Bruchfaktor
<input name="system.breakFactor" type="number" value="{{system.breakFactor}}"/> <input name="system.breakFactor" type="number" value="{{system.breakFactor}}"/>
</label> </label>
</div> </div>
<div> <div class="at-mod">
<label>Attacke <label>Attacke
<input name="system.attackModifier" type="number" value="{{system.attackModifier}}"/> <input name="system.attackModifier" type="number" value="{{system.attackModifier}}"/>
</label> </label>
</div> </div>
<div> <div class="pa-mod">
<label>Parade <label>Parade
<input name="system.parryModifier" type="number" value="{{system.parryModifier}}"/> <input name="system.parryModifier" type="number" value="{{system.parryModifier}}"/>
</label> </label>

View File

@ -1,29 +1,29 @@
<section class="tab {{tabs.ranged.id}} {{tabs.ranged.cssClass}}" <section class="tab {{tabs.ranged.id}} {{tabs.ranged.cssClass}}"
data-tab="{{tabs.ranged.id}}" data-tab="{{tabs.ranged.id}}"
data-group="{{tabs.ranged.group}}"> data-group="{{tabs.ranged.group}}">
<div> <div class="ranged">
<div> <div class="tp">
<label>TP <label>TP
<input type="text" name="system.rangedAttackDamage" value="{{system.rangedAttackDamage}}"/> <input type="text" name="system.rangedAttackDamage" value="{{system.rangedAttackDamage}}"/>
</label> </label>
</div> </div>
<div> <div class="ranges">
<label>Reichweiten <label>Reichweiten
<input type="text" name="system.rangedRangeModifier" value="{{system.rangedRangeModifier}}"/> <input type="text" name="system.rangedRangeModifier" value="{{system.rangedRangeModifier}}"/>
</label> </label>
</div> </div>
<div> <div class="tpmod">
<label>TP+ <label>TP+
<input type="text" name="system.rangeRangeDamageModifier" <input type="text" name="system.rangeRangeDamageModifier"
value="{{system.rangeRangeDamageModifier}}"/> value="{{system.rangeRangeDamageModifier}}"/>
</label> </label>
</div> </div>
<div> <div class="applicable-skills">
<label>Geführte Talente <label>Geführte Talente
{{> "systems/DSA_4-1/templates/ui/partial-array-editor.hbs" this.rangedSkillsAndOptions}} {{> "systems/DSA_4-1/templates/ui/partial-array-editor.hbs" this.rangedSkillsAndOptions}}
</label> </label>
</div> </div>
<div> <div class="reload-time">
<label>Ladedauer (Aktionen) <label>Ladedauer (Aktionen)
<input type="text" name="system.rangedReloadTime" value="{{system.rangedReloadTime}}"/> <input type="text" name="system.rangedReloadTime" value="{{system.rangedReloadTime}}"/>
</label> </label>

View File

@ -2,10 +2,18 @@
<ul> <ul>
{{#each entries}} {{#each entries}}
<li>{{this}}</li> <li class="array-entry">
<span class="label">{{this}}</span>
<button class="remove" type="button" data-action="{{../removeOption}}" data-option-id="{{this}}">
<i class="fa fa-minus"></i>
</button>
</li>
{{/each}} {{/each}}
</ul> </ul>
<select data-target-field="{{targetField}}"> <div class="options">
<select class="selector" data-target-field="{{targetField}}">
{{selectOptions options inverted=true}} {{selectOptions options inverted=true}}
</select> </select>
<button class=add" type="button" data-target-field="{{targetField}}" data-action="{{addOption}}"><i class="fa fa-plus"></i></button>
</div>
</div> </div>