From 54ea76141b77532831f70d02d5955e6cc9ba599c Mon Sep 17 00:00:00 2001 From: "JORDI.ALONSO" Date: Mon, 30 May 2022 13:39:26 +0200 Subject: [PATCH] #126: Pass multiple targets to combat manager (WIP) --- .../ws-combat/gm/WSGMCombatManager.ts | 76 ++++++++++--------- .../user/WSUserCombatMessageTypes.ts | 2 +- .../ws-combat/util/getTargetToken.ts | 22 +++--- .../dialogs/combat/CombatAttackDialog.ts | 6 +- src/module/dialogs/combat/GMCombatDialog.ts | 52 +++++++------ 5 files changed, 84 insertions(+), 74 deletions(-) diff --git a/src/module/combat/websocket/ws-combat/gm/WSGMCombatManager.ts b/src/module/combat/websocket/ws-combat/gm/WSGMCombatManager.ts index 1bdd356c..ba011010 100644 --- a/src/module/combat/websocket/ws-combat/gm/WSGMCombatManager.ts +++ b/src/module/combat/websocket/ws-combat/gm/WSGMCombatManager.ts @@ -131,18 +131,18 @@ export class WSGMCombatManager extends WSCombatManager { - if (selectedToken?.id && targetToken?.id) { - this.combat = this.createNewCombat(selectedToken!, targetToken); + if (selectedToken?.id && targetTokens?.every(t=> { return t?.id })) { + this.combat = this.createNewCombat(selectedToken!, targetTokens); - this.manageAttack(selectedToken!, targetToken); + this.manageAttack(selectedToken!, targetTokens); } } } @@ -167,7 +167,7 @@ export class WSGMCombatManager extends WSCombatManager { return this.findTokenById(id) }); if (!attacker || !defender) { Log.warn('Can not handle user attack request due attacker or defender actor do not exist'); @@ -176,7 +176,7 @@ export class WSGMCombatManager extends WSCombatManager) { + return new GMCombatDialog(attacker, defenders, { onClose: () => { this.endCombat(); }, - onCounterAttack: bonus => { + onCounterAttack: (defender, bonus) => { this.endCombat(); this.combat = new GMCombatDialog( defender, - attacker, + [attacker], { onClose: () => { this.endCombat(); @@ -233,46 +233,48 @@ export class WSGMCombatManager extends WSCombatManager, bonus?: number) { this.attackDialog = new CombatAttackDialog( attacker, - defender, + defenders, { onAttack: result => { - this.attackDialog?.close({ force: true }); + defenders.forEach(defender=> { + this.attackDialog?.close({ force: true }); - this.attackDialog = undefined; + this.attackDialog = undefined; - if (this.combat) { - this.combat.updateAttackerData(result); - - if (canOwnerReceiveMessage(defender.actor!)) { - const newMsg: GMAttackMessage = { - type: GMMessageTypes.Attack, - payload: { attackerTokenId: attacker.id!, defenderTokenId: defender.id!, result } - }; - - this.emit(newMsg); - } else { - const { critic } = result.values; - - try { - this.manageDefense(attacker, defender, result.type, critic); - } catch (err) { - if (err) { - Log.error(err); - } + if (this.combat) { + this.combat.updateAttackerData(result); + + if (canOwnerReceiveMessage(defender.actor!)) { + const newMsg: GMAttackMessage = { + type: GMMessageTypes.Attack, + payload: { attackerTokenId: attacker.id!, defenderTokenId: defender.id!, result } + }; + + this.emit(newMsg); + } else { + const { critic } = result.values; - this.endCombat(); + try { + this.manageDefense(attacker, defender, result.type, critic); + } catch (err) { + if (err) { + Log.error(err); + } + + this.endCombat(); + } } } - } + }); } }, { counterAttackBonus: bonus } diff --git a/src/module/combat/websocket/ws-combat/user/WSUserCombatMessageTypes.ts b/src/module/combat/websocket/ws-combat/user/WSUserCombatMessageTypes.ts index d7c1b117..4288d9ab 100644 --- a/src/module/combat/websocket/ws-combat/user/WSUserCombatMessageTypes.ts +++ b/src/module/combat/websocket/ws-combat/user/WSUserCombatMessageTypes.ts @@ -13,7 +13,7 @@ export type UserRequestToAttackMessage = { senderId: string; payload: { attackerTokenId: string; - defenderTokenId: string; + defenderTokenId: Array; }; }; diff --git a/src/module/combat/websocket/ws-combat/util/getTargetToken.ts b/src/module/combat/websocket/ws-combat/util/getTargetToken.ts index e24a63f9..ae4fc994 100644 --- a/src/module/combat/websocket/ws-combat/util/getTargetToken.ts +++ b/src/module/combat/websocket/ws-combat/util/getTargetToken.ts @@ -18,20 +18,22 @@ export const getTargetToken = (attackerToken: TokenDocument, targetTokens: UserT throw new Error(message); } - const target = targetTokens.values().next().value as TokenDocument; - - if (!target.actor?.id) { - message = tgame.i18n.localize('macros.combat.dialog.error.withoutActor.title'); - } - - if (target.id === attackerToken.id) { - message = tgame.i18n.localize('macros.combat.dialog.error.cannotAttackYourself.title'); - } + const resultTargets = new Array(); + targetTokens.forEach(target => { + if (!target.actor?.id) { + message = tgame.i18n.localize('macros.combat.dialog.error.withoutActor.title'); + } + + if (target.id === attackerToken.id) { + message = tgame.i18n.localize('macros.combat.dialog.error.cannotAttackYourself.title'); + } + resultTargets.push(target.document); + }); if (message) { ABFDialogs.prompt(message); throw new Error(message); } - return target; + return resultTargets; }; diff --git a/src/module/dialogs/combat/CombatAttackDialog.ts b/src/module/dialogs/combat/CombatAttackDialog.ts index 8a3484f3..34477d61 100644 --- a/src/module/dialogs/combat/CombatAttackDialog.ts +++ b/src/module/dialogs/combat/CombatAttackDialog.ts @@ -179,14 +179,14 @@ export class CombatAttackDialog extends FormApplication, private hooks: { onAttack: (attackValues: UserCombatAttackResult) => void; }, options: { allowed?: boolean; counterAttackBonus?: number } = {} ) { - super(getInitialData(attacker, defender, options)); - + super(getInitialData(attacker, defenders[0], options)); + let defender = defenders[0]; this.data = getInitialData(attacker, defender, options); const weapons = this.attackerActor.data.data.combat.weapons as WeaponDataSource[]; diff --git a/src/module/dialogs/combat/GMCombatDialog.ts b/src/module/dialogs/combat/GMCombatDialog.ts index 56e9cc96..549a6181 100644 --- a/src/module/dialogs/combat/GMCombatDialog.ts +++ b/src/module/dialogs/combat/GMCombatDialog.ts @@ -15,6 +15,17 @@ export type GMCombatAttackResult = UserCombatAttackResult & { power?: PsychicPowerDataSource; }; +type GMCombatDefenderData = { + actor: ABFActor; + token: TokenDocument; + isReady: boolean; + customModifier: number; + result?: UserCombatDefenseResult & { + spell?: SpellDataSource; + power?: PsychicPowerDataSource; + }; + }; + type GMCombatDialogData = { ui: { isCounter: boolean; @@ -27,16 +38,8 @@ type GMCombatDialogData = { counterAttackBonus?: number; result?: GMCombatAttackResult; }; - defender: { - actor: ABFActor; - token: TokenDocument; - isReady: boolean; - customModifier: number; - result?: UserCombatDefenseResult & { - spell?: SpellDataSource; - power?: PsychicPowerDataSource; - }; - }; + defender: GMCombatDefenderData; + listDefenders: Array; calculations?: | { winner: TokenDocument; @@ -54,11 +57,18 @@ type GMCombatDialogData = { const getInitialData = ( attacker: TokenDocument, - defender: TokenDocument, + defenders: Array, options: { isCounter?: boolean; counterAttackBonus?: number } = {} ): GMCombatDialogData => { const attackerActor = attacker.actor!; - const defenderActor = defender.actor!; + const defend = defenders.map(defender=> { + return { + token: defender, + actor: defender.actor!, + customModifier: 0, + isReady: false + }; + }) return { ui: { @@ -71,12 +81,8 @@ const getInitialData = ( counterAttackBonus: options.counterAttackBonus, isReady: false }, - defender: { - token: defender, - actor: defenderActor, - customModifier: 0, - isReady: false - } + defender: defend[0], + listDefenders: defend }; }; @@ -85,16 +91,16 @@ export class GMCombatDialog extends FormApplication, private hooks: { onClose: () => Promise | void; - onCounterAttack: (bonus: number) => Promise | void; + onCounterAttack: (defender: TokenDocument, bonus: number) => Promise | void; }, options: { isCounter?: boolean; counterAttackBonus?: number } = {} ) { - super(getInitialData(attacker, defender, options)); + super(getInitialData(attacker, defenders, options)); - this.data = getInitialData(attacker, defender, options); + this.data = getInitialData(attacker, defenders, options); this.render(true); } @@ -146,7 +152,7 @@ export class GMCombatDialog extends FormApplication