Agent skill

Dota2 UI

by XavierCHN in XavierCHN/x-template

DOTA2 自定义游戏 UI(Panorama)开发指南。触发词:UI、界面、面板、panorama、frontend、前端、HUD、layout、xml、css、样式。Use when user asks to create or modify DOTA2 custom game UI panels, React components, CSS styles, layout XML…

MITAuto-check passedFrontend & Design

Install Dota2 UI

skills CLI
$ npx skills add XavierCHN/x-template --skill dota2-ui -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install XavierCHN/x-template dota2-ui --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/XavierCHN/x-template.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/dota2-ui .claude/skills/dota2-ui && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
dota2-ui
GitHub stars
216
Token cost
~5.5k tokens
SKILL.md length
1,028 words
Files
1
Skills in repo
6
Repo updated
First seen
Licence
MIT

At a glance

DOTA2 自定义游戏 UI(Panorama)开发指南。触发词:UI、界面、面板、panorama、frontend、前端、HUD、layout、xml、css、样式。Use when user asks to create or modify DOTA2 custom game UI panels, React components, CSS styles, layout XML…

  • Works in 6 steps: 严格使用 DOTA2 Panel 类型:Panorama 不是浏览器,不能使用… → 严格使用 Panorama CSS 属性:不能使用标准 CSS 中… → Label 文本必须使用 text 属性:❌ 禁止 文本… → …
  • User asks to create
  • SKILL.md covers 核心原则, 文件结构, 工作流 and Panel 类型参考, plus 2 more sections
  • Calls npx

What it does

Dota2 UI is an agent skill from XavierCHN/x-template. DOTA2 自定义游戏 UI(Panorama)开发指南。触发词:UI、界面、面板、panorama、frontend、前端、HUD、layout、xml、css、样式。Use when user asks to create or modify DOTA2 custom game UI panels, React components, CSS styles, layout XML, game events communication, or net table data binding.

Its SKILL.md is about 5.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Frontend & Design, covering React components. It works with React. The repository describes itself as: DOTA2自定义游戏开发模板项目,使用typesscript和react开发; Xavier's DOTA 2 custom game template using typescript and react-panorama. The licence is MIT.

When your agent uses it

  • User asks to create
  • Modify DOTA2 custom game UI panels
  • React components
  • Game events communication

Example prompts

  • “/dota2-ui”

Requirements

  • Node.js

Workflow steps

6 steps, taken from the first numbered list in SKILL.md.

  1. 严格使用 DOTA2 Panel 类型:Panorama 不是浏览器,不能使用 HTML 标签(如 、、),只能使用 Valve 提供的 Panel 类型
  2. 严格使用 Panorama CSS 属性:不能使用标准 CSS 中 Panorama 不支持的属性,所有属性值必须符合 Panorama 规范
  3. Label 文本必须使用 text 属性:❌ 禁止 文本 写法(会导致语法错误),✅ 必须使用 。需要本地化时使用 或 $.Localize('#token'),并在 game/resource/addon.csv 中添加对应 Token
  4. 优先使用前端 API 获取数据:如果 Panorama API 可直接获取数据,优先在前端获取;需要后端提供的数据,使用 Game Events 通信
  5. Net Table 限制:每个 CustomNetTable 不能超过 2MB,表名必须注册到 custom_net_tables.txt;大数据量使用 XNetTable,但原则上优先使用 NetTable
  6. 配置与代码分离:所有可能与后端共享或需要集中管理的配置、数值、常量(包括但不限于技能属性、物品数据、单位属性、游戏规则参数、界面显示配置等),都必须放在 game/scripts/npc/ 下的 KV 文件中。前端通过编译后的…

What it can do on your machine

Read from SKILL.md and the folder at commit ba97b00. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • npx

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use npx, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Dota2 UI loads about 5.5k tokens when it runs. Until then it costs about 64 tokens; SKILL.md has 1,028 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~64
When it runs · the whole SKILL.md, loaded when a task matches
~5.5k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from XavierCHN/x-template at commit ba97b00, republished under its MIT licence (© XavierCHN). 1,028 words, ~5,464 tokens.

