mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
Add Save
This commit is contained in:
parent
8423ab6776
commit
ddbb6c4fd8
34 changed files with 609 additions and 378 deletions
|
|
@ -316,9 +316,12 @@ const preloadHandlebarsTemplates = async function () {
|
|||
'systems/daggerheart/templates/views/actionTypes/uuid.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/uses.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/roll.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/save.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/cost.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/range-target.hbs',
|
||||
'systems/daggerheart/templates/views/actionTypes/effect.hbs',
|
||||
'systems/daggerheart/templates/settings/components/settings-item-line.hbs'
|
||||
'systems/daggerheart/templates/settings/components/settings-item-line.hbs',
|
||||
|
||||
'systems/daggerheart/templates/chat/parts/target-chat.hbs'
|
||||
]);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,18 +1,13 @@
|
|||
import { DualityRollColor } from '../data/settings/Appearance.mjs';
|
||||
import DHDualityRoll from '../data/chat-message/dualityRoll.mjs';
|
||||
|
||||
export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
||||
async renderHTML() {
|
||||
if (this.type === 'dualityRoll' || this.type === 'adversaryRoll') {
|
||||
this.content = await foundry.applications.handlebars.renderTemplate(this.content, this.system);
|
||||
}
|
||||
if(this.system.messageTemplate) this.content = await foundry.applications.handlebars.renderTemplate(this.system.messageTemplate, this.system);
|
||||
|
||||
/* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */
|
||||
const html = await super.renderHTML();
|
||||
this.applyPermission(html);
|
||||
|
||||
if (this.type === 'dualityRoll') {
|
||||
html.classList.add('duality');
|
||||
/* const dualityResult = this.system.dualityResult; */
|
||||
switch (this.system.roll.result.duality) {
|
||||
case 1:
|
||||
html.classList.add('hope');
|
||||
|
|
@ -24,11 +19,18 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
|||
html.classList.add('critical');
|
||||
break;
|
||||
}
|
||||
/* if (dualityResult === DHDualityRoll.dualityResult.hope) html.classList.add('hope');
|
||||
else if (dualityResult === DHDualityRoll.dualityResult.fear) html.classList.add('fear');
|
||||
else html.classList.add('critical'); */
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
applyPermission(html) {
|
||||
const elements = html.querySelectorAll('[data-perm-id]');
|
||||
elements.forEach(e => {
|
||||
const uuid = e.dataset.permId,
|
||||
document = fromUuidSync(uuid);
|
||||
e.setAttribute('data-view-perm', document.testUserPermission(game.user, 'OBSERVER'));
|
||||
e.setAttribute('data-use-perm', document.testUserPermission(game.user, 'OWNER'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,9 +65,10 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
if (this.action.damage?.hasOwnProperty('includeBase') && this.action.type === 'attack')
|
||||
context.hasBaseDamage = !!this.action.parent.damage;
|
||||
context.getRealIndex = this.getRealIndex.bind(this);
|
||||
context.getEffectDetails = this.getEffectDetails.bind(this);
|
||||
context.disableOption = this.disableOption.bind(this);
|
||||
context.isNPC = this.action.actor && this.action.actor.type !== 'character';
|
||||
context.hasRoll = this.action.hasRoll();
|
||||
context.hasRoll = this.action.hasRoll;
|
||||
console.log(context)
|
||||
return context;
|
||||
}
|
||||
|
|
@ -90,24 +91,16 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
return data.damage.parts.find(d => d.base) ? index - 1 : index;
|
||||
}
|
||||
|
||||
getEffectDetails(id) {
|
||||
return this.action.item.effects.get(id);
|
||||
}
|
||||
|
||||
_prepareSubmitData(event, formData) {
|
||||
const submitData = foundry.utils.expandObject(formData.object);
|
||||
for ( const keyPath of this.constructor.CLEAN_ARRAYS ) {
|
||||
const data = foundry.utils.getProperty(submitData, keyPath);
|
||||
if ( data ) foundry.utils.setProperty(submitData, keyPath, Object.values(data));
|
||||
/* const data = foundry.utils.getProperty(submitData, keyPath),
|
||||
originalData = foundry.utils.getProperty(this.action.toObject(), keyPath);
|
||||
if ( data ) {
|
||||
const aData = Object.values(data);
|
||||
originalData.forEach((v,i) => {
|
||||
aData[i] = {...originalData[i], ...aData[i]};
|
||||
})
|
||||
foundry.utils.setProperty(submitData, keyPath, aData);
|
||||
} */
|
||||
}
|
||||
// this.element.querySelectorAll("fieldset[disabled] :is(input, select)").forEach(input => {
|
||||
// foundry.utils.setProperty(submitData, input.name, input.value);
|
||||
// });
|
||||
return submitData;
|
||||
}
|
||||
|
||||
|
|
@ -138,6 +131,7 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
}
|
||||
|
||||
static removeElement(event) {
|
||||
event.stopPropagation();
|
||||
const data = this.action.toObject(),
|
||||
key = event.target.closest('.action-category-data').dataset.key,
|
||||
index = event.target.dataset.index;
|
||||
|
|
@ -192,5 +186,8 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
this.action.item.deleteEmbeddedDocuments('ActiveEffect', [effectId]);
|
||||
}
|
||||
|
||||
static editEffect(event) {}
|
||||
static editEffect(event) {
|
||||
const id = event.target.closest('[data-effect-id]')?.dataset?.effectId;
|
||||
this.action.item.effects.get(id).sheet.render(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export class DHRoll extends Roll {
|
|||
if (!roll) return;
|
||||
await this.buildEvaluate(roll, config, (message = {}));
|
||||
await this.buildPost(roll, config, (message = {}));
|
||||
return roll;
|
||||
return config;
|
||||
}
|
||||
|
||||
static async buildConfigure(config = {}, message = {}) {
|
||||
|
|
@ -58,7 +58,7 @@ export class DHRoll extends Roll {
|
|||
if (message.data) {
|
||||
} else {
|
||||
const messageData = {};
|
||||
await this.toMessage(roll, config);
|
||||
config.message = await this.toMessage(roll, config);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,10 +71,9 @@ export class DHRoll extends Roll {
|
|||
user: game.user.id,
|
||||
sound: config.mute ? null : CONFIG.sounds.dice,
|
||||
system: config,
|
||||
content: await this.messageTemplate(config),
|
||||
rolls: [roll]
|
||||
};
|
||||
await cls.create(msg);
|
||||
return await cls.create(msg);
|
||||
}
|
||||
|
||||
static applyKeybindings(config) {
|
||||
|
|
@ -110,12 +109,6 @@ export class D20Roll extends DHRoll {
|
|||
|
||||
static messageType = 'adversaryRoll';
|
||||
|
||||
// static messageTemplate = 'systems/daggerheart/templates/chat/adversary-roll.hbs';
|
||||
|
||||
static messageTemplate = async config => {
|
||||
return 'systems/daggerheart/templates/chat/adversary-roll.hbs';
|
||||
};
|
||||
|
||||
static CRITICAL_TRESHOLD = 20;
|
||||
|
||||
static DefaultDialog = D20RollDialog;
|
||||
|
|
@ -214,9 +207,9 @@ export class D20Roll extends DHRoll {
|
|||
if (config.targets?.length) {
|
||||
config.targets.forEach(target => {
|
||||
const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion;
|
||||
target.hit = roll.total >= difficulty;
|
||||
target.hit = this.isCritical || roll.total >= difficulty;
|
||||
});
|
||||
} else if (config.roll.difficulty) roll.success = roll.total >= config.roll.difficulty;
|
||||
} else if (config.roll.difficulty) config.roll.success = roll.isCritical || roll.total >= config.roll.difficulty;
|
||||
config.roll.total = roll.total;
|
||||
config.roll.formula = roll.formula;
|
||||
config.roll.advantage = {
|
||||
|
|
@ -260,12 +253,6 @@ export class DualityRoll extends D20Roll {
|
|||
|
||||
static messageType = 'dualityRoll';
|
||||
|
||||
// static messageTemplate = 'systems/daggerheart/templates/chat/duality-roll.hbs';
|
||||
|
||||
static messageTemplate = async config => {
|
||||
return 'systems/daggerheart/templates/chat/duality-roll.hbs';
|
||||
};
|
||||
|
||||
static DefaultDialog = D20RollDialog;
|
||||
|
||||
get dHope() {
|
||||
|
|
@ -395,21 +382,22 @@ export class DamageRoll extends DHRoll {
|
|||
|
||||
static messageType = 'damageRoll';
|
||||
|
||||
// static messageTemplate = 'systems/daggerheart/templates/chat/damage-roll.hbs';
|
||||
static messageTemplate = async config => {
|
||||
return await foundry.applications.handlebars.renderTemplate(
|
||||
config.messageTemplate ?? 'systems/daggerheart/templates/chat/damage-roll.hbs',
|
||||
config
|
||||
);
|
||||
};
|
||||
|
||||
static DefaultDialog = DamageDialog;
|
||||
|
||||
static async postEvaluate(roll, config = {}) {
|
||||
config.roll = {
|
||||
result: roll.total,
|
||||
dice: roll.dice,
|
||||
total: roll.total,
|
||||
formula: roll.formula,
|
||||
type: config.type
|
||||
};
|
||||
config.roll.dice = [];
|
||||
roll.dice.forEach(d => {
|
||||
config.roll.dice.push({
|
||||
dice: d.denomination,
|
||||
total: d.total,
|
||||
formula: d.formula,
|
||||
results: d.results
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
context.document = this.document;
|
||||
context.tabs = super._getTabs(this.constructor.TABS);
|
||||
context.systemFields.attack.fields = this.document.system.attack.schema.fields;
|
||||
context.getEffectDetails = this.getEffectDetails.bind(this);
|
||||
context.isNPC = true;
|
||||
console.log(context)
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
@ -80,6 +82,10 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
this.actor.diceRoll(config);
|
||||
}
|
||||
|
||||
getEffectDetails(id) {
|
||||
return {};
|
||||
}
|
||||
|
||||
static async attackRoll(event) {
|
||||
this.actor.system.attack.use(event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import AncestrySelectionDialog from '../ancestrySelectionDialog.mjs';
|
|||
import DaggerheartSheet from './daggerheart-sheet.mjs';
|
||||
import { abilities } from '../../config/actorConfig.mjs';
|
||||
import DhlevelUp from '../levelup.mjs';
|
||||
import DHDualityRoll from '../../data/chat-message/dualityRoll.mjs';
|
||||
|
||||
const { ActorSheetV2 } = foundry.applications.sheets;
|
||||
const { TextEditor } = foundry.applications.ux;
|
||||
|
|
@ -370,47 +369,9 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
title: game.i18n.format('DAGGERHEART.Chat.DualityRoll.AbilityCheckTitle', { ability: abilityLabel }),
|
||||
roll: {
|
||||
trait: button.dataset.attribute
|
||||
/* label: abilityLabel,
|
||||
modifier: button.dataset.value */
|
||||
}
|
||||
/* chatMessage: {
|
||||
template: 'systems/daggerheart/templates/chat/duality-roll.hbs'
|
||||
} */
|
||||
};
|
||||
this.document.diceRoll(config);
|
||||
|
||||
// Delete when new roll logic test done
|
||||
/* const { roll, hope, fear, advantage, disadvantage, modifiers } = await this.document.dualityRoll(
|
||||
{ title: game.i18n.localize(abilities[button.dataset.attribute].label), value: button.dataset.value },
|
||||
event.shiftKey
|
||||
);
|
||||
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
|
||||
const systemContent = new DHDualityRoll({
|
||||
title: game.i18n.format('DAGGERHEART.Chat.DualityRoll.AbilityCheckTitle', {
|
||||
ability: game.i18n.localize(abilities[button.dataset.attribute].label)
|
||||
}),
|
||||
origin: this.document.id,
|
||||
roll: roll._formula,
|
||||
modifiers: modifiers,
|
||||
hope: hope,
|
||||
fear: fear,
|
||||
advantage: advantage,
|
||||
disadvantage: disadvantage
|
||||
});
|
||||
|
||||
await cls.create({
|
||||
type: 'dualityRoll',
|
||||
sound: CONFIG.sounds.dice,
|
||||
system: systemContent,
|
||||
user: game.user.id,
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/chat/duality-roll.hbs',
|
||||
systemContent
|
||||
),
|
||||
rolls: [roll]
|
||||
}); */
|
||||
}
|
||||
|
||||
static async toggleMarks(_, button) {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ export default class DhpEnvironment extends DaggerheartSheet(ActorSheetV2) {
|
|||
const context = await super._prepareContext(_options);
|
||||
context.document = this.document;
|
||||
context.tabs = super._getTabs(this.constructor.TABS);
|
||||
context.getEffectDetails = this.getEffectDetails.bind(this);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
|
@ -62,6 +63,10 @@ export default class DhpEnvironment extends DaggerheartSheet(ActorSheetV2) {
|
|||
this.render();
|
||||
}
|
||||
|
||||
getEffectDetails(id) {
|
||||
return {};
|
||||
}
|
||||
|
||||
static async addAdversary() {
|
||||
await this.document.update({
|
||||
[`system.potentialAdversaries.${foundry.utils.randomID()}.label`]: game.i18n.localize(
|
||||
|
|
|
|||
|
|
@ -111,16 +111,18 @@ export default function DHItemMixin(Base) {
|
|||
}
|
||||
}
|
||||
|
||||
static async editAction(_, button) {
|
||||
const action = this.document.system.actions[button.dataset.index];
|
||||
static async editAction(event, button) {
|
||||
const index = event.target.closest('[data-index]').dataset.index,
|
||||
action = this.document.system.actions[index];
|
||||
await new DHActionConfig(action).render(true);
|
||||
}
|
||||
|
||||
static async removeAction(event, button) {
|
||||
event.stopPropagation();
|
||||
const action = event.target.closest('[data-index]').dataset.index;
|
||||
await this.document.update({
|
||||
'system.actions': this.document.system.actions.filter(
|
||||
(_, index) => index !== Number.parseInt(button.dataset.index)
|
||||
(_, index) => index !== Number.parseInt(action)
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,3 +59,21 @@ export const targetTypes = {
|
|||
label: 'Any'
|
||||
}
|
||||
};
|
||||
|
||||
export const damageOnSave = {
|
||||
none: {
|
||||
id: 'none',
|
||||
label: 'None',
|
||||
mod: 0
|
||||
},
|
||||
half: {
|
||||
id: 'half',
|
||||
label: 'Half Damage',
|
||||
mod: 0.5
|
||||
},
|
||||
full: {
|
||||
id: 'full',
|
||||
label: 'Full damage',
|
||||
mod: 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,52 +1,24 @@
|
|||
import DamageSelectionDialog from '../../applications/damageSelectionDialog.mjs';
|
||||
import CostSelectionDialog from '../../applications/costSelectionDialog.mjs';
|
||||
import { abilities } from '../../config/actorConfig.mjs';
|
||||
import { DHActionDiceData, DHDamageData, DHDamageField } from './actionDice.mjs';
|
||||
import DhpActor from '../../documents/actor.mjs';
|
||||
import D20RollDialog from '../../dialogs/d20RollDialog.mjs';
|
||||
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
/*
|
||||
!!! I'm currently refactoring the whole Action thing, it's a WIP !!!
|
||||
*/
|
||||
|
||||
/*
|
||||
ToDo
|
||||
- Add setting for Hope/Fear result on Damage, Heal, Resource (Handle Roll result as part of formula if needed)
|
||||
- Add setting and/or checkbox for cost and damage like
|
||||
- Target Check / Target Picker
|
||||
- Range Check
|
||||
- Area of effect and measurement placement
|
||||
- Summon Action create method
|
||||
|
||||
- Create classes form Target, Cost, etc ?
|
||||
|
||||
Other
|
||||
- Add optionnal Role for Healing ?
|
||||
- Auto use action <= Into Roll
|
||||
|
||||
Done
|
||||
- Cost Check
|
||||
- Auto use costs
|
||||
- Auto disable selected Cost from other cost list
|
||||
- Apply ActiveEffect => Add to Chat message like Damage Button ?
|
||||
- Add Drag & Drop for documentUUID field (Macro & Summon)
|
||||
|
||||
Activity Types List
|
||||
- Attack => Weapon Attack, Spell Attack, etc...
|
||||
- Effects => Like Attack without damage
|
||||
- Damage => Like Attack without roll
|
||||
- Healing
|
||||
- Resource => Merge Healing & Resource ?
|
||||
- Summon
|
||||
- Sequencer => Trigger a list of Activities set on the item one by one
|
||||
- Macro
|
||||
|
||||
Actor Modifier
|
||||
- Weapon Attack
|
||||
- Spell Attack
|
||||
- Weapon Damage
|
||||
- Magical Damage
|
||||
- Physical Damage ?
|
||||
- Magical Damage ?
|
||||
- Healing
|
||||
- Bard Rally (Math.ceil(LeveL / 5))
|
||||
*/
|
||||
|
||||
export class DHBaseAction extends foundry.abstract.DataModel {
|
||||
|
|
@ -105,7 +77,8 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
}),
|
||||
save: new fields.SchemaField({
|
||||
trait: new fields.StringField({ nullable: true, initial: null, choices: SYSTEM.ACTOR.abilities }),
|
||||
difficulty: new fields.NumberField({ nullable: true, initial: null, integer: true, min: 0 })
|
||||
difficulty: new fields.NumberField({ nullable: true, initial: 10, integer: true, min: 0 }),
|
||||
damageMod: new fields.StringField({ initial: SYSTEM.ACTIONS.damageOnSave.none.id, choices: SYSTEM.ACTIONS.damageOnSave })
|
||||
}),
|
||||
target: new fields.SchemaField({
|
||||
type: new fields.StringField({
|
||||
|
|
@ -118,7 +91,8 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
}),
|
||||
effects: new fields.ArrayField( // ActiveEffect
|
||||
new fields.SchemaField({
|
||||
_id: new fields.DocumentIdField()
|
||||
_id: new fields.DocumentIdField(),
|
||||
onSave: new fields.BooleanField({ initial: false })
|
||||
})
|
||||
),
|
||||
healing: new fields.SchemaField({
|
||||
|
|
@ -186,22 +160,122 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
|
||||
getRollData() {
|
||||
const actorData = this.actor.getRollData(false);
|
||||
return {
|
||||
...actorData.toObject(),
|
||||
prof: actorData.proficiency?.value ?? 1,
|
||||
cast: actorData.spellcast?.value ?? 1,
|
||||
scale: this.cost.length
|
||||
|
||||
// Remove when included directly in Actor getRollData
|
||||
actorData.prof = actorData.proficiency?.value ?? 1,
|
||||
actorData.cast = actorData.spellcast?.value ?? 1,
|
||||
actorData.scale = this.cost.length
|
||||
? this.cost.reduce((a, c) => {
|
||||
a[c.type] = c.value;
|
||||
return a;
|
||||
}, {})
|
||||
: 1,
|
||||
roll: {}
|
||||
};
|
||||
actorData.roll = {}
|
||||
|
||||
return actorData;
|
||||
}
|
||||
|
||||
async use(event, ...args) {
|
||||
const isFastForward = event.shiftKey || (!this.hasRoll && !this.hasSave);
|
||||
// Prepare base Config
|
||||
const initConfig = this.initActionConfig(event);
|
||||
// let config = this.initActionConfig(event);
|
||||
|
||||
// Prepare Targets
|
||||
const targetConfig = this.prepareTarget();
|
||||
if (isFastForward && !targetConfig) return ui.notifications.warn('Too many targets selected for that actions.');
|
||||
// config = this.prepareTarget(config);
|
||||
|
||||
// Prepare Range
|
||||
const rangeConfig = this.prepareRange();
|
||||
// config = this.prepareRange(config);
|
||||
|
||||
// Prepare Costs
|
||||
const costsConfig = this.prepareCost();
|
||||
if(isFastForward && !this.hasCost(costsConfig)) return ui.notifications.warn("You don't have the resources to use that action.");
|
||||
// config = this.prepareUseCost(config)
|
||||
|
||||
// Prepare Uses
|
||||
const usesConfig = this.prepareUse();
|
||||
if(isFastForward && !this.hasUses(usesConfig)) return ui.notifications.warn("That action doesn't have remaining uses.");
|
||||
// config = this.prepareUseCost(config)
|
||||
|
||||
// Prepare Roll Data
|
||||
const actorData = this.getRollData();
|
||||
|
||||
let config = {
|
||||
...initConfig,
|
||||
targets: targetConfig,
|
||||
range: rangeConfig,
|
||||
costs: costsConfig,
|
||||
uses: usesConfig,
|
||||
data: actorData
|
||||
}
|
||||
|
||||
if ( Hooks.call(`${SYSTEM.id}.preUseAction`, this, config) === false ) return;
|
||||
|
||||
// Display configuration window if necessary
|
||||
if ( config.dialog.configure && this.requireConfigurationDialog(config) ) {
|
||||
config = await D20RollDialog.configure(config);
|
||||
if (!config) return;
|
||||
}
|
||||
|
||||
if ( this.hasRoll ) {
|
||||
const rollConfig = this.prepareRoll(config);
|
||||
config.roll = rollConfig;
|
||||
config = await this.actor.diceRoll(config);
|
||||
if (!config) return;
|
||||
}
|
||||
|
||||
if( this.hasSave ) {
|
||||
/* config.targets.forEach((t) => {
|
||||
if(t.hit) {
|
||||
const target = game.canvas.tokens.get(t.id),
|
||||
actor = target?.actor;
|
||||
console.log(actor)
|
||||
if(!actor) return;
|
||||
actor.saveRoll({
|
||||
event,
|
||||
title: 'Roll Save',
|
||||
roll: {
|
||||
trait: this.save.trait,
|
||||
difficulty: this.save.difficulty
|
||||
},
|
||||
dialog: {
|
||||
configure: false
|
||||
},
|
||||
data: actor.getRollData()
|
||||
}).then(async (result) => {
|
||||
t.saved = result;
|
||||
setTimeout(async () => {
|
||||
const message = ui.chat.collection.get(config.message.id),
|
||||
msgTargets = message.system.targets,
|
||||
msgTarget = msgTargets.find(mt => mt.id === t.id);
|
||||
msgTarget.saved = result;
|
||||
await message.update({'system.targets': msgTargets});
|
||||
},100)
|
||||
})
|
||||
}
|
||||
}) */
|
||||
}
|
||||
|
||||
if ( this.doFollowUp() ) {
|
||||
if(this.rollDamage) await this.rollDamage(event, config);
|
||||
if(this.rollHealing) await this.rollHealing(event, config);
|
||||
if(this.trigger) await this.trigger(event, config);
|
||||
}
|
||||
|
||||
// Consume resources
|
||||
await this.consume(config);
|
||||
|
||||
if ( Hooks.call(`${SYSTEM.id}.postUseAction`, this, config) === false ) return;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/* */
|
||||
initActionConfig(event) {
|
||||
return {
|
||||
event,
|
||||
title: this.item.name,
|
||||
source: {
|
||||
|
|
@ -209,79 +283,93 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
action: this._id
|
||||
// action: this
|
||||
},
|
||||
dialog: {
|
||||
configure: true
|
||||
},
|
||||
type: this.type,
|
||||
hasDamage: !!this.damage?.parts?.length,
|
||||
hasHealing: !!this.healing,
|
||||
hasEffect: !!this.effects?.length
|
||||
};
|
||||
|
||||
// this.proceedChatDisplay(config);
|
||||
|
||||
// Filter selected targets based on Target parameters
|
||||
config.targets = await this.getTarget(config);
|
||||
if (!config.targets) return ui.notifications.warn('Too many targets selected for that actions.');
|
||||
|
||||
// Filter selected targets based on Range parameters
|
||||
config.range = await this.checkRange(config);
|
||||
if (!config.range.hasRange) return ui.notifications.warn('No Target within range.');
|
||||
|
||||
// Display Uses/Costs Dialog & Check if Actor get enough resources
|
||||
config = {
|
||||
...config,
|
||||
...(await this.getCost(config))
|
||||
};
|
||||
|
||||
if ((!this.hasRoll() || config.event.shiftKey) && (!this.hasCost(config.costs) || !this.hasUses(config.uses)))
|
||||
return ui.notifications.warn("You don't have the resources to use that action.");
|
||||
|
||||
// Proceed with Roll
|
||||
config = await this.proceedRoll(config);
|
||||
if (this.roll && !config.roll.result) return;
|
||||
|
||||
// Update Actor resources based on Action Cost configuration
|
||||
this.spendCost(config.costs.values);
|
||||
this.spendUses(config.uses);
|
||||
|
||||
return config;
|
||||
hasEffect: !!this.effects?.length,
|
||||
hasSave: this.hasSave
|
||||
}
|
||||
}
|
||||
|
||||
requireConfigurationDialog(config) {
|
||||
return !config.event.shiftkey && !this.hasRoll && (config.costs?.length || config.uses);
|
||||
}
|
||||
|
||||
prepareCost() {
|
||||
const costs = this.cost?.length ? foundry.utils.deepClone(this.cost) : [];
|
||||
return costs;
|
||||
}
|
||||
|
||||
prepareUse() {
|
||||
const uses = this.uses?.max ? foundry.utils.deepClone(this.uses) : null;
|
||||
if (uses && !uses.value) uses.value = 0;
|
||||
return uses;
|
||||
}
|
||||
|
||||
prepareTarget() {
|
||||
let targets;
|
||||
if (this.target?.type === SYSTEM.ACTIONS.targetTypes.self.id)
|
||||
targets = this.formatTarget(this.actor.token ?? this.actor.prototypeToken);
|
||||
targets = Array.from(game.user.targets);
|
||||
// foundry.CONST.TOKEN_DISPOSITIONS.FRIENDLY
|
||||
if (this.target?.type && this.target.type !== SYSTEM.ACTIONS.targetTypes.any.id) {
|
||||
targets = targets.filter(t => this.isTargetFriendly(t));
|
||||
if (this.target.amount && targets.length > this.target.amount) targets = [];
|
||||
}
|
||||
targets = targets.map(t => this.formatTarget(t));
|
||||
return targets;
|
||||
|
||||
}
|
||||
|
||||
prepareRange() {
|
||||
const range = this.range ?? null;
|
||||
return range;
|
||||
}
|
||||
|
||||
prepareRoll() {
|
||||
const roll = {
|
||||
modifiers: [],
|
||||
trait: this.roll?.trait,
|
||||
label: 'Attack',
|
||||
type: this.actionType,
|
||||
difficulty: this.roll?.difficulty
|
||||
};
|
||||
return roll;
|
||||
}
|
||||
|
||||
doFollowUp(config) {
|
||||
return !this.hasRoll;
|
||||
}
|
||||
|
||||
async consume(config) {
|
||||
const resources = config.costs.filter(c => c.enabled !== false).map(c => {
|
||||
return { type: c.type, value: c.total * -1 };
|
||||
});
|
||||
await this.actor.modifyResource(resources);
|
||||
if(config.uses?.enabled) {
|
||||
const newActions = foundry.utils.getProperty(this.item.system, this.systemPath).map(x => x.toObject());
|
||||
newActions[this.index].uses.value++;
|
||||
await this.item.update({ [`system.${this.systemPath}`]: newActions });
|
||||
}
|
||||
}
|
||||
/* */
|
||||
|
||||
/* ROLL */
|
||||
hasRoll() {
|
||||
// return this.roll?.type && this.roll?.trait;
|
||||
get hasRoll() {
|
||||
return !!this.roll?.type;
|
||||
}
|
||||
|
||||
async proceedRoll(config) {
|
||||
if (!this.hasRoll()) return config;
|
||||
// const modifierValue = this.actor.system.traits[this.roll.trait].value;
|
||||
config = {
|
||||
...config,
|
||||
roll: {
|
||||
modifiers: [],
|
||||
trait: this.roll?.trait,
|
||||
// label: game.i18n.localize(abilities[this.roll.trait].label),
|
||||
label: 'Attack',
|
||||
type: this.actionType,
|
||||
difficulty: this.roll?.difficulty
|
||||
}
|
||||
};
|
||||
// config = await this.actor.diceRoll(config, this);
|
||||
return this.actor.diceRoll(config, this);
|
||||
}
|
||||
/* ROLL */
|
||||
|
||||
/* COST */
|
||||
async getCost(config) {
|
||||
let costs = this.cost?.length ? foundry.utils.deepClone(this.cost) : [];
|
||||
let uses = this.getUses();
|
||||
if (!config.event.shiftKey && !this.hasRoll() && !(!costs.length && !uses)) {
|
||||
const dialogClosed = new Promise((resolve, _) => {
|
||||
new CostSelectionDialog(costs, uses, this, resolve).render(true);
|
||||
});
|
||||
({ costs, uses } = await dialogClosed);
|
||||
}
|
||||
return { costs, uses };
|
||||
/* SAVE */
|
||||
get hasSave() {
|
||||
return !!this.save?.trait;
|
||||
}
|
||||
/* SAVE */
|
||||
|
||||
/* COST */
|
||||
|
||||
getRealCosts(costs) {
|
||||
const realCosts = costs?.length ? costs.filter(c => c.enabled) : [];
|
||||
|
|
@ -302,28 +390,9 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
const realCosts = this.getRealCosts(costs);
|
||||
return realCosts.reduce((a, c) => a && this.actor.system.resources[c.type]?.value >= (c.total ?? c.value), true);
|
||||
}
|
||||
|
||||
async spendCost(config) {
|
||||
if (!config.costs?.values?.length) return;
|
||||
return await this.actor.modifyResource(config.costs.values);
|
||||
}
|
||||
/* COST */
|
||||
|
||||
/* USES */
|
||||
async spendUses(config) {
|
||||
if (!this.uses.max || config.enabled === false) return;
|
||||
const newActions = foundry.utils.getProperty(this.item.system, this.systemPath).map(x => x.toObject());
|
||||
newActions[this.index].uses.value++;
|
||||
await this.item.update({ [`system.${this.systemPath}`]: newActions });
|
||||
}
|
||||
|
||||
getUses() {
|
||||
if (!this.uses?.max) return null;
|
||||
const uses = foundry.utils.deepClone(this.uses);
|
||||
if (!uses.value) uses.value = 0;
|
||||
return uses;
|
||||
}
|
||||
|
||||
calcUses(uses) {
|
||||
if(!uses) return null;
|
||||
return {
|
||||
|
|
@ -339,18 +408,6 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
/* USES */
|
||||
|
||||
/* TARGET */
|
||||
async getTarget(config) {
|
||||
if (this.target?.type === SYSTEM.ACTIONS.targetTypes.self.id)
|
||||
return this.formatTarget(this.actor.token ?? this.actor.prototypeToken);
|
||||
let targets = Array.from(game.user.targets);
|
||||
// foundry.CONST.TOKEN_DISPOSITIONS.FRIENDLY
|
||||
if (this.target?.type && this.target.type !== SYSTEM.ACTIONS.targetTypes.any.id) {
|
||||
targets = targets.filter(t => this.isTargetFriendly(t));
|
||||
if (this.target.amount && targets.length > this.target.amount) return false;
|
||||
}
|
||||
return targets.map(t => this.formatTarget(t));
|
||||
}
|
||||
|
||||
isTargetFriendly(target) {
|
||||
const actorDisposition = this.actor.token
|
||||
? this.actor.token.disposition
|
||||
|
|
@ -365,6 +422,7 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
formatTarget(actor) {
|
||||
return {
|
||||
id: actor.id,
|
||||
actorId: actor.actor.uuid,
|
||||
name: actor.actor.name,
|
||||
img: actor.actor.img,
|
||||
difficulty: actor.actor.system.difficulty,
|
||||
|
|
@ -374,18 +432,20 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
/* TARGET */
|
||||
|
||||
/* RANGE */
|
||||
async checkRange(config) {
|
||||
if (!this.range || !this.actor) return true;
|
||||
return { values: [], hasRange: true };
|
||||
}
|
||||
|
||||
/* RANGE */
|
||||
|
||||
/* EFFECTS */
|
||||
async applyEffects(event, data, force = false) {
|
||||
if (!this.effects?.length || !data.system.targets.length) return;
|
||||
let effects = this.effects;
|
||||
data.system.targets.forEach(async token => {
|
||||
if (!token.hit && !force) return;
|
||||
this.effects.forEach(async e => {
|
||||
if(this.hasSave && token.saved.success === true) {
|
||||
effects = this.effects.filter(e => e.onSave === true)
|
||||
}
|
||||
if(!effects.length) return;
|
||||
effects.forEach(async e => {
|
||||
const actor = canvas.tokens.get(token.id)?.actor,
|
||||
effect = this.item.effects.get(e._id);
|
||||
if (!actor || !effect) return;
|
||||
|
|
@ -417,28 +477,55 @@ export class DHBaseAction extends foundry.abstract.DataModel {
|
|||
}
|
||||
/* EFFECTS */
|
||||
|
||||
/* CHAT */
|
||||
async proceedChatDisplay(config) {
|
||||
if (!this.chatDisplay) return;
|
||||
/* SAVE */
|
||||
async rollSave(target, event, message) {
|
||||
if(!target?.actor) return;
|
||||
target.actor.diceRoll({
|
||||
event,
|
||||
title: 'Roll Save',
|
||||
roll: {
|
||||
trait: this.save.trait,
|
||||
difficulty: this.save.difficulty,
|
||||
type: "reaction"
|
||||
},
|
||||
data: target.actor.getRollData()
|
||||
}).then(async (result) => {
|
||||
this.updateChatMessage(message, target.id, {result: result.roll.total, success: result.roll.success});
|
||||
})
|
||||
}
|
||||
/* CHAT */
|
||||
|
||||
async updateChatMessage(message, targetId, changes, chain=true) {
|
||||
setTimeout(async () => {
|
||||
const chatMessage = ui.chat.collection.get(message._id),
|
||||
msgTargets = chatMessage.system.targets,
|
||||
msgTarget = msgTargets.find(mt => mt.id === targetId);
|
||||
msgTarget.saved = changes;
|
||||
await chatMessage.update({'system.targets': msgTargets});
|
||||
},100);
|
||||
if(chain) {
|
||||
if(message.system.source.message) this.updateChatMessage(ui.chat.collection.get(message.system.source.message), targetId, changes, false);
|
||||
const relatedChatMessages = ui.chat.collection.filter(c => c.system.source.message === message._id);
|
||||
relatedChatMessages.forEach(c => {
|
||||
this.updateChatMessage(c, targetId, changes, false);
|
||||
})
|
||||
}
|
||||
}
|
||||
/* SAVE */
|
||||
}
|
||||
|
||||
export class DHDamageAction extends DHBaseAction {
|
||||
directDamage = true;
|
||||
|
||||
static extraSchemas = ['damage', 'target', 'effects'];
|
||||
|
||||
async use(event, ...args) {
|
||||
/* async use(event, ...args) {
|
||||
const config = await super.use(event, args);
|
||||
if (!config || ['error', 'warning'].includes(config.type)) return;
|
||||
if (!this.directDamage) return;
|
||||
return await this.rollDamage(event, config);
|
||||
}
|
||||
} */
|
||||
|
||||
getFormulaValue(part, data) {
|
||||
let formulaValue = part.value;
|
||||
if(this.hasRoll() && part.resultBased && data.system.roll.result.duality === -1) return part.valueAlt;
|
||||
if(this.hasRoll && part.resultBased && data.system.roll.result.duality === -1) return part.valueAlt;
|
||||
return formulaValue;
|
||||
}
|
||||
|
||||
|
|
@ -448,25 +535,25 @@ export class DHDamageAction extends DHBaseAction {
|
|||
if (!formula || formula == '') return;
|
||||
let roll = { formula: formula, total: formula },
|
||||
bonusDamage = [];
|
||||
|
||||
|
||||
const config = {
|
||||
title: game.i18n.format('DAGGERHEART.Chat.DamageRoll.Title', { damage: this.name }),
|
||||
formula,
|
||||
targets: (data.system?.targets ?? data.targets).map(x => ({
|
||||
id: x.id,
|
||||
name: x.name,
|
||||
img: x.img,
|
||||
hit: true
|
||||
}))
|
||||
targets: (data.system?.targets.filter(t => t.hit) ?? data.targets),
|
||||
hasSave: this.hasSave,
|
||||
source: data.system?.source
|
||||
};
|
||||
if(this.hasSave) config.onSave = this.save.damageMod;
|
||||
if(data.system) {
|
||||
config.source.message = data._id;
|
||||
config.directDamage = false;
|
||||
}
|
||||
|
||||
roll = CONFIG.Dice.daggerheart.DamageRoll.build(config);
|
||||
}
|
||||
}
|
||||
|
||||
export class DHAttackAction extends DHDamageAction {
|
||||
directDamage = false;
|
||||
|
||||
static extraSchemas = [...super.extraSchemas, ...['roll', 'save']];
|
||||
|
||||
static getRollType(parent) {
|
||||
|
|
@ -505,16 +592,9 @@ export class DHHealingAction extends DHBaseAction {
|
|||
return 'spellcast';
|
||||
}
|
||||
|
||||
async use(event, ...args) {
|
||||
const config = await super.use(event, args);
|
||||
if (!config || ['error', 'warning'].includes(config.type)) return;
|
||||
if (this.hasRoll()) return;
|
||||
return await this.rollHealing(event, config);
|
||||
}
|
||||
|
||||
getFormulaValue(data) {
|
||||
let formulaValue = this.healing.value;
|
||||
if(this.hasRoll() && this.healing.resultBased && data.system.roll.result.duality === -1) return this.healing.valueAlt;
|
||||
if(this.hasRoll && this.healing.resultBased && data.system.roll.result.duality === -1) return this.healing.valueAlt;
|
||||
return formulaValue;
|
||||
}
|
||||
|
||||
|
|
@ -531,13 +611,8 @@ export class DHHealingAction extends DHBaseAction {
|
|||
healing: game.i18n.localize(SYSTEM.GENERAL.healingTypes[this.healing.type].label)
|
||||
}),
|
||||
formula,
|
||||
targets: (data.system?.targets ?? data.targets).map(x => ({
|
||||
id: x.id,
|
||||
name: x.name,
|
||||
img: x.img,
|
||||
hit: true
|
||||
})),
|
||||
messageTemplate: 'systems/daggerheart/templates/chat/healing-roll.hbs',
|
||||
targets: (data.system?.targets ?? data.targets).filter(t => t.hit),
|
||||
messageType: 'healing',
|
||||
type: this.healing.type
|
||||
};
|
||||
|
||||
|
|
@ -557,9 +632,9 @@ export class DHSummonAction extends DHBaseAction {
|
|||
};
|
||||
}
|
||||
|
||||
async use(event, ...args) {
|
||||
async trigger(event, ...args) {
|
||||
if (!this.canSummon || !canvas.scene) return;
|
||||
const config = await super.use(event, args);
|
||||
// const config = await super.use(event, args);
|
||||
}
|
||||
|
||||
get canSummon() {
|
||||
|
|
@ -614,9 +689,9 @@ export class DHMacroAction extends DHBaseAction {
|
|||
};
|
||||
}
|
||||
|
||||
async use(event, ...args) {
|
||||
const config = await super.use(event, args);
|
||||
if (['error', 'warning'].includes(config.type)) return;
|
||||
async trigger(event, ...args) {
|
||||
// const config = await super.use(event, args);
|
||||
// if (['error', 'warning'].includes(config.type)) return;
|
||||
const fixUUID = !this.documentUUID.includes('Macro.') ? `Macro.${this.documentUUID}` : this.documentUUID,
|
||||
macro = await fromUuid(fixUUID);
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
import DhpActor from '../../documents/actor.mjs';
|
||||
import ActionField from '../fields/actionField.mjs';
|
||||
|
||||
export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
|
|
@ -11,16 +8,22 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel {
|
|||
targets: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
id: new fields.StringField({}),
|
||||
actorId: new fields.StringField({}),
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
difficulty: new fields.NumberField({ integer: true, nullable: true }),
|
||||
evasion: new fields.NumberField({ integer: true }),
|
||||
hit: new fields.BooleanField({ initial: false })
|
||||
hit: new fields.BooleanField({ initial: false }),
|
||||
saved: new fields.SchemaField({
|
||||
result: new fields.NumberField(),
|
||||
success: new fields.BooleanField({ nullable: true, initial: null })
|
||||
})
|
||||
})
|
||||
),
|
||||
hasDamage: new fields.BooleanField({ initial: false }),
|
||||
hasHealing: new fields.BooleanField({ initial: false }),
|
||||
hasEffect: new fields.BooleanField({ initial: false }),
|
||||
hasSave: new fields.BooleanField({ initial: false }),
|
||||
source: new fields.SchemaField({
|
||||
actor: new fields.StringField(),
|
||||
item: new fields.StringField(),
|
||||
|
|
@ -28,4 +31,8 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel {
|
|||
})
|
||||
};
|
||||
}
|
||||
|
||||
get messageTemplate() {
|
||||
return 'systems/daggerheart/templates/chat/adversary-roll.hbs';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,34 +3,35 @@ export default class DHDamageRoll extends foundry.abstract.TypeDataModel {
|
|||
const fields = foundry.data.fields;
|
||||
|
||||
return {
|
||||
messageType: new fields.StringField({initial: 'damage'}),
|
||||
title: new fields.StringField(),
|
||||
// roll: new fields.StringField({ required: true }),
|
||||
roll: new fields.DataField({}),
|
||||
/* damage: new fields.SchemaField({
|
||||
total: new fields.NumberField({ required: true, integer: true }),
|
||||
type: new fields.StringField({ choices: Object.keys(SYSTEM.GENERAL.damageTypes), integer: false })
|
||||
}),
|
||||
dice: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
type: new fields.StringField({ required: true }),
|
||||
rolls: new fields.ArrayField(new fields.NumberField({ required: true, integer: true })),
|
||||
total: new fields.NumberField({ integer: true })
|
||||
})
|
||||
),
|
||||
modifiers: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
value: new fields.NumberField({ required: true, integer: true }),
|
||||
operator: new fields.StringField({ required: true, choices: ['+', '-', '*', '/'] })
|
||||
})
|
||||
), */
|
||||
targets: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
id: new fields.StringField({ required: true }),
|
||||
actorId: new fields.StringField({}),
|
||||
name: new fields.StringField(),
|
||||
img: new fields.StringField(),
|
||||
hit: new fields.BooleanField({ initial: false })
|
||||
hit: new fields.BooleanField({ initial: false }),
|
||||
saved: new fields.SchemaField({
|
||||
result: new fields.NumberField(),
|
||||
success: new fields.BooleanField({ nullable: true, initial: null })
|
||||
})
|
||||
})
|
||||
)
|
||||
),
|
||||
hasSave: new fields.BooleanField({ initial: false }),
|
||||
onSave: new fields.StringField(),
|
||||
source: new fields.SchemaField({
|
||||
actor: new fields.StringField(),
|
||||
item: new fields.StringField(),
|
||||
action: new fields.StringField(),
|
||||
message: new fields.StringField()
|
||||
}),
|
||||
directDamage: new fields.BooleanField({initial: true})
|
||||
};
|
||||
}
|
||||
|
||||
get messageTemplate() {
|
||||
return `systems/daggerheart/templates/chat/${this.messageType}-roll.hbs`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,16 +14,22 @@ export default class DHDualityRoll extends foundry.abstract.TypeDataModel {
|
|||
targets: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
id: new fields.StringField({}),
|
||||
actorId: new fields.StringField({}),
|
||||
name: new fields.StringField({}),
|
||||
img: new fields.StringField({}),
|
||||
difficulty: new fields.NumberField({ integer: true, nullable: true }),
|
||||
evasion: new fields.NumberField({ integer: true }),
|
||||
hit: new fields.BooleanField({ initial: false })
|
||||
hit: new fields.BooleanField({ initial: false }),
|
||||
saved: new fields.SchemaField({
|
||||
result: new fields.NumberField(),
|
||||
success: new fields.BooleanField({ nullable: true, initial: null })
|
||||
})
|
||||
})
|
||||
),
|
||||
hasDamage: new fields.BooleanField({ initial: false }),
|
||||
hasHealing: new fields.BooleanField({ initial: false }),
|
||||
hasEffect: new fields.BooleanField({ initial: false }),
|
||||
hasSave: new fields.BooleanField({ initial: false }),
|
||||
source: new fields.SchemaField({
|
||||
actor: new fields.StringField(),
|
||||
item: new fields.StringField(),
|
||||
|
|
@ -31,4 +37,8 @@ export default class DHDualityRoll extends foundry.abstract.TypeDataModel {
|
|||
})
|
||||
};
|
||||
}
|
||||
|
||||
get messageTemplate() {
|
||||
return 'systems/daggerheart/templates/chat/duality-roll.hbs';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.hasRoll = !!this.config.roll;
|
||||
context.experiences = Object.keys(this.config.data.experiences).map(id => ({
|
||||
id,
|
||||
...this.config.data.experiences[id]
|
||||
|
|
@ -67,6 +68,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
context.uses = this.action.calcUses(this.config.uses);
|
||||
context.canRoll = context.canRoll && this.action.hasUses(context.uses);
|
||||
}
|
||||
console.log(context, _options)
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
@ -101,9 +103,9 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
if (!options.submitted) this.config = false;
|
||||
}
|
||||
|
||||
static async configure(config = {}) {
|
||||
static async configure(config = {}, options={}) {
|
||||
return new Promise(resolve => {
|
||||
const app = new this(config);
|
||||
const app = new this(config, options);
|
||||
app.addEventListener('close', () => resolve(app.config), { once: true });
|
||||
app.render({ force: true });
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
import DamageSelectionDialog from '../applications/damageSelectionDialog.mjs';
|
||||
import NpcRollSelectionDialog from '../applications/npcRollSelectionDialog.mjs';
|
||||
import RollSelectionDialog from '../applications/rollSelectionDialog.mjs';
|
||||
import { GMUpdateEvent, socketEvent } from '../helpers/socket.mjs';
|
||||
import { setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
|
||||
import DHDualityRoll from '../data/chat-message/dualityRoll.mjs';
|
||||
import DamageReductionDialog from '../applications/damageReductionDialog.mjs';
|
||||
|
||||
export default class DhpActor extends Actor {
|
||||
|
|
@ -265,12 +261,14 @@ export default class DhpActor extends Actor {
|
|||
* @param {object} [config.targets]
|
||||
* @param {object} [config.costs]
|
||||
*/
|
||||
async diceRoll(config, action) {
|
||||
// config.source = {...(config.source ?? {}), actor: this._id};
|
||||
async diceRoll(config) {
|
||||
config.source = {...(config.source ?? {}), actor: this.uuid};
|
||||
config.data = this.getRollData()
|
||||
const roll = await CONFIG.Dice.daggerheart[this.type === 'character' ? 'DualityRoll' : 'D20Roll'].build(config)
|
||||
return config;
|
||||
config.data = this.getRollData();
|
||||
return await this.rollClass.build(config);
|
||||
}
|
||||
|
||||
get rollClass() {
|
||||
return CONFIG.Dice.daggerheart[this.type === 'character' ? 'DualityRoll' : 'D20Roll'];
|
||||
}
|
||||
|
||||
getRollData() {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
html.querySelectorAll('.duality-action-healing').forEach(element =>
|
||||
element.addEventListener('click', event => this.onRollHealing(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.target-save-container').forEach(element =>
|
||||
element.addEventListener('click', event => this.onRollSave(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.duality-action-effect').forEach(element =>
|
||||
element.addEventListener('click', event => this.onApplyEffect(event, data.message))
|
||||
);
|
||||
|
|
@ -98,6 +101,20 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
}
|
||||
};
|
||||
|
||||
onRollSave = async (event, message) => {
|
||||
event.stopPropagation();
|
||||
const actor = await this.getActor(message.system.source.actor),
|
||||
tokenId = event.target.closest('[data-token]')?.dataset.token,
|
||||
token = game.canvas.tokens.get(tokenId);
|
||||
if (!token?.actor || !token.isOwner) return true;
|
||||
console.log(token.actor.canUserModify(game.user, 'update'));
|
||||
if (message.system.source.item && message.system.source.action) {
|
||||
const action = this.getAction(actor, message.system.source.item, message.system.source.action);
|
||||
if (!action || !action?.hasSave) return;
|
||||
action.rollSave(token, event, message);
|
||||
}
|
||||
};
|
||||
|
||||
onApplyEffect = async (event, message) => {
|
||||
event.stopPropagation();
|
||||
const actor = await this.getActor(message.system.source.actor);
|
||||
|
|
@ -137,10 +154,24 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
? message.system.targets.map(target => game.canvas.tokens.get(target.id))
|
||||
: Array.from(game.user.targets);
|
||||
|
||||
if(message.system.onSave && event.currentTarget.dataset.targetHit) {
|
||||
console.log(message.system.targets)
|
||||
const pendingingSaves = message.system.targets.filter(target => target.hit && target.saved.success === null);
|
||||
if(pendingingSaves.length) {
|
||||
const confirm = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {title: "Pending Reaction Rolls found"},
|
||||
content: `<p>Some Tokens still need to roll their Reaction Roll.</p><p>Are you sure you want to continue ?</p><p><i>Undone reaction rolls will be considered as failed</i></p>`
|
||||
});
|
||||
if ( !confirm ) return;
|
||||
}
|
||||
}
|
||||
|
||||
if (targets.length === 0)
|
||||
ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.NoTargetsSelected'));
|
||||
for (var target of targets) {
|
||||
await target.actor.takeDamage(message.system.roll.result, message.system.roll.type);
|
||||
for (let target of targets) {
|
||||
let damage = message.system.roll.total;
|
||||
if(message.system.onSave && message.system.targets.find(t => t.id === target.id)?.saved?.success === true) damage = Math.ceil(damage * (SYSTEM.ACTIONS.damageOnSave[message.system.onSave]?.mod ?? 1));
|
||||
await target.actor.takeDamage(damage, message.system.roll.type);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -152,7 +183,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.NoTargetsSelected'));
|
||||
|
||||
for (var target of targets) {
|
||||
await target.actor.takeHealing([{ value: message.system.roll.result, type: message.system.roll.type }]);
|
||||
await target.actor.takeHealing([{ value: message.system.roll.total, type: message.system.roll.type }]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
fieldset.daggerheart.chat {
|
||||
padding: 0;
|
||||
border-left-width: 0;
|
||||
border-right-width: 0;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.daggerheart.chat {
|
||||
&.downtime {
|
||||
display: flex;
|
||||
|
|
@ -227,19 +234,35 @@
|
|||
background: @miss;
|
||||
}
|
||||
|
||||
img {
|
||||
flex: 0;
|
||||
img, .target-save-container {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-left: 8px;
|
||||
align-self: center;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
img {
|
||||
flex: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.target-save-container {
|
||||
margin-right: 8px;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: unset;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.target-inner-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-size: var(--font-size-16);
|
||||
}
|
||||
|
||||
&:not(:has(.target-save-container)) .target-inner-container {
|
||||
margin-right: @hugeMargin;
|
||||
}
|
||||
}
|
||||
|
|
@ -313,12 +336,29 @@
|
|||
width: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
[data-use-perm='false'] {
|
||||
pointer-events: none;
|
||||
border-color: transparent;
|
||||
}
|
||||
[data-view-perm='false'] {
|
||||
> * {
|
||||
display: none;
|
||||
}
|
||||
&::after {
|
||||
content: "??";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.theme-colorful {
|
||||
.chat-message.duality {
|
||||
border-color: black;
|
||||
padding: 8px 0 0 0;
|
||||
fieldset.daggerheart.chat {
|
||||
border-top-width: 0;
|
||||
display: contents;
|
||||
}
|
||||
.message-header {
|
||||
color: var(--color-light-3);
|
||||
padding: 0 8px;
|
||||
|
|
|
|||
|
|
@ -1399,6 +1399,12 @@
|
|||
.chat-message .dice-title {
|
||||
display: none;
|
||||
}
|
||||
fieldset.daggerheart.chat {
|
||||
padding: 0;
|
||||
border-left-width: 0;
|
||||
border-right-width: 0;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
.daggerheart.chat.downtime {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -1552,18 +1558,32 @@
|
|||
.daggerheart.chat.roll .target-section .target-container.miss {
|
||||
background: #ff0000;
|
||||
}
|
||||
.daggerheart.chat.roll .target-section .target-container img {
|
||||
flex: 0;
|
||||
.daggerheart.chat.roll .target-section .target-container img,
|
||||
.daggerheart.chat.roll .target-section .target-container .target-save-container {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin-left: 8px;
|
||||
align-self: center;
|
||||
border-color: transparent;
|
||||
}
|
||||
.daggerheart.chat.roll .target-section .target-container img {
|
||||
flex: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
.daggerheart.chat.roll .target-section .target-container .target-save-container {
|
||||
margin-right: 8px;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: unset;
|
||||
border: 1px solid black;
|
||||
}
|
||||
.daggerheart.chat.roll .target-section .target-container .target-inner-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-size: var(--font-size-16);
|
||||
}
|
||||
.daggerheart.chat.roll .target-section .target-container:not(:has(.target-save-container)) .target-inner-container {
|
||||
margin-right: 32px;
|
||||
}
|
||||
.daggerheart.chat.roll .dice-actions {
|
||||
|
|
@ -1620,10 +1640,24 @@
|
|||
.daggerheart.chat.domain-card img {
|
||||
width: 80px;
|
||||
}
|
||||
.daggerheart.chat [data-use-perm='false'] {
|
||||
pointer-events: none;
|
||||
border-color: transparent;
|
||||
}
|
||||
.daggerheart.chat [data-view-perm='false'] > * {
|
||||
display: none;
|
||||
}
|
||||
.daggerheart.chat [data-view-perm='false']::after {
|
||||
content: "??";
|
||||
}
|
||||
.theme-colorful .chat-message.duality {
|
||||
border-color: black;
|
||||
padding: 8px 0 0 0;
|
||||
}
|
||||
.theme-colorful .chat-message.duality fieldset.daggerheart.chat {
|
||||
border-top-width: 0;
|
||||
display: contents;
|
||||
}
|
||||
.theme-colorful .chat-message.duality .message-header {
|
||||
color: var(--color-light-3);
|
||||
padding: 0 8px;
|
||||
|
|
|
|||
|
|
@ -26,26 +26,18 @@
|
|||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dice-total">
|
||||
<div class="dice-total-value">{{roll.total}}</div>
|
||||
</div>
|
||||
{{#if (gt targets.length 0)}}
|
||||
<div class="target-section">
|
||||
{{#each targets as |target|}}
|
||||
<div class="dice-total target-container {{#if target.hit}}hit{{else}}miss{{/if}}" data-token="{{target.id}}">
|
||||
<img src="{{target.img}}" />
|
||||
<div class="target-inner-container">
|
||||
{{#if target.hit}}{{localize "Hit"}}{{else}}{{localize "Miss"}}{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if hasDamage}}
|
||||
</div>
|
||||
</div>
|
||||
{{> 'systems/daggerheart/templates/chat/parts/target-chat.hbs'}}
|
||||
{{#if hasDamage}}
|
||||
<div class="dice-roll daggerheart chat roll">
|
||||
<div class="dice-result">
|
||||
<div class="flexrow">
|
||||
<button class="duality-action duality-action-damage" data-value="{{roll.total}}"><span>Roll Damage</span></button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
@ -1,15 +1,14 @@
|
|||
<div class="dice-roll daggerheart chat roll" data-action="expandRoll">
|
||||
<div class="dice-flavor">{{title}}</div>
|
||||
<div class="dice-result">
|
||||
<div class="dice-formula">{{formula}}</div>
|
||||
<div class="dice-formula">{{roll.formula}}</div>
|
||||
<div class="dice-tooltip">
|
||||
<div class="wrapper">
|
||||
<section class="tooltip-part">
|
||||
{{#each roll.dice}}
|
||||
<div class="dice">
|
||||
<header class="part-header flexrow">
|
||||
<span class="part-formula">{{formula}}</span>
|
||||
|
||||
<span class="part-formula">{{formula}}</span>
|
||||
<span class="part-total">{{total}}</span>
|
||||
</header>
|
||||
<ol class="dice-rolls">
|
||||
|
|
@ -22,7 +21,12 @@
|
|||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dice-total">{{roll.result}}</div>
|
||||
<div class="dice-total">{{roll.total}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{> 'systems/daggerheart/templates/chat/parts/target-chat.hbs'}}
|
||||
<div class="dice-roll daggerheart chat roll">
|
||||
<div class="dice-result">
|
||||
<div class="dice-actions">
|
||||
<button class="damage-button" data-target-hit="true" {{#if (eq targets.length 0)}}disabled{{/if}}>{{localize "DAGGERHEART.Chat.DamageRoll.DealDamageToTargets"}}</button>
|
||||
<button class="damage-button">{{localize "DAGGERHEART.Chat.DamageRoll.DealDamage"}}</button>
|
||||
|
|
|
|||
|
|
@ -92,18 +92,11 @@
|
|||
{{roll.total}}
|
||||
</div>
|
||||
</div>
|
||||
{{#if (gt targets.length 0)}}
|
||||
<div class="target-section">
|
||||
{{#each targets as |target|}}
|
||||
<div class="dice-total target-container {{#if target.hit}}hit{{else}}{{#if (not ../total.alternate)}}miss{{/if}}{{/if}}" data-token="{{target.id}}">
|
||||
<img src="{{target.img}}" />
|
||||
<div class="target-inner-container">
|
||||
{{#if target.hit}}{{localize "Hit"}}{{else}}{{#if (not ../total.alternate)}}{{localize "Miss"}}{{else}}?{{/if}}{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{> 'systems/daggerheart/templates/chat/parts/target-chat.hbs'}}
|
||||
<div class="dice-roll daggerheart chat roll">
|
||||
<div class="dice-result">
|
||||
<div class="dice-actions{{#unless (or hasDamage hasHealing)}} duality-alone{{/unless}}">
|
||||
{{#if hasDamage}}
|
||||
<button class="duality-action duality-action-damage" data-value="{{roll.total}}"><span>{{localize "DAGGERHEART.Chat.AttackRoll.RollDamage"}}</span></button>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<div class="dice-roll daggerheart chat roll" data-action="expandRoll">
|
||||
<div class="dice-flavor">{{title}}</div>
|
||||
<div class="dice-result">
|
||||
<div class="dice-formula">{{formula}}</div>
|
||||
<div class="dice-formula">{{roll.formula}}</div>
|
||||
<div class="dice-tooltip">
|
||||
<div class="wrapper">
|
||||
<section class="tooltip-part">
|
||||
|
|
@ -9,7 +9,6 @@
|
|||
<div class="dice">
|
||||
<header class="part-header flexrow">
|
||||
<span class="part-formula">{{formula}}</span>
|
||||
|
||||
<span class="part-total">{{total}}</span>
|
||||
</header>
|
||||
<ol class="dice-rolls">
|
||||
|
|
@ -22,7 +21,7 @@
|
|||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dice-total">{{roll.result}}</div>
|
||||
<div class="dice-total">{{roll.total}}</div>
|
||||
<div class="flexrow">
|
||||
<button class="healing-button"><span>{{localize "DAGGERHEART.Chat.HealingRoll.Heal"}}</span></button>
|
||||
</div>
|
||||
|
|
|
|||
32
templates/chat/parts/target-chat.hbs
Normal file
32
templates/chat/parts/target-chat.hbs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
{{#if (gt targets.length 0)}}
|
||||
<fieldset class="dice-roll daggerheart chat roll expanded" data-action="expandRoll">
|
||||
<legend class="dice-flavor">Targets</legend>
|
||||
<div class="dice-result">
|
||||
<div class="dice-tooltip">
|
||||
<div class="wrapper">
|
||||
<div class="target-section">
|
||||
{{#each targets as |target|}}
|
||||
<div class="dice-total target-container {{#if target.hit}}hit{{else}}{{#if (not ../total.alternate)}}miss{{/if}}{{/if}}" data-token="{{target.id}}">
|
||||
<img src="{{target.img}}" />
|
||||
<div class="target-inner-container">
|
||||
{{#if ../directDamage}}
|
||||
<div data-perm-id="{{target.actorId}}"><span>{{target.name}}</span></div>
|
||||
{{else}}
|
||||
{{#if target.hit}}{{localize "Hit"}}{{else}}{{#if (not ../total.alternate)}}{{localize "Miss"}}{{else}}?{{/if}}{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if ../hasSave}}
|
||||
<button class="target-save-container{{#if target.saved.result includeZero=true}} is-rolled{{/if}}"{{#unless target.hit}} style="visibility: hidden;"{{/unless}} data-perm-id="{{target.actorId}}">
|
||||
{{!-- {{target.saved.result}} --}}
|
||||
<i class="fa-solid {{#if target.saved.result includeZero=true}}{{#if target.saved.success}}fa-check{{else}}fa-xmark{{/if}}{{else}}fa-shield{{/if}}">
|
||||
</i>
|
||||
</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
{{/if}}
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
</div>
|
||||
{{> 'systems/daggerheart/templates/views/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=source.system.attack.damage path="system.attack."}}
|
||||
<div style="grid-column: 1 / -1;">
|
||||
{{> 'systems/daggerheart/templates/views/actionTypes/effect.hbs'}}
|
||||
{{> 'systems/daggerheart/templates/views/actionTypes/effect.hbs' fields=systemFields.attack.fields.effects.element.fields source=source.system.attack.effects}}
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@
|
|||
<div class="hope-section">
|
||||
<h4>{{localize "DAGGERHEART.General.Hope"}}</h4>
|
||||
{{#times document.system.resources.hope.max}}
|
||||
<span class='hope-value' data-action='toggleHope' data-value="{{this}}">
|
||||
{{#if (gte ../document.system.resources.hope.value this)}}
|
||||
<span class='hope-value' data-action='toggleHope' data-value="{{add this 1}}">
|
||||
{{#if (gte ../document.system.resources.hope.value (add this 1))}}
|
||||
<i class='fa-solid fa-diamond'></i>
|
||||
{{else}}
|
||||
<i class='fa-regular fa-circle'></i>
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@
|
|||
<legend>{{localize "DAGGERHEART.Sheets.Global.Actions"}} <a><i class="fa-solid fa-plus icon-button" data-action="addAction"></i></a></legend>
|
||||
<div class="actions-list">
|
||||
{{#each document.system.actions as |action index|}}
|
||||
<div class="action-item">
|
||||
<div class="action-item"
|
||||
data-action="editAction"
|
||||
data-index="{{index}}"
|
||||
>
|
||||
<img class="image" src="{{action.img}}" />
|
||||
<span>{{action.name}}</span>
|
||||
<div class="controls">
|
||||
<a data-action="editAction" data-index="{{index}}"><i class="fa-solid fa-pen-to-square"></i></a>
|
||||
<a data-action="removeAction" data-index="{{index}}"><i class="fa-solid fa-trash"></i></a>
|
||||
<a data-action="removeAction"><i class="fa-solid fa-trash"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<div class="hope-container">
|
||||
{{#times 6}}
|
||||
<span class="hope-inner-container">
|
||||
<input class="hope-value" type="checkbox" data-action="toggleHope" data-value="{{this}}" {{ checked (gte ../document.system.resources.hope.value this) }} {{#if (gte this ../document.system.resources.hope.max)}}disabled{{/if}} />
|
||||
<input class="hope-value" type="checkbox" data-action="toggleHope" data-value="{{add this 1}}" {{ checked (gte ../document.system.resources.hope.value (add this 1)) }} {{#if (gte this ../document.system.resources.hope.max)}}disabled{{/if}} />
|
||||
{{#if (gte this ../document.system.resources.hope.max)}}<i class="fa-solid fa-droplet-slash hope-scar"></i>{{/if}}
|
||||
</span>
|
||||
{{/times}}
|
||||
|
|
|
|||
|
|
@ -41,11 +41,12 @@
|
|||
</div>
|
||||
<div class="tab {{this.tabs.effect.cssClass}}" data-group="primary" data-tab="effect">
|
||||
{{#if fields.roll}}{{> 'systems/daggerheart/templates/views/actionTypes/roll.hbs' fields=fields.roll.fields source=source.roll}}{{/if}}
|
||||
{{#if fields.save}}{{> 'systems/daggerheart/templates/views/actionTypes/save.hbs' fields=fields.save.fields source=source.save}}{{/if}}
|
||||
{{#if fields.damage}}{{> 'systems/daggerheart/templates/views/actionTypes/damage.hbs' fields=fields.damage.fields.parts.element.fields source=source.damage}}{{/if}}
|
||||
{{#if fields.healing}}{{> 'systems/daggerheart/templates/views/actionTypes/healing.hbs' fields=fields.healing.fields source=source.healing}}{{/if}}
|
||||
{{#if fields.resource}}{{> 'systems/daggerheart/templates/views/actionTypes/resource.hbs' fields=fields.resource.fields source=source.resource}}{{/if}}
|
||||
{{#if fields.documentUUID}}{{> 'systems/daggerheart/templates/views/actionTypes/uuid.hbs' fields=fields.documentUUID source=source.documentUUID}}{{/if}}
|
||||
{{#if fields.effects}}{{> 'systems/daggerheart/templates/views/actionTypes/effect.hbs'}}{{/if}}
|
||||
{{#if fields.effects}}{{> 'systems/daggerheart/templates/views/actionTypes/effect.hbs' fields=fields.effects.element.fields source=source.effects}}{{/if}}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
@ -14,15 +14,15 @@
|
|||
{{/unless}}
|
||||
{{#each source.parts as |dmg index|}}
|
||||
{{#if @root.isNPC}}
|
||||
{{formField ../fields.custom.fields.enabled value=dmg.custom.enabled name=(concat ../path "damage.parts." index ".custom.enabled")}}
|
||||
<input type="hidden" name="{{../path}}damage.parts.{{index}}.multiplier" value="{{dmg.multiplier}}">
|
||||
{{#if dmg.custom.enabled}}
|
||||
{{formField ../fields.custom.fields.formula value=dmg.custom.formula name=(concat ../path "damage.parts." index ".custom.formula") localize=true}}
|
||||
{{formField ../fields.value.fields.custom.fields.enabled value=dmg.value.custom.enabled name=(concat ../path "damage.parts." index ".value.custom.enabled")}}
|
||||
<input type="hidden" name="{{../path}}damage.parts.{{index}}.value.multiplier" value="{{dmg.value.multiplier}}">
|
||||
{{#if dmg.value.custom.enabled}}
|
||||
{{formField ../fields.value.fields.custom.fields.formula value=dmg.value.custom.formula name=(concat ../path "damage.parts." index ".value.custom.formula") localize=true}}
|
||||
{{else}}
|
||||
<div class="multi-display">
|
||||
{{formField ../fields.flatMultiplier value=dmg.flatMultiplier name=(concat ../path "damage.parts." index ".flatMultiplier") label="Multiplier" }}
|
||||
{{formField ../fields.dice value=dmg.dice name=(concat ../path "damage.parts." index ".dice")}}
|
||||
{{formField ../fields.bonus value=dmg.bonus name=(concat ../path "damage.parts." index ".bonus") localize=true}}
|
||||
{{formField ../fields.value.fields.flatMultiplier value=dmg.value.flatMultiplier name=(concat ../path "damage.parts." index ".value.flatMultiplier") label="Multiplier" }}
|
||||
{{formField ../fields.value.fields.dice value=dmg.value.dice name=(concat ../path "damage.parts." index ".value.dice")}}
|
||||
{{formField ../fields.value.fields.bonus value=dmg.value.bonus name=(concat ../path "damage.parts." index ".value.bonus") localize=true}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{formField ../fields.type value=dmg.type name=(concat ../path "damage.parts." index ".type") localize=true}}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,31 @@
|
|||
</legend>
|
||||
<div class="action-category-data open" data-key="effects">
|
||||
<div class="fas fa-plus icon-button" data-action="addEffect"></div>
|
||||
{{#each @root.effects as | effect index | }}
|
||||
{{!-- {{#each @root.effects as | effect index | }}
|
||||
<fieldset>
|
||||
{{!-- <div class="multi-display"> --}}
|
||||
<div class="multi-display">
|
||||
<div class="form-group">
|
||||
<img src="{{img}}">
|
||||
<label data-action="editEffect">{{name}}</label>
|
||||
<div class="fas fa-trash" data-action="removeEffect" data-index="{{index}}"></div>
|
||||
</div>
|
||||
{{!-- </div> --}}
|
||||
{{formfield }}
|
||||
</div>
|
||||
</fieldset>
|
||||
{{/each}} --}}
|
||||
{{#each source as | effect index |}}
|
||||
<fieldset data-effect-id="{{effect._id}}">
|
||||
<div class="multi-display">
|
||||
{{#with (@root.getEffectDetails effect._id) as | details |}}
|
||||
<div class="form-group" data-action="editEffect">
|
||||
<img src="{{img}}">
|
||||
<label>{{name}}</label>
|
||||
<div class="fas fa-trash" data-action="removeEffect" data-index="{{index}}"></div>
|
||||
</div>
|
||||
{{/with}}
|
||||
<input type="hidden" name="effects.{{index}}._id" value="{{effect._id}}">
|
||||
{{formField ../fields.onSave value=effect.onSave name=(concat "effects." index ".onSave")}}
|
||||
</div>
|
||||
</fieldset>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
{{formField fields.bonus label="Bonus" name="roll.bonus" value=source.bonus}}
|
||||
{{else}}
|
||||
{{formField fields.type label="Type" name="roll.type" value=source.type localize=true}}
|
||||
{{formField fields.trait label="Trait" name="roll.trait" value=source.trait localize=true}}
|
||||
{{formField fields.difficulty label="Difficulty" name="roll.difficulty" value=source.difficulty}}
|
||||
{{formField fields.trait label="Trait" name="roll.trait" value=source.trait localize=true disabled=(not source.type)}}
|
||||
{{formField fields.difficulty label="Difficulty" name="roll.difficulty" value=source.difficulty disabled=(not source.type)}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</fieldset>
|
||||
10
templates/views/actionTypes/save.hbs
Normal file
10
templates/views/actionTypes/save.hbs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<fieldset class="action-category">
|
||||
<legend class="action-category-label" data-action="toggleSection" data-section="roll">
|
||||
<div>Save</div>
|
||||
</legend>
|
||||
<div class="action-category-data open">
|
||||
{{formField fields.trait label="Trait" name="save.trait" value=source.trait localize=true}}
|
||||
{{formField fields.difficulty label="Difficulty" name="save.difficulty" value=source.difficulty disabled=(not source.trait)}}
|
||||
{{formField fields.damageMod label="Damage on Save" name="save.damageMod" value=source.damageMod localize=true disabled=(not source.trait)}}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
<footer>
|
||||
{{!-- <footer>
|
||||
<button data-action="sendCost"{{#unless canUse}} disabled{{/unless}}>Accept</button>
|
||||
</footer>
|
||||
</footer> --}}
|
||||
</div>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
<div>
|
||||
{{#if @root.hasRoll}}
|
||||
<div class="roll-dialog-container">
|
||||
<div class="flexcol">
|
||||
<div class="roll-dialog-experience-container">
|
||||
|
|
@ -34,8 +35,9 @@
|
|||
</div> --}}
|
||||
{{!-- {{/if}} --}}
|
||||
</div>
|
||||
<footer>
|
||||
<button data-action="submitRoll"{{#unless canRoll}} disabled{{/unless}}>Roll</button>
|
||||
</footer>
|
||||
</div>
|
||||
{{/if}}
|
||||
<footer>
|
||||
<button data-action="submitRoll"{{#unless canRoll}} disabled{{/unless}}>Roll</button>
|
||||
</footer>
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue