Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,6 @@
"unequip": "Unequip",
"useItem": "Use Item"
},
"defaultHopeDice": "Default Hope Dice",
"defaultFearDice": "Default Fear Dice",
"defaultAdvantageDice": "Default Advantage Dice",
"defaultDisadvantageDice": "Default Disadvantage Dice",
"disadvantageSources": {
"label": "Disadvantage Sources",
"hint": "Add single words or short text as reminders and hints of what a character has disadvantage on."
Expand Down Expand Up @@ -314,6 +310,16 @@
},
"noPartner": "No Partner selected"
},
"Creature": {
"rules": {
"roll": {
"hope": { "label": "Default Hope Dice Index", "hint": "Index for the default hope dice. 0=d4, 1=d6, 2=d8, 3=d10, 4=d12, 5=d20" },
"fear": { "label": "Default Fear Dice Index", "hint": "Index for the default fear dice. 0=d4, 1=d6, 2=d8, 3=d10, 4=d12, 5=d20" },
"advantage": { "label": "Default Advantage Dice Index", "hint": "Index for the default advantage dice. 0=d4, 1=d6, 2=d8, 3=d10, 4=d12, 5=d20" },
"disadvantage": { "label": "Default Disadvantage Dice Index", "hint": "Index for the default disadvantage dice. 0=d4, 1=d6, 2=d8, 3=d10, 4=d12, 5=d20" }
}
}
},
"Environment": {
"FIELDS": {
"description": {
Expand Down Expand Up @@ -690,6 +696,9 @@
"title": "{actor} Level Up",
"viewModeTitle": "{actor} Level Up (View Mode)"
},
"LevelupOptionsDialog": {
"title": "Levelup Options: {name}"
},
"MulticlassChoice": {
"title": "Multiclassing - {actor}",
"explanation": "You are adding {class} as your multiclass",
Expand Down Expand Up @@ -1271,6 +1280,10 @@
"diceValue": "Dice Value",
"die": "Die"
},
"LevelupData": {
"checkboxSelections": "Checkboxes",
"minCost": "Minimum Boxes Picked"
},
"Range": {
"self": {
"name": "Self",
Expand Down Expand Up @@ -2483,6 +2496,7 @@
"step": "Step",
"stress": "Stress",
"subclasses": "Subclasses",
"subType": "Subtype",
"success": "Success",
"summon": {
"single": "Summon",
Expand Down Expand Up @@ -3267,6 +3281,7 @@
"rightClickExtend": "Right-Click to extend",
"companionPartnerLevelBlock": "The companion needs an assigned partner to level up.",
"configureAttribution": "Configure Attribution",
"configureLevelupOptions": "Configure Levelup Options",
"deleteItem": "Delete Item",
"immune": "Immune",
"middleClick": "[Middle Click] Keep tooltip view",
Expand Down
1 change: 1 addition & 0 deletions module/applications/dialogs/_module.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ export { default as TagTeamDialog } from './tagTeamDialog.mjs';
export { default as GroupRollDialog } from './groupRollDialog.mjs';
export { default as RiskItAllDialog } from './riskItAllDialog.mjs';
export { default as CompendiumBrowserSettingsDialog } from './CompendiumBrowserSettings.mjs';
export { default as LevelupOptionsDialog } from './levelupOptionsDialog.mjs';
8 changes: 4 additions & 4 deletions module/applications/dialogs/d20RollDialog.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,11 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio

this.config.roll.advantage = this.config.roll.advantage === advantage ? 0 : advantage;

if (this.config.roll.advantage === 1 && this.config.data.rules.roll.defaultAdvantageDice) {
const faces = Number.parseInt(this.config.data.rules.roll.defaultAdvantageDice);
if (this.config.roll.advantage === 1 && this.config.data.rules.roll.advantageFaces) {
const faces = Number.parseInt(this.config.data.rules.roll.advantageFaces);
this.roll.advantageFaces = Number.isNaN(faces) ? this.roll.advantageFaces : faces;
} else if (this.config.roll.advantage === -1 && this.config.data.rules.roll.defaultDisadvantageDice) {
const faces = Number.parseInt(this.config.data.rules.roll.defaultDisadvantageDice);
} else if (this.config.roll.advantage === -1 && this.config.data.rules.roll.disadvantageFaces) {
const faces = Number.parseInt(this.config.data.rules.roll.disadvantageFaces);
this.roll.advantageFaces = Number.isNaN(faces) ? this.roll.advantageFaces : faces;
}

Expand Down
110 changes: 110 additions & 0 deletions module/applications/dialogs/levelupOptionsDialog.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { LevelOptionType } from '../../data/levelTier.mjs';

const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;

export default class LevelupOptionsDialog extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(item) {
super({});

this.item = item;
this.selectedOption = null;
}

get title() {
return game.i18n.format('DAGGERHEART.APPLICATIONS.LevelupOptionsDialog.title', { name: this.item.name });
}

static DEFAULT_OPTIONS = {
tag: 'form',
classes: ['daggerheart', 'dh-style', 'dialog', 'views', 'levelup-options-dialog'],
position: { width: 480, height: 'auto' },
window: { icon: 'fa-solid fa-angles-up fa-fw' },
actions: {
addTierOption: LevelupOptionsDialog.#addTierOption,
removeTierOption: LevelupOptionsDialog.#removeTierOption
},
form: { handler: this.updateData, submitOnChange: true, closeOnSubmit: false }
};

static PARTS = {
header: { template: 'systems/daggerheart/templates/dialogs/levelupOptionsDialog/header.hbs' },
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
tiers: { template: 'systems/daggerheart/templates/dialogs/levelupOptionsDialog/tiers.hbs' }
};

/** @inheritdoc */
static TABS = {
primary: {
tabs: [
{ id: 'tier2', label: 'DAGGERHEART.GENERAL.Tiers.2', tier: 2 },
{ id: 'tier3', label: 'DAGGERHEART.GENERAL.Tiers.3', tier: 3 },
{ id: 'tier4', label: 'DAGGERHEART.GENERAL.Tiers.4', tier: 4 }
],
initial: 'tier2'
}
};

_attachPartListeners(partId, htmlElement, options) {
super._attachPartListeners(partId, htmlElement, options);

for (const element of htmlElement.querySelectorAll('.option-type-select'))
element.addEventListener('change', this.updateSelectedOption.bind(this));
}

async _prepareContext(_options) {
const context = await super._prepareContext(_options);
context.fields = this.item.system.schema.fields.levelupOptionTiers.element.element.fields;
context.item = this.item;
context.levelupOptionTiers = Object.keys(this.item.system.levelupOptionTiers).reduce((acc, key) => {
const tier = this.item.system.levelupOptionTiers[key];
acc[key] = Object.keys(tier).reduce((acc, key) => {
const option = tier[key];
acc[key] = {
...option,
typeData: option.type ? LevelOptionType[option.type] : null
};

return acc;
}, {});

return acc;
}, {});

context.optionTypes = LevelOptionType;
context.selectedOption = this.selectedOption;

return context;
}

static async updateData(_event, _element, formData) {
const data = foundry.utils.expandObject(formData.object);
await this.item.update(data);

this.render();
}

updateSelectedOption(event) {
this.selectedOption = event.target.value;
this.render();
}

static async #addTierOption(_event, button) {
const { tier } = button.dataset;
await this.item.update({
[`system.levelupOptionTiers.${tier}.${foundry.utils.randomID()}`]: {
label: LevelOptionType[this.selectedOption].label,
type: this.selectedOption
}
});

this.selectedOption = null;
this.render();
}

static async #removeTierOption(_event, button) {
const { tier, key } = button.dataset;

await this.item.update({ [`system.levelupOptionTiers.${tier}.${key}`]: _del });
this.render();
}
}
4 changes: 1 addition & 3 deletions module/applications/levelup/characterLevelup.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ export default class DhCharacterLevelUp extends LevelUpBase {
constructor(actor) {
super(actor);

this.levelTiers = this.addBonusChoices(
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers)
);
this.levelTiers = this.addBonusChoices(actor.system.levelupTiers);
const playerLevelupData = actor.system.levelData;
this.levelup = new DhLevelup(DhLevelup.initializeData(this.levelTiers, playerLevelupData));
}
Expand Down
3 changes: 2 additions & 1 deletion module/applications/levelup/levelup.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,8 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
minCost: Number(button.dataset.cost),
amount: button.dataset.amount ? Number(button.dataset.amount) : null,
value: button.dataset.value,
type: button.dataset.type
type: button.dataset.type,
subType: button.dataset.subType
};

if (button.dataset.type === 'domainCard') {
Expand Down
21 changes: 20 additions & 1 deletion module/applications/sheets/api/application-mixin.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ export default function DHApplicationMixin(Base) {
toggleExtended: DHSheetV2.#toggleExtended,
addNewItem: DHSheetV2.#addNewItem,
browseItem: DHSheetV2.#browseItem,
editAttribution: DHSheetV2.#editAttribution
editAttribution: DHSheetV2.#editAttribution,
configureLevelUpOptions: DHSheetV2.#configureLevelUpOptions
},
contextMenus: [
{
Expand All @@ -119,6 +120,16 @@ export default function DHApplicationMixin(Base) {
}
}
],
window: {
controls: [
{
icon: 'fa-solid fa-angles-up fa-fw',
label: 'DAGGERHEART.UI.Tooltip.configureLevelupOptions',
action: 'configureLevelUpOptions',
visible: DHSheetV2.#hasLevelUpOptions
}
]
},
dragDrop: [{ dragSelector: '.inventory-item[data-type="effect"]', dropSelector: null }],
tagifyConfigs: []
};
Expand All @@ -142,6 +153,10 @@ export default function DHApplicationMixin(Base) {
return frame;
}

static #hasLevelUpOptions() {
return this.document.system.metadata.hasLevelUpOptions;
}

/**
* Refresh the custom parts of the application frame
*/
Expand Down Expand Up @@ -709,6 +724,10 @@ export default function DHApplicationMixin(Base) {
new game.system.api.applications.dialogs.AttributionDialog(this.document).render({ force: true });
}

static async #configureLevelUpOptions() {
new game.system.api.applications.dialogs.LevelupOptionsDialog(this.document).render({ force: true });
}

/**
* Create an embedded document.
* @type {ApplicationClickAction}
Expand Down
88 changes: 60 additions & 28 deletions module/data/actor/character.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -261,24 +261,6 @@ export default class DhCharacter extends DhCreature {
})
}
}),
dualityRoll: new fields.SchemaField({
defaultHopeDice: new fields.NumberField({
nullable: false,
required: true,
integer: true,
choices: CONFIG.DH.GENERAL.dieFaces,
initial: 12,
label: 'DAGGERHEART.ACTORS.Character.defaultHopeDice'
}),
defaultFearDice: new fields.NumberField({
nullable: false,
required: true,
integer: true,
choices: CONFIG.DH.GENERAL.dieFaces,
initial: 12,
label: 'DAGGERHEART.ACTORS.Character.defaultFearDice'
})
}),
burden: new fields.SchemaField({
ignore: new fields.BooleanField({ label: 'DAGGERHEART.ACTORS.Character.burden.ignore.label' })
}),
Expand All @@ -287,21 +269,47 @@ export default class DhCharacter extends DhCreature {
label: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.label',
hint: 'DAGGERHEART.ACTORS.Character.roll.guaranteedCritical.hint'
}),
defaultAdvantageDice: new fields.NumberField({
nullable: true,
hopeIndex: new fields.NumberField({
required: true,
integer: true,
min: 0,
max: 5,
initial: 4,
label: 'DAGGERHEART.ACTORS.Creature.rules.roll.hope.label',
hint: 'DAGGERHEART.ACTORS.Creature.rules.roll.hope.hint'
}),
fearIndex: new fields.NumberField({
required: true,
integer: true,
choices: CONFIG.DH.GENERAL.dieFaces,
initial: null,
label: 'DAGGERHEART.ACTORS.Character.defaultAdvantageDice'
min: 0,
max: 5,
initial: 4,
label: 'DAGGERHEART.ACTORS.Creature.rules.roll.fear.label',
hint: 'DAGGERHEART.ACTORS.Creature.rules.roll.fear.hint'
}),
defaultDisadvantageDice: new fields.NumberField({
nullable: true,
advantageIndex: new fields.NumberField({
required: true,
integer: true,
choices: CONFIG.DH.GENERAL.dieFaces,
initial: null,
label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice'
min: 0,
max: 5,
initial: 1,
label: 'DAGGERHEART.ACTORS.Creature.rules.roll.advantage.label',
hint: 'DAGGERHEART.ACTORS.Creature.rules.roll.advantage.hint'
}),
disadvantageIndex: new fields.NumberField({
required: true,
integer: true,
min: 0,
max: 5,
initial: 1,
label: 'DAGGERHEART.ACTORS.Creature.rules.roll.disadvantage.label',
hint: 'DAGGERHEART.ACTORS.Creature.rules.roll.disadvantage.hint'
}),
comboDieIndex: new fields.NumberField({
integer: true,
min: 0,
max: 5,
initial: 0
})
})
})
Expand Down Expand Up @@ -447,6 +455,19 @@ export default class DhCharacter extends DhCreature {
return attack;
}

get levelupTiers() {
const tierData = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers);
for (const tierKey of Object.keys(this.class?.value?.system.levelupOptionTiers ?? {})) {
const tier = this.class.value.system.levelupOptionTiers[tierKey];
for (const optionKey of Object.keys(tier)) {
const option = tier[optionKey];
tierData.tiers[tierKey].options[optionKey] = option;
}
}

return tierData;
}

/* All items are valid on characters */
isItemValid() {
return true;
Expand Down Expand Up @@ -745,6 +766,9 @@ export default class DhCharacter extends DhCreature {
}
});
break;
case 'dice':
this.rules.roll[selection.subType] += 1;
break;
}
}
}
Expand Down Expand Up @@ -802,6 +826,14 @@ export default class DhCharacter extends DhCreature {
isReversed: true
};

/* Add convience <dice>Faces properties for all dice */
const { hopeIndex, fearIndex, advantageIndex, disadvantageIndex, comboDieIndex } = this.rules.roll;
const dice = { hopeIndex, fearIndex, advantageIndex, disadvantageIndex, comboDieIndex };
for (const dieKey of Object.keys(dice)) {
const diceBaseKey = dieKey.replace('Index', '');
this.rules.roll[`${diceBaseKey}Faces`] = CONFIG.DH.GENERAL.dieFaces[dice[dieKey]];
}

this.attack.damage.parts.hitPoints.value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`;
}

Expand Down
Loading
Loading