Download SKILL.mdSave it as .claude/skills/dota2-ui/SKILL.md (or your agent's skills folder).
name
dota2-ui
description
DOTA2 自定义游戏 UI(Panorama)开发指南。触发词:UI、界面、面板、panorama、frontend、前端、HUD、layout、xml、css、样式。Use when user asks to create or modify DOTA2 custom game UI panels, React components, CSS styles, layout XML, game events communication, or net table data binding.

为 DOTA2 自定义游戏项目编写 Panorama UI 界面。

核心原则

  1. 严格使用 DOTA2 Panel 类型:Panorama 不是浏览器,不能使用 HTML 标签(如 <div>、<span>、<p>),只能使用 Valve 提供的 Panel 类型
  2. 严格使用 Panorama CSS 属性:不能使用标准 CSS 中 Panorama 不支持的属性,所有属性值必须符合 Panorama 规范
  3. Label 文本必须使用 text 属性:❌ 禁止 <Label>文本</Label> 写法(会导致语法错误),✅ 必须使用 <Label text="文本" />。需要本地化时使用 <Label localizedText="#token" /> 或 $.Localize('#token'),并在 game/resource/addon.csv 中添加对应 Token
  4. 优先使用前端 API 获取数据:如果 Panorama API 可直接获取数据,优先在前端获取;需要后端提供的数据,使用 Game Events 通信
  5. Net Table 限制:每个 CustomNetTable 不能超过 2MB,表名必须注册到 custom_net_tables.txt;大数据量使用 XNetTable,但原则上优先使用 NetTable
  6. 配置与代码分离:所有可能与后端共享或需要集中管理的配置、数值、常量(包括但不限于技能属性、物品数据、单位属性、游戏规则参数、界面显示配置等),都必须放在 game/scripts/npc/ 下的 KV 文件中。前端通过编译后的 JSON(content/panorama/src/json/)读取,严禁在前端代码中硬编码任何可能变化的配置值。修改配置后需运行 npx gulp kv_2_js 刷新 JSON

文件结构

文件路径用途
布局 XMLcontent/panorama/src/<模块名>/layout.xml面板结构定义
脚本 TSXcontent/panorama/src/<模块名>/script.tsxReact 组件逻辑
样式 LESScontent/panorama/src/<模块名>/styles.lessCSS 样式
类型定义shared/gameevents.d.ts前后端通信事件类型
网络表类型shared/net_tables.d.tsCustomNetTable 类型定义
X网络表类型shared/x-net-table.d.tsXNetTable 类型定义
网络表注册game/scripts/custom_net_tables.txt注册 NetTable 表名

工作流

步骤 1:确认 UI 需求
  • 明确 UI 的功能、交互、数据来源
  • 确定是否需要后端数据(Game Events 还是 Net Table)
  • 确定数据获取方式(优先前端 API → Game Events → Net Table → XNetTable)
步骤 2:创建布局文件 (layout.xml)
xml
<root>
    <scripts>
        <include src="./script.tsx" />
    </scripts>
    <styles>
        <include src="s2r://panorama/styles/dotastyles.vcss_c" />
        <include src="./styles.less" />
    </styles>
    <Panel class="root" hittest="false" />
</root>
  • <root> 是根节点
  • <scripts> 引入 TSX 脚本
  • <styles> 引入样式,s2r://panorama/styles/dotastyles.vcss_c 是 DOTA2 默认样式
  • 根 <Panel> 是 React 的挂载点
步骤 3:编写 React 组件 (script.tsx)
tsx
import 'panorama-polyfill-x/lib/console';
import 'panorama-polyfill-x/lib/timers';
import { FC } from 'react';
import { render } from 'react-panorama-x';

const MyComponent: FC = () => {
    return (
        <Panel className="my-container">
            <Label text="Hello DOTA2" className="my-label" />
        </Panel>
    );
};

render(<MyComponent />, $.GetContextPanel());
步骤 4:编写样式 (styles.less)
less
.my-container {
    width: 100%;
    height: 100%;
    flow-children: down;
}

.my-label {
    font-size: 24px;
    color: white;
    horizontal-align: center;
    vertical-align: center;
}
步骤 4b:从 JSON 读取 KV 数据(推荐)

游戏数值配置(技能属性、物品数据、单位属性等)存储在 KV 文件中,编译后位于 content/panorama/src/json/,前端可导入使用:

tsx
import abilityData from '../json/npc_abilities_custom.json';

// 读取技能数值
const healData = abilityData.dbg_card_heal?.AbilityValues;
const cooldown = abilityData.dbg_card_heal?.AbilityCooldown;

前后端数据分离原则:

  • 所有游戏数值配置写在 KV 文件中
  • 前后端都从编译后的 JSON 文件中读取同一份数据
  • 禁止在前端代码中硬编码数值常量,避免数据不一致
步骤 5:数据通信(如需要)
  • 前端 API 可获取的数据:直接使用 Panorama API
  • 需要后端推送的数据:使用 Game Events
  • 需要持久同步的数据:使用 Net Table
步骤 6:编译验证(必须执行)

完成代码编写后,必须运行编译命令验证没有错误:

bash
# 验证前端 Panorama 编译(非 watch 模式,仅编译一次检查错误)
npx webpack --config content/panorama/webpack.dev.js
  • 如果编译成功(退出码 0),无错误输出,则验证通过
  • 如果编译失败,根据错误信息修复代码后重新编译验证
  • 必须确保编译通过后才能告知用户完成

如果同时修改了后端代码(如 Game Events 声明、NetTable 类型等),还需要验证服务端编译:

bash
# 验证服务端 TSTL 编译
npx tstl --project game/scripts/tsconfig.json
KV → JSON 编译(如修改了 KV 文件)

如果修改了 game/scripts/npc/ 下的 KV 文件,在编译前端之前先编译 KV:

bash
npx gulp kv_2_js
完整验证命令
bash
# 先编译 KV,再同时验证前端 + 服务端
npx gulp jssync && npx webpack --config content/panorama/webpack.dev.js && npx tstl --project game/scripts/tsconfig.json

Panel 类型参考

基础面板
Panel 类型XML 标签用途React 组件
Panel<Panel>基础容器,类似 HTML div<Panel>
Label<Label>文本标签<Label>

⚠️ Label 文本规则:

  • ❌ 错误:<Label>文本内容</Label> — 会导致语法错误
  • ✅ 正确:<Label text="文本内容" />
  • 本地化:<Label localizedText="#my_token" /> 或 <Label text={$.Localize('#my_token')} />
  • 动态文本:<Label text={HP: ${hp}/${maxHp}} /> | Image | <Image> | 图片显示 | <Image> | | Button | <Button> | 按钮 | <Button> | | ToggleButton | <ToggleButton> | 开关按钮 | <ToggleButton> | | RadioButton | <RadioButton> | 单选按钮 | <RadioButton> | | TextEntry | <TextEntry> | 文本输入框 | <TextEntry> | | NumberEntry | <NumberEntry> | 数字输入框 | <NumberEntry> | | Slider | <Slider> | 滑动条 | <Slider> | | DropDown | <DropDown> | 下拉选择框 | <DropDown> | | ProgressBar | <ProgressBar> | 进度条 | <ProgressBar> | | CircularProgressBar | <CircularProgressBar> | 圆形进度条 | <CircularProgressBar> |
DOTA2 专用面板
Panel 类型XML 标签用途关键属性
AbilityImage<DOTAAbilityImage>技能图标abilityname, contextEntityIndex
ItemImage<DOTAItemImage>物品图标itemname, contextEntityIndex
HeroImage<DOTAHeroImage>英雄头像heroid, heroname, heroimagestyle (icon/portrait/landscape)
ScenePanel<DOTAScenePanel>3D 场景渲染SetUnit(), SetRotateParams(), LerpToCameraEntity()
ParticleScenePanel<DOTAParticleScenePanel>粒子场景StartParticles(), SetControlPoint()
UserName<DOTAUserName>玩家名称steamid, accountid
AvatarImage<DOTAAvatarImage>头像SetAccountID()
EconItemPanel<DOTAEconItem>饰品面板SetItemByDefinition()
HUDOverlayMap<DOTAHUDOverlayMap>HUD 地图mapscale, maptexture, mapscroll
MoviePanel<Movie>视频播放Play(), Pause(), Stop(), SetRepeat()
HTMLPanel<HTML> / <DOTAHTMLPanel>HTML 嵌入SetURL(), RunJavascript()
CountdownPanel<Countdown>倒计时startTime, endTime, updateInterval
Panel 通用属性
属性说明
id面板 ID
class / classNameCSS 类名
hittest是否响应鼠标点击 (true/false)
hittestchildren子面板是否响应鼠标点击
enabled是否启用
visible是否可见
defaultfocus默认焦点子面板 ID
selectionpos_x / selectionpos_y选择位置
Panel 通用事件
事件说明React 写法
onactivate点击/激活onactivate={() => {}}
onmouseover鼠标进入onmouseover={() => {}}
onmouseout鼠标离开onmouseout={() => {}}
oncontextmenu右键菜单oncontextmenu={() => {}}
onfocus获得焦点onfocus={() => {}}
onblur失去焦点onblur={() => {}}
ondblclick双击ondblclick={() => {}}
onselect选中onselect={() => {}}
ondeselect取消选中ondeselect={() => {}}
onvaluechanged值变化(Slider/DropDown等)onvaluechanged={() => {}}
ontextentrychange文本变化ontextentrychange={() => {}}
ontextentrysubmit文本提交ontextentrysubmit={() => {}}

CSS 属性参考

重要:与标准 CSS 的差异
差异点标准 CSSPanorama
颜色格式#RRGGBB / rgba()#RRGGBBAA(8位,最后两位为 alpha)
渐变语法linear-gradient(...)gradient(linear, ...)
背景图路径url("path")url("file://{images}/path.png") 或 s2r://panorama/...
默认溢出visiblesquish
文字溢出默认clipellipsis
可见性值visible/hidden/collapsevisible/collapse(无 hidden)
子元素布局display: flexflow-children: right/down
对齐justify-content/align-itemshorizontal-align/vertical-align
尺寸特殊值无fit-children、fill-parent-flow(weight)、width-percentage()、height-percentage()
布局属性
CSS 属性可选值说明
widthfit-children / <px> / <%> / fill-parent-flow(weight) / height-percentage(pct)宽度
heightfit-children / <px> / <%> / fill-parent-flow(weight) / width-percentage(pct)高度
flow-childrenright / down / right-wrap / none子元素流式布局方向
horizontal-alignleft / center / right水平对齐
vertical-aligntop / center / bottom垂直对齐
overflowsquish / clip / scroll(可组合如 squish scroll)溢出处理
margin / margin-top/right/bottom/left<px> / <%>外边距
padding / padding-top/right/bottom/left<px> / <%>内边距
min-width / max-width<px> / <%>宽度范围
min-height / max-height<px> / <%>高度范围
定位属性
CSS 属性可选值说明
position<x> <y> <z>定位(3% 20px 0px)
x / y / z<px> / <%>单独坐标
z-index<number>绘制/点击测试排序(不影响透视)
视觉属性
CSS 属性可选值说明
background-color#RRGGBBAA / gradient(...)背景色/渐变
background-imageurl("file://{images}/...") / url("s2r://...")背景图
background-sizeauto / <px> / <%> / contains背景图尺寸
background-position<%> / center / left / right / top / bottom背景图位置
background-repeatrepeat / no-repeat / space / round背景图重复
color#RRGGBBAA / gradient(...)前景色/文字色
opacity0.0 ~ 1.0透明度
wash-color#RRGGBBAA叠加混合色(alpha 决定着色强度)
blurgaussian(stdDev) / gaussian(h, v, passes)高斯模糊
brightness<multiplier>亮度倍率
contrast<value>对比度
saturation0.0(灰度) ~ 1.0(正常) ~ >1.0(过饱和)饱和度
hue-rotation<deg>色相旋转
visibilityvisible / collapse可见性
Show full SKILL.md (405 more words)Show less
边框属性
CSS 属性可选值说明
border<width> <style> <color>边框简写
border-top/right/bottom/left同上各方向边框
border-color#RRGGBBAA(1~4个值)边框颜色
border-stylesolid / none边框样式
border-width<px>(1~4个值)边框宽度
border-radius<px> / <%> / <h> / <v>圆角
box-shadow[fill/inset] <color> <x> <y> <blur> <spread>盒阴影
文字属性
CSS 属性可选值说明
font-family字体名称字体族
font-size<px>字体大小(像素)
font-weightlight / thin / normal / medium / bold / black字体粗细
font-stylenormal / italic字体样式
text-alignleft / right / center文字对齐
text-decorationnone / underline / line-through文字装饰
text-overflowellipsis(默认) / clip / shrink文字溢出
text-shadow<x> <y> <blur> <strength> <color>文字阴影
text-transformnone / uppercase / lowercase文字转换
letter-spacingnormal / <px>字间距
line-height<px>行高
white-spacenormal / nowrap空白处理
变换与动画
CSS 属性说明
transformtranslate3d(x,y,z) / rotateX/Y/Z(deg) / scale3d(x,y,z)
transform-origin变换原点(默认 50% 50%)
pre-transform-rotate2d3D 变换前的 2D 旋转
pre-transform-scale2d3D 变换前的 2D 缩放(0.8 或 0.4, 0.6)
perspective透视深度(默认 1000)
perspective-origin透视原点/相机位置
transition过渡简写:<property> <duration> <timing> <delay>
transition-timing-functionease / ease-in / ease-out / ease-in-out / linear / cubic-bezier()
animation-name动画名称(需在 XML <styles> 中用 @keyframes 定义)
animation-duration动画时长
animation-delay动画延迟
animation-iteration-count动画迭代次数
animation-timing-function同 transition
animation-direction动画方向
ui-scaleUI 缩放(布局级,150% 或 50% 100% 150%)
clip裁剪区域:rect(t,r,b,l) / radial(cx,cy,startAngle,angularWidth)
sound选择器应用时播放的声音
sound-out选择器移除时播放的声音
伪选择器
伪选择器说明
:hover鼠标悬停
:active鼠标按下
:focus获得键盘焦点
:selected被选中
:disabled被禁用
:enabled被启用
:descendantfocus子级获得焦点
:parentdisabled父级被禁用
:activationdisabled激活被禁用但仍可聚焦
渐变语法
/* 线性渐变 */
background-color: gradient(linear, 0% 0%, 0% 100%, from(#fbfbfbff), to(#c0c0c0ff));
background-color: gradient(linear, 0% 0%, 0% 100%, from(#fbfbfbff), color-stop(0.3, #ebebebff), to(#c0c0c0ff));

/* 径向渐变 */
background-color: gradient(radial, 50% 50%, 0% 0%, 80% 80%, from(#00ff00ff), to(#0000ffff));

/* 多层叠加 */
background-color: #0d1c22ff, gradient(radial, 100% -0%, 100px -40px, 320% 270%, from(#3a464bff), color-stop(0.23, #0d1c22ff), to(#0d1c22ff));

数据通信

方式 1:前端 API 直接获取(优先)

Panorama 提供了丰富的客户端 API,优先使用这些 API 获取数据:

tsx
// 获取本地玩家信息
const localPlayer = Game.GetLocalPlayerInfo();
const playerID = Game.GetLocalPlayerID();

// 获取英雄信息
const hero = Players.GetLocalPlayerPortraitUnit();
const heroName = Entities.GetUnitName(hero);
const hp = Entities.GetHealth(hero);
const maxHp = Entities.GetMaxHealth(hero);

// 获取能力信息
const abilityCount = Entities.GetAbilityCount(hero);

// 游戏状态
const gameState = Game.GameStateIs(DOTA_GameState.DOTA_GAMERULES_STATE_GAME_IN_PROGRESS);
const gameTime = Game.GetGameTime();

// 获取玩家金钱
const gold = Players.GetGold(playerID);

// 获取队伍信息
const team = Entities.GetTeamNumber(hero);

// 获取所有玩家
const playerIDs = Game.GetAllPlayerIDs();
方式 2:Game Events(需要后端推送时使用)

前端→后端:GameEvents.SendCustomGameEventToServer 后端→前端:GameEvents.Subscribe / GameEvents.SendCustomGameEventToAllClients

步骤 1:在 shared/gameevents.d.ts 声明事件类型
typescript
declare interface CustomGameEventDeclarations {
    // 前端→后端
    c2s_buy_item: { item_name: string; count: number };
    // 后端→前端
    s2c_update_score: { team_id: number; score: number };
}
步骤 2:前端发送事件
tsx
GameEvents.SendCustomGameEventToServer('c2s_buy_item', {
    item_name: 'item_healing_salve',
    count: 1,
});
步骤 3:前端监听后端事件
tsx
import { useGameEvent } from 'react-panorama-x';

const MyComponent: FC = () => {
    const [score, setScore] = React.useState(0);

    useGameEvent('s2c_update_score', event => {
        setScore(event.score);
    }, []);

    return <Label text={`Score: ${score}`} />;
};
步骤 4:后端处理和发送(Lua/TSTL)
typescript
// 监听前端事件
ListenToGameEvent('c2s_buy_item', event => {
    const playerID = event.activator_entindex ? EntIndexToHScript(event.activator_entindex) : null;
    // 处理逻辑...
}, undefined);

// 发送事件到前端
CustomGameEventManager.Send_ServerToAllClients('s2c_update_score', {
    team_id: 2,
    score: 100,
});
方式 3:CustomNetTable(需要持久同步的数据)

限制:每个表不能超过 2MB

步骤 1:在 game/scripts/custom_net_tables.txt 注册表名
<!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:generic:version{7412167c-06e9-4698-aff2-e63eb59037e7} -->
{
    custom_net_tables = 
    [
        "hero_list",
        "game_timer",
        "my_new_table"
    ]
}
步骤 2:在 shared/net_tables.d.ts 声明类型
typescript
declare interface CustomNetTableDeclarations {
    my_new_table: {
        my_new_table: {
            some_value: number;
            some_string: string;
        };
    };
}
步骤 3:前端使用
tsx
import { useNetTableKey, useNetTableValues } from 'react-panorama-x';

// 监听特定 key
const data = useNetTableKey('my_new_table', 'my_new_table');

// 监听整个表
const allData = useNetTableValues('my_new_table');
步骤 4:后端写入(Lua/TSTL)
typescript
CustomNetTables.SetTableValue('my_new_table', 'my_new_table', {
    some_value: 42,
    some_string: 'hello',
});
方式 4:XNetTable(大数据量场景)

当数据量可能超过 2MB 限制时使用 XNetTable,它通过 Game Events 分片传输,没有大小限制。

在 shared/x-net-table.d.ts 声明类型
typescript
declare interface XNetTableDefinitions {
    large_data_table: {
        [key: string]: any;
    };
}
后端使用
typescript
// XNetTable 的写入方式(通过自定义的网络表封装)
// 具体使用方式参考项目中 src/utils/xnet-table/ 的实现

原则:优先使用 NetTable,仅在数据量可能超过 2MB 时才使用 XNetTable。

React 组件开发参考

常用 Hooks(react-panorama-x)
Hook用途
useGameEvent(name, handler)监听游戏事件
useNetTableKey(table, key)监听 NetTable 特定 key
useNetTableValues(table)监听 NetTable 整个表
useRegisterForUnhandledEvent(name, handler)注册未处理事件
组件示例
基础面板
tsx
const BasicPanel: FC = () => {
    return (
        <Panel className="container">
            <Label text="标题" className="title" />
            <Panel className="content">
                <Label text="内容区域" />
            </Panel>
        </Panel>
    );
};
按钮交互
tsx
const ButtonExample: FC = () => {
    const [count, setCount] = React.useState(0);

    return (
        <Panel className="container">
            <Label text={`点击次数: ${count}`} />
            <Button className="my-button" onactivate={() => setCount(c => c + 1)}>
                <Label text="点击我" />
            </Button>
        </Panel>
    );
};
本地化文本
tsx
// 方式 1:使用 localizedText 属性(推荐)
<Label localizedText="#my_ui_title" />

// 方式 2:使用 $.Localize() 函数
<Label text={$.Localize('#my_ui_title')} />

// 动态文本中使用本地化
<Label text={`${$.Localize('#score_label')}: ${score}`} />

本地化 Token 需要在 game/resource/addon.csv 中注册:

csv
// addon.csv 格式:Token,English,SChinese
my_ui_title,My Title,我的标题
score_label,Score,分数
显示技能图标
tsx
const AbilityPanel: FC = () => {
    return (
        <Panel className="ability-container">
            <DOTAAbilityImage abilityname="lina_light_strike_array" className="ability-icon" />
            <DOTAItemImage itemname="item_blink" className="item-icon" />
            <DOTAHeroImage heroname="npc_dota_hero_lina" heroimagestyle="icon" className="hero-icon" />
        </Panel>
    );
};
进度条
tsx
const HealthBar: FC = () => {
    const [hp, setHp] = React.useState(100);
    const [maxHp, setMaxHp] = React.useState(100);

    // 使用 GameEvents 或 API 更新 hp/maxHp

    return (
        <Panel className="health-bar-container">
            <ProgressBar
                value={hp}
                min={0}
                max={maxHp}
                className="health-bar"
            />
        </Panel>
    );
};
文本输入
tsx
const InputExample: FC = () => {
    const [text, setText] = React.useState('');

    const handleSubmit = () => {
        GameEvents.SendCustomGameEventToServer('c2s_chat_message', { message: text });
        setText('');
    };

    return (
        <Panel className="input-container" flow-children="right">
            <TextEntry
                text={text}
                ontextentrychange={panel => setText(panel.text)}
                ontextentrysubmit={handleSubmit}
                className="chat-input"
                placeholder="输入消息..."
            />
            <Button onactivate={handleSubmit} className="send-button">
                <Label text="发送" />
            </Button>
        </Panel>
    );
};
下拉选择
tsx
const DropDownExample: FC = () => {
    const [selected, setSelected] = React.useState('');

    return (
        <Panel className="dropdown-container">
            <DropDown onvaluechanged={panel => setSelected(panel.GetSelected().id)} className="my-dropdown">
                <Label id="option1" text="选项一" />
                <Label id="option2" text="选项二" />
                <Label id="option3" text="选项三" />
            </DropDown>
        </Panel>
    );
};
样式最佳实践
less
// 使用 LESS 变量管理主题色
@primary-color: #ffffff;
@accent-color: #4fc3f7ff;
@bg-color: #1a1a2eff;
@danger-color: #ff5252ff;

// 容器布局
.my-container {
    width: 100%;
    height: 100%;
    flow-children: down;     // 子元素纵向排列
    background-color: @bg-color;
    padding: 10px;
}

// 水平居中的标题
.my-title {
    horizontal-align: center;
    font-size: 28px;
    font-weight: bold;
    color: @primary-color;
    margin-bottom: 10px;
}

// 可交互按钮
.my-button {
    flow-children: right;
    background-color: #333355ff;
    border: 1px solid #555577ff;
    border-radius: 4px;
    padding: 8px 16px;
    transition: background-color 0.2s ease-in-out;

    &:hover {
        background-color: #444466ff;
        brightness: 1.2;
    }

    &:active {
        brightness: 0.8;
    }
}

// 响应式宽度
.my-panel {
    width: fill-parent-flow(1.0);   // 等比填充父容器
    height: fit-children;            // 高度自适应内容
}

// 悬浮面板
.floating-panel {
    width: 300px;
    background-color: #000000cc;     // 半透明背景
    border-radius: 8px;
    box-shadow: #00000080 4px 4px 12px 0px;
    padding: 16px;
}

常见陷阱

  1. 不要使用 <div>、<span>:Panorama 中没有这些标签,容器统一用 <Panel>,文字用 <Label>
  2. ❌ 禁止 <Label>文本</Label> 写法:Label 不支持子文本内容,必须使用 text 属性:<Label text="文本" />。这在 XML 和 React TSX 中都适用
  3. 本地化文本:需要本地化时使用 <Label localizedText="#token" /> 或 $.Localize('#token'),并在 game/resource/addon.csv 中添加对应的 Token 行
  4. 颜色必须 8 位十六进制:#RRGGBBAA,如 #FFFFFF80(50% 透明白色)
  5. 不能用 display: flex:Panorama 用 flow-children: right/down 替代
  6. 不能用 position: absolute/relative:Panorama 默认就是绝对定位,子元素通过 horizontal-align/vertical-align 对齐
  7. 不能用 hidden:Panorama 的 visibility 只有 visible 和 collapse,用 collapse 替代 hidden
  8. overflow 默认是 squish:不是标准 CSS 的 visible,如果内容需要溢出显示,要显式设置
  9. 图片路径使用特殊协议:file://{images}/xxx.png 或 s2r://panorama/images/xxx.vtex
  10. font-size 不需要单位:直接写数字,如 font-size: 24;
  11. NetTable 必须注册:忘记在 custom_net_tables.txt 注册表名会导致数据无法同步
  12. NetTable 大小限制:每个表不超过 2MB,大数据用 XNetTable

资源路径协议

协议用途示例
file://{images}/引用 content/panorama/images/ 下的图片file://{images}/custom/my_icon.png
file://{movies}/引用视频文件file://{movies}/intro.webm
s2r://panorama/引用 DOTA2 内置资源s2r://panorama/images/hud/reborn/icon_glyph_on_psd.vtex

编译验证(必须)

代码编写完成后,必须执行以下命令验证编译无错误:

bash
# 编译前端 Panorama(非 watch 模式,仅编译一次检查错误)
npx webpack --config content/panorama/webpack.dev.js
  • 编译成功:退出码 0,无错误输出
  • 编译失败:输出错误信息(文件名、行号、错误描述),修复后重新编译
  • 必须确保编译通过后才能认为任务完成

如果同时修改了后端代码(如 shared/gameevents.d.ts、shared/net_tables.d.ts 等),还需要验证服务端:

bash
# 同时验证前端 + 服务端
npx webpack --config content/panorama/webpack.dev.js && npx tstl --project game/scripts/tsconfig.json

© XavierCHN, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/dota2-ui of XavierCHN/x-template.

Open the folder on GitHubat commit ba97b00

Compare with similar skills

Dota2 UI next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Dota2 UI compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Dota2 UI this skillXavierCHN/x-template216—~5.5kAutomated safety check: PassMIT
Web Artifacts Builderanthropics/skills180k41 repos~769Automated safety check: PassApache-2.0
React Router Developmentremix-run/react-router57k1 repos~1.5kAutomated safety check: PassMIT
React UI State PatternsChrisWiles/claude-code-showcase6.1k8 repos~1.6kAutomated safety check: PassNone
Chakra UI v3 Builderchakra-ui/chakra-ui41k—~3.1kAutomated safety check: PassMIT
React Component PerformanceDimillian/Skills4k5 repos~1.2kAutomated safety check: PassMIT

Similar skills

  • Web Artifacts Builder

    anthropics/skills

    Official

    Builds multi-component claude.ai HTML artifacts as a small React, TypeScript and Tailwind project, then bundles it into one shareable HTML file.

    180k GitHub starsUsed in 41 repos~769 tokens
    Frontend & DesignAuto-check passed
  • React Router Development

    remix-run/react-router

    Guides work on React Router apps by first identifying whether the app uses Framework, Data or Declarative mode, then loading the matching reference and the installed package docs.

    57k GitHub starsUsed in 1 repo~1.5k tokens
    Frontend & DesignAuto-check passed
  • React UI State Patterns

    ChrisWiles/claude-code-showcase

    Sets patterns for React interfaces: when to show loading spinners or skeletons, how to surface errors, how to disable buttons during async work and how to handle empty lists.

    6.1k GitHub starsUsed in 8 repos~1.6k tokens
    Frontend & DesignAuto-check passed
  • Chakra UI v3 Builder

    chakra-ui/chakra-ui

    Builds responsive, accessible Chakra UI v3 components and layouts, sets up Chakra in new or existing projects, and designs themes with tokens, semantic tokens and recipes.

    41k GitHub stars~3.1k tokensUpdated 2 days ago
    Frontend & DesignAuto-check passed
  • Analyze and optimize React component performance issues (slow renders, re-render thrash, laggy lists, expensive computations).

    4k GitHub starsUsed in 5 repos~1.2k tokens
    Frontend & DesignAuto-check passed
  • React View Transitions Guide

    vercel-labs/next-beats

    Official

    Guides implementing animated page and state transitions in React with the native View Transition API, covering shared elements, list reorders and directional navigation.

    167 GitHub starsUsed in 10 repos~3.1k tokens
    Frontend & DesignAuto-check passed

More from XavierCHN/x-template

  • Dota2 Localization

    XavierCHN/x-template

    为 DOTA2自定义游戏 项目生成 Dota 2 本地化文本(addon.csv)。触发词:本地化、翻译、loc、i18n、addon.csv、文本、tooltip、多语言。Use when user asks to generate localization entries for abilities/units/items/modifiers, translate Chinese to…

    216 GitHub stars~567 tokensUpdated 4 mo ago
    Auto-check passed
  • Dota2 Game Logic

    XavierCHN/x-template

    DOTA2 自定义游戏服务端逻辑开发指南。触发词:游戏逻辑、服务端、server、game mode、游戏模式、GameRules、modifier、timer、lua、TSTL。Use when user asks to create or modify DOTA2 custom game server-side logic, game mode configuration…

    216 GitHub stars~2.7k tokensUpdated 4 mo ago
    Auto-check passed
  • Dota2 Ability

    XavierCHN/x-template

    Dota 2 自定义技能编写指南。触发词:技能、ability、spell、被动、主动. An agent skill from XavierCHN/x-template.

    216 GitHub stars~3.2k tokensUpdated 4 mo ago
    Auto-check passed
  • Dota2 Item

    XavierCHN/x-template

    Dota 2 自定义物品编写指南。触发词:物品、item、装备、道具、配方、recipe、合成. An agent skill from XavierCHN/x-template.

    216 GitHub stars~1.7k tokensUpdated 4 mo ago
    Auto-check passed
  • Dota2 Unit

    XavierCHN/x-template

    Dota 2 自定义单位编写指南。适用于编写/修改单位 KV 配置文件(game/scripts/npc/customunits/)。触发词:单位、unit、creature、怪物、召唤物、建筑、塔、npc。

    216 GitHub stars~2.4k tokensUpdated 4 mo ago
    Auto-check passed

Works with

Questions about Dota2 UI

What does Dota2 UI do?

DOTA2 自定义游戏 UI(Panorama)开发指南。触发词:UI、界面、面板、panorama、frontend、前端、HUD、layout、xml、css、样式。Use when user asks to create or modify DOTA2 custom game UI panels, React components, CSS styles, layout XML…. Dota2 UI is an agent skill from XavierCHN/x-template. DOTA2 自定义游戏 UI(Panorama)开发指南。触发词:UI、界面、面板、panorama、frontend、前端、HUD、layout、xml、css、样式。Use when user asks to create or modify DOTA2 custom game UI panels, React components, CSS styles, layout XML, game events communication, or net table data binding.

When should I use Dota2 UI?

Dota2 UI fits situations like: user asks to create; modify DOTA2 custom game UI panels; React components; game events communication.

How do I install Dota2 UI in Claude Code?

Run `npx skills add XavierCHN/x-template --skill dota2-ui -a claude-code`. Or copy the skill folder (.agents/skills/dota2-ui in XavierCHN/x-template) into .claude/skills/dota2-ui in your project. Claude Code loads it when a task matches its description.

How do I install Dota2 UI in Codex?

Run `npx skills add XavierCHN/x-template --skill dota2-ui -a codex`. Or copy the skill folder (.agents/skills/dota2-ui in XavierCHN/x-template) into .agents/skills/dota2-ui in your project. Codex loads it when a task matches its description.

Can I use Dota2 UI in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add XavierCHN/x-template --skill dota2-ui -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/dota2-ui, .gemini/skills/dota2-ui, .github/skills/dota2-ui and .opencode/skills/dota2-ui in your project.

What does Dota2 UI need to run?

Going by SKILL.md and its folder, Dota2 UI needs the command-line tools its instructions call (npx). Our summary lists: Node.js.

Does Dota2 UI access the network?

SKILL.md contains no URLs. Its commands use npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Dota2 UI safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Dota2 UI use?

Dota2 UI is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Dota2 UI use?

About 5.5k tokens (SKILL.md is roughly 22k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Dota2 UI?

Skills that share tags, products or a category with Dota2 UI: Web Artifacts Builder (anthropics/skills, 180k stars), React Router Development (remix-run/react-router, 57k stars), React UI State Patterns (ChrisWiles/claude-code-showcase, 6.1k stars) and Chakra UI v3 Builder (chakra-ui/chakra-ui, 41k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Dota2 UI?

XavierCHN (a GitHub user) maintains it in XavierCHN/x-template, which has 216 GitHub stars. The repository holds 6 skills in this directory. The repository was last updated on May 23, 2026.

Source: XavierCHN/x-template on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.