name nba2k-skin-moment-config description NBA2KOL2 游戏"时刻"皮肤配表工具。用于向 PlayerSkin.xlsx 及其关联 sheet 追加新的皮肤条目,覆盖完整的依赖链(UniformPanel、PicPanel、VideoPanel、CelebratePanel、IntroPanel、Main、UserInfoPanel),并配置关联的 Equipment.xlsx、Condition.xlsx、ClothesSet.xlsx、ID2StringMapTable.xlsx、Item.xlsx、CommonExchange.xlsx。
在以下场景下请主动使用本技能:
- 用户提到要"配表"、"新增皮肤"、"加皮肤条目"、"填 PlayerSkin"
- 用户说要配置"时刻"内容、新球员皮肤、或某某球员的XXX版本
- 用户提到 PlayerSkin.xlsx 的任何 sheet(Main、IntroPanel、PicPanel、VideoPanel、UniformPanel、CelebratePanel)
- 用户提供了 Main ID、球员英文名文件夹、中文名版本标签等皮肤配置相关信息
- 用户提到"陈列室"、"致敬传奇"、"历史球员"、"现役球员"等系列名称
- 用户说"配XX球员"、"加个时刻"、"新增一个皮肤"、"开始配表"
- 用户提到 Equipment、Condition、ClothesSet、Item、CommonExchange 等关联表的配置
- 用户说"碎片"、"合成"、"分解"、"道具配置"、"本地化文本"等配表相关术语
NBA2KOL2 时刻皮肤配表技能
本技能采用 checklist 逐步推进 模式。每个阶段有明确完成条件,必须全部 ✅ 后才能进入下一阶段。
核心规范:每收集完一个字段或完成一个步骤后,必须立即在回复中展示当前阶段的完整 checklist,用 [x] 标记已完成项,[ ] 标记未完成项,并附上已确认的值。 不得跳过 checklist 展示。
预置脚本说明
本 skill 目录下的 scripts/ 提供可直接调用的工具,不需要每次临时写代码 :
PlayerSkin 相关(阶段 1~5)
脚本 用途 调用方式 scripts/read_sheet_info.py读取 PlayerSkin 指定 sheet 的最大 ID 及末尾行 python <skill_dir>/scripts/read_sheet_info.py --sheet PicPanelscripts/write_skin_rows.py按依赖顺序向 PlayerSkin 各 sheet 写入新行 python <skill_dir>/scripts/write_skin_rows.py --data skin_data.jsonscripts/verify_skin_rows.py写入后读回验证,逐字段对比 python <skill_dir>/scripts/verify_skin_rows.py --data skin_data.json
全局状态读取
脚本 用途 调用方式 scripts/read_all_state.py一次性读取所有表格 (PlayerSkin/Equipment/Condition/ClothesSet/Item/CommonExchange/ID2StringMapTable)的最大 ID、号段末尾等关键状态,输出 JSONpython <skill_dir>/scripts/read_all_state.py --output state.json
⚠️ 必须在阶段 1 第1问之前调用 read_all_state.py ,一次获取所有推断 ID 所需的基础数据,后续阶段直接引用,减少重复读表。这是强制步骤,不可跳过。
列结构扫描(新增关联表规则时使用)
当需要为新表补充配表规则时,先运行 --dump-columns 扫描真实数据的所有非空列,避免遗漏"每行都一样的固定列":
python <skill_dir>/scripts/read_all_state.py --dump-columns
python <skill_dir>/scripts/read_all_state.py --dump-columns --output columns.json
输出每张表每个 sheet 的:列号、列名、非空率(%)、唯一值数量、前5个样本值。重点关注:
非空率 100% + 唯一值 1~3 → 大概率是必填固定值列,不可遗漏
非空率 > 90% + 唯一值较多 → 大概率是每行不同的业务字段
关联表写入(阶段 6~11)
脚本 用途 调用方式 scripts/write_equipment.pyEquipment 表(Equip_PlayerSkin + Equip_Clothes)+ 可选 Condition 表一次写入 python <skill_dir>/scripts/write_equipment.py --data equip_data.jsonscripts/write_clothesset.pyClothesSet 表追加一行 python <skill_dir>/scripts/write_clothesset.py --data clothesset_data.jsonscripts/write_id2string.pyID2StringMapTable LangShort 追加本地化文本行 python <skill_dir>/scripts/write_id2string.py --data id2string_data.jsonscripts/write_item.pyItem 表写入碎片/完整/服装行(支持 80XXX 中间插入 + 88XXX 末尾追加) python <skill_dir>/scripts/write_item.py --data item_data.jsonscripts/write_exchange.pyCommonExchange 合成/分解行写入 + Item 碎片 UseLinkID 回填 python <skill_dir>/scripts/write_exchange.py --data exchange_data.json
所有写入脚本均支持 --dry-run 预演模式,均内置格式继承、ID 占用校验、写入后验证。
<skill_dir> 为本技能目录:C:\Users\siminggao\.workbuddy\skills\nba2k-skin-moment-config
阶段 1:前置信息收集
进入条件 :用户发起配表请求
完成条件 :下方所有字段均已确认 ✅
重要原则:逐个发问,一次只用 AskUserQuestion 问一个问题,收到回答后再问下一个。 不要把多个问题合并成一次询问。
AskUserQuestion 交互规范:
推荐/默认选项文本末尾加 "- 默认值" 标识(如 队服(ClothesType = 0)- 默认值)
自由输入选项用 "直接在聊天框输入" 而非"自行输入"
checklist 展示规范:每收到一个回答后,立即展示如下格式的阶段1进度 checklist,然后再提问下一个问题。
### 阶段 1 进度
- [x] 球员系列: {值}(SeriesID={值})
- [x] 皮肤类型: {小时刻/大时刻}(仅陈列室/致敬传奇)
- [ ] Main ID
- [ ] 文件夹名
- [ ] 球员中文名及版本标签
- [ ] 时刻中文名
- [ ] IntroPanel ID
- [ ] VideoMarkID
- [ ] 可选功能模块
这些信息贯穿所有 sheet,是路径命名基础。按以下顺序逐一收集:
第1问:球员系列(AskUserQuestion 单选,按 SeriesID 升序排列)
陈列室时刻(SeriesID = 0)
致敬传奇时刻(SeriesID = 1)
历史球员时刻(SeriesID = 2)
现役球员时刻(SeriesID = 3)
皮肤类型三分类 :小时刻、大时刻、普通皮肤。
若系列为陈列室时刻或致敬传奇时刻,紧接着追加一问:皮肤类型 (单选:小时刻 / 大时刻)。小时刻当前与普通皮肤规则一致,大时刻为原特殊皮肤规则。
其他系列跳过此问,默认普通皮肤。
陈列室/致敬传奇连续配置流程 :选择陈列室或致敬传奇系列后,先完成小时刻 的阶段13全部字段收集,再完成大时刻 的阶段13全部字段收集,两个时刻数据一起在阶段4汇总确认,阶段5一次性写入。
第2问:Main ID
皮肤唯一主键,所有美术资产以此命名(如 70068)
若用户在请求中已提供,可跳过此问,直接在 checklist 中标记为 [x]
第3问:文件夹名
美术资产存放目录名(如 Julius_Erving)
第4问:球员中文名及版本标签
第5问:时刻中文名
用于 Main 备注字段(如 J博士、炉火纯青、致命封锁)
注意:使用"时刻中文名"而非"系列名"或"时刻名",避免歧义
第6问:IntroPanel ID 和 VideoMarkID
运行 read_sheet_info.py --sheet IntroPanel 和 --sheet VideoPanel 自动读取当前最大 ID,推断值为最大 ID+1
将推断值告知用户,允许用户自定义;若用户确认使用推断值,直接标记 [x]
第7问:可选功能模块(此问用多选)
是否有入场视频 (影响 PicPanel 的 VideoPic/VideoRes/PostionX/PostionY)
是否需要球衣页签 (需要 UniformPanel)
是否需要徽章视频 (需要 VideoPanel)
是否需要庆祝动作 (需要 CelebratePanel,见"⚠️ 尚未完整定义的关联表"处理流程)
注意:如果用户在初始请求中已经提供了部分信息,跳过对应的问题,直接在 checklist 中标记为 [x],不要重复询问已知信息。
阶段 1 全部完成后,展示完整的最终 checklist,并显示:
### 阶段 1 ✅ 全部完成
- [x] 球员系列: {值}(SeriesID={值})
- [x] 皮肤类型: {小时刻/大时刻}
- [x] Main ID: {值}
- [x] 文件夹名: {值}
- [x] 球员中文名及版本标签: {值}
- [x] 时刻中文名: {值}
- [x] IntroPanel ID: {值}
- [x] VideoMarkID: {值}(读取 VideoPanel 最大 ID +1,独立推断)
- [x] 可选功能模块: {列出所有已选模块}
阶段 2:依赖链确认
进入条件 :阶段 1 全部 ✅
完成条件 :依赖链结构已展示给用户,填写顺序已确认
根据阶段 1 的选择,生成本次的依赖链图示并展示给用户:
Main (ID={MainID})
├── IntroPanelID ──→ IntroPanel (ID={IntroPanelID})
│ ├── Option1 ──→ PicPanel 页签1(始终需要)
│ ├── Option2 ──→ PicPanel 页签2(始终需要)
│ ├── OptionN ──→ UniformPanel(如有球衣页签)
│ ├── OptionN ──→ VideoPanel(如有徽章视频)
│ └── OptionN ──→ CelebratePanel(如有庆祝动作)
└── VideoMarkID ──→ VideoPanel(ID={VideoMarkID})
展示依赖链图示后,立即展示阶段2 checklist 初始状态:
### 阶段 2 进度
- [x] 依赖链图示已展示
- [ ] UniformPanel 处理方式确认(如需)
- [ ] VideoPanel 处理方式确认(如需)
- [ ] CelebratePanel 处理方式确认(如需)
- [ ] 填写顺序确认
对于 UniformPanel / VideoPanel / CelebratePanel:
UniformPanel 和 VideoPanel 默认新增一行 ,无需用 AskUserQuestion 询问。仅当用户主动说要复用已有记录时才走已有 ID 流程。
CelebratePanel 需要询问是否有庆祝动作:选"无"则跳过;选"有"则查询该列 ID 最大值+1 推断新 ID。
每问完一个,立即更新 checklist。
本次填写顺序(从底层到顶层),展示时用实际启用的 sheet:
UniformPanel(如需,确认使用已有记录 or 新增)
PicPanel(始终需要,成对新增2行)
VideoPanel(如需,确认使用已有记录 or 新增)
CelebratePanel(如需,见"⚠️ 尚未完整定义的关联表"处理流程)
IntroPanel
Main
阶段 2 全部完成后,展示:
### 阶段 2 ✅ 全部完成
- [x] 依赖链图示已展示
- [x] UniformPanel: {新增一行 / 使用已有ID=XX}
- [x] VideoPanel: {新增一行 / 使用已有ID=XX}
- [x] 填写顺序已确认:UniformPanel → PicPanel → VideoPanel → IntroPanel → Main
阶段 3:各 Sheet 字段逐一确认
进入条件 :阶段 2 全部 ✅
完成条件 :所有需要填写的 sheet 的每一字段均已确认
字段类型标记:
[输入] 必须用 AskUserQuestion 逐个向用户询问,无论字段说明中是否给出了默认值或常见值,都不能自行决定,必须问用户确认
[推断] 根据规则推导,直接计算填入,无需发问(可在汇总时展示供用户核查)
[推断-ID] 需先运行 read_sheet_info.py 读取当前最大 ID,告知用户后用 AskUserQuestion 确认
[引用] 引用其他 sheet 主键,自动填入已确认的关联 ID,无需发问
[固定留空] 固定为空,无需发问
阶段3 checklist 展示规范:
进入每个 sheet 小节时,先展示该 sheet 的完整 checklist(全部 [ ])
每收集完一个 [输入] 字段,或确认完一批 [推断] 字段后,立即更新展示 checklist
该 sheet 所有字段确认完毕后,展示全部 [x] 的完成状态
3.1 UniformPanel(球衣面板)
仅在需要球衣页签且选择新增时填写
运行命令读取当前状态:
python <skill_dir>/scripts/read_sheet_info.py --sheet UniformPanel
进入本节时展示初始 checklist:
### 3.1 UniformPanel 进度
- [ ] ID [输入]
- [ ] ClothesType [输入]
- [ ] BkgRes [推断]
- [ ] DetailResHome [推断]
- [ ] DetailResAway [推断]
- [ ] IconLogo [推断]
- [ ] IconTitleBg [推断]
- [ ] HomeName [推断]
- [ ] AwayName [推断]
字段说明:
ID [输入] 明确输入,不强制连续
ClothesType [输入] 队服=0,休闲=其他值
BkgRes [推断] Skin\{文件夹名}\Jersey_Bkg.dds
DetailResHome [推断] Skin\{文件夹名}\Jersey_Home_{MainID}
DetailResAway [推断] Skin\{文件夹名}\Jersey_Away_{MainID}
IconLogo [推断] 固定 Icon\Jerseylogo_01_256.dds
IconTitleBg [推断] 固定 Skin\All_Skin\Tipstop_01.dds
HomeName [推断] 固定 400000001
AwayName [推断] 固定 400000002
收集完 ID 后,立即展示更新的 checklist(ID 变为 [x],推断字段一并填入并标 [x]):
### 3.1 UniformPanel 进度
- [x] ID: {值}
- [ ] ClothesType [输入]
- [x] BkgRes: Skin\{文件夹名}\Jersey_Bkg.dds(推断)
- [x] DetailResHome: Skin\{文件夹名}\Jersey_Home_{MainID}(推断)
- [x] DetailResAway: Skin\{文件夹名}\Jersey_Away_{MainID}(推断)
- [x] IconLogo: Icon\Jerseylogo_01_256.dds(推断)
- [x] IconTitleBg: Skin\All_Skin\Tipstop_01.dds(推断)
- [x] HomeName: 400000001(推断)
- [x] AwayName: 400000002(推断)
收集完所有字段后展示:
### 3.1 UniformPanel ✅ 完成
- [x] ID: {值}
- [x] ClothesType: {值}
- [x] BkgRes: {路径}(推断)
... (所有字段全部 [x])
3.2 PicPanel(图片面板)
始终需要,每次固定成对新增两行
运行命令读取当前最大 ID:
python <skill_dir>/scripts/read_sheet_info.py --sheet PicPanel
进入本节时展示初始 checklist:
### 3.2 PicPanel 进度
**行1(页签1 时刻介绍)**
- [ ] ID [推断-ID]
- [ ] 备注 [推断]
- [ ] BkgRes [推断]
- [ ] VideoPic [输入]
- [ ] VideoRes [输入]
- [ ] PostionX [输入]
- [ ] PostionY [输入]
**行2(页签2 卡面效果)**
- [ ] ID [推断-ID]
- [ ] 备注 [推断]
- [ ] BkgRes [推断]
- [ ] VideoPic/VideoRes/PostionX/PostionY [固定留空]
字段说明:
行1(页签1 时刻介绍):
ID [推断-ID] 读取后告知"当前最大 ID 为 X,推断新行为 X+1",允许用户自定义
备注 [推断] {球员中文名及版本} 页签1 时刻介绍
BkgRes [推断] Skin\{文件夹名}\L_Bkg_{MainID}_Intro.dds
VideoPic [推断+确认]
现役球员时刻:先用多选 AskUserQuestion 询问"是否需要配置以下可选项:入场视频封面(VideoPic)/ 入场视频(VideoRes)/ 视频坐标(PostionX/Y)",勾选的才填入,未勾选留空
其他系列且有入场视频:推断值为 Skin\{文件夹名}\Entrance_{MainID}.dds,与 VideoRes 合并为一题确认(见下);否则留空
VideoRes [推断+确认]
现役球员时刻:同上多选结果决定是否填入
其他系列且有入场视频:推断值为 Skin\{文件夹名}\V_Entrance_{MainID}.usm,与 VideoPic 合并为一题,用 AskUserQuestion 展示两个推断值,选项为"确认使用 - 默认值"和"直接在聊天框输入";否则留空
PostionX / PostionY [输入] VideoRes 不为空时(含现役勾选后),合并为一题"PostionX / PostionY",用 AskUserQuestion 提供选项:
陈列室时刻 / 致敬传奇时刻 → 140, 490 - 默认值
历史球员时刻 → 994, 509 - 默认值
直接在聊天框输入
VideoRes 为空时,PostionX/PostionY 均填 0
行2(页签2 卡面效果):
ID [推断-ID] 推断值为行1 ID+1,告知用户,允许自定义
备注 [推断] {球员中文名及版本} 页签2 卡面效果
BkgRes [推断] Skin\{文件夹名}\L_Bkg_{MainID}_Scene.dds
VideoPic / VideoRes / PostionX / PostionY [固定留空]
每收集完一个 [输入] 字段后立即更新 checklist。所有字段确认完毕后展示:
### 3.2 PicPanel ✅ 完成
**行1(页签1)**
- [x] ID: {值}
- [x] 备注: {值}(推断)
- [x] BkgRes: {路径}(推断)
- [x] VideoPic: {值}
- [x] VideoRes: {值}
- [x] PostionX: {值}
- [x] PostionY: {值}
**行2(页签2)**
- [x] ID: {值}
- [x] 备注: {值}(推断)
- [x] BkgRes: {路径}(推断)
- [x] VideoPic/VideoRes/PostionX/PostionY: 留空(固定)
3.3 VideoPanel(徽章视频面板)
仅在需要徽章视频且选择新增时填写;ID 与 Main.VideoMarkID 相同
运行命令读取当前状态:
python <skill_dir>/scripts/read_sheet_info.py --sheet VideoPanel
进入本节时展示初始 checklist:
### 3.3 VideoPanel 进度
- [ ] ID [输入]
- [ ] BadgeName [输入]
- [ ] BkgRes [推断]
- [ ] VideoRes [输入]
- [ ] 备注 [推断]
字段说明:
ID [输入] 与 Main.VideoMarkID 相同
BadgeName [输入] 用 AskUserQuestion 从已知枚举中选择(见下方列表)
BkgRes [推断] Skin\{文件夹名}\L_Bkg_{MainID}_Badge.dds
VideoRes [推断+确认] 规律:Skin\{文件夹名}\V_{版本缩写}{球员英文名}_Bdg_{徽章类型去掉Bdg_TC}_TC.usm
版本缩写推断规则 :从"球员中文名及版本标签"的括号中提取数字部分,如 (75版) → 75,(13版) → 13。最终路径示例:V_75Julius_Erving_Bdg_Slithery_TC.usm。推断后用 AskUserQuestion 确认,允许用户自定义。
备注 [推断] {时刻中文名} 页签N 徽章展示,其中 N 为该页签在 IntroPanel 中的序号(页签1=PicPanel介绍、页签2=PicPanel卡面,有球衣页签则+1,VideoPanel 徽章页签紧随其后);例:无球衣→页签3,有球衣→页签4
BadgeName 选项(AskUserQuestion):
已知枚举:Bdg_TCPowerDunk / Bdg_TCLimitlessTakeoff / Bdg_TCMismatchExpert / Bdg_TCFastTwitch / Bdg_TCRiseUp / Bdg_TCQuickRelease / Bdg_TCReboundChaser / Bdg_TCLightningBoost / Bdg_TCPosterizer / Bdg_TCLimitlessRange / Bdg_TCCornerSpecialist / Bdg_TCFastTwitchPro / Bdg_TCAgent3 / Bdg_TCPickDodger / Bdg_TCBackdownMaster / Bdg_TCLimitlessDunk / Bdg_TCSlithery / Bdg_TCGlove
末尾追加选项:"直接在聊天框输入" (允许用户输入枚举列表以外的新徽章名)
每收集完一个 [输入] 字段后立即更新 checklist。所有字段确认完毕后展示:
### 3.3 VideoPanel ✅ 完成
- [x] ID: {值}
- [x] BadgeName: {值}
- [x] BkgRes: {路径}(推断)
- [x] VideoRes: {值}
- [x] 备注: {值}(推断)
3.4 IntroPanel(出场面板)
进入本节时展示初始 checklist:
### 3.4 IntroPanel 进度
- [ ] ID [输入]
- [ ] 备注 [推断]
- [ ] IntroBKG [推断]
- [ ] TitleRes [推断]
- [ ] TitleDes [推断-确认]
- [ ] TipsDes [推断]
- [ ] Option1Type/ID/Des [推断+引用]
- [ ] Option2Type/ID/Des [推断+引用]
- [ ] Option3Type/ID/Des(如有)
- [ ] Option4Type/ID/Des(如有)
...
字段说明:
ID [输入] 与 Main.IntroPanelID 相同
备注 [推断] {球员中文名及版本}
IntroBKG [推断] Skin\{文件夹名}\Intro_R_Bkg.dds
TitleRes [推断] Skin\{文件夹名}\Title_{MainID}.dds
TitleDes [推断] 读取 IntroPanel 末尾行的 TitleDes 值,递增 2 得到本次值(规律:每行 +2,如上一行为 300603142 则本次为 300603144);告知用户推断值,允许自定义
TipsDes [推断] 固定为 TitleDes + 1,无需发问
Option1Type [推断] 固定 PLAYER_SKIN_INTRO_PANEL_PIC
Option1ID [引用] PicPanel 页签1 ID
Option1Des [推断] 固定 300604001
Option2Type [推断] 固定 PLAYER_SKIN_INTRO_PANEL_PIC
Option2ID [引用] PicPanel 页签2 ID
Option2Des [推断] 固定 300605001
Option3~6 Type/ID/Des:如有额外页签,逐个 用 AskUserQuestion 询问,每个 Option 单独问(类型选择 + 对应 ID),不要合并
Des 推断规则:UNIFORM→300608001,VIDEO→300606001,CELEBRATE→300609001
Option Type 枚举:
PLAYER_SKIN_INTRO_PANEL_UNIFORM → 引用 UniformPanel
PLAYER_SKIN_INTRO_PANEL_VIDEO → 引用 VideoPanel
PLAYER_SKIN_INTRO_PANEL_CELEBRATE → 引用 CelebratePanel(见"⚠️ 尚未完整定义的关联表"处理流程)
每收集完一个 [输入] 字段后立即更新 checklist。所有字段确认完毕后展示:
### 3.4 IntroPanel ✅ 完成
- [x] ID: {值}
- [x] 备注: {值}(推断)
- [x] IntroBKG: {路径}(推断)
- [x] TitleRes: {路径}(推断)
- [x] TitleDes: {值}
- [x] TipsDes: {值}
- [x] Option1: PIC / {ID} / 300604001(推断+引用)
- [x] Option2: PIC / {ID} / 300605001(推断+引用)
- [x] Option3: {类型} / {ID} / {Des}
...
3.5 Main sheet(皮肤主表)
进入本节时展示初始 checklist:
### 3.5 Main 进度
- [ ] ID [已知]
- [ ] 备注 [推断]
- [ ] PlayerTemplate [输入]
- [ ] PlayerName [推断]
- [ ] 备注.1 [推断]
- [ ] SeriesID [引用]
- [ ] SkinIcon [推断]
- [ ] SkinRectImage [推断]
- [ ] UserInfoPanelID [推断]
- [ ] Avatar [推断]
- [ ] PlayerImage [推断]
- [ ] Signature [推断]
- [ ] SignatureVideo [推断]
- [ ] CardTypeIcon [推断]
- [ ] IngameFootNote [推断]
- [ ] ScoreAnimationSetID [推断]
- [ ] IntroPanelID [引用]
- [ ] VideoMarkID [引用]
- [ ] SerialRuleID [推断]
- [ ] MergeAnimationVideo [推断]
- [ ] MergeAnimationAdjustColorBrightness [推断]
- [ ] MergeAnimationAdjustColorSaturation [推断]
- [ ] MergeAnimationAdjustColorHue [推断]
- [ ] MergeAnimationPlayerPicture [推断]
- [ ] MergeAnimationTextPicture [推断]
- [ ] ColorBar [推断]
- [ ] SessionLoadingColorType [推断]
- [ ] SessionLoadingColor [推断]
- [ ] ClothItemID [推断]
- [ ] MiscAnimationSetID [输入]
字段说明:
ID [已知] 前置输入
备注 [推断] {时刻中文名} {球员中文名及版本}
PlayerTemplate [输入] 球员模板 ID。收集后需校验 :如果该 PlayerTemplate 在 Main 中已有其他皮肤记录(排除本次正在配置的),需要向用户问询确认是否正确,避免输入错误导致关联配置全错。
PlayerName [推断] 同一 PlayerTemplate 的所有皮肤共用同一个 PlayerName ID。若该 PlayerTemplate 已有皮肤记录,复用已有 PlayerName;若为首次,读取 Main 末尾行的 PlayerName 值 +1 推断。大时刻复用小时刻的 PlayerName,不再额外 +1。
备注.1 [推断] {球员中文名及版本}
SeriesID [引用] 阶段1已确认:陈列室时刻=0,致敬传奇时刻=1,历史球员时刻=2,现役球员时刻=3
SkinIcon [推断] Skin\{文件夹名}\head_{MainID}.dds
SkinRectImage [推断] Skin\{文件夹名}\changingroom_{MainID}.dds
UserInfoPanelID [推断]
Avatar [推断] 同 SkinIcon
PlayerImage [推断] Skin\{文件夹名}\skin{MainID}.dds(注意:无下划线)
Signature [推断]
小时刻 / 普通皮肤:留空,无需询问
大时刻:自动推断路径 Skin\{文件夹名}\Signature_{MainID}.dds,无需询问
SignatureVideo [推断]
小时刻 / 普通皮肤:留空
大时刻:自动推断路径 Skin\{文件夹名}\V_Signature_{MainID}.usm
CardTypeIcon [推断]
小时刻 / 普通皮肤:留空
大时刻:自动推断 {球员英文名}Skin(英文名无空格无下划线,如 KawhiLeonardSkin),从文件夹名去掉下划线推断
IngameFootNote [推断] 根据系列和皮肤类型自动填入,无需询问:
陈列室大时刻 → GAMELIBRARY_ROSTER_PLAYERDATA_ABILITY_ICON_TC_DESIGNED
致敬传奇大时刻 → GAMELIBRARY_ROSTER_PLAYERDATA_ABILITY_ICON_TC_DESIGNED_LEGEND
其他所有情况(小时刻、普通皮肤)→ 0
ScoreAnimationSetID [推断] 固定 0
IntroPanelID [引用] IntroPanel 主键
VideoMarkID [引用] VideoPanel 主键
SerialRuleID [推断] 根据系列和皮肤类型自动推断,无需询问:
致敬传奇时刻(所有)→ 0(无贴纸)
陈列室大时刻 → 读取 Main sheet SerialRuleID 列当前非零最大值 +1
其他(小时刻、普通皮肤)→ 0
MergeAnimationVideo [推断] 固定 Skin\All_Skin\V_General_Merge_02.usm
MergeAnimationAdjustColorBrightness [推断] 固定 0
MergeAnimationAdjustColorSaturation [推断] 根据皮肤类型自动填入,无需发问:
特殊皮肤(陈列室/致敬传奇中被用户标记为大时刻)→ 0
普通皮肤(其他系列,或陈列室/致敬传奇中未标记)→ -100
MergeAnimationAdjustColorHue [推断] 根据皮肤类型自动填入,无需发问:
皮肤类型判断 :当系列为陈列室时刻或致敬传奇时刻时,阶段1已收集皮肤类型(小时刻/大时刻),直接引用。其他系列默认为普通皮肤。
大时刻自动复用规则 (陈列室/致敬传奇连续配置时):大时刻以下字段与小时刻一致,自动复用无需询问:
文件夹名、球员中文名及版本标签、PlayerTemplate、可选功能模块
大时刻自动递推规则 :
Main ID = 小时刻 Main ID + 1
IntroPanel ID = 小时刻 IntroPanel ID + 1
VideoMarkID = 小时刻 VideoMarkID + 1
UniformPanel ID = 小时刻 UniformPanel ID + 1
PicPanel ID = 小时刻 PicPanel 最后一个 ID + 1(连续)
PlayerName = 复用小时刻的 PlayerName(同模板共用)
TitleDes = 小时刻 TitleDes + 2
ClothItemID = 小时刻 ClothItemID + 1
大时刻需要单独询问的差异字段 :
MergeAnimationPlayerPicture [推断] 同 PlayerImage
MergeAnimationTextPicture [推断] Skin\{文件夹名}\textskin_{MainID}.dds
ColorBar [推断] 根据系列和皮肤类型自动填入,无需发问:
陈列室时刻 + 大时刻(特殊)→ 2
陈列室时刻 + 普通 → 1
致敬传奇时刻 + 大时刻(特殊)→ 20
致敬传奇时刻 + 普通 → 1
历史球员时刻 / 现役球员时刻 → 1
SessionLoadingColorType [推断] 根据系列自动推断,无需询问:
陈列室/致敬传奇 → SESSION_LOADING_COLOR_TYPE_SKIN_COLOR(固定)
历史/现役 → 需询问(SKIN_COLOR 或 TEAM_COLOR)
SessionLoadingColor [推断] 根据系列和皮肤类型自动推断,无需询问:
陈列室/致敬传奇 小时刻 → 14277081
陈列室 大时刻 → 16770194
致敬传奇 大时刻 → 15378318
历史/现役 → 需询问(TEAM_COLOR 时通常 0,SKIN_COLOR 时为 ARGB 整数值)
ClothItemID [推断] 读取 Main sheet ClothItemID 列当前最大值 +1,自动推断无需询问
MiscAnimationSetID [输入] 用 AskUserQuestion 询问"本次是否有庆祝动作?",选项A为"留空(不使用)- 无庆祝动作 - 默认值",选项B为"有庆祝动作"。选B则读取该列当前非零最大值 +1 自动推断
每收集完一个 [输入] 字段后立即更新 checklist。推断字段可在首次问答后批量标注为 [x]。
所有字段确认完毕后展示:
### 3.5 Main ✅ 完成
- [x] ID: {值}
- [x] 备注: {值}(推断)
... (全部 [x])
阶段 3 全部完成后展示:
### 阶段 3 ✅ 全部完成
- [x] 3.1 UniformPanel(9字段)
- [x] 3.2 PicPanel(行1×7字段 + 行2×3字段)
- [x] 3.3 VideoPanel(5字段)
- [x] 3.4 IntroPanel(N字段)
- [x] 3.5 Main(30字段)
阶段 4:汇总确认
进入条件 :阶段 3 全部 ✅
完成条件 :用户确认汇总表无误
将所有 sheet 的完整数据以表格形式展示给用户:
=== 本次写入数据汇总 ===
[UniformPanel] (如有)
ID: ...
ClothesType: ...
...
[PicPanel - 行1(页签1)]
ID: ...
备注: ...
...
[PicPanel - 行2(页签2)]
ID: ...
...
[VideoPanel] (如有)
...
[IntroPanel]
...
[Main]
ID: ...
...
询问用户:以上数据是否确认无误?确认后将写入 PlayerSkin.xlsx。
阶段 4 完成标志:用户明确回复"确认"或"开始写入"。
阶段 5:写入 Excel
进入条件 :阶段 4 用户确认 ✅
完成条件 :所有 sheet 写入成功,验证通过
进入阶段5时展示初始 checklist:
### 阶段 5 进度
- [ ] 5.1 文件锁定检查
- [ ] 5.2 生成 skin_data.json
- [ ] 5.3 dry-run 预演
- [ ] 5.4 实际写入
- [ ] 5.5 验证写入结果
- [ ] 5.6 清理临时文件
每完成一个步骤后立即更新 checklist,例如:
### 阶段 5 进度
- [x] 5.1 文件锁定检查:未锁定 ✅
- [x] 5.2 生成 skin_data.json ✅
- [ ] 5.3 dry-run 预演
- [ ] 5.4 实际写入
- [ ] 5.5 验证写入结果
- [ ] 5.6 清理临时文件
步骤 5.1:检查文件锁定
ls "F:/OL2wc/NBA2KOL2Doc_proj/~\$PlayerSkin.xlsx" 2>/dev/null && echo "文件被锁定,请先关闭Excel" || echo "文件未锁定,可以写入"
若有锁定文件,停止并提示用户关闭 Excel。完成后更新 checklist,5.1 标为 [x]。
步骤 5.2:生成 skin_data.json
将阶段 3 确认的所有字段组装为 JSON 文件,写入当前工作目录下的 skin_data.json。该文件为临时文件,步骤 5.6 完成后需删除。
列号为字符串键,空值字段不填:
{
"PicPanel" : [
{ "1" : 142 , "2" : "..." , "3" : "..." , "6" : 994 , "7" : 509 } ,
{ "1" : 143 , "2" : "..." , "3" : "..." }
] ,
"VideoPanel" : [
{ "1" : 68 , "2" : "Bdg_TCSlithery" , "3" : "..." , "4" : "..." }
] ,
"IntroPanel" : [
{ "1" : 68 , "2" : "..." , ...}
] ,
"Main" : [
{ "1" : 70068 , "2" : "..." , ...}
]
}
注意:
列号从 1 开始(对应 Excel 列 A=1, B=2...)
空值字段不填入 JSON(脚本会跳过)
数字值写数字,不要写成字符串
生成后更新 checklist,5.2 标为 [x]。
步骤 5.3:预演确认(dry-run)
python <skill_dir>/scripts/write_skin_rows.py --data skin_data.json --dry-run
确认输出无误后,执行实际写入。完成后更新 checklist,5.3 标为 [x]。
步骤 5.4:执行写入
python <skill_dir>/scripts/write_skin_rows.py --data skin_data.json
脚本会:
检测锁定文件(~$PlayerSkin.xlsx),有则中止
按依赖顺序逐 sheet 写入(UniformPanel → PicPanel → VideoPanel → IntroPanel → Main)
写入前验证 ID 是否已存在(防重复)
逐列写入,空值字段跳过
写入后读回验证 ID
保存并关闭(finally 块保证执行)
写入成功后更新 checklist,5.4 标为 [x]。
步骤 5.5:验证写入结果并输出改动清单
写入成功后,必须 运行验证脚本,对本次所有改动逐行逐列读回核对:
python <skill_dir>/scripts/verify_skin_rows.py --data skin_data.json
脚本会:
按 ID 在每个 sheet 中查找对应行
逐列对比期望值与 Excel 实际值
输出每个字段的 ✓/✗ 状态
在末尾打印完整改动清单汇总及整体 PASS/FAIL 结论
验证报告示例:
=== PlayerSkin 写入验证 ===
============================================================
Sheet: PicPanel
============================================================
✓ ID=142 行验证通过:
✓ 列1(A): 142
✓ 列2(B): '朱利叶斯.欧文(75版) 页签1 时刻介绍'
✓ 列3(C): 'Skin\\Julius_Erving\\L_Bkg_70068_Intro.dds'
...
改动清单汇总(共 XX 个字段)
[PicPanel]
ID=142:
✓ 列1(A): 142
✓ 列2(B): '朱利叶斯.欧文(75版) 页签1 时刻介绍'
...
[Main]
ID=70068:
✓ 列1(A): 70068
...
✓ 验证通过:全部 XX 个字段已正确写入 Excel
若出现 ✗ 字段,说明写入有误,需要排查后重新写入。
将验证报告的改动清单完整展示给用户,作为本次配表的最终确认。
验证完成后更新 checklist,5.5 标为 [x],附注验证结果(如"69/72字段通过")。
步骤 5.6:清理临时文件
验证通过后,删除本次 skill 执行过程中产生的所有临时文件:
rm -f skin_data.json tmp_*.json tmp_*.py
清理完成后展示阶段5最终 checklist:
### 阶段 5 ✅ 全部完成
- [x] 5.1 文件锁定检查:未锁定
- [x] 5.2 skin_data.json 已生成
- [x] 5.3 dry-run 预演:通过
- [x] 5.4 实际写入:成功(UniformPanel/PicPanel/VideoPanel/IntroPanel/Main)
- [x] 5.5 验证:{N}/{总} 字段通过
- [x] 5.6 临时文件已清理
路径命名速查
资产用途 路径规律 皮肤头像 / Avatar Skin\{文件夹名}\head_{MainID}.dds换衣间图 Skin\{文件夹名}\changingroom_{MainID}.dds球员全身图 Skin\{文件夹名}\skin{MainID}.dds(无下划线)合卡文字图 Skin\{文件夹名}\textskin_{MainID}.dds出场背景 Skin\{文件夹名}\Intro_R_Bkg.dds标题图 Skin\{文件夹名}\Title_{MainID}.dds页签1背景 Skin\{文件夹名}\L_Bkg_{MainID}_Intro.dds页签2背景 Skin\{文件夹名}\L_Bkg_{MainID}_Scene.dds徽章背景 Skin\{文件夹名}\L_Bkg_{MainID}_Badge.dds入场视频封面 Skin\{文件夹名}\Entrance_{MainID}.dds入场视频 Skin\{文件夹名}\V_Entrance_{MainID}.usm徽章视频 Skin\{文件夹名}\V_{版本缩写}{球员英文名}_Bdg_{徽章类型}_TC.usm(版本缩写=版本标签括号内数字,如75版→75)球衣背景 Skin\{文件夹名}\Jersey_Bkg.dds主场球衣 Skin\{文件夹名}\Jersey_Home_{MainID}(无扩展名)客场球衣 Skin\{文件夹名}\Jersey_Away_{MainID}(无扩展名)
⚠️ 尚未完整定义的关联表(待补充)
遇到以下场景时,必须明确告知用户 规则尚未录入,并按以下方式处理:
关联表 触发场景 处理方式 PlayerSkin.xlsx CelebratePanel sheet用户选择了庆祝动作(MiscAnimationSetID 非空) 询问用户提供 CelebratePanel 的字段值(ID、各列内容),手工记录后写入 skin_data.json 的 "CelebratePanel" 键下,write_skin_rows.py 已支持该 sheet 写入 SerialRule.xlsx Main sheet陈列室大时刻 SerialRuleID ≠ 0 提示用户需手动在 SerialRule.xlsx 中新增对应的贴纸规则行,skill 不负责该表写入
CelebratePanel 字段收集模板 (用于询问用户):
CelebratePanel 规则尚未录入本技能,需要您手动提供以下字段:
- ID:(推断值为 CelebratePanel 当前最大 ID +1 = {值})
- 各列内容:请参考已有行的格式填写
如您提供字段值,我会一并写入 PlayerSkin.xlsx。如暂时不配置,可跳过此项,后续手动补充。
通用 Excel 写入安全规范
1. 写N行 = 先插N个空行
在表格中间插入多行数据时,必须先在同一位置连续插入N个空行 :
insert_pos = max_row + 1
for _ in range (N):
sheet.range (f'A{insert_pos} ' ).api.EntireRow.Insert()
assert int (sheet.range (insert_pos + N, 1 ).value) == expected_next_id
2. 格式继承
写入数据前,先从上一行复制整行格式:
sheet.range (f'{prev_row} :{prev_row} ' ).api.Copy()
sheet.range (f'{first_new_row} :{last_new_row} ' ).api.PasteSpecial(Paste=-4122 )
app.api.CutCopyMode = False
3. 路径字符串
Python 中用单转义:'Skin\\Kawhi_Leonard\\PSP70071'
不要双转义:'Skin\\\\Kawhi_Leonard\\\\'
Icon 路径统一不带 .dds 后缀(CommonExchange、Item 表均适用)
4. 插入后行号偏移
插入行后,后续操作必须重新扫描 获取最新行号,不得使用插入前缓存的行号。
5. 写入后必须验证
逐单元格读回对比
验证上下文完整性(上方/下方原数据未被覆盖)
验证相邻列未被污染
6. 错误恢复策略
写入失败或验证不通过时,按以下顺序处理:
立即停止 :不要继续后续阶段,避免错上加错
诊断原因 :读取当前 Excel 状态,确认是部分写入还是完全失败
用户确认 :将错误详情展示给用户,等待用户指示
恢复方式 (按场景):
ID 重复 / 已存在 :说明该 ID 已被占用,建议用户检查是否为之前配置的残留,确认后跳过或分配新 ID
验证不通过(部分字段错误) :如果用户要求回滚重配,需先手动删除已写入的行(告知用户行号),然后从阶段4开始重新走流程;不要尝试局部修正
文件锁定 :提示用户关闭 Excel,然后从当前步骤重试
脚本报错(Python 异常) :xlwings 的 finally 块会保证 app.quit(),Excel 进程不会残留;检查错误信息后重试
SVN 安全网 :提醒用户重要操作前先 SVN commit,写入失败时可通过 SVN revert 恢复
阶段 6~11:关联表配置
进入阶段 6 时,必须先读取详细规则文件:
read_file: <skill_dir>/references/stages-6-11.md
该文件包含 Equipment / Condition / ClothesSet / ID2StringMapTable / Item / CommonExchange 六张表的完整字段规则、JSON 示例和操作流程。
以下为各阶段摘要(详细规则见 references/stages-6-11.md):
阶段 表格 操作 脚本 6+7 Equipment + Condition 新增 Equip_PlayerSkin(70XXX)+ Equip_Clothes(88XXX)两行;首次配置时同步新增 Condition write_equipment.py8 ClothesSet 新增1行(88XXX),需收集 HomeUniformID/AwayUniformID write_clothesset.py9 ID2StringMapTable 追加 PlayerName/TitleDes/TipsDes 本地化文本 write_id2string.py10 Item 碎片×2+完整×2+服装×2,80XXX 中间插入 + 88XXX 末尾追加 write_item.py11 CommonExchange 合成+分解行(<10000号段),写完后回填 Item 碎片 UseLinkID write_exchange.py
所有写入脚本均支持 --dry-run,均内置锁定检查、格式继承、ID 占用校验、写入后验证。