|
|
@@ -47,6 +47,13 @@ except ImportError:
|
|
|
ENEMY_MANAGER_AVAILABLE = False
|
|
|
print("警告: enemy_config_manager.py 未找到,敌人配置功能将不可用")
|
|
|
|
|
|
+try:
|
|
|
+ from level_config_manager import LevelConfigManager
|
|
|
+ LEVEL_MANAGER_AVAILABLE = True
|
|
|
+except ImportError:
|
|
|
+ LEVEL_MANAGER_AVAILABLE = False
|
|
|
+ print("警告: level_config_manager.py 未找到,关卡配置功能将不可用")
|
|
|
+
|
|
|
class SkillConfigImporter:
|
|
|
"""技能配置表导入工具类"""
|
|
|
def __init__(self, excel_dir=None):
|
|
|
@@ -471,14 +478,23 @@ class ConfigManagerGUI:
|
|
|
ttk.Label(enemy_btn_frame, text="敌人配置管理器不可用",
|
|
|
foreground="red").pack(side=tk.LEFT)
|
|
|
|
|
|
-
|
|
|
+ # 关卡配置专用按钮
|
|
|
+ level_btn_frame = ttk.Frame(right_frame)
|
|
|
+ level_btn_frame.grid(row=4, column=0, sticky=(tk.W, tk.E), pady=(10, 0))
|
|
|
+
|
|
|
+ if LEVEL_MANAGER_AVAILABLE:
|
|
|
+ ttk.Button(level_btn_frame, text="导入关卡配置",
|
|
|
+ command=self.import_level_config).pack(side=tk.LEFT)
|
|
|
+ else:
|
|
|
+ ttk.Label(level_btn_frame, text="关卡配置管理器不可用",
|
|
|
+ foreground="red").pack(side=tk.LEFT)
|
|
|
|
|
|
# 底部状态栏
|
|
|
self.status_var = tk.StringVar()
|
|
|
self.status_var.set("就绪")
|
|
|
status_bar = ttk.Label(main_frame, textvariable=self.status_var,
|
|
|
relief=tk.SUNKEN, anchor=tk.W)
|
|
|
- status_bar.grid(row=4, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(10, 0))
|
|
|
+ status_bar.grid(row=5, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(10, 0))
|
|
|
|
|
|
# 绑定事件
|
|
|
self.file_listbox.bind('<<ListboxSelect>>', self.on_file_select)
|
|
|
@@ -980,118 +996,7 @@ class ConfigManagerGUI:
|
|
|
|
|
|
return config
|
|
|
|
|
|
- def parse_level_multi_sheet_data(self, all_sheets_data, filename):
|
|
|
- """解析关卡配置的多工作表数据"""
|
|
|
- config = []
|
|
|
-
|
|
|
- try:
|
|
|
- # 获取各个工作表的数据(支持中英文工作表名)
|
|
|
- basic_config = None
|
|
|
- for sheet_name in ['关卡基础配置', 'Level Config', 'levels', '关卡配置']:
|
|
|
- if sheet_name in all_sheets_data:
|
|
|
- basic_config = all_sheets_data[sheet_name]
|
|
|
- break
|
|
|
-
|
|
|
- weapon_config = None
|
|
|
- for sheet_name in ['关卡武器配置', 'Level Weapon Config', 'level_weapons', '武器配置']:
|
|
|
- if sheet_name in all_sheets_data:
|
|
|
- weapon_config = all_sheets_data[sheet_name]
|
|
|
- break
|
|
|
-
|
|
|
- wave_config = None
|
|
|
- for sheet_name in ['关卡波次配置', 'Wave Config', 'waves', '波次配置']:
|
|
|
- if sheet_name in all_sheets_data:
|
|
|
- wave_config = all_sheets_data[sheet_name]
|
|
|
- break
|
|
|
-
|
|
|
- enemy_config = None
|
|
|
- for sheet_name in ['敌人详细配置', 'Enemy Detail Config', 'enemy_details', '敌人配置']:
|
|
|
- if sheet_name in all_sheets_data:
|
|
|
- enemy_config = all_sheets_data[sheet_name]
|
|
|
- break
|
|
|
-
|
|
|
- if basic_config is None:
|
|
|
- print("错误: 未找到关卡基础配置工作表(支持的工作表名: 关卡基础配置, Level Config, levels, 关卡配置)")
|
|
|
- return config
|
|
|
-
|
|
|
- # 处理每个关卡
|
|
|
- for _, basic_row in basic_config.iterrows():
|
|
|
- if pd.isna(basic_row['关卡ID']):
|
|
|
- continue
|
|
|
-
|
|
|
- level_id = str(basic_row['关卡ID'])
|
|
|
-
|
|
|
- # 获取武器配置
|
|
|
- available_weapons = []
|
|
|
- if weapon_config is not None:
|
|
|
- weapon_rows = weapon_config[weapon_config['关卡ID'] == level_id]
|
|
|
- for _, weapon_row in weapon_rows.iterrows():
|
|
|
- if pd.notna(weapon_row['可用武器']):
|
|
|
- weapons_str = str(weapon_row['可用武器'])
|
|
|
- # 支持多种分隔符
|
|
|
- import re
|
|
|
- weapons = re.split(r'[、,,;;]', weapons_str)
|
|
|
- available_weapons.extend([w.strip() for w in weapons if w.strip()])
|
|
|
-
|
|
|
- level_data = {
|
|
|
- 'levelId': level_id,
|
|
|
- 'name': str(basic_row['关卡名称']) if pd.notna(basic_row['关卡名称']) else '',
|
|
|
- 'scene': str(basic_row['场景']) if pd.notna(basic_row['场景']) else 'grassland',
|
|
|
- 'description': str(basic_row['描述']) if pd.notna(basic_row['描述']) else '',
|
|
|
- 'backgroundImage': str(basic_row['关卡背景图路径']) if pd.notna(basic_row['关卡背景图路径']) else 'images/LevelBackground/BG1',
|
|
|
- 'availableWeapons': available_weapons,
|
|
|
- 'coinReward': int(basic_row['钞票奖励']) if pd.notna(basic_row['钞票奖励']) else 100,
|
|
|
- 'diamondReward': int(basic_row['钻石奖励']) if pd.notna(basic_row['钻石奖励']) else 0,
|
|
|
- 'timeLimit': 300, # 默认值
|
|
|
- 'difficulty': 'normal', # 默认值
|
|
|
- 'healthMultiplier': float(basic_row['生命倍数']) if pd.notna(basic_row['生命倍数']) else 1.0, # 从Excel读取生命倍数
|
|
|
- 'waves': []
|
|
|
- }
|
|
|
-
|
|
|
- # 获取该关卡的波次配置
|
|
|
- if wave_config is not None:
|
|
|
- level_waves = wave_config[wave_config['关卡ID'] == level_id]
|
|
|
-
|
|
|
- for _, wave_row in level_waves.iterrows():
|
|
|
- wave_id = int(wave_row['波次ID']) if pd.notna(wave_row['波次ID']) else 1
|
|
|
-
|
|
|
- # 获取该波次的敌人配置
|
|
|
- wave_enemies = []
|
|
|
- if enemy_config is not None:
|
|
|
- wave_enemy_data = enemy_config[
|
|
|
- (enemy_config['关卡ID'] == level_id) &
|
|
|
- (enemy_config['波次ID'] == wave_id)
|
|
|
- ]
|
|
|
-
|
|
|
- for _, enemy_row in wave_enemy_data.iterrows():
|
|
|
- enemy_type = str(enemy_row['敌人类型']) if pd.notna(enemy_row['敌人类型']) else '普通僵尸'
|
|
|
-
|
|
|
- enemy_data = {
|
|
|
- 'enemyType': enemy_type,
|
|
|
- 'count': int(enemy_row['数量']) if pd.notna(enemy_row['数量']) else 1,
|
|
|
- 'spawnInterval': float(enemy_row['生成间隔']) if pd.notna(enemy_row['生成间隔']) else 2.0,
|
|
|
- 'spawnDelay': float(enemy_row['生成延迟']) if pd.notna(enemy_row['生成延迟']) else 0.0,
|
|
|
- 'characteristics': str(enemy_row['特征描述']) if pd.notna(enemy_row['特征描述']) else ''
|
|
|
- }
|
|
|
- wave_enemies.append(enemy_data)
|
|
|
-
|
|
|
- wave_data = {
|
|
|
- 'waveId': wave_id,
|
|
|
- 'enemies': wave_enemies
|
|
|
- }
|
|
|
- level_data['waves'].append(wave_data)
|
|
|
-
|
|
|
- config.append(level_data)
|
|
|
- print(f"处理关卡: {level_id}, 波次数: {len(level_data['waves'])}")
|
|
|
-
|
|
|
- print(f"成功解析关卡配置,共 {len(config)} 个关卡")
|
|
|
-
|
|
|
- except Exception as e:
|
|
|
- print(f"解析关卡多工作表数据时出错: {e}")
|
|
|
- import traceback
|
|
|
- traceback.print_exc()
|
|
|
-
|
|
|
- return config
|
|
|
+
|
|
|
|
|
|
def parse_skill_multi_sheet_data(self, all_sheets_data, filename):
|
|
|
"""解析技能配置的多工作表数据"""
|
|
|
@@ -1626,6 +1531,75 @@ class ConfigManagerGUI:
|
|
|
print(error_details)
|
|
|
messagebox.showerror("错误", f"启动敌人配置导入失败: {str(e)}\n\n详细错误信息已输出到控制台,请查看。")
|
|
|
|
|
|
+ def import_level_config(self):
|
|
|
+ """导入关卡配置"""
|
|
|
+ try:
|
|
|
+ if not LEVEL_MANAGER_AVAILABLE:
|
|
|
+ messagebox.showerror("错误", "关卡配置管理器不可用,请检查level_config_manager.py文件是否存在")
|
|
|
+ return
|
|
|
+
|
|
|
+ # 创建关卡配置管理器
|
|
|
+ excel_dir = Path(self.excel_dir)
|
|
|
+ level_excel_file = excel_dir / "关卡配置" / "关卡配置表.xlsx"
|
|
|
+ levels_dir = excel_dir.parent / "levels"
|
|
|
+
|
|
|
+ if not level_excel_file.exists():
|
|
|
+ messagebox.showwarning("警告", f"未找到关卡配置文件: {level_excel_file}")
|
|
|
+ return
|
|
|
+
|
|
|
+ if not levels_dir.exists():
|
|
|
+ messagebox.showwarning("警告", f"未找到关卡配置目录: {levels_dir}")
|
|
|
+ return
|
|
|
+
|
|
|
+ # 使用LevelConfigManager导入配置
|
|
|
+ level_manager = LevelConfigManager(
|
|
|
+ excel_path=str(level_excel_file),
|
|
|
+ levels_dir=str(levels_dir)
|
|
|
+ )
|
|
|
+
|
|
|
+ # 在后台线程中执行导入
|
|
|
+ def import_thread():
|
|
|
+ try:
|
|
|
+ success = level_manager.import_from_excel()
|
|
|
+
|
|
|
+ # 在主线程中更新UI
|
|
|
+ def update_ui():
|
|
|
+ if success:
|
|
|
+ messagebox.showinfo("成功", "关卡配置导入成功!")
|
|
|
+ self.status_var.set("关卡配置导入成功")
|
|
|
+ # 更新预览文本
|
|
|
+ self.preview_text.delete(1.0, tk.END)
|
|
|
+ self.preview_text.insert(tk.END, "关卡配置导入成功\n\n配置已从Excel文件合并到各个关卡JSON文件中")
|
|
|
+ else:
|
|
|
+ messagebox.showerror("错误", "关卡配置导入失败,请查看控制台输出")
|
|
|
+ self.status_var.set("关卡配置导入失败")
|
|
|
+
|
|
|
+ self.root.after(0, update_ui)
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ def show_error():
|
|
|
+ import traceback
|
|
|
+ error_details = traceback.format_exc()
|
|
|
+ print(f"导入关卡配置失败,详细错误信息:")
|
|
|
+ print(error_details)
|
|
|
+ messagebox.showerror("错误", f"导入关卡配置失败: {str(e)}\n\n详细错误信息已输出到控制台,请查看。")
|
|
|
+ self.status_var.set("关卡配置导入失败")
|
|
|
+
|
|
|
+ self.root.after(0, show_error)
|
|
|
+
|
|
|
+ # 启动导入线程
|
|
|
+ self.status_var.set("正在导入关卡配置...")
|
|
|
+ thread = threading.Thread(target=import_thread)
|
|
|
+ thread.daemon = True
|
|
|
+ thread.start()
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ import traceback
|
|
|
+ error_details = traceback.format_exc()
|
|
|
+ print(f"启动关卡配置导入失败,详细错误信息:")
|
|
|
+ print(error_details)
|
|
|
+ messagebox.showerror("错误", f"启动关卡配置导入失败: {str(e)}\n\n详细错误信息已输出到控制台,请查看。")
|
|
|
+
|
|
|
def _import_vertical_config(self):
|
|
|
"""导入纵向表格配置"""
|
|
|
# 读取现有JSON配置
|
|
|
@@ -1773,23 +1747,14 @@ class ConfigManagerGUI:
|
|
|
# 读取现有JSON配置
|
|
|
print(f"JSON配置文件路径: {self.selected_json_path}")
|
|
|
|
|
|
- # 检查是否是关卡配置(目录类型)
|
|
|
- if is_level_config:
|
|
|
- print("处理关卡配置目录...")
|
|
|
- # 关卡配置是目录,确保目录存在
|
|
|
- if not self.selected_json_path.exists():
|
|
|
- print(f"创建关卡配置目录: {self.selected_json_path}")
|
|
|
- self.selected_json_path.mkdir(parents=True, exist_ok=True)
|
|
|
- current_config = {}
|
|
|
+ # 普通JSON文件配置
|
|
|
+ if self.selected_json_path.exists():
|
|
|
+ print("读取现有JSON配置文件...")
|
|
|
+ with open(self.selected_json_path, 'r', encoding='utf-8') as f:
|
|
|
+ current_config = json.load(f)
|
|
|
else:
|
|
|
- # 普通JSON文件配置
|
|
|
- if self.selected_json_path.exists():
|
|
|
- print("读取现有JSON配置文件...")
|
|
|
- with open(self.selected_json_path, 'r', encoding='utf-8') as f:
|
|
|
- current_config = json.load(f)
|
|
|
- else:
|
|
|
- print("创建新的JSON配置...")
|
|
|
- current_config = {}
|
|
|
+ print("创建新的JSON配置...")
|
|
|
+ current_config = {}
|
|
|
|
|
|
# 根据用户选择的处理模式和数据类型处理
|
|
|
if not self.selected_files:
|
|
|
@@ -1805,164 +1770,50 @@ class ConfigManagerGUI:
|
|
|
is_single_json = self.single_json_var.get()
|
|
|
print(f"处理模式 - 多工作表: {is_multi_sheet}, 单个JSON: {is_single_json}")
|
|
|
|
|
|
- # 根据数据类型和用户选择的模式进行处理
|
|
|
- if is_level_config:
|
|
|
- # 关卡配置:始终为目录模式,每个关卡一个JSON文件
|
|
|
- print("处理关卡配置...")
|
|
|
- # 关卡配置:为每个关卡创建单独的JSON文件
|
|
|
- levels_dir = self.selected_json_path
|
|
|
- print(f"关卡配置目录: {levels_dir}")
|
|
|
-
|
|
|
- try:
|
|
|
- # 检查并创建目录
|
|
|
- if not levels_dir.exists():
|
|
|
- print(f"创建关卡配置目录: {levels_dir}")
|
|
|
- levels_dir.mkdir(parents=True, exist_ok=True)
|
|
|
- else:
|
|
|
- print(f"关卡配置目录已存在: {levels_dir}")
|
|
|
-
|
|
|
- # 测试目录写入权限
|
|
|
- test_file = levels_dir / "test_permission.tmp"
|
|
|
- try:
|
|
|
- with open(test_file, 'w', encoding='utf-8') as f:
|
|
|
- f.write("test")
|
|
|
- test_file.unlink() # 删除测试文件
|
|
|
- except PermissionError:
|
|
|
- messagebox.showerror("错误", f"没有写入权限到目录: {levels_dir}\n请检查目录权限或以管理员身份运行")
|
|
|
- return
|
|
|
-
|
|
|
- # 检查数据格式:多工作表数据 vs 传统items数据
|
|
|
- if isinstance(self.config_data, list):
|
|
|
- # 新的多工作表数据格式:直接是关卡数据列表
|
|
|
- print("使用多工作表数据格式")
|
|
|
- level_configs = self.config_data
|
|
|
- elif 'items' in self.config_data:
|
|
|
- # 传统的items数据格式:需要转换
|
|
|
- print("使用传统items数据格式")
|
|
|
- level_configs = []
|
|
|
- for item in items:
|
|
|
- level_data = self._convert_level_data(item)
|
|
|
- if level_data:
|
|
|
- level_configs.append(level_data)
|
|
|
- else:
|
|
|
- print(f"错误: 未知的关卡配置数据格式: {type(self.config_data)}")
|
|
|
- messagebox.showerror("错误", "关卡配置数据格式错误")
|
|
|
- return
|
|
|
-
|
|
|
- # 保存关卡配置文件
|
|
|
- updated_count = 0
|
|
|
- failed_count = 0
|
|
|
-
|
|
|
- for level_data in level_configs:
|
|
|
- try:
|
|
|
- if level_data and 'levelId' in level_data and level_data['levelId']:
|
|
|
- level_id = level_data['levelId']
|
|
|
- level_file = levels_dir / f"{level_id}.json"
|
|
|
-
|
|
|
- print(f"保存关卡配置: {level_file}")
|
|
|
- with open(level_file, 'w', encoding='utf-8') as f:
|
|
|
- json.dump(level_data, f, indent=2, ensure_ascii=False)
|
|
|
- updated_count += 1
|
|
|
- else:
|
|
|
- print(f"跳过无效的关卡数据: {level_data}")
|
|
|
- failed_count += 1
|
|
|
- except Exception as e:
|
|
|
- print(f"保存关卡配置时出错: {e}")
|
|
|
- failed_count += 1
|
|
|
- continue
|
|
|
-
|
|
|
- if updated_count > 0:
|
|
|
- message = f"关卡配置导入成功!\n更新了 {updated_count} 个关卡文件"
|
|
|
- if failed_count > 0:
|
|
|
- message += f"\n跳过了 {failed_count} 个无效配置"
|
|
|
- messagebox.showinfo("成功", message)
|
|
|
- self.status_var.set("关卡配置导入成功")
|
|
|
- else:
|
|
|
- messagebox.showerror("错误", "没有成功导入任何关卡配置\n请检查Excel文件格式和数据")
|
|
|
- self.status_var.set("关卡配置导入失败")
|
|
|
-
|
|
|
- except Exception as e:
|
|
|
- error_msg = f"关卡配置导入失败: {str(e)}"
|
|
|
- print(error_msg)
|
|
|
- messagebox.showerror("错误", error_msg)
|
|
|
- self.status_var.set("关卡配置导入失败")
|
|
|
-
|
|
|
- self.clear_selection()
|
|
|
+ # 根据用户选择的模式和数据内容进行处理
|
|
|
+ print("处理配置数据...")
|
|
|
+
|
|
|
+ # 根据数据类型自动识别配置类型
|
|
|
+ config_type = self._detect_config_type()
|
|
|
+ print(f"检测到配置类型: {config_type}")
|
|
|
+
|
|
|
+ if config_type == 'unknown':
|
|
|
+ print(f"警告: 无法识别的配置类型")
|
|
|
+ messagebox.showwarning("警告", f"无法识别配置类型\n请检查Excel文件的工作表名称或数据格式")
|
|
|
return
|
|
|
|
|
|
- else:
|
|
|
- # 非关卡配置:根据用户选择的模式和数据内容进行处理
|
|
|
- print("处理非关卡配置...")
|
|
|
-
|
|
|
- # 根据数据类型自动识别配置类型
|
|
|
- config_type = self._detect_config_type()
|
|
|
- print(f"检测到配置类型: {config_type}")
|
|
|
+ # 根据配置类型处理数据
|
|
|
+ if config_type == 'enemy':
|
|
|
+ print("敌人配置现在由EnemyConfigManager处理,请使用专门的敌人配置导入按钮")
|
|
|
+ messagebox.showwarning("提示", "敌人配置现在由专门的管理器处理,请使用'导入敌人配置'按钮")
|
|
|
+ return
|
|
|
+ elif config_type == 'weapon':
|
|
|
+ print("武器配置现在由WeaponConfigManager处理,请使用专门的武器配置导入按钮")
|
|
|
+ messagebox.showwarning("提示", "武器配置现在由专门的管理器处理,请使用'导入武器配置'按钮")
|
|
|
+ return
|
|
|
+ elif config_type == 'skill':
|
|
|
+ print("处理技能配置...")
|
|
|
+ if 'skills' not in current_config:
|
|
|
+ current_config['skills'] = []
|
|
|
+
|
|
|
+ updated_skills = []
|
|
|
+ for i, item in enumerate(items):
|
|
|
+ print(f"转换技能数据 {i+1}/{len(items)}: {item}")
|
|
|
+ skill_data = self._convert_skill_data(item)
|
|
|
+ if skill_data:
|
|
|
+ updated_skills.append(skill_data)
|
|
|
+ print(f"成功转换技能数据: {skill_data.get('id', 'Unknown')}")
|
|
|
+ else:
|
|
|
+ print(f"跳过无效的技能数据: {item}")
|
|
|
|
|
|
- if config_type == 'unknown':
|
|
|
- print(f"警告: 无法识别的配置类型")
|
|
|
- messagebox.showwarning("警告", f"无法识别配置类型\n请检查Excel文件的工作表名称或数据格式")
|
|
|
- return
|
|
|
+ print(f"总共转换了 {len(updated_skills)} 个技能配置")
|
|
|
+ current_config['skills'] = updated_skills
|
|
|
|
|
|
- # 根据配置类型处理数据
|
|
|
- if config_type == 'enemy':
|
|
|
- print("处理敌人配置...")
|
|
|
- if 'enemies' not in current_config:
|
|
|
- current_config['enemies'] = []
|
|
|
-
|
|
|
- updated_enemies = []
|
|
|
- for i, item in enumerate(items):
|
|
|
- print(f"转换敌人数据 {i+1}/{len(items)}: {item}")
|
|
|
- enemy_data = self._convert_enemy_data(item)
|
|
|
- if enemy_data:
|
|
|
- updated_enemies.append(enemy_data)
|
|
|
- print(f"成功转换敌人数据: {enemy_data['id']}")
|
|
|
- else:
|
|
|
- print(f"跳过无效的敌人数据: {item}")
|
|
|
-
|
|
|
- print(f"总共转换了 {len(updated_enemies)} 个敌人配置")
|
|
|
- current_config['enemies'] = updated_enemies
|
|
|
-
|
|
|
- elif config_type == 'weapon':
|
|
|
- print("处理武器配置...")
|
|
|
- if 'weapons' not in current_config:
|
|
|
- current_config['weapons'] = []
|
|
|
-
|
|
|
- updated_weapons = []
|
|
|
- for i, item in enumerate(items):
|
|
|
- print(f"转换武器数据 {i+1}/{len(items)}: {item}")
|
|
|
- weapon_data = self._convert_weapon_data(item)
|
|
|
- if weapon_data:
|
|
|
- updated_weapons.append(weapon_data)
|
|
|
- print(f"成功转换武器数据: {weapon_data.get('id', 'Unknown')}")
|
|
|
- else:
|
|
|
- print(f"跳过无效的武器数据: {item}")
|
|
|
-
|
|
|
- print(f"总共转换了 {len(updated_weapons)} 个武器配置")
|
|
|
- current_config['weapons'] = updated_weapons
|
|
|
-
|
|
|
- elif config_type == 'skill':
|
|
|
- print("处理技能配置...")
|
|
|
- if 'skills' not in current_config:
|
|
|
- current_config['skills'] = []
|
|
|
-
|
|
|
- updated_skills = []
|
|
|
- for i, item in enumerate(items):
|
|
|
- print(f"转换技能数据 {i+1}/{len(items)}: {item}")
|
|
|
- skill_data = self._convert_skill_data(item)
|
|
|
- if skill_data:
|
|
|
- updated_skills.append(skill_data)
|
|
|
- print(f"成功转换技能数据: {skill_data.get('id', 'Unknown')}")
|
|
|
- else:
|
|
|
- print(f"跳过无效的技能数据: {item}")
|
|
|
-
|
|
|
- print(f"总共转换了 {len(updated_skills)} 个技能配置")
|
|
|
- current_config['skills'] = updated_skills
|
|
|
-
|
|
|
- else:
|
|
|
- # 通用配置处理
|
|
|
- print(f"处理通用配置类型: {config_type}")
|
|
|
- # 直接使用items数据
|
|
|
- current_config['items'] = items
|
|
|
+ else:
|
|
|
+ # 通用配置处理
|
|
|
+ print(f"处理通用配置类型: {config_type}")
|
|
|
+ # 直接使用items数据
|
|
|
+ current_config['items'] = items
|
|
|
|
|
|
# 写入更新后的配置(关卡配置已在前面处理,跳过)
|
|
|
if not is_level_config:
|
|
|
@@ -2015,41 +1866,7 @@ class ConfigManagerGUI:
|
|
|
# 如果config_data是字典,合并到current_config
|
|
|
print(f"合并字典格式的配置数据")
|
|
|
|
|
|
- # 特殊处理武器配置,保留现有武器中表格没有的字段
|
|
|
- if 'weapons' in self.config_data and 'weapons' in current_config:
|
|
|
- print("检测到武器配置,执行智能合并以保留现有字段")
|
|
|
- new_weapons = self.config_data['weapons']
|
|
|
- existing_weapons = current_config['weapons']
|
|
|
-
|
|
|
- # 创建现有武器的ID映射
|
|
|
- existing_weapons_map = {}
|
|
|
- for weapon in existing_weapons:
|
|
|
- weapon_id = weapon.get('ID', '') or weapon.get('id', '')
|
|
|
- if weapon_id:
|
|
|
- existing_weapons_map[weapon_id] = weapon
|
|
|
-
|
|
|
- # 合并武器配置,保留现有字段
|
|
|
- merged_weapons = []
|
|
|
- for new_weapon_data in new_weapons:
|
|
|
- weapon_id = new_weapon_data.get('ID', '') or new_weapon_data.get('id', '')
|
|
|
- if weapon_id and weapon_id in existing_weapons_map:
|
|
|
- # 找到对应的现有武器,转换新数据时传入现有武器配置
|
|
|
- existing_weapon = existing_weapons_map[weapon_id]
|
|
|
- # 转换新武器数据,传入现有武器配置以保留特效字段
|
|
|
- converted_weapon = self._convert_weapon_data(new_weapon_data, existing_weapon)
|
|
|
- if converted_weapon:
|
|
|
- merged_weapons.append(converted_weapon)
|
|
|
- print(f"✓ 武器 {weapon_id} 已转换并保留了现有的特效字段")
|
|
|
- else:
|
|
|
- # 新武器,直接转换
|
|
|
- converted_weapon = self._convert_weapon_data(new_weapon_data)
|
|
|
- if converted_weapon:
|
|
|
- merged_weapons.append(converted_weapon)
|
|
|
- print(f"+ 新武器 {weapon_id} 已添加")
|
|
|
-
|
|
|
- # 更新武器配置
|
|
|
- self.config_data['weapons'] = merged_weapons
|
|
|
- print(f"武器配置合并完成,共 {len(merged_weapons)} 个武器")
|
|
|
+
|
|
|
|
|
|
current_config.update(self.config_data)
|
|
|
|
|
|
@@ -2074,26 +1891,7 @@ class ConfigManagerGUI:
|
|
|
# 刷新预览
|
|
|
self.clear_selection()
|
|
|
|
|
|
- def _deep_merge_weapon_config(self, existing_weapon, new_weapon):
|
|
|
- """深度合并武器配置,保留现有武器中表格没有的字段"""
|
|
|
- import copy
|
|
|
-
|
|
|
- # 创建新武器的深拷贝作为基础
|
|
|
- merged = copy.deepcopy(new_weapon)
|
|
|
-
|
|
|
- # 递归合并函数,将现有武器中新武器没有的字段添加到合并结果中
|
|
|
- def preserve_existing_fields(target, existing):
|
|
|
- for key, value in existing.items():
|
|
|
- if key not in target:
|
|
|
- # 现有武器有但新武器没有的字段,保留
|
|
|
- target[key] = copy.deepcopy(value)
|
|
|
- elif isinstance(target[key], dict) and isinstance(value, dict):
|
|
|
- # 如果两者都是字典,递归处理
|
|
|
- preserve_existing_fields(target[key], value)
|
|
|
-
|
|
|
- # 执行深度合并,保留现有武器中的额外字段
|
|
|
- preserve_existing_fields(merged, existing_weapon)
|
|
|
- return merged
|
|
|
+
|
|
|
|
|
|
def _detect_config_type(self):
|
|
|
"""根据数据内容和工作表名称自动识别配置类型"""
|
|
|
@@ -2107,8 +1905,7 @@ class ConfigManagerGUI:
|
|
|
return 'skill'
|
|
|
elif '武器配置' in str(self.config_data.keys()) or '武器信息' in self.config_data:
|
|
|
return 'weapon'
|
|
|
- elif any('关卡' in str(key) for key in self.config_data.keys()):
|
|
|
- return 'level'
|
|
|
+
|
|
|
|
|
|
# 检查数据内容中的字段来判断类型
|
|
|
if hasattr(self, 'config_data'):
|
|
|
@@ -2141,10 +1938,7 @@ class ConfigManagerGUI:
|
|
|
if weapon_fields.intersection(fields):
|
|
|
return 'weapon'
|
|
|
|
|
|
- # 关卡配置特征字段
|
|
|
- level_fields = {'levelId', 'name', 'enemies', 'waves'}
|
|
|
- if level_fields.intersection(fields):
|
|
|
- return 'level'
|
|
|
+
|
|
|
|
|
|
# 如果无法通过数据内容判断,尝试通过文件名判断(作为后备方案)
|
|
|
if hasattr(self, 'selected_files') and self.selected_files:
|
|
|
@@ -2155,8 +1949,7 @@ class ConfigManagerGUI:
|
|
|
return 'skill'
|
|
|
elif '武器' in filename:
|
|
|
return 'weapon'
|
|
|
- elif '关卡' in filename:
|
|
|
- return 'level'
|
|
|
+
|
|
|
|
|
|
return 'unknown'
|
|
|
|
|
|
@@ -2202,78 +1995,7 @@ class ConfigManagerGUI:
|
|
|
print(f"转换技能数据失败: {e} - 数据: {item}")
|
|
|
return None
|
|
|
|
|
|
- def _convert_level_data(self, item):
|
|
|
- """转换关卡数据格式"""
|
|
|
- try:
|
|
|
- # 如果item已经是完整的关卡数据结构(来自多工作表解析),直接返回
|
|
|
- if isinstance(item, dict) and 'waves' in item:
|
|
|
- return item
|
|
|
-
|
|
|
- # 处理传统的单行数据格式
|
|
|
- # 处理可用武器字符串,转换为数组(支持中英文字段名)
|
|
|
- available_weapons = []
|
|
|
- weapons_field = item.get('weapons', item.get('可用武器', ''))
|
|
|
- if weapons_field:
|
|
|
- weapons_str = str(weapons_field)
|
|
|
- # 支持逗号、顿号、分号等多种分隔符
|
|
|
- for separator in ['、', ',', ',', ';', ';']:
|
|
|
- if separator in weapons_str:
|
|
|
- available_weapons = [weapon.strip() for weapon in weapons_str.split(separator)]
|
|
|
- break
|
|
|
- # 如果没有找到分隔符,则作为单个武器处理
|
|
|
- if not available_weapons:
|
|
|
- available_weapons = [weapons_str.strip()]
|
|
|
-
|
|
|
- # 获取关卡ID,用于读取现有配置(支持中英文字段名)
|
|
|
- level_id = str(item.get('levelId', item.get('关卡ID', '')))
|
|
|
-
|
|
|
- # 尝试读取现有的关卡配置文件,保留waves数据
|
|
|
- existing_waves = []
|
|
|
- existing_data = {}
|
|
|
- if level_id:
|
|
|
- try:
|
|
|
- levels_dir = self.project_root / "assets/resources/data/levels"
|
|
|
- level_file = levels_dir / f"{level_id}.json"
|
|
|
- if level_file.exists():
|
|
|
- with open(level_file, 'r', encoding='utf-8') as f:
|
|
|
- existing_data = json.load(f)
|
|
|
- existing_waves = existing_data.get('waves', [])
|
|
|
- print(f"保留现有关卡 {level_id} 的 {len(existing_waves)} 个波次数据")
|
|
|
- except Exception as e:
|
|
|
- print(f"读取现有关卡配置时出错: {e}")
|
|
|
-
|
|
|
- # 构建新的关卡数据,保留现有的waves(支持中英文字段名)
|
|
|
- level_data = {
|
|
|
- "levelId": level_id,
|
|
|
- "name": str(item.get('name', item.get('关卡名称', existing_data.get('name', '')))),
|
|
|
- "scene": str(item.get('scene', item.get('场景', existing_data.get('scene', '')))),
|
|
|
- "description": str(item.get('description', item.get('描述', existing_data.get('description', '')))),
|
|
|
- "backgroundImage": str(item.get('backgroundImage', item.get('关卡背景图路径', existing_data.get('backgroundImage', 'images/LevelBackground/BG1')))),
|
|
|
- "weapons": available_weapons if available_weapons else existing_data.get('weapons', existing_data.get('availableWeapons', [])),
|
|
|
- "timeLimit": int(item.get('timeLimit', item.get('时间限制', existing_data.get('timeLimit', 300)))),
|
|
|
- "difficulty": str(item.get('difficulty', item.get('难度', existing_data.get('difficulty', 'normal')))),
|
|
|
- "healthMultiplier": float(item.get('healthMultiplier', item.get('生命倍数', existing_data.get('healthMultiplier', 1.0)))),
|
|
|
- "waves": existing_waves # 保留现有的waves数据
|
|
|
- }
|
|
|
-
|
|
|
- # 添加可选字段(如果存在,支持中英文字段名)
|
|
|
- coin_reward = item.get('coinReward', item.get('钞票奖励'))
|
|
|
- if coin_reward is not None:
|
|
|
- level_data["coinReward"] = int(coin_reward)
|
|
|
- elif 'coinReward' in existing_data:
|
|
|
- level_data["coinReward"] = existing_data['coinReward']
|
|
|
-
|
|
|
- diamond_reward = item.get('diamondReward', item.get('钻石奖励'))
|
|
|
- if diamond_reward is not None:
|
|
|
- level_data["diamondReward"] = int(diamond_reward)
|
|
|
- elif 'diamondReward' in existing_data:
|
|
|
- level_data["diamondReward"] = existing_data['diamondReward']
|
|
|
-
|
|
|
- return level_data
|
|
|
-
|
|
|
- except Exception as e:
|
|
|
- print(f"转换关卡数据时出错: {e}")
|
|
|
- return None
|
|
|
+
|
|
|
|
|
|
|
|
|
|