mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-15 05:01:08 +01:00
Fixed automatic battleToggles
This commit is contained in:
parent
e32454b7c7
commit
d7bbc9e650
10 changed files with 201 additions and 21 deletions
28
lang/en.json
28
lang/en.json
|
|
@ -914,12 +914,28 @@
|
||||||
"hybrid": "Hybrid"
|
"hybrid": "Hybrid"
|
||||||
},
|
},
|
||||||
"BPModifiers": {
|
"BPModifiers": {
|
||||||
"increaseDamage": "if you add +1d4 (or a static +2) to all adversaries' damage rolls (to increase the challenge without lengthening the battle)",
|
"increaseDamage": {
|
||||||
"lessDifficult": "if the fight should be less difficult or shorter.",
|
"description": "if you add +1d4 (or a static +2) to all adversaries' damage rolls (to increase the challenge without lengthening the battle)",
|
||||||
"lowerTier": "if you choose an adversary from a lower tier.",
|
"effect": {
|
||||||
"manySolos": "if you're using 2 or more Solo adversaries.",
|
"name": "Increase Damage",
|
||||||
"moreDangerous": "if the fight should be more dangerous or last longer",
|
"description": "Add 1d4 to damage"
|
||||||
"noToughies": "if you don't include any Bruisers, Hordes, Leaders, or Solos"
|
}
|
||||||
|
},
|
||||||
|
"lessDifficult": {
|
||||||
|
"description": "if the fight should be less difficult or shorter."
|
||||||
|
},
|
||||||
|
"lowerTier": {
|
||||||
|
"description": "if you choose an adversary from a lower tier."
|
||||||
|
},
|
||||||
|
"manySolos": {
|
||||||
|
"description": "if you're using 2 or more Solo adversaries."
|
||||||
|
},
|
||||||
|
"moreDangerous": {
|
||||||
|
"description": "if the fight should be more dangerous or last longer"
|
||||||
|
},
|
||||||
|
"noToughies": {
|
||||||
|
"description": "if you don't include any Bruisers, Hordes, Leaders, or Solos"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Burden": {
|
"Burden": {
|
||||||
"oneHanded": "One-Handed",
|
"oneHanded": "One-Handed",
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C
|
||||||
const modifierBP =
|
const modifierBP =
|
||||||
this.combats
|
this.combats
|
||||||
.find(x => x.active)
|
.find(x => x.active)
|
||||||
?.system?.battleToggles?.reduce((acc, toggle) => acc + toggle.category, 0) ?? 0;
|
?.system?.extendedBattleToggles?.reduce((acc, toggle) => acc + toggle.category, 0) ?? 0;
|
||||||
const maxBP = CONFIG.DH.ENCOUNTER.BaseBPPerEncounter(context.characters.length) + modifierBP;
|
const maxBP = CONFIG.DH.ENCOUNTER.BaseBPPerEncounter(context.characters.length) + modifierBP;
|
||||||
const currentBP = AdversaryBPPerEncounter(context.adversaries, context.characters);
|
const currentBP = AdversaryBPPerEncounter(context.adversaries, context.characters);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,33 +75,68 @@ export const BPModifiers = {
|
||||||
[-2]: {
|
[-2]: {
|
||||||
manySolos: {
|
manySolos: {
|
||||||
sort: 1,
|
sort: 1,
|
||||||
description: 'DAGGERHEART.CONFIG.BPModifiers.manySolos'
|
description: 'DAGGERHEART.CONFIG.BPModifiers.manySolos.description',
|
||||||
|
automatic: true,
|
||||||
|
conditional: (_combat, adversaries) => {
|
||||||
|
return adversaries.filter(x => x.system.type === 'solo').length > 1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
increaseDamage: {
|
increaseDamage: {
|
||||||
sort: 2,
|
sort: 2,
|
||||||
description: 'DAGGERHEART.CONFIG.BPModifiers.increaseDamage'
|
description: 'DAGGERHEART.CONFIG.BPModifiers.increaseDamage.description',
|
||||||
|
effects: [
|
||||||
|
{
|
||||||
|
name: 'DAGGERHEART.CONFIG.BPModifiers.increaseDamage.effect.name',
|
||||||
|
description: 'DAGGERHEART.CONFIG.BPModifiers.increaseDamage.effect.description',
|
||||||
|
img: 'icons/magic/control/buff-flight-wings-red.webp',
|
||||||
|
changes: [
|
||||||
|
{
|
||||||
|
key: 'system.bonuses.damage.physical.dice',
|
||||||
|
mode: 2,
|
||||||
|
value: '1d4'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'system.bonuses.damage.magical.dice',
|
||||||
|
mode: 2,
|
||||||
|
value: '1d4'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[-1]: {
|
[-1]: {
|
||||||
lessDifficult: {
|
lessDifficult: {
|
||||||
sort: 2,
|
sort: 2,
|
||||||
description: 'DAGGERHEART.CONFIG.BPModifiers.lessDifficult'
|
description: 'DAGGERHEART.CONFIG.BPModifiers.lessDifficult.description'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
1: {
|
1: {
|
||||||
lowerTier: {
|
lowerTier: {
|
||||||
sort: 1,
|
sort: 1,
|
||||||
description: 'DAGGERHEART.CONFIG.BPModifiers.lowerTier'
|
description: 'DAGGERHEART.CONFIG.BPModifiers.lowerTier.description',
|
||||||
|
automatic: true,
|
||||||
|
conditional: (_combat, adversaries, characters) => {
|
||||||
|
const characterMaxTier = characters.reduce((maxTier, character) => {
|
||||||
|
return character.system.tier > maxTier ? character.system.tier : maxTier;
|
||||||
|
}, 1);
|
||||||
|
return adversaries.some(adversary => adversary.system.tier < characterMaxTier);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
noToughies: {
|
noToughies: {
|
||||||
sort: 2,
|
sort: 2,
|
||||||
description: 'DAGGERHEART.CONFIG.BPModifiers.noToughies'
|
description: 'DAGGERHEART.CONFIG.BPModifiers.noToughies.description',
|
||||||
|
automatic: true,
|
||||||
|
conditional: (_combat, adversaries) => {
|
||||||
|
const toughyTypes = ['bruiser', 'horde', 'leader', 'solo'];
|
||||||
|
return !adversaries.some(adversary => toughyTypes.includes(adversary.system.type));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
2: {
|
2: {
|
||||||
moreDangerous: {
|
moreDangerous: {
|
||||||
sort: 2,
|
sort: 2,
|
||||||
description: 'DAGGERHEART.CONFIG.BPModifiers.moreDangerous'
|
description: 'DAGGERHEART.CONFIG.BPModifiers.moreDangerous.description'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -26,3 +26,5 @@ export const userFlags = {
|
||||||
welcomeMessage: 'welcome-message',
|
welcomeMessage: 'welcome-message',
|
||||||
countdownMode: 'countdown-mode'
|
countdownMode: 'countdown-mode'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const combatToggle = 'combat-toggle-origin';
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,30 @@ export default class DhCombat extends foundry.abstract.TypeDataModel {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Includes automatic BPModifiers */
|
||||||
|
get extendedBattleToggles() {
|
||||||
|
const modifiers = CONFIG.DH.ENCOUNTER.BPModifiers;
|
||||||
|
const adversaries =
|
||||||
|
this.parent.turns?.filter(x => x.isNPC)?.map(x => ({ ...x.actor, type: x.actor.system.type })) ?? [];
|
||||||
|
const characters = this.parent.turns?.filter(x => !x.isNPC) ?? [];
|
||||||
|
|
||||||
|
const activeAutomatic = Object.keys(modifiers).reduce((acc, categoryKey) => {
|
||||||
|
const category = modifiers[categoryKey];
|
||||||
|
acc.push(
|
||||||
|
...Object.keys(category).reduce((acc, groupingKey) => {
|
||||||
|
const grouping = category[groupingKey];
|
||||||
|
if (grouping.automatic && grouping.conditional?.(this.parent, adversaries, characters)) {
|
||||||
|
acc.push({ category: Number(categoryKey), grouping: groupingKey });
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, [])
|
||||||
|
);
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return [...this.battleToggles, ...activeAutomatic];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,57 @@ export default class DhpCombat extends Combat {
|
||||||
|
|
||||||
return a.name.localeCompare(b.name);
|
return a.name.localeCompare(b.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async toggleModifierEffects(add, actors, category, groupingKey) {
|
||||||
|
const effectData = category && groupingKey ? [{ category, grouping: groupingKey }] : this.system.battleToggles;
|
||||||
|
if (add) {
|
||||||
|
const effects = effectData.reduce((acc, toggle) => {
|
||||||
|
const grouping = CONFIG.DH.ENCOUNTER.BPModifiers[toggle.category]?.[toggle.grouping];
|
||||||
|
if (!grouping?.effects?.length) return acc;
|
||||||
|
acc.push(
|
||||||
|
...grouping.effects.map(effect => ({
|
||||||
|
...effect,
|
||||||
|
name: game.i18n.localize(effect.name),
|
||||||
|
description: game.i18n.localize(effect.description),
|
||||||
|
flags: {
|
||||||
|
[`${CONFIG.DH.id}.${CONFIG.DH.FLAGS.combatToggle}`]: {
|
||||||
|
category: toggle.category,
|
||||||
|
grouping: toggle.grouping
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!effects.length) return;
|
||||||
|
|
||||||
|
for (let actor of actors) {
|
||||||
|
await actor.createEmbeddedDocuments(
|
||||||
|
'ActiveEffect',
|
||||||
|
effects.map(effect => ({
|
||||||
|
...effect,
|
||||||
|
name: game.i18n.localize(effect.name),
|
||||||
|
description: game.i18n.localize(effect.description)
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let actor of actors) {
|
||||||
|
await actor.deleteEmbeddedDocuments(
|
||||||
|
'ActiveEffect',
|
||||||
|
actor.effects
|
||||||
|
.filter(x => {
|
||||||
|
const flag = x.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.combatToggle);
|
||||||
|
if (!flag) return false;
|
||||||
|
return effectData.some(
|
||||||
|
data => flag.category == data.category && flag.grouping === data.grouping
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.map(x => x.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,4 +76,28 @@ export default class DHToken extends TokenDocument {
|
||||||
_shouldRecordMovementHistory() {
|
_shouldRecordMovementHistory() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**@inheritdoc */
|
||||||
|
static async createCombatants(tokens, combat) {
|
||||||
|
combat ??= game.combats.viewed;
|
||||||
|
if (combat?.system?.battleToggles?.length) {
|
||||||
|
await combat.toggleModifierEffects(
|
||||||
|
true,
|
||||||
|
tokens.map(x => x.actor)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
super.createCombatants(tokens, combat ?? {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**@inheritdoc */
|
||||||
|
static async deleteCombatants(tokens, { combat } = {}) {
|
||||||
|
combat ??= game.combats.viewed;
|
||||||
|
if (combat?.system?.battleToggles?.length) {
|
||||||
|
await combat.toggleModifierEffects(
|
||||||
|
false,
|
||||||
|
tokens.map(x => x.actor)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
super.deleteCombatants(tokens, combat ?? {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti
|
||||||
|
|
||||||
const nrCharacters = characters.length;
|
const nrCharacters = characters.length;
|
||||||
const currentBP = AdversaryBPPerEncounter(adversaries, characters);
|
const currentBP = AdversaryBPPerEncounter(adversaries, characters);
|
||||||
const maxBP = combat.system.battleToggles.reduce(
|
const maxBP = combat.system.extendedBattleToggles.reduce(
|
||||||
(acc, toggle) => acc + toggle.category,
|
(acc, toggle) => acc + toggle.category,
|
||||||
BaseBPPerEncounter(nrCharacters)
|
BaseBPPerEncounter(nrCharacters)
|
||||||
);
|
);
|
||||||
|
|
@ -252,18 +252,21 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti
|
||||||
return acc;
|
return acc;
|
||||||
}, foundry.utils.deepClone(CONFIG.DH.ENCOUNTER.adversaryTypeCostBrackets));
|
}, foundry.utils.deepClone(CONFIG.DH.ENCOUNTER.adversaryTypeCostBrackets));
|
||||||
|
|
||||||
|
const extendedBattleToggles = combat.system.extendedBattleToggles;
|
||||||
const toggles = Object.keys(CONFIG.DH.ENCOUNTER.BPModifiers)
|
const toggles = Object.keys(CONFIG.DH.ENCOUNTER.BPModifiers)
|
||||||
.reduce((acc, categoryKey) => {
|
.reduce((acc, categoryKey) => {
|
||||||
const category = CONFIG.DH.ENCOUNTER.BPModifiers[categoryKey];
|
const category = CONFIG.DH.ENCOUNTER.BPModifiers[categoryKey];
|
||||||
acc.push(
|
acc.push(
|
||||||
...Object.keys(category).reduce((acc, toggleKey) => {
|
...Object.keys(category).reduce((acc, toggleKey) => {
|
||||||
|
const grouping = category[toggleKey];
|
||||||
acc.push({
|
acc.push({
|
||||||
...category[toggleKey],
|
...grouping,
|
||||||
categoryKey: Number(categoryKey),
|
categoryKey: Number(categoryKey),
|
||||||
toggleKey,
|
toggleKey,
|
||||||
checked: combat.system.battleToggles.find(
|
checked: extendedBattleToggles.find(
|
||||||
x => x.category == categoryKey && x.grouping === toggleKey
|
x => x.category == categoryKey && x.grouping === toggleKey
|
||||||
)
|
),
|
||||||
|
disabled: grouping.automatic
|
||||||
});
|
});
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
|
|
@ -302,6 +305,13 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await combat.toggleModifierEffects(
|
||||||
|
event.target.checked,
|
||||||
|
combat.combatants.filter(x => x.actor.type === 'adversary').map(x => x.actor),
|
||||||
|
category,
|
||||||
|
grouping
|
||||||
|
);
|
||||||
|
|
||||||
this.tooltip.innerHTML = await this.getBattlepointHTML(combatId);
|
this.tooltip.innerHTML = await this.getBattlepointHTML(combatId);
|
||||||
const lockedTooltip = this.lockTooltip();
|
const lockedTooltip = this.lockTooltip();
|
||||||
lockedTooltip.querySelectorAll('.battlepoint-toggle-container input').forEach(element => {
|
lockedTooltip.querySelectorAll('.battlepoint-toggle-container input').forEach(element => {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,16 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
|
||||||
|
&.inactive {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grouping-lock {
|
||||||
|
font-size: 17.5px;
|
||||||
|
margin: 0 5px;
|
||||||
|
color: @golden;
|
||||||
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
{{#if grouping.nr}}
|
{{#if grouping.nr}}
|
||||||
<label>{{key}} BP: {{concat (localize grouping.description) ' ' '('grouping.nr 'x)'}}</label>
|
<label>{{key}} BP: {{concat (localize grouping.description) ' ' '('grouping.nr 'x)'}}</label>
|
||||||
{{else}}
|
{{else}}
|
||||||
<label class="unselected-grouping">{{key}}BP - {{localize grouping.description}}</label>
|
<label class="unselected-grouping">{{key}} BP - {{localize grouping.description}}</label>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
@ -16,8 +16,12 @@
|
||||||
<div class="battlepoint-toggles-container">
|
<div class="battlepoint-toggles-container">
|
||||||
<h3>{{localize "Modifiers"}}</h3>
|
<h3>{{localize "Modifiers"}}</h3>
|
||||||
{{#each toggles as |toggle|}}
|
{{#each toggles as |toggle|}}
|
||||||
<div class="battlepoint-toggle-container">
|
<div class="battlepoint-toggle-container {{#if (and toggle.disabled (not toggle.checked))}}inactive{{/if}}">
|
||||||
<input type="checkbox" data-combat-id="{{@root.combatId}}" data-category="{{toggle.categoryKey}}" data-grouping="{{toggle.toggleKey}}" {{checked toggle.checked}} />
|
{{#if toggle.disabled}}
|
||||||
|
<i class="grouping-lock fa-solid {{#if toggle.checked}}fa-lock{{else}}fa-unlock{{/if}}"></i>
|
||||||
|
{{else}}
|
||||||
|
<input type="checkbox" data-combat-id="{{@root.combatId}}" data-category="{{toggle.categoryKey}}" data-grouping="{{toggle.toggleKey}}" {{checked toggle.checked}} />
|
||||||
|
{{/if}}
|
||||||
<label class="unselected-grouping">{{toggle.categoryKey}} BP: {{localize toggle.description}}</label>
|
<label class="unselected-grouping">{{toggle.categoryKey}} BP: {{localize toggle.description}}</label>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue