generate_excel_from_json.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. 从weapons.json生成Excel配置表
  5. 确保Excel配置与JSON配置保持同步
  6. """
  7. import json
  8. import os
  9. from pathlib import Path
  10. from datetime import datetime
  11. try:
  12. import pandas as pd
  13. PANDAS_AVAILABLE = True
  14. except ImportError:
  15. PANDAS_AVAILABLE = False
  16. print("错误: pandas未安装,无法生成Excel文件")
  17. print("请运行: pip install pandas openpyxl")
  18. exit(1)
  19. class WeaponExcelGenerator:
  20. """从weapons.json生成Excel配置表的工具类"""
  21. def __init__(self, json_file_path=None, excel_output_path=None):
  22. """初始化生成器
  23. Args:
  24. json_file_path: weapons.json文件路径
  25. excel_output_path: 输出Excel文件路径
  26. """
  27. self.script_dir = Path(__file__).parent
  28. # 设置默认路径
  29. if json_file_path is None:
  30. self.json_file = self.script_dir.parent / "weapons.json"
  31. else:
  32. self.json_file = Path(json_file_path)
  33. if excel_output_path is None:
  34. self.excel_file = self.script_dir / "方块武器配置" / "方块武器配置表.xlsx"
  35. else:
  36. self.excel_file = Path(excel_output_path)
  37. print(f"JSON文件路径: {self.json_file}")
  38. print(f"Excel输出路径: {self.excel_file}")
  39. # 确保输出目录存在
  40. self.excel_file.parent.mkdir(parents=True, exist_ok=True)
  41. def load_weapons_json(self):
  42. """加载weapons.json文件"""
  43. try:
  44. if not self.json_file.exists():
  45. raise FileNotFoundError(f"JSON文件不存在: {self.json_file}")
  46. with open(self.json_file, 'r', encoding='utf-8') as f:
  47. config = json.load(f)
  48. print(f"成功加载JSON配置,包含 {len(config.get('weapons', []))} 个武器")
  49. return config
  50. except Exception as e:
  51. print(f"加载JSON配置失败: {e}")
  52. raise
  53. def create_weapon_base_config_sheet(self, weapons_data):
  54. """创建武器基础配置工作表"""
  55. base_config_data = []
  56. # 表头
  57. headers = [
  58. 'ID', '名称', '类型', '稀有度', '权重',
  59. '伤害', '射速', '射程', '子弹速度', '子弹数量',
  60. '子弹轨迹类型', '子弹速度值', '穿透数', '反弹次数',
  61. '精灵路径', '音效路径'
  62. ]
  63. for weapon in weapons_data:
  64. # 提取基础信息
  65. weapon_id = weapon.get('id', '')
  66. name = weapon.get('name', '')
  67. weapon_type = weapon.get('type', '')
  68. rarity = weapon.get('rarity', '')
  69. weight = weapon.get('weight', 0)
  70. # 提取统计信息
  71. stats = weapon.get('stats', {})
  72. damage = stats.get('damage', 0)
  73. fire_rate = stats.get('fireRate', 0.0)
  74. weapon_range = stats.get('range', 0)
  75. bullet_speed = stats.get('bulletSpeed', 0)
  76. # 提取子弹配置
  77. bullet_config = weapon.get('bulletConfig', {})
  78. bullet_count = bullet_config.get('bulletCount', 1)
  79. # 提取轨迹配置
  80. trajectory = bullet_config.get('trajectory', {})
  81. trajectory_type = trajectory.get('type', '')
  82. trajectory_speed = trajectory.get('speed', 0)
  83. pierce_count = trajectory.get('pierceCount', 0)
  84. bounce_count = trajectory.get('bounceCount', 0)
  85. # 提取视觉配置
  86. visuals = weapon.get('visuals', {})
  87. sprite_path = visuals.get('spritePath', '')
  88. sound_path = visuals.get('soundPath', '')
  89. base_config_data.append([
  90. weapon_id, name, weapon_type, rarity, weight,
  91. damage, fire_rate, weapon_range, bullet_speed, bullet_count,
  92. trajectory_type, trajectory_speed, pierce_count, bounce_count,
  93. sprite_path, sound_path
  94. ])
  95. # 创建DataFrame
  96. df = pd.DataFrame(base_config_data, columns=headers)
  97. return df
  98. def create_upgrade_cost_sheet(self, weapons_data):
  99. """创建武器升级费用配置工作表"""
  100. upgrade_data = []
  101. # 表头:武器ID + 等级1-10费用 + 等级1-10伤害
  102. headers = ['武器ID', '武器名称', '基础伤害', '最大伤害']
  103. # 添加等级1-10的费用列
  104. for level in range(1, 11):
  105. headers.append(f'等级{level}费用')
  106. # 添加等级1-10的伤害列
  107. for level in range(1, 11):
  108. headers.append(f'等级{level}伤害')
  109. for weapon in weapons_data:
  110. weapon_id = weapon.get('id', '')
  111. weapon_name = weapon.get('name', '')
  112. base_damage = weapon.get('stats', {}).get('damage', 0)
  113. # 获取升级配置
  114. upgrade_config = weapon.get('upgradeConfig', {})
  115. levels = upgrade_config.get('levels', {})
  116. row_data = [weapon_id, weapon_name, base_damage]
  117. # 计算最大伤害
  118. max_damage = base_damage
  119. for level in range(1, 11):
  120. level_config = levels.get(str(level), {})
  121. level_damage = level_config.get('damage', base_damage)
  122. if level_damage > max_damage:
  123. max_damage = level_damage
  124. row_data.append(max_damage)
  125. # 添加等级1-10的费用
  126. for level in range(1, 11):
  127. level_config = levels.get(str(level), {})
  128. cost = level_config.get('cost', '')
  129. row_data.append(cost)
  130. # 添加等级1-10的伤害
  131. for level in range(1, 11):
  132. level_config = levels.get(str(level), {})
  133. damage = level_config.get('damage', base_damage)
  134. row_data.append(damage)
  135. upgrade_data.append(row_data)
  136. # 创建DataFrame
  137. df = pd.DataFrame(upgrade_data, columns=headers)
  138. return df
  139. def create_game_cost_sheet(self, weapons_data):
  140. """创建游戏内成本配置工作表"""
  141. cost_data = []
  142. # 表头
  143. headers = [
  144. '武器ID', '武器名称', '武器基础售价',
  145. 'I形状成本', 'H-I形状成本', 'L形状成本',
  146. 'S形状成本', 'D-T形状成本', 'O形状成本',
  147. 'T形状成本', 'Z形状成本', 'J形状成本', 'U形状成本'
  148. ]
  149. for weapon in weapons_data:
  150. weapon_id = weapon.get('id', '')
  151. weapon_name = weapon.get('name', '')
  152. # 获取游戏内成本配置
  153. cost_config = weapon.get('inGameCostConfig', {})
  154. base_cost = cost_config.get('baseCost', 5)
  155. shape_costs = cost_config.get('shapeCosts', {})
  156. row_data = [weapon_id, weapon_name, base_cost]
  157. # 添加各形状成本
  158. shape_keys = ['I', 'H-I', 'L', 'S', 'D-T', 'O', 'T', 'Z', 'J', 'U']
  159. for shape_key in shape_keys:
  160. cost = shape_costs.get(shape_key, '')
  161. row_data.append(cost)
  162. cost_data.append(row_data)
  163. # 创建DataFrame
  164. df = pd.DataFrame(cost_data, columns=headers)
  165. return df
  166. def create_rarity_weights_sheet(self, config_data):
  167. """创建稀有度权重配置工作表"""
  168. rarity_weights = config_data.get('rarityWeights', {})
  169. rarity_data = []
  170. headers = ['稀有度', '权重', '描述']
  171. # 稀有度描述映射
  172. rarity_descriptions = {
  173. 'common': '普通',
  174. 'uncommon': '不常见',
  175. 'rare': '稀有',
  176. 'epic': '史诗'
  177. }
  178. for rarity, weight in rarity_weights.items():
  179. description = rarity_descriptions.get(rarity, '')
  180. rarity_data.append([rarity, weight, description])
  181. # 创建DataFrame
  182. df = pd.DataFrame(rarity_data, columns=headers)
  183. return df
  184. def create_rarity_damage_multipliers_sheet(self, config_data):
  185. """创建稀有度伤害倍率配置工作表"""
  186. rarity_damage_multipliers = config_data.get('rarityDamageMultipliers', [])
  187. multiplier_data = []
  188. headers = ['配置项', '值', '描述']
  189. # 将数组转换为逗号分隔的字符串
  190. multipliers_str = ', '.join(map(str, rarity_damage_multipliers))
  191. # 添加配置行
  192. multiplier_data.append([
  193. 'rarityDamageMultipliers',
  194. multipliers_str,
  195. '稀有度伤害倍率数组,按等级顺序:[普通, 不常见, 稀有, 史诗]'
  196. ])
  197. # 添加说明行
  198. rarity_level_names = ['普通(common)', '不常见(uncommon)', '稀有(rare)', '史诗(epic)']
  199. for i, multiplier in enumerate(rarity_damage_multipliers):
  200. if i < len(rarity_level_names):
  201. multiplier_data.append([
  202. f'等级{i}',
  203. str(multiplier),
  204. f'{rarity_level_names[i]} - {multiplier}倍伤害'
  205. ])
  206. # 创建DataFrame
  207. df = pd.DataFrame(multiplier_data, columns=headers)
  208. return df
  209. def create_block_shapes_sheet(self, config_data):
  210. """创建方块形状配置工作表"""
  211. block_sizes = config_data.get('blockSizes', [])
  212. shape_data = []
  213. headers = ['ID', '名称', '形状矩阵', '占用格数', '成本倍数', '描述']
  214. for shape in block_sizes:
  215. shape_id = shape.get('id', '')
  216. name = shape.get('name', '')
  217. shape_matrix = str(shape.get('shape', []))
  218. grid_count = shape.get('gridCount', 0)
  219. cost_multiplier = shape.get('costMultiplier', 1)
  220. description = shape.get('description', '')
  221. shape_data.append([
  222. shape_id, name, shape_matrix, grid_count, cost_multiplier, description
  223. ])
  224. # 创建DataFrame
  225. df = pd.DataFrame(shape_data, columns=headers)
  226. return df
  227. def generate_excel_file(self):
  228. """生成Excel配置文件"""
  229. try:
  230. # 加载JSON配置
  231. config_data = self.load_weapons_json()
  232. weapons_data = config_data.get('weapons', [])
  233. if not weapons_data:
  234. print("警告: 没有找到武器数据")
  235. return False
  236. print(f"开始生成Excel文件,包含 {len(weapons_data)} 个武器...")
  237. # 创建Excel写入器
  238. with pd.ExcelWriter(self.excel_file, engine='openpyxl') as writer:
  239. # 创建武器基础配置工作表
  240. base_config_df = self.create_weapon_base_config_sheet(weapons_data)
  241. base_config_df.to_excel(writer, sheet_name='武器基础配置', index=False)
  242. print("✓ 创建武器基础配置工作表")
  243. # 创建武器升级费用配置工作表
  244. upgrade_cost_df = self.create_upgrade_cost_sheet(weapons_data)
  245. upgrade_cost_df.to_excel(writer, sheet_name='武器升级费用配置', index=False)
  246. print("✓ 创建武器升级费用配置工作表")
  247. # 创建游戏内成本配置工作表
  248. game_cost_df = self.create_game_cost_sheet(weapons_data)
  249. game_cost_df.to_excel(writer, sheet_name='游戏内成本配置', index=False)
  250. print("✓ 创建游戏内成本配置工作表")
  251. # 创建稀有度权重配置工作表
  252. rarity_weights_df = self.create_rarity_weights_sheet(config_data)
  253. rarity_weights_df.to_excel(writer, sheet_name='稀有度权重配置', index=False)
  254. print("✓ 创建稀有度权重配置工作表")
  255. # 创建稀有度伤害倍率配置工作表
  256. rarity_damage_multipliers_df = self.create_rarity_damage_multipliers_sheet(config_data)
  257. rarity_damage_multipliers_df.to_excel(writer, sheet_name='稀有度伤害倍率配置', index=False)
  258. print("✓ 创建稀有度伤害倍率配置工作表")
  259. # 创建方块形状配置工作表
  260. block_shapes_df = self.create_block_shapes_sheet(config_data)
  261. block_shapes_df.to_excel(writer, sheet_name='方块形状配置', index=False)
  262. print("✓ 创建方块形状配置工作表")
  263. print(f"\n✅ Excel文件生成成功: {self.excel_file}")
  264. print(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
  265. return True
  266. except Exception as e:
  267. print(f"❌ 生成Excel文件失败: {e}")
  268. return False
  269. def main():
  270. """主函数"""
  271. print("=== 从weapons.json生成Excel配置表 ===")
  272. print(f"开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
  273. print()
  274. # 创建生成器
  275. generator = WeaponExcelGenerator()
  276. # 生成Excel文件
  277. success = generator.generate_excel_file()
  278. if success:
  279. print("\n🎉 Excel配置表生成完成!")
  280. print("\n生成的工作表包括:")
  281. print(" 1. 武器基础配置 - 包含所有武器的基本属性")
  282. print(" 2. 武器升级费用配置 - 包含武器升级的费用和伤害配置")
  283. print(" 3. 游戏内成本配置 - 包含武器在游戏中的购买成本")
  284. print(" 4. 稀有度权重配置 - 包含武器稀有度的权重分布")
  285. print(" 5. 稀有度伤害倍率配置 - 包含不同稀有度的伤害倍率")
  286. print(" 6. 方块形状配置 - 包含所有方块形状的定义")
  287. else:
  288. print("\n❌ Excel配置表生成失败!")
  289. return 1
  290. return 0
  291. if __name__ == '__main__':
  292. exit(main())