Skip to content

Commit

Permalink
oopsy: report overwritten mit (#5814)
Browse files Browse the repository at this point in the history
  • Loading branch information
g0shu authored Sep 27, 2023
1 parent 38f8e52 commit 26c2665
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 1 deletion.
3 changes: 2 additions & 1 deletion types/data.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Lang } from '../resources/languages';
import PartyTracker from '../resources/party';
import { ConfigValue } from '../resources/user_config';
import { OopsyOptions } from '../ui/oopsyraidsy/oopsy_options';

import { SystemInfo } from './event';
import { Job, Role } from './job';
Expand Down Expand Up @@ -54,7 +55,7 @@ export interface OopsyData {
ShortName: (x?: string) => string;
IsPlayerId: (x?: string) => boolean;
DamageFromMatches: (matches: NetMatches['Ability']) => number;
options: BaseOptions;
options: OopsyOptions;

/** @deprecated Use parseFloat instead */
ParseLocaleFloat: (string: string) => number;
Expand Down
109 changes: 109 additions & 0 deletions ui/oopsyraidsy/data/00-misc/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,63 @@ import ZoneId from '../../../../resources/zone_id';
import { OopsyData } from '../../../../types/data';
import { OopsyTriggerSet } from '../../../../types/oopsy';

type MitTracker = {
[abilityId: string]: {
time: number;
source: string;
};
};

export interface Data extends OopsyData {
lostFood?: { [name: string]: boolean };
raiseTracker?: { [targetId: string]: string };
targetMitTracker?: {
[targetId: string]: MitTracker;
};
partyMitTracker?: MitTracker;
}

const targetMitAbilityIdToDuration: { [id: string]: number } = {
'1D6F': 10, // reprisal
'1D7D': 10, // feint
'B47': 10, // dismantle
'1D88': 10, // addle
};
const targetMitAbilityIds = Object.keys(targetMitAbilityIdToDuration);

const partyMitAbilityIdToDuration: { [id: string]: number } = {
// tanks
'1CDC': 30, // shake it off
'DD4': 30, // divine veil
'4057': 15, // dark missionary
'3F20': 15, // heart of light
// healers
'4098': 20, // temperance
'BC': 15, // sacred soil
'650C': 20, // expedient
'409A': 20, // fey/seraphic illumination (order)
'5EEA': 15, // kerachole
'5EF6': 20, // holos
'5EF7': 15, // panhaima
// melee
'41': 15, // mantra
// ranged
'1CED': 15, // troubadour
'1CF0': 15, // nature's minne
'3E8C': 15, // shield samba
'41F9': 15, // tactician
// casters
'6501': 10, // magick barrier
};
const partyMitAbilityIds = Object.keys(partyMitAbilityIdToDuration);

const shieldEffectIdToAbilityId: { [id: string]: string } = {
'5B1': '1CDC', // shake it off
'552': 'DD4', // divine veil
'D25': '5EF6', // holosakos -> holos
'A53': '5EF7', // panhaimatinon -> panhaima
};

// General mistakes; these apply everywhere.
const triggerSet: OopsyTriggerSet<Data> = {
zoneId: ZoneId.MatchAll,
Expand Down Expand Up @@ -115,6 +167,63 @@ const triggerSet: OopsyTriggerSet<Data> = {
delete data.raiseTracker[matches.targetId];
},
},
{
id: 'General Overwritten Mit',
type: 'Ability',
netRegex: NetRegexes.ability({ id: targetMitAbilityIds.concat(partyMitAbilityIds) }),
mistake: (data, matches) => {
const isTargetMit = targetMitAbilityIds.includes(matches.id);
const isPartyMit = partyMitAbilityIds.includes(matches.id);
if (isTargetMit && matches.targetId === 'E0000000') // missed
return;
if (isPartyMit && !data.party.partyIds_.includes(matches.sourceId))
return;
if (isPartyMit && matches.targetId !== matches.sourceId)
return;

const mitTracker = isTargetMit
? ((data.targetMitTracker ??= {})[matches.targetId] ??= {})
: (data.partyMitTracker ??= {});
const newTime = new Date(matches.timestamp).getTime();
const newSource = data.ShortName(matches.source);
const lastTime = mitTracker[matches.id]?.time;
const lastSource = mitTracker[matches.id]?.source;

mitTracker[matches.id] = {
time: newTime,
source: newSource,
};

const duration = isTargetMit
? targetMitAbilityIdToDuration[matches.id]
: partyMitAbilityIdToDuration[matches.id];
if (lastTime !== undefined && lastSource !== undefined && duration !== undefined) {
const diff = newTime - lastTime;
const leeway =
(duration * 1000 - diff) > data.options.MinimumTimeForOverwrittenMit * 1000;
if (diff < duration * 1000 && leeway) {
return {
type: 'heal',
blame: matches.source,
reportId: matches.sourceId,
text: {
en: 'overwrote ' + lastSource + '\'s ' + matches.ability,
},
};
}
}
},
},
{
id: 'General Shield Removal',
type: 'LosesEffect',
netRegex: NetRegexes.losesEffect({ effectId: Object.keys(shieldEffectIdToAbilityId) }),
run: (data, matches) => {
const abilityId = shieldEffectIdToAbilityId[matches.effectId];
if (abilityId !== undefined)
delete (data.partyMitTracker ??= {})?.[abilityId];
},
},
],
};

Expand Down
2 changes: 2 additions & 0 deletions ui/oopsyraidsy/oopsy_options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ type OopsyConfigOptions = {
MinimumTimeForPullMistake: number;
TimeToShowDeathReportMs: number;
DeathReportSide: DeathReportSide;
MinimumTimeForOverwrittenMit: number;
};

const defaultOopsyConfigOptions: OopsyConfigOptions = {
NumLiveListItemsInCombat: 5,
MinimumTimeForPullMistake: 0.4,
TimeToShowDeathReportMs: 4000,
DeathReportSide: 'left',
MinimumTimeForOverwrittenMit: 2,
};

export interface OopsyOptions extends BaseOptions, OopsyNonConfigOptions, OopsyConfigOptions {}
Expand Down
8 changes: 8 additions & 0 deletions ui/oopsyraidsy/oopsyraidsy_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,14 @@ const templateOptions: OptionsTemplate = {
},
default: 'left',
},
{
id: 'MinimumTimeForOverwrittenMit',
name: {
en: 'Minimum time to show overwritten mit (seconds)',
},
type: 'float',
default: 2,
},
],
};

Expand Down

0 comments on commit 26c2665

Please sign in to comment.