Skip to content

Commit

Permalink
Refactor alternative scalings
Browse files Browse the repository at this point in the history
  • Loading branch information
VioletHynes committed Nov 6, 2024
1 parent 407a264 commit bc7cf4a
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 34 deletions.
11 changes: 6 additions & 5 deletions packages/core/src/sims/sim_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ export type DamagingAbility = Readonly<{
autoCrit?: boolean,
autoDh?: boolean,
dot?: DotInfo,
alternativeScaling?: AlternativeScaling,
alternativeScalings?: AlternativeScaling[],
}>;

/**
Expand All @@ -266,9 +266,9 @@ export type ComboBehavior = ComboData['comboBehavior'];

/**
* Alternate scalings that can exist for abilities, e.g. Living
* Shadow and Bunshin.
* Shadow, Bunshin, SMN pet actions.
*/
export type AlternativeScaling = 'Living Shadow';
export type AlternativeScaling = "Living Shadow Strength Scaling" | "Pet Action Weapon Damage";

export type BaseAbility = Readonly<{
/**
Expand Down Expand Up @@ -333,9 +333,10 @@ export type BaseAbility = Readonly<{
*/
levelModifiers?: LevelModifier[],
/**
* If the ability uses alternate scaling, such as Living Shadow.
* If the ability uses alternate scalings, such as Living Shadow Strength
* scaling or using the pet action Weapon Damage multiplier.
*/
alternativeScaling?: AlternativeScaling,
alternativeScalings?: AlternativeScaling[],
} & (NonDamagingAbility | DamagingAbility)>;


Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/sims/sim_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function dotPotencyToDamage(stats: ComputedSetStats, potency: number, dmgAbility
// TODO: are there any dots with auto-crit or auto-dh?
const forceDhit = false;
const forceCrit = false;
const nonCritDmg = baseDamageFull(modifiedStats, potency, dmgAbility.attackType, forceDhit, true, dmgAbility.alternativeScaling);
const nonCritDmg = baseDamageFull(modifiedStats, potency, dmgAbility.attackType, forceDhit, true, dmgAbility.alternativeScalings);
const afterCritDh = applyDhCritFull(nonCritDmg, modifiedStats, forceCrit, forceDhit);
return multiplyFixed(afterCritDh, combinedBuffEffects.dmgMod);
}
Expand All @@ -31,7 +31,7 @@ function potencyToDamage(stats: ComputedSetStats, potency: number, dmgAbility: D
bonuses.forceDh = true;
}
});
const nonCritDmg = baseDamageFull(modifiedStats, potency, dmgAbility.attackType, forceDhit, false, dmgAbility.alternativeScaling);
const nonCritDmg = baseDamageFull(modifiedStats, potency, dmgAbility.attackType, forceDhit, false, dmgAbility.alternativeScalings);
const afterCritDh = applyDhCritFull(nonCritDmg, modifiedStats, forceCrit, forceDhit);
return multiplyFixed(afterCritDh, combinedBuffEffects.dmgMod);
}
Expand Down
27 changes: 9 additions & 18 deletions packages/core/src/sims/tank/drk/drk_actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Darkside, DrkGauge } from "./drk_gauge";
import { DrkGcdAbility, DrkOgcdAbility, BloodWeaponBuff, DeliriumBuff, ScornBuff, SaltedEarthBuff } from "./drk_types";
import { DrkGcdAbility, DrkOgcdAbility, BloodWeaponBuff, DeliriumBuff, ScornBuff, SaltedEarthBuff, livingShadowScalings } from "./drk_types";

export const HardSlash: DrkGcdAbility = {
type: 'gcd',
Expand Down Expand Up @@ -282,15 +282,6 @@ export const Shadowbringer: DrkOgcdAbility = {

// While Living Shadow abilities are actually Weaponskills in some cases,
// they've all been programmed to be abilities so that it doesn't roll GCD.
//
// This shouldn't change anything damage wise.

// Esteem has the same stats as the player but ignores skill speed, Tank Mastery, and party strength bonus.
// It also substitutes Midlander racial strength bonus regardless of the player's race.
// It has an alternate strength scaling.

// Esteem updates buffs/debuffs in real time. It is NOT affected by Darkside or by Weakness,
// but mirrors all other statuses on the player (including tincture, AST cards, DNC partner buffs, and Damage Down).
export const LivingShadow: DrkOgcdAbility = {
type: 'ogcd',
name: "Living Shadow",
Expand All @@ -314,7 +305,7 @@ export const LivingShadow: DrkOgcdAbility = {
export const LivingShadowShadowstride: DrkOgcdAbility = {
type: 'ogcd',
name: "(Living Shadow) Shadowstride",
alternativeScaling: "Living Shadow",
alternativeScalings: livingShadowScalings,
animationLock: 0,
id: 38512,
potency: 0,
Expand All @@ -324,7 +315,7 @@ export const LivingShadowShadowstride: DrkOgcdAbility = {
export const LivingShadowAbyssalDrain: DrkOgcdAbility = {
type: 'ogcd',
name: "(Living Shadow) Abyssal Drain",
alternativeScaling: "Living Shadow",
alternativeScalings: livingShadowScalings,
animationLock: 0,
id: 17904,
potency: 340,
Expand All @@ -340,7 +331,7 @@ export const LivingShadowAbyssalDrain: DrkOgcdAbility = {
export const LivingShadowShadowbringer: DrkOgcdAbility = {
type: 'ogcd',
name: "(Living Shadow) Shadowbringer",
alternativeScaling: "Living Shadow",
alternativeScalings: livingShadowScalings,
animationLock: 0,
id: 25881,
potency: 570,
Expand All @@ -350,7 +341,7 @@ export const LivingShadowShadowbringer: DrkOgcdAbility = {
export const LivingShadowEdgeOfShadow: DrkOgcdAbility = {
type: 'ogcd',
name: "(Living Shadow) Edge of Shadow",
alternativeScaling: "Living Shadow",
alternativeScalings: livingShadowScalings,
animationLock: 0,
id: 17908,
potency: 340,
Expand All @@ -367,7 +358,7 @@ export const LivingShadowEdgeOfShadow: DrkOgcdAbility = {
export const LivingShadowFloodOfShadow: DrkOgcdAbility = {
type: 'ogcd',
name: "(Living Shadow) Flood of Shadow",
alternativeScaling: "Living Shadow",
alternativeScalings: livingShadowScalings,
animationLock: 0,
id: 17907,
potency: 340,
Expand All @@ -377,7 +368,7 @@ export const LivingShadowFloodOfShadow: DrkOgcdAbility = {
export const LivingShadowBloodspiller: DrkOgcdAbility = {
type: 'ogcd',
name: "(Living Shadow) Bloodspiller",
alternativeScaling: "Living Shadow",
alternativeScalings: livingShadowScalings,
animationLock: 0,
id: 17909,
potency: 340,
Expand All @@ -394,7 +385,7 @@ export const LivingShadowBloodspiller: DrkOgcdAbility = {
export const LivingShadowCarveAndSpit: DrkOgcdAbility = {
type: 'ogcd',
name: "(Living Shadow) Carve And Spit",
alternativeScaling: "Living Shadow",
alternativeScalings: livingShadowScalings,
animationLock: 0,
id: 17915,
potency: 340,
Expand All @@ -410,7 +401,7 @@ export const LivingShadowCarveAndSpit: DrkOgcdAbility = {
export const LivingShadowDisesteem: DrkOgcdAbility = {
type: 'ogcd',
name: "(Living Shadow) Disesteem",
alternativeScaling: "Living Shadow",
alternativeScalings: livingShadowScalings,
animationLock: 0,
id: 36933,
potency: 620,
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/sims/tank/drk/drk_types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Ability, GcdAbility, OgcdAbility, Buff, BuffController } from "@xivgear/core/sims/sim_types";
import { Ability, GcdAbility, OgcdAbility, Buff, BuffController, AlternativeScaling } from "@xivgear/core/sims/sim_types";
import { DrkGauge } from "./drk_gauge";
import { removeSelf } from "@xivgear/core/sims/common/utils";

Expand All @@ -21,6 +21,11 @@ export type DrkGcdAbility = GcdAbility & DrkAbility;

export type DrkOgcdAbility = OgcdAbility & DrkAbility;

// All Living Shadow abilities use the following scalings:
// - Alternate strength scaling (no Tank Mastery, no party bonus, replaced racial bonus)
// - Pet action weapon damage scaling (100 instead of the usual)
export const livingShadowScalings: AlternativeScaling[] = ["Living Shadow Strength Scaling", "Pet Action Weapon Damage"];

/** DRK ability that costs blood */
export type BloodAbility = DrkAbility & Readonly<{
bloodCost: number;
Expand Down
8 changes: 5 additions & 3 deletions packages/core/src/test/stats/general_stats_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {expect} from "chai";
import {applyDhCritFull, baseDamageFull, fl} from "@xivgear/xivmath/xivmath";
import { multiplyFixed } from "@xivgear/xivmath/deviation";
import { HEADLESS_SHEET_PROVIDER } from "../../sheet";
import { AlternativeScaling } from "../../sims/sim_types";


const level = 100;
Expand Down Expand Up @@ -851,17 +852,18 @@ describe("Final damage values for known values", () => {
expect(stats.mainStatMultiLivingShadow).to.eq(1.04);

// These match up with observed values.
const livingShadowScalings: AlternativeScaling[] = ["Living Shadow Strength Scaling", "Pet Action Weapon Damage"];

// 420 potency Living Shadow Attack
const damageBeforeCrit420 = baseDamageFull(stats, 420, 'Ability', false, false, "Living Shadow");
const damageBeforeCrit420 = baseDamageFull(stats, 420, 'Ability', false, false, livingShadowScalings);
expect(damageBeforeCrit420.expected).to.eq(344);

// 570 potency Living Shadow Attack
const damageBeforeCrit570 = baseDamageFull(stats, 570, 'Ability', false, false, "Living Shadow");
const damageBeforeCrit570 = baseDamageFull(stats, 570, 'Ability', false, false, livingShadowScalings);
expect(damageBeforeCrit570.expected).to.eq(467);

// 620 potency Living Shadow Attack
const damageBeforeCrit620 = baseDamageFull(stats, 620, 'Ability', false, false, "Living Shadow");
const damageBeforeCrit620 = baseDamageFull(stats, 620, 'Ability', false, false, livingShadowScalings);
expect(damageBeforeCrit620.expected).to.eq(508);
});
});
15 changes: 10 additions & 5 deletions packages/xivmath/src/xivmath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@ function usesCasterDamageFormula(stats: ComputedSetStats, attackType: AttackType
/**
* Computes base damage. Does not factor in crit/dh RNG nor damage variance.
*/
export function baseDamageFull(stats: ComputedSetStats, potency: number, attackType: AttackType = 'Unknown', autoDH: boolean = false, isDot: boolean = false, alternativeScaling: AlternativeScaling = undefined): ValueWithDev {
export function baseDamageFull(stats: ComputedSetStats, potency: number, attackType: AttackType = 'Unknown', autoDH: boolean = false, isDot: boolean = false, alternativeScalings: AlternativeScaling[] = []): ValueWithDev {
//export function baseDamageFull(stats: ComputedSetStats, potency: number, attackType: AttackType = 'Unknown', autoDH: boolean = false, isDot: boolean = false, alternativeScaling: AlternativeScaling = undefined): ValueWithDev {

let spdMulti: number;
const isAA = attackType === 'Auto-attack';
Expand All @@ -313,10 +314,14 @@ export function baseDamageFull(stats: ComputedSetStats, potency: number, attackT
// Multiplier from weapon damage. If this is an auto-attack, use the AA multi instead of the pure WD multi.
let wdMulti = isAA ? stats.aaMulti : stats.wdMulti;

// Override the multipliers for Living Shadow abilities
if (alternativeScaling === "Living Shadow") {
mainStatMulti = stats.mainStatMultiLivingShadow;
wdMulti = stats.wdMultiPetAction;
// Process alternative scalings for the ability
if (alternativeScalings) {
if (alternativeScalings.find(scaling => scaling === "Living Shadow Strength Scaling")) {
mainStatMulti = stats.mainStatMultiLivingShadow;
}
if (alternativeScalings.find(scaling => scaling === "Pet Action Weapon Damage")) {
wdMulti = stats.wdMultiPetAction;
}
}

// Det multiplier
Expand Down

0 comments on commit bc7cf4a

Please sign in to comment.