2022-05-16 02:19:31 +02:00
|
|
|
// SPDX-FileCopyrightText: 2022 Johannes Loher
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
2022-05-16 02:08:27 +02:00
|
|
|
import { packageId } from '../constants';
|
|
|
|
|
|
|
|
import type { TickwerkCombatant } from '../data/documents/combatant';
|
|
|
|
|
|
|
|
export const registerDS4SpecificFunctionality = () => {
|
|
|
|
if (CONFIG.tickwerk === undefined) CONFIG.tickwerk = {};
|
2022-05-16 03:46:53 +02:00
|
|
|
foundry.utils.mergeObject(CONFIG.tickwerk, { getTiebreaker, getInitiativeFormula });
|
2022-05-16 02:08:27 +02:00
|
|
|
};
|
|
|
|
|
2022-05-16 03:46:53 +02:00
|
|
|
const getTiebreaker = async (combatant: TickwerkCombatant, combatants: TickwerkCombatant[]): Promise<number> => {
|
2022-05-18 23:46:48 +02:00
|
|
|
const ds4combatant = combatant as DS4TickwerkCombatant;
|
|
|
|
const ds4combatants = combatants as DS4TickwerkCombatant[];
|
2022-05-16 02:08:27 +02:00
|
|
|
if (combatants.length === 0) return 0;
|
2022-05-18 23:46:48 +02:00
|
|
|
|
|
|
|
const lowerBounds: number[] = [];
|
|
|
|
const upperBounds: number[] = [];
|
|
|
|
const equals: number[] = [];
|
|
|
|
|
|
|
|
for (const combatant of ds4combatants) {
|
|
|
|
const tiebreaker = combatant._newTiebreaker ?? combatant.getFlag(packageId, 'tiebreaker') ?? 0;
|
2022-05-19 00:28:55 +02:00
|
|
|
if (getInitiative(combatant) > getInitiative(ds4combatant)) {
|
2022-05-18 23:46:48 +02:00
|
|
|
lowerBounds.push(tiebreaker);
|
2022-05-19 00:28:55 +02:00
|
|
|
} else if (getInitiative(combatant) < getInitiative(ds4combatant)) {
|
2022-05-18 23:46:48 +02:00
|
|
|
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);
|
|
|
|
}
|
2022-05-16 02:08:27 +02:00
|
|
|
});
|
2022-05-18 23:46:48 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2022-05-16 02:08:27 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const getInitiativeFormula = (combatant: TickwerkCombatant) => {
|
|
|
|
const started = combatant.combat?.started ?? false;
|
|
|
|
if (!started) return '-@combatValues.initiative.total';
|
|
|
|
const tickValue = combatant.combat?.round ?? 0;
|
|
|
|
return `max(${tickValue} + 10 - @combatValues.initiative.total, ${tickValue})`;
|
|
|
|
};
|
2022-05-18 23:46:48 +02:00
|
|
|
|
|
|
|
type DS4TickwerkCombatant = TickwerkCombatant & { actor: (Actor & { data: { data: ActorData } }) | null };
|
|
|
|
|
2022-05-19 00:28:55 +02:00
|
|
|
const getInitiative = (combatant: DS4TickwerkCombatant): number => {
|
|
|
|
return combatant.actor?.data.data.combatValues.initiative.total ?? -Infinity;
|
|
|
|
};
|
|
|
|
|
2022-05-18 23:46:48 +02:00
|
|
|
interface ActorData {
|
|
|
|
combatValues: {
|
|
|
|
initiative: {
|
|
|
|
total: number;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|