tickwerk/src/data/documents/combat.ts

136 lines
3.7 KiB
TypeScript
Raw Normal View History

2022-05-16 02:08:27 +02:00
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { packageId } from '../../constants';
import type { TickwerkCombatant } from './combatant';
export const registerCombatFunctionality = () => {
CONFIG.Combat.documentClass = CombatMixin(CONFIG.Combat.documentClass);
};
const CombatMixin = (BaseCombat: typeof Combat) => {
return class TickwerkCombat extends BaseCombat {
override get combatant() {
return this.turns[0];
}
override get round() {
return this.tickValue;
}
override get started() {
return this.turns.length > 0 && (this.getFlag(packageId, 'started') ?? false);
}
override get turn() {
return 0;
}
2022-05-16 03:46:53 +02:00
/**
* The current tick value of the Combat encounter.
*/
2022-05-16 02:08:27 +02:00
get tickValue(): number {
const tickValues = this.combatants
.filter((combatant) => !combatant.isDefeated && !combatant.waiting)
2022-05-16 02:08:27 +02:00
.map((combatant) => combatant.initiative)
.filter((tickValue): tickValue is number => tickValue !== null);
const tickValue = Math.min(...tickValues);
return tickValue === Infinity ? 0 : tickValue;
}
2022-05-16 03:46:53 +02:00
override async nextRound(): Promise<never> {
throw new Error('Not implemented!');
}
2022-05-16 02:08:27 +02:00
override async nextTurn() {
await this.combatant?.advanceTicksDialog();
2022-05-16 03:46:53 +02:00
return this;
}
override previousRound(): Promise<never> {
throw new Error('Not implemented!');
}
override previousTurn(): Promise<never> {
throw new Error('Not implemented!');
2022-05-16 02:08:27 +02:00
}
override async resetAll() {
for (const c of this.combatants) {
c.data.update({ initiative: null });
}
return this.update(
{
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 } },
},
2022-05-16 02:08:27 +02:00
{ diff: false },
);
}
override setupTurns(): this['turns'] {
const turns = this.combatants.contents.sort(this._sortCombatants);
const c = turns[0];
this.current = {
round: this.round,
turn: 0,
combatantId: c?.id ?? null,
tokenId: c?.data.tokenId ?? null,
};
return (this.turns = turns);
}
override async startCombat(): Promise<this | undefined> {
const hasCombatantWithTickValue = this.combatants.find(
(combatant) => !combatant.isDefeated && combatant.initiative !== null,
);
if (!hasCombatantWithTickValue) {
ui.notifications?.warn('TICKWERK.WarningCannotStartCombat', { localize: true });
return this;
}
return this.setFlag(packageId, 'started', true);
}
protected override _sortCombatants(a: TickwerkCombatant, b: TickwerkCombatant): number {
const da = a.isDefeated ? 1 : 0;
const db = b.isDefeated ? 1 : 0;
const cd = da - db;
if (cd !== 0) return cd;
const wa = a.waiting ? 1 : 0;
const wb = b.waiting ? 1 : 0;
const cw = wa - wb;
if (cw !== 0) return cw;
const ia = a.initiative ?? Infinity;
const ib = b.initiative ?? Infinity;
const ci = ia - ib;
if (ci !== 0) return ci;
2022-05-16 03:46:53 +02:00
const tba = a.getFlag(packageId, 'tiebreaker') ?? 0;
const tbb = b.getFlag(packageId, 'tiebreaker') ?? 0;
2022-05-16 02:08:27 +02:00
const ctb = tba - tbb;
if (ctb !== 0) return ctb;
return (b.id ?? '') > (a.id ?? '') ? 1 : -1;
}
};
};
declare global {
interface FlagConfig {
Combat: {
tickwerk?: {
started?: boolean;
};
};
}
}