From 2e9c56cc2b4b036d2955c80193e34e3e04022984 Mon Sep 17 00:00:00 2001 From: Johannes Loher Date: Wed, 18 May 2022 23:46:48 +0200 Subject: [PATCH] feat: add ds4 specific tiebreaker functionality --- src/data/documents/combat.ts | 9 ++++- src/data/documents/combatant.ts | 6 ++- src/systems/ds4.ts | 66 +++++++++++++++++++++++++++++---- 3 files changed, 71 insertions(+), 10 deletions(-) diff --git a/src/data/documents/combat.ts b/src/data/documents/combat.ts index 699f407..1322917 100644 --- a/src/data/documents/combat.ts +++ b/src/data/documents/combat.ts @@ -84,7 +84,14 @@ const CombatMixin = (BaseCombat: typeof Combat) => { c.data.update({ initiative: null }); } return this.update( - { turn: 0, combatants: this.combatants.toObject(), flags: { [packageId]: { started: false } } }, + { + turn: 0, + combatants: this.combatants.toObject().map((combatant) => { + if (combatant.flags.tickwerk.tiebreaker) delete combatant.flags.tickwerk.tiebreaker; + return { ...combatant, [`flags.${packageId}.-=tiebreaker`]: null }; + }), + flags: { [packageId]: { started: false } }, + }, { diff: false }, ); } diff --git a/src/data/documents/combatant.ts b/src/data/documents/combatant.ts index 4672951..f38305d 100644 --- a/src/data/documents/combatant.ts +++ b/src/data/documents/combatant.ts @@ -107,12 +107,14 @@ const CombatantMixin = (BaseCombatant: typeof Combatant) => { await this.#updateTiebreakerData(args[0]); } - protected override _onCreate(): void { + protected override _onCreate(...args: Parameters): void { + super._onCreate(...args); this._newInitiative = undefined; this._newTiebreaker = undefined; } - protected override _onUpdate(): void { + protected override _onUpdate(...args: Parameters): void { + super._onUpdate(...args); this._newInitiative = undefined; this._newTiebreaker = undefined; } diff --git a/src/systems/ds4.ts b/src/systems/ds4.ts index 0667c5d..7dcbcb5 100644 --- a/src/systems/ds4.ts +++ b/src/systems/ds4.ts @@ -12,15 +12,57 @@ export const registerDS4SpecificFunctionality = () => { }; const getTiebreaker = async (combatant: TickwerkCombatant, combatants: TickwerkCombatant[]): Promise => { + const ds4combatant = combatant as DS4TickwerkCombatant; + const ds4combatants = combatants as DS4TickwerkCombatant[]; if (combatants.length === 0) return 0; - const tiebreakers = combatants.map((combatant) => { - return ( - (combatant._newTiebreaker !== undefined - ? combatant._newTiebreaker - : combatant.getFlag(packageId, 'tiebreaker')) ?? 0 - ); + + const lowerBounds: number[] = []; + const upperBounds: number[] = []; + const equals: number[] = []; + + for (const combatant of ds4combatants) { + const tiebreaker = combatant._newTiebreaker ?? combatant.getFlag(packageId, 'tiebreaker') ?? 0; + if ( + (combatant.actor?.data.data.combatValues.initiative.total ?? -Infinity) > + (ds4combatant.actor?.data.data.combatValues.initiative.total ?? -Infinity) + ) { + lowerBounds.push(tiebreaker); + } else if ( + (combatant.actor?.data.data.combatValues.initiative.total ?? -Infinity) < + (ds4combatant.actor?.data.data.combatValues.initiative.total ?? -Infinity) + ) { + upperBounds.push(tiebreaker); + } else { + equals.push(tiebreaker); + } + } + + equals.sort(); + const positionAmongEquals = Math.floor(twist.random() * (equals.length + 1)); + + equals.forEach((equal, index) => { + if (index < positionAmongEquals) { + lowerBounds.push(equal); + } else { + upperBounds.push(equal); + } }); - return Math.max(...tiebreakers) + 1; + const lowerBound = Math.max(...lowerBounds); + const upperBound = Math.min(...upperBounds); + + if (lowerBound === -Infinity) { + if (upperBound === Infinity) { + return 0; + } else { + return upperBound - 1; + } + } else { + if (upperBound === Infinity) { + return lowerBound + 1; + } else { + return (lowerBound + upperBound) / 2; + } + } }; const getInitiativeFormula = (combatant: TickwerkCombatant) => { @@ -29,3 +71,13 @@ const getInitiativeFormula = (combatant: TickwerkCombatant) => { const tickValue = combatant.combat?.round ?? 0; return `max(${tickValue} + 10 - @combatValues.initiative.total, ${tickValue})`; }; + +type DS4TickwerkCombatant = TickwerkCombatant & { actor: (Actor & { data: { data: ActorData } }) | null }; + +interface ActorData { + combatValues: { + initiative: { + total: number; + }; + }; +}