mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-16 05:31:07 +01:00
Added DomainCard selection
This commit is contained in:
parent
07c533c82c
commit
66defbffce
18 changed files with 823 additions and 132 deletions
|
|
@ -285,6 +285,7 @@ const preloadHandlebarsTemplates = async function () {
|
||||||
'systems/daggerheart/templates/sheets/pc/parts/advancementCard.hbs',
|
'systems/daggerheart/templates/sheets/pc/parts/advancementCard.hbs',
|
||||||
'systems/daggerheart/templates/views/parts/level.hbs',
|
'systems/daggerheart/templates/views/parts/level.hbs',
|
||||||
'systems/daggerheart/templates/components/slider.hbs',
|
'systems/daggerheart/templates/components/slider.hbs',
|
||||||
|
'systems/daggerheart/templates/components/card-preview.hbs',
|
||||||
'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs'
|
'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs'
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
30
lang/en.json
30
lang/en.json
|
|
@ -142,6 +142,12 @@
|
||||||
"Or": "Or",
|
"Or": "Or",
|
||||||
"Description": "Description",
|
"Description": "Description",
|
||||||
"Features": "Features",
|
"Features": "Features",
|
||||||
|
"proficiency": "Proficiency",
|
||||||
|
"unarmored": "Unarmored",
|
||||||
|
"Experience": {
|
||||||
|
"Single": "Experience",
|
||||||
|
"plural": "Experiences"
|
||||||
|
},
|
||||||
"RefreshType": {
|
"RefreshType": {
|
||||||
"Session": "Session",
|
"Session": "Session",
|
||||||
"Shortrest": "Short Rest",
|
"Shortrest": "Short Rest",
|
||||||
|
|
@ -744,14 +750,38 @@
|
||||||
"TakeDowntime": "Take Downtime"
|
"TakeDowntime": "Take Downtime"
|
||||||
},
|
},
|
||||||
"LevelUp": {
|
"LevelUp": {
|
||||||
|
"Title": "{actor} Level Up",
|
||||||
|
"Tabs": {
|
||||||
|
"advancement": "Level Advancement",
|
||||||
|
"selections": "Advancement Choices",
|
||||||
|
"summary": "Summary"
|
||||||
|
},
|
||||||
"AdvanceLevel": "Continue To Level {level}",
|
"AdvanceLevel": "Continue To Level {level}",
|
||||||
"TakeLevelUp": "Finish Level Up",
|
"TakeLevelUp": "Finish Level Up",
|
||||||
|
"Selections": {
|
||||||
|
"emptyDomainCardHint": "Domain Card Level {level} or below"
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"levelAchievements": "Level Achievements",
|
||||||
|
"levelAdvancements": "Level Advancements",
|
||||||
|
"proficiencyIncrease": "Proficiency Increased: {proficiency}",
|
||||||
|
"statisticIncreases": "Statistic Increases",
|
||||||
|
"damageThresholdMajorIncrease": "Major: {threshold}",
|
||||||
|
"damageThresholdSevereIncrease": "Severe: {threshold}",
|
||||||
|
"newExperiences": "New Experiences",
|
||||||
|
"experiencePlaceholder": "A new experience..",
|
||||||
|
"domainCards": "Domain Cards"
|
||||||
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"info": {
|
"info": {
|
||||||
"tierAdvancementInfo": "Advancements from a higher tier can always be used to select advancements in a lower tier.",
|
"tierAdvancementInfo": "Advancements from a higher tier can always be used to select advancements in a lower tier.",
|
||||||
"remainingAdvancementInfo": "Remaining Choices: {choices}",
|
"remainingAdvancementInfo": "Remaining Choices: {choices}",
|
||||||
"insufficentAdvancements": "You don't have enough advancements left.",
|
"insufficentAdvancements": "You don't have enough advancements left.",
|
||||||
"insufficientTierAdvancements": "You have no available advancements for this tier."
|
"insufficientTierAdvancements": "You have no available advancements for this tier."
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"domainCardWrongDomain": "You don't have access to that Domain",
|
||||||
|
"domainCardToHighLevel": "The Domain Card is too high level to be selected"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,16 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
|
|
||||||
const playerLevelupData = actor.system.levelData;
|
const playerLevelupData = actor.system.levelData;
|
||||||
this.levelup = new DhLevelup(DhLevelup.initializeData(this.levelTiers, playerLevelupData, actor.system.level));
|
this.levelup = new DhLevelup(DhLevelup.initializeData(this.levelTiers, playerLevelupData, actor.system.level));
|
||||||
|
|
||||||
|
this._dragDrop = this._createDragDropHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
get title() {
|
get title() {
|
||||||
return `${this.actor.name} - Level Up`;
|
return game.i18n.format('DAGGERHEART.Application.LevelUp.Title', { actor: this.actor.name });
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
|
tag: 'form',
|
||||||
classes: ['daggerheart', 'levelup'],
|
classes: ['daggerheart', 'levelup'],
|
||||||
position: { width: 1000, height: 'auto' },
|
position: { width: 1000, height: 'auto' },
|
||||||
window: {
|
window: {
|
||||||
|
|
@ -25,31 +28,188 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
save: this.save
|
save: this.save
|
||||||
}
|
},
|
||||||
|
form: {
|
||||||
|
handler: this.updateForm,
|
||||||
|
submitOnChange: true,
|
||||||
|
closeOnSubmit: false
|
||||||
|
},
|
||||||
|
dragDrop: [{ dragSelector: null, dropSelector: '.levelup-card-selection .card-preview-container' }]
|
||||||
};
|
};
|
||||||
|
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
form: {
|
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||||
id: 'levelup',
|
advancements: { template: 'systems/daggerheart/templates/views/levelup/tabs/advancements.hbs' },
|
||||||
template: 'systems/daggerheart/templates/views/levelup.hbs'
|
selections: { template: 'systems/daggerheart/templates/views/levelup/tabs/selections.hbs' },
|
||||||
|
summary: { template: 'systems/daggerheart/templates/views/levelup/tabs/summary.hbs' }
|
||||||
|
};
|
||||||
|
|
||||||
|
static TABS = {
|
||||||
|
advancements: {
|
||||||
|
active: true,
|
||||||
|
cssClass: '',
|
||||||
|
group: 'primary',
|
||||||
|
id: 'advancements',
|
||||||
|
icon: null,
|
||||||
|
label: 'DAGGERHEART.Application.LevelUp.Tabs.advancement'
|
||||||
|
},
|
||||||
|
selections: {
|
||||||
|
active: false,
|
||||||
|
cssClass: '',
|
||||||
|
group: 'primary',
|
||||||
|
id: 'selections',
|
||||||
|
icon: null,
|
||||||
|
label: 'DAGGERHEART.Application.LevelUp.Tabs.selections'
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
active: false,
|
||||||
|
cssClass: '',
|
||||||
|
group: 'primary',
|
||||||
|
id: 'summary',
|
||||||
|
icon: null,
|
||||||
|
label: 'DAGGERHEART.Application.LevelUp.Tabs.summary'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async _prepareContext(_options) {
|
async _prepareContext(_options) {
|
||||||
const context = await super._prepareContext(_options);
|
const context = await super._prepareContext(_options);
|
||||||
context.levelup = this.levelup;
|
context.levelup = this.levelup;
|
||||||
|
context.tabs = this._getTabs(this.constructor.TABS);
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _preparePartContext(partId, context) {
|
||||||
|
switch (partId) {
|
||||||
|
case 'selections':
|
||||||
|
context.advancementChoices = this.levelup.selectionData.reduce((acc, data) => {
|
||||||
|
const advancementChoice = {
|
||||||
|
...data,
|
||||||
|
path: `tiers.${data.tier}.levels.${data.level}.optionSelections.${data.optionKey}.${data.checkboxNr}.data`
|
||||||
|
};
|
||||||
|
if (acc[data.type]) acc[data.type].push(advancementChoice);
|
||||||
|
else acc[data.type] = [advancementChoice];
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
context.newExperiences = this.levelup.allInitialAchievements.newExperiences;
|
||||||
|
const allDomainCards = {
|
||||||
|
...context.advancementChoices.domainCard,
|
||||||
|
...this.levelup.domainCards
|
||||||
|
};
|
||||||
|
const allDomainCardValues = Object.values(allDomainCards);
|
||||||
|
|
||||||
|
context.domainCards = [];
|
||||||
|
for (var domainCard of allDomainCardValues) {
|
||||||
|
const uuid = domainCard.data ?? domainCard.uuid;
|
||||||
|
const card = uuid ? await foundry.utils.fromUuid(uuid) : { path: domainCard.path };
|
||||||
|
context.domainCards.push({
|
||||||
|
...(card.toObject?.() ?? card),
|
||||||
|
emptySubtext: game.i18n.format(
|
||||||
|
'DAGGERHEART.Application.LevelUp.Selections.emptyDomainCardHint',
|
||||||
|
{ level: domainCard.level }
|
||||||
|
),
|
||||||
|
limit: domainCard.level
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'summary':
|
||||||
|
const actorArmor = this.actor.system.armor;
|
||||||
|
const { current: currentLevel, changed: changedLevel } = this.actor.system.levelData.level;
|
||||||
|
context.levelAchievements = {
|
||||||
|
statisticIncreases: {
|
||||||
|
proficiency: {
|
||||||
|
old: this.actor.system.proficiency,
|
||||||
|
new: this.actor.system.proficiency + this.levelup.allInitialAchievements.proficiency
|
||||||
|
},
|
||||||
|
damageThresholds: {
|
||||||
|
major: {
|
||||||
|
old: this.actor.system.damageThresholds.major,
|
||||||
|
new: this.actor.system.damageThresholds.major + changedLevel - currentLevel
|
||||||
|
},
|
||||||
|
severe: {
|
||||||
|
old: this.actor.system.damageThresholds.severe,
|
||||||
|
new:
|
||||||
|
this.actor.system.damageThresholds.severe +
|
||||||
|
(actorArmor ? changedLevel - currentLevel : (changedLevel - currentLevel) * 2)
|
||||||
|
},
|
||||||
|
unarmored: !actorArmor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getTabs(tabs) {
|
||||||
|
for (const v of Object.values(tabs)) {
|
||||||
|
v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active;
|
||||||
|
v.cssClass = v.active ? 'active' : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return tabs;
|
||||||
|
}
|
||||||
|
|
||||||
|
_createDragDropHandlers() {
|
||||||
|
return this.options.dragDrop.map(d => {
|
||||||
|
d.callbacks = {
|
||||||
|
drop: this._onDrop.bind(this)
|
||||||
|
};
|
||||||
|
return new foundry.applications.ux.DragDrop.implementation(d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_attachPartListeners(partId, htmlElement, options) {
|
_attachPartListeners(partId, htmlElement, options) {
|
||||||
super._attachPartListeners(partId, htmlElement, options);
|
super._attachPartListeners(partId, htmlElement, options);
|
||||||
$(htmlElement).find('.selection-checkbox').on('change', this.selectionClick.bind(this));
|
htmlElement
|
||||||
|
.querySelectorAll('.selection-checkbox')
|
||||||
|
.forEach(element => element.addEventListener('change', this.selectionClick.bind(this)));
|
||||||
|
this._dragDrop.forEach(d => d.bind(htmlElement));
|
||||||
|
}
|
||||||
|
|
||||||
|
static async updateForm(event, _, formData) {
|
||||||
|
const { levelup } = foundry.utils.expandObject(formData.object);
|
||||||
|
await this.levelup.updateSource(levelup);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onDrop(event) {
|
||||||
|
const data = foundry.applications.ux.TextEditor.getDragEventData(event);
|
||||||
|
const item = await fromUuid(data.uuid);
|
||||||
|
if (event.currentTarget.parentElement?.classList?.contains('domain-cards')) {
|
||||||
|
if (item.type === 'domainCard') {
|
||||||
|
if (!this.actor.system.class.system.domains.includes(item.system.domain)) {
|
||||||
|
// Also needs to check for multiclass adding a new domain
|
||||||
|
ui.notifications.error(
|
||||||
|
game.i18n.localize('DAGGERHEART.Application.LevelUp.notifications.error.domainCardWrongDomain')
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.system.level > Number(event.currentTarget.dataset.limit)) {
|
||||||
|
ui.notifications.error(
|
||||||
|
game.i18n.localize('DAGGERHEART.Application.LevelUp.notifications.error.domainCardToHighLevel')
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const achievementCard = event.currentTarget.dataset.path.startsWith('domainCards');
|
||||||
|
await this.levelup.updateSource({ [event.currentTarget.dataset.path]: item.uuid });
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectionClick(event) {
|
async selectionClick(event) {
|
||||||
|
event.stopPropagation();
|
||||||
const button = event.currentTarget;
|
const button = event.currentTarget;
|
||||||
|
|
||||||
|
// const advancementSelections = this.getAdvancementSelectionUpdates(button);
|
||||||
if (!button.checked) {
|
if (!button.checked) {
|
||||||
await this.levelup.updateSource({
|
await this.levelup.updateSource({
|
||||||
[`tiers.${button.dataset.tier}.levels.${button.dataset.level}.optionSelections.${button.dataset.option}.-=${button.dataset.checkboxNr}`]:
|
[`tiers.${button.dataset.tier}.levels.${button.dataset.level}.optionSelections.${button.dataset.option}.-=${button.dataset.checkboxNr}`]:
|
||||||
|
|
@ -101,12 +261,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
static async save() {
|
static async save() {
|
||||||
await this.actor.update({
|
await this.actor.levelUp(this.levelup.selectionData);
|
||||||
'system.levelData': {
|
|
||||||
'level.current': this.actor.system.levelData.level.changed,
|
|
||||||
'selections': this.levelup.playerData
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,9 +182,9 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
|
||||||
htmlElement
|
htmlElement
|
||||||
.querySelectorAll('.experience-value')
|
.querySelectorAll('.experience-value')
|
||||||
.forEach(element => element.addEventListener('change', this.experienceValueChange.bind(this)));
|
.forEach(element => element.addEventListener('change', this.experienceValueChange.bind(this)));
|
||||||
htmlElement
|
// htmlElement
|
||||||
.querySelectorAll('[data-item]')
|
// .querySelectorAll('[data-item]')
|
||||||
.forEach(element => element.addEventListener.on('change', this.itemUpdate.bind(this)));
|
// .forEach(element => element.addEventListener.on('change', this.itemUpdate.bind(this)));
|
||||||
htmlElement.querySelector('.level-value').addEventListener('change', this.onLevelChange.bind(this));
|
htmlElement.querySelector('.level-value').addEventListener('change', this.onLevelChange.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,19 +61,31 @@ class DhLevelOption extends foundry.abstract.DataModel {
|
||||||
export const LevelOptionType = {
|
export const LevelOptionType = {
|
||||||
trait: {
|
trait: {
|
||||||
id: 'trait',
|
id: 'trait',
|
||||||
label: 'Character Trait'
|
label: 'Character Trait',
|
||||||
|
dataPath: ''
|
||||||
},
|
},
|
||||||
hitPoint: {
|
hitPoint: {
|
||||||
id: 'hitPoint',
|
id: 'hitPoint',
|
||||||
label: 'Hit Points'
|
label: 'Hit Points',
|
||||||
|
dataPath: 'resources.hitPoints',
|
||||||
|
dataPathData: {
|
||||||
|
property: 'max',
|
||||||
|
dependencies: ['value']
|
||||||
|
}
|
||||||
},
|
},
|
||||||
stress: {
|
stress: {
|
||||||
id: 'stress',
|
id: 'stress',
|
||||||
label: 'Stress'
|
label: 'Stress',
|
||||||
|
dataPath: 'resources.stress',
|
||||||
|
dataPathData: {
|
||||||
|
property: 'max',
|
||||||
|
dependencies: ['value']
|
||||||
|
}
|
||||||
},
|
},
|
||||||
evasion: {
|
evasion: {
|
||||||
id: 'evasion',
|
id: 'evasion',
|
||||||
label: 'Evasion'
|
label: 'Evasion',
|
||||||
|
dataPath: 'evasion'
|
||||||
},
|
},
|
||||||
proficiency: {
|
proficiency: {
|
||||||
id: 'proficiency',
|
id: 'proficiency',
|
||||||
|
|
@ -108,8 +120,8 @@ export const defaultLevelTiers = {
|
||||||
},
|
},
|
||||||
initialAchievements: {
|
initialAchievements: {
|
||||||
experience: {
|
experience: {
|
||||||
nr: 2,
|
nr: 1,
|
||||||
modifier: 1
|
modifier: 2
|
||||||
},
|
},
|
||||||
proficiency: 1
|
proficiency: 1
|
||||||
},
|
},
|
||||||
|
|
@ -171,8 +183,8 @@ export const defaultLevelTiers = {
|
||||||
},
|
},
|
||||||
initialAchievements: {
|
initialAchievements: {
|
||||||
experience: {
|
experience: {
|
||||||
nr: 2,
|
nr: 1,
|
||||||
modifier: 1
|
modifier: 2
|
||||||
},
|
},
|
||||||
proficiency: 1
|
proficiency: 1
|
||||||
},
|
},
|
||||||
|
|
@ -252,8 +264,8 @@ export const defaultLevelTiers = {
|
||||||
},
|
},
|
||||||
initialAchievements: {
|
initialAchievements: {
|
||||||
experience: {
|
experience: {
|
||||||
nr: 2,
|
nr: 1,
|
||||||
modifier: 1
|
modifier: 2
|
||||||
},
|
},
|
||||||
proficiency: 1
|
proficiency: 1
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,63 @@ export class DhLevelup extends foundry.abstract.DataModel {
|
||||||
const tierKeys = Object.keys(levelTierData.tiers);
|
const tierKeys = Object.keys(levelTierData.tiers);
|
||||||
const maxLevel = levelTierData.tiers[tierKeys[tierKeys.length - 1]].levels.end;
|
const maxLevel = levelTierData.tiers[tierKeys[tierKeys.length - 1]].levels.end;
|
||||||
|
|
||||||
return {
|
const totalLevelProgression = [];
|
||||||
tiers: tierKeys.reduce((acc, key) => {
|
for (var level = pcLevelData.level.current + 1; level <= pcLevelData.level.changed; level++) {
|
||||||
acc[key] = DhLevelupTier.initializeData(
|
totalLevelProgression.push(level);
|
||||||
levelTierData.tiers[key],
|
}
|
||||||
maxLevel,
|
|
||||||
pcLevelData.selections.filter(x => x.tier === Number(key)),
|
const tiers = tierKeys.reduce((acc, key) => {
|
||||||
pcLevelData.level.changed
|
acc[key] = DhLevelupTier.initializeData(
|
||||||
);
|
levelTierData.tiers[key],
|
||||||
|
maxLevel,
|
||||||
|
pcLevelData.selections.filter(x => x.tier === Number(key)),
|
||||||
|
pcLevelData.level.changed
|
||||||
|
);
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const allInitialAchievements = Object.values(tiers).reduce(
|
||||||
|
(acc, tier) => {
|
||||||
|
const levelThreshold = Math.min(...tier.belongingLevels);
|
||||||
|
|
||||||
|
if (totalLevelProgression.includes(levelThreshold)) {
|
||||||
|
acc.proficiency += tier.initialAchievements.proficiency;
|
||||||
|
[...Array(tier.initialAchievements.experience.nr).keys()].forEach(_ => {
|
||||||
|
acc.newExperiences[foundry.utils.randomID()] = {
|
||||||
|
name: '',
|
||||||
|
modifier: tier.initialAchievements.experience.modifier
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {}),
|
},
|
||||||
|
{ newExperiences: {}, proficiency: 0 }
|
||||||
|
);
|
||||||
|
|
||||||
|
const domainCards = Object.keys(tiers).reduce((acc, tierKey) => {
|
||||||
|
const tier = tiers[tierKey];
|
||||||
|
for (var level of tier.belongingLevels) {
|
||||||
|
if (level <= pcLevelData.level.changed) {
|
||||||
|
for (var domainCardSlot = 1; domainCardSlot <= tier.domainCardByLevel; domainCardSlot++) {
|
||||||
|
const cardId = foundry.utils.randomID();
|
||||||
|
acc[cardId] = {
|
||||||
|
uuid: null,
|
||||||
|
tier: tierKey,
|
||||||
|
level: level,
|
||||||
|
domainCardSlot: domainCardSlot,
|
||||||
|
path: `domainCards.${cardId}.uuid`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return {
|
||||||
|
tiers: tiers,
|
||||||
maxSelections: [...Array(pcLevelData.level.changed).keys()].reduce((acc, index) => {
|
maxSelections: [...Array(pcLevelData.level.changed).keys()].reduce((acc, index) => {
|
||||||
const level = index + 1;
|
const level = index + 1;
|
||||||
const availableChoices = availableChoicesPerLevel[level];
|
const availableChoices = availableChoicesPerLevel[level];
|
||||||
|
|
@ -26,7 +72,12 @@ export class DhLevelup extends foundry.abstract.DataModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, 0)
|
}, 0),
|
||||||
|
allInitialAchievements: {
|
||||||
|
newExperiences: allInitialAchievements.newExperiences,
|
||||||
|
proficiency: allInitialAchievements.proficiency
|
||||||
|
},
|
||||||
|
domainCards: domainCards
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +86,28 @@ export class DhLevelup extends foundry.abstract.DataModel {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tiers: new fields.TypedObjectField(new fields.EmbeddedDataField(DhLevelupTier)),
|
tiers: new fields.TypedObjectField(new fields.EmbeddedDataField(DhLevelupTier)),
|
||||||
maxSelections: new fields.NumberField({ required: true, integer: true })
|
maxSelections: new fields.NumberField({ required: true, integer: true }),
|
||||||
|
allInitialAchievements: new fields.SchemaField({
|
||||||
|
newExperiences: new fields.TypedObjectField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
name: new fields.StringField({ required: true }),
|
||||||
|
modifier: new fields.NumberField({ required: true, integer: true })
|
||||||
|
})
|
||||||
|
),
|
||||||
|
proficiency: new fields.NumberField({ required: true, integer: true })
|
||||||
|
}),
|
||||||
|
domainCards: new fields.TypedObjectField(
|
||||||
|
new fields.SchemaField({
|
||||||
|
uuid: new fields.StringField({ required: true, nullable: true, initial: null }),
|
||||||
|
tier: new fields.NumberField({ required: true, integer: true }),
|
||||||
|
level: new fields.NumberField({ required: true, integer: true }),
|
||||||
|
domainCardSlot: new fields.NumberField({ required: true, integer: true }),
|
||||||
|
path: new fields.StringField({ required: true })
|
||||||
|
})
|
||||||
|
)
|
||||||
|
// advancementSelections: new fields.SchemaField({
|
||||||
|
// experiences: new fields.SetField(new fields.StringField()),
|
||||||
|
// }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,7 +129,7 @@ export class DhLevelup extends foundry.abstract.DataModel {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get playerData() {
|
get selectionData() {
|
||||||
return Object.keys(this.tiers).flatMap(tierKey => {
|
return Object.keys(this.tiers).flatMap(tierKey => {
|
||||||
const tier = this.tiers[tierKey];
|
const tier = this.tiers[tierKey];
|
||||||
return Object.keys(tier.levels).flatMap(levelKey => {
|
return Object.keys(tier.levels).flatMap(levelKey => {
|
||||||
|
|
@ -66,15 +138,19 @@ export class DhLevelup extends foundry.abstract.DataModel {
|
||||||
const selection = level.optionSelections[optionSelectionKey];
|
const selection = level.optionSelections[optionSelectionKey];
|
||||||
const optionSelect = tier.options[optionSelectionKey];
|
const optionSelect = tier.options[optionSelectionKey];
|
||||||
|
|
||||||
return Object.keys(selection).map(checkboxNr => ({
|
return Object.keys(selection).map(checkboxNr => {
|
||||||
tier: Number(tierKey),
|
const selectionObj = selection[checkboxNr];
|
||||||
level: Number(levelKey),
|
return {
|
||||||
optionKey: optionSelectionKey,
|
tier: Number(tierKey),
|
||||||
type: optionSelect.type,
|
level: Number(levelKey),
|
||||||
checkboxNr: Number(checkboxNr),
|
optionKey: optionSelectionKey,
|
||||||
value: optionSelect.value,
|
type: optionSelect.type,
|
||||||
amount: optionSelect.amount
|
checkboxNr: Number(checkboxNr),
|
||||||
}));
|
value: optionSelect.value,
|
||||||
|
amount: optionSelect.amount,
|
||||||
|
data: selectionObj.data
|
||||||
|
};
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -108,6 +184,8 @@ class DhLevelupTier extends foundry.abstract.DataModel {
|
||||||
return acc;
|
return acc;
|
||||||
}, {}),
|
}, {}),
|
||||||
belongingLevels: belongingLevels,
|
belongingLevels: belongingLevels,
|
||||||
|
initialAchievements: levelTier.initialAchievements,
|
||||||
|
domainCardByLevel: levelTier.domainCardByLevel,
|
||||||
levels: levels
|
levels: levels
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -121,10 +199,22 @@ class DhLevelupTier extends foundry.abstract.DataModel {
|
||||||
active: new fields.BooleanField({ required: true, initial: true }),
|
active: new fields.BooleanField({ required: true, initial: true }),
|
||||||
options: new fields.TypedObjectField(new fields.EmbeddedDataField(DhLevelupTierOption)),
|
options: new fields.TypedObjectField(new fields.EmbeddedDataField(DhLevelupTierOption)),
|
||||||
belongingLevels: new fields.ArrayField(new fields.NumberField({ required: true, integer: true })),
|
belongingLevels: new fields.ArrayField(new fields.NumberField({ required: true, integer: true })),
|
||||||
|
initialAchievements: new fields.SchemaField({
|
||||||
|
experience: new fields.SchemaField({
|
||||||
|
nr: new fields.NumberField({ required: true, initial: 1 }),
|
||||||
|
modifier: new fields.NumberField({ required: true, initial: 2 })
|
||||||
|
}),
|
||||||
|
proficiency: new fields.NumberField({ integer: true, initial: 1 })
|
||||||
|
}),
|
||||||
|
domainCardByLevel: new fields.NumberField({ required: true, integer: true }),
|
||||||
levels: new fields.TypedObjectField(new fields.EmbeddedDataField(DhLevelupLevel))
|
levels: new fields.TypedObjectField(new fields.EmbeddedDataField(DhLevelupLevel))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get initialAchievementData() {
|
||||||
|
return this.active ? this.initialAchievements : null;
|
||||||
|
}
|
||||||
|
|
||||||
get selections() {
|
get selections() {
|
||||||
const allSelections = Object.keys(this.levels).reduce(
|
const allSelections = Object.keys(this.levels).reduce(
|
||||||
(acc, key) => {
|
(acc, key) => {
|
||||||
|
|
@ -223,7 +313,8 @@ class DhLevelupLevel extends foundry.abstract.DataModel {
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
selected: new fields.BooleanField({ required: true, initial: true }),
|
selected: new fields.BooleanField({ required: true, initial: true }),
|
||||||
minCost: new fields.NumberField({ required: true, integer: true }),
|
minCost: new fields.NumberField({ required: true, integer: true }),
|
||||||
locked: new fields.BooleanField({ required: true, initial: false })
|
locked: new fields.BooleanField({ required: true, initial: false }),
|
||||||
|
data: new fields.StringField()
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,7 @@ const attributeField = () =>
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
data: new fields.SchemaField({
|
data: new fields.SchemaField({
|
||||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
base: new fields.NumberField({ initial: 0, integer: true }),
|
bonus: new fields.NumberField({ initial: 0, integer: true })
|
||||||
bonus: new fields.NumberField({ initial: 0, integer: true }),
|
|
||||||
actualValue: new fields.NumberField({ initial: 0, integer: true }),
|
|
||||||
overrideValue: new fields.NumberField({ initial: 0, integer: true })
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -52,11 +49,7 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
|
||||||
presence: attributeField(),
|
presence: attributeField(),
|
||||||
knowledge: attributeField()
|
knowledge: attributeField()
|
||||||
}),
|
}),
|
||||||
proficiency: new fields.SchemaField({
|
proficiency: new fields.NumberField({ required: true, initial: 1, integer: true }),
|
||||||
value: new fields.NumberField({ initial: 1, integer: true }),
|
|
||||||
min: new fields.NumberField({ initial: 1, integer: true }),
|
|
||||||
max: new fields.NumberField({ initial: 6, integer: true })
|
|
||||||
}),
|
|
||||||
evasion: new fields.NumberField({ initial: 0, integer: true }),
|
evasion: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
experiences: new fields.ArrayField(
|
experiences: new fields.ArrayField(
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
|
|
@ -347,7 +340,15 @@ export default class DhpPC extends foundry.abstract.TypeDataModel {
|
||||||
|
|
||||||
this.evasion = this.class?.system?.evasion ?? 0;
|
this.evasion = this.class?.system?.evasion ?? 0;
|
||||||
// this.armor.value = this.activeArmor?.baseScore ?? 0;
|
// this.armor.value = this.activeArmor?.baseScore ?? 0;
|
||||||
// this.damageThresholds = this.computeDamageThresholds();
|
const armor = this.armor;
|
||||||
|
this.damageThresholds = {
|
||||||
|
major: armor
|
||||||
|
? armor.system.baseThresholds.major + this.levelData.level.current
|
||||||
|
: this.levelData.level.current,
|
||||||
|
severe: armor
|
||||||
|
? armor.system.baseThresholds.severe + this.levelData.level.current
|
||||||
|
: this.levelData.level.current * 2
|
||||||
|
};
|
||||||
|
|
||||||
this.applyLevels();
|
this.applyLevels();
|
||||||
this.applyEffects();
|
this.applyEffects();
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,15 @@ export default class DhpActor extends Actor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async levelUp(levelupData) {
|
||||||
|
await this.actor.update({
|
||||||
|
'system.levelData': {
|
||||||
|
'level.current': this.system.levelData.level.changed,
|
||||||
|
'selections': levelupData
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async diceRoll(modifier, shiftKey) {
|
async diceRoll(modifier, shiftKey) {
|
||||||
if (this.type === 'pc') {
|
if (this.type === 'pc') {
|
||||||
return await this.dualityRoll(modifier, shiftKey);
|
return await this.dualityRoll(modifier, shiftKey);
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,19 @@ import { getWidthOfText } from './utils.mjs';
|
||||||
export default class RegisterHandlebarsHelpers {
|
export default class RegisterHandlebarsHelpers {
|
||||||
static registerHelpers() {
|
static registerHelpers() {
|
||||||
Handlebars.registerHelper({
|
Handlebars.registerHelper({
|
||||||
looseEq: this.looseEq,
|
|
||||||
times: this.times,
|
times: this.times,
|
||||||
join: this.join,
|
join: this.join,
|
||||||
add: this.add,
|
add: this.add,
|
||||||
subtract: this.subtract,
|
subtract: this.subtract,
|
||||||
objectSelector: this.objectSelector,
|
objectSelector: this.objectSelector,
|
||||||
includes: this.includes,
|
includes: this.includes,
|
||||||
simpleEditor: this.simpleEditor,
|
debug: this.debug,
|
||||||
debug: this.debug
|
signedNumber: this.signedNumber,
|
||||||
|
switch: this.switch,
|
||||||
|
case: this.case
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static looseEq(a, b) {
|
|
||||||
return a == b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static times(nr, block) {
|
static times(nr, block) {
|
||||||
var accum = '';
|
var accum = '';
|
||||||
for (var i = 0; i < nr; ++i) accum += block.fn(i);
|
for (var i = 0; i < nr; ++i) accum += block.fn(i);
|
||||||
|
|
@ -77,33 +74,25 @@ export default class RegisterHandlebarsHelpers {
|
||||||
return new Handlebars.SafeString(html);
|
return new Handlebars.SafeString(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
static rangePicker(options) {
|
|
||||||
let { name, value, min, max, step } = options.hash;
|
|
||||||
name = name || 'range';
|
|
||||||
value = value ?? '';
|
|
||||||
if (Number.isNaN(value)) value = '';
|
|
||||||
const html = `<input type="range" name="${name}" value="${value}" min="${min}" max="${max}" step="${step}"/>
|
|
||||||
<span class="range-value">${value}</span>`;
|
|
||||||
return new Handlebars.SafeString(html);
|
|
||||||
}
|
|
||||||
|
|
||||||
static includes(list, item) {
|
static includes(list, item) {
|
||||||
return list.includes(item);
|
return list.includes(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static simpleEditor(content, options) {
|
static signedNumber(number) {
|
||||||
const {
|
return number >= 0 ? `+${number}` : number;
|
||||||
target,
|
}
|
||||||
editable = true,
|
|
||||||
button,
|
static switch(value, options) {
|
||||||
engine = 'tinymce',
|
this.switch_value = value;
|
||||||
collaborate = false,
|
this.switch_break = false;
|
||||||
class: cssClass
|
return options.fn(this);
|
||||||
} = options.hash;
|
}
|
||||||
const config = { name: target, value: content, button, collaborate, editable, engine };
|
|
||||||
const element = foundry.applications.fields.createEditorInput(config);
|
static case(value, options) {
|
||||||
if (cssClass) element.querySelector('.editor-content').classList.add(cssClass);
|
if (value == this.switch_value) {
|
||||||
return new Handlebars.SafeString(element.outerHTML);
|
this.switch_break = true;
|
||||||
|
return options.fn(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static debug(a) {
|
static debug(a) {
|
||||||
|
|
|
||||||
|
|
@ -2791,6 +2791,11 @@ div.daggerheart.views.multiclass {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
.daggerheart.levelup section .section-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
.daggerheart.levelup .tiers-container {
|
.daggerheart.levelup .tiers-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
|
@ -2844,9 +2849,75 @@ div.daggerheart.views.multiclass {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
.daggerheart.levelup .levelup-selections-container .achievement-experience-cards {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.daggerheart.levelup .levelup-selections-container .achievement-experience-cards .achievement-experience-card {
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding-right: 4px;
|
||||||
|
font-size: 18px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
.daggerheart.levelup .levelup-selections-container .achievement-experience-cards .achievement-experience-card .achievement-experience-marker {
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.daggerheart.levelup .levelup-selections-container .levelup-card-selection {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
|
gap: 40px;
|
||||||
|
padding-right: 120px;
|
||||||
|
}
|
||||||
|
.daggerheart.levelup .levelup-summary-container .level-achievements-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.daggerheart.levelup .levelup-summary-container .level-achievements-container h2,
|
||||||
|
.daggerheart.levelup .levelup-summary-container .level-achievements-container h3,
|
||||||
|
.daggerheart.levelup .levelup-summary-container .level-achievements-container h4,
|
||||||
|
.daggerheart.levelup .levelup-summary-container .level-achievements-container h5 {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
.daggerheart.levelup .levelup-summary-container .increase-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
.daggerheart.levelup .levelup-footer {
|
.daggerheart.levelup .levelup-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
.daggerheart.levelup .levelup-footer .advancement-information-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
border-bottom: 3px solid;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-left: 8px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 8px;
|
||||||
|
border-color: #9f8475;
|
||||||
|
}
|
||||||
|
.daggerheart.levelup .levelup-footer .advancement-information-container .advancement-tier-stats {
|
||||||
|
border: 1px solid;
|
||||||
|
padding: 0 2px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
.daggerheart.levelup .levelup-footer .advancement-information-container .advancement-tier-info {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
.application.sheet.daggerheart.dh-style.feature .item-sheet-header {
|
.application.sheet.daggerheart.dh-style.feature .item-sheet-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
@ -2892,14 +2963,14 @@ div.daggerheart.views.multiclass {
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url(https://fonts.gstatic.com/s/montserrat/v29/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Ew-.ttf) format('truetype');
|
src: url(https://fonts.gstatic.com/s/montserrat/v30/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Ew-.ttf) format('truetype');
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Montserrat';
|
font-family: 'Montserrat';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
src: url(https://fonts.gstatic.com/s/montserrat/v29/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCu170w-.ttf) format('truetype');
|
src: url(https://fonts.gstatic.com/s/montserrat/v30/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCu170w-.ttf) format('truetype');
|
||||||
}
|
}
|
||||||
.application.sheet.daggerheart.dh-style h1 {
|
.application.sheet.daggerheart.dh-style h1 {
|
||||||
font-family: 'Cinzel Decorative', serif;
|
font-family: 'Cinzel Decorative', serif;
|
||||||
|
|
@ -3167,6 +3238,60 @@ div.daggerheart.views.multiclass {
|
||||||
.application.setting.dh-style footer button {
|
.application.setting.dh-style footer button {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
.theme-light .application .component.dh-style.card.card-preview-container {
|
||||||
|
background-image: url('../assets/parchments/dh-parchment-light.png');
|
||||||
|
}
|
||||||
|
.theme-light .application .component.dh-style.card.card-preview-container .preview-text-container {
|
||||||
|
background-image: url(../assets/parchments/dh-parchment-dark.png);
|
||||||
|
}
|
||||||
|
.application .component.dh-style.card-preview-container {
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 2px solid var(--color-tabs-border);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
aspect-ratio: 0.75;
|
||||||
|
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||||
|
}
|
||||||
|
.application .component.dh-style.card-preview-container.empty {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.application .component.dh-style.card-preview-container .preview-image-container {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 4px 4px 0;
|
||||||
|
}
|
||||||
|
.application .component.dh-style.card-preview-container .preview-text-container {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 18px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--color-text-selection-bg);
|
||||||
|
background-image: url(../assets/parchments/dh-parchment-light.png);
|
||||||
|
}
|
||||||
|
.application .component.dh-style.card-preview-container .preview-empty-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.application .component.dh-style.card-preview-container .preview-empty-container .preview-empty-inner-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.application .component.dh-style.card-preview-container .preview-empty-container .preview-empty-inner-container .preview-add-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
.application .component.dh-style.card-preview-container .preview-empty-container .preview-empty-inner-container .preview-empty-subtext {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -48px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-variant: small-caps;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
.sheet.daggerheart.dh-style .tab-navigation {
|
.sheet.daggerheart.dh-style .tab-navigation {
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
@ -3399,6 +3524,12 @@ div.daggerheart.views.multiclass {
|
||||||
/* Flex */
|
/* Flex */
|
||||||
/****/
|
/****/
|
||||||
}
|
}
|
||||||
|
.daggerheart .vertical-separator {
|
||||||
|
border-left: 2px solid black;
|
||||||
|
height: 56px;
|
||||||
|
flex: 0;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
.daggerheart .flex-centered {
|
.daggerheart .flex-centered {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
||||||
|
|
@ -212,3 +212,77 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-light {
|
||||||
|
.application {
|
||||||
|
.component.dh-style.card {
|
||||||
|
&.card-preview-container {
|
||||||
|
background-image: url('../assets/parchments/dh-parchment-light.png');
|
||||||
|
|
||||||
|
.preview-text-container {
|
||||||
|
background-image: url(../assets/parchments/dh-parchment-dark.png);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.application {
|
||||||
|
.component.dh-style {
|
||||||
|
&.card-preview-container {
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 2px solid var(--color-tabs-border);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
aspect-ratio: 0.75;
|
||||||
|
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||||
|
|
||||||
|
&.empty {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image-container {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 4px 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-text-container {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 18px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--color-text-selection-bg);
|
||||||
|
background-image: url(../assets/parchments/dh-parchment-light.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-empty-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.preview-empty-inner-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.preview-add-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-empty-subtext {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -48px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-variant: small-caps;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,14 @@
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
.section-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.tiers-container {
|
.tiers-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
|
@ -73,13 +81,72 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.levelup-selections-container {
|
||||||
|
.achievement-experience-cards {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.achievement-experience-card {
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding-right: 4px;
|
||||||
|
font-size: 18px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
.achievement-experience-marker {
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.levelup-card-selection {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
|
gap: 40px;
|
||||||
|
padding-right: 120px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.levelup-summary-container {
|
||||||
|
.level-achievements-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5 {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.increase-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.levelup-footer {
|
.levelup-footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.advancement-information-container {
|
.advancement-information-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
border: 1px solid;
|
border-bottom: 3px solid;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
||||||
13
templates/components/card-preview.hbs
Normal file
13
templates/components/card-preview.hbs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<div class="component dh-style card-preview-container" data-path="{{this.path}}" data-limit="{{this.limit}}">
|
||||||
|
{{#if this.img}}
|
||||||
|
<img class="preview-image-container" src="{{this.img}}" />
|
||||||
|
<div class="preview-text-container">{{this.name}}</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="preview-empty-container">
|
||||||
|
<div class="preview-empty-inner-container">
|
||||||
|
<i class="preview-add-icon fa-solid fa-plus"></i>
|
||||||
|
<div class="preview-empty-subtext">{{this.emptySubtext}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
<div>
|
|
||||||
<div class="tiers-container">
|
|
||||||
{{#each this.levelup.tiers as |tier key|}}
|
|
||||||
<fieldset class="tier-container {{#if (not tier.active)}}inactive{{/if}}">
|
|
||||||
<legend>{{tier.name}}</legend>
|
|
||||||
|
|
||||||
{{#each tier.tierCheckboxGroups}}
|
|
||||||
<div class="checkbox-group-container">
|
|
||||||
<div class="checkboxes-container">
|
|
||||||
{{#each this.checkboxGroups}}
|
|
||||||
<div class="checkbox-grouping-coontainer {{#if this.multi}}multi{{/if}}">
|
|
||||||
{{#each this.checkboxes}}
|
|
||||||
<input
|
|
||||||
type="checkbox" class="selection-checkbox{{#if (gt this.cost 1)}} multi{{/if}}" {{checked this.selected}} {{#if this.disabled}}disabled{{/if}}
|
|
||||||
data-tier="{{this.tier}}"
|
|
||||||
data-level="{{this.level}}"
|
|
||||||
data-option="{{this.optionKey}}"
|
|
||||||
data-checkbox-nr="{{this.checkboxNr}}"
|
|
||||||
data-cost="{{this.cost}}"
|
|
||||||
/>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
<div class="checkbox-group-label">{{this.label}}</div>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</fieldset>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
<footer class="levelup-footer">
|
|
||||||
<button data-action="save">{{localize "Finish Levelup"}}</button>
|
|
||||||
<div class="advancement-information-container">
|
|
||||||
{{localize "DAGGERHEART.Application.LevelUp.notifications.info.remainingAdvancementInfo" choices=this.levelup.levelSelections.totalAvailable}}
|
|
||||||
|
|
||||||
{{#each this.levelup.tiers as |tier key|}}
|
|
||||||
<div class="advancement-tier-stats">Tier {{tier.tier}}: {{tier.selections.totalAvailable}}</div>
|
|
||||||
{{/each}}
|
|
||||||
<i class="advancement-tier-info fa-solid fa-circle-question" data-tooltip="{{localize "DAGGERHEART.Application.LevelUp.notifications.info.tierAdvancementInfo"}}"></i>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
29
templates/views/levelup/advancementSelection.hbs
Normal file
29
templates/views/levelup/advancementSelection.hbs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
{{#switch}}
|
||||||
|
{{#case 'trait'}}
|
||||||
|
|
||||||
|
{{/case}}
|
||||||
|
{{/switch}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
trait: {
|
||||||
|
id: 'trait',
|
||||||
|
label: 'Character Trait',
|
||||||
|
dataPath: ''
|
||||||
|
},
|
||||||
|
experience: {
|
||||||
|
id: 'experience',
|
||||||
|
label: 'Experience'
|
||||||
|
},
|
||||||
|
domainCard: {
|
||||||
|
id: 'domainCard',
|
||||||
|
label: 'Domain Card'
|
||||||
|
},
|
||||||
|
subclass: {
|
||||||
|
id: 'subclass',
|
||||||
|
label: 'Subclass'
|
||||||
|
},
|
||||||
|
multiclass: {
|
||||||
|
id: 'multiclass',
|
||||||
|
label: 'Multiclass'
|
||||||
|
}
|
||||||
37
templates/views/levelup/tabs/advancements.hbs
Normal file
37
templates/views/levelup/tabs/advancements.hbs
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
<section
|
||||||
|
class='tab {{tabs.advancements.cssClass}} {{tabs.advancements.id}}'
|
||||||
|
data-tab='{{tabs.advancements.id}}'
|
||||||
|
data-group='{{tabs.advancements.group}}'
|
||||||
|
>
|
||||||
|
<div class="section-container">
|
||||||
|
<div class="tiers-container">
|
||||||
|
{{#each this.levelup.tiers as |tier key|}}
|
||||||
|
<fieldset class="tier-container {{#if (not tier.active)}}inactive{{/if}}">
|
||||||
|
<legend>{{tier.name}}</legend>
|
||||||
|
|
||||||
|
{{#each tier.tierCheckboxGroups}}
|
||||||
|
<div class="checkbox-group-container">
|
||||||
|
<div class="checkboxes-container">
|
||||||
|
{{#each this.checkboxGroups}}
|
||||||
|
<div class="checkbox-grouping-coontainer {{#if this.multi}}multi{{/if}}">
|
||||||
|
{{#each this.checkboxes}}
|
||||||
|
<input
|
||||||
|
type="checkbox" class="selection-checkbox{{#if (gt this.cost 1)}} multi{{/if}}" {{checked this.selected}} {{#if this.disabled}}disabled{{/if}}
|
||||||
|
data-tier="{{this.tier}}"
|
||||||
|
data-level="{{this.level}}"
|
||||||
|
data-option="{{this.optionKey}}"
|
||||||
|
data-checkbox-nr="{{this.checkboxNr}}"
|
||||||
|
data-cost="{{this.cost}}"
|
||||||
|
/>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
<div class="checkbox-group-label">{{this.label}}</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</fieldset>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
34
templates/views/levelup/tabs/selections.hbs
Normal file
34
templates/views/levelup/tabs/selections.hbs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<section
|
||||||
|
class='tab {{tabs.selections.cssClass}} {{tabs.selections.id}}'
|
||||||
|
data-tab='{{tabs.selections.id}}'
|
||||||
|
data-group='{{tabs.selections.group}}'
|
||||||
|
>
|
||||||
|
<div class="section-container levelup-selections-container">
|
||||||
|
<div>
|
||||||
|
<h3>{{localize "DAGGERHEART.Application.LevelUp.summary.newExperiences"}}</h3>
|
||||||
|
<div class="achievement-experience-cards">
|
||||||
|
{{#each this.newExperiences as |experience key|}}
|
||||||
|
<div class="achievement-experience-card">
|
||||||
|
<div class="flexrow">
|
||||||
|
<input type="text" name="{{concat "levelup.allInitialAchievements.newExperiences." key ".name"}}" value="{{experience.name}}" placeholder="{{localize "DAGGERHEART.Application.LevelUp.summary.experiencePlaceholder"}}" />
|
||||||
|
<div class="flex0">{{signedNumber experience.modifier}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="achievement-experience-marker">
|
||||||
|
{{#if experience.name}}<i class="fa-solid fa-check"></i>{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>{{localize "DAGGERHEART.Application.LevelUp.summary.domainCards"}}</h3>
|
||||||
|
|
||||||
|
<div class="levelup-card-selection domain-cards">
|
||||||
|
{{#each this.domainCards}}
|
||||||
|
{{> "systems/daggerheart/templates/components/card-preview.hbs" img=this.img name=this.name path=this.path }}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
60
templates/views/levelup/tabs/summary.hbs
Normal file
60
templates/views/levelup/tabs/summary.hbs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
<section
|
||||||
|
class='tab {{tabs.summary.cssClass}} {{tabs.summary.id}}'
|
||||||
|
data-tab='{{tabs.summary.id}}'
|
||||||
|
data-group='{{tabs.summary.group}}'
|
||||||
|
>
|
||||||
|
<div class="section-container levelup-summary-container">
|
||||||
|
<fieldset>
|
||||||
|
<legend>{{localize "DAGGERHEART.Application.LevelUp.summary.levelAchievements"}}</legend>
|
||||||
|
|
||||||
|
<div class="level-achievements-container">
|
||||||
|
<div>
|
||||||
|
<h3>{{localize "DAGGERHEART.Application.LevelUp.summary.statisticIncreases"}}</h3>
|
||||||
|
<div class="increase-container">
|
||||||
|
{{localize "DAGGERHEART.Application.LevelUp.summary.proficiencyIncrease" proficiency=this.levelAchievements.statisticIncreases.proficiency.old }}
|
||||||
|
<i class="fa-solid fa-arrow-right-long"></i>
|
||||||
|
{{this.levelAchievements.statisticIncreases.proficiency.new}}
|
||||||
|
</div>
|
||||||
|
<h5>{{localize "Damage Thresholds"}}{{#if this.levelAchievements.statisticIncreases.damageThresholds.unarmored}}({{localize "DAGGERHEART.General.unarmored"}}){{/if}}</h5>
|
||||||
|
<div class="increase-container">
|
||||||
|
{{localize "DAGGERHEART.Application.LevelUp.summary.damageThresholdMajorIncrease" threshold=this.levelAchievements.statisticIncreases.damageThresholds.major.old }}
|
||||||
|
<i class="fa-solid fa-arrow-right-long"></i>
|
||||||
|
{{this.levelAchievements.statisticIncreases.damageThresholds.major.new}}
|
||||||
|
</div>
|
||||||
|
<div class="increase-container">
|
||||||
|
{{localize "DAGGERHEART.Application.LevelUp.summary.damageThresholdSevereIncrease" threshold=this.levelAchievements.statisticIncreases.damageThresholds.severe.old }}
|
||||||
|
<i class="fa-solid fa-arrow-right-long"></i>
|
||||||
|
{{this.levelAchievements.statisticIncreases.damageThresholds.severe.new}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>{{localize "DAGGERHEART.Application.LevelUp.summary.levelAdvancements"}}</legend>
|
||||||
|
|
||||||
|
{{!-- <div>
|
||||||
|
<h4>{{localize "DAGGERHEART.General.Experience.plural"}}</h4>
|
||||||
|
<div class="level-experience-cards">
|
||||||
|
{{#each this.levelAchievements.experience}}
|
||||||
|
<div class="level-experience-card">
|
||||||
|
{{this.label}}
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div> --}}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<footer class="levelup-footer">
|
||||||
|
<button data-action="save">{{localize "Finish Levelup"}}</button>
|
||||||
|
<div class="advancement-information-container">
|
||||||
|
{{localize "DAGGERHEART.Application.LevelUp.notifications.info.remainingAdvancementInfo" choices=this.levelup.levelSelections.totalAvailable}}
|
||||||
|
|
||||||
|
{{#each this.levelup.tiers as |tier key|}}
|
||||||
|
<div class="advancement-tier-stats">Tier {{tier.tier}}: {{tier.selections.totalAvailable}}</div>
|
||||||
|
{{/each}}
|
||||||
|
<i class="advancement-tier-info fa-solid fa-circle-question" data-tooltip="{{localize "DAGGERHEART.Application.LevelUp.notifications.info.tierAdvancementInfo"}}"></i>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue