import { Lang } from '../resources/languages'; import { TrackedEvent } from '../ui/oopsyraidsy/player_state_tracker'; import { OopsyData } from './data'; import { NetAnyMatches, NetMatches } from './net_matches'; import { CactbotBaseRegExp, TriggerTypes } from './net_trigger'; import { LocaleText, TimelineReplacement, ZoneIdType } from './trigger'; export type OopsyMistakeType = | 'pull' | 'warn' | 'fail' | 'potion' | 'death' | 'wipe' | 'damage' | 'heal' | 'good'; export type OopsyField = | boolean | number | string | OopsyMistake | OopsyMistake[] | OopsyDeathReason | void; export type InternalOopsyTriggerType = | 'Buff' | 'Damage' | 'GainsEffect' | 'Share' | 'Solo'; export type DeathReportData = { lang: Lang; baseTimestamp: number | undefined; deathTimestamp: number; targetId: string; targetName: string; events: TrackedEvent[]; }; export type OopsyMistake = { type: OopsyMistakeType; name?: string; blame?: string; reportId?: string; text: string | LocaleText; // Internal annotation for which trigger type created this. // This will get overwritten when triggers are loaded/created. triggerType?: InternalOopsyTriggerType; // TODO: change type so this only exists for type='death'. report?: DeathReportData; }; export type OopsyDeathReason = { id: string; name: string; text: string | LocaleText; }; export type OopsyFunc = ( data: Data, matches: MatchType, ) => Return; export type OopsyTriggerField = [Return] extends [void] ? OopsyFunc : OopsyFunc | Return | undefined; export type BaseOopsyTrigger = { id: string; comment?: Partial; condition?: OopsyTriggerField; delaySeconds?: OopsyTriggerField; suppressSeconds?: OopsyTriggerField; deathReason?: OopsyTriggerField; mistake?: OopsyTriggerField; run?: OopsyTriggerField; }; type OopsyTriggerRegex = { type: T; netRegex: CactbotBaseRegExp; }; export type OopsyTriggerGeneric = & BaseOopsyTrigger & OopsyTriggerRegex; export type OopsyTrigger = | (TriggerTypes extends infer T ? T extends TriggerTypes ? OopsyTriggerGeneric : never : never) | { // Triggers that want to show up in the UI but are implemented internally. id: string; }; type MistakeMap = { [mistakeId: string]: string }; export type DataInitializeFunc = () => Omit; // This helper takes all of the properties in Type and checks to see if they can be assigned to a // blank object, and if so excludes them from the returned union. The `-?` syntax removes the // optional modifier from the attribute which prevents `undefined` from being included in the union // See also: https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#mapping-modifiers type RequiredFieldsAsUnion = { [key in keyof Type]-?: Record extends Pick ? never : key; }[keyof Type]; export type OopsyMistakeMapFields = { damageWarn?: MistakeMap; damageFail?: MistakeMap; gainsEffectWarn?: MistakeMap; gainsEffectFail?: MistakeMap; shareWarn?: MistakeMap; shareFail?: MistakeMap; soloWarn?: MistakeMap; soloFail?: MistakeMap; }; type SimpleOopsyTriggerSet = { zoneId: ZoneIdType | ZoneIdType[]; zoneLabel?: LocaleText; triggers?: OopsyTrigger[]; timelineReplace?: TimelineReplacement[]; } & OopsyMistakeMapFields; // If Data contains required properties that are not on OopsyData, require initData export type OopsyTriggerSet = & SimpleOopsyTriggerSet & (RequiredFieldsAsUnion extends RequiredFieldsAsUnion ? { initData?: DataInitializeFunc; } : { initData: DataInitializeFunc; }); export type LooseOopsyTrigger = Partial< BaseOopsyTrigger & OopsyTriggerRegex<'None'> >; export type LooseOopsyTriggerSet = Exclude>, 'triggers'> & { zoneRegex?: RegExp | { [lang in Lang]?: RegExp }; triggers?: LooseOopsyTrigger[]; }; export interface OopsyFileData { [filename: string]: LooseOopsyTriggerSet; }