MosswartMassacre/README.md
Erik 2213abf475 docs: rewrite README to reflect current plugin features
Full rewrite covering:
- VitalSharingTracker + DxHud overlay (cross-machine vital sharing
  replacing UB's localhost-only VTankFellowHeals)
- CombatStatsTracker (~50 Mag-Tools regex patterns, per-element
  breakdown, session/lifetime split)
- LiveInventoryTracker (OnCreate/OnChange/OnRelease → inventory_delta)
- Full event stream catalog (telemetry, vitals, character_stats,
  combat_stats, share_*, nearby_objects, dungeon_map, quest, rare, etc.)
- DECAL STA threading rules (WinForms.Timer not Timers.Timer)
- Hot reload path
- Per-character YAML config structure
- In-game /mm commands (including new radar + vitalsharing toggles)
- Complete project structure
- Cross-repo contract guidance

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 14:55:36 +02:00

326 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# MosswartMassacre — DECAL Plugin for Asheron's Call
> **Status**: Production · In-game companion plugin for the [Mosswart Overlord](https://github.com/SawatoMosswartsEnjoyersClub/MosswartOverlord) backend
A comprehensive DECAL plugin for Asheron's Call that streams live telemetry, vitals, inventory, combat, chat, and rare discoveries to a backend server via WebSocket. Pairs with the Mosswart Overlord web dashboard for real-time multi-account tracking, analytics, and cross-machine utilities.
---
## 📋 Table of Contents
- [Features](#-features)
- [Architecture](#-architecture)
- [Installation](#-installation)
- [Configuration](#-configuration)
- [In-Game Commands](#-in-game-commands)
- [Event Streams](#-event-streams)
- [Cross-Machine Vital Sharing](#-cross-machine-vital-sharing)
- [Building](#-building)
- [Technical Details](#-technical-details)
- [Project Structure](#-project-structure)
- [Contributing](#-contributing)
---
## 🚀 Features
### Core Tracking
- **Telemetry**: Position, kills, kills/hour, online time, VTank state, memory/CPU stats — streamed every 2 seconds
- **Vitals**: Health / Stamina / Mana / Vitae percentages, updated continuously
- **Character Stats**: Full attributes, skills, allegiance, augmentations — sent every 10 minutes
- **Chat**: All chat lines forwarded with color preservation (supports server-side filtering by channel)
- **Rare Discoveries**: Automatic detection + classification (common vs great rares)
- **Quest Timers**: Progress tracking with countdown/ready state
### Inventory
- **Full Inventory Dump**: Complete snapshot on login via `full_inventory`
- **Live Deltas**: `inventory_delta` events for add/update/remove on `OnCreate`, `OnChange`, `OnRelease`
- **ID Requests**: Auto-requests appraisal for items needing spell/combat data
- **Rich Metadata**: Spells, materials, tinkers, workmanship, mana charge, imbues, spellcraft
### Combat Stats (Mag-Tools Style)
- **CombatStatsTracker**: Parses ~50 chat regex patterns matching Mag-Tools combat output
- **Per-element Breakdown**: Damage offense/defense split by slashing/piercing/bludgeoning/fire/cold/acid/lightning
- **Monster Records**: Per-monster damage given/received/kill count
- **Aetheria Surge Tracking**: Counts surge triggers
- **Session Deltas**: Sends session snapshot every 10s; backend accumulates lifetime
### Cross-Machine Vital Sharing (VTankFellowHeals Replacement)
- Broadcasts own vitals + debuff state via WebSocket at 150ms intervals
- Receives peer vitals and feeds them into `UBHelper.vTank.Instance`, making fellow members visible to VTank's heal logic across different machines (vs UB's localhost-only default)
- **DxHud Overlay**: In-game UB-style vital bars with direction arrows, Ctrl+drag repositioning
### Nearby Objects / Radar
- On-demand broadcast of nearby monsters, players, NPCs, containers
- Dungeon tile data for the browser's radar overlay
- Range + entity-type filters configurable from backend command
### Navigation Visualization
- Parses VTank `.nav` files (Circular, Linear, Target, Once; Point/Portal/Recall/Pause/ChatCommand/OpenVendor/UseNPC/Checkpoint/Jump waypoints)
- Renders routes as red lines in the 3D game world
- Side-by-side comparison with UtilityBelt's active navigation
- Performance-capped at 500 rendered segments
### Remote Command Execution
- Backend can send `{player_name, command}` envelopes via the `/ws/live` route → plugin executes in-game
- Supports `/radar`, `/mm` subcommands, chat sends, and any `/` command that VTank/game accepts
### Death & Idle Detection (backend-assisted)
- Plugin reports vitals; backend detects vitae 0→>0 transitions (death) and continuous idle state (5-min grace period) and posts to Discord
### Rare Meta Auto-State
- Optional: toggles VTank meta state on rare detection (e.g., to auto-loot or pause)
## 🏗️ Architecture
```
┌─────────────────────────────────────────────────┐
│ Asheron's Call client │
│ ┌────────────────────────────────────────────┐ │
│ │ DECAL │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ MosswartMassacre.dll │ │ │
│ │ │ │ │ │
│ │ │ • PluginCore — lifecycle + wiring │ │ │
│ │ │ • WebSocket client │ │ │
│ │ │ • KillTracker / CombatStatsTracker │ │ │
│ │ │ • LiveInventoryTracker │ │ │
│ │ │ • VitalSharingTracker │ │ │
│ │ │ • VitalSharingOverlayView (DxHud) │ │ │
│ │ │ • NavVisualization │ │ │
│ │ │ • VVSTabbedMainView (UI) │ │ │
│ │ └──────────────────┬───────────────────┘ │ │
│ └─────────────────────│────────────────────── │
└─────────────────────────│─────────────────────┘
│ wss://
overlord.snakedesert.se/ws/position
(Mosswart Overlord backend)
```
DECAL COM objects are **apartment-threaded (STA)** — the plugin carefully uses `System.Windows.Forms.Timer` (never `System.Timers.Timer`) for any periodic work touching the game API, and hooks `EchoFilter.ServerDispatch` early enough to catch pre-login events.
## 📥 Installation
### Prerequisites
- Windows with .NET Framework 4.8
- Asheron's Call client with DECAL Adapter installed
- VirindiViewService (included in `lib/`)
### Quick Setup
1. Build (or grab the release DLL): see [Building](#-building)
2. Copy `MosswartMassacre.dll` to `C:\Games\Decal Plugins\MosswartMassacre\`
3. Restart DECAL and enable the plugin under *Plugins → MosswartMassacre*
4. Configure settings through the tabbed in-game UI
### Building from Source
```bash
# From repo root
dotnet build mossy.sln -c Release -v minimal
```
Output DLL: `MosswartMassacre\MosswartMassacre\bin\Release\MosswartMassacre.dll`
## ⚙️ Configuration
Settings are stored per-character in YAML at `<PluginDir>\<CharacterName>.yaml`:
```yaml
# Core
websocket_enabled: true
telemetry_enabled: true
char_tag: "default"
rare_meta_enabled: true
remote_commands_enabled: true
http_server_enabled: false
# Vital Sharing
vital_sharing_enabled: true
vital_sharing_overlay_x: 100
vital_sharing_overlay_y: 200
# Navigation
vtank_profiles_path: "C:\\Games\\VirindiPlugins\\VirindiTank\\"
# UI
main_window_x: 100
main_window_y: 100
```
### Backend endpoint
The WebSocket URL is set in `WebSocket.cs`. Shared-secret auth is sent as a query string parameter.
## 🎮 In-Game Commands
Access plugin commands via `/mm`:
```
/mm help — show all commands
/mm report — current kill stats
/mm loc — current map coordinates
/mm reset — reset counters/timers
/mm meta — toggle auto rare meta state
/mm start_radar — start broadcasting nearby objects
/mm stop_radar — stop radar broadcasts
/mm http <on|off> — toggle local HTTP command server (port 8085)
/mm telemetry <on|off> — toggle telemetry streaming
/mm vitalsharing <on|off> — toggle cross-machine vital sharing
/mm combat <show|reset> — combat stats session control
```
## 📡 Event Streams
All events are JSON frames over a single `/ws/position` WebSocket connection. Type discriminator is the `type` field.
| Event | Frequency | Purpose |
|---|---|---|
| `telemetry` | 2s | Position, kill count, session metrics |
| `vitals` | 150ms (on change) | HP / Stam / Mana / Vitae |
| `character_stats` | 10 min | Full attributes/skills |
| `full_inventory` | login | Complete inventory snapshot |
| `inventory_delta` | on item add/change/remove | Incremental per-item update |
| `equipment_cantrip_state` | on equip change | Current equipped spell effects |
| `combat_stats` | 10s | Mag-Tools-style combat deltas |
| `chat` | on line | Any chat message |
| `rare` | on discovery | Rare item find |
| `spawn` | on spawn observation | Monster appeared nearby |
| `portal` | on discovery | Portal with coordinates |
| `quest` | on update | Quest timer/progress |
| `nearby_objects` | on radar command | Entities within range |
| `share_vitals` / `share_debuffs` / `share_cast` | continuous | Cross-machine vital sharing |
| `dungeon_map` | on dungeon entry | Floor tile data |
See backend `EVENT_FORMATS.json` for exact schemas.
## 🩺 Cross-Machine Vital Sharing
Default UtilityBelt `VTankFellowHeals` only works across characters on the **same machine** (IPC-based). This plugin replaces it with a WebSocket relay through the backend, enabling multi-box setups across multiple machines.
### How it works
1. Each plugin instance publishes its own `vitals` / cast state via WebSocket at 150ms intervals
2. The backend relays `share_*` envelopes to every subscribed plugin
3. `VitalSharingTracker` feeds peer data into `UBHelper.vTank.Instance` — VTank then behaves as if the peers are on the same machine
4. Hooks packet `0xF7B1` and `0x004A` for cast-attempt detection, plus chat regex for cast success
### DxHud Overlay
A draggable in-game overlay shows each peer's vital bars with a direction arrow pointing toward that player. Ctrl+drag to reposition; click the × to hide.
## 🛠️ Building
### Standard build
```bash
dotnet build mossy.sln -c Release -v minimal
```
### Deploy (local test)
```bash
cp MosswartMassacre\MosswartMassacre\bin\Release\MosswartMassacre.dll \
"C:\Games\Decal Plugins\MosswartMassacre\MosswartMassacre.dll"
```
Some repo workflows keep the release DLL checked in. If the path is gitignored, use `git add -f` when publishing a release.
### Hot Reload
PluginCore supports an `InitializeForHotReload` path that re-wires trackers without a full DECAL restart. Useful during development — modify, rebuild, replace DLL, invoke hot-reload.
## 🔧 Technical Details
### Build Configuration
- **Target**: .NET Framework 4.8
- **Platform**: AnyCPU / x86 (depending on DECAL host)
- **Architecture**: Direct VirindiViewService integration (no wrapper abstraction)
- **Unsafe blocks**: Enabled for P/Invoke
### Threading Rules
- **Never** touch DECAL COM objects from background threads — they're STA
- Use `System.Windows.Forms.Timer` (UI-thread marshaled), not `System.Timers.Timer`
- WebSocket send methods (`SendXxxAsync`) marshal to a background send queue safely
### Key Files
| File | Responsibility |
|---|---|
| `PluginCore.cs` | Lifecycle, tracker wiring, hot-reload entrypoint |
| `PluginSettings.cs` | YAML per-character config |
| `WebSocket.cs` | Single WS connection, reconnect, send helpers |
| `ChatEventRouter.cs` | Dispatches chat to KillTracker + CombatStatsTracker + others |
| `KillTracker.cs` | Parses kill messages, tracks session kills |
| `CombatStatsTracker.cs` | Parses ~50 regex patterns (Mag-Tools style) |
| `LiveInventoryTracker.cs` | OnCreate/OnChange/OnRelease → inventory_delta |
| `VitalSharingTracker.cs` | Cross-machine vital/debuff relay |
| `VitalSharingOverlayView.cs` | DxHud peer-vitals overlay |
| `MossyInventory.cs` | Rare detection + classification |
| `NavRoute.cs` / `NavVisualization.cs` | VTank .nav parser + renderer |
| `VtankControl.cs` | VTank automation interface |
| `Views/VVSTabbedMainView.cs` | Main tabbed UI |
### Dependencies
- **DECAL Framework** — Decal.Adapter, Decal.Interop.Core, Decal.Interop.D3DService
- **VirindiViewService** — UI framework for game overlays
- **Newtonsoft.Json** — JSON serialization
- **YamlDotNet** — Config file management
- **Mag.Shared** — shared Mag-Tools utilities
- **UBHelper / UtilityBelt interop** — for VTank state injection
## 📁 Project Structure
```
MosswartMassacre/
├── MosswartMassacre/
│ ├── PluginCore.cs
│ ├── PluginSettings.cs
│ ├── WebSocket.cs
│ ├── ChatEventRouter.cs
│ ├── KillTracker.cs
│ ├── CombatStatsTracker.cs
│ ├── CombatInfo.cs
│ ├── LiveInventoryTracker.cs
│ ├── VitalSharingTracker.cs
│ ├── MossyInventory.cs
│ ├── NavRoute.cs
│ ├── NavVisualization.cs
│ ├── VtankControl.cs
│ ├── HttpCommandServer.cs
│ ├── Telemetry.cs
│ ├── Utils.cs
│ ├── Views/
│ │ ├── VVSBaseView.cs
│ │ ├── VVSTabbedMainView.cs
│ │ └── VitalSharingOverlayView.cs
│ ├── ViewXML/
│ │ └── mainViewTabbed.xml
│ └── lib/ # DECAL / VVS / UB interop DLLs
├── Shared/
│ ├── MyWorldObject.cs
│ └── MyWorldObjectCreator.cs
├── mossy.sln
└── README.md
```
## 🤝 Contributing
1. Fork & branch (`feature/...` or `fix/...`)
2. Respect the DECAL STA threading rules
3. When changing event payload schema, **update both plugin and backend** in the same change — the systems are tightly coupled. See `MosswartOverlord/EVENT_FORMATS.json` for the authoritative contract.
4. Prefer additive payload changes (new optional fields) over renames/removes
5. Test end-to-end: plugin → backend WebSocket → browser dashboard
For cross-repo workflow guidance, see `CLAUDE.md` in both repos.
## 📚 Related
- [MosswartOverlord](https://github.com/SawatoMosswartsEnjoyersClub/MosswartOverlord) — the backend + frontend this plugin feeds
- `CLAUDE.md` — developer guidance (AI assistant context)
## 📄 License
MIT — see `LICENSE`.
---
*Built for the Asheron's Call community.*