Files
docxmaker/wenzijiaoben/py/generate_doc.py
2026-06-08 10:49:52 +08:00

569 lines
24 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
生成《不朽封仙》游戏文字脚本文档
"""
import csv
import os
import glob
from docx import Document
from docx.shared import Pt, Cm, Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn
# ============ 路径配置 ============
CSV_DIR = r"d:\p-L12\work\cvs"
GAME_DIR = r"d:\p-L12\P-L12_game\unity\Assets\Resources\Resources_moved\gui\atlas_ui"
ICON_DIRS = {
"product": os.path.join(GAME_DIR, "atlas_product_icons"),
"skill": os.path.join(GAME_DIR, "atlas_skill"),
"rune": os.path.join(GAME_DIR, "atlas_rune_icons"),
"talent": os.path.join(GAME_DIR, "atlas_talent_icons"),
"equip": os.path.join(GAME_DIR, "atlas_equip_icons"),
}
OUTPUT_PATH = r"d:\p-L12\work\《不朽封仙》游戏文字脚本.docx"
# ============ 辅助函数 ============
def read_csv(filename):
"""读取CSV文件跳过前3行中文头、类型头、英文头返回数据行"""
path = os.path.join(CSV_DIR, filename)
# 尝试多种编码
for encoding in ["utf-8-sig", "gbk", "gb2312", "utf-8"]:
try:
with open(path, "r", encoding=encoding) as f:
reader = csv.reader(f)
rows = list(reader)
return rows[3:] # skip header rows
except (UnicodeDecodeError, UnicodeError):
continue
raise ValueError(f"无法读取文件 {filename},尝试了所有编码")
def find_image(icon_name, icon_dir_key):
"""根据icon名称查找图片文件路径返回完整路径或None"""
icon_dir = ICON_DIRS.get(icon_dir_key)
if not icon_dir or not os.path.isdir(icon_dir):
return None
# 尝试直接匹配
for ext in [".png", ".jpg"]:
p = os.path.join(icon_dir, icon_name + ext)
if os.path.isfile(p):
return p
# 尝试补零匹配(如 icon_product_1 -> icon_product_01
import re
m = re.match(r"^(.+?)(\d+)$", icon_name)
if m:
prefix, num = m.group(1), m.group(2)
for pad in [2, 3]:
padded = prefix + num.zfill(pad)
for ext in [".png", ".jpg"]:
p = os.path.join(icon_dir, padded + ext)
if os.path.isfile(p):
return p
return None
def add_image_to_cell(cell, image_path, height_cm=3):
"""在表格单元格中插入图片,锁定纵横比,设置高度"""
paragraph = cell.paragraphs[0]
paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = paragraph.add_run()
run.add_picture(image_path, height=Cm(height_cm))
def set_cell_text(cell, text):
"""设置单元格文本"""
cell.text = ""
paragraph = cell.paragraphs[0]
paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = paragraph.add_run(str(text))
run.font.size = Pt(10)
def add_table_with_icons(doc, headers, rows_data, icon_dir_key):
"""添加带图标的表格"""
table = doc.add_table(rows=1, cols=len(headers), style="Table Grid")
table.alignment = WD_TABLE_ALIGNMENT.CENTER
# 设置表头
for i, header in enumerate(headers):
cell = table.rows[0].cells[i]
cell.text = header
for paragraph in cell.paragraphs:
paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
for run in paragraph.runs:
run.font.bold = True
run.font.size = Pt(10)
# 添加数据行
for row_data in rows_data:
row = table.add_row()
name, icon_name, desc = row_data[0], row_data[1], row_data[2] if len(row_data) > 2 else ""
set_cell_text(row.cells[0], name)
# 图标列
img_path = find_image(icon_name, icon_dir_key) if icon_name else None
if img_path:
add_image_to_cell(row.cells[1], img_path)
else:
set_cell_text(row.cells[1], "")
# 描述列
if desc:
set_cell_text(row.cells[2], desc)
def add_table_equip(doc, headers, rows_data, icon_dir_key):
"""添加装备表格(只有名称和图标两列)"""
table = doc.add_table(rows=1, cols=len(headers), style="Table Grid")
table.alignment = WD_TABLE_ALIGNMENT.CENTER
for i, header in enumerate(headers):
cell = table.rows[0].cells[i]
cell.text = header
for paragraph in cell.paragraphs:
paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
for run in paragraph.runs:
run.font.bold = True
run.font.size = Pt(10)
for row_data in rows_data:
row = table.add_row()
name, icon_name = row_data[0], row_data[1]
set_cell_text(row.cells[0], name)
img_path = find_image(icon_name, icon_dir_key) if icon_name else None
if img_path:
add_image_to_cell(row.cells[1], img_path)
else:
set_cell_text(row.cells[1], "")
# ============ 数据准备 ============
def get_system_prompts():
"""获取被引用的GameTextConst系统提示"""
# 所有GameTextConst常量及其文本值
all_consts = {
"ErrorTaskFailed": "领取失败。",
"ErrorBuyFailed": "购买失败。",
"ErrorUseFailed": "使用失败。",
"ErrorTakesuccess": "领取成功。",
"ErrorStrengthLimit": "强化已达上限。",
"ErrorChallengeTimesNotEnough": "今日挑战次数不足。",
"ErrorRecruitTimesNotEnough": "今日可招募次数不足。",
"ErrorRecruitTicketNotEnough": "召唤道具与月灵玉璧不足。",
"ErrorRecruitDiamondNotEnough": "星棱幻晶不足,无法进行招募。",
"ErrorUpStageFirst": "请先升阶。",
"ErrorUpStage1First": "请先升品。",
"ErrorUpLevelFirst": "请先升级。",
"ErrorUpStarFirst": "请先升星。",
"ErrorUpStrengthFirst": "请先强化。",
"ErrorLevelNotExist": "关卡不存在。",
"ErrorInvalidGuideId": "无效的引导。",
"ErrorItemNotEnough": "道具不足。",
"ErrorRewardAlreadyClaimed": "您已领奖。",
"ErrorNotSettlementTime": "未到结算时间。",
"ErrorNoReward": "暂无奖励。",
"ErrorHeroStarUpSuccess": "升星成功。",
"ErrorTujianProgressNotEnough": "图鉴进度未达到领取条件。",
"ErrorUpLevelSuccess": "升级成功。",
"ErrorUpStageSuccess": "升阶成功。",
"ErrorGuildSetSuccess": "设置公会成功。",
"ErrorNoPackagePurchased": "未购买礼包。",
"ErrorNotMeetClaimCondition": "暂未达到领取条件。",
"ErrorNameNotAvailable": "含有敏感字符,无法使用该名字。",
"ErrorNameOnlyChinese": "昵称只能包含中文。",
"ErrorPleaseInputName": "请输入昵称。",
"ErrorSetSuccess": "修改成功。",
"ErrorCurrencyNotEnough": "货币不足。",
"ErrorHeroMaxCountReached": "伙伴达到最大人数。",
"ErrorNoHeroToCombine": "没有可合成的伙伴。",
"ErrorJoinSuccess": "加入成功。",
"ErrorApplySuccess": "申请成功。",
"ErrorEnergyNotEnough": "体力不足。",
"ErrorBuySuccess": "购买成功。",
"ErrorQuitGuildSuccess": "退出公会成功。",
"ErrorGuildNameEmpty": "公会名称不能为空。",
"ErrorGuildNameTooLong": "公会名称不能超过6个字符。",
"ErrorCreateGuildSuccess": "创建公会成功。",
"ErrorMaterialNotEnough": "材料不足。",
"ErrorEquipStrengthSuccess": "装备强化成功。",
"ErrorEquipBreakthroughSuccess": "装备升品成功。",
"ErrorStrengthSuccess": "强化成功。",
"ErrorDiamondNotEnough": "星棱幻晶不足。",
"ErrorQuickSweepTimesNotEnough": "快速游历次数不足。",
"ErrorCopySuccess": "复制成功。",
"ErrorReceiveConditionNotMet": "未达成领取条件。",
"ErrorAlreadyClaimed": "已领取。",
"ErrorItemDailyUseTimesReached": "该道具今日使用次数已达上限。",
"ErrorConditionNotMet": "条件不足。",
"ErrorVipLevelNotEnough": "权益等级不足。",
"ErrorLevelNotEnough": "等级不足。",
"ErrorScoreNotEnough": "积分不足。",
"ErrorPassNotOpen": "关卡未开放。",
"ErrorPreyFailed": "祈愿失败。",
"ErrorInvalidId": "无效的ID。",
"ErrorSaveSuccess": "保存成功。",
"ErrorSaveFailed": "保存失败。",
"ErrorNoHeroCarry": "无上阵伙伴。",
"ErrorNoHeroInTeam": "至少上阵一名修士。",
"ErrorNoFreePos": "人数已达上限。",
"ErrorRefreshTimesNotEnough": "刷新次数不足。",
"ErrorTimesNotEnough": "次数不足。",
"ErrorHeroLevelUnlock": "修士{0}级解锁。",
"TipChallengeTimesConfirm": "\u3000是否消耗{0}进行挑战。\n\u3000今日剩余(<color=#19F45C>{1}</color>/{2})次。",
"ErrorFusionRuneCountNotEnough": "合成铭文所需数量不足。",
"TipFusionSuccess": "合成成功。",
"ErrorFusionRuneRarityNotSame": "合成铭文必须是相同稀有度。",
"ErrorFusionRuneCountMax": "合成铭文所需数量已达上限。",
"ErrorFusionRuneNotFusion": "该铭文不能合成。",
"ErrorRunePutOnSuccess": "镶嵌成功。",
"ErrorTitleNotUnlock": "称号未解锁。",
"ErrorHeroNotUnlock": "该伙伴尚未获得,需前往旅人驿站招募哦。",
"ErrorRuneSlotFull": "铭文槽已满,请先卸下。",
"ErrorPushBoxLock": "通过{0}后解锁。",
"ErrorFriendApplySuccess": "已同意成为好友。",
"ErrorFriendApplyRefuse": "已拒绝成为好友。",
"ErrorFriendAddOrNotExist": "玩家已添加或不存在。",
"ErrorBagFull": "背包已满。",
"ErrorTargetNotEnough": "{0}不足。",
"ErrorPassNotUnlock": "通关后解锁。",
"ErrorSaveHostage": "解救{0}个人质后解锁。",
"ErrorSomethingNotEnough": "{0}不足。",
"ErrorRetreatNotNow": "现在还不能撤离。",
"ErrorNotUnlock": "未解锁。",
"ErrorSendGiftSuccess": "赠送成功",
"ErrorCollectionUnlock": "请在关卡中拾取藏品解锁。",
"ErrorTaskNotFinish": "任务未完成。",
"ErrorTaskRewardNotClaimed": "任务奖励未领取。",
"ErrorNotNewApply": "暂无新的好友申请。",
"ErrorNotPassBigBox": "请通关当前所有关卡后领取。",
"ErrorNotPassBigBoxStar": "满星通过前置关卡后解锁。",
"ErrorBreakthroughSuccess": "突破成功。",
"ErrorLearnSuccess": "学习成功。",
}
# 被引用的常量(排除只在注释中引用的)
referenced = {
"ErrorAlreadyClaimed", "ErrorApplySuccess", "ErrorBagFull",
"ErrorBreakthroughSuccess", "ErrorBuyFailed", "ErrorBuySuccess",
"ErrorChallengeTimesNotEnough", "ErrorCollectionUnlock",
"ErrorConditionNotMet", "ErrorCopySuccess", "ErrorCreateGuildSuccess",
"ErrorCurrencyNotEnough", "ErrorDiamondNotEnough", "ErrorEnergyNotEnough",
"ErrorEquipBreakthroughSuccess", "ErrorEquipStrengthSuccess",
"ErrorFriendAddOrNotExist", "ErrorFriendApplyRefuse",
"ErrorFriendApplySuccess", "ErrorFusionRuneCountMax",
"ErrorFusionRuneCountNotEnough", "ErrorFusionRuneNotFusion",
"ErrorFusionRuneRarityNotSame", "ErrorGuildNameEmpty",
"ErrorGuildNameTooLong", "ErrorGuildSetSuccess", "ErrorHeroLevelUnlock",
"ErrorHeroNotUnlock", "ErrorHeroStarUpSuccess", "ErrorInvalidGuideId",
"ErrorItemDailyUseTimesReached", "ErrorItemNotEnough",
"ErrorJoinSuccess", "ErrorLearnSuccess", "ErrorLevelNotEnough",
"ErrorLevelNotExist", "ErrorMaterialNotEnough", "ErrorNameNotAvailable",
"ErrorNameOnlyChinese", "ErrorNoFreePos", "ErrorNoHeroCarry",
"ErrorNoHeroInTeam", "ErrorNoPackagePurchased", "ErrorNoReward",
"ErrorNotMeetClaimCondition", "ErrorNotNewApply", "ErrorNotPassBigBox",
"ErrorNotPassBigBoxStar", "ErrorNotSettlementTime", "ErrorNotUnlock",
"ErrorPassNotOpen", "ErrorPassNotUnlock", "ErrorPleaseInputName",
"ErrorPreyFailed", "ErrorPushBoxLock", "ErrorQuickSweepTimesNotEnough",
"ErrorQuitGuildSuccess", "ErrorRefreshTimesNotEnough",
"ErrorRetreatNotNow", "ErrorRewardAlreadyClaimed",
"ErrorRunePutOnSuccess", "ErrorRuneSlotFull", "ErrorSaveHostage",
"ErrorSaveSuccess", "ErrorScoreNotEnough", "ErrorSendGiftSuccess",
"ErrorSetSuccess", "ErrorSomethingNotEnough", "ErrorTakesuccess",
"ErrorTargetNotEnough", "ErrorTaskFailed", "ErrorTaskNotFinish",
"ErrorTaskRewardNotClaimed", "ErrorTimesNotEnough",
"ErrorTitleNotUnlock", "ErrorUpLevelFirst", "ErrorUpLevelSuccess",
"ErrorUpStage1First", "ErrorUpStageFirst", "ErrorUpStageSuccess",
"ErrorUpStrengthFirst", "ErrorVipLevelNotEnough",
"TipChallengeTimesConfirm", "TipFusionSuccess",
}
# 只保留被引用的,去重文本值
seen_texts = set()
result = []
for name, text in all_consts.items():
if name in referenced and text not in seen_texts:
seen_texts.add(text)
result.append(text)
return result
def get_quest_texts():
"""获取任务文本category 1和2的desc字段去重"""
rows = read_csv("quest.csv")
seen = set()
result = []
for row in rows:
if len(row) > 3:
category = row[1].strip()
desc = row[3].strip()
if category in ("1", "2") and desc and desc not in seen:
seen.add(desc)
result.append(desc)
return result
def get_achievement_texts():
"""获取成就文本category 9的desc字段去重"""
rows = read_csv("quest.csv")
seen = set()
result = []
for row in rows:
if len(row) > 3:
category = row[1].strip()
desc = row[3].strip()
if category == "9" and desc and desc not in seen:
seen.add(desc)
result.append(desc)
return result
def get_guide_texts():
"""获取新手指引文本guide.csv的desc字段去重"""
rows = read_csv("guide.csv")
seen = set()
result = []
for row in rows:
if len(row) > 7:
desc = row[7].strip()
if desc and desc not in seen:
seen.add(desc)
result.append(desc)
return result
def get_prop_data():
"""获取道具数据 [(name, icon, tips), ...]"""
rows = read_csv("prop.csv")
result = []
for row in rows:
if len(row) > 7:
name = row[2].strip()
tips = row[6].strip()
icon = row[7].strip()
if name:
result.append((name, icon, tips))
return result
def get_skill_data():
"""获取技能数据 [(name, icon, desc), ...]"""
rows = read_csv("skill.csv")
result = []
for row in rows:
if len(row) > 21:
name = row[1].strip()
icon = row[6].strip()
desc = row[21].strip()
if name:
result.append((name, icon, desc))
return result
def get_rune_data():
"""获取灵石数据 [(name, icon, desc), ...]"""
rows = read_csv("rune.csv")
result = []
for row in rows:
if len(row) > 8:
name = row[1].strip()
icon = row[2].strip()
desc = row[8].strip()
if name:
result.append((name, icon, desc))
return result
def get_talent_data():
"""获取天赋数据 [(name, icon, desc), ...] 去重"""
rows = read_csv("playerlevel.csv")
seen = set()
result = []
for row in rows:
if len(row) > 15:
name = row[13].strip()
desc = row[14].strip()
icon = row[15].strip()
if name and name not in seen:
seen.add(name)
result.append((name, icon, desc))
return result
def get_equip_data():
"""获取装备数据 [(name, icon), ...] 去重"""
rows = read_csv("equip.csv")
seen = set()
result = []
for row in rows:
if len(row) > 5:
name = row[1].strip()
icon = row[5].strip()
if name and name not in seen:
seen.add(name)
result.append((name, icon))
return result
def get_level_names():
"""获取关卡名称fight_sample.csv的name字段去重"""
rows = read_csv("fight_sample.csv")
seen = set()
result = []
for row in rows:
if len(row) > 2:
name = row[2].strip()
if name and name not in seen:
seen.add(name)
result.append(name)
return result
# 玩家随机名称文本(保持不变)
PLAYER_NAMES = [
("", "子轩"), ("", "梓涵"), ("", "浩然"), ("", "欣怡"),
("", "宇轩"), ("", "晨曦"), ("", "俊杰"), ("", "雅静"),
("", "天佑"), ("", "梦琪"), ("", "博文"), ("", "思彤"),
("", "睿智"), ("", "静怡"), ("", "昊天"), ("", "雨桐"),
("", "泽宇"), ("", "婉清"), ("", "俊熙"), ("", "雪柔"),
("", "子豪"), ("", "依琳"), ("", "宇航"), ("", "诗涵"),
("", "志强"), ("", "梦瑶"), ("", "文博"), ("", "雅楠"),
("", "天宇"), ("", "欣妍"), ("", "子睿"), ("", "静雯"),
("", "俊豪"), ("", "雨欣"), ("", "浩宇"), ("", "语嫣"),
("", "子涵"), ("", "思雨"), ("", "博涛"), ("", "雅婷"),
("", "天翔"), ("", "梦洁"), ("", "文轩"), ("", "雪梅"),
("", "志远"), ("", "依娜"), ("", "子安"), ("", "静雅"),
("", "俊峰"), ("", "雨婷"), ("", "浩轩"), ("", "诗琪"),
("", "子恒"), ("", "思雅"), ("", "博超"), ("", "雅琪"),
("", "天瑞"), ("", "梦菲"), ("", "文昊"), ("", "雪莲"),
("", "志鹏"), ("", "依婷"), ("", "子健"), ("", "静淑"),
("", "俊凯"), ("", "雨菲"), ("", "浩南"), ("", "诗瑶"),
("", "子宁"), ("", "思琪"), ("", "博远"), ("", "雅静"),
("", "天浩"), ("", "梦婷"), ("", "文杰"), ("", "雪琪"),
("", "志伟"), ("", "依静"), ("", "子文"), ("", "静怡"),
("", "俊杰"), ("", "雨萱"), ("", "浩天"), ("", "诗涵"),
("", "子辰"), ("", "思妍"), ("", "博文"), ("", "雅欣"),
("", "天佑"), ("", "梦瑶"), ("", "文豪"), ("", "雪莹"),
("", "志强"), ("", "依琳"), ("", "子轩"), ("", "静雯"),
("", "俊熙"), ("", "雨桐"), ("", "浩宇"), ("", "诗琪"),
]
# ============ 文档生成 ============
# 中文编号
CN_NUMBERS = ["", "", "", "", "", "", "", "", "", "", "十一"]
def add_title(doc, text):
"""添加文档标题:宋体、二号(22pt)、加粗、居中、无下划线"""
para = doc.add_paragraph()
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = para.add_run(text)
run.font.name = "宋体"
run._element.rPr.rFonts.set(qn("w:eastAsia"), "宋体")
run.font.size = Pt(22)
run.font.bold = True
run.font.underline = False
run.font.color.rgb = None # 确保黑色,无蓝色
def add_section_heading(doc, cn_num, title_text):
"""添加小标题:仿宋、四号(14pt)、加粗、中文编号"""
para = doc.add_paragraph()
run = para.add_run(f"{cn_num}{title_text}")
run.font.name = "仿宋"
run._element.rPr.rFonts.set(qn("w:eastAsia"), "仿宋")
run.font.size = Pt(14)
run.font.bold = True
def add_numbered_paragraph(doc, index, text):
"""添加编号段落:仿宋、四号(14pt)、不加粗、阿拉伯数字编号"""
para = doc.add_paragraph()
run = para.add_run(f"{index}.{text}")
run.font.name = "仿宋"
run._element.rPr.rFonts.set(qn("w:eastAsia"), "仿宋")
run.font.size = Pt(14)
run.font.bold = False
def add_numbered_items(doc, items):
"""批量添加编号段落"""
for i, text in enumerate(items, 1):
add_numbered_paragraph(doc, i, text)
def add_name_table(doc, names):
"""添加玩家随机名称表格:姓/名两列"""
table = doc.add_table(rows=1, cols=2, style="Table Grid")
table.alignment = WD_TABLE_ALIGNMENT.CENTER
# 表头
for i, header in enumerate(["", ""]):
cell = table.rows[0].cells[i]
cell.text = ""
para = cell.paragraphs[0]
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = para.add_run(header)
run.font.name = "仿宋"
run._element.rPr.rFonts.set(qn("w:eastAsia"), "仿宋")
run.font.size = Pt(14)
run.font.bold = True
# 数据行
for surname, given_name in names:
row = table.add_row()
for j, text in enumerate([surname, given_name]):
cell = row.cells[j]
cell.text = ""
para = cell.paragraphs[0]
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = para.add_run(text)
run.font.name = "仿宋"
run._element.rPr.rFonts.set(qn("w:eastAsia"), "仿宋")
run.font.size = Pt(14)
run.font.bold = False
def build_document():
doc = Document()
# 设置默认字体
style = doc.styles["Normal"]
style.font.name = "仿宋"
style.font.size = Pt(14)
style._element.rPr.rFonts.set(qn("w:eastAsia"), "仿宋")
# 标题:宋体、二号、加粗、无蓝色下划线
add_title(doc, "《不朽封仙》文字脚本")
# ======= 一、系统提示 =======
add_section_heading(doc, CN_NUMBERS[0], "系统提示")
add_numbered_items(doc, get_system_prompts())
# ======= 二、任务文本 =======
add_section_heading(doc, CN_NUMBERS[1], "任务文本")
add_numbered_items(doc, get_quest_texts())
# ======= 三、成就文本 =======
add_section_heading(doc, CN_NUMBERS[2], "成就文本")
add_numbered_items(doc, get_achievement_texts())
# ======= 四、玩家随机名称文本 =======
add_section_heading(doc, CN_NUMBERS[3], "玩家随机名称文本")
add_name_table(doc, PLAYER_NAMES)
# ======= 五、新手指引文本 =======
add_section_heading(doc, CN_NUMBERS[4], "新手指引文本")
add_numbered_items(doc, get_guide_texts())
# ======= 六、道具说明 =======
add_section_heading(doc, CN_NUMBERS[5], "道具说明")
prop_data = get_prop_data()
add_table_with_icons(doc, ["道具名称", "图标", "道具描述"], prop_data, "product")
# ======= 七、技能 =======
add_section_heading(doc, CN_NUMBERS[6], "技能")
skill_data = get_skill_data()
add_table_with_icons(doc, ["技能名称", "技能图标", "技能描述"], skill_data, "skill")
# ======= 八、灵石 =======
add_section_heading(doc, CN_NUMBERS[7], "灵石")
rune_data = get_rune_data()
add_table_with_icons(doc, ["灵石名称", "灵石图标", "灵石介绍"], rune_data, "rune")
# ======= 九、天赋 =======
add_section_heading(doc, CN_NUMBERS[8], "天赋")
talent_data = get_talent_data()
add_table_with_icons(doc, ["天赋名称", "天赋图标", "天赋介绍"], talent_data, "talent")
# ======= 十、装备 =======
add_section_heading(doc, CN_NUMBERS[9], "装备")
equip_data = get_equip_data()
add_table_equip(doc, ["装备名称", "装备图标"], equip_data, "equip")
# ======= 十一、关卡名称 =======
add_section_heading(doc, CN_NUMBERS[10], "关卡名称")
add_numbered_items(doc, get_level_names())
# 保存文档
doc.save(OUTPUT_PATH)
print(f"文档已生成: {OUTPUT_PATH}")
if __name__ == "__main__":
build_document()