Combat/automation enhancements !
All checks were successful
Release Creation / build (release) Successful in 58s
All checks were successful
Release Creation / build (release) Successful in 58s
This commit is contained in:
@@ -3168,35 +3168,35 @@ i.fvtt-cthulhu-eternal {
|
||||
display: none;
|
||||
}
|
||||
.opposed-roll-result {
|
||||
padding: 1rem;
|
||||
padding: 0.5rem;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 5px;
|
||||
font-family: var(--font-primary);
|
||||
}
|
||||
.opposed-roll-result .opposed-header {
|
||||
text-align: center;
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid var(--color-border-light-primary);
|
||||
margin-bottom: 0.3rem;
|
||||
padding-bottom: 0.2rem;
|
||||
border-bottom: 1px solid var(--color-border-light-primary);
|
||||
}
|
||||
.opposed-roll-result .opposed-header h3 {
|
||||
margin: 0;
|
||||
font-family: var(--font-title);
|
||||
font-size: calc(var(--font-size-standard) * 1.2);
|
||||
font-size: calc(var(--font-size-standard) * 1);
|
||||
color: var(--color-dark-1);
|
||||
}
|
||||
.opposed-roll-result .opposed-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
gap: 0.15rem;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
.opposed-roll-result .opposed-winner,
|
||||
.opposed-roll-result .opposed-loser {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.75rem;
|
||||
padding: 0.3rem 0.4rem;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.opposed-roll-result .opposed-winner {
|
||||
@@ -3210,48 +3210,48 @@ i.fvtt-cthulhu-eternal {
|
||||
.opposed-roll-result .character-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.opposed-roll-result .character-info img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--color-border-light-primary);
|
||||
border: 1px solid var(--color-border-light-primary);
|
||||
}
|
||||
.opposed-roll-result .character-info .character-name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
gap: 0.15rem;
|
||||
}
|
||||
.opposed-roll-result .character-info .character-name strong {
|
||||
font-size: calc(var(--font-size-standard) * 0.85);
|
||||
font-size: calc(var(--font-size-standard) * 0.75);
|
||||
text-transform: uppercase;
|
||||
color: var(--color-dark-2);
|
||||
}
|
||||
.opposed-roll-result .character-info .character-name .winner-name {
|
||||
font-size: calc(var(--font-size-standard) * 1.1);
|
||||
font-size: calc(var(--font-size-standard) * 0.95);
|
||||
font-weight: bold;
|
||||
color: var(--color-success);
|
||||
}
|
||||
.opposed-roll-result .character-info .character-name .loser-name {
|
||||
font-size: calc(var(--font-size-standard) * 1.1);
|
||||
font-size: calc(var(--font-size-standard) * 0.95);
|
||||
font-weight: bold;
|
||||
color: var(--color-failure);
|
||||
}
|
||||
.opposed-roll-result .roll-result {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
.opposed-roll-result .roll-result .roll-value {
|
||||
font-size: calc(var(--font-size-standard) * 1.5);
|
||||
font-size: calc(var(--font-size-standard) * 1.2);
|
||||
font-weight: bold;
|
||||
font-family: var(--font-title);
|
||||
}
|
||||
.opposed-roll-result .roll-result .critical-badge {
|
||||
padding: 0.25rem 0.5rem;
|
||||
padding: 0.15rem 0.3rem;
|
||||
border-radius: 3px;
|
||||
font-size: calc(var(--font-size-standard) * 0.8);
|
||||
font-size: calc(var(--font-size-standard) * 0.7);
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
background: var(--color-critical-success);
|
||||
@@ -3267,21 +3267,21 @@ i.fvtt-cthulhu-eternal {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 0;
|
||||
font-size: calc(var(--font-size-standard) * 1.1);
|
||||
gap: 0.3rem;
|
||||
padding: 0;
|
||||
font-size: calc(var(--font-size-standard) * 0.85);
|
||||
font-weight: bold;
|
||||
color: var(--color-dark-2);
|
||||
}
|
||||
.opposed-roll-result .versus-separator i {
|
||||
font-size: calc(var(--font-size-standard) * 1.3);
|
||||
font-size: calc(var(--font-size-standard) * 0.9);
|
||||
}
|
||||
.opposed-roll-result .chat-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 0.375rem;
|
||||
padding: 0.75rem;
|
||||
margin-top: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
margin-top: 0.3rem;
|
||||
border-top: 1px solid var(--color-border-light-primary);
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 0 0 5px 5px;
|
||||
|
||||
43
lang/en.json
43
lang/en.json
@@ -59,6 +59,12 @@
|
||||
},
|
||||
"hp": {
|
||||
"label": "HP",
|
||||
"value": {
|
||||
"label": "Current"
|
||||
},
|
||||
"max": {
|
||||
"label": "Max"
|
||||
},
|
||||
"stunned": {
|
||||
"label": "Stun."
|
||||
}
|
||||
@@ -126,6 +132,18 @@
|
||||
"damageBonus": {
|
||||
"label": "Dmg.Bonus"
|
||||
},
|
||||
"hp": {
|
||||
"label": "HP",
|
||||
"value": {
|
||||
"label": "Current"
|
||||
},
|
||||
"max": {
|
||||
"label": "Max"
|
||||
},
|
||||
"stunned": {
|
||||
"label": "Stun."
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"permanentRating": {
|
||||
"label": "Permanent Rating"
|
||||
@@ -557,10 +575,19 @@
|
||||
"noDefenseRoll": "No defense roll available",
|
||||
"opposedRoll": "Opposed Roll",
|
||||
"Target": "Target",
|
||||
"feet": "feet",
|
||||
"feets": "feet",
|
||||
"yard": "yard",
|
||||
"Yard": "Yard",
|
||||
"yards": "yards",
|
||||
"Feet": "Feet",
|
||||
"Yards": "Yards",
|
||||
"sanLoss5": "You suffered a SAN loss of 5+ ({value}) : you suffer a temporary insanity (Flee, Submit, Struggle or understanding the Unnatural).",
|
||||
"sanViolenceReset": "The violence SAN loss count has been reset.",
|
||||
"sanHelplessnessReset": "The helplessness SAN loss count has been reset.",
|
||||
"sanLoss": "You suffer a SAN loss",
|
||||
"noSanLoss": "No SAN loss",
|
||||
"sanLossInfo": "Select the SAN loss using the buttons below.",
|
||||
"selectSANType": "Select the type of SAN loss with the buttons below.",
|
||||
"Violence" : "Violence",
|
||||
"Helplessness": "Helplessness",
|
||||
@@ -716,9 +743,11 @@
|
||||
"skillProgress": "Skill Progress",
|
||||
"unconscious": "Unconscious",
|
||||
"dying": "Dying",
|
||||
"stunnedWarning": "The Protagonist is stunned. He cannot act until he recovers by successfully rolling a CONx5 check.",
|
||||
"deadWarning": "The Protagonist is dead. He cannot act until he is revived by a successful First Aid roll.",
|
||||
"unconsciousWarning": "The Protagonist is unconscious. He cannot act until he has at least 3 HP.",
|
||||
"luck": "Luck",
|
||||
"Other": "Other",
|
||||
"Skills": "Skills",
|
||||
"WP": "WP",
|
||||
"Luck": "Luck",
|
||||
"titleLuck": "Luck Roll",
|
||||
"healingRoll": "Healing Roll succes, the target gains",
|
||||
@@ -740,7 +769,15 @@
|
||||
"opposedRollWinner": "Opposed Roll Winner",
|
||||
"opposedRollResult": "Opposed Roll Result",
|
||||
"defeats": "defeats",
|
||||
"critical": "Critical"
|
||||
"critical": "Critical",
|
||||
"other": "Other",
|
||||
"str": "STR",
|
||||
"dex": "DEX",
|
||||
"int": "INT",
|
||||
"pow": "POW",
|
||||
"con": "CON",
|
||||
"cha": "CHA",
|
||||
"Damage": "Damage"
|
||||
},
|
||||
"ChatMessage": {
|
||||
"exhausted": "Your protagonist is exhausted. He loses [[/r 1d6]] Willpower Points."
|
||||
|
||||
@@ -771,7 +771,9 @@
|
||||
"int": "INT",
|
||||
"pow": "POU",
|
||||
"con": "CON",
|
||||
"cha": "CHA"
|
||||
"cha": "CHA",
|
||||
"Luck": "Chance",
|
||||
"Damage": "Dégâts"
|
||||
},
|
||||
"ChatMessage": {
|
||||
"exhausted": "Votre protagoniste est épuisé. Il perd [[/r 1d6]] Points de Volonté."
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// System Module Imports
|
||||
import { Utils } from './utils.js'
|
||||
import { SYSTEM } from "../../config/system.mjs"
|
||||
import CthulhuEternalUtils from '../../utils.mjs'
|
||||
|
||||
export let ActionHandler = null
|
||||
|
||||
@@ -53,7 +54,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
async buildCharacteristics() {
|
||||
const actions = []
|
||||
for (const key in this.actor.system.characteristics) {
|
||||
const encodedValue = [coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.characteristics'), key].join(this.delimiter)
|
||||
const encodedValue = ['characteristics', key].join(this.delimiter)
|
||||
const tooltip = {
|
||||
content: String(this.actor.system.characteristics[key].value * 5),
|
||||
class: 'tah-system-tooltip',
|
||||
@@ -94,7 +95,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
if (typeof this.actor.system?.san?.value !== 'undefined') {
|
||||
const actions = []
|
||||
const groupData = {
|
||||
id: 'other_sanity',
|
||||
id: 'other_san',
|
||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.SAN'),
|
||||
type: 'system'
|
||||
}
|
||||
@@ -106,29 +107,29 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
}
|
||||
actions.push({
|
||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.SAN'),
|
||||
id: 'sanity',
|
||||
id: 'san',
|
||||
info1: this.#showValue() ? { text: tooltip.content } : null,
|
||||
tooltip,
|
||||
encodedValue: ['characteristics', 'sanity'].join(this.delimiter)
|
||||
encodedValue: ['characteristics', 'san'].join(this.delimiter)
|
||||
},
|
||||
{
|
||||
name: '+',
|
||||
id: 'sanity_add',
|
||||
id: 'san_add',
|
||||
tooltip,
|
||||
encodedValue: ['characteristics', 'sanity_add'].join(this.delimiter)
|
||||
encodedValue: ['characteristics', 'san_add'].join(this.delimiter)
|
||||
},
|
||||
{
|
||||
name: '-',
|
||||
id: 'sanity_subtract',
|
||||
id: 'san_subtract',
|
||||
tooltip,
|
||||
encodedValue: ['characteristics', 'sanity_subtract'].join(this.delimiter)
|
||||
encodedValue: ['characteristics', 'san_subtract'].join(this.delimiter)
|
||||
})
|
||||
await this.addActions(actions, { id: 'other_sanity', type: 'system' })
|
||||
await this.addActions(actions, { id: 'other_san', type: 'system' })
|
||||
}
|
||||
if (typeof this.actor.system.hp.value !== 'undefined') {
|
||||
const actions = []
|
||||
const groupData = {
|
||||
id: 'other_health',
|
||||
id: 'other_hp',
|
||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.HP'),
|
||||
type: 'system'
|
||||
}
|
||||
@@ -140,24 +141,24 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
}
|
||||
actions.push({
|
||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.HP'),
|
||||
id: 'health',
|
||||
id: 'hp',
|
||||
info1: this.#showValue() ? { text: tooltip.content } : null,
|
||||
tooltip,
|
||||
encodedValue: ['characteristics', 'health'].join(this.delimiter)
|
||||
encodedValue: ['characteristics', 'hp'].join(this.delimiter)
|
||||
},
|
||||
{
|
||||
name: '+',
|
||||
id: 'health_add',
|
||||
id: 'hp_add',
|
||||
tooltip,
|
||||
encodedValue: ['characteristics', 'health_add'].join(this.delimiter)
|
||||
encodedValue: ['characteristics', 'hp_add'].join(this.delimiter)
|
||||
},
|
||||
{
|
||||
name: '-',
|
||||
id: 'health_subtract',
|
||||
id: 'hp_subtract',
|
||||
tooltip,
|
||||
encodedValue: ['characteristics', 'health_subtract'].join(this.delimiter)
|
||||
encodedValue: ['characteristics', 'hp_subtract'].join(this.delimiter)
|
||||
})
|
||||
await this.addActions(actions, { id: 'other_health', type: 'system' })
|
||||
await this.addActions(actions, { id: 'other_hp', type: 'system' })
|
||||
}
|
||||
if (typeof this.actor.system.wp.value !== 'undefined') {
|
||||
const actions = []
|
||||
@@ -197,12 +198,15 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
|
||||
async buildSkills() {
|
||||
const actions = []
|
||||
for (const item of this.actor.items) {
|
||||
if (item.type !== 'skill') continue;
|
||||
if (item.type === 'skill' && item.system.skillTotal > 0) {
|
||||
const skill = item
|
||||
// Build alpha sorted skill list
|
||||
let skills = this.actor.items.filter(i => i.type === 'skill')
|
||||
skills = skills.sort((a, b) => a.name.localeCompare(b.name))
|
||||
console.log('Building skills actions for skills:', skills)
|
||||
for (const skill of skills) {
|
||||
console.log('Processing skill item:', skill)
|
||||
if (skill.system.skillTotal > 0) {
|
||||
const tooltip = {
|
||||
content: String(item.system.skillTotal),
|
||||
content: String(skill.system.skillTotal),
|
||||
direction: 'LEFT'
|
||||
}
|
||||
actions.push({
|
||||
@@ -218,56 +222,55 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
}
|
||||
|
||||
async buildEquipment() {
|
||||
let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era")
|
||||
|
||||
// const rituals = []
|
||||
for (const item of this.actor.items) {
|
||||
// Push the weapon name as a new group
|
||||
const groupData = {
|
||||
id: 'weapons_' + item._id,
|
||||
id: `weapons_${item._id}`,
|
||||
name: item.name,
|
||||
type: 'system'
|
||||
}
|
||||
this.addGroup(groupData, { id: 'weapons', type: 'system' }, true)
|
||||
if (item.type === 'weapon') {
|
||||
const weapons = []
|
||||
let skill = CthulhuEternalUtils.getWeaponSkill(this.actor, item, era)
|
||||
item.skillTotal = skill ? skill.system.skillTotal : 0
|
||||
let weapons = []
|
||||
const tooltip = {
|
||||
content: String(item.system.skillTotal),
|
||||
content: String(item.skillTotal),
|
||||
direction: 'LEFT'
|
||||
}
|
||||
console.log('Weapon skill total for', item.name, 'is', item.skillTotal, item._id)
|
||||
weapons.push({
|
||||
name: item.name,
|
||||
id: item._id,
|
||||
name: `${item.name} (${item.skillTotal})`,
|
||||
id: `weapon_${item._id}`,
|
||||
info1: this.#showValue() ? { text: tooltip.content } : null,
|
||||
encodedValue: ['weapons', item._id].join(this.delimiter),
|
||||
tooltip
|
||||
})
|
||||
let damage = ''
|
||||
if (item.system.lethality > 0) {
|
||||
damage = `L:${item.system.lethality}%`
|
||||
} else {
|
||||
damage = item.system.damage
|
||||
}
|
||||
const damageTooltip = {
|
||||
content: String(item.system.damage),
|
||||
content: String(damage),
|
||||
direction: 'LEFT'
|
||||
}
|
||||
if (item.system.damage !== '') {
|
||||
weapons.push({
|
||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Damage'),
|
||||
id: item._id,
|
||||
name: `${coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Damage')} (${damage})`,
|
||||
id: `damage_${item._id}`,
|
||||
info1: this.#showValue() ? { text: damageTooltip.content } : null,
|
||||
encodedValue: ['damage', item._id].join(this.delimiter),
|
||||
tooltip: damageTooltip
|
||||
})
|
||||
}
|
||||
if (item.system.lethality > 0) {
|
||||
const lethalityTooltip = {
|
||||
content: String(item.system.lethality),
|
||||
direction: 'LEFT'
|
||||
}
|
||||
weapons.push({
|
||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.Lethality'),
|
||||
id: item._id,
|
||||
info1: this.#showValue() ? { text: lethalityTooltip.content } : null,
|
||||
encodedValue: ['lethality', item._id].join(this.delimiter),
|
||||
tooltip: lethalityTooltip
|
||||
})
|
||||
}
|
||||
console.log('Adding weapon actions for', item.name, weapons)
|
||||
await this.addActions(weapons, {
|
||||
id: 'weapons_' + item._id,
|
||||
id: `weapons_${item._id}`,
|
||||
type: 'system'
|
||||
})
|
||||
}/* else if (item.type === 'ritual') {
|
||||
|
||||
@@ -22,7 +22,7 @@ export const REQUIRED_CORE_MODULE_VERSION = '2.0'
|
||||
*/
|
||||
export const ACTION_TYPE = {
|
||||
characteristics: 'CTHULHUETERNAL.Label.characteristics',
|
||||
skills: 'CTHULHUETERNAL.Label.skills',
|
||||
skills: 'CTHULHUETERNAL.Label.Skills',
|
||||
equipment: 'CTHULHUETERNAL.Label.gear'
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export const GROUP = {
|
||||
characteristics: { id: 'characteristics', name: 'CTHULHUETERNAL.Label.characteristics', type: 'system' },
|
||||
luck: { id: 'luck', name: 'CTHULHUETERNAL.Label.luck', type: 'system' },
|
||||
other: { id: 'other', name: 'CTHULHUETERNAL.Label.other', type: 'system' },
|
||||
skills: { id: 'skills', name: 'CTHULHUETERNAL.Label.skills', type: 'system' },
|
||||
skills: { id: 'skills', name: 'CTHULHUETERNAL.Label.Skills', type: 'system' },
|
||||
weapons: { id: 'weapons', name: 'CTHULHUETERNAL.Label.weapons', type: 'system' },
|
||||
rituals: { id: 'rituals', name: 'CTHULHUETERNAL.Label.rituals', type: 'system' }
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
{
|
||||
nestId: 'statistics',
|
||||
id: 'statistics',
|
||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.characteristics'),
|
||||
name: game.i18n.localize('CTHULHUETERNAL.Label.characteristics'),
|
||||
groups: [
|
||||
{ ...groups.characteristics, nestId: 'statistics_characteristics' },
|
||||
{ ...groups.other, nestId: 'statistics_other' },
|
||||
@@ -27,7 +27,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
{
|
||||
nestId: 'skills',
|
||||
id: 'skills',
|
||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.skills'),
|
||||
name: game.i18n.localize('CTHULHUETERNAL.Label.skills'),
|
||||
groups: [
|
||||
{ ...groups.skills, nestId: 'skills_skills' }
|
||||
]
|
||||
@@ -35,7 +35,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
{
|
||||
nestId: 'equipment',
|
||||
id: 'equipment',
|
||||
name: coreModule.api.Utils.i18n('CTHULHUETERNAL.Label.gear'),
|
||||
name: game.i18n.localize('CTHULHUETERNAL.Label.gear'),
|
||||
groups: [
|
||||
{ ...groups.weapons, nestId: 'equipment_weapons' },
|
||||
{ ...groups.rituals, nestId: 'equipment_rituals' }
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { SystemManager } from './system-manager.js'
|
||||
import { MODULE, REQUIRED_CORE_MODULE_VERSION } from './constants.js'
|
||||
|
||||
Hooks.on('tokenActionHudCoreApiReady', async () => {
|
||||
/**
|
||||
* Return the SystemManager and requiredCoreModuleVersion to Token Action HUD Core
|
||||
*/
|
||||
const module = game.modules.get(MODULE.ID)
|
||||
module.api = {
|
||||
requiredCoreModuleVersion: REQUIRED_CORE_MODULE_VERSION,
|
||||
SystemManager
|
||||
}
|
||||
Hooks.call('tokenActionHudSystemReady', module)
|
||||
})
|
||||
@@ -66,9 +66,10 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
* @param {string} actionId The actionId
|
||||
*/
|
||||
async #handleAction(event, actor, token, actionTypeId, actionId) {
|
||||
console.log('Handling action', actionId, 'of type', actionTypeId, 'for actor', actor.name)
|
||||
switch (actionTypeId) {
|
||||
case 'attributes':
|
||||
await this.#handleAttributesAction(event, actor, actionId)
|
||||
case 'characteristics':
|
||||
await this.#handleCharacteristicsAction(event, actor, actionId)
|
||||
break
|
||||
case 'skills':
|
||||
await this.#handleSkillsAction(event, actor, actionId)
|
||||
@@ -92,18 +93,20 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Attribute action
|
||||
* Handle Characteristic action
|
||||
* @private
|
||||
* @param {object} event The event
|
||||
* @param {object} actor The actor
|
||||
* @param {string} actionId The action id
|
||||
*/
|
||||
async #handleAttributesAction(event, actor, actionId) {
|
||||
async #handleCharacteristicsAction(event, actor, actionId) {
|
||||
let rollType
|
||||
if (actionId === 'wp' || actionId === 'health') return
|
||||
if (actionId === 'wp' || actionId === 'hp') return
|
||||
|
||||
if (actionId.includes('_add') || actionId.includes('_subtract')) {
|
||||
const attr = actionId.split('_')[0]
|
||||
const action = actionId.split('_')[1]
|
||||
console.log('Updating', attr, 'with action', action)
|
||||
const update = {}
|
||||
update.system = {}
|
||||
update.system[attr] = {}
|
||||
@@ -111,21 +114,23 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
if (update.system[attr].value > this.actor.system[attr].max || update.system[attr].value < this.actor.system[attr].min) return
|
||||
return await this.actor.update(update)
|
||||
}
|
||||
if (actionId === 'sanity') {
|
||||
rollType = actionId
|
||||
if (actionId === 'san') {
|
||||
let item = foundry.utils.duplicate(actor.system.san)
|
||||
item.name = game.i18n.localize("CTHULHUETERNAL.Label.SAN")
|
||||
item.targetScore = item.value
|
||||
await actor.system.roll('san', item)
|
||||
} else if (actionId === 'luck') {
|
||||
rollType = actionId
|
||||
let item = foundry.utils.duplicate(actor.system.characteristics.int)
|
||||
item.name = game.i18n.localize("CTHULHUETERNAL.Label.Luck")
|
||||
item.value = 10
|
||||
item.targetScore = 50
|
||||
await actor.system.roll('luck', item)
|
||||
} else {
|
||||
rollType = 'stat'
|
||||
let item = foundry.utils.duplicate(actor.system.characteristics[actionId])
|
||||
item.name = game.i18n.localize(`CTHULHUETERNAL.Label.${actionId}Long`)
|
||||
item.targetScore = item.value * 5
|
||||
await actor.system.roll('char', item)
|
||||
}
|
||||
const options = {
|
||||
actor: this.actor,
|
||||
rollType,
|
||||
key: actionId
|
||||
}
|
||||
|
||||
/*const roll = new DGPercentileRoll('1D100', {}, options)
|
||||
return await this.actor.sheet.processRoll(event, roll)*/
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,18 +141,9 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
* @param {string} actionId The action id
|
||||
*/
|
||||
async #handleSkillsAction(event, actor, actionId) {
|
||||
const options = {
|
||||
actor: this.actor,
|
||||
rollType: 'skill',
|
||||
key: actionId
|
||||
}
|
||||
|
||||
const skill = this.actor.items.find(i => i.type === 'skill' && i.id === actionId)
|
||||
if (!skill) return ui.notifications.warn('Bad skill name in HUD.')
|
||||
|
||||
/** TO FIX
|
||||
const roll = new DGPercentileRoll('1D100', {}, options)
|
||||
await this.actor.sheet.processRoll(event, roll)*/
|
||||
const skill = actor.items.find(i => i.type === 'skill' && i.id === actionId)
|
||||
if (!skill) return ui.notifications.warn(`Skill not found for action id '${actionId}'`)
|
||||
await actor.system.roll('skill', skill)
|
||||
}
|
||||
|
||||
|
||||
@@ -159,16 +155,10 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
* @param {string} actionId The action id
|
||||
*/
|
||||
async #handleWeaponsAction(event, actor, actionId) {
|
||||
const item = this.actor.items.get(actionId)
|
||||
const options = {
|
||||
actor: this.actor,
|
||||
rollType: 'weapon',
|
||||
key: item.system.skill,
|
||||
item
|
||||
}
|
||||
/* TO FIX
|
||||
const roll = new DGPercentileRoll('1D100', {}, options)
|
||||
await this.actor.sheet.processRoll(event, roll)*/
|
||||
let weapon = actor.items.find(i => i.type === 'weapon' && i.id === actionId)
|
||||
weapon.damageFormula = weapon.system.damage
|
||||
weapon.damageBonus = actor.system.damageBonus
|
||||
await actor.system.roll('weapon', weapon)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,22 +169,10 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
* @param {string} actionId The action id
|
||||
*/
|
||||
async #handleDamageAction(event, actor, actionId) {
|
||||
const item = this.actor.items.get(actionId)
|
||||
if (item.system.lethality > 0 && event.ctrlKey) {
|
||||
// Toggle on/off lethality
|
||||
const isLethal = !item.system.isLethal
|
||||
await item.update({ 'system.isLethal': isLethal })
|
||||
} else {
|
||||
const options = {
|
||||
actor: this.actor,
|
||||
rollType: 'damage',
|
||||
key: item.system.damage,
|
||||
item
|
||||
}
|
||||
/* TOFIX
|
||||
const roll = new DGDamageRoll(item.system.damage, {}, options)
|
||||
await this.actor.sheet.processRoll(event, roll)*/
|
||||
}
|
||||
let weapon = actor.items.find(i => i.type === 'weapon' && i.id === actionId)
|
||||
weapon.damageFormula = weapon.system.damage
|
||||
weapon.damageBonus = actor.system.damageBonus
|
||||
await actor.system.roll('damage', weapon)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -463,6 +463,13 @@ export default class CthulhuEternalUtils {
|
||||
|
||||
static async damageRoll(rollMessage, formula = null) {
|
||||
let rollData = rollMessage.rolls[0]?.options?.rollData
|
||||
if (!rollData) {
|
||||
rollData = rollMessage.getFlag("fvtt-cthulhu-eternal", "rollData")
|
||||
}
|
||||
if (!rollData) {
|
||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Label.noRollDataFound"))
|
||||
return
|
||||
}
|
||||
let actor = game.actors.get(rollData.actorId)
|
||||
if (!actor) {
|
||||
ui.notifications.error(game.i18n.localize("CTHULHUETERNAL.Label.noActorFound"))
|
||||
|
||||
@@ -1 +1 @@
|
||||
MANIFEST-000265
|
||||
MANIFEST-000269
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2025/11/12-23:40:11.531092 7f47827fc6c0 Recovering log #263
|
||||
2025/11/12-23:40:11.541025 7f47827fc6c0 Delete type=0 #263
|
||||
2025/11/12-23:40:11.541091 7f47827fc6c0 Delete type=3 #261
|
||||
2025/11/12-23:40:47.861546 7f4780bff6c0 Level-0 table #268: started
|
||||
2025/11/12-23:40:47.861580 7f4780bff6c0 Level-0 table #268: 0 bytes OK
|
||||
2025/11/12-23:40:47.867844 7f4780bff6c0 Delete type=0 #266
|
||||
2025/11/12-23:40:47.874806 7f4780bff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
|
||||
2025/11/12-23:48:30.686758 7f4781ffb6c0 Recovering log #267
|
||||
2025/11/12-23:48:30.697449 7f4781ffb6c0 Delete type=3 #265
|
||||
2025/11/12-23:48:30.697507 7f4781ffb6c0 Delete type=0 #267
|
||||
2025/11/13-13:58:42.410831 7f4780bff6c0 Level-0 table #272: started
|
||||
2025/11/13-13:58:42.410865 7f4780bff6c0 Level-0 table #272: 0 bytes OK
|
||||
2025/11/13-13:58:42.417362 7f4780bff6c0 Delete type=0 #270
|
||||
2025/11/13-13:58:42.434870 7f4780bff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2025/10/08-22:08:44.664871 7f77151f96c0 Recovering log #259
|
||||
2025/10/08-22:08:44.675676 7f77151f96c0 Delete type=3 #257
|
||||
2025/10/08-22:08:44.675773 7f77151f96c0 Delete type=0 #259
|
||||
2025/10/08-23:43:02.763720 7f770f3ff6c0 Level-0 table #264: started
|
||||
2025/10/08-23:43:02.763751 7f770f3ff6c0 Level-0 table #264: 0 bytes OK
|
||||
2025/10/08-23:43:02.770330 7f770f3ff6c0 Delete type=0 #262
|
||||
2025/10/08-23:43:02.770574 7f770f3ff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
|
||||
2025/11/12-23:40:11.531092 7f47827fc6c0 Recovering log #263
|
||||
2025/11/12-23:40:11.541025 7f47827fc6c0 Delete type=0 #263
|
||||
2025/11/12-23:40:11.541091 7f47827fc6c0 Delete type=3 #261
|
||||
2025/11/12-23:40:47.861546 7f4780bff6c0 Level-0 table #268: started
|
||||
2025/11/12-23:40:47.861580 7f4780bff6c0 Level-0 table #268: 0 bytes OK
|
||||
2025/11/12-23:40:47.867844 7f4780bff6c0 Delete type=0 #266
|
||||
2025/11/12-23:40:47.874806 7f4780bff6c0 Manual compaction at level-0 from '!items!4oyPRBWPBWAChrJP' @ 72057594037927935 : 1 .. '!items!zVFfp3o0G0Zg3Ia4' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000434
|
||||
MANIFEST-000438
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2025/11/12-23:40:11.502931 7f4781ffb6c0 Recovering log #432
|
||||
2025/11/12-23:40:11.512928 7f4781ffb6c0 Delete type=0 #432
|
||||
2025/11/12-23:40:11.512984 7f4781ffb6c0 Delete type=3 #430
|
||||
2025/11/12-23:40:47.855365 7f4780bff6c0 Level-0 table #437: started
|
||||
2025/11/12-23:40:47.855411 7f4780bff6c0 Level-0 table #437: 0 bytes OK
|
||||
2025/11/12-23:40:47.861414 7f4780bff6c0 Delete type=0 #435
|
||||
2025/11/12-23:40:47.874794 7f4780bff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
|
||||
2025/11/12-23:48:30.659183 7f47817fa6c0 Recovering log #436
|
||||
2025/11/12-23:48:30.670042 7f47817fa6c0 Delete type=3 #434
|
||||
2025/11/12-23:48:30.670124 7f47817fa6c0 Delete type=0 #436
|
||||
2025/11/13-13:58:42.417482 7f4780bff6c0 Level-0 table #441: started
|
||||
2025/11/13-13:58:42.417509 7f4780bff6c0 Level-0 table #441: 0 bytes OK
|
||||
2025/11/13-13:58:42.423396 7f4780bff6c0 Delete type=0 #439
|
||||
2025/11/13-13:58:42.434882 7f4780bff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2025/10/08-22:08:44.633139 7f77159fa6c0 Recovering log #428
|
||||
2025/10/08-22:08:44.643368 7f77159fa6c0 Delete type=3 #426
|
||||
2025/10/08-22:08:44.643480 7f77159fa6c0 Delete type=0 #428
|
||||
2025/10/08-23:43:02.756716 7f770f3ff6c0 Level-0 table #433: started
|
||||
2025/10/08-23:43:02.756789 7f770f3ff6c0 Level-0 table #433: 0 bytes OK
|
||||
2025/10/08-23:43:02.763557 7f770f3ff6c0 Delete type=0 #431
|
||||
2025/10/08-23:43:02.770557 7f770f3ff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
|
||||
2025/11/12-23:40:11.502931 7f4781ffb6c0 Recovering log #432
|
||||
2025/11/12-23:40:11.512928 7f4781ffb6c0 Delete type=0 #432
|
||||
2025/11/12-23:40:11.512984 7f4781ffb6c0 Delete type=3 #430
|
||||
2025/11/12-23:40:47.855365 7f4780bff6c0 Level-0 table #437: started
|
||||
2025/11/12-23:40:47.855411 7f4780bff6c0 Level-0 table #437: 0 bytes OK
|
||||
2025/11/12-23:40:47.861414 7f4780bff6c0 Delete type=0 #435
|
||||
2025/11/12-23:40:47.874794 7f4780bff6c0 Manual compaction at level-0 from '!folders!5PrT9QmN1cFPzDFP' @ 72057594037927935 : 1 .. '!items!zvoUByzWSWZ87fxA' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
MANIFEST-000080
|
||||
MANIFEST-000084
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2025/11/12-23:40:11.517421 7f4782ffd6c0 Recovering log #78
|
||||
2025/11/12-23:40:11.527038 7f4782ffd6c0 Delete type=0 #78
|
||||
2025/11/12-23:40:11.527106 7f4782ffd6c0 Delete type=3 #76
|
||||
2025/11/12-23:40:47.867960 7f4780bff6c0 Level-0 table #83: started
|
||||
2025/11/12-23:40:47.867984 7f4780bff6c0 Level-0 table #83: 0 bytes OK
|
||||
2025/11/12-23:40:47.874660 7f4780bff6c0 Delete type=0 #81
|
||||
2025/11/12-23:40:47.874816 7f4780bff6c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)
|
||||
2025/11/12-23:48:30.674156 7f4781ffb6c0 Recovering log #82
|
||||
2025/11/12-23:48:30.683495 7f4781ffb6c0 Delete type=3 #80
|
||||
2025/11/12-23:48:30.683546 7f4781ffb6c0 Delete type=0 #82
|
||||
2025/11/13-13:58:42.404378 7f4780bff6c0 Level-0 table #87: started
|
||||
2025/11/13-13:58:42.404437 7f4780bff6c0 Level-0 table #87: 0 bytes OK
|
||||
2025/11/13-13:58:42.410719 7f4780bff6c0 Delete type=0 #85
|
||||
2025/11/13-13:58:42.434856 7f4780bff6c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
2025/10/08-22:08:44.648914 7f770ffff6c0 Recovering log #74
|
||||
2025/10/08-22:08:44.660220 7f770ffff6c0 Delete type=3 #72
|
||||
2025/10/08-22:08:44.660388 7f770ffff6c0 Delete type=0 #74
|
||||
2025/10/08-23:43:02.832863 7f770f3ff6c0 Level-0 table #79: started
|
||||
2025/10/08-23:43:02.832918 7f770f3ff6c0 Level-0 table #79: 0 bytes OK
|
||||
2025/10/08-23:43:02.839997 7f770f3ff6c0 Delete type=0 #77
|
||||
2025/10/08-23:43:02.852551 7f770f3ff6c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)
|
||||
2025/11/12-23:40:11.517421 7f4782ffd6c0 Recovering log #78
|
||||
2025/11/12-23:40:11.527038 7f4782ffd6c0 Delete type=0 #78
|
||||
2025/11/12-23:40:11.527106 7f4782ffd6c0 Delete type=3 #76
|
||||
2025/11/12-23:40:47.867960 7f4780bff6c0 Level-0 table #83: started
|
||||
2025/11/12-23:40:47.867984 7f4780bff6c0 Level-0 table #83: 0 bytes OK
|
||||
2025/11/12-23:40:47.874660 7f4780bff6c0 Delete type=0 #81
|
||||
2025/11/12-23:40:47.874816 7f4780bff6c0 Manual compaction at level-0 from '!folders!0DI3T2jve3nsmsfZ' @ 72057594037927935 : 1 .. '!items!zyxA9DhO36t5OBDv' @ 0 : 0; will stop at (end)
|
||||
|
||||
Binary file not shown.
@@ -188,21 +188,21 @@
|
||||
}
|
||||
|
||||
.opposed-roll-result {
|
||||
padding: 1rem;
|
||||
padding: 0.5rem;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 5px;
|
||||
font-family: var(--font-primary);
|
||||
|
||||
.opposed-header {
|
||||
text-align: center;
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid var(--color-border-light-primary);
|
||||
margin-bottom: 0.3rem;
|
||||
padding-bottom: 0.2rem;
|
||||
border-bottom: 1px solid var(--color-border-light-primary);
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-family: var(--font-title);
|
||||
font-size: calc(var(--font-size-standard) * 1.2);
|
||||
font-size: calc(var(--font-size-standard) * 1);
|
||||
color: var(--color-dark-1);
|
||||
}
|
||||
}
|
||||
@@ -210,8 +210,8 @@
|
||||
.opposed-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
gap: 0.15rem;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
.opposed-winner,
|
||||
@@ -219,7 +219,7 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.75rem;
|
||||
padding: 0.3rem 0.4rem;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
@@ -236,34 +236,34 @@
|
||||
.character-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
gap: 0.5rem;
|
||||
|
||||
img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--color-border-light-primary);
|
||||
border: 1px solid var(--color-border-light-primary);
|
||||
}
|
||||
|
||||
.character-name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
gap: 0.15rem;
|
||||
|
||||
strong {
|
||||
font-size: calc(var(--font-size-standard) * 0.85);
|
||||
font-size: calc(var(--font-size-standard) * 0.75);
|
||||
text-transform: uppercase;
|
||||
color: var(--color-dark-2);
|
||||
}
|
||||
|
||||
.winner-name {
|
||||
font-size: calc(var(--font-size-standard) * 1.1);
|
||||
font-size: calc(var(--font-size-standard) * 0.95);
|
||||
font-weight: bold;
|
||||
color: var(--color-success);
|
||||
}
|
||||
|
||||
.loser-name {
|
||||
font-size: calc(var(--font-size-standard) * 1.1);
|
||||
font-size: calc(var(--font-size-standard) * 0.95);
|
||||
font-weight: bold;
|
||||
color: var(--color-failure);
|
||||
}
|
||||
@@ -273,18 +273,18 @@
|
||||
.roll-result {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
gap: 0.3rem;
|
||||
|
||||
.roll-value {
|
||||
font-size: calc(var(--font-size-standard) * 1.5);
|
||||
font-size: calc(var(--font-size-standard) * 1.2);
|
||||
font-weight: bold;
|
||||
font-family: var(--font-title);
|
||||
}
|
||||
|
||||
.critical-badge {
|
||||
padding: 0.25rem 0.5rem;
|
||||
padding: 0.15rem 0.3rem;
|
||||
border-radius: 3px;
|
||||
font-size: calc(var(--font-size-standard) * 0.8);
|
||||
font-size: calc(var(--font-size-standard) * 0.7);
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
background: var(--color-critical-success);
|
||||
@@ -304,14 +304,14 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 0;
|
||||
font-size: calc(var(--font-size-standard) * 1.1);
|
||||
gap: 0.3rem;
|
||||
padding: 0;
|
||||
font-size: calc(var(--font-size-standard) * 0.85);
|
||||
font-weight: bold;
|
||||
color: var(--color-dark-2);
|
||||
|
||||
i {
|
||||
font-size: calc(var(--font-size-standard) * 1.3);
|
||||
font-size: calc(var(--font-size-standard) * 0.9);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,8 +319,8 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 0.375rem;
|
||||
padding: 0.75rem;
|
||||
margin-top: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
margin-top: 0.3rem;
|
||||
border-top: 1px solid var(--color-border-light-primary);
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 0 0 5px 5px;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
w{{! Template for opposed roll result }}
|
||||
{{! Template for opposed roll result }}
|
||||
<div class="cthulhu-eternal-roll opposed-roll-result">
|
||||
<div class="opposed-header">
|
||||
<h3>{{localize "CTHULHUETERNAL.Label.opposedRollResult"}}</h3>
|
||||
|
||||
Reference in New Issue
Block a user