mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-06-06 21:04:16 +02:00
Compare commits
79 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d98f16ac6 | ||
|
|
98c8e1f498 | ||
|
|
2e524878b3 | ||
|
|
161c8222dc | ||
|
|
00a1d9766c | ||
|
|
f7b82b7d7e | ||
|
|
3d7199e7e5 | ||
|
|
b3ab7ee3a7 | ||
|
|
3157fd450f | ||
|
|
cfd9950aae | ||
|
|
702c9e0b6a | ||
|
|
607ee3b580 | ||
|
|
931b84d16d | ||
|
|
2a79468ce1 | ||
|
|
c4d314171b | ||
|
|
24073e4a16 | ||
|
|
cc5bfbe27d | ||
|
|
f66088971d | ||
|
|
882143c1bb | ||
|
|
baa72ff461 | ||
|
|
cf28e011f2 | ||
|
|
623f62e4b9 | ||
|
|
40109dbbe4 | ||
|
|
d12220c64f | ||
|
|
f4282429cd | ||
|
|
1f02795b5d | ||
|
|
d7b37f8178 | ||
|
|
f8df53ed83 | ||
|
|
8ee5db2832 | ||
|
|
bbc521ece0 | ||
|
|
be8d7f6469 | ||
|
|
3a4b66f487 | ||
|
|
cdf159b4a7 | ||
|
|
413a37483c | ||
|
|
c5e21d9d92 | ||
|
|
10c0b6b51e | ||
|
|
652a554c9a | ||
|
|
c0ed5fe697 | ||
|
|
ff65abe09b | ||
|
|
ec7a7b378d | ||
|
|
8e34356905 | ||
|
|
35bceac520 | ||
|
|
436acb0617 | ||
|
|
1d114633f5 | ||
|
|
1c70b46639 | ||
|
|
ae38245877 | ||
|
|
af5d3d4568 | ||
|
|
6b5c1ff965 | ||
|
|
42a22a49f0 | ||
|
|
da77c2a190 | ||
|
|
68decf0b57 | ||
|
|
4f0670cc35 | ||
|
|
b346ce6766 | ||
|
|
dddd0581f7 | ||
|
|
83329fac46 | ||
|
|
ee0b7b2792 | ||
|
|
4d062a6892 | ||
|
|
487c1fd9a2 | ||
|
|
3aa5cd806a | ||
|
|
2e93b79633 | ||
|
|
244dbd4902 | ||
|
|
c7aed6825a | ||
|
|
9cb5112b62 | ||
|
|
81b6f7fc51 | ||
|
|
828fffd552 | ||
|
|
fc5626ac47 | ||
|
|
2e62545aa7 | ||
|
|
b09c712dd5 | ||
|
|
ca4336bd39 | ||
|
|
77ac11c522 | ||
|
|
50311679a5 | ||
|
|
3a7bcd1b0a | ||
|
|
511e4bd644 | ||
|
|
395820513b | ||
|
|
3566ea3fd3 | ||
|
|
29d502fb97 | ||
|
|
685a25d25a | ||
|
|
dd045b3df7 | ||
|
|
0aabcec340 |
70 changed files with 295 additions and 233 deletions
2
.github/workflows/deploy.yml
vendored
2
.github/workflows/deploy.yml
vendored
|
|
@ -35,7 +35,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
version: ${{steps.get_version.outputs.version-without-v}}
|
version: ${{steps.get_version.outputs.version-without-v}}
|
||||||
url: https://github.com/${{github.repository}}
|
url: https://github.com/${{github.repository}}
|
||||||
manifest: https://github.com/${{github.repository}}/releases/latest/download/system.json
|
manifest: https://raw.githubusercontent.com/${{github.repository}}/V13/system.json
|
||||||
download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/system.zip
|
download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/system.zip
|
||||||
|
|
||||||
# Create a zip file with all files required by the module to add to the release
|
# Create a zip file with all files required by the module to add to the release
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ You can find the documentation here: https://github.com/Foundryborne/daggerheart
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Looking to contribute to the project? Look no further, check out our [contributing guide](contributing.md), and keep the [Code of Conduct](coc.md) in mind when working on things.
|
Looking to contribute to the project? Look no further, check out our [contributing guide](CONTRIBUTING.md), and keep the [Code of Conduct](coc.md) in mind when working on things.
|
||||||
|
|
||||||
## Disclaimer:
|
## Disclaimer:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -405,6 +405,8 @@ Hooks.on('chatMessage', (_, message) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateActorsRangeDependentEffects = async token => {
|
const updateActorsRangeDependentEffects = async token => {
|
||||||
|
if (!token) return;
|
||||||
|
|
||||||
const rangeMeasurement = game.settings.get(
|
const rangeMeasurement = game.settings.get(
|
||||||
CONFIG.DH.id,
|
CONFIG.DH.id,
|
||||||
CONFIG.DH.SETTINGS.gameSettings.variantRules
|
CONFIG.DH.SETTINGS.gameSettings.variantRules
|
||||||
|
|
|
||||||
67
lang/en.json
67
lang/en.json
|
|
@ -71,9 +71,7 @@
|
||||||
"name": "Summon",
|
"name": "Summon",
|
||||||
"tooltip": "Create tokens in the scene.",
|
"tooltip": "Create tokens in the scene.",
|
||||||
"error": "You do not have permission to summon tokens or there is no active scene.",
|
"error": "You do not have permission to summon tokens or there is no active scene.",
|
||||||
"invalidDrop": "You can only drop Actor entities to summon.",
|
"invalidDrop": "You can only drop Actor entities to summon."
|
||||||
"chatMessageTitle": "Test2",
|
|
||||||
"chatMessageHeaderTitle": "Summoning"
|
|
||||||
},
|
},
|
||||||
"transform": {
|
"transform": {
|
||||||
"name": "Transform",
|
"name": "Transform",
|
||||||
|
|
@ -87,9 +85,7 @@
|
||||||
},
|
},
|
||||||
"Config": {
|
"Config": {
|
||||||
"beastform": {
|
"beastform": {
|
||||||
"exact": "Beastform Max Tier",
|
"exact": { "label": "Beastform Max Tier", "hint": "The Character's Tier is used if empty" }
|
||||||
"exactHint": "The Character's Tier is used if empty",
|
|
||||||
"label": "Beastform"
|
|
||||||
},
|
},
|
||||||
"countdown": {
|
"countdown": {
|
||||||
"defaultOwnership": "Default Ownership",
|
"defaultOwnership": "Default Ownership",
|
||||||
|
|
@ -198,7 +194,10 @@
|
||||||
"type": { "label": "Type" }
|
"type": { "label": "Type" }
|
||||||
},
|
},
|
||||||
"hordeDamage": "Horde Damage",
|
"hordeDamage": "Horde Damage",
|
||||||
"horderHp": "Horde/HP"
|
"horderHp": "Horde/HP",
|
||||||
|
"adversaryReactionRoll": {
|
||||||
|
"headerTitle": "Adversary Reaction Roll"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"Character": {
|
"Character": {
|
||||||
"advantageSources": {
|
"advantageSources": {
|
||||||
|
|
@ -440,6 +439,10 @@
|
||||||
"defaultOwnershipTooltip": "The default player ownership of countdowns",
|
"defaultOwnershipTooltip": "The default player ownership of countdowns",
|
||||||
"hideNewCountdowns": "Hide New Countdowns"
|
"hideNewCountdowns": "Hide New Countdowns"
|
||||||
},
|
},
|
||||||
|
"CreateItemDialog": {
|
||||||
|
"createItem": "Create Item",
|
||||||
|
"browseCompendium": "Browse Compendium"
|
||||||
|
},
|
||||||
"DaggerheartMenu": {
|
"DaggerheartMenu": {
|
||||||
"title": "GM Tools",
|
"title": "GM Tools",
|
||||||
"refreshFeatures": "Refresh Features"
|
"refreshFeatures": "Refresh Features"
|
||||||
|
|
@ -653,6 +656,12 @@
|
||||||
"noPlayers": "No players to assign ownership to",
|
"noPlayers": "No players to assign ownership to",
|
||||||
"default": "Default Ownership"
|
"default": "Default Ownership"
|
||||||
},
|
},
|
||||||
|
"PendingReactionsDialog": {
|
||||||
|
"title": "Pending Reaction Rolls Found",
|
||||||
|
"unfinishedRolls": "Some Tokens still need to roll their Reaction Roll.",
|
||||||
|
"confirmation": "Are you sure you want to continue ?",
|
||||||
|
"warning": "Undone reaction rolls will be considered as failed"
|
||||||
|
},
|
||||||
"ReactionRoll": {
|
"ReactionRoll": {
|
||||||
"title": "Reaction Roll: {trait}"
|
"title": "Reaction Roll: {trait}"
|
||||||
},
|
},
|
||||||
|
|
@ -684,7 +693,13 @@
|
||||||
"damageNotRolled": "Damage not rolled in chat message yet",
|
"damageNotRolled": "Damage not rolled in chat message yet",
|
||||||
"insufficientHope": "The initiating character doesn't have enough hope",
|
"insufficientHope": "The initiating character doesn't have enough hope",
|
||||||
"createTagTeam": "Create TagTeam Roll",
|
"createTagTeam": "Create TagTeam Roll",
|
||||||
"chatMessageRollTitle": "Roll"
|
"chatMessageRollTitle": "Roll",
|
||||||
|
"cancelConfirmTitle": "Cancel Tag Team Roll",
|
||||||
|
"cancelConfirmText": "Are you sure you want to cancel the Tag Team Roll? This will close it for all other players too.",
|
||||||
|
"hints": {
|
||||||
|
"completeRolls": "Set up and complete the rolls for the characters",
|
||||||
|
"selectRoll": "Select which roll value to be used for the Tag Team"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"TokenConfig": {
|
"TokenConfig": {
|
||||||
"actorSizeUsed": "Actor size is set, determining the dimensions"
|
"actorSizeUsed": "Actor size is set, determining the dimensions"
|
||||||
|
|
@ -697,6 +712,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
|
"ActionAutomationChoices": {
|
||||||
|
"never": "Never",
|
||||||
|
"showDialog": "Show Dialog Only",
|
||||||
|
"always": "Always"
|
||||||
|
},
|
||||||
"AdversaryTrait": {
|
"AdversaryTrait": {
|
||||||
"relentless": {
|
"relentless": {
|
||||||
"name": "Relentless",
|
"name": "Relentless",
|
||||||
|
|
@ -1215,6 +1235,11 @@
|
||||||
"on": "On",
|
"on": "On",
|
||||||
"onWithToggle": "On With Toggle"
|
"onWithToggle": "On With Toggle"
|
||||||
},
|
},
|
||||||
|
"SceneRangeMeasurementTypes": {
|
||||||
|
"disable": "Disable Daggerheart Range Measurement",
|
||||||
|
"default": "Default",
|
||||||
|
"custom": "Custom"
|
||||||
|
},
|
||||||
"SelectAction": {
|
"SelectAction": {
|
||||||
"selectType": "Select Action Type",
|
"selectType": "Select Action Type",
|
||||||
"selectAction": "Action Selection"
|
"selectAction": "Action Selection"
|
||||||
|
|
@ -1894,6 +1919,10 @@
|
||||||
"hint": "Multiply any damage dealt to you by this number"
|
"hint": "Multiply any damage dealt to you by this number"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Battlepoints": {
|
||||||
|
"full": "Battlepoints",
|
||||||
|
"short": "BP"
|
||||||
|
},
|
||||||
"Bonuses": {
|
"Bonuses": {
|
||||||
"rest": {
|
"rest": {
|
||||||
"downtimeAction": "Downtime Action",
|
"downtimeAction": "Downtime Action",
|
||||||
|
|
@ -2305,8 +2334,10 @@
|
||||||
"multiclass": "Multiclass",
|
"multiclass": "Multiclass",
|
||||||
"newCategory": "New Category",
|
"newCategory": "New Category",
|
||||||
"newThing": "New {thing}",
|
"newThing": "New {thing}",
|
||||||
|
"next": "Next",
|
||||||
"none": "None",
|
"none": "None",
|
||||||
"noTarget": "No current target",
|
"noTarget": "No current target",
|
||||||
|
"optionalThing": "Optional {thing}",
|
||||||
"partner": "Partner",
|
"partner": "Partner",
|
||||||
"player": {
|
"player": {
|
||||||
"single": "Player",
|
"single": "Player",
|
||||||
|
|
@ -2329,9 +2360,11 @@
|
||||||
"rollDamage": "Roll Damage",
|
"rollDamage": "Roll Damage",
|
||||||
"rollWith": "{roll} Roll",
|
"rollWith": "{roll} Roll",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
|
"saveSettings": "Save Settings",
|
||||||
"scalable": "Scalable",
|
"scalable": "Scalable",
|
||||||
"scars": "Scars",
|
"scars": "Scars",
|
||||||
"situationalBonus": "Situational Bonus",
|
"situationalBonus": "Situational Bonus",
|
||||||
|
"searchPlaceholder": "Search...",
|
||||||
"spent": "Spent",
|
"spent": "Spent",
|
||||||
"step": "Step",
|
"step": "Step",
|
||||||
"stress": "Stress",
|
"stress": "Stress",
|
||||||
|
|
@ -2482,8 +2515,14 @@
|
||||||
},
|
},
|
||||||
"Weapon": {
|
"Weapon": {
|
||||||
"weaponType": "Weapon Type",
|
"weaponType": "Weapon Type",
|
||||||
"primaryWeapon": "Primary Weapon",
|
"primaryWeapon": {
|
||||||
"secondaryWeapon": "Secondary Weapon"
|
"full": "Primary Weapon",
|
||||||
|
"short": "Primary"
|
||||||
|
},
|
||||||
|
"secondaryWeapon": {
|
||||||
|
"full": "Secondary Weapon",
|
||||||
|
"short": "Secondary"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"MACROS": {
|
"MACROS": {
|
||||||
|
|
@ -2915,6 +2954,9 @@
|
||||||
"resourceRoll": {
|
"resourceRoll": {
|
||||||
"playerMessage": "{user} rerolled their {name}"
|
"playerMessage": "{user} rerolled their {name}"
|
||||||
},
|
},
|
||||||
|
"saveRoll": {
|
||||||
|
"reactionRollAllTargets": "Reaction Roll All Targets"
|
||||||
|
},
|
||||||
"tagTeam": {
|
"tagTeam": {
|
||||||
"title": "Tag Team",
|
"title": "Tag Team",
|
||||||
"membersTitle": "Members"
|
"membersTitle": "Members"
|
||||||
|
|
@ -2941,9 +2983,9 @@
|
||||||
},
|
},
|
||||||
"ItemBrowser": {
|
"ItemBrowser": {
|
||||||
"title": "Daggerheart Compendium Browser",
|
"title": "Daggerheart Compendium Browser",
|
||||||
|
"windowTitle": "Compendium Browser",
|
||||||
"hint": "Select a Folder in sidebar to start browsing through the compendium",
|
"hint": "Select a Folder in sidebar to start browsing through the compendium",
|
||||||
"browserSettings": "Browser Settings",
|
"browserSettings": "Browser Settings",
|
||||||
"searchPlaceholder": "Search...",
|
|
||||||
"columnName": "Name",
|
"columnName": "Name",
|
||||||
"tooltipFilters": "Filters",
|
"tooltipFilters": "Filters",
|
||||||
"tooltipErase": "Erase",
|
"tooltipErase": "Erase",
|
||||||
|
|
@ -2979,7 +3021,7 @@
|
||||||
"weapons": "Weapons",
|
"weapons": "Weapons",
|
||||||
"armors": "Armors",
|
"armors": "Armors",
|
||||||
"consumables": "Consumables",
|
"consumables": "Consumables",
|
||||||
"loots": "Loots"
|
"loots": "Loot"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Notifications": {
|
"Notifications": {
|
||||||
|
|
@ -3070,6 +3112,7 @@
|
||||||
"companion": "Level {level} - {partner}",
|
"companion": "Level {level} - {partner}",
|
||||||
"companionNoPartner": "No Partner",
|
"companionNoPartner": "No Partner",
|
||||||
"duplicateToNewTier": "Duplicate to New Tier",
|
"duplicateToNewTier": "Duplicate to New Tier",
|
||||||
|
"createAdversary": "Create Adversary",
|
||||||
"pickTierTitle": "Pick a new tier for this adversary"
|
"pickTierTitle": "Pick a new tier for this adversary"
|
||||||
},
|
},
|
||||||
"daggerheartMenu": {
|
"daggerheartMenu": {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,10 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
this.character = character;
|
this.character = character;
|
||||||
|
|
||||||
this.setup = {
|
this.setup = {
|
||||||
traits: this.character.system.traits,
|
traits: Object.keys(this.character.system.traits).reduce((acc, key) => {
|
||||||
|
acc[key] = { value: null };
|
||||||
|
return acc;
|
||||||
|
}, {}),
|
||||||
ancestryName: {
|
ancestryName: {
|
||||||
primary: '',
|
primary: '',
|
||||||
secondary: ''
|
secondary: ''
|
||||||
|
|
@ -377,8 +380,10 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
];
|
];
|
||||||
return Object.values(this.setup.traits).reduce((acc, x) => {
|
return Object.values(this.setup.traits).reduce((acc, x) => {
|
||||||
const index = traitCompareArray.indexOf(x.value);
|
const index = traitCompareArray.indexOf(x.value);
|
||||||
|
if (index === -1) return acc;
|
||||||
|
|
||||||
traitCompareArray.splice(index, 1);
|
traitCompareArray.splice(index, 1);
|
||||||
acc += index !== -1;
|
acc += 1;
|
||||||
return acc;
|
return acc;
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -259,8 +259,9 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
||||||
const resetValue = increasing
|
const resetValue = increasing
|
||||||
? 0
|
? 0
|
||||||
: feature.system.resource.max
|
: feature.system.resource.max
|
||||||
? Roll.replaceFormulaData(feature.system.resource.max, this.actor)
|
? new Roll(Roll.replaceFormulaData(feature.system.resource.max, this.actor.getRollData())).evaluateSync().total
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
await feature.update({ 'system.resource.value': resetValue });
|
await feature.update({ 'system.resource.value': resetValue });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,8 +118,13 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
|
||||||
break;
|
break;
|
||||||
case 'footer':
|
case 'footer':
|
||||||
partContext.buttons = [
|
partContext.buttons = [
|
||||||
{ type: 'button', action: 'reset', icon: 'fa-solid fa-arrow-rotate-left', label: 'Reset' },
|
{
|
||||||
{ type: 'submit', icon: 'fa-solid fa-floppy-disk', label: 'Save Changes' }
|
type: 'button',
|
||||||
|
action: 'reset',
|
||||||
|
icon: 'fa-solid fa-arrow-rotate-left',
|
||||||
|
label: game.i18n.localize('Reset')
|
||||||
|
},
|
||||||
|
{ type: 'submit', icon: 'fa-solid fa-floppy-disk', label: game.i18n.localize('EDITOR.Save') }
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,8 +188,9 @@ export default class SettingFeatureConfig extends HandlebarsApplicationMixin(App
|
||||||
if (type === 'effect') {
|
if (type === 'effect') {
|
||||||
const move = foundry.utils.getProperty(this.settings, this.movePath);
|
const move = foundry.utils.getProperty(this.settings, this.movePath);
|
||||||
for (const action of move.actions) {
|
for (const action of move.actions) {
|
||||||
const remainingEffects = action.effects.filter(x => x._id !== id);
|
const actionEffects = action.effects ?? [];
|
||||||
if (action.effects.length !== remainingEffects.length) {
|
const remainingEffects = actionEffects.filter(x => x._id !== id);
|
||||||
|
if (actionEffects.length !== remainingEffects.length) {
|
||||||
await action.update({
|
await action.update({
|
||||||
effects: remainingEffects.map(x => {
|
effects: remainingEffects.map(x => {
|
||||||
const { _id, ...rest } = x;
|
const { _id, ...rest } = x;
|
||||||
|
|
|
||||||
|
|
@ -217,8 +217,8 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
||||||
static #reactionRoll(event) {
|
static #reactionRoll(event) {
|
||||||
const config = {
|
const config = {
|
||||||
event,
|
event,
|
||||||
title: `Reaction Roll: ${this.actor.name}`,
|
title: game.i18n.localize('DAGGERHEART.GENERAL.reactionRoll'),
|
||||||
headerTitle: 'Adversary Reaction Roll',
|
headerTitle: game.i18n.localize('DAGGERHEART.ACTORS.Adversary.adversaryReactionRoll.headerTitle'),
|
||||||
roll: {
|
roll: {
|
||||||
type: 'trait'
|
type: 'trait'
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ export default class Party extends DHBaseActorSheet {
|
||||||
title: game.i18n.localize(`DAGGERHEART.APPLICATIONS.Downtime.${button.dataset.type}.title`),
|
title: game.i18n.localize(`DAGGERHEART.APPLICATIONS.Downtime.${button.dataset.type}.title`),
|
||||||
icon: button.dataset.type === 'shortRest' ? 'fa-solid fa-utensils' : 'fa-solid fa-bed'
|
icon: button.dataset.type === 'shortRest' ? 'fa-solid fa-utensils' : 'fa-solid fa-bed'
|
||||||
},
|
},
|
||||||
content: 'This will trigger a dialog to players make their downtime moves, are you sure?',
|
content: game.i18n.localize('DAGGERHEART.ACTORS.Party.triggerRestContent'),
|
||||||
classes: ['daggerheart', 'dialog', 'dh-style']
|
classes: ['daggerheart', 'dialog', 'dh-style']
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -652,12 +652,12 @@ export default function DHApplicationMixin(Base) {
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
action: 'create',
|
action: 'create',
|
||||||
label: 'Create Item',
|
label: game.i18n.localize('DAGGERHEART.APPLICATIONS.CreateItemDialog.createItem'),
|
||||||
icon: 'fa-solid fa-plus'
|
icon: 'fa-solid fa-plus'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
action: 'browse',
|
action: 'browse',
|
||||||
label: 'Browse Compendium',
|
label: game.i18n.localize('DAGGERHEART.APPLICATIONS.CreateItemDialog.browseCompendium'),
|
||||||
icon: 'fa-solid fa-book'
|
icon: 'fa-solid fa-book'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ export default class DhActorDirectory extends foundry.applications.sidebar.tabs.
|
||||||
window: { title: 'DAGGERHEART.UI.Sidebar.actorDirectory.pickTierTitle' },
|
window: { title: 'DAGGERHEART.UI.Sidebar.actorDirectory.pickTierTitle' },
|
||||||
content,
|
content,
|
||||||
ok: {
|
ok: {
|
||||||
label: 'Create Adversary',
|
label: 'DAGGERHEART.UI.Sidebar.actorDirectory.createAdversary',
|
||||||
callback: (event, button, dialog) => Number(button.form.elements.tier.value)
|
callback: (event, button, dialog) => Number(button.form.elements.tier.value)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
||||||
tag: 'div',
|
tag: 'div',
|
||||||
window: {
|
window: {
|
||||||
frame: true,
|
frame: true,
|
||||||
title: 'Fear',
|
title: 'DAGGERHEART.GENERAL.fear',
|
||||||
positioned: true,
|
positioned: true,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
minimizable: false
|
minimizable: false
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
tag: 'div',
|
tag: 'div',
|
||||||
window: {
|
window: {
|
||||||
frame: true,
|
frame: true,
|
||||||
title: 'Compendium Browser',
|
title: 'DAGGERHEART.UI.ItemBrowser.windowTitle',
|
||||||
icon: 'fa-solid fa-book-atlas',
|
icon: 'fa-solid fa-book-atlas',
|
||||||
positioned: true,
|
positioned: true,
|
||||||
resizable: true
|
resizable: true
|
||||||
|
|
@ -207,8 +207,23 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
label: game.i18n.localize(col.label)
|
label: game.i18n.localize(col.label)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const splitPath = folderId?.split('.') ?? [];
|
||||||
|
const { pathLabels } = splitPath.reduce(
|
||||||
|
(acc, curr) => {
|
||||||
|
acc.currentPath = !acc.currentPath ? curr : [acc.currentPath, curr].join('.');
|
||||||
|
if (curr === 'folder') return acc;
|
||||||
|
|
||||||
|
const label = foundry.utils.getProperty(this.config, acc.currentPath)?.label;
|
||||||
|
if (label) acc.pathLabels.push(game.i18n.localize(label));
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{ pathLabels: [], currentPath: '' }
|
||||||
|
);
|
||||||
|
|
||||||
this.selectedMenu = {
|
this.selectedMenu = {
|
||||||
path: folderId?.split('.') ?? [],
|
path: splitPath,
|
||||||
|
pathLabels: pathLabels,
|
||||||
data: {
|
data: {
|
||||||
...folderData,
|
...folderData,
|
||||||
columns: columns
|
columns: columns
|
||||||
|
|
@ -568,7 +583,9 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
const { itemUuid } = event.target.closest('[data-item-uuid]').dataset,
|
const { itemUuid } = event.target.closest('[data-item-uuid]').dataset,
|
||||||
item = await foundry.utils.fromUuid(itemUuid),
|
item = await foundry.utils.fromUuid(itemUuid),
|
||||||
dragData = item.toDragData();
|
dragData = item.toDragData();
|
||||||
|
|
||||||
event.dataTransfer.setData('text/plain', JSON.stringify(dragData));
|
event.dataTransfer.setData('text/plain', JSON.stringify(dragData));
|
||||||
|
event.dataTransfer.setDragImage(event.target.querySelector('img'), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
_canDragStart() {
|
_canDragStart() {
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,7 @@ export default class FilterMenu extends foundry.applications.ux.ContextMenu {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const damageTypeFilter = Object.values(CONFIG.DH.GENERAL.damageTypes).map(({ id, abbreviation }) => ({
|
const damageTypeFilter = Object.values(CONFIG.DH.GENERAL.damageTypes).map(({ id, abbreviation }) => ({
|
||||||
group: 'Damage Type', //TODO localize
|
group: game.i18n.localize('DAGGERHEART.GENERAL.damageType'),
|
||||||
name: game.i18n.localize(abbreviation),
|
name: game.i18n.localize(abbreviation),
|
||||||
filter: {
|
filter: {
|
||||||
field: 'system.damage.type',
|
field: 'system.damage.type',
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ export default class DhMeasuredTemplate extends foundry.canvas.placeables.Measur
|
||||||
|
|
||||||
static getRangeLabels(distanceValue, settings) {
|
static getRangeLabels(distanceValue, settings) {
|
||||||
let result = { distance: distanceValue, units: '' };
|
let result = { distance: distanceValue, units: '' };
|
||||||
if (!settings.enabled) return result;
|
if (!settings.enabled || !canvas.scene) return result;
|
||||||
|
|
||||||
const sceneRangeMeasurement = canvas.scene.flags.daggerheart?.rangeMeasurement;
|
const sceneRangeMeasurement = canvas.scene.flags.daggerheart?.rangeMeasurement;
|
||||||
const { disable, custom } = CONFIG.DH.GENERAL.sceneRangeMeasurementSetting;
|
const { disable, custom } = CONFIG.DH.GENERAL.sceneRangeMeasurementSetting;
|
||||||
|
|
|
||||||
|
|
@ -943,14 +943,14 @@ export const countdownAppMode = {
|
||||||
export const sceneRangeMeasurementSetting = {
|
export const sceneRangeMeasurementSetting = {
|
||||||
disable: {
|
disable: {
|
||||||
id: 'disable',
|
id: 'disable',
|
||||||
label: 'Disable Daggerheart Range Measurement'
|
label: 'DAGGERHEART.CONFIG.SceneRangeMeasurementTypes.disable'
|
||||||
},
|
},
|
||||||
default: {
|
default: {
|
||||||
id: 'default',
|
id: 'default',
|
||||||
label: 'Default'
|
label: 'DAGGERHEART.CONFIG.SceneRangeMeasurementTypes.default'
|
||||||
},
|
},
|
||||||
custom: {
|
custom: {
|
||||||
id: 'custom',
|
id: 'custom',
|
||||||
label: 'Custom'
|
label: 'DAGGERHEART.CONFIG.SceneRangeMeasurementTypes.custom'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,12 @@ export const typeConfig = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'system.type',
|
key: 'system.type',
|
||||||
label: 'DAGGERHEART.GENERAL.type'
|
label: 'DAGGERHEART.GENERAL.type',
|
||||||
|
format: type => {
|
||||||
|
if (!type) return '-';
|
||||||
|
|
||||||
|
return CONFIG.DH.ACTOR.allAdversaryTypes()[type].label;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
filters: [
|
filters: [
|
||||||
|
|
@ -69,12 +74,13 @@ export const typeConfig = {
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
key: 'type',
|
key: 'type',
|
||||||
label: 'DAGGERHEART.GENERAL.type'
|
label: 'DAGGERHEART.GENERAL.type',
|
||||||
|
format: type => type ? `TYPES.Item.${type}` : '-'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'system.secondary',
|
key: 'system.secondary',
|
||||||
label: 'DAGGERHEART.UI.ItemBrowser.subtype',
|
label: 'DAGGERHEART.UI.ItemBrowser.subtype',
|
||||||
format: isSecondary => (isSecondary ? 'secondary' : isSecondary === false ? 'primary' : '-')
|
format: isSecondary => (isSecondary ? 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.short' : isSecondary === false ? 'DAGGERHEART.ITEMS.Weapon.primaryWeapon.short' : '-')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'system.tier',
|
key: 'system.tier',
|
||||||
|
|
@ -94,8 +100,8 @@ export const typeConfig = {
|
||||||
key: 'system.secondary',
|
key: 'system.secondary',
|
||||||
label: 'DAGGERHEART.UI.ItemBrowser.subtype',
|
label: 'DAGGERHEART.UI.ItemBrowser.subtype',
|
||||||
choices: [
|
choices: [
|
||||||
{ value: false, label: 'DAGGERHEART.ITEMS.Weapon.primaryWeapon' },
|
{ value: false, label: 'DAGGERHEART.ITEMS.Weapon.primaryWeapon.full' },
|
||||||
{ value: true, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon' }
|
{ value: true, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.full' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -166,8 +172,8 @@ export const typeConfig = {
|
||||||
key: 'system.secondary',
|
key: 'system.secondary',
|
||||||
label: 'DAGGERHEART.UI.ItemBrowser.subtype',
|
label: 'DAGGERHEART.UI.ItemBrowser.subtype',
|
||||||
choices: [
|
choices: [
|
||||||
{ value: false, label: 'DAGGERHEART.ITEMS.Weapon.primaryWeapon' },
|
{ value: false, label: 'DAGGERHEART.ITEMS.Weapon.primaryWeapon.short' },
|
||||||
{ value: true, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon' }
|
{ value: true, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.short' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -253,11 +259,13 @@ export const typeConfig = {
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
key: 'system.type',
|
key: 'system.type',
|
||||||
label: 'DAGGERHEART.GENERAL.type'
|
label: 'DAGGERHEART.GENERAL.type',
|
||||||
|
format: type => type ? `DAGGERHEART.CONFIG.DomainCardTypes.${type}` : '-'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'system.domain',
|
key: 'system.domain',
|
||||||
label: 'DAGGERHEART.GENERAL.Domain.single'
|
label: 'DAGGERHEART.GENERAL.Domain.single',
|
||||||
|
format: domain => domain ? CONFIG.DH.DOMAIN.allDomains()[domain].label : '-'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'system.level',
|
key: 'system.level',
|
||||||
|
|
@ -318,7 +326,14 @@ export const typeConfig = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'system.domains',
|
key: 'system.domains',
|
||||||
label: 'DAGGERHEART.GENERAL.Domain.plural'
|
label: 'DAGGERHEART.GENERAL.Domain.plural',
|
||||||
|
format: domains => {
|
||||||
|
const config = CONFIG.DH.DOMAIN.allDomains();
|
||||||
|
return domains
|
||||||
|
.map(x => (x ? game.i18n.localize(config[x].label) : null))
|
||||||
|
.filter(x => x)
|
||||||
|
.join(', ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
filters: [
|
filters: [
|
||||||
|
|
@ -362,18 +377,19 @@ export const typeConfig = {
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
key: 'system.linkedClass',
|
key: 'system.linkedClass',
|
||||||
label: 'Class',
|
label: 'TYPES.Item.class',
|
||||||
format: linkedClass => linkedClass?.name ?? 'DAGGERHEART.UI.ItemBrowser.missing'
|
format: linkedClass => linkedClass?.name ?? 'DAGGERHEART.UI.ItemBrowser.missing'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'system.spellcastingTrait',
|
key: 'system.spellcastingTrait',
|
||||||
label: 'DAGGERHEART.ITEMS.Subclass.spellcastingTrait'
|
label: 'DAGGERHEART.ITEMS.Subclass.spellcastingTrait',
|
||||||
|
format: trait => (trait ? `DAGGERHEART.CONFIG.Traits.${trait}.name` : '-')
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
key: 'system.linkedClass.uuid',
|
key: 'system.linkedClass.uuid',
|
||||||
label: 'Class',
|
label: 'TYPES.Item.class',
|
||||||
choices: items => {
|
choices: items => {
|
||||||
const list = items
|
const list = items
|
||||||
.filter(item => item.system.linkedClass)
|
.filter(item => item.system.linkedClass)
|
||||||
|
|
@ -397,7 +413,8 @@ export const typeConfig = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'system.mainTrait',
|
key: 'system.mainTrait',
|
||||||
label: 'DAGGERHEART.GENERAL.Trait.single'
|
label: 'DAGGERHEART.GENERAL.Trait.single',
|
||||||
|
format: trait => (trait ? `DAGGERHEART.CONFIG.Traits.${trait}.name` : '-')
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
filters: [
|
filters: [
|
||||||
|
|
|
||||||
|
|
@ -453,7 +453,7 @@ export const allArmorFeatures = () => {
|
||||||
const feature = homebrewFeatures[key];
|
const feature = homebrewFeatures[key];
|
||||||
const actions = feature.actions.map(action => ({
|
const actions = feature.actions.map(action => ({
|
||||||
...action,
|
...action,
|
||||||
effects: action.effects.map(effect => feature.effects.find(x => x.id === effect._id)),
|
effects: action.effects?.map(effect => feature.effects.find(x => x.id === effect._id))??[],
|
||||||
type: action.type
|
type: action.type
|
||||||
}));
|
}));
|
||||||
const actionEffects = actions.flatMap(a => a.effects);
|
const actionEffects = actions.flatMap(a => a.effects);
|
||||||
|
|
@ -1389,7 +1389,7 @@ export const allWeaponFeatures = () => {
|
||||||
|
|
||||||
const actions = feature.actions.map(action => ({
|
const actions = feature.actions.map(action => ({
|
||||||
...action,
|
...action,
|
||||||
effects: action.effects.map(effect => feature.effects.find(x => x.id === effect._id)),
|
effects: action.effects?.map(effect => feature.effects.find(x => x.id === effect._id))??[],
|
||||||
type: action.type
|
type: action.type
|
||||||
}));
|
}));
|
||||||
const actionEffects = actions.flatMap(a => a.effects);
|
const actionEffects = actions.flatMap(a => a.effects);
|
||||||
|
|
|
||||||
|
|
@ -57,16 +57,10 @@ const companionBaseResources = Object.freeze({
|
||||||
stress: {
|
stress: {
|
||||||
id: 'stress',
|
id: 'stress',
|
||||||
initial: 0,
|
initial: 0,
|
||||||
max: 0,
|
max: 3,
|
||||||
reverse: true,
|
reverse: true,
|
||||||
label: 'DAGGERHEART.GENERAL.stress'
|
label: 'DAGGERHEART.GENERAL.stress'
|
||||||
},
|
},
|
||||||
hope: {
|
|
||||||
id: 'hope',
|
|
||||||
initial: 0,
|
|
||||||
reverse: false,
|
|
||||||
label: 'DAGGERHEART.GENERAL.hope'
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const character = {
|
export const character = {
|
||||||
|
|
|
||||||
|
|
@ -46,18 +46,14 @@ export const gameSettings = {
|
||||||
export const actionAutomationChoices = {
|
export const actionAutomationChoices = {
|
||||||
never: {
|
never: {
|
||||||
id: 'never',
|
id: 'never',
|
||||||
label: 'Never'
|
label: 'DAGGERHEART.CONFIG.ActionAutomationChoices.never'
|
||||||
},
|
},
|
||||||
showDialog: {
|
showDialog: {
|
||||||
id: 'showDialog',
|
id: 'showDialog',
|
||||||
label: 'Show Dialog only'
|
label: 'DAGGERHEART.CONFIG.ActionAutomationChoices.showDialog'
|
||||||
},
|
},
|
||||||
// npcOnly: {
|
|
||||||
// id: "npcOnly",
|
|
||||||
// label: "Always for non-characters"
|
|
||||||
// },
|
|
||||||
always: {
|
always: {
|
||||||
id: 'always',
|
id: 'always',
|
||||||
label: 'Always'
|
label: 'DAGGERHEART.CONFIG.ActionAutomationChoices.always'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,9 @@ export default class DhpAdversary extends DhCreature {
|
||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
super.prepareDerivedData();
|
super.prepareDerivedData();
|
||||||
this.attack.roll.isStandardAttack = true;
|
this.attack.roll.isStandardAttack = true;
|
||||||
|
|
||||||
|
// Clamp resources (must be done last to ensure all updates occur)
|
||||||
|
this.resources.clamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
_getTags() {
|
_getTags() {
|
||||||
|
|
|
||||||
|
|
@ -660,6 +660,8 @@ export default class DhCharacter extends DhCreature {
|
||||||
|
|
||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
super.prepareDerivedData();
|
super.prepareDerivedData();
|
||||||
|
|
||||||
|
this.resources.hope.max -= this.scars;
|
||||||
if (this.companion) {
|
if (this.companion) {
|
||||||
for (let levelKey in this.companion.system.levelData.levelups) {
|
for (let levelKey in this.companion.system.levelData.levelups) {
|
||||||
const level = this.companion.system.levelData.levelups[levelKey];
|
const level = this.companion.system.levelData.levelups[levelKey];
|
||||||
|
|
@ -673,7 +675,6 @@ export default class DhCharacter extends DhCreature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resources.hope.max -= this.scars;
|
|
||||||
this.attack.roll.trait = this.rules.attack.roll.trait ?? this.attack.roll.trait;
|
this.attack.roll.trait = this.rules.attack.roll.trait ?? this.attack.roll.trait;
|
||||||
|
|
||||||
this.resources.armor = {
|
this.resources.armor = {
|
||||||
|
|
@ -684,6 +685,9 @@ export default class DhCharacter extends DhCreature {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.attack.damage.parts[0].value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`;
|
this.attack.damage.parts[0].value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`;
|
||||||
|
|
||||||
|
// Clamp resources (must be done last to ensure all updates occur)
|
||||||
|
this.resources.clamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
getRollData() {
|
getRollData() {
|
||||||
|
|
|
||||||
|
|
@ -130,9 +130,6 @@ export default class DhCompanion extends DhCreature {
|
||||||
const level = this.levelData.levelups[levelKey];
|
const level = this.levelData.levelups[levelKey];
|
||||||
for (let selection of level.selections) {
|
for (let selection of level.selections) {
|
||||||
switch (selection.type) {
|
switch (selection.type) {
|
||||||
case 'hope':
|
|
||||||
this.resources.hope += selection.value;
|
|
||||||
break;
|
|
||||||
case 'vicious':
|
case 'vicious':
|
||||||
if (selection.data[0] === 'damage') {
|
if (selection.data[0] === 'damage') {
|
||||||
this.attack.damage.parts[0].value.dice = adjustDice(this.attack.damage.parts[0].value.dice);
|
this.attack.damage.parts[0].value.dice = adjustDice(this.attack.damage.parts[0].value.dice);
|
||||||
|
|
@ -167,6 +164,9 @@ export default class DhCompanion extends DhCreature {
|
||||||
return acc;
|
return acc;
|
||||||
}, this.partner.system.companionData.levelupChoices);
|
}, this.partner.system.companionData.levelupChoices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clamp resources (must be done last to ensure all updates occur)
|
||||||
|
this.resources.clamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
async _preUpdate(changes, options, userId) {
|
async _preUpdate(changes, options, userId) {
|
||||||
|
|
|
||||||
|
|
@ -60,14 +60,4 @@ export default class DhCreature extends BaseDataActor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareDerivedData() {
|
|
||||||
const minLimitResource = resource => {
|
|
||||||
if (resource) resource.value = Math.min(resource.value, resource.max);
|
|
||||||
};
|
|
||||||
|
|
||||||
minLimitResource(this.resources.stress);
|
|
||||||
minLimitResource(this.resources.hitPoints);
|
|
||||||
minLimitResource(this.resources.hope);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,8 @@ export default class BeastformField extends fields.SchemaField {
|
||||||
{ 1: game.i18n.localize('DAGGERHEART.GENERAL.Tiers.1') }
|
{ 1: game.i18n.localize('DAGGERHEART.GENERAL.Tiers.1') }
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
hint: 'DAGGERHEART.ACTIONS.Config.beastform.exactHint'
|
label: 'DAGGERHEART.ACTIONS.Config.beastform.exact.label',
|
||||||
|
hint: 'DAGGERHEART.ACTIONS.Config.beastform.exact.hint'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -295,7 +295,7 @@ export class DHDamageData extends DHResourceData {
|
||||||
required: true
|
required: true
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
label: 'Type'
|
label: game.i18n.localize('DAGGERHEART.GENERAL.type')
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,18 @@ class ResourcesField extends fields.TypedObjectField {
|
||||||
value.isReversed = resources[key].reverse;
|
value.isReversed = resources[key].reverse;
|
||||||
value.max = typeof resource.max === 'number' ? (value.max ?? resource.max) : null;
|
value.max = typeof resource.max === 'number' ? (value.max ?? resource.max) : null;
|
||||||
}
|
}
|
||||||
|
Object.defineProperty(data, 'clamp', {
|
||||||
|
value: function () {
|
||||||
|
for (const key of Object.keys(this)) {
|
||||||
|
const resource = this[key];
|
||||||
|
if (typeof resource?.max === 'number') {
|
||||||
|
resource.value = Math.clamp(resource.value, 0, resource.max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enumerable: false
|
||||||
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ export default class DHWeapon extends AttachableItem {
|
||||||
equipped: new fields.BooleanField({ initial: false }),
|
equipped: new fields.BooleanField({ initial: false }),
|
||||||
|
|
||||||
//SETTINGS
|
//SETTINGS
|
||||||
secondary: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon' }),
|
secondary: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.full' }),
|
||||||
burden: new fields.StringField({
|
burden: new fields.StringField({
|
||||||
required: true,
|
required: true,
|
||||||
choices: CONFIG.DH.GENERAL.burden,
|
choices: CONFIG.DH.GENERAL.burden,
|
||||||
|
|
|
||||||
|
|
@ -197,8 +197,8 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
||||||
const pendingingSaves = targets.filter(t => t.saved.success === null);
|
const pendingingSaves = targets.filter(t => t.saved.success === null);
|
||||||
if (pendingingSaves.length) {
|
if (pendingingSaves.length) {
|
||||||
const confirm = await foundry.applications.api.DialogV2.confirm({
|
const confirm = await foundry.applications.api.DialogV2.confirm({
|
||||||
window: { title: 'Pending Reaction Rolls found' },
|
window: { title: game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.title') },
|
||||||
content: `<p>Some Tokens still need to roll their Reaction Roll.</p><p>Are you sure you want to continue ?</p><p><i>Undone reaction rolls will be considered as failed</i></p>`
|
content: `<p>${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.unfinishedRolls')}</p><p>${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.confirmation')}</p><p><i>${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.warning')}</i></p>`
|
||||||
});
|
});
|
||||||
if (!confirm) return;
|
if (!confirm) return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ export default class DhTokenManager {
|
||||||
: this.#actor;
|
: this.#actor;
|
||||||
const tokenData = await actor.getTokenDocument();
|
const tokenData = await actor.getTokenDocument();
|
||||||
const result = await canvas.scene.createEmbeddedDocuments('Token', [
|
const result = await canvas.scene.createEmbeddedDocuments('Token', [
|
||||||
{ ...tokenData, x: this.#activePreview.document.x, y: this.#activePreview.document.y }
|
{ ...tokenData.toObject(), x: this.#activePreview.document.x, y: this.#activePreview.document.y }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this.#activePreview = undefined;
|
this.#activePreview = undefined;
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,7 @@ export const renderMeasuredTemplate = async event => {
|
||||||
? '180'
|
? '180'
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
let baseDistance = range;
|
const distance = getTemplateDistance(range, type);
|
||||||
if (Number.isNaN(Number(range))) {
|
|
||||||
baseDistance = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.variantRules).rangeMeasurement[
|
|
||||||
range
|
|
||||||
];
|
|
||||||
}
|
|
||||||
const distance = type === CONFIG.DH.GENERAL.templateTypes.EMANATION ? baseDistance + 2.5 : baseDistance;
|
|
||||||
|
|
||||||
const { width, height } = game.canvas.scene.dimensions;
|
const { width, height } = game.canvas.scene.dimensions;
|
||||||
const data = {
|
const data = {
|
||||||
|
|
@ -86,3 +80,23 @@ export const renderMeasuredTemplate = async event => {
|
||||||
|
|
||||||
CONFIG.ux.TemplateManager.createPreview(data);
|
CONFIG.ux.TemplateManager.createPreview(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getTemplateDistance = (range, type) => {
|
||||||
|
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;
|
||||||
|
const baseDistance = settings[range];
|
||||||
|
|
||||||
|
if (type !== CONFIG.DH.GENERAL.templateTypes.EMANATION) return baseDistance;
|
||||||
|
|
||||||
|
const emanationAddDistance = settings.melee / 2;
|
||||||
|
return baseDistance + emanationAddDistance;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,8 @@
|
||||||
"experiences": {
|
"experiences": {
|
||||||
"ti3Z1mq2M92KK4GJ": {
|
"ti3Z1mq2M92KK4GJ": {
|
||||||
"name": "Bloodthirsty",
|
"name": "Bloodthirsty",
|
||||||
"description": ""
|
"description": "",
|
||||||
|
"value": 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bonuses": {
|
"bonuses": {
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@
|
||||||
"name": "Crushing Blows",
|
"name": "Crushing Blows",
|
||||||
"type": "feature",
|
"type": "feature",
|
||||||
"system": {
|
"system": {
|
||||||
"description": "<p>When the @Lookup[@name] makes a successful attack, the target must mark an Armor Slot without receiving its benefi ts (they can still use armor to reduce the damage). If they can’t mark an Armor Slot, they must mark an additional HP.</p>",
|
"description": "<p>When the @Lookup[@name] makes a successful attack, the target must mark an Armor Slot without receiving its benefits (they can still use armor to reduce the damage). If they can’t mark an Armor Slot, they must mark an additional HP.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"0sXciTiPc30v8czv": {
|
"0sXciTiPc30v8czv": {
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,7 @@
|
||||||
"name": "Acidic Form",
|
"name": "Acidic Form",
|
||||||
"type": "feature",
|
"type": "feature",
|
||||||
"system": {
|
"system": {
|
||||||
"description": "<p>When the @Lookup[@name] makes a successful attack, the target must mark an Armor Slot without receiving its benefi ts (they can still use armor to reduce the damage). If they can’t mark an Armor Slot, they must mark an additional HP.</p>",
|
"description": "<p>When the @Lookup[@name] makes a successful attack, the target must mark an Armor Slot without receiving its benefits (they can still use armor to reduce the damage). If they can’t mark an Armor Slot, they must mark an additional HP.</p>",
|
||||||
"resource": null,
|
"resource": null,
|
||||||
"actions": {
|
"actions": {
|
||||||
"gtT2oHSyZg9OHHJD": {
|
"gtT2oHSyZg9OHHJD": {
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@
|
||||||
{
|
{
|
||||||
"key": "system.disadvantageSources",
|
"key": "system.disadvantageSources",
|
||||||
"mode": 2,
|
"mode": 2,
|
||||||
"value": "Retract",
|
"value": "Action Rolls",
|
||||||
"priority": null
|
"priority": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -35,19 +35,7 @@
|
||||||
{
|
{
|
||||||
"key": "system.advantageSources",
|
"key": "system.advantageSources",
|
||||||
"mode": 2,
|
"mode": 2,
|
||||||
"value": "In an area with low light or heavy shadow: hide, investigate, or perceive",
|
"value": "Rolls to hide, investigate, or perceive details in low light",
|
||||||
"priority": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "system.advantageSources",
|
|
||||||
"mode": 2,
|
|
||||||
"value": "",
|
|
||||||
"priority": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "",
|
|
||||||
"mode": 2,
|
|
||||||
"value": "",
|
|
||||||
"priority": null
|
"priority": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -61,7 +49,7 @@
|
||||||
"startRound": null,
|
"startRound": null,
|
||||||
"startTurn": null
|
"startTurn": null
|
||||||
},
|
},
|
||||||
"description": "",
|
"description": "<p>When you’re in an area with low light or heavy shadow, you have advantage on rolls to hide, investigate, or perceive details within that area.</p>",
|
||||||
"origin": null,
|
"origin": null,
|
||||||
"tint": "#ffffff",
|
"tint": "#ffffff",
|
||||||
"transfer": true,
|
"transfer": true,
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@
|
||||||
{
|
{
|
||||||
"key": "system.advantageSources",
|
"key": "system.advantageSources",
|
||||||
"mode": 2,
|
"mode": 2,
|
||||||
"value": "1",
|
"value": "Attack Rolls",
|
||||||
"priority": null
|
"priority": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -152,7 +152,7 @@
|
||||||
"startRound": null,
|
"startRound": null,
|
||||||
"startTurn": null
|
"startTurn": null
|
||||||
},
|
},
|
||||||
"description": "",
|
"description": "<p>You gain advantage on attack rolls until you or an ally rolls a failure with Fear.</p>",
|
||||||
"tint": "#ffffff",
|
"tint": "#ffffff",
|
||||||
"statuses": [],
|
"statuses": [],
|
||||||
"sort": 0,
|
"sort": 0,
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@
|
||||||
"resultBased": false,
|
"resultBased": false,
|
||||||
"value": {
|
"value": {
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false,
|
||||||
|
"formula": ""
|
||||||
},
|
},
|
||||||
"multiplier": "prof",
|
"multiplier": "prof",
|
||||||
"dice": "d8",
|
"dice": "d8",
|
||||||
|
|
@ -44,7 +45,9 @@
|
||||||
"flatMultiplier": 1
|
"flatMultiplier": 1
|
||||||
},
|
},
|
||||||
"applyTo": "hitPoints",
|
"applyTo": "hitPoints",
|
||||||
"type": [],
|
"type": [
|
||||||
|
"magical"
|
||||||
|
],
|
||||||
"base": false,
|
"base": false,
|
||||||
"valueAlt": {
|
"valueAlt": {
|
||||||
"multiplier": "prof",
|
"multiplier": "prof",
|
||||||
|
|
@ -52,7 +55,8 @@
|
||||||
"dice": "d6",
|
"dice": "d6",
|
||||||
"bonus": null,
|
"bonus": null,
|
||||||
"custom": {
|
"custom": {
|
||||||
"enabled": false
|
"enabled": false,
|
||||||
|
"formula": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -87,57 +91,6 @@
|
||||||
"name": "Cast",
|
"name": "Cast",
|
||||||
"img": "icons/skills/melee/spear-tips-three-green.webp",
|
"img": "icons/skills/melee/spear-tips-three-green.webp",
|
||||||
"range": "veryClose"
|
"range": "veryClose"
|
||||||
},
|
|
||||||
"CUKoYyDxQhNc0pLs": {
|
|
||||||
"type": "damage",
|
|
||||||
"_id": "CUKoYyDxQhNc0pLs",
|
|
||||||
"systemPath": "actions",
|
|
||||||
"description": "<p>If a target you hit is <em>Vulnerable</em>, they take an extra <strong>1d8</strong> damage.</p>",
|
|
||||||
"chatDisplay": true,
|
|
||||||
"actionType": "action",
|
|
||||||
"cost": [],
|
|
||||||
"uses": {
|
|
||||||
"value": null,
|
|
||||||
"max": "",
|
|
||||||
"recovery": null
|
|
||||||
},
|
|
||||||
"damage": {
|
|
||||||
"parts": [
|
|
||||||
{
|
|
||||||
"value": {
|
|
||||||
"custom": {
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
"multiplier": "flat",
|
|
||||||
"flatMultiplier": 1,
|
|
||||||
"dice": "d8",
|
|
||||||
"bonus": null
|
|
||||||
},
|
|
||||||
"applyTo": "hitPoints",
|
|
||||||
"type": [],
|
|
||||||
"base": false,
|
|
||||||
"resultBased": false,
|
|
||||||
"valueAlt": {
|
|
||||||
"multiplier": "prof",
|
|
||||||
"flatMultiplier": 1,
|
|
||||||
"dice": "d6",
|
|
||||||
"bonus": null,
|
|
||||||
"custom": {
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"includeBase": false
|
|
||||||
},
|
|
||||||
"target": {
|
|
||||||
"type": "any",
|
|
||||||
"amount": null
|
|
||||||
},
|
|
||||||
"effects": [],
|
|
||||||
"name": "Damage Against Vulnerable",
|
|
||||||
"img": "icons/skills/melee/spear-tips-three-purple.webp",
|
|
||||||
"range": ""
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"attribution": {
|
"attribution": {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
{
|
{
|
||||||
"value": {
|
"value": {
|
||||||
"dice": "d10",
|
"dice": "d10",
|
||||||
"bonus": 1,
|
"bonus": 2,
|
||||||
"multiplier": "prof",
|
"multiplier": "prof",
|
||||||
"flatMultiplier": 1,
|
"flatMultiplier": 1,
|
||||||
"custom": {
|
"custom": {
|
||||||
|
|
|
||||||
|
|
@ -5,22 +5,14 @@
|
||||||
"_id": "ijWppQzSOqVCb3rE",
|
"_id": "ijWppQzSOqVCb3rE",
|
||||||
"img": "icons/weapons/axes/axe-battle-jagged.webp",
|
"img": "icons/weapons/axes/axe-battle-jagged.webp",
|
||||||
"system": {
|
"system": {
|
||||||
"description": "",
|
"description": "<strong>Protective</strong>: +1 to Armor Score",
|
||||||
"actions": {},
|
"actions": {},
|
||||||
"attached": [],
|
"attached": [],
|
||||||
"tier": 3,
|
"tier": 3,
|
||||||
"equipped": false,
|
"equipped": false,
|
||||||
"secondary": false,
|
"secondary": false,
|
||||||
"burden": "twoHanded",
|
"burden": "twoHanded",
|
||||||
"weaponFeatures": [
|
"weaponFeatures": [],
|
||||||
{
|
|
||||||
"value": "protective",
|
|
||||||
"effectIds": [
|
|
||||||
"qTxADRsQnKiYfOiQ"
|
|
||||||
],
|
|
||||||
"actionIds": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"attack": {
|
"attack": {
|
||||||
"name": "Attack",
|
"name": "Attack",
|
||||||
"img": "icons/skills/melee/blood-slash-foam-red.webp",
|
"img": "icons/skills/melee/blood-slash-foam-red.webp",
|
||||||
|
|
@ -111,13 +103,13 @@
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"name": "Protective",
|
"name": "Protective",
|
||||||
"description": "Add your character's Tier to your Armor Score",
|
"description": "+1 to Armor Score",
|
||||||
"img": "icons/skills/melee/shield-block-gray-orange.webp",
|
"img": "icons/magic/defensive/shield-barrier-deflect-teal.webp",
|
||||||
"changes": [
|
"changes": [
|
||||||
{
|
{
|
||||||
"key": "system.armorScore",
|
"key": "system.armorScore",
|
||||||
"mode": 2,
|
"mode": 2,
|
||||||
"value": "ITEM.@system.tier"
|
"value": "1"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_id": "qTxADRsQnKiYfOiQ",
|
"_id": "qTxADRsQnKiYfOiQ",
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,11 @@
|
||||||
opacity: 0.2;
|
opacity: 0.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.no-horizontal-padding {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
legend {
|
legend {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
|
@ -274,6 +279,15 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
|
|
||||||
|
&.separated {
|
||||||
|
border-bottom: 2px solid;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
padding: 0 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.experience-inner-container {
|
.experience-inner-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
}
|
}
|
||||||
h4 {
|
h4 {
|
||||||
font-size: var(--font-size-16);
|
font-size: var(--font-size-16);
|
||||||
color: @beige;
|
color: light-dark(@dark, @beige);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
.encounter-battlepoints {
|
.encounter-battlepoints {
|
||||||
display: flex;
|
display: flex;
|
||||||
cursor: help;
|
cursor: help;
|
||||||
|
color: light-dark(@dark, @beige);
|
||||||
}
|
}
|
||||||
|
|
||||||
.inner-controls {
|
.inner-controls {
|
||||||
|
|
|
||||||
10
system.json
10
system.json
|
|
@ -2,12 +2,15 @@
|
||||||
"id": "daggerheart",
|
"id": "daggerheart",
|
||||||
"title": "Daggerheart",
|
"title": "Daggerheart",
|
||||||
"description": "An unofficial implementation of the Daggerheart system",
|
"description": "An unofficial implementation of the Daggerheart system",
|
||||||
"version": "1.9.6",
|
"version": "1.9.13",
|
||||||
"compatibility": {
|
"compatibility": {
|
||||||
"minimum": "13.346",
|
"minimum": "13.346",
|
||||||
"verified": "13.351",
|
"verified": "13.351",
|
||||||
"maximum": "13"
|
"maximum": "13"
|
||||||
},
|
},
|
||||||
|
"url": "https://github.com/Foundryborne/daggerheart",
|
||||||
|
"manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/V13/system.json",
|
||||||
|
"download": "https://github.com/Foundryborne/daggerheart/releases/download/1.9.13/system.zip",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "WBHarry"
|
"name": "WBHarry"
|
||||||
|
|
@ -296,8 +299,5 @@
|
||||||
},
|
},
|
||||||
"background": "systems/daggerheart/assets/logos/FoundrybornBackgroundLogo.png",
|
"background": "systems/daggerheart/assets/logos/FoundrybornBackgroundLogo.png",
|
||||||
"primaryTokenAttribute": "resources.hitPoints",
|
"primaryTokenAttribute": "resources.hitPoints",
|
||||||
"secondaryTokenAttribute": "resources.stress",
|
"secondaryTokenAttribute": "resources.stress"
|
||||||
"url": "https://your/hosted/system/repo/",
|
|
||||||
"manifest": "https://your/hosted/system/repo/system.json",
|
|
||||||
"download": "https://your/packaged/download/archive.zip"
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{{localize "DAGGERHEART.ACTIONS.Config.beastform.label"}}</legend>
|
<legend>{{localize "DAGGERHEART.ACTIONS.TYPES.beastform.name"}}</legend>
|
||||||
{{formGroup fields.tierAccess.fields.exact value=source.tierAccess.exact name="beastform.tierAccess.exact" labelAttr="label" valueAttr="key" localize=true blank=""}}
|
{{formGroup fields.tierAccess.fields.exact value=source.tierAccess.exact name="beastform.tierAccess.exact" labelAttr="label" valueAttr="key" localize=true blank=""}}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
@ -3,6 +3,6 @@
|
||||||
{{#if isLastTab}}
|
{{#if isLastTab}}
|
||||||
<button data-action="finish">{{localize "DAGGERHEART.APPLICATIONS.CharacterCreation.finishCreation"}}</button>
|
<button data-action="finish">{{localize "DAGGERHEART.APPLICATIONS.CharacterCreation.finishCreation"}}</button>
|
||||||
{{else}}
|
{{else}}
|
||||||
<button data-action="setupGoNext" {{disabled nextDisabled}}>{{localize "Next"}}</button>
|
<button data-action="setupGoNext" {{disabled nextDisabled}}>{{localize "DAGGERHEART.GENERAL.next"}}</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -4,18 +4,26 @@
|
||||||
data-group='{{tabs.experience.group}}'
|
data-group='{{tabs.experience.group}}'
|
||||||
>
|
>
|
||||||
<div class="main-selections-container">
|
<div class="main-selections-container">
|
||||||
<fieldset class="section-container">
|
<fieldset class="section-container no-horizontal-padding">
|
||||||
<legend>{{localize "DAGGERHEART.APPLICATIONS.CharacterCreation.initialExperiences"}} {{experience.nrSelected}}/{{experience.nrTotal}}</legend>
|
<legend>{{localize "DAGGERHEART.APPLICATIONS.CharacterCreation.initialExperiences"}} {{experience.nrSelected}}/{{experience.nrTotal}}</legend>
|
||||||
<div class="experiences-inner-container">
|
<div class="experiences-inner-container">
|
||||||
{{#each experience.values as |experience id|}}
|
{{#each experience.values as |experience id|}}
|
||||||
<div class="experience-container">
|
<div class="experience-container {{#unless @last}}separated{{/unless}}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{localize "DAGGERHEART.GENERAL.label"}}</label>
|
||||||
<div class="experience-inner-container">
|
<div class="experience-inner-container">
|
||||||
<input class="experience-description" type="text" name="{{concat "experiences." id ".name" }}" value="{{experience.name}}" placeholder="{{localize "DAGGERHEART.APPLICATIONS.CharacterCreation.newExperience"}}" />
|
<input class="experience-description" type="text" name="{{concat "experiences." id ".name" }}" value="{{experience.name}}" placeholder="{{localize "DAGGERHEART.APPLICATIONS.CharacterCreation.newExperience"}}" />
|
||||||
<span class="experience-value">{{numberFormat this.value sign=true}}</span>
|
<span class="experience-value">{{numberFormat this.value sign=true}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{localize "DAGGERHEART.GENERAL.optionalThing" thing=(localize "DAGGERHEART.GENERAL.description")}}</label>
|
||||||
|
<div class="form-fields">
|
||||||
<textarea name="{{concat "experiences." id ".description"}}">{{experience.description}}</textarea>
|
<textarea name="{{concat "experiences." id ".description"}}">{{experience.description}}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
<footer>
|
<footer>
|
||||||
<button data-action="finish">{{localize "Save Settings"}}</button>
|
<button data-action="finish">{{localize "DAGGERHEART.GENERAL.saveSettings"}}</button>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" value="{{extraFormula}}" name="roll.{{ @index }}.extraFormula" placeholder="Situational Bonus">
|
<input type="text" value="{{extraFormula}}" name="roll.{{ @index }}.extraFormula" placeholder="{{localize "DAGGERHEART.GENERAL.situationalBonus"}}">
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{#unless (empty @root.modifiers)}}
|
{{#unless (empty @root.modifiers)}}
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@
|
||||||
</select>
|
</select>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq @root.rollType 'DualityRoll')}}<span class="formula-label">{{localize "DAGGERHEART.GENERAL.situationalBonus"}}</span>{{/if}}
|
{{#if (eq @root.rollType 'DualityRoll')}}<span class="formula-label">{{localize "DAGGERHEART.GENERAL.situationalBonus"}}</span>{{/if}}
|
||||||
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="{{#if (eq @root.rollType 'DualityRoll')}}Ex: 1d6 + 5{{else}}Situational Bonus{{/if}}">
|
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="{{#if (eq @root.rollType 'DualityRoll')}}Ex: 1d6 + 5{{else}}{{localize "DAGGERHEART.GENERAL.situationalBonus"}}{{/if}}">
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,6 @@
|
||||||
</button>
|
</button>
|
||||||
<button data-action="save" >
|
<button data-action="save" >
|
||||||
<i class="fa-solid fa-floppy-disk"></i>
|
<i class="fa-solid fa-floppy-disk"></i>
|
||||||
<span>{{localize "Save Changes"}}</span>
|
<span>{{localize "EDITOR.Save"}}</span>
|
||||||
</button>
|
</button>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
@ -5,6 +5,6 @@
|
||||||
</button>
|
</button>
|
||||||
<button type="button" data-action="save" >
|
<button type="button" data-action="save" >
|
||||||
<i class="fa-solid fa-floppy-disk"></i>
|
<i class="fa-solid fa-floppy-disk"></i>
|
||||||
<span>{{localize "Save Changes"}}</span>
|
<span>{{localize "EDITOR.Save"}}</span>
|
||||||
</button>
|
</button>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
@ -5,6 +5,6 @@
|
||||||
</button>
|
</button>
|
||||||
<button data-action="save" >
|
<button data-action="save" >
|
||||||
<i class="fa-solid fa-floppy-disk"></i>
|
<i class="fa-solid fa-floppy-disk"></i>
|
||||||
<span>{{localize "Save Changes"}}</span>
|
<span>{{localize "EDITOR.Save"}}</span>
|
||||||
</button>
|
</button>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
</button>
|
</button>
|
||||||
<button data-action="save" >
|
<button data-action="save" >
|
||||||
<i class="fa-solid fa-floppy-disk"></i>
|
<i class="fa-solid fa-floppy-disk"></i>
|
||||||
<span>{{localize "Save Changes"}}</span>
|
<span>{{localize "EDITOR.Save"}}</span>
|
||||||
</button>
|
</button>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<i class="fa-solid fa-magnifying-glass"></i>
|
<i class="fa-solid fa-magnifying-glass"></i>
|
||||||
</div>
|
</div>
|
||||||
<input type="search" name="search" class="search-inventory" placeholder="Search...">
|
<input type="search" name="search" class="search-inventory" placeholder="{{localize "DAGGERHEART.GENERAL.searchPlaceholder"}}">
|
||||||
</div>
|
</div>
|
||||||
<a class="filter-button">
|
<a class="filter-button">
|
||||||
<i class="fa-solid fa-filter"></i>
|
<i class="fa-solid fa-filter"></i>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<i class="fa-solid fa-magnifying-glass"></i>
|
<i class="fa-solid fa-magnifying-glass"></i>
|
||||||
</div>
|
</div>
|
||||||
<input type="search" name="search" class="search-loadout" placeholder="Search...">
|
<input type="search" name="search" class="search-loadout" placeholder="{{localize "DAGGERHEART.GENERAL.searchPlaceholder"}}">
|
||||||
</div>
|
</div>
|
||||||
<a class="filter-button">
|
<a class="filter-button">
|
||||||
<i class="fa-solid fa-filter"></i>
|
<i class="fa-solid fa-filter"></i>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<i class="fa-solid fa-magnifying-glass"></i>
|
<i class="fa-solid fa-magnifying-glass"></i>
|
||||||
</div>
|
</div>
|
||||||
<input type="search" name="search" class="search-inventory" placeholder="Search...">
|
<input type="search" name="search" class="search-inventory" placeholder="{{localize "DAGGERHEART.GENERAL.searchPlaceholder"}}">
|
||||||
</div>
|
</div>
|
||||||
<a class="filter-button">
|
<a class="filter-button">
|
||||||
<i class="fa-solid fa-filter"></i>
|
<i class="fa-solid fa-filter"></i>
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@
|
||||||
<div class="actions-section">
|
<div class="actions-section">
|
||||||
<button data-action="tagTeamRoll">
|
<button data-action="tagTeamRoll">
|
||||||
<i class="fa-solid fa-user-group"></i>
|
<i class="fa-solid fa-user-group"></i>
|
||||||
<span>Tag Team Roll</span>
|
<span>{{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.title"}}</span>
|
||||||
</button>
|
</button>
|
||||||
<button data-action="groupRoll">
|
<button data-action="groupRoll">
|
||||||
<i class="fa-solid fa-users"></i>
|
<i class="fa-solid fa-users"></i>
|
||||||
<span>Group Roll</span>
|
<span>{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.title"}}</span>
|
||||||
</button>
|
</button>
|
||||||
{{!-- NOT YET IMPLEMENTED --}}
|
{{!-- NOT YET IMPLEMENTED --}}
|
||||||
{{!-- <button>
|
{{!-- <button>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<div class="item-description-outer-container">
|
{{#if features.length}}
|
||||||
{{#if features.length}}
|
<div class="item-description-outer-container">
|
||||||
<div class="item-description-container">
|
<div class="item-description-container">
|
||||||
{{#each features as | feature |}}
|
{{#each features as | feature |}}
|
||||||
<div><strong>{{localize feature.label}}</strong>: {{{localize feature.description}}}</div>
|
<div><strong>{{localize feature.label}}</strong>: {{{localize feature.description}}}</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
</div>
|
||||||
</div>
|
{{/if}}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<div class="item-description-outer-container">
|
{{#if features.length}}
|
||||||
{{#if features.length}}
|
<div class="item-description-outer-container">
|
||||||
<div class="item-description-container">
|
<div class="item-description-container">
|
||||||
{{#each features as | feature |}}
|
{{#each features as | feature |}}
|
||||||
<div><strong>{{localize feature.label}}</strong>: {{{localize feature.description}}}</div>
|
<div><strong>{{localize feature.label}}</strong>: {{{localize feature.description}}}</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
</div>
|
||||||
</div>
|
{{/if}}
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
<h1 class='item-name'><input type='text' name='name' value='{{source.name}}' /></h1>
|
<h1 class='item-name'><input type='text' name='name' value='{{source.name}}' /></h1>
|
||||||
<div class='item-description'>
|
<div class='item-description'>
|
||||||
{{#if source.system.secondary}}
|
{{#if source.system.secondary}}
|
||||||
<h3>{{localize "DAGGERHEART.ITEMS.Weapon.secondaryWeapon"}}</h3>
|
<h3>{{localize "DAGGERHEART.ITEMS.Weapon.secondaryWeapon.full"}}</h3>
|
||||||
{{else}}
|
{{else}}
|
||||||
<h3>{{localize "DAGGERHEART.ITEMS.Weapon.primaryWeapon"}}</h3>
|
<h3>{{localize "DAGGERHEART.ITEMS.Weapon.primaryWeapon.full"}}</h3>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<h3>
|
<h3>
|
||||||
{{localize (concat 'DAGGERHEART.CONFIG.Traits.' source.system.attack.roll.trait '.short')}}
|
{{localize (concat 'DAGGERHEART.CONFIG.Traits.' source.system.attack.roll.trait '.short')}}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<legend>{{localize tabs.settings.label}}</legend>
|
<legend>{{localize tabs.settings.label}}</legend>
|
||||||
<span>{{localize "DAGGERHEART.GENERAL.Tiers.singular"}}</span>
|
<span>{{localize "DAGGERHEART.GENERAL.Tiers.singular"}}</span>
|
||||||
{{formInput systemFields.tier value=source.system.tier}}
|
{{formInput systemFields.tier value=source.system.tier}}
|
||||||
<span>{{localize "DAGGERHEART.ITEMS.Weapon.secondaryWeapon"}}</span>
|
<span>{{localize "DAGGERHEART.ITEMS.Weapon.secondaryWeapon.full"}}</span>
|
||||||
{{formInput systemFields.secondary value=source.system.secondary}}
|
{{formInput systemFields.secondary value=source.system.secondary}}
|
||||||
<span>{{localize "DAGGERHEART.GENERAL.Trait.single"}}</span>
|
<span>{{localize "DAGGERHEART.GENERAL.Trait.single"}}</span>
|
||||||
{{formInput systemFields.attack.fields.roll.fields.trait value=document.system.attack.roll.trait name="system.attack.roll.trait" label="DAGGERHEART.GENERAL.Trait.single" localize=true}}
|
{{formInput systemFields.attack.fields.roll.fields.trait value=document.system.attack.roll.trait name="system.attack.roll.trait" label="DAGGERHEART.GENERAL.Trait.single" localize=true}}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
<div class="roll-part-header"><div></div></div>
|
<div class="roll-part-header"><div></div></div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (and hasSave currentTargets.length)}}<div class="roll-part-extra roll-all-save-button">Reaction Roll All Targets<i class="fa-solid fa-shield fa-lg"></i></div>{{/if}}
|
{{#if (and hasSave currentTargets.length)}}<div class="roll-part-extra roll-all-save-button">{{localize "DAGGERHEART.UI.Chat.saveRoll.reactionRollAllTargets"}}<i class="fa-solid fa-shield fa-lg"></i></div>{{/if}}
|
||||||
{{#each currentTargets}}
|
{{#each currentTargets}}
|
||||||
<div class="roll-target" data-token="{{id}}">
|
<div class="roll-target" data-token="{{id}}">
|
||||||
<img class="target-img" src="{{img}}">
|
<img class="target-img" src="{{img}}">
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
|
|
||||||
{{#if (and combats.length user.isGM)}}
|
{{#if (and combats.length user.isGM)}}
|
||||||
<div class="encounter-battlepoints" data-tooltip="#battlepoints#" data-combat-id="{{combat.id}}">
|
<div class="encounter-battlepoints" data-tooltip="#battlepoints#" data-combat-id="{{combat.id}}">
|
||||||
{{battlepoints.current}}/{{battlepoints.max}} BP{{#if battlepoints.hasModifierBP}}*{{/if}}
|
{{battlepoints.current}}/{{battlepoints.max}} {{localize "DAGGERHEART.GENERAL.Battlepoints.short"}}{{#if battlepoints.hasModifierBP}}*{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
<div class="compendium-results">
|
<div class="compendium-results">
|
||||||
{{#if menu.path.length }}
|
{{#if menu.path.length }}
|
||||||
<div class="menu-path">
|
<div class="menu-path">
|
||||||
{{#each menu.path}}
|
{{#each menu.pathLabels}}
|
||||||
{{#if (eq this "folders")}}
|
{{#unless @first}}
|
||||||
<span class="path-link">
|
<span class="path-link">
|
||||||
/
|
/
|
||||||
</span>
|
</span>
|
||||||
{{else}}
|
{{/unless}}
|
||||||
|
|
||||||
<span class="item-path">{{this}}</span>
|
<span class="item-path">{{this}}</span>
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
<div class="item-filter">
|
<div class="item-filter">
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<i class="fa-solid fa-magnifying-glass"></i>
|
<i class="fa-solid fa-magnifying-glass"></i>
|
||||||
</div>
|
</div>
|
||||||
<input type="search" name="search" class="search-input" placeholder="{{localize 'DAGGERHEART.UI.ItemBrowser.searchPlaceholder'}}">
|
<input type="search" name="search" class="search-input" placeholder="{{localize 'DAGGERHEART.GENERAL.searchPlaceholder'}}">
|
||||||
</div>
|
</div>
|
||||||
<a data-tooltip="{{localize 'DAGGERHEART.UI.ItemBrowser.tooltipFilters'}}" data-action="expandContent" disabled><i class="fa-solid fa-filter"></i></a>
|
<a data-tooltip="{{localize 'DAGGERHEART.UI.ItemBrowser.tooltipFilters'}}" data-action="expandContent" disabled><i class="fa-solid fa-filter"></i></a>
|
||||||
<a data-tooltip="{{localize 'DAGGERHEART.UI.ItemBrowser.tooltipErase'}}" data-action="resetFilters"><i class="fa-solid fa-eraser"></i></a>
|
<a data-tooltip="{{localize 'DAGGERHEART.UI.ItemBrowser.tooltipErase'}}" data-action="resetFilters"><i class="fa-solid fa-eraser"></i></a>
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
{{#if (gt item.cost.length 0)}}
|
{{#if (gt item.cost.length 0)}}
|
||||||
{{#each item.cost as | cost |}}
|
{{#each item.cost as | cost |}}
|
||||||
<div class="tag">
|
<div class="tag">
|
||||||
<span>{{localize "Type"}} {{#with (lookup @root.config.GENERAL.abilityCosts cost.type) as | type |}}{{localize type.label}}{{/with}}</span>
|
<span>{{localize "DAGGERHEART.GENERAL.type"}} {{#with (lookup @root.config.GENERAL.abilityCosts cost.type) as | type |}}{{localize type.label}}{{/with}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tag">
|
<div class="tag">
|
||||||
<span>{{localize "DAGGERHEART.GENERAL.value"}} {{cost.value}}</span>
|
<span>{{localize "DAGGERHEART.GENERAL.value"}} {{cost.value}}</span>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
{{/with}}
|
{{/with}}
|
||||||
</div>
|
</div>
|
||||||
<div class="tooltip-information">
|
<div class="tooltip-information">
|
||||||
<label>{{localize "Type"}}</label>
|
<label>{{localize "DAGGERHEART.GENERAL.type"}}</label>
|
||||||
{{#with (lookup adversaryTypes item.system.type) as | type |}}
|
{{#with (lookup adversaryTypes item.system.type) as | type |}}
|
||||||
<div>{{localize type.label}}</div>
|
<div>{{localize type.label}}</div>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
<div class="daggerheart dh-style tooltip">
|
<div class="daggerheart dh-style tooltip">
|
||||||
|
|
||||||
<div class="tooltip-header"><h2>{{localize "Adversaries"}} ({{currentBP}}/{{maxBP}})</h2></div>
|
<div class="tooltip-header"><h2>{{localize "DAGGERHEART.GENERAL.Adversary.plural"}} ({{currentBP}}/{{maxBP}})</h2></div>
|
||||||
<div class="battlepoint-categories-container">
|
<div class="battlepoint-categories-container">
|
||||||
<div class="battlepoint-categories-inner-container">
|
<div class="battlepoint-categories-inner-container">
|
||||||
{{#each categories as |category key|}}
|
{{#each categories as |category key|}}
|
||||||
{{#each category as |grouping index|}}
|
{{#each category as |grouping index|}}
|
||||||
<div class="battlepoint-grouping-container">
|
<div class="battlepoint-grouping-container">
|
||||||
{{#if grouping.nr}}
|
{{#if grouping.nr}}
|
||||||
<label>{{key}} BP: {{concat (localize grouping.description) ' ' '('grouping.nr 'x)'}}</label>
|
<label>{{key}} {{localize "DAGGERHEART.GENERAL.Battlepoints.short"}} - {{concat (localize grouping.description) ' ' '('grouping.nr 'x)'}}</label>
|
||||||
{{else}}
|
{{else}}
|
||||||
<label class="unselected-grouping">{{key}} BP - {{localize grouping.description}}</label>
|
<label class="unselected-grouping">{{key}} {{localize "DAGGERHEART.GENERAL.Battlepoints.short"}} - {{localize grouping.description}}</label>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tooltip-header"><h2>{{localize "Modifiers"}}</h2></div>
|
<div class="tooltip-header"><h2>{{localize "DAGGERHEART.GENERAL.Modifier.plural"}}</h2></div>
|
||||||
<div class="battlepoint-toggles-container">
|
<div class="battlepoint-toggles-container">
|
||||||
{{#each toggles as |toggle|}}
|
{{#each toggles as |toggle|}}
|
||||||
<div class="battlepoint-toggle-container {{#if (and toggle.disabled (not toggle.checked))}}inactive{{/if}}">
|
<div class="battlepoint-toggle-container {{#if (and toggle.disabled (not toggle.checked))}}inactive{{/if}}">
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
<input type="checkbox" data-combat-id="{{@root.combatId}}" data-category="{{toggle.categoryKey}}" data-grouping="{{toggle.toggleKey}}" {{checked toggle.checked}} />
|
<input type="checkbox" data-combat-id="{{@root.combatId}}" data-category="{{toggle.categoryKey}}" data-grouping="{{toggle.toggleKey}}" {{checked toggle.checked}} />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<label class="unselected-grouping">{{toggle.categoryKey}} BP: {{localize toggle.description}}</label>
|
<label class="unselected-grouping">{{toggle.categoryKey}} {{localize "DAGGERHEART.GENERAL.Battlepoints.short"}}: {{localize toggle.description}}</label>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<h2 class="tooltip-title">{{item.name}}</h2>
|
<h2 class="tooltip-title">{{item.name}}</h2>
|
||||||
<div class="tags">
|
<div class="tags">
|
||||||
<div class="tag">
|
<div class="tag">
|
||||||
<span>{{#if item.system.secondary}}{{localize "DAGGERHEART.ITEMS.Weapon.secondaryWeapon"}}{{else}}{{localize "DAGGERHEART.ITEMS.Weapon.primaryWeapon"}}{{/if}}</span>
|
<span>{{#if item.system.secondary}}{{localize "DAGGERHEART.ITEMS.Weapon.secondaryWeapon.full"}}{{else}}{{localize "DAGGERHEART.ITEMS.Weapon.primaryWeapon.full"}}{{/if}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tag">
|
<div class="tag">
|
||||||
{{#with (lookup config.GENERAL.burden item.system.burden) as | burden |}}
|
{{#with (lookup config.GENERAL.burden item.system.burden) as | burden |}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue