From 3fdb3a009cb47ba5d9839192e2861fe5ec6f66b3 Mon Sep 17 00:00:00 2001 From: juanferrer Date: Thu, 27 Jun 2024 22:52:21 +0100 Subject: [PATCH] Fix vision modes --- src/lang/en.json | 5 ++ src/module/chat/roll-messages.js | 28 +++++++--- src/module/demonlord.js | 4 ++ src/module/macros/gm-macros.js | 14 ++--- src/module/vision.js | 91 ++++++++++++++++++++++++++++++++ 5 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 src/module/vision.js diff --git a/src/lang/en.json b/src/lang/en.json index b2d23b2c..7dfa7445 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -736,6 +736,11 @@ "DL.VehicleSpace": "Space", "DL.VehicleSpeedTraits": "Speed traits", "DL.VehicleTraits": "Traits", + "DL.VisionBasic": "Basic vision", + "DL.VisionShadowsight": "Shadowsight", + "DL.VisionDarksight": "Darksight", + "DL.VisionSightless": "Sightless", + "DL.VisionTruesight": "Truesight", "DL.VSRoll": "VS Roll", "DL.WealthCoinsBits": "Bits: ", "DL.WealthCoinsCP": "CP: ", diff --git a/src/module/chat/roll-messages.js b/src/module/chat/roll-messages.js index 0a28ac77..f3995a66 100644 --- a/src/module/chat/roll-messages.js +++ b/src/module/chat/roll-messages.js @@ -41,6 +41,9 @@ export function postAttackToChat(attacker, defender, item, attackRoll, attackAtt const defenseShow = game.settings.get('demonlord', 'attackShowDefense') const againstNumber = ((defender?.type === 'character' && defender?.isPC) || defenseShow) && targetNumber ? targetNumber : '?' + let extraDamage = (attacker.system.bonuses.attack.damage.weapon ?? '') + (attacker.system.bonuses.attack.damage.all ?? '') + let extraDamage20Plus = (attacker.system.bonuses.attack.plus20Damage.weapon ?? '') + (attacker.system.bonuses.attack.plus20Damage.all ?? '') + const templateData = { actor: attacker, item: {id: item._id, data: item, name: item.name, uuid: item.uuid}, @@ -59,10 +62,10 @@ export function postAttackToChat(attacker, defender, item, attackRoll, attackAtt data['againstNumber'] = defenseAttributeImmune ? '-' : againstNumber data['againstNumberGM'] = defenseAttributeImmune ? '-' : (againstNumber === '?' ? targetNumber : againstNumber) data['damageFormula'] = itemData?.action?.damage - data['extraDamageFormula'] = attacker.system.bonuses.attack.damage + data['extraDamageFormula'] = extraDamage data['damageType'] = itemData.action.damagetype data['damageTypes'] = itemData.action.damagetypes - data['damageExtra20PlusFormula'] = itemData.action?.plus20damage + attacker.system.bonuses?.attack?.plus20Damage + data['damageExtra20PlusFormula'] = itemData.action?.plus20damage + extraDamage20Plus data['description'] = itemData.description data['defense'] = itemData.action?.defense data['defenseboonsbanes'] = parseInt(itemData.action?.defenseboonsbanes) @@ -197,6 +200,9 @@ export function postTalentToChat(actor, talent, attackRoll, target, inputBoons) const defenseShow = game.settings.get('demonlord', 'attackShowDefense') const againstNumber = ((target?.actor?.type === 'character' && target?.actor?.isPC) || defenseShow) && targetNumber ? targetNumber : '?' + let extraDamage = (actor.system.bonuses.attack.damage.talent ?? '') + (actor.system.bonuses.attack.damage.all ?? '') + let extraDamage20Plus = (actor.system.bonuses.attack.plus20Damage.talent ?? '') + (actor.system.bonuses.attack.plus20Damage.all ?? '') + const templateData = { actor: actor, item: talent, @@ -216,10 +222,10 @@ export function postTalentToChat(actor, talent, attackRoll, target, inputBoons) data['againstNumber'] = defenseAttributeImmune ? '-' : againstNumber data['againstNumberGM'] = defenseAttributeImmune ? '-' : (againstNumber === '?' ? targetNumber : againstNumber) data['damageFormula'] = talentData?.action?.damage - data['extraDamageFormula'] = actor.system.bonuses.attack.damage + data['extraDamageFormula'] = extraDamage data['damageType'] = talentData.action?.damageactive && talentData?.action?.damage ? talentData?.action?.damagetype : talentData?.action?.damagetype data['damageTypes'] = talentData.action?.damagetypes - data['damageExtra20PlusFormula'] = talentData.action?.plus20damage + actor.system.bonuses?.attack?.plus20Damage + data['damageExtra20PlusFormula'] = talentData.action?.plus20damage + extraDamage20Plus data['description'] = talentData.description data['defense'] = talentData.action?.defense data['defenseboonsbanes'] = parseInt(talentData.action?.defenseboonsbanes) @@ -311,6 +317,9 @@ export async function postSpellToChat(actor, spell, attackRoll, target, inputBoo effectdice = effectRoll.total } + let extraDamage = (actor.system.bonuses.attack.damage.spell ?? '') + (actor.system.bonuses.attack.damage.all ?? '') + let extraDamage20Plus = (actor.system.bonuses.attack.plus20Damage.spell ?? '') + (actor.system.bonuses.attack.plus20Damage.all ?? '') + const templateData = { actor: actor, item: spell, @@ -329,10 +338,10 @@ export async function postSpellToChat(actor, spell, attackRoll, target, inputBoo data['againstNumber'] = defenseAttributeImmune ? '-' : againstNumber data['againstNumberGM'] = defenseAttributeImmune ? '-' : (againstNumber === '?' ? targetNumber : againstNumber) data['damageFormula'] = spellData?.action?.damage - data['extraDamageFormula'] = actor.system.bonuses.attack.damage + data['extraDamageFormula'] = extraDamage data['damageType'] = spellData.action?.damagetype data['damageTypes'] = spellData.action?.damagetypes - data['damageExtra20PlusFormula'] = spellData.action?.plus20damage + actor.system.bonuses?.attack?.plus20Damage + data['damageExtra20PlusFormula'] = spellData.action?.plus20damage + extraDamage20Plus data['description'] = spellData.description data['defense'] = spellData.action?.defense data['defenseboonsbanes'] = parseInt(spellData.action?.defenseboonsbanes) @@ -472,6 +481,9 @@ export const postItemToChat = (actor, item, attackRoll, target, inputBoons) => { const defenseShow = game.settings.get('demonlord', 'attackShowDefense') const againstNumber = ((target?.actor?.type === 'character' && target?.actor?.isPC) || defenseShow) && targetNumber ? targetNumber : '?' + let extraDamage = (actor.system.bonuses.attack.damage.weapon ?? '') + (actor.system.bonuses.attack.damage.all ?? '') + let extraDamage20Plus = (actor.system.bonuses.attack.plus20Damage.weapon ?? '') + (actor.system.bonuses.attack.plus20Damage.all ?? '') + const templateData = { actor, token: actor.token, @@ -499,10 +511,10 @@ export const postItemToChat = (actor, item, attackRoll, target, inputBoons) => { data['againstNumber'] = defenseAttributeImmune ? '-' : againstNumber data['againstNumberGM'] = defenseAttributeImmune ? '-' : (againstNumber === '?' ? targetNumber : againstNumber) data['damageFormula'] = itemData?.action?.damage - data['extraDamageFormula'] = actor.system.bonuses.attack.damage + data['extraDamageFormula'] = extraDamage data['damageType'] = itemData.action?.damagetype data['damageTypes'] = itemData.action?.damagetypes - data['damageExtra20PlusFormula'] = itemData.action?.plus20damage + actor.system.bonuses?.attack?.plus20Damage + data['damageExtra20PlusFormula'] = itemData.action?.plus20damage + extraDamage20Plus data['description'] = itemData.description data['defense'] = itemData.action?.defense data['defenseboonsbanes'] = parseInt(itemData.action?.defenseboonsbanes) diff --git a/src/module/demonlord.js b/src/module/demonlord.js index fa6ac3a4..4111cbaa 100644 --- a/src/module/demonlord.js +++ b/src/module/demonlord.js @@ -5,6 +5,7 @@ import {DemonlordToken} from './actor/token.js' import {DemonlordItem} from './item/item.js' import {ActionTemplate} from './pixi/action-template.js' import {registerSettings} from './settings.js' +import {registerVisionModes} from './vision.js' import {DLCombatTracker} from './combat/combat-tracker.js' import {preloadHandlebarsTemplates} from './templates.js' import * as migrations from './migration.js' @@ -102,6 +103,9 @@ Hooks.once('init', async function () { CONFIG.Item.dataModels.talent = TalentDataModel CONFIG.Item.dataModels.weapon = WeaponDataModel + // Vision modes + registerVisionModes() + registerSettings() // Register sheet application classes diff --git a/src/module/macros/gm-macros.js b/src/module/macros/gm-macros.js index afffc5eb..f3a2cf82 100644 --- a/src/module/macros/gm-macros.js +++ b/src/module/macros/gm-macros.js @@ -364,24 +364,26 @@ export async function applyVisionType(token, visionType = undefined, _otherData } if (visionType === 'darksight') { updateData.sight.range = 20 - updateData.sight.visionMode = 'darkvision' + updateData.sight.visionMode = 'darksight' updateData.detectionModes[0].range = 20 } else if (visionType === 'shadowsight') { - // Pass, waiting for foundry to implement shadow vision - ui.notifications.warn('In foundry v10 Shadowsight works the same as Basic sight, since no options for dim light exist yet.') + updateData.sight.range = 0 + updateData.sight.visionMode = 'shadowsight' + updateData.detectionModes[0].range = 0 } else if (visionType === 'sightless') { updateData.sight.range = 100 - updateData.sight.visionMode = 'tremorsense' + updateData.sight.visionMode = 'sightless' updateData.detectionModes[0].enabled = false updateData.detectionModes.push({ - id: 'feelTremor', + id: 'senseAll', enabled: true, range: 100, }) } else if (visionType === 'truesight') { - updateData.sight.range = 100 + updateData.sight.range = null updateData.detectionModes[0].enabled = false + updateData.sight.visionMode = 'truesight' updateData.detectionModes.push({ id: 'seeAll', enabled: true, diff --git a/src/module/vision.js b/src/module/vision.js new file mode 100644 index 00000000..51bc2970 --- /dev/null +++ b/src/module/vision.js @@ -0,0 +1,91 @@ +/* globals VisionMode, ColorAdjustmentsSamplerShader */ +export function registerVisionModes() { + + // Shadows as lit + CONFIG.Canvas.visionModes.shadowsight = new VisionMode({ + id: "shadowsight", + label: "DL.VisionShadowsight", + canvas: { + shader: ColorAdjustmentsSamplerShader, + uniforms: { contrast: 0, saturation: 0, brightness: 0 } + }, + lighting: { + levels: { + [VisionMode.LIGHTING_LEVELS.DIM]: VisionMode.LIGHTING_LEVELS.BRIGHT + }, + background: { + visibility: VisionMode.LIGHTING_VISIBILITY.REQUIRED, + } + }, + vision: { + darkness: { adaptive: false }, + defaults: { attenuation: 0, contrast: 0, saturation: 0, brightness: 0 } + } + }) + + // Shadows and darkness as lit (needs vision range to 20) + CONFIG.Canvas.visionModes.darksight = new VisionMode({ + id: "darksight", + label: "DL.VisionDarksight", + canvas: { + shader: ColorAdjustmentsSamplerShader, + uniforms: { contrast: 0, saturation: 0, brightness: 0 } + }, + lighting: { + levels: { + [VisionMode.LIGHTING_LEVELS.DIM]: VisionMode.LIGHTING_LEVELS.BRIGHT, + [VisionMode.LIGHTING_LEVELS.UNLIT]: VisionMode.LIGHTING_LEVELS.DIM + }, + background: { + visibility: VisionMode.LIGHTING_VISIBILITY.REQUIRED, + } + }, + vision: { + defaults: { attenuation: 0, contrast: 0, saturation: 0, brightness: 0 }, + darkness: { adaptive: false } + } + }), + + // Dim light + sense all + CONFIG.Canvas.visionModes.sightless = new VisionMode({ + id: "sightless", + label: "DL.VisionSightless", + canvas: { + shader: ColorAdjustmentsSamplerShader, + uniforms: { contrast: 0, saturation: 0, brightness: 0 } + }, + lighting: { + levels: { + [VisionMode.LIGHTING_LEVELS.BRIGHT]: VisionMode.LIGHTING_LEVELS.DIM, + [VisionMode.LIGHTING_LEVELS.BRIGHTEST]: VisionMode.LIGHTING_LEVELS.DIM, + } + }, + vision: { + darkness: { adaptive: false }, + defaults: { attenuation: 0, contrast: 0, saturation: 0, brightness: 0 } + } + }) + + // Darkvision + sense all + CONFIG.Canvas.visionModes.truesight = new VisionMode({ + id: "truesight", + label: "DL.VisionTruesight", + canvas: { + shader: ColorAdjustmentsSamplerShader, + uniforms: { contrast: 0, saturation: 0, brightness: 0 } + }, + lighting: { + levels: { + [VisionMode.LIGHTING_LEVELS.DIM]: VisionMode.LIGHTING_LEVELS.BRIGHT, + [VisionMode.LIGHTING_LEVELS.UNLIT]: VisionMode.LIGHTING_LEVELS.BRIGHT + }, + background: { + visibility: VisionMode.LIGHTING_VISIBILITY.REQUIRED, + } + }, + vision: { + darkness: { adaptive: false }, + defaults: { attenuation: 0, contrast: 0, saturation: 0, brightness: 0 } + } + }) +} \ No newline at end of file