diff --git a/src/module/entities/TwodsixActor.ts b/src/module/entities/TwodsixActor.ts index 226e2d9fc..9ab43ec36 100644 --- a/src/module/entities/TwodsixActor.ts +++ b/src/module/entities/TwodsixActor.ts @@ -3,7 +3,6 @@ * @extends {Actor} */ import {calcModFor, getKeyByValue} from "../utils/sheetUtils"; -import {CharacteristicType, UpdateData} from "../../types/twodsix"; import {TWODSIX} from "../config"; import {TwodsixRollSettings} from "../utils/TwodsixRollSettings"; import {TwodsixDiceRoll} from "../utils/TwodsixDiceRoll"; @@ -57,21 +56,43 @@ export default class TwodsixActor extends Actor { const characteristics = this.data.data.characteristics; const armor = this.data.data.primaryArmor.value; let remaining:number = damage - armor; - remaining = characteristics['endurance'].current > 0 ? TwodsixActor.addDamage(remaining, characteristics['endurance']) : remaining; + let updateData = {}; + + [remaining, updateData] = this.addDamage(remaining, updateData, 'endurance'); if (remaining > 0 && characteristics['strength'].current > characteristics['dexterity'].current) { - remaining = characteristics['strength'].current > 0 ? TwodsixActor.addDamage(remaining, characteristics['strength']) : remaining; - remaining = characteristics['dexterity'].current > 0 ? TwodsixActor.addDamage(remaining, characteristics['dexterity']) : remaining; + [remaining, updateData] = this.addDamage(remaining, updateData, 'strength'); + [remaining, updateData] = this.addDamage(remaining, updateData, 'dexterity'); } else { - remaining = characteristics['dexterity'].current > 0 ? TwodsixActor.addDamage(remaining, characteristics['dexterity']) : remaining; - remaining = characteristics['strength'].current > 0 ? TwodsixActor.addDamage(remaining, characteristics['strength']) : remaining; + [remaining, updateData] = this.addDamage(remaining, updateData, 'dexterity'); + [remaining, updateData] = this.addDamage(remaining, updateData, 'strength'); } if (remaining > 0) { console.log(`Twodsix | Actor ${this.name} was overkilled by ${remaining}`); } - await this.updateActor(); + this.update(updateData); return remaining; } + private addDamage(damage:number, updateData, chrName):[number,any] { + const characteristics = this.data.data.characteristics; + const characteristic = characteristics[chrName]; + if (characteristic.current > 0) { + let handledDamage = 0; + let totalDamage = characteristic.damage; + if (damage + characteristic.damage > characteristic.value) { + handledDamage = characteristic.value - characteristic.damage; + totalDamage = characteristic.value; + } else if (damage > 0) { + handledDamage = damage; + totalDamage = characteristic.damage + damage; + } + updateData[`data.characteristics.${chrName}.damage`] = totalDamage; + return [damage - handledDamage, updateData]; + } else { + return [damage, updateData]; + } + } + public getCharacteristicModifier(characteristic:string):number { if (characteristic === 'NONE') { return 0; @@ -99,36 +120,4 @@ export default class TwodsixActor extends Actor { console.log("DEBUG CHARACTERISTICS ROLL:", diceRoll); return diceRoll; } - - private static addDamage(damage:number, characteristic:CharacteristicType):number { - let handledDamage = 0; - if (damage + characteristic.damage > characteristic.value) { - handledDamage = characteristic.value - characteristic.damage; - characteristic.damage = characteristic.value; - } else if (damage > 0) { - handledDamage = damage; - characteristic.damage += damage; - } - characteristic.current = characteristic.value - characteristic.damage; - characteristic.mod = calcModFor(characteristic.current); - return damage - handledDamage; - } - - async updateActor():Promise { - const updateData = {}; - const characteristics = this.data.data.characteristics; - - for (const cha of Object.values(characteristics as Record)) { - cha.current = cha.value - cha.damage; - cha.mod = calcModFor(cha.current); - updateData[`data.characteristics.${cha.key}.current`] = cha.current; - updateData[`data.characteristics.${cha.key}.damage`] = cha.damage; - } - - this.data.data.hits.value = characteristics["endurance"].current + characteristics["strength"].current + characteristics["dexterity"].current; - this.data.data.hits.max = characteristics["endurance"].value + characteristics["strength"].value + characteristics["dexterity"].value; - updateData['data.hits.value'] = this.data.data.hits.value; - updateData['data.hits.max'] = this.data.data.hits.max; - await this.update(updateData); - } } diff --git a/src/module/hooks/index.ts b/src/module/hooks/index.ts index 69662140b..394ef0940 100644 --- a/src/module/hooks/index.ts +++ b/src/module/hooks/index.ts @@ -4,4 +4,5 @@ import './ready.ts'; import './renderChatMessage.ts'; import './renderItemSheet.ts'; import './renderSettingsConfig.ts'; +import './updateHits.ts'; import './setup.ts'; diff --git a/src/module/hooks/updateHits.ts b/src/module/hooks/updateHits.ts new file mode 100644 index 000000000..118cb305f --- /dev/null +++ b/src/module/hooks/updateHits.ts @@ -0,0 +1,33 @@ +import TwodsixActor from "../entities/TwodsixActor"; +import { mergeDeep } from "../utils/utils"; + +function getCurrentHits(target: Record, ...args: Record[]) { + const characteristics = mergeDeep(target, ...args); + const hitsCharacteristics = ["strength", "dexterity", "endurance"]; + + return Object.entries(characteristics).reduce((hits, [key, chr]) => { + if (hitsCharacteristics.includes(key)) { + hits.value += chr.value-chr.damage; + hits.max += chr.value; + } + return hits; + }, {value: 0, max: 0}); +} + +Hooks.on('preUpdateActor', async (actor:TwodsixActor, update:Record) => { + if (update.data?.characteristics) { + update.data.hits =getCurrentHits(actor.data.data.characteristics, update.data.characteristics); + } +}); + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +Hooks.on('preUpdateToken', async (scene, token:Record, update:Record) => { + if (update.actorData?.data?.characteristics) { + const actor = TwodsixActor.collection.get(token.actorId); + update.actorData.data.hits = getCurrentHits( + actor.data.data.characteristics, + token.actorData.data.characteristics, + update.actorData.data.characteristics + ); + } +}); diff --git a/src/module/sheets/TwodsixActorSheet.ts b/src/module/sheets/TwodsixActorSheet.ts index eb80be7ed..c6cbeb94a 100644 --- a/src/module/sheets/TwodsixActorSheet.ts +++ b/src/module/sheets/TwodsixActorSheet.ts @@ -1,8 +1,6 @@ import {AbstractTwodsixActorSheet} from "./AbstractTwodsixActorSheet"; -import {calcModFor} from "../utils/sheetUtils"; import {TWODSIX} from "../config"; import TwodsixItem from "../entities/TwodsixItem"; -import {CharacteristicType} from "../../types/twodsix"; export class TwodsixActorSheet extends AbstractTwodsixActorSheet { @@ -61,26 +59,8 @@ export class TwodsixActorSheet extends AbstractTwodsixActorSheet { html.find('.roll-damage').on('click', (this._onRollDamage.bind(this))); - html.find('.stat-damage').on('change', this._setDamageFromEvent.bind(this)); - html.find('.special-damage').on('change', this._setDamageFromEvent.bind(this)); } - private async _setDamageFromEvent(event:Event):Promise { - const eventTargets = $(event.currentTarget); - const characteristicKey = eventTargets.parents('.stat:first,.special:first').attr('data-characteristic'); - const characteristic:CharacteristicType = this.actor.data.data.characteristics[characteristicKey]; - let damage = Number(eventTargets.children("").val()); - if (damage > characteristic.value) { - damage = characteristic.value; - } else if (damage < 0) { - damage = 0; - } - eventTargets.children("").val(damage); - characteristic.damage = damage; - characteristic.current = characteristic.value - characteristic.damage; - characteristic.mod = calcModFor(characteristic.current); - await this.actor.updateActor(); - } private getItem(event:Event):TwodsixItem { const itemId = $(event.currentTarget).parents('.item').data('item-id'); diff --git a/src/module/utils/utils.ts b/src/module/utils/utils.ts new file mode 100644 index 000000000..a637ffa9c --- /dev/null +++ b/src/module/utils/utils.ts @@ -0,0 +1,36 @@ +// https://stackoverflow.com/a/34749873 +/** + * Simple object check. + * @param item + * @returns {boolean} + */ +export function isObject(item: unknown):boolean { + return (item && typeof item === 'object' && !Array.isArray(item)); +} + +/** + * Deep merge two objects. + * @param target + * @param ...sources + */ +export function mergeDeep(target:Record, ...sources:Record[]):Record { + if (!sources.length) { + return target; + } + const source = sources.shift(); + + if (isObject(target) && isObject(source)) { + for (const key in source) { + if (isObject(source[key])) { + if (!target[key]) { + Object.assign(target, { [key]: {} }); + } + mergeDeep(target[key], source[key]); + } else { + Object.assign(target, { [key]: source[key] }); + } + } + } + + return mergeDeep(target, ...sources); +}