Added optional equipment tab

This commit is contained in:
WBHarry 2025-06-18 15:40:51 +02:00
parent f755d7f9f5
commit a902b2f1e5
8 changed files with 648 additions and 141 deletions

View file

@ -427,6 +427,15 @@
"SelectCommunity": "Select Community", "SelectCommunity": "Select Community",
"SelectClass": "Select Class", "SelectClass": "Select Class",
"SelectSubclass": "Select Subclass", "SelectSubclass": "Select Subclass",
"SelectArmor": "Select Armor",
"SelectPrimaryWeapon": "Select Primary Weapon",
"SelectSecondaryWeapon": "Select Secondary Weapon",
"SuggestedArmor": "Suggested Armor",
"SuggestedWeapons": "Suggested Weapon",
"SuggestedPrimaryWeapon": "Suggested Primary Weapon",
"SuggestedSecondaryWeapon": "Suggested Secondary Weapon",
"StartingItems": "Starting Items",
"Choice": "Choice",
"NewExperience": "New Experience..", "NewExperience": "New Experience..",
"FinishCreation": "Finish Character Setup", "FinishCreation": "Finish Character Setup",
"Tabs": { "Tabs": {
@ -440,7 +449,11 @@
"MissingClass": "You don't have a class selected yet.", "MissingClass": "You don't have a class selected yet.",
"WrongDomain": "The card isn't from one of your class domains.", "WrongDomain": "The card isn't from one of your class domains.",
"CardTooHighLevel": "The card is too high level!", "CardTooHighLevel": "The card is too high level!",
"DuplicateCard": "You cannot select the same card more than once." "DuplicateCard": "You cannot select the same card more than once.",
"NotPrimary": "The weapon is not a primary weapon!",
"NotSecondary": "The weapon is not a secondary weapon!",
"ItemTooHighTier": "The item must be from Tier1",
"PrimaryIsTwoHanded": "Cannot select a secondary weapon with a two-handed primary!"
} }
}, },
"LevelUp": { "LevelUp": {

View file

@ -1,4 +1,5 @@
import { abilities } from '../config/actorConfig.mjs'; import { abilities } from '../config/actorConfig.mjs';
import { burden } from '../config/generalConfig.mjs';
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
@ -21,9 +22,20 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
domainCards: { domainCards: {
[foundry.utils.randomID()]: {}, [foundry.utils.randomID()]: {},
[foundry.utils.randomID()]: {} [foundry.utils.randomID()]: {}
},
visibility: 1
};
this.equipment = {
armor: {},
primaryWeapon: {},
secondaryWeapon: {},
inventory: {
take: {},
choiceA: {},
choiceB: {}
} }
}; };
this.visibility = 5;
this._dragDrop = this._createDragDropHandlers(); this._dragDrop = this._createDragDropHandlers();
} }
@ -38,7 +50,9 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
position: { width: 800, height: 'auto' }, position: { width: 800, height: 'auto' },
actions: { actions: {
viewCompendium: this.viewCompendium, viewCompendium: this.viewCompendium,
viewItem: this.viewItem,
useSuggestedTraits: this.useSuggestedTraits, useSuggestedTraits: this.useSuggestedTraits,
equipmentChoice: this.equipmentChoice,
finish: this.finish finish: this.finish
}, },
form: { form: {
@ -51,7 +65,11 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
{ dragSelector: null, dropSelector: '.community-card' }, { dragSelector: null, dropSelector: '.community-card' },
{ dragSelector: null, dropSelector: '.class-card' }, { dragSelector: null, dropSelector: '.class-card' },
{ dragSelector: null, dropSelector: '.subclass-card' }, { dragSelector: null, dropSelector: '.subclass-card' },
{ dragSelector: null, dropSelector: '.domain-card' } { dragSelector: null, dropSelector: '.domain-card' },
{ dragSelector: null, dropSelector: '.armor-card' },
{ dragSelector: null, dropSelector: '.primary-weapon-card' },
{ dragSelector: null, dropSelector: '.secondary-weapon-card' },
{ dragSelector: '.suggestion-inner-container', dropSelector: '.selections-container' }
] ]
}; };
@ -59,7 +77,7 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
tabs: { template: 'systems/daggerheart/templates/views/characterCreation/tabs.hbs' }, tabs: { template: 'systems/daggerheart/templates/views/characterCreation/tabs.hbs' },
setup: { template: 'systems/daggerheart/templates/views/characterCreation/tabs/setup.hbs' }, setup: { template: 'systems/daggerheart/templates/views/characterCreation/tabs/setup.hbs' },
equipment: { template: 'systems/daggerheart/templates/views/characterCreation/tabs/equipment.hbs' }, equipment: { template: 'systems/daggerheart/templates/views/characterCreation/tabs/equipment.hbs' },
story: { template: 'systems/daggerheart/templates/views/characterCreation/tabs/story.hbs' }, // story: { template: 'systems/daggerheart/templates/views/characterCreation/tabs/story.hbs' },
footer: { template: 'systems/daggerheart/templates/views/characterCreation/footer.hbs' } footer: { template: 'systems/daggerheart/templates/views/characterCreation/footer.hbs' }
}; };
@ -78,15 +96,15 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
id: 'equipment', id: 'equipment',
label: 'DAGGERHEART.CharacterCreation.Tabs.Equipment', label: 'DAGGERHEART.CharacterCreation.Tabs.Equipment',
optional: true optional: true
},
story: {
active: false,
cssClass: '',
group: 'primary',
id: 'story',
label: 'DAGGERHEART.CharacterCreation.Tabs.Story',
optional: true
} }
// story: {
// active: false,
// cssClass: '',
// group: 'primary',
// id: 'story',
// label: 'DAGGERHEART.CharacterCreation.Tabs.Story',
// optional: true
// }
}; };
_getTabs(tabs) { _getTabs(tabs) {
@ -108,15 +126,39 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
experiencesFinished && experiencesFinished &&
domainCardsFinished; domainCardsFinished;
break; break;
case 'equipment':
const armorFinished = this.equipment.armor?.uuid;
const primaryFinished = this.equipment.primaryWeapon?.uuid;
const secondaryFinished =
this.equipment.secondaryWeapon?.uuid ||
(primaryFinished && this.equipment.primaryWeapon.system.burden == burden.twoHanded.value);
const choiceAFinished = this.equipment.inventory.choiceA?.uuid;
const choiceBFinished = this.equipment.inventory.choiceB?.uuid;
v.finished =
armorFinished && primaryFinished && secondaryFinished && choiceAFinished && choiceBFinished;
} }
} }
tabs.equipment.cssClass = tabs.setup.finished ? tabs.equipment.cssClass : 'disabled'; tabs.equipment.cssClass = tabs.setup.finished ? tabs.equipment.cssClass : 'disabled';
tabs.story.cssClass = tabs.setup.finished ? tabs.story.cssClass : 'disabled'; // tabs.story.cssClass = tabs.setup.finished ? tabs.story.cssClass : 'disabled';
return tabs; return tabs;
} }
changeTab(tab, group, options) {
super.changeTab(tab, group, options);
for (var listTab of Object.keys(this.constructor.TABS)) {
const marker = options.navElement.querySelector(`a[data-action="tab"].${listTab} .finish-marker`);
if (listTab === tab) {
marker.classList.add('active');
} else {
marker.classList.remove('active');
}
}
}
_attachPartListeners(partId, htmlElement, options) { _attachPartListeners(partId, htmlElement, options) {
super._attachPartListeners(partId, htmlElement, options); super._attachPartListeners(partId, htmlElement, options);
@ -127,59 +169,104 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
const context = await super._prepareContext(_options); const context = await super._prepareContext(_options);
context.tabs = this._getTabs(this.constructor.TABS); context.tabs = this._getTabs(this.constructor.TABS);
const availableTraitModifiers = game.settings return context;
.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Homebrew) }
.traitArray.map(trait => ({ key: trait, name: trait }));
for (let trait of Object.values(this.setup.traits).filter(x => x.value !== null)) {
const index = availableTraitModifiers.findIndex(x => x.key === trait.value);
if (index !== -1) {
availableTraitModifiers.splice(index, 1);
}
}
context.suggestedTraits = this.setup.class.system async _preparePartContext(partId, context) {
? Object.keys(this.setup.class.system.characterGuide.suggestedTraits).map(traitKey => { switch (partId) {
const trait = this.setup.class.system.characterGuide.suggestedTraits[traitKey]; case 'setup':
return `${game.i18n.localize(`DAGGERHEART.Abilities.${traitKey}.short`)} ${trait > 0 ? `+${trait}` : trait}`; const availableTraitModifiers = game.settings
}) .get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Homebrew)
: []; .traitArray.map(trait => ({ key: trait, name: trait }));
context.traits = { for (let trait of Object.values(this.setup.traits).filter(x => x.value !== null)) {
values: Object.keys(this.setup.traits).map(traitKey => { const index = availableTraitModifiers.findIndex(x => x.key === trait.value);
const trait = this.setup.traits[traitKey]; if (index !== -1) {
const options = [...availableTraitModifiers]; availableTraitModifiers.splice(index, 1);
if (trait.value !== null && !options.some(x => x.key === trait.value)) }
options.push({ key: trait.value, name: trait.value }); }
return { context.suggestedTraits = this.setup.class.system
...trait, ? Object.keys(this.setup.class.system.characterGuide.suggestedTraits).map(traitKey => {
key: traitKey, const trait = this.setup.class.system.characterGuide.suggestedTraits[traitKey];
name: game.i18n.localize(abilities[traitKey].label), return `${game.i18n.localize(`DAGGERHEART.Abilities.${traitKey}.short`)} ${trait > 0 ? `+${trait}` : trait}`;
options: options })
: [];
context.traits = {
values: Object.keys(this.setup.traits).map(traitKey => {
const trait = this.setup.traits[traitKey];
const options = [...availableTraitModifiers];
if (trait.value !== null && !options.some(x => x.key === trait.value))
options.push({ key: trait.value, name: trait.value });
return {
...trait,
key: traitKey,
name: game.i18n.localize(abilities[traitKey].label),
options: options
};
})
}; };
}) context.traits.nrTotal = Object.keys(context.traits.values).length;
}; context.traits.nrSelected = Object.values(context.traits.values).reduce(
context.traits.nrTotal = Object.keys(context.traits.values).length; (acc, trait) => acc + (trait.value !== null ? 1 : 0),
context.traits.nrSelected = Object.values(context.traits.values).reduce( 0
(acc, trait) => acc + (trait.value !== null ? 1 : 0), );
0
);
context.experience = { context.experience = {
values: this.setup.experiences, values: this.setup.experiences,
nrTotal: Object.keys(this.setup.experiences).length, nrTotal: Object.keys(this.setup.experiences).length,
nrSelected: Object.values(this.setup.experiences).reduce((acc, exp) => acc + (exp.description ? 1 : 0), 0) nrSelected: Object.values(this.setup.experiences).reduce(
}; (acc, exp) => acc + (exp.description ? 1 : 0),
0
)
};
context.ancestry = { ...this.setup.ancestry, compendium: 'ancestries' }; context.ancestry = { ...this.setup.ancestry, compendium: 'ancestries' };
context.community = { ...this.setup.community, compendium: 'communities' }; context.community = { ...this.setup.community, compendium: 'communities' };
context.class = { ...this.setup.class, compendium: 'classes' }; context.class = { ...this.setup.class, compendium: 'classes' };
context.subclass = { ...this.setup.subclass, compendium: 'subclasses' }; context.subclass = { ...this.setup.subclass, compendium: 'subclasses' };
context.domainCards = Object.keys(this.setup.domainCards).reduce((acc, x) => { context.domainCards = Object.keys(this.setup.domainCards).reduce((acc, x) => {
acc[x] = { ...this.setup.domainCards[x], compendium: 'domains' }; acc[x] = { ...this.setup.domainCards[x], compendium: 'domains' };
return acc; return acc;
}, {}); }, {});
context.visibility = this.visibility; context.visibility = this.setup.visibility;
break;
case 'equipment':
const suggestions = await this.getEquipmentSuggestions(
this.equipment.inventory.choiceA,
this.equipment.inventory.choiceB
);
context.armor = {
...this.equipment.armor,
suggestion: { ...suggestions.armor, taken: suggestions.armor?.uuid === this.equipment.armor?.uuid },
compendium: 'armors'
};
context.primaryWeapon = {
...this.equipment.primaryWeapon,
suggestion: {
...suggestions.primaryWeapon,
taken: suggestions.primaryWeapon?.uuid === this.equipment.primaryWeapon?.uuid
},
compendium: 'weapons'
};
context.secondaryWeapon = {
...this.equipment.secondaryWeapon,
suggestion: {
...suggestions.secondaryWeapon,
taken: suggestions.secondaryWeapon?.uuid === this.equipment.secondaryWeapon?.uuid
},
disabled: this.equipment.primaryWeapon?.system?.burden === burden.twoHanded.value,
compendium: 'weapons'
};
context.inventory = {
take: suggestions.inventory.take,
choiceA: { suggestions: suggestions.inventory.choiceA, compendium: 'consumables' },
choiceB: { suggestions: suggestions.inventory.choiceB, compendium: 'general-items' }
};
break;
}
return context; return context;
} }
@ -187,12 +274,12 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
this.setup = foundry.utils.mergeObject(this.setup, formData.object); this.setup = foundry.utils.mergeObject(this.setup, formData.object);
this.visibility = this.getUpdateVisibility(); this.setup.visibility = this.getUpdateVisibility();
this.render(); this.render();
} }
getUpdateVisibility() { getUpdateVisibility() {
switch (this.visibility) { switch (this.setup.visibility) {
case 5: case 5:
return 5; return 5;
case 4: case 4:
@ -206,9 +293,29 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
} }
} }
async getEquipmentSuggestions(choiceA, choiceB) {
if (!this.setup.class.uuid) return { inventory: { take: [] } };
const { inventory, characterGuide } = this.setup.class.system;
return {
armor: characterGuide.suggestedArmor ?? null,
primaryWeapon: characterGuide.suggestedPrimaryWeapon ?? null,
secondaryWeapon:
{ ...characterGuide.suggestedSecondaryWeapon, uuid: characterGuide.suggestedSecondaryWeapon.uuid } ??
null,
inventory: {
take: inventory.take ?? [],
choiceA:
inventory.choiceA?.map(x => ({ ...x, uuid: x.uuid, selected: x.uuid === choiceA?.uuid })) ?? [],
choiceB: inventory.choiceB?.map(x => ({ ...x, uuid: x.uuid, selected: x.uuid === choiceB?.uuid })) ?? []
}
};
}
_createDragDropHandlers() { _createDragDropHandlers() {
return this.options.dragDrop.map(d => { return this.options.dragDrop.map(d => {
d.callbacks = { d.callbacks = {
dragstart: this._onDragStart.bind(this),
drop: this._onDrop.bind(this) drop: this._onDrop.bind(this)
}; };
return new foundry.applications.ux.DragDrop.implementation(d); return new foundry.applications.ux.DragDrop.implementation(d);
@ -219,6 +326,10 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
(await game.packs.get(`daggerheart.${target.dataset.compendium}`))?.render(true); (await game.packs.get(`daggerheart.${target.dataset.compendium}`))?.render(true);
} }
static async viewItem(_, target) {
(await foundry.utils.fromUuid(target.dataset.uuid)).sheet.render(true);
}
static useSuggestedTraits() { static useSuggestedTraits() {
this.setup.traits = Object.keys(this.setup.traits).reduce((acc, traitKey) => { this.setup.traits = Object.keys(this.setup.traits).reduce((acc, traitKey) => {
acc[traitKey] = { acc[traitKey] = {
@ -227,6 +338,13 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
}; };
return acc; return acc;
}, {}); }, {});
this.setup.visibility = this.getUpdateVisibility();
this.render();
}
static async equipmentChoice(_, target) {
this.equipment.inventory[target.dataset.path] = await foundry.utils.fromUuid(target.dataset.uuid);
this.render(); this.render();
} }
@ -237,6 +355,27 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
await this.character.createEmbeddedDocuments('Item', [this.setup.subclass]); await this.character.createEmbeddedDocuments('Item', [this.setup.subclass]);
await this.character.createEmbeddedDocuments('Item', Object.values(this.setup.domainCards)); await this.character.createEmbeddedDocuments('Item', Object.values(this.setup.domainCards));
if (this.equipment.armor.uuid)
await this.character.createEmbeddedDocuments('Item', [
{ ...this.equipment.armor, system: { ...this.equipment.armor.system, equipped: true } }
]);
if (this.equipment.primaryWeapon.uuid)
await this.character.createEmbeddedDocuments('Item', [
{ ...this.equipment.primaryWeapon, system: { ...this.equipment.primaryWeapon.system, equipped: true } }
]);
if (this.equipment.secondaryWeapon.uuid)
await this.character.createEmbeddedDocuments('Item', [
{
...this.equipment.secondaryWeapon,
system: { ...this.equipment.secondaryWeapon.system, equipped: true }
}
]);
if (this.equipment.inventory.choiceA.uuid)
await this.character.createEmbeddedDocuments('Item', [this.equipment.inventory.choiceA]);
if (this.equipment.inventory.choiceB.uuid)
await this.character.createEmbeddedDocuments('Item', [this.equipment.inventory.choiceB]);
await this.character.createEmbeddedDocuments('Item', this.setup.class.system.inventory.take);
await this.character.update({ await this.character.update({
system: { system: {
traits: this.setup.traits, traits: this.setup.traits,
@ -249,6 +388,13 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
this.close(); this.close();
} }
async _onDragStart(event) {
const target = event.currentTarget;
event.dataTransfer.setData('text/plain', JSON.stringify(target.dataset));
event.dataTransfer.setDragImage(target, 60, 0);
}
async _onDrop(event) { async _onDrop(event) {
const data = TextEditor.getDragEventData(event); const data = TextEditor.getDragEventData(event);
const item = await foundry.utils.fromUuid(data.uuid); const item = await foundry.utils.fromUuid(data.uuid);
@ -296,11 +442,55 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
} }
this.setup.domainCards[event.target.closest('.domain-card').dataset.card] = { ...item, uuid: item.uuid }; this.setup.domainCards[event.target.closest('.domain-card').dataset.card] = { ...item, uuid: item.uuid };
} else if (item.type === 'armor' && event.target.closest('.armor-card')) {
if (item.system.tier > 1) {
ui.notifications.error(
game.i18n.localize('DAGGERHEART.CharacterCreation.Notifications.ItemTooHighTier')
);
return;
}
this.equipment.armor = { ...item, uuid: item.uuid };
} else if (item.type === 'weapon' && event.target.closest('.primary-weapon-card')) {
if (item.system.secondary) {
ui.notifications.error(game.i18n.localize('DAGGERHEART.CharacterCreation.Notifications.NotPrimary'));
return;
}
if (item.system.tier > 1) {
ui.notifications.error(
game.i18n.localize('DAGGERHEART.CharacterCreation.Notifications.ItemTooHighTier')
);
return;
}
this.equipment.primaryWeapon = { ...item, uuid: item.uuid };
} else if (item.type === 'weapon' && event.target.closest('.secondary-weapon-card')) {
if (this.equipment.primaryWeapon?.system?.burden === burden.twoHanded.value) {
ui.notifications.error(
game.i18n.localize('DAGGERHEART.CharacterCreation.Notifications.PrimaryIsTwoHanded')
);
return;
}
if (!item.system.secondary) {
ui.notifications.error(game.i18n.localize('DAGGERHEART.CharacterCreation.Notifications.NotSecondary'));
return;
}
if (item.system.tier > 1) {
ui.notifications.error(
game.i18n.localize('DAGGERHEART.CharacterCreation.Notifications.ItemTooHighTier')
);
return;
}
this.equipment.secondaryWeapon = { ...item, uuid: item.uuid };
} else { } else {
return; return;
} }
this.visibility = this.getUpdateVisibility(); this.setup.visibility = this.getUpdateVisibility();
this.render(); this.render();
} }
} }

View file

@ -221,46 +221,53 @@ export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) {
async _onDrop(event) { async _onDrop(event) {
const data = TextEditor.getDragEventData(event); const data = TextEditor.getDragEventData(event);
const item = await fromUuid(data.uuid); const item = await fromUuid(data.uuid);
const target = event.target.closest('fieldset.drop-section');
if (item.type === 'subclass') { if (item.type === 'subclass') {
await this.document.update({ await this.document.update({
'system.subclasses': [...this.document.system.subclasses.map(x => x.uuid), item.uuid] 'system.subclasses': [...this.document.system.subclasses.map(x => x.uuid), item.uuid]
}); });
} else if (item.type === 'weapon') { } else if (item.type === 'weapon') {
if (event.currentTarget.classList.contains('primary-weapon-section')) { if (target.classList.contains('primary-weapon-section')) {
if (!this.document.system.characterGuide.suggestedPrimaryWeapon && !item.system.secondary) if (!this.document.system.characterGuide.suggestedPrimaryWeapon && !item.system.secondary)
await this.document.update({ await this.document.update({
'system.characterGuide.suggestedPrimaryWeapon': item.uuid 'system.characterGuide.suggestedPrimaryWeapon': item.uuid
}); });
} else if (event.currentTarget.classList.contains('secondary-weapon-section')) { } else if (target.classList.contains('secondary-weapon-section')) {
if (!this.document.system.characterGuide.suggestedSecondaryWeapon && item.system.secondary) if (!this.document.system.characterGuide.suggestedSecondaryWeapon && item.system.secondary)
await this.document.update({ await this.document.update({
'system.characterGuide.suggestedSecondaryWeapon': item.uuid 'system.characterGuide.suggestedSecondaryWeapon': item.uuid
}); });
} }
} else if (item.type === 'armor') { } else if (item.type === 'armor') {
if (event.currentTarget.classList.contains('armor-section')) { if (target.classList.contains('armor-section')) {
if (!this.document.system.characterGuide.suggestedArmor) if (!this.document.system.characterGuide.suggestedArmor)
await this.document.update({ await this.document.update({
'system.characterGuide.suggestedArmor': item.uuid 'system.characterGuide.suggestedArmor': item.uuid
}); });
} }
} else if (event.currentTarget.classList.contains('choice-a-section')) { } else if (target.classList.contains('choice-a-section')) {
if (item.type === 'miscellaneous' || item.type === 'consumable') { if (item.type === 'miscellaneous' || item.type === 'consumable') {
if (this.document.system.inventory.choiceA.length < 2) if (this.document.system.inventory.choiceA.length < 2)
await this.document.update({ await this.document.update({
'system.inventory.choiceA': [...this.document.system.inventory.choiceA, item.uuid] 'system.inventory.choiceA': [
...this.document.system.inventory.choiceA.map(x => x.uuid),
item.uuid
]
}); });
} }
} else if (item.type === 'miscellaneous') { } else if (item.type === 'miscellaneous') {
if (event.currentTarget.classList.contains('take-section')) { if (target.classList.contains('take-section')) {
if (this.document.system.inventory.take.length < 3) if (this.document.system.inventory.take.length < 3)
await this.document.update({ await this.document.update({
'system.inventory.take': [...this.document.system.inventory.take, item.uuid] 'system.inventory.take': [...this.document.system.inventory.take.map(x => x.uuid), item.uuid]
}); });
} else if (event.currentTarget.classList.contains('choice-b-section')) { } else if (target.classList.contains('choice-b-section')) {
if (this.document.system.inventory.choiceB.length < 2) if (this.document.system.inventory.choiceB.length < 2)
await this.document.update({ await this.document.update({
'system.inventory.choiceB': [...this.document.system.inventory.choiceB, item.uuid] 'system.inventory.choiceB': [
...this.document.system.inventory.choiceB.map(x => x.uuid),
item.uuid
]
}); });
} }
} }

View file

@ -67,6 +67,23 @@
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
.selections-container {
width: 140px;
display: flex;
flex-direction: column;
text-align: center;
.card-preview-container {
border-color: light-dark(@dark-blue, @golden);
}
}
.selections-outer-container {
display: flex;
justify-content: space-evenly;
height: 210px;
}
.section-container { .section-container {
border-radius: 8px; border-radius: 8px;
border-color: light-dark(@dark-blue, @golden); border-color: light-dark(@dark-blue, @golden);
@ -170,23 +187,6 @@
} }
} }
.selections-container {
display: flex;
justify-content: space-evenly;
height: 210px;
.selections-inner-container {
width: 140px;
display: flex;
flex-direction: column;
text-align: center;
.card-preview-container {
border-color: light-dark(@dark-blue, @golden);
}
}
}
.creation-action-footer { .creation-action-footer {
display: flex; display: flex;
align-items: center; align-items: center;
@ -261,6 +261,127 @@
} }
} }
} }
.main-equipment-selection {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 16px;
&.triple {
grid-template-columns: 1fr 1fr 1fr;
}
}
.equipment-selection {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
border: 2px solid light-dark(@dark-blue, @golden);
border-radius: 8px;
legend {
margin-left: auto;
margin-right: auto;
font-size: 28px;
font-weight: bold;
padding: 0 8px;
white-space: nowrap;
}
.equipment-subsection {
display: flex;
align-items: start;
gap: 32px;
}
.equipment-wrapper {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.simple-equipment-container {
display: flex;
flex-direction: column;
justify-content: space-evenly;
gap: 8px;
height: 100%;
.simple-equipment {
border: 1px solid light-dark(@dark-blue, @golden);
border-radius: 8px;
position: relative;
display: flex;
justify-content: center;
&.selectable {
cursor: pointer;
}
&.inactive {
opacity: 0.4;
}
label {
position: absolute;
top: -8px;
font-size: 12px;
white-space: nowrap;
border: 1px solid light-dark(@dark-blue, @golden);
border-radius: 6px;
color: light-dark(@beige, @dark);
background-image: url('../assets/parchments/dh-parchment-light.png');
padding: 0 2px;
}
img {
width: 60px;
height: 60px;
border-radius: 8px;
}
}
}
.suggestion-container {
position: relative;
display: flex;
justify-content: center;
height: min-content;
border: 2px solid light-dark(@dark-blue, @golden);
border-radius: 8px;
legend {
margin-left: auto;
margin-right: auto;
font-size: 12px;
}
.suggestion-inner-container {
position: relative;
display: flex;
justify-content: center;
align-items: center;
padding: 6px;
cursor: grab;
&.taken {
opacity: 0.4;
}
label {
position: absolute;
top: -2px;
font-size: 12px;
}
img {
width: 120px;
}
}
}
}
} }
.creation-action-footer { .creation-action-footer {

View file

@ -2524,7 +2524,7 @@ div.daggerheart.views.multiclass {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: var(--color-cool-4); background-color: var(--color-cool-4);
content: ""; content: '';
} }
.daggerheart.dh-style.dialog.character-creation .tab-navigation nav a .finish-marker.active { .daggerheart.dh-style.dialog.character-creation .tab-navigation nav a .finish-marker.active {
background-color: var(--color-warm-2); background-color: var(--color-warm-2);
@ -2547,6 +2547,20 @@ div.daggerheart.views.multiclass {
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
} }
.daggerheart.dh-style.dialog.character-creation .main-selections-container .selections-container {
width: 140px;
display: flex;
flex-direction: column;
text-align: center;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .selections-container .card-preview-container {
border-color: light-dark(#18162e, #f3c267);
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .selections-outer-container {
display: flex;
justify-content: space-evenly;
height: 210px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .section-container { .daggerheart.dh-style.dialog.character-creation .main-selections-container .section-container {
border-radius: 8px; border-radius: 8px;
border-color: light-dark(#18162e, #f3c267); border-color: light-dark(#18162e, #f3c267);
@ -2635,20 +2649,6 @@ div.daggerheart.views.multiclass {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.daggerheart.dh-style.dialog.character-creation .main-selections-container .selections-container {
display: flex;
justify-content: space-evenly;
height: 210px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .selections-container .selections-inner-container {
width: 140px;
display: flex;
flex-direction: column;
text-align: center;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .selections-container .selections-inner-container .card-preview-container {
border-color: light-dark(#18162e, #f3c267);
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .creation-action-footer { .daggerheart.dh-style.dialog.character-creation .main-selections-container .creation-action-footer {
display: flex; display: flex;
align-items: center; align-items: center;
@ -2692,7 +2692,7 @@ div.daggerheart.views.multiclass {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: var(--color-cool-4); background-color: var(--color-cool-4);
content: ""; content: '';
} }
.daggerheart.dh-style.dialog.character-creation .main-selections-container .creation-action-footer .footer-section nav a .finish-marker.finished { .daggerheart.dh-style.dialog.character-creation .main-selections-container .creation-action-footer .footer-section nav a .finish-marker.finished {
background-color: var(--color-warm-2); background-color: var(--color-warm-2);
@ -2715,6 +2715,109 @@ div.daggerheart.views.multiclass {
height: 100%; height: 100%;
white-space: nowrap; white-space: nowrap;
} }
.daggerheart.dh-style.dialog.character-creation .main-selections-container .main-equipment-selection {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 16px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .main-equipment-selection.triple {
grid-template-columns: 1fr 1fr 1fr;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
border: 2px solid light-dark(#18162e, #f3c267);
border-radius: 8px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection legend {
margin-left: auto;
margin-right: auto;
font-size: 28px;
font-weight: bold;
padding: 0 8px;
white-space: nowrap;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .equipment-subsection {
display: flex;
align-items: start;
gap: 32px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .equipment-wrapper {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .simple-equipment-container {
display: flex;
flex-direction: column;
justify-content: space-evenly;
gap: 8px;
height: 100%;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .simple-equipment-container .simple-equipment {
border: 1px solid light-dark(#18162e, #f3c267);
border-radius: 8px;
position: relative;
display: flex;
justify-content: center;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .simple-equipment-container .simple-equipment.selectable {
cursor: pointer;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .simple-equipment-container .simple-equipment.inactive {
opacity: 0.4;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .simple-equipment-container .simple-equipment label {
position: absolute;
top: -8px;
font-size: 12px;
white-space: nowrap;
border: 1px solid light-dark(#18162e, #f3c267);
border-radius: 6px;
color: light-dark(#efe6d8, #222);
background-image: url('../assets/parchments/dh-parchment-light.png');
padding: 0 2px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .simple-equipment-container .simple-equipment img {
width: 60px;
height: 60px;
border-radius: 8px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .suggestion-container {
position: relative;
display: flex;
justify-content: center;
height: min-content;
border: 2px solid light-dark(#18162e, #f3c267);
border-radius: 8px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .suggestion-container legend {
margin-left: auto;
margin-right: auto;
font-size: 12px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .suggestion-container .suggestion-inner-container {
position: relative;
display: flex;
justify-content: center;
align-items: center;
padding: 6px;
cursor: grab;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .suggestion-container .suggestion-inner-container.taken {
opacity: 0.4;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .suggestion-container .suggestion-inner-container label {
position: absolute;
top: -2px;
font-size: 12px;
}
.daggerheart.dh-style.dialog.character-creation .main-selections-container .equipment-selection .suggestion-container .suggestion-inner-container img {
width: 120px;
}
.daggerheart.dh-style.dialog.character-creation .creation-action-footer { .daggerheart.dh-style.dialog.character-creation .creation-action-footer {
display: flex; display: flex;
align-items: center; align-items: center;

View file

@ -3,7 +3,105 @@
data-tab='{{tabs.equipment.id}}' data-tab='{{tabs.equipment.id}}'
data-group='{{tabs.equipment.group}}' data-group='{{tabs.equipment.group}}'
> >
<div> <div class="main-selections-container">
Test <div class="main-equipment-selection">
<fieldset class="equipment-selection">
<legend>{{localize "DAGGERHEART.CharacterCreation.SuggestedArmor"}}</legend>
<div class="selections-container armor-card">
{{#> "systems/daggerheart/templates/components/card-preview.hbs" armor }}
{{localize "DAGGERHEART.CharacterCreation.SelectArmor"}}
{{/"systems/daggerheart/templates/components/card-preview.hbs"}}
</div>
{{#if armor.suggestion}}
<fieldset class="suggestion-container">
<legend>{{armor.suggestion.name}}</legend>
<div class="suggestion-inner-container {{#if armor.suggestion.taken}}taken{{/if}}" data-action="viewItem" data-uuid="{{armor.suggestion.uuid}}">
<img src="{{armor.suggestion.img}}" />
</div>
</fieldset>
{{/if}}
</fieldset>
<fieldset class="equipment-selection">
<legend>{{localize "DAGGERHEART.CharacterCreation.SuggestedWeapons"}}</legend>
<div class="equipment-subsection">
<div class="equipment-wrapper">
<div class="selections-container primary-weapon-card">
{{#> "systems/daggerheart/templates/components/card-preview.hbs" primaryWeapon }}
{{localize "DAGGERHEART.CharacterCreation.SelectPrimaryWeapon"}}
{{/"systems/daggerheart/templates/components/card-preview.hbs"}}
</div>
{{#if primaryWeapon.suggestion}}
<fieldset class="suggestion-container">
<legend>{{primaryWeapon.suggestion.name}}</legend>
<div class="suggestion-inner-container {{#if primaryWeapon.suggestion.taken}}taken{{/if}}" data-action="viewItem" data-uuid="{{primaryWeapon.suggestion.uuid}}">
<img src="{{primaryWeapon.suggestion.img}}" />
</div>
</fieldset>
{{/if}}
</div>
<div class="equipment-wrapper">
<div class="selections-container secondary-weapon-card">
{{#> "systems/daggerheart/templates/components/card-preview.hbs" secondaryWeapon }}
{{localize "DAGGERHEART.CharacterCreation.SelectSecondaryWeapon"}}
{{/"systems/daggerheart/templates/components/card-preview.hbs"}}
</div>
{{#if secondaryWeapon.suggestion}}
<fieldset class="suggestion-container">
<legend>{{secondaryWeapon.suggestion.name}}</legend>
<div
class="suggestion-inner-container {{#if secondaryWeapon.suggestion.taken}}taken{{/if}}"
data-action="viewItem" data-uuid="{{secondaryWeapon.suggestion.uuid}}"
>
<img src="{{secondaryWeapon.suggestion.img}}" />
</div>
</fieldset>
{{/if}}
</div>
</div>
</fieldset>
</div>
<div class="main-equipment-selection triple">
<fieldset class="equipment-selection">
<legend>{{localize "DAGGERHEART.CharacterCreation.StartingItems"}}</legend>
<div class="simple-equipment-container">
{{#each inventory.take}}
<div class="simple-equipment">
<label>{{this.name}}</label>
<img src="{{this.img}}" />
</div>
{{/each}}
</div>
</fieldset>
<fieldset class="equipment-selection">
<legend>{{localize "DAGGERHEART.CharacterCreation.Choice"}}</legend>
<div class="simple-equipment-container">
{{#each inventory.choiceA.suggestions}}
<div class="simple-equipment selectable {{#if (not this.selected)}}inactive{{/if}}" data-action="equipmentChoice" data-path="choiceA" data-uuid="{{this.uuid}}">
<label>{{this.name}}</label>
<img src="{{this.img}}" />
</div>
{{/each}}
</div>
</fieldset>
<fieldset class="equipment-selection">
<legend>{{localize "DAGGERHEART.CharacterCreation.Choice"}}</legend>
<div class="simple-equipment-container">
{{#each inventory.choiceB.suggestions}}
<div class="simple-equipment selectable {{#if (not this.selected)}}inactive{{/if}}" data-action="equipmentChoice" data-path="choiceB" data-uuid="{{this.uuid}}" >
<label>{{this.name}}</label>
<img src="{{this.img}}" />
</div>
{{/each}}
</div>
</fieldset>
</div>
</div> </div>
</section> </section>

View file

@ -6,14 +6,14 @@
<div class="main-selections-container"> <div class="main-selections-container">
<fieldset class="section-container"> <fieldset class="section-container">
<legend>{{localize "TYPES.Item.class"}}</legend> <legend>{{localize "TYPES.Item.class"}}</legend>
<div class="selections-container"> <div class="selections-outer-container">
<div class="selections-inner-container class-card"> <div class="selections-container class-card">
{{#> "systems/daggerheart/templates/components/card-preview.hbs" class }} {{#> "systems/daggerheart/templates/components/card-preview.hbs" class }}
{{localize "DAGGERHEART.CharacterCreation.SelectClass"}} {{localize "DAGGERHEART.CharacterCreation.SelectClass"}}
{{/"systems/daggerheart/templates/components/card-preview.hbs"}} {{/"systems/daggerheart/templates/components/card-preview.hbs"}}
</div> </div>
<div class="selections-inner-container subclass-card"> <div class="selections-container subclass-card">
{{#> "systems/daggerheart/templates/components/card-preview.hbs" subclass disabled=(not class.img) }} {{#> "systems/daggerheart/templates/components/card-preview.hbs" subclass disabled=(not class.img) }}
{{localize "DAGGERHEART.CharacterCreation.SelectSubclass"}} {{localize "DAGGERHEART.CharacterCreation.SelectSubclass"}}
{{/"systems/daggerheart/templates/components/card-preview.hbs"}} {{/"systems/daggerheart/templates/components/card-preview.hbs"}}
@ -24,14 +24,14 @@
{{#if (gte visibility 2)}} {{#if (gte visibility 2)}}
<fieldset class="section-container"> <fieldset class="section-container">
<legend>{{localize "DAGGERHEART.CharacterCreation.Heritage"}}</legend> <legend>{{localize "DAGGERHEART.CharacterCreation.Heritage"}}</legend>
<div class="selections-container"> <div class="selections-outer-container">
<div class="selections-inner-container ancestry-card"> <div class="selections-container ancestry-card">
{{#> "systems/daggerheart/templates/components/card-preview.hbs" ancestry }} {{#> "systems/daggerheart/templates/components/card-preview.hbs" ancestry }}
{{localize "DAGGERHEART.CharacterCreation.SelectAncestry"}} {{localize "DAGGERHEART.CharacterCreation.SelectAncestry"}}
{{/"systems/daggerheart/templates/components/card-preview.hbs"}} {{/"systems/daggerheart/templates/components/card-preview.hbs"}}
</div> </div>
<div class="selections-inner-container community-card"> <div class="selections-container community-card">
{{#> "systems/daggerheart/templates/components/card-preview.hbs" community }} {{#> "systems/daggerheart/templates/components/card-preview.hbs" community }}
{{localize "DAGGERHEART.CharacterCreation.SelectCommunity"}} {{localize "DAGGERHEART.CharacterCreation.SelectCommunity"}}
{{/"systems/daggerheart/templates/components/card-preview.hbs"}} {{/"systems/daggerheart/templates/components/card-preview.hbs"}}
@ -84,9 +84,9 @@
{{#if (gte visibility 5)}} {{#if (gte visibility 5)}}
<fieldset class="section-container"> <fieldset class="section-container">
<legend>{{localize "TYPES.Item.domainCard"}}</legend> <legend>{{localize "TYPES.Item.domainCard"}}</legend>
<div class="selections-container"> <div class="selections-outer-container">
{{#each domainCards as |domainCard id|}} {{#each domainCards as |domainCard id|}}
<div class="selections-inner-container domain-card" data-card="{{id}}"> <div class="selections-container domain-card" data-card="{{id}}">
{{#> "systems/daggerheart/templates/components/card-preview.hbs" domainCard }} {{#> "systems/daggerheart/templates/components/card-preview.hbs" domainCard }}
{{#each @root.class.system.domains }} {{#each @root.class.system.domains }}
<div>{{localize (concat "DAGGERHEART.Domains." this ".label")}}</div> <div>{{localize (concat "DAGGERHEART.Domains." this ".label")}}</div>
@ -97,30 +97,5 @@
</div> </div>
</fieldset> </fieldset>
{{/if}} {{/if}}
{{!-- <footer class="creation-action-footer">
<div class="footer-section">
<nav class="feature-tab sheet-tabs tabs">
<a>
{{localize "DAGGERHEART.CharacterCreation.Tabs.Setup"}}
<div class="finish-marker finished"><i class="fa-solid fa-check"></i></div>
</a>
<a>
{{localize "DAGGERHEART.CharacterCreation.Tabs.Equipment"}}
<div class="finish-marker"></div>
<div class="descriptor">{{localize "DAGGERHEART.CharacterCreation.Tabs.Optional"}}</div>
</a>
<a>
{{localize "DAGGERHEART.CharacterCreation.Tabs.Story"}}
<div class="finish-marker"></div>
<div class="descriptor">{{localize "DAGGERHEART.CharacterCreation.Tabs.Optional"}}</div>
</a>
</nav>
</div>
<div class="footer-section">
<button data-action="close">{{localize "Cancel"}}</button>
<button {{#if this.finished}}data-action="finish"{{else}}disabled{{/if}}>{{localize "DAGGERHEART.CharacterCreation.FinishCreation"}}</button>
</div>
</footer> --}}
</div> </div>
</section> </section>

View file

@ -4,6 +4,6 @@
data-group='{{tabs.story.group}}' data-group='{{tabs.story.group}}'
> >
<div> <div>
Test Story
</div> </div>
</section> </section>