refactor: cleanup
This commit is contained in:
parent
ddcbcffe4c
commit
2d9e418ba7
9 changed files with 118 additions and 79 deletions
|
@ -4,5 +4,8 @@
|
|||
"TICKWERK.Tick": "Tick",
|
||||
"TICKWERK.Wait": "Abwarten",
|
||||
"TICKWERK.Waiting": "Abwarten",
|
||||
"TICKWERK.WarningCannotAdvanceWhileWaiting": "Während des Abwartens ist es nicht möglich, auf der Tickleiste vorzurücken.",
|
||||
"TICKWERK.WarningCannotAdvanceWithoutStartedCombat": "Solange der Kampf nicht gestartet ist es nicht möglich, auf der Tickleiste vorzurücken.",
|
||||
"TICKWERK.WarningCannotAdvanceWithoutTickValue": "Ohne Tickwert ist es nicht möglich, auf der Tickleiste vorzurücken.",
|
||||
"TICKWERK.WarningCannotStartCombat": "Der Kampf kann nur begonnen werden, wenn mindestens ein Kampfteilnehmer einen Tickwert hat."
|
||||
}
|
||||
|
|
|
@ -4,5 +4,8 @@
|
|||
"TICKWERK.Tick": "Tick",
|
||||
"TICKWERK.Wait": "Wait",
|
||||
"TICKWERK.Waiting": "Waiting",
|
||||
"TICKWERK.WarningCannotAdvanceWhileWaiting": "Cannot advance while waiting.",
|
||||
"TICKWERK.WarningCannotAdvanceWithoutStartedCombat": "Cannot advance without the combat being started.",
|
||||
"TICKWERK.WarningCannotAdvanceWithoutTickValue": "Cannot advance without having a tick value.",
|
||||
"TICKWERK.WarningCannotStartCombat": "In order to start the combat, there needs to be at least one combatant with a tick value."
|
||||
}
|
||||
|
|
|
@ -21,11 +21,16 @@ const CombatTrackerMixin = (BaseCombatTracker: typeof CombatTracker) => {
|
|||
turns: data.turns.map((turn) => ({ ...turn, waiting: this.viewed?.combatants.get(turn.id)?.waiting })),
|
||||
} as CombatTracker.Data; // TODO: Improve upstream types
|
||||
}
|
||||
|
||||
override activateListeners(html: JQuery): void {
|
||||
super.activateListeners(html);
|
||||
html.find('.combatant-control[data-control="toggleWaiting"]').on('click', this._onToggleWaiting.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle clicks on the Combatant waiting control button.
|
||||
* @param event The originating click event
|
||||
*/
|
||||
_onToggleWaiting(event: JQuery.ClickEvent) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
|
|
@ -15,9 +15,12 @@ const onActiveEffectChanged = (activeEffect: ActiveEffect) => {
|
|||
const parent = activeEffect.parent;
|
||||
const actorId = parent?.id;
|
||||
if (!(parent instanceof Actor) || actorId === null || actorId === undefined) return;
|
||||
|
||||
const statusId = activeEffect.getFlag('core', 'statusId');
|
||||
|
||||
if (statusId === CONFIG.Combat.defeatedStatusId) {
|
||||
const relevantCombats = game.combats?.filter((combat) => combat.getCombatantByActor(actorId) !== undefined) ?? [];
|
||||
|
||||
for (const combat of relevantCombats) {
|
||||
combat.setupTurns();
|
||||
if (combat === game.combat) {
|
||||
|
|
|
@ -29,10 +29,9 @@ const CombatMixin = (BaseCombat: typeof Combat) => {
|
|||
return 0;
|
||||
}
|
||||
|
||||
override async nextRound(): Promise<never> {
|
||||
throw new Error('Not implemented!');
|
||||
}
|
||||
|
||||
/**
|
||||
* The current tick value of the Combat encounter.
|
||||
*/
|
||||
get tickValue(): number {
|
||||
const tickValues = this.combatants
|
||||
.filter((combatant) => !combatant.isDefeated)
|
||||
|
@ -42,11 +41,15 @@ const CombatMixin = (BaseCombat: typeof Combat) => {
|
|||
return tickValue === Infinity ? 0 : tickValue;
|
||||
}
|
||||
|
||||
override async nextRound(): Promise<never> {
|
||||
throw new Error('Not implemented!');
|
||||
}
|
||||
|
||||
override async nextTurn() {
|
||||
const game = getGame();
|
||||
|
||||
const combatant = this.combatant;
|
||||
if (combatant === undefined || combatant.initiative === null || combatant.id === null) {
|
||||
if (combatant === undefined || combatant.id === null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -62,10 +65,18 @@ const CombatMixin = (BaseCombat: typeof Combat) => {
|
|||
});
|
||||
|
||||
if (ticks !== undefined && ticks !== null) {
|
||||
await combatant.update({ initiative: combatant.initiative + ticks });
|
||||
const advanceTime = ticks * CONFIG.time.roundTime;
|
||||
return this.update(undefined, { diff: false, advanceTime } as DocumentModificationContext); // TODO: improve upstream types to allow this without type assertion
|
||||
await combatant.advanceTicks(ticks);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
override previousRound(): Promise<never> {
|
||||
throw new Error('Not implemented!');
|
||||
}
|
||||
|
||||
override previousTurn(): Promise<never> {
|
||||
throw new Error('Not implemented!');
|
||||
}
|
||||
|
||||
override async resetAll() {
|
||||
|
@ -118,8 +129,8 @@ const CombatMixin = (BaseCombat: typeof Combat) => {
|
|||
const ci = ia - ib;
|
||||
if (ci !== 0) return ci;
|
||||
|
||||
const tba = a.getFlag(packageId, 'tieBreaker') ?? 0;
|
||||
const tbb = b.getFlag(packageId, 'tieBreaker') ?? 0;
|
||||
const tba = a.getFlag(packageId, 'tiebreaker') ?? 0;
|
||||
const tbb = b.getFlag(packageId, 'tiebreaker') ?? 0;
|
||||
const ctb = tba - tbb;
|
||||
if (ctb !== 0) return ctb;
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ const CombatantMixin = (BaseCombatant: typeof Combatant) => {
|
|||
_newInitiative: number | null | undefined;
|
||||
|
||||
/**
|
||||
* An temporary property to make changes to the tieBreaker available to other instances in their `_pre…` methods.
|
||||
* An temporary property to make changes to the tiebreaker available to other instances in their `_pre…` methods.
|
||||
*/
|
||||
_newTieBreaker: number | undefined;
|
||||
_newTiebreaker: number | undefined;
|
||||
|
||||
/***
|
||||
* Is this combatant currently waiting?
|
||||
|
@ -28,31 +28,45 @@ const CombatantMixin = (BaseCombatant: typeof Combatant) => {
|
|||
return this.getFlag(packageId, 'waiting') ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the waiting state of this combatant.
|
||||
*/
|
||||
toggleWaiting(): Promise<this | undefined> {
|
||||
return this.update({ [`flags.${packageId}.waiting`]: !this.waiting, initiative: this.parent?.round });
|
||||
const update: Record<string, unknown> = { [`flags.${packageId}.waiting`]: !this.waiting };
|
||||
if (this.parent?.started && this.waiting) update.initiative = this.parent?.round;
|
||||
return this.update(update);
|
||||
}
|
||||
|
||||
protected override async _preCreate(...args: Parameters<Combatant['_preCreate']>): Promise<void> {
|
||||
await super._preCreate(...args);
|
||||
await this.#updateTieBreakerData(args[0]);
|
||||
/**
|
||||
* Advance for the given number of ticks.
|
||||
* @param ticks The number of ticks to advance for
|
||||
*/
|
||||
async advanceTicks(ticks: number): Promise<void> {
|
||||
if (this.initiative === null) {
|
||||
ui.notifications?.warn('TICKWERK.WarningCannotAdvanceWithoutTickValue', { localize: true });
|
||||
return;
|
||||
}
|
||||
if (this.waiting) {
|
||||
ui.notifications?.warn('TICKWERK.WarningCannotAdvanceWhileWaiting', { localize: true });
|
||||
return;
|
||||
}
|
||||
if (!this.combat?.started) {
|
||||
ui.notifications?.warn('TICKWERK.WarningCannotAdvanceWithoutStartedCombat', { localize: true });
|
||||
return;
|
||||
}
|
||||
|
||||
await this.update({ initiative: this.initiative + ticks });
|
||||
const advanceTime = ticks * CONFIG.time.roundTime;
|
||||
if (advanceTime !== 0) {
|
||||
await this.combat?.update(undefined, { diff: false, advanceTime } as DocumentModificationContext);
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
/**
|
||||
* Update tiebreaker data for a given creation or update.
|
||||
* @param data The data of the creation / update
|
||||
*/
|
||||
async #updateTiebreakerData(data: DeepPartial<CombatantDataConstructorData>): Promise<void> {
|
||||
if ('initiative' in data) {
|
||||
const combatantsWithSameTickValue =
|
||||
this.parent?.combatants.filter((combatant) => {
|
||||
|
@ -60,16 +74,21 @@ const CombatantMixin = (BaseCombatant: typeof Combatant) => {
|
|||
combatant._newInitiative !== undefined ? combatant._newInitiative : combatant.initiative;
|
||||
return otherInitiative === data.initiative;
|
||||
}) ?? [];
|
||||
const tieBreaker = await this.#getTieBreaker(combatantsWithSameTickValue);
|
||||
setProperty(data, `flags.${packageId}.tieBreaker`, tieBreaker);
|
||||
const tiebreaker = await this.#getTiebreaker(combatantsWithSameTickValue);
|
||||
setProperty(data, `flags.${packageId}.tiebreaker`, tiebreaker);
|
||||
this._newInitiative = data.initiative;
|
||||
this._newTieBreaker = tieBreaker;
|
||||
this._newTiebreaker = tiebreaker;
|
||||
}
|
||||
}
|
||||
|
||||
async #getTieBreaker(combatants: TickwerkCombatant[]): Promise<number> {
|
||||
const getTieBreaker = CONFIG.tickwerk?.getTieBreaker ?? defaultGetTieBreaker;
|
||||
return getTieBreaker(this, combatants);
|
||||
/**
|
||||
* Get a tiebreaker between this combatant and the given other combatants.
|
||||
* @param combatants The other combatants among which to find a tiebreaker
|
||||
* @returns A promise that resolves to the tiebreaker
|
||||
*/
|
||||
async #getTiebreaker(combatants: TickwerkCombatant[]): Promise<number> {
|
||||
const getTiebreaker = CONFIG.tickwerk?.getTiebreaker ?? defaultGetTiebreaker;
|
||||
return getTiebreaker(this, combatants);
|
||||
}
|
||||
|
||||
protected override _getInitiativeFormula(): string {
|
||||
|
@ -77,19 +96,39 @@ const CombatantMixin = (BaseCombatant: typeof Combatant) => {
|
|||
if (getInitiativeFormula) return getInitiativeFormula(this);
|
||||
return super._getInitiativeFormula();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const defaultGetTieBreaker = async (combatant: TickwerkCombatant, combatants: TickwerkCombatant[]): Promise<number> => {
|
||||
const defaultGetTiebreaker = async (combatant: TickwerkCombatant, combatants: TickwerkCombatant[]): Promise<number> => {
|
||||
if (combatants.length === 0) return 0;
|
||||
const tieBreakers = combatants.map((combatant) => {
|
||||
const tiebreakers = combatants.map((combatant) => {
|
||||
return (
|
||||
(combatant._newTieBreaker !== undefined
|
||||
? combatant._newTieBreaker
|
||||
: combatant.getFlag(packageId, 'tieBreaker')) ?? 0
|
||||
(combatant._newTiebreaker !== undefined
|
||||
? combatant._newTiebreaker
|
||||
: combatant.getFlag(packageId, 'tiebreaker')) ?? 0
|
||||
);
|
||||
});
|
||||
return Math.max(...tieBreakers) + 1;
|
||||
return Math.max(...tiebreakers) + 1;
|
||||
};
|
||||
|
||||
export type TickwerkCombatantConstructor = ReturnType<typeof CombatantMixin>;
|
||||
|
@ -99,7 +138,7 @@ declare global {
|
|||
interface FlagConfig {
|
||||
Combatant: {
|
||||
tickwerk: {
|
||||
tieBreaker?: number | undefined;
|
||||
tiebreaker?: number | undefined;
|
||||
waiting?: boolean | undefined;
|
||||
};
|
||||
};
|
||||
|
@ -111,7 +150,7 @@ declare global {
|
|||
|
||||
interface CONFIG {
|
||||
tickwerk?: {
|
||||
getTieBreaker?: (combatant: TickwerkCombatant, combatants: TickwerkCombatant[]) => Promise<number>;
|
||||
getTiebreaker?: (combatant: TickwerkCombatant, combatants: TickwerkCombatant[]) => Promise<number>;
|
||||
getInitiativeFormula?: (combatant: TickwerkCombatant) => string;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { packageId } from './constants';
|
||||
|
||||
const loggingContext = packageId;
|
||||
const loggingSeparator = '|';
|
||||
|
||||
type LogLevel = 'debug' | 'info' | 'warning' | 'error';
|
||||
type LoggingFunction = (...data: unknown[]) => void;
|
||||
|
||||
const getLoggingFunction = (type: LogLevel = 'info'): LoggingFunction => {
|
||||
const log = { debug: console.debug, info: console.info, warning: console.warn, error: console.error }[type];
|
||||
return (...data: unknown[]) => log(loggingContext, loggingSeparator, ...data);
|
||||
};
|
||||
|
||||
const logger = Object.freeze({
|
||||
debug: getLoggingFunction('debug'),
|
||||
info: getLoggingFunction('info'),
|
||||
warn: getLoggingFunction('warning'),
|
||||
error: getLoggingFunction('error'),
|
||||
getLoggingFunction,
|
||||
});
|
||||
|
||||
export default logger;
|
|
@ -8,19 +8,19 @@ import type { TickwerkCombatant } from '../data/documents/combatant';
|
|||
|
||||
export const registerDS4SpecificFunctionality = () => {
|
||||
if (CONFIG.tickwerk === undefined) CONFIG.tickwerk = {};
|
||||
foundry.utils.mergeObject(CONFIG.tickwerk, { getTieBreaker, getInitiativeFormula });
|
||||
foundry.utils.mergeObject(CONFIG.tickwerk, { getTiebreaker, getInitiativeFormula });
|
||||
};
|
||||
|
||||
const getTieBreaker = async (combatant: TickwerkCombatant, combatants: TickwerkCombatant[]): Promise<number> => {
|
||||
const getTiebreaker = async (combatant: TickwerkCombatant, combatants: TickwerkCombatant[]): Promise<number> => {
|
||||
if (combatants.length === 0) return 0;
|
||||
const tieBreakers = combatants.map((combatant) => {
|
||||
const tiebreakers = combatants.map((combatant) => {
|
||||
return (
|
||||
(combatant._newTieBreaker !== undefined
|
||||
? combatant._newTieBreaker
|
||||
: combatant.getFlag(packageId, 'tieBreaker')) ?? 0
|
||||
(combatant._newTiebreaker !== undefined
|
||||
? combatant._newTiebreaker
|
||||
: combatant.getFlag(packageId, 'tiebreaker')) ?? 0
|
||||
);
|
||||
});
|
||||
return Math.max(...tieBreakers) + 1;
|
||||
return Math.max(...tiebreakers) + 1;
|
||||
};
|
||||
|
||||
const getInitiativeFormula = (combatant: TickwerkCombatant) => {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{{!--
|
||||
SPDX-FileCopyrightText: 2022 Foundry Gaming LLC.
|
||||
SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
|
||||
SPDX-License-Identifier: MIT
|
||||
|
|
Loading…
Reference in a new issue