Skip to content

Repository files navigation

wowdps

A World of Warcraft combat-log damage meter for Linux. A headless daemon tails the combat log; a Wayland layer-shell overlay, a windowed GUI and a TUI are thin clients over a unix socket.

The meter reads WoWCombatLog-*.txt from disk, outside the game process. No addon, no injection, no screen reading.

The overlay during a raid kill: the visit's pull strip up top, class-colored bars with spec icons, totals, dps and share for twenty players

Player drilldown: per-spell rows with school-tinted bars over a rolling dps curve marked with trinket uses and procs Ability drilldown: breadcrumb with school tag, stat cards, who it hit, and the ability's own curve over the player's ghost

Healing drilldown with an hps curve A timed +10 keystone's Σ overall: the Σ–①②③④–⚑ strip, TIMED, and the whole run's damage merged

Two-player comparison on a wipe: per-spell tables over timeline graphs sharing one scale

What it does

  • Live meter. Damage, healing, interrupts, crowd control, dispels and deaths, per player, with class colors, crests and spec icons. Updates at 10 Hz.
  • Overlay. A wlr-layer-shell surface for Hyprland, sway and other wlroots compositors. It starts with the game, follows the game's workspace, and shrinks to a 1x1 click-through pixel when hidden.
  • Segments. Pulls split into encounters and trash the same way the game does. Mythic+ runs group into instance visits with a Σ overall view and keystone par timers. Arena matches are titled as wins or losses.
  • Drill-down and comparison. Per-spell breakdowns (hits, crit%, average), death recaps, and a two-player side-by-side with rolling or cumulative DPS graphs marked with trinket uses, procs and consumables. Both panes share one scale, so the comparison stays honest.
  • Big logs. A structural index lists the segments of a 300 MB+ log in under a second. A segment is parsed only when opened. Index checkpoints persist across restarts, so only the tail is rescanned.
  • History. Every past pull in the log is browsable in the same UI.

Install

The daemon/TUI binary is pure Rust with no system library dependencies:

cargo build --release            # everything
cargo run --bin wowdps           # daemon + TUI, finds the game install itself

On Nix, the flake packages the daemon/TUI and exports a Home Manager module and a NixOS module. Each runs the daemon as a user service:

nix build .#wowdps        # two derivations: .#wowdps-deps (the dependency
                          # tree, keyed on Cargo.lock) + the workspace crates
# home-manager:
#   imports = [ wowdps.homeManagerModules.default ];
#   services.wowdps.enable = true;
# or NixOS:
#   imports = [ wowdps.nixosModules.default ];
#   services.wowdps.enable = true;

The GUI and overlay need pkg-config and libxkbcommon to build, and wayland, vulkan-loader and libGL at runtime. On NixOS use the dev shell (nix develop or devenv).

Use

wowdps                       # follow the configured or discovered logs dir
wowdps --file some-log.txt   # follow a specific log
wowdps status                # daemon state
wowdps stop                  # stop the daemon
wowdps-gui                   # windowed client
wowdps-gui --overlay         # layer-shell overlay (the daemon starts this
                             # itself when the game launches)
wowdps mcp                   # MCP server over stdio: fight data as tools for
                             # an LLM.  claude mcp add wowdps -- wowdps mcp
wowdps <cmd> [args...]       # runs wowdps-<cmd> (next to the binary, else
                             # on $PATH), e.g. `wowdps extract ...`

The daemon starts on demand, is shared by every client, and exits about 10 s after the last client disconnects. Configuration is ~/.config/wowdps/config.toml: logs_dir, auto_overlay, overlay placement, Hyprland workspace following, and the history store's history_* keys (fights persist across sessions as JSON under ~/.local/share/wowdps/history/; wowdps history sql "…" runs DuckDB over them, and the MCP server exposes the same store as history, progression, trend, stored_fight, pin_fight and history_sql). Log discovery checks $WOWDPS_WOW_DIR, then scans Steam/Proton prefixes for the newest install.

Game data caches

Class crests, spec icons and spell icons come from your own game install, extracted into ~/.local/share/wowdps/ by tools/gen-icons.sh and tools/gen-spell-icons.sh (in the dev shell: wowdps gen-icons, wowdps gen-spell-icons). Without them the meter draws class-colored discs and no ability icons. Extracted artwork never enters this repository.

The MCP server's talent tools (talent_tree, decode_talents, encode_talents) read ~/.local/share/wowdps/talents.json, generated by tools/gen-talent-trees.sh once per game patch.

Talent viewer

Press t in the meter window. Paste an in-game talent import string or a SimulationCraft addon export and the build is drawn the way the game draws it: class and spec panes, the chosen hero tree between them, gold paths and rank pills. A SimC export also brings its saved loadouts, gear, bags and currencies. Pastes are remembered per character, so opening the viewer on a player's meter row restores their build. Opening it on a player with COMBATANT_INFO in the log shows their actual logged talents and gear instead. The pane artwork comes from tools/gen-talent-art.sh; without it the trees draw on plain panels.

Development

CONTRACT.md is the binding interface spec: parser, meter and index signatures, the semantic rulings (what counts as damage, absorb attribution, segment boundaries, pet attribution, class inference) and the wire protocol. Fixture golden values are computed from the rulings and checked independently of the parser:

cargo test                       # workspace: parity, IPC, fixture gates
crates/core/fixtures/verify.sh   # gawk recomputes the golden totals
cargo clippy && cargo fmt        # clippy denies panics in production code

Dependency policy: model has no dependencies; core, proto and daemon are stdlib only. The TUI uses ratatui and crossterm; the GUI uses iced and iced_layershell. No tokio, no chrono, no serde outside the GUI.

docs/roadmap.md lists what comes next.

AI use

This project was built with Claude Code. Contributions made with an LLM are welcome under the same rules as any other:

  • The project's standards apply: idiomatic Rust, the no-panic lint, CONTRACT.md, the dependency policy, and test coverage.
  • No copyrighted material. Nothing copied from other codebases, and no running someone else's code through a model to strip its license. You must have the right to contribute what you submit, and it lands under this project's MIT/Apache-2.0 terms.
  • You are responsible for what you submit: review it, test it, and be able to explain it.

Legal

This project is not affiliated with, endorsed by, or sponsored by Blizzard Entertainment. World of Warcraft® and Blizzard Entertainment® are trademarks or registered trademarks of Blizzard Entertainment, Inc.

The repository contains no Blizzard-owned assets. The generated tables (class_spells.rs, item_spells.rs, keystone_timers.rs) hold only factual identifiers (spell ids, class and spec mappings, dungeon timers) extracted from the user's own game installation. Artwork is likewise extracted locally into per-machine caches and never committed or distributed. The screenshots above show the application rendering the author's own combat logs; the small game icons visible in them remain Blizzard's property and appear only to depict the software in use.

License

Licensed under either of

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

WoW combat-log damage meter for Linux: headless daemon, Wayland layer-shell overlay, GUI and TUI clients

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages