mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-21 23:13:39 +02:00
Compare commits
18 commits
70e21f34db
...
e111f7c2ae
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e111f7c2ae | ||
|
|
bb179db758 | ||
|
|
bbc1781d01 | ||
|
|
a897037dc4 | ||
|
|
97636fa134 | ||
|
|
e7be2a7d2b | ||
|
|
9bea8d6a97 | ||
|
|
7ca420ae0e | ||
|
|
ae480157d1 | ||
|
|
b505e15eb2 | ||
|
|
087e69694c | ||
|
|
fad830580c | ||
|
|
4c2d31b2f4 | ||
|
|
67d142df3d | ||
|
|
fdfd8c5a8d | ||
|
|
dbcef140a2 | ||
|
|
90f4339898 | ||
|
|
0d7469801e |
77 changed files with 3154 additions and 1227 deletions
|
|
@ -343,6 +343,17 @@ Hooks.on(CONFIG.DH.HOOKS.hooksConfig.tagTeamStart, async data => {
|
|||
}
|
||||
});
|
||||
|
||||
Hooks.on(CONFIG.DH.HOOKS.hooksConfig.groupRollStart, async data => {
|
||||
if (data.openForAllPlayers && data.partyId) {
|
||||
const party = game.actors.get(data.partyId);
|
||||
if (!party) return;
|
||||
|
||||
const dialog = new game.system.api.applications.dialogs.GroupRollDialog(party);
|
||||
dialog.tabGroups.application = 'groupRoll';
|
||||
await dialog.render({ force: true });
|
||||
}
|
||||
});
|
||||
|
||||
const updateActorsRangeDependentEffects = async token => {
|
||||
const rangeMeasurement = game.settings.get(
|
||||
CONFIG.DH.id,
|
||||
|
|
|
|||
45
lang/en.json
45
lang/en.json
|
|
@ -131,6 +131,7 @@
|
|||
"attackName": "Attack Name",
|
||||
"criticalThreshold": "Critical Threshold",
|
||||
"includeBase": { "label": "Include Item Damage" },
|
||||
"groupAttack": { "label": "Group Attack" },
|
||||
"multiplier": "Multiplier",
|
||||
"saveHint": "Set a default Trait to enable Reaction Roll. It can be changed later in Reaction Roll Dialog.",
|
||||
"resultBased": {
|
||||
|
|
@ -318,6 +319,21 @@
|
|||
}
|
||||
},
|
||||
"newAdversary": "New Adversary"
|
||||
},
|
||||
"Party": {
|
||||
"Subtitle": {
|
||||
"character": "{community} {ancestry} | {subclass} {class}",
|
||||
"companion": "Companion of {partner}"
|
||||
},
|
||||
"RemoveConfirmation": {
|
||||
"title": "Remove member {name}",
|
||||
"text": "Are you sure you want to remove {name} from the party?"
|
||||
},
|
||||
"Thresholds": {
|
||||
"minor": "MIN",
|
||||
"major": "MAJ",
|
||||
"severe": "SEV"
|
||||
}
|
||||
}
|
||||
},
|
||||
"APPLICATIONS": {
|
||||
|
|
@ -353,7 +369,7 @@
|
|||
"selectSecondaryWeapon": "Select Secondary Weapon",
|
||||
"selectSubclass": "Select Subclass",
|
||||
"setupSkipTitle": "Skipping Character Setup",
|
||||
"setupSkipContent": "You are skipping the Character Setup by adding this manually. The character setup is the blinking arrows in the top-right. Are you sure you want to continue?",
|
||||
"setupSkipContent": "You are skipping the Character Setup by adding this manually. The character setup is the blinking button in the top-right. Are you sure you want to continue?",
|
||||
"startingItems": "Starting Items",
|
||||
"story": "Story",
|
||||
"storyExplanation": "Select which background and connection prompts you want to copy into your character's background.",
|
||||
|
|
@ -717,6 +733,17 @@
|
|||
"selectRoll": "Select which roll value to be used for the Tag Team"
|
||||
}
|
||||
},
|
||||
"GroupRollSelect": {
|
||||
"title": "Group Roll",
|
||||
"leader": "Leader",
|
||||
"leaderRoll": "Leader Roll",
|
||||
"openDialogForAll": "Open Dialog For All",
|
||||
"startGroupRoll": "Start Group Roll",
|
||||
"cancelGroupRoll": "Cancel",
|
||||
"finishGroupRoll": "Finish Group Roll",
|
||||
"cancelConfirmTitle": "Cancel Group Roll",
|
||||
"cancelConfirmText": "Are you sure you want to cancel the Group Roll? This will close it for all other players too."
|
||||
},
|
||||
"TokenConfig": {
|
||||
"actorSizeUsed": "Actor size is set, determining the dimensions"
|
||||
}
|
||||
|
|
@ -2857,6 +2884,7 @@
|
|||
"system": "Dice Preset",
|
||||
"font": "Font",
|
||||
"critical": "Duality Critical Animation",
|
||||
"muted": "Muted",
|
||||
"diceAppearance": "Dice Appearance",
|
||||
"animations": "Animations",
|
||||
"defaultAnimations": "Set Animations As Player Defaults",
|
||||
|
|
@ -2965,18 +2993,6 @@
|
|||
"immunityTo": "Immunity: {immunities}"
|
||||
},
|
||||
"featureTitle": "Class Feature",
|
||||
"groupRoll": {
|
||||
"title": "Group Roll",
|
||||
"leader": "Leader",
|
||||
"partyTeam": "Party Team",
|
||||
"team": "Team",
|
||||
"selectLeader": "Select a Leader",
|
||||
"selectMember": "Select a Member",
|
||||
"rerollTitle": "Reroll Group Roll",
|
||||
"rerollContent": "Are you sure you want to reroll your {trait} roll?",
|
||||
"rerollTooltip": "Reroll",
|
||||
"wholePartySelected": "The whole party is selected"
|
||||
},
|
||||
"healingRoll": {
|
||||
"title": "Heal - {damage}",
|
||||
"heal": "Heal",
|
||||
|
|
@ -3142,7 +3158,8 @@
|
|||
"tokenActorsMissing": "[{names}] missing Actors",
|
||||
"domainTouchRequirement": "This domain card requires {nr} {domain} cards in the loadout to be used",
|
||||
"knowTheTide": "Know The Tide gained a token",
|
||||
"lackingItemTransferPermission": "User {user} lacks owner permission needed to transfer items to {target}"
|
||||
"lackingItemTransferPermission": "User {user} lacks owner permission needed to transfer items to {target}",
|
||||
"noTokenTargeted": "No token is targeted"
|
||||
},
|
||||
"Progress": {
|
||||
"migrationLabel": "Performing system migration. Please wait and do not close Foundry."
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export { default as OwnershipSelection } from './ownershipSelection.mjs';
|
|||
export { default as RerollDamageDialog } from './rerollDamageDialog.mjs';
|
||||
export { default as ResourceDiceDialog } from './resourceDiceDialog.mjs';
|
||||
export { default as ActionSelectionDialog } from './actionSelectionDialog.mjs';
|
||||
export { default as GroupRollDialog } from './group-roll-dialog.mjs';
|
||||
export { default as TagTeamDialog } from './tagTeamDialog.mjs';
|
||||
export { default as GroupRollDialog } from './groupRollDialog.mjs';
|
||||
export { default as RiskItAllDialog } from './riskItAllDialog.mjs';
|
||||
export { default as CompendiumBrowserSettingsDialog } from './CompendiumBrowserSettings.mjs';
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application
|
|||
},
|
||||
actions: {
|
||||
toggleSelectedEffect: this.toggleSelectedEffect,
|
||||
updateGroupAttack: this.updateGroupAttack,
|
||||
toggleCritical: this.toggleCritical,
|
||||
submitRoll: this.submitRoll
|
||||
},
|
||||
|
|
@ -64,15 +65,40 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application
|
|||
context.hasSelectedEffects = Boolean(Object.keys(this.selectedEffects).length);
|
||||
context.selectedEffects = this.selectedEffects;
|
||||
|
||||
context.damageOptions = this.config.damageOptions;
|
||||
context.rangeOptions = CONFIG.DH.GENERAL.groupAttackRange;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static updateRollConfiguration(_event, _, formData) {
|
||||
const { ...rest } = foundry.utils.expandObject(formData.object);
|
||||
foundry.utils.mergeObject(this.config.roll, rest.roll);
|
||||
foundry.utils.mergeObject(this.config.modifiers, rest.modifiers);
|
||||
this.config.selectedMessageMode = rest.selectedMessageMode;
|
||||
const data = foundry.utils.expandObject(formData.object);
|
||||
foundry.utils.mergeObject(this.config.roll, data.roll);
|
||||
foundry.utils.mergeObject(this.config.modifiers, data.modifiers);
|
||||
this.config.selectedMessageMode = data.selectedMessageMode;
|
||||
|
||||
if (data.damageOptions) {
|
||||
const numAttackers = data.damageOptions.groupAttack?.numAttackers;
|
||||
if (typeof numAttackers !== 'number' || numAttackers % 1 !== 0) {
|
||||
data.damageOptions.groupAttack.numAttackers = null;
|
||||
}
|
||||
|
||||
foundry.utils.mergeObject(this.config.damageOptions, data.damageOptions);
|
||||
}
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
static updateGroupAttack() {
|
||||
const targets = Array.from(game.user.targets);
|
||||
if (targets.length === 0)
|
||||
return ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.noTokenTargeted'));
|
||||
|
||||
const actorId = this.roll.data.parent.id;
|
||||
const range = this.config.damageOptions.groupAttack.range;
|
||||
const groupAttackTokens = game.system.api.fields.ActionFields.DamageField.getGroupAttackTokens(actorId, range);
|
||||
|
||||
this.config.damageOptions.groupAttack.numAttackers = groupAttackTokens.length;
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,204 +0,0 @@
|
|||
import autocomplete from 'autocompleter';
|
||||
import { abilities } from '../../config/actorConfig.mjs';
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
export default class GroupRollDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
constructor(actors) {
|
||||
super();
|
||||
this.actors = actors;
|
||||
this.actorLeader = {};
|
||||
this.actorsMembers = [];
|
||||
}
|
||||
|
||||
get title() {
|
||||
return 'Group Roll';
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'views', 'dh-style', 'dialog', 'group-roll'],
|
||||
position: { width: 'auto', height: 'auto' },
|
||||
window: {
|
||||
title: 'DAGGERHEART.UI.Chat.groupRoll.title'
|
||||
},
|
||||
actions: {
|
||||
roll: GroupRollDialog.#roll,
|
||||
removeLeader: GroupRollDialog.#removeLeader,
|
||||
removeMember: GroupRollDialog.#removeMember
|
||||
},
|
||||
form: { handler: this.updateData, submitOnChange: true, closeOnSubmit: false }
|
||||
};
|
||||
|
||||
static PARTS = {
|
||||
application: {
|
||||
id: 'group-roll',
|
||||
template: 'systems/daggerheart/templates/dialogs/group-roll/group-roll.hbs'
|
||||
}
|
||||
};
|
||||
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
const leaderChoices = this.actors.filter(x => this.actorsMembers.every(member => member.actor?.id !== x.id));
|
||||
const memberChoices = this.actors.filter(
|
||||
x => this.actorLeader?.actor?.id !== x.id && this.actorsMembers.every(member => member.actor?.id !== x.id)
|
||||
);
|
||||
|
||||
htmlElement.querySelectorAll('.leader-change-input').forEach(element => {
|
||||
autocomplete({
|
||||
input: element,
|
||||
fetch: function (text, update) {
|
||||
if (!text) {
|
||||
update(leaderChoices);
|
||||
} else {
|
||||
text = text.toLowerCase();
|
||||
var suggestions = leaderChoices.filter(n => n.name.toLowerCase().includes(text));
|
||||
update(suggestions);
|
||||
}
|
||||
},
|
||||
render: function (actor, search) {
|
||||
const actorName = game.i18n.localize(actor.name);
|
||||
const matchIndex = actorName.toLowerCase().indexOf(search);
|
||||
|
||||
const beforeText = actorName.slice(0, matchIndex);
|
||||
const matchText = actorName.slice(matchIndex, matchIndex + search.length);
|
||||
const after = actorName.slice(matchIndex + search.length, actorName.length);
|
||||
const img = document.createElement('img');
|
||||
img.src = actor.img;
|
||||
|
||||
const element = document.createElement('li');
|
||||
element.appendChild(img);
|
||||
|
||||
const label = document.createElement('span');
|
||||
label.innerHTML =
|
||||
`${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`.replaceAll(
|
||||
' ',
|
||||
' '
|
||||
);
|
||||
element.appendChild(label);
|
||||
|
||||
return element;
|
||||
},
|
||||
renderGroup: function (label) {
|
||||
const itemElement = document.createElement('div');
|
||||
itemElement.textContent = game.i18n.localize(label);
|
||||
return itemElement;
|
||||
},
|
||||
onSelect: actor => {
|
||||
element.value = actor.uuid;
|
||||
this.actorLeader = { actor: actor, trait: 'agility', difficulty: 0 };
|
||||
this.render();
|
||||
},
|
||||
click: e => e.fetch(),
|
||||
customize: function (_input, _inputRect, container) {
|
||||
container.style.zIndex = foundry.applications.api.ApplicationV2._maxZ;
|
||||
},
|
||||
minLength: 0
|
||||
});
|
||||
});
|
||||
|
||||
htmlElement.querySelectorAll('.team-push-input').forEach(element => {
|
||||
autocomplete({
|
||||
input: element,
|
||||
fetch: function (text, update) {
|
||||
if (!text) {
|
||||
update(memberChoices);
|
||||
} else {
|
||||
text = text.toLowerCase();
|
||||
var suggestions = memberChoices.filter(n => n.name.toLowerCase().includes(text));
|
||||
update(suggestions);
|
||||
}
|
||||
},
|
||||
render: function (actor, search) {
|
||||
const actorName = game.i18n.localize(actor.name);
|
||||
const matchIndex = actorName.toLowerCase().indexOf(search);
|
||||
|
||||
const beforeText = actorName.slice(0, matchIndex);
|
||||
const matchText = actorName.slice(matchIndex, matchIndex + search.length);
|
||||
const after = actorName.slice(matchIndex + search.length, actorName.length);
|
||||
const img = document.createElement('img');
|
||||
img.src = actor.img;
|
||||
|
||||
const element = document.createElement('li');
|
||||
element.appendChild(img);
|
||||
|
||||
const label = document.createElement('span');
|
||||
label.innerHTML =
|
||||
`${beforeText}${matchText ? `<strong>${matchText}</strong>` : ''}${after}`.replaceAll(
|
||||
' ',
|
||||
' '
|
||||
);
|
||||
element.appendChild(label);
|
||||
|
||||
return element;
|
||||
},
|
||||
renderGroup: function (label) {
|
||||
const itemElement = document.createElement('div');
|
||||
itemElement.textContent = game.i18n.localize(label);
|
||||
return itemElement;
|
||||
},
|
||||
onSelect: actor => {
|
||||
element.value = actor.uuid;
|
||||
this.actorsMembers.push({ actor: actor, trait: 'agility', difficulty: 0 });
|
||||
this.render({ force: true });
|
||||
},
|
||||
click: e => e.fetch(),
|
||||
customize: function (_input, _inputRect, container) {
|
||||
container.style.zIndex = foundry.applications.api.ApplicationV2._maxZ;
|
||||
},
|
||||
minLength: 0
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.leader = this.actorLeader;
|
||||
context.members = this.actorsMembers;
|
||||
context.traitList = abilities;
|
||||
|
||||
context.allSelected = this.actorsMembers.length + (this.actorLeader?.actor ? 1 : 0) === this.actors.length;
|
||||
context.rollDisabled = context.members.length === 0 || !this.actorLeader?.actor;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static updateData(event, _, formData) {
|
||||
const { actorLeader, actorsMembers } = foundry.utils.expandObject(formData.object);
|
||||
this.actorLeader = foundry.utils.mergeObject(this.actorLeader, actorLeader);
|
||||
this.actorsMembers = foundry.utils.mergeObject(this.actorsMembers, actorsMembers);
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
static async #removeLeader(_, button) {
|
||||
this.actorLeader = null;
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async #removeMember(_, button) {
|
||||
this.actorsMembers = this.actorsMembers.filter(m => m.actor.uuid !== button.dataset.memberUuid);
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async #roll() {
|
||||
const cls = getDocumentClass('ChatMessage');
|
||||
const systemData = {
|
||||
leader: this.actorLeader,
|
||||
members: this.actorsMembers
|
||||
};
|
||||
const msg = {
|
||||
type: 'groupRoll',
|
||||
user: game.user.id,
|
||||
speaker: cls.getSpeaker(),
|
||||
title: game.i18n.localize('DAGGERHEART.UI.Chat.groupRoll.title'),
|
||||
system: systemData,
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/groupRoll.hbs',
|
||||
{ system: systemData }
|
||||
)
|
||||
};
|
||||
|
||||
cls.create(msg);
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
527
module/applications/dialogs/groupRollDialog.mjs
Normal file
527
module/applications/dialogs/groupRollDialog.mjs
Normal file
|
|
@ -0,0 +1,527 @@
|
|||
import { ResourceUpdateMap } from '../../data/action/baseAction.mjs';
|
||||
import { emitAsGM, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
|
||||
import Party from '../sheets/actors/party.mjs';
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
export default class GroupRollDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
constructor(party) {
|
||||
super();
|
||||
|
||||
this.party = party;
|
||||
this.partyMembers = party.system.partyMembers
|
||||
.filter(x => Party.DICE_ROLL_ACTOR_TYPES.includes(x.type))
|
||||
.map(member => ({
|
||||
...member.toObject(),
|
||||
uuid: member.uuid,
|
||||
id: member.id,
|
||||
selected: true,
|
||||
owned: member.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
|
||||
}));
|
||||
|
||||
this.leader = null;
|
||||
this.openForAllPlayers = true;
|
||||
|
||||
this.tabGroups.application = Object.keys(party.system.groupRoll.participants).length
|
||||
? 'groupRoll'
|
||||
: 'initialization';
|
||||
|
||||
Hooks.on(socketEvent.Refresh, this.groupRollRefresh.bind());
|
||||
}
|
||||
|
||||
get title() {
|
||||
return game.i18n.localize('DAGGERHEART.APPLICATIONS.GroupRollSelect.title');
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
id: 'GroupRollDialog',
|
||||
classes: ['daggerheart', 'views', 'dh-style', 'dialog', 'group-roll-dialog'],
|
||||
position: { width: 550, height: 'auto' },
|
||||
actions: {
|
||||
toggleSelectMember: this.#toggleSelectMember,
|
||||
startGroupRoll: this.#startGroupRoll,
|
||||
makeRoll: this.#makeRoll,
|
||||
removeRoll: this.#removeRoll,
|
||||
rerollDice: this.#rerollDice,
|
||||
makeLeaderRoll: this.#makeLeaderRoll,
|
||||
removeLeaderRoll: this.#removeLeaderRoll,
|
||||
rerollLeaderDice: this.#rerollLeaderDice,
|
||||
markSuccessfull: this.#markSuccessfull,
|
||||
cancelRoll: this.#onCancelRoll,
|
||||
finishRoll: this.#finishRoll
|
||||
},
|
||||
form: { handler: this.updateData, submitOnChange: true, closeOnSubmit: false }
|
||||
};
|
||||
|
||||
static PARTS = {
|
||||
initialization: {
|
||||
id: 'initialization',
|
||||
template: 'systems/daggerheart/templates/dialogs/groupRollDialog/initialization.hbs'
|
||||
},
|
||||
leader: {
|
||||
id: 'leader',
|
||||
template: 'systems/daggerheart/templates/dialogs/groupRollDialog/leader.hbs'
|
||||
},
|
||||
groupRoll: {
|
||||
id: 'groupRoll',
|
||||
template: 'systems/daggerheart/templates/dialogs/groupRollDialog/groupRoll.hbs'
|
||||
},
|
||||
footer: {
|
||||
id: 'footer',
|
||||
template: 'systems/daggerheart/templates/dialogs/groupRollDialog/footer.hbs'
|
||||
}
|
||||
};
|
||||
|
||||
/** @inheritdoc */
|
||||
static TABS = {
|
||||
application: {
|
||||
tabs: [{ id: 'initialization' }, { id: 'groupRoll' }]
|
||||
}
|
||||
};
|
||||
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
htmlElement
|
||||
.querySelector('.main-character-field')
|
||||
?.addEventListener('input', this.updateLeaderField.bind(this));
|
||||
}
|
||||
|
||||
_configureRenderParts(options) {
|
||||
const { initialization, leader, groupRoll, footer } = super._configureRenderParts(options);
|
||||
const augmentedParts = { initialization };
|
||||
for (const memberKey of Object.keys(this.party.system.groupRoll.aidingCharacters)) {
|
||||
augmentedParts[memberKey] = {
|
||||
id: memberKey,
|
||||
template: 'systems/daggerheart/templates/dialogs/groupRollDialog/groupRollMember.hbs'
|
||||
};
|
||||
}
|
||||
|
||||
augmentedParts.leader = leader;
|
||||
augmentedParts.groupRoll = groupRoll;
|
||||
augmentedParts.footer = footer;
|
||||
|
||||
return augmentedParts;
|
||||
}
|
||||
|
||||
/**@inheritdoc */
|
||||
async _onRender(context, options) {
|
||||
await super._onRender(context, options);
|
||||
|
||||
if (this.element.querySelector('.team-container')) return;
|
||||
|
||||
if (this.tabGroups.application !== this.constructor.PARTS.initialization.id) {
|
||||
const initializationPart = this.element.querySelector('.initialization-container');
|
||||
initializationPart.insertAdjacentHTML('afterend', '<div class="team-container"></div>');
|
||||
initializationPart.insertAdjacentHTML(
|
||||
'afterend',
|
||||
`<div class="section-title">${game.i18n.localize('Aiding Characters')}</div>`
|
||||
);
|
||||
|
||||
const teamContainer = this.element.querySelector('.team-container');
|
||||
for (const memberContainer of this.element.querySelectorAll('.team-member-container'))
|
||||
teamContainer.appendChild(memberContainer);
|
||||
}
|
||||
}
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
|
||||
context.isGM = game.user.isGM;
|
||||
context.isEditable = this.getIsEditable();
|
||||
context.fields = this.party.system.schema.fields.groupRoll.fields;
|
||||
context.data = this.party.system.groupRoll;
|
||||
context.traitOptions = CONFIG.DH.ACTOR.abilities;
|
||||
context.members = {};
|
||||
context.allHaveRolled = Object.keys(context.data.participants).every(key => {
|
||||
const data = context.data.participants[key];
|
||||
return Boolean(data.rollData);
|
||||
});
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
async _preparePartContext(partId, context, options) {
|
||||
const partContext = await super._preparePartContext(partId, context, options);
|
||||
partContext.partId = partId;
|
||||
|
||||
switch (partId) {
|
||||
case 'initialization':
|
||||
partContext.groupRollFields = this.party.system.schema.fields.groupRoll.fields;
|
||||
partContext.memberSelection = this.partyMembers;
|
||||
|
||||
const selectedMembers = partContext.memberSelection.filter(x => x.selected);
|
||||
|
||||
partContext.selectedLeader = this.leader;
|
||||
partContext.selectedLeaderOptions = selectedMembers
|
||||
.filter(actor => actor.owned)
|
||||
.map(x => ({ value: x.id, label: x.name }));
|
||||
partContext.selectedLeaderDisabled = !selectedMembers.length;
|
||||
|
||||
partContext.canStartGroupRoll = selectedMembers.length > 1 && this.leader?.memberId;
|
||||
partContext.openForAllPlayers = this.openForAllPlayers;
|
||||
break;
|
||||
case 'leader':
|
||||
partContext.leader = this.getRollCharacterData(this.party.system.groupRoll.leader);
|
||||
break;
|
||||
case 'groupRoll':
|
||||
const leader = this.party.system.groupRoll.leader;
|
||||
partContext.hasRolled =
|
||||
leader?.rollData ||
|
||||
Object.values(this.party.system.groupRoll?.aidingCharacters ?? {}).some(
|
||||
x => x.successfull !== null
|
||||
);
|
||||
const { modifierTotal, modifiers } = Object.values(this.party.system.groupRoll.aidingCharacters).reduce(
|
||||
(acc, curr) => {
|
||||
const modifier = curr.successfull === true ? 1 : curr.successfull === false ? -1 : null;
|
||||
if (modifier) {
|
||||
acc.modifierTotal += modifier;
|
||||
acc.modifiers.push(modifier);
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
{ modifierTotal: 0, modifiers: [] }
|
||||
);
|
||||
const leaderTotal = leader?.rollData ? leader.roll.total : null;
|
||||
partContext.groupRoll = {
|
||||
totalLabel: leader?.rollData
|
||||
? game.i18n.format('DAGGERHEART.GENERAL.withThing', {
|
||||
thing: leader.roll.totalLabel
|
||||
})
|
||||
: null,
|
||||
totalDualityClass: leader?.roll?.isCritical ? 'critical' : leader?.roll?.withHope ? 'hope' : 'fear',
|
||||
total: leaderTotal + modifierTotal,
|
||||
leaderTotal: leaderTotal,
|
||||
modifiers
|
||||
};
|
||||
break;
|
||||
case 'footer':
|
||||
partContext.canFinishRoll =
|
||||
Boolean(this.party.system.groupRoll.leader?.rollData) &&
|
||||
Object.values(this.party.system.groupRoll.aidingCharacters).every(x => x.successfull !== null);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Object.keys(this.party.system.groupRoll.aidingCharacters).includes(partId)) {
|
||||
const characterData = this.party.system.groupRoll.aidingCharacters[partId];
|
||||
partContext.members[partId] = this.getRollCharacterData(characterData, partId);
|
||||
}
|
||||
|
||||
return partContext;
|
||||
}
|
||||
|
||||
getRollCharacterData(data, partId) {
|
||||
if (!data) return {};
|
||||
|
||||
const actor = game.actors.get(data.id);
|
||||
|
||||
return {
|
||||
...data,
|
||||
roll: data.roll,
|
||||
isEditable: actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER),
|
||||
key: partId,
|
||||
readyToRoll: Boolean(data.rollChoice),
|
||||
hasRolled: Boolean(data.rollData)
|
||||
};
|
||||
}
|
||||
|
||||
static async updateData(event, _, formData) {
|
||||
const partyData = foundry.utils.expandObject(formData.object);
|
||||
|
||||
this.updatePartyData(partyData, this.getUpdatingParts(event.target));
|
||||
}
|
||||
|
||||
async updatePartyData(update, updatingParts, options = { render: true }) {
|
||||
if (!game.users.activeGM)
|
||||
return ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.gmRequired'));
|
||||
|
||||
const gmUpdate = async update => {
|
||||
await this.party.update(update);
|
||||
this.render({ parts: updatingParts });
|
||||
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
||||
action: socketEvent.Refresh,
|
||||
data: { refreshType: RefreshType.GroupRoll, action: 'refresh', parts: updatingParts }
|
||||
});
|
||||
};
|
||||
|
||||
await emitAsGM(
|
||||
GMUpdateEvent.UpdateDocument,
|
||||
gmUpdate,
|
||||
update,
|
||||
this.party.uuid,
|
||||
options.render ? { refreshType: RefreshType.GroupRoll, action: 'refresh', parts: updatingParts } : undefined
|
||||
);
|
||||
}
|
||||
|
||||
getUpdatingParts(target) {
|
||||
const { initialization, leader, groupRoll, footer } = this.constructor.PARTS;
|
||||
const isInitialization = this.tabGroups.application === initialization.id;
|
||||
const updatingMember = target.closest('.team-member-container')?.dataset?.memberKey;
|
||||
const updatingLeader = target.closest('.main-character-outer-container');
|
||||
|
||||
return [
|
||||
...(isInitialization ? [initialization.id] : []),
|
||||
...(updatingMember ? [updatingMember] : []),
|
||||
...(updatingLeader ? [leader.id] : []),
|
||||
...(!isInitialization ? [groupRoll.id, footer.id] : [])
|
||||
];
|
||||
}
|
||||
|
||||
getIsEditable() {
|
||||
return this.party.system.partyMembers.some(actor => {
|
||||
const selected = Boolean(this.party.system.groupRoll.participants[actor.id]);
|
||||
return selected && actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER);
|
||||
});
|
||||
}
|
||||
|
||||
groupRollRefresh = ({ refreshType, action, parts }) => {
|
||||
if (refreshType !== RefreshType.GroupRoll) return;
|
||||
|
||||
switch (action) {
|
||||
case 'startGroupRoll':
|
||||
this.tabGroups.application = 'groupRoll';
|
||||
break;
|
||||
case 'refresh':
|
||||
this.render({ parts });
|
||||
break;
|
||||
case 'close':
|
||||
this.close();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
async close(options = {}) {
|
||||
/* Opt out of Foundry's standard behavior of closing all application windows marked as UI when Escape is pressed */
|
||||
if (options.closeKey) return;
|
||||
|
||||
Hooks.off(socketEvent.Refresh, this.groupRollRefresh);
|
||||
return super.close(options);
|
||||
}
|
||||
|
||||
//#region Initialization
|
||||
static #toggleSelectMember(_, button) {
|
||||
const member = this.partyMembers.find(x => x.id === button.dataset.id);
|
||||
member.selected = !member.selected;
|
||||
this.render();
|
||||
}
|
||||
|
||||
updateLeaderField(event) {
|
||||
if (!this.leader) this.leader = {};
|
||||
this.leader.memberId = event.target.value;
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async #startGroupRoll() {
|
||||
const leader = this.partyMembers.find(x => x.id === this.leader.memberId);
|
||||
const aidingCharacters = this.partyMembers.reduce((acc, curr) => {
|
||||
if (curr.selected && curr.id !== this.leader.memberId)
|
||||
acc[curr.id] = { id: curr.id, name: curr.name, img: curr.img };
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
await this.party.update({
|
||||
'system.groupRoll': _replace(
|
||||
new game.system.api.data.GroupRollData({
|
||||
...this.party.system.groupRoll.toObject(),
|
||||
leader: { id: leader.id, name: leader.name, img: leader.img },
|
||||
aidingCharacters
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
const hookData = { openForAllPlayers: this.openForAllPlayers, partyId: this.party.id };
|
||||
Hooks.callAll(CONFIG.DH.HOOKS.hooksConfig.groupRollStart, hookData);
|
||||
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
||||
action: socketEvent.GroupRollStart,
|
||||
data: hookData
|
||||
});
|
||||
|
||||
this.render();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
async makeRoll(button, characterData, path) {
|
||||
const actor = game.actors.find(x => x.id === characterData.id);
|
||||
if (!actor) return;
|
||||
|
||||
const result = await actor.rollTrait(characterData.rollChoice, {
|
||||
skips: {
|
||||
createMessage: true,
|
||||
resources: true,
|
||||
triggers: true
|
||||
}
|
||||
});
|
||||
|
||||
if (!result) return;
|
||||
if (!game.modules.get('dice-so-nice')?.active) foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice });
|
||||
|
||||
const rollData = result.messageRoll.toJSON();
|
||||
delete rollData.options.messageRoll;
|
||||
this.updatePartyData(
|
||||
{
|
||||
[path]: rollData
|
||||
},
|
||||
this.getUpdatingParts(button)
|
||||
);
|
||||
}
|
||||
|
||||
static async #makeRoll(_event, button) {
|
||||
const { member } = button.dataset;
|
||||
const character = this.party.system.groupRoll.aidingCharacters[member];
|
||||
this.makeRoll(button, character, `system.groupRoll.aidingCharacters.${member}.rollData`);
|
||||
}
|
||||
|
||||
static async #makeLeaderRoll(_event, button) {
|
||||
const character = this.party.system.groupRoll.leader;
|
||||
this.makeRoll(button, character, 'system.groupRoll.leader.rollData');
|
||||
}
|
||||
|
||||
async removeRoll(button, path) {
|
||||
this.updatePartyData(
|
||||
{
|
||||
[path]: {
|
||||
rollData: null,
|
||||
rollChoice: null,
|
||||
selected: false,
|
||||
successfull: null
|
||||
}
|
||||
},
|
||||
this.getUpdatingParts(button)
|
||||
);
|
||||
}
|
||||
|
||||
static async #removeRoll(_event, button) {
|
||||
this.removeRoll(button, `system.groupRoll.aidingCharacters.${button.dataset.member}`);
|
||||
}
|
||||
|
||||
static async #removeLeaderRoll(_event, button) {
|
||||
this.removeRoll(button, 'system.groupRoll.leader');
|
||||
}
|
||||
|
||||
async rerollDice(button, data, path) {
|
||||
const { diceType } = button.dataset;
|
||||
|
||||
const dieIndex = diceType === 'hope' ? 0 : diceType === 'fear' ? 1 : 2;
|
||||
const newRoll = game.system.api.dice.DualityRoll.fromData(data.rollData);
|
||||
const dice = newRoll.dice[dieIndex];
|
||||
await dice.reroll(`/r1=${dice.total}`, {
|
||||
liveRoll: {
|
||||
roll: newRoll,
|
||||
isReaction: true
|
||||
}
|
||||
});
|
||||
const rollData = newRoll.toJSON();
|
||||
this.updatePartyData(
|
||||
{
|
||||
[path]: rollData
|
||||
},
|
||||
this.getUpdatingParts(button)
|
||||
);
|
||||
}
|
||||
|
||||
static async #rerollDice(_, button) {
|
||||
const { member } = button.dataset;
|
||||
this.rerollDice(
|
||||
button,
|
||||
this.party.system.groupRoll.aidingCharacters[member],
|
||||
`system.groupRoll.aidingCharacters.${member}.rollData`
|
||||
);
|
||||
}
|
||||
|
||||
static async #rerollLeaderDice(_, button) {
|
||||
this.rerollDice(button, this.party.system.groupRoll.leader, `system.groupRoll.leader.rollData`);
|
||||
}
|
||||
|
||||
static #markSuccessfull(_event, button) {
|
||||
const previousValue = this.party.system.groupRoll.aidingCharacters[button.dataset.member].successfull;
|
||||
const newValue = Boolean(button.dataset.successfull === 'true');
|
||||
this.updatePartyData(
|
||||
{
|
||||
[`system.groupRoll.aidingCharacters.${button.dataset.member}.successfull`]:
|
||||
previousValue === newValue ? null : newValue
|
||||
},
|
||||
this.getUpdatingParts(button)
|
||||
);
|
||||
}
|
||||
|
||||
static async #onCancelRoll(_event, _button, options = { confirm: true }) {
|
||||
this.cancelRoll(options);
|
||||
}
|
||||
|
||||
async cancelRoll(options = { confirm: true }) {
|
||||
if (options.confirm) {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.localize('DAGGERHEART.APPLICATIONS.GroupRollSelect.cancelConfirmTitle')
|
||||
},
|
||||
content: game.i18n.localize('DAGGERHEART.APPLICATIONS.GroupRollSelect.cancelConfirmText')
|
||||
});
|
||||
|
||||
if (!confirmed) return;
|
||||
}
|
||||
|
||||
await this.updatePartyData(
|
||||
{
|
||||
'system.groupRoll': {
|
||||
leader: null,
|
||||
aidingCharacters: _replace({})
|
||||
}
|
||||
},
|
||||
[],
|
||||
{ render: false }
|
||||
);
|
||||
|
||||
this.close();
|
||||
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
||||
action: socketEvent.Refresh,
|
||||
data: { refreshType: RefreshType.GroupRoll, action: 'close' }
|
||||
});
|
||||
}
|
||||
|
||||
static async #finishRoll() {
|
||||
const totalRoll = this.party.system.groupRoll.leader.roll;
|
||||
for (const character of Object.values(this.party.system.groupRoll.aidingCharacters)) {
|
||||
totalRoll.terms.push(new foundry.dice.terms.OperatorTerm({ operator: character.successfull ? '+' : '-' }));
|
||||
totalRoll.terms.push(new foundry.dice.terms.NumericTerm({ number: 1 }));
|
||||
}
|
||||
|
||||
await totalRoll._evaluate();
|
||||
|
||||
const systemData = totalRoll.options;
|
||||
const actor = game.actors.get(this.party.system.groupRoll.leader.id);
|
||||
|
||||
const cls = getDocumentClass('ChatMessage'),
|
||||
msgData = {
|
||||
type: 'dualityRoll',
|
||||
user: game.user.id,
|
||||
title: game.i18n.localize('DAGGERHEART.APPLICATIONS.GroupRollSelect.title'),
|
||||
speaker: cls.getSpeaker({ actor }),
|
||||
system: systemData,
|
||||
rolls: [JSON.stringify(totalRoll)],
|
||||
sound: null,
|
||||
flags: { core: { RollTable: true } }
|
||||
};
|
||||
|
||||
await cls.create(msgData);
|
||||
|
||||
const resourceMap = new ResourceUpdateMap(actor);
|
||||
if (totalRoll.isCritical) {
|
||||
resourceMap.addResources([
|
||||
{ key: 'stress', value: -1, total: 1 },
|
||||
{ key: 'hope', value: 1, total: 1 }
|
||||
]);
|
||||
} else if (totalRoll.withHope) {
|
||||
resourceMap.addResources([{ key: 'hope', value: 1, total: 1 }]);
|
||||
} else {
|
||||
resourceMap.addResources([{ key: 'fear', value: 1, total: 1 }]);
|
||||
}
|
||||
|
||||
resourceMap.updateResources();
|
||||
|
||||
/* Fin */
|
||||
this.cancelRoll({ confirm: false });
|
||||
}
|
||||
}
|
||||
|
|
@ -366,8 +366,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
let rollIsSelected = false;
|
||||
for (const member of Object.values(members)) {
|
||||
const rollFinished = Boolean(member.rollData);
|
||||
const damageFinished =
|
||||
member.rollData?.options?.hasDamage !== undefined ? member.rollData.options.damage : true;
|
||||
const damageFinished = member.rollData?.options?.hasDamage ? Boolean(member.rollData.options.damage) : true;
|
||||
|
||||
rollsAreFinished = rollsAreFinished && rollFinished && damageFinished;
|
||||
rollIsSelected = rollIsSelected || member.selected;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import DHBaseActorSheet from '../api/base-actor.mjs';
|
||||
import { getDocFromElement } from '../../../helpers/utils.mjs';
|
||||
import { getDocFromElement, sortBy } from '../../../helpers/utils.mjs';
|
||||
import { ItemBrowser } from '../../ui/itemBrowser.mjs';
|
||||
import FilterMenu from '../../ux/filter-menu.mjs';
|
||||
import DaggerheartMenu from '../../sidebar/tabs/daggerheartMenu.mjs';
|
||||
import { socketEvent } from '../../../systemRegistration/socket.mjs';
|
||||
import GroupRollDialog from '../../dialogs/group-roll-dialog.mjs';
|
||||
import DhpActor from '../../../documents/actor.mjs';
|
||||
|
||||
export default class Party extends DHBaseActorSheet {
|
||||
|
|
@ -18,13 +17,14 @@ export default class Party extends DHBaseActorSheet {
|
|||
static DEFAULT_OPTIONS = {
|
||||
classes: ['party'],
|
||||
position: {
|
||||
width: 550,
|
||||
width: 600,
|
||||
height: 900
|
||||
},
|
||||
window: {
|
||||
resizable: true
|
||||
},
|
||||
actions: {
|
||||
openDocument: Party.#openDocument,
|
||||
deletePartyMember: Party.#deletePartyMember,
|
||||
deleteItem: Party.#deleteItem,
|
||||
toggleHope: Party.#toggleHope,
|
||||
|
|
@ -45,10 +45,6 @@ export default class Party extends DHBaseActorSheet {
|
|||
header: { template: 'systems/daggerheart/templates/sheets/actors/party/header.hbs' },
|
||||
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||
partyMembers: { template: 'systems/daggerheart/templates/sheets/actors/party/party-members.hbs' },
|
||||
resources: {
|
||||
template: 'systems/daggerheart/templates/sheets/actors/party/resources.hbs',
|
||||
scrollable: ['']
|
||||
},
|
||||
/* NOT YET IMPLEMENTED */
|
||||
// projects: {
|
||||
// template: 'systems/daggerheart/templates/sheets/actors/party/projects.hbs',
|
||||
|
|
@ -66,7 +62,6 @@ export default class Party extends DHBaseActorSheet {
|
|||
primary: {
|
||||
tabs: [
|
||||
{ id: 'partyMembers' },
|
||||
{ id: 'resources' },
|
||||
/* NOT YET IMPLEMENTED */
|
||||
// { id: 'projects' },
|
||||
{ id: 'inventory' },
|
||||
|
|
@ -96,6 +91,8 @@ export default class Party extends DHBaseActorSheet {
|
|||
case 'header':
|
||||
await this._prepareHeaderContext(context, options);
|
||||
break;
|
||||
case 'partyMembers':
|
||||
await this._prepareMembersContext(context, options);
|
||||
case 'notes':
|
||||
await this._prepareNotesContext(context, options);
|
||||
break;
|
||||
|
|
@ -119,6 +116,60 @@ export default class Party extends DHBaseActorSheet {
|
|||
relativeTo: this.document
|
||||
});
|
||||
context.tagTeamActive = Boolean(this.document.system.tagTeam.initiator);
|
||||
context.groupRollActive = Boolean(this.document.system.groupRoll.leader);
|
||||
}
|
||||
|
||||
async _prepareMembersContext(context, _options) {
|
||||
context.partyMembers = [];
|
||||
const traits = ['agility', 'strength', 'finesse', 'instinct', 'presence', 'knowledge'];
|
||||
for (const actor of this.document.system.partyMembers) {
|
||||
const weapons = [];
|
||||
if (actor.type === 'character') {
|
||||
if (actor.system.usedUnarmed) {
|
||||
weapons.push(actor.system.usedUnarmed);
|
||||
}
|
||||
const equipped = actor.items.filter(i => i.system.equipped && i.type === 'weapon');
|
||||
weapons.push(...sortBy(equipped, i => (i.system.secondary ? 1 : 0)));
|
||||
}
|
||||
|
||||
context.partyMembers.push({
|
||||
uuid: actor.uuid,
|
||||
img: actor.img,
|
||||
name: actor.name,
|
||||
subtitle: (() => {
|
||||
if (!['character', 'companion'].includes(actor.type)) {
|
||||
return game.i18n.format(`TYPES.Actor.${actor.type}`);
|
||||
}
|
||||
|
||||
const { value: classItem, subclass } = actor.system.class ?? {};
|
||||
const partner = actor.system.partner;
|
||||
const ancestry = actor.system.ancestry;
|
||||
const community = actor.system.community;
|
||||
if (partner || (classItem && subclass && ancestry && community)) {
|
||||
return game.i18n.format(`DAGGERHEART.ACTORS.Party.Subtitle.${actor.type}`, {
|
||||
class: classItem?.name,
|
||||
subclass: subclass?.name,
|
||||
partner: partner?.name,
|
||||
ancestry: ancestry?.name,
|
||||
community: community?.name
|
||||
});
|
||||
}
|
||||
})(),
|
||||
type: actor.type,
|
||||
resources: actor.system.resources,
|
||||
armorScore: actor.system.armorScore,
|
||||
damageThresholds: actor.system.damageThresholds,
|
||||
evasion: actor.system.evasion,
|
||||
difficulty: actor.system.difficulty,
|
||||
traits: actor.system.traits
|
||||
? traits.map(t => ({
|
||||
label: game.i18n.localize(`DAGGERHEART.CONFIG.Traits.${t}.short`),
|
||||
value: actor.system.traits[t].value
|
||||
}))
|
||||
: null,
|
||||
weapons
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -149,6 +200,12 @@ export default class Party extends DHBaseActorSheet {
|
|||
}
|
||||
}
|
||||
|
||||
static async #openDocument(_, target) {
|
||||
const uuid = target.dataset.uuid;
|
||||
const document = await foundry.utils.fromUuid(uuid);
|
||||
document?.sheet?.render(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles a hope resource value.
|
||||
* @type {ApplicationClickAction}
|
||||
|
|
@ -190,7 +247,7 @@ export default class Party extends DHBaseActorSheet {
|
|||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #toggleArmorSlot(_, target) {
|
||||
const actor = game.actors.get(target.dataset.actorId);
|
||||
const actor = await foundry.utils.fromUuid(target.dataset.actorId);
|
||||
const { value, max } = actor.system.armorScore;
|
||||
const inputValue = Number.parseInt(target.dataset.value);
|
||||
const newValue = value >= inputValue ? inputValue - 1 : inputValue;
|
||||
|
|
@ -261,9 +318,7 @@ export default class Party extends DHBaseActorSheet {
|
|||
}
|
||||
|
||||
static async #groupRoll(_params) {
|
||||
new GroupRollDialog(
|
||||
this.document.system.partyMembers.filter(x => Party.DICE_ROLL_ACTOR_TYPES.includes(x.type))
|
||||
).render({ force: true });
|
||||
new game.system.api.applications.dialogs.GroupRollDialog(this.document).render({ force: true });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
|
@ -425,25 +480,23 @@ export default class Party extends DHBaseActorSheet {
|
|||
}
|
||||
|
||||
static async #deletePartyMember(event, target) {
|
||||
const doc = await getDocFromElement(target.closest('.inventory-item'));
|
||||
|
||||
const doc = await foundry.utils.fromUuid(target.closest('[data-uuid]')?.dataset.uuid);
|
||||
if (!event.shiftKey) {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.title', {
|
||||
type: game.i18n.localize('TYPES.Actor.adversary'),
|
||||
title: game.i18n.format('DAGGERHEART.ACTORS.Party.RemoveConfirmation.title', {
|
||||
name: doc.name
|
||||
})
|
||||
},
|
||||
content: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.text', { name: doc.name })
|
||||
content: game.i18n.format('DAGGERHEART.ACTORS.Party.RemoveConfirmation.text', { name: doc.name })
|
||||
});
|
||||
|
||||
if (!confirmed) return;
|
||||
}
|
||||
|
||||
const currentMembers = this.document.system.partyMembers.map(x => x.uuid);
|
||||
const newMemberdList = currentMembers.filter(uuid => uuid !== doc.uuid);
|
||||
await this.document.update({ 'system.partyMembers': newMemberdList });
|
||||
const newMembersList = currentMembers.filter(uuid => uuid !== doc.uuid);
|
||||
await this.document.update({ 'system.partyMembers': newMembersList });
|
||||
}
|
||||
|
||||
static async #deleteItem(event, target) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { abilities } from '../../config/actorConfig.mjs';
|
||||
import { enrichedDualityRoll } from '../../enrichers/DualityRollEnricher.mjs';
|
||||
import { enrichedFateRoll, getFateTypeData } from '../../enrichers/FateRollEnricher.mjs';
|
||||
import { getCommandTarget, rollCommandToJSON } from '../../helpers/utils.mjs';
|
||||
import { emitAsGM, GMUpdateEvent } from '../../systemRegistration/socket.mjs';
|
||||
|
||||
export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog {
|
||||
constructor(options) {
|
||||
|
|
@ -150,18 +148,6 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
html.querySelectorAll('.reroll-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.rerollEvent(event, message))
|
||||
);
|
||||
html.querySelectorAll('.group-roll-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.groupRollButton(event, message))
|
||||
);
|
||||
html.querySelectorAll('.group-roll-reroll').forEach(element =>
|
||||
element.addEventListener('click', event => this.groupRollReroll(event, message))
|
||||
);
|
||||
html.querySelectorAll('.group-roll-success').forEach(element =>
|
||||
element.addEventListener('click', event => this.groupRollSuccessEvent(event, message))
|
||||
);
|
||||
html.querySelectorAll('.group-roll-header-expand-section').forEach(element =>
|
||||
element.addEventListener('click', this.groupRollExpandSection)
|
||||
);
|
||||
html.querySelectorAll('.risk-it-all-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.riskItAllClearStressAndHitPoints(event, data))
|
||||
);
|
||||
|
|
@ -305,174 +291,6 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
}
|
||||
}
|
||||
|
||||
async groupRollButton(event, message) {
|
||||
const path = event.currentTarget.dataset.path;
|
||||
const isLeader = path === 'leader';
|
||||
const { actor: actorData, trait } = foundry.utils.getProperty(message.system, path);
|
||||
const actor = game.actors.get(actorData._id);
|
||||
|
||||
if (!actor) {
|
||||
return ui.notifications.error(
|
||||
game.i18n.format('DAGGERHEART.UI.Notifications.documentIsMissing', {
|
||||
documentType: game.i18n.localize('TYPES.Actor.character')
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (!actor.testUserPermission(game.user, 'OWNER')) {
|
||||
return ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.noActorOwnership'));
|
||||
}
|
||||
|
||||
const traitLabel = game.i18n.localize(abilities[trait].label);
|
||||
const config = {
|
||||
event: event,
|
||||
title: `${game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll')}: ${actor.name}`,
|
||||
headerTitle: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||
ability: traitLabel
|
||||
}),
|
||||
roll: {
|
||||
trait: trait,
|
||||
advantage: 0,
|
||||
modifiers: [{ label: traitLabel, value: actor.system.traits[trait].value }]
|
||||
},
|
||||
hasRoll: true,
|
||||
skips: {
|
||||
createMessage: true,
|
||||
resources: !isLeader,
|
||||
updateCountdowns: !isLeader
|
||||
}
|
||||
};
|
||||
const result = await actor.diceRoll({
|
||||
...config,
|
||||
headerTitle: `${game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll')}: ${actor.name}`,
|
||||
title: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||
ability: traitLabel
|
||||
})
|
||||
});
|
||||
|
||||
if (!result) return;
|
||||
|
||||
const newMessageData = foundry.utils.deepClone(message.system);
|
||||
foundry.utils.setProperty(newMessageData, `${path}.result`, result.roll);
|
||||
const renderData = { system: new game.system.api.models.chatMessages.config.groupRoll(newMessageData) };
|
||||
|
||||
const updatedContent = await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/groupRoll.hbs',
|
||||
{ ...renderData, user: game.user }
|
||||
);
|
||||
const mess = game.messages.get(message._id);
|
||||
|
||||
await emitAsGM(
|
||||
GMUpdateEvent.UpdateDocument,
|
||||
mess.update.bind(mess),
|
||||
{
|
||||
...renderData,
|
||||
content: updatedContent
|
||||
},
|
||||
mess.uuid
|
||||
);
|
||||
}
|
||||
|
||||
async groupRollReroll(event, message) {
|
||||
const path = event.currentTarget.dataset.path;
|
||||
const { actor: actorData, trait } = foundry.utils.getProperty(message.system, path);
|
||||
const actor = game.actors.get(actorData._id);
|
||||
|
||||
if (!actor.testUserPermission(game.user, 'OWNER')) {
|
||||
return ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.noActorOwnership'));
|
||||
}
|
||||
|
||||
const traitLabel = game.i18n.localize(abilities[trait].label);
|
||||
|
||||
const config = {
|
||||
event: event,
|
||||
title: `${game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll')}: ${actor.name}`,
|
||||
headerTitle: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||
ability: traitLabel
|
||||
}),
|
||||
roll: {
|
||||
trait: trait,
|
||||
advantage: 0,
|
||||
modifiers: [{ label: traitLabel, value: actor.system.traits[trait].value }]
|
||||
},
|
||||
hasRoll: true,
|
||||
skips: {
|
||||
createMessage: true,
|
||||
updateCountdowns: true
|
||||
}
|
||||
};
|
||||
const result = await actor.diceRoll({
|
||||
...config,
|
||||
headerTitle: `${game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll')}: ${actor.name}`,
|
||||
title: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||
ability: traitLabel
|
||||
})
|
||||
});
|
||||
|
||||
const newMessageData = foundry.utils.deepClone(message.system);
|
||||
foundry.utils.setProperty(newMessageData, `${path}.result`, { ...result.roll, rerolled: true });
|
||||
const renderData = { system: new game.system.api.models.chatMessages.config.groupRoll(newMessageData) };
|
||||
|
||||
const updatedContent = await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/groupRoll.hbs',
|
||||
{ ...renderData, user: game.user }
|
||||
);
|
||||
const mess = game.messages.get(message._id);
|
||||
await emitAsGM(
|
||||
GMUpdateEvent.UpdateDocument,
|
||||
mess.update.bind(mess),
|
||||
{
|
||||
...renderData,
|
||||
content: updatedContent
|
||||
},
|
||||
mess.uuid
|
||||
);
|
||||
}
|
||||
|
||||
async groupRollSuccessEvent(event, message) {
|
||||
if (!game.user.isGM) {
|
||||
return ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.gmOnly'));
|
||||
}
|
||||
|
||||
const { path, success } = event.currentTarget.dataset;
|
||||
const { actor: actorData } = foundry.utils.getProperty(message.system, path);
|
||||
const actor = game.actors.get(actorData._id);
|
||||
|
||||
if (!actor.testUserPermission(game.user, 'OWNER')) {
|
||||
return ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.noActorOwnership'));
|
||||
}
|
||||
|
||||
const newMessageData = foundry.utils.deepClone(message.system);
|
||||
foundry.utils.setProperty(newMessageData, `${path}.manualSuccess`, Boolean(success));
|
||||
const renderData = { system: new game.system.api.models.chatMessages.config.groupRoll(newMessageData) };
|
||||
|
||||
const updatedContent = await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/ui/chat/groupRoll.hbs',
|
||||
{ ...renderData, user: game.user }
|
||||
);
|
||||
const mess = game.messages.get(message._id);
|
||||
await emitAsGM(
|
||||
GMUpdateEvent.UpdateDocument,
|
||||
mess.update.bind(mess),
|
||||
{
|
||||
...renderData,
|
||||
content: updatedContent
|
||||
},
|
||||
mess.uuid
|
||||
);
|
||||
}
|
||||
|
||||
async groupRollExpandSection(event) {
|
||||
event.target
|
||||
.closest('.group-roll-header-expand-section')
|
||||
.querySelectorAll('i')
|
||||
.forEach(element => {
|
||||
element.classList.toggle('fa-angle-up');
|
||||
element.classList.toggle('fa-angle-down');
|
||||
});
|
||||
event.target.closest('.group-roll-section').querySelector('.group-roll-content').classList.toggle('closed');
|
||||
}
|
||||
|
||||
async riskItAllClearStressAndHitPoints(event, data) {
|
||||
const resourceValue = event.target.dataset.resourceValue;
|
||||
const actor = game.actors.get(event.target.dataset.actorId);
|
||||
|
|
|
|||
|
|
@ -137,6 +137,8 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
}
|
||||
|
||||
static #getPlayerOwnership(user, setting, countdown) {
|
||||
if (user.isGM) return CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER;
|
||||
|
||||
const playerOwnership = countdown.ownership[user.id];
|
||||
return playerOwnership === undefined || playerOwnership === CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT
|
||||
? setting.defaultOwnership
|
||||
|
|
|
|||
|
|
@ -70,6 +70,14 @@ export const range = {
|
|||
}
|
||||
};
|
||||
|
||||
export const groupAttackRange = {
|
||||
melee: range.melee,
|
||||
veryClose: range.veryClose,
|
||||
close: range.close,
|
||||
far: range.far,
|
||||
veryFar: range.veryFar
|
||||
};
|
||||
|
||||
/* circle|cone|rect|ray used to be CONST.MEASURED_TEMPLATE_TYPES. Hardcoded for now */
|
||||
export const templateTypes = {
|
||||
CIRCLE: 'circle',
|
||||
|
|
@ -484,7 +492,7 @@ export const defaultRestOptions = {
|
|||
value: {
|
||||
custom: {
|
||||
enabled: true,
|
||||
formula: '@system.armorScore'
|
||||
formula: '@system.armorScore.max'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -708,14 +716,14 @@ const getDiceSoNiceSFX = sfxOptions => {
|
|||
if (sfxOptions.critical && criticalAnimationData.class) {
|
||||
return {
|
||||
specialEffect: criticalAnimationData.class,
|
||||
options: {}
|
||||
options: { ...criticalAnimationData.options }
|
||||
};
|
||||
}
|
||||
|
||||
if (sfxOptions.higher && sfxOptions.data.higher) {
|
||||
return {
|
||||
specialEffect: sfxOptions.data.higher.class,
|
||||
options: {}
|
||||
options: { ...sfxOptions.data.higher.options }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
export const hooksConfig = {
|
||||
effectDisplayToggle: 'DHEffectDisplayToggle',
|
||||
lockedTooltipDismissed: 'DHLockedTooltipDismissed',
|
||||
tagTeamStart: 'DHTagTeamRollStart'
|
||||
tagTeamStart: 'DHTagTeamRollStart',
|
||||
groupRollStart: 'DHGroupRollStart'
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ export { default as DhRollTable } from './rollTable.mjs';
|
|||
export { default as RegisteredTriggers } from './registeredTriggers.mjs';
|
||||
export { default as CompendiumBrowserSettings } from './compendiumBrowserSettings.mjs';
|
||||
export { default as TagTeamData } from './tagTeamData.mjs';
|
||||
export { default as GroupRollData } from './groupRollData.mjs';
|
||||
export { default as SpotlightTracker } from './spotlightTracker.mjs';
|
||||
|
||||
export * as countdowns from './countdowns.mjs';
|
||||
|
|
|
|||
|
|
@ -280,6 +280,26 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
|||
}
|
||||
};
|
||||
|
||||
if (this.damage) {
|
||||
config.isDirect = this.damage.direct;
|
||||
|
||||
const groupAttackTokens = this.damage.groupAttack
|
||||
? game.system.api.fields.ActionFields.DamageField.getGroupAttackTokens(
|
||||
this.actor.id,
|
||||
this.damage.groupAttack
|
||||
)
|
||||
: null;
|
||||
|
||||
config.damageOptions = {
|
||||
groupAttack: this.damage.groupAttack
|
||||
? {
|
||||
numAttackers: Math.max(groupAttackTokens.length, 1),
|
||||
range: this.damage.groupAttack
|
||||
}
|
||||
: null
|
||||
};
|
||||
}
|
||||
|
||||
DHBaseAction.applyKeybindings(config);
|
||||
return config;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ export default class ArmorChange extends foundry.abstract.DataModel {
|
|||
{
|
||||
...change,
|
||||
key: 'system.damageThresholds.major',
|
||||
type: CONFIG.DH.GENERAL.activeEffectModes.override.id,
|
||||
type: CONFIG.DH.GENERAL.activeEffectModes.add.id,
|
||||
priority: 50,
|
||||
value: major
|
||||
},
|
||||
|
|
@ -96,7 +96,7 @@ export default class ArmorChange extends foundry.abstract.DataModel {
|
|||
{
|
||||
...change,
|
||||
key: 'system.damageThresholds.severe',
|
||||
type: CONFIG.DH.GENERAL.activeEffectModes.override.id,
|
||||
type: CONFIG.DH.GENERAL.activeEffectModes.add.id,
|
||||
priority: 50,
|
||||
value: severe
|
||||
},
|
||||
|
|
@ -111,6 +111,8 @@ export default class ArmorChange extends foundry.abstract.DataModel {
|
|||
};
|
||||
|
||||
get isSuppressed() {
|
||||
if (!this.parent.parent?.actor) return false;
|
||||
|
||||
switch (this.value.interaction) {
|
||||
case CONFIG.DH.GENERAL.activeEffectArmorInteraction.active.id:
|
||||
return !this.parent.parent?.actor.system.armor;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import BaseDataActor from './base.mjs';
|
||||
import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs';
|
||||
import TagTeamData from '../tagTeamData.mjs';
|
||||
import GroupRollData from '../groupRollData.mjs';
|
||||
|
||||
export default class DhParty extends BaseDataActor {
|
||||
/**@inheritdoc */
|
||||
|
|
@ -16,7 +17,8 @@ export default class DhParty extends BaseDataActor {
|
|||
bags: new fields.NumberField({ initial: 0, integer: true }),
|
||||
chests: new fields.NumberField({ initial: 0, integer: true })
|
||||
}),
|
||||
tagTeam: new fields.EmbeddedDataField(TagTeamData)
|
||||
tagTeam: new fields.EmbeddedDataField(TagTeamData),
|
||||
groupRoll: new fields.EmbeddedDataField(GroupRollData)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import DHAbilityUse from './abilityUse.mjs';
|
||||
import DHActorRoll from './actorRoll.mjs';
|
||||
import DHGroupRoll from './groupRoll.mjs';
|
||||
import DHSystemMessage from './systemMessage.mjs';
|
||||
|
||||
export const config = {
|
||||
|
|
@ -9,6 +8,5 @@ export const config = {
|
|||
damageRoll: DHActorRoll,
|
||||
dualityRoll: DHActorRoll,
|
||||
fateRoll: DHActorRoll,
|
||||
groupRoll: DHGroupRoll,
|
||||
systemMessage: DHSystemMessage
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
|
|||
action: new fields.StringField()
|
||||
}),
|
||||
damage: new fields.ObjectField(),
|
||||
damageOptions: new fields.ObjectField(),
|
||||
costs: new fields.ArrayField(new fields.ObjectField()),
|
||||
successConsumed: new fields.BooleanField({ initial: false })
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
import { abilities } from '../../config/actorConfig.mjs';
|
||||
|
||||
export default class DHGroupRoll extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
return {
|
||||
leader: new fields.EmbeddedDataField(GroupRollMemberField),
|
||||
members: new fields.ArrayField(new fields.EmbeddedDataField(GroupRollMemberField))
|
||||
};
|
||||
}
|
||||
|
||||
get totalModifier() {
|
||||
return this.members.reduce((acc, m) => {
|
||||
if (m.manualSuccess === null) return acc;
|
||||
|
||||
return acc + (m.manualSuccess ? 1 : -1);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
class GroupRollMemberField extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
return {
|
||||
actor: new fields.ObjectField(),
|
||||
trait: new fields.StringField({ choices: abilities }),
|
||||
difficulty: new fields.StringField(),
|
||||
result: new fields.ObjectField({ nullable: true, initial: null }),
|
||||
manualSuccess: new fields.BooleanField({ nullable: true, initial: null })
|
||||
};
|
||||
}
|
||||
|
||||
/* Can be expanded if we handle automation of success/failure */
|
||||
get success() {
|
||||
return manualSuccess;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,10 +5,6 @@ export default class DhCountdowns extends foundry.abstract.DataModel {
|
|||
const fields = foundry.data.fields;
|
||||
|
||||
return {
|
||||
/* Outdated and unused. Needed for migration. Remove in next minor version. (1.3) */
|
||||
narrative: new fields.EmbeddedDataField(DhCountdownData),
|
||||
encounter: new fields.EmbeddedDataField(DhCountdownData),
|
||||
/**/
|
||||
countdowns: new fields.TypedObjectField(new fields.EmbeddedDataField(DhCountdown)),
|
||||
defaultOwnership: new fields.NumberField({
|
||||
required: true,
|
||||
|
|
@ -19,122 +15,6 @@ export default class DhCountdowns extends foundry.abstract.DataModel {
|
|||
}
|
||||
}
|
||||
|
||||
/* Outdated and unused. Needed for migration. Remove in next minor version. (1.3) */
|
||||
class DhCountdownData extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
countdowns: new fields.TypedObjectField(new fields.EmbeddedDataField(DhOldCountdown)),
|
||||
ownership: new fields.SchemaField({
|
||||
default: new fields.NumberField({
|
||||
required: true,
|
||||
choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS),
|
||||
initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE
|
||||
}),
|
||||
players: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
type: new fields.NumberField({
|
||||
required: true,
|
||||
choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS),
|
||||
initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT
|
||||
})
|
||||
})
|
||||
)
|
||||
}),
|
||||
window: new fields.SchemaField({})
|
||||
};
|
||||
}
|
||||
|
||||
get playerOwnership() {
|
||||
return Array.from(game.users).reduce((acc, user) => {
|
||||
acc[user.id] = {
|
||||
value: user.isGM
|
||||
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
|
||||
: this.ownership.players[user.id] && this.ownership.players[user.id].type !== -1
|
||||
? this.ownership.players[user.id].type
|
||||
: this.ownership.default,
|
||||
isGM: user.isGM
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
|
||||
/* Outdated and unused. Needed for migration. Remove in next minor version. (1.3) */
|
||||
class DhOldCountdown extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
name: new fields.StringField({
|
||||
required: true,
|
||||
label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.name.label'
|
||||
}),
|
||||
img: new fields.FilePathField({
|
||||
categories: ['IMAGE'],
|
||||
base64: false,
|
||||
initial: 'icons/magic/time/hourglass-yellow-green.webp'
|
||||
}),
|
||||
ownership: new fields.SchemaField({
|
||||
default: new fields.NumberField({
|
||||
required: true,
|
||||
choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS),
|
||||
initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE
|
||||
}),
|
||||
players: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
type: new fields.NumberField({
|
||||
required: true,
|
||||
choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS),
|
||||
initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT
|
||||
})
|
||||
})
|
||||
)
|
||||
}),
|
||||
progress: new fields.SchemaField({
|
||||
current: new fields.NumberField({
|
||||
required: true,
|
||||
integer: true,
|
||||
initial: 1,
|
||||
label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.current.label'
|
||||
}),
|
||||
max: new fields.NumberField({
|
||||
required: true,
|
||||
integer: true,
|
||||
initial: 1,
|
||||
label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.max.label'
|
||||
}),
|
||||
type: new fields.SchemaField({
|
||||
value: new fields.StringField({
|
||||
required: true,
|
||||
choices: CONFIG.DH.GENERAL.countdownProgressionTypes,
|
||||
initial: CONFIG.DH.GENERAL.countdownProgressionTypes.custom.id,
|
||||
label: 'DAGGERHEART.GENERAL.type'
|
||||
}),
|
||||
label: new fields.StringField({
|
||||
label: 'DAGGERHEART.APPLICATIONS.Countdown.FIELDS.countdowns.element.progress.type.label.label'
|
||||
})
|
||||
})
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
get playerOwnership() {
|
||||
return Array.from(game.users).reduce((acc, user) => {
|
||||
acc[user.id] = {
|
||||
value: user.isGM
|
||||
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
|
||||
: this.ownership.players[user.id] && this.ownership.players[user.id].type !== -1
|
||||
? this.ownership.players[user.id].type
|
||||
: this.ownership.default,
|
||||
isGM: user.isGM
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
|
||||
export class DhCountdown extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ export default class CountdownField extends fields.ArrayField {
|
|||
|
||||
data.countdowns[foundry.utils.randomID()] = {
|
||||
...countdown,
|
||||
ownership: game.users.reduce((acc, curr) => {
|
||||
if (!curr.isGM) acc[curr.id] = countdown.defaultOwnership;
|
||||
return acc;
|
||||
}, {}),
|
||||
progress: {
|
||||
...countdown.progress,
|
||||
current: countdownStart,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,12 @@ export default class DamageField extends fields.SchemaField {
|
|||
initial: false,
|
||||
label: 'DAGGERHEART.ACTIONS.Settings.includeBase.label'
|
||||
}),
|
||||
direct: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.CONFIG.DamageType.direct.name' })
|
||||
direct: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.CONFIG.DamageType.direct.name' }),
|
||||
groupAttack: new fields.StringField({
|
||||
choices: CONFIG.DH.GENERAL.groupAttackRange,
|
||||
blank: true,
|
||||
label: 'DAGGERHEART.ACTIONS.Settings.groupAttack.label'
|
||||
})
|
||||
};
|
||||
super(damageFields, options, context);
|
||||
}
|
||||
|
|
@ -224,6 +229,22 @@ export default class DamageField extends fields.SchemaField {
|
|||
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).roll.damageApply.players)
|
||||
);
|
||||
}
|
||||
|
||||
static getGroupAttackTokens(actorId, range) {
|
||||
if (!canvas.scene) return [];
|
||||
|
||||
const targets = Array.from(game.user.targets);
|
||||
const rangeSettings = canvas.scene?.rangeSettings;
|
||||
if (!rangeSettings) return [];
|
||||
|
||||
const maxDistance = rangeSettings[range];
|
||||
return canvas.scene.tokens.filter(x => {
|
||||
if (x.actor?.id !== actorId) return false;
|
||||
if (targets.every(target => x.object.distanceTo(target) > maxDistance)) return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class DHActionDiceData extends foundry.abstract.DataModel {
|
||||
|
|
|
|||
|
|
@ -89,13 +89,13 @@ class ResourcesField extends fields.TypedObjectField {
|
|||
*/
|
||||
_getField(path) {
|
||||
if (path.length === 0) return this;
|
||||
const first = path.shift();
|
||||
if (first === this.element.name) return this.element_getField(path);
|
||||
const name = path.pop();
|
||||
if (name === this.element.name) return this.element_getField(path);
|
||||
|
||||
const resources = CONFIG.DH.RESOURCE[this.actorType].all;
|
||||
if (first in resources) {
|
||||
if (name in resources) {
|
||||
const field = this.element._getField(path);
|
||||
field.label = resources[first].label;
|
||||
field.label = resources[name].label;
|
||||
return field;
|
||||
}
|
||||
|
||||
|
|
|
|||
40
module/data/groupRollData.mjs
Normal file
40
module/data/groupRollData.mjs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
export default class GroupRollData extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
return {
|
||||
leader: new fields.EmbeddedDataField(CharacterData, { nullable: true, initial: null }),
|
||||
aidingCharacters: new fields.TypedObjectField(new fields.EmbeddedDataField(CharacterData))
|
||||
};
|
||||
}
|
||||
|
||||
get participants() {
|
||||
return {
|
||||
...(this.leader ? { [this.leader.id]: this.leader } : {}),
|
||||
...this.aidingCharacters
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CharacterData extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
return {
|
||||
id: new fields.StringField({ required: true }),
|
||||
name: new fields.StringField({ required: true }),
|
||||
img: new fields.StringField({ required: true }),
|
||||
rollChoice: new fields.StringField({
|
||||
choices: CONFIG.DH.ACTOR.abilities,
|
||||
initial: CONFIG.DH.ACTOR.abilities.agility.id
|
||||
}),
|
||||
rollData: new fields.JSONField({ nullable: true, initial: null }),
|
||||
selected: new fields.BooleanField({ initial: false }),
|
||||
successfull: new fields.BooleanField({ nullable: true, initial: null })
|
||||
};
|
||||
}
|
||||
|
||||
get roll() {
|
||||
return this.rollData ? CONFIG.Dice.daggerheart.DualityRoll.fromData(this.rollData) : null;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,9 @@ export default class DhAppearance extends foundry.abstract.DataModel {
|
|||
initial: null,
|
||||
blank: true,
|
||||
choices: CONFIG.DH.GENERAL.diceSoNiceSFXClasses
|
||||
}),
|
||||
options: new foundry.data.fields.SchemaField({
|
||||
muteSound: new foundry.data.fields.BooleanField()
|
||||
})
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ export default class DamageRoll extends DHRoll {
|
|||
constructFormula(config) {
|
||||
this.options.isCritical = config.isCritical;
|
||||
for (const [index, part] of this.options.roll.entries()) {
|
||||
const isHitpointPart = part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id;
|
||||
part.roll = new Roll(Roll.replaceFormulaData(part.formula, config.data));
|
||||
part.roll.terms = Roll.parse(part.roll.formula, config.data);
|
||||
if (part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) {
|
||||
|
|
@ -169,7 +170,16 @@ export default class DamageRoll extends DHRoll {
|
|||
);
|
||||
}
|
||||
|
||||
if (config.isCritical && part.applyTo === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) {
|
||||
if (config.damageOptions.groupAttack?.numAttackers > 1 && isHitpointPart) {
|
||||
const damageTypes = [foundry.dice.terms.Die, foundry.dice.terms.NumericTerm];
|
||||
for (const term of part.roll.terms) {
|
||||
if (damageTypes.some(type => term instanceof type)) {
|
||||
term.number *= config.damageOptions.groupAttack.numAttackers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.isCritical && isHitpointPart) {
|
||||
const total = part.roll.dice.reduce((acc, term) => acc + term._faces * term._number, 0);
|
||||
if (total > 0) {
|
||||
part.roll.terms.push(...this.formatModifier(total));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
import DHToken from './token.mjs';
|
||||
|
||||
export default class DhScene extends Scene {
|
||||
get rangeSettings() {
|
||||
const { custom } = CONFIG.DH.GENERAL.sceneRangeMeasurementSetting;
|
||||
const sceneMeasurements = this.flags.daggerheart?.rangeMeasurement;
|
||||
const globalMeasurements = game.settings.get(
|
||||
CONFIG.DH.id,
|
||||
CONFIG.DH.SETTINGS.gameSettings.variantRules
|
||||
).rangeMeasurement;
|
||||
return sceneMeasurements?.setting === custom.id ? sceneMeasurements : globalMeasurements;
|
||||
}
|
||||
|
||||
/** A map of `TokenDocument` IDs embedded in this scene long with new dimensions from actor size-category changes */
|
||||
#sizeSyncBatch = new Map();
|
||||
|
||||
|
|
|
|||
|
|
@ -118,13 +118,6 @@ const getTemplateDistance = range => {
|
|||
const rangeNumber = Number(range);
|
||||
if (!Number.isNaN(rangeNumber)) return rangeNumber;
|
||||
|
||||
const { custom } = CONFIG.DH.GENERAL.sceneRangeMeasurementSetting;
|
||||
const sceneMeasurements = canvas.scene?.flags.daggerheart?.rangeMeasurement;
|
||||
const globalMeasurements = game.settings.get(
|
||||
CONFIG.DH.id,
|
||||
CONFIG.DH.SETTINGS.gameSettings.variantRules
|
||||
).rangeMeasurement;
|
||||
|
||||
const settings = sceneMeasurements?.setting === custom.id ? sceneMeasurements : globalMeasurements;
|
||||
return settings[range];
|
||||
const settings = canvas.scene?.rangeSettings;
|
||||
return settings ? settings[range] : 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { defaultRestOptions } from '../config/generalConfig.mjs';
|
||||
import { RefreshType, socketEvent } from './socket.mjs';
|
||||
|
||||
export async function runMigrations() {
|
||||
|
|
@ -341,6 +342,18 @@ export async function runMigrations() {
|
|||
|
||||
lastMigrationVersion = '2.0.0';
|
||||
}
|
||||
|
||||
if (foundry.utils.isNewerVersion('2.1.0', lastMigrationVersion)) {
|
||||
const downtimeMoves = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew);
|
||||
if (downtimeMoves.restMoves.longRest.moves.repairArmor) {
|
||||
await downtimeMoves.updateSource({
|
||||
'restMoves.longRest.moves.repairArmor': defaultRestOptions.longRest().repairArmor
|
||||
});
|
||||
game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, downtimeMoves.toObject());
|
||||
}
|
||||
|
||||
lastMigrationVersion = '2.1.0';
|
||||
}
|
||||
//#endregion
|
||||
|
||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion, lastMigrationVersion);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ export function handleSocketEvent({ action = null, data = {} } = {}) {
|
|||
case socketEvent.TagTeamStart:
|
||||
Hooks.callAll(CONFIG.DH.HOOKS.hooksConfig.tagTeamStart, data);
|
||||
break;
|
||||
case socketEvent.GroupRollStart:
|
||||
Hooks.callAll(CONFIG.DH.HOOKS.hooksConfig.groupRollStart, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -26,7 +28,8 @@ export const socketEvent = {
|
|||
Refresh: 'DhRefresh',
|
||||
DhpFearUpdate: 'DhFearUpdate',
|
||||
DowntimeTrigger: 'DowntimeTrigger',
|
||||
TagTeamStart: 'DhTagTeamStart'
|
||||
TagTeamStart: 'DhTagTeamStart',
|
||||
GroupRollStart: 'DhGroupRollStart'
|
||||
};
|
||||
|
||||
export const GMUpdateEvent = {
|
||||
|
|
@ -41,6 +44,7 @@ export const GMUpdateEvent = {
|
|||
export const RefreshType = {
|
||||
Countdown: 'DhCoundownRefresh',
|
||||
TagTeamRoll: 'DhTagTeamRollRefresh',
|
||||
GroupRoll: 'DhGroupRollRefresh',
|
||||
EffectsDisplay: 'DhEffectsDisplayRefresh',
|
||||
Scene: 'DhSceneRefresh',
|
||||
CompendiumBrowser: 'DhCompendiumBrowserRefresh'
|
||||
|
|
|
|||
|
|
@ -131,12 +131,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -187,7 +184,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -213,7 +210,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -249,33 +247,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"vgguNWz8vG8aoLXR": {
|
||||
"type": "effect",
|
||||
"_id": "vgguNWz8vG8aoLXR",
|
||||
"SrNyZgPvCXMpbCLG": {
|
||||
"type": "attack",
|
||||
"_id": "SrNyZgPvCXMpbCLG",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"step": null
|
||||
"itemId": null,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "4"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/magic/unholy/orb-hands-pink.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -242,33 +240,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"cbAvPSIhwBMBTI3D": {
|
||||
"type": "effect",
|
||||
"_id": "cbAvPSIhwBMBTI3D",
|
||||
"FCeTuf71gCzRiO5N": {
|
||||
"type": "attack",
|
||||
"_id": "FCeTuf71gCzRiO5N",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"step": null
|
||||
"itemId": null,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "6"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -242,33 +240,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all Cult @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"EH1preaTWBD4rOvx": {
|
||||
"type": "effect",
|
||||
"_id": "EH1preaTWBD4rOvx",
|
||||
"4M2MvVzEgIQEQHBS": {
|
||||
"type": "attack",
|
||||
"_id": "4M2MvVzEgIQEQHBS",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"step": null
|
||||
"itemId": null,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "5"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": null,
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -242,33 +240,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"vXHZVb0Y7Hqu3uso": {
|
||||
"type": "effect",
|
||||
"_id": "vXHZVb0Y7Hqu3uso",
|
||||
"S3dYxRclyhYINRi8": {
|
||||
"type": "attack",
|
||||
"_id": "S3dYxRclyhYINRi8",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"step": null
|
||||
"itemId": null,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "5"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/magic/unholy/orb-hands-pink.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -320,33 +318,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"QHNRSEQmqOcaoXq4": {
|
||||
"type": "effect",
|
||||
"_id": "QHNRSEQmqOcaoXq4",
|
||||
"G0DVft7h55pBnwJA": {
|
||||
"type": "attack",
|
||||
"_id": "G0DVft7h55pBnwJA",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"step": null
|
||||
"itemId": null,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "12"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/magic/unholy/orb-hands-pink.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -131,12 +131,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -187,7 +184,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -213,7 +210,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -272,8 +270,38 @@
|
|||
"recovery": null
|
||||
},
|
||||
"damage": {
|
||||
"parts": {},
|
||||
"includeBase": false
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "1"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"target": {
|
||||
"type": "any",
|
||||
|
|
@ -300,7 +328,7 @@
|
|||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Attack",
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -242,35 +240,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"DjbPQowW1OdBD9Zn": {
|
||||
"type": "effect",
|
||||
"_id": "DjbPQowW1OdBD9Zn",
|
||||
"wez1xgy9vScux9wi": {
|
||||
"type": "attack",
|
||||
"_id": "wez1xgy9vScux9wi",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"consumeOnSuccess": false,
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"keyIsID": false,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
"itemId": null,
|
||||
"step": null
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "5"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -297,33 +295,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"eo7J0v1B5zPHul1M": {
|
||||
"type": "effect",
|
||||
"_id": "eo7J0v1B5zPHul1M",
|
||||
"irZGPKPpGLA6sP2y": {
|
||||
"type": "attack",
|
||||
"_id": "irZGPKPpGLA6sP2y",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"step": null
|
||||
"itemId": null,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "10"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -131,12 +131,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -187,7 +184,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -213,7 +210,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -251,33 +249,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name] within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"aoQDb2m32NDxE6ZP": {
|
||||
"type": "effect",
|
||||
"_id": "aoQDb2m32NDxE6ZP",
|
||||
"ferZO3BuiP9zU46m": {
|
||||
"type": "attack",
|
||||
"_id": "ferZO3BuiP9zU46m",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"consumeOnSuccess": false,
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"itemId": null,
|
||||
"step": null
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "2"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -245,33 +243,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"xTMNAHcoErKuR6TZ": {
|
||||
"type": "effect",
|
||||
"_id": "xTMNAHcoErKuR6TZ",
|
||||
"xFlhxnQWmVvDqQ55": {
|
||||
"type": "attack",
|
||||
"_id": "xFlhxnQWmVvDqQ55",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"step": null
|
||||
"itemId": null,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "4"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -242,33 +240,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"tvQetauskZoHDR5y": {
|
||||
"type": "effect",
|
||||
"_id": "tvQetauskZoHDR5y",
|
||||
"6VKv71tPUIGGIfkZ": {
|
||||
"type": "attack",
|
||||
"_id": "6VKv71tPUIGGIfkZ",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"consumeOnSuccess": false,
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"itemId": null,
|
||||
"step": null
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "11"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -245,33 +243,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"DJBNtd3hWjwsjPwq": {
|
||||
"type": "effect",
|
||||
"_id": "DJBNtd3hWjwsjPwq",
|
||||
"8wRrAWHU0xHW4zuE": {
|
||||
"type": "attack",
|
||||
"_id": "8wRrAWHU0xHW4zuE",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"step": null
|
||||
"itemId": null,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "2"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -245,33 +243,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"ghgFZskDiizJDjcn": {
|
||||
"type": "effect",
|
||||
"_id": "ghgFZskDiizJDjcn",
|
||||
"K3pF2DBnR9zJ90W8": {
|
||||
"type": "attack",
|
||||
"_id": "K3pF2DBnR9zJ90W8",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"consumeOnSuccess": false,
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"itemId": null,
|
||||
"step": null
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "3"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -245,33 +243,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"Sz55uB8xkoNytLwJ": {
|
||||
"type": "effect",
|
||||
"_id": "Sz55uB8xkoNytLwJ",
|
||||
"6rdwJKwsSCO4R0Ty": {
|
||||
"type": "attack",
|
||||
"_id": "6rdwJKwsSCO4R0Ty",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"step": null
|
||||
"itemId": null,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "1"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -164,12 +164,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -220,7 +217,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -246,7 +243,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -284,33 +282,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"ZC5pKIb9N82vgMWu": {
|
||||
"type": "effect",
|
||||
"_id": "ZC5pKIb9N82vgMWu",
|
||||
"V58Ry90tvIjvfDTZ": {
|
||||
"type": "attack",
|
||||
"_id": "V58Ry90tvIjvfDTZ",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"consumeOnSuccess": false,
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"itemId": null,
|
||||
"step": null
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "2"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/creatures/abilities/tail-strike-bone-orange.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -125,12 +125,9 @@
|
|||
"src": "systems/daggerheart/assets/icons/documents/actors/dragon-head.svg",
|
||||
"anchorX": 0.5,
|
||||
"anchorY": 0.5,
|
||||
"offsetX": 0,
|
||||
"offsetY": 0,
|
||||
"fit": "contain",
|
||||
"scaleX": 1,
|
||||
"scaleY": 1,
|
||||
"rotation": 0,
|
||||
"tint": "#ffffff",
|
||||
"alphaThreshold": 0.75
|
||||
},
|
||||
|
|
@ -181,7 +178,7 @@
|
|||
"saturation": 0,
|
||||
"contrast": 0
|
||||
},
|
||||
"detectionModes": [],
|
||||
"detectionModes": {},
|
||||
"occludable": {
|
||||
"radius": 0
|
||||
},
|
||||
|
|
@ -207,7 +204,8 @@
|
|||
"flags": {},
|
||||
"randomImg": false,
|
||||
"appendNumber": false,
|
||||
"prependAdjective": false
|
||||
"prependAdjective": false,
|
||||
"depth": 1
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
|
|
@ -242,33 +240,95 @@
|
|||
"description": "<p><strong>Spend a Fear</strong> to choose a target and spotlight all @Lookup[@name]s within Close range of them. Those Minions move into Melee range of the target and make one shared attack roll. On a success, they deal @Lookup[@system.attack.damageFormula] physical damage each. Combine this damage.</p>",
|
||||
"resource": null,
|
||||
"actions": {
|
||||
"euP8VA4wvfsCpwN1": {
|
||||
"type": "effect",
|
||||
"_id": "euP8VA4wvfsCpwN1",
|
||||
"Itubbr63irPJcbXG": {
|
||||
"type": "attack",
|
||||
"_id": "Itubbr63irPJcbXG",
|
||||
"systemPath": "actions",
|
||||
"baseAction": false,
|
||||
"description": "",
|
||||
"chatDisplay": true,
|
||||
"originItem": {
|
||||
"type": "itemCollection"
|
||||
},
|
||||
"actionType": "action",
|
||||
"triggers": [],
|
||||
"cost": [
|
||||
{
|
||||
"scalable": false,
|
||||
"key": "fear",
|
||||
"value": 1,
|
||||
"step": null
|
||||
"itemId": null,
|
||||
"step": null,
|
||||
"consumeOnSuccess": false
|
||||
}
|
||||
],
|
||||
"uses": {
|
||||
"value": null,
|
||||
"max": "",
|
||||
"recovery": null
|
||||
"recovery": null,
|
||||
"consumeOnSuccess": false
|
||||
},
|
||||
"damage": {
|
||||
"parts": {
|
||||
"hitPoints": {
|
||||
"applyTo": "hitPoints",
|
||||
"resultBased": false,
|
||||
"value": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": true,
|
||||
"formula": "8"
|
||||
}
|
||||
},
|
||||
"valueAlt": {
|
||||
"multiplier": "flat",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"bonus": null,
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"formula": ""
|
||||
}
|
||||
},
|
||||
"base": false,
|
||||
"type": [
|
||||
"physical"
|
||||
]
|
||||
}
|
||||
},
|
||||
"includeBase": false,
|
||||
"direct": false,
|
||||
"groupAttack": "close"
|
||||
},
|
||||
"effects": [],
|
||||
"target": {
|
||||
"type": "self",
|
||||
"type": "any",
|
||||
"amount": null
|
||||
},
|
||||
"effects": [],
|
||||
"roll": {
|
||||
"type": "attack",
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"bonus": null,
|
||||
"advState": "neutral",
|
||||
"diceRolling": {
|
||||
"multiplier": "prof",
|
||||
"flatMultiplier": 1,
|
||||
"dice": "d6",
|
||||
"compare": null,
|
||||
"treshold": null
|
||||
},
|
||||
"useDefault": false
|
||||
},
|
||||
"save": {
|
||||
"trait": null,
|
||||
"difficulty": null,
|
||||
"damageMod": "none"
|
||||
},
|
||||
"name": "Spend Fear",
|
||||
"img": "icons/magic/unholy/orb-hands-pink.webp",
|
||||
"range": ""
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"type": "domainCard",
|
||||
"folder": "QpOL7jPbMBzH96qR",
|
||||
"system": {
|
||||
"description": "<p class=\"Body-Foundation\">When you choose not to equip armor, you have a base Armor Score of 3 + your Strength and use the following as your base damage thresholds:</p><ul><li class=\"vertical-card-list-found\"><em><strong>Tier 1:</strong></em> 9/19</li><li class=\"vertical-card-list-found\"><em><strong>Tier 2:</strong></em> 11/24</li><li class=\"vertical-card-list-found\"><em><strong>Tier 3:</strong></em> 13/31</li><li class=\"vertical-card-list-found\"><em><strong>Tier 4:</strong></em> 15/38</li></ul><p>Equip the below armor to use Bare Bones.</p><p>@UUID[Compendium.daggerheart.armors.Item.ITAjcigTcUw5pMCN]{Bare Bones}</p>",
|
||||
"description": "<p class=\"Body-Foundation\">When you choose not to equip armor, you have a base Armor Score of 3 + your Strength and use the following as your base damage thresholds:</p><ul><li class=\"vertical-card-list-found\"><p><em><strong>Tier 1:</strong></em> 9/19</p></li><li class=\"vertical-card-list-found\"><p><em><strong>Tier 2:</strong></em> 11/24</p></li><li class=\"vertical-card-list-found\"><p><em><strong>Tier 3:</strong></em> 13/31</p></li><li class=\"vertical-card-list-found\"><p><em><strong>Tier 4:</strong></em> 15/38</p></li></ul>",
|
||||
"domain": "valor",
|
||||
"recallCost": 0,
|
||||
"level": 1,
|
||||
|
|
@ -28,22 +28,33 @@
|
|||
{
|
||||
"type": "armor",
|
||||
"phase": "initial",
|
||||
"priority": 20,
|
||||
"value": {
|
||||
"current": 0,
|
||||
"max": "3 + @system.traits.strength.value",
|
||||
"interaction": "inactive",
|
||||
"damageThresholds": {
|
||||
"major": "9 + (@tier - 1) * 5 + max(0, (@tier -2) * 2 )",
|
||||
"major": "9 + (@tier - 1) * 2",
|
||||
"severe": "19 + (@tier - 1) * 5 + max(0, (@tier -2) * 2 )"
|
||||
}
|
||||
}
|
||||
},
|
||||
"priority": 20
|
||||
}
|
||||
]
|
||||
],
|
||||
"duration": {
|
||||
"type": ""
|
||||
}
|
||||
},
|
||||
"_id": "FCsgz7Tdsw6QUzBs",
|
||||
"img": "icons/magic/control/buff-strength-muscle-damage-orange.webp",
|
||||
"disabled": false,
|
||||
"start": null,
|
||||
"start": {
|
||||
"time": 0,
|
||||
"combat": null,
|
||||
"combatant": null,
|
||||
"initiative": null,
|
||||
"round": null,
|
||||
"turn": null
|
||||
},
|
||||
"duration": {
|
||||
"value": null,
|
||||
"units": "seconds",
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
gap: 4px;
|
||||
.critical-chip {
|
||||
flex: 0;
|
||||
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
|
|
@ -41,6 +41,26 @@
|
|||
}
|
||||
}
|
||||
|
||||
.group-attack-container {
|
||||
margin: 0;
|
||||
|
||||
.group-attack-inner-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
|
||||
> * {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.group-attack-tools {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.damage-section-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
78
styles/less/dialog/group-roll-dialog/initialization.less
Normal file
78
styles/less/dialog/group-roll-dialog/initialization.less
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
.theme-light .daggerheart.dialog.dh-style.views.group-roll-dialog {
|
||||
.initialization-container .members-container .member-container {
|
||||
.member-name {
|
||||
background-image: url('../assets/parchments/dh-parchment-light.png');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.daggerheart.dialog.dh-style.views.group-roll-dialog {
|
||||
.initialization-container {
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.members-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
gap: 8px;
|
||||
|
||||
.member-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
&.inactive {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.member-name {
|
||||
position: absolute;
|
||||
padding: 0 2px;
|
||||
border: 1px solid;
|
||||
border-radius: 6px;
|
||||
margin-top: 4px;
|
||||
color: light-dark(@dark, @beige);
|
||||
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 6px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-roll {
|
||||
margin-top: 8px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
|
||||
&.inactive {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.finish-tools {
|
||||
flex: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
&.inactive {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
styles/less/dialog/group-roll-dialog/leader.less
Normal file
35
styles/less/dialog/group-roll-dialog/leader.less
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
.daggerheart.dialog.dh-style.views.group-roll-dialog {
|
||||
.main-character-outer-container {
|
||||
&.inactive {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.main-character-container {
|
||||
.character-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
|
||||
img {
|
||||
height: 64px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
}
|
||||
|
||||
.character-data {
|
||||
padding-left: 0.75rem;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
text-align: left;
|
||||
font-size: var(--font-size-18);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
266
styles/less/dialog/group-roll-dialog/sheet.less
Normal file
266
styles/less/dialog/group-roll-dialog/sheet.less
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
.daggerheart.dialog.dh-style.views.group-roll-dialog {
|
||||
.team-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.team-member-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
|
||||
&.inactive {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.data-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.member-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
|
||||
img {
|
||||
height: 64px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
}
|
||||
|
||||
.member-data {
|
||||
padding-left: 0.75rem;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
text-align: left;
|
||||
font-size: var(--font-size-18);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.roll-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.roll-title {
|
||||
font-size: var(--font-size-20);
|
||||
font-weight: bold;
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
&.hope,
|
||||
&.fear,
|
||||
&.critical {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
&.hope {
|
||||
--text-color: @golden;
|
||||
}
|
||||
|
||||
&.fear {
|
||||
--text-color: @chat-blue;
|
||||
}
|
||||
|
||||
&.critical {
|
||||
--text-color: @chat-purple;
|
||||
}
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
color: var(--text-color);
|
||||
content: '';
|
||||
flex: 1;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
&::before {
|
||||
background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, light-dark(@dark-blue, @golden) 100%);
|
||||
}
|
||||
|
||||
&::after {
|
||||
background: linear-gradient(90deg, light-dark(@dark-blue, @golden) 0%, rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.roll-tools {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
font-size: 16px;
|
||||
|
||||
&:hover {
|
||||
text-shadow: none;
|
||||
filter: drop-shadow(0 0 8px var(--golden));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.roll-data {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
&.hope {
|
||||
--text-color: @golden;
|
||||
--bg-color: @golden-40;
|
||||
}
|
||||
|
||||
&.fear {
|
||||
--text-color: @chat-blue;
|
||||
--bg-color: @chat-blue-40;
|
||||
}
|
||||
|
||||
&.critical {
|
||||
--text-color: @chat-purple;
|
||||
--bg-color: @chat-purple-40;
|
||||
}
|
||||
|
||||
.duality-label {
|
||||
color: var(--text-color);
|
||||
font-size: var(--font-size-20);
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
|
||||
.unused-damage {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
.roll-dice-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
|
||||
.roll-dice {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.dice-label {
|
||||
position: absolute;
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
paint-order: stroke fill;
|
||||
-webkit-text-stroke: 2px black;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.roll-operator {
|
||||
font-size: var(--font-size-24);
|
||||
}
|
||||
|
||||
.roll-value {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.roll-total {
|
||||
background: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
border-radius: 4px;
|
||||
padding: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.roll-success-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
|
||||
.roll-success-tools {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
|
||||
i {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.roll-success-modifier {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: right;
|
||||
gap: 2px;
|
||||
font-size: var(--font-size-20);
|
||||
padding: 0px 4px;
|
||||
|
||||
&.success {
|
||||
background: @green-10;
|
||||
color: @green;
|
||||
}
|
||||
|
||||
&.failure {
|
||||
background: @red-10;
|
||||
color: @red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: var(--font-size-18);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.group-roll-results {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: var(--font-size-20);
|
||||
|
||||
.group-roll-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.finish-container {
|
||||
margin-top: 16px;
|
||||
gap: 16px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
|
||||
.finish-button {
|
||||
grid-column: span 2;
|
||||
}
|
||||
}
|
||||
|
||||
.hint {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
|
@ -36,6 +36,10 @@
|
|||
@import './tag-team-dialog/initialization.less';
|
||||
@import './tag-team-dialog/sheet.less';
|
||||
|
||||
@import './group-roll-dialog/initialization.less';
|
||||
@import './group-roll-dialog/leader.less';
|
||||
@import './group-roll-dialog/sheet.less';
|
||||
|
||||
@import './image-select/sheet.less';
|
||||
|
||||
@import './item-transfer/sheet.less';
|
||||
|
|
|
|||
|
|
@ -20,6 +20,17 @@
|
|||
|
||||
.member-name {
|
||||
position: absolute;
|
||||
padding: 0 2px;
|
||||
border: 1px solid;
|
||||
border-radius: 6px;
|
||||
margin-top: 4px;
|
||||
color: light-dark(@dark, @beige);
|
||||
background-image: url('../assets/parchments/dh-parchment-dark.png');
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 6px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -419,11 +419,19 @@
|
|||
width: fit-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.form-fields {
|
||||
height: 32px;
|
||||
align-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
&.select {
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.scalable-input {
|
||||
|
|
|
|||
|
|
@ -1,28 +1,293 @@
|
|||
@import '../../../utils/colors.less';
|
||||
@import '../../../utils/fonts.less';
|
||||
@import '../../../utils/mixin.less';
|
||||
|
||||
.application.sheet.daggerheart.actor.dh-style.party {
|
||||
.tab.partyMembers {
|
||||
max-height: 400px;
|
||||
overflow: auto;
|
||||
body.game:is(.performance-low, .noblur) {
|
||||
.application.sheet.daggerheart.actor.dh-style.party .tab.resources .actors-list .actor-resources {
|
||||
background: light-dark(@dark-blue, @dark-golden);
|
||||
|
||||
.actors-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
.actors-dragger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
border: 1px dashed light-dark(@dark-blue-50, @beige-50);
|
||||
border-radius: 3px;
|
||||
color: light-dark(@dark-blue-50, @beige-50);
|
||||
.actor-name {
|
||||
background: light-dark(@dark-blue, @dark-golden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.application.sheet.daggerheart.actor.dh-style.party .tab.partyMembers {
|
||||
overflow: auto;
|
||||
|
||||
.actors-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
|
||||
.actor-resources {
|
||||
display: grid;
|
||||
grid-template:
|
||||
"img header" min-content
|
||||
"img body" 1fr
|
||||
/ 7.5rem 1fr;
|
||||
gap: 6px;
|
||||
column-gap: 12px;
|
||||
padding: 6px;
|
||||
background-color: light-dark(@dark-blue-10, @golden-10);
|
||||
|
||||
.actor-img-frame {
|
||||
grid-area: img;
|
||||
width: 7.5rem;
|
||||
height: 7.5rem;
|
||||
position: relative;
|
||||
|
||||
.actor-img {
|
||||
object-fit: cover;
|
||||
object-position: top center;
|
||||
border-radius: 6px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.equipped-weapons {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -3px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1px;
|
||||
img {
|
||||
border-radius: 50%;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.evasion {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 1.75rem;
|
||||
height: 1.75rem;
|
||||
background: url('../assets/svg/trait-shield.svg') no-repeat;
|
||||
background-size: 100%;
|
||||
font-size: var(--font-size-14);
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.threshold-section {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: -2px;
|
||||
margin: auto;
|
||||
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
background-color: light-dark(transparent, @dark-blue);
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
padding: 4px 6px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 3px;
|
||||
align-items: baseline;
|
||||
width: fit-content;
|
||||
|
||||
h4 {
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
|
||||
&.threshold-label {
|
||||
font-size: var(--font-size-10);
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
}
|
||||
|
||||
&.threshold-value {
|
||||
font-size: var(--font-size-11);
|
||||
color: light-dark(@dark, @beige);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
grid-area: header;
|
||||
display: grid;
|
||||
grid-template:
|
||||
"name hope" min-content
|
||||
"subtitle subtitle" min-content
|
||||
/ 1fr min-content;
|
||||
|
||||
.actor-name {
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
font-size: var(--font-size-20);
|
||||
color: light-dark(@beige, @golden);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
grid-area: subtitle;
|
||||
font-size: var(--font-size-14);
|
||||
}
|
||||
|
||||
.hope-section {
|
||||
display: flex;
|
||||
background-color: light-dark(transparent, @dark-blue);
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
padding: 3px 6px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
width: fit-content;
|
||||
margin-left: auto;
|
||||
|
||||
h4 {
|
||||
font-size: var(--font-size-12);
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.hope-value {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-12);
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
grid-area: body;
|
||||
display: flex;
|
||||
align-items: start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.resources {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.slot-section {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
|
||||
.slot-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: light-dark(@beige, @dark-blue);
|
||||
background: light-dark(@dark-blue, @golden);
|
||||
padding: 0 4px;
|
||||
width: fit-content;
|
||||
font-weight: bold;
|
||||
border-radius: 6px 0px 0px 6px;
|
||||
font-size: var(--font-size-12);
|
||||
white-space: nowrap;
|
||||
|
||||
.label {
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-variant-numeric: tabular-nums;
|
||||
.current {
|
||||
display: inline-block;
|
||||
text-align: end;
|
||||
width: 2ch;
|
||||
}
|
||||
.max {
|
||||
display: inline-block;
|
||||
text-align: start;
|
||||
width: 2ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slot-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
|
||||
background-color: light-dark(@dark-blue-10, @dark-blue);
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
padding: 2px 5px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 0 6px 6px 0;
|
||||
width: fit-content;
|
||||
min-height: 22px;
|
||||
|
||||
.armor-slot {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-size: var(--font-size-12);
|
||||
|
||||
.fa-shield-halved {
|
||||
color: light-dark(@dark-blue-40, @golden-40);
|
||||
}
|
||||
}
|
||||
|
||||
.slot {
|
||||
width: 16px;
|
||||
height: 10px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
background: light-dark(@dark-blue-10, @golden-10);
|
||||
border-radius: 3px;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
|
||||
&.filled {
|
||||
background: light-dark(@dark-blue, @golden);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.traits {
|
||||
background-color: light-dark(@dark-blue-10, @dark-blue);
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 6px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
font-size: var(--font-size-12);
|
||||
padding: 3px 4px;
|
||||
gap: 3px 7px;
|
||||
.trait {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 3px;
|
||||
.label {
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
}
|
||||
.value {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actors-dragger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
border: 1px dashed light-dark(@dark-blue-50, @beige-50);
|
||||
border-radius: 3px;
|
||||
color: light-dark(@dark-blue-50, @beige-50);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,216 +0,0 @@
|
|||
@import '../../../utils/colors.less';
|
||||
@import '../../../utils/fonts.less';
|
||||
@import '../../../utils/mixin.less';
|
||||
|
||||
body.game:is(.performance-low, .noblur) {
|
||||
.application.sheet.daggerheart.actor.dh-style.party .tab.resources .actors-list .actor-resources {
|
||||
background: light-dark(@dark-blue, @dark-golden);
|
||||
|
||||
.actor-name {
|
||||
background: light-dark(@dark-blue, @dark-golden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.application.sheet.daggerheart.actor.dh-style.party {
|
||||
.tab.resources {
|
||||
overflow: auto;
|
||||
|
||||
.actors-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
|
||||
.actor-resources {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
background: light-dark(@dark-blue-40, @dark-golden-40);
|
||||
border-radius: 6px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
width: 230px;
|
||||
height: -webkit-fill-available;
|
||||
|
||||
.actor-name {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
background: light-dark(@dark-blue-90, @dark-golden-80);
|
||||
backdrop-filter: blur(6.5px);
|
||||
border-radius: 6px 6px 0px 0px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
font-size: var(--font-size-20);
|
||||
color: light-dark(@beige, @golden);
|
||||
font-weight: bold;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.actor-img {
|
||||
height: 150px;
|
||||
object-fit: cover;
|
||||
object-position: top center;
|
||||
border-radius: 6px 6px 0px 0px;
|
||||
mask-image: linear-gradient(180deg, black 88%, transparent 100%);
|
||||
}
|
||||
|
||||
.resources {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
margin: 10px;
|
||||
|
||||
.slot-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.slot-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
width: 239px;
|
||||
|
||||
background-color: light-dark(@dark-blue-10, @dark-blue);
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
padding: 5px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 6px;
|
||||
width: fit-content;
|
||||
|
||||
.armor-slot {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-size: var(--font-size-12);
|
||||
|
||||
.fa-shield-halved {
|
||||
color: light-dark(@dark-blue-40, @golden-40);
|
||||
}
|
||||
}
|
||||
|
||||
.slot {
|
||||
width: 20px;
|
||||
height: 10px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
background: light-dark(@dark-blue-10, @golden-10);
|
||||
border-radius: 3px;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
|
||||
&.filled {
|
||||
background: light-dark(@dark-blue, @golden);
|
||||
}
|
||||
}
|
||||
}
|
||||
.slot-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: light-dark(@beige, @dark-blue);
|
||||
background: light-dark(@dark-blue, @golden);
|
||||
padding: 0 5px;
|
||||
width: fit-content;
|
||||
font-weight: bold;
|
||||
border-radius: 0px 0px 5px 5px;
|
||||
font-size: var(--font-size-12);
|
||||
|
||||
.label {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.value {
|
||||
padding-left: 6px;
|
||||
border-left: 1px solid light-dark(@beige, @dark-golden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hope-section {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
background-color: light-dark(transparent, @dark-blue);
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
padding: 5px 10px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
width: fit-content;
|
||||
|
||||
h4 {
|
||||
font-size: var(--font-size-12);
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
}
|
||||
|
||||
.hope-value {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-12);
|
||||
}
|
||||
}
|
||||
|
||||
.stat-section {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
background-color: light-dark(transparent, @dark-blue);
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
padding: 5px 10px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
width: fit-content;
|
||||
|
||||
h4 {
|
||||
font-size: var(--font-size-12);
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
}
|
||||
}
|
||||
|
||||
.threshold-section {
|
||||
display: flex;
|
||||
align-self: center;
|
||||
gap: 10px;
|
||||
background-color: light-dark(transparent, @dark-blue);
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
padding: 5px 10px;
|
||||
border: 1px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 3px;
|
||||
align-items: center;
|
||||
width: fit-content;
|
||||
|
||||
h4 {
|
||||
font-size: var(--font-size-12);
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
color: light-dark(@dark-blue, @golden);
|
||||
|
||||
&.threshold-value {
|
||||
color: light-dark(@dark, @beige);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.actors-dragger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
border: 1px dashed light-dark(@dark-blue-50, @beige-50);
|
||||
border-radius: 3px;
|
||||
color: light-dark(@dark-blue-50, @beige-50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,6 @@
|
|||
@import './actors/party/party-members.less';
|
||||
@import './actors/party/sheet.less';
|
||||
@import './actors/party/inventory.less';
|
||||
@import './actors/party/resources.less';
|
||||
|
||||
@import './items/beastform.less';
|
||||
@import './items/class.less';
|
||||
|
|
|
|||
|
|
@ -68,5 +68,29 @@
|
|||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
color-picker {
|
||||
gap: 4px;
|
||||
background: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.animation-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.animation-inner-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: right;
|
||||
gap: 8px;
|
||||
|
||||
.animation-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
"id": "daggerheart",
|
||||
"title": "Daggerheart",
|
||||
"description": "An unofficial implementation of the Daggerheart system",
|
||||
"version": "2.0.3",
|
||||
"version": "2.1.1",
|
||||
"compatibility": {
|
||||
"minimum": "14.359",
|
||||
"verified": "14.359",
|
||||
"verified": "14.360",
|
||||
"maximum": "14"
|
||||
},
|
||||
"authors": [
|
||||
|
|
@ -290,7 +290,6 @@
|
|||
"damageRoll": {},
|
||||
"abilityUse": {},
|
||||
"tagTeam": {},
|
||||
"groupRoll": {},
|
||||
"systemMessage": {}
|
||||
}
|
||||
},
|
||||
|
|
@ -299,5 +298,5 @@
|
|||
"secondaryTokenAttribute": "resources.stress",
|
||||
"url": "https://github.com/Foundryborne/daggerheart",
|
||||
"manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/main/system.json",
|
||||
"download": "https://github.com/Foundryborne/daggerheart/releases/download/2.0.3/system.zip"
|
||||
"download": "https://github.com/Foundryborne/daggerheart/releases/download/2.1.1/system.zip"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,16 @@
|
|||
{{/if}}
|
||||
{{#unless (eq path 'system.attack.')}}<a data-action="addDamage" {{#if @root.allDamageTypesUsed}}disabled{{/if}}><i class="fa-solid fa-plus icon-button"></i></a>{{/unless}}
|
||||
</legend>
|
||||
<div class="nest-inputs space-between">
|
||||
<div class="nest-inputs">
|
||||
{{#if @root.hasBaseDamage}}
|
||||
{{formField @root.fields.damage.fields.includeBase value=@root.source.damage.includeBase name="damage.includeBase" classes="checkbox" localize=true }}
|
||||
{{/if}}
|
||||
{{#unless (eq @root.source.type 'healing')}}
|
||||
{{formField directField value=source.direct name=(concat path "damage.direct") localize=true classes="checkbox"}}
|
||||
{{formField baseFields.direct value=source.direct name=(concat path "damage.direct") localize=true classes="checkbox"}}
|
||||
{{/unless}}
|
||||
{{#if (and @root.isNPC (not (eq path 'system.attack.')))}}
|
||||
{{formField baseFields.groupAttack value=source.groupAttack name=(concat path "damage.groupAttack") localize=true classes="select"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{!-- Handlebars uses Symbol.Iterator to produce index|key. This isn't compatible with our parts object, so we instead use applyTo, which is the same value --}}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,24 @@
|
|||
</button>
|
||||
</div>
|
||||
{{/each}}
|
||||
|
||||
{{#if damageOptions.groupAttack}}
|
||||
<fieldset class="group-attack-container">
|
||||
<legend>{{localize "DAGGERHEART.ACTIONS.Settings.groupAttack.label"}}</legend>
|
||||
|
||||
<div class="group-attack-inner-container">
|
||||
<input type="text" data-dtype="Number" name="damageOptions.groupAttack.numAttackers" value="{{damageOptions.groupAttack.numAttackers}}" />
|
||||
|
||||
<div class="group-attack-tools">
|
||||
<select name="damageOptions.groupAttack.range">
|
||||
{{selectOptions rangeOptions selected=damageOptions.groupAttack.range localize=true}}
|
||||
</select>
|
||||
<button data-action="updateGroupAttack"><i class="fa-solid fa-crosshairs"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
{{/if}}
|
||||
|
||||
{{#unless (empty @root.modifiers)}}
|
||||
<fieldset class="modifier-container two-columns">
|
||||
<legend>{{localize "DAGGERHEART.GENERAL.Modifier.plural"}}</legend>
|
||||
|
|
|
|||
6
templates/dialogs/groupRollDialog/footer.hbs
Normal file
6
templates/dialogs/groupRollDialog/footer.hbs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<section class="tab {{#if tabs.groupRoll.active}} active{{/if}}" data-group="{{tabs.groupRoll.group}}" data-tab="{{tabs.groupRoll.id}}">
|
||||
<div class="finish-container">
|
||||
<button type="button" data-action="cancelRoll">{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.cancelGroupRoll"}}</button>
|
||||
<button type="button" data-action="finishRoll" {{#unless canFinishRoll}}disabled{{/unless}} class="finish-button">{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.finishGroupRoll"}}</button>
|
||||
</div>
|
||||
</section>
|
||||
20
templates/dialogs/groupRollDialog/groupRoll.hbs
Normal file
20
templates/dialogs/groupRollDialog/groupRoll.hbs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<section class="tab {{#if tabs.groupRoll.active}} active{{/if}}" data-group="{{tabs.groupRoll.group}}" data-tab="{{tabs.groupRoll.id}}">
|
||||
<fieldset>
|
||||
<legend>{{localize "DAGGERHEART.GENERAL.result.single"}}</legend>
|
||||
|
||||
<div class="group-roll-results">
|
||||
{{#if hasRolled}}<span class="roll-title {{groupRoll.totalDualityClass}}">{{groupRoll.total}} {{groupRoll.totalLabel}}</span>{{/if}}
|
||||
<div class="group-roll-container">
|
||||
<span>{{#if groupRoll.leaderTotal includeZero=true}}{{groupRoll.leaderTotal}}{{else}}{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leaderRoll"}}{{/if}}</span>
|
||||
{{#each groupRoll.modifiers as |modifier|}}
|
||||
<span>{{#if (gte modifier 0)}}+{{else}}-{{/if}}</span>
|
||||
<span>{{positive modifier}}</span>
|
||||
{{/each}}
|
||||
{{#unless groupRoll.modifiers.length}}
|
||||
<span>+</span>
|
||||
<span>{{localize "DAGGERHEART.GENERAL.Modifier.plural"}}</span>
|
||||
{{/unless}}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</section>
|
||||
85
templates/dialogs/groupRollDialog/groupRollMember.hbs
Normal file
85
templates/dialogs/groupRollDialog/groupRollMember.hbs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
{{#with (lookup members partId)}}
|
||||
<fieldset class="team-member-container {{#if @root.allHaveRolled}}select-padding{{/if}} {{#unless isEditable}}inactive{{/unless}}" data-member-key="{{@root.partId}}">
|
||||
<div class="data-container">
|
||||
<div class="member-info">
|
||||
<img src="{{img}}" />
|
||||
<div class="member-data">
|
||||
<span class="member-name">{{name}}</span>
|
||||
<div class="roll-setup">
|
||||
<div class="form-group">
|
||||
<div class="form-fields">
|
||||
{{!-- <label>{{localize "DAGGERHEART.GENERAL.Trait.single"}}</label> --}}
|
||||
<select name="{{concat "system.groupRoll.aidingCharacters." @root.partId ".rollChoice"}}" {{#if hasRolled}}disabled{{/if}}>
|
||||
{{selectOptions ../traitOptions selected=rollChoice localize=true}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if readyToRoll}}
|
||||
<div class="roll-container">
|
||||
<span class="roll-title">
|
||||
{{localize "DAGGERHEART.GENERAL.roll"}}
|
||||
<div class="roll-tools">
|
||||
<a class="roll-button" data-action="makeRoll" data-member="{{@root.partId}}">
|
||||
<img src="systems/daggerheart/assets/icons/dice/hope/d12.svg" />
|
||||
</a>
|
||||
|
||||
{{#if hasRolled}}
|
||||
<a class="delete-button" data-action="removeRoll" data-member="{{@root.partId}}">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</span>
|
||||
|
||||
{{#if roll}}
|
||||
<div class="roll-data {{#if roll.withHope}}hope{{else if roll.withFear}}fear{{else}}critical{{/if}}">
|
||||
<div class="duality-label">{{roll.total}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.totalLabel}}</div>
|
||||
<div class="roll-dice-container">
|
||||
<a class="roll-dice" data-action="rerollDice" data-member="{{@root.partId}}" data-dice-type="hope">
|
||||
<span class="dice-label">{{roll.dHope.total}}</span>
|
||||
<img src="{{concat "systems/daggerheart/assets/icons/dice/hope/" roll.dHope.denomination ".svg"}}" />
|
||||
</a>
|
||||
<span class="roll-operator">+</span>
|
||||
<a class="roll-dice" data-action="rerollDice" data-member="{{@root.partId}}" data-dice-type="fear">
|
||||
<span class="dice-label">{{roll.dFear.total}}</span>
|
||||
<img src="{{concat "systems/daggerheart/assets/icons/dice/fear/" roll.dFear.denomination ".svg"}}" />
|
||||
</a>
|
||||
{{#if roll.advantage.type}}
|
||||
<span class="roll-operator">{{#if (eq roll.advantage.type 1)}}+{{else}}-{{/if}}</span>
|
||||
<span class="roll-dice">
|
||||
<span class="dice-label">{{roll.advantage.value}}</span>
|
||||
<img src="{{concat "systems/daggerheart/assets/icons/dice/" (ifThen (eq roll.advantage.type 1) "adv/" "disadv/") roll.advantage.dice ".svg"}}" />
|
||||
</span>
|
||||
{{/if}}
|
||||
<span class="roll-operator">{{#if (gte roll.modifierTotal 0)}}+{{else}}-{{/if}}</span>
|
||||
<span class="roll-value">{{positive roll.modifierTotal}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<span class="hint">{{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.makeYourRoll"}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if hasRolled}}
|
||||
<div class="roll-success-container">
|
||||
{{#if ../isGM}}
|
||||
<div class="roll-success-tools">
|
||||
<a data-action="markSuccessfull" data-member="{{@root.partId}}" data-successfull="true">
|
||||
<i class="{{#if successfull}}fa-solid{{else}}fa-regular{{/if}} fa-circle-check"></i>
|
||||
</a>
|
||||
<a data-action="markSuccessfull" data-member="{{@root.partId}}">
|
||||
<i class="{{#unless successfull}}fa-solid{{else}}fa-regular{{/unless}} fa-circle-xmark"></i>
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="roll-success-modifier {{#if successfull}}success{{else if (not (isNullish successfull))}}failure{{/if}}">
|
||||
{{localize "DAGGERHEART.GENERAL.Modifier.single"}}{{#if successfull}} + 1{{else if (isNullish successfull)}} + ?{{else}} - 1{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</fieldset>
|
||||
{{/with}}
|
||||
32
templates/dialogs/groupRollDialog/initialization.hbs
Normal file
32
templates/dialogs/groupRollDialog/initialization.hbs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<section class="initialization-container tab {{#if tabs.initialization.active}} active{{/if}}" data-group="{{tabs.initialization.group}}" data-tab="{{tabs.initialization.id}}">
|
||||
<div class="members-container">
|
||||
{{#each memberSelection as |member|}}
|
||||
<a
|
||||
class="member-container {{#unless member.selected}}inactive {{#if ../allselected}}locked{{/if}}{{/unless}}"
|
||||
data-action="toggleSelectMember" data-id="{{member.id}}" {{#if (and (not member.selected) ../allSelected)}}disabled{{/if}}
|
||||
>
|
||||
<span class="member-name">{{member.name}}</span>
|
||||
<img src="{{member.img}}" />
|
||||
</a>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
<div class="main-roll {{#if selectedLeaderDisabled}}inactive{{/if}}">
|
||||
<div class="form-group">
|
||||
<label>{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leader"}}</label>
|
||||
<div class="form-fields">
|
||||
<select class="main-character-field" {{#if selectedLeaderDisabled}}disabled{{/if}}>
|
||||
{{selectOptions selectedLeaderOptions selected=selectedLeader.memberId blank="" }}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<button type="button" data-action="startGroupRoll" {{#unless canStartGroupRoll}}disabled{{/unless}}>{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.startGroupRoll"}} <i class="fa-solid fa-arrow-right-long"></i></button>
|
||||
<div class="finish-tools {{#unless canStartGroupRoll}}inactive{{/unless}}">
|
||||
<span>{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.openDialogForAll"}}</span>
|
||||
<input type="checkbox" class="openforall-field" {{#unless canStartGroupRoll}}disabled{{/unless}} {{checked openForAllPlayers}} />
|
||||
</div>
|
||||
</footer>
|
||||
</section>
|
||||
73
templates/dialogs/groupRollDialog/leader.hbs
Normal file
73
templates/dialogs/groupRollDialog/leader.hbs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<section class="tab {{#if tabs.groupRoll.active}} active{{/if}}" data-group="{{tabs.groupRoll.group}}" data-tab="{{tabs.groupRoll.id}}">
|
||||
{{#with leader}}
|
||||
<div class="main-character-outer-container {{#unless isEditable}}inactive{{/unless}}">
|
||||
<div class="section-title">{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leader"}}</div>
|
||||
<fieldset>
|
||||
<div class="main-character-container">
|
||||
<div class="character-info">
|
||||
<img src="{{img}}" />
|
||||
<div class="character-data">
|
||||
<span>{{name}}</span>
|
||||
<div class="roll-setup">
|
||||
<div class="form-group">
|
||||
<div class="form-fields">
|
||||
<select name="system.groupRoll.leader.rollChoice" {{#if hasRolled}}disabled{{/if}}>
|
||||
{{selectOptions ../traitOptions selected=rollChoice localize=true}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if readyToRoll}}
|
||||
<div class="roll-container">
|
||||
<span class="roll-title">
|
||||
{{localize "DAGGERHEART.GENERAL.roll"}}
|
||||
<div class="roll-tools">
|
||||
<a class="roll-button" data-action="makeLeaderRoll">
|
||||
<img src="systems/daggerheart/assets/icons/dice/hope/d12.svg" />
|
||||
</a>
|
||||
|
||||
{{#if hasRolled}}
|
||||
<a class="delete-button" data-action="removeLeaderRoll">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</span>
|
||||
|
||||
{{#if roll}}
|
||||
<div class="roll-data {{#if roll.withHope}}hope{{else if roll.withFear}}fear{{else}}critical{{/if}}">
|
||||
<div class="duality-label">{{roll.total}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.totalLabel}}</div>
|
||||
<div class="roll-dice-container">
|
||||
<a class="roll-dice" data-action="rerollLeaderDice" data-dice-type="hope">
|
||||
<span class="dice-label">{{roll.dHope.total}}</span>
|
||||
<img src="{{concat "systems/daggerheart/assets/icons/dice/hope/" roll.dHope.denomination ".svg"}}" />
|
||||
</a>
|
||||
<span class="roll-operator">+</span>
|
||||
<a class="roll-dice" data-action="rerollLeaderDice" data-dice-type="fear">
|
||||
<span class="dice-label">{{roll.dFear.total}}</span>
|
||||
<img src="{{concat "systems/daggerheart/assets/icons/dice/fear/" roll.dFear.denomination ".svg"}}" />
|
||||
</a>
|
||||
{{#if roll.advantage.type}}
|
||||
<span class="roll-operator">{{#if (eq roll.advantage.type 1)}}+{{else}}-{{/if}}</span>
|
||||
<span class="roll-dice">
|
||||
<span class="dice-label">{{roll.advantage.value}}</span>
|
||||
<img src="{{concat "systems/daggerheart/assets/icons/dice/" (ifThen (eq roll.advantage.type 1) "adv/" "disadv/") roll.advantage.dice ".svg"}}" />
|
||||
</span>
|
||||
{{/if}}
|
||||
<span class="roll-operator">{{#if (gte roll.modifierTotal 0)}}+{{else}}-{{/if}}</span>
|
||||
<span class="roll-value">{{positive roll.modifierTotal}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<span class="hint">{{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.makeYourRoll"}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</fieldset>
|
||||
</div>
|
||||
{{/with}}
|
||||
</section>
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
<section class="initialization-container tab {{#if tabs.initialization.active}} active{{/if}}" data-group="{{tabs.initialization.group}}" data-tab="{{tabs.initialization.id}}">
|
||||
{{partId}}
|
||||
<h2>{{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.selectParticipants"}}</h2>
|
||||
<div class="members-container">
|
||||
{{#each memberSelection as |member|}}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,16 @@
|
|||
{{/if}}
|
||||
<div class="form-group">
|
||||
<label>{{localize "DAGGERHEART.SETTINGS.Menu.appearance.diceSoNice.critical"}}</label>
|
||||
|
||||
<div class="form-fields">
|
||||
{{formInput fields.diceSoNice.fields.sfx.fields.critical.fields.class value=setting.diceSoNice.sfx.critical.class blank="" localize=true}}
|
||||
</div>
|
||||
<div class="form-fields">
|
||||
{{formInput fields.diceSoNice.fields.sfx.fields.critical.fields.class value=setting.diceSoNice.sfx.critical.class blank="" localize=true}}
|
||||
</div>
|
||||
<label>{{localize "DAGGERHEART.SETTINGS.Menu.appearance.diceSoNice.muted"}}</label>
|
||||
<div class="form-fields">
|
||||
{{formInput fields.diceSoNice.fields.sfx.fields.critical.fields.options.fields.muteSound value=setting.diceSoNice.sfx.critical.options.muteSound localize=true}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section class='tab-navigation'>
|
||||
|
|
|
|||
|
|
@ -42,9 +42,15 @@
|
|||
|
||||
{{#if animations}}
|
||||
<h3>{{localize "DAGGERHEART.SETTINGS.Menu.appearance.diceSoNice.animations"}}</h3>
|
||||
<div class="label-container full-width">
|
||||
<div class="animation-container">
|
||||
<label>{{localize "DAGGERHEART.CONFIG.DaggerheartDiceAnimationEvents.higher.name"}}</label>
|
||||
{{formInput fields.sfx.fields.higher.fields.class value=values.sfx.higher.class blank="" localize=true}}
|
||||
<div class="animation-inner-container">
|
||||
{{formInput fields.sfx.fields.higher.fields.class value=values.sfx.higher.class blank="" localize=true}}
|
||||
<div class="animation-control">
|
||||
<label>{{localize "DAGGERHEART.SETTINGS.Menu.appearance.diceSoNice.muted"}}</label>
|
||||
{{formInput fields.sfx.fields.higher.fields.options.fields.muteSound value=values.sfx.higher.options.muteSound localize=true}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
>
|
||||
{{#if fields.roll}}{{> 'systems/daggerheart/templates/actionTypes/roll.hbs' fields=fields.roll.fields source=source.roll}}{{/if}}
|
||||
{{#if fields.save}}{{> 'systems/daggerheart/templates/actionTypes/save.hbs' fields=fields.save.fields source=source.save}}{{/if}}
|
||||
{{#if fields.damage}}{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=fields.damage.fields.parts.element.fields source=source.damage directField=fields.damage.fields.direct }}{{/if}}
|
||||
{{#if fields.damage}}{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=fields.damage.fields.parts.element.fields source=source.damage baseFields=fields.damage.fields }}{{/if}}
|
||||
{{#if fields.macro}}{{> 'systems/daggerheart/templates/actionTypes/macro.hbs' fields=fields.macro source=source.macro}}{{/if}}
|
||||
{{#if fields.effects}}{{> 'systems/daggerheart/templates/actionTypes/effect.hbs' fields=fields.effects.element.fields source=source.effects}}{{/if}}
|
||||
{{#if fields.beastform}}{{> 'systems/daggerheart/templates/actionTypes/beastform.hbs' fields=fields.beastform.fields source=source.beastform}}{{/if}}
|
||||
|
|
|
|||
|
|
@ -22,5 +22,5 @@
|
|||
</div>
|
||||
{{formGroup systemFields.criticalThreshold value=document._source.system.criticalThreshold label="DAGGERHEART.ACTIONS.Settings.criticalThreshold" name="system.criticalThreshold" localize=true}}
|
||||
</fieldset>
|
||||
{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." directField=systemFields.attack.fields.damage.fields.direct horde=(eq document._source.system.type 'horde')}}
|
||||
{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." baseFields=systemFields.attack.fields.damage.fields horde=(eq document._source.system.type 'horde')}}
|
||||
</section>
|
||||
|
|
@ -18,5 +18,5 @@
|
|||
{{/if}}
|
||||
{{/if}}
|
||||
</fieldset>
|
||||
{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." directField=systemFields.attack.fields.damage.fields.direct}}
|
||||
{{> 'systems/daggerheart/templates/actionTypes/damage.hbs' fields=systemFields.attack.fields.damage.fields.parts.element.fields source=document.system.attack.damage path="system.attack." baseFields=systemFields.attack.fields.damage.fields}}
|
||||
</section>
|
||||
|
|
@ -4,17 +4,27 @@
|
|||
<h1 class="actor-name input" contenteditable="plaintext-only" data-property="name" placeholder="{{localize "DAGGERHEART.GENERAL.actorName"}}">{{source.name}}</h1>
|
||||
<div class='level-div'>
|
||||
<h3 class='label'>
|
||||
{{#if (or document.system.needsCharacterSetup document.system.levelData.canLevelUp)}}
|
||||
{{#if document.system.needsCharacterSetup}}
|
||||
<button
|
||||
type="button"
|
||||
class="level-button glow" data-tooltip="{{#if document.system.needsCharacterSetup}}{{localize "DAGGERHEART.APPLICATIONS.CharacterCreation.buttonTitle"}}{{else}}{{localize "DAGGERHEART.ACTORS.Character.levelUp"}}{{/if}}"
|
||||
class="level-button glow"
|
||||
data-action="levelManagement"
|
||||
>
|
||||
{{localize "DAGGERHEART.APPLICATIONS.CharacterCreation.buttonTitle"}}
|
||||
</button>
|
||||
{{else if document.system.levelData.canLevelUp}}
|
||||
<button
|
||||
type="button"
|
||||
class="level-button glow" data-tooltip="{{localize "DAGGERHEART.ACTORS.Character.levelUp"}}"
|
||||
data-action="levelManagement"
|
||||
>
|
||||
<i class="fa-solid fa-angles-up"></i>
|
||||
</button>
|
||||
{{/if}}
|
||||
{{localize 'DAGGERHEART.GENERAL.level'}}
|
||||
<input type="text" data-dtype="Number" class="level-value" value={{#if document.system.needsCharacterSetup}}0{{else}}{{document.system.levelData.level.changed}}{{/if}} {{#if document.system.needsCharacterSetup}}disabled{{/if}} />
|
||||
{{#unless document.system.needsCharacterSetup}}
|
||||
{{localize 'DAGGERHEART.GENERAL.level'}}
|
||||
<input type="text" data-dtype="Number" class="level-value" value={{#if document.system.needsCharacterSetup}}0{{else}}{{document.system.levelData.level.changed}}{{/if}} {{#if document.system.needsCharacterSetup}}disabled{{/if}} />
|
||||
{{/unless}}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
<div class='item-container'>
|
||||
<div class="item-info">
|
||||
<h1 class='item-name'><input type='text' name='name' value='{{source.name}}' /></h1>
|
||||
<h2 class="label">Party</h2>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
@ -9,33 +9,160 @@
|
|||
<i class="fa-solid fa-user-group"></i>
|
||||
<span>Tag Team Roll</span>
|
||||
</button>
|
||||
<button data-action="groupRoll">
|
||||
<button data-action="groupRoll" class="{{#if groupRollActive}}active-action{{/if}}">
|
||||
<i class="fa-solid fa-users"></i>
|
||||
<span>Group Roll</span>
|
||||
</button>
|
||||
{{!-- NOT YET IMPLEMENTED --}}
|
||||
{{!-- <button>
|
||||
<i class="fa-solid fa-handshake-angle"></i>
|
||||
<span>Help Action</span>
|
||||
</button> --}}
|
||||
<button data-action="triggerRest" data-action="triggerRest" data-type="shortRest">
|
||||
<i class="fa-solid fa-utensils"></i>
|
||||
<span>{{localize "DAGGERHEART.APPLICATIONS.Downtime.shortRest.title"}}</span>
|
||||
</button>
|
||||
<button data-action="triggerRest" data-type="longRest">
|
||||
<i class="fa-solid fa-bed"></i>
|
||||
<span>{{localize "DAGGERHEART.APPLICATIONS.Downtime.longRest.title"}}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<fieldset class="actors-section glassy">
|
||||
<legend>{{localize tabs.partyMembers.label}}</legend>
|
||||
<ul class="actors-list">
|
||||
{{#each document.system.partyMembers as |actor id|}}
|
||||
{{> 'daggerheart.inventory-item'
|
||||
item=actor
|
||||
type='character'
|
||||
isActor=true
|
||||
hideContextMenu=true
|
||||
}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{#unless document.system.partyMembers.length}}
|
||||
<div class="actors-dragger">
|
||||
<span>{{localize "DAGGERHEART.GENERAL.dropActorsHere"}}</span>
|
||||
</div>
|
||||
{{/unless}}
|
||||
</fieldset>
|
||||
</section>
|
||||
<ul class="actors-list">
|
||||
{{#each partyMembers as |member id|}}
|
||||
<li class="actor-resources">
|
||||
<div class="actor-img-frame">
|
||||
<img class="actor-img" src="{{member.img}}">
|
||||
{{#if member.weapons}}
|
||||
<div class="equipped-weapons">
|
||||
{{#each member.weapons as |weapon|}}
|
||||
<img src="{{weapon.img}}" data-tooltip="{{weapon.name}}"/>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if member.evasion includeZero=true}}
|
||||
<div class="evasion" data-tooltip="DAGGERHEART.GENERAL.evasion">{{member.evasion}}</div>
|
||||
{{/if}}
|
||||
{{#if member.difficulty includeZero=true}}
|
||||
<div class="evasion" data-tooltip="DAGGERHEART.GENERAL.difficulty">{{member.difficulty}}</div>
|
||||
{{/if}}
|
||||
{{#unless (eq member.type 'companion')}}
|
||||
<div class="threshold-section">
|
||||
<h4 class="threshold-label">{{localize "DAGGERHEART.ACTORS.Party.Thresholds.minor"}}</h4>
|
||||
<h4 class="threshold-value">{{member.damageThresholds.major}}</h4>
|
||||
<h4 class="threshold-label">{{localize "DAGGERHEART.ACTORS.Party.Thresholds.major"}}</h4>
|
||||
<h4 class="threshold-value">{{member.damageThresholds.severe}}</h4>
|
||||
<h4 class="threshold-label">{{localize "DAGGERHEART.ACTORS.Party.Thresholds.severe"}}</h4>
|
||||
</div>
|
||||
{{/unless}}
|
||||
</div>
|
||||
<header>
|
||||
<h2 class="actor-name">
|
||||
<a data-action="openDocument" data-uuid="{{member.uuid}}">{{member.name}}</a>
|
||||
<a class="delete-icon" data-action="deletePartyMember" data-uuid="{{member.uuid}}"><i class="fa-regular fa-times" inert></i></a>
|
||||
</h2>
|
||||
<div>
|
||||
{{#unless (or (eq member.type 'companion') (eq member.type 'adversary')) }}
|
||||
<div class="hope-section">
|
||||
<h4>{{localize "DAGGERHEART.GENERAL.hope"}}</h4>
|
||||
{{#times member.resources.hope.max}}
|
||||
<span class='hope-value' data-action='toggleHope' data-actor-id="{{member.uuid}}" data-value="{{add this 1}}">
|
||||
{{#if (gte member.resources.hope.value (add this 1))}}
|
||||
<i class='fa-solid fa-diamond'></i>
|
||||
{{else}}
|
||||
<i class='fa-regular fa-circle'></i>
|
||||
{{/if}}
|
||||
</span>
|
||||
{{/times}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
</div>
|
||||
{{#if member.subtitle}}
|
||||
<span class="subtitle">{{member.subtitle}}</span>
|
||||
{{/if}}
|
||||
</header>
|
||||
<section class="body">
|
||||
<section class="resources">
|
||||
{{#unless (eq member.type 'companion') }}
|
||||
<div class="slot-section">
|
||||
<div class="slot-label" data-tooltip="DAGGERHEART.GENERAL.HitPoints.plural">
|
||||
<span class="label">
|
||||
<i class="fa-solid fa-heart" inert></i>
|
||||
</span>
|
||||
<span class="value">
|
||||
<span class="current">{{member.resources.hitPoints.value}}</span>
|
||||
/
|
||||
<span class="max">{{member.resources.hitPoints.max}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="slot-bar">
|
||||
{{#times member.resources.hitPoints.max}}
|
||||
<span class='slot {{#if (gte member.resources.hitPoints.value (add this 1))}}filled{{/if}}'
|
||||
data-action='toggleHitPoints' data-actor-id="{{member.uuid}}" data-value="{{add this 1}}">
|
||||
</span>
|
||||
{{/times}}
|
||||
</div>
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
<div class="slot-section">
|
||||
<div class="slot-label" data-tooltip="DAGGERHEART.GENERAL.stress">
|
||||
<span class="label">
|
||||
<i class="fa-solid fa-bolt" inert></i>
|
||||
</span>
|
||||
<span class="value">
|
||||
<span class="current">{{member.resources.stress.value}}</span>
|
||||
/
|
||||
<span class="max">{{member.resources.stress.max}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="slot-bar">
|
||||
{{#times member.resources.stress.max}}
|
||||
<span class='slot {{#if (gte member.resources.stress.value (add this 1))}}filled{{/if}}'
|
||||
data-action='toggleStress' data-actor-id="{{member.uuid}}" data-value="{{add this 1}}">
|
||||
</span>
|
||||
{{/times}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if member.armorScore.max}}
|
||||
<div class="slot-section">
|
||||
<div class="slot-label" data-tooltip="DAGGERHEART.GENERAL.armorSlots">
|
||||
<span class="label">
|
||||
<i class="fa-solid fa-shield" inert></i>
|
||||
</span>
|
||||
<span class="value">
|
||||
<span class="current">{{member.armorScore.value}}</span>
|
||||
/
|
||||
<span class="max">{{member.armorScore.max}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="slot-bar">
|
||||
{{#times member.armorScore.max}}
|
||||
<a class='armor-slot' data-action='toggleArmorSlot' data-actor-id="{{member.uuid}}" data-value="{{add this 1}}">
|
||||
{{#if (gte member.armorScore.value (add this 1))}}
|
||||
<i class="fa-solid fa-shield"></i>
|
||||
{{else}}
|
||||
<i class="fa-solid fa-shield-halved"></i>
|
||||
{{/if}}
|
||||
</a>
|
||||
{{/times}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</section>
|
||||
{{#if member.traits}}
|
||||
<div class="traits">
|
||||
{{#each member.traits as |trait|}}
|
||||
<span class="trait">
|
||||
<span class="label">{{trait.label}}</span>
|
||||
<span class="value">{{trait.value}}</span>
|
||||
</span>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</section>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{#unless document.system.partyMembers.length}}
|
||||
<div class="actors-dragger">
|
||||
<span>{{localize "DAGGERHEART.GENERAL.dropActorsHere"}}</span>
|
||||
</div>
|
||||
{{/unless}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,110 +0,0 @@
|
|||
<section
|
||||
class='tab {{tabs.resources.cssClass}} {{tabs.resources.id}}'
|
||||
data-tab='{{tabs.resources.id}}'
|
||||
data-group='{{tabs.resources.group}}'
|
||||
>
|
||||
<div data-action="triggerRest" data-type="longRest" class="actions-section">
|
||||
<button data-type="longRest">
|
||||
<i class="fa-solid fa-bed"></i>
|
||||
<span>{{localize "DAGGERHEART.APPLICATIONS.Downtime.longRest.title"}}</span>
|
||||
</button>
|
||||
<button data-action="triggerRest" data-type="shortRest">
|
||||
<i class="fa-solid fa-utensils"></i>
|
||||
<span>{{localize "DAGGERHEART.APPLICATIONS.Downtime.shortRest.title"}}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<fieldset class="resource-section glassy">
|
||||
<legend>{{localize tabs.resources.label}}</legend>
|
||||
<ul class="actors-list">
|
||||
{{#each document.system.partyMembers as |actor id|}}
|
||||
<li class="actor-resources">
|
||||
<h2 class="actor-name">{{actor.name}}</h2>
|
||||
<img class="actor-img" src="{{actor.img}}">
|
||||
<div class="resources">
|
||||
{{#unless (eq actor.type 'companion') }}
|
||||
<div class="slot-section">
|
||||
<div class="slot-bar">
|
||||
{{#times actor.system.resources.hitPoints.max}}
|
||||
<span class='slot {{#if (gte actor.system.resources.hitPoints.value (add this 1))}}filled{{/if}}'
|
||||
data-action='toggleHitPoints' data-actor-id="{{actor.uuid}}" data-value="{{add this 1}}">
|
||||
</span>
|
||||
{{/times}}
|
||||
</div>
|
||||
<div class="slot-label">
|
||||
<span class="label">{{localize "DAGGERHEART.GENERAL.HitPoints.short"}}</span>
|
||||
<span class="value">{{actor.system.resources.hitPoints.value}} / {{actor.system.resources.hitPoints.max}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
<div class="slot-section">
|
||||
<div class="slot-bar">
|
||||
{{#times actor.system.resources.stress.max}}
|
||||
<span class='slot {{#if (gte actor.system.resources.stress.value (add this 1))}}filled{{/if}}'
|
||||
data-action='toggleStress' data-actor-id="{{actor.uuid}}" data-value="{{add this 1}}">
|
||||
</span>
|
||||
{{/times}}
|
||||
</div>
|
||||
<div class="slot-label">
|
||||
<span class="label">{{localize "DAGGERHEART.GENERAL.stress"}}</span>
|
||||
<span class="value">{{actor.system.resources.stress.value}} / {{actor.system.resources.stress.max}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if actor.system.armorScore.max}}
|
||||
<div class="slot-section">
|
||||
<div class="slot-bar">
|
||||
{{#times actor.system.armorScore.max}}
|
||||
<a class='armor-slot' data-action='toggleArmorSlot' data-actor-id="{{actor.id}}" data-value="{{add this 1}}">
|
||||
{{#if (gte actor.system.armorScore.value (add this 1))}}
|
||||
<i class="fa-solid fa-shield"></i>
|
||||
{{else}}
|
||||
<i class="fa-solid fa-shield-halved"></i>
|
||||
{{/if}}
|
||||
</a>
|
||||
{{/times}}
|
||||
</div>
|
||||
<div class="slot-label">
|
||||
<span class="label">{{localize "DAGGERHEART.GENERAL.armorSlots"}}</span>
|
||||
<span class="value">{{actor.system.armorScore.value}} / {{actor.system.armorScore.max}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#unless (or (eq actor.type 'companion') (eq actor.type 'adversary')) }}
|
||||
<div class="hope-section">
|
||||
<h4>{{localize "DAGGERHEART.GENERAL.hope"}}</h4>
|
||||
{{#times actor.system.resources.hope.max}}
|
||||
<span class='hope-value' data-action='toggleHope' data-actor-id="{{actor.uuid}}" data-value="{{add this 1}}">
|
||||
{{#if (gte actor.system.resources.hope.value (add this 1))}}
|
||||
<i class='fa-solid fa-diamond'></i>
|
||||
{{else}}
|
||||
<i class='fa-regular fa-circle'></i>
|
||||
{{/if}}
|
||||
</span>
|
||||
{{/times}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
{{#if (eq actor.type 'character')}}
|
||||
<div class="stat-section">
|
||||
<h4>{{localize "DAGGERHEART.GENERAL.evasion"}}: {{actor.system.evasion}}</h4>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#unless (eq actor.type 'companion')}}
|
||||
<div class="threshold-section">
|
||||
<h4 class="threshold-label">{{localize "DAGGERHEART.GENERAL.DamageThresholds.minor"}}</h4>
|
||||
<h4 class="threshold-value">{{actor.system.damageThresholds.major}}</h4>
|
||||
<h4 class="threshold-label">{{localize "DAGGERHEART.GENERAL.DamageThresholds.major"}}</h4>
|
||||
<h4 class="threshold-value">{{actor.system.damageThresholds.severe}}</h4>
|
||||
<h4 class="threshold-label">{{localize "DAGGERHEART.GENERAL.DamageThresholds.severe"}}</h4>
|
||||
</div>
|
||||
{{/unless}}
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</fieldset>
|
||||
</section>
|
||||
|
|
@ -33,31 +33,32 @@
|
|||
<div class="roll-formula">{{total}}</div></span></label>
|
||||
{{/if}}
|
||||
<div class="roll-dice">
|
||||
{{#each dice}}
|
||||
{{#each results}}
|
||||
{{#unless discarded}}
|
||||
<div class="roll-die{{#unless @../first}} has-plus{{/unless}}">
|
||||
<div
|
||||
class="dice reroll-button {{../dice}}"
|
||||
data-die-index="0" data-type="damage" data-damage-type="{{@../../../key}}" data-part="{{@../../key}}" data-dice="{{@../key}}" data-result="{{@key}}"
|
||||
>
|
||||
{{#if hasRerolls}}<i class="fa-solid fa-dice dice-rerolled" data-tooltip="{{localize "DAGGERHEART.GENERAL.rerolled"}}"></i>{{/if}}
|
||||
{{result}}
|
||||
{{#if dice.length}}
|
||||
{{#each dice}}
|
||||
{{#each results}}
|
||||
{{#unless discarded}}
|
||||
<div class="roll-die{{#unless @../first}} has-plus{{/unless}}">
|
||||
<div
|
||||
class="dice reroll-button {{../dice}}"
|
||||
data-die-index="0" data-type="damage" data-damage-type="{{@../../../key}}" data-part="{{@../../key}}" data-dice="{{@../key}}" data-result="{{@key}}"
|
||||
>
|
||||
{{#if hasRerolls}}<i class="fa-solid fa-dice dice-rerolled" data-tooltip="{{localize "DAGGERHEART.GENERAL.rerolled"}}"></i>{{/if}}
|
||||
{{result}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/unless}}
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
{{#if modifierTotal}}
|
||||
<div class="roll-die{{#if (gt modifierTotal 0)}} has-plus{{/if}}">
|
||||
<div class="font-20">{{modifierTotal}}</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#unless dice.length}}
|
||||
{{#if modifierTotal}}
|
||||
<div class="roll-die{{#if (gt modifierTotal 0)}} has-plus{{/if}}">
|
||||
<div class="font-20">{{modifierTotal}}</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<div class="roll-die">
|
||||
<div class="font-20">{{total}}</div>
|
||||
</div>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</fieldset>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue