mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-21 23:13:39 +02:00
Initial
This commit is contained in:
parent
f1f5102af1
commit
c6bf482b07
12 changed files with 280 additions and 94 deletions
|
|
@ -97,6 +97,30 @@ Hooks.once('init', () => {
|
|||
fields
|
||||
};
|
||||
|
||||
CONFIG.DH.ACTOR.characterResources.corruption = {
|
||||
id: 'corruption',
|
||||
initial: 0,
|
||||
max: 4,
|
||||
reverse: false,
|
||||
label: 'Corruption'
|
||||
};
|
||||
|
||||
CONFIG.DH.ACTOR.characterResources.hunger = {
|
||||
id: 'hunger',
|
||||
initial: 0,
|
||||
max: 6,
|
||||
reverse: false,
|
||||
label: 'Hunger'
|
||||
};
|
||||
|
||||
CONFIG.DH.ACTOR.characterResources.glitched = {
|
||||
id: 'glitched',
|
||||
initial: 0,
|
||||
max: 6,
|
||||
reverse: false,
|
||||
label: 'Glitched'
|
||||
};
|
||||
|
||||
game.system.registeredTriggers = new game.system.api.data.RegisteredTriggers();
|
||||
|
||||
const { DocumentSheetConfig } = foundry.applications.apps;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
handleResourceDice: CharacterSheet.#handleResourceDice,
|
||||
advanceResourceDie: CharacterSheet.#advanceResourceDie,
|
||||
cancelBeastform: CharacterSheet.#cancelBeastform,
|
||||
toggleResourceManagement: CharacterSheet.#toggleResourceManagement,
|
||||
useDowntime: this.useDowntime,
|
||||
viewParty: CharacterSheet.#viewParty
|
||||
},
|
||||
|
|
@ -942,6 +943,71 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
});
|
||||
}
|
||||
|
||||
static async #toggleResourceManagement(_event, button) {
|
||||
const existingTooltip = document.body.querySelector('.locked-tooltip .resource-management-container');
|
||||
if (existingTooltip) {
|
||||
game.tooltip.dismissLockedTooltips();
|
||||
return;
|
||||
}
|
||||
|
||||
const extraResources = Object.values(CONFIG.DH.ACTOR.characterResources).reduce((acc, resource) => {
|
||||
if (CONFIG.DH.ACTOR.characterBaseResources[resource.id]) return acc;
|
||||
|
||||
const resourceData = this.document.system.resources[resource.id];
|
||||
acc[resource.id] = {
|
||||
id: resource.id,
|
||||
label: game.i18n.localize(resource.label),
|
||||
value: resourceData.value,
|
||||
max: resourceData.max
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const html = document.createElement('div');
|
||||
html.innerHTML = await foundry.applications.handlebars.renderTemplate(
|
||||
`systems/daggerheart/templates/ui/tooltip/resourceManagement.hbs`,
|
||||
{
|
||||
resources: extraResources
|
||||
}
|
||||
);
|
||||
|
||||
const target = button.closest('.resource-section');
|
||||
|
||||
game.tooltip.dismissLockedTooltips();
|
||||
game.tooltip.activate(target, {
|
||||
html,
|
||||
locked: true,
|
||||
cssClass: 'bordered-tooltip',
|
||||
direction: 'DOWN'
|
||||
});
|
||||
|
||||
for (const element of html.querySelectorAll('.resource-value'))
|
||||
element.addEventListener('click', CharacterSheet.resourceUpdate.bind(this));
|
||||
}
|
||||
|
||||
static async resourceUpdate(event) {
|
||||
const target = event.target.closest('.resource-value');
|
||||
const { resource, value: textValue } = target.dataset;
|
||||
|
||||
const inputValue = Number.parseInt(textValue);
|
||||
const decreasing = inputValue <= this.document.system.resources[resource].value;
|
||||
const value = decreasing ? inputValue - 1 : inputValue;
|
||||
await this.document.update({ [`system.resources.${resource}.value`]: value });
|
||||
|
||||
/* Update resource symbols */
|
||||
const section = target.closest('.resource-section');
|
||||
for (const element of section.querySelectorAll('.resource-value')) {
|
||||
if (Number.parseInt(element.dataset.value) <= value) {
|
||||
element.querySelector('.fa-diamond').classList.remove('hidden');
|
||||
element.querySelector('.fa-circle').classList.add('hidden');
|
||||
} else {
|
||||
element.querySelector('.fa-diamond').classList.add('hidden');
|
||||
element.querySelector('.fa-circle').classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the downtime application.
|
||||
* @type {ApplicationClickAction}
|
||||
|
|
|
|||
|
|
@ -55,24 +55,47 @@ export const abilities = {
|
|||
}
|
||||
};
|
||||
|
||||
export const scrollingTextResource = {
|
||||
const baseResources = {
|
||||
hitPoints: {
|
||||
id: 'hitPoints',
|
||||
initial: 0,
|
||||
max: 0,
|
||||
reverse: true,
|
||||
label: 'DAGGERHEART.GENERAL.HitPoints.plural',
|
||||
reversed: true
|
||||
maxLabel: 'DAGGERHEART.ACTORS.Character.maxHPBonus'
|
||||
},
|
||||
stress: {
|
||||
label: 'DAGGERHEART.GENERAL.stress',
|
||||
reversed: true
|
||||
id: 'stress',
|
||||
initial: 0,
|
||||
max: 6,
|
||||
reverse: true,
|
||||
label: 'DAGGERHEART.GENERAL.stress'
|
||||
},
|
||||
hope: {
|
||||
id: 'hope',
|
||||
initial: 2,
|
||||
min: 0,
|
||||
reverse: false,
|
||||
label: 'DAGGERHEART.GENERAL.hope'
|
||||
},
|
||||
armor: {
|
||||
label: 'DAGGERHEART.GENERAL.armor',
|
||||
reversed: true
|
||||
}
|
||||
};
|
||||
|
||||
export const characterBaseResources = {
|
||||
...baseResources
|
||||
};
|
||||
|
||||
export const characterResources = {
|
||||
...characterBaseResources
|
||||
};
|
||||
|
||||
export const getScrollingTextResources = actorType => ({
|
||||
armor: {
|
||||
label: 'DAGGERHEART.GENERAL.armor',
|
||||
reverse: true
|
||||
},
|
||||
...(actorType === 'character' ? characterResources : {})
|
||||
});
|
||||
|
||||
export const featureProperties = {
|
||||
agility: {
|
||||
name: 'DAGGERHEART.CONFIG.Traits.agility.name',
|
||||
|
|
@ -518,7 +541,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 10,
|
||||
hp: 1,
|
||||
stress: 2,
|
||||
attack: 2,
|
||||
attack: 2
|
||||
},
|
||||
3: {
|
||||
difficulty: 2,
|
||||
|
|
@ -526,7 +549,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 15,
|
||||
hp: 1,
|
||||
stress: 0,
|
||||
attack: 2,
|
||||
attack: 2
|
||||
},
|
||||
4: {
|
||||
difficulty: 2,
|
||||
|
|
@ -534,7 +557,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 25,
|
||||
hp: 1,
|
||||
stress: 0,
|
||||
attack: 2,
|
||||
attack: 2
|
||||
}
|
||||
},
|
||||
horde: {
|
||||
|
|
@ -544,7 +567,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 8,
|
||||
hp: 2,
|
||||
stress: 0,
|
||||
attack: 0,
|
||||
attack: 0
|
||||
},
|
||||
3: {
|
||||
difficulty: 2,
|
||||
|
|
@ -552,7 +575,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 12,
|
||||
hp: 0,
|
||||
stress: 1,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
4: {
|
||||
difficulty: 2,
|
||||
|
|
@ -560,7 +583,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 15,
|
||||
hp: 2,
|
||||
stress: 0,
|
||||
attack: 0,
|
||||
attack: 0
|
||||
}
|
||||
},
|
||||
leader: {
|
||||
|
|
@ -570,7 +593,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 10,
|
||||
hp: 0,
|
||||
stress: 0,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
3: {
|
||||
difficulty: 2,
|
||||
|
|
@ -578,7 +601,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 15,
|
||||
hp: 1,
|
||||
stress: 0,
|
||||
attack: 2,
|
||||
attack: 2
|
||||
},
|
||||
4: {
|
||||
difficulty: 2,
|
||||
|
|
@ -586,7 +609,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 25,
|
||||
hp: 1,
|
||||
stress: 1,
|
||||
attack: 3,
|
||||
attack: 3
|
||||
}
|
||||
},
|
||||
minion: {
|
||||
|
|
@ -596,7 +619,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 0,
|
||||
hp: 0,
|
||||
stress: 0,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
3: {
|
||||
difficulty: 2,
|
||||
|
|
@ -604,7 +627,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 0,
|
||||
hp: 0,
|
||||
stress: 1,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
4: {
|
||||
difficulty: 2,
|
||||
|
|
@ -612,7 +635,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 0,
|
||||
hp: 0,
|
||||
stress: 0,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
}
|
||||
},
|
||||
ranged: {
|
||||
|
|
@ -622,7 +645,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 6,
|
||||
hp: 1,
|
||||
stress: 0,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
3: {
|
||||
difficulty: 2,
|
||||
|
|
@ -630,7 +653,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 14,
|
||||
hp: 1,
|
||||
stress: 1,
|
||||
attack: 2,
|
||||
attack: 2
|
||||
},
|
||||
4: {
|
||||
difficulty: 2,
|
||||
|
|
@ -638,7 +661,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 10,
|
||||
hp: 1,
|
||||
stress: 1,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
}
|
||||
},
|
||||
skulk: {
|
||||
|
|
@ -648,7 +671,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 8,
|
||||
hp: 1,
|
||||
stress: 1,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
3: {
|
||||
difficulty: 2,
|
||||
|
|
@ -656,7 +679,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 12,
|
||||
hp: 1,
|
||||
stress: 1,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
4: {
|
||||
difficulty: 2,
|
||||
|
|
@ -664,7 +687,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 10,
|
||||
hp: 1,
|
||||
stress: 1,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
}
|
||||
},
|
||||
solo: {
|
||||
|
|
@ -674,7 +697,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 10,
|
||||
hp: 0,
|
||||
stress: 1,
|
||||
attack: 2,
|
||||
attack: 2
|
||||
},
|
||||
3: {
|
||||
difficulty: 2,
|
||||
|
|
@ -682,7 +705,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 15,
|
||||
hp: 2,
|
||||
stress: 1,
|
||||
attack: 2,
|
||||
attack: 2
|
||||
},
|
||||
4: {
|
||||
difficulty: 2,
|
||||
|
|
@ -690,7 +713,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 25,
|
||||
hp: 0,
|
||||
stress: 1,
|
||||
attack: 3,
|
||||
attack: 3
|
||||
}
|
||||
},
|
||||
standard: {
|
||||
|
|
@ -700,7 +723,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 8,
|
||||
hp: 0,
|
||||
stress: 0,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
3: {
|
||||
difficulty: 2,
|
||||
|
|
@ -708,7 +731,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 15,
|
||||
hp: 1,
|
||||
stress: 1,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
4: {
|
||||
difficulty: 2,
|
||||
|
|
@ -716,7 +739,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 15,
|
||||
hp: 0,
|
||||
stress: 1,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
}
|
||||
},
|
||||
support: {
|
||||
|
|
@ -726,7 +749,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 8,
|
||||
hp: 1,
|
||||
stress: 1,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
3: {
|
||||
difficulty: 2,
|
||||
|
|
@ -734,7 +757,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 12,
|
||||
hp: 0,
|
||||
stress: 0,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
},
|
||||
4: {
|
||||
difficulty: 2,
|
||||
|
|
@ -742,7 +765,7 @@ export const adversaryScalingData = {
|
|||
severeThreshold: 10,
|
||||
hp: 1,
|
||||
stress: 1,
|
||||
attack: 1,
|
||||
attack: 1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ export default class BaseDataActor extends foundry.abstract.TypeDataModel {
|
|||
const textData = Object.keys(changes.system.resources).reduce((acc, key) => {
|
||||
const resource = changes.system.resources[key];
|
||||
if (resource.value !== undefined && resource.value !== this.resources[key].value) {
|
||||
acc.push(getScrollTextData(this.resources, resource, key));
|
||||
acc.push(getScrollTextData(this.resources, resource, key, this.parent.type));
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
|
|
|||
|
|
@ -28,26 +28,32 @@ export default class DhCharacter extends DhCreature {
|
|||
return {
|
||||
...super.defineSchema(),
|
||||
resources: new fields.SchemaField({
|
||||
hitPoints: resourceField(
|
||||
0,
|
||||
0,
|
||||
'DAGGERHEART.GENERAL.HitPoints.plural',
|
||||
true,
|
||||
'DAGGERHEART.ACTORS.Character.maxHPBonus'
|
||||
),
|
||||
stress: resourceField(6, 0, 'DAGGERHEART.GENERAL.stress', true),
|
||||
hope: new fields.SchemaField(
|
||||
...Object.values(CONFIG.DH.ACTOR.characterResources).reduce((acc, resource) => {
|
||||
if (resource.max !== undefined) {
|
||||
acc[resource.id] = resourceField(
|
||||
resource.max,
|
||||
resource.initial,
|
||||
resource.label,
|
||||
resource.reverse,
|
||||
resource.maxLabel
|
||||
);
|
||||
} else {
|
||||
acc[resource.id] = new fields.SchemaField(
|
||||
{
|
||||
value: new fields.NumberField({
|
||||
initial: 2,
|
||||
min: 0,
|
||||
initial: resource.initial,
|
||||
min: resource.min,
|
||||
integer: true,
|
||||
label: 'DAGGERHEART.GENERAL.hope'
|
||||
label: resource.label
|
||||
}),
|
||||
isReversed: new fields.BooleanField({ initial: false })
|
||||
isReversed: new fields.BooleanField({ initial: resource.reverse })
|
||||
},
|
||||
{ label: 'DAGGERHEART.GENERAL.hope' }
|
||||
)
|
||||
{ label: resource.label }
|
||||
);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
}),
|
||||
traits: new fields.SchemaField({
|
||||
agility: attributeField('DAGGERHEART.CONFIG.Traits.agility.name'),
|
||||
|
|
|
|||
|
|
@ -224,7 +224,12 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
|
|||
const armorChanged =
|
||||
changed.system?.marks?.value !== undefined && changed.system.marks.value !== this.marks.value;
|
||||
if (armorChanged && autoSettings.resourceScrollTexts && this.parent.parent?.type === 'character') {
|
||||
const armorData = getScrollTextData(this.parent.parent.system.resources, changed.system.marks, 'armor');
|
||||
const armorData = getScrollTextData(
|
||||
this.parent.parent.system.resources,
|
||||
changed.system.marks,
|
||||
'armor',
|
||||
this.parent.parent.type
|
||||
);
|
||||
options.scrollingTextData = [armorData];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -378,17 +378,17 @@ export const arraysEqual = (a, b) =>
|
|||
|
||||
export const setsEqual = (a, b) => a.size === b.size && [...a].every(value => b.has(value));
|
||||
|
||||
export function getScrollTextData(resources, resource, key) {
|
||||
const { reversed, label } = CONFIG.DH.ACTOR.scrollingTextResource[key];
|
||||
export function getScrollTextData(resources, resource, key, actorType) {
|
||||
const { reverse, label } = CONFIG.DH.ACTOR.getScrollingTextResources(actorType)[key];
|
||||
const { BOTTOM, TOP } = CONST.TEXT_ANCHOR_POINTS;
|
||||
const increased = resources[key].value < resource.value;
|
||||
const value = -1 * (resources[key].value - resource.value);
|
||||
|
||||
const text = `${game.i18n.localize(label)} ${value.signedString()}`;
|
||||
|
||||
const stroke = increased ? (reversed ? 0xffffff : 0x000000) : reversed ? 0x000000 : 0xffffff;
|
||||
const fill = increased ? (reversed ? 0x0032b1 : 0xffe760) : reversed ? 0xffe760 : 0x0032b1;
|
||||
const direction = increased ? (reversed ? BOTTOM : TOP) : reversed ? TOP : BOTTOM;
|
||||
const stroke = increased ? (reverse ? 0xffffff : 0x000000) : reverse ? 0x000000 : 0xffffff;
|
||||
const fill = increased ? (reverse ? 0x0032b1 : 0xffe760) : reverse ? 0xffe760 : 0x0032b1;
|
||||
const direction = increased ? (reverse ? BOTTOM : TOP) : reverse ? TOP : BOTTOM;
|
||||
|
||||
return { text, stroke, fill, direction };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,8 +133,15 @@
|
|||
padding: 0;
|
||||
margin-bottom: 15px;
|
||||
|
||||
.hope-section {
|
||||
.resource-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-right: 20px;
|
||||
|
||||
.resource-manager {
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
}
|
||||
}
|
||||
|
||||
.downtime-section {
|
||||
|
|
|
|||
|
|
@ -4,3 +4,5 @@
|
|||
@import './tooltip/domain-cards.less';
|
||||
|
||||
@import './autocomplete/autocomplete.less';
|
||||
|
||||
@import './tooltip/resource-management.less';
|
||||
|
|
|
|||
37
styles/less/ux/tooltip/resource-management.less
Normal file
37
styles/less/ux/tooltip/resource-management.less
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
.bordered-tooltip.locked-tooltip .daggerheart.resource-management-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
.resource-section {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
background-color: light-dark(transparent, @dark-blue);
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
padding: 5px 10px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 6px;
|
||||
align-items: center;
|
||||
width: fit-content;
|
||||
height: 30px;
|
||||
|
||||
h4 {
|
||||
font-family: var(--dh-font-body, 'Montserrat'), sans-serif;
|
||||
font-size: var(--font-size-14);
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.resource-value {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -65,6 +65,7 @@
|
|||
</div>
|
||||
|
||||
<div class="character-row">
|
||||
<div class="resource-section">
|
||||
<div class="hope-section">
|
||||
<h4>{{localize "DAGGERHEART.GENERAL.hope"}}</h4>
|
||||
{{#times document.system.resources.hope.max}}
|
||||
|
|
@ -82,6 +83,8 @@
|
|||
</span>
|
||||
{{/times}}
|
||||
</div>
|
||||
<a class="resource-manager" data-action="toggleResourceManagement"><i class="fa-solid fa-gear"></i></a>
|
||||
</div>
|
||||
{{#if document.system.class.value}}
|
||||
<div class="domains-section">
|
||||
{{#each document.system.domainData as |data|}}
|
||||
|
|
|
|||
13
templates/ui/tooltip/resourceManagement.hbs
Normal file
13
templates/ui/tooltip/resourceManagement.hbs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<div class="daggerheart resource-management-container">
|
||||
{{#each resources as |resource|}}
|
||||
<div class="resource-section">
|
||||
<h4>{{resource.label}}</h4>
|
||||
{{#times resource.max}}
|
||||
<span class='resource-value' data-action='toggleResource' data-value="{{add this 1}}" data-resource="{{resource.id}}">
|
||||
<i class='fa-solid fa-diamond {{#unless (gte ../value (add this 1))}}hidden{{/unless}}'></i>
|
||||
<i class='fa-regular fa-circle {{#if (gte ../value (add this 1))}}hidden{{/if}}'></i>
|
||||
</span>
|
||||
{{/times}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue