93 lines
3.4 KiB
TypeScript
93 lines
3.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { EMPTY_ITEM_STATS } from "./itemStats";
|
|
import {
|
|
baseAttributesFor,
|
|
baseResourcesFor,
|
|
damageAfterEquipmentMitigation,
|
|
deriveCharacterStats,
|
|
hastedDuration,
|
|
healthFromTotalStamina,
|
|
MANA_POOL_MULTIPLIER,
|
|
ratingMultiplier,
|
|
ratingPerPercent,
|
|
} from "./wotlkStats";
|
|
|
|
describe("WoW 3.3.5a character stats", () => {
|
|
it("uses the authored race/class base-stat table", () => {
|
|
expect(baseAttributesFor("warrior", 1, "human")).toEqual({
|
|
strength: 23,
|
|
agility: 20,
|
|
stamina: 22,
|
|
intellect: 20,
|
|
spirit: 20,
|
|
});
|
|
});
|
|
|
|
it("uses exact client combat-rating conversions at low level and level 80", () => {
|
|
expect(ratingMultiplier("meleeHit", 20)).toBeCloseTo(0.433333, 5);
|
|
expect(ratingPerPercent("meleeHit", 80)).toBeCloseTo(32.789989, 5);
|
|
expect(ratingPerPercent("spellHit", 80)).toBeCloseTo(26.231993, 5);
|
|
expect(ratingPerPercent("meleeCrit", 80)).toBeCloseTo(45.905987, 5);
|
|
expect(ratingMultiplier("meleeHaste", 20, "paladin")).toBeGreaterThan(
|
|
ratingMultiplier("meleeHaste", 20, "warrior"),
|
|
);
|
|
});
|
|
|
|
it("turns primary attributes into class resources and combat power", () => {
|
|
const warriorBase = deriveCharacterStats("warrior", 20, EMPTY_ITEM_STATS);
|
|
const warriorGeared = deriveCharacterStats("warrior", 20, {
|
|
...EMPTY_ITEM_STATS,
|
|
strength: 10,
|
|
stamina: 10,
|
|
});
|
|
expect(warriorGeared.attackPower - warriorBase.attackPower).toBe(20);
|
|
expect(warriorGeared.health - warriorBase.health).toBe(100);
|
|
|
|
const mageBase = deriveCharacterStats("mage", 20, EMPTY_ITEM_STATS);
|
|
const mageGeared = deriveCharacterStats("mage", 20, {
|
|
...EMPTY_ITEM_STATS,
|
|
intellect: 10,
|
|
spirit: 10,
|
|
spellPower: 7,
|
|
mp5: 4,
|
|
});
|
|
expect(mageGeared.mana - mageBase.mana).toBe(150 * MANA_POOL_MULTIPLIER);
|
|
expect(mageGeared.spellPower).toBe(7);
|
|
expect(mageGeared.spellCritPercent).toBeGreaterThan(mageBase.spellCritPercent);
|
|
expect(mageGeared.manaPer5).toBeGreaterThan(mageBase.manaPer5 + 4);
|
|
});
|
|
|
|
it("applies automatic Ascension racial passives to starting attributes and pools", () => {
|
|
const humanMage = deriveCharacterStats("mage", 1, EMPTY_ITEM_STATS, "human");
|
|
const gnomeMage = deriveCharacterStats("mage", 1, EMPTY_ITEM_STATS, "gnome");
|
|
expect(gnomeMage.intellect).toBeGreaterThan(baseAttributesFor("mage", 1, "gnome").intellect);
|
|
expect(gnomeMage.mana).toBeGreaterThan(humanMage.mana);
|
|
|
|
const taurenAttributes = baseAttributesFor("warrior", 1, "tauren");
|
|
const taurenWithoutEndurance = baseResourcesFor("warrior", 1).health
|
|
+ healthFromTotalStamina(taurenAttributes.stamina);
|
|
const taurenWarrior = deriveCharacterStats("warrior", 1, EMPTY_ITEM_STATS, "tauren");
|
|
expect(taurenWarrior.health).toBeGreaterThan(taurenWithoutEndurance);
|
|
});
|
|
|
|
it("makes haste, armor, avoidance, block, and resistances affect combat", () => {
|
|
expect(hastedDuration(2_000, 25)).toBe(1_600);
|
|
const physical = damageAfterEquipmentMitigation(100, {
|
|
...EMPTY_ITEM_STATS,
|
|
strength: 8,
|
|
agility: 8,
|
|
armor: 200,
|
|
defenseRating: 6,
|
|
dodgeRating: 5,
|
|
blockRating: 5,
|
|
blockValue: 10,
|
|
}, 20);
|
|
const fire = damageAfterEquipmentMitigation(100, {
|
|
...EMPTY_ITEM_STATS,
|
|
fireResistance: 100,
|
|
}, 20, "fire", 20);
|
|
expect(physical).toBeLessThan(100);
|
|
expect(fire).toBeLessThan(100);
|
|
});
|
|
});
|