Skip to content

Commit

Permalink
fix: fixes to import harness and import latest scripts (#994)
Browse files Browse the repository at this point in the history
* fix: generate 9.1 scripts from Tier27 SimulationCraft profiles

* fix: adjust names of spell scripts for Shadowlands 9.1

* fix: use correct SpellId names instead of hardcoding constants

* fix: ensure that 'this' is valid within parseGroup

* fix: update conduit data

* fix: update usage of method in OvaleScripts class to correct name

The name of the script registration method was changed to
`registerScript` in commit af6216a.

* fix: remove identifier fixes that were not necessary

* style: sort fixIdentifier() section

* fix: support heroic_charge action (Heroic Leap, then Charge)

* fix: workaround name=name= syntax error in SimC profiles

The offending line is in T27_Warlock_Affliction.simc:

  /use_item,name=name=shadowed_orb_of_torment,...

where the `name=name=` looks like a copy-and-paste error.

* fix: workaround name=BT&Foo syntax error in SimC profiles

The SimulationCraft parser accepts `&` as a valid character in
name strings, which is surprising since it's a keyword token. The
offending lines are in T27_Warrior_Fury.simc:

  /sequence,...,name=BT&Charge:bloodthirst:heroic_charge
  /sequence,...,name=BT&Reck:bloodthirst:recklessness

and we simply replace the `&` with `_` to harmlessly fix the error.

* fix: add Merciless Bonegrinder soulbind and buff for warriors

* fix: decorate warlock pet interrupt and CC spells

* fix: support warlock interrupts

SimulationCraft profiles use an warlock-specific action `interrupt`
as a catch-all action to trigger pet interrupt abilities. Convert
that action to a warlock-specific `InterruptActions` function in
the Ovale script.

* fix: from_the_shadows is a target debuff, not a player buff

Fix a bug in the SimC usage of `from_the_shadows` as it's
implemented as a target debuff, but the profile is using it as a
player buff.

* fix: add flagellation_buff granted by spending CPs during Flagellation

* fix: disambiguate blood_fury for paladins

Orcs can't (currently) be paladins, but the `T27_Paladin_Holy.simc`
profile tries suggesting `blood_fury`, so make it work.

* fix: change bonedust_brew_debuff to just bonedust_brew

Bonedust Brew coats friendlies and enemies alike with the same
aura, but it is a buff or debuff depending on the target.

* fix: add spell definition for ravenous_frenzy_sinful_hysteria_buff

This is the buff that's triggered by the Sinful Hysteria legendary
when the druid casts the Venthyr covenant ability Ravenous Frenzy.

* fix: add partial support for "newfound_resolve" action

Ignore all modifiers for the `newfound_resolve` action and just
replace it with a check for whether the Trial of Doubt debuff
exists and whether it's time to face the manifestation.

* fix: support cp_gain modifier in SimC profile

`cp_gain` is the actual number of combo points that would be gained
by using an ability, taking into account the combo point cap.

* fix: update Serrated Bone Spike to 9.1 behavior

Serrated Bone Spikes grants one combo point on use plus an
additional combo point for each Serrated Bone Spike that is active.

* fix: ignore "retarget_auto_attack" action

For now, ignore `retarget_auto_attack`. It's an indication to
target other enemies for attack and used by havoc demon hunter
profiles to suggest spreading Burning Wound, but the SimC
implementation is clunky and not worth directly translating.

* fix: correctly translate cooldowns for items that proc buffs

SimulationCraft added a way to get the cooldown of an item by
checking the cooldown of the procced buff. Translate the buff name
back into the item name and directly check the item cooldown.

* fix: support {duration,remains}_expected as cooldown properties

For Ovale, `duration_expected` and `remains_expected` are
essentially the same as `duration` and `remains` since we are
constantly updating state from the game client.

* fix: support {regen,time_to_max}_combined as energy properties

The implementation of these two properties should factor in energy
regenerated from active buffs, but for now, treating them the same
as `regen` and `time_to_max` is sufficient.

* fix: add missing HasWeapon script condition used for main_hand.2h

* fix: parse 'sequence' actions correctly

Correctly handle the `:` token that separates the different
sub-actions within each sequence. Each sub-action can have
modifiers as well, which are separated by `,` tokens.

* fix: include item identifiers in the common script

Add `Define(identifier nnn)` lines to `ovale_common` for better
readability.

* fix: support more SimC "trinket" properties

Emit code for more `trinket` conditions:
  - `trinket.cooldown.ready`
  - `trinket.has_buff.<stat>`
  - `trinket.has_proc.<stat>.duration`
  - `trinket.has_use_buff`

* fix: support "death_and_decay.active_remains" in SimC profiles

* fix: use correct trinket name for Tormented Insight buff

Add a special adjustment for `tormented_insight_355321` so that
the correct trinket name is inferred by renaming the buff in the
profile to `shadowed_orb_of_torment_355321`.

* refactor: extract function to walk a spell "replaced_by" chain

Extract a function from `best-action` to walk the `replaced_by`
chain in `SpellInfo` declarations and add it to the `data` module
as `resolveSpell()`.

* fix: resolve spells in SpellCooldown() condition before checking

`SpellCooldown()` can take a list of spell IDs and returns the
earliest time that one is available. Resolve the spell IDs to their
final replacement spells if they were replaced because the WoW API
function `GetSpellCooldown()` returns 0 if used with original spell
ID, even though it's been replaced in the spell book.

* fix: disambiguate "bs_inc" into "berserk_{bear,cat}"

Disambiguate `bs_inc` into `berserk_bear` or `berserk_cat` based
on druid specialization so that we can correctly check the cooldown
of the spell.

* fix: disambiguate "berserk" into "berserk_{bear,cat}"

Disambiguate `berserk` into `berserk_bear` or `berserk_cat` based
on the druid specialization so we refer to the corect action.

* fix: disambiguate "incarnation" action for each druid specialization

* fix: remove unneeded "berserk" spell list

* fix: support "ca_inc" in balance druid SimC profiles

`buff.ca_inc.up` should check for either Celestial Alignment or
Incarnation: Chosen of Elune, so create a `ca_inc_buff` spell list
for those two buffs.

* fix: eclipse module correctly handles Incarnation: Chosen of Elune

* fix: remaining_winters_chill tracks a target, not player, debuff

* style: minor whitespace changes to ovale_mage_spells

* fix: decorate winters_chill_debuff for frost mages

Note which spells add and remove Winter's Chill debuff from the
target.

* fix: support raid_event.vulnerable.{exists,in,up} in SimC profiles

Support `raid_event.vulnerable.*` events by assuming the target is
always vulnerable.

* fix: support "searing_touch.active" for fire mage SimC profiles

* fix: support "precast_etf_equip" for MM hunter SimC profiles

The MM hunter profile uses `precast_etf_equip=1` to test if the
Eagletalon's True Focus legendary is equipped.

* fix: support "bloodseeker.remains" in survival hunter SimC profiles

* fix: allow "code" without "symbolsInCode" in emitMiscOperand

* fix: support "expected_kindling_reduction" in fire mage SimC profiles

* fix: support "target.cooldown.pause_action.*" in SimC profiles

`pause_action` is a dummy action that indicates that the enemy is
not attacking the player. Model this dummy action as never
happening.

* fix: support "buff.recent_purifies.value" in SimC profiles

`buff.recent_purifies.value` is how SimC exports the amount of
Stagger that was removed by the most recent Purifying Brew. Model
this as simply always being the value `MaxHealth() * 0.05` for now.

* fix: support "execute_time" operand for "use_item" actions

Assume that on-use items have an execute time of zero seconds.

* fix: aura IDs are not always in the spellbook

Don't set `isSpell` when describing the first positional parameter
to `BuffPresent` and its aliases. Otherwise, the compiler will
complain if `BuffPresent` is called with an ID not in the
spellbook, which can often happen with buffs.

* fix: use the exact item if the name is provided

Many SimC profiles are now very sophisticated in using specific
trinkets under specific conditions. Use the exact trinket if the
name is provided in `use_item` actions.

* fix: correctly tag items identified by slot name for splitting

* fix: import scripts from simc shadowlands branch from 2021-09-03

* fix: use T27 script names in the integration tests

* fix: fixes for integration test

There is probably a better way to do this by telling the compiler
that item cannot be undefined, but I'm not sure how to do that yet.

* fix: set the T27 scripts as the default for all specializations

Co-authored-by: Sidoine De Wispelaere <sidoine@sidoine.net>
  • Loading branch information
johnnylam88 and Sidoine authored Sep 4, 2021
1 parent f3cb6d7 commit 47a513d
Show file tree
Hide file tree
Showing 45 changed files with 19,837 additions and 6,725 deletions.
7 changes: 5 additions & 2 deletions src/engine/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2651,15 +2651,18 @@ export class OvaleASTClass {
return node;
};

private parseGroup(tokenStream: OvaleLexer, annotation: AstAnnotation) {
private parseGroup = (
tokenStream: OvaleLexer,
annotation: AstAnnotation
): AstNode | undefined => {
const group = this.innerParseGroup(tokenStream, annotation);
if (group && lualength(group.child) === 1) {
const result = group.child[1];
this.nodesPool.release(group);
return result;
}
return group;
}
};

private innerParseGroup: ParserFunction<AstGroupNode> = (
tokenStream,
Expand Down
30 changes: 8 additions & 22 deletions src/engine/best-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
} from "./ast";
import { OvaleCooldownClass } from "../states/Cooldown";
import { OvaleSpellsClass } from "../states/Spells";
import { isNumber, isString, oneTimeMessage } from "../tools/tools";
import { isNumber, isString } from "../tools/tools";
import { OvaleClass } from "../Ovale";
import { AceModule } from "@wowts/tsaddon";
import { Guids } from "./guid";
Expand Down Expand Up @@ -187,28 +187,14 @@ export class OvaleBestActionClass {
let si = this.ovaleData.spellInfo[spellId];
let replacedSpellId = undefined;
if (si) {
const maxGuard = 20;
let guard = 0;
let replacementId = spellId;
let id: number | undefined = replacementId;
while (id !== undefined && guard < maxGuard) {
guard = guard + 1;
replacementId = id;
id = this.ovaleData.getSpellInfoProperty(
<number>replacementId,
atTime,
"replaced_by",
targetGUID
);
}
if (guard >= maxGuard) {
oneTimeMessage(
"Recursive 'replaced_by' chain for spell ID '%s'.",
spellId
);
} else if (replacementId != spellId) {
const replacementSpellId = this.ovaleData.resolveSpell(
spellId,
atTime,
targetGUID
);
if (replacementSpellId && replacementSpellId != spellId) {
replacedSpellId = spellId;
spellId = replacementId;
spellId = replacementSpellId;
si = this.ovaleData.spellInfo[spellId];
this.tracer.log(
"Spell ID '%s' is replaced by spell ID '%s'.",
Expand Down
200 changes: 85 additions & 115 deletions src/engine/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
LuaObj,
} from "@wowts/lua";
import { find } from "@wowts/string";
import { isNumber } from "../tools/tools";
import { isNumber, oneTimeMessage } from "../tools/tools";
import { HasteType } from "../states/PaperDoll";
import { PowerType } from "../states/Power";
import { GetSpellInfo, SpellId } from "@wowts/wow-mock";
Expand Down Expand Up @@ -306,147 +306,86 @@ export class OvaleDataClass {

buffSpellList: LuaObj<LuaArray<boolean>> = {
attack_power_multiplier_buff: {
[6673]: true,
[19506]: true,
[57330]: true,
[SpellId.battle_shout]: true,
},
critical_strike_buff: {
[1459]: true,
[24604]: true,
[24932]: true,
[61316]: true,
[90309]: true,
[90363]: true,
[97229]: true,
[116781]: true,
[126309]: true,
[126373]: true,
[128997]: true,
[160052]: true,
[160200]: true,
},
haste_buff: {
[49868]: true,
[55610]: true,
[113742]: true,
[128432]: true,
[135678]: true,
[160003]: true,
[160074]: true,
[160203]: true,
},
mastery_buff: {
[19740]: true,
[24907]: true,
[93435]: true,
[116956]: true,
[128997]: true,
[155522]: true,
[160073]: true,
[160198]: true,
[SpellId.arcane_intellect]: true,
},
haste_buff: {},
mastery_buff: {},
spell_power_multiplier_buff: {
[1459]: true,
[61316]: true,
[90364]: true,
[109773]: true,
[126309]: true,
[128433]: true,
[160205]: true,
[SpellId.arcane_intellect]: true,
},
stamina_buff: {
[469]: true,
[21562]: true,
[50256]: true,
[90364]: true,
[160003]: true,
[160014]: true,
[166928]: true,
[160199]: true,
},
str_agi_int_buff: {
[1126]: true,
[20217]: true,
[90363]: true,
[115921]: true,
[116781]: true,
[159988]: true,
[160017]: true,
[160077]: true,
[160206]: true,
},
versatility_buff: {
[1126]: true,
[35290]: true,
[50518]: true,
[55610]: true,
[57386]: true,
[159735]: true,
[160045]: true,
[160077]: true,
[167187]: true,
[167188]: true,
[172967]: true,
[SpellId.power_word_fortitude]: true,
},
str_agi_int_buff: {},
versatility_buff: {},
bleed_debuff: {
[1079]: true,
[16511]: true,
[33745]: true,
[77758]: true,
[113344]: true,
[115767]: true,
[122233]: true,
[154953]: true,
[155722]: true,
[SpellId.bloodbath_debuff]: true,
[SpellId.crimson_tempest]: true,
[SpellId.deep_wounds_debuff]: true,
[SpellId.garrote]: true,
[SpellId.internal_bleeding_debuff]: true,
[SpellId.rake_debuff]: true,
[SpellId.rend]: true,
[SpellId.rip]: true,
[SpellId.rupture]: true,
[SpellId.thrash_debuff]: true,
[SpellId.serrated_bone_spike]: true,
},
healing_reduced_debuff: {
[8680]: true,
[54680]: true,
[115625]: true,
[115804]: true,
[8680]: true, // Wound Poison debuff
[SpellId.mortal_wounds_debuff]: true,
},
stealthed_buff: {
[SpellId.stealth]: true,
[115191]: true,
[SpellId.incarnation_king_of_the_jungle]: true,
[SpellId.prowl]: true,
[SpellId.vanish]: true,
[11327]: true,
[SpellId.shadowmeld]: true,
[SpellId.incarnation_king_of_the_jungle]: true,
[SpellId.shadow_dance_buff]: true,
[SpellId.stealth]: true,
[SpellId.subterfuge_buff]: true,
[115193]: true,
[SpellId.shadow_dance]: true,
[185422]: true,
[347037]: true,
[SpellId.vanish]: true,
[11327]: true, // Vanish buff
[115191]: true, // Stealth (Subterfuge)
[115193]: true, // Vanish buff
[347037]: true, // Sepsis debuff
},
rogue_stealthed_buff: {
[SpellId.stealth]: true,
[115191]: true,
[SpellId.vanish]: true,
[11327]: true,
[SpellId.shadow_dance]: true,
[185422]: true,
[SpellId.shadow_dance_buff]: true,
[SpellId.subterfuge_buff]: true,
[347037]: true,
[SpellId.vanish]: true,
[11327]: true, // Vanish buff
[115191]: true, // Stealth (Subterfuge)
[115193]: true, // Vanish buff
[347037]: true, // Sepsis debuff
},
mantle_stealthed_buff: {
[SpellId.stealth]: true,
[SpellId.vanish]: true,
[11327]: true, // Vanish buff
[115193]: true, // Vanish buff
},
burst_haste_buff: {
[2825]: true,
[32182]: true,
[80353]: true,
[90355]: true,
[SpellId.bloodlust]: true,
[SpellId.drums_of_deathly_ferocity]: true,
[SpellId.drums_of_fury]: true,
[SpellId.drums_of_rage]: true,
[SpellId.drums_of_the_maelstrom]: true,
[SpellId.drums_of_the_mountain]: true,
[SpellId.heroism]: true,
[SpellId.primal_rage_pet]: true,
[SpellId.time_warp]: true,
},
burst_haste_debuff: {
[57723]: true,
[57724]: true,
[80354]: true,
[95809]: true,
[SpellId.exhaustion_debuff]: true,
[SpellId.sated_debuff]: true,
[SpellId.temporal_displacement_debuff]: true,
},
raid_movement_buff: {
[106898]: true,
[SpellId.stampeding_roar]: true,
[SpellId.wind_rush_buff]: true,
},
roll_the_bones_buff: {
[SpellId.broadside_buff]: true,
Expand All @@ -458,8 +397,12 @@ export class OvaleDataClass {
},
lethal_poison_buff: {
[SpellId.deadly_poison]: true,
[8679]: true,
[315584]: true,
[SpellId.instant_poison]: true,
[SpellId.wound_poison]: true,
},
non_lethal_poison_buff: {
[SpellId.crippling_poison]: true,
[SpellId.numbing_poison]: true,
},
};
constructor(private runner: Runner, ovaleDebug: DebugTools) {
Expand Down Expand Up @@ -793,6 +736,33 @@ export class OvaleDataClass {
return [value * ratio];
}

resolveSpell(
spellId: number,
atTime: number | undefined,
targetGUID: string | undefined
): number | undefined {
const maxGuard = 20;
let guard = 0;
let nextId;
let id: number | undefined = spellId;
while (id && guard < maxGuard) {
guard += 1;
nextId = id;
id = this.getSpellInfoProperty(
nextId,
atTime,
"replaced_by",
targetGUID
);
}
if (guard >= maxGuard) {
oneTimeMessage(
`Recursive 'replaced_by' chain for spell ID '${spellId}'.`
);
}
return nextId;
}

getDamage(
spellId: number,
attackpower: number,
Expand Down
Loading

0 comments on commit 47a513d

Please sign in to comment.