DOTA2 Custom Game Dev
Use this skill for DOTA2 custom game addon work across Lua, TypeScriptToLua/TSTL, SolidJS Panorama UI, Panorama JS/TS, Panorama CSS/XML, KV files, and live Dota 2 runtime inspection when Dota2 MCP tools are available.
Reference Source
Prefer live Dota2 MCP tools when the runtime exposes them. Use bundled
BigCiba/vscode-dota2-tools
snapshots when MCP tools are unavailable, Dota 2 is not running, or the user only needs offline source work.
- Upstream repo:
https://github.com/BigCiba/vscode-dota2-tools
- Local source map:
references/upstream-source-map.md
- TSTL DOTA2 guide:
- SolidJS Panorama guide:
references/solid-panorama-ui.md
- Refresh script:
scripts/update_references.ps1
- API search helper:
scripts/search_dota2_api.py
- TSTL project detector:
scripts/detect_tstl_project.py
- SolidJS Panorama detector:
scripts/detect_solid_panorama_project.py
Do not treat the bundled references as permanent truth. They are snapshots and should be refreshed from upstream when the user asks for latest API behavior or when API accuracy matters.
Dota2 MCP Workflow
Use Dota2 MCP only when live game evidence helps: testing an addon, checking in-game behavior, reading console errors, launching a map, or inspecting current runtime state. Do not make MCP a prerequisite for ordinary source edits.
Call
first for live testing/debugging. It reports connection, addon/map state, and the next useful step. If the client exposes
instead of
, use
as the status fallback.
Prefer the fast runtime loop: edit source, let the repo build/watch command compile, reload in the live game, then verify with MCP. Do not call
just to pick up routine code edits; use
with project reload commands such as
when the addon supports them.
Do not mutate live game state, send destructive console commands, or run arbitrary server Lua unless the user asked for live debugging/testing. For ordinary source edits, read project files first and use MCP output only as evidence.
Project Model
Start by identifying the addon roots:
- Game scripts:
- NPC/KV config:
- Panorama layout:
content/panorama/layout/custom_game/
- Panorama JS:
content/panorama/scripts/custom_game/
- Panorama CSS:
content/panorama/styles/custom_game/
- Localization:
- TSTL source, when present: , ,
- SolidJS Panorama source, when present: , ,
If the project layout differs, search for
,
,
,
,
,
,
,
,
,
, and
.
For TSTL projects, inspect the generated Lua but edit the TypeScript source. Do not patch generated Lua under
unless the user explicitly asks for an emergency generated-output patch.
For SolidJS Panorama projects, inspect generated JS/XML/CSS but edit the Solid TSX, Less/SCSS, declarations, or build scripts. Do not patch generated Panorama assets unless the user explicitly asks for an emergency generated-output patch.
API Lookup Workflow
Prefer Dota2 MCP API tools for live/current API behavior. If MCP is unavailable, prefer targeted lookup through the bundled script instead of reading large JSON files directly. Run examples from this skill directory, or replace
with the resolved path to the skill directory when working from another current directory.
powershell
python .\scripts\search_dota2_api.py --kind lua --query CustomGameEventManager
python .\scripts\search_dota2_api.py --kind js --query SendCustomGameEventToServer
python .\scripts\search_dota2_api.py --kind css --query flow-children
python .\scripts\search_dota2_api.py --kind panel --query DOTAAbilityImage
python .\scripts\detect_tstl_project.py <path-to-addon>
python .\scripts\detect_solid_panorama_project.py <path-to-addon>
When references are missing or stale, refresh them from this skill directory:
powershell
powershell -ExecutionPolicy Bypass -File .\scripts\update_references.ps1
Boundaries
- Server Lua is authoritative. Do not trust Panorama client payloads for economy, damage, inventory, rewards, cooldowns, or win conditions.
- Panorama JS is client UI logic. It can send intent to the server, read public state from custom net tables, and update panels, but server Lua must validate.
- KV files define data and engine bindings. Verify , , , modifier names, and localization tokens against Lua and Panorama usage.
- CSS is Panorama CSS, not browser CSS. Check the DOTA2 CSS reference before using modern web CSS.
- XML panels are Panorama panels, not DOM elements. Check panel-specific attributes/events before assuming browser semantics.
- TSTL changes should preserve emitted Lua semantics. Be careful with , multi-return values, Lua arrays/tables, decorators, module imports, and APIs that rely on Lua colon-call behavior.
- Generated Lua and generated Panorama JS are build artifacts in TSTL template projects. Prefer fixing and then running the repo's build/typecheck command.
- SolidJS Panorama is not browser DOM work. Components render into Panorama panels, use Panorama events/attributes, and must respect Panorama CSS/XML limitations.
- Solid effects and subscriptions must clean up , , timers, and panel handlers with or the project's helper utilities.
Common Workflows
For Lua ability or modifier work:
- Find the KV entry and .
- Inspect Lua class names, , intrinsic modifiers, and special value reads.
- Use Dota2 MCP API/runtime tools when available; otherwise search the Lua API snapshot for engine calls.
- Validate server/client boundary and authority.
For TSTL vscripts work:
- Run or emulate
scripts/detect_tstl_project.py
to find , , TSTL packages, and source/output roots.
- Read before changing TypeScript semantics.
- Trace from KV to generated Lua and then back to .
- Prefer source edits in TypeScript and validate with the repository's scripts such as , , , or
npx tstl -p tsconfig.json
, depending on what exists.
- For live verification, prefer watch/build plus
console_send(commands="reload_script")
and console_output(channel="VScript", level=3)
before restarting the map.
- If build commands need dependencies or network, ask for permission or report the missing dependency clearly.
For Panorama UI work:
- Locate XML, JS, CSS, and .
- Search JS APIs for , , , , or .
- Search CSS and panel references for unsupported properties or wrong panel attributes.
- Trace event flow between JS and Lua through and .
- When live MCP tools are available, use with and the Panorama API/CSS/event tools to confirm runtime errors and supported UI APIs.
For SolidJS Panorama UI work:
- Run or emulate
scripts/detect_solid_panorama_project.py
to find , Solid dependencies, source roots, build scripts, and output roots.
- Read
references/solid-panorama-ui.md
before changing Solid rendering, reactivity, generated XML/CSS, or manifest behavior.
- Trace a UI entry from to
solid/src/ui/<name>/<name>.tsx
, then to generated content/<addon>/panorama/scripts/custom_game/<name>.js
, layout XML, styles, and .
- Prefer source edits in TSX/Less/SCSS/declarations/build plugins and validate with or the project's equivalent command.
- Keep DOTA2 trust boundaries: Solid/Panorama may send intent and render replicated state, but server vscripts remain authoritative.
For synchronization bugs:
- Identify whether state should be push event, net table, or local-only UI state.
- In Lua, inspect
CustomGameEventManager:RegisterListener
, CustomNetTables:SetTableValue
, and player validation.
- In JS, inspect ,
GameEvents.SendCustomGameEventToServer
, and CustomNetTables.SubscribeNetTableListener
.
- When live MCP tools are available, inspect console output, entities/modifiers, and safe Lua expressions to confirm actual runtime state.
- Report stale state, trust boundary, and lifecycle risks separately.
Output
When explaining an API or fixing code, include:
- Which layer is involved: Lua server, Panorama JS, CSS/XML, KV, or localization.
- The exact project files and API references used.
- Any server/client trust boundary.
- Whether the code is source TypeScript or generated Lua/JS.
- Whether SolidJS Panorama source or generated Panorama assets were changed.
- Whether Dota2 MCP live evidence was used, or why the work fell back to bundled/offline references.
- Any reference freshness caveat if the bundled snapshot was not refreshed in the current turn.