sync_json_to_excel.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. 同步enemies.json到敌人配置表.xlsx
  5. """
  6. import json
  7. import pandas as pd
  8. from pathlib import Path
  9. import os
  10. def load_enemies_json():
  11. """加载enemies.json文件"""
  12. json_file = Path('../enemies.json')
  13. if not json_file.exists():
  14. print(f"❌ JSON文件不存在: {json_file}")
  15. return None
  16. try:
  17. with open(json_file, 'r', encoding='utf-8') as f:
  18. data = json.load(f)
  19. print(f"✅ 成功加载JSON文件,包含 {len(data.get('enemies', []))} 个敌人")
  20. return data
  21. except Exception as e:
  22. print(f"❌ 加载JSON文件失败: {e}")
  23. return None
  24. def create_excel_sheets(enemies_data):
  25. """根据JSON数据创建Excel工作表"""
  26. enemies = enemies_data.get('enemies', [])
  27. name_mapping = enemies_data.get('nameMapping', {})
  28. # 1. 敌人基础配置表
  29. basic_config = []
  30. for enemy in enemies:
  31. basic_config.append({
  32. '敌人ID': enemy['id'],
  33. '敌人名称': enemy['name'],
  34. '敌人类型': enemy['type'],
  35. '生命值': enemy['stats']['health'],
  36. '最大生命值': enemy['stats']['maxHealth'],
  37. '攻击力': enemy['stats']['attack'],
  38. '防御力': enemy['stats']['defense'],
  39. '移动速度': enemy['stats']['speed']
  40. })
  41. # 2. 战斗配置表
  42. combat_config = []
  43. for enemy in enemies:
  44. combat = enemy.get('combat', {})
  45. combat_config.append({
  46. '敌人ID': enemy['id'],
  47. '攻击伤害': combat.get('attackDamage', 0),
  48. '攻击范围': combat.get('attackRange', 0),
  49. '攻击速度': combat.get('attackSpeed', 1.0),
  50. '能否格挡': combat.get('canBlock', False),
  51. '格挡几率': combat.get('blockChance', 0.0),
  52. '格挡伤害减免': combat.get('blockDamageReduction', 0.5),
  53. '攻击冷却': combat.get('attackCooldown', 1.0),
  54. '攻击类型': combat.get('attackType', 'melee'),
  55. '攻击延迟': combat.get('attackDelay', 0.5),
  56. '武器类型': combat.get('weaponType', 'none'),
  57. '投射物类型': combat.get('projectileType', 'none'),
  58. '投射物速度': combat.get('projectileSpeed', 100)
  59. })
  60. # 3. 移动配置表
  61. movement_config = []
  62. for enemy in enemies:
  63. movement = enemy.get('movement', {})
  64. movement_config.append({
  65. '敌人ID': enemy['id'],
  66. '移动模式': movement.get('pattern', 'walk_forward'),
  67. '移动速度': movement.get('speed', 50.0),
  68. '巡逻范围': movement.get('patrolRange', 100),
  69. '追击范围': movement.get('chaseRange', 200),
  70. '旋转速度': movement.get('rotationSpeed', 180),
  71. '移动类型': movement.get('moveType', 'straight'),
  72. '摆动幅度': movement.get('swingAmplitude', 0.0),
  73. '摆动频率': movement.get('swingFrequency', 0.0),
  74. '速度变化': movement.get('speedVariation', 0.1)
  75. })
  76. # 4. 视觉配置表
  77. visual_config = []
  78. for enemy in enemies:
  79. visual = enemy.get('visualConfig', {})
  80. animations = visual.get('animations', {})
  81. visual_config.append({
  82. '敌人ID': enemy['id'],
  83. '精灵路径': visual.get('spritePath', ''),
  84. '缩放比例': visual.get('scale', 1.0),
  85. '动画速度': visual.get('animationSpeed', 1.0),
  86. '水平翻转': visual.get('flipX', False),
  87. '待机动画': animations.get('idle', 'idle'),
  88. '行走动画': animations.get('walk', 'walk'),
  89. '攻击动画': animations.get('attack', 'attack'),
  90. '死亡动画': animations.get('death', 'dead'),
  91. '武器道具': visual.get('weaponProp', '')
  92. })
  93. # 5. 音频配置表
  94. audio_config = []
  95. for enemy in enemies:
  96. audio = enemy.get('audioConfig', {})
  97. audio_config.append({
  98. '敌人ID': enemy['id'],
  99. '攻击音效': audio.get('attackSound', ''),
  100. '死亡音效': audio.get('deathSound', ''),
  101. '受击音效': audio.get('hitSound', ''),
  102. '行走音效': audio.get('walkSound', ''),
  103. '格挡音效': audio.get('blockSound', ''),
  104. '隐身音效': audio.get('stealthSound', ''),
  105. '护甲破碎音效': audio.get('armorBreakSound', ''),
  106. '引信音效': audio.get('fuseSound', '')
  107. })
  108. # 6. 特殊能力配置表
  109. special_abilities = []
  110. for enemy in enemies:
  111. abilities = enemy.get('specialAbilities', [])
  112. if abilities:
  113. for ability in abilities:
  114. special_abilities.append({
  115. '敌人ID': enemy['id'],
  116. '能力类型': ability.get('type', ''),
  117. '伤害': ability.get('damage', 0),
  118. '范围': ability.get('range', ability.get('radius', 0)),
  119. '冷却时间': ability.get('cooldown', 0)
  120. })
  121. else:
  122. # 为没有特殊能力的敌人添加空行
  123. special_abilities.append({
  124. '敌人ID': enemy['id'],
  125. '能力类型': '',
  126. '伤害': 0,
  127. '范围': 0,
  128. '冷却时间': 0
  129. })
  130. # 7. BOSS配置表
  131. boss_config = []
  132. for enemy in enemies:
  133. boss = enemy.get('bossConfig', {})
  134. if boss:
  135. boss_config.append({
  136. '敌人ID': enemy['id'],
  137. '是否BOSS': boss.get('isBoss', False),
  138. '阶段数': boss.get('phases', 1),
  139. '狂暴阈值': boss.get('enrageThreshold', 0.3),
  140. '狂暴伤害倍数': boss.get('enrageDamageMultiplier', 1.5),
  141. '狂暴速度倍数': boss.get('enrageSpeedMultiplier', 1.3)
  142. })
  143. else:
  144. # 为非BOSS敌人添加空行
  145. boss_config.append({
  146. '敌人ID': enemy['id'],
  147. '是否BOSS': False,
  148. '阶段数': 1,
  149. '狂暴阈值': 0.3,
  150. '狂暴伤害倍数': 1.0,
  151. '狂暴速度倍数': 1.0
  152. })
  153. # 8. 敌人名称映射表
  154. name_mapping_list = []
  155. for enemy_id, enemy_name in name_mapping.items():
  156. name_mapping_list.append({
  157. '敌人ID': enemy_id,
  158. '显示名称': enemy_name
  159. })
  160. return {
  161. '敌人基础配置': pd.DataFrame(basic_config),
  162. '战斗配置': pd.DataFrame(combat_config),
  163. '移动配置': pd.DataFrame(movement_config),
  164. '视觉配置': pd.DataFrame(visual_config),
  165. '音频配置': pd.DataFrame(audio_config),
  166. '特殊能力配置': pd.DataFrame(special_abilities),
  167. 'BOSS配置': pd.DataFrame(boss_config),
  168. '敌人名称映射': pd.DataFrame(name_mapping_list)
  169. }
  170. def save_to_excel(sheets_data, output_file):
  171. """保存数据到Excel文件"""
  172. try:
  173. # 备份原文件
  174. if output_file.exists():
  175. backup_file = output_file.with_suffix('.backup.xlsx')
  176. import shutil
  177. shutil.copy2(output_file, backup_file)
  178. print(f"✅ 已备份原文件到: {backup_file}")
  179. # 写入新的Excel文件
  180. with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
  181. for sheet_name, df in sheets_data.items():
  182. df.to_excel(writer, sheet_name=sheet_name, index=False)
  183. print(f" 📄 已写入工作表: {sheet_name} ({len(df)} 行)")
  184. print(f"✅ 成功保存Excel文件: {output_file}")
  185. return True
  186. except Exception as e:
  187. print(f"❌ 保存Excel文件失败: {e}")
  188. return False
  189. def main():
  190. """主函数"""
  191. print("🔄 开始同步enemies.json到敌人配置表.xlsx...")
  192. # 加载JSON数据
  193. enemies_data = load_enemies_json()
  194. if not enemies_data:
  195. return False
  196. # 创建Excel工作表数据
  197. print("\n📊 创建Excel工作表数据...")
  198. sheets_data = create_excel_sheets(enemies_data)
  199. # 保存到Excel文件
  200. output_file = Path('敌人配置表.xlsx')
  201. print(f"\n💾 保存到Excel文件: {output_file}")
  202. if save_to_excel(sheets_data, output_file):
  203. print("\n🎉 同步完成!")
  204. print("\n📋 同步内容:")
  205. print(" ✅ 敌人基础配置 (ID、名称、类型、属性)")
  206. print(" ✅ 战斗配置 (攻击类型、武器、投射物等)")
  207. print(" ✅ 移动配置 (移动模式、摆动参数等)")
  208. print(" ✅ 视觉配置 (动画路径、动画状态等)")
  209. print(" ✅ 音频配置 (各种音效路径)")
  210. print(" ✅ 特殊能力配置 (BOSS技能等)")
  211. print(" ✅ BOSS配置 (狂暴机制等)")
  212. print(" ✅ 敌人名称映射")
  213. print("\n🎯 Excel文件已与最新的enemies.json完全同步!")
  214. return True
  215. else:
  216. print("\n❌ 同步失败")
  217. return False
  218. if __name__ == '__main__':
  219. success = main()
  220. if not success:
  221. print("\n❌ 同步过程中发生错误,请检查上述错误信息")