mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
Feature/163 actor subdatas (#346)
* Actor Roll bonuses * Removed console log and comment --------- Co-authored-by: WBHarry <williambjrklund@gmail.com>
This commit is contained in:
parent
422f28c93c
commit
37c1d7ad88
21 changed files with 210 additions and 103 deletions
|
|
@ -686,11 +686,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"RollTypes": {
|
"RollTypes": {
|
||||||
"ability": {
|
"trait": {
|
||||||
"name": "Ability"
|
"name": "Trait"
|
||||||
},
|
},
|
||||||
"weapon": {
|
"attack": {
|
||||||
"name": "Weapon"
|
"name": "Attack"
|
||||||
},
|
},
|
||||||
"spellcast": {
|
"spellcast": {
|
||||||
"name": "SpellCast"
|
"name": "SpellCast"
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,6 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
||||||
}
|
}
|
||||||
|
|
||||||
addChatListeners = async (app, html, data) => {
|
addChatListeners = async (app, html, data) => {
|
||||||
super.addChatListeners(app, html, data);
|
|
||||||
|
|
||||||
html.querySelectorAll('.duality-action-damage').forEach(element =>
|
html.querySelectorAll('.duality-action-damage').forEach(element =>
|
||||||
element.addEventListener('click', event => this.onRollDamage(event, data.message))
|
element.addEventListener('click', event => this.onRollDamage(event, data.message))
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -388,17 +388,17 @@ export const countdownTypes = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const rollTypes = {
|
export const rollTypes = {
|
||||||
weapon: {
|
attack: {
|
||||||
id: 'weapon',
|
id: 'attack',
|
||||||
label: 'DAGGERHEART.CONFIG.RollTypes.weapon.name'
|
label: 'DAGGERHEART.CONFIG.RollTypes.attack.name'
|
||||||
},
|
},
|
||||||
spellcast: {
|
spellcast: {
|
||||||
id: 'spellcast',
|
id: 'spellcast',
|
||||||
label: 'DAGGERHEART.CONFIG.RollTypes.spellcast.name'
|
label: 'DAGGERHEART.CONFIG.RollTypes.spellcast.name'
|
||||||
},
|
},
|
||||||
ability: {
|
trait: {
|
||||||
id: 'ability',
|
id: 'trait',
|
||||||
label: 'DAGGERHEART.CONFIG.RollTypes.ability.name'
|
label: 'DAGGERHEART.CONFIG.RollTypes.trait.name'
|
||||||
},
|
},
|
||||||
diceSet: {
|
diceSet: {
|
||||||
id: 'diceSet',
|
id: 'diceSet',
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ export default class DHAttackAction extends DHDamageAction {
|
||||||
static extraSchemas = [...super.extraSchemas, ...['roll', 'save']];
|
static extraSchemas = [...super.extraSchemas, ...['roll', 'save']];
|
||||||
|
|
||||||
static getRollType(parent) {
|
static getRollType(parent) {
|
||||||
return parent.type === 'weapon' ? 'weapon' : 'spellcast';
|
return parent.type === 'weapon' ? 'attack' : 'spellcast';
|
||||||
}
|
}
|
||||||
|
|
||||||
get chatTemplate() {
|
get chatTemplate() {
|
||||||
|
|
@ -21,7 +21,7 @@ export default class DHAttackAction extends DHDamageAction {
|
||||||
}
|
}
|
||||||
if (this.roll.useDefault) {
|
if (this.roll.useDefault) {
|
||||||
this.roll.trait = this.item.system.attack.roll.trait;
|
this.roll.trait = this.item.system.attack.roll.trait;
|
||||||
this.roll.type = 'weapon';
|
this.roll.type = 'attack';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -37,4 +37,8 @@ export default class DHAttackAction extends DHDamageAction {
|
||||||
base: true
|
base: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get modifiers() {
|
||||||
|
// return [];
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ export default class DHBaseAction extends foundry.abstract.DataModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
static getRollType(parent) {
|
static getRollType(parent) {
|
||||||
return 'ability';
|
return 'trait';
|
||||||
}
|
}
|
||||||
|
|
||||||
static getSourceConfig(parent) {
|
static getSourceConfig(parent) {
|
||||||
|
|
@ -308,7 +308,7 @@ export default class DHBaseAction extends foundry.abstract.DataModel {
|
||||||
|
|
||||||
prepareRoll() {
|
prepareRoll() {
|
||||||
const roll = {
|
const roll = {
|
||||||
modifiers: [],
|
modifiers: this.modifiers,
|
||||||
trait: this.roll?.trait,
|
trait: this.roll?.trait,
|
||||||
label: 'Attack',
|
label: 'Attack',
|
||||||
type: this.actionType,
|
type: this.actionType,
|
||||||
|
|
@ -362,6 +362,13 @@ export default class DHBaseAction extends foundry.abstract.DataModel {
|
||||||
get hasRoll() {
|
get hasRoll() {
|
||||||
return !!this.roll?.type || !!this.roll?.bonus;
|
return !!this.roll?.type || !!this.roll?.bonus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get modifiers() {
|
||||||
|
if(!this.actor) return [];
|
||||||
|
const modifiers = [];
|
||||||
|
/** Placeholder for specific bonuses **/
|
||||||
|
return modifiers;
|
||||||
|
}
|
||||||
/* ROLL */
|
/* ROLL */
|
||||||
|
|
||||||
/* SAVE */
|
/* SAVE */
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ export default class DHDamageAction extends DHBaseAction {
|
||||||
hasSave: this.hasSave,
|
hasSave: this.hasSave,
|
||||||
isCritical: data.system?.roll?.isCritical ?? false,
|
isCritical: data.system?.roll?.isCritical ?? false,
|
||||||
source: data.system?.source,
|
source: data.system?.source,
|
||||||
|
data: this.getRollData(),
|
||||||
damageTypes,
|
damageTypes,
|
||||||
event
|
event
|
||||||
};
|
};
|
||||||
|
|
@ -39,4 +40,8 @@ export default class DHDamageAction extends DHBaseAction {
|
||||||
|
|
||||||
roll = CONFIG.Dice.daggerheart.DamageRoll.build(config);
|
roll = CONFIG.Dice.daggerheart.DamageRoll.build(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get modifiers() {
|
||||||
|
// return [];
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,4 +39,8 @@ export default class DHHealingAction extends DHBaseAction {
|
||||||
get chatTemplate() {
|
get chatTemplate() {
|
||||||
return 'systems/daggerheart/templates/ui/chat/healing-roll.hbs';
|
return 'systems/daggerheart/templates/ui/chat/healing-roll.hbs';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get modifiers() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,7 @@
|
||||||
import DHAdversarySettings from '../../applications/sheets-configs/adversary-settings.mjs';
|
import DHAdversarySettings from '../../applications/sheets-configs/adversary-settings.mjs';
|
||||||
import ActionField from '../fields/actionField.mjs';
|
import ActionField from '../fields/actionField.mjs';
|
||||||
import BaseDataActor from './base.mjs';
|
import BaseDataActor from './base.mjs';
|
||||||
|
import { resourceField, bonusField } from '../fields/actorField.mjs';
|
||||||
const resourceField = () =>
|
|
||||||
new foundry.data.fields.SchemaField({
|
|
||||||
value: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
|
|
||||||
max: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
|
|
||||||
isReversed: new foundry.data.fields.BooleanField({ initial: true })
|
|
||||||
});
|
|
||||||
|
|
||||||
export default class DhpAdversary extends BaseDataActor {
|
export default class DhpAdversary extends BaseDataActor {
|
||||||
static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Adversary'];
|
static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Adversary'];
|
||||||
|
|
@ -43,8 +37,8 @@ export default class DhpAdversary extends BaseDataActor {
|
||||||
severe: new fields.NumberField({ required: true, initial: 0, integer: true })
|
severe: new fields.NumberField({ required: true, initial: 0, integer: true })
|
||||||
}),
|
}),
|
||||||
resources: new fields.SchemaField({
|
resources: new fields.SchemaField({
|
||||||
hitPoints: resourceField(),
|
hitPoints: resourceField(0, true),
|
||||||
stress: resourceField()
|
stress: resourceField(0, true)
|
||||||
}),
|
}),
|
||||||
attack: new ActionField({
|
attack: new ActionField({
|
||||||
initial: {
|
initial: {
|
||||||
|
|
@ -59,7 +53,7 @@ export default class DhpAdversary extends BaseDataActor {
|
||||||
amount: 1
|
amount: 1
|
||||||
},
|
},
|
||||||
roll: {
|
roll: {
|
||||||
type: 'weapon'
|
type: 'attack'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: [
|
||||||
|
|
@ -80,9 +74,14 @@ export default class DhpAdversary extends BaseDataActor {
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
bonuses: new fields.SchemaField({
|
bonuses: new fields.SchemaField({
|
||||||
difficulty: new fields.SchemaField({
|
roll: new fields.SchemaField({
|
||||||
all: new fields.NumberField({ integer: true, initial: 0 }),
|
attack: bonusField(),
|
||||||
reaction: new fields.NumberField({ integer: true, initial: 0 })
|
action: bonusField(),
|
||||||
|
reaction: bonusField()
|
||||||
|
}),
|
||||||
|
damage: new fields.SchemaField({
|
||||||
|
physical: bonusField(),
|
||||||
|
magical: bonusField()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,7 @@ import { burden } from '../../config/generalConfig.mjs';
|
||||||
import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
|
import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
|
||||||
import DhLevelData from '../levelData.mjs';
|
import DhLevelData from '../levelData.mjs';
|
||||||
import BaseDataActor from './base.mjs';
|
import BaseDataActor from './base.mjs';
|
||||||
|
import { attributeField, resourceField, stressDamageReductionRule, bonusField } from '../fields/actorField.mjs';
|
||||||
const attributeField = () =>
|
|
||||||
new foundry.data.fields.SchemaField({
|
|
||||||
value: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
|
|
||||||
tierMarked: new foundry.data.fields.BooleanField({ initial: false })
|
|
||||||
});
|
|
||||||
|
|
||||||
const resourceField = (max, reverse = false) =>
|
|
||||||
new foundry.data.fields.SchemaField({
|
|
||||||
value: new foundry.data.fields.NumberField({ initial: 0, integer: true }),
|
|
||||||
max: new foundry.data.fields.NumberField({ initial: max, integer: true }),
|
|
||||||
isReversed: new foundry.data.fields.BooleanField({ initial: reverse })
|
|
||||||
});
|
|
||||||
|
|
||||||
const stressDamageReductionRule = () =>
|
|
||||||
new foundry.data.fields.SchemaField({
|
|
||||||
enabled: new foundry.data.fields.BooleanField({ required: true, initial: false }),
|
|
||||||
cost: new foundry.data.fields.NumberField({ integer: true })
|
|
||||||
});
|
|
||||||
|
|
||||||
export default class DhCharacter extends BaseDataActor {
|
export default class DhCharacter extends BaseDataActor {
|
||||||
static get metadata() {
|
static get metadata() {
|
||||||
|
|
@ -94,22 +76,25 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
levelData: new fields.EmbeddedDataField(DhLevelData),
|
levelData: new fields.EmbeddedDataField(DhLevelData),
|
||||||
bonuses: new fields.SchemaField({
|
bonuses: new fields.SchemaField({
|
||||||
roll: new fields.SchemaField({
|
roll: new fields.SchemaField({
|
||||||
attack: new fields.NumberField({ integer: true, initial: 0 }),
|
attack: bonusField(),
|
||||||
primaryWeapon: new fields.SchemaField({
|
spellcast: bonusField(),
|
||||||
attack: new fields.NumberField({ integer: true, initial: 0 })
|
trait: bonusField(),
|
||||||
}),
|
action: bonusField(),
|
||||||
spellcast: new fields.NumberField({ integer: true, initial: 0 }),
|
reaction: bonusField(),
|
||||||
action: new fields.NumberField({ integer: true, initial: 0 }),
|
primaryWeapon: bonusField(),
|
||||||
hopeOrFear: new fields.NumberField({ integer: true, initial: 0 })
|
secondaryWeapon: bonusField()
|
||||||
}),
|
}),
|
||||||
damage: new fields.SchemaField({
|
damage: new fields.SchemaField({
|
||||||
all: new fields.NumberField({ integer: true, initial: 0 }),
|
physical: bonusField(),
|
||||||
physical: new fields.NumberField({ integer: true, initial: 0 }),
|
magical: bonusField(),
|
||||||
magic: new fields.NumberField({ integer: true, initial: 0 }),
|
primaryWeapon: bonusField(),
|
||||||
primaryWeapon: new fields.SchemaField({
|
secondaryWeapon: bonusField()
|
||||||
bonus: new fields.NumberField({ integer: true }),
|
}),
|
||||||
extraDice: new fields.NumberField({ integer: true })
|
healing: bonusField(),
|
||||||
})
|
range: new fields.SchemaField({
|
||||||
|
weapon: new fields.NumberField({ integer: true, initial: 0 }),
|
||||||
|
spell: new fields.NumberField({ integer: true, initial: 0 }),
|
||||||
|
other: new fields.NumberField({ integer: true, initial: 0 })
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
companion: new ForeignDocumentUUIDField({ type: 'Actor', nullable: true, initial: null }),
|
companion: new ForeignDocumentUUIDField({ type: 'Actor', nullable: true, initial: null }),
|
||||||
|
|
@ -181,6 +166,11 @@ export default class DhCharacter extends BaseDataActor {
|
||||||
return !this.class.value || !this.class.subclass;
|
return !this.class.value || !this.class.subclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get spellcastModifier() {
|
||||||
|
const subClasses = this.parent.items.filter(x => x.type === 'subclass') ?? [];
|
||||||
|
return Math.max(subClasses?.map(sc => this.traits[sc.system.spellcastingTrait]?.value));
|
||||||
|
}
|
||||||
|
|
||||||
get spellcastingModifiers() {
|
get spellcastingModifiers() {
|
||||||
return {
|
return {
|
||||||
main: this.class.subclass?.system?.spellcastingTrait,
|
main: this.class.subclass?.system?.spellcastingTrait,
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
|
||||||
import ActionField from '../fields/actionField.mjs';
|
import ActionField from '../fields/actionField.mjs';
|
||||||
import { adjustDice, adjustRange } from '../../helpers/utils.mjs';
|
import { adjustDice, adjustRange } from '../../helpers/utils.mjs';
|
||||||
import DHCompanionSettings from '../../applications/sheets-configs/companion-settings.mjs';
|
import DHCompanionSettings from '../../applications/sheets-configs/companion-settings.mjs';
|
||||||
|
import { resourceField, bonusField } from '../fields/actorField.mjs';
|
||||||
|
|
||||||
export default class DhCompanion extends BaseDataActor {
|
export default class DhCompanion extends BaseDataActor {
|
||||||
static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Companion'];
|
static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Companion'];
|
||||||
|
|
@ -23,11 +24,7 @@ export default class DhCompanion extends BaseDataActor {
|
||||||
...super.defineSchema(),
|
...super.defineSchema(),
|
||||||
partner: new ForeignDocumentUUIDField({ type: 'Actor' }),
|
partner: new ForeignDocumentUUIDField({ type: 'Actor' }),
|
||||||
resources: new fields.SchemaField({
|
resources: new fields.SchemaField({
|
||||||
stress: new fields.SchemaField({
|
stress: resourceField(3, true),
|
||||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
|
||||||
max: new fields.NumberField({ initial: 3, integer: true }),
|
|
||||||
isReversed: new foundry.data.fields.BooleanField({ initial: true })
|
|
||||||
}),
|
|
||||||
hope: new fields.NumberField({ initial: 0, integer: true })
|
hope: new fields.NumberField({ initial: 0, integer: true })
|
||||||
}),
|
}),
|
||||||
evasion: new fields.NumberField({ required: true, min: 1, initial: 10, integer: true }),
|
evasion: new fields.NumberField({ required: true, min: 1, initial: 10, integer: true }),
|
||||||
|
|
@ -56,7 +53,7 @@ export default class DhCompanion extends BaseDataActor {
|
||||||
amount: 1
|
amount: 1
|
||||||
},
|
},
|
||||||
roll: {
|
roll: {
|
||||||
type: 'weapon',
|
type: 'attack',
|
||||||
bonus: 0,
|
bonus: 0,
|
||||||
trait: 'instinct'
|
trait: 'instinct'
|
||||||
},
|
},
|
||||||
|
|
@ -74,7 +71,13 @@ export default class DhCompanion extends BaseDataActor {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
actions: new fields.ArrayField(new ActionField()),
|
actions: new fields.ArrayField(new ActionField()),
|
||||||
levelData: new fields.EmbeddedDataField(DhLevelData)
|
levelData: new fields.EmbeddedDataField(DhLevelData),
|
||||||
|
bonuses: new fields.SchemaField({
|
||||||
|
damage: new fields.SchemaField({
|
||||||
|
physical: bonusField(),
|
||||||
|
magical: bonusField()
|
||||||
|
})
|
||||||
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,7 +92,7 @@ export default class DhCompanion extends BaseDataActor {
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareBaseData() {
|
prepareBaseData() {
|
||||||
const partnerSpellcastingModifier = this.partner?.system?.spellcastingModifiers?.main;
|
const partnerSpellcastingModifier = this.partner?.system?.spellcastModifier;
|
||||||
const spellcastingModifier = this.partner?.system?.traits?.[partnerSpellcastingModifier]?.value;
|
const spellcastingModifier = this.partner?.system?.traits?.[partnerSpellcastingModifier]?.value;
|
||||||
this.attack.roll.bonus = spellcastingModifier ?? 0; // Needs to expand on which modifier it is that should be used because of multiclassing;
|
this.attack.roll.bonus = spellcastingModifier ?? 0; // Needs to expand on which modifier it is that should be used because of multiclassing;
|
||||||
|
|
||||||
|
|
|
||||||
28
module/data/fields/actorField.mjs
Normal file
28
module/data/fields/actorField.mjs
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
const fields = foundry.data.fields;
|
||||||
|
|
||||||
|
const attributeField = () =>
|
||||||
|
new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
tierMarked: new fields.BooleanField({ initial: false })
|
||||||
|
});
|
||||||
|
|
||||||
|
const resourceField = (max = 0, reverse = false) =>
|
||||||
|
new fields.SchemaField({
|
||||||
|
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
|
max: new fields.NumberField({ initial: max, integer: true }),
|
||||||
|
isReversed: new fields.BooleanField({ initial: reverse })
|
||||||
|
});
|
||||||
|
|
||||||
|
const stressDamageReductionRule = () =>
|
||||||
|
new fields.SchemaField({
|
||||||
|
enabled: new fields.BooleanField({ required: true, initial: false }),
|
||||||
|
cost: new fields.NumberField({ integer: true })
|
||||||
|
});
|
||||||
|
|
||||||
|
const bonusField = () =>
|
||||||
|
new fields.SchemaField({
|
||||||
|
bonus: new fields.NumberField({ integer: true, initial: 0 }),
|
||||||
|
dice: new fields.ArrayField(new fields.StringField())
|
||||||
|
})
|
||||||
|
|
||||||
|
export { attributeField, resourceField, stressDamageReductionRule, bonusField };
|
||||||
|
|
@ -50,7 +50,7 @@ export default class DHWeapon extends AttachableItem {
|
||||||
},
|
},
|
||||||
roll: {
|
roll: {
|
||||||
trait: 'agility',
|
trait: 'agility',
|
||||||
type: 'weapon'
|
type: 'attack'
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
parts: [
|
parts: [
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,6 @@ export default class D20Roll extends DHRoll {
|
||||||
}
|
}
|
||||||
|
|
||||||
constructFormula(config) {
|
constructFormula(config) {
|
||||||
// this.terms = [];
|
|
||||||
this.createBaseDice();
|
this.createBaseDice();
|
||||||
this.configureModifiers();
|
this.configureModifiers();
|
||||||
this.resetFormula();
|
this.resetFormula();
|
||||||
|
|
@ -91,7 +90,10 @@ export default class D20Roll extends DHRoll {
|
||||||
|
|
||||||
configureModifiers() {
|
configureModifiers() {
|
||||||
this.applyAdvantage();
|
this.applyAdvantage();
|
||||||
this.applyBaseBonus();
|
|
||||||
|
this.baseTerms = foundry.utils.deepClone(this.terms);
|
||||||
|
|
||||||
|
this.options.roll.modifiers = this.applyBaseBonus();
|
||||||
|
|
||||||
this.options.experiences?.forEach(m => {
|
this.options.experiences?.forEach(m => {
|
||||||
if (this.options.data.experiences?.[m])
|
if (this.options.data.experiences?.[m])
|
||||||
|
|
@ -100,13 +102,8 @@ export default class D20Roll extends DHRoll {
|
||||||
value: this.options.data.experiences[m].value
|
value: this.options.data.experiences[m].value
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.options.roll.modifiers?.forEach(m => {
|
this.addModifiers();
|
||||||
this.terms.push(...this.formatModifier(m.value));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.baseTerms = foundry.utils.deepClone(this.terms);
|
|
||||||
|
|
||||||
if (this.options.extraFormula) {
|
if (this.options.extraFormula) {
|
||||||
this.terms.push(
|
this.terms.push(
|
||||||
new foundry.dice.terms.OperatorTerm({ operator: '+' }),
|
new foundry.dice.terms.OperatorTerm({ operator: '+' }),
|
||||||
|
|
@ -125,13 +122,18 @@ export default class D20Roll extends DHRoll {
|
||||||
}
|
}
|
||||||
|
|
||||||
applyBaseBonus() {
|
applyBaseBonus() {
|
||||||
this.options.roll.modifiers = [];
|
const modifiers = [];
|
||||||
if (!this.options.roll.bonus) return;
|
|
||||||
this.options.roll.modifiers.push({
|
if(this.options.roll.bonus)
|
||||||
label: 'Bonus to Hit',
|
modifiers.push({
|
||||||
value: this.options.roll.bonus
|
label: 'Bonus to Hit',
|
||||||
// value: Roll.replaceFormulaData('@attackBonus', this.data)
|
value: this.options.roll.bonus
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modifiers.push(...this.getBonus(`roll.${this.options.type}`, `${this.options.type.capitalize()} Bonus`));
|
||||||
|
modifiers.push(...this.getBonus(`roll.${this.options.roll.type}`, `${this.options.roll.type.capitalize()} Bonus`));
|
||||||
|
|
||||||
|
return modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async buildEvaluate(roll, config = {}, message = {}) {
|
static async buildEvaluate(roll, config = {}, message = {}) {
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,26 @@ export default class DamageRoll extends DHRoll {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyBaseBonus() {
|
||||||
|
const modifiers = [],
|
||||||
|
type = this.options.messageType ?? 'damage';
|
||||||
|
|
||||||
|
modifiers.push(...this.getBonus(`${type}`, `${type.capitalize()} Bonus`));
|
||||||
|
this.options.damageTypes?.forEach(t => {
|
||||||
|
modifiers.push(...this.getBonus(`${type}.${t}`, `${t.capitalize()} ${type.capitalize()} Bonus`));
|
||||||
|
});
|
||||||
|
const weapons = ['primaryWeapon', 'secondaryWeapon'];
|
||||||
|
weapons.forEach(w => {
|
||||||
|
if(this.options.source.item && this.options.source.item === this.data[w]?.id)
|
||||||
|
modifiers.push(...this.getBonus(`${type}.${w}`, 'Weapon Bonus'));
|
||||||
|
});
|
||||||
|
|
||||||
|
return modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
constructFormula(config) {
|
constructFormula(config) {
|
||||||
super.constructFormula(config);
|
super.constructFormula(config);
|
||||||
|
|
||||||
if (config.isCritical) {
|
if (config.isCritical) {
|
||||||
const tmpRoll = new Roll(this._formula)._evaluateSync({ maximize: true }),
|
const tmpRoll = new Roll(this._formula)._evaluateSync({ maximize: true }),
|
||||||
criticalBonus = tmpRoll.total - this.constructor.calculateTotalModifiers(tmpRoll);
|
criticalBonus = tmpRoll.total - this.constructor.calculateTotalModifiers(tmpRoll);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ export default class DHRoll extends Roll {
|
||||||
baseTerms = [];
|
baseTerms = [];
|
||||||
constructor(formula, data, options) {
|
constructor(formula, data, options) {
|
||||||
super(formula, data, options);
|
super(formula, data, options);
|
||||||
|
if(!this.data || !Object.keys(this.data).length) this.data = options.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static messageType = 'adversaryRoll';
|
static messageType = 'adversaryRoll';
|
||||||
|
|
@ -99,11 +100,44 @@ export default class DHRoll extends Roll {
|
||||||
}
|
}
|
||||||
|
|
||||||
formatModifier(modifier) {
|
formatModifier(modifier) {
|
||||||
const numTerm = modifier < 0 ? '-' : '+';
|
if(Array.isArray(modifier)) {
|
||||||
return [
|
return [
|
||||||
new foundry.dice.terms.OperatorTerm({ operator: numTerm }),
|
new foundry.dice.terms.OperatorTerm({ operator: '+' }),
|
||||||
new foundry.dice.terms.NumericTerm({ number: Math.abs(modifier) })
|
...this.constructor.parse(modifier.join(' + '), this.options.data)
|
||||||
];
|
];
|
||||||
|
} else {
|
||||||
|
const numTerm = modifier < 0 ? '-' : '+';
|
||||||
|
return [
|
||||||
|
new foundry.dice.terms.OperatorTerm({ operator: numTerm }),
|
||||||
|
new foundry.dice.terms.NumericTerm({ number: Math.abs(modifier) })
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
applyBaseBonus() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
addModifiers() {
|
||||||
|
this.options.roll.modifiers?.forEach(m => {
|
||||||
|
this.terms.push(...this.formatModifier(m.value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getBonus(path, label) {
|
||||||
|
const bonus = foundry.utils.getProperty(this.data.bonuses, path),
|
||||||
|
modifiers = [];
|
||||||
|
if(bonus?.bonus)
|
||||||
|
modifiers.push({
|
||||||
|
label: label,
|
||||||
|
value: bonus?.bonus
|
||||||
|
});
|
||||||
|
if(bonus?.dice?.length)
|
||||||
|
modifiers.push({
|
||||||
|
label: label,
|
||||||
|
value: bonus?.dice
|
||||||
|
});
|
||||||
|
return modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFaces(faces) {
|
getFaces(faces) {
|
||||||
|
|
@ -113,6 +147,9 @@ export default class DHRoll extends Roll {
|
||||||
constructFormula(config) {
|
constructFormula(config) {
|
||||||
this.terms = Roll.parse(this.options.roll.formula, config.data);
|
this.terms = Roll.parse(this.options.roll.formula, config.data);
|
||||||
|
|
||||||
|
this.options.roll.modifiers = this.applyBaseBonus();
|
||||||
|
this.addModifiers();
|
||||||
|
|
||||||
if (this.options.extraFormula) {
|
if (this.options.extraFormula) {
|
||||||
this.terms.push(
|
this.terms.push(
|
||||||
new foundry.dice.terms.OperatorTerm({ operator: '+' }),
|
new foundry.dice.terms.OperatorTerm({ operator: '+' }),
|
||||||
|
|
|
||||||
|
|
@ -119,12 +119,21 @@ export default class DualityRoll extends D20Roll {
|
||||||
}
|
}
|
||||||
|
|
||||||
applyBaseBonus() {
|
applyBaseBonus() {
|
||||||
this.options.roll.modifiers = [];
|
const modifiers = super.applyBaseBonus();
|
||||||
if (!this.options.roll.trait) return;
|
|
||||||
this.options.roll.modifiers.push({
|
if(this.options.roll.trait && this.data.traits[this.options.roll.trait])
|
||||||
label: `DAGGERHEART.CONFIG.Traits.${this.options.roll.trait}.name`,
|
modifiers.unshift({
|
||||||
value: Roll.replaceFormulaData(`@traits.${this.options.roll.trait}.value`, this.data)
|
label: `DAGGERHEART.CONFIG.Traits.${this.options.roll.trait}.name`,
|
||||||
|
value: this.data.traits[this.options.roll.trait].value
|
||||||
|
});
|
||||||
|
|
||||||
|
const weapons = ['primaryWeapon', 'secondaryWeapon'];
|
||||||
|
weapons.forEach(w => {
|
||||||
|
if(this.options.source.item && this.options.source.item === this.data[w]?.id)
|
||||||
|
modifiers.push(...this.getBonus(`roll.${w}`, 'Weapon Bonus'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static postEvaluate(roll, config = {}) {
|
static postEvaluate(roll, config = {}) {
|
||||||
|
|
|
||||||
|
|
@ -371,7 +371,7 @@ export default class DhpActor extends Actor {
|
||||||
getRollData() {
|
getRollData() {
|
||||||
const rollData = super.getRollData();
|
const rollData = super.getRollData();
|
||||||
rollData.prof = this.system.proficiency ?? 1;
|
rollData.prof = this.system.proficiency ?? 1;
|
||||||
rollData.cast = this.system.spellcast ?? 1;
|
rollData.cast = this.system.spellcastModifier ?? 1;
|
||||||
return rollData;
|
return rollData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,9 @@ export default class RegisterHandlebarsHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
static damageSymbols(damageParts) {
|
static damageSymbols(damageParts) {
|
||||||
const symbols = new Set();
|
const symbols = [...new Set(damageParts.reduce((a, c) => a.concat([...c.type]), []))].map(
|
||||||
damageParts.forEach(part => symbols.add(...CONFIG.DH.GENERAL.damageTypes[part.type].icon));
|
p => CONFIG.DH.GENERAL.damageTypes[p].icon
|
||||||
|
);
|
||||||
return new Handlebars.SafeString(Array.from(symbols).map(symbol => `<i class="fa-solid ${symbol}"></i>`));
|
return new Handlebars.SafeString(Array.from(symbols).map(symbol => `<i class="fa-solid ${symbol}"></i>`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,7 @@ export const itemAbleRollParse = (value, actor, item) => {
|
||||||
const isItemTarget = value.toLowerCase().startsWith('item.');
|
const isItemTarget = value.toLowerCase().startsWith('item.');
|
||||||
const slicedValue = isItemTarget ? value.slice(5) : value;
|
const slicedValue = isItemTarget ? value.slice(5) : value;
|
||||||
try {
|
try {
|
||||||
return Roll.safeEval(Roll.replaceFormulaData(slicedValue, isItemTarget ? item : actor));
|
return Roll.replaceFormulaData(slicedValue, isItemTarget ? item : actor);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,12 +44,14 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
|
flex-wrap: wrap;
|
||||||
.duality-modifier {
|
.duality-modifier {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
background: var(--color-dark-6);
|
background: var(--color-dark-6);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dice-flavor {
|
.dice-flavor {
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
<ul class="actions-list">
|
<ul class="actions-list">
|
||||||
{{#each actions}}
|
{{#each actions}}
|
||||||
<li class="action-item">
|
<li class="action-item">
|
||||||
<input type="radio" name="actionId" value="{{_id}}" {{#if (eq @index 0)}}checked{{/if}}>
|
<input type="radio" id="action-{{_id}}" name="actionId" value="{{_id}}" {{#if (eq @index 0)}}checked{{/if}}>
|
||||||
<span class="label">{{ name }}</span>
|
<label class="label" for="action-{{_id}}">{{ name }}</label>
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue