Trigger VoiceAttack commands when pixels on your screen change color.
A lightweight plugin for VoiceAttack that watches screen regions for specific colors and triggers VoiceAttack commands when they appear, disappear, or change. Useful for reacting to in-game UI events — low HP indicators, ammo refills, notifications, pickup icons — without writing any OCR or image recognition code.
This plugin uses BitBlt screen capture. Strict anti-cheat systems (EAC, BattleEye, Vanguard, Faceit AC, FairFight…) may flag this activity as suspicious.
Using this plugin on competitive games (Valorant, CS2, Apex, Fortnite, R6, Rust, Escape from Tarkov, etc.) may result in a permanent ban of your account.
Safe use: single-player games, emulators, productivity apps, games without strict anti-cheat. Use at your own risk.
- 🎯 Zone and point capture — draw a rectangle on screen or click a single pixel to define what to watch
- 💧 Eyedropper — capture target colors directly from the screen with a live hover HUD
- 👁️ Live preview — see what the scanner sees in real time while editing a watcher
- 🎨 RGB / HSV / Exact match modes — HSV with separate tolerances for Hue / Saturation / Value handles dynamic lighting gracefully
- 🪟 Window-relative coords — lock coords to a specific window's client area
- 😴 Auto-pause when the target window is not in focus
- 🔥 Four trigger modes —
onEnter,onLeave,onChange,whileTrue - ⌨️ Global hotkey — open the configuration window from anywhere (default:
Ctrl+Shift+P) - 🌍 Bilingual UI — French / English, auto-follows system language
- 📋 Clipboard-ready variables panel — one click to copy any VoiceAttack token
- 📤 Import / Export — share watcher configurations via JSON
- 📊 Runtime stats — trigger counter and last-fired timestamp per watcher
- 📁 Groups — organise watchers by game or context, filter the list
-
Pick the region to watch — a fullscreen overlay lets you draw a rectangle directly on the game window. The picker works across multiple monitors.
-
The plugin captures the region, shows a live preview, and starts matching against your target color with the tolerance and trigger mode you chose. Runtime stats (trigger count, last fired) update in the list.
|
Eyedropper — floating HUD that follows the cursor, showing the live color and coords. Left-click captures. |
Settings — language, global hotkey, import/export of watcher configurations. |
- Download the latest release or clone this repo
- Build once:
dotnet build -c Release - Close VoiceAttack
- Double-click
Install.bat— it copies the DLL to%APPDATA%\VoiceAttack2\Apps\PixelDetect\ - Start VoiceAttack
Copy the three files from bin\Release\net8.0-windows\:
VoiceAttackPixelDetectPlugin.dllVoiceAttackPixelDetectPlugin.deps.jsonVoiceAttackPixelDetectPlugin.pdb(optional, for debugging)
into %APPDATA%\VoiceAttack2\Apps\PixelDetect\ (create the folder if needed).
⚠️ Do not copybin/orobj/folders themselves — VoiceAttack scans recursively and will detect duplicate plugin instances.
- Launch VoiceAttack
Options→ tick Enable Plugin Support- Restart VoiceAttack
- The log should show:
PixelDetect: ready — N watcher(s) loaded...
- Create a VoiceAttack command (voice trigger or keyboard shortcut) that calls:
- Action type:
Other → Advanced → Execute External Plugin Function - Plugin:
Pixel Detect - Plugin context:
config
- Action type:
- Run the command (or press
Ctrl+Shift+P) — the configuration window opens - Click + Add to create a new watcher
- Name it, type the name of a VoiceAttack command to trigger (e.g.
drink potion) - Click 🎯 Point and click on the pixel you want to watch — coords and color are captured in one go
- Adjust the tolerance with the slider; use Test now to verify
- Click Save and apply — the watcher starts running in the background
The Plugin Context field of VoiceAttack's Execute External Plugin Function action accepts:
| Context | Purpose |
|---|---|
config |
Open the configuration window (same as the global hotkey) |
reload |
Reload watchers.json without opening the UI |
check |
One-shot pixel check (reads input variables, writes result variables) |
sample |
Read the color of a pixel (at cursor by default, or at given coords) |
watch.add |
Programmatically add a watcher (requires WatcherName, Command, region/color variables) |
watch.remove |
Remove a watcher by name |
watch.list |
List all registered watchers |
watch.clearAll |
Remove all watchers |
watch.pause |
Temporarily pause one watcher (or all if no name provided) |
watch.resume |
Resume paused watchers |
Variables the plugin writes automatically when a watcher fires:
| Variable | Type | Description |
|---|---|---|
PixelDetect.Last.Name |
Text | Name of the watcher that fired |
PixelDetect.Last.X / .Y |
Integer | Screen coords where the match occurred |
PixelDetect.Last.Color |
Text | Detected color as #RRGGBB |
PixelDetect.Last.Distance |
Integer | Colorimetric distance to the target (0 = perfect) |
PixelDetect.Last.Found |
Boolean | Always true when invoked by a watcher |
Variables set by check:
| Variable | Type | Description |
|---|---|---|
PixelDetect.Result |
Boolean | true if a matching pixel was found |
PixelDetect.SampledColor |
Text | Closest color found in the region |
PixelDetect.FoundX / .FoundY |
Integer | Coords of the match (null if none) |
PixelDetect.Distance |
Integer | Colorimetric distance |
In the config window, click 📋 Variables to browse every token and copy it to the clipboard ready-to-paste.
- RGB — per-channel tolerance (0–255). Simple but struggles with lighting variation.
- HSV — separate tolerances for Hue (±°), Saturation (±%), Value (±%). Robust to shadows, highlights, anti-aliasing. Recommended for game UI with dynamic lighting.
- Exact — no tolerance. Strict.
- onEnter — fires once when the color appears (most common: alerts, pickups)
- onLeave — fires once when the color disappears (end of animation, buff fade)
- onChange — fires on every transition, both directions
- whileTrue — fires continuously while the color is present (respects cooldown)
Watchers and plugin settings are persisted to:
%APPDATA%\VoiceAttack2\Apps\PixelDetect\watchers.json
The file uses a versioned JSON schema. It's hand-editable but the UI is much faster.
Requirements:
- Windows 10/11
- .NET 8 SDK
- VoiceAttack (for runtime testing)
git clone https://github.com/jarod0476/VoiceAttackPixelDetectPlugin.git
cd VoiceAttackPixelDetectPlugin
dotnet build -c Release
.\Install.batThe log says "Multiple instances of plugin found". What do I do?
You probably copied the project folder (with bin/ and obj/ inside) into VoiceAttack's Apps folder. VoiceAttack scans recursively and finds the DLL in multiple places. Solution: delete everything under Apps\PixelDetect\ and copy only the three files from bin\Release\net8.0-windows\, or re-run Install.bat.
Can the plugin trigger different commands based on which pixel matched?
Yes. Use {INT:PixelDetect.Last.X} / {INT:PixelDetect.Last.Y} inside the triggered command, combined with VoiceAttack's If actions.
Does it work on multi-monitor setups? Yes. The zone picker covers the entire virtual screen. Coordinates are absolute screen coords unless a window title is provided.
Why is my watcher not firing even though the color is visible? Check three things: (1) the target window must be in focus if "scan only when focused" is checked; (2) the tolerance might be too low — try RGB 15 or switch to HSV; (3) the live preview shows exactly what the scanner sees — use it to diagnose.
PRs welcome. Please:
- Keep the UI bilingual — every new UI string goes in both
Resources/Strings.fr.xamlandStrings.en.xaml - Follow the existing code style (nullable enable, clear separation between model/UI/scanner)
- Test your change with
dotnet build -c Releaseand a live install before opening a PR
MIT — do whatever you want, just keep the copyright notice.
Built with extensive pair-programming assistance from Claude (Anthropic). All design decisions, product direction, UX choices, feature scope and real-world testing were done by me — Claude handled the code production and documentation based on my specifications and iterative reviews.
If this plugin saves you time or replaces a command you'd otherwise pay for, consider buying me a coffee:
Every euro is appreciated. No pressure — the plugin stays fully free and MIT-licensed regardless.