Update class mechanics, stat rulesets, and CoA reference catalogs

This commit is contained in:
phenom committed 2026-10-04 12:56:30 -04:00
1 parent b16821e92e
commit 39458d5de6
221 files changed
+2584962 -568

No files matched your search

+202
View File
@@ -9,6 +9,7 @@ import {
loadAccountBossCards,
saveAccountBossCards,
replaceCharactersForOwner,
setRosterChangeListener,
deleteCharacter,
loadCombatPresentationSettings,
loginLocalAccount,
@@ -16,10 +17,12 @@ import {
saveSession,
updateCharacterActionBindings,
updateCharacterEquipment,
updateCharacterHunterPetFamily,
updateCharacterDungeonRunCheckpoint,
updateCharacterInventory,
updateCharacterManastormProgress,
updateCharacterProgression,
updateCharacterStatRuleset,
updateCharacterSettings,
updateCharacterSpecialization,
updateCombatPresentationSettings,
@@ -48,7 +51,206 @@ class MemoryStorage implements StorageLike {
removeItem(key: string) { this.values.delete(key); }
}
class FailingWriteStorage extends MemoryStorage {
failWrites = false;
setItem(key: string, value: string) {
if (this.failWrites) throw new Error("Storage quota exceeded.");
super.setItem(key, value);
}
}
describe("local profile repository", () => {
it("normalizes legacy Hunter family data to Wolf and persists implemented family choices", () => {
const storage = new MemoryStorage();
const hunter = createCharacter({
ownerId: "offline-roster",
name: "Shellguard",
categoryId: "wow",
raceId: "human",
classId: "hunter",
gender: "female",
appearance: { skinColor: 0, face: 0, hairStyle: 0, hairColor: 0, feature: 0 },
}, storage).character!;
expect(hunter.hunterPetFamily).toBe("wolf");
const cat = updateCharacterHunterPetFamily(hunter.ownerId, hunter.id, "cat", storage)!;
expect(cat.hunterPetFamily).toBe("cat");
expect(listCharacters(hunter.ownerId, storage)[0]?.hunterPetFamily).toBe("cat");
expect(updateCharacterHunterPetFamily(hunter.ownerId, hunter.id, "bear", storage)).toBeNull();
expect(listCharacters(hunter.ownerId, storage)[0]?.hunterPetFamily).toBe("cat");
const invalidStoredFamily = { ...cat, hunterPetFamily: "bear" } as unknown as typeof cat;
const [normalizedLegacy] = replaceCharactersForOwner(hunter.ownerId, [invalidStoredFamily], storage);
expect(normalizedLegacy?.hunterPetFamily).toBe("wolf");
});
it("defaults legacy saved characters to WoW stat rules and new RoM characters to native RoM", () => {
const storage = new MemoryStorage();
const legacyRom = {
id: "legacy-rom",
ownerId: "offline-roster",
name: "Old Healer",
categoryId: "rom",
raceId: "rom-human",
classId: "rom-priest",
gender: "female",
appearance: { skinColor: 0, face: 0, hairStyle: 0, hairColor: 0, feature: 0 },
level: 4,
location: "Dungeon Entrance",
createdAt: 1,
lastPlayedAt: 1,
};
storage.setItem(PROFILE_STORAGE_KEYS.database, JSON.stringify({
version: 7,
accounts: [],
rosters: { "offline-roster": [legacyRom] },
bossCardsByOwner: {},
presentationSettingsByOwner: {},
}));
expect(listCharacters("offline-roster", storage)[0]?.statRuleset).toBe("wow");
expect(JSON.parse(storage.getItem(PROFILE_STORAGE_KEYS.database)!).rosters["offline-roster"][0].statRuleset)
.toBe("wow");
const created = createCharacter({
ownerId: "offline-roster",
name: "New Healer",
categoryId: "rom",
raceId: "rom-human",
classId: "rom-priest",
gender: "female",
appearance: { skinColor: 0, face: 0, hairStyle: 0, hairColor: 0, feature: 0 },
}, storage).character!;
expect(created.statRuleset).toBe("rom");
});
it("keeps a legacy roster readable when its ruleset migration cannot be written", () => {
const storage = new FailingWriteStorage();
const character = createCharacter({
ownerId: "offline-roster", name: "Legacy Healer", classId: "rom-priest",
raceId: "rom-human", gender: "female",
appearance: { skinColor: 0, face: 0, hairStyle: 0, hairColor: 0, feature: 0 },
}, storage).character!;
const raw = JSON.parse(storage.getItem(PROFILE_STORAGE_KEYS.database)!);
delete raw.rosters[character.ownerId][0].statRuleset;
const legacySave = JSON.stringify(raw);
storage.setItem(PROFILE_STORAGE_KEYS.database, legacySave);
storage.failWrites = true;
expect(listCharacters(character.ownerId, storage)[0]).toMatchObject({
id: character.id, statRuleset: "wow",
});
expect(updateCharacterStatRuleset(character.ownerId, character.id, "rom", storage)).toBeNull();
expect(storage.getItem(PROFILE_STORAGE_KEYS.database)).toBe(legacySave);
expect(listCharacters(character.ownerId, storage)[0]?.statRuleset).toBe("wow");
storage.failWrites = false;
expect(listCharacters(character.ownerId, storage)[0]?.statRuleset).toBe("wow");
expect(JSON.parse(storage.getItem(PROFILE_STORAGE_KEYS.database)!).rosters[character.ownerId][0].statRuleset)
.toBe("wow");
});
it("switches one RoM profile while preserving its build and other characters", () => {
const storage = new MemoryStorage();
const first = createCharacter({
ownerId: "offline-roster",
name: "First",
categoryId: "rom",
raceId: "rom-human",
classId: "rom-priest",
secondaryClassId: "rom-mage",
actionLoadouts: { "rom-priest:rom-mage": { "primary:face-top": "rom-priest-heal" } },
gender: "female",
appearance: { skinColor: 0, face: 0, hairStyle: 0, hairColor: 0, feature: 0 },
}, storage).character!;
const item = {
instanceId: "kept-item",
itemId: 10412,
itemKey: "belt-of-the-fang",
name: "Belt of the Fang",
quality: "rare" as const,
inventorySlot: "waist",
armorType: "leather",
weaponType: null,
itemLevel: 17,
sourceItemLevel: 21,
stats: { ...EMPTY_ITEM_STATS, agility: 4, stamina: 4, armor: 15 },
quantity: 1,
sourceBossKey: "lady-anacondra",
sourceBossName: "Lady Anacondra",
acquiredAt: 5_000,
};
updateCharacterActionBindings(first.ownerId, first.id, { "primary:face-top": "rom-priest-heal" }, storage);
updateCharacterInventory(first.ownerId, first.id, [item], storage);
const second = createCharacter({
ownerId: "offline-roster",
name: "Second",
categoryId: "rom",
raceId: "rom-human",
classId: "rom-mage",
gender: "female",
appearance: { skinColor: 0, face: 0, hairStyle: 0, hairColor: 0, feature: 0 },
}, storage).character!;
const wowCharacter = createCharacter({
ownerId: "offline-roster",
name: "WoW Character",
categoryId: "wow",
raceId: "human",
classId: "priest",
gender: "female",
appearance: { skinColor: 0, face: 0, hairStyle: 0, hairColor: 0, feature: 0 },
}, storage).character!;
let cloudSnapshot: ReadonlyArray<ReturnType<typeof listCharacters>[number]> = [];
setRosterChangeListener((ownerId, characters) => {
if (ownerId === first.ownerId) cloudSnapshot = characters;
});
const updated = updateCharacterStatRuleset(first.ownerId, first.id, "wow", storage)!;
setRosterChangeListener(null);
expect(updated).toMatchObject({
statRuleset: "wow",
secondaryClassId: "rom-mage",
actionBindings: { "primary:face-top": "rom-priest-heal" },
actionLoadouts: { "rom-priest:rom-mage": { "primary:face-top": "rom-priest-heal" } },
inventory: [item],
});
expect(listCharacters(first.ownerId, storage).find((entry) => entry.id === first.id)?.statRuleset).toBe("wow");
expect(listCharacters(second.ownerId, storage).find((entry) => entry.id === second.id)?.statRuleset).toBe("rom");
expect(updateCharacterStatRuleset(first.ownerId, first.id, "rom", storage)?.statRuleset).toBe("rom");
expect(cloudSnapshot.find((entry) => entry.id === first.id)?.statRuleset).toBe("wow");
expect(updateCharacterDungeonRunCheckpoint(first.ownerId, first.id, {
version: DUNGEON_RUN_CHECKPOINT_VERSION,
dungeonId: "wailing-caverns",
difficultyId: "normal",
checkpointId: "entrance",
spawn: { footPosition: [-158, -82, 123], yaw: 0 },
encounters: [],
savedAt: 42,
}, storage)?.statRuleset).toBe("rom");
expect(updateCharacterStatRuleset(first.ownerId, second.id, "invalid", storage)).toBeNull();
expect(updateCharacterStatRuleset(first.ownerId, wowCharacter.id, "rom", storage)).toBeNull();
expect(updateCharacterStatRuleset(first.ownerId, "missing", "wow", storage)).toBeNull();
});
it("leaves the saved stat ruleset unchanged when storage rejects a switch", () => {
const storage = new FailingWriteStorage();
const character = createCharacter({
ownerId: "offline-roster",
name: "Steady",
categoryId: "rom",
raceId: "rom-human",
classId: "rom-priest",
gender: "female",
appearance: { skinColor: 0, face: 0, hairStyle: 0, hairColor: 0, feature: 0 },
}, storage).character!;
storage.failWrites = true;
expect(updateCharacterStatRuleset(character.ownerId, character.id, "wow", storage)).toBeNull();
storage.failWrites = false;
expect(listCharacters(character.ownerId, storage).find((entry) => entry.id === character.id)?.statRuleset)
.toBe("rom");
});
it("defaults new glyph loadouts to empty and persists explicit glyph choices", () => {
const storage = new MemoryStorage();
const character = createCharacter({
+66 -1
View File
@@ -33,6 +33,14 @@ import {
normalizeDungeonRunCheckpoint,
type DungeonRunCheckpoint,
} from "../game/dungeonRunCheckpoint";
import {
isWow335HunterPetFamily,
normalizeWow335HunterPetFamily,
} from "../game/wow335HunterPetFamilySelection";
import {
isCharacterStatRuleset,
normalizeCharacterStatRuleset,
} from "../game/characterStatRuleset";
const DATABASE_KEY = "healer-man.profile-database.v1";
const SESSION_KEY = "healer-man.session.v1";
@@ -123,6 +131,12 @@ function isCharacterProfile(value: unknown): value is CharacterProfile {
function normalizeCharacterProfile(value: CharacterProfile): CharacterProfile {
const profile = { ...value };
profile.statRuleset = normalizeCharacterStatRuleset(value.statRuleset, value.classId);
if (value.classId === "hunter") {
profile.hunterPetFamily = normalizeWow335HunterPetFamily(value.hunterPetFamily);
} else {
delete profile.hunterPetFamily;
}
// Cards now belong to the owner; legacy fields are consumed before normalization.
delete profile.bossCards;
const legacy = value as CharacterProfile & {
@@ -235,8 +249,13 @@ function readDatabase(storage: StorageLike | null = browserLocalStorage()): Prof
? parsed.bossCardsByOwner : {};
const bossCardsByOwner = Object.fromEntries(Object.entries(rawCards).map(([owner, cards]) => [owner, normalizeBossCardCollection(cards)]));
let cardsMigrated = false;
let statRulesetsMigrated = false;
const rosters = Object.fromEntries(Object.entries(parsed.rosters as Record<string, unknown>).map(([ownerId, roster]) => {
const characters = Array.isArray(roster) ? roster.filter(isCharacterProfile).slice(0, MAX_CHARACTERS) : [];
if (characters.some((character) => (
!isCharacterStatRuleset(character.statRuleset)
|| normalizeCharacterStatRuleset(character.statRuleset, character.classId) !== character.statRuleset
))) statRulesetsMigrated = true;
if (characters.some((character) => character.bossCards !== undefined)) {
const legacyCards = mergeBossCardCollections(characters.map((character) => character.bossCards), "sum");
bossCardsByOwner[ownerId] = mergeBossCardCollections([bossCardsByOwner[ownerId], legacyCards]);
@@ -278,7 +297,11 @@ function readDatabase(storage: StorageLike | null = browserLocalStorage()): Prof
const rawUi = parsed.uiPreferencesByOwner && typeof parsed.uiPreferencesByOwner === "object" ? parsed.uiPreferencesByOwner : {};
const uiPreferencesByOwner = Object.fromEntries(Object.entries(rawUi).map(([owner, value]) => [owner, normalizeUiPreferences(value)]));
const database: ProfileDatabase = { version: 7, accounts, rosters, bossCardsByOwner, presentationSettingsByOwner, uiPreferencesByOwner };
if (parsed.version !== 7 || presentationSettingsMigrated || cardsMigrated) writeDatabase(database, storage);
if (parsed.version !== 7 || presentationSettingsMigrated || cardsMigrated || statRulesetsMigrated) {
// A full or read-only device must still expose its existing roster.
// Retry migration on the next read when persistence is available.
try { writeDatabase(database, storage); } catch { /* Keep the normalized in-memory profiles. */ }
}
return database;
} catch {
return emptyDatabase();
@@ -535,6 +558,7 @@ export function createCharacter(
const now = Date.now();
const character = normalizeCharacterProfile({
...profile,
statRuleset: profile.statRuleset ?? (contentCategoryForClass(profile.classId) === "rom" ? "rom" : "wow"),
id: makeId("character"),
level: 1,
experience: 0,
@@ -553,6 +577,29 @@ export function createCharacter(
return { ok: true, character };
}
export function updateCharacterStatRuleset(
ownerId: string,
characterId: string,
value: unknown,
storage: StorageLike | null = browserLocalStorage(),
): CharacterProfile | null {
if (!storage || !isCharacterStatRuleset(value)) return null;
const database = readDatabase(storage);
let updated: CharacterProfile | null = null;
database.rosters[ownerId] = (database.rosters[ownerId] ?? []).map((character) => {
if (character.id !== characterId || contentCategoryForClass(character.classId) !== "rom") return character;
updated = normalizeCharacterProfile({ ...character, statRuleset: value });
return updated;
});
if (!updated) return null;
try {
writeDatabase(database, storage);
} catch {
return null;
}
return updated;
}
export function touchCharacter(
ownerId: string,
characterId: string,
@@ -788,6 +835,24 @@ export function updateCharacterEquipment(
return updated;
}
export function updateCharacterHunterPetFamily(
ownerId: string,
characterId: string,
family: unknown,
storage: StorageLike | null = browserLocalStorage(),
): CharacterProfile | null {
if (!storage || !isWow335HunterPetFamily(family)) return null;
const database = readDatabase(storage);
let updated: CharacterProfile | null = null;
database.rosters[ownerId] = (database.rosters[ownerId] ?? []).map((character) => {
if (character.id !== characterId || character.classId !== "hunter") return character;
updated = normalizeCharacterProfile({ ...character, hunterPetFamily: family });
return updated;
});
if (updated) writeDatabase(database, storage);
return updated;
}
export function loadAccountBossCards(
ownerId: string,
storage: StorageLike | null = browserLocalStorage(),
+6 -1
View File
@@ -1,6 +1,7 @@
import { dungeonById } from "../game/dungeonCatalog";
import { activateDungeonSession } from "../game/dungeonSession";
import { useGameStore } from "../game/store";
import { useCombatStore } from "../game/combatStore";
import {
classCanFillPartyRole,
defaultPartyRoleForClass,
@@ -15,7 +16,11 @@ import { dungeonContentIsUsable } from "../content/contentManager";
import { preparedBiteSizedRunSelection } from "./biteSizedLayoutContent";
export function installDungeonShellRuntime(): void {
registerDungeonShellRuntime({ enterDungeon });
registerDungeonShellRuntime({
enterDungeon,
canChangeCharacterStatRuleset: () => !Object.values(useCombatStore.getState().mobs)
.some((mob) => mob.engaged && !mob.dead),
});
}
function enterDungeon(dungeonId: string, requestedRole?: PartyRole, settings?: DungeonEntrySettings): boolean {
+1
View File
@@ -2,6 +2,7 @@ import type { PartyRole } from "../game/partyRoles";
export interface DungeonShellRuntime {
enterDungeon: (dungeonId: string, playerRole?: PartyRole, settings?: DungeonEntrySettings) => boolean;
canChangeCharacterStatRuleset?: () => boolean;
}
export interface DungeonEntrySettings {
+104
View File
@@ -6,6 +6,7 @@ import { installManastormShellRuntime } from "./manastormShellRuntime";
import { SHELVED_MODES_ENABLED } from "./releaseFeatures";
import { DUNGEON_MANIFEST } from "../game/dungeonManifest";
import { useGameStore } from "../game/store";
import { useCombatStore } from "../game/combatStore";
import { useManastormStore } from "../game/manastormStore";
import { createEmptyManastormProgress, recordManastormCheckpoint } from "../game/manastormProgress";
import {
@@ -21,6 +22,8 @@ import {
resolveBossAdminEntry,
} from "../game/manastormAdminConfig";
import { useManastormAdminStore } from "../game/manastormAdminStore";
import { createCharacter, listCharacters, type StorageLike } from "./accountRepository";
import { useOnlineGroupStore } from "./onlineGroupStore";
installDungeonShellRuntime();
installManastormShellRuntime();
@@ -62,6 +65,20 @@ function readyBossForMode(modeId: number) {
const readyLevelingBoss = readyBossForMode(0);
const readyEndgameBoss = readyBossForMode(2);
if (!readyLevelingBoss || !readyEndgameBoss) throw new Error("Shell tests require runnable Manastorm bosses for both modes.");
class MemoryStorage implements StorageLike {
private values = new Map<string, string>();
getItem(key: string) { return this.values.get(key) ?? null; }
setItem(key: string, value: string) { this.values.set(key, value); }
removeItem(key: string) { this.values.delete(key); }
}
class FailingWriteStorage extends MemoryStorage {
failWrites = false;
setItem(key: string, value: string) {
if (this.failWrites) throw new Error("Storage quota exceeded.");
super.setItem(key, value);
}
}
const readyTestConfig = {
...DEFAULT_MANASTORM_ADMIN_CONFIG,
bosses: {
@@ -84,9 +101,11 @@ function prepareSelectedCharacter(): void {
describe("shell store", () => {
afterEach(() => {
vi.unstubAllEnvs();
vi.unstubAllGlobals();
});
beforeEach(() => {
useOnlineGroupStore.getState().reset();
useShellStore.setState({
phase: "login",
session: null,
@@ -108,6 +127,91 @@ describe("shell store", () => {
expect(useShellStore.getState().notice).toMatch(/select or create/i);
});
it("saves a Hunter's selected family to the active character and local roster", () => {
const storage = new MemoryStorage();
vi.stubGlobal("window", { localStorage: storage });
const hunter = createCharacter({
ownerId: "offline-roster",
name: "Turtlekeeper",
categoryId: "wow",
raceId: "human",
classId: "hunter",
specializationId: "hunter:marksmanship",
gender: "female",
appearance: createDefaultAppearance(),
}, storage).character!;
useShellStore.setState({
session: { kind: "offline", ownerId: hunter.ownerId, displayName: "Offline" },
characters: [hunter],
activeCharacter: hunter,
});
expect(useShellStore.getState().saveActiveHunterPetFamily("turtle")).toBe(true);
expect(useShellStore.getState().activeCharacter?.hunterPetFamily).toBe("turtle");
expect(listCharacters(hunter.ownerId, storage)[0]?.hunterPetFamily).toBe("turtle");
expect(useShellStore.getState().saveActiveHunterPetFamily("cat")).toBe(true);
expect(useShellStore.getState().activeCharacter?.hunterPetFamily).toBe("cat");
expect(listCharacters(hunter.ownerId, storage)[0]?.hunterPetFamily).toBe("cat");
});
it("switches the selected RoM stat profile only from the main menu and reports storage failure", () => {
const storage = new FailingWriteStorage();
vi.stubGlobal("window", { localStorage: storage });
const romCharacter = createCharacter({
ownerId: "offline-roster",
name: "Runekeeper",
categoryId: "rom",
raceId: "rom-human",
classId: "rom-priest",
gender: "female",
appearance: createDefaultAppearance(),
}, storage).character!;
useShellStore.setState({
phase: "main-menu",
session: { kind: "offline", ownerId: romCharacter.ownerId, displayName: "Offline" },
characters: [romCharacter],
selectedCharacterId: romCharacter.id,
activeCharacter: null,
});
expect(useShellStore.getState().setSelectedCharacterStatRuleset("wow")).toBe(true);
expect(useShellStore.getState().characters[0]?.statRuleset).toBe("wow");
expect(listCharacters(romCharacter.ownerId, storage)[0]?.statRuleset).toBe("wow");
storage.failWrites = true;
expect(useShellStore.getState().setSelectedCharacterStatRuleset("rom")).toBe(false);
expect(useShellStore.getState().characters[0]?.statRuleset).toBe("wow");
expect(useShellStore.getState().notice).toMatch(/could not be saved/i);
storage.failWrites = false;
const previousMobs = useCombatStore.getState().mobs;
try {
useCombatStore.setState({ mobs: { "live-fight": { engaged: true, dead: false } as never } });
expect(useShellStore.getState().setSelectedCharacterStatRuleset("rom")).toBe(false);
expect(useShellStore.getState().notice).toMatch(/combat is active/i);
expect(listCharacters(romCharacter.ownerId, storage)[0]?.statRuleset).toBe("wow");
} finally {
useCombatStore.setState({ mobs: previousMobs });
}
useShellStore.setState({ activeCharacter: romCharacter });
expect(useShellStore.getState().setSelectedCharacterStatRuleset("rom")).toBe(false);
useShellStore.setState({ activeCharacter: null });
useOnlineGroupStore.setState({ snapshot: {
group: { activity: { id: "live-run" } } as never,
invitations: [],
} });
useShellStore.setState({ phase: "main-menu", notice: "" });
expect(useShellStore.getState().setSelectedCharacterStatRuleset("rom")).toBe(false);
expect(useShellStore.getState().characters[0]?.statRuleset).toBe("wow");
expect(useShellStore.getState().notice).toMatch(/live online group activity/i);
useOnlineGroupStore.getState().reset();
useShellStore.setState({ phase: "game", notice: "" });
expect(useShellStore.getState().setSelectedCharacterStatRuleset("rom")).toBe(false);
expect(useShellStore.getState().characters[0]?.statRuleset).toBe("wow");
expect(listCharacters(romCharacter.ownerId, storage)[0]?.statRuleset).toBe("wow");
});
it("routes a legacy WoW character through the mandatory specialization picker", () => {
prepareSelectedCharacter();
useShellStore.setState({ characters: [{ ...character, specializationId: null }] });
+47
View File
@@ -12,6 +12,8 @@ import {
updateCharacterActionBindings,
updateCharacterEquipment,
updateCharacterInventory,
updateCharacterHunterPetFamily,
updateCharacterStatRuleset,
saveAccountBossCards as persistAccountBossCards,
updateCharacterManastormProgress,
updateCharacterDungeonRunCheckpoint,
@@ -119,6 +121,8 @@ export interface ShellState {
saveActiveInventory: (inventory: readonly InventoryItem[]) => void;
saveAccountBossCards: (bossCards: BossCardCollection) => void;
saveActiveEquipment: (equipment: EquipmentAssignments) => void;
saveActiveHunterPetFamily: (family: unknown) => boolean;
setSelectedCharacterStatRuleset: (ruleset: unknown) => boolean;
saveActiveSettings: (settings: GameplaySettings) => void;
updateCombatPresentationSettings: (patch: Partial<CombatPresentationSettings>) => void;
resetCombatPresentationSettings: () => void;
@@ -286,6 +290,7 @@ export const useShellStore = create<ShellState>((set, get) => ({
categoryId: draft.categoryId,
raceId: draft.raceId,
classId: draft.classId,
statRuleset: draft.categoryId === "rom" ? "rom" : "wow",
specializationId: draft.categoryId === "rom" ? null : draft.specializationId,
gender: draft.gender,
appearance: clampAppearance(draft.raceId, draft.gender, draft.appearance),
@@ -595,6 +600,48 @@ export const useShellStore = create<ShellState>((set, get) => ({
characters: state.characters.map((character) => character.id === updated.id ? updated : character),
}));
},
saveActiveHunterPetFamily: (family) => {
const { session, activeCharacter } = get();
if (!session || !activeCharacter || activeCharacter.classId !== "hunter") return false;
const updated = updateCharacterHunterPetFamily(
session.ownerId,
activeCharacter.id,
family,
);
if (!updated) return false;
set((state) => ({
activeCharacter: updated,
characters: state.characters.map((character) => character.id === updated.id ? updated : character),
}));
return true;
},
setSelectedCharacterStatRuleset: (ruleset) => {
const { phase, session, selectedCharacterId, activeCharacter } = get();
if (phase !== "main-menu" || !session || !selectedCharacterId) return false;
if (activeCharacter || dungeonShellRuntime()?.canChangeCharacterStatRuleset?.() === false) {
set({ notice: "Stat profiles cannot change while combat is active. Finish leaving the expedition first." });
return false;
}
if (useOnlineGroupStore.getState().snapshot.group?.activity) {
set({ notice: "Stat profiles cannot change during a live online group activity." });
return false;
}
const updated = updateCharacterStatRuleset(
session.ownerId,
selectedCharacterId,
ruleset,
);
if (!updated) {
set({ notice: "Stat profile could not be saved. Check device storage and try again." });
return false;
}
set((state) => ({
characters: state.characters.map((character) => character.id === updated.id ? updated : character),
activeCharacter: state.activeCharacter?.id === updated.id ? updated : state.activeCharacter,
notice: "Stat profile saved.",
}));
return true;
},
saveActiveSettings: (settings) => {
const { session, activeCharacter } = get();
if (!session || !activeCharacter) return;
+6
View File
@@ -6,6 +6,8 @@ import type { GameplaySettings } from "../game/combatStore";
import type { ManastormProgress } from "../game/manastormProgress";
import type { DungeonRunCheckpoint } from "../game/dungeonRunCheckpoint";
import type { BossCardCollection } from "../game/bossCards";
import type { Wow335HunterPetFamily } from "../game/wow335HunterPetFamilySelection";
import type { CharacterStatRuleset } from "../game/characterStatRuleset";
export type ShellPhase = "login" | "characters" | "create-character" | "main-menu" | "class-hall" | "dungeons" | "manastorms" | "arenas" | "arena-game" | "gm-admin" | "bite-sized-editor" | "game";
export type SessionKind = "account" | "offline";
@@ -32,6 +34,10 @@ export interface CharacterProfile {
categoryId?: ContentCategoryId;
/** RoM's inactive class. The active primary remains `classId`. */
secondaryClassId?: RomClassId | null;
/** Optional for legacy profile inputs; repository-normalized profiles always include a value. */
statRuleset?: CharacterStatRuleset;
/** Persisted choice for a Hunter's current pet family; legacy profiles default to Wolf. */
hunterPetFamily?: Wow335HunterPetFamily;
gender: GenderId;
appearance: CharacterAppearance;
level: number;
+1 -1
View File
@@ -197,7 +197,7 @@ export type AbilityEffect =
readonly resource?: ResourceType;
readonly percentage?: boolean;
/** Party-scoped resource effects use the ability's radius and targeting shape. */
readonly scope?: "target" | "party";
readonly scope?: "target" | "party" | "caster";
}
| { readonly kind: "combo"; readonly amount: number }
| { readonly kind: "taunt"; readonly durationMs: number; readonly maxTargets?: number }
+10 -1
View File
@@ -21,7 +21,16 @@ export function arenaAbilityIsLearned(ability: AbilityDefinition, character: Cha
}
export function createArenaCharacterKit(character: CharacterProfile, level = character.level): ArenaCharacterKit {
const stats = deriveCharacterStats(character.classId, level, activeEquipmentStatsForClass(character.equipment, character.inventory, PLAYER_EQUIPMENT_OWNER_ID, character.classId), character.raceId, {}, character.secondaryClassId);
const stats = deriveCharacterStats(
character.classId,
level,
activeEquipmentStatsForClass(character.equipment, character.inventory, PLAYER_EQUIPMENT_OWNER_ID, character.classId),
character.raceId,
{},
character.secondaryClassId,
character.gender,
character.statRuleset ?? "wow",
);
const profile = resourceProfileForClass(character.classId);
const resource = profile.type === "mana" ? { ...profile, maximum: stats.mana, initial: stats.mana, regenerationPerSecond: stats.mana * 0.004 } : profile;
const abilities = arenaCharacterAbilities(character, level).filter((ability) => arenaAbilityIsLearned(ability, character, level));
+25
View File
@@ -0,0 +1,25 @@
import { describe, expect, it } from "vitest";
import {
isCharacterStatRuleset,
normalizeCharacterStatRuleset,
} from "./characterStatRuleset";
describe("character stat ruleset", () => {
it("validates supported profile values", () => {
expect(isCharacterStatRuleset("wow")).toBe(true);
expect(isCharacterStatRuleset("rom")).toBe(true);
expect(isCharacterStatRuleset("RoM")).toBe(false);
expect(isCharacterStatRuleset(undefined)).toBe(false);
});
it("keeps missing and invalid saved values on WoW behavior", () => {
expect(normalizeCharacterStatRuleset(undefined, "rom-priest")).toBe("wow");
expect(normalizeCharacterStatRuleset("invalid", "rom-priest")).toBe("wow");
});
it("accepts native RoM only for a RoM class", () => {
expect(normalizeCharacterStatRuleset("rom", "rom-priest")).toBe("rom");
expect(normalizeCharacterStatRuleset("rom", "priest")).toBe("wow");
expect(normalizeCharacterStatRuleset("wow", "rom-priest")).toBe("wow");
});
});
+15
View File
@@ -0,0 +1,15 @@
import { isRomClassId, type ClassId } from "../app/characterCatalog";
export type CharacterStatRuleset = "wow" | "rom";
export function isCharacterStatRuleset(value: unknown): value is CharacterStatRuleset {
return value === "wow" || value === "rom";
}
/** Missing or invalid saved/runtime values keep the historical WoW behavior. */
export function normalizeCharacterStatRuleset(
value: unknown,
classId: ClassId,
): CharacterStatRuleset {
return value === "rom" && isRomClassId(classId) ? "rom" : "wow";
}
@@ -0,0 +1,30 @@
import { describe, expect, it } from "vitest";
import type { ClassId, RaceId } from "../app/characterCatalog";
import fixture from "./generated/characterStatRulesetCompatibility.json";
import type { ItemStats } from "./itemStats";
import { deriveCharacterStats } from "./wotlkStats";
describe("saved-character stat compatibility", () => {
for (const row of fixture.rows) {
it(`preserves frozen ${row.classId} level ${row.level} stats with and without an explicit WoW profile`, () => {
const args = [
row.classId as ClassId,
row.level,
fixture.gear as ItemStats,
row.raceId as RaceId,
fixture.modifiers,
row.secondaryClassId as ClassId | null,
] as const;
for (const stats of [
deriveCharacterStats(...args),
deriveCharacterStats(...args, undefined, "wow"),
]) {
// Compare the pre-existing outputs; extra ruleset metadata may be added.
expect(Object.fromEntries(Object.keys(row.expected).map((key) => [
key,
stats[key as keyof typeof stats],
]))).toEqual(row.expected);
}
});
}
});
@@ -0,0 +1,617 @@
import { beforeEach, describe, expect, it } from "vitest";
import {
PLAYER_AURA_ENTITY_ID,
auraAdjustedCharacterStats,
useCombatStore,
equipmentAdjustedCombatAmount,
} from "./combatStore";
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
import {
clearPartyRuntimeRegistry,
registerPartyRuntimePosition,
updatePartyRuntimePosition,
updatePartyRuntimeTargetVisibility,
} from "./partyRuntimeRegistry";
import { createConfiguredPartyMember, usePartyStore } from "./partyStore";
import { EMPTY_ITEM_STATS } from "./itemStats";
import { deriveCharacterStats } from "./wotlkStats";
import { ROM_ALL_ABILITIES } from "./romAbilityCatalog";
import { advanceDungeonPartyCombat, resetPartyRuntimeClock } from "./partyRuntime";
import { usePartyBuffPolicyStore } from "./partyBuffPolicyStore";
import {
ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG,
ROM_MAGE_DRUID_GREEN_GUARDIAN_SKILL_ID,
romMageDruidGreenGuardianMovementSpeedMultiplier,
} from "./romMageDruidGreenGuardianRuntime";
import { applyRomNativeStatModifiers, type RomNativeGearStats } from "./romNativeStats";
import { romPriestHolyBlessingWisdom } from "./romPriestHolyBlessingRuntime";
const manaAuraAbility = ROM_ALL_ABILITIES.find((ability) => ability.id === "rom-priest-general-2")!;
const chainOfLight = ROM_ALL_ABILITIES.find((ability) => ability.dbcSpellId === 491_164
&& ability.classId === "rom-priest" && !ability.secondaryClassId);
function nativeTrinket(
instanceId: string,
romNative: RomNativeGearStats,
otherStats: Partial<typeof EMPTY_ITEM_STATS> = {},
) {
return {
instanceId,
itemId: 990_001,
itemKey: instanceId,
name: "Native stat test trinket",
quality: "rare" as const,
inventorySlot: "trinket",
armorType: null,
weaponType: null,
itemLevel: 30,
sourceItemLevel: 30,
stats: { ...EMPTY_ITEM_STATS, ...otherStats, romNative },
quantity: 1,
sourceBossKey: "integration-test",
sourceBossName: "Integration Test",
acquiredAt: 0,
};
}
function nativeCompanionSwingDamage(physicalAttack: number, foreignWowRatings = false): number {
clearMobRuntimeRegistry();
clearPartyRuntimeRegistry();
resetPartyRuntimeClock();
useCombatStore.getState().initializeCharacter({ classId: "rom-priest", raceId: "rom-human", level: 30 });
const targetId = "native-physical-attack-target";
const member = createConfiguredPartyMember({
name: "Native Attack Warrior",
classId: "rom-warrior",
raceId: "rom-human",
specialization: "Primary",
role: "damage",
statRuleset: "rom",
}, 30, 0, "native-physical-attack-warrior");
usePartyStore.getState().initializeParty(
`native-physical-attack-${physicalAttack}-${foreignWowRatings}`, 30,
useCombatStore.getState().health, "damage", 1, "rom",
);
usePartyStore.setState({
members: [{
...member,
gearStats: {
...EMPTY_ITEM_STATS,
...(foreignWowRatings ? {
attackPower: 2_000_000,
criticalStrikeRating: 2_000_000,
hitRating: 2_000_000,
} : {}),
romNative: { physicalAttack },
},
}],
command: "attack",
activeMobId: targetId,
});
registerPartyRuntimePosition(member.id, [0, 0, 0]);
useCombatStore.getState().synchronizeActors();
useCombatStore.getState().registerMob(targetId, {
name: "Native physical attack target", level: 30, maxHealth: 1_000_000, xpReward: 0,
});
setMobPosition(targetId, [2, 0, 0]);
useCombatStore.getState().damageMob(targetId, 1, 100);
updatePartyRuntimeTargetVisibility(member.id, targetId, true);
advanceDungeonPartyCombat(1_000);
const swing = useCombatStore.getState().combatEvents.find((event) => (
event.kind === "damage" && event.sourceActorId === member.id
&& event.targetActorId === targetId && event.abilityId === "party-auto-attack"
));
if (!swing) throw new Error("Native warrior companion did not produce its expected autoattack");
return swing.rawAmount;
}
function playerChannelTiming(ruleset: "wow" | "rom", hasteRating: number): {
castMs: number;
gcdMs: number;
} {
if (!chainOfLight) throw new Error("Missing generated RoM Priest Chain of Light channel");
const item = nativeTrinket(`channel-timing-${ruleset}-${hasteRating}`, {}, { hasteRating });
useCombatStore.getState().initializeCharacter({
classId: "rom-priest",
raceId: "rom-human",
level: 30,
statRuleset: ruleset,
inventory: [item],
equipment: { player: { trinket: item.instanceId } },
});
useCombatStore.getState().synchronizeActors();
useCombatStore.getState().registerMob("channel-timing-target", {
name: "Channel timing target", level: 30, maxHealth: 10_000_000, xpReward: 0,
});
setMobPosition("channel-timing-target", [3, 0, 0]);
useCombatStore.getState().selectMob("channel-timing-target");
const now = 20_000;
expect(useCombatStore.getState().castAbility(chainOfLight.id, undefined, now)).toMatchObject({ ok: true });
const state = useCombatStore.getState();
const activeCast = state.activeCast;
if (!activeCast) throw new Error("Chain of Light did not start a timed cast");
return {
castMs: activeCast.completesAt - activeCast.startedAt,
gcdMs: state.globalCooldownEndsAt - activeCast.startedAt,
};
}
function temporaryManaAura(percent = 0.5) {
return {
kind: "apply-aura" as const,
recipient: "caster" as const,
aura: {
id: "character-stat-ruleset:test-mana-cap",
name: "Mana Pool Test Aura",
disposition: "buff" as const,
durationMs: 2_000,
maxStacks: 1,
stackBehavior: "refresh" as const,
modifiers: [{
kind: "resource" as const,
resource: "mana",
property: "maximum" as const,
operation: "percent" as const,
value: percent,
perStack: false,
}],
},
sourceEffectType: -1,
sourceAuraType: -1,
miscValue: 0,
triggerSpellId: 0,
};
}
function castPlayerChannel(ruleset: "wow" | "rom", gear: RomNativeGearStats): {
actorRuleset: string | undefined;
amounts: number[];
} {
if (!chainOfLight) throw new Error("Missing generated RoM Priest Chain of Light channel");
const item = nativeTrinket(`channel-${ruleset}-native-trinket`, gear);
useCombatStore.getState().initializeCharacter({
classId: "rom-priest",
raceId: "rom-human",
level: 30,
statRuleset: ruleset,
inventory: [item],
equipment: { player: { trinket: item.instanceId } },
});
useCombatStore.getState().synchronizeActors();
useCombatStore.getState().registerMob("native-channel-target", {
name: "Native channel target", level: 30, maxHealth: 10_000_000, xpReward: 0,
});
setMobPosition("native-channel-target", [3, 0, 0]);
useCombatStore.getState().selectMob("native-channel-target");
const actorRuleset = useCombatStore.getState().actors[PLAYER_AURA_ENTITY_ID]?.statRuleset;
expect(useCombatStore.getState().castAbility(chainOfLight.id, undefined, 10_000)).toMatchObject({ ok: true });
for (const now of [11_000, 12_000, 13_000, 14_000]) useCombatStore.getState().tick(1, now);
const amounts = useCombatStore.getState().combatEvents
.filter((event) => event.kind === "damage" && event.abilityId === chainOfLight.id)
.map((event) => event.rawAmount);
return { actorRuleset, amounts };
}
describe("selectable native RoM character stat ruleset runtime integration", () => {
beforeEach(() => {
clearMobRuntimeRegistry();
clearPartyRuntimeRegistry();
useCombatStore.getState().initializeCharacter({ classId: "rom-priest", raceId: "rom-human", level: 30 });
usePartyStore.getState().initializeParty(
"native-stat-ruleset-integration", 30, useCombatStore.getState().health, "damage", 5, "rom",
);
});
it("threads the explicit native ruleset through the player and generated companion actor snapshots while omitted seeds stay legacy", () => {
useCombatStore.getState().initializeCharacter({
classId: "rom-priest",
secondaryClassId: "rom-knight",
raceId: "rom-human",
level: 30,
statRuleset: "rom",
});
usePartyStore.getState().initializeParty(
"native-stat-ruleset-actors", 30, useCombatStore.getState().health, "damage", 5, "rom",
);
useCombatStore.getState().synchronizeActors();
const state = useCombatStore.getState();
const playerActor = state.actors[PLAYER_AURA_ENTITY_ID];
const companions = usePartyStore.getState().members;
expect(state.statRuleset).toBe("rom");
expect(playerActor?.statRuleset).toBe("rom");
expect(playerActor?.resources.mana?.maximum).toBe(state.maxResourcePools.mana);
expect(companions.length).toBeGreaterThan(0);
for (const companion of companions) {
expect(companion.statRuleset).toBe("rom");
expect(state.actors[companion.id]?.statRuleset).toBe("rom");
expect(state.actors[companion.id]?.resources.mana?.maximum).toBe(companion.resourceMaximums?.mana);
}
const rageCaster = createConfiguredPartyMember({
name: "Native Warrior Priest",
classId: "rom-warrior",
secondaryClassId: "rom-priest",
raceId: "rom-human",
specialization: "Warrior/Priest",
role: "damage",
statRuleset: "rom",
}, 10, 0, "native-rage-caster-companion");
usePartyStore.setState((party) => ({ members: [...party.members, rageCaster] }));
useCombatStore.getState().synchronizeActors();
const rageCasterActor = useCombatStore.getState().actors[rageCaster.id];
const rageCasterNative = deriveCharacterStats(
"rom-warrior", 10, rageCaster.gearStats, rageCaster.raceId, {}, "rom-priest", rageCaster.gender, "rom",
).romNative;
expect(rageCasterNative?.usesMana).toBe(true);
expect(rageCaster.resourceMaximums?.mana).toBeCloseTo(rageCasterNative!.mana.max);
expect(rageCaster.resourcePools.mana).toBeCloseTo(rageCaster.resourceMaximums!.mana!, 0);
expect(rageCasterActor?.statRuleset).toBe("rom");
expect(rageCasterActor?.resources.mana?.maximum).toBeCloseTo(rageCasterNative!.mana.max);
expect(rageCasterActor?.resources.mana?.current).toBeCloseTo(rageCaster.resourcePools.mana!, 0);
useCombatStore.getState().initializeCharacter({ classId: "rom-priest", raceId: "rom-human", level: 30 });
useCombatStore.getState().synchronizeActors();
expect(useCombatStore.getState().statRuleset).toBe("wow");
expect(useCombatStore.getState().actors[PLAYER_AURA_ENTITY_ID]?.statRuleset).toBe("wow");
});
it("activates the canonical secondary at level 10 and mirrors the native Mana cap and current value", () => {
usePartyStore.getState().initializeParty(
"native-level-gate", 9, useCombatStore.getState().health, "damage", 5, "rom",
);
const before = createConfiguredPartyMember({
name: "Serenna",
classId: "rom-priest",
secondaryClassId: "rom-knight",
raceId: "rom-human",
specialization: "Primary",
role: "healer",
statRuleset: "rom",
}, 9, 0, "native-level-gate-canonical-member");
usePartyStore.setState({ members: [before] });
expect(before).toMatchObject({ classId: "rom-priest", level: 9, secondaryClassId: null, statRuleset: "rom" });
useCombatStore.getState().synchronizeActors();
usePartyStore.getState().syncLevel(10);
useCombatStore.getState().synchronizeActors();
const after = usePartyStore.getState().members.find((member) => member.name === "Serenna");
const actor = useCombatStore.getState().actors[after!.id];
const native = deriveCharacterStats(
"rom-priest", 10, after!.gearStats, after!.raceId, {}, "rom-knight", after!.gender, "rom",
).romNative;
expect(after).toMatchObject({ level: 10, secondaryClassId: "rom-knight", statRuleset: "rom" });
expect(native?.usesMana).toBe(true);
expect(after!.resourceMaximums?.mana).toBeCloseTo(native!.mana.max);
expect(after!.resourcePools.mana).toBeCloseTo(after!.resourceMaximums!.mana!, 0);
expect(actor?.statRuleset).toBe("rom");
expect(actor?.resources.mana?.maximum).toBeCloseTo(native!.mana.max);
expect(actor?.resources.mana?.current).toBeCloseTo(after!.resourcePools.mana!, 0);
});
it("keeps player and companion Mana current values and actor mirrors in step across a native maximum-Mana aura expiry", () => {
useCombatStore.getState().initializeCharacter({
classId: "rom-priest", secondaryClassId: "rom-knight", raceId: "rom-human", level: 30, statRuleset: "rom",
});
const companion = createConfiguredPartyMember({
name: "Native Mana Priest",
classId: "rom-priest",
secondaryClassId: "rom-knight",
raceId: "rom-human",
specialization: "Primary",
role: "healer",
statRuleset: "rom",
}, 30, 0, "native-mana-aura-companion");
usePartyStore.setState({ members: [companion] });
useCombatStore.getState().synchronizeActors();
const basePlayerMaximum = useCombatStore.getState().maxResourcePools.mana!;
const baseCompanionMaximum = useCombatStore.getState().actors[companion.id]!.resources.mana!.maximum;
const playerCurrentBefore = useCombatStore.getState().resourcePools.mana!;
const companionCurrentBefore = useCombatStore.getState().actors[companion.id]!.resources.mana!.current;
const effect = temporaryManaAura();
expect(useCombatStore.getState().applyActorAura(PLAYER_AURA_ENTITY_ID, PLAYER_AURA_ENTITY_ID, manaAuraAbility, effect, 1_000)).toBe(true);
expect(useCombatStore.getState().applyActorAura(PLAYER_AURA_ENTITY_ID, companion.id, manaAuraAbility, effect, 1_000)).toBe(true);
const increasedPlayerMaximum = useCombatStore.getState().maxResourcePools.mana!;
const increasedCompanionMaximum = useCombatStore.getState().actors[companion.id]!.resources.mana!.maximum;
expect(increasedPlayerMaximum).toBeCloseTo(basePlayerMaximum * 1.5);
expect(increasedCompanionMaximum).toBeCloseTo(baseCompanionMaximum * 1.5);
expect(useCombatStore.getState().resourcePools.mana).toBe(playerCurrentBefore);
expect(useCombatStore.getState().actors[PLAYER_AURA_ENTITY_ID]?.resources.mana?.current).toBe(playerCurrentBefore);
expect(useCombatStore.getState().actors[companion.id]?.resources.mana?.current).toBe(companionCurrentBefore);
expect(usePartyStore.getState().members[0]?.resourcePools.mana).toBe(companionCurrentBefore);
expect(usePartyStore.getState().members[0]?.resourceMaximums?.mana).toBeCloseTo(increasedCompanionMaximum);
useCombatStore.getState().restoreActorResource(PLAYER_AURA_ENTITY_ID, "mana", increasedPlayerMaximum);
useCombatStore.getState().restoreActorResource(companion.id, "mana", increasedCompanionMaximum);
expect(useCombatStore.getState().resourcePools.mana).toBeCloseTo(increasedPlayerMaximum);
expect(usePartyStore.getState().members[0]?.resourcePools.mana).toBeCloseTo(increasedCompanionMaximum);
const resourceOnlyPlayerMaximum = useCombatStore.getState().maxResourcePools.mana!;
const resourceOnlyCompanionMaximum = useCombatStore.getState().actors[companion.id]!.resources.mana!.maximum;
const gmWisdomEffect = {
kind: "apply-aura" as const,
recipient: "caster" as const,
aura: {
id: "character-stat-ruleset:gm-wisdom",
name: "GM Wisdom Test Buff",
disposition: "buff" as const,
durationMs: null,
exclusiveGroup: "gm-party-buff:test-wisdom",
modifiers: [{ kind: "stat" as const, stat: "wisdom", operation: "flat" as const, value: 30 }],
},
sourceEffectType: -1,
sourceAuraType: -1,
miscValue: 0,
triggerSpellId: 0,
};
expect(useCombatStore.getState().applyActorAura(
PLAYER_AURA_ENTITY_ID, PLAYER_AURA_ENTITY_ID, manaAuraAbility, gmWisdomEffect, 1_500,
)).toBe(true);
expect(useCombatStore.getState().applyActorAura(
PLAYER_AURA_ENTITY_ID, companion.id, manaAuraAbility, gmWisdomEffect, 1_500,
)).toBe(true);
const gmPlayerMaximum = useCombatStore.getState().maxResourcePools.mana!;
const gmCompanionMaximum = useCombatStore.getState().actors[companion.id]!.resources.mana!.maximum;
expect(gmPlayerMaximum).toBeGreaterThan(resourceOnlyPlayerMaximum);
expect(gmCompanionMaximum).toBeGreaterThan(resourceOnlyCompanionMaximum);
useCombatStore.getState().restoreActorResource(PLAYER_AURA_ENTITY_ID, "mana", gmPlayerMaximum);
useCombatStore.getState().restoreActorResource(companion.id, "mana", gmCompanionMaximum);
usePartyBuffPolicyStore.setState({
config: { schemaVersion: 1, rules: [] },
draft: { schemaVersion: 1, rules: [] },
});
useCombatStore.getState().applyDefaultPartyBuffs(2_000);
expect(useCombatStore.getState().auras.some((aura) => aura.definition.id === gmWisdomEffect.aura.id)).toBe(false);
expect(useCombatStore.getState().maxResourcePools.mana).toBeCloseTo(resourceOnlyPlayerMaximum);
expect(useCombatStore.getState().resourcePools.mana).toBeCloseTo(resourceOnlyPlayerMaximum);
expect(useCombatStore.getState().actors[PLAYER_AURA_ENTITY_ID]?.resources.mana).toMatchObject({
current: resourceOnlyPlayerMaximum,
maximum: resourceOnlyPlayerMaximum,
});
expect(useCombatStore.getState().actors[companion.id]?.resources.mana).toMatchObject({
current: resourceOnlyCompanionMaximum,
maximum: resourceOnlyCompanionMaximum,
});
expect(usePartyStore.getState().members[0]?.resourcePools.mana).toBeCloseTo(resourceOnlyCompanionMaximum);
expect(usePartyStore.getState().members[0]?.resourceMaximums?.mana).toBeCloseTo(resourceOnlyCompanionMaximum);
useCombatStore.getState().tick(0, 3_000);
expect(useCombatStore.getState().maxResourcePools.mana).toBeCloseTo(basePlayerMaximum);
expect(useCombatStore.getState().resourcePools.mana).toBeCloseTo(basePlayerMaximum);
expect(useCombatStore.getState().actors[PLAYER_AURA_ENTITY_ID]?.resources.mana).toMatchObject({
current: basePlayerMaximum,
maximum: basePlayerMaximum,
});
expect(useCombatStore.getState().actors[companion.id]?.resources.mana).toMatchObject({
current: baseCompanionMaximum,
maximum: baseCompanionMaximum,
});
expect(usePartyStore.getState().members[0]?.resourcePools.mana).toBeCloseTo(baseCompanionMaximum);
expect(usePartyStore.getState().members[0]?.resourceMaximums?.mana).toBeCloseTo(baseCompanionMaximum);
});
it("applies native Holy Blessing after a native Wisdom BodyRate and ordinary Wisdom aura without changing MDMG", () => {
const gear = { wisdom: 35, wisdomRateFactor: 1.45, magicalDamage: 180, magicalDamageRateFactor: 1.2 };
const item = nativeTrinket("native-wisdom-test-trinket", gear);
useCombatStore.getState().initializeCharacter({
classId: "rom-priest",
raceId: "rom-human",
level: 30,
statRuleset: "rom",
inventory: [item],
equipment: { player: { trinket: item.instanceId } },
});
useCombatStore.getState().synchronizeActors();
const before = useCombatStore.getState();
const blessingActive = before.auras.some((aura) => aura.targetId === PLAYER_AURA_ENTITY_ID
&& aura.definition.name === "Holy Blessing");
expect(blessingActive).toBe(true);
const base = deriveCharacterStats(
"rom-priest", 30, before.gearStats, before.raceId, {}, null, before.gender, "rom",
).romNative!;
const ordinaryWisdom = applyRomNativeStatModifiers(base, {
attributes: { wisdom: 30 },
rates: { wisdom: 1.2 },
});
const wisdomAfterBlessing = romPriestHolyBlessingWisdom(ordinaryWisdom.attributes.wisdom);
const blessingRate = ordinaryWisdom.rateFactors.wisdom * ordinaryWisdom.rateFactors.allAttributes;
const expected = applyRomNativeStatModifiers(ordinaryWisdom, {
attributes: { wisdom: (wisdomAfterBlessing - ordinaryWisdom.attributes.wisdom) / blessingRate },
});
expect(expected.magicalDamage).toBeCloseTo(base.magicalDamage);
const wisdomAura = {
kind: "apply-aura" as const,
recipient: "caster" as const,
aura: {
id: "character-stat-ruleset:test-wisdom",
name: "Ordinary Wisdom Test Aura",
disposition: "buff" as const,
durationMs: 2_000,
modifiers: [
{ kind: "stat" as const, stat: "wisdom", operation: "flat" as const, value: 30 },
{ kind: "stat" as const, stat: "wisdom", operation: "percent" as const, value: 0.2 },
],
},
sourceEffectType: -1,
sourceAuraType: -1,
miscValue: 0,
triggerSpellId: 0,
};
const manaBeforeWisdomAura = before.maxResourcePools.mana!;
expect(useCombatStore.getState().applyActorAura(
PLAYER_AURA_ENTITY_ID, PLAYER_AURA_ENTITY_ID, manaAuraAbility, wisdomAura, 1_000,
)).toBe(true);
const withWisdomAura = useCombatStore.getState();
const effective = auraAdjustedCharacterStats(
deriveCharacterStats("rom-priest", 30, withWisdomAura.gearStats, withWisdomAura.raceId,
{}, null, withWisdomAura.gender, "rom"),
withWisdomAura.auras,
PLAYER_AURA_ENTITY_ID,
1_000,
);
expect(effective.romNative?.attributes.wisdom).toBeCloseTo(
(ordinaryWisdom.attributes.wisdom + 115) * 1.105,
);
expect(effective.romNative?.attributes.wisdom).toBeCloseTo(wisdomAfterBlessing);
expect(effective.romNative?.magicalDamage).toBeCloseTo(base.magicalDamage);
expect(effective.romNative?.magicalDefense).toBeCloseTo(expected.magicalDefense);
expect(effective.mana).toBeCloseTo(expected.mana.max);
expect(withWisdomAura.maxResourcePools.mana).toBeCloseTo(expected.mana.max);
expect(withWisdomAura.maxResourcePools.mana).toBeGreaterThan(manaBeforeWisdomAura);
useCombatStore.getState().tick(0, 3_000);
expect(useCombatStore.getState().maxResourcePools.mana).toBeCloseTo(manaBeforeWisdomAura);
expect(useCombatStore.getState().actors[PLAYER_AURA_ENTITY_ID]?.resources.mana?.maximum)
.toBeCloseTo(manaBeforeWisdomAura);
if (!chainOfLight) throw new Error("Missing generated RoM Priest Chain of Light channel");
useCombatStore.getState().registerMob("native-wisdom-channel-target", {
name: "Native Wisdom Channel Target", level: 30, maxHealth: 10_000_000, xpReward: 0,
});
setMobPosition("native-wisdom-channel-target", [3, 0, 0]);
useCombatStore.getState().selectMob("native-wisdom-channel-target");
expect(useCombatStore.getState().castAbility(chainOfLight.id, undefined, 10_000)).toMatchObject({ ok: true });
for (const now of [11_000, 12_000, 13_000, 14_000]) useCombatStore.getState().tick(1, now);
const amounts = useCombatStore.getState().combatEvents.filter((event) => (
event.kind === "damage" && event.abilityId === chainOfLight.id
)).map((event) => event.rawAmount);
expect(amounts).toHaveLength(4);
expect(amounts.every((amount) => amount > 0)).toBe(true);
for (const amount of amounts) expect(amount).toBeCloseTo(amounts[0]!, 5);
});
it("uses the configured companion ruleset for a real native periodic damage source", () => {
const nativeGear: RomNativeGearStats = { magicalDamage: 160, magicalDamageRateFactor: 1.35 };
const native = createConfiguredPartyMember({
name: "Native Periodic Priest",
classId: "rom-priest",
raceId: "rom-human",
specialization: "Primary",
role: "damage",
statRuleset: "rom",
}, 30, 0, "native-periodic-companion");
const legacy = createConfiguredPartyMember({
name: "Legacy Periodic Priest",
classId: "rom-priest",
raceId: "rom-human",
specialization: "Primary",
role: "damage",
}, 30, 1, "legacy-periodic-companion");
const members = [native, legacy].map((member) => ({
...member,
gearStats: { ...member.gearStats, romNative: nativeGear },
}));
usePartyStore.setState({ members });
useCombatStore.getState().synchronizeActors();
for (const id of ["native-periodic-target", "legacy-periodic-target"]) {
useCombatStore.getState().registerMob(id, {
name: id, level: 30, maxHealth: 10_000_000, xpReward: 0,
});
}
const boneChill = ROM_ALL_ABILITIES.find((ability) => ability.id === "rom-priest-primary-4");
const dot = boneChill?.effects.find((effect) => effect.kind === "dot");
if (!boneChill || !dot || dot.kind !== "dot") throw new Error("Missing generated Priest Bone Chill periodic damage");
const nativeExpected = equipmentAdjustedCombatAmount(
dot, native.level, members[0]!.gearStats, native.classId, boneChill, 0, undefined,
native.raceId, native.gender, "rom",
);
const legacyExpected = equipmentAdjustedCombatAmount(
dot, legacy.level, members[1]!.gearStats, legacy.classId, boneChill, 0, undefined,
legacy.raceId, legacy.gender, "wow",
);
expect(useCombatStore.getState().applyTimedActorEffect(native.id, "native-periodic-target", boneChill, dot, 1_000)).toBe(true);
expect(useCombatStore.getState().applyTimedActorEffect(legacy.id, "legacy-periodic-target", boneChill, dot, 1_000)).toBe(true);
const appliedEffects = useCombatStore.getState().effects.filter((effect) => effect.sourceAbilityId === boneChill.id);
expect(appliedEffects.map((effect) => effect.kind === "dot" ? effect.fixedAmount : null)).toEqual([
nativeExpected, legacyExpected,
]);
expect(useCombatStore.getState().actors[native.id]?.statRuleset).toBe("rom");
expect(useCombatStore.getState().actors[legacy.id]?.statRuleset).toBe("wow");
useCombatStore.getState().tick(0, 3_000);
const ticks = useCombatStore.getState().combatEvents.filter((event) => (
event.kind === "damage" && event.abilityId === boneChill.id
));
expect(ticks.map((event) => [event.sourceActorId, event.targetActorId, event.rawAmount])).toEqual([
[native.id, "native-periodic-target", nativeExpected],
[legacy.id, "legacy-periodic-target", legacyExpected],
]);
});
it("advances Green Guardian stacks for a native Mage/Druid companion", () => {
const skill = ROM_ALL_ABILITIES.find((ability) => ability.dbcSpellId === ROM_MAGE_DRUID_GREEN_GUARDIAN_SKILL_ID
&& ability.classId === "rom-mage" && ability.secondaryClassId === "rom-druid");
if (!skill) throw new Error("Missing generated Mage/Druid Green Guardian ability");
const companion = createConfiguredPartyMember({
name: "Native Green Guardian Mage",
classId: "rom-mage",
secondaryClassId: "rom-druid",
raceId: "rom-elf",
specialization: "Primary",
role: "damage",
statRuleset: "rom",
}, 45, 0, "native-green-guardian-companion");
usePartyStore.setState({ members: [companion] });
registerPartyRuntimePosition(companion.id, [0, 0, 0]);
useCombatStore.getState().synchronizeActors();
const effect = skill.effects.find((candidate) => candidate.kind === "apply-aura");
if (!effect || effect.kind !== "apply-aura") throw new Error("Green Guardian has no self aura effect");
expect(useCombatStore.getState().actors[companion.id]?.statRuleset).toBe("rom");
expect(useCombatStore.getState().applyActorAura(companion.id, companion.id, skill, effect, 1_000)).toBe(true);
useCombatStore.getState().tick(0.5, 1_500);
useCombatStore.getState().tick(0.5, 2_000);
useCombatStore.getState().tick(0.5, 2_500);
const guardian = useCombatStore.getState().auras.find((aura) => aura.targetId === companion.id
&& aura.definition.utilityTags?.includes(ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG));
expect(guardian?.stacks).toBe(1);
expect(romMageDruidGreenGuardianMovementSpeedMultiplier(
useCombatStore.getState().auras, companion.id, 2_500,
)).toBe(1.01);
updatePartyRuntimePosition(companion.id, 1, 0, 0);
useCombatStore.getState().tick(0.25, 2_750);
const movedGuardian = useCombatStore.getState().auras.find((aura) => aura.targetId === companion.id
&& aura.definition.utilityTags?.includes(ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG));
expect(movedGuardian?.stacks).toBe(1);
expect(romMageDruidGreenGuardianMovementSpeedMultiplier(
useCombatStore.getState().auras, companion.id, 2_750,
)).toBe(1.01);
useCombatStore.getState().tick(1, 3_750);
const stationaryGuardian = useCombatStore.getState().auras.find((aura) => aura.targetId === companion.id
&& aura.definition.utilityTags?.includes(ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG));
expect(stationaryGuardian?.stacks).toBe(2);
});
it("uses native and legacy source stats for player Chain of Light channel pulses", () => {
const gear: RomNativeGearStats = { magicalDamage: 140, magicalDamageRateFactor: 1.25 };
const legacy = castPlayerChannel("wow", gear);
clearMobRuntimeRegistry();
const native = castPlayerChannel("rom", gear);
expect(legacy.actorRuleset).toBe("wow");
expect(native.actorRuleset).toBe("rom");
expect(legacy.amounts).toHaveLength(4);
expect(native.amounts).toHaveLength(4);
expect(native.amounts[0]).toBeGreaterThan(legacy.amounts[0]!);
for (const amount of legacy.amounts) expect(amount).toBeCloseTo(legacy.amounts[0]!, 5);
for (const amount of native.amounts) expect(amount).toBeCloseTo(native.amounts[0]!, 5);
});
it("keeps native companion autoattacks on RoM ATK and ignores foreign WoW attack and haste ratings", () => {
const noNativeAttack = nativeCompanionSwingDamage(0);
const nativeAttack = nativeCompanionSwingDamage(2_000);
const nativeAttackWithForeignRatings = nativeCompanionSwingDamage(2_000, true);
expect(nativeAttack).toBeGreaterThan(noNativeAttack);
expect(nativeAttackWithForeignRatings).toBe(nativeAttack);
const nativeBaseTiming = playerChannelTiming("rom", 0);
const nativeForeignHasteTiming = playerChannelTiming("rom", 1_000_000);
const legacyForeignHasteTiming = playerChannelTiming("wow", 1_000_000);
expect(nativeForeignHasteTiming).toEqual(nativeBaseTiming);
expect(legacyForeignHasteTiming.castMs).toBeLessThan(nativeBaseTiming.castMs);
expect(legacyForeignHasteTiming.gcdMs).toBeLessThan(nativeBaseTiming.gcdMs);
});
});
+43 -7
View File
@@ -9,10 +9,18 @@ import {
import {
COA_PROGRESSION_CHAINS,
COA_TREE_ENTRIES,
ascensionSpellById,
coaClassIdFromDbcId,
coaSpellById,
} from "./coaLiveCatalog";
const UNSOURCED_BASE_RANK_SPELL_IDS = new Set([
501862, 501863, 501864, 501865,
501918, 501919, 501920,
501922, 501923, 501924, 501925,
502889,
560469,
]);
const abilities = Object.values(COA_ABILITIES_BY_CLASS).flat();
it("keeps Drakkari Barrier friendly and its retaliation in the damage-taken proc", () => {
@@ -63,12 +71,17 @@ describe("Ascension Conquest ability catalog", () => {
expect(payload.effects.find(effect => effect.kind === "hot")).toMatchObject({ scope: "party", radius: 30, maximumTargets: 1 });
});
it("normalizes negative DBC cast-time sentinels for runtime ranks", () => {
const berserkerAxe = ranks.find(({ rank }) => rank.spellId === 804138);
expect(berserkerAxe?.rank).toMatchObject({ castMode: "instant", castTimeMs: 0 });
});
it("covers every class, source family, and playable rank", () => {
expect(Object.keys(COA_ABILITIES_BY_CLASS).sort()).toEqual([...COA_CLASS_IDS].sort());
expect(Object.keys(COA_CLASS_RESOURCES).sort()).toEqual([...COA_CLASS_IDS].sort());
expect(abilities).toHaveLength(1_275);
expect(ranks).toHaveLength(3_394);
expect(new Set(ranks.map(({ rank }) => rank.spellId)).size).toBe(3_347);
expect(abilities).toHaveLength(1_276);
expect(ranks).toHaveLength(3_395);
expect(new Set(ranks.map(({ rank }) => rank.spellId)).size).toBe(3_348);
const runtimeSpellIds = new Set(ranks.map(({ rank }) => rank.spellId));
for (const chain of COA_PROGRESSION_CHAINS) {
@@ -87,7 +100,7 @@ describe("Ascension Conquest ability catalog", () => {
}
});
it("gives every family and rank finite, executable runtime data", () => {
it("gives every rank finite data and every sourced rank an executable effect", () => {
expect(new Set(abilities.map((ability) => ability.id)).size).toBe(abilities.length);
for (const ability of abilities) {
expect(ability.classId, ability.id).toBeTruthy();
@@ -109,13 +122,36 @@ describe("Ascension Conquest ability catalog", () => {
expect(rank.cost.amount, label).toBeGreaterThanOrEqual(0);
expect(rank.effects.length, label).toBeGreaterThan(0);
expect(rank.effects.some((effect) => effect.kind === "scripted" || effect.kind === "unsupported"), label).toBe(false);
if (!ability.passive) {
if (!ability.passive && !UNSOURCED_BASE_RANK_SPELL_IDS.has(rank.spellId)) {
expect(rank.effects.some((effect) => effect.kind !== "utility" || effect.action !== "class-script"), label).toBe(true);
}
}
}
});
it("keeps known BASE DBC gaps explicit without borrowing another realm's payload", () => {
const emptySourcePlaceholder = [{
kind: "utility",
action: "class-script",
effectType: 0,
auraType: 0,
miscValue: 0,
triggerSpellId: 0,
durationMs: 0,
}];
for (const spellId of UNSOURCED_BASE_RANK_SPELL_IDS) {
const label = `spell ${spellId}`;
expect(coaSpellById(spellId), label).not.toBeNull();
expect(coaSpellById(spellId)?.dbc, `${label} CoA BASE row`).toBeUndefined();
expect(ascensionSpellById(spellId)?.dbc, `${label} classic source row`).toBeUndefined();
const sourceRank = ranks.find(({ rank }) => rank.spellId === spellId);
expect(sourceRank, label).toBeDefined();
if (!sourceRank) continue;
expect(sourceRank.rank.description, label).toBe("No client tooltip is available.");
expect(sourceRank.rank.effects, label).toEqual(emptySourcePlaceholder);
}
});
it("translates every standard DBC combat effect into its executable semantic", () => {
const applyAuraTypes = new Set([0, 3, 6, 27, 35, 65, 119, 128, 129, 143, 190]);
const triggerTypes = new Set([32, 64, 140, 141, 142, 148, 151, 160, 165, 169, 175, 178, 183]);
@@ -199,7 +235,7 @@ describe("Ascension Conquest ability catalog", () => {
it("ships executable hidden payloads for proc-triggered DBC spell IDs", () => {
// Geode Barrage now uses its ranked parent payload instead of hidden placeholder 803138.
expect(Object.keys(COA_TRIGGERED_ABILITIES_BY_SPELL_ID)).toHaveLength(584);
expect(Object.keys(COA_TRIGGERED_ABILITIES_BY_SPELL_ID)).toHaveLength(578);
expect(COA_TRIGGERED_ABILITIES_BY_SPELL_ID[803138]).toBeUndefined();
expect(COA_TRIGGERED_ABILITIES_BY_SPELL_ID[800951]).toMatchObject({
name: "Battle Rhythm",
@@ -207,7 +243,7 @@ describe("Ascension Conquest ability catalog", () => {
});
expect(Object.values(COA_TRIGGERED_ABILITIES_BY_SPELL_ID).filter((ability) => (
ability.effects.some((effect) => effect.kind !== "utility")
))).toHaveLength(545);
))).toHaveLength(536);
for (const [spellId, ability] of Object.entries(COA_TRIGGERED_ABILITIES_BY_SPELL_ID)) {
expect(ability.dbcSpellId, spellId).toBe(Number(spellId));
expect(ability.effects.length, spellId).toBeGreaterThan(0);
+30 -14
View File
@@ -26,6 +26,8 @@ import {
coaEntryRank,
coaIconUrl,
coaSpellById,
ascensionSpellById,
isCoaClassId,
type CoaDbcEffect,
type CoaDbcSpell,
type CoaProgressionChain,
@@ -44,9 +46,13 @@ interface CoaSourceSpell {
const COA_TRIGGERED_DBC_BY_ID = new Map(
(triggeredSpellCatalog.spells as unknown as readonly CoaDbcSpell[]).map((spell) => [spell.id, spell]),
);
const CLASSIC_TRIGGERED_DBC_BY_ID = new Map(
((triggeredSpellCatalog as unknown as { classicSpells?: readonly CoaDbcSpell[] }).classicSpells
?? triggeredSpellCatalog.spells as unknown as readonly CoaDbcSpell[]).map((spell) => [spell.id, spell]),
);
function coaSourceSpellById(spellId: number): CoaSourceSpell | null {
const live = coaSpellById(spellId);
function coaSourceSpellById(spellId: number, classic = false): CoaSourceSpell | null {
const live = (classic ? ascensionSpellById : coaSpellById)(spellId);
if (live?.dbc) return {
name: live.name,
rank: live.rank,
@@ -54,7 +60,9 @@ function coaSourceSpellById(spellId: number): CoaSourceSpell | null {
...(live.liveTooltip ? { liveTooltip: live.liveTooltip } : {}),
dbc: live.dbc,
};
const dbc = COA_TRIGGERED_DBC_BY_ID.get(spellId);
// An unresolved live record must not inherit a different realm's fallback.
if (live) return null;
const dbc = (classic ? CLASSIC_TRIGGERED_DBC_BY_ID : COA_TRIGGERED_DBC_BY_ID).get(spellId);
return dbc ? {
name: dbc.name || `Triggered Spell ${spellId}`,
rank: dbc.rankText,
@@ -750,6 +758,7 @@ function effectsForSpell(
abilityName: string,
depth = 0,
visitedSpellIds: ReadonlySet<number> = new Set(),
classic = false,
): readonly AbilityEffect[] {
if (!spell) {
if (/\b(?:heal|restore|mend|rejuvenat)\w*\b/i.test(description)) return [{ kind: "heal", coefficient: 1 }];
@@ -856,7 +865,7 @@ function effectsForSpell(
if (effect.effectType === 30) {
// Primalist's imported energizes use DBC power units. Other CoA class
// script payloads retain their existing interpretation in this pass.
if (!coaSpellById(spell.id)?.classIds.includes(31)) {
if (!(classic ? ascensionSpellById : coaSpellById)(spell.id)?.classIds.includes(31)) {
effects.push({ kind: "resource", amount: Math.abs(effect.basePoints) });
continue;
}
@@ -865,7 +874,7 @@ function effectsForSpell(
continue;
}
if (effect.effectType === 137) {
effects.push({ kind: "resource", ...(coaSpellById(spell.id)?.classIds.includes(31) ? { resource: resourceForPowerType(effect.miscValue) } : {}),
effects.push({ kind: "resource", ...((classic ? ascensionSpellById : coaSpellById)(spell.id)?.classIds.includes(31) ? { resource: resourceForPowerType(effect.miscValue) } : {}),
amount: Math.abs(effect.basePoints), percentage: true });
continue;
}
@@ -941,18 +950,18 @@ function effectsForSpell(
}
const triggeredSpellId = effect.triggerSpellId > 0
? effect.triggerSpellId
: effect.effectType === 168 && coaSourceSpellById(effect.miscValue) ? effect.miscValue : 0;
: effect.effectType === 168 && coaSourceSpellById(effect.miscValue, classic) ? effect.miscValue : 0;
if ((TRIGGER_SPELL_EFFECTS.has(effect.effectType) || effect.effectType === 168) && triggeredSpellId > 0) {
effects.push({
kind: "trigger-spell",
spellId: triggeredSpellId,
// Expanded payloads below execute in the parent; retain this marker
// for source lookup without executing the same payload a second time.
expanded: depth < 2 && !visitedSpellIds.has(triggeredSpellId) && Boolean(coaSourceSpellById(triggeredSpellId)),
expanded: depth < 2 && !visitedSpellIds.has(triggeredSpellId) && Boolean(coaSourceSpellById(triggeredSpellId, classic)),
...([141, 142, 183].includes(effect.effectType) ? { withValue: effect.basePoints } : {}),
});
if (depth < 2 && !visitedSpellIds.has(triggeredSpellId)) {
const triggered = coaSourceSpellById(triggeredSpellId);
const triggered = coaSourceSpellById(triggeredSpellId, classic);
if (triggered) {
const expandedVisited = new Set(visitedSpellIds);
expandedVisited.add(spell.id);
@@ -962,6 +971,7 @@ function effectsForSpell(
triggered.name,
depth + 1,
expandedVisited,
classic,
).filter((nested) => nested.kind !== "utility"));
} else if (effect.effectType === 142) {
const describesDamagePayload = /\bdamage\b/i.test(description);
@@ -1015,7 +1025,7 @@ function effectsForSpell(
continue;
}
if (effect.effectType === 192 || effect.effectType === 195) {
const affected = coaSourceSpellById(effect.miscValue);
const affected = coaSourceSpellById(effect.miscValue, classic);
const describedNames = description.match(/cooldown of\s+(.+?)(?:\s+spells?\b|\.)/i)?.[1]
?.split(/,|\band\b/i)
.map((name) => name.trim())
@@ -1225,14 +1235,19 @@ function rankDefinition(
spellId: number,
rank: number,
level: number,
classic = false,
): AbilityRankDefinition {
const liveSpell = coaSourceSpellById(spellId);
const liveSpell = coaSourceSpellById(spellId, classic);
const dbc = liveSpell?.dbc;
const liveTooltip = liveSpell?.liveTooltip ?? "";
const mechanicsTooltip = liveTooltipMechanics(liveSpell, liveTooltip);
const description = liveTooltip || liveSpell?.description || dbc?.description || "No client tooltip is available.";
const effects = effectsForSpell(dbc, description, liveSpell?.name ?? dbc?.name ?? `Spell ${spellId}`);
const castTimeMs = liveTooltipCastTime(mechanicsTooltip, dbc?.castTimeMs ?? 0);
const effects = effectsForSpell(dbc, description, liveSpell?.name ?? dbc?.name ?? `Spell ${spellId}`, 0, new Set(), classic);
const sourcedCastTimeMs = liveTooltipCastTime(mechanicsTooltip, dbc?.castTimeMs ?? 0);
// DBC cast-time lookups can yield negative sentinels (for example -1000000
// at cast-time index 18); these are not executable durations. Keep classic
// runtime behavior untouched while normalizing CoA rank values.
const castTimeMs = classic ? sourcedCastTimeMs : Math.max(0, sourcedCastTimeMs);
const channeling = Boolean(dbc?.channelInterruptFlags && dbc.durationMs > 0);
const channelTickMs = channeling ? dbc?.effects
.map((effect) => effect.periodMs)
@@ -1268,9 +1283,10 @@ export function ascensionProgressionAbility(
id = chain.id,
): AbilityDefinition | null {
if (!chain.ranks.length) return null;
const ranks = chain.ranks.map((rank) => rankDefinition(resource, rank.spellId, rank.rank, rank.level));
const classic = !isCoaClassId(classId);
const ranks = chain.ranks.map((rank) => rankDefinition(resource, rank.spellId, rank.rank, rank.level, classic));
const first = ranks[0];
const firstSpell = coaSourceSpellById(first.spellId);
const firstSpell = coaSourceSpellById(first.spellId, classic);
const dbc = firstSpell?.dbc;
const target = targetForSpell(dbc, first.effects, first.description);
const radius = Math.max(0, ...((dbc?.effects ?? []).map((effect) => effect.radius)));
+2 -1
View File
@@ -30,7 +30,8 @@ describe("CoA healer resources and recipients", () => {
const state = useCombatStore.getState();
usePartyStore.getState().initializeParty("tinker-mana", 80, state.health);
const member = { ...usePartyStore.getState().members[0], classId: "tinker" as const, raceId: state.raceId, level: 80,
resourceType: "energy" as const, maxResource: state.maxResource, resourcePools: state.resourcePools, gearStats: state.gearStats };
resourceType: "energy" as const, maxResource: state.maxResource, resourcePools: state.resourcePools,
resourceMaximums: state.maxResourcePools, gearStats: state.gearStats };
const actor = companionActorFromMember(member);
expect(state.maxResourcePools.mana).toBeGreaterThan(1_000);
expect(actor.resources.mana.current).toBe(state.resourcePools.mana);
+10 -9
View File
@@ -14,7 +14,7 @@ import {
} from "./coaLiveCatalog";
describe("live Ascension Conquest catalog", () => {
it("contains the complete validated Vol'Jin payload", () => {
it("contains the pinned August Vol'Jin trees with separately preserved classic data", () => {
expect(COA_LIVE_SOURCE).toMatchObject({
realmId: 40,
realmSlug: "voljin",
@@ -24,24 +24,24 @@ describe("live Ascension Conquest catalog", () => {
expect(COA_LIVE_COUNTS).toMatchObject({
classes: 21,
tabs: 91,
entries: 3612,
abilityEntries: 700,
talentEntries: 2912,
rankedNodeSpells: 3929,
entries: 3618,
abilityEntries: 701,
talentEntries: 2917,
rankedNodeSpells: 3933,
classSpellRows: 12374,
classicClassSpellRows: 6930,
coaClassSpellRows: 5444,
uniqueSpells: 15439,
dbcMatchedSpells: 15439,
progressionChains: 1822,
classicProgressionChains: 1266,
classicBaseProgressionChains: 612,
coaProgressionChains: 556,
progressionRanks: 8405,
});
expect(COA_LIVE_SOURCE.spellDbcPath).toContain("client-current/area-52/patch-D");
expect(COA_LIVE_SOURCE.coaSpellDbcPath).toContain("client-current/patch-T");
expect(COA_LIVE_SOURCE.classicSpellDbcPath).toContain("client-current/area-52/patch-D");
expect(COA_LIVE_SOURCE.supportDbcDirectory).toContain("client-current/patch-S");
expect(COA_LIVE_COUNTS.dbcMatchedSpells).toBe(COA_LIVE_COUNTS.uniqueSpells);
expect(COA_LIVE_SOURCE.synchronizedAt).toBe("2026-08-12T21:02:51+00:00");
expect(COA_LIVE_COUNTS.dbcMatchedSpells).toBeLessThan(COA_LIVE_COUNTS.uniqueSpells);
expect(COA_LIVE_CLASSES).toHaveLength(COA_CLASS_IDS.length);
expect(COA_TREE_ENTRIES).toHaveLength(COA_LIVE_COUNTS.entries);
});
@@ -89,6 +89,7 @@ describe("live Ascension Conquest catalog", () => {
expect(rank.spellId).toBeGreaterThan(0);
expect(rank.description.length).toBeGreaterThan(0);
expect(coaSpellById(rank.spellId)).not.toBeNull();
expect(coaSpellById(rank.spellId)?.dbc, `node ${entry.id} rank ${rank.rank}`).toBeDefined();
rankCount += 1;
}
}
+14
View File
@@ -21,6 +21,10 @@ export interface CoaLiveSource {
readonly synchronizedAt: string;
readonly spellDbcPath: string;
readonly supportDbcDirectory: string;
readonly coaSpellDbcPath?: string;
readonly classicSpellDbcPath?: string;
readonly coaSkillLineAbilityDbcPath?: string;
readonly classicSkillLineAbilityDbcPath?: string;
}
export interface CoaLiveCounts {
@@ -205,6 +209,7 @@ interface CoaLiveData {
readonly entries: readonly CoaTreeEntry[];
readonly progressionChains: readonly CoaProgressionChain[];
readonly spells: readonly CoaLiveSpell[];
readonly coaSpellOverrides?: readonly CoaLiveSpell[];
}
const data = liveData as unknown as CoaLiveData;
@@ -219,6 +224,10 @@ const CLASSIC_CLASS_ID_BY_DBC_ID = Object.freeze(Object.fromEntries(
.map((definition) => [definition.dbcId, definition.id]),
)) as Readonly<Record<number, BaseClassId>>;
const SPELL_BY_ID = new Map(data.spells.map((spell) => [spell.id, spell]));
const COA_SPELL_BY_ID = new Map([
...data.spells.filter((spell) => spell.classIds.some((classId) => classId > 11)),
...(data.coaSpellOverrides ?? []),
].map((spell) => [spell.id, spell]));
const ENTRY_BY_ID = new Map(data.entries.map((entry) => [entry.id, entry]));
const CLASS_BY_DBC_ID = new Map(data.classes.map((definition) => [definition.classId, definition]));
@@ -266,6 +275,11 @@ export function coaEntriesForTab(classId: CoaClassId, tabId: number): readonly C
}
export function coaSpellById(spellId: number): CoaLiveSpell | null {
return COA_SPELL_BY_ID.get(spellId) ?? null;
}
/** Classic classes retain their realm-specific values when a spell ID is shared. */
export function ascensionSpellById(spellId: number): CoaLiveSpell | null {
return SPELL_BY_ID.get(spellId) ?? null;
}
File diff suppressed because it is too large. Load diff
+25
View File
@@ -0,0 +1,25 @@
import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
import { gunzipSync } from "node:zlib";
import { describe, expect, it } from "vitest";
import { ASCENSION_CLASSIC_ABILITIES_BY_CLASS } from "./ascensionClassicAbilityCatalog";
import { ASCENSION_CLASSIC_PROGRESSION_CHAINS, COA_TREE_ENTRIES, ascensionSpellById } from "./coaLiveCatalog";
const july = JSON.parse(gunzipSync(readFileSync("data/coa-reference/baselines/coa-july-2026-07-25.json.gz")).toString("utf8"));
describe("offline CoA promotion preservation", () => {
it("preserves every July node identity and all classic chains and owned spell records", () => {
const entries = new Map(COA_TREE_ENTRIES.map((node) => [node.id, node]));
for (const node of july.entries) expect(entries.get(node.id)?.classId, String(node.id)).toBe(node.classId);
expect(ASCENSION_CLASSIC_PROGRESSION_CHAINS).toEqual(july.progressionChains.filter((chain: { classId: number }) => chain.classId <= 11));
for (const spell of july.spells) {
if (spell.classIds.some((id: number) => id <= 11)) expect(ascensionSpellById(spell.id), `classic spell ${spell.id}`).toEqual(spell);
}
});
it("leaves all 612 classic generated progression abilities identical to the pre-promotion capture", () => {
expect(Object.values(ASCENSION_CLASSIC_ABILITIES_BY_CLASS).flat()).toHaveLength(612);
const digest = createHash("sha256").update(JSON.stringify(ASCENSION_CLASSIC_ABILITIES_BY_CLASS)).digest("hex");
expect(digest).toBe("30d3647c76a8903d081c6cbdc6d2ccaa17b4c86067e762cc4697f7614c1892f0");
});
});
+222
View File
@@ -0,0 +1,222 @@
import { describe, expect, it, vi } from "vitest";
import type { AbilityDefinition } from "./abilityCatalog";
import {
ascensionSpellById,
coaSpellById,
type CoaProgressionChain,
} from "./coaLiveCatalog";
import { ascensionProgressionAbility } from "./coaAbilityCatalog";
const fixture = vi.hoisted(() => {
const makeEffect = (effectType: number, triggerSpellId = 0, basePoints = 1) => ({
index: 0,
effectType,
auraType: 0,
basePoints,
dieSides: 0,
pointsPerLevel: 0,
mechanic: 0,
implicitTargetA: 6,
implicitTargetB: 0,
radiusIndex: 0,
radius: 0,
periodMs: 0,
valueMultiplier: 0,
chainTargets: 0,
itemType: 0,
miscValue: 0,
miscValueB: 0,
triggerSpellId,
pointsPerCombo: 0,
coefficient: 0,
});
const makeDbc = (
id: number,
name: string,
effects: ReturnType<typeof makeEffect>[] = [],
startRecoveryTimeMs = 1_500,
) => ({
id,
name,
rankText: "Rank 1",
description: `${name} fixture description`,
categoryId: 0,
dispelType: 0,
mechanic: 0,
attributes: Array(8).fill(0),
castTimeIndex: 0,
castTimeMs: 0,
recoveryTimeMs: 0,
categoryRecoveryTimeMs: 0,
interruptFlags: 0,
auraInterruptFlags: 0,
channelInterruptFlags: 0,
procFlags: 0,
procChance: 0,
procCharges: 0,
maxLevel: 80,
baseLevel: 1,
spellLevel: 1,
durationIndex: 0,
durationMs: 0,
powerType: 0,
powerCost: 0,
powerCostPerLevel: 0,
powerCostPerSecond: 0,
powerCostPerSecondPerLevel: 0,
rangeIndex: 0,
rangeMin: 0,
rangeMax: 30,
projectileSpeed: 0,
stackAmount: 0,
equippedItemClass: 0,
equippedItemSubclassMask: 0,
equippedItemInventoryMask: 0,
iconId: 0,
powerCostPercentage: 0,
startRecoveryCategory: 0,
startRecoveryTimeMs,
maximumTargets: 0,
damageClass: 0,
preventionType: 0,
schoolMask: 1,
runeCostId: 0,
powerDisplayId: 0,
effects,
});
const makeLiveSpell = (id: number, name: string, dbc?: ReturnType<typeof makeDbc>) => ({
id,
classIds: [11, 27],
name,
iconBasename: "fixture",
level: 1,
rank: "Rank 1",
description: `${name} live description`,
sourceIds: [],
advancementType: "",
advancementTabId: 0,
talented: false,
excluded: false,
...(dbc ? { dbc } : {}),
});
const mainSpells = [
makeLiveSpell(900, "Shared Classic Root", makeDbc(900, "Classic Root", [], 700)),
makeLiveSpell(910, "Shared Trigger Root", makeDbc(910, "Classic Trigger Root", [makeEffect(64, 920)])),
makeLiveSpell(920, "Shared First Payload", makeDbc(920, "Classic First Payload", [makeEffect(64, 930)])),
makeLiveSpell(930, "Shared Nested Payload", makeDbc(930, "Classic Nested Payload", [makeEffect(2)])),
makeLiveSpell(940, "Shared Missing CoA Base", makeDbc(940, "Area52 Overlay Payload", [makeEffect(2)])),
{ ...makeLiveSpell(950, "Classic Only Root", makeDbc(950, "Classic Only Root", [makeEffect(2)])), classIds: [11] },
];
const coaOverrides = [
makeLiveSpell(900, "Shared CoA Root", makeDbc(900, "CoA Root", [], 0)),
makeLiveSpell(910, "Shared CoA Trigger Root", makeDbc(910, "CoA Trigger Root", [makeEffect(64, 920)])),
makeLiveSpell(920, "Shared CoA First Payload", makeDbc(920, "CoA First Payload", [makeEffect(64, 930)])),
makeLiveSpell(930, "Shared CoA Nested Payload", makeDbc(930, "CoA Nested Payload", [makeEffect(67)])),
makeLiveSpell(940, "Shared CoA Missing Base"),
];
const overlayPayload = makeDbc(940, "Area52 Overlay Payload", [makeEffect(2)]);
return {
liveData: {
source: {
builderUrl: "fixture",
databaseClassUrl: "fixture",
realmId: 1,
realmSlug: "fixture",
realmName: "Fixture",
maximumLevel: 80,
schemaVersion: {},
synchronizedAt: "2026-01-01T00:00:00.000Z",
spellDbcPath: "fixture/classic/Spell.dbc",
supportDbcDirectory: "fixture/support",
},
counts: {},
classes: [],
entries: [],
progressionChains: [],
spells: mainSpells,
coaSpellOverrides: coaOverrides,
},
triggeredCatalog: {
spells: [overlayPayload],
classicSpells: [overlayPayload],
},
};
});
vi.mock("./coaLiveData.generated.json", () => ({ default: fixture.liveData }));
vi.mock("./generated/coaTriggeredSpellCatalog.json", () => ({ default: fixture.triggeredCatalog }));
function chain(spellId: number): CoaProgressionChain {
return {
id: `scope-${spellId}`,
classId: 11,
name: `Scope ${spellId}`,
iconBasename: "fixture",
talented: false,
advancementType: "",
trainer: false,
ranks: [{ spellId, rank: 1, level: 1 }],
};
}
function ability(spellId: number, classId: "druid" | "sun-cleric"): AbilityDefinition {
const classic = classId === "druid";
const result = ascensionProgressionAbility(
chain(spellId),
classId,
"mana",
classic ? "ascension-progression" : "coa-progression",
);
if (!result) throw new Error(`Fixture spell ${spellId} did not produce an ability`);
return result;
}
describe("classic and CoA spell source scope", () => {
it("excludes classic-only records from CoA lookup", () => {
expect(ascensionSpellById(950)?.dbc?.name).toBe("Classic Only Root");
expect(coaSpellById(950)).toBeNull();
expect(ability(950, "druid").effects.some((effect) => effect.kind === "damage")).toBe(true);
expect(ability(950, "sun-cleric").effects.some((effect) => effect.kind === "damage")).toBe(false);
});
it("resolves a shared root spell through separate classic and CoA wrappers", () => {
expect(ascensionSpellById(900)?.dbc?.name).toBe("Classic Root");
expect(coaSpellById(900)?.dbc?.name).toBe("CoA Root");
expect(ability(900, "druid").ranks?.[0].gcdMs).toBe(700);
expect(ability(900, "sun-cleric").ranks?.[0].gcdMs).toBe(0);
});
it("keeps nested triggered payloads in the root spell's class scope", () => {
const classicEffects = ability(910, "druid").ranks?.[0].effects ?? [];
const coaEffects = ability(910, "sun-cleric").ranks?.[0].effects ?? [];
expect(classicEffects).toEqual(expect.arrayContaining([
expect.objectContaining({ kind: "trigger-spell", spellId: 920 }),
expect.objectContaining({ kind: "trigger-spell", spellId: 930 }),
expect.objectContaining({ kind: "damage" }),
]));
expect(classicEffects.some((effect) => effect.kind === "heal")).toBe(false);
expect(coaEffects).toEqual(expect.arrayContaining([
expect.objectContaining({ kind: "trigger-spell", spellId: 920 }),
expect.objectContaining({ kind: "trigger-spell", spellId: 930 }),
expect.objectContaining({ kind: "heal" }),
]));
expect(coaEffects.some((effect) => effect.kind === "damage")).toBe(false);
});
it("does not fall back to classic overlay DBC when a CoA override has no base row", () => {
expect(ascensionSpellById(940)?.dbc?.name).toBe("Area52 Overlay Payload");
expect(coaSpellById(940)).toMatchObject({ id: 940, name: "Shared CoA Missing Base" });
expect(coaSpellById(940)?.dbc).toBeUndefined();
const classicEffects = ability(940, "druid").ranks?.[0].effects ?? [];
const coaEffects = ability(940, "sun-cleric").ranks?.[0].effects ?? [];
expect(classicEffects.some((effect) => effect.kind === "damage")).toBe(true);
expect(coaEffects.some((effect) => effect.kind === "damage")).toBe(false);
});
});
+47 -14
View File
@@ -4,12 +4,19 @@ import {
type CombatActorState,
} from "./combatActors";
import type { PartyMember } from "./partyStore";
import { baseClassFor, isRomClassId } from "../app/characterCatalog";
import { isRomClassId } from "../app/characterCatalog";
import { deriveCharacterStats } from "./wotlkStats";
export function companionResourceMaximum(member: PartyMember, id: string): number {
return id === member.resourceType ? member.maxResource : id === "mana" && !isRomClassId(member.classId)
? deriveCharacterStats(baseClassFor(member.classId), member.level, member.gearStats, member.raceId).mana
if (id === member.resourceType) return member.maxResource;
const mirroredMaximum = member.resourceMaximums?.[id as ResourceType];
if (mirroredMaximum !== undefined) return mirroredMaximum;
return id === "mana"
&& (member.statRuleset === "rom" || !isRomClassId(member.classId))
? deriveCharacterStats(
member.classId, member.level, member.gearStats, member.raceId, {},
member.secondaryClassId, member.gender, member.statRuleset ?? "wow",
).mana
: id === "nature-power" ? naturePowerMaximumForCharacter(member.classId, member.secondaryClassId, member.level)
: id === "psi" ? 6
: 100;
@@ -25,23 +32,47 @@ export function companionActorFromMember(
existing?: CombatActorState | null,
): CombatActorState {
const profile = resourceProfileForClass(member.classId);
const resources = existing?.kind === "companion"
? existing.resources
: Object.fromEntries(Object.entries(member.resourcePools).map(([id, current]) => [id,
normalizeActorResourcePool(
id,
current ?? 0,
companionResourceMaximum(member, id),
id === member.resourceType ? profile.regenerationPerSecond : 0,
member.lastResourceSpentAt[id as ResourceType] ?? 0,
),
]));
let resources: CombatActorState["resources"];
if (existing?.kind === "companion" && member.statRuleset === "rom" && isRomClassId(member.classId)) {
const previousResources = existing.resources;
const nextResources: Record<string, ReturnType<typeof normalizeActorResourcePool>> = {};
const resourceIds = new Set([...Object.keys(previousResources), ...Object.keys(member.resourcePools)]);
for (const id of resourceIds) {
const previous = previousResources[id];
const nextMaximum = companionResourceMaximum(member, id);
const hasChangedMaximum = previous !== undefined && Math.abs(previous.maximum - nextMaximum) > 1e-6;
const current = hasChangedMaximum
? member.resourcePools[id as ResourceType] ?? previous.current
: previous?.current ?? member.resourcePools[id as ResourceType] ?? 0;
nextResources[id] = normalizeActorResourcePool(
id,
current,
nextMaximum,
id === member.resourceType ? profile.regenerationPerSecond : previous?.regenerationPerSecond ?? 0,
member.lastResourceSpentAt[id as ResourceType] ?? previous?.lastSpentAt ?? 0,
);
}
resources = nextResources;
} else if (existing?.kind === "companion") {
resources = existing.resources;
} else {
resources = Object.fromEntries(Object.entries(member.resourcePools).map(([id, current]) => [id,
normalizeActorResourcePool(
id,
current ?? 0,
companionResourceMaximum(member, id),
id === member.resourceType ? profile.regenerationPerSecond : 0,
member.lastResourceSpentAt[id as ResourceType] ?? 0,
),
]));
}
const actor = existing?.kind === "companion" ? existing : null;
return Object.freeze({
id: member.id,
threatActorId: member.id,
kind: "companion" as const,
classId: member.classId,
statRuleset: member.statRuleset,
level: member.level,
health: actor?.health ?? member.health,
maxHealth: actor?.maxHealth ?? member.maxHealth,
@@ -64,6 +95,7 @@ export function companionActorFromMember(
export function memberFromCompanionActor(member: PartyMember, actor?: CombatActorState | null): PartyMember {
if (!actor || actor.kind !== "companion") return member;
const resourcePools = Object.fromEntries(Object.entries(actor.resources).map(([id, pool]) => [id, pool.current])) as Partial<Record<ResourceType, number>>;
const resourceMaximums = Object.fromEntries(Object.entries(actor.resources).map(([id, pool]) => [id, pool.maximum])) as Partial<Record<ResourceType, number>>;
const lastResourceSpentAt = Object.fromEntries(Object.entries(actor.resources).map(([id, pool]) => [id, pool.lastSpentAt])) as Partial<Record<ResourceType, number>>;
const primary = actor.resources[member.resourceType];
return {
@@ -73,6 +105,7 @@ export function memberFromCompanionActor(member: PartyMember, actor?: CombatActo
resource: primary?.current ?? member.resource,
maxResource: primary?.maximum ?? member.maxResource,
resourcePools,
resourceMaximums,
lastResourceSpentAt,
comboPoints: actor.comboPoints,
comboTargetId: actor.comboTargetId,
+3
View File
@@ -1,5 +1,6 @@
import type { ClassId } from "../app/characterCatalog";
import type { DamageSchool } from "./combatAuras";
import type { CharacterStatRuleset } from "./characterStatRuleset";
export type CombatActorKind = "player" | "companion" | "enemy" | "pet" | "totem" | "summon";
export type CombatResourceId = string;
@@ -59,6 +60,8 @@ export interface CombatActorState {
readonly kind: CombatActorKind;
readonly ownerId?: string;
readonly classId?: ClassId;
/** The owning character's stat model, carried with authoritative snapshots. */
readonly statRuleset?: CharacterStatRuleset;
readonly level: number;
readonly health: number;
readonly maxHealth: number;
+4
View File
@@ -258,6 +258,10 @@ export interface ProcEvent {
readonly amount?: number;
readonly school?: DamageSchool;
readonly attackKind?: AttackKind;
/** True only for a normal weapon swing, never a melee spell hit. */
readonly isAutoAttack?: boolean;
/** Stable originating combat roll seed for ordered source proc branches. */
readonly rollSeed?: string;
}
export interface ProcRollContext {
+19
View File
@@ -90,6 +90,25 @@ describe("discrete combat results", () => {
expect(result.finalDamage).toBe(100 - result.armorMitigatedAmount);
});
it("lets a source-marked bleed tick bypass armor without skipping other target reductions", () => {
const result = resolveCombatResult({
...physicalAttack({
attacker: { level: 80, hitPercent: 100 },
defender: { level: 80, armor: 100_000, damageReductionPercent: 20 },
rules: { ignoreArmor: true, canMiss: false, canCrit: false, canDodge: false, canParry: false, canBlock: false },
}),
roll: fixedRoll(0.5),
});
expect(result).toMatchObject({
outcome: "hit",
effectiveArmor: 0,
armorReductionPercent: 0,
armorMitigatedAmount: 0,
damageReductionAmount: 20,
finalDamage: 80,
});
});
it("fully resists binary spells using a separate deterministic resistance roll", () => {
const result = resolveCombatResult({
amount: 100,
+4 -2
View File
@@ -42,6 +42,8 @@ export interface CombatResultRules {
readonly canDodge?: boolean;
readonly canParry?: boolean;
readonly canBlock?: boolean;
/** Source mechanic exception (for example, bleed effects that bypass armor). */
readonly ignoreArmor?: boolean;
readonly resistanceMode?: CombatResistanceMode;
/** Overrides the level-derived base miss chance before the attacker's hit bonus is applied. */
readonly baseMissChancePercent?: number;
@@ -300,10 +302,10 @@ export function resolveCombatResult(input: ResolveCombatResultInput): CombatResu
);
const armorPenetration = finitePercent(input.attacker.armorPenetrationPercent);
const effectiveArmor = input.damageSchool === "physical"
const effectiveArmor = input.damageSchool === "physical" && !input.rules?.ignoreArmor
? finiteNonNegative(input.defender.armor) * (1 - armorPenetration / 100)
: 0;
const physicalReduction = input.damageSchool === "physical"
const physicalReduction = input.damageSchool === "physical" && !input.rules?.ignoreArmor
? armorReductionPercent(effectiveArmor, input.attacker.level)
: 0;
const armorMitigatedAmount = Math.min(
+1929 -164
View File
File diff suppressed because it is too large. Load diff
+30
View File
@@ -10,6 +10,7 @@ import {
unequipInventorySlot,
} from "./equipment";
import { EMPTY_ITEM_STATS, type ItemStats } from "./itemStats";
import { deriveRomNativeStats } from "./romNativeStats";
function stats(overrides: Partial<ItemStats>): ItemStats {
return { ...EMPTY_ITEM_STATS, ...overrides };
@@ -96,4 +97,33 @@ describe("equipment assignments", () => {
expect(equipmentStats(assignments, [cloak, staff], "companion"))
.toMatchObject({ strength: 8, stamina: 2, armor: 0 });
});
it("bridges foreign direct stats per item while native payloads take precedence", () => {
const sourceNative = item("native", "head", {
stats: stats({ strength: 40, health: 99, mana: 99, romNative: { strength: 3, health: 5, mana: 5 } }),
});
const foreign = item("foreign", "back", {
stats: stats({ strength: 2, health: 10, mana: 10, spirit: 700, attackPower: 500, armor: 100, spellPower: 600 }),
});
const inventory = [sourceNative, foreign];
const assignments = { player: { head: sourceNative.instanceId, back: foreign.instanceId } };
const equipped = equipmentStats(assignments, inventory, "player");
expect(equipped).toMatchObject({ strength: 42, health: 109, mana: 109 });
expect(equipped.romNative).toEqual({ strength: 5, health: 15, mana: 15 });
const withoutGear = deriveRomNativeStats({ classId: "rom-warrior", level: 1 });
const withGear = deriveRomNativeStats({ classId: "rom-warrior", level: 1, gear: equipped.romNative });
expect(withGear.attributes.strength - withoutGear.attributes.strength).toBe(5);
expect(withGear.physicalAttack - withoutGear.physicalAttack).toBe(10);
expect(withGear.health.max - withoutGear.health.max).toBeCloseTo(16);
expect(withGear.attributes.wisdom).toBe(withoutGear.attributes.wisdom);
const mageWithoutGear = deriveRomNativeStats({ classId: "rom-mage", level: 1 });
const mageWithGear = deriveRomNativeStats({ classId: "rom-mage", level: 1, gear: equipped.romNative });
expect(mageWithGear.mana.max - mageWithoutGear.mana.max).toBe(15);
const unequipped = equipmentStats({}, inventory, "player");
expect(unequipped.romNative).toBeUndefined();
expect(deriveRomNativeStats({ classId: "rom-warrior", level: 1, gear: unequipped.romNative }).health.max)
.toBe(withoutGear.health.max);
});
});
+6 -1
View File
@@ -12,6 +12,7 @@ import {
type WeaponStats,
} from "./itemStats";
import type { InventoryItem } from "./lootTypes";
import { romNativeGearFromSharedDirectStats, sumRomNativeGearStats } from "./romNativeStatsTypes";
export const PLAYER_EQUIPMENT_OWNER_ID = "player";
@@ -254,14 +255,18 @@ export function equipmentStats(
const numeric = Object.fromEntries(ITEM_STAT_KEYS.map((key) => [key, 0])) as Record<NumericItemStatKey, number>;
let meleeWeapon: WeaponStats | null = null;
let rangedWeapon: WeaponStats | null = null;
const nativePayloads = [] as NonNullable<ItemStats["romNative"]>[];
for (const instanceId of Object.values(loadout)) {
const stats = instanceId ? itemById.get(instanceId)?.stats : null;
if (!stats) continue;
for (const key of ITEM_STAT_KEYS) numeric[key] += stats[key];
const nativePayload = stats.romNative ?? romNativeGearFromSharedDirectStats(stats);
if (nativePayload) nativePayloads.push(nativePayload);
if (stats.meleeWeapon) meleeWeapon = stats.meleeWeapon;
if (stats.rangedWeapon) rangedWeapon = stats.rangedWeapon;
}
return Object.freeze({ ...numeric, meleeWeapon, rangedWeapon });
const romNative = sumRomNativeGearStats(nativePayloads);
return Object.freeze({ ...numeric, meleeWeapon, rangedWeapon, ...(romNative ? { romNative } : {}) });
}
/** Keeps incompatible items owned and visibly assigned while excluding their stats in the active class orientation. */
File diff suppressed because it is too large. Load diff
@@ -1 +1 @@
{"schemaVersion":1,"classId":"barbarian","abilities":[{"id":"coa-tree-30762","classId":"barbarian","dbcSpellId":500918,"name":"Ancestral Roar","unlockLevel":1,"icon":"/assets/ui/spells/_d3threateningshout.png","sigil":"AR","description":"Ancestral RoarRank 1Instant cast25 sec cooldownRequires Enraged Roar with ancestral fervor, healing you for 100+0+AP*0.5.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":25000,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"heal","coefficient":1.6580645243326824,"basePoints":100,"dieSides":7,"pointsPerLevel":3.200000047683716,"bonusPowerCoefficient":0,"sourceLevel":16,"maxScalingLevel":22,"attackPowerCoefficient":0.5,"recipient":"caster"},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":3,"triggerSpellId":0,"durationMs":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":500918,"level":1,"description":"Ancestral RoarRank 1Instant cast25 sec cooldownRequires Enraged Roar with ancestral fervor, healing you for 100+0+AP*0.5.","castMode":"instant","castTimeMs":0,"cooldownMs":25000,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"heal","coefficient":1.6580645243326824,"basePoints":100,"dieSides":7,"pointsPerLevel":3.200000047683716,"bonusPowerCoefficient":0,"sourceLevel":16,"maxScalingLevel":22,"attackPowerCoefficient":0.5,"recipient":"caster"},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":3,"triggerSpellId":0,"durationMs":0}]}],"talentEntryId":30762},{"id":"coa-12-ancestral-spirit-47-705153","classId":"barbarian","dbcSpellId":705153,"name":"Ancestral Spirit","unlockLevel":1,"icon":"/assets/ui/spells/inv_misc_questionmark.png","sigil":"AS","description":"Ancestral SpiritRank 1Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by 50%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705153:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705153:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705153,"level":1,"description":"Ancestral SpiritRank 1Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by 50%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705153:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705153:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}]},{"rank":2,"spellId":705154,"level":1,"description":"Ancestral SpiritRank 2Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by 100%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705154:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705154:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}]}]},{"id":"coa-tree-34279","classId":"barbarian","dbcSpellId":560456,"namLine truncated
{"schemaVersion":1,"classId":"barbarian","abilities":[{"id":"coa-tree-30762","classId":"barbarian","dbcSpellId":500918,"name":"Ancestral Roar","unlockLevel":1,"icon":"/assets/ui/spells/_d3threateningshout.png","sigil":"AR","description":"Requires Enraged Roar with ancestral fervor, healing you for 100 + 50% AP.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":25000,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"heal","coefficient":1.6580645243326824,"basePoints":100,"dieSides":7,"pointsPerLevel":3.200000047683716,"bonusPowerCoefficient":0,"sourceLevel":16,"maxScalingLevel":22,"attackPowerCoefficient":0.5,"recipient":"caster"},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":3,"triggerSpellId":0,"durationMs":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":500918,"level":1,"description":"Requires Enraged Roar with ancestral fervor, healing you for 100 + 50% AP.","castMode":"instant","castTimeMs":0,"cooldownMs":25000,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"heal","coefficient":1.6580645243326824,"basePoints":100,"dieSides":7,"pointsPerLevel":3.200000047683716,"bonusPowerCoefficient":0,"sourceLevel":16,"maxScalingLevel":22,"attackPowerCoefficient":0.5,"recipient":"caster"},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":3,"triggerSpellId":0,"durationMs":0}]}],"talentEntryId":30762},{"id":"coa-12-ancestral-spirit-47-705153","classId":"barbarian","dbcSpellId":705153,"name":"Ancestral Spirit","unlockLevel":1,"icon":"/assets/ui/spells/inv_misc_questionmark.png","sigil":"AS","description":"Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by -50%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705153:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705153:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705153,"level":1,"description":"Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by -50%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705153:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705153:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}]},{"rank":2,"spellId":705154,"level":1,"description":"Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by -100%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705154:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705154:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}]}]},{"id":"coa-tree-34279","classId":"barbarian","dbcSpellId":560456,"name":"Athleticism","unlockLevel":1,"icon":"/assets/ui/spells/5_run_border.png","sigil":"AT","description":"Increases your Energy regeneration by 25%.","target":"self","Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"bloodmage","abilities":[{"id":"coa-tree-29871","classId":"bloodmage","dbcSpellId":504285,"name":"Alacrity","unlockLevel":1,"icon":"/assets/ui/spells/5_run_border.png","sigil":"AL","description":"Increases all primary stats by 4%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:504285:effect:0:aura:137","name":"Alacrity (Aura 137)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"all-primary","operation":"percent","value":0.04}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":137,"miscValue":-1,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":504285,"level":1,"description":"Increases all primary stats by 4%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:504285:effect:0:aura:137","name":"Alacrity (Aura 137)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"all-primary","operation":"percent","value":0.04}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":137,"miscValue":-1,"triggerSpellId":0}]},{"rank":2,"spellId":504893,"level":1,"description":"Increases all primary stats by 8%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:504893:effect:0:aura:137","name":"Alacrity (Aura 137)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"all-primary","operation":"percent","value":0.08}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":137,"miscValue":-1,"triggerSpellId":0}]}],"talentEntryId":29871},{"id":"coa-20-atheranns-wickedness-73-704642","classId":"bloodmage","dbcSpellId":704642,"name":"Atherann's Wickedness","unlockLevel":1,"icon":"/assets/ui/spells/spell_shadow_destructivesoul.png","sigil":"AS","description":"Atherann's WickednessRank 1Increases your Shadow damage dealt by 4% and increases your hit chance by 3%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704642:effect:0:aura:79","name":"Atherann's Wickedness (Aura 79)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"dealt","school":"shadow","operation":"percent","value":0.04}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":79,"miscValue":32,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:704642:effect:1:aura:333","name":"Atherann's Wickedness (Aura 333)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":333,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":704642,"level":1,"description":"Atherann's WickednessRank 1Increases your Shadow damage dealt by 4% and increases your hit chance by 3%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704642:effect:0:aura:79","name":"Atherann's Wickedness (Aura 79)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"dealt","school":"shadow","operation":"percent","value":0.04}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":79,"miscValue":32,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:704642:effect:1:aura:333","name":"Atherann's Wickedness (Aura 333)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":333,"miscValue":0,"triggerSpellId":0}]},{"rank":2,"spellId":704643,"level":1,"description":"Atherann's WickednessRank 2Increases the damage of Atherann's Anguish by 20%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704643:effect:0:aura:108","name":"Atherann's Wickedness (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}]}]},{"id":"coa-tree-8215","classId":"bloodmage","dbcSpellId":504627,"name":"Blood Bond","unlockLevel":1,"icon":"/assets/ui/spells/nhi_bloodsacrifice_border.png","sigil":"BB","description":"Bond yourself to an ally for 30 minutes, causing direct damage taken by tLine truncated
{"schemaVersion":1,"classId":"bloodmage","abilities":[{"id":"coa-tree-29871","classId":"bloodmage","dbcSpellId":504285,"name":"Alacrity","unlockLevel":1,"icon":"/assets/ui/spells/5_run_border.png","sigil":"AL","description":"Increases all primary stats by 4%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:504285:effect:0:aura:137","name":"Alacrity (Aura 137)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"all-primary","operation":"percent","value":0.04}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":137,"miscValue":-1,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":504285,"level":1,"description":"Increases all primary stats by 4%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:504285:effect:0:aura:137","name":"Alacrity (Aura 137)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"all-primary","operation":"percent","value":0.04}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":137,"miscValue":-1,"triggerSpellId":0}]},{"rank":2,"spellId":504893,"level":1,"description":"Increases all primary stats by 8%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:504893:effect:0:aura:137","name":"Alacrity (Aura 137)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"all-primary","operation":"percent","value":0.08}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":137,"miscValue":-1,"triggerSpellId":0}]}],"talentEntryId":29871},{"id":"coa-20-atheranns-wickedness-73-704642","classId":"bloodmage","dbcSpellId":704642,"name":"Atherann's Wickedness","unlockLevel":1,"icon":"/assets/ui/spells/spell_shadow_destructivesoul.png","sigil":"AS","description":"Increases your Shadow damage dealt by 4% and increases your hit chance by 3%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704642:effect:0:aura:79","name":"Atherann's Wickedness (Aura 79)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"dealt","school":"shadow","operation":"percent","value":0.04}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":79,"miscValue":32,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:704642:effect:1:aura:333","name":"Atherann's Wickedness (Aura 333)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":333,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":704642,"level":1,"description":"Increases your Shadow damage dealt by 4% and increases your hit chance by 3%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704642:effect:0:aura:79","name":"Atherann's Wickedness (Aura 79)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"dealt","school":"shadow","operation":"percent","value":0.04}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":79,"miscValue":32,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:704642:effect:1:aura:333","name":"Atherann's Wickedness (Aura 333)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":333,"miscValue":0,"triggerSpellId":0}]},{"rank":2,"spellId":704643,"level":1,"description":"Increases the damage of Atherann's Anguish by $s1%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704643:effect:0:aura:108","name":"Atherann's Wickedness (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}]}]},{"id":"coa-tree-8215","classId":"bloodmage","dbcSpellId":504627,"name":"Blood Bond","unlockLevel":1,"icon":"/assets/ui/spells/nhi_bloodsacrifice_border.png","sigil":"BB","description":"Bond yourself to an ally for 30 minutes, causing direct damage taken by the ally to generate 1 Rage and 3% base health and redirect -10% of their threat generated to you. Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"chronomancer","abilities":[{"id":"coa-tree-30277","classId":"chronomancer","dbcSpellId":800857,"name":"Accelerated Recovery","unlockLevel":1,"icon":"/assets/ui/spells/spell_holy_healingfocus.png","sigil":"AR","description":"Accelerated RecoveryRank 118% of base mana Instant castAccelerates the bodies natural healing process, healing the target for (15*1000/3)*(12+0+Heal*0.23) over 15 sec. Periodic healing done by this scales with your spell haste.","target":"friendly","range":{"min":0,"max":40},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":18,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:800857:effect:0:aura:8","name":"Accelerated Recovery (Aura 8)","disposition":"buff","hideFromAuraStrip":true,"durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"sourceEffectType":6,"sourceAuraType":8,"miscValue":0,"triggerSpellId":0},{"kind":"hot","coefficient":0.24070173263549804,"basePoints":12,"dieSides":1,"pointsPerLevel":0.6052629947662354,"bonusPowerCoefficient":0.23,"sourceLevel":10,"maxScalingLevel":16,"ticks":5,"intervalMs":3000},{"kind":"apply-aura","aura":{"id":"coa:800857:effect:1:aura:283","name":"Accelerated Recovery (Aura 283)","disposition":"buff","durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"sourceEffectType":3,"sourceAuraType":283,"miscValue":0,"triggerSpellId":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":800857,"level":1,"description":"Accelerated RecoveryRank 118% of base mana Instant castAccelerates the bodies natural healing process, healing the target for (15*1000/3)*(12+0+Heal*0.23) over 15 sec. Periodic healing done by this scales with your spell haste.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":18,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:800857:effect:0:aura:8","name":"Accelerated Recovery (Aura 8)","disposition":"buff","hideFromAuraStrip":true,"durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"sourceEffectType":6,"sourceAuraType":8,"miscValue":0,"triggerSpellId":0},{"kind":"hot","coefficient":0.24070173263549804,"basePoints":12,"dieSides":1,"pointsPerLevel":0.6052629947662354,"bonusPowerCoefficient":0.23,"sourceLevel":10,"maxScalingLevel":16,"ticks":5,"intervalMs":3000},{"kind":"apply-aura","aura":{"id":"coa:800857:effect:1:aura:283","name":"Accelerated Recovery (Aura 283)","disposition":"buff","durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"sourceEffectType":3,"sourceAuraType":283,"miscValue":0,"triggerSpellId":0}]}],"talentEntryId":30277},{"id":"coa-tree-4032","classId":"chronomancer","dbcSpellId":92119,"name":"Aeon of Resilience","unlockLevel":1,"icon":"/assets/ui/spells/inv_trinket_80_kultiras02a.png","sigil":"AO","description":"Level 10 Passive Teaches you Aeon of Resilience.Aeon of ResilienceReduces Epoch's cast time by -25% and it's mana cost by -10%, and healing done by it now reduces the target's damage taken by -5% for 6 seconds.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"heal","coefficient":1},{"kind":"apply-aura","aura":{"id":"coa:92119:effect:0:aura:4","name":"Aeon of Resilience (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":92119,"level":1,"description":"Level 10 Passive Teaches you Aeon of Resilience.Aeon of ResilienceReduces Epoch's cast time by -25% and it's mana cost by -10%, and healing done by it now reduces the target's damage taken by -5% for 6 seconds.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"heal","coefficient":1},{"kind":"apply-aura","aura":{"id":"coa:92119:effect:0:aura:4","name":"Aeon of Resilience (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0}]}],"talentEntryId":4032},{"id":"coa-tree-6214","classId":"chronomancer","dbcSpellId":560948,"name":"Ahead of the Game","unlockLevel":1,"icon":"/assets/ui/spells/achievement_bg_win_av_x_times.png","sigil":"AO","description":"Every 10th instance of your damage dealt or healing now gives you 60 increased spell power for 10 seconds.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:5609Line truncated
{"schemaVersion":1,"classId":"chronomancer","abilities":[{"id":"coa-tree-30277","classId":"chronomancer","dbcSpellId":800857,"name":"Accelerated Recovery","unlockLevel":1,"icon":"/assets/ui/spells/spell_holy_healingfocus.png","sigil":"AR","description":"Accelerates the bodies natural healing process, healing the target for 144 + 276% healing over 15 seconds.","target":"friendly","range":{"min":0,"max":40},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":18,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:800857:effect:0:aura:8","name":"Accelerated Recovery (Aura 8)","disposition":"buff","hideFromAuraStrip":true,"durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"sourceEffectType":6,"sourceAuraType":8,"miscValue":0,"triggerSpellId":0},{"kind":"hot","coefficient":0.24070173263549804,"basePoints":12,"dieSides":1,"pointsPerLevel":0.6052629947662354,"bonusPowerCoefficient":0.23,"sourceLevel":10,"maxScalingLevel":16,"ticks":5,"intervalMs":3000},{"kind":"apply-aura","aura":{"id":"coa:800857:effect:1:aura:283","name":"Accelerated Recovery (Aura 283)","disposition":"buff","durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"sourceEffectType":3,"sourceAuraType":283,"miscValue":0,"triggerSpellId":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":800857,"level":1,"description":"Accelerates the bodies natural healing process, healing the target for 144 + 276% healing over 15 seconds.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":18,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:800857:effect:0:aura:8","name":"Accelerated Recovery (Aura 8)","disposition":"buff","hideFromAuraStrip":true,"durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"sourceEffectType":6,"sourceAuraType":8,"miscValue":0,"triggerSpellId":0},{"kind":"hot","coefficient":0.24070173263549804,"basePoints":12,"dieSides":1,"pointsPerLevel":0.6052629947662354,"bonusPowerCoefficient":0.23,"sourceLevel":10,"maxScalingLevel":16,"ticks":5,"intervalMs":3000},{"kind":"apply-aura","aura":{"id":"coa:800857:effect:1:aura:283","name":"Accelerated Recovery (Aura 283)","disposition":"buff","durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"sourceEffectType":3,"sourceAuraType":283,"miscValue":0,"triggerSpellId":0}]}],"talentEntryId":30277},{"id":"coa-tree-4032","classId":"chronomancer","dbcSpellId":92119,"name":"Aeon of Resilience","unlockLevel":1,"icon":"/assets/ui/spells/inv_trinket_80_kultiras02a.png","sigil":"AO","description":"Level 10 Passive Teaches you Aeon of Resilience.Aeon of ResilienceReduces Epoch's cast time by -25% and it's mana cost by -25%, and Epoch causes an active Accelerated Recovery on the target to bounce to another nearby ally.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:92119:effect:0:aura:4","name":"Aeon of Resilience (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":92119,"level":1,"description":"Level 10 Passive Teaches you Aeon of Resilience.Aeon of ResilienceReduces Epoch's cast time by -25% and it's mana cost by -25%, and Epoch causes an active Accelerated Recovery on the target to bounce to another nearby ally.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:92119:effect:0:aura:4","name":"Aeon of Resilience (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0}]}],"talentEntryId":4032},{"id":"coa-tree-6214","classId":"chronomancer","dbcSpellId":560948,"name":"Ahead of the Game","unlockLevel":1,"icon":"/assets/ui/spells/achievement_bg_win_av_x_times.png","sigil":"AO","description":"Every 10th instance of your damage dealt or healing now gives you 60 increased spell power for 10 seconds.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:560948:effect:0:aura:42","name":"Ahead of the Game (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:560948:proc:0:592009","triggers":["heal"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":592009}Line truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"cultist","abilities":[{"id":"coa-25-abyssal-decay-89-500705","classId":"cultist","dbcSpellId":500705,"name":"Abyssal Decay","unlockLevel":1,"icon":"/assets/ui/spells/spell_priest_void_blast.png","sigil":"AD","description":"Abyssal DecayRank 19% of base mana Instant castApplies an Eldritch curse to an enemy, causing 9+(PL*0.6) Shadow damage every 3 sec for 18 sec. Generates 5 Insanity.","target":"hostile","range":{"min":0,"max":30},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":9,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:500705:effect:0:aura:3","name":"Abyssal Decay (Aura 3)","disposition":"debuff","hideFromAuraStrip":true,"durationMs":18000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse"},"sourceEffectType":6,"sourceAuraType":3,"miscValue":0,"triggerSpellId":0},{"kind":"dot","coefficient":0.24166666716337204,"basePoints":9,"dieSides":5,"pointsPerLevel":0.6000000238418579,"bonusPowerCoefficient":0,"sourceLevel":1,"maxScalingLevel":9,"ticks":6,"intervalMs":3000,"tag":"spell-500705"},{"kind":"utility","action":"class-script","effectType":168,"auraType":0,"miscValue":120640,"triggerSpellId":0,"durationMs":18000}],"passive":false,"source":"coa-progression","ranks":[{"rank":1,"spellId":500705,"level":1,"description":"Abyssal DecayRank 19% of base mana Instant castApplies an Eldritch curse to an enemy, causing 9+(PL*0.6) Shadow damage every 3 sec for 18 sec. Generates 5 Insanity.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":9,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:500705:effect:0:aura:3","name":"Abyssal Decay (Aura 3)","disposition":"debuff","hideFromAuraStrip":true,"durationMs":18000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse"},"sourceEffectType":6,"sourceAuraType":3,"miscValue":0,"triggerSpellId":0},{"kind":"dot","coefficient":0.24166666716337204,"basePoints":9,"dieSides":5,"pointsPerLevel":0.6000000238418579,"bonusPowerCoefficient":0,"sourceLevel":1,"maxScalingLevel":9,"ticks":6,"intervalMs":3000,"tag":"spell-500705"},{"kind":"utility","action":"class-script","effectType":168,"auraType":0,"miscValue":120640,"triggerSpellId":0,"durationMs":18000}]},{"rank":2,"spellId":502144,"level":10,"description":"Abyssal DecayRank 29% of base mana Instant castApplies an Eldritch curse to an enemy, causing 17+(PL*1-10*1) Shadow damage every 3 sec for 18 sec. Generates 5 Insanity.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":9,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:502144:effect:0:aura:3","name":"Abyssal Decay (Aura 3)","disposition":"debuff","hideFromAuraStrip":true,"durationMs":18000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse"},"sourceEffectType":6,"sourceAuraType":3,"miscValue":0,"triggerSpellId":0},{"kind":"dot","coefficient":0.36066666603088376,"basePoints":17,"dieSides":1,"pointsPerLevel":1.0049999952316284,"bonusPowerCoefficient":0,"sourceLevel":10,"maxScalingLevel":18,"ticks":6,"intervalMs":3000,"tag":"spell-502144"},{"kind":"utility","action":"class-script","effectType":168,"auraType":0,"miscValue":120640,"triggerSpellId":0,"durationMs":18000}]},{"rank":3,"spellId":502145,"level":19,"description":"Abyssal DecayRank 39% of base mana Instant castApplies an Eldritch curse to an enemy, causing 31+(PL*1.4-19*1.4) Shadow damage every 3 sec for 18 sec. Generates 5 Insanity.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":9,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:502145:effect:0:aura:3","name":"Abyssal Decay (Aura 3)","disposition":"debuff","hideFromAuraStrip":true,"durationMs":18000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse"},"sourceEffectType":6,"sourceAuraType":3,"miscValue":0,"triggerSpellId":0},{"kind":"dot","coefficient":0.5590245174426659,"basePoints":31,"dieSides":1,"pointsPerLevel":1.3695000410079956,"bonusPowerCoefficient":0,"sourceLevel":19,"maxScalingLevel":27,"ticks":6,"intervalMs":3000,"tag":"spell-502145"},{"kind":"utility","action":"class-script","effectType":168,"auraType":0,"miscValue":120640,"triggerSpellId":0,"durationMs":18000}]},{"rank":4,"spellId":502146,"level":28,"description":"Abyssal DecayRank 49% of base mana Instant castApplies an Eldritch curse to an enemy, causing 55+(PL*1.7-28*1.7) Shadow damage every 3 sec for18 sec. Generates 5 Insanity.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":9,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:502146:effect:0:aura:3","name":"Abyssal Decay (Aura 3)","disposition":"debuff","hideFromAuraStrip":true,"durLine truncated
{"schemaVersion":1,"classId":"cultist","abilities":[{"id":"coa-25-abyssal-decay-89-500705","classId":"cultist","dbcSpellId":500705,"name":"Abyssal Decay","unlockLevel":1,"icon":"/assets/ui/spells/spell_priest_void_blast.png","sigil":"AD","description":"Applies an Eldritch curse to an enemy, causing ${$m1+($pl*0.6)} Shadow damage every $t1 sec for $d. Generates 5 Insanity.","target":"hostile","range":{"min":0,"max":30},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":9,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:500705:effect:0:aura:3","name":"Abyssal Decay (Aura 3)","disposition":"debuff","hideFromAuraStrip":true,"durationMs":18000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse"},"sourceEffectType":6,"sourceAuraType":3,"miscValue":0,"triggerSpellId":0},{"kind":"dot","coefficient":0.24166666716337204,"basePoints":9,"dieSides":5,"pointsPerLevel":0.6000000238418579,"bonusPowerCoefficient":0,"sourceLevel":1,"maxScalingLevel":9,"ticks":6,"intervalMs":3000,"tag":"spell-500705"},{"kind":"utility","action":"class-script","effectType":168,"auraType":0,"miscValue":120640,"triggerSpellId":0,"durationMs":18000}],"passive":false,"source":"coa-progression","ranks":[{"rank":1,"spellId":500705,"level":1,"description":"Applies an Eldritch curse to an enemy, causing ${$m1+($pl*0.6)} Shadow damage every $t1 sec for $d. Generates 5 Insanity.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":9,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:500705:effect:0:aura:3","name":"Abyssal Decay (Aura 3)","disposition":"debuff","hideFromAuraStrip":true,"durationMs":18000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse"},"sourceEffectType":6,"sourceAuraType":3,"miscValue":0,"triggerSpellId":0},{"kind":"dot","coefficient":0.24166666716337204,"basePoints":9,"dieSides":5,"pointsPerLevel":0.6000000238418579,"bonusPowerCoefficient":0,"sourceLevel":1,"maxScalingLevel":9,"ticks":6,"intervalMs":3000,"tag":"spell-500705"},{"kind":"utility","action":"class-script","effectType":168,"auraType":0,"miscValue":120640,"triggerSpellId":0,"durationMs":18000}]},{"rank":2,"spellId":502144,"level":10,"description":"Applies an Eldritch curse to an enemy, causing ${$m1+($pl*1-10*1)} Shadow damage every $t1 sec for $d. Generates 5 Insanity.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":9,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:502144:effect:0:aura:3","name":"Abyssal Decay (Aura 3)","disposition":"debuff","hideFromAuraStrip":true,"durationMs":18000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse"},"sourceEffectType":6,"sourceAuraType":3,"miscValue":0,"triggerSpellId":0},{"kind":"dot","coefficient":0.36066666603088376,"basePoints":17,"dieSides":1,"pointsPerLevel":1.0049999952316284,"bonusPowerCoefficient":0,"sourceLevel":10,"maxScalingLevel":18,"ticks":6,"intervalMs":3000,"tag":"spell-502144"},{"kind":"utility","action":"class-script","effectType":168,"auraType":0,"miscValue":120640,"triggerSpellId":0,"durationMs":18000}]},{"rank":3,"spellId":502145,"level":19,"description":"Applies an Eldritch curse to an enemy, causing ${$m1+($pl*1.4-19*1.4)} Shadow damage every $t1 sec for $d. Generates 5 Insanity.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":9,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:502145:effect:0:aura:3","name":"Abyssal Decay (Aura 3)","disposition":"debuff","hideFromAuraStrip":true,"durationMs":18000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse"},"sourceEffectType":6,"sourceAuraType":3,"miscValue":0,"triggerSpellId":0},{"kind":"dot","coefficient":0.5590245174426659,"basePoints":31,"dieSides":1,"pointsPerLevel":1.3695000410079956,"bonusPowerCoefficient":0,"sourceLevel":19,"maxScalingLevel":27,"ticks":6,"intervalMs":3000,"tag":"spell-502145"},{"kind":"utility","action":"class-script","effectType":168,"auraType":0,"miscValue":120640,"triggerSpellId":0,"durationMs":18000}]},{"rank":4,"spellId":502146,"level":28,"description":"Applies an Eldritch curse to an enemy, causing ${$m1+($pl*1.7-28*1.7)} Shadow damage every $t1 sec for$d. Generates 5 Insanity.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":9,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:502146:effect:0:aura:3","name":"Abyssal Decay (Aura 3)","disposition":"debuff","hideFromAuraStrip":true,"durationMs":18000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse"},"sourceEffectType":6,"sourceAuraType":3,"miscValue":0,"triggerSpellId":0},{"kind":"dot","coefficient":0.8027286751325741,"basePoints":55,Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"felsworn","abilities":[{"id":"coa-tree-29686","classId":"felsworn","dbcSpellId":803904,"name":"Annihilation","unlockLevel":1,"icon":"/assets/ui/spells/ability_boss_lordanthricystgreen.png","sigil":"AN","description":"Gorge on fel energy, guaranteeing your next direct instance of damage to critically strike, but causing it to consume 5% of your maximum health. Lasts for 5 attacks or 12 seconds.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:803904:effect:0:aura:290","name":"Annihilation (Aura 290)","disposition":"buff","durationMs":12000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:803904:effect:1:aura:42","name":"Annihilation (Aura 42)","disposition":"buff","durationMs":12000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:803904:proc:1:807961","triggers":["crit","hit"],"chance":1,"charges":5,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":807961}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":807961}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":803904,"level":1,"description":"Gorge on fel energy, guaranteeing your next direct instance of damage to critically strike, but causing it to consume 5% of your maximum health. Lasts for 5 attacks or 12 seconds.","castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:803904:effect:0:aura:290","name":"Annihilation (Aura 290)","disposition":"buff","durationMs":12000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:803904:effect:1:aura:42","name":"Annihilation (Aura 42)","disposition":"buff","durationMs":12000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:803904:proc:1:807961","triggers":["crit","hit"],"chance":1,"charges":5,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":807961}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":807961}]}],"talentEntryId":29686},{"id":"coa-tree-30301","classId":"felsworn","dbcSpellId":560822,"name":"Anti-Magic","unlockLevel":1,"icon":"/assets/ui/spells/spell_shadow_antimagicshell.png","sigil":"AM","description":"When Hateforged Barrier is removed from you, you now reduce -10% of all Magic damage taken for 8 seconds. In addition, Hateforged Barrier now heals for an additional 2% of your maximum health each tick.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"heal","coefficient":1},{"kind":"apply-aura","aura":{"id":"coa:560822:effect:0:aura:4","name":"Anti-Magic (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:560822:effect:1:aura:107","name":"Anti-Magic (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.02}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":3,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":560822,"level":1,"description":"When Hateforged Barrier is removed from you, you now reduce -10% of all Magic damage taken for 8 seconds. In addition, Hateforged Barrier now heals for an additional 2% of your maximum health each tick.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"heal","coefficient":1},{"kind":"apply-aura","aura":{"id":"coa:560822:effect:0:aura:4","name":"Anti-Magic (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:560822:effect:1:aura:107","name":"Anti-Magic (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.02}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":3,"triggerSpellId":0}]}],"talentEntryId":30301},{"id":"coa-tree-33671","classId":"felsworn","dbcSpellId":706266,"namLine truncated
{"schemaVersion":1,"classId":"felsworn","abilities":[{"id":"coa-tree-29686","classId":"felsworn","dbcSpellId":803904,"name":"Annihilation","unlockLevel":1,"icon":"/assets/ui/spells/ability_boss_lordanthricystgreen.png","sigil":"AN","description":"Gorge on fel energy, guaranteeing your next direct instance of damage to critically strike, but causing it to consume 5% of your maximum health. Lasts for 5 attacks or 12 seconds.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":0,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:803904:effect:0:aura:290","name":"Annihilation (Aura 290)","disposition":"buff","durationMs":12000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:803904:effect:1:aura:42","name":"Annihilation (Aura 42)","disposition":"buff","durationMs":12000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:803904:proc:1:807961","triggers":["crit","hit"],"chance":1,"charges":5,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":807961}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":807961}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":803904,"level":1,"description":"Gorge on fel energy, guaranteeing your next direct instance of damage to critically strike, but causing it to consume 5% of your maximum health. Lasts for 5 attacks or 12 seconds.","castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":0,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:803904:effect:0:aura:290","name":"Annihilation (Aura 290)","disposition":"buff","durationMs":12000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:803904:effect:1:aura:42","name":"Annihilation (Aura 42)","disposition":"buff","durationMs":12000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:803904:proc:1:807961","triggers":["crit","hit"],"chance":1,"charges":5,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":807961}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":807961}]}],"talentEntryId":29686},{"id":"coa-tree-30301","classId":"felsworn","dbcSpellId":560822,"name":"Anti-Magic","unlockLevel":1,"icon":"/assets/ui/spells/spell_shadow_antimagicshell.png","sigil":"AM","description":"When Hateforged Barrier is removed from you, you now reduce -10% of all Magic damage taken for 8 seconds. In addition, Hateforged Barrier now heals for an additional 2% of your maximum health each tick.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"heal","coefficient":1},{"kind":"apply-aura","aura":{"id":"coa:560822:effect:0:aura:4","name":"Anti-Magic (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:560822:effect:1:aura:107","name":"Anti-Magic (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.02}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":3,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":560822,"level":1,"description":"When Hateforged Barrier is removed from you, you now reduce -10% of all Magic damage taken for 8 seconds. In addition, Hateforged Barrier now heals for an additional 2% of your maximum health each tick.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"heal","coefficient":1},{"kind":"apply-aura","aura":{"id":"coa:560822:effect:0:aura:4","name":"Anti-Magic (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:560822:effect:1:aura:107","name":"Anti-Magic (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.02}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":3,"triggerSpellId":0}]}],"talentEntryId":30301},{"id":"coa-tree-33671","classId":"felsworn","dbcSpellId":706266,"name":"ArmamentLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"guardian","abilities":[{"id":"coa-18-banner-boy-68-705358","classId":"guardian","dbcSpellId":705358,"name":"Banner Boy","unlockLevel":1,"icon":"/assets/ui/spells/achievement_bg_captureflag_wsg.png","sigil":"BB","description":"Banner BoyRank 1Reduces the Energy cost of Banners by 10.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705358:effect:0:aura:107","name":"Banner Boy (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705358:effect:1:aura:4","name":"Banner Boy (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705358:effect:2:aura:4","name":"Banner Boy (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":3,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705358,"level":1,"description":"Banner BoyRank 1Reduces the Energy cost of Banners by 10.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705358:effect:0:aura:107","name":"Banner Boy (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705358:effect:1:aura:4","name":"Banner Boy (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705358:effect:2:aura:4","name":"Banner Boy (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":3,"triggerSpellId":0}]}]},{"id":"coa-tree-11797","classId":"guardian","dbcSpellId":803683,"name":"Battle Drums","unlockLevel":1,"icon":"/assets/ui/spells/inv_archaeology_70_tauren_drum.png","sigil":"BD","description":"Place down 3 Battle Drums around you for 1 minute. Allies may click on the drums to increase their critical strike chance, haste, damage, and healing done by 10% and causes their damage dealt to trigger a Sound of War for their next 5 instances of damage or 30 seconds.","target":"hostile","range":{"min":0,"max":0},"radius":3,"castMode":"instant","castTimeMs":0,"cooldownMs":180000,"gcdMs":1500,"cost":{"resource":"energy","amount":50},"effects":[{"kind":"damage","coefficient":1},{"kind":"heal","coefficient":1},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":803683,"level":1,"description":"Place down 3 Battle Drums around you for 1 minute. Allies may click on the drums to increase their critical strike chance, haste, damage, and healing done by 10% and causes their damage dealt to trigger a Sound of War for their next 5 instances of damage or 30 seconds.","castMode":"instant","castTimeMs":0,"cooldownMs":180000,"gcdMs":1500,"cost":{"resource":"energy","amount":50},"effects":[{"kind":"damage","coefficient":1},{"kind":"heal","coefficient":1},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000}]}],"talentEntryId":11797},{"id":"guardian-battle-rush","classId":"guardian","dbcSpellId":802197,"name":"Battle Rush","unlockLevel":1,"icon":"/assets/ui/spells/warrior_talent_icon_skirmisher.png","sigil":"BR","description":"Battle RushRank 1Instant cast30 sec cooldownCharge an enemy, dealing 16+0+AP*0.09996 Physical damage and stunnLine truncated
{"schemaVersion":1,"classId":"guardian","abilities":[{"id":"coa-18-banner-boy-68-705358","classId":"guardian","dbcSpellId":705358,"name":"Banner Boy","unlockLevel":1,"icon":"/assets/ui/spells/achievement_bg_captureflag_wsg.png","sigil":"BB","description":"Reduces the Energy cost of Banners by $s1.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705358:effect:0:aura:107","name":"Banner Boy (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705358:effect:1:aura:4","name":"Banner Boy (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705358:effect:2:aura:4","name":"Banner Boy (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":3,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705358,"level":1,"description":"Reduces the Energy cost of Banners by $s1.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705358:effect:0:aura:107","name":"Banner Boy (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705358:effect:1:aura:4","name":"Banner Boy (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705358:effect:2:aura:4","name":"Banner Boy (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":3,"triggerSpellId":0}]}]},{"id":"coa-tree-11797","classId":"guardian","dbcSpellId":803683,"name":"Battle Drums","unlockLevel":1,"icon":"/assets/ui/spells/inv_archaeology_70_tauren_drum.png","sigil":"BD","description":"Place down 3 Battle Drums around you for 1 minute. Allies within 12 yards of the drums have their critical strike chance, haste, damage, and healing done increased by 10% and their damage dealt will trigger a Sound of War for their next 5 instances of damage or 30 seconds.","target":"hostile","range":{"min":0,"max":0},"radius":3,"castMode":"instant","castTimeMs":0,"cooldownMs":180000,"gcdMs":1500,"cost":{"resource":"energy","amount":50},"effects":[{"kind":"damage","coefficient":1},{"kind":"heal","coefficient":1},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":803683,"level":1,"description":"Place down 3 Battle Drums around you for 1 minute. Allies within 12 yards of the drums have their critical strike chance, haste, damage, and healing done increased by 10% and their damage dealt will trigger a Sound of War for their next 5 instances of damage or 30 seconds.","castMode":"instant","castTimeMs":0,"cooldownMs":180000,"gcdMs":1500,"cost":{"resource":"energy","amount":50},"effects":[{"kind":"damage","coefficient":1},{"kind":"heal","coefficient":1},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000},{"kind":"utility","action":"portal","effectType":50,"auraType":0,"miscValue":9000117,"triggerSpellId":0,"durationMs":60000}]}],"talentEntryId":11797},{"id":"guardian-battle-rush","classId":"guardian","dbcSpellId":802197,"name":"Battle Rush","unlockLevel":1,"icon":"/assets/ui/spells/warrior_talent_icon_skirmisher.png","sigil":"BR","description":"Charge an enemy, dealing ${$m2+0+$AP*0.09996} Physical damage and stunning them for $d.","target":"hostile","range":{"min":8,"max":25},"caLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"knight-of-xoroth","abilities":[{"id":"coa-tree-30701","classId":"knight-of-xoroth","dbcSpellId":805679,"name":"Black Shield","unlockLevel":1,"icon":"/assets/ui/spells/spell_warlock_soulburn_haunt.png","sigil":"BS","description":"Consume all of your Demon's Blood stacks to create a demonic shield that absorbs 860 damage, increased by 20% per Demon's Blood stack, for 30 seconds.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":120000,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"shield","coefficient":1,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":0,"triggerSpellId":0,"durationMs":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":805679,"level":1,"description":"Consume all of your Demon's Blood stacks to create a demonic shield that absorbs 860 damage, increased by 20% per Demon's Blood stack, for 30 seconds.","castMode":"instant","castTimeMs":0,"cooldownMs":120000,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"shield","coefficient":1,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":0,"triggerSpellId":0,"durationMs":0}]}],"talentEntryId":30701},{"id":"coa-tree-34064","classId":"knight-of-xoroth","dbcSpellId":300395,"name":"Boiling Blood","unlockLevel":1,"icon":"/assets/ui/spells/nhi_bloodboil_border.png","sigil":"BB","description":"Casting Suffuse now increases your healing received by 25% for the first 6 seconds of it's duration.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:300395:effect:0:aura:42","name":"Boiling Blood (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:300395:proc:0:300394","triggers":["cast","heal"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":300394}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":300394}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":300395,"level":1,"description":"Casting Suffuse now increases your healing received by 25% for the first 6 seconds of it's duration.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:300395:effect:0:aura:42","name":"Boiling Blood (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:300395:proc:0:300394","triggers":["cast","heal"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":300394}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":300394}]}],"talentEntryId":34064},{"id":"coa-tree-4018","classId":"knight-of-xoroth","dbcSpellId":92104,"name":"Brimstone Buckler","unlockLevel":1,"icon":"/assets/ui/spells/ability_warlock_improveddemonictactics.png","sigil":"BB","description":"Level 10 Passive Successful blocks now have a 30% chance to summon 1 Hellfire Imp to aid you in battle for 12 seconds. Can only occur once every 3 sec.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:92104:effect:0:aura:23","name":"Brimstone Buckler (Aura 23)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:92104:proc:0:562029","triggers":["periodic"],"chance":0.3,"internalCooldownMs":3000,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":562029}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":23,"miscValue":0,"triggerSpellId":562029},{"kind":"apply-aura","aura":{"id":"coa:92104:effect:1:aura:42","name":"Brimstone Buckler (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:92104:proc:1:805966","triggers":["block"],"chance":0.3,"internalCooldownMs":3000,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":805966}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":805966}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":92104,"level":1,"description":"Level 10 Passive Successful blocks now have a 30% chance to summon 1 Hellfire Imp to aid you in battle for 12 seconds. Can only occur once every 3 sec.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:92104:effect:0:aura:23","name":"Brimstone Buckler (Aura 23)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:92104:proLine truncated
{"schemaVersion":1,"classId":"knight-of-xoroth","abilities":[{"id":"coa-tree-30701","classId":"knight-of-xoroth","dbcSpellId":805679,"name":"Black Shield","unlockLevel":1,"icon":"/assets/ui/spells/spell_warlock_soulburn_haunt.png","sigil":"BS","description":"Consume all of your Demon's Blood stacks to create a demonic shield that absorbs 860 damage, increased by 20% per Demon's Blood stack, for 30 seconds.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":120000,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"shield","coefficient":1,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":0,"triggerSpellId":0,"durationMs":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":805679,"level":1,"description":"Consume all of your Demon's Blood stacks to create a demonic shield that absorbs 860 damage, increased by 20% per Demon's Blood stack, for 30 seconds.","castMode":"instant","castTimeMs":0,"cooldownMs":120000,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"shield","coefficient":1,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":0,"triggerSpellId":0,"durationMs":0}]}],"talentEntryId":30701},{"id":"coa-tree-34064","classId":"knight-of-xoroth","dbcSpellId":300395,"name":"Boiling Blood","unlockLevel":1,"icon":"/assets/ui/spells/nhi_bloodboil_border.png","sigil":"BB","description":"Casting Suffuse now increases your healing received by 25% for the first 6 seconds of it's duration.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:300395:effect:0:aura:42","name":"Boiling Blood (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:300395:proc:0:300394","triggers":["cast","heal"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":300394}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":300394}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":300395,"level":1,"description":"Casting Suffuse now increases your healing received by 25% for the first 6 seconds of it's duration.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:300395:effect:0:aura:42","name":"Boiling Blood (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:300395:proc:0:300394","triggers":["cast","heal"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":300394}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":300394}]}],"talentEntryId":34064},{"id":"coa-tree-4018","classId":"knight-of-xoroth","dbcSpellId":92104,"name":"Brimstone Buckler","unlockLevel":1,"icon":"/assets/ui/spells/ability_warlock_improveddemonictactics.png","sigil":"BB","description":"Level 10 Passive Successful blocks now have a 30% chance to summon 1 Hellfire Imp to aid you in battle for 12 seconds. Can only occur once every 3 sec.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:92104:effect:0:aura:23","name":"Brimstone Buckler (Aura 23)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:92104:proc:0:562029","triggers":["periodic"],"chance":0.3,"internalCooldownMs":3000,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":562029}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":23,"miscValue":0,"triggerSpellId":562029},{"kind":"apply-aura","aura":{"id":"coa:92104:effect:1:aura:42","name":"Brimstone Buckler (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:92104:proc:1:805966","triggers":["block"],"chance":0.3,"internalCooldownMs":3000,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":805966}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":805966}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":92104,"level":1,"description":"Level 10 Passive Successful blocks now have a 30% chance to summon 1 Hellfire Imp to aid you in battle for 12 seconds. Can only occur once every 3 sec.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:92104:effect:0:aura:23","name":"Brimstone Buckler (Aura 23)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:92104:proc:0:562029","triggLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"necromancer","abilities":[{"id":"coa-tree-30600","classId":"necromancer","dbcSpellId":805428,"name":"Animate: Frost Wyrm","unlockLevel":1,"icon":"/assets/ui/spells/5_dragoncoldbreath_border.png","sigil":"AF","description":"Animate a Frost Wyrm that flies behind the Necromancer that blasts nearby enemies every 2 sec for 30 seconds, dealing 1500 + 14.88% frost SP + 14.88% Intellect Frost damage.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":120000,"gcdMs":1500,"cost":{"resource":"mana","amount":31,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"summon","creatureId":50177,"coefficient":0.08,"durationMs":30000}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":805428,"level":1,"description":"Animate a Frost Wyrm that flies behind the Necromancer that blasts nearby enemies every 2 sec for 30 seconds, dealing 1500 + 14.88% frost SP + 14.88% Intellect Frost damage.","castMode":"instant","castTimeMs":0,"cooldownMs":120000,"gcdMs":1500,"cost":{"resource":"mana","amount":31,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"summon","creatureId":50177,"coefficient":0.08,"durationMs":30000}]}],"talentEntryId":30600},{"id":"coa-23-animate-zombies-84-504315","classId":"necromancer","dbcSpellId":504315,"name":"Animate: Zombies","unlockLevel":1,"icon":"/assets/ui/spells/zombiewc3.png","sigil":"AZ","description":"Animate: ZombiesRank 121% of base mana 3 sec cast15 sec cooldownAnimate 2 Zombies to aid you in combat for 15 sec. Every 3 sec, Zombies emit Zombie Plague, dealing 79+1.0 Points Per Level+SP*0.1 Plague Damage to nearby enemies.","target":"hostile","range":{"min":0,"max":0},"radius":3,"castMode":"cast","castTimeMs":3000,"cooldownMs":15000,"gcdMs":1000,"cost":{"resource":"mana","amount":21,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"trigger-spell","spellId":525379,"expanded":true,"withValue":2},{"kind":"damage","coefficient":1},{"kind":"summon","creatureId":503031,"coefficient":0.08,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":524287,"triggerSpellId":500991,"durationMs":100}],"passive":false,"source":"coa-progression","ranks":[{"rank":1,"spellId":504315,"level":1,"description":"Animate: ZombiesRank 121% of base mana 3 sec cast15 sec cooldownAnimate 2 Zombies to aid you in combat for 15 sec. Every 3 sec, Zombies emit Zombie Plague, dealing 79+1.0 Points Per Level+SP*0.1 Plague Damage to nearby enemies.","castMode":"cast","castTimeMs":3000,"cooldownMs":15000,"gcdMs":1000,"cost":{"resource":"mana","amount":21,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"trigger-spell","spellId":525379,"expanded":true,"withValue":2},{"kind":"damage","coefficient":1},{"kind":"summon","creatureId":503031,"coefficient":0.08,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":524287,"triggerSpellId":500991,"durationMs":100}]},{"rank":2,"spellId":525378,"level":30,"description":"Animate: ZombiesRank 223% of base mana 3 sec cast15 sec cooldownAnimate 3 Zombies to aid you in combat for 15 sec. Every 3 sec, Zombies emit Zombie Plague, dealing 79+1.0 Points Per Level+SP*0.1 Plague Damage to nearby enemies.","castMode":"cast","castTimeMs":3000,"cooldownMs":15000,"gcdMs":1000,"cost":{"resource":"mana","amount":23,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"trigger-spell","spellId":525379,"expanded":true,"withValue":3},{"kind":"damage","coefficient":1},{"kind":"summon","creatureId":503031,"coefficient":0.08,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":524287,"triggerSpellId":500991,"durationMs":100}]},{"rank":3,"spellId":525381,"level":51,"description":"Animate: ZombiesRank 324% of base mana 3 sec cast15 sec cooldownAnimate 4 Zombies to aid you in combat for 10 sec. Every 3 sec, Zombies emit Zombie Plague, dealing 79+1.0 Points Per Level+SP*0.1 Plague Damage to nearby enemies.","castMode":"cast","castTimeMs":3000,"cooldownMs":15000,"gcdMs":1000,"cost":{"resource":"mana","amount":24,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"trigger-spell","spellId":525379,"expanded":true,"withValue":4},{"kind":"damage","coefficient":1},{"kind":"summon","creatureId":503031,"coefficient":0.08,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":524287,"triggerSpellId":500991,"durationMs":100}]}]},{"id":"coa-tree-29774","classId":"necromancer","dbcSpellId":802121,"name":"Bone Tithe","unlockLevel":1,"icon":"/assets/ui/spells/ossuary_bond.png","sigil":"BT","description":"Siphon life from your undead minions, sacrificing 40% of their health to grant yourself an absorb shield equal to half of the health stolen for 20 seconds. Usable while stunned.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMsLine truncated
{"schemaVersion":1,"classId":"necromancer","abilities":[{"id":"coa-tree-30600","classId":"necromancer","dbcSpellId":805428,"name":"Animate: Frost Wyrm","unlockLevel":1,"icon":"/assets/ui/spells/5_dragoncoldbreath_border.png","sigil":"AF","description":"Animate a Frost Wyrm that flies behind the Necromancer that blasts nearby enemies every 2 sec for 30 seconds, dealing 1500 + 14.88% frost SP + 14.88% Intellect Frost damage.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":120000,"gcdMs":1500,"cost":{"resource":"mana","amount":31,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"summon","creatureId":50177,"coefficient":0.08,"durationMs":30000}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":805428,"level":1,"description":"Animate a Frost Wyrm that flies behind the Necromancer that blasts nearby enemies every 2 sec for 30 seconds, dealing 1500 + 14.88% frost SP + 14.88% Intellect Frost damage.","castMode":"instant","castTimeMs":0,"cooldownMs":120000,"gcdMs":1500,"cost":{"resource":"mana","amount":31,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"summon","creatureId":50177,"coefficient":0.08,"durationMs":30000}]}],"talentEntryId":30600},{"id":"coa-23-animate-zombies-84-504315","classId":"necromancer","dbcSpellId":504315,"name":"Animate: Zombies","unlockLevel":1,"icon":"/assets/ui/spells/zombiewc3.png","sigil":"AZ","description":"Animate $s1 Zombies to aid you in combat for $525379d. Every $504023t1 sec, Zombies emit Zombie Plague, dealing ${$504022m1+$504022ppl1+$SP*0.1} Plague Damage to nearby enemies.","target":"hostile","range":{"min":0,"max":0},"radius":3,"castMode":"cast","castTimeMs":3000,"cooldownMs":15000,"gcdMs":1000,"cost":{"resource":"mana","amount":21,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"trigger-spell","spellId":525379,"expanded":true,"withValue":2},{"kind":"damage","coefficient":1},{"kind":"summon","creatureId":503031,"coefficient":0.08,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":524287,"triggerSpellId":500991,"durationMs":100}],"passive":false,"source":"coa-progression","ranks":[{"rank":1,"spellId":504315,"level":1,"description":"Animate $s1 Zombies to aid you in combat for $525379d. Every $504023t1 sec, Zombies emit Zombie Plague, dealing ${$504022m1+$504022ppl1+$SP*0.1} Plague Damage to nearby enemies.","castMode":"cast","castTimeMs":3000,"cooldownMs":15000,"gcdMs":1000,"cost":{"resource":"mana","amount":21,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"trigger-spell","spellId":525379,"expanded":true,"withValue":2},{"kind":"damage","coefficient":1},{"kind":"summon","creatureId":503031,"coefficient":0.08,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":524287,"triggerSpellId":500991,"durationMs":100}]},{"rank":2,"spellId":525378,"level":30,"description":"Animate $s1 Zombies to aid you in combat for $525379d. Every $504023t1 sec, Zombies emit Zombie Plague, dealing ${$504022m1+$504022ppl1+$SP*0.1} Plague Damage to nearby enemies.","castMode":"cast","castTimeMs":3000,"cooldownMs":15000,"gcdMs":1000,"cost":{"resource":"mana","amount":23,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"trigger-spell","spellId":525379,"expanded":true,"withValue":3},{"kind":"damage","coefficient":1},{"kind":"summon","creatureId":503031,"coefficient":0.08,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":524287,"triggerSpellId":500991,"durationMs":100}]},{"rank":3,"spellId":525381,"level":51,"description":"Animate $s1 Zombies to aid you in combat for $504313d. Every $504023t1 sec, Zombies emit Zombie Plague, dealing ${$504022m1+$504022ppl1+$SP*0.1} Plague Damage to nearby enemies.","castMode":"cast","castTimeMs":3000,"cooldownMs":15000,"gcdMs":1000,"cost":{"resource":"mana","amount":24,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"trigger-spell","spellId":525379,"expanded":true,"withValue":4},{"kind":"damage","coefficient":1},{"kind":"summon","creatureId":503031,"coefficient":0.08,"durationMs":15000},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":524287,"triggerSpellId":500991,"durationMs":100}]}]},{"id":"coa-tree-29774","classId":"necromancer","dbcSpellId":802121,"name":"Bone Tithe","unlockLevel":1,"icon":"/assets/ui/spells/ossuary_bond.png","sigil":"BT","description":"Siphon life from your undead minions, sacrificing 40% of their health to grant yourself an absorb shield equal to half of the health stolen for 20 seconds. Usable while stunned.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":120000,"gcdMs":1500,"cost":{"resource":"mana","amount":25,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"shield","coefficient":1,"durationMs":15000},{"kind":"utility","action":Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"primalist","abilities":[{"id":"coa-tree-29362","classId":"primalist","dbcSpellId":800094,"name":"Bearskin","unlockLevel":1,"icon":"/assets/ui/spells/spell_druid_primaltenacity.png","sigil":"BE","description":"Reduces all damage taken by -60% and reduces the duration of root, stun, and incapacitate effects on you by -30% for 10 seconds.","target":"hostile","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":300000,"gcdMs":1500,"cost":{"resource":"mana","amount":24,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"status","status":"sleep","durationMs":10000},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:0:aura:87","name":"Bearskin (Aura 87)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":-0.6}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:1:aura:232","name":"Bearskin (Aura 232)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":232,"miscValue":5,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:2:aura:232","name":"Bearskin (Aura 232)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":232,"miscValue":12,"triggerSpellId":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":800094,"level":1,"description":"Reduces all damage taken by -60% and reduces the duration of root, stun, and incapacitate effects on you by -30% for 10 seconds.","castMode":"instant","castTimeMs":0,"cooldownMs":300000,"gcdMs":1500,"cost":{"resource":"mana","amount":24,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"status","status":"sleep","durationMs":10000},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:0:aura:87","name":"Bearskin (Aura 87)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":-0.6}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:1:aura:232","name":"Bearskin (Aura 232)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":232,"miscValue":5,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:2:aura:232","name":"Bearskin (Aura 232)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":232,"miscValue":12,"triggerSpellId":0}]}],"talentEntryId":29362},{"id":"coa-tree-29252","classId":"primalist","dbcSpellId":500692,"name":"Boulder Dash","unlockLevel":1,"icon":"/assets/ui/spells/custom_elementl(earth)_b_01_border.png","sigil":"BD","description":"Raise a boulder out of the ground and encase yourself within it, preventing you from attacking or casting spells. For 10 seconds, you roll forward at 70% increased movement speed, dealing 1 + 50% AP + 100% SP Physical damage to enemies you roll over, and you are immune to crowd control effects.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":180000,"gcdMs":1250,"cost":{"resource":"mana","amount":35,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:500692:effect:0:aura:23","name":"Boulder Dash (Aura 23)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:500692:proc:0:500693","triggers":["periodic"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":500693}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":23,"miscValue":0,"triggerSpellId":500693},{"kind":"apply-aura","aura":{"id":"coa:500692:effect:1:aura:31","name":"Boulder Dash (Aura 31)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"stat","stat":"movement-speed","operation":"percent","value":0.7}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":31,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:500692:effect:2:aura:241","name":"Boulder Dash (Aura 241)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":241,"miscValue":0,"triggerSpellId":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":500692,"level"Line truncated
{"schemaVersion":1,"classId":"primalist","abilities":[{"id":"coa-tree-29362","classId":"primalist","dbcSpellId":800094,"name":"Bearskin","unlockLevel":1,"icon":"/assets/ui/spells/spell_druid_primaltenacity.png","sigil":"BE","description":"Reduces all damage taken by -60% and reduces the duration of root, stun, and incapacitate effects on you by -30% for 10 seconds.","target":"hostile","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":300000,"gcdMs":0,"cost":{"resource":"mana","amount":24,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"status","status":"sleep","durationMs":10000},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:0:aura:87","name":"Bearskin (Aura 87)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":-0.6}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:1:aura:232","name":"Bearskin (Aura 232)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":232,"miscValue":5,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:2:aura:232","name":"Bearskin (Aura 232)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":232,"miscValue":12,"triggerSpellId":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":800094,"level":1,"description":"Reduces all damage taken by -60% and reduces the duration of root, stun, and incapacitate effects on you by -30% for 10 seconds.","castMode":"instant","castTimeMs":0,"cooldownMs":300000,"gcdMs":0,"cost":{"resource":"mana","amount":24,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"status","status":"sleep","durationMs":10000},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:0:aura:87","name":"Bearskin (Aura 87)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":-0.6}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:1:aura:232","name":"Bearskin (Aura 232)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":232,"miscValue":5,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:800094:effect:2:aura:232","name":"Bearskin (Aura 232)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":232,"miscValue":12,"triggerSpellId":0}]}],"talentEntryId":29362},{"id":"coa-tree-29252","classId":"primalist","dbcSpellId":500692,"name":"Boulder Dash","unlockLevel":1,"icon":"/assets/ui/spells/custom_elementl(earth)_b_01_border.png","sigil":"BD","description":"Raise a boulder out of the ground and encase yourself within it, preventing you from attacking or casting spells. For 10 seconds, you roll forward at 70% increased movement speed, dealing 1 + 50% AP + 100% SP Physical damage to enemies you roll over, and you are immune to crowd control effects.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":180000,"gcdMs":1250,"cost":{"resource":"mana","amount":35,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:500692:effect:0:aura:23","name":"Boulder Dash (Aura 23)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:500692:proc:0:500693","triggers":["periodic"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":500693}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":23,"miscValue":0,"triggerSpellId":500693},{"kind":"apply-aura","aura":{"id":"coa:500692:effect:1:aura:31","name":"Boulder Dash (Aura 31)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"stat","stat":"movement-speed","operation":"percent","value":0.7}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":31,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:500692:effect:2:aura:241","name":"Boulder Dash (Aura 241)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":241,"miscValue":0,"triggerSpellId":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":500692,"level":1,"deLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"pyromancer","abilities":[{"id":"coa-tree-33843","classId":"pyromancer","dbcSpellId":300921,"name":"Al Dente","unlockLevel":1,"icon":"/assets/ui/spells/achievement_cooking_masteroftheoven.png","sigil":"AD","description":"Targets affected by Gaze of Ysera now take 15% increased Fire damage.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:300921:effect:0:aura:107","name":"Al Dente (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.15}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":23,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":300921,"level":1,"description":"Targets affected by Gaze of Ysera now take 15% increased Fire damage.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:300921:effect:0:aura:107","name":"Al Dente (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.15}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":23,"triggerSpellId":0}]}],"talentEntryId":33843},{"id":"coa-tree-33882","classId":"pyromancer","dbcSpellId":504397,"name":"Blessing of the Firelands","unlockLevel":1,"icon":"/assets/ui/spells/nhi_fire_soul_border.png","sigil":"BO","description":"Each stack of Heat now increases the damage dealt by Dragon Leap by 6%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:504397:effect:0:aura:107","name":"Blessing of the Firelands (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.06}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":12,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:504397:effect:1:aura:107","name":"Blessing of the Firelands (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":23,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":504397,"level":1,"description":"Each stack of Heat now increases the damage dealt by Dragon Leap by 6%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:504397:effect:0:aura:107","name":"Blessing of the Firelands (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.06}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":12,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:504397:effect:1:aura:107","name":"Blessing of the Firelands (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":23,"triggerSpellId":0}]}],"talentEntryId":33882},{"id":"coa-tree-32499","classId":"pyromancer","dbcSpellId":300759,"name":"Bright Flames","unlockLevel":1,"icon":"/assets/ui/spells/spell_frost_fireresistancetotem.png","sigil":"BF","description":"Increases the amount absorbed by Inferno Barrier by 10% and the damage it deals by 15%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:300759:effect:0:aura:317","name":"Bright Flames (Aura 317)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":317,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:300759:effect:1:aura:108","name":"Bright Flames (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.15}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":300759,"level":1,"description":"Increases the amount absorbed by Inferno Barrier by 10% and the damage it dLine truncated
{"schemaVersion":1,"classId":"pyromancer","abilities":[{"id":"coa-tree-33843","classId":"pyromancer","dbcSpellId":300921,"name":"Al Dente","unlockLevel":1,"icon":"/assets/ui/spells/achievement_cooking_masteroftheoven.png","sigil":"AD","description":"Targets affected by Gaze of Ysera now take 15% increased Fire damage.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:300921:effect:0:aura:107","name":"Al Dente (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.15}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":23,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":300921,"level":1,"description":"Targets affected by Gaze of Ysera now take 15% increased Fire damage.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:300921:effect:0:aura:107","name":"Al Dente (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.15}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":23,"triggerSpellId":0}]}],"talentEntryId":33843},{"id":"coa-tree-33882","classId":"pyromancer","dbcSpellId":504397,"name":"Blessing of the Firelands","unlockLevel":1,"icon":"/assets/ui/spells/nhi_fire_soul_border.png","sigil":"BO","description":"Each stack of Heat now increases the damage dealt by Dragon Leap by 6%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:504397:effect:0:aura:107","name":"Blessing of the Firelands (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.06}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":12,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:504397:effect:1:aura:107","name":"Blessing of the Firelands (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":23,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":504397,"level":1,"description":"Each stack of Heat now increases the damage dealt by Dragon Leap by 6%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:504397:effect:0:aura:107","name":"Blessing of the Firelands (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.06}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":12,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:504397:effect:1:aura:107","name":"Blessing of the Firelands (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":23,"triggerSpellId":0}]}],"talentEntryId":33882},{"id":"coa-tree-32499","classId":"pyromancer","dbcSpellId":300759,"name":"Bright Flames","unlockLevel":1,"icon":"/assets/ui/spells/spell_frost_fireresistancetotem.png","sigil":"BF","description":"Increases the amount absorbed by Inferno Barrier by 10% and the damage it deals by 15%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:300759:effect:0:aura:317","name":"Bright Flames (Aura 317)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":317,"miscValue":4,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:300759:effect:1:aura:108","name":"Bright Flames (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.15}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":300759,"level":1,"description":"Increases the amount absorbed by Inferno Barrier by 10% and the damage it deals by 15%.","caLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"ranger","abilities":[{"id":"coa-21-agile-none-560796","classId":"ranger","dbcSpellId":560796,"name":"Agile","unlockLevel":1,"icon":"/assets/ui/spells/inv_sword_38.png","sigil":"AG","description":"AgileRank 2Increases the damage of Wild Strike, Whipvine Arrow, and Ravage by 10%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:560796:effect:0:aura:108","name":"Agile (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:560796:effect:1:aura:108","name":"Agile (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":22,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":2,"spellId":560796,"level":1,"description":"AgileRank 2Increases the damage of Wild Strike, Whipvine Arrow, and Ravage by 10%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:560796:effect:0:aura:108","name":"Agile (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:560796:effect:1:aura:108","name":"Agile (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":22,"triggerSpellId":0}]}]},{"id":"coa-21-archery-training-76-705036","classId":"ranger","dbcSpellId":705036,"name":"Archery Training","unlockLevel":1,"icon":"/assets/ui/spells/inv_bow_1h_draenorcrafted_d_01_a_horde.png","sigil":"AT","description":"Archery TrainingRank 1Increases the damage of Skullpiercer by 3% and your critical strike chance by 1%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705036:effect:0:aura:290","name":"Archery Training (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705036:effect:1:aura:108","name":"Archery Training (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.03}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705036,"level":1,"description":"Archery TrainingRank 1Increases the damage of Skullpiercer by 3% and your critical strike chance by 1%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705036:effect:0:aura:290","name":"Archery Training (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705036:effect:1:aura:108","name":"Archery Training (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.03}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}]},{"rank":2,"spellId":705037,"level":1,"description":"Archery TrainingRank 2Increases the damage of Skullpiercer by 6% and your critical strike chance by 2%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705037:effect:0:aura:290","name":"Archery Training (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705037:effect:1:aura:108","name":"Archery Training (Aura 108)","disposition":"buff","dLine truncated
{"schemaVersion":1,"classId":"ranger","abilities":[{"id":"coa-21-agile-none-560796","classId":"ranger","dbcSpellId":560796,"name":"Agile","unlockLevel":1,"icon":"/assets/ui/spells/inv_sword_38.png","sigil":"AG","description":"Increases the damage of Wild Strike, Whipvine Arrow$?s500024[, Assault][], and Ravage by $s1%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:560796:effect:0:aura:108","name":"Agile (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:560796:effect:1:aura:108","name":"Agile (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":22,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":2,"spellId":560796,"level":1,"description":"Increases the damage of Wild Strike, Whipvine Arrow$?s500024[, Assault][], and Ravage by $s1%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:560796:effect:0:aura:108","name":"Agile (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:560796:effect:1:aura:108","name":"Agile (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":22,"triggerSpellId":0}]}]},{"id":"coa-21-archery-training-76-705036","classId":"ranger","dbcSpellId":705036,"name":"Archery Training","unlockLevel":1,"icon":"/assets/ui/spells/inv_bow_1h_draenorcrafted_d_01_a_horde.png","sigil":"AT","description":"Increases the damage of Skullpiercer by $s2% and your critical strike chance by $s1%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705036:effect:0:aura:290","name":"Archery Training (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705036:effect:1:aura:108","name":"Archery Training (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.03}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705036,"level":1,"description":"Increases the damage of Skullpiercer by $s2% and your critical strike chance by $s1%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705036:effect:0:aura:290","name":"Archery Training (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705036:effect:1:aura:108","name":"Archery Training (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.03}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}]},{"rank":2,"spellId":705037,"level":1,"description":"Increases the damage of Skullpiercer by $s2% and your critical strike chance by $s1%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705037:effect:0:aura:290","name":"Archery Training (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705037:effect:1:aura:108","name":"Archery Training (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior"Line truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"reaper","abilities":[{"id":"coa-tree-6708","classId":"reaper","dbcSpellId":706790,"name":"Backswing","unlockLevel":1,"icon":"/assets/ui/spells/novart_magicspell_(32)_border.png","sigil":"BA","description":"Increases the Runic Power generated by Reap by 5.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:706790:effect:0:aura:107","name":"Backswing (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.5}]},"sourceEffectType":6,"sourceAuraType":107,"miscValue":3,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":706790,"level":1,"description":"Increases the Runic Power generated by Reap by 5.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:706790:effect:0:aura:107","name":"Backswing (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.5}]},"sourceEffectType":6,"sourceAuraType":107,"miscValue":3,"triggerSpellId":0}]}],"talentEntryId":6708},{"id":"coa-tree-34500","classId":"reaper","dbcSpellId":560412,"name":"Between Shadows","unlockLevel":1,"icon":"/assets/ui/spells/5_shadowworld_border.png","sigil":"BS","description":"Casting Spectre Stride now generates 1 Reaped Soul.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:560412:effect:0:aura:42","name":"Between Shadows (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:560412:proc:0:504390","triggers":["cast"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":504390}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":504390}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":560412,"level":1,"description":"Casting Spectre Stride now generates 1 Reaped Soul.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:560412:effect:0:aura:42","name":"Between Shadows (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:560412:proc:0:504390","triggers":["cast"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":504390}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":504390}]}],"talentEntryId":34500},{"id":"coa-tree-31289","classId":"reaper","dbcSpellId":680337,"name":"Bolstered Form","unlockLevel":1,"icon":"/assets/ui/spells/achievement_raid_torghast_shadowscourge_prisonofnerzhul.png","sigil":"BF","description":"Assume a bolstered form for 15 seconds, generating 30 Runic Power, increasing your Armor and your parry chance by 30%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:680337:effect:0:aura:101","name":"Bolstered Form (Aura 101)","disposition":"buff","durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"stat","stat":"resistance:physical","operation":"percent","value":0.25}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":101,"miscValue":1,"triggerSpellId":0},{"kind":"trigger-spell","spellId":359505,"expanded":true},{"kind":"resource","amount":300},{"kind":"apply-aura","aura":{"id":"coa:680337:effect:2:aura:47","name":"Bolstered Form (Aura 47)","disposition":"buff","durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"stat","stat":"parry","operation":"percent","value":0.25}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":47,"miscValue":127,"triggerSpellId":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":680337,"level":1,"description":"Assume a bolstered form for 15 seconds, generating 30 Runic Power, increasing your Armor and your parry chance by 30%.","castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:680337:effect:0:aura:101","name":"Bolstered Form (Aura 101)","disposition":"buff","durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"stat","stat":"resistance:physical","operation":"percent","value":0.25}]},"recipient":"caster","sourceEffectType":6,"sLine truncated
{"schemaVersion":1,"classId":"reaper","abilities":[{"id":"coa-tree-6708","classId":"reaper","dbcSpellId":706790,"name":"Backswing","unlockLevel":1,"icon":"/assets/ui/spells/novart_magicspell_(32)_border.png","sigil":"BA","description":"Increases the Runic Power generated by Reap by 5.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:706790:effect:0:aura:107","name":"Backswing (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.5}]},"sourceEffectType":6,"sourceAuraType":107,"miscValue":3,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":706790,"level":1,"description":"Increases the Runic Power generated by Reap by 5.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:706790:effect:0:aura:107","name":"Backswing (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.5}]},"sourceEffectType":6,"sourceAuraType":107,"miscValue":3,"triggerSpellId":0}]}],"talentEntryId":6708},{"id":"coa-tree-34500","classId":"reaper","dbcSpellId":560412,"name":"Between Shadows","unlockLevel":1,"icon":"/assets/ui/spells/5_shadowworld_border.png","sigil":"BS","description":"Casting Spectre Stride now generates 1 Reaped Soul.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:560412:effect:0:aura:42","name":"Between Shadows (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:560412:proc:0:504390","triggers":["cast"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":504390}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":504390}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":560412,"level":1,"description":"Casting Spectre Stride now generates 1 Reaped Soul.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:560412:effect:0:aura:42","name":"Between Shadows (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:560412:proc:0:504390","triggers":["cast"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":504390}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":504390}]}],"talentEntryId":34500},{"id":"coa-tree-31289","classId":"reaper","dbcSpellId":680337,"name":"Bolstered Form","unlockLevel":1,"icon":"/assets/ui/spells/achievement_raid_torghast_shadowscourge_prisonofnerzhul.png","sigil":"BF","description":"Assume a bolstered form for 15 seconds, generating 30 Runic Power, increasing your Armor and your parry chance by 30%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:680337:effect:0:aura:101","name":"Bolstered Form (Aura 101)","disposition":"buff","durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"stat","stat":"resistance:physical","operation":"percent","value":0.3}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":101,"miscValue":1,"triggerSpellId":0},{"kind":"trigger-spell","spellId":359505,"expanded":true},{"kind":"resource","amount":300},{"kind":"apply-aura","aura":{"id":"coa:680337:effect:2:aura:47","name":"Bolstered Form (Aura 47)","disposition":"buff","durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"stat","stat":"parry","operation":"percent","value":0.3}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":47,"miscValue":127,"triggerSpellId":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":680337,"level":1,"description":"Assume a bolstered form for 15 seconds, generating 30 Runic Power, increasing your Armor and your parry chance by 30%.","castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:680337:effect:0:aura:101","name":"Bolstered Form (Aura 101)","disposition":"buff","durationMs":15000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"stat","stat":"resistance:physical","operation":"percent","value":0.3}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":101,"mLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"runemaster","abilities":[{"id":"coa-32-ancient-carvings-117-705616","classId":"runemaster","dbcSpellId":705616,"name":"Ancient Carvings","unlockLevel":1,"icon":"/assets/ui/spells/inv_relics_6orunestone_ogremissive.png","sigil":"AC","description":"Ancient CarvingsRank 2InstantReduces the cooldown of Words by 20%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705616:effect:0:aura:108","name":"Ancient Carvings (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.2}]},"recipient":"caster","sourceEffectType":3,"sourceAuraType":108,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705616:effect:1:aura:4","name":"Ancient Carvings (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705616:effect:2:aura:4","name":"Ancient Carvings (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":34,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":2,"spellId":705616,"level":1,"description":"Ancient CarvingsRank 2InstantReduces the cooldown of Words by 20%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705616:effect:0:aura:108","name":"Ancient Carvings (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.2}]},"recipient":"caster","sourceEffectType":3,"sourceAuraType":108,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705616:effect:1:aura:4","name":"Ancient Carvings (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705616:effect:2:aura:4","name":"Ancient Carvings (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":34,"triggerSpellId":0}]}]},{"id":"coa-tree-29226","classId":"runemaster","dbcSpellId":806797,"name":"Ancient Teachings","unlockLevel":1,"icon":"/assets/ui/spells/ability_mage_potentspirit.png","sigil":"AT","description":"Increases the effectiveness of Etching of the Dextrous by 20%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:806797:effect:0:aura:216","name":"Ancient Teachings (Aura 216)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":216,"miscValue":126,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:806797:effect:1:aura:192","name":"Ancient Teachings (Aura 192)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":192,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:806797:effect:2:aura:108","name":"Ancient Teachings (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":8,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":806797,"level":1,"description":"Increases the effectiveness of Etching of the Dextrous by 20%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:806797:effect:0:aura:216","name":"Ancient Teachings (Aura 216)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":216,"miscValue":126,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:806797:effect:1:aura:192","name":"Ancient Teachings (Aura 192)","disposition":Line truncated
{"schemaVersion":1,"classId":"runemaster","abilities":[{"id":"coa-32-ancient-carvings-117-705616","classId":"runemaster","dbcSpellId":705616,"name":"Ancient Carvings","unlockLevel":1,"icon":"/assets/ui/spells/inv_relics_6orunestone_ogremissive.png","sigil":"AC","description":"Reduces the cooldown of Words by $s1%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705616:effect:0:aura:108","name":"Ancient Carvings (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.2}]},"recipient":"caster","sourceEffectType":3,"sourceAuraType":108,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705616:effect:1:aura:4","name":"Ancient Carvings (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705616:effect:2:aura:4","name":"Ancient Carvings (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":34,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":2,"spellId":705616,"level":1,"description":"Reduces the cooldown of Words by $s1%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705616:effect:0:aura:108","name":"Ancient Carvings (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.2}]},"recipient":"caster","sourceEffectType":3,"sourceAuraType":108,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705616:effect:1:aura:4","name":"Ancient Carvings (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705616:effect:2:aura:4","name":"Ancient Carvings (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":34,"triggerSpellId":0}]}]},{"id":"coa-tree-29226","classId":"runemaster","dbcSpellId":806797,"name":"Ancient Teachings","unlockLevel":1,"icon":"/assets/ui/spells/ability_mage_potentspirit.png","sigil":"AT","description":"Increases the effectiveness of Etching of the Dextrous by 20%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:806797:effect:0:aura:216","name":"Ancient Teachings (Aura 216)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":216,"miscValue":126,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:806797:effect:1:aura:192","name":"Ancient Teachings (Aura 192)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":192,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:806797:effect:2:aura:108","name":"Ancient Teachings (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":8,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":806797,"level":1,"description":"Increases the effectiveness of Etching of the Dextrous by 20%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:806797:effect:0:aura:216","name":"Ancient Teachings (Aura 216)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":216,"miscValue":126,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:806797:effect:1:aura:192","name":"Ancient Teachings (Aura 192)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","moLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"starcaller","abilities":[{"id":"coa-26-arrows-of-starlight-93-704733","classId":"starcaller","dbcSpellId":704733,"name":"Arrows of Starlight","unlockLevel":1,"icon":"/assets/ui/spells/ability_ironmaidens_ironshot.png","sigil":"AO","description":"Arrows of StarlightRank 1Increases the damage of Moon Arrow by 20%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704733:effect:0:aura:108","name":"Arrows of Starlight (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":704733,"level":1,"description":"Arrows of StarlightRank 1Increases the damage of Moon Arrow by 20%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704733:effect:0:aura:108","name":"Arrows of Starlight (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}]}]},{"id":"coa-tree-30838","classId":"starcaller","dbcSpellId":806155,"name":"Astral Aegis","unlockLevel":1,"icon":"/assets/ui/spells/ability_bastion_monk.png","sigil":"AA","description":"Drains 30% Maximum Mana For 10 seconds, direct Magic damage taken will silence the attacker for 1 seconds and deal 57 + 18% arcane SP Arcane damage to them.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":30000,"gcdMs":1500,"cost":{"resource":"mana","amount":19,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:806155:effect:0:aura:87","name":"Astral Aegis (Aura 87)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:806155:effect:1:aura:42","name":"Astral Aegis (Aura 42)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:806155:proc:1:806453","triggers":["damage-taken","hit"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":806453}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":806453}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":806155,"level":1,"description":"Drains 30% Maximum Mana For 10 seconds, direct Magic damage taken will silence the attacker for 1 seconds and deal 57 + 18% arcane SP Arcane damage to them.","castMode":"instant","castTimeMs":0,"cooldownMs":30000,"gcdMs":1500,"cost":{"resource":"mana","amount":19,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:806155:effect:0:aura:87","name":"Astral Aegis (Aura 87)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:806155:effect:1:aura:42","name":"Astral Aegis (Aura 42)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:806155:proc:1:806453","triggers":["damage-taken","hit"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":806453}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":806453}]}],"talentEntryId":30838},{"id":"starcaller-astral-flare","classId":"starcaller","dbcSpellId":800499,"name":"Astral Flare","unlockLevel":1,"icon":"/assets/ui/spells/spell_shadow_manaburn.png","sigil":"AF","description":"Astral FlareRank 12 sec castYou call an Astral Flare down from the sky, dealing 1 Arcane Damage to an enemy and regenerating 5% of your Maximum Mana.","target":"hostile","range":{"min":0,"max":40},"castMode":"cast","castTimeMs":2000,"cooldownMs":0,"gcdMs":1250,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"trigger-spell","spellId":800507,"expanded":true,"withValue":10},{"kind":"damage","coefficient":0.08,"basePoints":1,"dieSides":1,"pointsPerLevel":0,"bonusPowerCoefficient":0,"sourceLevel":6},{"kind":"trigger-spell","spellId":804096,"exLine truncated
{"schemaVersion":1,"classId":"starcaller","abilities":[{"id":"coa-26-arrows-of-starlight-93-704733","classId":"starcaller","dbcSpellId":704733,"name":"Arrows of Starlight","unlockLevel":1,"icon":"/assets/ui/spells/ability_ironmaidens_ironshot.png","sigil":"AO","description":"Increases the damage of Moon Arrow by $s1%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704733:effect:0:aura:108","name":"Arrows of Starlight (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":704733,"level":1,"description":"Increases the damage of Moon Arrow by $s1%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704733:effect:0:aura:108","name":"Arrows of Starlight (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":0,"triggerSpellId":0}]}]},{"id":"coa-tree-30838","classId":"starcaller","dbcSpellId":806155,"name":"Astral Aegis","unlockLevel":1,"icon":"/assets/ui/spells/ability_bastion_monk.png","sigil":"AA","description":"Drains 30% Maximum Mana For 10 seconds, direct Magic damage taken will silence the attacker for 1 seconds and deal 57 + 18% arcane SP Arcane damage to them.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":30000,"gcdMs":0,"cost":{"resource":"mana","amount":19,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:806155:effect:0:aura:87","name":"Astral Aegis (Aura 87)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:806155:effect:1:aura:42","name":"Astral Aegis (Aura 42)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:806155:proc:1:806453","triggers":["damage-taken","hit"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":806453}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":806453}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":806155,"level":1,"description":"Drains 30% Maximum Mana For 10 seconds, direct Magic damage taken will silence the attacker for 1 seconds and deal 57 + 18% arcane SP Arcane damage to them.","castMode":"instant","castTimeMs":0,"cooldownMs":30000,"gcdMs":0,"cost":{"resource":"mana","amount":19,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:806155:effect:0:aura:87","name":"Astral Aegis (Aura 87)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:806155:effect:1:aura:42","name":"Astral Aegis (Aura 42)","disposition":"buff","durationMs":10000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:806155:proc:1:806453","triggers":["damage-taken","hit"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":806453}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":806453}]}],"talentEntryId":30838},{"id":"starcaller-astral-flare","classId":"starcaller","dbcSpellId":800499,"name":"Astral Flare","unlockLevel":1,"icon":"/assets/ui/spells/spell_shadow_manaburn.png","sigil":"AF","description":"You call an Astral Flare down from the sky, dealing $800507s1 Arcane Damage to an enemy and regenerating $s2% of your Maximum Mana.","target":"hostile","range":{"min":0,"max":40},"castMode":"cast","castTimeMs":2000,"cooldownMs":0,"gcdMs":1250,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"trigger-spell","spellId":800507,"expanded":true,"withValue":10},{"kind":"damage","coefficient":0.08,"basePoints":1,"dieSides":1,"pointsPerLevel":0,"bonusPowerCoefficient":0,"sourceLevel":6},{"kind":"trigger-spell","spellId":804096,"expanded":true,"withValue":5},{"kind":"resource","amount":2,"percentage":true}],Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"stormbringer","abilities":[{"id":"coa-tree-34916","classId":"stormbringer","dbcSpellId":807462,"name":"Aether Mastery","unlockLevel":1,"icon":"/assets/ui/spells/achievement_zone_netherstorm_01.png","sigil":"AM","description":"Allows 30% of your mana regeneration to continue while casting and increases your critical strike chance by 2%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:807462:effect:0:aura:134","name":"Aether Mastery (Aura 134)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"resource","resource":"mana","property":"regeneration","operation":"percent","value":0.3}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":134,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:807462:effect:1:aura:290","name":"Aether Mastery (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":807462,"level":1,"description":"Allows 30% of your mana regeneration to continue while casting and increases your critical strike chance by 2%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:807462:effect:0:aura:134","name":"Aether Mastery (Aura 134)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"resource","resource":"mana","property":"regeneration","operation":"percent","value":0.3}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":134,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:807462:effect:1:aura:290","name":"Aether Mastery (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0}]},{"rank":2,"spellId":807887,"level":1,"description":"Allows 60% of your mana regeneration to continue while casting and increases your critical strike chance by 4%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:807887:effect:0:aura:134","name":"Aether Mastery (Aura 134)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"resource","resource":"mana","property":"regeneration","operation":"percent","value":0.6}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":134,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:807887:effect:1:aura:290","name":"Aether Mastery (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0}]}],"talentEntryId":34916},{"id":"coa-16-aethermancy-62-705690","classId":"stormbringer","dbcSpellId":705690,"name":"Aethermancy","unlockLevel":1,"icon":"/assets/ui/spells/spell_shaman_improvedreincarnation.png","sigil":"AE","description":"AethermancyRank 1Increases the critical strike chance of your Invigorating Surge by 20%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705690:effect:0:aura:107","name":"Aethermancy (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":7,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705690:effect:1:aura:107","name":"Aethermancy (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":1}]},"recipient":"caster","sourceEffectType":3,"sourceAuraType":107,"miscValue":7,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705690,"level":1,"description":"AethermancyRank 1Increases the critical strike chance of your Invigorating Surge by 20%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705690:effect:0:aura:107","name":"Aethermancy (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":7,"triggerSpellId":0},{"kinLine truncated
{"schemaVersion":1,"classId":"stormbringer","abilities":[{"id":"coa-tree-34916","classId":"stormbringer","dbcSpellId":807462,"name":"Aether Mastery","unlockLevel":1,"icon":"/assets/ui/spells/achievement_zone_netherstorm_01.png","sigil":"AM","description":"Allows 30% of your mana regeneration to continue while casting and increases your critical strike chance by 2%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:807462:effect:0:aura:134","name":"Aether Mastery (Aura 134)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"resource","resource":"mana","property":"regeneration","operation":"percent","value":0.3}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":134,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:807462:effect:1:aura:290","name":"Aether Mastery (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":807462,"level":1,"description":"Allows 30% of your mana regeneration to continue while casting and increases your critical strike chance by 2%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:807462:effect:0:aura:134","name":"Aether Mastery (Aura 134)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"resource","resource":"mana","property":"regeneration","operation":"percent","value":0.3}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":134,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:807462:effect:1:aura:290","name":"Aether Mastery (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0}]},{"rank":2,"spellId":807887,"level":1,"description":"Allows 60% of your mana regeneration to continue while casting and increases your critical strike chance by 4%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:807887:effect:0:aura:134","name":"Aether Mastery (Aura 134)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"resource","resource":"mana","property":"regeneration","operation":"percent","value":0.6}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":134,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:807887:effect:1:aura:290","name":"Aether Mastery (Aura 290)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh"},"recipient":"caster","sourceEffectType":6,"sourceAuraType":290,"miscValue":0,"triggerSpellId":0}]}],"talentEntryId":34916},{"id":"coa-16-aethermancy-62-705690","classId":"stormbringer","dbcSpellId":705690,"name":"Aethermancy","unlockLevel":1,"icon":"/assets/ui/spells/spell_shaman_improvedreincarnation.png","sigil":"AE","description":"Increases the critical strike chance of your Invigorating Surge by 20%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705690:effect:0:aura:107","name":"Aethermancy (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":7,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705690:effect:1:aura:107","name":"Aethermancy (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":1}]},"recipient":"caster","sourceEffectType":3,"sourceAuraType":107,"miscValue":7,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705690,"level":1,"description":"Increases the critical strike chance of your Invigorating Surge by 20%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705690:effect:0:aura:107","name":"Aethermancy (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.2}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":7,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705690Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"sun-cleric","abilities":[{"id":"coa-tree-4048","classId":"sun-cleric","dbcSpellId":92137,"name":"Angelic Presence","unlockLevel":1,"icon":"/assets/ui/spells/ability_paladin_conviction.png","sigil":"AP","description":"Level 10 Passive Avoiding an attack now has a 20% chance to grant you Angelic Presence.Angelic PresenceYour next Illumination within 15 seconds is instant cast and free of cost.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:92137:effect:0:aura:42","name":"Angelic Presence (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:92137:proc:0:800722","triggers":["cast","hit"],"chance":0.2,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":800722}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":800722},{"kind":"apply-aura","aura":{"id":"coa:92137:effect:1:aura:79","name":"Angelic Presence (Aura 79)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"dealt","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":79,"miscValue":127,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":92137,"level":1,"description":"Level 10 Passive Avoiding an attack now has a 20% chance to grant you Angelic Presence.Angelic PresenceYour next Illumination within 15 seconds is instant cast and free of cost.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:92137:effect:0:aura:42","name":"Angelic Presence (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:92137:proc:0:800722","triggers":["cast","hit"],"chance":0.2,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":800722}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":800722},{"kind":"apply-aura","aura":{"id":"coa:92137:effect:1:aura:79","name":"Angelic Presence (Aura 79)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"dealt","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":79,"miscValue":127,"triggerSpellId":0}]}],"talentEntryId":4048},{"id":"coa-27-bastion-of-vengeance-97-704925","classId":"sun-cleric","dbcSpellId":704925,"name":"Bastion of Vengeance","unlockLevel":1,"icon":"/assets/ui/spells/inv_shield_1h_artifactnorgannon_d_06.png","sigil":"BO","description":"Bastion of VengeanceRank 1Increases your block chance by 2% and gives successful blocks a 50% chance to reduce the remaining cooldown of Vengeful Slam by 0.01 sec.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704925:effect:0:aura:42","name":"Bastion of Vengeance (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:704925:proc:0:704926","triggers":["block"],"chance":0.5,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":704926}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":704926},{"kind":"apply-aura","aura":{"id":"coa:704925:effect:1:aura:51","name":"Bastion of Vengeance (Aura 51)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"block","operation":"percent","value":0.02}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":51,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":704925,"level":1,"description":"Bastion of VengeanceRank 1Increases your block chance by 2% and gives successful blocks a 50% chance to reduce the remaining cooldown of Vengeful Slam by 0.01 sec.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704925:effect:0:aura:42","name":"Bastion of Vengeance (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:704925:proc:0:704926","triggers":["block"],"chance":0.5,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":704926}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":704926},{"kind":"apply-aura","aura":{"id":"coa:704925:effect:1:aura:51","name":"Bastion of Vengeance (Aura 51)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","statLine truncated
{"schemaVersion":1,"classId":"sun-cleric","abilities":[{"id":"coa-tree-4048","classId":"sun-cleric","dbcSpellId":92137,"name":"Angelic Presence","unlockLevel":1,"icon":"/assets/ui/spells/ability_paladin_conviction.png","sigil":"AP","description":"Level 10 Passive Avoiding an attack now has a 20% chance to grant you Angelic Presence.Angelic PresenceYour next Illumination within 15 seconds is instant cast and free of cost.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:92137:effect:0:aura:42","name":"Angelic Presence (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:92137:proc:0:800722","triggers":["cast","hit"],"chance":0.2,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":800722}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":800722},{"kind":"apply-aura","aura":{"id":"coa:92137:effect:1:aura:79","name":"Angelic Presence (Aura 79)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"dealt","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":79,"miscValue":127,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":92137,"level":1,"description":"Level 10 Passive Avoiding an attack now has a 20% chance to grant you Angelic Presence.Angelic PresenceYour next Illumination within 15 seconds is instant cast and free of cost.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:92137:effect:0:aura:42","name":"Angelic Presence (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:92137:proc:0:800722","triggers":["cast","hit"],"chance":0.2,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":800722}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":800722},{"kind":"apply-aura","aura":{"id":"coa:92137:effect:1:aura:79","name":"Angelic Presence (Aura 79)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"dealt","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":79,"miscValue":127,"triggerSpellId":0}]}],"talentEntryId":4048},{"id":"coa-27-bastion-of-vengeance-97-704925","classId":"sun-cleric","dbcSpellId":704925,"name":"Bastion of Vengeance","unlockLevel":1,"icon":"/assets/ui/spells/inv_shield_1h_artifactnorgannon_d_06.png","sigil":"BO","description":"Increases your block chance by $s2% and gives successful blocks a $h% chance to reduce the remaining cooldown of Vengeful Slam by $/1000;704926s1 sec.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704925:effect:0:aura:42","name":"Bastion of Vengeance (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:704925:proc:0:704926","triggers":["block"],"chance":0.5,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":704926}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":704926},{"kind":"apply-aura","aura":{"id":"coa:704925:effect:1:aura:51","name":"Bastion of Vengeance (Aura 51)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"block","operation":"percent","value":0.02}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":51,"miscValue":0,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":704925,"level":1,"description":"Increases your block chance by $s2% and gives successful blocks a $h% chance to reduce the remaining cooldown of Vengeful Slam by $/1000;704926s1 sec.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:704925:effect:0:aura:42","name":"Bastion of Vengeance (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:704925:proc:0:704926","triggers":["block"],"chance":0.5,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":704926}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":704926},{"kind":"apply-aura","aura":{"id":"coa:704925:effect:1:aura:51","name":"Bastion of Vengeance (Aura 51)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"block","operation":"percent","valueLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"templar","abilities":[{"id":"coa-19-alertness-71-706321","classId":"templar","dbcSpellId":706321,"name":"Alertness","unlockLevel":1,"icon":"/assets/ui/spells/spell_holy_powerinfusion.png","sigil":"AL","description":"AlertnessRank 1Reduces damage taken by 5%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:706321:effect:0:aura:87","name":"Alertness (Aura 87)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":-0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:706321:effect:1:aura:107","name":"Alertness (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":5,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":706321,"level":1,"description":"AlertnessRank 1Reduces damage taken by 5%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:706321:effect:0:aura:87","name":"Alertness (Aura 87)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":-0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:706321:effect:1:aura:107","name":"Alertness (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":5,"triggerSpellId":0}]},{"rank":2,"spellId":706322,"level":1,"description":"AlertnessRank 2Reduces Physical Damage taken by 4% and increases the range of Benediction by 10 yds.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:706322:effect:0:aura:87","name":"Alertness (Aura 87)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":-0.04}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:706322:effect:1:aura:107","name":"Alertness (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":5,"triggerSpellId":0}]}]},{"id":"coa-tree-34375","classId":"templar","dbcSpellId":801457,"name":"Binding Scripture","unlockLevel":1,"icon":"/assets/ui/spells/_d3breathofheaven.png","sigil":"BS","description":"Healing an ally now redirects 10% of their damage taken to you and reduces your damage taken by -5% for 10 seconds, stacking 3 times.","target":"friendly","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:801457:effect:0:aura:42","name":"Binding Scripture (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:801457:proc:0:705309","triggers":["heal","damage-taken"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":705309}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":705309}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":801457,"level":1,"description":"Healing an ally now redirects 10% of their damage taken to you and reduces your damage taken by -5% for 10 seconds, stacking 3 times.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:801457:effect:0:aura:42","name":"Binding Scripture (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:801457:proc:0:705309","triggers":["heal","damage-taken"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":705309}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":705309}]}],"talentEntryId":34375},{"id":"coa-tree-29704","classId":"templar","dbcSpellId":803872,"name":"Blade of Faith","unlockLevel":1,"icon":"/aLine truncated
{"schemaVersion":1,"classId":"templar","abilities":[{"id":"coa-19-alertness-71-706321","classId":"templar","dbcSpellId":706321,"name":"Alertness","unlockLevel":1,"icon":"/assets/ui/spells/spell_holy_powerinfusion.png","sigil":"AL","description":"Reduces damage taken by $s1%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:706321:effect:0:aura:87","name":"Alertness (Aura 87)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":-0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:706321:effect:1:aura:107","name":"Alertness (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":5,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":706321,"level":1,"description":"Reduces damage taken by $s1%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:706321:effect:0:aura:87","name":"Alertness (Aura 87)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":-0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:706321:effect:1:aura:107","name":"Alertness (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":5,"triggerSpellId":0}]},{"rank":2,"spellId":706322,"level":1,"description":"Reduces Physical Damage taken by $s1% and increases the range of Benediction by $s2 yds.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:706322:effect:0:aura:87","name":"Alertness (Aura 87)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"damage","direction":"taken","operation":"percent","value":-0.04}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":87,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:706322:effect:1:aura:107","name":"Alertness (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":5,"triggerSpellId":0}]}]},{"id":"coa-tree-34375","classId":"templar","dbcSpellId":801457,"name":"Binding Scripture","unlockLevel":1,"icon":"/assets/ui/spells/_d3breathofheaven.png","sigil":"BS","description":"Healing an ally now redirects 10% of their damage taken to you and reduces your damage taken by -5% for 10 seconds, stacking 3 times.","target":"friendly","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:801457:effect:0:aura:42","name":"Binding Scripture (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:801457:proc:0:705309","triggers":["heal","damage-taken"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":705309}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":705309}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":801457,"level":1,"description":"Healing an ally now redirects 10% of their damage taken to you and reduces your damage taken by -5% for 10 seconds, stacking 3 times.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:801457:effect:0:aura:42","name":"Binding Scripture (Aura 42)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","procs":[{"id":"coa:801457:proc:0:705309","triggers":["heal","damage-taken"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":705309}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":705309}]}],"talentEntryId":34375},{"id":"coa-tree-29704","classId":"templar","dbcSpellId":803872,"name":"Blade of Faith","unlockLevel":1,"icon":"/assets/ui/spells/holy_blade_templar.png","sigil":"BO",Line truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"tinker","abilities":[{"id":"coa-tree-29440","classId":"tinker","dbcSpellId":801744,"name":"Air Strike","unlockLevel":1,"icon":"/assets/ui/spells/ability_mount_gyrocoptor.png","sigil":"AS","description":"Mark the target location for an Air Strike. After 7 seconds, it deals 1250 Fire damage to up to 12 enemies caught within the blast. This ability always critically strikes.","target":"hostile","range":{"min":0,"max":60},"radius":20,"castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":1500,"cost":{"resource":"mana","amount":25,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:801744:effect:0:aura:23","name":"Air Strike (Aura 23)","disposition":"debuff","durationMs":7000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:801744:proc:0:801745","triggers":["periodic"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":801745}}}]},"sourceEffectType":27,"sourceAuraType":23,"miscValue":0,"triggerSpellId":801745}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":801744,"level":1,"description":"Mark the target location for an Air Strike. After 7 seconds, it deals 1250 Fire damage to up to 12 enemies caught within the blast. This ability always critically strikes.","castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":1500,"cost":{"resource":"mana","amount":25,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:801744:effect:0:aura:23","name":"Air Strike (Aura 23)","disposition":"debuff","durationMs":7000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:801744:proc:0:801745","triggers":["periodic"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":801745}}}]},"sourceEffectType":27,"sourceAuraType":23,"miscValue":0,"triggerSpellId":801745}]}],"talentEntryId":29440},{"id":"coa-tree-5997","classId":"tinker","dbcSpellId":520445,"name":"Auto Resuscitation Device","unlockLevel":1,"icon":"/assets/ui/spells/inv_misc_enggizmos_15.png","sigil":"AR","description":"Attach a resuscitation device to your target ally for 20 seconds. When the target would otherwise die, they are instead healed for 50% of their maximum health.","target":"friendly","range":{"min":0,"max":20},"castMode":"cast","castTimeMs":1500,"cooldownMs":180000,"gcdMs":1500,"cost":{"resource":"mana","amount":40,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"heal","coefficient":1},{"kind":"apply-aura","aura":{"id":"coa:520445:effect:0:aura:69","name":"Auto Resuscitation Device (Aura 69)","disposition":"buff","durationMs":20000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","absorbs":[{"id":"coa:520445:absorb:0","amount":20,"perStack":false}]},"sourceEffectType":6,"sourceAuraType":69,"miscValue":127,"triggerSpellId":524780}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":520445,"level":1,"description":"Attach a resuscitation device to your target ally for 20 seconds. When the target would otherwise die, they are instead healed for 50% of their maximum health.","castMode":"cast","castTimeMs":1500,"cooldownMs":180000,"gcdMs":1500,"cost":{"resource":"mana","amount":40,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"heal","coefficient":1},{"kind":"apply-aura","aura":{"id":"coa:520445:effect:0:aura:69","name":"Auto Resuscitation Device (Aura 69)","disposition":"buff","durationMs":20000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","absorbs":[{"id":"coa:520445:absorb:0","amount":20,"perStack":false}]},"sourceEffectType":6,"sourceAuraType":69,"miscValue":127,"triggerSpellId":524780}]}],"talentEntryId":5997},{"id":"coa-28-blasting-barrels-99-705835","classId":"tinker","dbcSpellId":705835,"name":"Blasting Barrels","unlockLevel":1,"icon":"/assets/ui/spells/5_gunshot_(3)_border.png","sigil":"BB","description":"Blasting BarrelsRank 1InstantIncreases critical strike damage by 0% and increases damage dealt by Rounds by 0%.","target":"hostile","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"damage","coefficient":1}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705835,"level":1,"description":"Blasting BarrelsRank 1InstantIncreases critical strike damage by 0% and increases damage dealt by Rounds by 0%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"damage","coefficient":1}]}]},{"id":"coa-tree-30583","classId":"tinker","dbcSpellId":560754,"name":"Build: Alarm Beacon","unlockLevel":1,"icon":"/assets/ui/spells/inv_lightforgedmechsuit.png","sigil":"BA","description":"3 Charges, 15 sec recharge Throw down an alarm beacon for 10 seconds, removing fear, charm and sleep effects from up to 1 ally within 20 ydLine truncated
{"schemaVersion":1,"classId":"tinker","abilities":[{"id":"coa-tree-29440","classId":"tinker","dbcSpellId":801744,"name":"Air Strike","unlockLevel":1,"icon":"/assets/ui/spells/ability_mount_gyrocoptor.png","sigil":"AS","description":"Mark the target location for an Air Strike. After 7 seconds, it deals 1250 Fire damage to up to 12 enemies caught within the blast. This ability always critically strikes.","target":"hostile","range":{"min":0,"max":60},"radius":20,"castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":1500,"cost":{"resource":"mana","amount":25,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:801744:effect:0:aura:23","name":"Air Strike (Aura 23)","disposition":"debuff","durationMs":7000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:801744:proc:0:801745","triggers":["periodic"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":801745}}}]},"sourceEffectType":27,"sourceAuraType":23,"miscValue":0,"triggerSpellId":801745}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":801744,"level":1,"description":"Mark the target location for an Air Strike. After 7 seconds, it deals 1250 Fire damage to up to 12 enemies caught within the blast. This ability always critically strikes.","castMode":"instant","castTimeMs":0,"cooldownMs":60000,"gcdMs":1500,"cost":{"resource":"mana","amount":25,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:801744:effect:0:aura:23","name":"Air Strike (Aura 23)","disposition":"debuff","durationMs":7000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","procs":[{"id":"coa:801744:proc:0:801745","triggers":["periodic"],"chance":1,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":801745}}}]},"sourceEffectType":27,"sourceAuraType":23,"miscValue":0,"triggerSpellId":801745}]}],"talentEntryId":29440},{"id":"coa-tree-5997","classId":"tinker","dbcSpellId":520445,"name":"Auto Resuscitation Device","unlockLevel":1,"icon":"/assets/ui/spells/inv_misc_enggizmos_15.png","sigil":"AR","description":"Attach a resuscitation device to your target ally for 20 seconds. When the target would otherwise die, they are instead healed for 50% of their maximum health.","target":"friendly","range":{"min":0,"max":20},"castMode":"cast","castTimeMs":1500,"cooldownMs":180000,"gcdMs":0,"cost":{"resource":"mana","amount":40,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"heal","coefficient":1},{"kind":"apply-aura","aura":{"id":"coa:520445:effect:0:aura:69","name":"Auto Resuscitation Device (Aura 69)","disposition":"buff","durationMs":20000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","absorbs":[{"id":"coa:520445:absorb:0","amount":20,"perStack":false}]},"sourceEffectType":6,"sourceAuraType":69,"miscValue":127,"triggerSpellId":524780}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":520445,"level":1,"description":"Attach a resuscitation device to your target ally for 20 seconds. When the target would otherwise die, they are instead healed for 50% of their maximum health.","castMode":"cast","castTimeMs":1500,"cooldownMs":180000,"gcdMs":0,"cost":{"resource":"mana","amount":40,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"heal","coefficient":1},{"kind":"apply-aura","aura":{"id":"coa:520445:effect:0:aura:69","name":"Auto Resuscitation Device (Aura 69)","disposition":"buff","durationMs":20000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"magic","absorbs":[{"id":"coa:520445:absorb:0","amount":20,"perStack":false}]},"sourceEffectType":6,"sourceAuraType":69,"miscValue":127,"triggerSpellId":524780}]}],"talentEntryId":5997},{"id":"coa-28-blasting-barrels-99-705835","classId":"tinker","dbcSpellId":705835,"name":"Blasting Barrels","unlockLevel":1,"icon":"/assets/ui/spells/5_gunshot_(3)_border.png","sigil":"BB","description":"Increases critical strike damage by $s1% and increases damage dealt by Rounds by $s2%.","target":"hostile","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"damage","coefficient":1}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705835,"level":1,"description":"Increases critical strike damage by $s1% and increases damage dealt by Rounds by $s2%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"damage","coefficient":1}]}]},{"id":"coa-tree-30583","classId":"tinker","dbcSpellId":560754,"name":"Build: Alarm Beacon","unlockLevel":1,"icon":"/assets/ui/spells/inv_lightforgedmechsuit.png","sigil":"BA","description":"3 Charges, 15 sec recharge Throw down an alarm beacon for 10 seconds, removing fear, charm and sleep effects from up to 1 ally within 20 yds every 1 sec.","target":"hostile","range":{"min":0,"max":20},Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"venomancer","abilities":[{"id":"coa-29-acceleration-103-705960","classId":"venomancer","dbcSpellId":705960,"name":"Acceleration","unlockLevel":1,"icon":"/assets/ui/spells/_meat_rotten.png","sigil":"AC","description":"AccelerationRank 2Increases the tick rate of Wilt and Shadra's Vigil by 10%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705960:effect:0:aura:108","name":"Acceleration (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":19,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705960:effect:1:aura:108","name":"Acceleration (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":19,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":2,"spellId":705960,"level":1,"description":"AccelerationRank 2Increases the tick rate of Wilt and Shadra's Vigil by 10%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705960:effect:0:aura:108","name":"Acceleration (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":19,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705960:effect:1:aura:108","name":"Acceleration (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":19,"triggerSpellId":0}]}]},{"id":"coa-tree-6086","classId":"venomancer","dbcSpellId":805775,"name":"Adrenal Venom","unlockLevel":1,"icon":"/assets/ui/spells/trade_alchemy_dpotion_a26.png","sigil":"AV","description":"Activate Adrenal Venom for 120 minutes, giving your casts a 25% chance to increase your haste by 6% for 6 seconds, stacking 3 times. You can have a maximum of 2 unique Venoms active at a time.","target":"self","range":{"min":0,"max":0},"castMode":"cast","castTimeMs":1000,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":20,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:805775:effect:0:aura:42","name":"Adrenal Venom (Aura 42)","disposition":"buff","durationMs":7200000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"poison","procs":[{"id":"coa:805775:proc:0:805894","triggers":["cast"],"chance":0.25,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":805894}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":805894},{"kind":"apply-aura","aura":{"id":"coa:805775:effect:1:aura:107","name":"Adrenal Venom (Aura 107)","disposition":"buff","durationMs":7200000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"poison","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":17,"triggerSpellId":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":805775,"level":1,"description":"Activate Adrenal Venom for 120 minutes, giving your casts a 25% chance to increase your haste by 6% for 6 seconds, stacking 3 times. You can have a maximum of 2 unique Venoms active at a time.","castMode":"cast","castTimeMs":1000,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":20,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:805775:effect:0:aura:42","name":"Adrenal Venom (Aura 42)","disposition":"buff","durationMs":7200000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"poison","procs":[{"id":"coa:805775:proc:0:805894","triggers":["cast"],"chance":0.25,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":805894}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":805894},{"kind":"apply-aura","aura":{"id":"coa:805775:effect:1:aura:107","name":"Adrenal Venom (Aura 107)","disposition":"buff","durationMs":7200000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"poison","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":17,"triggeLine truncated
{"schemaVersion":1,"classId":"venomancer","abilities":[{"id":"coa-29-acceleration-103-705960","classId":"venomancer","dbcSpellId":705960,"name":"Acceleration","unlockLevel":1,"icon":"/assets/ui/spells/_meat_rotten.png","sigil":"AC","description":"Increases the tick rate of Wilt and Shadra's Vigil by $s1%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705960:effect:0:aura:108","name":"Acceleration (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":19,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705960:effect:1:aura:108","name":"Acceleration (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":19,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":2,"spellId":705960,"level":1,"description":"Increases the tick rate of Wilt and Shadra's Vigil by $s1%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705960:effect:0:aura:108","name":"Acceleration (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":19,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705960:effect:1:aura:108","name":"Acceleration (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":19,"triggerSpellId":0}]}]},{"id":"coa-tree-6086","classId":"venomancer","dbcSpellId":805775,"name":"Adrenal Venom","unlockLevel":1,"icon":"/assets/ui/spells/trade_alchemy_dpotion_a26.png","sigil":"AV","description":"Activate Adrenal Venom for 120 minutes, giving your casts a 25% chance to increase your haste by 6% for 6 seconds, stacking 3 times. You can have a maximum of 2 unique Venoms active at a time.","target":"self","range":{"min":0,"max":0},"castMode":"cast","castTimeMs":1000,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":20,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:805775:effect:0:aura:42","name":"Adrenal Venom (Aura 42)","disposition":"buff","durationMs":7200000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"poison","procs":[{"id":"coa:805775:proc:0:805894","triggers":["cast"],"chance":0.25,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":805894}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":805894},{"kind":"apply-aura","aura":{"id":"coa:805775:effect:1:aura:107","name":"Adrenal Venom (Aura 107)","disposition":"buff","durationMs":7200000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"poison","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":17,"triggerSpellId":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":805775,"level":1,"description":"Activate Adrenal Venom for 120 minutes, giving your casts a 25% chance to increase your haste by 6% for 6 seconds, stacking 3 times. You can have a maximum of 2 unique Venoms active at a time.","castMode":"cast","castTimeMs":1000,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":20,"percentage":true,"percentageBasis":"base-mana"},"effects":[{"kind":"apply-aura","aura":{"id":"coa:805775:effect:0:aura:42","name":"Adrenal Venom (Aura 42)","disposition":"buff","durationMs":7200000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"poison","procs":[{"id":"coa:805775:proc:0:805894","triggers":["cast"],"chance":0.25,"action":{"kind":"custom","id":"wow335-trigger-spell","data":{"spellId":805894}}}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":42,"miscValue":0,"triggerSpellId":805894},{"kind":"apply-aura","aura":{"id":"coa:805775:effect:1:aura:107","name":"Adrenal Venom (Aura 107)","disposition":"buff","durationMs":7200000,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"poison","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":17,"triggerSpellId":0}]}],"talentEntryId":6086},{"id":"cLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"witch-doctor","abilities":[{"id":"coa-tree-30147","classId":"witch-doctor","dbcSpellId":705921,"name":"Alchemical Enhancement","unlockLevel":1,"icon":"/assets/ui/spells/inv_alchemy_71_potion4.png","sigil":"AE","description":"Increases your haste by 5%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705921:effect:0:aura:216","name":"Alchemical Enhancement (Aura 216)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":216,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705921:effect:1:aura:192","name":"Alchemical Enhancement (Aura 192)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":192,"miscValue":127,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":705921,"level":1,"description":"Increases your haste by 5%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705921:effect:0:aura:216","name":"Alchemical Enhancement (Aura 216)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":216,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705921:effect:1:aura:192","name":"Alchemical Enhancement (Aura 192)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":192,"miscValue":127,"triggerSpellId":0}]}],"talentEntryId":30147},{"id":"coa-tree-11323","classId":"witch-doctor","dbcSpellId":301297,"name":"Blatant Curse","unlockLevel":1,"icon":"/assets/ui/spells/spell_nature_removecurse.png","sigil":"BC","description":"Reduces the mana cost of your Jinxes by -25%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:301297:effect:0:aura:108","name":"Blatant Curse (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":8,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:301297:effect:1:aura:108","name":"Blatant Curse (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.25}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":301297,"level":1,"description":"Reduces the mana cost of your Jinxes by -25%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:301297:effect:0:aura:108","name":"Blatant Curse (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":8,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:301297:effect:1:aura:108","name":"Blatant Curse (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.25}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0}]}],"talentEntryId":11323},{"id":"coa-tree-12048","classId":"witch-doctor","dbcSpellId":572870,"name":"Blessing of Hir'eek","unlockLevel":1,"icon":"/assets/ui/spells/trade_archaeology_trollbatidol.png","sigil":"BO","description":"Your Hexbreak now removes an additional curse effect.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:572870:effect:0:aura:107","name":"Blessing of Hir'eek (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"sLine truncated
{"schemaVersion":1,"classId":"witch-doctor","abilities":[{"id":"coa-tree-30147","classId":"witch-doctor","dbcSpellId":705921,"name":"Alchemical Enhancement","unlockLevel":1,"icon":"/assets/ui/spells/inv_alchemy_71_potion4.png","sigil":"AE","description":"Increases your haste by 5%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705921:effect:0:aura:216","name":"Alchemical Enhancement (Aura 216)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":216,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705921:effect:1:aura:192","name":"Alchemical Enhancement (Aura 192)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":192,"miscValue":127,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":705921,"level":1,"description":"Increases your haste by 5%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705921:effect:0:aura:216","name":"Alchemical Enhancement (Aura 216)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":216,"miscValue":0,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705921:effect:1:aura:192","name":"Alchemical Enhancement (Aura 192)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"haste","operation":"percent","value":0.05}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":192,"miscValue":127,"triggerSpellId":0}]}],"talentEntryId":30147},{"id":"coa-tree-11323","classId":"witch-doctor","dbcSpellId":301297,"name":"Blatant Curse","unlockLevel":1,"icon":"/assets/ui/spells/spell_nature_removecurse.png","sigil":"BC","description":"Reduces the mana cost of your Jinxes by -25%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:301297:effect:0:aura:108","name":"Blatant Curse (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":8,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:301297:effect:1:aura:108","name":"Blatant Curse (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.25}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0}],"passive":true,"source":"coa-tree","ranks":[{"rank":1,"spellId":301297,"level":1,"description":"Reduces the mana cost of your Jinxes by -25%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:301297:effect:0:aura:108","name":"Blatant Curse (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":8,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:301297:effect:1:aura:108","name":"Blatant Curse (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","dispelCategory":"curse","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.25}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0}]}],"talentEntryId":11323},{"id":"coa-tree-12048","classId":"witch-doctor","dbcSpellId":572870,"name":"Blessing of Hir'eek","unlockLevel":1,"icon":"/assets/ui/spells/trade_archaeology_trollbatidol.png","sigil":"BO","description":"Your Hexbreak now removes an additional curse effect.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"mana","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:572870:effect:0:aura:107","name":"Blessing of Hir'eek (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"witch-hunter","abilities":[{"id":"coa-15-agile-steps-58-705521","classId":"witch-hunter","dbcSpellId":705521,"name":"Agile Steps","unlockLevel":1,"icon":"/assets/ui/spells/inv_boot_cloth_nzothraidmythic_d_01.png","sigil":"AS","description":"Agile StepsRank 1Reduces the cooldown of Vault by 2 sec.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705521:effect:0:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705521:effect:1:aura:107","name":"Agile Steps (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-20}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705521:effect:2:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":1,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705521,"level":1,"description":"Agile StepsRank 1Reduces the cooldown of Vault by 2 sec.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705521:effect:0:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705521:effect:1:aura:107","name":"Agile Steps (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-20}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705521:effect:2:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":1,"triggerSpellId":0}]},{"rank":2,"spellId":705522,"level":1,"description":"Agile StepsRank 2Reduces the cooldown of Vault by 4 sec.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705522:effect:0:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705522:effect:1:aura:107","name":"Agile Steps (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-40}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705522:effect:2:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":1,"triggerSpellId":0}]},{"rank":3,"spellId":705523,"level":1,"description":"Agile StepsRank 3InstantReduces the cooldown of Vault by 3 sec.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705523:effect:0:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705523:effect:1:aura:107","name":"Agile Steps (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-30}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705523:effect:2:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceALine truncated
{"schemaVersion":1,"classId":"witch-hunter","abilities":[{"id":"coa-15-agile-steps-58-705521","classId":"witch-hunter","dbcSpellId":705521,"name":"Agile Steps","unlockLevel":1,"icon":"/assets/ui/spells/inv_boot_cloth_nzothraidmythic_d_01.png","sigil":"AS","description":"Reduces the cooldown of Vault by $/1000;s2 sec.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705521:effect:0:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705521:effect:1:aura:107","name":"Agile Steps (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-20}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705521:effect:2:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":1,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705521,"level":1,"description":"Reduces the cooldown of Vault by $/1000;s2 sec.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705521:effect:0:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705521:effect:1:aura:107","name":"Agile Steps (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-20}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705521:effect:2:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":1,"triggerSpellId":0}]},{"rank":2,"spellId":705522,"level":1,"description":"Reduces the cooldown of Vault by $/1000;s2 sec.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705522:effect:0:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705522:effect:1:aura:107","name":"Agile Steps (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-40}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705522:effect:2:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":1,"triggerSpellId":0}]},{"rank":3,"spellId":705523,"level":1,"description":"Reduces the cooldown of Vault by $/1000;s2 sec.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"rage","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705523:effect:0:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":127,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705523:effect:1:aura:107","name":"Agile Steps (Aura 107)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"attack-power","operation":"percent","value":-30}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":107,"miscValue":11,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705523:effect:2:aura:4","name":"Agile Steps (Aura 4)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","utilityTags":["coa-aura:4"]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":4,"miscValue":1,"triggerSpellId":0}]}]},{"id":Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"abilitiesByClass":{"barbarian":[{"id":"coa-tree-30762","classId":"barbarian","dbcSpellId":500918,"name":"Ancestral Roar","unlockLevel":1,"icon":"/assets/ui/spells/_d3threateningshout.png","sigil":"AR","description":"Ancestral RoarRank 1Instant cast25 sec cooldownRequires Enraged Roar with ancestral fervor, healing you for 100+0+AP*0.5.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":25000,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"heal","coefficient":1.6580645243326824,"basePoints":100,"dieSides":7,"pointsPerLevel":3.200000047683716,"bonusPowerCoefficient":0,"sourceLevel":16,"maxScalingLevel":22,"attackPowerCoefficient":0.5,"recipient":"caster"},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":3,"triggerSpellId":0,"durationMs":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":500918,"level":1,"description":"Ancestral RoarRank 1Instant cast25 sec cooldownRequires Enraged Roar with ancestral fervor, healing you for 100+0+AP*0.5.","castMode":"instant","castTimeMs":0,"cooldownMs":25000,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"heal","coefficient":1.6580645243326824,"basePoints":100,"dieSides":7,"pointsPerLevel":3.200000047683716,"bonusPowerCoefficient":0,"sourceLevel":16,"maxScalingLevel":22,"attackPowerCoefficient":0.5,"recipient":"caster"},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":3,"triggerSpellId":0,"durationMs":0}]}],"talentEntryId":30762},{"id":"coa-12-ancestral-spirit-47-705153","classId":"barbarian","dbcSpellId":705153,"name":"Ancestral Spirit","unlockLevel":1,"icon":"/assets/ui/spells/inv_misc_questionmark.png","sigil":"AS","description":"Ancestral SpiritRank 1Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by 50%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705153:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705153:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705153,"level":1,"description":"Ancestral SpiritRank 1Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by 50%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705153:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705153:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}]},{"rank":2,"spellId":705154,"level":1,"description":"Ancestral SpiritRank 2Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by 100%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705154:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705154:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}]}]},{"id":"coa-tree-34279","classId":"barbarian","dbcSpellId":560456,"name"Line truncated
{"schemaVersion":1,"abilitiesByClass":{"barbarian":[{"id":"coa-tree-30762","classId":"barbarian","dbcSpellId":500918,"name":"Ancestral Roar","unlockLevel":1,"icon":"/assets/ui/spells/_d3threateningshout.png","sigil":"AR","description":"Requires Enraged Roar with ancestral fervor, healing you for 100 + 50% AP.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":25000,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"heal","coefficient":1.6580645243326824,"basePoints":100,"dieSides":7,"pointsPerLevel":3.200000047683716,"bonusPowerCoefficient":0,"sourceLevel":16,"maxScalingLevel":22,"attackPowerCoefficient":0.5,"recipient":"caster"},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":3,"triggerSpellId":0,"durationMs":0}],"passive":false,"source":"coa-tree","ranks":[{"rank":1,"spellId":500918,"level":1,"description":"Requires Enraged Roar with ancestral fervor, healing you for 100 + 50% AP.","castMode":"instant","castTimeMs":0,"cooldownMs":25000,"gcdMs":1500,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"heal","coefficient":1.6580645243326824,"basePoints":100,"dieSides":7,"pointsPerLevel":3.200000047683716,"bonusPowerCoefficient":0,"sourceLevel":16,"maxScalingLevel":22,"attackPowerCoefficient":0.5,"recipient":"caster"},{"kind":"utility","action":"class-script","effectType":3,"auraType":0,"miscValue":3,"triggerSpellId":0,"durationMs":0}]}],"talentEntryId":30762},{"id":"coa-12-ancestral-spirit-47-705153","classId":"barbarian","dbcSpellId":705153,"name":"Ancestral Spirit","unlockLevel":1,"icon":"/assets/ui/spells/inv_misc_questionmark.png","sigil":"AS","description":"Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by -50%.","target":"self","range":{"min":0,"max":0},"castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705153:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705153:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}],"passive":true,"source":"coa-progression","ranks":[{"rank":1,"spellId":705153,"level":1,"description":"Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by -50%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705153:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705153:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":0.5}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}]},{"rank":2,"spellId":705154,"level":1,"description":"Reduces the Energy cost of your Spirit spells and increases the duration of your Shouts by -100%.","castMode":"instant","castTimeMs":0,"cooldownMs":0,"gcdMs":0,"cost":{"resource":"energy","amount":0},"effects":[{"kind":"apply-aura","aura":{"id":"coa:705154:effect:0:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":-1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":14,"triggerSpellId":0},{"kind":"apply-aura","aura":{"id":"coa:705154:effect:1:aura:108","name":"Ancestral Spirit (Aura 108)","disposition":"buff","durationMs":null,"maxStacks":1,"stackBehavior":"refresh","modifiers":[{"kind":"stat","stat":"ranged-attack-power","operation":"percent","value":1}]},"recipient":"caster","sourceEffectType":6,"sourceAuraType":108,"miscValue":1,"triggerSpellId":0}]}]},{"id":"coa-tree-34279","classId":"barbarian","dbcSpellId":560456,"name":"Athleticism","unlockLevel":1,"icon":"/assets/ui/spells/5_run_border.png","sigil":"AT","description":"Increases your Energy regeneration by 25%.","target":"self","raLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"spells":[{"id":500917,"name":"Add Carnage","rankText":"","description":"Being torn to shreds.","categoryId":60,"dispelType":0,"mechanic":0,"attributes":[2216951808,0,0,0,1048576,0,8388608,33554432],"castTimeIndex":1,"castTimeMs":0,"recoveryTimeMs":0,"categoryRecoveryTimeMs":0,"interruptFlags":8,"auraInterruptFlags":0,"channelInterruptFlags":0,"procFlags":0,"procChance":100,"procCharges":0,"maxLevel":0,"baseLevel":4,"spellLevel":4,"durationIndex":0,"durationMs":0,"powerType":0,"powerCost":0,"powerCostPerLevel":0,"powerCostPerSecond":0,"powerCostPerSecondPerLevel":0,"rangeIndex":6,"rangeMin":0,"rangeMax":100,"projectileSpeed":0,"stackAmount":20,"equippedItemClass":0,"equippedItemSubclassMask":-1,"equippedItemInventoryMask":0,"iconId":1531,"powerCostPercentage":0,"startRecoveryCategory":0,"startRecoveryTimeMs":0,"maximumTargets":0,"damageClass":0,"preventionType":0,"schoolMask":1,"runeCostId":0,"powerDisplayId":0,"effects":[{"index":0,"effectType":3,"auraType":0,"basePoints":0,"dieSides":1,"pointsPerLevel":0,"mechanic":0,"implicitTargetA":6,"implicitTargetB":0,"radiusIndex":0,"radius":0,"periodMs":0,"valueMultiplier":0,"chainTargets":0,"itemType":0,"miscValue":0,"miscValueB":1,"triggerSpellId":0,"pointsPerCombo":0,"coefficient":0},{"index":1,"effectType":0,"auraType":0,"basePoints":0,"dieSides":1,"pointsPerLevel":0,"mechanic":0,"implicitTargetA":0,"implicitTargetB":0,"radiusIndex":0,"radius":0,"periodMs":0,"valueMultiplier":0,"chainTargets":0,"itemType":0,"miscValue":0,"miscValueB":0,"triggerSpellId":0,"pointsPerCombo":0,"coefficient":0},{"index":2,"effectType":0,"auraType":0,"basePoints":0,"dieSides":1,"pointsPerLevel":0,"mechanic":0,"implicitTargetA":0,"implicitTargetB":0,"radiusIndex":0,"radius":0,"periodMs":0,"valueMultiplier":0,"chainTargets":0,"itemType":0,"miscValue":0,"miscValueB":0,"triggerSpellId":0,"pointsPerCombo":0,"coefficient":0}]},{"id":800951,"name":"Battle Rhythm","rankText":"","description":"Grants 5 Energy.","categoryId":0,"dispelType":0,"mechanic":0,"attributes":[65536,0,0,0,0,0,0,0],"castTimeIndex":1,"castTimeMs":0,"recoveryTimeMs":8000,"categoryRecoveryTimeMs":0,"interruptFlags":15,"auraInterruptFlags":0,"channelInterruptFlags":0,"procFlags":0,"procChance":101,"procCharges":0,"maxLevel":0,"baseLevel":1,"spellLevel":1,"durationIndex":0,"durationMs":0,"powerType":0,"powerCost":0,"powerCostPerLevel":0,"powerCostPerSecond":0,"powerCostPerSecondPerLevel":0,"rangeIndex":5,"rangeMin":0,"rangeMax":40,"projectileSpeed":0,"stackAmount":0,"equippedItemClass":0,"equippedItemSubclassMask":-1,"equippedItemInventoryMask":0,"iconId":2025,"powerCostPercentage":13,"startRecoveryCategory":133,"startRecoveryTimeMs":1500,"maximumTargets":0,"damageClass":1,"preventionType":1,"schoolMask":1,"runeCostId":0,"powerDisplayId":0,"effects":[{"index":0,"effectType":30,"auraType":0,"basePoints":5,"dieSides":1,"pointsPerLevel":0,"mechanic":0,"implicitTargetA":1,"implicitTargetB":0,"radiusIndex":0,"radius":0,"periodMs":0,"valueMultiplier":0,"chainTargets":0,"itemType":0,"miscValue":3,"miscValueB":0,"triggerSpellId":0,"pointsPerCombo":0,"coefficient":0},{"index":1,"effectType":3,"auraType":0,"basePoints":-1000,"dieSides":1,"pointsPerLevel":0,"mechanic":0,"implicitTargetA":1,"implicitTargetB":0,"radiusIndex":0,"radius":0,"periodMs":0,"valueMultiplier":0,"chainTargets":0,"itemType":0,"miscValue":0,"miscValueB":0,"triggerSpellId":0,"pointsPerCombo":0,"coefficient":0},{"index":2,"effectType":0,"auraType":0,"basePoints":0,"dieSides":1,"pointsPerLevel":0,"mechanic":0,"implicitTargetA":0,"implicitTargetB":0,"radiusIndex":0,"radius":0,"periodMs":0,"valueMultiplier":0,"chainTargets":0,"itemType":0,"miscValue":0,"miscValueB":0,"triggerSpellId":0,"pointsPerCombo":0,"coefficient":0}]},{"id":806960,"name":"Berserker Axe","rankText":"Damage","description":"|cffffffffRequires Enraged|r |cffffffff3 Charges, 8 sec recharge|r Hurl two axes at an enemy, each dealing ${$m1+0+$RAP*0.35} Physical Damage and reducing enemy armor by ${-($m3)} for $d. @ext:Shares a cooldown with |cffffffffAxe Volley|r.:ext@","categoryId":0,"dispelType":0,"mechanic":0,"attributes":[65552,0,1073872896,0,262144,0,0,0],"castTimeIndex":1,"castTimeMs":0,"recoveryTimeMs":0,"categoryRecoveryTimeMs":0,"interruptFlags":15,"auraInterruptFlags":0,"channelInterruptFlags":0,"procFlags":0,"procChance":0,"procCharges":0,"maxLevel":0,"baseLevel":11,"spellLevel":11,"durationIndex":0,"durationMs":0,"powerType":3,"powerCost":0,"powerCostPerLevel":0,"powerCostPerSecond":0,"powerCostPerSecondPerLevel":0,"rangeIndex":4,"rangeMin":0,"rangeMax":30,"projectileSpeed":30,"stackAmount":0,"equippedItemClass":0,"equippedItemSubclassMask":2,"equippedItemInventoryMask":65536,"iconId":8547,"powerCostPercentage":0,"startRecoveryCategory":0,"startRecoveryTimeMs":0,"maximumTargets":0,"damageClass":3,"preventionType":2,"schoolMask":1,"runeCostId":0,"powerDisplayId":0,"effects":[{"index":0,"effectType":2,"auraType":0,"basePoints":1,"dieSides":1,"pointsPerLevel":0,"mechanic":0,"imLine truncated
{"schemaVersion":1,"source":{"spellDbcPath":"client-current/patch-T/DBFilesClient/Spell.dbc","sha256":"c4601cb80e2fb58dd10af3da82e2fdea653d4462714e30fdf48db6ba4a152794"},"spells":[{"id":1604,"name":"Dazed","rankText":"","description":"A concussive strike dismounts the target and reduces movement speed by $s1%.","categoryId":0,"dispelType":0,"mechanic":27,"attributes":[16,262144,0,0,1,0,0,0],"castTimeIndex":1,"castTimeMs":0,"recoveryTimeMs":0,"categoryRecoveryTimeMs":0,"interruptFlags":0,"auraInterruptFlags":0,"channelInterruptFlags":0,"procFlags":0,"procChance":101,"procCharges":0,"maxLevel":0,"baseLevel":0,"spellLevel":0,"durationIndex":35,"durationMs":4000,"powerType":0,"powerCost":0,"powerCostPerLevel":0,"powerCostPerSecond":0,"powerCostPerSecondPerLevel":0,"rangeIndex":2,"rangeMin":0,"rangeMax":5,"projectileSpeed":0,"stackAmount":0,"equippedItemClass":0,"equippedItemSubclassMask":-1,"equippedItemInventoryMask":0,"iconId":15,"powerCostPercentage":0,"startRecoveryCategory":0,"startRecoveryTimeMs":0,"maximumTargets":0,"damageClass":0,"preventionType":0,"schoolMask":1,"runeCostId":0,"powerDisplayId":0,"effects":[{"index":0,"effectType":6,"auraType":33,"basePoints":-50,"dieSides":1,"pointsPerLevel":0,"mechanic":27,"implicitTargetA":6,"implicitTargetB":0,"radiusIndex":0,"radius":0,"periodMs":0,"valueMultiplier":0,"chainTargets":0,"itemType":0,"miscValue":0,"miscValueB":0,"triggerSpellId":0,"pointsPerCombo":0,"coefficient":0},{"index":1,"effectType":108,"auraType":0,"basePoints":1,"dieSides":1,"pointsPerLevel":0,"mechanic":0,"implicitTargetA":6,"implicitTargetB":0,"radiusIndex":0,"radius":0,"periodMs":0,"valueMultiplier":0,"chainTargets":0,"itemType":0,"miscValue":21,"miscValueB":0,"triggerSpellId":0,"pointsPerCombo":0,"coefficient":1}]},{"id":32991,"name":"Nature Cast Visual","rankText":"Rank 1","description":"","categoryId":0,"dispelType":0,"mechanic":0,"attributes":[65920,0,0,0,0,0,0,0],"castTimeIndex":6,"castTimeMs":5000,"recoveryTimeMs":0,"categoryRecoveryTimeMs":0,"interruptFlags":15,"auraInterruptFlags":524290,"channelInterruptFlags":0,"procFlags":0,"procChance":101,"procCharges":0,"maxLevel":0,"baseLevel":1,"spellLevel":1,"durationIndex":0,"durationMs":0,"powerType":0,"powerCost":0,"powerCostPerLevel":0,"powerCostPerSecond":0,"powerCostPerSecondPerLevel":0,"rangeIndex":1,"rangeMin":0,"rangeMax":0,"projectileSpeed":0,"stackAmount":0,"equippedItemClass":0,"equippedItemSubclassMask":-1,"equippedItemInventoryMask":0,"iconId":82,"powerCostPercentage":0,"startRecoveryCategory":133,"startRecoveryTimeMs":0,"maximumTargets":0,"damageClass":1,"preventionType":1,"schoolMask":8,"runeCostId":0,"powerDisplayId":0,"effects":[{"index":0,"effectType":3,"auraType":0,"basePoints":1,"dieSides":0,"pointsPerLevel":0,"mechanic":0,"implicitTargetA":1,"implicitTargetB":0,"radiusIndex":0,"radius":0,"periodMs":0,"valueMultiplier":0,"chainTargets":0,"itemType":0,"miscValue":0,"miscValueB":0,"triggerSpellId":0,"pointsPerCombo":0,"coefficient":0}]},{"id":35764,"name":"Astral Armor Visual","rankText":"","description":"","categoryId":0,"dispelType":0,"mechanic":0,"attributes":[262528,0,0,0,0,0,0,0],"castTimeIndex":1,"castTimeMs":0,"recoveryTimeMs":0,"categoryRecoveryTimeMs":0,"interruptFlags":0,"auraInterruptFlags":0,"channelInterruptFlags":0,"procFlags":0,"procChance":101,"procCharges":0,"maxLevel":0,"baseLevel":0,"spellLevel":0,"durationIndex":0,"durationMs":0,"powerType":0,"powerCost":0,"powerCostPerLevel":0,"powerCostPerSecond":0,"powerCostPerSecondPerLevel":0,"rangeIndex":1,"rangeMin":0,"rangeMax":0,"projectileSpeed":0,"stackAmount":0,"equippedItemClass":0,"equippedItemSubclassMask":-1,"equippedItemInventoryMask":0,"iconId":1918,"powerCostPercentage":0,"startRecoveryCategory":0,"startRecoveryTimeMs":0,"maximumTargets":0,"damageClass":0,"preventionType":0,"schoolMask":64,"runeCostId":0,"powerDisplayId":0,"effects":[{"index":0,"effectType":3,"auraType":0,"basePoints":1,"dieSides":0,"pointsPerLevel":0,"mechanic":0,"implicitTargetA":1,"implicitTargetB":0,"radiusIndex":16,"radius":1,"periodMs":0,"valueMultiplier":0,"chainTargets":0,"itemType":0,"miscValue":0,"miscValueB":0,"triggerSpellId":0,"pointsPerCombo":0,"coefficient":0}]},{"id":48108,"name":"Hot Streak","rankText":"","description":"Your next Pyroblast is instant.","categoryId":0,"dispelType":0,"mechanic":0,"attributes":[0,0,0,0,0,0,64,0],"castTimeIndex":1,"castTimeMs":0,"recoveryTimeMs":0,"categoryRecoveryTimeMs":0,"interruptFlags":0,"auraInterruptFlags":0,"channelInterruptFlags":0,"procFlags":0,"procChance":100,"procCharges":1,"maxLevel":0,"baseLevel":0,"spellLevel":0,"durationIndex":1,"durationMs":10000,"powerType":0,"powerCost":0,"powerCostPerLevel":0,"powerCostPerSecond":0,"powerCostPerSecondPerLevel":0,"rangeIndex":1,"rangeMin":0,"rangeMax":0,"projectileSpeed":0,"stackAmount":0,"equippedItemClass":0,"equippedItemSubclassMask":-1,"equippedItemInventoryMask":0,"iconId":2999,"powerCostPercentage":0,"startRecoveryCategory":0,"startRecoveryTimeMs":0,"maximumTargets":0,"damageLine truncated
@@ -0,0 +1 @@
{"schemaVersion":1,"status":"source-item stat references with synthetic class/slot selection and level interpolation","sourceRecordSha256":{"armorobject.db":"a2f0017c4772165d562ebb08ca0ac51625cdc4453e3670a1501df7d741d2bad3","weaponobject.db":"2bc28eebbe413bd6118f027e3fec1a3953cef371476937d0b65622c542971a67","addpowerobject.db":"d651861fc5918bac937d726d754d17a92da34db5059f9c70ac9f6b2c15711432","string_enus.db":"4fce021ba9ed110a213e08d3228b2de57cec66ddbbc8cdcf5753204874d9ab75"},"statTypeMap":{"12":"physicalAttack","13":"physicalDefense","14":"magicalDefense","15":"magicalAttack","16":"physicalHit","17":"physicalDodge","18":"physicalCritical","20":"magicalCritical","22":"parry","25":"physicalDamage","148":"magicalDamagePoint","150":"healPoint","191":"magicalDamage","195":"magicalHit"},"profiles":{"rom-knight":{"head":[{"stamina":1,"physicalDefense":5,"magicalDefense":3},{"stamina":1,"physicalDefense":10,"magicalDefense":7},{"stamina":2,"physicalDefense":14,"magicalDefense":10},{"stamina":2,"physicalDefense":19,"magicalDefense":14},{"stamina":3,"physicalDefense":24,"magicalDefense":17},{"stamina":3,"physicalDefense":27,"magicalDefense":19},{"stamina":4,"physicalDefense":29,"magicalDefense":21},{"stamina":4,"physicalDefense":32,"magicalDefense":22},{"stamina":4,"physicalDefense":35,"magicalDefense":24},{"stamina":5,"physicalDefense":37,"magicalDefense":26},{"stamina":5,"physicalDefense":40,"magicalDefense":28},{"stamina":5,"physicalDefense":43,"magicalDefense":30},{"stamina":6,"physicalDefense":45,"magicalDefense":32},{"stamina":6,"physicalDefense":48,"magicalDefense":33},{"stamina":7,"physicalDefense":50,"magicalDefense":35},{"stamina":7,"physicalDefense":53,"magicalDefense":37},{"stamina":7,"physicalDefense":56,"magicalDefense":39},{"stamina":8,"physicalDefense":58,"magicalDefense":41},{"stamina":8,"physicalDefense":61,"magicalDefense":43},{"stamina":8,"physicalDefense":64,"magicalDefense":44},{"stamina":9,"physicalDefense":66,"magicalDefense":46},{"stamina":9,"physicalDefense":69,"magicalDefense":48},{"stamina":9,"health":155,"physicalDefense":72,"magicalDefense":51},{"stamina":9,"health":155,"physicalDefense":76,"magicalDefense":53},{"stamina":9,"health":155,"physicalDefense":79,"magicalDefense":56},{"stamina":9,"health":155,"physicalDefense":83,"magicalDefense":58},{"stamina":9,"health":155,"physicalDefense":86,"magicalDefense":61},{"stamina":9,"health":155,"physicalDefense":90,"magicalDefense":63},{"stamina":10,"health":155,"physicalDefense":93,"magicalDefense":65},{"stamina":11,"health":155,"physicalDefense":97,"magicalDefense":68},{"stamina":13,"health":155,"physicalDefense":100,"magicalDefense":70},{"stamina":13,"health":155,"physicalAttack":4,"physicalDefense":104,"magicalDefense":73},{"stamina":13,"health":155,"physicalAttack":8,"physicalDefense":108,"magicalDefense":76},{"stamina":13,"health":155,"physicalAttack":11,"physicalDefense":112,"magicalDefense":78},{"stamina":13,"health":155,"physicalAttack":15,"physicalDefense":116,"magicalDefense":81},{"stamina":13,"health":155,"physicalAttack":15,"physicalDefense":120,"magicalDefense":84},{"stamina":13,"health":179,"physicalAttack":15,"physicalDefense":124,"magicalDefense":87},{"stamina":13,"health":179,"physicalAttack":15,"physicalDefense":128,"magicalDefense":90},{"stamina":13,"health":194,"physicalAttack":15,"physicalDefense":133,"magicalDefense":93},{"stamina":13,"health":209,"physicalAttack":15,"physicalDefense":137,"magicalDefense":96},{"stamina":13,"health":223,"physicalAttack":15,"physicalDefense":142,"magicalDefense":99},{"stamina":13,"health":238,"physicalAttack":15,"physicalDefense":146,"magicalDefense":102},{"stamina":13,"health":238,"physicalAttack":15,"physicalDefense":151,"magicalDefense":106},{"stamina":13,"health":238,"physicalAttack":15,"physicalDefense":156,"magicalDefense":109},{"stamina":13,"health":238,"physicalAttack":15,"physicalDefense":161,"magicalDefense":113},{"stamina":13,"health":238,"physicalAttack":15,"physicalDefense":166,"magicalDefense":116},{"stamina":13,"health":238,"physicalAttack":15,"physicalDefense":171,"magicalDefense":120},{"stamina":22,"health":238,"physicalAttack":15,"physicalDefense":227,"magicalDefense":123},{"stamina":22,"health":238,"physicalAttack":15,"physicalDefense":227,"magicalDefense":177},{"stamina":45,"health":280,"physicalAttack":90,"physicalDefense":227,"magicalDefense":177},{"stamina":45,"health":280,"physicalAttack":90,"physicalDefense":227,"magicalDefense":177},{"stamina":45,"health":280,"physicalAttack":90,"physicalDefense":227,"magicalDefense":177},{"stamina":45,"health":280,"physicalAttack":90,"physicalDefense":227,"magicalDefense":177},{"stamina":45,"health":280,"physicalAttack":90,"physicalDefense":227,"magicalDefense":177},{"stamina":59,"health":280,"physicalAttack":127,"physicalDefense":441,"magicalDefense":263},{"stamina":59,"health":280,"physicalAttack":127,"physicalDefense":441,"magicalDefense":263},{"stamina":59,"health":280,"physicalAttack":127,"physicalDefense":441,"magicalDefensLine truncated
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"maximumCoaLevel":60,"coaBudgetsByClass":{"barbarian":{"maximumAbility":26,"maximumTalent":25},"witch-doctor":{"maximumAbility":26,"maximumTalent":25},"felsworn":{"maximumAbility":26,"maximumTalent":25},"witch-hunter":{"maximumAbility":26,"maximumTalent":25},"stormbringer":{"maximumAbility":26,"maximumTalent":25},"knight-of-xoroth":{"maximumAbility":26,"maximumTalent":25},"guardian":{"maximumAbility":26,"maximumTalent":25},"templar":{"maximumAbility":26,"maximumTalent":25},"bloodmage":{"maximumAbility":26,"maximumTalent":25},"ranger":{"maximumAbility":26,"maximumTalent":25},"chronomancer":{"maximumAbility":26,"maximumTalent":25},"necromancer":{"maximumAbility":26,"maximumTalent":25},"pyromancer":{"maximumAbility":26,"maximumTalent":25},"cultist":{"maximumAbility":26,"maximumTalent":25},"starcaller":{"maximumAbility":26,"maximumTalent":25},"sun-cleric":{"maximumAbility":26,"maximumTalent":25},"tinker":{"maximumAbility":26,"maximumTalent":25},"venomancer":{"maximumAbility":26,"maximumTalent":25},"reaper":{"maximumAbility":26,"maximumTalent":25},"primalist":{"maximumAbility":26,"maximumTalent":25},"runemaster":{"maximumAbility":26,"maximumTalent":25}},"trees":[{"id":"death-knight-blood","classId":"death-knight"},{"id":"death-knight-frost","classId":"death-knight"},{"id":"death-knight-unholy","classId":"death-knight"},{"id":"druid-balance","classId":"druid"},{"id":"druid-feral-combat","classId":"druid"},{"id":"druid-restoration","classId":"druid"},{"id":"hunter-beast-mastery","classId":"hunter"},{"id":"hunter-marksmanship","classId":"hunter"},{"id":"hunter-survival","classId":"hunter"},{"id":"mage-arcane","classId":"mage"},{"id":"mage-fire","classId":"mage"},{"id":"mage-frost","classId":"mage"},{"id":"paladin-holy","classId":"paladin"},{"id":"paladin-protection","classId":"paladin"},{"id":"paladin-retribution","classId":"paladin"},{"id":"priest-discipline","classId":"priest"},{"id":"priest-holy","classId":"priest"},{"id":"priest-shadow","classId":"priest"},{"id":"rogue-assassination","classId":"rogue"},{"id":"rogue-combat","classId":"rogue"},{"id":"rogue-subtlety","classId":"rogue"},{"id":"shaman-elemental","classId":"shaman"},{"id":"shaman-enhancement","classId":"shaman"},{"id":"shaman-restoration","classId":"shaman"},{"id":"warlock-affliction","classId":"warlock"},{"id":"warlock-demonology","classId":"warlock"},{"id":"warlock-destruction","classId":"warlock"},{"id":"warrior-arms","classId":"warrior"},{"id":"warrior-fury","classId":"warrior"},{"id":"warrior-protection","classId":"warrior"},{"id":"coa-barbarian-31","classId":"barbarian"},{"id":"coa-barbarian-32","classId":"barbarian"},{"id":"coa-barbarian-33","classId":"barbarian"},{"id":"coa-barbarian-87","classId":"barbarian"},{"id":"coa-witch-doctor-36","classId":"witch-doctor"},{"id":"coa-witch-doctor-34","classId":"witch-doctor"},{"id":"coa-witch-doctor-35","classId":"witch-doctor"},{"id":"coa-witch-doctor-87","classId":"witch-doctor"},{"id":"coa-felsworn-37","classId":"felsworn"},{"id":"coa-felsworn-38","classId":"felsworn"},{"id":"coa-felsworn-18","classId":"felsworn"},{"id":"coa-felsworn-87","classId":"felsworn"},{"id":"coa-witch-hunter-39","classId":"witch-hunter"},{"id":"coa-witch-hunter-40","classId":"witch-hunter"},{"id":"coa-witch-hunter-41","classId":"witch-hunter"},{"id":"coa-witch-hunter-94","classId":"witch-hunter"},{"id":"coa-witch-hunter-87","classId":"witch-hunter"},{"id":"coa-stormbringer-42","classId":"stormbringer"},{"id":"coa-stormbringer-43","classId":"stormbringer"},{"id":"coa-stormbringer-44","classId":"stormbringer"},{"id":"coa-stormbringer-87","classId":"stormbringer"},{"id":"coa-knight-of-xoroth-46","classId":"knight-of-xoroth"},{"id":"coa-knight-of-xoroth-45","classId":"knight-of-xoroth"},{"id":"coa-knight-of-xoroth-47","classId":"knight-of-xoroth"},{"id":"coa-knight-of-xoroth-87","classId":"knight-of-xoroth"},{"id":"coa-guardian-7","classId":"guardian"},{"id":"coa-guardian-48","classId":"guardian"},{"id":"coa-guardian-49","classId":"guardian"},{"id":"coa-guardian-87","classId":"guardian"},{"id":"coa-templar-50","classId":"templar"},{"id":"coa-templar-16","classId":"templar"},{"id":"coa-templar-51","classId":"templar"},{"id":"coa-templar-87","classId":"templar"},{"id":"coa-bloodmage-26","classId":"bloodmage"},{"id":"coa-bloodmage-52","classId":"bloodmage"},{"id":"coa-bloodmage-53","classId":"bloodmage"},{"id":"coa-bloodmage-93","classId":"bloodmage"},{"id":"coa-bloodmage-87","classId":"bloodmage"},{"id":"coa-ranger-55","classId":"ranger"},{"id":"coa-ranger-87","classId":"ranger"},{"id":"coa-ranger-2","classId":"ranger"},{"id":"coa-ranger-54","classId":"ranger"},{"id":"coa-chronomancer-56","classId":"chronomancer"},{"id":"coa-chronomancer-57","classId":"chronomancer"},{"id":"coa-chronomancer-87","classId":"chronomancer"},{"id":"coa-chronomancer-58","classId":"chronomancer"},{"id":"coa-necromancer-61","classId":"necromancer"},{"id":"coa-necromancer-87","classId":"necromancer"},{"id":"coa-necromancer-59","classId"Line truncated
{"schemaVersion":1,"maximumCoaLevel":60,"coaBudgetsByClass":{"barbarian":{"maximumAbility":26,"maximumTalent":25},"witch-doctor":{"maximumAbility":26,"maximumTalent":25},"felsworn":{"maximumAbility":26,"maximumTalent":25},"witch-hunter":{"maximumAbility":26,"maximumTalent":25},"stormbringer":{"maximumAbility":26,"maximumTalent":25},"knight-of-xoroth":{"maximumAbility":26,"maximumTalent":25},"guardian":{"maximumAbility":26,"maximumTalent":25},"templar":{"maximumAbility":26,"maximumTalent":25},"bloodmage":{"maximumAbility":26,"maximumTalent":25},"ranger":{"maximumAbility":26,"maximumTalent":25},"chronomancer":{"maximumAbility":26,"maximumTalent":25},"necromancer":{"maximumAbility":26,"maximumTalent":25},"pyromancer":{"maximumAbility":26,"maximumTalent":25},"cultist":{"maximumAbility":26,"maximumTalent":25},"starcaller":{"maximumAbility":26,"maximumTalent":25},"sun-cleric":{"maximumAbility":26,"maximumTalent":25},"tinker":{"maximumAbility":26,"maximumTalent":25},"venomancer":{"maximumAbility":26,"maximumTalent":25},"reaper":{"maximumAbility":26,"maximumTalent":25},"primalist":{"maximumAbility":26,"maximumTalent":25},"runemaster":{"maximumAbility":26,"maximumTalent":25}},"trees":[{"id":"death-knight-blood","classId":"death-knight"},{"id":"death-knight-frost","classId":"death-knight"},{"id":"death-knight-unholy","classId":"death-knight"},{"id":"druid-balance","classId":"druid"},{"id":"druid-feral-combat","classId":"druid"},{"id":"druid-restoration","classId":"druid"},{"id":"hunter-beast-mastery","classId":"hunter"},{"id":"hunter-marksmanship","classId":"hunter"},{"id":"hunter-survival","classId":"hunter"},{"id":"mage-arcane","classId":"mage"},{"id":"mage-fire","classId":"mage"},{"id":"mage-frost","classId":"mage"},{"id":"paladin-holy","classId":"paladin"},{"id":"paladin-protection","classId":"paladin"},{"id":"paladin-retribution","classId":"paladin"},{"id":"priest-discipline","classId":"priest"},{"id":"priest-holy","classId":"priest"},{"id":"priest-shadow","classId":"priest"},{"id":"rogue-assassination","classId":"rogue"},{"id":"rogue-combat","classId":"rogue"},{"id":"rogue-subtlety","classId":"rogue"},{"id":"shaman-elemental","classId":"shaman"},{"id":"shaman-enhancement","classId":"shaman"},{"id":"shaman-restoration","classId":"shaman"},{"id":"warlock-affliction","classId":"warlock"},{"id":"warlock-demonology","classId":"warlock"},{"id":"warlock-destruction","classId":"warlock"},{"id":"warrior-arms","classId":"warrior"},{"id":"warrior-fury","classId":"warrior"},{"id":"warrior-protection","classId":"warrior"},{"id":"coa-barbarian-87","classId":"barbarian"},{"id":"coa-barbarian-31","classId":"barbarian"},{"id":"coa-barbarian-32","classId":"barbarian"},{"id":"coa-barbarian-33","classId":"barbarian"},{"id":"coa-witch-doctor-87","classId":"witch-doctor"},{"id":"coa-witch-doctor-34","classId":"witch-doctor"},{"id":"coa-witch-doctor-35","classId":"witch-doctor"},{"id":"coa-witch-doctor-36","classId":"witch-doctor"},{"id":"coa-felsworn-87","classId":"felsworn"},{"id":"coa-felsworn-37","classId":"felsworn"},{"id":"coa-felsworn-38","classId":"felsworn"},{"id":"coa-felsworn-18","classId":"felsworn"},{"id":"coa-witch-hunter-87","classId":"witch-hunter"},{"id":"coa-witch-hunter-39","classId":"witch-hunter"},{"id":"coa-witch-hunter-40","classId":"witch-hunter"},{"id":"coa-witch-hunter-94","classId":"witch-hunter"},{"id":"coa-witch-hunter-41","classId":"witch-hunter"},{"id":"coa-stormbringer-87","classId":"stormbringer"},{"id":"coa-stormbringer-42","classId":"stormbringer"},{"id":"coa-stormbringer-43","classId":"stormbringer"},{"id":"coa-stormbringer-44","classId":"stormbringer"},{"id":"coa-knight-of-xoroth-45","classId":"knight-of-xoroth"},{"id":"coa-knight-of-xoroth-46","classId":"knight-of-xoroth"},{"id":"coa-knight-of-xoroth-47","classId":"knight-of-xoroth"},{"id":"coa-knight-of-xoroth-87","classId":"knight-of-xoroth"},{"id":"coa-guardian-87","classId":"guardian"},{"id":"coa-guardian-7","classId":"guardian"},{"id":"coa-guardian-48","classId":"guardian"},{"id":"coa-guardian-49","classId":"guardian"},{"id":"coa-templar-87","classId":"templar"},{"id":"coa-templar-50","classId":"templar"},{"id":"coa-templar-16","classId":"templar"},{"id":"coa-templar-51","classId":"templar"},{"id":"coa-bloodmage-87","classId":"bloodmage"},{"id":"coa-bloodmage-26","classId":"bloodmage"},{"id":"coa-bloodmage-52","classId":"bloodmage"},{"id":"coa-bloodmage-53","classId":"bloodmage"},{"id":"coa-bloodmage-93","classId":"bloodmage"},{"id":"coa-ranger-87","classId":"ranger"},{"id":"coa-ranger-54","classId":"ranger"},{"id":"coa-ranger-55","classId":"ranger"},{"id":"coa-ranger-2","classId":"ranger"},{"id":"coa-chronomancer-87","classId":"chronomancer"},{"id":"coa-chronomancer-56","classId":"chronomancer"},{"id":"coa-chronomancer-58","classId":"chronomancer"},{"id":"coa-chronomancer-57","classId":"chronomancer"},{"id":"coa-necromancer-87","classId":"necromancer"},{"id":"coa-necromancer-59","classId":"necromancer"},{"id":"coa-necromancer-60","classId"Line truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"barbarian","trees":[{"id":"coa-barbarian-31","classId":"barbarian","name":"Brutality","icon":"/assets/ui/spells/novart_physical_ability_(47)_border.png","background":"","description":"Brutality nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-barbarian-32","classId":"barbarian","name":"Headhunting","icon":"/assets/ui/spells/inv_axe_1h_draenorcrafted_d_02_a_horde.png","background":"","description":"Headhunting nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-barbarian-33","classId":"barbarian","name":"Ancestry","icon":"/assets/ui/spells/ability_monk_elusiveale.png","background":"","description":"Ancestry nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-barbarian-87","classId":"barbarian","name":"Class","icon":"/assets/ui/spells/maiming_spear.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-5744","treeId":"coa-barbarian-31","index":5744,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/novart_physical_ability_(47)_border.png","maxRank":1,"name":"Decapitate","description":"Attempt to decapitate an injured enemy, dealing 220% Weapon Damage plus 27, and converting each extra point of Energy to deal additional damage (up to a maximum cost of 100 Energy). Only usable on enemies below 35% health.","rankDescriptions":["Attempt to decapitate an injured enemy, dealing 220% Weapon Damage plus 27, and converting each extra point of Energy to deal additional damage (up to a maximum cost of 100 Energy). Only usable on enemies below 35% health."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4001","treeId":"coa-barbarian-31","index":4001,"prerequisiteId":"coa-entry-29783","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29783","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/_orc_06.png","maxRank":1,"name":"Excessive Power","description":"Level 10 Passive Increases your maximum Energy by 100%.","rankDescriptions":["Level 10 Passive Increases your maximum Energy by 100%."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-6744","treeId":"coa-barbarian-31","index":6744,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/inv_archaeology_ogres_warmaul_chieftain.png","maxRank":1,"name":"Beheader","description":"Scoring a kill blow with Decapitate now refunds 100% of your maximum Energy.","rankDescriptions":["Scoring a kill blow with Decapitate now refunds 100% of your maximum Energy."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30792","treeId":"coa-barbarian-31","index":30792,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/achievement_boss_blackhand.png","maxRank":1,"name":"Reckless Movements","description":"Increases the damage of Ancestral Strike and Barbaric Whirl by 20%.","rankDescriptions":["Increases the damage of Ancestral Strike and Barbaric Whirl by 20%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29281","treeId":"coa-barbarian-31","index":29281,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/_d3leapattack.png","maxRank":1,"name":"Killing Spree","description":"Charge at an enemy, dealing 25 + 30% AP Physical damage. Can only be used within 6 seconds of scoring a killing blow or applying Born in Blood.","rankDescriptions":["Charge at an enemy, dealing 25 + 30% AP Physical damage. Can only be used within 6 seconds of scoring a killing blow or applying Born in Blood."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6742","treeId":"coa-barbarian-31","index":6742,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/ability_revendreth_rogue.png","maxRank":2,"name":"Pure Power","description":"Increases the damage of Smash by 30% and your expertise by 10.","rankDescriptions":["Increases the damage of Smash by 15% and your expertise by 5.","Increases the damage of Smash by 30% and your expertise by 10."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-9170","treeId":"coa-bLine truncated
{"schemaVersion":1,"classId":"barbarian","trees":[{"id":"coa-barbarian-87","classId":"barbarian","name":"Class","icon":"/assets/ui/spells/maiming_spear.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-barbarian-31","classId":"barbarian","name":"Brutality","icon":"/assets/ui/spells/novart_physical_ability_(47)_border.png","background":"","description":"Brutality nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-barbarian-32","classId":"barbarian","name":"Headhunting","icon":"/assets/ui/spells/inv_axe_1h_draenorcrafted_d_02_a_horde.png","background":"","description":"Headhunting nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-barbarian-33","classId":"barbarian","name":"Ancestry","icon":"/assets/ui/spells/ability_monk_elusiveale.png","background":"","description":"Ancestry nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-5744","treeId":"coa-barbarian-31","index":5744,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/novart_physical_ability_(47)_border.png","maxRank":1,"name":"Decapitate","description":"Attempt to decapitate an injured enemy, dealing 220% Weapon Damage plus 27, and converting each extra point of Energy to deal additional damage (up to a maximum cost of 100 Energy). Only usable on enemies below 35% health.","rankDescriptions":["Attempt to decapitate an injured enemy, dealing 220% Weapon Damage plus 27, and converting each extra point of Energy to deal additional damage (up to a maximum cost of 100 Energy). Only usable on enemies below 35% health."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4001","treeId":"coa-barbarian-31","index":4001,"prerequisiteId":"coa-entry-29783","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29783","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/_orc_06.png","maxRank":1,"name":"Excessive Power","description":"Level 10 Passive Increases your maximum Energy by 100%.","rankDescriptions":["Level 10 Passive Increases your maximum Energy by 100%."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-6744","treeId":"coa-barbarian-31","index":6744,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/inv_archaeology_ogres_warmaul_chieftain.png","maxRank":1,"name":"Beheader","description":"Scoring a kill blow with Decapitate now refunds 100% of your maximum Energy.","rankDescriptions":["Scoring a kill blow with Decapitate now refunds 100% of your maximum Energy."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30792","treeId":"coa-barbarian-31","index":30792,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/achievement_boss_blackhand.png","maxRank":1,"name":"Reckless Movements","description":"Increases the damage of Ancestral Strike and Barbaric Whirl by 20%.","rankDescriptions":["Increases the damage of Ancestral Strike and Barbaric Whirl by 20%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29281","treeId":"coa-barbarian-31","index":29281,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/_d3leapattack.png","maxRank":1,"name":"Killing Spree","description":"Charge at an enemy, dealing 25 + 30% AP Physical damage. Can only be used within 6 seconds of scoring a killing blow or applying Born in Blood.","rankDescriptions":["Charge at an enemy, dealing 25 + 30% AP Physical damage. Can only be used within 6 seconds of scoring a killing blow or applying Born in Blood."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6742","treeId":"coa-barbarian-31","index":6742,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/ability_revendreth_rogue.png","maxRank":2,"name":"Pure Power","description":"Increases the damage of Smash by 30% and your expertise by 10.","rankDescriptions":["Increases the damage of Smash by 15% and your expertise by 5.","Increases the damage of Smash by 30% and your expertise by 10."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-9170","treeId":"coa-bLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"bloodmage","trees":[{"id":"coa-bloodmage-26","classId":"bloodmage","name":"Sanguine","icon":"/assets/ui/spells/epic_rpg_icon_pack_blood_0002s_0000_foreground_border.png","background":"","description":"Sanguine nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-bloodmage-52","classId":"bloodmage","name":"Accursed","icon":"/assets/ui/spells/achievement_dungeon_hallsofattonement_echelon.png","background":"","description":"Accursed nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-bloodmage-53","classId":"bloodmage","name":"Eternal","icon":"/assets/ui/spells/5_clawstrike_border.png","background":"","description":"Eternal nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-bloodmage-93","classId":"bloodmage","name":"Fleshweaver","icon":"/assets/ui/spells/spell_animarevendreth_orb.png","background":"","description":"Fleshweaver nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-bloodmage-87","classId":"bloodmage","name":"Class","icon":"/assets/ui/spells/nhi_blooddrop_(2)_border.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31175","treeId":"coa-bloodmage-26","index":31175,"prerequisiteId":"coa-entry-4025","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4025","requiredRank":1},{"talentId":"coa-entry-29543","requiredRank":1}],"column":4,"row":1,"icon":"/assets/ui/spells/epic_rpg_icon_pack_blood_0002s_0000_foreground_border.png","maxRank":1,"name":"Transgression","description":"Transforms your Blood Curse into Transgression.Transgression (Cursed Form)Enter a unique Cursed Form for 30 seconds that does not disable the use of Mortal Form abilities and casts a free Vampiric Fang on your target. While active, direct spell damage triggers a Vampiric Feast, dealing 20% additional Shadow damage to enemies, healing you equal to 50% of the damage dealt.","rankDescriptions":["Transforms your Blood Curse into Transgression.Transgression (Cursed Form)Enter a unique Cursed Form for 30 seconds that does not disable the use of Mortal Form abilities and casts a free Vampiric Fang on your target. While active, direct spell damage triggers a Vampiric Feast, dealing 20% additional Shadow damage to enemies, healing you equal to 50% of the damage dealt."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4525","treeId":"coa-bloodmage-26","index":4525,"prerequisiteId":"coa-entry-4025","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4025","requiredRank":1},{"talentId":"coa-entry-29543","requiredRank":1}],"column":6,"row":1,"icon":"/assets/ui/spells/custom_t_bloodhaze_border.png","maxRank":1,"name":"Vampiric Fang","description":"Expends Thirst Stacks Steal 36 + 34% SP health from an enemy. Damage increased by 10% for each Thirst stack. Clears Insatiable and Thirst stacks.","rankDescriptions":["Expends Thirst Stacks Steal 36 + 34% SP health from an enemy. Damage increased by 10% for each Thirst stack. Clears Insatiable and Thirst stacks."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4025","treeId":"coa-bloodmage-26","index":4025,"prerequisiteId":"coa-entry-29543","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29543","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/epic_rpg_icon_pack_blood_0003s_0000_hand_border.png","maxRank":1,"name":"Thirst","description":"Level 10 Passive Spells that cost health now grant Thirst. Reaching 10 stacks makes you Insatiable, reducing your damage dealt by -30% every 3 sec until Thirst ends. ThirstGenerates 5 Rage and then increases the health costs of your spells by 5% and increases their damage by 3%. Stacks 10 times.","rankDescriptions":["Level 10 Passive Spells that cost health now grant Thirst. Reaching 10 stacks makes you Insatiable, reducing your damage dealt by -30% every 3 sec until Thirst ends. ThirstGenerates 5 Rage and then increases the health costs of your spells by 5% and increases their damage by 3%. Stacks 10 times."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-30360","treeId":"coa-bloodmage-26","index":30360,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/ability_deathknight_necroticaura.png","maxRank":1,"name":"Valanar's Vengeance","description":"Requires Mortal Form Launch a powerful blood bolt at an enemy, dealing 188 + 127.75% SP Shadow damage. Each stack of Thirst reduces the cast time of this ability and increases its damage.","rankDescriptions":["Requires Mortal Form Launch a powerful blood bolt at an enemy, dealing 188 + 127.75%Line truncated
{"schemaVersion":1,"classId":"bloodmage","trees":[{"id":"coa-bloodmage-87","classId":"bloodmage","name":"Class","icon":"/assets/ui/spells/nhi_blooddrop_(2)_border.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-bloodmage-26","classId":"bloodmage","name":"Sanguine","icon":"/assets/ui/spells/epic_rpg_icon_pack_blood_0002s_0000_foreground_border.png","background":"","description":"Sanguine nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-bloodmage-52","classId":"bloodmage","name":"Accursed","icon":"/assets/ui/spells/achievement_dungeon_hallsofattonement_echelon.png","background":"","description":"Accursed nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-bloodmage-53","classId":"bloodmage","name":"Eternal","icon":"/assets/ui/spells/5_clawstrike_border.png","background":"","description":"Eternal nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-bloodmage-93","classId":"bloodmage","name":"Fleshweaver","icon":"/assets/ui/spells/spell_animarevendreth_orb.png","background":"","description":"Fleshweaver nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31175","treeId":"coa-bloodmage-26","index":31175,"prerequisiteId":"coa-entry-4025","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4025","requiredRank":1},{"talentId":"coa-entry-29543","requiredRank":1}],"column":4,"row":1,"icon":"/assets/ui/spells/epic_rpg_icon_pack_blood_0002s_0000_foreground_border.png","maxRank":1,"name":"Transgression","description":"Transforms your Blood Curse into Transgression.Transgression (Cursed Form)Enter a unique Cursed Form for 15 seconds that does not disable the use of Mortal Form abilities. While active, direct spell damage triggers a Vampiric Feast, dealing 20% additional Shadow damage to enemies, healing you equal to 50% of the damage dealt.","rankDescriptions":["Transforms your Blood Curse into Transgression.Transgression (Cursed Form)Enter a unique Cursed Form for 15 seconds that does not disable the use of Mortal Form abilities. While active, direct spell damage triggers a Vampiric Feast, dealing 20% additional Shadow damage to enemies, healing you equal to 50% of the damage dealt."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4525","treeId":"coa-bloodmage-26","index":4525,"prerequisiteId":"coa-entry-4025","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4025","requiredRank":1},{"talentId":"coa-entry-29543","requiredRank":1}],"column":6,"row":1,"icon":"/assets/ui/spells/custom_t_bloodhaze_border.png","maxRank":1,"name":"Vampiric Fang","description":"Expends Thirst Stacks Steal 36 + 34% SP health from an enemy. Damage increased by 10% for each Thirst stack. Clears Insatiable and Thirst stacks.","rankDescriptions":["Expends Thirst Stacks Steal 36 + 34% SP health from an enemy. Damage increased by 10% for each Thirst stack. Clears Insatiable and Thirst stacks."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4025","treeId":"coa-bloodmage-26","index":4025,"prerequisiteId":"coa-entry-29543","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29543","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/epic_rpg_icon_pack_blood_0003s_0000_hand_border.png","maxRank":1,"name":"Thirst","description":"Level 10 Passive Spells that cost health now grant Thirst. Reaching 10 stacks makes you Insatiable, reducing your damage dealt by -30% every 3 sec until Thirst ends. ThirstGenerates 5 Rage and then increases the health costs of your spells by 5% and increases their damage by 3%. Stacks 10 times.","rankDescriptions":["Level 10 Passive Spells that cost health now grant Thirst. Reaching 10 stacks makes you Insatiable, reducing your damage dealt by -30% every 3 sec until Thirst ends. ThirstGenerates 5 Rage and then increases the health costs of your spells by 5% and increases their damage by 3%. Stacks 10 times."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-30360","treeId":"coa-bloodmage-26","index":30360,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/ability_deathknight_necroticaura.png","maxRank":1,"name":"Valanar's Vengeance","description":"Requires Mortal Form Launch a powerful blood bolt at an enemy, dealing 188 + 127.75% SP Shadow damage. Each stack of Thirst reduces the cast time of this ability and increases its damage.","rankDescriptions":["Requires Mortal Form Launch a powerful blood bolt at an enemy, dealing 188 + 127.75% SP Shadow damage. Each stack of Thirst reduces the cast time of this ability and increases Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"chronomancer","trees":[{"id":"coa-chronomancer-56","classId":"chronomancer","name":"Infinite","icon":"/assets/ui/spells/spell_animamaw_beam.png","background":"","description":"Infinite nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-chronomancer-57","classId":"chronomancer","name":"Artificer","icon":"/assets/ui/spells/shatterecho.png","background":"","description":"Artificer nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-chronomancer-87","classId":"chronomancer","name":"Class","icon":"/assets/ui/spells/spell_holy_healingfocus.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-chronomancer-58","classId":"chronomancer","name":"Time","icon":"/assets/ui/spells/inv_staff_2h_nazmirraid_d_01.png","background":"","description":"Time nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-3997","treeId":"coa-chronomancer-56","index":3997,"prerequisiteId":"coa-entry-4031","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4031","requiredRank":1},{"talentId":"coa-entry-30249","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/spell_animamaw_beam.png","maxRank":1,"name":"Timerend","description":"Transforms your Wand of Time into Timerend.TimerendRend the fabric of time, dealing 36 Chromatic Damage over 6 seconds.","rankDescriptions":["Transforms your Wand of Time into Timerend.TimerendRend the fabric of time, dealing 36 Chromatic Damage over 6 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4031","treeId":"coa-chronomancer-56","index":4031,"prerequisiteId":"coa-entry-30249","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30249","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/achievement_boss_infinitecorruptor.png","maxRank":1,"name":"Infinite Power","description":"Level 10 Passive Casting damaging spells now reduces your damaging spell cooldowns by 10% of their remaining cooldown.","rankDescriptions":["Level 10 Passive Casting damaging spells now reduces your damaging spell cooldowns by 10% of their remaining cooldown."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-7200","treeId":"coa-chronomancer-56","index":7200,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/nhi_timewarp_border.png","maxRank":1,"name":"Melt Reality","description":"Melt the target's reality, dealing 1638 Chromatic Damage over 36 seconds. While active, periodic damage dealt to the target is replicated for 20% of the value to all enemies near them.","rankDescriptions":["Melt the target's reality, dealing 1638 Chromatic Damage over 36 seconds. While active, periodic damage dealt to the target is replicated for 20% of the value to all enemies near them."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6156","treeId":"coa-chronomancer-56","index":6156,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/inv_ingot_titansteel_dark.png","maxRank":2,"name":"Anomaly Spikes","description":"Periodic damage dealt now has a 15% chance to launch an Anomaly Spike at your target. Anomaly SpikeDeals cond(gt(SPA, SPS), 161*1+SPA*0.25, 161*1+SPS*0.25) Chromatic Damage.","rankDescriptions":["Periodic damage dealt now has a 8% chance to launch an Anomaly Spike at your target. Anomaly SpikeDeals cond(gt(SPA, SPS), 161*1+SPA*0.25, 161*1+SPS*0.25) Chromatic Damage.","Periodic damage dealt now has a 15% chance to launch an Anomaly Spike at your target. Anomaly SpikeDeals cond(gt(SPA, SPS), 161*1+SPA*0.25, 161*1+SPS*0.25) Chromatic Damage."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-31139","treeId":"coa-chronomancer-56","index":31139,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/spell_shadow_brainwash.png","maxRank":1,"name":"Mind Melt","description":"Damage dealt by Melt Reality now also reduces the target's primary attributes by -3% for 15 sec, stacking 5 times.","rankDescriptions":["Damage dealt by Melt Reality now also reduces the target's primary attributes by -3% for 15 sec, stacking 5 times."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-9185","treeId":"coa-chronomancer-56","index":9185,"prerequisiteId":null,"prerequisiteRank":nuLine truncated
{"schemaVersion":1,"classId":"chronomancer","trees":[{"id":"coa-chronomancer-87","classId":"chronomancer","name":"Class","icon":"/assets/ui/spells/spell_holy_healingfocus.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-chronomancer-56","classId":"chronomancer","name":"Infinite","icon":"/assets/ui/spells/spell_animamaw_beam.png","background":"","description":"Infinite nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-chronomancer-58","classId":"chronomancer","name":"Time","icon":"/assets/ui/spells/inv_staff_2h_nazmirraid_d_01.png","background":"","description":"Time nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-chronomancer-57","classId":"chronomancer","name":"Artificer","icon":"/assets/ui/spells/shatterecho.png","background":"","description":"Artificer nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-3997","treeId":"coa-chronomancer-56","index":3997,"prerequisiteId":"coa-entry-4031","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4031","requiredRank":1},{"talentId":"coa-entry-30249","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/spell_animamaw_beam.png","maxRank":1,"name":"Timerend","description":"Transforms your Wand of Time into Timerend.TimerendRend the fabric of time, dealing 36 Chromatic Damage over 6 seconds.","rankDescriptions":["Transforms your Wand of Time into Timerend.TimerendRend the fabric of time, dealing 36 Chromatic Damage over 6 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4031","treeId":"coa-chronomancer-56","index":4031,"prerequisiteId":"coa-entry-30249","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30249","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/achievement_boss_infinitecorruptor.png","maxRank":1,"name":"Infinite Power","description":"Level 10 Passive Casting damaging spells now reduces your damaging spell cooldowns by 10% of their remaining cooldown.","rankDescriptions":["Level 10 Passive Casting damaging spells now reduces your damaging spell cooldowns by 10% of their remaining cooldown."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-7200","treeId":"coa-chronomancer-56","index":7200,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/nhi_timewarp_border.png","maxRank":1,"name":"Melt Reality","description":"Melt the target's reality, dealing 1638 Chromatic Damage over 36 seconds. While active, periodic damage dealt to the target is replicated for 20% of the value to all enemies near them.","rankDescriptions":["Melt the target's reality, dealing 1638 Chromatic Damage over 36 seconds. While active, periodic damage dealt to the target is replicated for 20% of the value to all enemies near them."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6156","treeId":"coa-chronomancer-56","index":6156,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/inv_ingot_titansteel_dark.png","maxRank":2,"name":"Anomaly Spikes","description":"Periodic damage dealt now has a 15% chance to launch an Anomaly Spike at your target. Anomaly SpikeDeals cond(gt(SPA, SPS), 161*1+SPA*0.25, 161*1+SPS*0.25) Chromatic Damage.","rankDescriptions":["Periodic damage dealt now has a 8% chance to launch an Anomaly Spike at your target. Anomaly SpikeDeals cond(gt(SPA, SPS), 161*1+SPA*0.25, 161*1+SPS*0.25) Chromatic Damage.","Periodic damage dealt now has a 15% chance to launch an Anomaly Spike at your target. Anomaly SpikeDeals cond(gt(SPA, SPS), 161*1+SPA*0.25, 161*1+SPS*0.25) Chromatic Damage."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-31139","treeId":"coa-chronomancer-56","index":31139,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/spell_shadow_brainwash.png","maxRank":1,"name":"Mind Melt","description":"Damage dealt by Melt Reality now also reduces the target's primary attributes by -3% for 15 sec, stacking 5 times.","rankDescriptions":["Damage dealt by Melt Reality now also reduces the target's primary attributes by -3% for 15 sec, stacking 5 times."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-9185","treeId":"coa-chronomancer-56","index":9185,"prerequisiteId":null,"prerequisiteRank":nuLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"cultist","trees":[{"id":"coa-cultist-65","classId":"cultist","name":"Corruption","icon":"/assets/ui/spells/spell_shadow_unstableaffliction_3_purple.png","background":"","description":"Corruption nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-cultist-64","classId":"cultist","name":"Godblade","icon":"/assets/ui/spells/inv_chest_armor_voidelf_d_01.png","background":"","description":"Godblade nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-cultist-66","classId":"cultist","name":"Heretic","icon":"/assets/ui/spells/inv_mace_1h_orgrimmarraid_d_03.png","background":"","description":"Heretic nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-cultist-88","classId":"cultist","name":"Dreadnought","icon":"/assets/ui/spells/inv_shield_1h_artifactstormfist_d_05.png","background":"","description":"Dreadnought nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-cultist-87","classId":"cultist","name":"Class","icon":"/assets/ui/spells/_d3energyarmor.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31189","treeId":"coa-cultist-64","index":31189,"prerequisiteId":"coa-entry-4040","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4040","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/inv_chest_armor_voidelf_d_01.png","maxRank":1,"name":"Rift","description":"Apply a dark boon to yourself for 15 seconds, causing your next Hammer of Twilight to deal an additional 80% of its damage dealt as Shadow damage. Creates a rift that absorbs the next 690 + 150% AP healing taken by enemies that step inside and reduces their periodic healing received by -50% for 10 seconds while inside.","rankDescriptions":["Apply a dark boon to yourself for 15 seconds, causing your next Hammer of Twilight to deal an additional 80% of its damage dealt as Shadow damage. Creates a rift that absorbs the next 690 + 150% AP healing taken by enemies that step inside and reduces their periodic healing received by -50% for 10 seconds while inside."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4040","treeId":"coa-cultist-64","index":4040,"prerequisiteId":"coa-entry-7608","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-7608","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/nzothicon.png","maxRank":1,"name":"Obliteration","description":"Level 10 Passive Your Gaze of C'Thun now gains an additional 15 base damage and healing.","rankDescriptions":["Level 10 Passive Your Gaze of C'Thun now gains an additional 15 base damage and healing."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-33894","treeId":"coa-cultist-64","index":33894,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/spell_shadow_chilltouch.png","maxRank":1,"name":"Hand of N'Zoth","description":"Your Hammer of Twilight, Entropic Slam, and Gaze of C'Thun now refreshes a charge of Blade of the Empire.","rankDescriptions":["Your Hammer of Twilight, Entropic Slam, and Gaze of C'Thun now refreshes a charge of Blade of the Empire."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4810","treeId":"coa-cultist-64","index":4810,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/inv_sword_02.png","maxRank":3,"name":"Voidforged Edge","description":"Your auto attacks now deal an additional 30% of the damage dealt as Shadow damage.","rankDescriptions":["Your auto attacks now deal an additional 10% of the damage dealt as Shadow damage.","Your auto attacks now deal an additional 20% of the damage dealt as Shadow damage.","Your auto attacks now deal an additional 30% of the damage dealt as Shadow damage."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6543","treeId":"coa-cultist-64","index":6543,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/inv_sword_1h_draenei_c_03.png","maxRank":2,"name":"Abyssal Edge","description":"Increases the critical strike chance of Blade of the Empire by 4% and reduces its mana cost by -50%.","rankDescriptions":["Increases the critical strike chance of Blade of the Empire by 2% and reduces its mana cost by -25%.","Increases the critical strike chance of Blade of the Empire by 4% and reduces its mana cost by -50%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":Line truncated
{"schemaVersion":1,"classId":"cultist","trees":[{"id":"coa-cultist-87","classId":"cultist","name":"Class","icon":"/assets/ui/spells/_d3energyarmor.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-cultist-64","classId":"cultist","name":"Godblade","icon":"/assets/ui/spells/inv_chest_armor_voidelf_d_01.png","background":"","description":"Godblade nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-cultist-65","classId":"cultist","name":"Corruption","icon":"/assets/ui/spells/spell_shadow_unstableaffliction_3_purple.png","background":"","description":"Corruption nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-cultist-88","classId":"cultist","name":"Dreadnought","icon":"/assets/ui/spells/inv_shield_1h_artifactstormfist_d_05.png","background":"","description":"Dreadnought nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-cultist-66","classId":"cultist","name":"Heretic","icon":"/assets/ui/spells/inv_mace_1h_orgrimmarraid_d_03.png","background":"","description":"Heretic nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31189","treeId":"coa-cultist-64","index":31189,"prerequisiteId":"coa-entry-4040","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4040","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/inv_chest_armor_voidelf_d_01.png","maxRank":1,"name":"Rift","description":"Apply a dark boon to yourself for 15 seconds, causing your next Hammer of Twilight to deal an additional 80% of its damage dealt as Shadow damage. Creates a rift that absorbs the next 690 + 150% AP healing taken by enemies that step inside and reduces their periodic healing received by -50% for 10 seconds while inside.","rankDescriptions":["Apply a dark boon to yourself for 15 seconds, causing your next Hammer of Twilight to deal an additional 80% of its damage dealt as Shadow damage. Creates a rift that absorbs the next 690 + 150% AP healing taken by enemies that step inside and reduces their periodic healing received by -50% for 10 seconds while inside."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4040","treeId":"coa-cultist-64","index":4040,"prerequisiteId":"coa-entry-7608","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-7608","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/nzothicon.png","maxRank":1,"name":"Obliteration","description":"Level 10 Passive Your Gaze of C'Thun now gains an additional 15 base damage and healing.","rankDescriptions":["Level 10 Passive Your Gaze of C'Thun now gains an additional 15 base damage and healing."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-33894","treeId":"coa-cultist-64","index":33894,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/spell_shadow_chilltouch.png","maxRank":1,"name":"Hand of N'Zoth","description":"Your Hammer of Twilight, Entropic Slam, and Gaze of C'Thun now refreshes a charge of Blade of the Empire.","rankDescriptions":["Your Hammer of Twilight, Entropic Slam, and Gaze of C'Thun now refreshes a charge of Blade of the Empire."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4810","treeId":"coa-cultist-64","index":4810,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/inv_sword_02.png","maxRank":3,"name":"Voidforged Edge","description":"Your auto attacks now deal an additional 30% of the damage dealt as Shadow damage.","rankDescriptions":["Your auto attacks now deal an additional 10% of the damage dealt as Shadow damage.","Your auto attacks now deal an additional 20% of the damage dealt as Shadow damage.","Your auto attacks now deal an additional 30% of the damage dealt as Shadow damage."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6543","treeId":"coa-cultist-64","index":6543,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/inv_sword_1h_draenei_c_03.png","maxRank":2,"name":"Abyssal Edge","description":"Increases the critical strike chance of Blade of the Empire by 4% and reduces its mana cost by -50%.","rankDescriptions":["Increases the critical strike chance of Blade of the Empire by 2% and reduces its mana cost by -25%.","Increases the critical strike chance of Blade of the Empire by 4% and reduces its mana cost by -50%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":Line truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"felsworn","trees":[{"id":"coa-felsworn-37","classId":"felsworn","name":"Slayer","icon":"/assets/ui/spells/ability_creature_felsunder.png","background":"","description":"Slayer nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-felsworn-38","classId":"felsworn","name":"Infernal","icon":"/assets/ui/spells/inv_infernalmountgreen.png","background":"","description":"Infernal nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-felsworn-18","classId":"felsworn","name":"Tyrant","icon":"/assets/ui/spells/ability_demonhunter_infernalstrike2.png","background":"","description":"Tyrant nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-felsworn-87","classId":"felsworn","name":"Class","icon":"/assets/ui/spells/ability_boss_lordanthricystgreen.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31159","treeId":"coa-felsworn-18","index":31159,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/ability_demonhunter_infernalstrike2.png","maxRank":1,"name":"Carve","description":"Consumes 2 Felfury Charge up a powerful attack over 2.5 seconds. Upon ending the channel, slash in front of you, dealing increased Weapon Damage with both weapons based on how long you channel, dealing less damage with each target struck. Inner Demon: Reduces affected enemies melee and ranged haste by -20% for 8 seconds.","rankDescriptions":["Consumes 2 Felfury Charge up a powerful attack over 2.5 seconds. Upon ending the channel, slash in front of you, dealing increased Weapon Damage with both weapons based on how long you channel, dealing less damage with each target struck. Inner Demon: Reduces affected enemies melee and ranged haste by -20% for 8 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4009","treeId":"coa-felsworn-18","index":4009,"prerequisiteId":"coa-entry-30554","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30554","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/ability_demonhunter_demonictrample.png","maxRank":1,"name":"Burning Commander","description":"Level 10 Passive Allows you to wield a Two-Handed Axe, Mace, Polearm or Sword in each hand and grants you additional Armor and magic resistance based on your attack power.","rankDescriptions":["Level 10 Passive Allows you to wield a Two-Handed Axe, Mace, Polearm or Sword in each hand and grants you additional Armor and magic resistance based on your attack power."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-29845","treeId":"coa-felsworn-18","index":29845,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/ability_demonhunter_infernalchains.png","maxRank":1,"name":"Demonic Will","description":"Generates 1 Felfury Strengthen your will, reducing Physical damage taken by -30% for 10 seconds. While active, direct damaging abilities heal you for 3% of your maximum health. Can only occur once every 0.5 sec.","rankDescriptions":["Generates 1 Felfury Strengthen your will, reducing Physical damage taken by -30% for 10 seconds. While active, direct damaging abilities heal you for 3% of your maximum health. Can only occur once every 0.5 sec."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-11121","treeId":"coa-felsworn-18","index":11121,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/mannoroth.png","maxRank":1,"name":"Annihilan Rituals","description":"Fully channeling Carve now refunds 1 Felfury.","rankDescriptions":["Fully channeling Carve now refunds 1 Felfury."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30567","treeId":"coa-felsworn-18","index":30567,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/inv_polearm_2h_fellord.png","maxRank":1,"name":"Quick Carving","description":"Carve now channels 1 sec faster.","rankDescriptions":["Carve now channels 1 sec faster."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6338","treeId":"coa-felsworn-18","index":6338,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/inv_felhound4_custom.png","maxRank":2,"name":"Nether Disciple","dLine truncated
{"schemaVersion":1,"classId":"felsworn","trees":[{"id":"coa-felsworn-87","classId":"felsworn","name":"Class","icon":"/assets/ui/spells/ability_boss_lordanthricystgreen.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-felsworn-37","classId":"felsworn","name":"Slayer","icon":"/assets/ui/spells/ability_creature_felsunder.png","background":"","description":"Slayer nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-felsworn-38","classId":"felsworn","name":"Infernal","icon":"/assets/ui/spells/inv_infernalmountgreen.png","background":"","description":"Infernal nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-felsworn-18","classId":"felsworn","name":"Tyrant","icon":"/assets/ui/spells/ability_demonhunter_infernalstrike2.png","background":"","description":"Tyrant nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31159","treeId":"coa-felsworn-18","index":31159,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/ability_demonhunter_infernalstrike2.png","maxRank":1,"name":"Carve","description":"Consumes 2 Felfury Charge up a powerful attack over 2.5 seconds. Upon ending the channel, slash in front of you, dealing increased Weapon Damage with both weapons based on how long you channel, dealing less damage with each target struck. Inner Demon: Reduces affected enemies melee and ranged haste by -20% for 8 seconds.","rankDescriptions":["Consumes 2 Felfury Charge up a powerful attack over 2.5 seconds. Upon ending the channel, slash in front of you, dealing increased Weapon Damage with both weapons based on how long you channel, dealing less damage with each target struck. Inner Demon: Reduces affected enemies melee and ranged haste by -20% for 8 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4009","treeId":"coa-felsworn-18","index":4009,"prerequisiteId":"coa-entry-30554","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30554","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/ability_demonhunter_demonictrample.png","maxRank":1,"name":"Burning Commander","description":"Level 10 Passive Allows you to wield a Two-Handed Axe, Mace, Polearm or Sword in each hand and grants you additional Armor and magic resistance based on your attack power.","rankDescriptions":["Level 10 Passive Allows you to wield a Two-Handed Axe, Mace, Polearm or Sword in each hand and grants you additional Armor and magic resistance based on your attack power."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-29845","treeId":"coa-felsworn-18","index":29845,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/ability_demonhunter_infernalchains.png","maxRank":1,"name":"Demonic Will","description":"Generates 1 Felfury Strengthen your will, reducing Physical damage taken by -30% for 10 seconds. While active, direct damaging abilities heal you for 3% of your maximum health. Can only occur once every 0.5 sec.","rankDescriptions":["Generates 1 Felfury Strengthen your will, reducing Physical damage taken by -30% for 10 seconds. While active, direct damaging abilities heal you for 3% of your maximum health. Can only occur once every 0.5 sec."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-11121","treeId":"coa-felsworn-18","index":11121,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/mannoroth.png","maxRank":1,"name":"Annihilan Rituals","description":"Fully channeling Carve now refunds 1 Felfury.","rankDescriptions":["Fully channeling Carve now refunds 1 Felfury."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30567","treeId":"coa-felsworn-18","index":30567,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/inv_polearm_2h_fellord.png","maxRank":1,"name":"Quick Carving","description":"Carve now channels 1 sec faster.","rankDescriptions":["Carve now channels 1 sec faster."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6338","treeId":"coa-felsworn-18","index":6338,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/inv_felhound4_custom.png","maxRank":2,"name":"Nether Disciple","dLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"guardian","trees":[{"id":"coa-guardian-7","classId":"guardian","name":"Vanguard","icon":"/assets/ui/spells/spell_paladin_hammerofwrath.png","background":"","description":"Vanguard nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-guardian-48","classId":"guardian","name":"Inspiration","icon":"/assets/ui/spells/ability_maldraxxus_warriorplantbanner.png","background":"","description":"Inspiration nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-guardian-49","classId":"guardian","name":"Gladiator","icon":"/assets/ui/spells/custom_warriorskill_02_border.png","background":"","description":"Gladiator nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-guardian-87","classId":"guardian","name":"Class","icon":"/assets/ui/spells/ability_ensnare.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31169","treeId":"coa-guardian-7","index":31169,"prerequisiteId":"coa-entry-4019","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4019","requiredRank":1},{"talentId":"coa-entry-30057","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/spell_paladin_hammerofwrath.png","maxRank":1,"name":"Heavy Blow","description":"Smash an enemy and enemies behind them in a line, dealing 23 + 37% AP High Threat Physical damage, scaling with your defense rating.","rankDescriptions":["Smash an enemy and enemies behind them in a line, dealing 23 + 37% AP High Threat Physical damage, scaling with your defense rating."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4019","treeId":"coa-guardian-7","index":4019,"prerequisiteId":"coa-entry-30057","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30057","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/_human_06.png","maxRank":1,"name":"Footman's Calling","description":"Level 10 Passive Your damage taken is reduced by -10% while Tower Formation or Line Formation is active. In addition, your threat generated from Physical Damage dealt is increased significantly while Tower Formation or Line Formation is active.","rankDescriptions":["Level 10 Passive Your damage taken is reduced by -10% while Tower Formation or Line Formation is active. In addition, your threat generated from Physical Damage dealt is increased significantly while Tower Formation or Line Formation is active."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":10,"isPassive":true},{"id":"coa-entry-30056","treeId":"coa-guardian-7","index":30056,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/garrison_building_armory.png","maxRank":3,"name":"Iron Guardian","description":"Increases your Stamina by 15% and critical strike chance by 6%.","rankDescriptions":["Increases your Stamina by 5% and critical strike chance by 2%.","Increases your Stamina by 10% and critical strike chance by 4%.","Increases your Stamina by 15% and critical strike chance by 6%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30802","treeId":"coa-guardian-7","index":30802,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/ability_warrior_vigilance.png","maxRank":1,"name":"Heavy Expert","description":"Increases your chance to parry and dodge by 4% and increase your Armor contribution from mail and plate items by 20%.","rankDescriptions":["Increases your chance to parry and dodge by 4% and increase your Armor contribution from mail and plate items by 20%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-31319","treeId":"coa-guardian-7","index":31319,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/inv_shoulder_plate_raidpaladin_s_01.png","maxRank":1,"name":"With Honor","description":"Reduces the cooldown of Ram by -4 sec and its critical strike chance by 25%.","rankDescriptions":["Reduces the cooldown of Ram by -4 sec and its critical strike chance by 25%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4718","treeId":"coa-guardian-7","index":4718,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":11,"row":3,"icon":"/assets/ui/spells/inv_shield_06.png","maxRank":1,"name":"Bulwark","description":"Level 20 Passive Increases your block value by 25% and your hit rating by 5% oLine truncated
{"schemaVersion":1,"classId":"guardian","trees":[{"id":"coa-guardian-87","classId":"guardian","name":"Class","icon":"/assets/ui/spells/ability_ensnare.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-guardian-7","classId":"guardian","name":"Vanguard","icon":"/assets/ui/spells/spell_paladin_hammerofwrath.png","background":"","description":"Vanguard nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-guardian-48","classId":"guardian","name":"Inspiration","icon":"/assets/ui/spells/ability_maldraxxus_warriorplantbanner.png","background":"","description":"Inspiration nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-guardian-49","classId":"guardian","name":"Gladiator","icon":"/assets/ui/spells/custom_warriorskill_02_border.png","background":"","description":"Gladiator nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31169","treeId":"coa-guardian-7","index":31169,"prerequisiteId":"coa-entry-4019","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4019","requiredRank":1},{"talentId":"coa-entry-30057","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/spell_paladin_hammerofwrath.png","maxRank":1,"name":"Heavy Blow","description":"Smash an enemy and enemies behind them in a line, dealing 23 + 37% AP High Threat Physical damage, scaling with your defense rating.","rankDescriptions":["Smash an enemy and enemies behind them in a line, dealing 23 + 37% AP High Threat Physical damage, scaling with your defense rating."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4019","treeId":"coa-guardian-7","index":4019,"prerequisiteId":"coa-entry-30057","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30057","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/_human_06.png","maxRank":1,"name":"Footman's Calling","description":"Level 10 Passive Your damage taken is reduced by -10% while Tower Formation or Line Formation is active. In addition, your threat generated from Physical Damage dealt is increased significantly while Tower Formation or Line Formation is active.","rankDescriptions":["Level 10 Passive Your damage taken is reduced by -10% while Tower Formation or Line Formation is active. In addition, your threat generated from Physical Damage dealt is increased significantly while Tower Formation or Line Formation is active."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":10,"isPassive":true},{"id":"coa-entry-30056","treeId":"coa-guardian-7","index":30056,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/garrison_building_armory.png","maxRank":3,"name":"Iron Guardian","description":"Increases your Stamina by 15% and critical strike chance by 6%.","rankDescriptions":["Increases your Stamina by 5% and critical strike chance by 2%.","Increases your Stamina by 10% and critical strike chance by 4%.","Increases your Stamina by 15% and critical strike chance by 6%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30802","treeId":"coa-guardian-7","index":30802,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/ability_warrior_vigilance.png","maxRank":1,"name":"Heavy Expert","description":"Increases your chance to parry and dodge by 4% and increase your Armor contribution from mail and plate items by 20%.","rankDescriptions":["Increases your chance to parry and dodge by 4% and increase your Armor contribution from mail and plate items by 20%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-31319","treeId":"coa-guardian-7","index":31319,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/inv_shoulder_plate_raidpaladin_s_01.png","maxRank":1,"name":"With Honor","description":"Reduces the cooldown of Ram by -4 sec and its critical strike chance by 25%.","rankDescriptions":["Reduces the cooldown of Ram by -4 sec and its critical strike chance by 25%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4718","treeId":"coa-guardian-7","index":4718,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":11,"row":3,"icon":"/assets/ui/spells/inv_shield_06.png","maxRank":1,"name":"Bulwark","description":"Level 20 Passive Increases your block value by 25% and your hit rating by 5% oLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"knight-of-xoroth","trees":[{"id":"coa-knight-of-xoroth-46","classId":"knight-of-xoroth","name":"Hellfire","icon":"/assets/ui/spells/inv_firecatmount.png","background":"","description":"Hellfire nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-knight-of-xoroth-45","classId":"knight-of-xoroth","name":"War","icon":"/assets/ui/spells/inv_mace_2h_pvpcataclysms3_c_01.png","background":"","description":"War nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-knight-of-xoroth-47","classId":"knight-of-xoroth","name":"Defiance","icon":"/assets/ui/spells/inv_shield_draenorraid_d_02.png","background":"","description":"Defiance nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-knight-of-xoroth-87","classId":"knight-of-xoroth","name":"Class","icon":"/assets/ui/spells/_enslavespell_fire.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-12166","treeId":"coa-knight-of-xoroth-45","index":12166,"prerequisiteId":"coa-entry-4016","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4016","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/inv_mace_2h_pvpcataclysms3_c_01.png","maxRank":1,"name":"Warbringer","description":"Transforms your Flames of Xoroth into Warbringer.WarbringerSlam the ground, dealing 65% Weapon Damage plus 2 to nearby enemies, reducing the effectiveness of any healing by -50% for 10 seconds. Deals increased damage per Demonfire consumed.","rankDescriptions":["Transforms your Flames of Xoroth into Warbringer.WarbringerSlam the ground, dealing 65% Weapon Damage plus 2 to nearby enemies, reducing the effectiveness of any healing by -50% for 10 seconds. Deals increased damage per Demonfire consumed."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4016","treeId":"coa-knight-of-xoroth-45","index":4016,"prerequisiteId":"coa-entry-30668","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30668","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/warrior_skullbanner.png","maxRank":1,"name":"Crusher","description":"Level 10 Passive Doubles the base Weapon Damage dealt by Infernal Strike and increases all critical damage dealt by 25%.","rankDescriptions":["Level 10 Passive Doubles the base Weapon Damage dealt by Infernal Strike and increases all critical damage dealt by 25%."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-31166","treeId":"coa-knight-of-xoroth-45","index":31166,"prerequisiteId":"coa-entry-4016","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4016","requiredRank":1},{"talentId":"coa-entry-30668","requiredRank":1}],"column":5,"row":2,"icon":"/assets/ui/spells/inv_sword_140.png","maxRank":1,"name":"Gore","description":"2 Charges, 8 sec recharge Generates 1 Demonfire Quickly gore an enemy, dealing 100% Weapon Damage plus 15.","rankDescriptions":["2 Charges, 8 sec recharge Generates 1 Demonfire Quickly gore an enemy, dealing 100% Weapon Damage plus 15."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34127","treeId":"coa-knight-of-xoroth-45","index":34127,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/ability_skeer_bloodletting.png","maxRank":3,"name":"Mutilation","description":"Increases the damage of Gore and Sever by 30%.","rankDescriptions":["Increases the damage of Gore and Sever by 10%.","Increases the damage of Gore and Sever by 20%.","Increases the damage of Gore and Sever by 30%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6936","treeId":"coa-knight-of-xoroth-45","index":6936,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/sha_ability_warrior_bloodnova_nightmare.png","maxRank":1,"name":"Gored","description":"Damage dealt by Gore and Meatsaw now increases your target's damage taken from Skulltaker and Warbringer by 15% for 10 seconds, stacking 2 times.","rankDescriptions":["Damage dealt by Gore and Meatsaw now increases your target's damage taken from Skulltaker and Warbringer by 15% for 10 seconds, stacking 2 times."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7881","treeId":"coa-knight-of-xoroth-45","index":7881,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spellLine truncated
{"schemaVersion":1,"classId":"knight-of-xoroth","trees":[{"id":"coa-knight-of-xoroth-45","classId":"knight-of-xoroth","name":"War","icon":"/assets/ui/spells/inv_mace_2h_pvpcataclysms3_c_01.png","background":"","description":"War nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-knight-of-xoroth-46","classId":"knight-of-xoroth","name":"Hellfire","icon":"/assets/ui/spells/inv_firecatmount.png","background":"","description":"Hellfire nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-knight-of-xoroth-47","classId":"knight-of-xoroth","name":"Defiance","icon":"/assets/ui/spells/inv_shield_draenorraid_d_02.png","background":"","description":"Defiance nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-knight-of-xoroth-87","classId":"knight-of-xoroth","name":"Class","icon":"/assets/ui/spells/_enslavespell_fire.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-12166","treeId":"coa-knight-of-xoroth-45","index":12166,"prerequisiteId":"coa-entry-4016","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4016","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/inv_mace_2h_pvpcataclysms3_c_01.png","maxRank":1,"name":"Warbringer","description":"Transforms your Flames of Xoroth into Warbringer.WarbringerSlam the ground, dealing 65% Weapon Damage plus 2 to nearby enemies, reducing the effectiveness of any healing by -50% for 10 seconds. Deals increased damage per Demonfire consumed.","rankDescriptions":["Transforms your Flames of Xoroth into Warbringer.WarbringerSlam the ground, dealing 65% Weapon Damage plus 2 to nearby enemies, reducing the effectiveness of any healing by -50% for 10 seconds. Deals increased damage per Demonfire consumed."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4016","treeId":"coa-knight-of-xoroth-45","index":4016,"prerequisiteId":"coa-entry-30668","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30668","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/warrior_skullbanner.png","maxRank":1,"name":"Crusher","description":"Level 10 Passive Doubles the base Weapon Damage dealt by Infernal Strike and increases all critical damage dealt by 25%.","rankDescriptions":["Level 10 Passive Doubles the base Weapon Damage dealt by Infernal Strike and increases all critical damage dealt by 25%."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-31166","treeId":"coa-knight-of-xoroth-45","index":31166,"prerequisiteId":"coa-entry-4016","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4016","requiredRank":1},{"talentId":"coa-entry-30668","requiredRank":1}],"column":5,"row":2,"icon":"/assets/ui/spells/inv_sword_140.png","maxRank":1,"name":"Gore","description":"2 Charges, 8 sec recharge Generates 1 Demonfire Quickly gore an enemy, dealing 100% Weapon Damage plus 15.","rankDescriptions":["2 Charges, 8 sec recharge Generates 1 Demonfire Quickly gore an enemy, dealing 100% Weapon Damage plus 15."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34127","treeId":"coa-knight-of-xoroth-45","index":34127,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/ability_skeer_bloodletting.png","maxRank":3,"name":"Mutilation","description":"Increases the damage of Gore and Sever by 30%.","rankDescriptions":["Increases the damage of Gore and Sever by 10%.","Increases the damage of Gore and Sever by 20%.","Increases the damage of Gore and Sever by 30%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6936","treeId":"coa-knight-of-xoroth-45","index":6936,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/sha_ability_warrior_bloodnova_nightmare.png","maxRank":1,"name":"Gored","description":"Damage dealt by Gore and Meatsaw now increases your target's damage taken from Skulltaker and Warbringer by 15% for 10 seconds, stacking 2 times.","rankDescriptions":["Damage dealt by Gore and Meatsaw now increases your target's damage taken from Skulltaker and Warbringer by 15% for 10 seconds, stacking 2 times."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7881","treeId":"coa-knight-of-xoroth-45","index":7881,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spellLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"necromancer","trees":[{"id":"coa-necromancer-61","classId":"necromancer","name":"Animation","icon":"/assets/ui/spells/skeletalarcher.png","background":"","description":"Animation nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-necromancer-87","classId":"necromancer","name":"Class","icon":"/assets/ui/spells/ui_darkshore_warfront_horde_abomination.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-necromancer-59","classId":"necromancer","name":"Death","icon":"/assets/ui/spells/inv_pet_batpetmaldraxxus.png","background":"","description":"Death nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-necromancer-60","classId":"necromancer","name":"Rime","icon":"/assets/ui/spells/uico_frost_spell_09_border.png","background":"","description":"Rime nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-29866","treeId":"coa-necromancer-59","index":29866,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/inv_pet_batpetmaldraxxus.png","maxRank":1,"name":"Flesh to Worms","description":"Disease an enemy, dealing 15 + 11.06% shadow SP Plague damage and generating Runic Power every 3 sec for 18 seconds.","rankDescriptions":["Disease an enemy, dealing 15 + 11.06% shadow SP Plague damage and generating Runic Power every 3 sec for 18 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4034","treeId":"coa-necromancer-59","index":4034,"prerequisiteId":"coa-entry-29244","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29244","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/spell_shadow_plaguecloud.png","maxRank":1,"name":"Crypt Plague","description":"Level 10 Passive Damage dealt by Crypt Swarm now applies 1 stack of Crypt Plague and Lichfrost applies 2 stacks.Crypt Plague (Damage)Deals 2 + 6% SP Plague Damage every 2 sec for 10 seconds, stacking 10 times. Additional applications do not refresh duration.","rankDescriptions":["Level 10 Passive Damage dealt by Crypt Swarm now applies 1 stack of Crypt Plague and Lichfrost applies 2 stacks.Crypt Plague (Damage)Deals 2 + 6% SP Plague Damage every 2 sec for 10 seconds, stacking 10 times. Additional applications do not refresh duration."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-11904","treeId":"coa-necromancer-59","index":11904,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":2,"icon":"/assets/ui/spells/spell_holy_turnundead.png","maxRank":1,"name":"Cycle of Death","description":"Increases your spell haste by 5%.","rankDescriptions":["Increases your spell haste by 5%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-33752","treeId":"coa-necromancer-59","index":33752,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":2,"icon":"/assets/ui/spells/spell_shadow_deathanddecay.png","maxRank":1,"name":"Master of Death","description":"Casting Command spells on an enemy now applies Crypt Plague.","rankDescriptions":["Casting Command spells on an enemy now applies Crypt Plague."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7808","treeId":"coa-necromancer-59","index":7808,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":2,"row":3,"icon":"/assets/ui/spells/spell_shadow_raisedead.png","maxRank":1,"name":"Rotting Flesh","description":"Increases the damage of Flesh to Worms by 25% and allows its periodic damage to scale with your spell haste.","rankDescriptions":["Increases the damage of Flesh to Worms by 25% and allows its periodic damage to scale with your spell haste."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6904","treeId":"coa-necromancer-59","index":6904,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/spell_shadow_darksummoning.png","maxRank":1,"name":"Swarmer","description":"Increases the Runic Power generated by Crypt Swarm by 2 per tick.","rankDescriptions":["Increases the Runic Power generated by Crypt Swarm by 2 per tick."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6863","treeId":"coa-necromancer-59","index":6863,Line truncated
{"schemaVersion":1,"classId":"necromancer","trees":[{"id":"coa-necromancer-87","classId":"necromancer","name":"Class","icon":"/assets/ui/spells/ui_darkshore_warfront_horde_abomination.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-necromancer-59","classId":"necromancer","name":"Death","icon":"/assets/ui/spells/inv_pet_batpetmaldraxxus.png","background":"","description":"Death nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-necromancer-60","classId":"necromancer","name":"Rime","icon":"/assets/ui/spells/uico_frost_spell_09_border.png","background":"","description":"Rime nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-necromancer-61","classId":"necromancer","name":"Animation","icon":"/assets/ui/spells/skeletalarcher.png","background":"","description":"Animation nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-29866","treeId":"coa-necromancer-59","index":29866,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/inv_pet_batpetmaldraxxus.png","maxRank":1,"name":"Flesh to Worms","description":"Disease an enemy, dealing 15 + 11.06% shadow SP Plague damage and generating Runic Power every 3 sec for 18 seconds.","rankDescriptions":["Disease an enemy, dealing 15 + 11.06% shadow SP Plague damage and generating Runic Power every 3 sec for 18 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4034","treeId":"coa-necromancer-59","index":4034,"prerequisiteId":"coa-entry-29244","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29244","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/spell_shadow_plaguecloud.png","maxRank":1,"name":"Crypt Plague","description":"Level 10 Passive Damage dealt by Crypt Swarm now applies 1 stack of Crypt Plague and Lichfrost applies 2 stacks.Crypt Plague (Damage)Deals 2 + 6% SP Plague Damage every 2 sec for 10 seconds, stacking 10 times. Additional applications do not refresh duration.","rankDescriptions":["Level 10 Passive Damage dealt by Crypt Swarm now applies 1 stack of Crypt Plague and Lichfrost applies 2 stacks.Crypt Plague (Damage)Deals 2 + 6% SP Plague Damage every 2 sec for 10 seconds, stacking 10 times. Additional applications do not refresh duration."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-11904","treeId":"coa-necromancer-59","index":11904,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":2,"icon":"/assets/ui/spells/spell_holy_turnundead.png","maxRank":1,"name":"Cycle of Death","description":"Increases your spell haste by 5%.","rankDescriptions":["Increases your spell haste by 5%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-33752","treeId":"coa-necromancer-59","index":33752,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":2,"icon":"/assets/ui/spells/spell_shadow_deathanddecay.png","maxRank":1,"name":"Master of Death","description":"Casting Command spells on an enemy now applies Crypt Plague.","rankDescriptions":["Casting Command spells on an enemy now applies Crypt Plague."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7808","treeId":"coa-necromancer-59","index":7808,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":2,"row":3,"icon":"/assets/ui/spells/spell_shadow_raisedead.png","maxRank":1,"name":"Rotting Flesh","description":"Increases the damage of Flesh to Worms by 25% and allows its periodic damage to scale with your spell haste.","rankDescriptions":["Increases the damage of Flesh to Worms by 25% and allows its periodic damage to scale with your spell haste."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6904","treeId":"coa-necromancer-59","index":6904,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/spell_shadow_darksummoning.png","maxRank":1,"name":"Swarmer","description":"Increases the Runic Power generated by Crypt Swarm by 2 per tick.","rankDescriptions":["Increases the Runic Power generated by Crypt Swarm by 2 per tick."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6863","treeId":"coa-necromancer-59","index":6863,Line truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"primalist","trees":[{"id":"coa-primalist-84","classId":"primalist","name":"Life","icon":"/assets/ui/spells/inv_mace_1h_draenorraid_d_04green.png","background":"","description":"Life nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-primalist-83","classId":"primalist","name":"Geomancy","icon":"/assets/ui/spells/seismic_tremor.png","background":"","description":"Geomancy nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-primalist-82","classId":"primalist","name":"Primal","icon":"/assets/ui/spells/spell_beastmaster_rylak.png","background":"","description":"Primal nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-primalist-91","classId":"primalist","name":"Mountain King","icon":"/assets/ui/spells/spell_shaman_earthquake.png","background":"","description":"Mountain King nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-primalist-87","classId":"primalist","name":"Class","icon":"/assets/ui/spells/spell_nature_stoneclawtotem.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-29667","treeId":"coa-primalist-82","index":29667,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/spell_beastmaster_rylak.png","maxRank":1,"name":"Rylak's Bite","description":"2 Charges, 10 sec recharge You and your pet rush towards an enemy and strike them, dealing 120% Weapon Damage plus 8.","rankDescriptions":["2 Charges, 10 sec recharge You and your pet rush towards an enemy and strike them, dealing 120% Weapon Damage plus 8."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4058","treeId":"coa-primalist-82","index":4058,"prerequisiteId":"coa-entry-30254","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30254","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/ability_druid_ripandtear.png","maxRank":1,"name":"Spirit Beast Master","description":"Level 10 Passive You may now tame beasts in Azeroth to aid you as a companion.","rankDescriptions":["Level 10 Passive You may now tame beasts in Azeroth to aid you as a companion."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-7109","treeId":"coa-primalist-82","index":7109,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/druid_stagstatue01.png","maxRank":1,"name":"Fury of the Wild","description":"When you cast a Boon, you cast the same Boon on your pet at 50% effectiveness.","rankDescriptions":["When you cast a Boon, you cast the same Boon on your pet at 50% effectiveness."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29382","treeId":"coa-primalist-82","index":29382,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/ability_smash.png","maxRank":1,"name":"Totemic Smash","description":"Smash an enemy for 140% Weapon Damage plus 20. Deals an additional 10 + 35% AP damage to up to 5 enemies within 8 yds.","rankDescriptions":["Smash an enemy for 140% Weapon Damage plus 20. Deals an additional 10 + 35% AP damage to up to 5 enemies within 8 yds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6205","treeId":"coa-primalist-82","index":6205,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/ability_druid_freshwound.png","maxRank":1,"name":"Primal Shred","description":"Command your pet to shred up to 5 enemies within 8 yds, causing them to bleed, dealing 53 + 35% AP Physical damage over 21 seconds.","rankDescriptions":["Command your pet to shred up to 5 enemies within 8 yds, causing them to bleed, dealing 53 + 35% AP Physical damage over 21 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-9212","treeId":"coa-primalist-82","index":9212,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":11,"row":3,"icon":"/assets/ui/spells/spell_nature_naturesblessing.png","maxRank":1,"name":"Primal Weapons","description":"Level 20 Passive Teaches you Primal Weapons which when used will grant you a bonus based on whether you use one-handed weapons or two-handed weapons.Primal Weapon: Bestial MightWhile wielding a one-handed weapon, your Physical critical strikes enrage you and any active pet for 8 seconds, increasing the haste ofLine truncated
{"schemaVersion":1,"classId":"primalist","trees":[{"id":"coa-primalist-82","classId":"primalist","name":"Primal","icon":"/assets/ui/spells/spell_beastmaster_rylak.png","background":"","description":"Primal nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-primalist-83","classId":"primalist","name":"Geomancy","icon":"/assets/ui/spells/seismic_tremor.png","background":"","description":"Geomancy nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-primalist-84","classId":"primalist","name":"Life","icon":"/assets/ui/spells/inv_mace_1h_draenorraid_d_04green.png","background":"","description":"Life nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-primalist-87","classId":"primalist","name":"Class","icon":"/assets/ui/spells/spell_nature_stoneclawtotem.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-primalist-91","classId":"primalist","name":"Mountain King","icon":"/assets/ui/spells/spell_shaman_earthquake.png","background":"","description":"Mountain King nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-29667","treeId":"coa-primalist-82","index":29667,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/spell_beastmaster_rylak.png","maxRank":1,"name":"Rylak's Bite","description":"2 Charges, 10 sec recharge You and your pet rush towards an enemy and strike them, dealing 120% Weapon Damage plus 8.","rankDescriptions":["2 Charges, 10 sec recharge You and your pet rush towards an enemy and strike them, dealing 120% Weapon Damage plus 8."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4058","treeId":"coa-primalist-82","index":4058,"prerequisiteId":"coa-entry-30254","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30254","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/ability_druid_ripandtear.png","maxRank":1,"name":"Spirit Beast Master","description":"Level 10 Passive You may now tame beasts in Azeroth to aid you as a companion.","rankDescriptions":["Level 10 Passive You may now tame beasts in Azeroth to aid you as a companion."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-7109","treeId":"coa-primalist-82","index":7109,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/druid_stagstatue01.png","maxRank":1,"name":"Fury of the Wild","description":"When you cast a Boon, you cast the same Boon on your pet at 50% effectiveness.","rankDescriptions":["When you cast a Boon, you cast the same Boon on your pet at 50% effectiveness."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29382","treeId":"coa-primalist-82","index":29382,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/ability_smash.png","maxRank":1,"name":"Totemic Smash","description":"Smash an enemy for 140% Weapon Damage plus 20. Deals an additional 10 + 35% AP damage to up to 5 enemies within 8 yds.","rankDescriptions":["Smash an enemy for 140% Weapon Damage plus 20. Deals an additional 10 + 35% AP damage to up to 5 enemies within 8 yds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6205","treeId":"coa-primalist-82","index":6205,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/ability_druid_freshwound.png","maxRank":1,"name":"Primal Shred","description":"Command your pet to shred up to 5 enemies within 8 yds, causing them to bleed, dealing 53 + 35% AP Physical damage over 21 seconds.","rankDescriptions":["Command your pet to shred up to 5 enemies within 8 yds, causing them to bleed, dealing 53 + 35% AP Physical damage over 21 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-9212","treeId":"coa-primalist-82","index":9212,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":11,"row":3,"icon":"/assets/ui/spells/spell_nature_naturesblessing.png","maxRank":1,"name":"Primal Weapons","description":"Level 20 Passive Teaches you Primal Weapons which when used will grant you a bonus based on whether you use one-handed weapons or two-handed weapons.Primal Weapon: Bestial MightWhile wielding a one-handed weapon, your Physical critical strikes enrage you and any active pet for 8 seconds, increasing the haste ofLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"pyromancer","trees":[{"id":"coa-pyromancer-63","classId":"pyromancer","name":"Draconic","icon":"/assets/ui/spells/nozdormuicon.png","background":"","description":"Draconic nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-pyromancer-19","classId":"pyromancer","name":"Flameweaving","icon":"/assets/ui/spells/inv_misc_phoenixegg.png","background":"","description":"Flameweaving nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-pyromancer-62","classId":"pyromancer","name":"Incineration","icon":"/assets/ui/spells/ability_mage_fierypayback.png","background":"","description":"Incineration nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-pyromancer-87","classId":"pyromancer","name":"Class","icon":"/assets/ui/spells/nhi_firehands_border.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-29189","treeId":"coa-pyromancer-19","index":29189,"prerequisiteId":"coa-entry-4038","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4038","requiredRank":1},{"talentId":"coa-entry-30206","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/inv_misc_phoenixegg.png","maxRank":1,"name":"Phoenix Egg","description":"Summon a Phoenix for 1 minute at the target location that heals nearby party members for 117 + 15% healing every 5 sec. You may only have 1 Phoenix active at a time.","rankDescriptions":["Summon a Phoenix for 1 minute at the target location that heals nearby party members for 117 + 15% healing every 5 sec. You may only have 1 Phoenix active at a time."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4038","treeId":"coa-pyromancer-19","index":4038,"prerequisiteId":"coa-entry-30206","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30206","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/custom_t_phoenix_border.png","maxRank":1,"name":"Spirit of the Phoenix","description":"Level 10 Passive Upon taking damage that would otherwise kill you, you are instead transformed into the Spirit of the Phoenix for 15 seconds. While transformed, your spells have no mana cost and your Spirit is increased by 100%. At the end of the duration, you will be reborn. Can only occur once every 10 min.","rankDescriptions":["Level 10 Passive Upon taking damage that would otherwise kill you, you are instead transformed into the Spirit of the Phoenix for 15 seconds. While transformed, your spells have no mana cost and your Spirit is increased by 100%. At the end of the duration, you will be reborn. Can only occur once every 10 min."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-29550","treeId":"coa-pyromancer-19","index":29550,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":4,"row":2,"icon":"/assets/ui/spells/novart_magicspell_(37)_border.png","maxRank":1,"name":"Phoenix Dive","description":"Command your Phoenix to swoop to the target ally and shield allies in their path with fire, absorbing 175 + 50% SP + 100% Spirit damage for 30 seconds, scaling with your Spirit.","rankDescriptions":["Command your Phoenix to swoop to the target ally and shield allies in their path with fire, absorbing 175 + 50% SP + 100% Spirit damage for 30 seconds, scaling with your Spirit."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-33919","treeId":"coa-pyromancer-19","index":33919,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":6,"row":2,"icon":"/assets/ui/spells/nhi_firebreath_(2)_border.png","maxRank":1,"name":"Cleansing Flames","description":"Generates 10 Heat Each Tick Spread cleansing flames on 5 allies and enemies in front of you, damaging or healing for 69 + 44.4% SP over 3 seconds.","rankDescriptions":["Generates 10 Heat Each Tick Spread cleansing flames on 5 allies and enemies in front of you, damaging or healing for 69 + 44.4% SP over 3 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30637","treeId":"coa-pyromancer-19","index":30637,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/ability_monk_breathoffire.png","maxRank":1,"name":"Soothing Flames","description":"Healing done by Kindle and Cinderheart now additionally heals the target for 30% of the healing done over 3 seconds.","rankDescriptions":["Healing done by Kindle and Cinderheart now additionally heals the target for 30% of the healing done over 3 seconds."],"system":"coa","entryTyLine truncated
{"schemaVersion":1,"classId":"pyromancer","trees":[{"id":"coa-pyromancer-87","classId":"pyromancer","name":"Class","icon":"/assets/ui/spells/nhi_firehands_border.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-pyromancer-62","classId":"pyromancer","name":"Incineration","icon":"/assets/ui/spells/ability_mage_fierypayback.png","background":"","description":"Incineration nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-pyromancer-19","classId":"pyromancer","name":"Flameweaving","icon":"/assets/ui/spells/inv_misc_phoenixegg.png","background":"","description":"Flameweaving nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-pyromancer-63","classId":"pyromancer","name":"Draconic","icon":"/assets/ui/spells/nozdormuicon.png","background":"","description":"Draconic nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-29189","treeId":"coa-pyromancer-19","index":29189,"prerequisiteId":"coa-entry-4038","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4038","requiredRank":1},{"talentId":"coa-entry-30206","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/inv_misc_phoenixegg.png","maxRank":1,"name":"Phoenix Egg","description":"Summon a Phoenix at the target location that heals nearby party members for 85 + 10% healing every 5 sec. You may only have 1 Phoenix active at a time.","rankDescriptions":["Summon a Phoenix at the target location that heals nearby party members for 85 + 10% healing every 5 sec. You may only have 1 Phoenix active at a time."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4038","treeId":"coa-pyromancer-19","index":4038,"prerequisiteId":"coa-entry-30206","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30206","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/custom_t_phoenix_border.png","maxRank":1,"name":"Spirit of the Phoenix","description":"Level 10 Passive Upon taking damage that would otherwise kill you, you are instead transformed into the Spirit of the Phoenix for 15 seconds. While transformed, your spells have no mana cost and your Spirit is increased by 100%. At the end of the duration, you will be reborn. Can only occur once every 10 min.","rankDescriptions":["Level 10 Passive Upon taking damage that would otherwise kill you, you are instead transformed into the Spirit of the Phoenix for 15 seconds. While transformed, your spells have no mana cost and your Spirit is increased by 100%. At the end of the duration, you will be reborn. Can only occur once every 10 min."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-29550","treeId":"coa-pyromancer-19","index":29550,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":4,"row":2,"icon":"/assets/ui/spells/novart_magicspell_(37)_border.png","maxRank":1,"name":"Phoenix Dive","description":"Command your Phoenix to swoop to the target ally, shielding up to 10 allies in its path with fire and absorbing 333 + 30% healing + 50% Spirit damage for 30 seconds, scaling with your healing spell power and Spirit.","rankDescriptions":["Command your Phoenix to swoop to the target ally, shielding up to 10 allies in its path with fire and absorbing 333 + 30% healing + 50% Spirit damage for 30 seconds, scaling with your healing spell power and Spirit."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-33919","treeId":"coa-pyromancer-19","index":33919,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":6,"row":2,"icon":"/assets/ui/spells/nhi_firebreath_(2)_border.png","maxRank":1,"name":"Cleansing Flames","description":"Generates 10 Heat Each Tick Spread cleansing flames on 5 allies and enemies in front of you, damaging or healing for 69 + 44.4% SP over 3 seconds.","rankDescriptions":["Generates 10 Heat Each Tick Spread cleansing flames on 5 allies and enemies in front of you, damaging or healing for 69 + 44.4% SP over 3 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30637","treeId":"coa-pyromancer-19","index":30637,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/ability_monk_breathoffire.png","maxRank":1,"name":"Soothing Flames","description":"Healing done by Kindle and Cinderheart now additionally heals the target for 30% of the healing done over 3 seconds.","rankDescriptions":["Healing done by Kindle and Cinderheart now additionally heals the target for 30% of the healinLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"ranger","trees":[{"id":"coa-ranger-55","classId":"ranger","name":"Brigand","icon":"/assets/ui/spells/ability_hunter_mongoosebite.png","background":"","description":"Brigand nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-ranger-87","classId":"ranger","name":"Class","icon":"/assets/ui/spells/custom_dismounting_shot.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-ranger-2","classId":"ranger","name":"Farstrider","icon":"/assets/ui/spells/ability_felarakkoa_focusedblast.png","background":"","description":"Farstrider nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-ranger-54","classId":"ranger","name":"Archery","icon":"/assets/ui/spells/5_archerskill07_border.png","background":"","description":"Archery nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31133","treeId":"coa-ranger-2","index":31133,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/ability_felarakkoa_focusedblast.png","maxRank":1,"name":"Falconstrike","description":"Every 5th Quick Shot within 15 seconds transforms into Falconstrike. Using a Horn instantly transforms Quick Shot into Falconstrike.Falconstrike (Transform)Generates 2 Advantage Call a cast of falcons to strike an enemy, dealing 121% Ranged Weapon Damage plus 10 Nature damage and calling 1 War Falcon to your aid for 6 seconds.","rankDescriptions":["Every 5th Quick Shot within 15 seconds transforms into Falconstrike. Using a Horn instantly transforms Quick Shot into Falconstrike.Falconstrike (Transform)Generates 2 Advantage Call a cast of falcons to strike an enemy, dealing 121% Ranged Weapon Damage plus 10 Nature damage and calling 1 War Falcon to your aid for 6 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":10,"isPassive":false},{"id":"coa-entry-4030","treeId":"coa-ranger-2","index":4030,"prerequisiteId":"coa-entry-30352","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30352","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/inv_legion_faction_dreamweavers.png","maxRank":1,"name":"Dream Flowers","description":"Level 10 Passive Your damaging critical strikes now spawn a green Dream Flower at a random location within 15 yds of you. Dream Flower (Spawner)When an ally runs over the flower, they consume it to heal for 3% maximum health and gain 40% increased movement speed for 5 seconds.Can only occur once per sec.","rankDescriptions":["Level 10 Passive Your damaging critical strikes now spawn a green Dream Flower at a random location within 15 yds of you. Dream Flower (Spawner)When an ally runs over the flower, they consume it to heal for 3% maximum health and gain 40% increased movement speed for 5 seconds.Can only occur once per sec."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-30926","treeId":"coa-ranger-2","index":30926,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":2,"icon":"/assets/ui/spells/misc_legionfall_hunter.png","maxRank":2,"name":"Cunning","description":"Increases your Focus regeneration by 30%.","rankDescriptions":["Increases your Focus regeneration by 15%.","Increases your Focus regeneration by 30%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7050","treeId":"coa-ranger-2","index":7050,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":2,"icon":"/assets/ui/spells/inv_ascend_horn_b_01.png","maxRank":2,"name":"Blow the Horns!","description":"Reduces the cooldown of Horn spells by -50%.","rankDescriptions":["Reduces the cooldown of Horn spells by -25%.","Reduces the cooldown of Horn spells by -50%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34181","treeId":"coa-ranger-2","index":34181,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":2,"row":3,"icon":"/assets/ui/spells/ability_skyreach_castdown.png","maxRank":1,"name":"Falcon's Call","description":"Call down war falcons upon a targeted area, slowing up to 8 enemies within the area by -60% for 5 seconds. A Falcon is summoned for each enemy affected for 12 seconds.","rankDescriptions":["Call down war falcons upon a targeted area, slowing up to 8 enemies within the area by -60% for 5 seconds. A Falcon is summoned for each enemy affected for 12 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPasLine truncated
{"schemaVersion":1,"classId":"ranger","trees":[{"id":"coa-ranger-87","classId":"ranger","name":"Class","icon":"/assets/ui/spells/custom_dismounting_shot.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-ranger-54","classId":"ranger","name":"Archery","icon":"/assets/ui/spells/5_archerskill07_border.png","background":"","description":"Archery nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-ranger-55","classId":"ranger","name":"Brigand","icon":"/assets/ui/spells/ability_hunter_mongoosebite.png","background":"","description":"Brigand nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-ranger-2","classId":"ranger","name":"Farstrider","icon":"/assets/ui/spells/ability_felarakkoa_focusedblast.png","background":"","description":"Farstrider nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31133","treeId":"coa-ranger-2","index":31133,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/ability_felarakkoa_focusedblast.png","maxRank":1,"name":"Falconstrike","description":"Every 5th Quick Shot within 15 seconds transforms into Falconstrike. Using a Horn instantly transforms Quick Shot into Falconstrike.Falconstrike (Transform)Generates 2 Advantage Call a cast of falcons to strike an enemy, dealing 121% Ranged Weapon Damage plus 10 Nature damage and calling 1 War Falcon to your aid for 6 seconds.","rankDescriptions":["Every 5th Quick Shot within 15 seconds transforms into Falconstrike. Using a Horn instantly transforms Quick Shot into Falconstrike.Falconstrike (Transform)Generates 2 Advantage Call a cast of falcons to strike an enemy, dealing 121% Ranged Weapon Damage plus 10 Nature damage and calling 1 War Falcon to your aid for 6 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":10,"isPassive":false},{"id":"coa-entry-4030","treeId":"coa-ranger-2","index":4030,"prerequisiteId":"coa-entry-30352","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-30352","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/inv_legion_faction_dreamweavers.png","maxRank":1,"name":"Dream Flowers","description":"Level 10 Passive Your damaging critical strikes now spawn a green Dream Flower at a random location within 15 yds of you. Dream Flower (Spawner)When an ally runs over the flower, they consume it to heal for 3% maximum health and gain 40% increased movement speed for 5 seconds.Can only occur once per sec.","rankDescriptions":["Level 10 Passive Your damaging critical strikes now spawn a green Dream Flower at a random location within 15 yds of you. Dream Flower (Spawner)When an ally runs over the flower, they consume it to heal for 3% maximum health and gain 40% increased movement speed for 5 seconds.Can only occur once per sec."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-30926","treeId":"coa-ranger-2","index":30926,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":2,"icon":"/assets/ui/spells/misc_legionfall_hunter.png","maxRank":2,"name":"Cunning","description":"Increases your Focus regeneration by 30%.","rankDescriptions":["Increases your Focus regeneration by 15%.","Increases your Focus regeneration by 30%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7050","treeId":"coa-ranger-2","index":7050,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":2,"icon":"/assets/ui/spells/inv_ascend_horn_b_01.png","maxRank":2,"name":"Blow the Horns!","description":"Reduces the cooldown of Horn spells by -50%.","rankDescriptions":["Reduces the cooldown of Horn spells by -25%.","Reduces the cooldown of Horn spells by -50%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34181","treeId":"coa-ranger-2","index":34181,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":2,"row":3,"icon":"/assets/ui/spells/ability_skyreach_castdown.png","maxRank":1,"name":"Falcon's Call","description":"Call down war falcons upon a targeted area, slowing up to 8 enemies within the area by -60% for 5 seconds. A Falcon is summoned for each enemy affected for 12 seconds.","rankDescriptions":["Call down war falcons upon a targeted area, slowing up to 8 enemies within the area by -60% for 5 seconds. A Falcon is summoned for each enemy affected for 12 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPasLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"reaper","trees":[{"id":"coa-reaper-79","classId":"reaper","name":"Harvest","icon":"/assets/ui/spells/inv_knife_1h_revendrethquest_b_03.png","background":"","description":"Harvest nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-reaper-80","classId":"reaper","name":"Soul","icon":"/assets/ui/spells/nhi_spiritstab_border.png","background":"","description":"Soul nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-reaper-81","classId":"reaper","name":"Domination","icon":"/assets/ui/spells/ability_argus_edgeofobliteration.png","background":"","description":"Domination nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-reaper-87","classId":"reaper","name":"Class","icon":"/assets/ui/spells/inv_archaeology_orcclans_tattooknife.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-29378","treeId":"coa-reaper-79","index":29378,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/inv_knife_1h_revendrethquest_b_03.png","maxRank":1,"name":"Doomrend","description":"Rend an enemy dealing 140% Weapon Damage plus 17 + 35% AP, causing you to apply a dark shield to them that absorbs the next 75 + 100% Strength healing done to them for 5 seconds, and generates Runic Power.","rankDescriptions":["Rend an enemy dealing 140% Weapon Damage plus 17 + 35% AP, causing you to apply a dark shield to them that absorbs the next 75 + 100% Strength healing done to them for 5 seconds, and generates Runic Power."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4055","treeId":"coa-reaper-79","index":4055,"prerequisiteId":"coa-entry-29248","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29248","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/ability_revendreth_deathknight.png","maxRank":1,"name":"Harvester","description":"Level 10 Passive You now heal yourself equal to 15% of all damage dealt.","rankDescriptions":["Level 10 Passive You now heal yourself equal to 15% of all damage dealt."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-29246","treeId":"coa-reaper-79","index":29246,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":2,"icon":"/assets/ui/spells/inv_helmet_plate_deathknight_m_01.png","maxRank":2,"name":"Maw Knight","description":"Increases the critical strike chance of Doomrend by 10%.","rankDescriptions":["Increases the critical strike chance of Doomrend by 5%.","Increases the critical strike chance of Doomrend by 10%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-9270","treeId":"coa-reaper-79","index":9270,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":2,"icon":"/assets/ui/spells/inv_harvestgolempet.png","maxRank":1,"name":"Bountiful Harvest","description":"Increases the damage of Reap and Murder by 25%.","rankDescriptions":["Increases the damage of Reap and Murder by 25%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34480","treeId":"coa-reaper-79","index":34480,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":2,"row":3,"icon":"/assets/ui/spells/inv_polearm_2h_warfrontshorde_c_01red.png","maxRank":1,"name":"Crow's Harvest","description":"Strike all nearby enemies for 65% Weapon Damage plus 6. Damage dealt harvests a Soul Fragment, up to a maximum of 3.","rankDescriptions":["Strike all nearby enemies for 65% Weapon Damage plus 6. Damage dealt harvests a Soul Fragment, up to a maximum of 3."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-31371","treeId":"coa-reaper-79","index":31371,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/ability_revendreth_warrior.png","maxRank":1,"name":"Slaughter","description":"Generates 1 Reaped Soul Eradicate an enemy with your scythe, dealing 130% Weapon Damage plus 14. Only usable on enemies below 35% health.","rankDescriptions":["Generates 1 Reaped Soul Eradicate an enemy with your scythe, dealing 130% Weapon Damage plus 14. Only usable on enemies below 35% health."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-5767","treeId":"coa-reaperLine truncated
{"schemaVersion":1,"classId":"reaper","trees":[{"id":"coa-reaper-87","classId":"reaper","name":"Class","icon":"/assets/ui/spells/inv_archaeology_orcclans_tattooknife.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-reaper-79","classId":"reaper","name":"Harvest","icon":"/assets/ui/spells/inv_knife_1h_revendrethquest_b_03.png","background":"","description":"Harvest nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-reaper-80","classId":"reaper","name":"Soul","icon":"/assets/ui/spells/nhi_spiritstab_border.png","background":"","description":"Soul nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-reaper-81","classId":"reaper","name":"Domination","icon":"/assets/ui/spells/ability_argus_edgeofobliteration.png","background":"","description":"Domination nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-29378","treeId":"coa-reaper-79","index":29378,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/inv_knife_1h_revendrethquest_b_03.png","maxRank":1,"name":"Doomrend","description":"Rend an enemy dealing 140% Weapon Damage plus 17 + 35% AP, causing you to apply a dark shield to them that absorbs the next 75 + 100% Strength healing done to them for 5 seconds, and generates Runic Power.","rankDescriptions":["Rend an enemy dealing 140% Weapon Damage plus 17 + 35% AP, causing you to apply a dark shield to them that absorbs the next 75 + 100% Strength healing done to them for 5 seconds, and generates Runic Power."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4055","treeId":"coa-reaper-79","index":4055,"prerequisiteId":"coa-entry-29248","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29248","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/ability_revendreth_deathknight.png","maxRank":1,"name":"Harvester","description":"Level 10 Passive You now heal yourself equal to 15% of all damage dealt.","rankDescriptions":["Level 10 Passive You now heal yourself equal to 15% of all damage dealt."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-29246","treeId":"coa-reaper-79","index":29246,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":2,"icon":"/assets/ui/spells/inv_helmet_plate_deathknight_m_01.png","maxRank":2,"name":"Maw Knight","description":"Increases the critical strike chance of Doomrend by 10%.","rankDescriptions":["Increases the critical strike chance of Doomrend by 5%.","Increases the critical strike chance of Doomrend by 10%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-9270","treeId":"coa-reaper-79","index":9270,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":2,"icon":"/assets/ui/spells/inv_harvestgolempet.png","maxRank":1,"name":"Bountiful Harvest","description":"Increases the damage of Reap and Murder by 25%.","rankDescriptions":["Increases the damage of Reap and Murder by 25%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34480","treeId":"coa-reaper-79","index":34480,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":2,"row":3,"icon":"/assets/ui/spells/inv_polearm_2h_warfrontshorde_c_01red.png","maxRank":1,"name":"Crow's Harvest","description":"Strike all nearby enemies for 75% Weapon Damage plus 8. Damage dealt harvests a Soul Fragment, up to a maximum of 3.","rankDescriptions":["Strike all nearby enemies for 75% Weapon Damage plus 8. Damage dealt harvests a Soul Fragment, up to a maximum of 3."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-31371","treeId":"coa-reaper-79","index":31371,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/ability_revendreth_warrior.png","maxRank":1,"name":"Slaughter","description":"Generates 1 Reaped Soul Eradicate an enemy with your scythe, dealing 150% Weapon Damage plus 17. Only usable on enemies below 35% health.","rankDescriptions":["Generates 1 Reaped Soul Eradicate an enemy with your scythe, dealing 150% Weapon Damage plus 17. Only usable on enemies below 35% health."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-5767","treeId":"coa-reaperLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"runemaster","trees":[{"id":"coa-runemaster-85","classId":"runemaster","name":"Runic","icon":"/assets/ui/spells/5_mageskill14_border.png","background":"","description":"Runic nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-runemaster-11","classId":"runemaster","name":"Arcane","icon":"/assets/ui/spells/achievement_raidprimalist_council.png","background":"","description":"Arcane nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-runemaster-86","classId":"runemaster","name":"Riftblade","icon":"/assets/ui/spells/uico_fire_spell_02_border.png","background":"","description":"Riftblade nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-runemaster-87","classId":"runemaster","name":"Class","icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_magickeeper_border.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-66733","treeId":"coa-runemaster-11","index":66733,"prerequisiteId":"coa-entry-4061","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4061","requiredRank":1},{"talentId":"coa-entry-31102","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/achievement_raidprimalist_council.png","maxRank":1,"name":"Glyphic Ruin","description":"Unleash your active Glyph effect on an enemy and deal 82 + 100% SP Elemental Damage.","rankDescriptions":["Unleash your active Glyph effect on an enemy and deal 82 + 100% SP Elemental Damage."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4061","treeId":"coa-runemaster-11","index":4061,"prerequisiteId":"coa-entry-31102","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-31102","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/70_inscription_vantus_rune_azure.png","maxRank":1,"name":"Frost Glyph","description":"Level 10 Passive Using Elemental Burst and Primordial Blast now grants you Frost Glyph. Frost GlyphUnleash: Deals 437 Frost Damage and slows movement speed by -30% for 4 seconds.","rankDescriptions":["Level 10 Passive Using Elemental Burst and Primordial Blast now grants you Frost Glyph. Frost GlyphUnleash: Deals 437 Frost Damage and slows movement speed by -30% for 4 seconds."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":10,"isPassive":true},{"id":"coa-entry-34664","treeId":"coa-runemaster-11","index":34664,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/70_inscription_vantus_rune_nightmare.png","maxRank":1,"name":"Flame Glyph","description":"Using Elemental Burst or Primordial Blast while Frost Glyph is active now grants you a Flame Glyph.Flame GlyphUnleash: Deals 250 + 65% fire SP Fire Damage and an additional 750 + 30% SP Fire Damage over 6 seconds.","rankDescriptions":["Using Elemental Burst or Primordial Blast while Frost Glyph is active now grants you a Flame Glyph.Flame GlyphUnleash: Deals 250 + 65% fire SP Fire Damage and an additional 750 + 30% SP Fire Damage over 6 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30208","treeId":"coa-runemaster-11","index":30208,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/spell_arcane_blast.png","maxRank":2,"name":"Focusing Crystals","description":"Increases your Magic Damage dealt by 6% and allows 60% of your mana regeneration to continue while in combat.","rankDescriptions":["Increases your Magic Damage dealt by 3% and allows 30% of your mana regeneration to continue while in combat.","Increases your Magic Damage dealt by 6% and allows 60% of your mana regeneration to continue while in combat."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7834","treeId":"coa-runemaster-11","index":7834,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/70_inscription_vantus_rune_suramar.png","maxRank":1,"name":"Arcane Glyph","description":"Using Elemental Burst or Primordial Blast while Flame Glyph is active now grants you Arcane Glyph.Arcane GlyphUnleash: Deals 276 + 18% arcane SP Arcane Damage to up to 0 enemies near the primary target.","rankDescriptions":["Using Elemental Burst or Primordial Blast while Flame Glyph is active now grants you Arcane Glyph.Arcane GlyphUnleash: Deals 276 + 18% arcane SP Arcane Damage to up to 0 enemies near the primary target."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":Line truncated
{"schemaVersion":1,"classId":"runemaster","trees":[{"id":"coa-runemaster-11","classId":"runemaster","name":"Arcane","icon":"/assets/ui/spells/achievement_raidprimalist_council.png","background":"","description":"Arcane nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-runemaster-85","classId":"runemaster","name":"Runic","icon":"/assets/ui/spells/5_mageskill14_border.png","background":"","description":"Runic nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-runemaster-86","classId":"runemaster","name":"Riftblade","icon":"/assets/ui/spells/uico_fire_spell_02_border.png","background":"","description":"Riftblade nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-runemaster-87","classId":"runemaster","name":"Class","icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_magickeeper_border.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-66733","treeId":"coa-runemaster-11","index":66733,"prerequisiteId":"coa-entry-4061","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4061","requiredRank":1},{"talentId":"coa-entry-31102","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/achievement_raidprimalist_council.png","maxRank":1,"name":"Glyphic Ruin","description":"Unleash your active Glyph effect on an enemy and deal 82 + 100% SP Elemental Damage.","rankDescriptions":["Unleash your active Glyph effect on an enemy and deal 82 + 100% SP Elemental Damage."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4061","treeId":"coa-runemaster-11","index":4061,"prerequisiteId":"coa-entry-31102","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-31102","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/70_inscription_vantus_rune_azure.png","maxRank":1,"name":"Frost Glyph","description":"Level 10 Passive Using Elemental Burst and Primordial Blast now grants you Frost Glyph. Frost GlyphUnleash: Deals 437 Frost Damage and slows movement speed by -30% for 4 seconds.","rankDescriptions":["Level 10 Passive Using Elemental Burst and Primordial Blast now grants you Frost Glyph. Frost GlyphUnleash: Deals 437 Frost Damage and slows movement speed by -30% for 4 seconds."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":10,"isPassive":true},{"id":"coa-entry-34664","treeId":"coa-runemaster-11","index":34664,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/70_inscription_vantus_rune_nightmare.png","maxRank":1,"name":"Flame Glyph","description":"Using Elemental Burst or Primordial Blast while Frost Glyph is active now grants you a Flame Glyph.Flame GlyphUnleash: Deals 250 + 65% fire SP Fire Damage and an additional 1250 + 50% SP Fire Damage over 10 seconds.","rankDescriptions":["Using Elemental Burst or Primordial Blast while Frost Glyph is active now grants you a Flame Glyph.Flame GlyphUnleash: Deals 250 + 65% fire SP Fire Damage and an additional 1250 + 50% SP Fire Damage over 10 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30208","treeId":"coa-runemaster-11","index":30208,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/spell_arcane_blast.png","maxRank":2,"name":"Focusing Crystals","description":"Increases your Magic Damage dealt by 6% and allows 60% of your mana regeneration to continue while in combat.","rankDescriptions":["Increases your Magic Damage dealt by 3% and allows 30% of your mana regeneration to continue while in combat.","Increases your Magic Damage dealt by 6% and allows 60% of your mana regeneration to continue while in combat."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7834","treeId":"coa-runemaster-11","index":7834,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/70_inscription_vantus_rune_suramar.png","maxRank":1,"name":"Arcane Glyph","description":"Using Elemental Burst or Primordial Blast while Flame Glyph is active now grants you Arcane Glyph.Arcane GlyphUnleash: Deals 276 + 18% arcane SP Arcane Damage to enemies near the primary target.","rankDescriptions":["Using Elemental Burst or Primordial Blast while Flame Glyph is active now grants you Arcane Glyph.Arcane GlyphUnleash: Deals 276 + 18% arcane SP Arcane Damage to enemies near the primary target."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"starcaller","trees":[{"id":"coa-starcaller-67","classId":"starcaller","name":"Moon Guard","icon":"/assets/ui/spells/ability_argus_soulburst.png","background":"","description":"Moon Guard nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-starcaller-69","classId":"starcaller","name":"Sentinel","icon":"/assets/ui/spells/_arcaneshot_lightblue.png","background":"","description":"Sentinel nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-starcaller-68","classId":"starcaller","name":"Moon Priest","icon":"/assets/ui/spells/achievement_leader_tyrande_whisperwind.png","background":"","description":"Moon Priest nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-starcaller-89","classId":"starcaller","name":"Warden","icon":"/assets/ui/spells/_fanofknives_lightblue.png","background":"","description":"Warden nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-starcaller-87","classId":"starcaller","name":"Class","icon":"/assets/ui/spells/spell_nature_moonglow.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-29896","treeId":"coa-starcaller-67","index":29896,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/ability_argus_soulburst.png","maxRank":1,"name":"Starburst","description":"Applies 1 Scattered Star Per Hit Smash up to 8 enemies, dealing 2 + 30% arcane SP + 15% AP Arcane damage, scaling with block value and maximum mana and reducing their attack speed by -20% for 10 seconds. Consuming a Scattered Star reduces the remaining cooldown of Starburst by -2 sec.","rankDescriptions":["Applies 1 Scattered Star Per Hit Smash up to 8 enemies, dealing 2 + 30% arcane SP + 15% AP Arcane damage, scaling with block value and maximum mana and reducing their attack speed by -20% for 10 seconds. Consuming a Scattered Star reduces the remaining cooldown of Starburst by -2 sec."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4043","treeId":"coa-starcaller-67","index":4043,"prerequisiteId":"coa-entry-29642","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29642","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/artifactability_balancedruid_newmoon.png","maxRank":1,"name":"Moon Guard","description":"Level 10 Passive You now gain Intellect equal to your Strength.","rankDescriptions":["Level 10 Passive You now gain Intellect equal to your Strength."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-29656","treeId":"coa-starcaller-67","index":29656,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":4,"row":2,"icon":"/assets/ui/spells/inv_cosmicvoid_orb.png","maxRank":1,"name":"Blanket of Stars","description":"Cover your shield in a blanket of stars for 8 seconds, increasing your block chance and block value by 100%.","rankDescriptions":["Cover your shield in a blanket of stars for 8 seconds, increasing your block chance and block value by 100%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30665","treeId":"coa-starcaller-67","index":30665,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":6,"row":2,"icon":"/assets/ui/spells/inv_sword_1h_warfrontsnightelf_d_01.png","maxRank":1,"name":"Starsweep","description":"Consumes Scattered Stars Sweep an enemy and all nearby enemies with your astral blade, dealing 30 + 30% AP + 35% SP Arcane damage. Every Scattered Star consumed reduces the cooldown of this spell by -3 sec.Consume Scattered StarsDeals 7 + 18.22% SP Arcane Damage and restores 8% maximum mana for each Scattered Star.","rankDescriptions":["Consumes Scattered Stars Sweep an enemy and all nearby enemies with your astral blade, dealing 30 + 30% AP + 35% SP Arcane damage. Every Scattered Star consumed reduces the cooldown of this spell by -3 sec.Consume Scattered StarsDeals 7 + 18.22% SP Arcane Damage and restores 8% maximum mana for each Scattered Star."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29651","treeId":"coa-starcaller-67","index":29651,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/spell_arcane_arcane01.png","maxRank":1,"name":"Improved Eclipse of Fury","description":"Increases the effectiveness of Eclipse of Fury by 40%.","rankDescriptions":["Increases the effectiveness of Eclipse of Fury by 40%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssLine truncated
{"schemaVersion":1,"classId":"starcaller","trees":[{"id":"coa-starcaller-87","classId":"starcaller","name":"Class","icon":"/assets/ui/spells/spell_nature_moonglow.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-starcaller-67","classId":"starcaller","name":"Moon Guard","icon":"/assets/ui/spells/ability_argus_soulburst.png","background":"","description":"Moon Guard nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-starcaller-69","classId":"starcaller","name":"Sentinel","icon":"/assets/ui/spells/_arcaneshot_lightblue.png","background":"","description":"Sentinel nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-starcaller-68","classId":"starcaller","name":"Moon Priest","icon":"/assets/ui/spells/achievement_leader_tyrande_whisperwind.png","background":"","description":"Moon Priest nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-starcaller-89","classId":"starcaller","name":"Warden","icon":"/assets/ui/spells/_fanofknives_lightblue.png","background":"","description":"Warden nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-29896","treeId":"coa-starcaller-67","index":29896,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/ability_argus_soulburst.png","maxRank":1,"name":"Starburst","description":"Applies 1 Scattered Star Per Hit Smash up to 8 enemies, dealing 2 + 30% arcane SP + 15% AP Arcane damage, scaling with block value and maximum mana and reducing their attack speed by -20% for 10 seconds. Consuming a Scattered Star reduces the remaining cooldown of Starburst by -2 sec.","rankDescriptions":["Applies 1 Scattered Star Per Hit Smash up to 8 enemies, dealing 2 + 30% arcane SP + 15% AP Arcane damage, scaling with block value and maximum mana and reducing their attack speed by -20% for 10 seconds. Consuming a Scattered Star reduces the remaining cooldown of Starburst by -2 sec."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4043","treeId":"coa-starcaller-67","index":4043,"prerequisiteId":"coa-entry-29642","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29642","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/artifactability_balancedruid_newmoon.png","maxRank":1,"name":"Moon Guard","description":"Level 10 Passive You now gain Intellect equal to your Strength and your maximum health now additionally scales with 10% of your maximum mana.","rankDescriptions":["Level 10 Passive You now gain Intellect equal to your Strength and your maximum health now additionally scales with 10% of your maximum mana."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-29656","treeId":"coa-starcaller-67","index":29656,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":4,"row":2,"icon":"/assets/ui/spells/inv_cosmicvoid_orb.png","maxRank":1,"name":"Blanket of Stars","description":"Cover your shield in a blanket of stars for 8 seconds, increasing your block chance and block value by 100%.","rankDescriptions":["Cover your shield in a blanket of stars for 8 seconds, increasing your block chance and block value by 100%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30665","treeId":"coa-starcaller-67","index":30665,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":6,"row":2,"icon":"/assets/ui/spells/inv_sword_1h_warfrontsnightelf_d_01.png","maxRank":1,"name":"Starsweep","description":"Consumes Scattered Stars Sweep an enemy and all nearby enemies with your astral blade, dealing 30 + 30% AP + 35% SP Arcane damage. Every Scattered Star consumed reduces the cooldown of this spell by -3 sec.Consume Scattered StarsDeals 7 + 18.22% SP Arcane Damage and restores 8% maximum mana for each Scattered Star.","rankDescriptions":["Consumes Scattered Stars Sweep an enemy and all nearby enemies with your astral blade, dealing 30 + 30% AP + 35% SP Arcane damage. Every Scattered Star consumed reduces the cooldown of this spell by -3 sec.Consume Scattered StarsDeals 7 + 18.22% SP Arcane Damage and restores 8% maximum mana for each Scattered Star."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29651","treeId":"coa-starcaller-67","index":29651,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/inv_helm_mask_fittedalpha_b_01_nightborne_02.png","maxRank":1,"name":"Improved Eclipse of Fury","description":"Reduces the cooldown of Line truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"stormbringer","trees":[{"id":"coa-stormbringer-42","classId":"stormbringer","name":"Lightning","icon":"/assets/ui/spells/epic_rpg_icon_pack_wind_icon_0002s_0000_lightning_border.png","background":"","description":"Lightning nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-stormbringer-43","classId":"stormbringer","name":"Wind","icon":"/assets/ui/spells/spell_nature_tranquility.png","background":"","description":"Wind nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-stormbringer-44","classId":"stormbringer","name":"Maelstrom","icon":"/assets/ui/spells/_liquidstone_water.png","background":"","description":"Maelstrom nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-stormbringer-87","classId":"stormbringer","name":"Class","icon":"/assets/ui/spells/inv_misc_volatileair.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31163","treeId":"coa-stormbringer-42","index":31163,"prerequisiteId":"coa-entry-4013","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4013","requiredRank":1},{"talentId":"coa-entry-29138","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/epic_rpg_icon_pack_wind_icon_0002s_0000_lightning_border.png","maxRank":1,"name":"Arm of Thorim","description":"Depletes All Static Call down a terrible beam of lightning upon an enemy, dealing 135 + 120% nature SP Nature damage and stunning them for 1 seconds. Damage and cast time increased based on Static level.","rankDescriptions":["Depletes All Static Call down a terrible beam of lightning upon an enemy, dealing 135 + 120% nature SP Nature damage and stunning them for 1 seconds. Damage and cast time increased based on Static level."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4013","treeId":"coa-stormbringer-42","index":4013,"prerequisiteId":"coa-entry-29138","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29138","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/nhi_frozenlightning_border.png","maxRank":1,"name":"Electrocutioner","description":"Level 10 Passive Dealing spell damage now has a 5% chance to grant you Electrocutioner.Electrocutioner (Proc)Resets the cooldown of Electrocute and makes your next usable regardless of the target's health percentage. Chance increases based on Static level.","rankDescriptions":["Level 10 Passive Dealing spell damage now has a 5% chance to grant you Electrocutioner.Electrocutioner (Proc)Resets the cooldown of Electrocute and makes your next usable regardless of the target's health percentage. Chance increases based on Static level."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-29837","treeId":"coa-stormbringer-42","index":29837,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/ability_siege_engineer_magnetic_crush.png","maxRank":1,"name":"Superconductor","description":"Increases the damage of your Arm of Thorim by an additional 1% per Static depleted.","rankDescriptions":["Increases the damage of your Arm of Thorim by an additional 1% per Static depleted."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29833","treeId":"coa-stormbringer-42","index":29833,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/spell_nature_lightningoverload.png","maxRank":1,"name":"Forked Lightning","description":"Shoot lightning at an enemy, dealing 69 + 49% SP Nature damage, bouncing to up to 4 enemies. Generates 5 Static for each enemy struck.","rankDescriptions":["Shoot lightning at an enemy, dealing 69 + 49% SP Nature damage, bouncing to up to 4 enemies. Generates 5 Static for each enemy struck."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29290","treeId":"coa-stormbringer-42","index":29290,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/shaman_pvp_staticcling.png","maxRank":1,"name":"Volt","description":"Fuse lightning into an enemy, dealing 150 + 114% nature SP Nature damage over 18 seconds and slowing them by -40%. Generates 2 Static per tick.","rankDescriptions":["Fuse lightning into an enemy, dealing 150 + 114% nature SP Nature damage over 18 seconds and slowing them by -40%. Generates 2 Static per tick."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":Line truncated
{"schemaVersion":1,"classId":"stormbringer","trees":[{"id":"coa-stormbringer-87","classId":"stormbringer","name":"Class","icon":"/assets/ui/spells/inv_misc_volatileair.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-stormbringer-42","classId":"stormbringer","name":"Lightning","icon":"/assets/ui/spells/epic_rpg_icon_pack_wind_icon_0002s_0000_lightning_border.png","background":"","description":"Lightning nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-stormbringer-43","classId":"stormbringer","name":"Wind","icon":"/assets/ui/spells/spell_nature_tranquility.png","background":"","description":"Wind nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-stormbringer-44","classId":"stormbringer","name":"Maelstrom","icon":"/assets/ui/spells/_liquidstone_water.png","background":"","description":"Maelstrom nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31163","treeId":"coa-stormbringer-42","index":31163,"prerequisiteId":"coa-entry-4013","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4013","requiredRank":1},{"talentId":"coa-entry-29138","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/epic_rpg_icon_pack_wind_icon_0002s_0000_lightning_border.png","maxRank":1,"name":"Arm of Thorim","description":"Depletes All Static Call down a terrible beam of lightning upon an enemy, dealing 135 + 120% nature SP Nature damage and stunning them for 1 seconds. Damage and cast time increased based on Static level.","rankDescriptions":["Depletes All Static Call down a terrible beam of lightning upon an enemy, dealing 135 + 120% nature SP Nature damage and stunning them for 1 seconds. Damage and cast time increased based on Static level."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4013","treeId":"coa-stormbringer-42","index":4013,"prerequisiteId":"coa-entry-29138","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29138","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/nhi_frozenlightning_border.png","maxRank":1,"name":"Electrocutioner","description":"Level 10 Passive Dealing spell damage now has a 5% chance to grant you Electrocutioner.Electrocutioner (Proc)Resets the cooldown of Electrocute and makes your next usable regardless of the target's health percentage. Chance increases based on Static level.","rankDescriptions":["Level 10 Passive Dealing spell damage now has a 5% chance to grant you Electrocutioner.Electrocutioner (Proc)Resets the cooldown of Electrocute and makes your next usable regardless of the target's health percentage. Chance increases based on Static level."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-29837","treeId":"coa-stormbringer-42","index":29837,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/ability_siege_engineer_magnetic_crush.png","maxRank":1,"name":"Superconductor","description":"Increases the damage of your Arm of Thorim by an additional 1% per Static depleted.","rankDescriptions":["Increases the damage of your Arm of Thorim by an additional 1% per Static depleted."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29833","treeId":"coa-stormbringer-42","index":29833,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/spell_nature_lightningoverload.png","maxRank":1,"name":"Forked Lightning","description":"Shoot lightning at an enemy, dealing 69 + 49% SP Nature damage, bouncing to up to 4 enemies. Generates 5 Static for each enemy struck.","rankDescriptions":["Shoot lightning at an enemy, dealing 69 + 49% SP Nature damage, bouncing to up to 4 enemies. Generates 5 Static for each enemy struck."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29290","treeId":"coa-stormbringer-42","index":29290,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/shaman_pvp_staticcling.png","maxRank":1,"name":"Volt","description":"Fuse lightning into an enemy, dealing 150 + 114% nature SP Nature damage over 18 seconds and slowing them by -40%. Generates 2 Static per tick.","rankDescriptions":["Fuse lightning into an enemy, dealing 150 + 114% nature SP Nature damage over 18 seconds and slowing them by -40%. Generates 2 Static per tick."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":Line truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"sun-cleric","trees":[{"id":"coa-sun-cleric-72","classId":"sun-cleric","name":"Seraphim","icon":"/assets/ui/spells/nhi_energyshield_border.png","background":"","description":"Seraphim nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-sun-cleric-70","classId":"sun-cleric","name":"Piety","icon":"/assets/ui/spells/nhi_fire_solar_border.png","background":"","description":"Piety nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-sun-cleric-90","classId":"sun-cleric","name":"Valkyrie","icon":"/assets/ui/spells/inv_sword_2h_armyoflight_c_01.png","background":"","description":"Valkyrie nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-sun-cleric-71","classId":"sun-cleric","name":"Blessings","icon":"/assets/ui/spells/ability_priest_ascendance.png","background":"","description":"Blessings nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-sun-cleric-87","classId":"sun-cleric","name":"Class","icon":"/assets/ui/spells/paladin_holy.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31194","treeId":"coa-sun-cleric-70","index":31194,"prerequisiteId":"coa-entry-4046","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4046","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/nhi_fire_solar_border.png","maxRank":1,"name":"Dawnsear","description":"Blast an enemy with burning light, dealing 88 + 100% fire SP Fire damage.","rankDescriptions":["Blast an enemy with burning light, dealing 88 + 100% fire SP Fire damage."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4046","treeId":"coa-sun-cleric-70","index":4046,"prerequisiteId":"coa-entry-29510","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29510","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_holymeditation_border.png","maxRank":1,"name":"Sunrise and Sunset","description":"Level 10 Passive After activating Dawn, casting a Holy spell grants Sunrise or casting a Fire spell grants Sunset. Entering Sunrise or Sunset prevents you from entering the other until you enter the next. SunriseIncreases all Holy Damage dealt by 20% for 2 minutes. SunsetIncreases your critical strike chance with Fire spells by 20% and Fire Damage by 10% for 2 minutes.","rankDescriptions":["Level 10 Passive After activating Dawn, casting a Holy spell grants Sunrise or casting a Fire spell grants Sunset. Entering Sunrise or Sunset prevents you from entering the other until you enter the next. SunriseIncreases all Holy Damage dealt by 20% for 2 minutes. SunsetIncreases your critical strike chance with Fire spells by 20% and Fire Damage by 10% for 2 minutes."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-30957","treeId":"coa-sun-cleric-70","index":30957,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/nhi_holysparks_border.png","maxRank":1,"name":"Radiant Flame","description":"Launch radiant spheres at an enemy each dealing 31 + 20.69% SP Holyflame Damage, repeating every 1 sec for 4 seconds.","rankDescriptions":["Launch radiant spheres at an enemy each dealing 31 + 20.69% SP Holyflame Damage, repeating every 1 sec for 4 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34050","treeId":"coa-sun-cleric-70","index":34050,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/inv_shield_1h_artifactstormfist_d_03.png","maxRank":1,"name":"Scorch Marks","description":"Casting Dawnsear and Sunflare now have a 40% chance to grant Scorch Marks for 10 seconds.Scorch MarksYour next Radiant Flame has no mana cost, ticks -50% faster, and its duration is reduced by -50%.","rankDescriptions":["Casting Dawnsear and Sunflare now have a 40% chance to grant Scorch Marks for 10 seconds.Scorch MarksYour next Radiant Flame has no mana cost, ticks -50% faster, and its duration is reduced by -50%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30311","treeId":"coa-sun-cleric-70","index":30311,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/custom_t_fireinourhands_border.png","maxRank":1,"name":"Solar Conduit","description":"Reduces the cast time of Dawnsear by -20% while Dawn is active.","rankDescriptions":["Reduces the cast time of Dawnsear by -20% while Dawn is active."],"system":"coa","entryType":"TLine truncated
{"schemaVersion":1,"classId":"sun-cleric","trees":[{"id":"coa-sun-cleric-87","classId":"sun-cleric","name":"Class","icon":"/assets/ui/spells/paladin_holy.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-sun-cleric-70","classId":"sun-cleric","name":"Piety","icon":"/assets/ui/spells/nhi_fire_solar_border.png","background":"","description":"Piety nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-sun-cleric-71","classId":"sun-cleric","name":"Blessings","icon":"/assets/ui/spells/ability_priest_ascendance.png","background":"","description":"Blessings nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-sun-cleric-90","classId":"sun-cleric","name":"Valkyrie","icon":"/assets/ui/spells/inv_sword_2h_armyoflight_c_01.png","background":"","description":"Valkyrie nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-sun-cleric-72","classId":"sun-cleric","name":"Seraphim","icon":"/assets/ui/spells/nhi_energyshield_border.png","background":"","description":"Seraphim nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31194","treeId":"coa-sun-cleric-70","index":31194,"prerequisiteId":"coa-entry-4046","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4046","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/nhi_fire_solar_border.png","maxRank":1,"name":"Dawnsear","description":"Blast an enemy with burning light, dealing 88 + 100% fire SP Fire damage.","rankDescriptions":["Blast an enemy with burning light, dealing 88 + 100% fire SP Fire damage."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4046","treeId":"coa-sun-cleric-70","index":4046,"prerequisiteId":"coa-entry-29510","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29510","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_holymeditation_border.png","maxRank":1,"name":"Sunrise and Sunset","description":"Level 10 Passive After activating Dawn, casting a Holy spell grants Sunrise or casting a Fire spell grants Sunset. Entering Sunrise or Sunset prevents you from entering the other until you enter the next. SunriseIncreases all Holy Damage dealt by 20% for 2 minutes. SunsetIncreases your critical strike chance with Fire spells by 20% and Fire Damage by 10% for 2 minutes.","rankDescriptions":["Level 10 Passive After activating Dawn, casting a Holy spell grants Sunrise or casting a Fire spell grants Sunset. Entering Sunrise or Sunset prevents you from entering the other until you enter the next. SunriseIncreases all Holy Damage dealt by 20% for 2 minutes. SunsetIncreases your critical strike chance with Fire spells by 20% and Fire Damage by 10% for 2 minutes."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-30957","treeId":"coa-sun-cleric-70","index":30957,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/nhi_holysparks_border.png","maxRank":1,"name":"Radiant Flame","description":"Launch radiant spheres at an enemy each dealing 31 + 20.69% SP Holyflame Damage, repeating every 1 sec for 4 seconds.","rankDescriptions":["Launch radiant spheres at an enemy each dealing 31 + 20.69% SP Holyflame Damage, repeating every 1 sec for 4 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34050","treeId":"coa-sun-cleric-70","index":34050,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/inv_shield_1h_artifactstormfist_d_03.png","maxRank":1,"name":"Scorch Marks","description":"Casting Dawnsear and Sunflare now have a 40% chance to grant Scorch Marks for 10 seconds.Scorch MarksYour next Radiant Flame has no mana cost, ticks -50% faster, and its duration is reduced by -50%.","rankDescriptions":["Casting Dawnsear and Sunflare now have a 40% chance to grant Scorch Marks for 10 seconds.Scorch MarksYour next Radiant Flame has no mana cost, ticks -50% faster, and its duration is reduced by -50%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30311","treeId":"coa-sun-cleric-70","index":30311,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/custom_t_fireinourhands_border.png","maxRank":1,"name":"Solar Conduit","description":"Reduces the cast time of Dawnsear by -20% while Dawn is active.","rankDescriptions":["Reduces the cast time of Dawnsear by -20% while Dawn is active."],"system":"coa","entryType":"TLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"templar","trees":[{"id":"coa-templar-50","classId":"templar","name":"Zealot","icon":"/assets/ui/spells/nhi_holystrike_border.png","background":"","description":"Zealot nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-templar-16","classId":"templar","name":"Oathkeeper","icon":"/assets/ui/spells/5_staffstrike_border.png","background":"","description":"Oathkeeper nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-templar-51","classId":"templar","name":"Crusader","icon":"/assets/ui/spells/_whirlwind_yellow.png","background":"","description":"Crusader nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-templar-87","classId":"templar","name":"Class","icon":"/assets/ui/spells/nhi_holymeditation_border.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31173","treeId":"coa-templar-16","index":31173,"prerequisiteId":"coa-entry-4023","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4023","requiredRank":1},{"talentId":"coa-entry-34402","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/5_staffstrike_border.png","maxRank":1,"name":"Sacred Swing","description":"Swing at enemies in front of you, dealing 125% High Threat Weapon Damage plus 9, slowing their attack and movement speed by -20% for 10 seconds. Only usable after avoiding an attack.","rankDescriptions":["Swing at enemies in front of you, dealing 125% High Threat Weapon Damage plus 9, slowing their attack and movement speed by -20% for 10 seconds. Only usable after avoiding an attack."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4023","treeId":"coa-templar-16","index":4023,"prerequisiteId":"coa-entry-34402","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-34402","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/inv_staff_2h_nazmirraid_d_01.png","maxRank":1,"name":"Keeping the Oath","description":"Level 10 Passive You now delay 40% of direct damage taken, instead taking it over 8 seconds. In addition, you no longer consume your Oaths with Oath Breakers.","rankDescriptions":["Level 10 Passive You now delay 40% of direct damage taken, instead taking it over 8 seconds. In addition, you no longer consume your Oaths with Oath Breakers."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-34395","treeId":"coa-templar-16","index":34395,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":2,"icon":"/assets/ui/spells/spell_holy_powerwordshield.png","maxRank":2,"name":"Blessed Padding","description":"Increases your Armor contribution from mail items by 100% and reduces damage taken from area of effect attacks by -20%.","rankDescriptions":["Increases your Armor contribution from mail items by 50% and reduces damage taken from area of effect attacks by -10%.","Increases your Armor contribution from mail items by 100% and reduces damage taken from area of effect attacks by -20%."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29717","treeId":"coa-templar-16","index":29717,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":2,"icon":"/assets/ui/spells/inv_staff_05.png","maxRank":1,"name":"Staffguard","description":"Casting Sacred Swing now grants you Staffguard, absorbing 125 + 30% Stamina damage, scaling with Stamina, parry and dodge rating, for 8 seconds.","rankDescriptions":["Casting Sacred Swing now grants you Staffguard, absorbing 125 + 30% Stamina damage, scaling with Stamina, parry and dodge rating, for 8 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30437","treeId":"coa-templar-16","index":30437,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":2,"row":3,"icon":"/assets/ui/spells/spell_holy_surgeoflight.png","maxRank":1,"name":"Paragon","description":"Increases your Stamina by 10, plus an additional amount equal to 10% of your Agility.","rankDescriptions":["Increases your Stamina by 10, plus an additional amount equal to 10% of your Agility."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6376","treeId":"coa-templar-16","index":6376,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_holyrod_border.png","maxRank":1,"name":"Reckoning","description":"UnLine truncated
{"schemaVersion":1,"classId":"templar","trees":[{"id":"coa-templar-87","classId":"templar","name":"Class","icon":"/assets/ui/spells/nhi_holymeditation_border.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-templar-50","classId":"templar","name":"Zealot","icon":"/assets/ui/spells/nhi_holystrike_border.png","background":"","description":"Zealot nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-templar-16","classId":"templar","name":"Oathkeeper","icon":"/assets/ui/spells/5_staffstrike_border.png","background":"","description":"Oathkeeper nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-templar-51","classId":"templar","name":"Crusader","icon":"/assets/ui/spells/_whirlwind_yellow.png","background":"","description":"Crusader nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31173","treeId":"coa-templar-16","index":31173,"prerequisiteId":"coa-entry-4023","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4023","requiredRank":1},{"talentId":"coa-entry-34402","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/5_staffstrike_border.png","maxRank":1,"name":"Sacred Swing","description":"Swing at enemies in front of you, dealing 140% High Threat Weapon Damage plus 13, slowing their attack and movement speed by -20% for 10 seconds. Only usable after avoiding an attack.","rankDescriptions":["Swing at enemies in front of you, dealing 140% High Threat Weapon Damage plus 13, slowing their attack and movement speed by -20% for 10 seconds. Only usable after avoiding an attack."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4023","treeId":"coa-templar-16","index":4023,"prerequisiteId":"coa-entry-34402","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-34402","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/inv_staff_2h_nazmirraid_d_01.png","maxRank":1,"name":"Keeping the Oath","description":"Level 10 Passive You now delay 40% of direct damage taken, instead taking it over 8 seconds. In addition, you no longer consume your Oaths with Oath Breakers.","rankDescriptions":["Level 10 Passive You now delay 40% of direct damage taken, instead taking it over 8 seconds. In addition, you no longer consume your Oaths with Oath Breakers."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":1,"isPassive":true},{"id":"coa-entry-34395","treeId":"coa-templar-16","index":34395,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":2,"icon":"/assets/ui/spells/spell_holy_powerwordshield.png","maxRank":2,"name":"Blessed Padding","description":"Increases your Armor contribution from mail items by 100% and reduces damage taken from area of effect attacks by -20%.","rankDescriptions":["Increases your Armor contribution from mail items by 50% and reduces damage taken from area of effect attacks by -10%.","Increases your Armor contribution from mail items by 100% and reduces damage taken from area of effect attacks by -20%."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29717","treeId":"coa-templar-16","index":29717,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":2,"icon":"/assets/ui/spells/inv_staff_05.png","maxRank":1,"name":"Staffguard","description":"Casting Sacred Swing now grants you Staffguard, absorbing 125 + 30% Stamina damage, scaling with Stamina, parry and dodge rating, for 8 seconds.","rankDescriptions":["Casting Sacred Swing now grants you Staffguard, absorbing 125 + 30% Stamina damage, scaling with Stamina, parry and dodge rating, for 8 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-30437","treeId":"coa-templar-16","index":30437,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":2,"row":3,"icon":"/assets/ui/spells/spell_holy_surgeoflight.png","maxRank":1,"name":"Paragon","description":"Increases your Stamina by 10, plus an additional amount equal to 10% of your Agility.","rankDescriptions":["Increases your Stamina by 10, plus an additional amount equal to 10% of your Agility."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6376","treeId":"coa-templar-16","index":6376,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_holyrod_border.png","maxRank":1,"name":"Reckoning","description":"Line truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"tinker","trees":[{"id":"coa-tinker-87","classId":"tinker","name":"Class","icon":"/assets/ui/spells/inv_gizmo_rocketbootextreme.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-tinker-75","classId":"tinker","name":"Mechanics","icon":"/assets/ui/spells/custom_engineerskill_49_border.png","background":"","description":"Mechanics nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-tinker-74","classId":"tinker","name":"Invention","icon":"/assets/ui/spells/spell_mekkatorque_bot_greenspring.png","background":"","description":"Invention nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-tinker-73","classId":"tinker","name":"Demolition","icon":"/assets/ui/spells/5_bomb_border.png","background":"","description":"Demolition nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-6828","treeId":"coa-tinker-73","index":6828,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/5_bomb_border.png","maxRank":1,"name":"Bomb Toss","description":"Lob a bomb at an enemy, dealing 36 + 30% ranged AP + 50% fire SP Fire damage and reducing their armor by -5% for 15 seconds, stacking 4 times.","rankDescriptions":["Lob a bomb at an enemy, dealing 36 + 30% ranged AP + 50% fire SP Fire damage and reducing their armor by -5% for 15 seconds, stacking 4 times."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4049","treeId":"coa-tinker-73","index":4049,"prerequisiteId":"coa-entry-31113","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-31113","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/inv_eng_bombfire.png","maxRank":1,"name":"Napalm","description":"Level 10 Passive Dealing direct Fire damage now applies Napalm to your target.Napalm (Damage)Fire Damage taken by you is increased and healing received reduced by -3% for 8 seconds. Stacks 10 times.","rankDescriptions":["Level 10 Passive Dealing direct Fire damage now applies Napalm to your target.Napalm (Damage)Fire Damage taken by you is increased and healing received reduced by -3% for 8 seconds. Stacks 10 times."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-29613","treeId":"coa-tinker-73","index":29613,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/ability_racial_rocketbarrage.png","maxRank":1,"name":"Rocket Launcher","description":"Fire a powerful rocket at an enemy that deals 126 + 35% ranged AP + 35% fire SP Fire damage.","rankDescriptions":["Fire a powerful rocket at an enemy that deals 126 + 35% ranged AP + 35% fire SP Fire damage."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7001","treeId":"coa-tinker-73","index":7001,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/ability_siege_engineer_detonate.png","maxRank":1,"name":"Build: Spider Bomb","description":"Build a Spider Bomb that will immediately run towards your target and detonate dealing 250 + 30% ranged AP Fire damage in an 8 yd radius. Using Scrap Shot will redirect the Spider Bombs to your new target.","rankDescriptions":["Build a Spider Bomb that will immediately run towards your target and detonate dealing 250 + 30% ranged AP Fire damage in an 8 yd radius. Using Scrap Shot will redirect the Spider Bombs to your new target."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34996","treeId":"coa-tinker-73","index":34996,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/nhi_holybullet_border.png","maxRank":2,"name":"Incendiary Bullets","description":"Increases the damage of Scrap Shot by 30% and increases your chance to hit by 4%.","rankDescriptions":["Increases the damage of Scrap Shot by 15% and increases your chance to hit by 2%.","Increases the damage of Scrap Shot by 30% and increases your chance to hit by 4%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-9621","treeId":"coa-tinker-73","index":9621,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":11,"row":3,"icon":"/assets/ui/spells/nhi_tech_rocket_border.png","maxRank":1,"name":"Sparked and Ready!","description":"Level 20 Passive Fire damage dealt has a 5% chance to grant you Sparked andLine truncated
{"schemaVersion":1,"classId":"tinker","trees":[{"id":"coa-tinker-87","classId":"tinker","name":"Class","icon":"/assets/ui/spells/inv_gizmo_rocketbootextreme.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-tinker-73","classId":"tinker","name":"Demolition","icon":"/assets/ui/spells/5_bomb_border.png","background":"","description":"Demolition nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-tinker-74","classId":"tinker","name":"Invention","icon":"/assets/ui/spells/spell_mekkatorque_bot_greenspring.png","background":"","description":"Invention nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-tinker-75","classId":"tinker","name":"Mechanics","icon":"/assets/ui/spells/custom_engineerskill_49_border.png","background":"","description":"Mechanics nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-6828","treeId":"coa-tinker-73","index":6828,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":1,"icon":"/assets/ui/spells/5_bomb_border.png","maxRank":1,"name":"Bomb Toss","description":"Lob a bomb at an enemy, dealing 36 + 30% ranged AP + 50% fire SP Fire damage and reducing their armor by -5% for 15 seconds, stacking 4 times.","rankDescriptions":["Lob a bomb at an enemy, dealing 36 + 30% ranged AP + 50% fire SP Fire damage and reducing their armor by -5% for 15 seconds, stacking 4 times."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4049","treeId":"coa-tinker-73","index":4049,"prerequisiteId":"coa-entry-31113","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-31113","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/inv_eng_bombfire.png","maxRank":1,"name":"Napalm","description":"Level 10 Passive Dealing direct Fire damage now applies Napalm to your target.Napalm (Damage)Fire Damage taken by you is increased and healing received reduced by -3% for 8 seconds. Stacks 10 times.","rankDescriptions":["Level 10 Passive Dealing direct Fire damage now applies Napalm to your target.Napalm (Damage)Fire Damage taken by you is increased and healing received reduced by -3% for 8 seconds. Stacks 10 times."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-29613","treeId":"coa-tinker-73","index":29613,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/ability_racial_rocketbarrage.png","maxRank":1,"name":"Rocket Launcher","description":"Fire a powerful rocket at an enemy that deals 126 + 35% ranged AP + 35% fire SP Fire damage.","rankDescriptions":["Fire a powerful rocket at an enemy that deals 126 + 35% ranged AP + 35% fire SP Fire damage."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7001","treeId":"coa-tinker-73","index":7001,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/ability_siege_engineer_detonate.png","maxRank":1,"name":"Build: Spider Bomb","description":"Build a Spider Bomb that will immediately run towards your target and detonate dealing 250 + 18% ranged AP + 18% SP Fire damage in an 8 yd radius. Using Scrap Shot will redirect the Spider Bombs to your new target.","rankDescriptions":["Build a Spider Bomb that will immediately run towards your target and detonate dealing 250 + 18% ranged AP + 18% SP Fire damage in an 8 yd radius. Using Scrap Shot will redirect the Spider Bombs to your new target."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34996","treeId":"coa-tinker-73","index":34996,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":3,"icon":"/assets/ui/spells/nhi_holybullet_border.png","maxRank":2,"name":"Incendiary Bullets","description":"Increases the damage of Scrap Shot by 30% and increases your chance to hit by 4%.","rankDescriptions":["Increases the damage of Scrap Shot by 15% and increases your chance to hit by 2%.","Increases the damage of Scrap Shot by 30% and increases your chance to hit by 4%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-9621","treeId":"coa-tinker-73","index":9621,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":11,"row":3,"icon":"/assets/ui/spells/nhi_tech_rocket_border.png","maxRank":1,"name":"Sparked and Ready!","description":"Level 20 Passive Fire damage dealt has a 5% chance to graLine truncated
+1 -1
View File
@@ -1 +1 @@
{"schemaVersion":1,"classId":"venomancer","trees":[{"id":"coa-venomancer-92","classId":"venomancer","name":"Vizier","icon":"/assets/ui/spells/nhi_natureburn_border.png","background":"","description":"Vizier nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-venomancer-76","classId":"venomancer","name":"Venom","icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_naturewrath_border.png","background":"","description":"Venom nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-venomancer-77","classId":"venomancer","name":"Stalking","icon":"/assets/ui/spells/inv_spidermountc5.png","background":"","description":"Stalking nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-venomancer-78","classId":"venomancer","name":"Fortitude","icon":"/assets/ui/spells/achievment_boss_wellofeternity.png","background":"","description":"Fortitude nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-venomancer-87","classId":"venomancer","name":"Class","icon":"/assets/ui/spells/inv_pet_shalespider.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-30477","treeId":"coa-venomancer-76","index":30477,"prerequisiteId":"coa-entry-4052","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4052","requiredRank":1},{"talentId":"coa-entry-29607","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_naturewrath_border.png","maxRank":1,"name":"Wilt","description":"Wilt the life of an enemy with vile poison, dealing 144 Nature damage over 18 seconds.","rankDescriptions":["Wilt the life of an enemy with vile poison, dealing 144 Nature damage over 18 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4052","treeId":"coa-venomancer-76","index":4052,"prerequisiteId":"coa-entry-29607","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29607","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/_instableaffliction_green.png","maxRank":1,"name":"Rot Lich","description":"Level 10 Passive Direct damage dealt now has a 20% chance to reset the cooldown of Serpent's Fang and grant you Rot Lich and allies Replenishment.Rot Lich (Proc)Your next Serpent's Fang within 15 seconds is free of cost.ReplenishmentReplenishes 5% of maximum mana per 5 sec for 15 seconds.","rankDescriptions":["Level 10 Passive Direct damage dealt now has a 20% chance to reset the cooldown of Serpent's Fang and grant you Rot Lich and allies Replenishment.Rot Lich (Proc)Your next Serpent's Fang within 15 seconds is free of cost.ReplenishmentReplenishes 5% of maximum mana per 5 sec for 15 seconds."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-30606","treeId":"coa-venomancer-76","index":30606,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/nhi_unholy_mushroom_border.png","maxRank":1,"name":"Spore","description":"Inject an enemy with parasitic spores, dealing 20 + 17.5% nature SP Shadow damage, plus an additional 231 over 21 seconds. After 10 sec, drop a Mushroom below the target that explodes after 2 sec, dealing 303 + 25% nature SP Nature damage to nearby enemies.","rankDescriptions":["Inject an enemy with parasitic spores, dealing 20 + 17.5% nature SP Shadow damage, plus an additional 231 over 21 seconds. After 10 sec, drop a Mushroom below the target that explodes after 2 sec, dealing 303 + 25% nature SP Nature damage to nearby enemies."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7219","treeId":"coa-venomancer-76","index":7219,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_natureportal_border.png","maxRank":2,"name":"Protraction","description":"Increases the duration of your Venomancer periodic damage effects by 6 sec.","rankDescriptions":["Increases the duration of your Venomancer periodic damage effects by 3 sec.","Increases the duration of your Venomancer periodic damage effects by 6 sec."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6137","treeId":"coa-venomancer-76","index":6137,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/inv_misc_starspecklemushroom.png","maxRank":1,"name":"Fungal Growth","description":"Shadow and Nature damage dealt now has a 35% chance to increase periodic damage you deal to the target by 2% for 30 seconds, stacking 10 times.","rankDescriLine truncated
{"schemaVersion":1,"classId":"venomancer","trees":[{"id":"coa-venomancer-76","classId":"venomancer","name":"Venom","icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_naturewrath_border.png","background":"","description":"Venom nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-venomancer-77","classId":"venomancer","name":"Stalking","icon":"/assets/ui/spells/inv_spidermountc5.png","background":"","description":"Stalking nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-venomancer-78","classId":"venomancer","name":"Fortitude","icon":"/assets/ui/spells/achievment_boss_wellofeternity.png","background":"","description":"Fortitude nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-venomancer-87","classId":"venomancer","name":"Class","icon":"/assets/ui/spells/inv_pet_shalespider.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-venomancer-92","classId":"venomancer","name":"Vizier","icon":"/assets/ui/spells/nhi_natureburn_border.png","background":"","description":"Vizier nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-30477","treeId":"coa-venomancer-76","index":30477,"prerequisiteId":"coa-entry-4052","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4052","requiredRank":1},{"talentId":"coa-entry-29607","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_naturewrath_border.png","maxRank":1,"name":"Wilt","description":"Wilt the life of an enemy with vile poison, dealing 144 Nature damage over 18 seconds.","rankDescriptions":["Wilt the life of an enemy with vile poison, dealing 144 Nature damage over 18 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4052","treeId":"coa-venomancer-76","index":4052,"prerequisiteId":"coa-entry-29607","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29607","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/_instableaffliction_green.png","maxRank":1,"name":"Rot Lich","description":"Level 10 Passive Direct damage dealt now has a 20% chance to reset the cooldown of Serpent's Fang and grant you Rot Lich and allies Replenishment.Rot Lich (Proc)Your next Serpent's Fang within 15 seconds is free of cost.ReplenishmentReplenishes 5% of maximum mana per 5 sec for 15 seconds.","rankDescriptions":["Level 10 Passive Direct damage dealt now has a 20% chance to reset the cooldown of Serpent's Fang and grant you Rot Lich and allies Replenishment.Rot Lich (Proc)Your next Serpent's Fang within 15 seconds is free of cost.ReplenishmentReplenishes 5% of maximum mana per 5 sec for 15 seconds."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-30606","treeId":"coa-venomancer-76","index":30606,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":2,"icon":"/assets/ui/spells/nhi_unholy_mushroom_border.png","maxRank":1,"name":"Spore","description":"Inject an enemy with parasitic spores, dealing 20 + 17.5% nature SP Shadow damage, plus an additional 231 over 21 seconds. After 10 sec, drop a Mushroom below the target that explodes after 2 sec, dealing 303 + 25% nature SP Nature damage to nearby enemies.","rankDescriptions":["Inject an enemy with parasitic spores, dealing 20 + 17.5% nature SP Shadow damage, plus an additional 231 over 21 seconds. After 10 sec, drop a Mushroom below the target that explodes after 2 sec, dealing 303 + 25% nature SP Nature damage to nearby enemies."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-7219","treeId":"coa-venomancer-76","index":7219,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/custom_t_nhance_rpg_icons_natureportal_border.png","maxRank":2,"name":"Protraction","description":"Increases the duration of your Venomancer periodic damage effects by 6 sec.","rankDescriptions":["Increases the duration of your Venomancer periodic damage effects by 3 sec.","Increases the duration of your Venomancer periodic damage effects by 6 sec."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-6137","treeId":"coa-venomancer-76","index":6137,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/inv_misc_starspecklemushroom.png","maxRank":1,"name":"Fungal Growth","description":"Shadow and Nature damage dealt now has a 35% chance to increase periodic damage you deal to the target by 2% for 30 seconds, stacking 10 times.","rankDescriLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"witch-doctor","trees":[{"id":"coa-witch-doctor-36","classId":"witch-doctor","name":"Shadowhunting","icon":"/assets/ui/spells/nhi_naturearrow_(2)_border.png","background":"","description":"Shadowhunting nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-doctor-34","classId":"witch-doctor","name":"Voodoo","icon":"/assets/ui/spells/custom_45_voodoo_border.png","background":"","description":"Voodoo nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-doctor-35","classId":"witch-doctor","name":"Brewing","icon":"/assets/ui/spells/inv_mushroom_07.png","background":"","description":"Brewing nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-doctor-87","classId":"witch-doctor","name":"Class","icon":"/assets/ui/spells/nhi_naturehide_border.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31154","treeId":"coa-witch-doctor-34","index":31154,"prerequisiteId":"coa-entry-4004","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4004","requiredRank":1},{"talentId":"coa-entry-29301","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/custom_45_voodoo_border.png","maxRank":1,"name":"Shadow Puppets","description":"Summon a Shadow Puppet that collects a Spirit and rushes towards your target, dealing 25 + 22% shadow SP Shadow damage, repeating every 1 sec for 3 seconds.","rankDescriptions":["Summon a Shadow Puppet that collects a Spirit and rushes towards your target, dealing 25 + 22% shadow SP Shadow damage, repeating every 1 sec for 3 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4004","treeId":"coa-witch-doctor-34","index":4004,"prerequisiteId":"coa-entry-29301","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29301","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/trade_archaeology_troll_voodoodoll.png","maxRank":1,"name":"Puppeteer's Threads","description":"Level 10 Passive Damaging abilities now leave behind Puppeteer's Threads on enemies for 10 seconds. Puppeteer’s Threads (Debuff)Damage taken from the Witch Doctor stores 15% of its value. When the effect ends the damage stored is dealt instantly.","rankDescriptions":["Level 10 Passive Damaging abilities now leave behind Puppeteer's Threads on enemies for 10 seconds. Puppeteer’s Threads (Debuff)Damage taken from the Witch Doctor stores 15% of its value. When the effect ends the damage stored is dealt instantly."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-31345","treeId":"coa-witch-doctor-34","index":31345,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":4,"row":2,"icon":"/assets/ui/spells/nhi_spiritualrage_border.png","maxRank":2,"name":"Loa Spirits","description":"Damage dealt and healing done now has a 15% chance to collect a Spirit. In addition, each active Spirit now increases your Spirit by 4%.SpiritRegenerates 7 health and mana, repeating every 4 sec for 12 seconds, stacking 5 times.","rankDescriptions":["Damage dealt and healing done now has a 8% chance to collect a Spirit. In addition, each active Spirit now increases your Spirit by 2%.SpiritRegenerates 7 health and mana, repeating every 4 sec for 12 seconds, stacking 5 times.","Damage dealt and healing done now has a 15% chance to collect a Spirit. In addition, each active Spirit now increases your Spirit by 4%.SpiritRegenerates 7 health and mana, repeating every 4 sec for 12 seconds, stacking 5 times."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-31344","treeId":"coa-witch-doctor-34","index":31344,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":6,"row":2,"icon":"/assets/ui/spells/achievement_zone_tanaanjungle.png","maxRank":1,"name":"Stranglethorn Style","description":"Increases your critical strike chance by 4% and reduces threat generated by your Voodoo spells by -20%.","rankDescriptions":["Increases your critical strike chance by 4% and reduces threat generated by your Voodoo spells by -20%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29928","treeId":"coa-witch-doctor-34","index":29928,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/skill_icon_skill5_border.png","maxRank":1,"name":"Bad Juju","description":"Hurl a bolt of dark magic at an enemy, dealing 191 + 100% SP + 30% Spirit Shadow damage. If the target is affected by Hex of Malice it also redLine truncated
{"schemaVersion":1,"classId":"witch-doctor","trees":[{"id":"coa-witch-doctor-87","classId":"witch-doctor","name":"Class","icon":"/assets/ui/spells/nhi_naturehide_border.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-doctor-34","classId":"witch-doctor","name":"Voodoo","icon":"/assets/ui/spells/custom_45_voodoo_border.png","background":"","description":"Voodoo nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-doctor-35","classId":"witch-doctor","name":"Brewing","icon":"/assets/ui/spells/inv_mushroom_07.png","background":"","description":"Brewing nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-doctor-36","classId":"witch-doctor","name":"Shadowhunting","icon":"/assets/ui/spells/nhi_naturearrow_(2)_border.png","background":"","description":"Shadowhunting nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31154","treeId":"coa-witch-doctor-34","index":31154,"prerequisiteId":"coa-entry-4004","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4004","requiredRank":1},{"talentId":"coa-entry-29301","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/custom_45_voodoo_border.png","maxRank":1,"name":"Shadow Puppets","description":"Summon a Shadow Puppet that collects a Spirit and rushes towards your target, dealing 25 + 22% shadow SP Shadow damage, repeating every 1 sec for 3 seconds.","rankDescriptions":["Summon a Shadow Puppet that collects a Spirit and rushes towards your target, dealing 25 + 22% shadow SP Shadow damage, repeating every 1 sec for 3 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4004","treeId":"coa-witch-doctor-34","index":4004,"prerequisiteId":"coa-entry-29301","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29301","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/trade_archaeology_troll_voodoodoll.png","maxRank":1,"name":"Puppeteer's Threads","description":"Level 10 Passive Damaging abilities now leave behind Puppeteer's Threads on enemies for 10 seconds. Puppeteer’s Threads (Debuff)Damage taken from the Witch Doctor stores 15% of its value. When the effect ends the damage stored is dealt instantly.","rankDescriptions":["Level 10 Passive Damaging abilities now leave behind Puppeteer's Threads on enemies for 10 seconds. Puppeteer’s Threads (Debuff)Damage taken from the Witch Doctor stores 15% of its value. When the effect ends the damage stored is dealt instantly."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-31345","treeId":"coa-witch-doctor-34","index":31345,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":4,"row":2,"icon":"/assets/ui/spells/nhi_spiritualrage_border.png","maxRank":2,"name":"Loa Spirits","description":"Damage dealt and healing done now has a 15% chance to collect a Spirit. In addition, each active Spirit now increases your Spirit by 4%.SpiritRegenerates 7 health and mana, repeating every 4 sec for 12 seconds, stacking 5 times.","rankDescriptions":["Damage dealt and healing done now has a 8% chance to collect a Spirit. In addition, each active Spirit now increases your Spirit by 2%.SpiritRegenerates 7 health and mana, repeating every 4 sec for 12 seconds, stacking 5 times.","Damage dealt and healing done now has a 15% chance to collect a Spirit. In addition, each active Spirit now increases your Spirit by 4%.SpiritRegenerates 7 health and mana, repeating every 4 sec for 12 seconds, stacking 5 times."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-31344","treeId":"coa-witch-doctor-34","index":31344,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":6,"row":2,"icon":"/assets/ui/spells/achievement_zone_tanaanjungle.png","maxRank":1,"name":"Stranglethorn Style","description":"Increases your critical strike chance by 4% and reduces threat generated by your Voodoo spells by -20%.","rankDescriptions":["Increases your critical strike chance by 4% and reduces threat generated by your Voodoo spells by -20%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29928","treeId":"coa-witch-doctor-34","index":29928,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":3,"icon":"/assets/ui/spells/skill_icon_skill5_border.png","maxRank":1,"name":"Bad Juju","description":"Hurl a bolt of dark magic at an enemy, dealing 191 + 100% SP + 30% Spirit Shadow damage. If the target is affected by Hex of Malice it also redLine truncated
@@ -1 +1 @@
{"schemaVersion":1,"classId":"witch-hunter","trees":[{"id":"coa-witch-hunter-39","classId":"witch-hunter","name":"Boltslinger","icon":"/assets/ui/spells/_d3rapidfire.png","background":"","description":"Boltslinger nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-hunter-40","classId":"witch-hunter","name":"Houndmaster","icon":"/assets/ui/spells/unleashthehounds.png","background":"","description":"Houndmaster nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-hunter-41","classId":"witch-hunter","name":"Inquisition","icon":"/assets/ui/spells/5_run_border.png","background":"","description":"Inquisition nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-hunter-94","classId":"witch-hunter","name":"Black Knight","icon":"/assets/ui/spells/nhi_brokensword_border.png","background":"","description":"Black Knight nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-hunter-87","classId":"witch-hunter","name":"Class","icon":"/assets/ui/spells/ability_demonhunter_vengefulretreat2.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31160","treeId":"coa-witch-hunter-39","index":31160,"prerequisiteId":"coa-entry-4010","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4010","requiredRank":1},{"talentId":"coa-entry-29150","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/_d3rapidfire.png","maxRank":1,"name":"Witchbane","description":"Unleash a series of devastating shots dealing 60 + 45% ranged AP Physical damage over 3 seconds.","rankDescriptions":["Unleash a series of devastating shots dealing 60 + 45% ranged AP Physical damage over 3 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4010","treeId":"coa-witch-hunter-39","index":4010,"prerequisiteId":"coa-entry-29150","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29150","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/inv_weapon_crossbow_21.png","maxRank":1,"name":"Boltslinger","description":"Level 10 Passive You may now cast Darkslayer while moving. Ranged attacks and abilities now have a 25% chance to shoot an additional shot, dealing 20% ranged AP Physical damage and generating 5 Rage.","rankDescriptions":["Level 10 Passive You may now cast Darkslayer while moving. Ranged attacks and abilities now have a 25% chance to shoot an additional shot, dealing 20% ranged AP Physical damage and generating 5 Rage."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-5076","treeId":"coa-witch-hunter-39","index":5076,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":2,"icon":"/assets/ui/spells/ability_hunter_blindingshot.png","maxRank":1,"name":"Mechanized Crossbows","description":"Increases your ranged attack power by 10% and the range of your ranged abilities by 5 yds.","rankDescriptions":["Increases your ranged attack power by 10% and the range of your ranged abilities by 5 yds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34570","treeId":"coa-witch-hunter-39","index":34570,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":2,"icon":"/assets/ui/spells/inv_weapon_crossbow_32.png","maxRank":2,"name":"My Trusty Arbalest","description":"Reduces the Rage cost of Witchbane and Shadowblast by -20% and increases your chance to hit by 4%.","rankDescriptions":["Reduces the Rage cost of Witchbane and Shadowblast by -10% and increases your chance to hit by 2%.","Reduces the Rage cost of Witchbane and Shadowblast by -20% and increases your chance to hit by 4%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29372","treeId":"coa-witch-hunter-39","index":29372,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/nhi_shadowarrow_border.png","maxRank":1,"name":"Heartseeking Bolt","description":"Charge up a powerful bolt that deals 200% Ranged Weapon Damage plus 40 + 50% ranged AP + 30% shadow SP to an enemy and reduces their healing received by -30% for 10 seconds. Generates Rage based on the damage dealt.","rankDescriptions":["Charge up a powerful bolt that deals 200% Ranged Weapon Damage plus 40 + 50% ranged AP + 30% shadow SP to an enemy and reduces their healing received by -30% for 10 seconds. Generates Rage based on the damage dealt."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPLine truncated
{"schemaVersion":1,"classId":"witch-hunter","trees":[{"id":"coa-witch-hunter-87","classId":"witch-hunter","name":"Class","icon":"/assets/ui/spells/ability_demonhunter_vengefulretreat2.png","background":"","description":"Class nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-hunter-39","classId":"witch-hunter","name":"Boltslinger","icon":"/assets/ui/spells/_d3rapidfire.png","background":"","description":"Boltslinger nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-hunter-40","classId":"witch-hunter","name":"Houndmaster","icon":"/assets/ui/spells/inv_wolfdraenormountshadow.png","background":"","description":"Houndmaster nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-hunter-94","classId":"witch-hunter","name":"Black Knight","icon":"/assets/ui/spells/nhi_brokensword_border.png","background":"","description":"Black Knight nodes synchronized from Vol'Jin.","system":"coa"},{"id":"coa-witch-hunter-41","classId":"witch-hunter","name":"Inquisition","icon":"/assets/ui/spells/5_run_border.png","background":"","description":"Inquisition nodes synchronized from Vol'Jin.","system":"coa"}],"nodes":[{"id":"coa-entry-31160","treeId":"coa-witch-hunter-39","index":31160,"prerequisiteId":"coa-entry-4010","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-4010","requiredRank":1},{"talentId":"coa-entry-29150","requiredRank":1}],"column":5,"row":1,"icon":"/assets/ui/spells/_d3rapidfire.png","maxRank":1,"name":"Witchbane","description":"Unleash a series of devastating shots dealing 60 + 45% ranged AP Physical damage over 3 seconds.","rankDescriptions":["Unleash a series of devastating shots dealing 60 + 45% ranged AP Physical damage over 3 seconds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-4010","treeId":"coa-witch-hunter-39","index":4010,"prerequisiteId":"coa-entry-29150","prerequisiteRank":1,"prerequisites":[{"talentId":"coa-entry-29150","requiredRank":1}],"column":11,"row":1,"icon":"/assets/ui/spells/inv_weapon_crossbow_21.png","maxRank":1,"name":"Boltslinger","description":"Level 10 Passive You may now cast Darkslayer while moving. Ranged attacks and abilities now have a 25% chance to shoot an additional shot, dealing 20% ranged AP Physical damage and generating 5 Rage.","rankDescriptions":["Level 10 Passive You may now cast Darkslayer while moving. Ranged attacks and abilities now have a 25% chance to shoot an additional shot, dealing 20% ranged AP Physical damage and generating 5 Rage."],"system":"coa","entryType":"Ability","abilityEssenceCost":0,"talentEssenceCost":0,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":true},{"id":"coa-entry-5076","treeId":"coa-witch-hunter-39","index":5076,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":3,"row":2,"icon":"/assets/ui/spells/ability_hunter_blindingshot.png","maxRank":1,"name":"Mechanized Crossbows","description":"Increases your ranged attack power by 10% and the range of your ranged abilities by 5 yds.","rankDescriptions":["Increases your ranged attack power by 10% and the range of your ranged abilities by 5 yds."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-34570","treeId":"coa-witch-hunter-39","index":34570,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":7,"row":2,"icon":"/assets/ui/spells/inv_weapon_crossbow_32.png","maxRank":2,"name":"My Trusty Arbalest","description":"Reduces the Rage cost of Witchbane and Shadowblast by -20% and increases your chance to hit by 4%.","rankDescriptions":["Reduces the Rage cost of Witchbane and Shadowblast by -10% and increases your chance to hit by 2%.","Reduces the Rage cost of Witchbane and Shadowblast by -20% and increases your chance to hit by 4%."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"requiredSpecPoints":0,"requiredLevel":0,"isPassive":false},{"id":"coa-entry-29372","treeId":"coa-witch-hunter-39","index":29372,"prerequisiteId":null,"prerequisiteRank":null,"prerequisites":[],"column":5,"row":3,"icon":"/assets/ui/spells/nhi_shadowarrow_border.png","maxRank":1,"name":"Heartseeking Bolt","description":"Charge up a powerful bolt that deals 200% Ranged Weapon Damage plus 40 + 50% ranged AP + 30% shadow SP to an enemy and reduces their healing received by -30% for 10 seconds. Generates Rage based on the damage dealt.","rankDescriptions":["Charge up a powerful bolt that deals 200% Ranged Weapon Damage plus 40 + 50% ranged AP + 30% shadow SP to an enemy and reduces their healing received by -30% for 10 seconds. Generates Rage based on the damage dealt."],"system":"coa","entryType":"Talent","abilityEssenceCost":0,"talentEssenceCost":1,"requiredClassPoints":0,"reqLine truncated
@@ -0,0 +1 @@
{"source":{"product":"World of Warcraft","build":"3.3.5a.12340","archive":"../wow335a/Data/enUS/patch-enUS.MPQ","familyRows":40,"skillLineAbilityRows":10149,"spellRows":46583},"families":[{"id":1,"name":"Wolf","minScale":0.699999988079071,"minScaleLevel":1,"maxScale":1,"maxScaleLevel":60,"petFoodMask":1,"petTalentType":0,"familySkillLineId":208,"commonPetSkillLineId":270,"categoryEnumId":23,"hunterPet":true,"familySkills":[{"spellId":17223,"name":"Tamed Pet Passive (DND)","rankText":"","mechanic":0,"requiredLevel":0,"passive":true,"attributesEx1":0,"powerType":0,"powerCost":0,"cooldownMs":0,"categoryCooldownMs":0,"globalCooldownMs":0,"auraInterruptFlags":0,"schoolMask":0,"procFlags":0,"procChance":101,"procCharges":0,"durationMs":0,"effects":[{"index":0,"effectType":6,"auraType":79,"mechanic":0,"basePoints":5,"dieSides":1,"pointsPerLevel":0,"periodMs":0,"miscValue":1,"triggerSpellId":0,"coefficient":0},{"index":1,"effectType":6,"auraType":142,"mechanic":0,"basePoints":5,"dieSides":1,"pointsPerLevel":0,"periodMs":0,"miscValue":1,"triggerSpellId":0,"coefficient":0},{"index":2,"effectType":6,"auraType":133,"mechanic":0,"basePoints":5,"dieSides":1,"pointsPerLevel":0,"periodMs":0,"miscValue":0,"triggerSpellId":0,"coefficient":0}],"acquireMethod":2,"raceMask":0,"classMask":0,"minSkill":1,"supersededBySpellId":0},{"spellId":61684,"name":"Dash","rankText":"","mechanic":0,"requiredLevel":0,"passive":false,"attributesEx1":32,"powerType":2,"powerCost":30,"cooldownMs":32000,"categoryCooldownMs":0,"globalCooldownMs":0,"auraInterruptFlags":0,"schoolMask":0,"procFlags":0,"procChance":101,"procCharges":0,"durationMs":16000,"effects":[{"index":0,"effectType":6,"auraType":31,"mechanic":0,"basePoints":80,"dieSides":1,"pointsPerLevel":0,"periodMs":0,"miscValue":0,"triggerSpellId":0,"coefficient":0}],"acquireMethod":0,"raceMask":0,"classMask":0,"minSkill":1,"supersededBySpellId":0},{"spellId":61685,"name":"Charge","rankText":"","mechanic":0,"requiredLevel":0,"passive":false,"attributesEx1":1024,"powerType":2,"powerCost":35,"cooldownMs":25000,"categoryCooldownMs":0,"globalCooldownMs":1500,"auraInterruptFlags":0,"schoolMask":0,"procFlags":20,"procChance":101,"procCharges":1,"durationMs":4000,"effects":[{"index":0,"effectType":96,"auraType":0,"mechanic":0,"basePoints":1,"dieSides":0,"pointsPerLevel":0,"periodMs":0,"miscValue":0,"triggerSpellId":0,"coefficient":1},{"index":1,"effectType":6,"auraType":166,"mechanic":0,"basePoints":25,"dieSides":1,"pointsPerLevel":0,"periodMs":0,"miscValue":0,"triggerSpellId":0,"coefficient":1},{"index":2,"effectType":64,"auraType":0,"mechanic":0,"basePoints":1,"dieSides":0,"pointsPerLevel":0,"periodMs":0,"miscValue":0,"triggerSpellId":53148,"coefficient":1}],"acquireMethod":0,"raceMask":0,"classMask":0,"minSkill":1,"supersededBySpellId":0},{"spellId":17253,"name":"Bite","rankText":"Rank 1","mechanic":0,"requiredLevel":1,"passive":false,"attributesEx1":512,"powerType":2,"powerCost":25,"cooldownMs":0,"categoryCooldownMs":0,"globalCooldownMs":1500,"auraInterruptFlags":0,"schoolMask":0,"procFlags":0,"procChance":101,"procCharges":0,"durationMs":0,"effects":[{"index":0,"effectType":2,"auraType":0,"mechanic":0,"basePoints":4,"dieSides":3,"pointsPerLevel":0,"periodMs":0,"miscValue":0,"triggerSpellId":0,"coefficient":1}],"acquireMethod":2,"raceMask":0,"classMask":0,"minSkill":1,"supersededBySpellId":17255},{"spellId":24604,"name":"Furious Howl","rankText":"Rank 1","mechanic":0,"requiredLevel":1,"passive":false,"attributesEx1":512,"powerType":2,"powerCost":20,"cooldownMs":40000,"categoryCooldownMs":0,"globalCooldownMs":0,"auraInterruptFlags":0,"schoolMask":0,"procFlags":0,"procChance":101,"procCharges":0,"durationMs":20000,"effects":[{"index":0,"effectType":6,"auraType":99,"mechanic":0,"basePoints":18,"dieSides":1,"pointsPerLevel":0,"periodMs":0,"miscValue":1,"triggerSpellId":0,"coefficient":0},{"index":1,"effectType":6,"auraType":124,"mechanic":0,"basePoints":18,"dieSides":1,"pointsPerLevel":0,"periodMs":0,"miscValue":0,"triggerSpellId":0,"coefficient":0}],"acquireMethod":2,"raceMask":0,"classMask":0,"minSkill":1,"supersededBySpellId":64491},{"spellId":17255,"name":"Bite","rankText":"Rank 2","mechanic":0,"requiredLevel":8,"passive":false,"attributesEx1":512,"powerType":2,"powerCost":25,"cooldownMs":0,"categoryCooldownMs":0,"globalCooldownMs":1500,"auraInterruptFlags":0,"schoolMask":0,"procFlags":0,"procChance":101,"procCharges":0,"durationMs":0,"effects":[{"index":0,"effectType":2,"auraType":0,"mechanic":0,"basePoints":8,"dieSides":5,"pointsPerLevel":0,"periodMs":0,"miscValue":0,"triggerSpellId":0,"coefficient":1}],"acquireMethod":2,"raceMask":0,"classMask":0,"minSkill":1,"supersededBySpellId":17256},{"spellId":17256,"name":"Bite","rankText":"Rank 3","mechanic":0,"requiredLevel":16,"passive":false,"attributesEx1":512,"powerType":2,"powerCost":25,"cooldownMs":0,"categoryCooldownMs":0,"globalCooldownMs":1500,"auraInterruptFlags":0,"schoolMask":0,"procFlags":0,"procChance":101,"procCharges":0,"durationMs":0,"Line truncated
+18 -2
View File
@@ -1,5 +1,6 @@
import {
classById,
isRomClassId,
type ClassId,
} from "../app/characterCatalog";
import {
@@ -22,6 +23,8 @@ import {
import { LOOT_CATALOG, type LootCatalogItem } from "./lootCatalog";
import type { InventoryItem } from "./lootTypes";
import type { PartyRole } from "./partyRoles";
import { romNativeGearReference } from "./romNativeGear";
import { romNativeGearFromSharedDirectStats, sumRomNativeGearStats } from "./romNativeStatsTypes";
import {
gearProfileFor,
isRomHybridGearClass,
@@ -213,7 +216,12 @@ function scaleStats(stats: ItemStats, factor: number): ItemStats {
damageMin: Math.max(1, Math.round(weapon.damageMin * factor * 10) / 10),
damageMax: Math.max(2, Math.round(weapon.damageMax * factor * 10) / 10),
} : null;
return Object.freeze({ ...numeric, meleeWeapon: scaleWeapon(stats.meleeWeapon), rangedWeapon: scaleWeapon(stats.rangedWeapon) });
return Object.freeze({
...numeric,
meleeWeapon: scaleWeapon(stats.meleeWeapon),
rangedWeapon: scaleWeapon(stats.rangedWeapon),
...(stats.romNative ? { romNative: stats.romNative } : {}),
});
}
function heirloomItem(
@@ -240,6 +248,9 @@ function heirloomItem(
? { ...distributedStats, blockValue: Math.max(1, Math.round(level * weight * 0.45)) }
: distributedStats;
const sourceWeapon = weaponStats(slot, inventorySlot, weaponType, budget);
const romNative = isRomClassId(context.classId)
? romNativeGearReference(context.classId, slot, level)
: null;
let stats = itemStatsFor({
itemId: 9_000_000,
quality: "heirloom",
@@ -250,6 +261,7 @@ function heirloomItem(
sourceItemLevel: level,
sourceStats,
sourceWeapon,
...(romNative ? { romNative } : {}),
});
const currentScore = specializationScore(stats, profile);
const catalogScore = isRomHybridGearClass(context.classId) ? 0 : highestCatalogScore(context.classId, slot, level, profile)
@@ -329,12 +341,16 @@ export function equipmentStatsForItems(items: readonly InventoryItem[]): ItemSta
const numeric = Object.fromEntries(ITEM_STAT_KEYS.map((key) => [key, 0])) as Record<NumericItemStatKey, number>;
let meleeWeapon: WeaponStats | null = null;
let rangedWeapon: WeaponStats | null = null;
const nativePayloads = [] as NonNullable<ItemStats["romNative"]>[];
for (const item of items) {
for (const key of ITEM_STAT_KEYS) numeric[key] += item.stats[key];
const nativePayload = item.stats.romNative ?? romNativeGearFromSharedDirectStats(item.stats);
if (nativePayload) nativePayloads.push(nativePayload);
if (item.stats.meleeWeapon) meleeWeapon = item.stats.meleeWeapon;
if (item.stats.rangedWeapon) rangedWeapon = item.stats.rangedWeapon;
}
return Object.freeze({ ...numeric, meleeWeapon, rangedWeapon });
const romNative = sumRomNativeGearStats(nativePayloads);
return Object.freeze({ ...numeric, meleeWeapon, rangedWeapon, ...(romNative ? { romNative } : {}) });
}
export function resolvedEquipmentStats(
+22
View File
@@ -57,6 +57,28 @@ describe("boss item stats", () => {
expect(normalizeItemStats(undefined, fallback)).toEqual(itemStatsFor(fallback));
});
it("persists explicit RoM-native gear separately from unchanged WotLK stats", () => {
const source = {
itemId: 999001,
quality: "rare" as const,
inventorySlot: "head",
armorType: null,
weaponType: null,
itemLevel: 20,
sourceItemLevel: 20,
sourceStats: { strength: 8, spellPower: 40 },
romNative: { strength: 3, magicalDamage: 17, healPowerRateFactor: 1.15 },
};
const item = itemStatsFor(source);
expect(item).toMatchObject({ strength: 8, spellPower: 40 });
expect(item.romNative).toEqual(source.romNative);
expect(normalizeItemStats(item, source)).toMatchObject({
strength: 8,
spellPower: 40,
romNative: source.romNative,
});
});
it("turns stamina into health and armor into reduced incoming damage", () => {
expect(healthFromStamina(7)).toBe(70);
expect(damageAfterArmor(100, 0, 20)).toBe(100);
+10 -1
View File
@@ -1,4 +1,5 @@
import generatedLootCatalog from "./generated/lootCatalog.json";
import { normalizeRomNativeGearStats, type RomNativeGearStats } from "./romNativeStatsTypes";
export type ItemQuality = "common" | "uncommon" | "rare" | "epic" | "legendary" | "heirloom";
export type DamageSchool = "physical" | "holy" | "fire" | "nature" | "frost" | "shadow" | "arcane";
@@ -47,6 +48,8 @@ export interface ItemStats {
readonly shadowResistance: number;
readonly meleeWeapon: WeaponStats | null;
readonly rangedWeapon: WeaponStats | null;
/** Optional, explicitly RoM-native gear values; never projected into WotLK fields. */
readonly romNative?: RomNativeGearStats;
}
export const ITEM_STAT_KEYS = [
@@ -95,6 +98,7 @@ export interface ItemStatSource {
readonly sourceItemLevel?: number;
readonly sourceStats?: SourceItemStats;
readonly sourceWeapon?: WeaponStats | null;
readonly romNative?: RomNativeGearStats;
}
const ZERO_NUMERIC_STATS = Object.fromEntries(
@@ -247,10 +251,12 @@ export function itemStatsFor(source: ItemStatSource): ItemStats {
ITEM_STAT_KEYS.map((key) => [key, scaledStat(sourceStats[key], ratio, key)]),
) as unknown as Readonly<Record<NumericItemStatKey, number>>;
const weapon = scaledWeapon(sourceWeapon, ratio);
const romNative = normalizeRomNativeGearStats(source.romNative);
return Object.freeze({
...numeric,
meleeWeapon: source.inventorySlot === "ranged" ? null : weapon,
rangedWeapon: source.inventorySlot === "ranged" ? weapon : null,
...(romNative ? { romNative } : {}),
});
}
@@ -275,14 +281,17 @@ export function normalizeItemStats(value: unknown, fallback: ItemStatSource): It
) return null;
return scaledWeapon(candidateWeapon as WeaponStats, 1);
};
const romNative = normalizeRomNativeGearStats(candidate.romNative);
const normalized: ItemStats = Object.freeze({
...numeric,
meleeWeapon: normalizeWeapon(candidate.meleeWeapon),
rangedWeapon: normalizeWeapon(candidate.rangedWeapon),
...(romNative ? { romNative } : {}),
});
const hasStats = ITEM_STAT_KEYS.some((key) => normalized[key] > 0)
|| normalized.meleeWeapon
|| normalized.rangedWeapon;
|| normalized.rangedWeapon
|| normalized.romNative;
return hasStats ? normalized : itemStatsFor(fallback);
}
+21
View File
@@ -87,6 +87,27 @@ describe("catalog-driven party rotations", () => {
expect(first && aiHintsForAbility(first).categories).toContain("interrupt");
});
it("prefers learned Knight/Rogue Punishment 499909 over the separate general 490151 variant", () => {
const knightRogue = {
...memberFor("rom-knight", "damage"),
secondaryClassId: "rom-rogue" as const,
comboPoints: 4,
comboTargetId: "caster",
};
const selected = choosePartyAbility(knightRogue, {
now: 2_000,
target: useCombatStore.getState().mobs.caster,
canUseAbility: (ability) => [490151, 499909].includes(ability.dbcSpellId ?? -1),
});
expect(selected).toMatchObject({
id: "rom-knight-rom-rogue-elite-50-499909",
dbcSpellId: 499909,
classId: "rom-knight",
secondaryClassId: "rom-rogue",
});
});
it("adds Blood Strike as a Reaping-only Blood rotation fallback when a base Blood rune is ready", () => {
const abilities = abilitiesForCharacter("death-knight", null);
const strike = abilities.find((ability) => ability.name === "Blood Strike")!;
+36 -7
View File
@@ -48,6 +48,7 @@ import {
import { romPriestChampionCooldownOverride } from "./romPriestChampionOverrides";
import { applyTalentModifierValue, talentModifiersForRanks } from "./talentModifiers";
import { romWarlockMageSoulBrandStingHasWillpowerBladeState } from "./romWarlockMageSoulBrandSting";
import { EMPTY_ITEM_STATS } from "./itemStats";
export interface PartyAbilityContext {
readonly now: number;
@@ -279,8 +280,16 @@ export function partyAbilityCosts(member: PartyMember, ability: AbilityDefinitio
aura.definition.utilityTags?.includes(WOW335_MAGE_ARCANE_CONCENTRATION_TAG)
));
return (adjustedAbility.costs?.length ? adjustedAbility.costs : [adjustedAbility.cost]).map((cost) => {
const baseMana = cost.percentageBasis === "base-mana"
? adjustedAbility.source === "runewaker" && member.statRuleset === "rom"
? deriveCharacterStats(
member.classId, member.level, EMPTY_ITEM_STATS, member.raceId, {}, member.secondaryClassId,
member.gender, "rom",
).mana
: baseResourcesFor(member.classId, member.level).mana
: 0;
const maximum = cost.percentageBasis === "base-mana"
? baseResourcesFor(member.classId, member.level).mana
? baseMana
: cost.resource === "health" ? member.maxHealth : companionResourceMaximum(member, cost.resource);
const baseAmount = cost.percentage ? cost.amount / 100 * maximum : cost.amount;
const adjusted = resolveResourceValue(
@@ -393,6 +402,21 @@ export function choosePartyRotationDecision(
.map((resource) => [resource, companionResourceMaximum(member, resource)]),
);
const learned = learnedAbilities(member);
const readyAbilities = learned.filter((ability) => partyAbilityIsReady(
member,
ability,
context.now,
Boolean(context.nextHealingSpellFree && ability.effects.some((effect) => effect.kind === "heal")),
));
const linkedKnightPunishment = member.classId === "rom-knight" && member.secondaryClassId === "rom-rogue"
? readyAbilities.find((ability) => ability.source === "runewaker"
&& ability.classId === "rom-knight" && ability.secondaryClassId === "rom-rogue"
&& ability.dbcSpellId === 499909
&& (context.canUseAbility?.(ability) ?? true))
: null;
const rotationAbilities = linkedKnightPunishment
? readyAbilities.filter((ability) => ability.dbcSpellId !== 490151)
: readyAbilities;
const reapingRank = member.classId === "death-knight"
? Math.max(0, Math.trunc(member.talentRanks["talent-2001"] ?? 0))
: 0;
@@ -442,12 +466,7 @@ export function choosePartyRotationDecision(
comboTargetId: member.comboTargetId,
runes: member.runes,
deathKnightReapingRank: reapingRank,
abilities: learned.filter((ability) => partyAbilityIsReady(
member,
ability,
context.now,
Boolean(context.nextHealingSpellFree && ability.effects.some((effect) => effect.kind === "heal")),
)),
abilities: rotationAbilities,
knownDamagingAbilityNames: new Set(learned.filter((ability) => {
const categories = aiHintsForAbility(ability).categories;
return categories.includes("damage") || categories.includes("execute");
@@ -555,6 +574,8 @@ export function partyAbilityAmount(
member.raceId,
{},
member.secondaryClassId,
member.gender,
member.statRuleset ?? "wow",
).intellect;
if (effect.kind === "finisher-damage" && effect.poison) {
const consumedDoses = Math.max(0, Math.min(
@@ -574,6 +595,10 @@ export function partyAbilityAmount(
ability,
0,
sourceIntellect,
member.raceId,
member.gender,
member.statRuleset ?? "wow",
member.secondaryClassId,
);
}
const coefficient = "coefficient" in effect
@@ -589,6 +614,10 @@ export function partyAbilityAmount(
ability,
0,
sourceIntellect,
member.raceId,
member.gender,
member.statRuleset ?? "wow",
member.secondaryClassId,
) + (effect.kind === "damage" ? effect.bonusFlat ?? 0 : 0);
if (member.classId === "druid" && (effect.kind === "damage" || effect.kind === "dot")) {
return applyTalentModifierValue(
+207 -1
View File
@@ -1,5 +1,6 @@
import { beforeAll, beforeEach, describe, expect, it } from "vitest";
import { useCombatStore, type EnemyActiveCast } from "./combatStore";
import { PLAYER_AURA_ENTITY_ID, useCombatStore, type EnemyActiveCast } from "./combatStore";
import { applyAura } from "./combatAuras";
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
import {
clearPartyRuntimeRegistry,
@@ -67,6 +68,38 @@ function partyHealCriticalAt(sourceId: string, abilityId: string, targetId: stri
throw new Error("Could not find a seeded companion healing crit.");
}
function applyRevivalTestCharges(auras: Parameters<typeof applyAura>[0], ownerId: string, stacks: number, now: number) {
return applyAura(auras, {
definition: {
id: "rom-state-revival-charge",
name: "Revival",
description: "Revival source-stack test fixture.",
disposition: "buff",
durationMs: null,
maxStacks: 10,
stackBehavior: "add",
utilityTags: ["rom-revival-charge"],
},
sourceId: ownerId,
targetId: ownerId,
stacks,
now,
}).auras;
}
function createRomRogueWarden(seed: string, level = 80) {
return createConfiguredPartyMember({
name: "Rogue/Warden",
classId: "rom-rogue",
secondaryClassId: "rom-warden",
raceId: "rom-elf",
specialization: "Rogue/Warden",
specializationId: "rom-rogue:rom-warden",
talentTreeId: "rom-rogue-rom-warden",
role: "damage",
}, level, 0, seed);
}
function createFrostbitePartyMage(seed: string) {
const mage = createConfiguredPartyMember({
name: "Frostbite Mage",
@@ -126,6 +159,179 @@ describe("party combat runtime", () => {
expect(activePartyTargetId(mobs, null)).toBe("pack:a");
});
it("lets an injured Rogue/Warden companion cast zero-stack Revival without critting or touching another owner", () => {
const seed = "rom-rogue-warden-revival-zero-stacks";
useCombatStore.getState().initializeCharacter({ classId: "mage", role: "damage", level: 80 });
const playerHealth = useCombatStore.getState().health;
const configured = createRomRogueWarden(seed);
const otherConfigured = createConfiguredPartyMember({
name: "Warden/Mage",
classId: "rom-warden",
secondaryClassId: "rom-mage",
raceId: "rom-elf",
specialization: "Warden/Mage",
specializationId: "rom-warden:rom-mage",
talentTreeId: "rom-warden-rom-mage",
role: "damage",
}, 80, 0, `${seed}:other`);
const revival = {
...configured,
health: Math.round(configured.maxHealth / 2),
nextActionAt: 0,
gearStats: { ...EMPTY_ITEM_STATS, criticalStrikeRating: 100_000 },
};
const other = {
...otherConfigured,
health: Math.round(otherConfigured.maxHealth / 2),
nextActionAt: 0,
};
usePartyStore.getState().initializeParty(seed, 80, playerHealth, "damage", 2, "rom");
usePartyStore.setState({ members: [revival, other] });
registerPartyRuntimePosition(revival.id, [0, 0, 0]);
registerPartyRuntimePosition(other.id, [1, 0, 0]);
useCombatStore.getState().synchronizeActors();
useCombatStore.setState((state) => ({
auras: applyRevivalTestCharges(
applyRevivalTestCharges(state.auras, PLAYER_AURA_ENTITY_ID, 2, 1_000),
other.id,
4,
1_000,
),
}));
advanceDungeonPartyCombat(1_000);
const after = useCombatStore.getState();
const healed = usePartyStore.getState().members.find((member) => member.id === revival.id)!;
const untouched = usePartyStore.getState().members.find((member) => member.id === other.id)!;
const healEvents = after.combatEvents.filter((event) => (
event.kind === "healing" && event.sourceActorId === revival.id
&& event.abilityId === "rom-rogue-rom-warden-elite-60"
));
expect(healed.health).toBe(revival.health + Math.round(revival.maxHealth * 0.1));
expect(healEvents).toHaveLength(1);
expect(healEvents[0]).toMatchObject({
targetActorId: revival.id,
rawAmount: Math.round(revival.maxHealth * 0.1),
effectiveAmount: Math.round(revival.maxHealth * 0.1),
critical: false,
});
expect(untouched.health).toBe(other.health);
expect(after.health).toBe(playerHealth);
expect(after.auras.some((aura) => aura.sourceId === PLAYER_AURA_ENTITY_ID
&& aura.definition.utilityTags?.includes("rom-revival-charge"))).toBe(true);
expect(after.auras.some((aura) => aura.sourceId === other.id
&& aura.definition.utilityTags?.includes("rom-revival-charge"))).toBe(true);
});
it("uses the companion's own capped stacks and caps Revival at its max health", () => {
const seed = "rom-rogue-warden-revival-charges";
useCombatStore.getState().initializeCharacter({ classId: "mage", role: "damage", level: 80 });
const playerHealth = useCombatStore.getState().health;
const configured = createRomRogueWarden(seed);
const otherConfigured = createConfiguredPartyMember({
name: "Warden/Mage",
classId: "rom-warden",
secondaryClassId: "rom-mage",
raceId: "rom-elf",
specialization: "Warden/Mage",
specializationId: "rom-warden:rom-mage",
talentTreeId: "rom-warden-rom-mage",
role: "damage",
}, 80, 0, `${seed}:other`);
const revival = {
...configured,
health: configured.maxHealth - 50,
nextActionAt: 0,
};
const other = {
...otherConfigured,
health: Math.round(otherConfigured.maxHealth / 2),
nextActionAt: 0,
};
usePartyStore.getState().initializeParty(seed, 80, playerHealth, "damage", 2, "rom");
usePartyStore.setState({ members: [revival, other] });
registerPartyRuntimePosition(revival.id, [0, 0, 0]);
registerPartyRuntimePosition(other.id, [1, 0, 0]);
useCombatStore.getState().synchronizeActors();
useCombatStore.setState((state) => ({
auras: applyRevivalTestCharges(
applyRevivalTestCharges(state.auras, revival.id, 10, 1_000),
PLAYER_AURA_ENTITY_ID,
3,
1_000,
),
}));
advanceDungeonPartyCombat(1_000);
const after = useCombatStore.getState();
const healed = usePartyStore.getState().members.find((member) => member.id === revival.id)!;
const healEvent = after.combatEvents.find((event) => (
event.kind === "healing" && event.sourceActorId === revival.id
&& event.abilityId === "rom-rogue-rom-warden-elite-60"
));
expect(healed.health).toBe(revival.maxHealth);
expect(healEvent).toMatchObject({
targetActorId: revival.id,
rawAmount: Math.round(revival.maxHealth * 0.6),
effectiveAmount: 50,
overheal: Math.round(revival.maxHealth * 0.6) - 50,
critical: false,
});
expect(after.health).toBe(playerHealth);
expect(after.auras.some((aura) => aura.sourceId === revival.id
&& aura.targetId === revival.id
&& aura.definition.utilityTags?.includes("rom-revival-charge"))).toBe(false);
expect(after.auras.some((aura) => aura.sourceId === PLAYER_AURA_ENTITY_ID
&& aura.definition.utilityTags?.includes("rom-revival-charge"))).toBe(true);
expect(after.auras.some((aura) => aura.sourceId === other.id
&& aura.definition.utilityTags?.includes("rom-revival-charge"))).toBe(false);
});
it("does not graft Rogue/Warden Revival onto below-level or Warden-primary companions", () => {
const seed = "rom-rogue-warden-revival-gates";
useCombatStore.getState().initializeCharacter({ classId: "mage", role: "damage", level: 80 });
const playerHealth = useCombatStore.getState().health;
const belowLevelConfigured = createRomRogueWarden(`${seed}:below-level`, 59);
const wardenPrimaryConfigured = createConfiguredPartyMember({
name: "Warden/Rogue",
classId: "rom-warden",
secondaryClassId: "rom-rogue",
raceId: "rom-elf",
specialization: "Warden/Rogue",
specializationId: "rom-warden:rom-rogue",
talentTreeId: "rom-warden-rom-rogue",
role: "damage",
}, 80, 0, `${seed}:warden-primary`);
const belowLevel = {
...belowLevelConfigured,
health: Math.round(belowLevelConfigured.maxHealth / 2),
nextActionAt: 0,
};
const wardenPrimary = {
...wardenPrimaryConfigured,
health: Math.round(wardenPrimaryConfigured.maxHealth / 2),
nextActionAt: 0,
};
usePartyStore.getState().initializeParty(seed, 80, playerHealth, "damage", 2, "rom");
usePartyStore.setState({ members: [belowLevel, wardenPrimary] });
registerPartyRuntimePosition(belowLevel.id, [0, 0, 0]);
registerPartyRuntimePosition(wardenPrimary.id, [1, 0, 0]);
useCombatStore.getState().synchronizeActors();
advanceDungeonPartyCombat(1_000);
const after = useCombatStore.getState();
expect(usePartyStore.getState().members.find((member) => member.id === belowLevel.id)?.health)
.toBe(belowLevel.health);
expect(usePartyStore.getState().members.find((member) => member.id === wardenPrimary.id)?.health)
.toBe(wardenPrimary.health);
expect(after.combatEvents.some((event) => event.kind === "healing"
&& event.abilityId === "rom-rogue-rom-warden-elite-60")).toBe(false);
expect(after.health).toBe(playerHealth);
});
it("extends a companion Druid's cast-time damage range with Nature's Reach", () => {
const seed = "druid-natures-reach-party";
const druid = createConfiguredPartyMember({
+273 -23
View File
@@ -21,6 +21,7 @@ import type { CombatSummon, MobCombatState, TimedCombatEffect } from "./combatSt
import {
PLAYER_AURA_ENTITY_ID,
abilityDamageSchool,
auraAdjustedCharacterStats,
equipmentAdjustedCombatAmount,
refreshPriestPainAndSufferingDot,
stableCombatUnit,
@@ -50,7 +51,7 @@ import {
updatePartyRuntimePosition,
} from "./partyRuntimeRegistry";
import { usePartyStore, type PartyCommand, type PartyMember } from "./partyStore";
import { baseClassFor, classById } from "../app/characterCatalog";
import { baseClassFor, classById, isRomClassId } from "../app/characterCatalog";
import { useGameStore } from "./store";
import { useManastormStore } from "./manastormStore";
import { WOW335_GLYPH_OF_SWIFTMEND_ID } from "./wow335GlyphCatalog";
@@ -80,6 +81,11 @@ import {
type DispelCategory,
} from "./combatAuras";
import { romPriestHolyBlessingDamage, romPriestHolyBlessingStats } from "./romPriestHolyBlessingRuntime";
import { romKnightGodsVengeanceShouldResetShadowStep } from "./romKnightOverrides";
import {
romChampionHasForgeRankTwoAura,
romChampionRunePulseUseEffect,
} from "./romChampionForgeRuntime";
import {
ROM_DRUID_MAGE_INSPIRATION_PASSIVE_ID,
isRomDruidMagePair,
@@ -88,6 +94,11 @@ import {
romDruidMageInspirationRecipientIds,
} from "./romDruidMageInspirationRuntime";
import { ROM_MAGE_DRUID_GREEN_GUARDIAN_AURA_TAG, ROM_MAGE_DRUID_GREEN_GUARDIAN_SKILL_ID, isRomMageDruidPair } from "./romMageDruidGreenGuardianRuntime";
import {
romWardenRevivalBuildMatches,
romWardenRevivalNormalHeal,
romWardenRevivalStateIsActive,
} from "./romWardenRevivalRuntime";
import {
romWarlockMageSoulBrandEffects,
} from "./romWarlockMageSoulBrand";
@@ -301,6 +312,10 @@ import {
wow335ShamanTidalWavesProcChance,
} from "./wow335ShamanTidalWavesRuntime";
import { wow335ShamanFlurryIsActive } from "./wow335ShamanFlurryRuntime";
import {
WOW335_SHAMAN_NATURES_GUARDIAN_NEXT_NATURE_CRIT_TAG,
wow335ShamanNaturesGuardianNextCritIsReady,
} from "./wow335ShamanNaturesGuardianRuntime";
import {
WOW335_SHAMAN_MAELSTROM_WEAPON_AURA_TAG,
WOW335_SHAMAN_MAELSTROM_WEAPON_ELIGIBLE_SPELLS,
@@ -323,6 +338,13 @@ import {
ROM_ROGUE_OFF_HAND_MASTERY_DAMAGE_PERCENT,
ROM_ROGUE_OFF_HAND_MASTERY_TAG,
} from "./romRogueMechanics";
import {
ROM_CHAMPION_RUNE_SIPHON_ID,
romChampionDarkEnergyStrikeGroup0Survives,
romChampionDarkEnergyStrikeMatchesBuild,
romChampionDarkEnergyStrikePacketGroupAtDamageIndex,
romChampionDarkEnergyStrikeShouldResetRuneSiphon,
} from "./romChampionDarkEnergyStrikeRuntime";
import {
romPriestChampionRageControlGain,
romPriestVowOfSilenceDurationMs,
@@ -670,6 +692,16 @@ function applyPartyDeathKnightBladeBarrier(
}, now);
}
function applyPartyRomChampionRunePulseOnUse(
member: PartyMember,
ability: AbilityDefinition,
now: number,
): void {
const combat = useCombatStore.getState();
const effect = romChampionRunePulseUseEffect(ability, combat.auras, member.id, now);
if (effect) combat.applyActorAura(member.id, member.id, ability, effect, now);
}
function maybeProcPartyShamanTidalWaves(
member: PartyMember,
ability: AbilityDefinition,
@@ -964,6 +996,8 @@ function partyAbilityAmountWithHolyBlessing(
member.raceId,
{},
member.secondaryClassId,
member.gender,
member.statRuleset ?? "wow",
);
const auras = state.auras.filter((aura) => aura.targetId === member.id
&& (aura.expiresAt === null || aura.expiresAt > now));
@@ -974,7 +1008,7 @@ function partyAbilityAmountWithHolyBlessing(
if (member.classId !== "rom-priest") {
return partyAbilityAmount(member, ability, effect, poisonDoses, intellect);
}
const bonus = romPriestHolyBlessingStats(base, auras).spellPowerBonus;
const bonus = member.statRuleset === "rom" ? 0 : romPriestHolyBlessingStats(base, auras).spellPowerBonus;
if (bonus <= 0) return partyAbilityAmount(member, ability, effect, poisonDoses, intellect);
return partyAbilityAmount({
...member,
@@ -1005,6 +1039,12 @@ function partyWarlockAbilityAmount(
member.gearStats,
member.classId,
sourceAbility,
0,
undefined,
member.raceId,
member.gender,
member.statRuleset ?? "wow",
member.secondaryClassId,
);
return Math.round(tickAmount * burstSeconds * 1_000 / Math.max(1, conflagrateDot.intervalMs))
+ (effect.bonusFlat ?? 0);
@@ -1144,7 +1184,9 @@ export function activePartyTargetId(
export function partyAttackDamage(
member: Pick<PartyMember, "level" | "role">
& Partial<Pick<PartyMember, "classId" | "specialization" | "gearStats">>,
& Partial<Pick<PartyMember,
"id" | "classId" | "specialization" | "gearStats" | "raceId" | "gender" | "statRuleset" | "secondaryClassId"
>>,
): number {
const coefficient = member.role === "tank" ? 0.85 : member.role === "healer" ? 0.55 : 1.25;
const gear = member.gearStats;
@@ -1157,18 +1199,34 @@ export function partyAttackDamage(
})
? baseClassFor(classId) === "hunter" ? "ranged" : "spell"
: "melee";
const nativeStats = member.statRuleset === "rom" && isRomClassId(classId)
? auraAdjustedCharacterStats(deriveCharacterStats(
classId,
member.level,
gear,
member.raceId ?? "rom-human",
{},
member.secondaryClassId,
member.gender ?? "male",
"rom",
), useCombatStore.getState().auras, member.id ?? "").romNative
: undefined;
const weapon = kind === "ranged" ? gear.rangedWeapon : kind === "melee" ? gear.meleeWeapon : null;
const equipmentPower = kind === "spell"
? equipmentAttackPower(classId, gear, kind)
: equipmentAttackPower(classId, gear, kind) / 14 * ((weapon?.speedMs ?? 2400) / 1_000)
+ (weapon ? (weapon.damageMin + weapon.damageMax) / 2 * 0.35 : 0);
const crit = ratingPercent(
const equipmentPower = nativeStats
? kind === "spell"
? nativeStats.magicalDamage
: nativeStats.physicalAttack / 14 * ((weapon?.speedMs ?? 2400) / 1_000)
: kind === "spell"
? equipmentAttackPower(classId, gear, kind)
: equipmentAttackPower(classId, gear, kind) / 14 * ((weapon?.speedMs ?? 2400) / 1_000)
+ (weapon ? (weapon.damageMin + weapon.damageMax) / 2 * 0.35 : 0);
const crit = nativeStats ? 0 : ratingPercent(
gear.criticalStrikeRating,
kind === "spell" ? "spellCrit" : kind === "ranged" ? "rangedCrit" : "meleeCrit",
member.level,
classId,
);
const hit = ratingPercent(
const hit = nativeStats ? 0 : ratingPercent(
gear.hitRating,
kind === "spell" ? "spellHit" : kind === "ranged" ? "rangedHit" : "meleeHit",
member.level,
@@ -1697,7 +1755,7 @@ function memberSwingMs(member: PartyMember, now: number): number {
const hasteStat = partyUsesRangedAttacks(member)
? baseClassFor(member.classId) === "hunter" ? "ranged-haste" : "spell-haste"
: "melee-haste";
const hasteRating = ratingPercent(
const hasteRating = member.statRuleset === "rom" ? 0 : ratingPercent(
member.gearStats.hasteRating,
partyUsesRangedAttacks(member)
? baseClassFor(member.classId) === "hunter" ? "rangedHaste" : "spellHaste"
@@ -1786,6 +1844,8 @@ function partyRogueOffhandAttackProfile(
member.raceId,
{},
member.secondaryClassId,
member.gender,
member.statRuleset ?? "wow",
);
const auras = useCombatStore.getState().auras.filter((aura) => (
aura.targetId === member.id && (aura.expiresAt === null || aura.expiresAt > now)
@@ -1881,6 +1941,8 @@ function partyShamanWeaponAttackProfile(
member.raceId,
{},
member.secondaryClassId,
member.gender,
member.statRuleset ?? "wow",
);
const auras = useCombatStore.getState().auras.filter((aura) => (
aura.targetId === member.id && (aura.expiresAt === null || aura.expiresAt > now)
@@ -1920,6 +1982,8 @@ function partyShamanWeaponHitDamage(
member.raceId,
{},
member.secondaryClassId,
member.gender,
member.statRuleset ?? "wow",
);
const auras = useCombatStore.getState().auras.filter((aura) => (
aura.targetId === member.id && (aura.expiresAt === null || aura.expiresAt > now)
@@ -2235,10 +2299,20 @@ function advancePartyWeaponAttack(member: PartyMember, targetId: string, now: nu
? member.talentRanks[WOW335_HUNTER_GO_FOR_THE_THROAT_TALENT_ID] ?? 0
: 0;
const rogueDualWielding = member.classId === "rom-rogue" && Boolean(rogueOffhandWeapon);
const activeAuras = useCombatStore.getState().auras;
const forgeRankOneActive = member.classId === "rom-champion"
&& activeAuras.some((aura) => aura.targetId === member.id
&& aura.definition.id === "rom-champion-forge-active"
&& (aura.expiresAt === null || aura.expiresAt > now));
const forgeRankTwoActive = member.classId === "rom-champion"
&& romChampionHasForgeRankTwoAura(activeAuras, member.id, now);
const forgeAutoAttackActive = forgeRankOneActive || forgeRankTwoActive;
const needsAttackRoll = scentRank > 0 || bloodCakedBladeRank > 0 || bloodyVengeanceRank > 0
|| unbridledWrathRank > 0 || goForTheThroatRank > 0 || rogueDualWielding;
|| unbridledWrathRank > 0 || goForTheThroatRank > 0 || rogueDualWielding || forgeAutoAttackActive;
const weaponSpeedMs = member.gearStats.meleeWeapon?.speedMs ?? 2_400;
const seed = `${member.id}:${targetId}:${abilityId}:${now}:${rogueDualWielding ? "rom-rogue-dual-wield-main-hand" : "scent-of-blood-auto-attack"}`;
const seed = `${member.id}:${targetId}:${abilityId}:${now}:${rogueDualWielding
? "rom-rogue-dual-wield-main-hand"
: forgeAutoAttackActive ? "rom-champion-forge-auto-attack" : "scent-of-blood-auto-attack"}`;
useCombatStore.getState().notifyOwnerHostileAction(member.id, targetId);
const ownerAttackDamage = partyAttackDamage(member);
const result = useCombatStore.getState().damageMob(targetId, ownerAttackDamage, now,
@@ -2266,6 +2340,11 @@ function advancePartyWeaponAttack(member: PartyMember, targetId: string, now: nu
scentRank > 0 && (result.combatResult?.landed ?? result.amount > 0),
now,
);
if (forgeAutoAttackActive && result.amount > 0) {
// The combat event proc already grants Forge's Rage through the actor mirror.
// Carry that result forward before applying this swing's ordinary +6 Rage.
runtimeMember = memberFromCompanionActor(runtimeMember, useCombatStore.getState().actors[member.id]);
}
runtimeMember = maybeProcPartyWarriorUnbridledWrath(
runtimeMember,
Boolean(result.combatResult?.landed && result.amount > 0),
@@ -2385,7 +2464,8 @@ export function partyAbilityTargetIsValid(
&& effect.remainingTicks > 0 && effect.tag === requiredTargetStateTag)) return false;
if (ability.dbcSpellId === 491613 && mob?.creatureFamily === "living"
&& !(member.classId === "rom-knight" && member.secondaryClassId === "rom-scout" && member.level >= 60)) return false;
if (ability.dbcSpellId === 490151 && (member.comboTargetId !== targetId || member.comboPoints <= 0)) return false;
if ([490151, 499909].includes(ability.dbcSpellId ?? -1)
&& (member.comboTargetId !== targetId || member.comboPoints <= 0)) return false;
if (ability.dbcSpellId === ROM_ROGUE_ENERGIZED_HANDS_SKILL_ID || ability.dbcSpellId === ROM_ROGUE_POISON_SKILL_ID) {
const handsEffect = ability.effects.find((effect) => effect.kind === "apply-aura");
const activeHandsAura = combat.auras.find((aura) => aura.targetId === member.id
@@ -2645,6 +2725,31 @@ function choosePartySupportIntent(
return { ability: mendPet, targetId: member.id };
}
}
if (member.classId === "rom-rogue" && member.secondaryClassId === "rom-warden"
&& member.health > 0 && member.health < member.maxHealth) {
const catalogAbility = abilitiesForCharacter(member.classId, member.secondaryClassId)
.find((ability) => ability.id === "rom-rogue-rom-warden-elite-60");
const revival = catalogAbility
? learnedAbilityForBuild(catalogAbility, member.level, member.talentRanks)
: null;
if (revival && partyAbilityIsReady(member, revival, now)
&& partyAbilityTargetIsValid(member, revival, member.id, undefined, now)) {
return { ability: revival, targetId: member.id };
}
}
if (romWardenRevivalBuildMatches(member.classId, member.secondaryClassId)) {
const catalogAbility = abilitiesForCharacter(member.classId, member.secondaryClassId)
.find((ability) => ability.source === "runewaker" && ability.dbcSpellId === 499544);
const stateAbility = catalogAbility
? learnedAbilityForBuild(catalogAbility, member.level, member.talentRanks)
: null;
if (stateAbility
&& !romWardenRevivalStateIsActive(combat.auras, member.id, now)
&& partyAbilityIsReady(member, stateAbility, now)
&& partyAbilityTargetIsValid(member, stateAbility, member.id, undefined, now)) {
return { ability: stateAbility, targetId: member.id };
}
}
if (member.role !== "healer") return null;
const dispelTargetId = [
...(!simulatedPartyExcludesPlayer() && combat.health > 0 ? [PLAYER_AGGRO_ID] : []),
@@ -3011,6 +3116,12 @@ function executePartyAbility(
&& ["Lightning Bolt", "Chain Lightning"].includes(ability.name)
? abilityDamageSchool("shaman", ability)
: presentationSchoolForAbility(ability);
const consumesShamanNaturesGuardianCrit = member.classId === "shaman"
&& (hostileTargets.length > 0 || friendlyTargets.length > 0)
&& ability.effects.some((effect) => effect.kind === "damage"
? (effect.school ?? abilityDamageSchool("shaman", ability)) === "nature"
: effect.kind === "heal" && abilityDamageSchool("shaman", ability) === "nature")
&& wow335ShamanNaturesGuardianNextCritIsReady(combat.auras, member.id, now);
const usesCombustion = spellSchool === "fire" && hostileTargets.length > 0
&& ability.effects.some((effect) => effect.kind === "damage")
&& combat.auras.some((aura) => aura.targetId === member.id
@@ -3031,12 +3142,13 @@ function executePartyAbility(
const elementalOathRank = combat.classId === "shaman"
? Math.min(3, Math.max(0, Math.trunc(combat.talentRanks["talent-2049"] ?? 0)))
: 0;
const criticalChance = Math.max(0, ratingPercent(
const criticalChance = Math.max(0, (member.statRuleset === "rom" ? 0 : ratingPercent(
member.gearStats.criticalStrikeRating,
"spellCrit",
member.level,
member.classId,
) / 100 + elementalOathRank / 100 + (consumesInnerFocus ? 0.25 : 0)
) / 100) + elementalOathRank / 100 + (consumesInnerFocus ? 0.25 : 0)
+ (consumesShamanNaturesGuardianCrit ? 1 : 0)
+ wow335ShamanTidalWavesCriticalChanceBonusPercent(ability.name, tidalWavesChargesConsumed) / 100);
const masterOfElementsCritPercent = member.classId === "mage"
? Math.min(3, Math.max(0, Math.trunc(member.talentRanks[WOW335_MAGE_MASTER_OF_ELEMENTS_TALENT_ID] ?? 0)))
@@ -3077,6 +3189,13 @@ function executePartyAbility(
&& (member.activeCast?.romPriestHolyCandleCharged ?? false);
let deathKnightReapingProcAttemptedForCast = false;
let deathKnightReapingSpendRestoreAttemptedForCast = false;
const isRomChampionDarkEnergyStrike = romChampionDarkEnergyStrikeMatchesBuild(
member.classId,
member.secondaryClassId,
ability,
);
let romChampionDarkEnergyStrikeDamageIndex = 0;
const romChampionDarkEnergyStrikeGroup0SurvivedTargets = new Set<string>();
const attemptDeathKnightReapingOnLandedTrigger = (): void => {
if (member.classId !== "death-knight" || deathKnightReapingProcAttemptedForCast) return;
if (!deathKnightReapingSpendRestoreAttemptedForCast) {
@@ -3213,6 +3332,9 @@ function executePartyAbility(
}));
}
for (const effect of castEffects) {
const darkEnergyStrikeGroup = effect.kind === "damage" && isRomChampionDarkEnergyStrike
? romChampionDarkEnergyStrikePacketGroupAtDamageIndex(romChampionDarkEnergyStrikeDamageIndex++)
: null;
// Necrotic Wound's Sinister Request rider belongs to the completed cast.
// romEffectsForCast also appends it to each synthetic channel-pulse ability,
// so applying it here would reduce the cooldown once per hit plus once at
@@ -3236,6 +3358,8 @@ function executePartyAbility(
continue;
}
for (const hostileTargetId of hostileTargets) {
if (darkEnergyStrikeGroup === "dark"
&& !romChampionDarkEnergyStrikeGroup0SurvivedTargets.has(hostileTargetId)) continue;
if (effect.kind === "dot") {
if (!groundAreaCreated) combat.applyTimedActorEffect(
member.id, hostileTargetId, ability,
@@ -3402,6 +3526,7 @@ function executePartyAbility(
const partyWarriorVictoryRushRank = member.classId === "warrior" && ability.name === "Victory Rush"
? member.talentRanks[WOW335_WARRIOR_IMPROVED_VICTORY_RUSH_TALENT_ID] ?? 0
: 0;
const darkEnergyStrikePhysicalHit = darkEnergyStrikeGroup === "physical";
const spreadingPainCriticalBuffActive = effect.kind === "damage"
&& member.classId === "rom-warlock"
&& member.secondaryClassId === "rom-priest"
@@ -3418,8 +3543,10 @@ function executePartyAbility(
|| shamanElementalFocusHit
|| shamanLightningOverloadHit
|| godsSwordDirectPhysicalHit
|| darkEnergyStrikePhysicalHit
|| spreadingPainCriticalBuffActive
|| partyWarriorVictoryRushRank > 0
|| consumesShamanNaturesGuardianCrit
|| consumesColdBlood || usesCombustion || arcanePotencyCriticalChanceBonusPercent > 0
|| masterOfElementsCritPercent > 0
|| hunterGoForTheThroatAttackKind !== null
@@ -3432,6 +3559,9 @@ function executePartyAbility(
? member.talentRanks[WOW335_MAGE_MOLTEN_FURY_TALENT_ID] ?? 0
: 0;
const partyDamageTargetBeforeHit = useCombatStore.getState().mobs[hostileTargetId];
const damageSchool = effect.kind === "damage" && isRomChampionDarkEnergyStrike
? effect.school ?? spellSchool
: spellSchool;
const partyRawDirectDamageBase = mageTargetDamageAmount
+ sunderStacks * (effect.kind === "damage" ? effect.bonusPerSunderStack ?? 0 : 0);
const partyBlessingAuras = !partyUsesCombatRollContext && member.classId === "rom-priest"
@@ -3452,7 +3582,7 @@ function executePartyAbility(
? wow335MageMoltenFuryDamage(
partyRawDirectDamage,
partyMageMoltenFuryRank,
spellSchool,
damageSchool,
partyDamageTargetBeforeHit.health,
partyDamageTargetBeforeHit.maxHealth,
)
@@ -3472,7 +3602,7 @@ function executePartyAbility(
)
: partyDirectDamageWithMoltenFury;
const maelstromWeaponPvpDamageReductionPercent = partyDamageTargetBeforeHit?.characterDefender
&& spellSchool !== "physical"
&& damageSchool !== "physical"
? wow335ShamanMaelstromWeaponPvpDamageReductionPercent(
maelstromWeaponRank,
maelstromWeaponStacksConsumed,
@@ -3489,12 +3619,12 @@ function executePartyAbility(
role: member.role,
abilityId: ability.id,
},
spellSchool,
damageSchool,
partyUsesCombatRollContext ? {
attackKind: drumsOfWarShot ? "ranged"
: hunterGoForTheThroatAttackKind
?? (deathKnightScentOfBloodMeleeHit || deathKnightBloodGorgedHit
|| shamanWeaponMeleeHit || godsSwordDirectPhysicalHit
|| shamanWeaponMeleeHit || godsSwordDirectPhysicalHit || darkEnergyStrikePhysicalHit
|| (deathKnightBloodyVengeanceHit && spellSchool === "physical")
|| consumesColdBlood || deathKnightSuddenDoomTrigger
? "melee" : "spell"),
@@ -3503,6 +3633,10 @@ function executePartyAbility(
seed: `${member.id}:${ability.id}:${hostileTargetId}:${now}:special-crit${shamanWeaponHand ? `:${shamanWeaponHand}` : ""}`,
...(deathKnightBloodyVengeanceHit && channelPulse ? { periodic: true } : {}),
criticalChanceBonusPercent: (consumesColdBlood ? 100 : 0)
+ (consumesShamanNaturesGuardianCrit
&& (effect.kind === "damage"
? (effect.school ?? abilityDamageSchool("shaman", ability)) === "nature"
: abilityDamageSchool("shaman", ability) === "nature") ? 100 : 0)
+ arcanePotencyCriticalChanceBonusPercent
+ masterOfElementsCritPercent,
...(godsSwordDirectPhysicalHit || spreadingPainCriticalBuffActive
@@ -3520,6 +3654,13 @@ function executePartyAbility(
: ability.name === "Shiv" ? { rules: { canCrit: false } } : {}),
} : undefined,
);
if (darkEnergyStrikeGroup === "physical" && hostileTargetId === targetId
&& romChampionDarkEnergyStrikeGroup0Survives({
effectiveDamage: result.amount,
combatResult: result.combatResult,
})) {
romChampionDarkEnergyStrikeGroup0SurvivedTargets.add(hostileTargetId);
}
effectiveAmount += result.amount;
const partyHitLanded = result.combatResult?.landed ?? result.amount > 0;
if (!partyUsesCombatRollContext && effect.kind === "damage" && partyHitLanded && result.amount > 0) {
@@ -3856,6 +3997,39 @@ function executePartyAbility(
attemptDeathKnightReapingOnLandedTrigger();
combat = useCombatStore.getState();
}
} else if (effect.kind === "utility"
&& effect.action === "class-script"
&& ability.id === "rom-rogue-rom-warden-elite-60"
&& member.classId === "rom-rogue"
&& member.secondaryClassId === "rom-warden") {
const revivalCharge = combat.auras.find((aura) => (
aura.sourceId === member.id
&& aura.targetId === member.id
&& (aura.expiresAt === null || aura.expiresAt > now)
&& aura.definition.utilityTags?.includes("rom-revival-charge")
));
const requested = romWardenRevivalNormalHeal({
stacks: matchingAuraStacks(combat.auras, "rom-revival-charge", member.id, member.id, now),
targetMaxHealth: member.maxHealth,
});
// RuneWaker's FixPer heal is already max-HP based; skip generic healing
// done/taken modifiers and critical rolls just as the player path does.
const result = useCombatStore.getState().healActor(member.id, requested, {
sourceActorId: member.id,
abilityId: ability.id,
criticalChance: 0,
amountAlreadyModified: true,
seed: `${member.id}:${ability.id}:${now}:rom-warden-revival`,
now,
});
effectiveAmount += result.effectiveAmount;
if (revivalCharge) {
useCombatStore.setState((state) => ({
auras: state.auras.filter((aura) => aura.instanceId !== revivalCharge.instanceId),
}));
}
combat = useCombatStore.getState();
runtimeMember = memberFromCompanionActor(runtimeMember, combat.actors[member.id]);
} else if (effect.kind === "utility"
&& effect.action === "class-script"
&& ability.source === "runewaker"
@@ -4191,9 +4365,11 @@ function executePartyAbility(
effectiveAmount += useCombatStore.getState().dispelActor(recipientId, effect.categories, effect.maxCount);
}
} else if (effect.kind === "resource") {
const resourceRecipients = effect.scope === "party"
? friendlyTargets
: friendlyTargets.length ? friendlyTargets : [member.id];
const resourceRecipients = effect.scope === "caster"
? [member.id]
: effect.scope === "party"
? friendlyTargets
: friendlyTargets.length ? friendlyTargets : [member.id];
for (const friendlyTargetId of resourceRecipients) {
const resource = effect.resource ?? member.resourceType;
if (effect.scope === "party"
@@ -4241,13 +4417,43 @@ function executePartyAbility(
}
}
} else if (effect.kind === "combo") {
if (ability.dbcSpellId === 490151) {
if ([490151, 499909].includes(ability.dbcSpellId ?? -1)) {
useCombatStore.setState((state) => ({
effects: state.effects.filter((entry) => !(entry.kind === "dot"
&& entry.tag === "rom-holy-seal" && entry.sourceActorId === member.id
&& entry.targetId === targetId)),
}));
}
if (targetId && ability.dbcSpellId === 499909
&& member.classId === "rom-knight" && member.secondaryClassId === "rom-rogue") {
const pairAbilities = abilitiesForCharacter(member.classId, member.secondaryClassId);
const vengeanceBase = pairAbilities.find((candidate) => candidate.source === "runewaker"
&& candidate.classId === "rom-knight" && candidate.secondaryClassId === "rom-rogue"
&& candidate.dbcSpellId === 499934 && candidate.passive);
const shadowStepBase = pairAbilities.find((candidate) => candidate.source === "runewaker"
&& candidate.classId === "rom-rogue" && candidate.dbcSpellId === 490344);
const vengeance = vengeanceBase
? learnedAbilityForBuild(vengeanceBase, runtimeMember.level, runtimeMember.talentRanks)
: null;
const shadowStep = shadowStepBase
? learnedAbilityForBuild(shadowStepBase, runtimeMember.level, runtimeMember.talentRanks)
: null;
if (shadowStep && romKnightGodsVengeanceShouldResetShadowStep({
characterClassId: member.classId,
secondaryClassId: member.secondaryClassId,
ability,
learnedPassiveSpellIds: vengeance ? [vengeance.dbcSpellId ?? -1] : [],
shadowStepLearned: true,
targetSealStacks: runtimeMember.comboTargetId === targetId ? runtimeMember.comboPoints : 0,
sameTarget: runtimeMember.comboTargetId === targetId,
landed: landedDirectHitTargetIdsForCast.has(targetId),
})) {
runtimeMember = {
...runtimeMember,
cooldowns: { ...runtimeMember.cooldowns, [shadowStep.id]: 0 },
};
}
}
const current = runtimeMember.comboTargetId === targetId ? runtimeMember.comboPoints : 0;
const comboPoints = Math.max(0, Math.min(member.classId === "rom-knight" ? 4 : 5, current + effect.amount));
runtimeMember = {
@@ -4389,6 +4595,42 @@ function executePartyAbility(
}
}
}
if (isRomChampionDarkEnergyStrike && !channelPulse && targetId) {
const runeSiphonBase = abilitiesForCharacter(member.classId, member.secondaryClassId)
.find((candidate) => candidate.source === "runewaker"
&& candidate.classId === "rom-champion"
&& candidate.secondaryClassId === "rom-warlock"
&& candidate.dbcSpellId === ROM_CHAMPION_RUNE_SIPHON_ID);
const learnedRuneSiphon = runeSiphonBase
? learnedAbilityForBuild(runeSiphonBase, member.level, member.talentRanks)
: null;
if (romChampionDarkEnergyStrikeShouldResetRuneSiphon({
characterClassId: member.classId,
secondaryClassId: member.secondaryClassId,
ability,
runeSiphonLearned: learnedRuneSiphon !== null,
singleTargetCast: hostileTargets.length === 1 && hostileTargets[0] === targetId,
group0Survived: romChampionDarkEnergyStrikeGroup0SurvivedTargets.has(targetId),
roll: stablePartyUnit(
`${member.id}:${ability.id}:${targetId}:${now}:rom-champion-dark-energy-strike-rune-siphon`,
),
}) && learnedRuneSiphon) {
runtimeMember = {
...runtimeMember,
cooldowns: { ...runtimeMember.cooldowns, [learnedRuneSiphon.id]: 0 },
};
useCombatStore.setState((state) => {
const actor = state.actors[member.id];
return actor ? {
actors: {
...state.actors,
[member.id]: { ...actor, cooldowns: { ...actor.cooldowns, [learnedRuneSiphon.id]: 0 } },
},
} : {};
});
combat = useCombatStore.getState();
}
}
if (!channelPulse && depth === 0) {
maybeProcPartyShamanTidalWaves(member, ability, directHealingRawAmount, now);
}
@@ -4486,6 +4728,12 @@ function executePartyAbility(
effectiveAmount += useCombatStore.getState().triggerChimeraShot(member.id, targetId, ability.id, now);
}
if (consumesColdBlood) useCombatStore.getState().consumeActorAuraTag(member.id, "next-offensive-critical");
if (consumesShamanNaturesGuardianCrit) {
useCombatStore.getState().consumeActorAuraTag(
member.id,
WOW335_SHAMAN_NATURES_GUARDIAN_NEXT_NATURE_CRIT_TAG,
);
}
if (ability.dbcSpellId === 491171) useCombatStore.getState().consumeActorAuraTag(member.id, "rom-charged");
if (ability.dbcSpellId === 491172) useCombatStore.getState().consumeActorAuraTag(member.id, "rom-static-field-charge");
if (ability.dbcSpellId === 498759) {
@@ -4893,6 +5141,7 @@ export function advanceDungeonPartyCombat(now = Date.now()): void {
nextMembers[index] = { ...member, status: "ready", nextActionAt: now + 250 };
continue;
}
applyPartyRomChampionRunePulseOnUse(member, castAbility, now);
if (castAbility.gcdMs > 0 && castingHastePercent > 0) {
committed = {
...committed,
@@ -5184,6 +5433,7 @@ export function advanceDungeonPartyCombat(now = Date.now()): void {
nextMembers[index] = { ...runtimeMember, status: desiredStatus, nextActionAt: now + 250 };
continue;
}
applyPartyRomChampionRunePulseOnUse(runtimeMember, castAbility, now);
if (castAbility.gcdMs > 0 && castingHastePercent > 0) {
committed = {
...committed,
+99 -26
View File
@@ -39,6 +39,7 @@ import {
} from "./companionSpecReadiness";
import type { RuntimeTalentRanks as TalentRanks } from "./talentRuntimeCatalog";
import type { EnemyControlMechanic } from "./enemyAttacks";
import { normalizeCharacterStatRuleset, type CharacterStatRuleset } from "./characterStatRuleset";
import type { ContentCategoryId } from "../app/contentCategories";
import { isValidRomClassPair, ROM_SECONDARY_UNLOCK_LEVEL } from "../app/romDualClass";
import type { PartyRole, PartySize } from "./partyRoles";
@@ -89,6 +90,7 @@ export interface PartyMember {
readonly gender: GenderId;
readonly appearance: CharacterAppearance;
readonly classId: ClassId;
readonly statRuleset?: CharacterStatRuleset;
readonly secondaryClassId?: ClassId | null;
readonly specialization: string;
readonly specializationId: string | null;
@@ -106,6 +108,7 @@ export interface PartyMember {
readonly resource: number;
readonly maxResource: number;
readonly resourcePools: Readonly<Partial<Record<ResourceType, number>>>;
readonly resourceMaximums?: Readonly<Partial<Record<ResourceType, number>>>;
readonly lastResourceSpentAt: Readonly<Partial<Record<ResourceType, number>>>;
readonly warriorAngerManagementRageRemainderMs?: number;
readonly comboPoints: number;
@@ -127,8 +130,10 @@ export interface PartyMember {
interface PartyTemplate {
readonly name: string;
readonly classId: ClassId;
readonly statRuleset?: CharacterStatRuleset;
readonly secondaryClassId?: ClassId | null;
readonly raceId?: RaceId;
readonly gender?: GenderId;
readonly specialization: string;
readonly talentTreeId: string;
readonly talentProfileId?: string | null;
@@ -137,8 +142,10 @@ interface PartyTemplate {
export interface ConfiguredPartyMemberSeed {
readonly name: string;
readonly classId: ClassId;
readonly statRuleset?: CharacterStatRuleset;
readonly secondaryClassId?: ClassId | null;
readonly raceId?: RaceId;
readonly gender?: GenderId;
readonly specialization: string;
readonly specializationId?: string | null;
readonly talentTreeId?: string;
@@ -195,20 +202,20 @@ function wowTemplates(
}
const ROM_TANK_TEMPLATES: readonly PartyTemplate[] = Object.freeze([
{ name: "Aldric", classId: "rom-warrior", specialization: "Primary", talentTreeId: "" },
{ ...romFiveIdentity("rom-knight", "tank")!, specialization: "Primary", talentTreeId: "" },
{ name: "Maerwen", classId: "rom-warden", specialization: "Primary", talentTreeId: "" },
{ name: "Bronn", classId: "rom-champion", specialization: "Primary", talentTreeId: "" },
{ name: "Aldric", classId: "rom-warrior", statRuleset: "rom", specialization: "Primary", talentTreeId: "" },
{ ...romFiveIdentity("rom-knight", "tank")!, statRuleset: "rom", specialization: "Primary", talentTreeId: "" },
{ name: "Maerwen", classId: "rom-warden", statRuleset: "rom", specialization: "Primary", talentTreeId: "" },
{ name: "Bronn", classId: "rom-champion", statRuleset: "rom", specialization: "Primary", talentTreeId: "" },
]);
const ROM_HEALER_TEMPLATES: readonly PartyTemplate[] = Object.freeze([
{ ...romFiveIdentity("rom-priest", "healer")!, specialization: "Primary", talentTreeId: "" },
{ name: "Sylva", classId: "rom-druid", specialization: "Primary", talentTreeId: "" },
{ ...romFiveIdentity("rom-priest", "healer")!, statRuleset: "rom", specialization: "Primary", talentTreeId: "" },
{ name: "Sylva", classId: "rom-druid", statRuleset: "rom", specialization: "Primary", talentTreeId: "" },
]);
const ROM_DAMAGE_TEMPLATES: readonly PartyTemplate[] = Object.freeze([
{ ...romFiveIdentity("rom-scout", "damage")!, specialization: "Primary", talentTreeId: "" },
{ ...romFiveIdentity("rom-rogue", "damage")!, specialization: "Primary", talentTreeId: "" },
{ ...romFiveIdentity("rom-mage", "damage")!, specialization: "Primary", talentTreeId: "" },
{ name: "Morgha", classId: "rom-warlock", specialization: "Primary", talentTreeId: "" },
{ ...romFiveIdentity("rom-scout", "damage")!, statRuleset: "rom", specialization: "Primary", talentTreeId: "" },
{ ...romFiveIdentity("rom-rogue", "damage")!, statRuleset: "rom", specialization: "Primary", talentTreeId: "" },
{ ...romFiveIdentity("rom-mage", "damage")!, statRuleset: "rom", specialization: "Primary", talentTreeId: "" },
{ name: "Morgha", classId: "rom-warlock", statRuleset: "rom", specialization: "Primary", talentTreeId: "" },
]);
export const TANK_SPECIALIZATIONS = Object.freeze(new Set(
@@ -251,10 +258,16 @@ function memberMaxHealth(
level: number,
role: PartyRole,
gearStats: ItemStats = EMPTY_ITEM_STATS,
_classId: ClassId = "warrior",
_raceId: RaceId = "human",
classId: ClassId = "warrior",
raceId: RaceId = "human",
statRuleset: CharacterStatRuleset = "wow",
secondaryClassId?: ClassId | null,
gender: GenderId = "male",
): number {
const safeLevel = Math.max(1, Math.trunc(level));
if (statRuleset === "rom") {
return deriveCharacterStats(classId, safeLevel, gearStats, raceId, {}, secondaryClassId, gender, statRuleset).health;
}
const base = role === "tank"
? 185 + safeLevel * 32
: role === "healer"
@@ -268,10 +281,13 @@ function memberMaxResource(
level: number,
raceId: RaceId,
gearStats: ItemStats = EMPTY_ITEM_STATS,
statRuleset: CharacterStatRuleset = "wow",
secondaryClassId?: ClassId | null,
gender: GenderId = "male",
): number {
const profile = resourceProfileForClass(classId);
return profile.type === "mana"
? deriveCharacterStats(classId, level, gearStats, raceId).mana
? deriveCharacterStats(classId, level, gearStats, raceId, {}, secondaryClassId, gender, statRuleset).mana
: profile.maximum;
}
@@ -280,6 +296,12 @@ function secondaryResourceMaximum(type: ResourceType, member: PartyMember): numb
return naturePowerMaximumForCharacter(member.classId, member.secondaryClassId, member.level);
}
if (type === "psi") return 6;
if (type === "mana" && member.statRuleset === "rom") {
return deriveCharacterStats(
member.classId, member.level, member.gearStats, member.raceId, {}, member.secondaryClassId,
member.gender, "rom",
).mana;
}
return 100;
}
@@ -292,6 +314,19 @@ function initialSecondaryResource(type: ResourceType, maximum: number): number {
/** Keeps every resource used by the member's learned kit available to companion AI. */
function withMemberAbilityResourcePools(member: PartyMember): PartyMember {
const types = new Set<ResourceType>([member.resourceType]);
if (member.statRuleset === "rom" && isRomClassId(member.classId)
&& deriveCharacterStats(
member.classId,
member.level,
member.gearStats,
member.raceId,
{},
member.secondaryClassId,
member.gender,
"rom",
).romNative?.usesMana) {
types.add("mana");
}
for (const ability of abilitiesForCharacter(member.classId, member.secondaryClassId)) {
const learned = learnedAbilityForBuild(ability, member.level, member.talentRanks);
if (!learned) continue;
@@ -300,18 +335,26 @@ function withMemberAbilityResourcePools(member: PartyMember): PartyMember {
}
}
const resourcePools: Partial<Record<ResourceType, number>> = {};
const resourceMaximums: Partial<Record<ResourceType, number>> = {};
for (const type of types) {
const maximum = type === member.resourceType
? member.maxResource
: member.resourceMaximums?.[type] ?? secondaryResourceMaximum(type, member);
resourceMaximums[type] = maximum;
if (type === member.resourceType) {
resourcePools[type] = member.resource;
continue;
}
const maximum = secondaryResourceMaximum(type, member);
resourcePools[type] = Math.max(0, Math.min(
maximum,
member.resourcePools[type] ?? initialSecondaryResource(type, maximum),
));
}
return { ...member, resourcePools: Object.freeze(resourcePools) };
return {
...member,
resourcePools: Object.freeze(resourcePools),
resourceMaximums: Object.freeze(resourceMaximums),
};
}
function withMemberGearStats(member: PartyMember, gearStats: ItemStats): PartyMember {
@@ -321,16 +364,22 @@ function withMemberGearStats(member: PartyMember, gearStats: ItemStats): PartyMe
gearStats,
member.classId,
member.raceId,
member.statRuleset,
member.secondaryClassId,
member.gender,
);
const health = member.health <= 0
? 0
: Math.max(1, Math.round(member.health / Math.max(1, member.maxHealth) * maxHealth));
const maxResource = memberMaxResource(member.classId, member.level, member.raceId, gearStats);
const maxResource = memberMaxResource(
member.classId, member.level, member.raceId, gearStats, member.statRuleset, member.secondaryClassId, member.gender,
);
const resource = Math.max(0, Math.round(
member.resource / Math.max(1, member.maxResource) * maxResource,
));
return withMemberAbilityResourcePools({
...member,
resourceMaximums: undefined,
gearStats,
health,
maxHealth,
@@ -367,9 +416,16 @@ function createMember(
const race = racePool.find((candidate) => candidate.id === template.raceId)
?? racePool[Math.floor(nextRandom(identityRandom) * racePool.length)] ?? racePool[0];
const genders = supportedGenders(race.id);
const gender: GenderId = genders[Math.floor(nextRandom(identityRandom) * genders.length)] ?? genders[0] ?? "male";
const gender: GenderId = template.gender
?? genders[Math.floor(nextRandom(identityRandom) * genders.length)]
?? genders[0]
?? "male";
const appearance = randomAppearance(race.id, gender, () => nextRandom(identityRandom));
const id = `party-${role}-${index}-${template.classId}`;
const statRuleset = normalizeCharacterStatRuleset(
template.statRuleset ?? "wow",
template.classId,
);
const specializationId = specializationsForClass(template.classId)
.find((definition) => definition.displayName === template.specialization)?.id ?? null;
const gearStats = resolvedEquipmentStats({}, [], {
@@ -381,9 +437,14 @@ function createMember(
role,
level,
});
const maxHealth = memberMaxHealth(level, role, gearStats, template.classId, race.id);
const secondaryClassId = level >= ROM_SECONDARY_UNLOCK_LEVEL ? template.secondaryClassId ?? null : null;
const maxHealth = memberMaxHealth(
level, role, gearStats, template.classId, race.id, statRuleset, secondaryClassId, gender,
);
const resourceProfile = resourceProfileForClass(template.classId);
const maxResource = memberMaxResource(template.classId, level, race.id, gearStats);
const maxResource = memberMaxResource(
template.classId, level, race.id, gearStats, statRuleset, secondaryClassId, gender,
);
const resource = Math.round(
maxResource * (resourceProfile.maximum > 0 ? resourceProfile.initial / resourceProfile.maximum : 0),
);
@@ -394,7 +455,8 @@ function createMember(
gender,
appearance,
classId: template.classId,
secondaryClassId: level >= ROM_SECONDARY_UNLOCK_LEVEL ? template.secondaryClassId ?? null : null,
statRuleset,
secondaryClassId,
specialization: template.specialization,
specializationId,
talentTreeId: template.talentTreeId,
@@ -439,8 +501,10 @@ export function createConfiguredPartyMember(
const member = createMember({
name: configuration.name,
classId: configuration.classId,
statRuleset: configuration.statRuleset ?? "wow",
secondaryClassId: configuration.secondaryClassId,
raceId: configuration.raceId,
gender: configuration.gender,
specialization: configuration.specialization,
talentTreeId: configuration.talentTreeId ?? configuration.specializationId ?? "",
talentProfileId: configuration.talentProfileId ?? null,
@@ -583,6 +647,7 @@ export interface PartyState {
| "resource"
| "maxResource"
| "resourcePools"
| "resourceMaximums"
| "lastResourceSpentAt"
| "cooldowns"
| "globalCooldownEndsAt"
@@ -678,12 +743,21 @@ export const usePartyStore = create<PartyState>((set, get) => ({
if (state.members.every((member) => member.level === safeLevel)) return state;
return {
members: state.members.map((member) => {
const nextSecondaryClassId = isRomClassId(member.classId)
&& romFiveIdentity(member.classId, member.role)?.name === member.name
? (safeLevel >= ROM_SECONDARY_UNLOCK_LEVEL
? romFiveIdentity(member.classId, member.role)?.secondaryClassId ?? null
: null)
: member.secondaryClassId;
const maxHealth = memberMaxHealth(
safeLevel,
member.role,
member.gearStats,
member.classId,
member.raceId,
member.statRuleset,
nextSecondaryClassId,
member.gender,
);
const health = member.health <= 0
? 0
@@ -693,19 +767,18 @@ export const usePartyStore = create<PartyState>((set, get) => ({
safeLevel,
member.raceId,
member.gearStats,
member.statRuleset,
nextSecondaryClassId,
member.gender,
);
const resource = Math.max(0, Math.round(
member.resource / Math.max(1, member.maxResource) * maxResource,
));
return withMemberAbilityResourcePools({
...member,
resourceMaximums: undefined,
level: safeLevel,
secondaryClassId: isRomClassId(member.classId)
&& romFiveIdentity(member.classId, member.role)?.name === member.name
? (safeLevel >= ROM_SECONDARY_UNLOCK_LEVEL
? romFiveIdentity(member.classId, member.role)?.secondaryClassId ?? null
: null)
: member.secondaryClassId,
secondaryClassId: nextSecondaryClassId,
health,
maxHealth,
resource,
+9
View File
@@ -1,10 +1,12 @@
import {
type GenderId,
type ClassId,
type RaceId,
} from "../app/characterCatalog";
import azerothCoreReference from "./generated/azerothCoreReference.json";
import { EMPTY_ITEM_STATS } from "./itemStats";
import { deriveCharacterStats } from "./wotlkStats";
import type { CharacterStatRuleset } from "./characterStatRuleset";
export const MIN_PLAYER_LEVEL = 1;
export const MAX_PLAYER_LEVEL = 80;
@@ -106,12 +108,19 @@ export function maxHealthForLevel(
classId: ClassId,
level: number,
raceId: RaceId = "human",
secondaryClassId?: ClassId | null,
gender: GenderId = "male",
statRuleset: CharacterStatRuleset = "wow",
): number {
return deriveCharacterStats(
classId,
clampPlayerLevel(level),
EMPTY_ITEM_STATS,
raceId,
{},
secondaryClassId,
gender,
statRuleset,
).health;
}
+9 -3
View File
@@ -204,7 +204,8 @@ function currentWarlockCoaDescription(sourceSkillId: number, fallback: string):
499827: "Passive: Increases Slash damage by an unspecified amount, which is not modeled. Reduces Slash's Rage cost by 10.",
499806: "Passive: Grants an additional 20% Physical Damage.",
498642: "Converts 75 Rage into 6 Psi. 1-second cooldown.",
498634: "Enraged restores additional Focus. Casting Psychic Arrows, Warp Charge, or Weakening Weave Curse can reset Enraged's cooldown. Current CoA does not publish the proc chance or Focus amount, so these riders are not modeled.",
498641: "Restores HP for up to 6 friendly targets in range. Also provides 1 Psi.",
498634: "When casting Psychic Arrows, Warp Charge, Weakening Weave Curse, Slash, Soul Trauma, Puzzlement, Heart Collection Strike, or Surge of Malice, there is a chance to trigger Enraged automatically. Enraged also recovers additional Focus. Current CoA does not publish the proc chance, trigger timing, or extra Focus amount, so these effects are not modeled.",
498633: "When Psychic Arrows hits, gain 12% healing power and 12% Wisdom for 20 seconds. Warp Charge heals a friendly target instead of dealing damage. The simulator does not model ally-target redirection to that ally's hostile target.",
498643: "Rising Tide becomes instant with a 5-second cooldown and restores 1 Psi. A critical hit activates Healing Fortune. The simulator cannot redirect an ally-targeted cast to that ally's hostile target.",
498648: "Urgent Heal restores 1 Psi. Defense Net's effect time is reduced by 1 second. Ring of Comfort's reset chance is not specified and is not modeled.",
@@ -680,6 +681,11 @@ function targetStateAuraEffect(row: GeneratedSemanticRow, stateId: string, name:
}
function specializedEffects(row: GeneratedSemanticRow): readonly AbilityEffect[] | null {
if (row.classId === "rom-rogue" && row.secondaryClassId === "rom-warden" && row.sourceSkillId === 499544) {
// The 900-second state owns Revival's 499545 on-hit child. The hit-time
// runtime supplies its sourced stack and physical-dodge components.
return [stateAuraEffect(row, "warden-revival-state", row.name, 900_000)];
}
if (row.classId === "rom-druid" && row.secondaryClassId === "rom-warrior" && row.sourceSkillId === 499955) {
// Briar Technique's modifiers are applied by its named source skills on a
// landed hit; it is a marker here, not a permanent stat aura.
@@ -1269,8 +1275,8 @@ function effects(row: GeneratedSemanticRow): readonly AbilityEffect[] {
...holySealDot(false),
{ kind: "combo", amount: 2 },
];
if (row.sourceSkillId === 490151) return [
...oneOutput("damage", true), ...oneOutput("dot", true), { kind: "combo", amount: -5 },
if (row.sourceSkillId === 490151 || row.sourceSkillId === 499909) return [
...oneOutput("damage", true), { kind: "combo", amount: -5 },
];
if (row.sourceSkillId === 491169) {
return [...translated, stateAuraEffect(row, "charged", "Charged", 6_000)];
+25 -2
View File
@@ -22,6 +22,7 @@ function isMeaningfulEffect(effect: AbilityEffect): boolean {
return (
output.coefficient > 0
|| (output.coefficientPerLevel ?? 0) > 0
|| (output.kind === "damage" && (output.weaponDpsCoefficient ?? 0) > 0)
|| (output.basePoints ?? 0) > 0
|| (output.pointsPerLevel ?? 0) > 0
|| (output.kind === "heal" && (output.percentMaxHealth ?? 0) > 0)
@@ -380,6 +381,23 @@ describe("executable RuneWaker ability mappings", () => {
});
it("gives every active base skill and playable rank a concrete runtime effect", () => {
const generatedSkillIds = new Set(generated.skills.map((skill) => skill.id));
const runtimeOnly = ROM_ALL_ABILITIES.filter((ability) => !generatedSkillIds.has(ability.id));
const generatedRankCount = generated.skills.reduce((count, skill) => count + skill.ranks.length, 0);
// Snapshot accounting is source-backed: 932 generated rows carry 937
// source ranks. Four explicit runtime additions have no separate ranks:
// Devotion Halo, CoA Blocking Stance, CoA Probing Attack, and CoA Enraged.
expect(generated.skills).toHaveLength(932);
expect(generatedRankCount).toBe(937);
expect(ROM_ALL_ABILITIES).toHaveLength(936);
expect(runtimeOnly.map((ability) => ability.id).sort()).toEqual([
"rom-priest-rom-knight-elite-70-devotion-halo",
"rom-warlock-rom-warrior-general-coa-499871",
"rom-warrior-rom-knight-elite-50-coa-493287",
"rom-warrior-rom-rogue-elite-50-coa-493283",
]);
expect(runtimeOnly.every((ability) => ability.ranks?.length === 0 || ability.ranks === undefined)).toBe(true);
const versions = ROM_ALL_ABILITIES.flatMap((ability) => [
{ name: ability.name, rank: 0, passive: ability.passive, effects: ability.effects },
...(ability.ranks ?? []).map((rank) => ({
@@ -390,7 +408,7 @@ describe("executable RuneWaker ability mappings", () => {
})),
]);
expect(versions).toHaveLength(1_864);
expect(versions).toHaveLength(1_873);
const scriptOnly = ROM_ALL_ABILITIES
.filter((ability) => !ability.passive && ability.effects.every((effect) => effect.kind === "scripted"))
.map((ability) => ability.name)
@@ -471,6 +489,11 @@ describe("executable RuneWaker ability mappings", () => {
expect(named("Holy Strike").effects.filter((effect) => effect.kind === "dot")).toHaveLength(1);
expect(named("Holy Seal").effects.filter((effect) => effect.kind === "dot")).toHaveLength(1);
expect(named("Punishment").effects.filter((effect) => effect.kind === "damage")).toHaveLength(1);
expect(named("Punishment").effects.filter((effect) => effect.kind === "dot")).toHaveLength(1);
expect(named("Punishment").effects.filter((effect) => effect.kind === "dot")).toHaveLength(0);
expect(sourceSkill(499909).effects).toEqual(expect.arrayContaining([
{ kind: "combo", amount: -5 },
expect.objectContaining({ kind: "damage" }),
]));
expect(sourceSkill(499909).effects.filter((effect) => effect.kind === "dot")).toHaveLength(0);
});
});
@@ -0,0 +1,311 @@
import { beforeEach, describe, expect, it } from "vitest";
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
import { useCombatStore, stableCombatUnit } from "./combatStore";
import { PLAYER_AGGRO_ID } from "./aggro";
import { applyAura } from "./combatAuras";
import {
abilitiesForCharacter,
abilityById,
learnedAbilityForBuild,
} from "./abilityCatalog";
import { advanceDungeonPartyCombat, resetPartyRuntimeClock } from "./partyRuntime";
import { createConfiguredPartyMember, usePartyStore } from "./partyStore";
import {
clearPartyRuntimeRegistry,
updatePartyRuntimePosition,
updatePartyRuntimeTargetVisibility,
} from "./partyRuntimeRegistry";
const STRIKE_ID = "rom-champion-rom-warlock-elite-30";
const SIPHON_ID = "rom-champion-rom-warlock-elite-20";
const TARGET_ID = "dark-energy-strike-source-target";
function seededStrikeTime(actorId: string, suffix: "direct" | "special-crit"): number {
const strike = abilityById(STRIKE_ID)!;
for (let now = 10_000; now < 100_000; now += 1) {
const resetRoll = stableCombatUnit(
`${actorId}:${strike.id}:${TARGET_ID}:${now}:rom-champion-dark-energy-strike-rune-siphon`,
);
const outcomeRoll = stableCombatUnit(`${actorId}:${strike.id}:${TARGET_ID}:${now}:${suffix}:outcome`);
if (resetRoll < 0.15 && outcomeRoll >= 0.2 && outcomeRoll < 0.8) return now;
}
throw new Error("Could not find a deterministic landed Dark Energy Strike reset seed.");
}
function setupPlayerStrike(
armor: number,
shadowResistance: number,
now: number,
targetLevel = 1,
shadowImmune = false,
targetHealth = 1_000_000,
) {
useCombatStore.getState().initializeCharacter({
classId: "rom-champion",
secondaryClassId: "rom-warlock",
raceId: "rom-dwarf",
level: 30,
});
useCombatStore.getState().registerMob(TARGET_ID, {
name: TARGET_ID,
level: targetLevel,
maxHealth: targetHealth,
resistances: { shadow: shadowResistance },
...(shadowImmune ? { schoolImmunities: ["shadow"] } : {}),
});
setMobPosition(TARGET_ID, [3, 0, 0]);
useCombatStore.setState((state) => {
const target = state.mobs[TARGET_ID]!;
return {
mobs: { ...state.mobs, [TARGET_ID]: { ...target, armor } },
resource: 100,
resourcePools: { ...state.resourcePools, rage: 100 },
cooldowns: { ...state.cooldowns, [SIPHON_ID]: now + 60_000 },
};
});
}
function playerStrikeDamage(armor: number, shadowResistance: number): number {
const now = seededStrikeTime(PLAYER_AGGRO_ID, "direct");
setupPlayerStrike(armor, shadowResistance, now);
const result = useCombatStore.getState().castAbility(STRIKE_ID, {
targetActorId: TARGET_ID,
now,
});
expect(result, JSON.stringify(result)).toMatchObject({ ok: true, affectedMobIds: [TARGET_ID] });
return result.damage;
}
describe("Dark Energy Strike ordered-group integration", () => {
beforeEach(() => {
clearMobRuntimeRegistry();
clearPartyRuntimeRegistry();
resetPartyRuntimeClock();
useCombatStore.setState({ playerPosition: [0, 0, 0] });
});
it("uses armor for the physical group and shadow resistance for the Darkness group", () => {
const noArmorNoShadowResistance = playerStrikeDamage(0, 0);
const armorNoShadowResistance = playerStrikeDamage(50_000, 0);
const armorHighShadowResistance = playerStrikeDamage(50_000, 1_000_000);
expect(noArmorNoShadowResistance).toBeGreaterThan(armorNoShadowResistance);
expect(armorNoShadowResistance).toBeGreaterThan(armorHighShadowResistance);
expect(armorHighShadowResistance).toBeGreaterThan(0);
});
it("resets the player's separately learned Rune Siphon after physical success even when Darkness is fully resisted", () => {
const now = seededStrikeTime(PLAYER_AGGRO_ID, "direct");
setupPlayerStrike(50_000, 0, now, 1, true);
const result = useCombatStore.getState().castAbility(STRIKE_ID, {
targetActorId: TARGET_ID,
now,
});
expect(result, JSON.stringify(result)).toMatchObject({ ok: true, damage: expect.any(Number) });
expect(result.damage).toBeGreaterThan(0);
expect(useCombatStore.getState().combatEvents.filter((event) => event.kind === "damage"
&& event.abilityId === STRIKE_ID && event.school === "shadow")).toEqual([
expect.objectContaining({ effectiveAmount: 0 }),
]);
expect(useCombatStore.getState().cooldowns[SIPHON_ID]).toBe(0);
});
it("does not run the Darkness packet or reset after the player's physical packet misses", () => {
const now = seededStrikeTime(PLAYER_AGGRO_ID, "direct");
setupPlayerStrike(0, 0, now, 255);
const result = useCombatStore.getState().castAbility(STRIKE_ID, {
targetActorId: TARGET_ID,
now,
});
const strikeDamageEvents = useCombatStore.getState().combatEvents.filter((event) => (
event.kind === "damage" && event.abilityId === STRIKE_ID
));
expect(result, JSON.stringify(result)).toMatchObject({ ok: true, damage: 0 });
expect(strikeDamageEvents).toHaveLength(1);
expect(strikeDamageEvents[0]).toMatchObject({ school: "physical", outcome: "miss" });
expect(useCombatStore.getState().cooldowns[SIPHON_ID]).toBe(now + 60_000);
});
it("does not run the Darkness packet or reset when an absorb reduces physical HP damage to zero", () => {
const now = seededStrikeTime(PLAYER_AGGRO_ID, "direct");
setupPlayerStrike(0, 0, now);
const shield = applyAura(useCombatStore.getState().auras, {
definition: {
id: "test:dark-energy-physical-absorb",
name: "Physical absorb fixture",
disposition: "buff",
durationMs: null,
absorbs: [{ id: "test:dark-energy-physical-absorb-pool", amount: 1_000_000, school: "physical" }],
},
sourceId: PLAYER_AGGRO_ID,
targetId: TARGET_ID,
now,
}).auras;
useCombatStore.setState({ auras: shield });
const result = useCombatStore.getState().castAbility(STRIKE_ID, {
targetActorId: TARGET_ID,
now,
});
const strikeDamageEvents = useCombatStore.getState().combatEvents.filter((event) => (
event.kind === "damage" && event.abilityId === STRIKE_ID
));
expect(result, JSON.stringify(result)).toMatchObject({ ok: true, damage: 0 });
expect(strikeDamageEvents).toHaveLength(1);
expect(strikeDamageEvents[0]).toMatchObject({
school: "physical",
effectiveAmount: 0,
absorbed: expect.any(Number),
});
expect(strikeDamageEvents[0]!.absorbed).toBeGreaterThan(0);
expect(useCombatStore.getState().cooldowns[SIPHON_ID]).toBe(now + 60_000);
});
it("keeps the physical success eligible for reset when that packet kills its target", () => {
const now = seededStrikeTime(PLAYER_AGGRO_ID, "direct");
setupPlayerStrike(0, 0, now, 1, false, 1);
const result = useCombatStore.getState().castAbility(STRIKE_ID, {
targetActorId: TARGET_ID,
now,
});
const strikeDamageEvents = useCombatStore.getState().combatEvents.filter((event) => (
event.kind === "damage" && event.abilityId === STRIKE_ID
));
expect(result, JSON.stringify(result)).toMatchObject({ ok: true, damage: 1 });
expect(useCombatStore.getState().mobs[TARGET_ID]?.dead).toBe(true);
expect(strikeDamageEvents).toHaveLength(1);
expect(strikeDamageEvents[0]).toMatchObject({ school: "physical", effectiveAmount: 1 });
expect(useCombatStore.getState().cooldowns[SIPHON_ID]).toBe(0);
});
it("resets a companion's Rune Siphon in both owner and combat-actor cooldown mirrors", () => {
const seed = "dark-energy-strike-companion";
useCombatStore.getState().initializeCharacter({ classId: "rom-champion", raceId: "rom-dwarf", level: 30 });
const companion = createConfiguredPartyMember({
name: "Champion/Warlock",
classId: "rom-champion",
secondaryClassId: "rom-warlock",
raceId: "rom-dwarf",
specialization: "Primary",
specializationId: "rom-champion:rom-warlock",
talentTreeId: "rom-champion-rom-warlock",
role: "damage",
}, 30, 0, seed);
const strike = abilitiesForCharacter("rom-champion", "rom-warlock")
.find((ability) => ability.dbcSpellId === 498_599)!;
const siphon = abilitiesForCharacter("rom-champion", "rom-warlock")
.find((ability) => ability.dbcSpellId === 498_595)!;
const learnedStrike = learnedAbilityForBuild(strike, companion.level, companion.talentRanks)!;
const learnedSiphon = learnedAbilityForBuild(siphon, companion.level, companion.talentRanks)!;
const now = seededStrikeTime(companion.id, "special-crit");
usePartyStore.getState().initializeParty(seed, 30, useCombatStore.getState().health, "damage", 1, "rom");
useCombatStore.getState().registerMob(TARGET_ID, { name: TARGET_ID, level: 1, maxHealth: 1_000_000, xpReward: 0 });
setMobPosition(TARGET_ID, [2, 0, 0]);
useCombatStore.getState().damageMob(TARGET_ID, 1, now);
updatePartyRuntimePosition(companion.id, 0, 0, 0);
usePartyStore.setState({
command: "attack",
members: [{
...companion,
resource: 100,
resourcePools: { ...companion.resourcePools, rage: 100 },
cooldowns: { ...companion.cooldowns, [learnedSiphon.id]: now + 60_000 },
activeCast: {
abilityId: learnedStrike.id,
school: "physical",
mode: "cast",
startedAt: now,
completesAt: now,
originalDurationMs: 0,
pushbackHits: 0,
origin: [0, 0, 0],
targetId: TARGET_ID,
},
activeCastTargetId: TARGET_ID,
status: "attacking",
}],
});
updatePartyRuntimeTargetVisibility(companion.id, TARGET_ID, true);
useCombatStore.getState().synchronizeActors();
advanceDungeonPartyCombat(now);
expect(usePartyStore.getState().members[0]?.cooldowns[learnedSiphon.id]).toBe(0);
expect(useCombatStore.getState().actors[companion.id]?.cooldowns[learnedSiphon.id]).toBe(0);
});
it("does not run the companion Darkness packet or reset after its physical packet misses", () => {
const seed = "dark-energy-strike-companion-miss";
useCombatStore.getState().initializeCharacter({ classId: "rom-champion", raceId: "rom-dwarf", level: 30 });
const companion = createConfiguredPartyMember({
name: "Champion/Warlock",
classId: "rom-champion",
secondaryClassId: "rom-warlock",
raceId: "rom-dwarf",
specialization: "Primary",
specializationId: "rom-champion:rom-warlock",
talentTreeId: "rom-champion-rom-warlock",
role: "damage",
}, 30, 0, seed);
const strike = abilitiesForCharacter("rom-champion", "rom-warlock")
.find((ability) => ability.dbcSpellId === 498_599)!;
const siphon = abilitiesForCharacter("rom-champion", "rom-warlock")
.find((ability) => ability.dbcSpellId === 498_595)!;
const learnedStrike = learnedAbilityForBuild(strike, companion.level, companion.talentRanks)!;
const learnedSiphon = learnedAbilityForBuild(siphon, companion.level, companion.talentRanks)!;
const now = seededStrikeTime(companion.id, "special-crit");
usePartyStore.getState().initializeParty(seed, 30, useCombatStore.getState().health, "damage", 1, "rom");
useCombatStore.getState().registerMob(TARGET_ID, {
name: TARGET_ID,
level: 255,
maxHealth: 1_000_000,
xpReward: 0,
});
setMobPosition(TARGET_ID, [2, 0, 0]);
useCombatStore.getState().damageMob(TARGET_ID, 1, now);
updatePartyRuntimePosition(companion.id, 0, 0, 0);
usePartyStore.setState({
command: "attack",
members: [{
...companion,
resource: 100,
resourcePools: { ...companion.resourcePools, rage: 100 },
cooldowns: { ...companion.cooldowns, [learnedSiphon.id]: now + 60_000 },
activeCast: {
abilityId: learnedStrike.id,
school: "physical",
mode: "cast",
startedAt: now,
completesAt: now,
originalDurationMs: 0,
pushbackHits: 0,
origin: [0, 0, 0],
targetId: TARGET_ID,
},
activeCastTargetId: TARGET_ID,
status: "attacking",
}],
});
updatePartyRuntimeTargetVisibility(companion.id, TARGET_ID, true);
useCombatStore.getState().synchronizeActors();
advanceDungeonPartyCombat(now);
const strikeDamageEvents = useCombatStore.getState().combatEvents.filter((event) => (
event.kind === "damage" && event.abilityId === learnedStrike.id
));
expect(strikeDamageEvents).toHaveLength(1);
expect(strikeDamageEvents[0]).toMatchObject({ school: "physical", outcome: "miss" });
expect(usePartyStore.getState().members[0]?.cooldowns[learnedSiphon.id]).toBe(now + 60_000);
expect(useCombatStore.getState().actors[companion.id]?.cooldowns[learnedSiphon.id]).toBe(now + 60_000);
});
});
@@ -0,0 +1,114 @@
import { describe, expect, it } from "vitest";
import generated from "./romPlayerCatalog.generated.json";
import { abilitiesForCharacter, abilityById, learnedAbilityForBuild } from "./abilityCatalog";
import { romEffectsForCast } from "./romCombatMechanics";
import {
ROM_CHAMPION_DARK_ENERGY_STRIKE_RESET_CHANCE,
romChampionDarkEnergyStrikeGroup0Survives,
romChampionDarkEnergyStrikeMatchesBuild,
romChampionDarkEnergyStrikePacketGroupAtDamageIndex,
romChampionDarkEnergyStrikeShouldResetRuneSiphon,
} from "./romChampionDarkEnergyStrikeRuntime";
describe("RuneWaker Champion/Warlock Dark Energy Strike source groups", () => {
const strike = abilityById("rom-champion-rom-warlock-elite-30")!;
it("keeps Dark Energy Strike and Rune Siphon as separately learned Champion/Warlock rows", () => {
const sourceStrike = generated.skills.find((ability) => ability.sourceSkillId === 498599);
const sourceSiphon = generated.skills.find((ability) => ability.sourceSkillId === 498595);
const pair = abilitiesForCharacter("rom-champion", "rom-warlock");
const strikeBase = pair.find((ability) => ability.dbcSpellId === 498599)!;
const siphonBase = pair.find((ability) => ability.dbcSpellId === 498595)!;
expect(sourceStrike).toMatchObject({
id: "rom-champion-rom-warlock-elite-30",
classId: "rom-champion",
secondaryClassId: "rom-warlock",
group: "elite",
unlockLevel: 30,
sourceSkillId: 498599,
ranks: [{ rank: 1, level: 30, prerequisites: [497958], sourceSkillId: 498599 }],
});
expect(sourceSiphon).toMatchObject({
id: "rom-champion-rom-warlock-elite-20",
classId: "rom-champion",
secondaryClassId: "rom-warlock",
unlockLevel: 20,
sourceSkillId: 498595,
ranks: [{ rank: 1, level: 20, prerequisites: [497958], sourceSkillId: 498595 }],
});
expect(learnedAbilityForBuild(strikeBase, 29, {})).toBeNull();
expect(learnedAbilityForBuild(strikeBase, 30, {})?.dbcSpellId).toBe(498599);
expect(learnedAbilityForBuild(siphonBase, 19, {})).toBeNull();
expect(learnedAbilityForBuild(siphonBase, 20, {})?.dbcSpellId).toBe(498595);
expect(abilitiesForCharacter("rom-champion", "rom-warrior")
.some((ability) => ability.dbcSpellId === 498599)).toBe(false);
expect(strike).toMatchObject({
source: "runewaker",
classId: "rom-champion",
secondaryClassId: "rom-warlock",
dbcSpellId: 498599,
unlockLevel: 30,
});
});
it("retains physical, darkness, then one cast-level reset group order", () => {
const damageGroups = romEffectsForCast(strike, {
sealStacks: 0,
bleedCount: 0,
charged: false,
mainHandDagger: false,
casterMaxHealth: 2_000,
targetHealthPercent: 1,
}).filter((effect) => effect.kind === "damage");
expect(damageGroups).toHaveLength(2);
expect(damageGroups.map((effect) => effect.kind === "damage" ? effect.school : null))
.toEqual(["physical", "shadow"]);
expect(romChampionDarkEnergyStrikePacketGroupAtDamageIndex(0)).toBe("physical");
expect(romChampionDarkEnergyStrikePacketGroupAtDamageIndex(1)).toBe("dark");
expect(romChampionDarkEnergyStrikePacketGroupAtDamageIndex(2)).toBeNull();
expect(ROM_CHAMPION_DARK_ENERGY_STRIKE_RESET_CHANCE).toBe(0.15);
});
it("lets only a nonzero, non-avoided physical result retain later groups, including a damaging parry", () => {
expect(romChampionDarkEnergyStrikeGroup0Survives({ effectiveDamage: 1 })).toBe(true);
expect(romChampionDarkEnergyStrikeGroup0Survives({
effectiveDamage: 1,
combatResult: {
missed: false, dodged: false, parried: true, blocked: false, fullyResisted: false,
},
})).toBe(true);
for (const failure of [
{ effectiveDamage: 0 }, // fully absorbed or no effect
{ effectiveDamage: 0, combatResult: { missed: true, dodged: false, parried: false, blocked: false, fullyResisted: false } },
{ effectiveDamage: 0, combatResult: { missed: false, dodged: true, parried: false, blocked: false, fullyResisted: false } },
{ effectiveDamage: 1, combatResult: { missed: false, dodged: false, parried: false, blocked: true, fullyResisted: false } },
{ effectiveDamage: 1, combatResult: { missed: false, dodged: false, parried: false, blocked: false, fullyResisted: true } },
]) {
expect(romChampionDarkEnergyStrikeGroup0Survives(failure)).toBe(false);
}
});
it("uses one exact-pair learned Rune Siphon reset roll after a surviving physical group", () => {
const base = {
characterClassId: "rom-champion",
secondaryClassId: "rom-warlock",
ability: strike,
runeSiphonLearned: true,
singleTargetCast: true,
group0Survived: true,
} as const;
expect(romChampionDarkEnergyStrikeShouldResetRuneSiphon({ ...base, roll: 0.149_999 })).toBe(true);
expect(romChampionDarkEnergyStrikeShouldResetRuneSiphon({ ...base, roll: 0.15 })).toBe(false);
expect(romChampionDarkEnergyStrikeShouldResetRuneSiphon({ ...base, group0Survived: false, roll: 0 })).toBe(false);
expect(romChampionDarkEnergyStrikeShouldResetRuneSiphon({ ...base, runeSiphonLearned: false, roll: 0 })).toBe(false);
expect(romChampionDarkEnergyStrikeShouldResetRuneSiphon({ ...base, singleTargetCast: false, roll: 0 })).toBe(false);
expect(romChampionDarkEnergyStrikeShouldResetRuneSiphon({ ...base, secondaryClassId: "rom-warrior", roll: 0 })).toBe(false);
expect(romChampionDarkEnergyStrikeShouldResetRuneSiphon({
...base,
ability: { ...strike, dbcSpellId: 498595 },
roll: 0,
})).toBe(false);
expect(romChampionDarkEnergyStrikeMatchesBuild("rom-warrior", "rom-warlock", strike)).toBe(false);
});
});
@@ -0,0 +1,81 @@
import type { AbilityDefinition } from "./abilityCatalog";
import type { CombatResult } from "./combatResults";
export const ROM_CHAMPION_DARK_ENERGY_STRIKE_ID = 498_599;
export const ROM_CHAMPION_RUNE_SIPHON_ID = 498_595;
export const ROM_CHAMPION_DARK_ENERGY_STRIKE_RESET_CHANCE = 0.15;
export type RomChampionDarkEnergyStrikePacketGroup = "physical" | "dark";
/** The two ordered MagicCollect groups that deal damage before the reset group. */
export function romChampionDarkEnergyStrikePacketGroupAtDamageIndex(
damageIndex: number,
): RomChampionDarkEnergyStrikePacketGroup | null {
if (damageIndex === 0) return "physical";
if (damageIndex === 1) return "dark";
return null;
}
export function romChampionDarkEnergyStrikeMatchesBuild(
characterClassId: string,
secondaryClassId: string | null | undefined,
ability: Pick<AbilityDefinition, "source" | "classId" | "secondaryClassId" | "dbcSpellId">,
): boolean {
return characterClassId === "rom-champion"
&& secondaryClassId === "rom-warlock"
&& ability.source === "runewaker"
&& ability.classId === "rom-champion"
&& ability.secondaryClassId === "rom-warlock"
&& ability.dbcSpellId === ROM_CHAMPION_DARK_ENERGY_STRIKE_ID;
}
export interface RomChampionDarkEnergyStrikeGroup0Result {
/** Effective HP damage remaining after mitigation and absorb application. */
readonly effectiveDamage: number;
readonly combatResult?: Pick<CombatResult, "missed" | "dodged" | "parried" | "blocked" | "fullyResisted">;
}
/**
* Source Magic00_AddHP preserves group 0 only for a nonzero, non-avoided
* result. Parry is intentionally not excluded: the source reports a nonzero
* parry result as eligible. This simulator gate uses effective HP damage for
* the nonzero/fully-absorbed boundary.
*/
export function romChampionDarkEnergyStrikeGroup0Survives(
result: RomChampionDarkEnergyStrikeGroup0Result,
): boolean {
if (!Number.isFinite(result.effectiveDamage) || result.effectiveDamage <= 0) return false;
if (!result.combatResult) return true;
return !result.combatResult.missed
&& !result.combatResult.dodged
&& !result.combatResult.blocked
&& !result.combatResult.fullyResisted;
}
export interface RomChampionDarkEnergyStrikeResetContext {
readonly characterClassId: string;
readonly secondaryClassId: string | null | undefined;
readonly ability: Pick<AbilityDefinition, "source" | "classId" | "secondaryClassId" | "dbcSpellId">;
readonly runeSiphonLearned: boolean;
readonly singleTargetCast: boolean;
readonly group0Survived: boolean;
/** One deterministic roll for this cast's ordered group 2. */
readonly roll: number;
}
/** Group 2 is one 15% roll after eligible group 0; group 1 has no gate input. */
export function romChampionDarkEnergyStrikeShouldResetRuneSiphon(
context: RomChampionDarkEnergyStrikeResetContext,
): boolean {
return romChampionDarkEnergyStrikeMatchesBuild(
context.characterClassId,
context.secondaryClassId,
context.ability,
)
&& context.runeSiphonLearned
&& context.singleTargetCast
&& context.group0Survived
&& Number.isFinite(context.roll)
&& context.roll >= 0
&& context.roll < ROM_CHAMPION_DARK_ENERGY_STRIKE_RESET_CHANCE;
}
+210
View File
@@ -0,0 +1,210 @@
import { describe, expect, it } from "vitest";
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
import { advanceDungeonPartyCombat, resetPartyRuntimeClock } from "./partyRuntime";
import { createConfiguredPartyMember, usePartyStore } from "./partyStore";
import { clearPartyRuntimeRegistry, updatePartyRuntimePosition, updatePartyRuntimeTargetVisibility } from "./partyRuntimeRegistry";
import { useCombatStore } from "./combatStore";
import { abilitiesForCharacter, learnedAbilityForBuild } from "./abilityCatalog";
import { applyAura, resolveDamageValue } from "./combatAuras";
import { ROM_ALL_ABILITIES } from "./romAbilityCatalog";
import { romChampionCastEffects } from "./romChampionOverrides";
import {
ROM_CHAMPION_CHAIN_DRIVE_BONUS_AURA,
ROM_CHAMPION_CHAIN_DRIVE_BONUS_DURATION_MS,
ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA,
ROM_CHAMPION_CHAIN_DRIVE_DURATION_MS,
ROM_CHAMPION_FORGE_FALLBACK_CHANCE,
ROM_CHAMPION_FORGE_SHIELD_FORM_CHANCE,
romChampionForgeProcSucceeds,
romChampionHasSourceComponentAura,
romChampionRunePulseWindowIsActive,
romChampionRunePulseUseEffect,
} from "./romChampionForgeRuntime";
function componentAura(id: number, targetId: string, now: number, durationMs = 10_000) {
return applyAura([], {
definition: { id: `rom-aura-498604-${id}-test`, name: `Source buff ${id}`, disposition: "buff", durationMs },
sourceId: targetId,
targetId,
now,
}).auras[0]!;
}
describe("RuneWaker Champion Forge rank two", () => {
it("uses only the fallback 30% roll when Shield Form is absent", () => {
const rolls: number[] = [];
const proc = romChampionForgeProcSucceeds(false, () => {
rolls.push(0.29);
return 0.29;
});
expect(ROM_CHAMPION_FORGE_FALLBACK_CHANCE).toBe(0.3);
expect(proc).toBe(true);
expect(rolls).toHaveLength(1);
});
it("tries Shield Form's 80% branch before the 30% fallback", () => {
const orderedRolls: number[] = [];
const firstBranch = romChampionForgeProcSucceeds(true, () => {
orderedRolls.push(0.79);
return 0.79;
});
expect(ROM_CHAMPION_FORGE_SHIELD_FORM_CHANCE).toBe(0.8);
expect(firstBranch).toBe(true);
expect(orderedRolls).toHaveLength(1);
const fallbackBranchRolls = [0.8, 0.29];
const fallbackBranch = romChampionForgeProcSucceeds(true, () => fallbackBranchRolls.shift()!);
expect(fallbackBranch).toBe(true);
expect(fallbackBranchRolls).toHaveLength(0);
const failedRolls = [0.8, 0.3];
expect(romChampionForgeProcSucceeds(true, () => failedRolls.shift()!)).toBe(false);
});
it("reads Shield Form and Rune Pulse windows from active owner auras", () => {
const shieldForm = componentAura(621218, "champion", 0);
const chainDrive = applyAura([], {
definition: ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA,
sourceId: "champion",
targetId: "champion",
now: 0,
}).auras[0]!;
const alternateWindow = componentAura(622185, "champion", 0);
expect(romChampionHasSourceComponentAura([shieldForm], "champion", 621218, 1)).toBe(true);
expect(romChampionHasSourceComponentAura([shieldForm], "another-actor", 621218, 1)).toBe(false);
expect(romChampionHasSourceComponentAura([shieldForm], "champion", 621218, 10_000)).toBe(false);
expect(romChampionRunePulseWindowIsActive([chainDrive], "champion", 1)).toBe(true);
expect(romChampionRunePulseWindowIsActive([alternateWindow], "champion", 1)).toBe(true);
expect(romChampionRunePulseWindowIsActive([chainDrive], "another-actor", 1)).toBe(false);
});
it("runs Rune Pulse's one-second effect at use only for source 498529", () => {
const runePulse = ROM_ALL_ABILITIES.find((ability) => (
ability.classId === "rom-champion" && ability.dbcSpellId === 498529
))!;
const shadowPulse = ROM_ALL_ABILITIES.find((ability) => (
ability.classId === "rom-champion" && ability.dbcSpellId === 498726
))!;
const chainDrive = applyAura([], {
definition: ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA,
sourceId: "champion",
targetId: "champion",
now: 0,
}).auras[0]!;
const useEffect = romChampionRunePulseUseEffect(runePulse, [chainDrive], "champion", 1);
expect(useEffect?.aura).toBe(ROM_CHAMPION_CHAIN_DRIVE_BONUS_AURA);
expect(useEffect?.aura.durationMs).toBe(ROM_CHAMPION_CHAIN_DRIVE_BONUS_DURATION_MS);
expect(romChampionRunePulseUseEffect(shadowPulse, [chainDrive], "champion", 1)).toBeNull();
expect(romChampionRunePulseUseEffect(
{ ...runePulse, classId: "rom-warrior" }, [chainDrive], "champion", 1,
)).toBeNull();
expect(romChampionRunePulseUseEffect(runePulse, [chainDrive], "another-actor", 1)).toBeNull();
});
it("applies the one-second Rune Pulse bonus once to physical and magic damage", () => {
const applied = applyAura([], {
definition: ROM_CHAMPION_CHAIN_DRIVE_BONUS_AURA,
sourceId: "champion",
targetId: "champion",
now: 1_000,
}).auras;
expect(ROM_CHAMPION_CHAIN_DRIVE_DURATION_MS).toBe(8_000);
expect(ROM_CHAMPION_CHAIN_DRIVE_BONUS_DURATION_MS).toBe(1_000);
expect(resolveDamageValue(100, applied, { direction: "dealt", school: "physical", attackKind: "melee" }))
.toBe(120);
expect(resolveDamageValue(100, applied, { direction: "dealt", school: "shadow", attackKind: "spell" }))
.toBe(120);
expect(applied[0]?.expiresAt).toBe(2_000);
});
});
describe("RuneWaker Champion companion Forge", () => {
it("rolls a real companion normal hit with rank 1 and grants its own stack and Rage", () => {
const seed = "champion-forge-companion-rank-one-auto-attack";
const targetId = "champion-forge-companion-target";
const now = 10_000;
clearMobRuntimeRegistry();
clearPartyRuntimeRegistry();
resetPartyRuntimeClock();
useCombatStore.getState().initializeCharacter({ classId: "rom-mage", level: 21 });
useCombatStore.getState().registerMob(targetId, {
name: targetId,
level: 1,
maxHealth: 1_000_000,
xpReward: 0,
});
setMobPosition(targetId, [2, 0, 0]);
useCombatStore.getState().damageMob(targetId, 1, now);
const configured = createConfiguredPartyMember({
name: "Champion/Warlock",
classId: "rom-champion",
secondaryClassId: "rom-warlock",
raceId: "rom-dwarf",
specialization: "Primary",
specializationId: "rom-champion:rom-warlock",
talentTreeId: "rom-champion-rom-warlock",
role: "damage",
}, 21, 0, seed);
const companion = {
...configured,
resource: 10,
resourcePools: { ...configured.resourcePools, rage: 10 },
nextActionAt: now + 100_000,
status: "attacking" as const,
};
usePartyStore.getState().initializeParty(seed, 21, useCombatStore.getState().health, "damage", 2, "rom");
usePartyStore.setState({ command: "attack", activeMobId: targetId, members: [companion] });
updatePartyRuntimePosition(companion.id, 0, 0, 0);
updatePartyRuntimeTargetVisibility(companion.id, targetId, true);
useCombatStore.getState().synchronizeActors();
const forgeBase = abilitiesForCharacter("rom-champion", "rom-warlock")
.find((ability) => ability.dbcSpellId === 498_523);
const forge = forgeBase
? learnedAbilityForBuild(forgeBase, companion.level, companion.talentRanks)
: null;
if (!forge || forge.dbcSpellId !== 498_523) throw new Error("Rank-1 Forge should be learned at level 21");
const activeEffect = romChampionCastEffects(forge, forge.effects, 1, companion.maxHealth)
.find((effect) => effect.kind === "apply-aura");
if (activeEffect?.kind !== "apply-aura") throw new Error("Missing rank-1 Forge active aura effect");
expect(useCombatStore.getState().applyActorAura(companion.id, companion.id, forge, activeEffect, now)).toBe(true);
useCombatStore.setState((state) => ({
mobs: { ...state.mobs, [targetId]: { ...state.mobs[targetId]!, characterShield: 1_000_000 } },
}));
advanceDungeonPartyCombat(now);
expect(useCombatStore.getState().auras.some((aura) => (
aura.targetId === companion.id && aura.definition.id === "rom-champion-forge-stack"
))).toBe(false);
expect(usePartyStore.getState().members[0]?.resourcePools.rage).toBe(10);
useCombatStore.setState((state) => ({
mobs: { ...state.mobs, [targetId]: { ...state.mobs[targetId]!, characterShield: 0 } },
}));
advanceDungeonPartyCombat(now + 2_500);
const normalHit = useCombatStore.getState().combatEvents.find((event) => (
event.kind === "damage" && event.sourceActorId === companion.id
&& event.abilityId === "party-auto-attack" && event.occurredAt === now + 2_500
));
expect(normalHit).toMatchObject({ targetActorId: targetId, effectiveAmount: expect.any(Number) });
expect(normalHit?.effectiveAmount).toBeGreaterThan(0);
expect(useCombatStore.getState().auras).toContainEqual(expect.objectContaining({
sourceId: companion.id,
targetId: companion.id,
definition: expect.objectContaining({ id: "rom-champion-forge-stack" }),
stacks: 1,
}));
expect(useCombatStore.getState().auras.some((aura) => (
aura.definition.id === "rom-champion-forge-stack" && aura.targetId !== companion.id
))).toBe(false);
expect(usePartyStore.getState().members[0]?.resourcePools.rage).toBe(26);
expect(useCombatStore.getState().actors[companion.id]?.resources.rage?.current).toBe(26);
});
});
+136
View File
@@ -0,0 +1,136 @@
import type { AbilityDefinition, AbilityEffect } from "./abilityCatalog";
import type { ActiveAura, AuraDefinition } from "./combatAuras";
export const ROM_CHAMPION_FORGE_SOURCE_SKILL_ID = 498604;
export const ROM_CHAMPION_FORGE_SOURCE_COMPONENT_ID = 621251;
export const ROM_CHAMPION_FORGE_SHIELD_FORM_COMPONENT_ID = 621218;
export const ROM_CHAMPION_CHAIN_DRIVE_WINDOW_COMPONENT_ID = 621252;
export const ROM_CHAMPION_CHAIN_DRIVE_BONUS_COMPONENT_ID = 621253;
export const ROM_CHAMPION_CHAIN_DRIVE_EXTERNAL_WINDOW_COMPONENT_ID = 622185;
export const ROM_CHAMPION_FORGE_SOURCE_DURATION_MS = 300_000;
export const ROM_CHAMPION_CHAIN_DRIVE_DURATION_MS = 8_000;
export const ROM_CHAMPION_CHAIN_DRIVE_BONUS_DURATION_MS = 1_000;
export const ROM_CHAMPION_FORGE_SHIELD_FORM_CHANCE = 0.8;
export const ROM_CHAMPION_FORGE_FALLBACK_CHANCE = 0.3;
export const ROM_CHAMPION_FORGE_RANK_TWO_AURA_ID =
`rom-aura-${ROM_CHAMPION_FORGE_SOURCE_SKILL_ID}-${ROM_CHAMPION_FORGE_SOURCE_COMPONENT_ID}-active`;
export const ROM_CHAMPION_FORGE_RANK_TWO_PROC_ACTION_ID = "rom-champion-forge-rank-two-hit";
export const ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA_ID =
`rom-aura-${ROM_CHAMPION_FORGE_SOURCE_SKILL_ID}-${ROM_CHAMPION_CHAIN_DRIVE_WINDOW_COMPONENT_ID}-window`;
export const ROM_CHAMPION_CHAIN_DRIVE_BONUS_AURA_ID =
`rom-aura-${ROM_CHAMPION_FORGE_SOURCE_SKILL_ID}-${ROM_CHAMPION_CHAIN_DRIVE_BONUS_COMPONENT_ID}-bonus`;
export const ROM_CHAMPION_RUNE_PULSE_WINDOW_TAG = "rom-champion-rune-pulse-chain-drive";
export const ROM_CHAMPION_FORGE_RANK_TWO_AURA: AuraDefinition = {
id: ROM_CHAMPION_FORGE_RANK_TWO_AURA_ID,
name: "Forge",
description: "For 5 minutes, normal attack hits build Forge stacks and restore Rage.",
disposition: "buff",
durationMs: ROM_CHAMPION_FORGE_SOURCE_DURATION_MS,
exclusiveGroup: "rom-champion-forge-active",
utilityTags: ["rom-champion-forge-active", "rom-champion-forge-rank-two-active"],
procs: [{
id: "rom-champion-forge-rank-two-normal-hit",
triggers: ["hit", "crit"],
attackKinds: ["melee"],
chance: 1,
action: { kind: "custom", id: ROM_CHAMPION_FORGE_RANK_TWO_PROC_ACTION_ID },
}],
};
export const ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA: AuraDefinition = {
id: ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA_ID,
name: "Chain Drive",
description: "Chain Drive enables Rune Pulse for 8 seconds.",
disposition: "buff",
durationMs: ROM_CHAMPION_CHAIN_DRIVE_DURATION_MS,
maxStacks: 1,
stackBehavior: "refresh",
utilityTags: ["rom-champion-chain-drive-window"],
};
export const ROM_CHAMPION_CHAIN_DRIVE_BONUS_AURA: AuraDefinition = {
id: ROM_CHAMPION_CHAIN_DRIVE_BONUS_AURA_ID,
name: "Rune Pulse",
description: "Rune Pulse increases outgoing damage by 20% for 1 second.",
disposition: "buff",
durationMs: ROM_CHAMPION_CHAIN_DRIVE_BONUS_DURATION_MS,
maxStacks: 1,
stackBehavior: "refresh",
utilityTags: [ROM_CHAMPION_RUNE_PULSE_WINDOW_TAG],
modifiers: [{
kind: "damage",
direction: "dealt",
operation: "percent",
value: 0.2,
}],
};
function hasNumericIdToken(id: string, token: number): boolean {
return id.includes(`-${token}-`)
|| id.endsWith(`-${token}`);
}
export function romChampionHasSourceComponentAura(
auras: readonly ActiveAura[],
ownerId: string,
componentId: number,
now: number,
): boolean {
return auras.some((aura) => aura.targetId === ownerId
&& (aura.expiresAt === null || aura.expiresAt > now)
&& hasNumericIdToken(aura.definition.id, componentId));
}
export function romChampionHasForgeRankTwoAura(
auras: readonly ActiveAura[],
ownerId: string,
now: number,
): boolean {
return auras.some((aura) => aura.targetId === ownerId
&& (aura.expiresAt === null || aura.expiresAt > now)
&& aura.definition.id === ROM_CHAMPION_FORGE_RANK_TWO_AURA_ID);
}
export function romChampionRunePulseWindowIsActive(
auras: readonly ActiveAura[],
ownerId: string,
now: number,
): boolean {
return romChampionHasSourceComponentAura(
auras, ownerId, ROM_CHAMPION_CHAIN_DRIVE_WINDOW_COMPONENT_ID, now,
) || romChampionHasSourceComponentAura(
auras, ownerId, ROM_CHAMPION_CHAIN_DRIVE_EXTERNAL_WINDOW_COMPONENT_ID, now,
);
}
/** Rune Pulse's source CheckUseScript applies this before cast scheduling. */
export function romChampionRunePulseUseEffect(
ability: AbilityDefinition,
auras: readonly ActiveAura[],
ownerId: string,
now: number,
): Extract<AbilityEffect, { kind: "apply-aura" }> | null {
if (ability.source !== "runewaker" || ability.classId !== "rom-champion"
|| ability.dbcSpellId !== 498529
|| !romChampionRunePulseWindowIsActive(auras, ownerId, now)) return null;
return {
kind: "apply-aura",
aura: ROM_CHAMPION_CHAIN_DRIVE_BONUS_AURA,
recipient: "caster",
sourceEffectType: -1,
sourceAuraType: -1,
miscValue: 0,
triggerSpellId: 498529,
};
}
/** Run the source's conditional 80% roll before its fallback 30% roll. */
export function romChampionForgeProcSucceeds(
hasShieldFormAura: boolean,
roll: () => number,
): boolean {
if (hasShieldFormAura && roll() < ROM_CHAMPION_FORGE_SHIELD_FORM_CHANCE) return true;
return roll() < ROM_CHAMPION_FORGE_FALLBACK_CHANCE;
}
+23 -2
View File
@@ -1,6 +1,7 @@
import type { AbilityDefinition, AbilityEffect } from "./abilityCatalog";
import type { AuraDefinition } from "./combatAuras";
import type { RomGeneratedAbilityLike } from "./romAbilitySemantics";
import { ROM_CHAMPION_FORGE_RANK_TWO_AURA } from "./romChampionForgeRuntime";
export const ROM_CHAMPION_FORGE_STACK_AURA: AuraDefinition = {
id: "rom-champion-forge-stack",
@@ -50,6 +51,7 @@ const ROM_CHAMPION_FORGE_ACTIVE_AURA: AuraDefinition = {
description: "For 5 minutes, normal attack hits build Forge stacks and restore Rage.",
disposition: "buff",
durationMs: 300_000,
exclusiveGroup: "rom-champion-forge-active",
utilityTags: ["rom-champion-forge-active"],
procs: [{
id: "rom-champion-forge-normal-hit",
@@ -275,6 +277,16 @@ export function romChampionCastEffects(
miscValue: 0,
triggerSpellId: 498524,
}];
case 498604: // Rank 2 Forge source component 621251 enables Chain Drive's attack proc.
return [{
kind: "apply-aura",
aura: ROM_CHAMPION_FORGE_RANK_TWO_AURA,
recipient: "caster",
sourceEffectType: 0,
sourceAuraType: 0,
miscValue: 0,
triggerSpellId: 498604,
}];
case 498572: // Rune Overload ends when its Rage drain reaches zero.
return effects.map((effect) => effect.kind === "apply-aura"
? {
@@ -296,9 +308,18 @@ export function romChampionCastEffects(
});
case 498535: // Chain Drive's proc chance and damage bonus are absent from the source payload.
return effects.filter((effect) => effect.kind !== "cooldown-reset");
case 498599: // Dark Energy Strike's cooldown proc chance is absent from the source payload.
case 498599: { // Source orders physical 621305, Darkness 621306, then a 15% reset group.
if (ability.secondaryClassId !== "rom-warlock") return effects;
return effects.filter((effect) => effect.kind !== "cooldown-reset");
const damageIndexes: number[] = [];
effects.forEach((effect, index) => {
if (effect.kind === "damage") damageIndexes.push(index);
});
if (damageIndexes.length !== 2) return effects.filter((effect) => effect.kind !== "cooldown-reset");
return effects.flatMap((effect, index): AbilityEffect[] => {
if (effect.kind !== "damage") return effect.kind === "cooldown-reset" ? [] : [effect];
return [{ ...effect, school: damageIndexes[0] === index ? "physical" : "shadow" }];
});
}
case 498651: // Heart Collection Rune explicitly resets Rune Siphon.
if (ability.secondaryClassId !== "rom-warlock") return effects;
return effects.map((effect) => effect.kind === "cooldown-reset"
+261 -1
View File
@@ -1,7 +1,8 @@
import { beforeEach, describe, expect, it } from "vitest";
import { applyAura, expireAuras, resolveDamageValue } from "./combatAuras";
import { ROM_ALL_ABILITIES } from "./romAbilityCatalog";
import { clearMobRuntimeRegistry, getMobPosition, setMobPosition } from "./mobRuntimeRegistry";
import { PLAYER_AURA_ENTITY_ID, useCombatStore } from "./combatStore";
import { PLAYER_AURA_ENTITY_ID, stableCombatUnit, useCombatStore } from "./combatStore";
import { romEffectsForCast, type RomCastMechanics } from "./romCombatMechanics";
import {
ROM_CHAMPION_SOUL_FORGE_PROC_ACTION_ID,
@@ -10,6 +11,10 @@ import {
ROM_CHAMPION_WAY_OF_FRENZY_PROFILE,
romChampionCastEffects,
} from "./romChampionOverrides";
import {
ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA_ID,
ROM_CHAMPION_FORGE_RANK_TWO_AURA_ID,
} from "./romChampionForgeRuntime";
const empty: RomCastMechanics = {
sealStacks: 0,
@@ -139,6 +144,191 @@ describe("RoM Champion source-specific behavior", () => {
expect(useCombatStore.getState().resourcePools.rage).toBeGreaterThanOrEqual(10);
});
it("keeps rank 1 at level 21 and unlocks the rank 2 Forge source aura at level 22", () => {
useCombatStore.getState().initializeCharacter({
classId: "rom-champion", secondaryClassId: "rom-rogue", raceId: "rom-dwarf", level: 21,
});
const forge = sourceAbility(498523);
expect(useCombatStore.getState().castAbility(forge.id, undefined, 1_000)).toMatchObject({ ok: true });
expect(useCombatStore.getState().auras.some((aura) => aura.definition.id === "rom-champion-forge-active"))
.toBe(true);
expect(useCombatStore.getState().auras.some((aura) => aura.definition.id === ROM_CHAMPION_FORGE_RANK_TWO_AURA_ID))
.toBe(false);
useCombatStore.setState({ level: 22 });
expect(useCombatStore.getState().castAbility(forge.id, undefined, 4_000)).toMatchObject({ ok: true });
const rankTwo = useCombatStore.getState().auras.find((aura) => (
aura.definition.id === ROM_CHAMPION_FORGE_RANK_TWO_AURA_ID
));
expect(rankTwo?.expiresAt).toBe(304_000);
expect(useCombatStore.getState().auras.some((aura) => aura.definition.id === "rom-champion-forge-active"))
.toBe(false);
});
it("grants Chain Drive on an eligible rank 2 auto attack and resets only learned owner cooldowns", () => {
useCombatStore.getState().initializeCharacter({
classId: "rom-champion", secondaryClassId: "rom-rogue", raceId: "rom-dwarf", level: 22,
});
useCombatStore.getState().registerMob("champion-chain-drive-target", {
name: "Chain Drive Target", maxHealth: 100_000,
});
const forge = sourceAbility(498523);
const runePulse = sourceAbility(498529);
const shadowPulse = sourceAbility(498726);
expect(useCombatStore.getState().castAbility(forge.id, undefined, 1_000)).toMatchObject({ ok: true });
useCombatStore.setState((state) => ({
resource: 0,
resourcePools: { ...state.resourcePools, rage: 0 },
cooldowns: { ...state.cooldowns, [runePulse.id]: 90_000, [shadowPulse.id]: 90_000 },
}));
const hitSeed = Array.from({ length: 100 }, (_, index) => `champion-chain-drive-${index}`)
.find((seed) => stableCombatUnit(`${seed}:498590:0`) < 0.3);
expect(hitSeed).toBeDefined();
const hit = useCombatStore.getState().damageMob(
"champion-chain-drive-target",
100,
2_000,
undefined,
"physical",
{
attackKind: "melee",
seed: hitSeed!,
abilityId: "party-auto-attack",
rules: { isAutoAttack: true, canMiss: false, canDodge: false, canParry: false, canBlock: false, canCrit: false },
},
);
expect(hit.amount).toBeGreaterThan(0);
expect(useCombatStore.getState().auras.some((aura) => (
aura.definition.id === ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA_ID
&& aura.targetId === PLAYER_AURA_ENTITY_ID
&& aura.expiresAt === 10_000
))).toBe(true);
expect(useCombatStore.getState().cooldowns[runePulse.id]).toBe(0);
expect(useCombatStore.getState().cooldowns[shadowPulse.id]).toBe(0);
expect(useCombatStore.getState().resourcePools.rage).toBeGreaterThanOrEqual(10);
expect(useCombatStore.getState().auras.find((aura) => aura.definition.id === "rom-champion-forge-stack")?.stacks)
.toBe(1);
});
it("keeps the rank 2 stack and Rage when Chain Drive's fallback roll fails", () => {
useCombatStore.getState().initializeCharacter({
classId: "rom-champion", secondaryClassId: "rom-rogue", raceId: "rom-dwarf", level: 22,
});
useCombatStore.getState().registerMob("champion-chain-drive-failed-target", {
name: "Chain Drive Failed Target", maxHealth: 100_000,
});
const forge = sourceAbility(498523);
expect(useCombatStore.getState().castAbility(forge.id, undefined, 1_000)).toMatchObject({ ok: true });
useCombatStore.setState((state) => ({ resourcePools: { ...state.resourcePools, rage: 0 }, resource: 0 }));
const failedSeed = Array.from({ length: 100 }, (_, index) => `chain-drive-failed-${index}`)
.find((seed) => stableCombatUnit(`${seed}:498590:0`) >= 0.8
&& stableCombatUnit(`${seed}:498590:1`) >= 0.3)!;
const hit = useCombatStore.getState().damageMob(
"champion-chain-drive-failed-target", 100, 2_000, undefined, "physical", {
attackKind: "melee",
seed: failedSeed,
abilityId: "party-auto-attack",
rules: { isAutoAttack: true, canMiss: false, canDodge: false, canParry: false, canBlock: false, canCrit: false },
},
);
expect(hit.amount).toBeGreaterThan(0);
expect(useCombatStore.getState().auras.find((aura) => aura.definition.id === "rom-champion-forge-stack")?.stacks)
.toBe(1);
expect(useCombatStore.getState().auras.some((aura) => (
aura.definition.id === ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA_ID
))).toBe(false);
expect(useCombatStore.getState().resourcePools.rage).toBeGreaterThanOrEqual(10);
});
it("does not proc rank 2 Forge from zero or fully absorbed physical packets", () => {
useCombatStore.getState().initializeCharacter({
classId: "rom-champion", secondaryClassId: "rom-rogue", raceId: "rom-dwarf", level: 22,
});
useCombatStore.getState().registerMob("champion-forge-zero-target", {
name: "Zero Packet Target", maxHealth: 100_000,
});
useCombatStore.getState().registerMob("champion-forge-absorbed-target", {
name: "Absorbed Packet Target", maxHealth: 100_000,
});
const forge = sourceAbility(498523);
expect(useCombatStore.getState().castAbility(forge.id, undefined, 1_000)).toMatchObject({ ok: true });
const zeroHit = useCombatStore.getState().damageMob(
"champion-forge-zero-target", 0, 2_000, undefined, "physical", {
attackKind: "melee",
seed: "champion-forge-zero-hit",
abilityId: "party-auto-attack",
rules: { isAutoAttack: true, canMiss: false, canDodge: false, canParry: false, canBlock: false, canCrit: false },
},
);
expect(zeroHit.amount).toBe(0);
const shieldedAuras = applyAura(useCombatStore.getState().auras, {
definition: {
id: "test:champion-forge-physical-absorb",
name: "Physical absorb fixture",
disposition: "buff",
durationMs: null,
absorbs: [{ id: "test:champion-forge-physical-absorb-pool", amount: 1_000_000, school: "physical" }],
},
sourceId: "champion-forge-absorbed-target",
targetId: "champion-forge-absorbed-target",
now: 3_000,
}).auras;
useCombatStore.setState({ auras: shieldedAuras });
const absorbedHit = useCombatStore.getState().damageMob(
"champion-forge-absorbed-target", 100, 3_000, undefined, "physical", {
attackKind: "melee",
seed: "champion-forge-absorbed-hit",
abilityId: "party-auto-attack",
rules: { isAutoAttack: true, canMiss: false, canDodge: false, canParry: false, canBlock: false, canCrit: false },
},
);
expect(absorbedHit.amount).toBe(0);
const absorbedEvent = useCombatStore.getState().combatEvents.filter((event) => (
event.kind === "damage" && event.targetActorId === "champion-forge-absorbed-target"
)).at(-1);
expect(absorbedEvent?.absorbed).toBeGreaterThan(0);
expect(useCombatStore.getState().auras.some((aura) => aura.definition.id === "rom-champion-forge-stack"))
.toBe(false);
expect(useCombatStore.getState().auras.some((aura) => aura.definition.id === ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA_ID))
.toBe(false);
expect(useCombatStore.getState().resourcePools.rage).toBe(0);
});
it("does not proc rank 2 Forge from a positive melee spell packet", () => {
useCombatStore.getState().initializeCharacter({ classId: "rom-champion", raceId: "rom-dwarf", level: 22 });
useCombatStore.getState().registerMob("champion-forge-melee-spell-target", {
name: "Melee Spell Target", maxHealth: 100_000,
});
expect(useCombatStore.getState().castAbility(sourceAbility(498523).id, undefined, 1_000))
.toMatchObject({ ok: true });
useCombatStore.setState((state) => ({ resource: 0, resourcePools: { ...state.resourcePools, rage: 0 } }));
useCombatStore.getState().damageMob(
"champion-forge-melee-spell-target",
100,
2_000,
undefined,
"physical",
{
attackKind: "melee",
seed: "champion-direct-melee-spell",
abilityId: sourceAbility(498529).id,
rules: { canMiss: false, canDodge: false, canParry: false, canBlock: false, canCrit: false },
},
);
expect(useCombatStore.getState().auras.some((aura) => aura.definition.id === "rom-champion-forge-stack"))
.toBe(false);
expect(useCombatStore.getState().auras.some((aura) => aura.definition.id === ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA_ID))
.toBe(false);
expect(useCombatStore.getState().resourcePools.rage).toBe(0);
});
it("restores Rune Pulse's source-defined Rage only when its damage lands", () => {
const runePulse = sourceAbility(498529);
expect(runePulse.description).toContain("When it hits, it will restore");
@@ -149,6 +339,76 @@ describe("RoM Champion source-specific behavior", () => {
if (hit?.kind === "damage") expect(hit.onDamageResource).toEqual({ resource: "rage", amount: 5 });
expect(effects.some((effect) => effect.kind === "apply-aura" && effect.aura.id.includes("-622327-")))
.toBe(false);
expect(effects.some((effect) => effect.kind === "apply-aura" && effect.aura.id === "rom-aura-498604-621253-bonus"))
.toBe(false);
expect(castEffects(498726)
.some((effect) => effect.kind === "apply-aura" && effect.aura.id === "rom-aura-498604-621253-bonus"))
.toBe(false);
});
it("grants Rune Pulse's one-second bonus at cast start and expires it before the two-second impact", () => {
useCombatStore.getState().initializeCharacter({
classId: "rom-champion", secondaryClassId: "rom-rogue", raceId: "rom-dwarf", level: 22,
});
useCombatStore.getState().registerMob("champion-rune-pulse-target", {
name: "Rune Pulse Target", maxHealth: 100_000,
});
setMobPosition("champion-rune-pulse-target", [3, 0, 0]);
useCombatStore.getState().selectMob("champion-rune-pulse-target");
const forge = sourceAbility(498523);
expect(useCombatStore.getState().castAbility(forge.id, undefined, 1_000)).toMatchObject({ ok: true });
useCombatStore.setState((state) => ({ cooldowns: { ...state.cooldowns, [forge.id]: 0 } }));
const hitSeed = Array.from({ length: 100 }, (_, index) => `rune-pulse-window-${index}`)
.find((seed) => stableCombatUnit(`${seed}:498590:0`) < 0.3)!;
useCombatStore.getState().damageMob(
"champion-rune-pulse-target", 100, 3_000, undefined, "physical", {
attackKind: "melee",
seed: hitSeed,
abilityId: "party-auto-attack",
rules: { isAutoAttack: true, canMiss: false, canDodge: false, canParry: false, canBlock: false, canCrit: false },
},
);
expect(useCombatStore.getState().auras.some((aura) => (
aura.definition.id === ROM_CHAMPION_CHAIN_DRIVE_WINDOW_AURA_ID
&& aura.expiresAt === 11_000
))).toBe(true);
const runePulse = sourceAbility(498529);
expect(runePulse.castTimeMs).toBe(2_000);
expect(useCombatStore.getState().castAbility(runePulse.id, undefined, 3_100)).toMatchObject({ ok: true });
const startedAura = useCombatStore.getState().auras.find((aura) => (
aura.definition.id === "rom-aura-498604-621253-bonus"
));
const runePulseBonuses = useCombatStore.getState().auras.filter((aura) => (
aura.definition.id === "rom-aura-498604-621253-bonus"
));
expect(startedAura?.appliedAt).toBe(3_100);
expect(startedAura?.expiresAt).toBe(4_100);
expect(runePulseBonuses).toHaveLength(1);
const activeAurasDuringBonus = expireAuras(useCombatStore.getState().auras, 3_500).active;
const activeAurasWithoutBonus = activeAurasDuringBonus.filter((aura) => (
aura.definition.id !== "rom-aura-498604-621253-bonus"
));
const outgoingDamageWithBonus = resolveDamageValue(100, activeAurasDuringBonus, {
direction: "dealt", school: "physical", attackKind: "melee",
});
const outgoingDamageWithoutBonus = resolveDamageValue(100, activeAurasWithoutBonus, {
direction: "dealt", school: "physical", attackKind: "melee",
});
expect(outgoingDamageWithBonus - outgoingDamageWithoutBonus).toBeCloseTo(20, 10);
useCombatStore.getState().tick(2, 5_100);
const aurasAtImpact = expireAuras(useCombatStore.getState().auras, 5_100).active;
const runePulseBonusesAtImpact = aurasAtImpact.filter((aura) => (
aura.definition.id === "rom-aura-498604-621253-bonus"
));
const outgoingDamageAtImpact = resolveDamageValue(100, aurasAtImpact, {
direction: "dealt", school: "physical", attackKind: "melee",
});
expect(outgoingDamageAtImpact).toBe(resolveDamageValue(100, aurasAtImpact.filter((aura) => (
aura.definition.id !== "rom-aura-498604-621253-bonus"
)), { direction: "dealt", school: "physical", attackKind: "melee" }));
expect(runePulseBonusesAtImpact).toHaveLength(0);
});
it("routes Rune Siphon's positive source component to the caster as healing", () => {
+14 -2
View File
@@ -168,9 +168,9 @@ describe("RoM primary class conditional combat effects", () => {
});
it("removes only the four retired Holy Seal DoTs and applies CoA Probing Attack's conditional weapon-DPS value", () => {
for (const spellId of [490148, 490149, 490150, 490151]) {
for (const spellId of [490148, 490149, 490150, 490151, 499909]) {
const ability = ROM_ALL_ABILITIES.find((candidate) => candidate.dbcSpellId === spellId)!;
const resolved = romEffectsForCast(ability, spellId === 490151 ? { ...empty, sealStacks: 4 } : empty);
const resolved = romEffectsForCast(ability, spellId === 490151 || spellId === 499909 ? { ...empty, sealStacks: 4 } : empty);
expect(resolved.some((effect) => effect.kind === "dot")).toBe(false);
expect(resolved.some((effect) => effect.kind === "damage")).toBe(true);
if (spellId === 490148 || spellId === 490150) {
@@ -178,6 +178,18 @@ describe("RoM primary class conditional combat effects", () => {
}
}
const punishment = ROM_ALL_ABILITIES.find((candidate) => candidate.dbcSpellId === 499909)!;
const atTwoSeals = romEffectsForCast(punishment, { ...empty, sealStacks: 2 })
.find((effect) => effect.kind === "damage");
const atFourSeals = romEffectsForCast(punishment, { ...empty, sealStacks: 4 })
.find((effect) => effect.kind === "damage");
expect(atTwoSeals?.kind).toBe("damage");
expect(atFourSeals?.kind).toBe("damage");
if (atTwoSeals?.kind === "damage" && atFourSeals?.kind === "damage") {
expect(atTwoSeals.coefficient).toBeCloseTo(atFourSeals.coefficient / 2);
}
expect(romEffectsForCast(punishment, { ...empty, sealStacks: 0 })).toEqual([]);
const probing = ROM_ALL_ABILITIES.find((candidate) => candidate.dbcSpellId === 493283)!;
const base = romEffectsForCast(probing, empty).find((effect) => effect.kind === "damage");
const bleedEmpowered = romEffectsForCast(probing, { ...empty, bleedCount: 1 })
+2 -1
View File
@@ -329,7 +329,8 @@ export function romEffectsForCast(ability: AbilityDefinition, context: RomCastMe
return context.bleedCount > 0 ? warriorAdjustedEffects : warriorAdjustedEffects.filter((effect) => effect.kind !== "dot");
case 491170: // Electric Explosion has mutually exclusive normal/Charged hits.
return context.charged ? damage.slice(0, 1) : damage.slice(-1);
case 490151: // Punishment spends Holy Seals and scales its one payoff.
case 490151: // General Punishment and the Knight/Rogue linked child spend Holy Seals and scale one payoff.
case 499909:
return seals > 0 ? warriorAdjustedEffects.map((effect) => scaleOutput(effect, seals / 4)) : [];
case 490153: { // Threaten: target debuffs and extra hit require Holy Seals.
const base = damage[0];
+6 -3
View File
@@ -1,5 +1,7 @@
import catalog from "./generated/romHeirloomReference.json";
export type { RomNativeGearStats } from "./romNativeStatsTypes";
export const ROM_HEIRLOOM_REFERENCE_CLASSES = [
"rom-knight", "rom-priest", "rom-scout", "rom-rogue", "rom-mage",
] as const;
@@ -11,7 +13,8 @@ export const ROM_HEIRLOOM_REFERENCE_SLOTS = [
] as const;
export type RomHeirloomReferenceSlot = (typeof ROM_HEIRLOOM_REFERENCE_SLOTS)[number];
export interface RomNativeGearStats {
/** Original exporter field names. `magicalDamage` here is source type 148. */
export interface RomHeirloomReferenceGearStats {
readonly strength?: number;
readonly stamina?: number;
readonly intellect?: number;
@@ -39,7 +42,7 @@ export interface RomNativeGearStats {
export interface RomHeirloomReference {
readonly level: number;
readonly stats: RomNativeGearStats;
readonly stats: RomHeirloomReferenceGearStats;
readonly referenceItemIds: readonly number[];
readonly packageId?: number;
readonly speedTenths?: number;
@@ -54,7 +57,7 @@ interface RomSourceReferenceItem {
readonly type: number;
readonly position: number;
readonly suitId: number;
readonly stats: RomNativeGearStats;
readonly stats: RomHeirloomReferenceGearStats;
}
const profiles = catalog.profiles as unknown as Readonly<Record<RomHeirloomReferenceClass, Readonly<Partial<Record<RomHeirloomReferenceSlot, readonly RomHeirloomReference[]>>>>>;
@@ -0,0 +1,75 @@
import { beforeEach, describe, expect, it } from "vitest";
import { useCombatStore } from "./combatStore";
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
import { advanceDungeonPartyCombat, resetPartyRuntimeClock } from "./partyRuntime";
import { clearPartyRuntimeRegistry, registerPartyRuntimePosition, updatePartyRuntimeTargetVisibility } from "./partyRuntimeRegistry";
import { createConfiguredPartyMember, usePartyStore } from "./partyStore";
import { abilityById } from "./abilityCatalog";
import { EMPTY_ITEM_STATS } from "./itemStats";
describe("Knight/Rogue God's Vengeance linked Punishment", () => {
beforeEach(() => {
clearMobRuntimeRegistry();
clearPartyRuntimeRegistry();
resetPartyRuntimeClock();
useCombatStore.getState().initializeCharacter({
classId: "rom-knight", secondaryClassId: "rom-rogue", raceId: "rom-human", level: 80,
});
usePartyStore.getState().initializeParty(
"knight-rogue-gods-vengeance", 80, useCombatStore.getState().health, "damage", 2, "rom",
);
});
it("resets only the owning companion's Shadow Step cooldown after its landed exact-four Seal child cast", () => {
const punishment = abilityById("rom-knight-rom-rogue-elite-50-499909")!;
const shadowStep = abilityById("rom-rogue-general-7")!;
const member = createConfiguredPartyMember({
name: "Knight/Rogue",
classId: "rom-knight",
secondaryClassId: "rom-rogue",
raceId: "rom-human",
specialization: "Knight/Rogue",
specializationId: "rom-knight:rom-rogue",
talentTreeId: "rom-knight-rom-rogue",
role: "damage",
}, 80, 0, "knight-rogue-gods-vengeance");
const targetId = "knight-rogue-gods-vengeance-target";
useCombatStore.getState().registerMob(targetId, { name: targetId, level: 1, maxHealth: 1_000_000, xpReward: 0 });
setMobPosition(targetId, [2, 0, 0]);
useCombatStore.getState().damageMob(targetId, 1, 100);
usePartyStore.setState({ members: [{
...member,
gearStats: { ...member.gearStats, ...EMPTY_ITEM_STATS, hitRating: 1_000_000 },
comboPoints: 4,
comboTargetId: targetId,
cooldowns: { ...member.cooldowns, [shadowStep.id]: 30_000 },
activeCast: {
abilityId: punishment.id,
school: "holy",
mode: "cast",
startedAt: 1_000,
completesAt: 1_000,
originalDurationMs: 0,
pushbackHits: 0,
origin: [0, 0, 0],
targetId,
},
activeCastTargetId: targetId,
status: "attacking",
nextActionAt: 1_000,
}] });
registerPartyRuntimePosition(member.id, [0, 0, 0]);
updatePartyRuntimeTargetVisibility(member.id, targetId, true);
useCombatStore.getState().synchronizeActors();
advanceDungeonPartyCombat(1_000);
const updated = usePartyStore.getState().members.find((candidate) => candidate.id === member.id)!;
expect(updated.comboPoints).toBe(0);
expect(updated.cooldowns[shadowStep.id]).toBe(0);
expect(useCombatStore.getState().actors[member.id]?.cooldowns[shadowStep.id]).toBe(0);
const hit = useCombatStore.getState().combatEvents.find((event) => event.kind === "damage"
&& event.abilityId === punishment.id && event.targetActorId === targetId);
expect(hit?.effectiveAmount).toBeGreaterThan(0);
});
});
Loaded 100 of 221 files, more files were not shown because too many files have changed in this diff. Show more