119 lines
4.0 KiB
TypeScript
119 lines
4.0 KiB
TypeScript
// SPDX-FileCopyrightText: 2022 Johannes Loher
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import type { CombatantDataConstructorData } from '@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs/combatantData';
|
|
import { packageId } from '../../constants';
|
|
|
|
export const registerCombatantFunctionality = () => {
|
|
CONFIG.Combatant.documentClass = CombatantMixin(CONFIG.Combatant.documentClass);
|
|
};
|
|
|
|
const CombatantMixin = (BaseCombatant: typeof Combatant) => {
|
|
return class TickwerkCombatant extends BaseCombatant {
|
|
/**
|
|
* An temporary property to make changes to the initiative available to other instances in their `_pre…` methods.
|
|
*/
|
|
_newInitiative: number | null | undefined;
|
|
|
|
/**
|
|
* An temporary property to make changes to the tieBreaker available to other instances in their `_pre…` methods.
|
|
*/
|
|
_newTieBreaker: number | undefined;
|
|
|
|
/***
|
|
* Is this combatant currently waiting?
|
|
*/
|
|
get waiting(): boolean {
|
|
return this.getFlag(packageId, 'waiting') ?? false;
|
|
}
|
|
|
|
toggleWaiting(): Promise<this | undefined> {
|
|
return this.update({ [`flags.${packageId}.waiting`]: !this.waiting, initiative: this.parent?.round });
|
|
}
|
|
|
|
protected override async _preCreate(...args: Parameters<Combatant['_preCreate']>): Promise<void> {
|
|
await super._preCreate(...args);
|
|
await this.#updateTieBreakerData(args[0]);
|
|
}
|
|
|
|
protected override async _preUpdate(...args: Parameters<Combatant['_preUpdate']>): Promise<void> {
|
|
await super._preUpdate(...args);
|
|
await this.#updateTieBreakerData(args[0]);
|
|
}
|
|
|
|
protected override _onCreate(): void {
|
|
this._newInitiative = undefined;
|
|
this._newTieBreaker = undefined;
|
|
}
|
|
|
|
protected override _onUpdate(): void {
|
|
this._newInitiative = undefined;
|
|
this._newTieBreaker = undefined;
|
|
}
|
|
|
|
async #updateTieBreakerData(data: DeepPartial<CombatantDataConstructorData>): Promise<void> {
|
|
if ('initiative' in data) {
|
|
const combatantsWithSameTickValue =
|
|
this.parent?.combatants.filter((combatant) => {
|
|
const otherInitiative =
|
|
combatant._newInitiative !== undefined ? combatant._newInitiative : combatant.initiative;
|
|
return otherInitiative === data.initiative;
|
|
}) ?? [];
|
|
const tieBreaker = await this.#getTieBreaker(combatantsWithSameTickValue);
|
|
setProperty(data, `flags.${packageId}.tieBreaker`, tieBreaker);
|
|
this._newInitiative = data.initiative;
|
|
this._newTieBreaker = tieBreaker;
|
|
}
|
|
}
|
|
|
|
async #getTieBreaker(combatants: TickwerkCombatant[]): Promise<number> {
|
|
const getTieBreaker = CONFIG.tickwerk?.getTieBreaker ?? defaultGetTieBreaker;
|
|
return getTieBreaker(this, combatants);
|
|
}
|
|
|
|
protected override _getInitiativeFormula(): string {
|
|
const getInitiativeFormula = CONFIG.tickwerk?.getInitiativeFormula;
|
|
if (getInitiativeFormula) return getInitiativeFormula(this);
|
|
return super._getInitiativeFormula();
|
|
}
|
|
};
|
|
};
|
|
|
|
const defaultGetTieBreaker = async (combatant: TickwerkCombatant, combatants: TickwerkCombatant[]): Promise<number> => {
|
|
if (combatants.length === 0) return 0;
|
|
const tieBreakers = combatants.map((combatant) => {
|
|
return (
|
|
(combatant._newTieBreaker !== undefined
|
|
? combatant._newTieBreaker
|
|
: combatant.getFlag(packageId, 'tieBreaker')) ?? 0
|
|
);
|
|
});
|
|
return Math.max(...tieBreakers) + 1;
|
|
};
|
|
|
|
export type TickwerkCombatantConstructor = ReturnType<typeof CombatantMixin>;
|
|
export type TickwerkCombatant = InstanceType<TickwerkCombatantConstructor>;
|
|
|
|
declare global {
|
|
interface FlagConfig {
|
|
Combatant: {
|
|
tickwerk: {
|
|
tieBreaker?: number | undefined;
|
|
waiting?: boolean | undefined;
|
|
};
|
|
};
|
|
}
|
|
|
|
interface DocumentClassConfig {
|
|
Combatant: TickwerkCombatantConstructor;
|
|
}
|
|
|
|
interface CONFIG {
|
|
tickwerk?: {
|
|
getTieBreaker?: (combatant: TickwerkCombatant, combatants: TickwerkCombatant[]) => Promise<number>;
|
|
getInitiativeFormula?: (combatant: TickwerkCombatant) => string;
|
|
};
|
|
}
|
|
}
|