diff --git a/src/assets/ui/consumables/incantation.svg b/src/assets/ui/consumables/incantation.svg new file mode 100644 index 00000000..260bb04d --- /dev/null +++ b/src/assets/ui/consumables/incantation.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/lang/en.json b/src/lang/en.json index 2a6218e7..fcab6a3a 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -226,6 +226,7 @@ "DL.ConsumableType": "Consumable Type", "DL.ConsumableTypeD": "Drink", "DL.ConsumableTypeF": "Food", + "DL.ConsumableTypeI": "Incantation", "DL.ConsumableTypeP": "Potion", "DL.ConsumableTypeT": "Trinket", "DL.ConsumableTypeV": "Poison", diff --git a/src/module/actor/actor.js b/src/module/actor/actor.js index 1bed267c..805aa483 100644 --- a/src/module/actor/actor.js +++ b/src/module/actor/actor.js @@ -449,27 +449,27 @@ export class DemonlordActor extends Actor { // Attack modifier and Boons/Banes const modifiers = [ - item.system.action?.rollbonus || 0, - attacker.system?.attributes[attackAttribute]?.modifier || 0, - attacker.system?.bonuses.attack.modifier?.[attackAttribute] || 0, - attacker.system?.bonuses.attack.modifier?.all || 0, - attacker.system?.bonuses.attack.modifier?.weapon || 0, + parseInt(item.system.action?.rollbonus) || 0, + parseInt(attacker.system?.attributes[attackAttribute]?.modifier) || 0, + parseInt(attacker.system?.bonuses.attack.modifier?.[attackAttribute]) || 0, + parseInt(attacker.system?.bonuses.attack.modifier?.all) || 0, + parseInt(attacker.system?.bonuses.attack.modifier?.weapon) || 0, parseInt(inputModifier) || 0, ] let boons = (parseInt(item.system.action.boonsbanes) || 0) + (parseInt(inputBoons) || 0) + - (attacker.system.bonuses.attack.boons[attackAttribute] || 0) + - (attacker.system.bonuses.attack.boons.all || 0) + - (attacker.system.bonuses.attack.boons.weapon || 0) + (parseInt(attacker.system.bonuses.attack.boons[attackAttribute]) || 0) + + (parseInt(attacker.system.bonuses.attack.boons.all) || 0) + + (parseInt(attacker.system.bonuses.attack.boons.weapon) || 0) const horrifyingBane = game.settings.get('demonlord', 'horrifyingBane') const ignoreLevelDependentBane = (game.settings.get('demonlord', 'optionalRuleLevelDependentBane') && ((attacker.system?.level >=3 && attacker.system?.level <=6 && defender?.system?.difficulty <= 25) || (attacker.system?.level >=7 && defender?.system?.difficulty <= 50))) ? false : true boons -= - (defender?.system.bonuses.defense.boons[defenseAttribute] || 0) + - (defender?.system.bonuses.defense.boons.all || 0) + - (defender?.system.bonuses.defense.boons.weapon || 0) + + (parseInt(defender?.system.bonuses.defense.boons[defenseAttribute]) || 0) + + (parseInt(defender?.system.bonuses.defense.boons.all) || 0) + + (parseInt(defender?.system.bonuses.defense.boons.weapon) || 0) + (horrifyingBane && ignoreLevelDependentBane && !attacker.system.horrifying && !attacker.system.frightening && defender?.system.horrifying && 1 || 0) // Check if requirements met @@ -560,7 +560,7 @@ export class DemonlordActor extends Actor { async rollAttributeChallenge(attribute, inputBoons, inputModifier) { const modifiers = [parseInt(inputModifier), this.getAttribute(attribute.key)?.modifier || 0] - const boons = (parseInt(inputBoons) || 0) + (this.system.bonuses.challenge.boons[attribute.key] || 0) + (this.system.bonuses.challenge.boons.all || 0) + const boons = (parseInt(inputBoons) || 0) + (parseInt(this.system.bonuses.challenge.boons[attribute.key]) || 0) + (parseInt(this.system.bonuses.challenge.boons.all) || 0) const boonsReroll = parseInt(this.system.bonuses.rerollBoon1Dice) const challengeRoll = new Roll(this.rollFormula(modifiers, boons, boonsReroll), this.system) @@ -596,15 +596,15 @@ export class DemonlordActor extends Actor { const modifiers = [ parseInt(inputModifier), - attacker.system?.attributes[attribute.key]?.modifier || 0, - attacker.system?.bonuses?.attack?.modifier?.[attribute.key] || 0, - attacker.system?.bonuses?.attack?.modifier?.all || 0, + parseInt(attacker.system?.attributes[attribute.key]?.modifier) || 0, + parseInt(attacker.system?.bonuses?.attack?.modifier?.[attribute.key]) || 0, + parseInt(attacker.system?.bonuses?.attack?.modifier?.all) || 0, ] let boons = (parseInt(inputBoons) || 0) + - (attacker.system.bonuses.attack.boons?.[attribute.key] || 0) + - (attacker.system.bonuses.attack.boons?.all || 0) + (parseInt(attacker.system.bonuses.attack.boons?.[attribute.key]) || 0) + + (parseInt(attacker.system.bonuses.attack.boons?.all) || 0) if (defendersTokens.length === 1) boons -= (defender?.system.bonuses.defense.boons[defense] || 0) + (defender?.system.bonuses.defense.boons.all || 0) + (horrifyingBane && ignoreLevelDependentBane && !attacker.system.horrifying && !attacker.system.frightening && defender?.system.horrifying && 1 || 0) @@ -684,17 +684,17 @@ export class DemonlordActor extends Actor { const attacker = this const modifiers = [ - talentData.action?.rollbonus || 0, - attacker.system?.attributes[attackAttribute]?.modifier || 0, - attacker.system?.bonuses.attack.modifier?.[attackAttribute] || 0, - attacker.system?.bonuses.attack.modifier?.all || 0, + parseInt(talentData.action?.rollbonus) || 0, + parseInt(attacker.system?.attributes[attackAttribute]?.modifier) || 0, + parseInt(attacker.system?.bonuses.attack.modifier?.[attackAttribute]) || 0, + parseInt(attacker.system?.bonuses.attack.modifier?.all) || 0, parseInt(inputModifier) || 0, ] let boons = (parseInt(inputBoons) || 0) + - (this.system.bonuses.attack.boons[attackAttribute] || 0) + - (this.system.bonuses.attack.boons.all || 0) + + (parseInt(this.system.bonuses.attack.boons[attackAttribute]) || 0) + + (parseInt(this.system.bonuses.attack.boons.all) || 0) + parseInt(talentData.action?.boonsbanes || 0) const horrifyingBane = game.settings.get('demonlord', 'horrifyingBane') @@ -773,29 +773,29 @@ export class DemonlordActor extends Actor { const attacker = this const modifiers = [ - spellData.action?.rollbonus || 0, - attacker.system?.attributes[attackAttribute]?.modifier || 0, - attacker.system?.bonuses.attack.modifier?.[attackAttribute] || 0, - attacker.system?.bonuses.attack.modifier?.all || 0, - attacker.system?.bonuses.attack.modifier?.spell || 0, + parseInt(spellData.action?.rollbonus) || 0, + parseInt(attacker.system?.attributes[attackAttribute]?.modifier) || 0, + parseInt(attacker.system?.bonuses.attack.modifier?.[attackAttribute]) || 0, + parseInt(attacker.system?.bonuses.attack.modifier?.all) || 0, + parseInt(attacker.system?.bonuses.attack.modifier?.spell) || 0, parseInt(inputModifier) || 0, ] let boons = (parseInt(inputBoons) || 0) + (parseInt(spellData.action?.boonsbanes) || 0) + - (this.system.bonuses.attack.boons[attackAttribute] || 0) + - (this.system.bonuses.attack.boons.all || 0) + - (this.system.bonuses.attack.boons.spell || 0) + (parseInt(this.system.bonuses.attack.boons[attackAttribute]) || 0) + + (parseInt(this.system.bonuses.attack.boons.all) || 0) + + (parseInt(this.system.bonuses.attack.boons.spell) || 0) const horrifyingBane = game.settings.get('demonlord', 'horrifyingBane') const ignoreLevelDependentBane = (game.settings.get('demonlord', 'optionalRuleLevelDependentBane') && ((this.system?.level >=3 && this.system?.level <=6 && target?.actor?.system?.difficulty <= 25) || (this.system?.level >=7 && target?.actor?.system?.difficulty <= 50))) ? false : true if (target) boons -= - (target?.actor?.system.bonuses.defense.boons[defenseAttribute] || 0) + - (target?.actor?.system.bonuses.defense.boons.all || 0) + - (target?.actor?.system.bonuses.defense.boons.spell || 0) + + (parseInt(target?.actor?.system.bonuses.defense.boons[defenseAttribute]) || 0) + + (parseInt(target?.actor?.system.bonuses.defense.boons.all) || 0) + + (parseInt(target?.actor?.system.bonuses.defense.boons.spell) || 0) + (horrifyingBane && ignoreLevelDependentBane && !this.system.horrifying && !this.system.frightening && target?.actor?.system.horrifying && 1 || 0) const boonsReroll = parseInt(this.system.bonuses.rerollBoon1Dice) @@ -864,14 +864,24 @@ export class DemonlordActor extends Actor { await item.update({'system.quantity': --item.system.quantity}, {parent: this}) } - if (item.system?.action?.attack) { - launchRollDialog(game.i18n.localize('DL.ItemVSRoll') + game.i18n.localize(item.name), async (event, html) => - await this.useItem(item, html.form.elements.boonsbanes.value, html.form.elements.modifier.value), - ) + // Incantations + if (item.system.consumabletype === 'I' && item.system.contents.length === 1) { + item.system.contents[0].name = `${game.i18n.localize('DL.ConsumableTypeI')}: ${item.system.contents[0].name}` + let spell = new Item(item.system.contents[0]) + let tempSpell = await this.createEmbeddedDocuments('Item', [spell]) + // Before deleting the spell we store the uuid of the spell in the chat card for later use + const updateData = {[`flags.${game.system.id}.incantationSpellUuid`]: item.system.contents[0]._stats.compendiumSource}; + await tempSpell[0].update(updateData); + await this.rollSpell(tempSpell[0].id) + await this.deleteEmbeddedDocuments('Item', [tempSpell[0].id]) } else { - await this.useItem(item, 0, 0) + if (item.system?.action?.attack) { + launchRollDialog(game.i18n.localize('DL.ItemVSRoll') + game.i18n.localize(item.name), async (event, html) => + await this.useItem(item, html.form.elements.boonsbanes.value, html.form.elements.modifier.value), ) + } else { + await this.useItem(item, 0, 0) + } } - if (deleteItem) await item.delete() } @@ -891,17 +901,17 @@ export class DemonlordActor extends Actor { const attacker = this const modifiers = [ - item.system.action.rollbonus || 0, - attacker.system?.attributes[attackAttribute]?.modifier || 0, - attacker.system?.bonuses.attack.modifier?.[attackAttribute] || 0, - attacker.system?.bonuses.attack.modifier?.all || 0, + parseInt(item.system.action.rollbonus) || 0, + parseInt(attacker.system?.attributes[attackAttribute]?.modifier) || 0, + parseInt(attacker.system?.bonuses.attack.modifier?.[attackAttribute]) || 0, + parseInt(attacker.system?.bonuses.attack.modifier?.all) || 0, parseInt(inputModifier) || 0, ] let boons = (parseInt(inputBoons) || 0) + - (this.system.bonuses.attack.boons[attackAttribute] || 0) + - (this.system.bonuses.attack.boons.all || 0) + + (parseInt(this.system.bonuses.attack.boons[attackAttribute]) || 0) + + (parseInt(this.system.bonuses.attack.boons.all) || 0) + parseInt(itemData.action?.boonsbanes || 0) const horrifyingBane = game.settings.get('demonlord', 'horrifyingBane') @@ -909,8 +919,8 @@ export class DemonlordActor extends Actor { if (targets.length === 1) boons -= ( - (target?.actor?.system.bonuses.defense.boons[defenseAttribute] || 0) + - (target?.actor?.system.bonuses.defense.boons.all || 0) + + (parseInt(target?.actor?.system.bonuses.defense.boons[defenseAttribute]) || 0) + + (parseInt(target?.actor?.system.bonuses.defense.boons.all || 0)) + (horrifyingBane && ignoreLevelDependentBane && !this.system.horrifying && !this.system.frightening && target?.actor?.system.horrifying && 1 || 0)) const boonsReroll = parseInt(this.system.bonuses.rerollBoon1Dice) diff --git a/src/module/actor/sheets/base-actor-sheet.js b/src/module/actor/sheets/base-actor-sheet.js index 5dccdfd7..093746ea 100644 --- a/src/module/actor/sheets/base-actor-sheet.js +++ b/src/module/actor/sheets/base-actor-sheet.js @@ -714,7 +714,8 @@ export default class DLBaseActorSheet extends HandlebarsApplicationMixin(ActorSh /** @override */ async _onDropItem(ev, _item) { try { - const item = _item + const incantation = this.tabGroups.primary === 'inventory' && _item.type === 'spell' ? true : false + const item = incantation ? await this.createIncantation(_item) : _item // TODO: If item (by ID) exists in this object, ignore if (this.actor.items.has(_item.id)) return @@ -722,8 +723,9 @@ export default class DLBaseActorSheet extends HandlebarsApplicationMixin(ActorSh const isAllowed = await this.checkDroppedItem(_item) if (isAllowed) { const data = foundry.utils.duplicate(item); - this.actor.createEmbeddedDocuments('Item', [data]) + let dropItem = await this.actor.createEmbeddedDocuments('Item', [data]) await this.postDropItemCreate(data) + if (incantation) await this.embedSpell(dropItem[0], foundry.utils.duplicate(_item)) } else { console.warn('Wrong item type dragged', this.document, item) } @@ -739,4 +741,76 @@ export default class DLBaseActorSheet extends HandlebarsApplicationMixin(ActorSh async postDropItemCreate(_itemData) { return true } + + async embedSpell(incantation, spell) { + const containerData = foundry.utils.duplicate(incantation) + containerData.system.contents.push(spell) + await incantation.update(containerData, {diff: false}) + } + + async createIncantation(_itemData) { + let availability + let value + switch (_itemData.system.rank) { + case 0: + availability = 'U' + value = '1 ss' + break + case 1: + availability = 'U' + value = '5 ss' + break + case 2: + availability = 'R' + value = '1 gc' + break + case 3: + availability = 'R' + value = '5 gc' + break + case 4: + availability = 'E' + value = '10 gc' + break + case 5: + availability = 'E' + value = '50 gc' + break + case 6: + availability = 'E' + value = '100 gc' + break + case 7: + availability = 'E' + value = '250 gc' + break + case 8: + availability = 'E' + value = '500 gc' + break + case 9: + availability = 'E' + value = '1000 gc' + break + case 10: + availability = 'E' + value = '5000 gc' + break + } + + let incantation = new Item({ + name: `${game.i18n.localize('DL.ConsumableTypeI')}: ${_itemData.name}`, + type: 'item', + system: { + consumabletype: 'I', + description : _itemData.system.description, + enrichedDescription : _itemData.system.enrichedDescription, + enrichedDescriptionUnrolled : _itemData.system.enrichedDescriptionUnrolled, + availability : availability, + value : value, + }, + img: _itemData.img, + }) + return incantation + } } diff --git a/src/module/chat/roll-messages.js b/src/module/chat/roll-messages.js index 5c257f8b..3a255cef 100644 --- a/src/module/chat/roll-messages.js +++ b/src/module/chat/roll-messages.js @@ -401,6 +401,12 @@ export async function postSpellToChat(actor, spell, attackRoll, target, inputBoo data['damageType'] = spellData.action?.damagetype data['damageTypes'] = spellData.action?.damagetypes data['damageExtra20PlusFormula'] = spellData.action?.plus20damage + extraDamage20Plus + // Incantation (effects) - We replace the uuid of the Scene.Actor.SpellItem.effect with the uuid of the SpellItem.effect as we already deleted the spell from the actor. + if (spell.getFlag('demonlord','incantationSpellUuid')) { + [...spell.effects].forEach((effect) => { + effect.incantationspelluuid = `${spell.getFlag('demonlord','incantationSpellUuid')}.ActiveEffect.${effect._id}` + }) + } data['itemEffects'] = spell.effects } data['description'] = spellData.description @@ -435,6 +441,8 @@ export async function postSpellToChat(actor, spell, attackRoll, target, inputBoo data['ifBlindedRoll'] = rollMode === 'blindroll' data['hasAreaTarget'] = spellData?.activatedEffect?.target?.type in CONFIG.DL.actionAreaShape data['actorInfo'] = buildActorInfo(actor) + // Incantation (measured templates) - We replace the uuid of the Scene.Actor.SpellItem with the uuid of the SpellItem as we already deleted the spell from the actor. + data['incantationspelluuid'] = spell.getFlag('demonlord','incantationSpellUuid') const chatData = getChatBaseData(actor, rollMode) if (attackRoll) { diff --git a/src/module/combat/combat.js b/src/module/combat/combat.js index f289a757..a28beeec 100644 --- a/src/module/combat/combat.js +++ b/src/module/combat/combat.js @@ -21,7 +21,7 @@ export class DLCombat extends Combat { await this.rollInitiativeStandard(ids, options) return this case "i": - await this.rollInitiativeInduvidual(ids, options) + await this.rollInitiativeIndividual(ids, options) return this case "h": await this.rollInitiativeGroup(ids, options) @@ -30,8 +30,8 @@ export class DLCombat extends Combat { } // eslint-disable-next-line no-unused-vars -async rollInitiativeInduvidual(ids, {formula = null, updateTurn = true, messageOptions = {}} = {}) { - console.log("Calling rollInitiativeInduvidual with", ids, formula, updateTurn, messageOptions) +async rollInitiativeIndividual(ids, {formula = null, updateTurn = true, messageOptions = {}} = {}) { + console.log("Calling rollInitiativeIndividual with", ids, formula, updateTurn, messageOptions) // Structure input data ids = typeof ids === 'string' ? [ids] : ids const combatantUpdates = [] diff --git a/src/module/compendium-browser/compendium-browser.js b/src/module/compendium-browser/compendium-browser.js index 6f2ab436..f8f70429 100644 --- a/src/module/compendium-browser/compendium-browser.js +++ b/src/module/compendium-browser/compendium-browser.js @@ -348,9 +348,10 @@ export default class DLCompendiumBrowser extends HandlebarsApplicationMixin(Appl } consumableTypeOptions = { - 'None': game.i18n.localize('DL.ConsumableNone'), + '': game.i18n.localize('DL.ConsumableNone'), 'D': game.i18n.localize('DL.ConsumableTypeD'), 'F': game.i18n.localize('DL.ConsumableTypeF'), + 'I': game.i18n.localize('DL.ConsumableTypeI'), 'P': game.i18n.localize('DL.ConsumableTypeP'), 'T': game.i18n.localize('DL.ConsumableTypeT'), 'V': game.i18n.localize('DL.ConsumableTypeV'), @@ -751,7 +752,7 @@ export default class DLCompendiumBrowser extends HandlebarsApplicationMixin(Appl case 'item': results = results.filter(e => { if (filters?.item?.availability && e.system.availability !== filters.item.availability) return false - if (filters?.item?.consumableType && e.system.consumableType !== filters.item.consumableType) return false + if (e.system.consumabletype !== filters.item.consumableType) return false return true }) diff --git a/src/module/demonlord.js b/src/module/demonlord.js index 784f1e17..07cab59a 100644 --- a/src/module/demonlord.js +++ b/src/module/demonlord.js @@ -45,6 +45,7 @@ import {registerHandlebarsHelpers} from "./utils/handlebars-helpers" import {_onUpdateWorldTime, DLCombat} from "./combat/combat" // optional for styling import { activateSocketListener } from "./utils/socket.js" import DLCompendiumBrowser from './compendium-browser/compendium-browser.js' +import TokenRulerDemonLord from "./utils/token-ruler.js" const { Actors, Items } = foundry.documents.collections //eslint-disable-line no-shadow const { ActorSheet, ItemSheet } = foundry.appv1.sheets //eslint-disable-line no-shadow @@ -158,6 +159,18 @@ Hooks.once('init', async function () { Babele.get().setSystemTranslationsDir('packs/translations') } activateSocketListener() + // Token Ruler + if (game.settings.get('demonlord', 'integrateTokenRuler')) { + delete CONFIG.Token.movement.actions.blink + delete CONFIG.Token.movement.actions.jump + delete CONFIG.Token.movement.actions.burrow + delete CONFIG.Token.movement.actions.climb.getCostFunction + delete CONFIG.Token.movement.actions.crawl.getCostFunction + delete CONFIG.Token.movement.actions.fly.getCostFunction + delete CONFIG.Token.movement.actions.swim.getCostFunction + CONFIG.Token.movement.actions.fly.canSelect = token => token?.actor?.system.canFly + CONFIG.Token.rulerClass = TokenRulerDemonLord + } }) Hooks.once('ready', async function () { @@ -613,6 +626,6 @@ Hooks.on('DL.ApplyHealing', data => { Hooks.on('DL.Action', async () => { if (!game.settings.get('demonlord', 'templateAutoRemove')) return - const actionTemplates = canvas.scene.templates.filter(a => a.flags.actionTemplate).map(a => a.id) + const actionTemplates = canvas.scene.templates.filter(a => a.flags.demonlord.actionTemplate).map(a => a.id) if (actionTemplates.length > 0) await canvas.scene.deleteEmbeddedDocuments('MeasuredTemplate', actionTemplates) }) diff --git a/src/module/item/sheets/base-item-sheet.js b/src/module/item/sheets/base-item-sheet.js index f7862d43..1d9c84f9 100644 --- a/src/module/item/sheets/base-item-sheet.js +++ b/src/module/item/sheets/base-item-sheet.js @@ -1064,7 +1064,8 @@ export default class DLBaseItemSheet extends HandlebarsApplicationMixin(ItemShee // Filter drops depending on the item type switch (this.document.type) { case 'item': - acceptedItemTypes = ['ammo', 'armor', 'item', 'weapon'] + if (this.document.system.consumabletype === '') acceptedItemTypes = ['ammo', 'armor', 'item', 'weapon'] + else if (this.document.system.consumabletype === 'I') acceptedItemTypes = ['spell'] break case 'relic': acceptedItemTypes = ['talent'] @@ -1074,7 +1075,7 @@ export default class DLBaseItemSheet extends HandlebarsApplicationMixin(ItemShee break } - if (!item && !acceptedItemTypes.includes(item.type)) return + if (!item || !acceptedItemTypes.includes(item.type)) return const itemUpdate = {'_id': item._id} if (itemData.uuid.startsWith('Actor.')) { diff --git a/src/module/pixi/action-template.js b/src/module/pixi/action-template.js index 35dcc8b5..80d547b1 100644 --- a/src/module/pixi/action-template.js +++ b/src/module/pixi/action-template.js @@ -111,7 +111,8 @@ export class ActionTemplate extends foundry.canvas.placeables.MeasuredTemplate { canvas.app.view.oncontextmenu = null canvas.app.view.onwheel = null initialLayer.activate() - this.actorSheet.maximize() + // Incantations: Measured template does not have parent actor. + if (this.actorSheet) this.actorSheet.maximize() } // Confirm the workflow (left-click) diff --git a/src/module/utils/handlebars-helpers.js b/src/module/utils/handlebars-helpers.js index 1be5bc9c..eb7e8dea 100644 --- a/src/module/utils/handlebars-helpers.js +++ b/src/module/utils/handlebars-helpers.js @@ -56,7 +56,6 @@ export function registerHandlebarsHelpers() { Handlebars.registerHelper('dlConsumableDropdown', (groupName, checkedKey) => _buildConsumableDropdownItem(groupName, checkedKey)) Handlebars.registerHelper('dlAmmoDropdown', (groupName, checkedKey, weapon) => _buildAmmoDropdownItem(groupName, checkedKey, weapon)) Handlebars.registerHelper('dlCheckItemOnActor', (data) => _CheckItemOnActor(data)) - Handlebars.registerHelper('dlCheckCharacteristicsIsNull', (actorData) => _CheckCharacteristicsIsNull(actorData)) Handlebars.registerHelper('dlIsNestedItem', (item) => _IsNestedItem(item)) Handlebars.registerHelper('dlGetNestedItemSource', (item) => _GetNestedItemSource(item)) @@ -91,7 +90,7 @@ function _getAttributes(groupName) { } else if (groupName === 'system.requirement.attribute') { attributes = ['', 'strength', 'agility', 'intellect', 'will', 'perception'] } else if (groupName === 'system.consumabletype') { - attributes = ['', 'D', 'F', 'P', 'V', 'T'] + attributes = ['', 'D', 'F', 'I', 'P', 'V', 'T'] } else if (groupName === 'level.attributeSelect') { attributes = ['', 'choosetwo', 'choosethree', 'fixed', 'twosets'] } @@ -148,14 +147,6 @@ function _GetNestedItemSource(item) { } -function _CheckCharacteristicsIsNull(actorData) { - if (actorData === null) { - return true - } else { - return false - } -} - function _CheckItemOnActor(data) { if (data.indexOf('Actor.') === -1) { return false @@ -470,7 +461,7 @@ function _buildAvailabilityDropdownItem(groupName, checkedKey) { function _buildConsumableDropdownItem(groupName, checkedKey) { - const attributes = ['', 'D', 'F', 'P', 'V', 'T'] + const attributes = ['', 'D', 'F', 'I', 'P', 'V', 'T'] for (let attribute of attributes) { if (checkedKey != attribute) continue const label = !attribute ? i18n('DL.ConsumableNone') : i18n(`DL.ConsumableType${attribute}`) @@ -655,7 +646,7 @@ function _buildDropdownWithValue(groupName, checkedKey, valueName, valueKey) { } function _buildConsumableDropdown(groupName, checkedKey) { - const attributes = ['', 'D', 'F', 'P', 'V', 'T'] + const attributes = ['', 'D', 'F', 'I', 'P', 'V', 'T'] for (let attribute of attributes) { if (checkedKey != attribute) continue const label = !attribute ? i18n('DL.ConsumableNone') : i18n(`DL.ConsumableType${attribute}`) diff --git a/src/module/utils/token-ruler.js b/src/module/utils/token-ruler.js index 3812fc47..c8fa7733 100644 --- a/src/module/utils/token-ruler.js +++ b/src/module/utils/token-ruler.js @@ -5,9 +5,9 @@ export default class TokenRulerDemonLord extends foundry.canvas.placeables.tokens.TokenRuler { static STYLES = { - move: { color: 0x5bcc28 }, - run: { color: 0xffcc00 }, - exceed: { color: 0xb22222 }, + move: { color: 0x33bc4e, alpha: 0.5}, + run: { color: 0xf1d836, alpha: 0.5 }, + exceed: { color: 0xe72124, alpha: 0.5 }, } /** @override */ @@ -20,7 +20,7 @@ export default class TokenRulerDemonLord extends foundry.canvas.placeables.token const cost = waypoint.measurement.cost - if (cost === 0) return style + if (cost === 0) return this.constructor.STYLES.move if (maxMovement < cost) return this.constructor.STYLES.exceed // 2-step gradient @@ -33,18 +33,14 @@ export default class TokenRulerDemonLord extends foundry.canvas.placeables.token /** @override */ _getSegmentStyle(waypoint) { const scale = canvas.dimensions.uiScale - if (canvas.scene.grid.type != 0) { - return { width: 0 } - } else { - const movement = this.token.actor.system.ranges[waypoint.action] || 0 - const maxMovement = typeof movement === 'object' ? movement[1] : movement - const cost = waypoint.measurement.cost + const movement = this.token.actor.system.ranges[waypoint.action] || 0 + const maxMovement = typeof movement === 'object' ? movement[1] : movement + const cost = waypoint.measurement.cost - let color = this.constructor.STYLES.move.color - if (movement[0] < cost && cost <= maxMovement) color = this.constructor.STYLES.run.color - else if (maxMovement < cost) color = this.constructor.STYLES.exceed.color - return { width: 4 * scale, color: color, alpha: 0.5 } - } + let color = this.constructor.STYLES.move.color + if (movement[0] < cost && cost <= maxMovement) color = this.constructor.STYLES.run.color + else if (maxMovement < cost) color = this.constructor.STYLES.exceed.color + return { width: 4 * scale, color: color} } } diff --git a/src/styles/v2/_sheets.scss b/src/styles/v2/_sheets.scss index b4ee8cf3..0237330a 100644 --- a/src/styles/v2/_sheets.scss +++ b/src/styles/v2/_sheets.scss @@ -411,6 +411,10 @@ span.vertical-rule { @include demonlord-icon('../assets/ui/consumables/food.svg'); } +.icon-consumable-I { + @include demonlord-icon('../assets/ui/consumables/incantation.svg'); +} + .icon-consumable-P { @include demonlord-icon('../assets/ui/consumables/potion.svg'); } diff --git a/src/templates/actor/tabs/creature-reference.hbs b/src/templates/actor/tabs/creature-reference.hbs index 5209e4cd..67e632b1 100644 --- a/src/templates/actor/tabs/creature-reference.hbs +++ b/src/templates/actor/tabs/creature-reference.hbs @@ -6,10 +6,12 @@