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:
references/tstl-dota2.md
- 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 dota_status first for live testing/debugging. It reports connection, addon/map state, and the next useful step. If the client exposes project_info instead of dota_status, use project_info 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 dota_restart just to pick up routine code edits; use console_send with project reload commands such as reload_script 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:
game/scripts/vscripts/
- NPC/KV config:
game/scripts/npc/
- Panorama layout:
content/panorama/layout/custom_game/
- Panorama JS:
content/panorama/scripts/custom_game/
- Panorama CSS:
content/panorama/styles/custom_game/
- Localization:
game/resource/
- TSTL source, when present:
src/vscripts/, src/panorama/, src/common/
- SolidJS Panorama source, when present:
solid/src/ui/, solid/src/components/, solid/src/utils/
If the project layout differs, search for addon_game_mode.lua, npc_abilities_custom.txt, custom_net_tables.txt, custom_events.txt, custom_ui_manifest.xml, layout/custom_game, package.json, tsconfig.json, tstl, solid/build.ts, and solid/src/ui.
For TSTL projects, inspect the generated Lua but edit the TypeScript source. Do not patch generated Lua under game/scripts/vscripts/ 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 .\scripts with the resolved path to the skill directory when working from another current directory.
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 -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
ScriptFile, BaseClass, AbilitySpecial, 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
this, 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
src/**/*.ts 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
GameEvents, CustomNetTables, timers, and panel handlers with onCleanup or the project's helper utilities.
Common Workflows
For Lua ability or modifier work:
- Find the KV entry and
ScriptFile.
- Inspect Lua class names,
LinkLuaModifier, 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 package.json, tsconfig.json, TSTL packages, and source/output roots.
- Read
references/tstl-dota2.md before changing TypeScript semantics.
- Trace from KV
ScriptFile to generated Lua and then back to src/vscripts/**/*.ts.
- Prefer source edits in TypeScript and validate with the repository's scripts such as
npm run build, npm run build:vscripts, npm run dev, 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
custom_ui_manifest.xml.
- Search JS APIs for
GameEvents, CustomNetTables, Players, Entities, or Abilities.
- Search CSS and panel references for unsupported properties or wrong panel attributes.
- Trace event flow between JS and Lua through
CustomGameEventManager and GameEvents.
- When live MCP tools are available, use
console_output with PanoramaScript 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 package.json.panorama, 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
package.json.panorama to solid/src/ui/<name>/<name>.tsx, then to generated content/<addon>/panorama/scripts/custom_game/<name>.js, layout XML, styles, and custom_ui_manifest.xml.
- Prefer source edits in TSX/Less/SCSS/declarations/build plugins and validate with
npm run build:solid 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.Subscribe, 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.
1---2name: dota2-custom-game-dev3description: Use when working on DOTA2 custom game addons, including server Lua, TypeScriptToLua/TSTL vscripts, SolidJS Panorama UI, TypeScript Panorama, Panorama JavaScript, Panorama CSS/XML, KV files, abilities, modifiers, custom game events, net tables, Dota2 MCP live status/testing, and API lookup against Dota 2 runtime or BigCiba/vscode-dota2-tools references.4---56# DOTA2 Custom Game Dev78Use 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.910## Reference Source1112Prefer 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.1314- Upstream repo: `https://github.com/BigCiba/vscode-dota2-tools`15- Local source map: `references/upstream-source-map.md`16- TSTL DOTA2 guide: `references/tstl-dota2.md`17- SolidJS Panorama guide: `references/solid-panorama-ui.md`18- Refresh script: `scripts/update_references.ps1`19- API search helper: `scripts/search_dota2_api.py`20- TSTL project detector: `scripts/detect_tstl_project.py`21- SolidJS Panorama detector: `scripts/detect_solid_panorama_project.py`2223Do 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.2425## Dota2 MCP Workflow2627Use 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.2829Call `dota_status` first for live testing/debugging. It reports connection, addon/map state, and the next useful step. If the client exposes `project_info` instead of `dota_status`, use `project_info` as the status fallback.3031Prefer 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 `dota_restart` just to pick up routine code edits; use `console_send` with project reload commands such as `reload_script` when the addon supports them.3233Do 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.3435## Project Model3637Start by identifying the addon roots:3839- Game scripts: `game/scripts/vscripts/`40- NPC/KV config: `game/scripts/npc/`41- Panorama layout: `content/panorama/layout/custom_game/`42- Panorama JS: `content/panorama/scripts/custom_game/`43- Panorama CSS: `content/panorama/styles/custom_game/`44- Localization: `game/resource/`45- TSTL source, when present: `src/vscripts/`, `src/panorama/`, `src/common/`46- SolidJS Panorama source, when present: `solid/src/ui/`, `solid/src/components/`, `solid/src/utils/`4748If the project layout differs, search for `addon_game_mode.lua`, `npc_abilities_custom.txt`, `custom_net_tables.txt`, `custom_events.txt`, `custom_ui_manifest.xml`, `layout/custom_game`, `package.json`, `tsconfig.json`, `tstl`, `solid/build.ts`, and `solid/src/ui`.4950For TSTL projects, inspect the generated Lua but edit the TypeScript source. Do not patch generated Lua under `game/scripts/vscripts/` unless the user explicitly asks for an emergency generated-output patch.5152For 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.5354## API Lookup Workflow5556Prefer 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 `.\scripts` with the resolved path to the skill directory when working from another current directory.5758```powershell59python .\scripts\search_dota2_api.py --kind lua --query CustomGameEventManager60python .\scripts\search_dota2_api.py --kind js --query SendCustomGameEventToServer61python .\scripts\search_dota2_api.py --kind css --query flow-children62python .\scripts\search_dota2_api.py --kind panel --query DOTAAbilityImage63python .\scripts\detect_tstl_project.py <path-to-addon>64python .\scripts\detect_solid_panorama_project.py <path-to-addon>65```6667When references are missing or stale, refresh them from this skill directory:6869```powershell70powershell -ExecutionPolicy Bypass -File .\scripts\update_references.ps171```7273## Boundaries7475- Server Lua is authoritative. Do not trust Panorama client payloads for economy, damage, inventory, rewards, cooldowns, or win conditions.76- 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.77- KV files define data and engine bindings. Verify `ScriptFile`, `BaseClass`, `AbilitySpecial`, modifier names, and localization tokens against Lua and Panorama usage.78- CSS is Panorama CSS, not browser CSS. Check the DOTA2 CSS reference before using modern web CSS.79- XML panels are Panorama panels, not DOM elements. Check panel-specific attributes/events before assuming browser semantics.80- TSTL changes should preserve emitted Lua semantics. Be careful with `this`, multi-return values, Lua arrays/tables, decorators, module imports, and APIs that rely on Lua colon-call behavior.81- Generated Lua and generated Panorama JS are build artifacts in TSTL template projects. Prefer fixing `src/**/*.ts` and then running the repo's build/typecheck command.82- SolidJS Panorama is not browser DOM work. Components render into Panorama panels, use Panorama events/attributes, and must respect Panorama CSS/XML limitations.83- Solid effects and subscriptions must clean up `GameEvents`, `CustomNetTables`, timers, and panel handlers with `onCleanup` or the project's helper utilities.8485## Common Workflows8687For Lua ability or modifier work:88891. Find the KV entry and `ScriptFile`.902. Inspect Lua class names, `LinkLuaModifier`, intrinsic modifiers, and special value reads.913. Use Dota2 MCP API/runtime tools when available; otherwise search the Lua API snapshot for engine calls.924. Validate server/client boundary and authority.9394For TSTL vscripts work:95961. Run or emulate `scripts/detect_tstl_project.py` to find `package.json`, `tsconfig.json`, TSTL packages, and source/output roots.972. Read `references/tstl-dota2.md` before changing TypeScript semantics.983. Trace from KV `ScriptFile` to generated Lua and then back to `src/vscripts/**/*.ts`.994. Prefer source edits in TypeScript and validate with the repository's scripts such as `npm run build`, `npm run build:vscripts`, `npm run dev`, or `npx tstl -p tsconfig.json`, depending on what exists.1005. For live verification, prefer watch/build plus `console_send(commands="reload_script")` and `console_output(channel="VScript", level=3)` before restarting the map.1016. If build commands need dependencies or network, ask for permission or report the missing dependency clearly.102103For Panorama UI work:1041051. Locate XML, JS, CSS, and `custom_ui_manifest.xml`.1062. Search JS APIs for `GameEvents`, `CustomNetTables`, `Players`, `Entities`, or `Abilities`.1073. Search CSS and panel references for unsupported properties or wrong panel attributes.1084. Trace event flow between JS and Lua through `CustomGameEventManager` and `GameEvents`.1095. When live MCP tools are available, use `console_output` with `PanoramaScript` and the Panorama API/CSS/event tools to confirm runtime errors and supported UI APIs.110111For SolidJS Panorama UI work:1121131. Run or emulate `scripts/detect_solid_panorama_project.py` to find `package.json.panorama`, Solid dependencies, source roots, build scripts, and output roots.1142. Read `references/solid-panorama-ui.md` before changing Solid rendering, reactivity, generated XML/CSS, or manifest behavior.1153. Trace a UI entry from `package.json.panorama` to `solid/src/ui/<name>/<name>.tsx`, then to generated `content/<addon>/panorama/scripts/custom_game/<name>.js`, layout XML, styles, and `custom_ui_manifest.xml`.1164. Prefer source edits in TSX/Less/SCSS/declarations/build plugins and validate with `npm run build:solid` or the project's equivalent command.1175. Keep DOTA2 trust boundaries: Solid/Panorama may send intent and render replicated state, but server vscripts remain authoritative.118119For synchronization bugs:1201211. Identify whether state should be push event, net table, or local-only UI state.1222. In Lua, inspect `CustomGameEventManager:RegisterListener`, `CustomNetTables:SetTableValue`, and player validation.1233. In JS, inspect `GameEvents.Subscribe`, `GameEvents.SendCustomGameEventToServer`, and `CustomNetTables.SubscribeNetTableListener`.1244. When live MCP tools are available, inspect console output, entities/modifiers, and safe Lua expressions to confirm actual runtime state.1255. Report stale state, trust boundary, and lifecycle risks separately.126127## Output128129When explaining an API or fixing code, include:130131- Which layer is involved: Lua server, Panorama JS, CSS/XML, KV, or localization.132- The exact project files and API references used.133- Any server/client trust boundary.134- Whether the code is source TypeScript or generated Lua/JS.135- Whether SolidJS Panorama source or generated Panorama assets were changed.136- Whether Dota2 MCP live evidence was used, or why the work fell back to bundled/offline references.137- Any reference freshness caveat if the bundled snapshot was not refreshed in the current turn.