#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 同步enemies.json到敌人配置表.xlsx """ import json import pandas as pd from pathlib import Path import os def load_enemies_json(): """加载enemies.json文件""" json_file = Path('../enemies.json') if not json_file.exists(): print(f"❌ JSON文件不存在: {json_file}") return None try: with open(json_file, 'r', encoding='utf-8') as f: data = json.load(f) print(f"✅ 成功加载JSON文件,包含 {len(data.get('enemies', []))} 个敌人") return data except Exception as e: print(f"❌ 加载JSON文件失败: {e}") return None def create_excel_sheets(enemies_data): """根据JSON数据创建Excel工作表""" enemies = enemies_data.get('enemies', []) name_mapping = enemies_data.get('nameMapping', {}) # 1. 敌人基础配置表 basic_config = [] for enemy in enemies: basic_config.append({ '敌人ID': enemy['id'], '敌人名称': enemy['name'], '敌人类型': enemy['type'], '生命值': enemy['stats']['health'], '最大生命值': enemy['stats']['maxHealth'], '攻击力': enemy['stats']['attack'], '防御力': enemy['stats']['defense'], '移动速度': enemy['stats']['speed'] }) # 2. 战斗配置表 combat_config = [] for enemy in enemies: combat = enemy.get('combat', {}) combat_config.append({ '敌人ID': enemy['id'], '攻击伤害': combat.get('attackDamage', 0), '攻击范围': combat.get('attackRange', 0), '攻击速度': combat.get('attackSpeed', 1.0), '能否格挡': combat.get('canBlock', False), '格挡几率': combat.get('blockChance', 0.0), '格挡伤害减免': combat.get('blockDamageReduction', 0.5), '攻击冷却': combat.get('attackCooldown', 1.0), '攻击类型': combat.get('attackType', 'melee'), '攻击延迟': combat.get('attackDelay', 0.5), '武器类型': combat.get('weaponType', 'none'), '投射物类型': combat.get('projectileType', 'none'), '投射物速度': combat.get('projectileSpeed', 100) }) # 3. 移动配置表 movement_config = [] for enemy in enemies: movement = enemy.get('movement', {}) movement_config.append({ '敌人ID': enemy['id'], '移动模式': movement.get('pattern', 'walk_forward'), '移动速度': movement.get('speed', 50.0), '巡逻范围': movement.get('patrolRange', 100), '追击范围': movement.get('chaseRange', 200), '旋转速度': movement.get('rotationSpeed', 180), '移动类型': movement.get('moveType', 'straight'), '摆动幅度': movement.get('swingAmplitude', 0.0), '摆动频率': movement.get('swingFrequency', 0.0), '速度变化': movement.get('speedVariation', 0.1) }) # 4. 视觉配置表 visual_config = [] for enemy in enemies: visual = enemy.get('visualConfig', {}) animations = visual.get('animations', {}) visual_config.append({ '敌人ID': enemy['id'], '精灵路径': visual.get('spritePath', ''), '缩放比例': visual.get('scale', 1.0), '动画速度': visual.get('animationSpeed', 1.0), '水平翻转': visual.get('flipX', False), '待机动画': animations.get('idle', 'idle'), '行走动画': animations.get('walk', 'walk'), '攻击动画': animations.get('attack', 'attack'), '死亡动画': animations.get('death', 'dead'), '武器道具': visual.get('weaponProp', '') }) # 5. 音频配置表 audio_config = [] for enemy in enemies: audio = enemy.get('audioConfig', {}) audio_config.append({ '敌人ID': enemy['id'], '攻击音效': audio.get('attackSound', ''), '死亡音效': audio.get('deathSound', ''), '受击音效': audio.get('hitSound', ''), '行走音效': audio.get('walkSound', ''), '格挡音效': audio.get('blockSound', ''), '隐身音效': audio.get('stealthSound', ''), '护甲破碎音效': audio.get('armorBreakSound', ''), '引信音效': audio.get('fuseSound', '') }) # 6. 特殊能力配置表 special_abilities = [] for enemy in enemies: abilities = enemy.get('specialAbilities', []) if abilities: for ability in abilities: special_abilities.append({ '敌人ID': enemy['id'], '能力类型': ability.get('type', ''), '伤害': ability.get('damage', 0), '范围': ability.get('range', ability.get('radius', 0)), '冷却时间': ability.get('cooldown', 0) }) else: # 为没有特殊能力的敌人添加空行 special_abilities.append({ '敌人ID': enemy['id'], '能力类型': '', '伤害': 0, '范围': 0, '冷却时间': 0 }) # 7. BOSS配置表 boss_config = [] for enemy in enemies: boss = enemy.get('bossConfig', {}) if boss: boss_config.append({ '敌人ID': enemy['id'], '是否BOSS': boss.get('isBoss', False), '阶段数': boss.get('phases', 1), '狂暴阈值': boss.get('enrageThreshold', 0.3), '狂暴伤害倍数': boss.get('enrageDamageMultiplier', 1.5), '狂暴速度倍数': boss.get('enrageSpeedMultiplier', 1.3) }) else: # 为非BOSS敌人添加空行 boss_config.append({ '敌人ID': enemy['id'], '是否BOSS': False, '阶段数': 1, '狂暴阈值': 0.3, '狂暴伤害倍数': 1.0, '狂暴速度倍数': 1.0 }) # 8. 敌人名称映射表 name_mapping_list = [] for enemy_id, enemy_name in name_mapping.items(): name_mapping_list.append({ '敌人ID': enemy_id, '显示名称': enemy_name }) return { '敌人基础配置': pd.DataFrame(basic_config), '战斗配置': pd.DataFrame(combat_config), '移动配置': pd.DataFrame(movement_config), '视觉配置': pd.DataFrame(visual_config), '音频配置': pd.DataFrame(audio_config), '特殊能力配置': pd.DataFrame(special_abilities), 'BOSS配置': pd.DataFrame(boss_config), '敌人名称映射': pd.DataFrame(name_mapping_list) } def save_to_excel(sheets_data, output_file): """保存数据到Excel文件""" try: # 备份原文件 if output_file.exists(): backup_file = output_file.with_suffix('.backup.xlsx') import shutil shutil.copy2(output_file, backup_file) print(f"✅ 已备份原文件到: {backup_file}") # 写入新的Excel文件 with pd.ExcelWriter(output_file, engine='openpyxl') as writer: for sheet_name, df in sheets_data.items(): df.to_excel(writer, sheet_name=sheet_name, index=False) print(f" 📄 已写入工作表: {sheet_name} ({len(df)} 行)") print(f"✅ 成功保存Excel文件: {output_file}") return True except Exception as e: print(f"❌ 保存Excel文件失败: {e}") return False def main(): """主函数""" print("🔄 开始同步enemies.json到敌人配置表.xlsx...") # 加载JSON数据 enemies_data = load_enemies_json() if not enemies_data: return False # 创建Excel工作表数据 print("\n📊 创建Excel工作表数据...") sheets_data = create_excel_sheets(enemies_data) # 保存到Excel文件 output_file = Path('敌人配置表.xlsx') print(f"\n💾 保存到Excel文件: {output_file}") if save_to_excel(sheets_data, output_file): print("\n🎉 同步完成!") print("\n📋 同步内容:") print(" ✅ 敌人基础配置 (ID、名称、类型、属性)") print(" ✅ 战斗配置 (攻击类型、武器、投射物等)") print(" ✅ 移动配置 (移动模式、摆动参数等)") print(" ✅ 视觉配置 (动画路径、动画状态等)") print(" ✅ 音频配置 (各种音效路径)") print(" ✅ 特殊能力配置 (BOSS技能等)") print(" ✅ BOSS配置 (狂暴机制等)") print(" ✅ 敌人名称映射") print("\n🎯 Excel文件已与最新的enemies.json完全同步!") return True else: print("\n❌ 同步失败") return False if __name__ == '__main__': success = main() if not success: print("\n❌ 同步过程中发生错误,请检查上述错误信息")