yyl
5 小时以前 30ba2ef747ced774bef177d5273cb5a3429cff49
130 子 【战斗】战斗系统 / 【战斗】战斗系统-客户端 部分战斗逻辑
90个文件已修改
41个文件已添加
2612 ■■■■ 已修改文件
Main/Config/ConfigManager.cs 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/AppointItemConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/AudioConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/CTGConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/CTGSelectItemConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ChatBubbleBoxConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ChestsAwardConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ChestsConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/DailyLivenessRewardConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/DailyQuestConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/DailyQuestOpenTimeConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/DienstgradConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/DirtyNameConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/DirtyWordConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/EffectConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/EmojiPackConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/EquipGSParamConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/EquipPlaceMapConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FaceConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FamilyConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FamilyEmblemConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FirstGoldConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FuncConfigConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FuncOpenLVConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/FunctionTeamSetConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/GetItemWaysConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/GmCmdConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/GuideConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroAwakeConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroBreakConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroConfig.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroFetterConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroQualityAwakeConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroQualityBreakConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroQualityConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroSkinConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroTalentConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/IconConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/InitialFunctionConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/ItemConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/KickOutReasonConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/LanguageConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/MailConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/NPCConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/NPCExConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/OrderInfoConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/PlayerFaceConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/PlayerFacePicConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/PlayerFacePicStarConfig.cs 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/PlayerFacePicStarConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/PlayerFaceStarConfig.cs 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/PlayerFaceStarConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/PlayerLVConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/PlayerPropertyConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/PriorLanguageConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/RealmConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/RealmLVUPTaskConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/RichTextMsgReplaceConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/RuleConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/SkillConfig.cs 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/StoreConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/SuccessConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/SysInfoConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/TaskConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/TitleStarUpConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/TreasureCntAwardConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/TreasureItemLibConfig.cs 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/TreasureSetConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/XBGetItemConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/priorbundleConfig.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Main.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Manager/UIManager.cs 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/BattleField.cs 136 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/BattleRootNode.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/BattleRootNode.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/AIOperationAgent.cs 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/AIOperationAgent.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/AutoModeOperationAgent.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/AutoModeOperationAgent.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/IOperationAgent.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/IOperationAgent.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/RecordModeOperationAgent.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/OperationAgent/RecordModeOperationAgent.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/RecordActions.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/RecordActions/SkillRecordAction.cs 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/RecordActions/SkillRecordAction.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/StoryBattleField.cs 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleManager.cs 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleObject/BattleObjMgr.cs 198 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleObject/BattleObject.cs 458 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleObject/BattleObjectFactory.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleWin.cs 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Buff.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define/DamageType.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define/DamageType.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define/SkillTargetRangeType.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define/SkillTargetRangeType.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define/SkillTargetType.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Define/SkillTargetType.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Motion/MotionBase.cs 99 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Motion/MotionName.cs 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/RecordPlayer/RecordAction.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/RecordPlayer/RecordActionType.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/RecordPlayer/RecordPlayer.cs 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/DirectlyDamageSkill.cs 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/DirectlyDamageSkill.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/SkillBase.cs 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/SkillBase.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/SkillFactory.cs 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/Skill/SkillFactory.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Hero/HeroInfo.Properties.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Hero/HeroInfo.cs 57 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Hero/HeroManager.cs 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Main/MainWin.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Team/TeamBase.Properties.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Team/TeamBase.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Team/TeamConst.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Team/TeamHero.Properties.cs 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Team/TeamHero.Properties.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Team/TeamHero.State.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Team/TeamHero.State.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Team/TeamHero.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Team/TeamManager.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/UniTaskExtension.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/VesselExtension.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/ConfigManager.cs
@@ -33,7 +33,7 @@
        isLoadFinished = false;
        // 加载配置文件
        int totalConfigs = 63;
        int totalConfigs = 65;
        Type[] configTypes = new Type[] {
            typeof(AppointItemConfig),
            typeof(AudioConfig),
@@ -81,6 +81,8 @@
            typeof(OrderInfoConfig),
            typeof(PlayerFaceConfig),
            typeof(PlayerFacePicConfig),
            typeof(PlayerFacePicStarConfig),
            typeof(PlayerFaceStarConfig),
            typeof(PlayerLVConfig),
            typeof(PlayerPropertyConfig),
            typeof(priorbundleConfig),
@@ -286,6 +288,10 @@
        ClearConfigDictionary<PlayerFaceConfig>();
        // 清空 PlayerFacePicConfig 字典
        ClearConfigDictionary<PlayerFacePicConfig>();
        // 清空 PlayerFacePicStarConfig 字典
        ClearConfigDictionary<PlayerFacePicStarConfig>();
        // 清空 PlayerFaceStarConfig 字典
        ClearConfigDictionary<PlayerFaceStarConfig>();
        // 清空 PlayerLVConfig 字典
        ClearConfigDictionary<PlayerLVConfig>();
        // 清空 PlayerPropertyConfig 字典
Main/Config/Configs/AppointItemConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/AudioConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/CTGConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/CTGSelectItemConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/ChatBubbleBoxConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月18日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/ChestsAwardConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/ChestsConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/DailyLivenessRewardConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月18日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/DailyQuestConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月18日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/DailyQuestOpenTimeConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月18日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/DienstgradConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/DirtyNameConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Tuesday, June 17, 2025
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/DirtyWordConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/EffectConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/EmojiPackConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/EquipGSParamConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月17日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/EquipPlaceMapConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月17日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/FaceConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/FamilyConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Wednesday, June 18, 2025
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/FamilyEmblemConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月18日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/FirstGoldConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月15日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/FuncConfigConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/FuncOpenLVConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/FunctionTeamSetConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/GetItemWaysConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/GmCmdConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/GuideConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/HeroAwakeConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月13日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/HeroBreakConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月13日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/HeroConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月16日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
@@ -24,6 +24,11 @@
    public int HPInheritPer;
    public string BatAttrDict;
    public int[] FetterIDList;
    public string Tachie;
    public string SquareIcon;
    public string RectangleIcon;
    public string SpineRes;
    public string BigSizeSpine;
    public override int LoadKey(string _key)
    {
@@ -80,6 +85,16 @@
                     int.TryParse(FetterIDListStringArray[i],out FetterIDList[i]);
                }
            }
            Tachie = tables[11];
            SquareIcon = tables[12];
            RectangleIcon = tables[13];
            SpineRes = tables[14];
            BigSizeSpine = tables[15];
        }
        catch (Exception exception)
        {
Main/Config/Configs/HeroFetterConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月16日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/HeroQualityAwakeConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月13日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/HeroQualityBreakConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月13日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/HeroQualityConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月13日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/HeroSkinConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月13日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/HeroTalentConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月13日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/IconConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/InitialFunctionConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/ItemConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/KickOutReasonConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/LanguageConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/MailConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/NPCConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/NPCExConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/OrderInfoConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/PlayerFaceConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/PlayerFacePicConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/PlayerFacePicStarConfig.cs
New file
@@ -0,0 +1,74 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System;
using UnityEngine;
using LitJson;
public partial class PlayerFacePicStarConfig : ConfigBase<int, PlayerFacePicStarConfig>
{
    public int index;
    public int FacePicID;
    public int FacePicStar;
    public int[][] StarUpNeedItemList;
    public int[] StarAttrType;
    public int[] StarAttrValue;
    public override int LoadKey(string _key)
    {
        int key = GetKey(_key);
        return key;
    }
    public override void LoadConfig(string input)
    {
        try {
        string[] tables = input.Split('\t');
        int.TryParse(tables[0],out index);
            int.TryParse(tables[1],out FacePicID);
            int.TryParse(tables[2],out FacePicStar);
            StarUpNeedItemList = JsonMapper.ToObject<int[][]>(tables[3].Replace("(", "[").Replace(")", "]"));
            if (tables[4].Contains("["))
            {
                StarAttrType = JsonMapper.ToObject<int[]>(tables[4]);
            }
            else
            {
                string[] StarAttrTypeStringArray = tables[4].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                StarAttrType = new int[StarAttrTypeStringArray.Length];
                for (int i=0;i<StarAttrTypeStringArray.Length;i++)
                {
                     int.TryParse(StarAttrTypeStringArray[i],out StarAttrType[i]);
                }
            }
            if (tables[5].Contains("["))
            {
                StarAttrValue = JsonMapper.ToObject<int[]>(tables[5]);
            }
            else
            {
                string[] StarAttrValueStringArray = tables[5].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                StarAttrValue = new int[StarAttrValueStringArray.Length];
                for (int i=0;i<StarAttrValueStringArray.Length;i++)
                {
                     int.TryParse(StarAttrValueStringArray[i],out StarAttrValue[i]);
                }
            }
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/PlayerFacePicStarConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 71543467d1c8a4544b1e0441440327cb
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/Configs/PlayerFaceStarConfig.cs
New file
@@ -0,0 +1,74 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System;
using UnityEngine;
using LitJson;
public partial class PlayerFaceStarConfig : ConfigBase<int, PlayerFaceStarConfig>
{
    public int index;
    public int FaceID;
    public int FaceStar;
    public int[][] StarUpNeedItemList;
    public int[] StarAttrType;
    public int[] StarAttrValue;
    public override int LoadKey(string _key)
    {
        int key = GetKey(_key);
        return key;
    }
    public override void LoadConfig(string input)
    {
        try {
        string[] tables = input.Split('\t');
        int.TryParse(tables[0],out index);
            int.TryParse(tables[1],out FaceID);
            int.TryParse(tables[2],out FaceStar);
            StarUpNeedItemList = JsonMapper.ToObject<int[][]>(tables[3].Replace("(", "[").Replace(")", "]"));
            if (tables[4].Contains("["))
            {
                StarAttrType = JsonMapper.ToObject<int[]>(tables[4]);
            }
            else
            {
                string[] StarAttrTypeStringArray = tables[4].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                StarAttrType = new int[StarAttrTypeStringArray.Length];
                for (int i=0;i<StarAttrTypeStringArray.Length;i++)
                {
                     int.TryParse(StarAttrTypeStringArray[i],out StarAttrType[i]);
                }
            }
            if (tables[5].Contains("["))
            {
                StarAttrValue = JsonMapper.ToObject<int[]>(tables[5]);
            }
            else
            {
                string[] StarAttrValueStringArray = tables[5].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
                StarAttrValue = new int[StarAttrValueStringArray.Length];
                for (int i=0;i<StarAttrValueStringArray.Length;i++)
                {
                     int.TryParse(StarAttrValueStringArray[i],out StarAttrValue[i]);
                }
            }
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/PlayerFaceStarConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ccdffb3c82145e64cb12c26fccdfa818
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/Configs/PlayerLVConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月25日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/PlayerPropertyConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月17日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/PriorLanguageConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/RealmConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月25日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/RealmLVUPTaskConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月25日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/RichTextMsgReplaceConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/RuleConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/SkillConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
@@ -80,17 +80,14 @@
    public int ExAttr3;
    public int ExAttr4;
    public int ExAttr5;
    public int WarnInfo;
    public int CtrlActionID;
    public int BuffEffectID;
    public int EffectName;
    public string IconName;
    public string SkillNameIcon;
    public string Description;
    public string BuffDescription;
    public string Skillsource;
    public int Skillactmark;
    public int BuffDisplay;
    public int CastPosition;
    public override int LoadKey(string _key)
    {
@@ -236,27 +233,21 @@
            int.TryParse(tables[66],out ExAttr5); 
            int.TryParse(tables[67],out WarnInfo);
            int.TryParse(tables[67],out BuffEffectID);
            int.TryParse(tables[68],out CtrlActionID);
            int.TryParse(tables[68],out EffectName);
            int.TryParse(tables[69],out BuffEffectID);
            IconName = tables[69];
            int.TryParse(tables[70],out EffectName);
            Description = tables[70];
            IconName = tables[71];
            BuffDescription = tables[71];
            SkillNameIcon = tables[72];
            int.TryParse(tables[72],out Skillactmark);
            Description = tables[73];
            int.TryParse(tables[73],out BuffDisplay);
            BuffDescription = tables[74];
            Skillsource = tables[75];
            int.TryParse(tables[76],out Skillactmark);
            int.TryParse(tables[77],out BuffDisplay);
            int.TryParse(tables[74],out CastPosition);
        }
        catch (Exception exception)
        {
Main/Config/Configs/StoreConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/SuccessConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/SysInfoConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/TaskConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月26日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/TitleStarUpConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/TreasureCntAwardConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月17日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/TreasureItemLibConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月17日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
@@ -13,7 +13,8 @@
public partial class TreasureItemLibConfig : ConfigBase<int, TreasureItemLibConfig>
{
    public int LibID;
    public int ID;
    public int LibID;
    public int ItemID;
    public int ItemCount;
@@ -27,11 +28,13 @@
    {
        try {
        string[] tables = input.Split('\t');
        int.TryParse(tables[0],out LibID);
        int.TryParse(tables[0],out ID);
            int.TryParse(tables[1],out ItemID);
            int.TryParse(tables[1],out LibID);
            int.TryParse(tables[2],out ItemCount);
            int.TryParse(tables[2],out ItemID);
            int.TryParse(tables[3],out ItemCount);
        }
        catch (Exception exception)
        {
Main/Config/Configs/TreasureSetConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月17日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/XBGetItemConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年6月17日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Config/Configs/priorbundleConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年5月22日
//    [  Date ]:           Friday, June 27, 2025
//--------------------------------------------------------
using System.Collections.Generic;
Main/Main.cs
@@ -93,7 +93,8 @@
    public static void OnSwitchToLoginScene()
    {
        ReleaseMgrs();
        //  前面有重新InitManagers了 这里就不在做清除
        // ReleaseMgrs();
    }
    private static void ReleaseMgrs()
Main/Manager/UIManager.cs
@@ -30,8 +30,13 @@
    private Transform loadingTrans;
    // UI字典,存储所有已加载的UI,键为UI名称,值为UI实例
    private Dictionary<string, List<UIBase>> uiDict = new Dictionary<string, List<UIBase>>();
#if UNITY_EDITOR
    public
#else
    private
#endif
    Dictionary<string, List<UIBase>> uiDict = new Dictionary<string, List<UIBase>>();
    // 存储关闭但未销毁的UI,键为UI名称,值为UI实例
    private Dictionary<string, List<UIBase>> closedUIDict = new Dictionary<string, List<UIBase>>();
Main/System/Battle/BattleField/BattleField.cs
@@ -1,22 +1,82 @@
using System.Collections.Generic;
using UnityEngine;
public class BattleField
{
    public BattleMode battleMode;
    public BattleObjMgr battleObjMgr;
    public RecordPlayer recordPlayer;
    public IOperationAgent operationAgent;
    public int round = 0;
    public bool IsActive
    {
        get;
        protected set;
    }
    public bool IsBattleFinish
    {
        get;
        protected set;
    }
    public virtual bool IsPvp
    {
        get
        {
            return false;
        }
    }
    private bool m_IsPause = false;
    public bool IsPause
    {
        get
        {
            return m_IsPause;
        }
        protected set
        {
            m_IsPause = value;
            if (m_IsPause)
            {
                PauseGame();
            }
            else
            {
                ResumeGame();
            }
        }
    }
    public BattleRootNode battleRootNode;
    private BattleMode battleMode;
    public virtual void Init(TeamBase _redTeam, TeamBase _blueTeam)
    {
        GameObject go = ResManager.Instance.LoadAsset<GameObject>("Battle/Prefabs", "BattleRootNode");
        GameObject battleRootNodeGO = GameObject.Instantiate(go);
        battleRootNode = battleRootNodeGO.GetComponent<BattleRootNode>();
        battleRootNodeGO.name = this.GetType().Name;
        battleObjMgr = new BattleObjMgr();
        battleObjMgr.Init(_redTeam, _blueTeam);
        battleObjMgr.Init(this, _redTeam, _blueTeam);
        recordPlayer = new RecordPlayer();
        recordPlayer.Init(this);
    }
    //  在Run之前要设置完毕 要创建Agent
    public void SetBattleMode(BattleMode _battleMode)
    {
        battleMode = _battleMode;
        CreateAgent();
    }
    public virtual void Release()
@@ -26,13 +86,47 @@
    public virtual void Run()
    {
        if (IsPause)
            return;
        if (IsRoundReachLimit())
        {
            return;
        }
        recordPlayer.Run();
        battleObjMgr.Run();
        if (operationAgent == null)
        {
            Debug.LogError("you should SetBattleMode before Run");
            return;
        }
        operationAgent.Run();
    }
    public void SetBattleMode(BattleMode _battleMode)
    protected virtual void CreateAgent()
    {
        battleMode = _battleMode;
        // Hand,//手动战斗
        // Auto,//自动战斗
        // Record,//战报
        switch (battleMode)
        {
            case BattleMode.Hand:
                operationAgent = new HandModeOperationAgent(this);
                break;
            case BattleMode.Auto:
                operationAgent = new AutoModeOperationAgent(this);
                break;
            case BattleMode.Record:
                operationAgent = new RecordModeOperationAgent(this);
                break;
            default:
                operationAgent = new HandModeOperationAgent(this);
                break;
        }
    }
    public virtual void PlayRecord(RecordAction recordAction)
@@ -45,33 +139,21 @@
        recordPlayer.PlayRecord(recordList);
    }
    public virtual void OnActionOver(int attackId)
    {
        //
// 手动推点一下发一个包 收一个包 播放一次报文 之后就停住 直到战斗结束的包文
// 自动的话 自动发包 播放报文 后 请求下一个包 循环 直到战斗结束的包文
// 战报播放就是一直播放战报 知道战斗结束的包文
        if (battleMode == BattleMode.Auto)
        {
            // Request next action
        }
        else if (battleMode == BattleMode.Record)
        {
            // Play next record
        }
        else
        {
            // Wait for user input
        }
    }
    public virtual void ResumeGame()
    protected virtual void ResumeGame()
    {
        battleObjMgr.ResumeGame();
        recordPlayer.ResumeGame();
    }
    public virtual void PauseGame()
    protected virtual void PauseGame()
    {
        battleObjMgr.PauseGame();
        recordPlayer.PauseGame();
    }
    public bool IsRoundReachLimit()
    {
        // return round > xxx;
        return false;
    }
}
Main/System/Battle/BattleField/BattleRootNode.cs
New file
@@ -0,0 +1,14 @@
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
public class BattleRootNode : MonoBehaviour
{
    public List<GameObject> redTeamNodeList = new List<GameObject>();
    public List<GameObject> blueTeamNodeList = new List<GameObject>();
    public RawImage imgBackground;
}
Main/System/Battle/BattleField/BattleRootNode.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7ff74171c89d45d46995ac2dd01acd80
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleField/OperationAgent.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7659a019bc5e73b45b9d0cea3bba2e4a
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleField/OperationAgent/AIOperationAgent.cs
New file
@@ -0,0 +1,171 @@
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
// 自己推进战斗的 Editor下使用就好
public class AIOperationAgent : IOperationAgent
{
    protected List<BattleObject> attackList = new List<BattleObject>();
    public AIOperationAgent(BattleField _battleField) : base (_battleField)
    {
    }
    public override void Run()
    {
        base.Run();
        bool isBattleBegin = battleField.round == 0 && attackList.Count <= 0;
        bool isRoundBegin = attackList.Count <= 0;
        if (attackList.Count <= 0 && !battleField.recordPlayer.IsPlaying())
        {
            // 战斗开始前,根据各自上阵武将战力之和决定谁为先攻方,战力之和高的为先攻主,先攻方优先攻击,确定先攻方后开始战斗。
            attackList.AddRange(battleField.battleObjMgr.redCampList);
            attackList.AddRange(battleField.battleObjMgr.blueCampList);
            // //    排序 战斗力高的靠前
            // attackList.Sort((a, b) => {
            //     int power1 = a.teamHero.GetPower();
            //     int power2 = b.teamHero.GetPower();
            //     return power2.CompareTo(power1);
            // });
            battleField.round++;
        }
        if (!battleField.recordPlayer.IsPlaying() && attackList.Count > 0)
        {
            List<RecordAction> playList = new List<RecordAction>();
            if (isBattleBegin)
            {
                playList.AddRange(CreateBattleBeginActionList());
            }
            else
            {
                if (isRoundBegin)
                {
                    playList.AddRange(CreateRoundBeginActionList());
                }
                else
                {
                    playList.AddRange(CreateActions(attackList[0]));
                    attackList.RemoveAt(0);
                }
            }
            battleField.recordPlayer.PlayRecord(playList);
        }
    }
    protected List<RecordAction> CreateBattleBeginActionList()
    {
        //    战斗开始前的轮次的操作
        List<RecordAction> returnList = new List<RecordAction>();
        // attackList
        return returnList;
    }
    protected List<RecordAction> CreateRoundBeginActionList()
    {
        //    每轮开始前的操作
        List<RecordAction> returnList = new List<RecordAction>();
        // attackList
        return returnList;
    }
    protected List<RecordAction> CreateActions(BattleObject _battleObj)
    {
        List<RecordAction> returnList = new List<RecordAction>();
        List<RecordAction> beforeActionList = CreateBeforeActionActionList(_battleObj);
        List<RecordAction> actionList = CreateActionList(_battleObj);
        List<RecordAction> afterActionList = CreateAfterActionList(_battleObj);
        List<RecordAction> afterDeathActionList = CreateAfterDeathActionList(_battleObj);
        returnList.AddRange(beforeActionList);
        returnList.AddRange(actionList);
        returnList.AddRange(afterActionList);
        returnList.AddRange(afterDeathActionList);
        return returnList;
    }
    protected List<RecordAction> CreateBeforeActionActionList(BattleObject _battleObj)
    {
        // 解异常 加减buff
        List<RecordAction> returnList = new List<RecordAction>();
        return returnList;
    }
    protected List<RecordAction> CreateActionList(BattleObject _battleObj)
    {
        //    放技能 或者被眩晕
        List<RecordAction> returnList = new List<RecordAction>();
        // //    能行动
        // if (_battleObj.IsCanDoActions())
        // {
        //     //    能放技能
        //     if (_battleObj.IsCanCastSkill())
        //     {
        //         SkillRecordAction action = new SkillRecordAction(_battleObj.teamHero.heroInfo.heroConfig.AngerSkillID,
        //             battleField, _battleObj);
        //         // 在这里主动做一下伤害计算 正常都是服务器给的
        //         returnList.Add(action);
        //     }
        //     else
        //     {
        //         //普攻
        //     }
        // }
        // else
        // {
        //     //    不能行动 飘字 过
        // }
        return returnList;
    }
    protected List<RecordAction> CreateAfterActionList(BattleObject _battleObj)
    {
        //    其他角色可能有连携攻击 有可能每回合buff有个dot
        List<RecordAction> returnList = new List<RecordAction>();
        return returnList;
    }
    protected List<RecordAction> CreateAfterDeathActionList(BattleObject _battleObj)
    {
        //    复活 给其他角色加buff之类的操作
        List<RecordAction> returnList = new List<RecordAction>();
        return returnList;
    }
    protected void OnHeroDeath(BattleObject _battleObj)
    {
    }
    protected void OnReviveHero(BattleObject _battleObj)
    {
    }
    public override void DoNext()
    {
        base.DoNext();
    }
}
Main/System/Battle/BattleField/OperationAgent/AIOperationAgent.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 90516a907f902eb4b9fd00896d54f896
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleField/OperationAgent/AutoModeOperationAgent.cs
New file
@@ -0,0 +1,35 @@
using UnityEngine;
public class AutoModeOperationAgent : IOperationAgent
{
    public AutoModeOperationAgent(BattleField battleField) : base(battleField)
    {
    }
    public override void Run()
    {
        if (!battleField.IsBattleFinish)
        {
            return;
        }
        base.Run();
        if (!battleField.recordPlayer.IsPlaying())
        {
            DoNext();
        }
    }
    public override void DoNext()
    {
        base.DoNext();
        if (!battleField.recordPlayer.IsPlaying())
        {
            //    ask for next action
        }
    }
}
Main/System/Battle/BattleField/OperationAgent/AutoModeOperationAgent.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3c8b7e2da006e7e4bb1274bb6818582c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs
New file
@@ -0,0 +1,30 @@
using UnityEngine;
public class HandModeOperationAgent : IOperationAgent
{
    public HandModeOperationAgent(BattleField battleField) : base(battleField)
    {
    }
    public override void Run()
    {
        base.Run();
    }
    //    通过主界面的按钮推动(调用)DoNext
    public override void DoNext()
    {
        base.DoNext();
        if (!battleField.recordPlayer.IsPlaying())
        {
            //    ask for next action
        }
        else
        {
            Debug.LogError("action doesnt finish, wait a moment please");
        }
    }
}
Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4693561ca16ed084baf04d0e7734f77d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleField/OperationAgent/IOperationAgent.cs
New file
@@ -0,0 +1,21 @@
public class IOperationAgent
{
    protected BattleField battleField;
    public IOperationAgent(BattleField _battleField)
    {
        battleField = _battleField;
    }
    public virtual void Run()
    {
    }
    public virtual void DoNext()
    {
    }
}
Main/System/Battle/BattleField/OperationAgent/IOperationAgent.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 137d74c25e4a988499579eb125835572
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleField/OperationAgent/RecordModeOperationAgent.cs
New file
@@ -0,0 +1,21 @@
using UnityEngine;
//    record直接全程播放就好了 不需要其他操作
public class RecordModeOperationAgent : IOperationAgent
{
    public RecordModeOperationAgent(BattleField battleField) : base(battleField)
    {
    }
    public override void Run()
    {
        base.Run();
    }
    public override void DoNext()
    {
        base.DoNext();
    }
}
Main/System/Battle/BattleField/OperationAgent/RecordModeOperationAgent.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 53b0f76e227371a46bc723a879c9953e
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleField/RecordActions.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 919949b557d0dc44ea63f47262263f21
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleField/RecordActions/SkillRecordAction.cs
New file
@@ -0,0 +1,87 @@
using UnityEngine;
using System.Collections.Generic;
public class SkillRecordAction : RecordAction
{
    public int SkillId;
    public SkillConfig skillConfig;
    protected SkillBase skillBase;
    protected List<Dictionary<int, List<int>>> damageList = new List<Dictionary<int, List<int>>>();
    private bool isCast = false;
    public SkillRecordAction(int _SkillId, BattleField _battleField, BattleObject _battleObj)
        : base(RecordActionType.Skill, _battleField, _battleObj)
    {
        SkillId = _SkillId;
        skillConfig = SkillConfig.Get(SkillId);
        if (null == skillConfig)
        {
            Debug.LogError("找不到技能配置 " + SkillId);
        }
        skillBase = SkillFactory.CreateSkill(skillConfig);
        // _battleObj使用了SkillId的技能
        damageList = skillBase.GetDamageList(battleObject, battleField);
    }
    public SkillRecordAction(int _SkillId, BattleField _battleField, BattleObject _battleObj, List<Dictionary<int, List<int>>> _damageList)
        : base(RecordActionType.Skill, _battleField, _battleObj)
    {
        SkillId = _SkillId;
        skillConfig = SkillConfig.Get(SkillId);
        if (null == skillConfig)
        {
            Debug.LogError("找不到技能配置 " + SkillId);
        }
        skillBase = SkillFactory.CreateSkill(skillConfig);
        damageList = _damageList;
        // _battleObj使用了SkillId的技能
    }
    public override bool IsFinished()
    {
        return skillBase.IsFinished();
    }
    public override void Run()
    {
        base.Run();
        if (null == skillBase)
        {
            return;
        }
        if (!skillBase.IsFinished())
        {
            skillBase.Run();
        }
        if (isCast)
            return;
        if (damageList.Count > 0)
        {
            skillBase.Cast(battleObject, battleField, damageList);
        }
        else
        {
            skillBase.ForceFinished();
        }
        isCast = true;
    }
}
Main/System/Battle/BattleField/RecordActions/SkillRecordAction.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c72895dea8c70844c9019d54023fbeb0
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleField/StoryBattleField.cs
@@ -6,15 +6,22 @@
{
    public override void Init(TeamBase _redTeam, TeamBase _blueTeam)
    {
        base.Init(_redTeam, _blueTeam);
        string savedStr = LocalSave.GetString("StoryBattleFieldBattleMode");
        if (string.IsNullOrEmpty(savedStr))
        {
            savedStr = "Hand";
        }
        battleMode = (BattleMode)Enum.Parse(typeof(BattleMode), savedStr);
        base.Init(_redTeam, _blueTeam);
        SetBattleMode((BattleMode)Enum.Parse(typeof(BattleMode), savedStr));
    }
    // public override void Run()
    // {
    //     //  一定要记住这个
    //     if (IsPause)
    //         return;
    //     base.Run();
    // }
}
Main/System/Battle/BattleManager.cs
@@ -5,18 +5,24 @@
public class BattleManager : GameSystemManager<BattleManager>
{
    public StoryBattleField storyBattleField = new StoryBattleField();//主线战场
    public StoryBattleField storyBattleField = null;
    protected Dictionary<int, BattleField> battleFields = new Dictionary<int, BattleField>();
    protected LogicUpdate logicUpdate = new LogicUpdate();
    public override void Init()
    {
        base.Init();
        StartStoryBattle();
        logicUpdate.Start(Run);
    }
    public override void Release()
    {
        Debug.LogError("who release this one");
        base.Release();
        logicUpdate.Destroy();
    }
    public void StartStoryBattle()
@@ -25,9 +31,27 @@
        {
            storyBattleField = new StoryBattleField();
            TeamBase redTeam = GetStoryTeam();//TeamManager.Instance.GetTeam(TeamType.Story);
            TeamBase blueTeam = GetStoryTeam();
            storyBattleField.Init(/*这里要加个创建背景的*/redTeam, blueTeam);
            // storyBattleField.Start();
            storyBattleField.battleRootNode.transform.SetParent(Launch.Instance.transform);
        }
    }
    private TeamBase GetStoryTeam()
    {
        TeamBase teamBase = new TeamBase();
        #if UNITY_EDITOR
        teamBase.FillWithFakeData();
        #else
        //  YYL TODO
        //  根据配表塞英雄 后面可能还要塞其他东西 先放在这里反正 做主线了再转移
        #endif
        return teamBase;
    }
    public void Run()
    {
        if (null != storyBattleField)
Main/System/Battle/BattleObject/BattleObjMgr.cs
@@ -2,21 +2,28 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class BattleObjMgr : Singleton<BattleObjMgr>
public class BattleObjMgr
{
    private List<BattleObject> redCampList => new List<BattleObject>(redCampDict.Values);
    private List<BattleObject> blueCampList => new List<BattleObject>(blueCampDict.Values);
    //  死亡不可以将BattleObject移出字典/列表
    public List<BattleObject> redCampList => new List<BattleObject>(redCampDict.Values);
    public List<BattleObject> blueCampList => new List<BattleObject>(blueCampDict.Values);
    private Dictionary<int, BattleObject> redCampDict = new Dictionary<int, BattleObject>();
    private Dictionary<int, BattleObject> blueCampDict = new Dictionary<int, BattleObject>();
    public void Init(TeamBase _redTeam, TeamBase _blueTeam)
    protected Dictionary<int, BattleObject> allBattleObjDict = new Dictionary<int, BattleObject>();
    protected BattleField battleField;
    public void Init(BattleField _battleField, TeamBase _redTeam, TeamBase _blueTeam)
    {
        CreateTeam(redCampDict, _redTeam);
        CreateTeam(blueCampDict, _blueTeam);
        battleField = _battleField;
        CreateTeam(battleField.battleRootNode.redTeamNodeList, redCampDict, _redTeam, BattleCamp.Red);
        CreateTeam(battleField.battleRootNode.blueTeamNodeList, blueCampDict, _blueTeam, BattleCamp.Blue);
    } 
    protected void CreateTeam(Dictionary<int, BattleObject> campDict, TeamBase teamBase)
    protected void CreateTeam(List<GameObject> posNodeList, Dictionary<int, BattleObject> campDict, TeamBase teamBase, BattleCamp _Camp)
    {
        DestroyTeam(campDict);
        for (int i = 0; i < teamBase.teamHeros.Length; i++)
@@ -24,11 +31,20 @@
            TeamHero teamHero = teamBase.teamHeros[i];
            if (teamHero != null)
            {
                BattleObject battleObj = BattleObjectFactory.CreateBattleObject(teamHero);
                battleObj.Init(teamHero);
                BattleObject battleObj = BattleObjectFactory.CreateBattleObject(battleField, posNodeList, teamHero, _Camp);
                allBattleObjDict.Add(battleObj.BattleObjectId, battleObj);
                campDict.Add(teamHero.heroIndex, battleObj);
            }
        }
    }
    public BattleObject GetBattleObject(int battleObjId)
    {
        if (allBattleObjDict.TryGetValue(battleObjId, out BattleObject battleObj))
        {
            return battleObj;
        }
        return null;
    }
    protected void DestroyTeam(Dictionary<int, BattleObject> campDict)
@@ -36,12 +52,14 @@
        foreach (var item in campDict)
        {
            BattleObject battleObj = item.Value;
            if (battleObj!= null)
            if (battleObj != null)
            {
                BattleObjectFactory.DestroyBattleObject(battleObj);
                allBattleObjDict.Remove(battleObj.BattleObjectId);
                BattleObjectFactory.DestroyBattleObject(item.Key, battleObj);
            }
        }
        campDict.Clear();
    }
    public void Release()
@@ -55,7 +73,6 @@
        foreach (var item in redCampDict)
        {
            item.Value.Run();
        }
        foreach (var item in blueCampDict)
@@ -64,29 +81,166 @@
        }
    }
    public void ResumeGame()
    public virtual void ResumeGame()
    {
        foreach (var item in redCampList)
        foreach (var obj in redCampDict.Values)
        {
            item.ResumeGame();
            obj.Resume();
        }
        foreach (var item in blueCampList)
        foreach(var obj in blueCampDict.Values)
        {
            item.ResumeGame();
            obj.Resume();
        }
    }
    public void PauseGame()
    public virtual void PauseGame()
    {
        foreach (var item in redCampList)
        foreach (var obj in redCampDict.Values)
        {
            item.PauseGame();
            obj.Pause();
        }
        foreach (var item in blueCampList)
        foreach(var obj in blueCampDict.Values)
        {
            item.PauseGame();
            obj.Pause();
        }
    }
    public List<BattleObject> GetEnemyList(BattleObject _battleObj)
    {
        if (_battleObj.Camp == BattleCamp.Red)
        {
            return blueCampList;
        }
        return redCampList;
    }
    public List<BattleObject> GetFriendlyList(BattleObject _battleObj)
    {
        if (_battleObj.Camp == BattleCamp.Red)
        {
            return redCampList;
        }
        return blueCampList;
    }
#if UNITY_EDITOR
    public void ReviveAll()
    {
        foreach (var kv in allBattleObjDict)
        {
            kv.Value.EditorRevive();
        }
    }
    public List<BattleObject> GetTargetList(BattleObject battleObj, SkillTargetType targetType, SkillTargetRangeType rangeType)
    {
        List<BattleObject> returnList = new List<BattleObject>();
        switch (targetType)
        {
            case SkillTargetType.Self:
                returnList.Add(battleObj);
                break;
            case SkillTargetType.Own:
                returnList.AddRange(GetFriendlyList(battleObj));
                break;
            case SkillTargetType.Enemy:
                returnList.AddRange(GetEnemyList(battleObj));
                break;
            case SkillTargetType.OwnExceptSelf:
                List<BattleObject> friendlyList = GetFriendlyList(battleObj);
                friendlyList.Remove(battleObj);
                returnList.AddRange(friendlyList);
                break;
            default:
                break;
        }
        //普攻为群攻时,以当前单体时默认攻击对象为主对象,其它为溅射单位;
        switch (rangeType)
        {
            case SkillTargetRangeType.Front:
                //暂时没有召唤物
                // 放在第7格的BOSS后排的。。位置放在正中间
                // a)前排,1、2、3号为前排,前排全部阵亡后,4、5、6号即是前排也是后排 7其实也是后排
                List<BattleObject> frontList = new List<BattleObject>(from BO in returnList where BO.teamHero.heroIndex < 3 && !BO.IsDead() select BO);
                if (frontList.Count == 0)
                {
                    frontList.AddRange(returnList);
                }
                returnList = frontList;
                break;
            case SkillTargetRangeType.Back:
                List<BattleObject> backList = new List<BattleObject>(from BO in returnList where BO.teamHero.heroIndex >= 3 && !BO.IsDead() select BO);
                if (backList.Count == 0)
                {
                    backList.AddRange(returnList);
                }
                returnList = backList;
                break;
            case SkillTargetRangeType.Random:
                int randomNumber = 3;
                returnList = new List<BattleObject>(from BO in returnList where !BO.IsDead() select BO);
                returnList = returnList.Shuffle();
                while (returnList.Count > randomNumber)
                {
                    returnList.RemoveAt(0);
                }
                break;
            case SkillTargetRangeType.All:
                break;
            case SkillTargetRangeType.HighestAttack:
                returnList = new List<BattleObject>(from BO in returnList where !BO.IsDead() select BO);
                BattleObject mostHighestAttckObj = null;
                for (int i = 0; i < returnList.Count; i++)
                {
                    if (mostHighestAttckObj == null)
                    {
                        mostHighestAttckObj = returnList[i];
                        continue;
                    }
                    if (returnList[i].teamHero.attack > mostHighestAttckObj.teamHero.attack)
                    {
                        mostHighestAttckObj = returnList[i];
                    }
                }
                returnList.Clear();
                if (mostHighestAttckObj != null)
                    returnList.Add(mostHighestAttckObj);
                break;
            case SkillTargetRangeType.LowestHP:
                returnList = new List<BattleObject>(from BO in returnList where !BO.IsDead() select BO);
                BattleObject loweastHpObj = null;
                for (int i = 0; i < returnList.Count; i++)
                {
                    if (loweastHpObj == null)
                    {
                        loweastHpObj = returnList[i];
                        continue;
                    }
                    if (returnList[i].teamHero.curHp < loweastHpObj.teamHero.curHp)
                    {
                        loweastHpObj = returnList[i];
                    }
                }
                returnList.Clear();
                if (null != loweastHpObj)
                    returnList.Add(loweastHpObj);
                break;
            case SkillTargetRangeType.Deadman:
                returnList = new List<BattleObject>(from BO in returnList where BO.IsDead() select BO);
                break;
            default:
                break;
        }
        return returnList;
    }
#endif
}
Main/System/Battle/BattleObject/BattleObject.cs
@@ -5,11 +5,14 @@
using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using Spine.Unity;
using UnityEngine.UI;
using System.Linq;
public enum BattleCamp
{
    Friendly,
    Enemy
    Red,
    Blue
}
public enum BattleState
@@ -25,141 +28,360 @@
public class BattleObject
{
    public string BattleObjectId { get; protected set; }
    public BattleCamp Camp { get; protected set; } = BattleCamp.Friendly;
    public BattleField battleField;
    public int BattleObjectId { get; set; }
    public BattleCamp Camp { get; protected set; }
    public TeamHero teamHero { get; protected set; }
    // public BuffMgr buffMgr;
    protected MotionBase motionBase;
    protected GameObject cardGO;
    public virtual void Init(TeamHero _teamHero)
    protected GameObject heroGo;
    public BattleObject(BattleField _battleField)
    {
        this.teamHero = _teamHero;
        battleField = _battleField;
    }
    public virtual void Init(GameObject _heroGo, TeamHero _teamHero, BattleCamp _camp)
    {
        heroGo = _heroGo;
        teamHero = _teamHero;
        Camp = _camp;
        motionBase = new MotionBase();
        motionBase.Init(heroGo.GetComponentInChildren<SkeletonGraphic>(true));
    }
    protected void LoadHero()
    {
    }
    #region 战斗相关函数
    public virtual void AttackTarget(List<BattleObject> targets)
    {
        // 找离自己最近的
        if (0 == targets.Count) return;
        BattleObject target = targets[0];
        if (1 != targets.Count)
        {
            for (int i = 1; i < targets.Count; i++)
            {
                if (Vector3.Distance(cardGO.transform.position, targets[i].cardGO.transform.position) < Vector3.Distance(cardGO.transform.position, target.cardGO.transform.position))
                {
                    target = targets[i];
                }
            }
        }
        Vector3 tempPos = cardGO.transform.position;
        motionBase.OnAttackAnimationComplete = () => {
            // 攻击动画结束之后 回到原来的位置
            cardGO.transform.DOMove(tempPos, 1f).OnComplete(() => {
                // motionBase.ClearEvent();// = null;
                //  通知本次攻击行动结束
                //  通过battleFieldId来告知BattleFieldMgr
            });
        };
        cardGO.transform.DOMove(target.cardGO.transform.position, 1f).OnComplete(() => {
            // 播放攻击动画
            motionBase.OnAttackHitEvent = (int attackIndex) => {
                for (int i = 0; i < targets.Count; i++)
                {
                    targets[i].UnderAttack(this);
                }
            };
            //普攻是hit1
            motionBase.PlayAnimationEx(MotionName.atk1, false, new List<int>(){
                5//假设是5帧 目前还没有数据
            });
        });
    }
    public virtual void CastSkill(List<BattleObject> targets)
    {
        //  需不需要move 攻击目标是谁
    }
    public virtual float UnderAttack(BattleObject attacker)
    {
        return 0;
    }
    public virtual float HealTargets(List<BattleObject> targets)
    {
        return 0;
    }
    public virtual float BeHealed(BattleObject healer, float healAmount)
    {
        return 0;
    }
    public virtual bool Revive(BattleObject target)
    {
        return false;
    }
    public virtual bool BeRevived(BattleObject reviver, float healthPercent = 0.5f)
    {
        return false;
    }
    #endregion
    #region 辅助函数
    public virtual bool IsEnemy(BattleObject other)
    {
        if (other == null) return false;
        return Camp != other.Camp;
    }
    public virtual bool IsFriendly(BattleObject other)
    {
        if (other == null) return false;
        return Camp == other.Camp;
    }
    public virtual void Run()
    {
        motionBase.Run();
    }
    public virtual void PauseGame()
    public virtual void Pause()
    {
        motionBase.Pause();
    }
    public virtual void ResumeGame()
    public virtual void Resume()
    {
        motionBase.Resume();
    }
    #endregion
    public virtual void Destroy()
    {
        if (heroGo != null)
        {
            GameObject.DestroyImmediate(heroGo);
            heroGo = null;
        }
        motionBase.Release();
        motionBase = null;
        teamHero = null;
        BattleObjectId = 0;
    }
    //  眩晕
    public bool IsStunned()
    {
        return teamHero.isStunned;
    }
    //  冰冻
    public bool IsFrozen()
    {
        return teamHero.isFrozen;
    }
    //  石化
    public bool IsStoned()
    {
        return teamHero.isStoned;
    }
    // //   禁锢
    // public bool IsConfined()
    // {
    //     return false;
    // }
    //  被沉默
    public bool IsSlient()
    {
        return teamHero.isSlient;
    }
    //  被缴械
    public bool IsDisarmed()
    {
        return teamHero.isDisarmed;
    }
    //  是否无敌
    public bool IsInvincable()
    {
        return teamHero.isInvinceble;
    }
    //  是否死亡
    public bool IsDead()
    {
        return teamHero.isDead;
    }
    //  是否被控住了
    public bool IsCrowdControlled()
    {
        return IsStunned() || IsStoned() || IsFrozen();
    }
    public virtual bool IsCanCastSkill()
    {
        //  被控住
        if (IsCrowdControlled())
        {
            return false;
        }
        //  被沉默
        if (IsSlient())
        {
            return false;
        }
        //  看看怒气是否达到释放要求
        return teamHero.rage >= 100;
    }
    public virtual bool IsCanNormalAttack()
    {
        //  被控住
        if (IsCrowdControlled())
        {
            return false;
        }
        //  缴械
        if (IsDisarmed())
        {
            return false;
        }
        return true;
    }
    public virtual void TakeDamage(List<int> damageValues)
    {
        if (IsDead())
            return;
        PopDamage(damageValues);
        motionBase.PlayAnimation(MotionName.hit, false);
        //  计算伤害
        int totalDamage = 0;
        foreach (var damage in damageValues)
        {
            totalDamage += damage;
        }
        //  扣血
        teamHero.curHp -= totalDamage;
        //  其实这里应该是等服务器发death的action
        // if (IsDead())
        // {
        //     OnDeath();
        // }
    }
    //  闪避开始
    public virtual void OnDodgeBegin()
    {
        float pingpongTime = 0.2f;
        RectTransform rectTrans = heroGo.GetComponent<RectTransform>();
        rectTrans.DOAnchorPos(new Vector3(-50, 50, 0), pingpongTime)
            .SetEase(Ease.OutCubic);
    }
    //  闪避结束
    public virtual void OnDodgeEnd()
    {
        float pingpongTime = 0.2f;
        RectTransform rectTrans = heroGo.GetComponent<RectTransform>();
        rectTrans.DOAnchorPos(Vector3.zero, pingpongTime)
                            .SetEase(Ease.OutCubic);
    }
    protected virtual void OnDeath()
    {
        motionBase.OnOtherAnimationComplete = OnOtherAnimationComplete;
        motionBase.PlayAnimation(MotionName.dead, false);
    }
    protected virtual void OnOtherAnimationComplete(MotionName motionName)
    {
        if (motionName == MotionName.dead)
        {
            OnDeadAnimationComplete();
        }
    }
    protected virtual void OnDeadAnimationComplete()
    {
        //  或许看看溶解特效? YYL TODO
        heroGo.SetActive(false);
    }
     // 伤害还要看 是否闪避 暴击 and so on 需要有一个DamageType 服务器应该会给
    protected virtual void PopDamage(List<int> damageValues)
    {
        //  其实应该通知出去给UI界面解耦 让UI界面自己来显示的 YYL TODO
        //  播放伤害数字
        //  这里可以实现一个伤害数字的弹出效果
        //  比如使用一个UI组件来显示伤害数字
        foreach (var damage in damageValues)
        {
            Debug.Log($"Damage: {damage}");
        }
    }
    public void PlaySkill(SkillConfig skillConfig, List<Dictionary<int, List<int>>> damageList, Action _onComplete)
    {
        bool moveToTarget = true;
        if (moveToTarget)
        {
            int targetId = damageList[0].First().Key;
            BattleObject _targetObj = battleField.battleObjMgr.GetBattleObject(targetId);
            RectTransform selfRect = heroGo.GetComponent<RectTransform>();
            RectTransform targetRect = _targetObj.heroGo.GetComponent<RectTransform>();
            Vector2 curAnchoredPos = selfRect.anchoredPosition;
            MoveToTargetUI(selfRect, targetRect, new Vector2(100f, 0f), () =>
            {
                PlaySkillAnimation(skillConfig, damageList, () =>
                {
                    // 回到原位置
                    selfRect.DOAnchorPos(curAnchoredPos, 0.2f)
                        .SetEase(Ease.Linear)
                        .OnComplete(() => {
                            _onComplete?.Invoke();
                        });
                });
            });
        }
        else
        {
            PlaySkillAnimation(skillConfig, damageList, _onComplete);
        }
    }
    protected void MoveToTargetUI(RectTransform selfRect, RectTransform targetRect, Vector2 offset, Action _onComplete)
    {
        // 1. 目标的本地坐标转为世界坐标
        Vector3 targetWorldPos = targetRect.TransformPoint(targetRect.anchoredPosition + offset);
        // 2. 世界坐标转为自己父节点下的本地坐标
        RectTransform parentRect = selfRect.parent as RectTransform;
        Vector2 targetAnchoredPos;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            parentRect,
            RectTransformUtility.WorldToScreenPoint(null, targetWorldPos),
            null,
            out targetAnchoredPos);
        // 3. DOTween 移动
        selfRect.DOAnchorPos(targetAnchoredPos, 0.2f)
            .SetEase(Ease.Linear)
            .OnComplete(() => _onComplete?.Invoke());
    }
    protected void PlaySkillAnimation(SkillConfig skillConfig, List<Dictionary<int, List<int>>> damageList, Action _onComplete)
    {
        //  关键帧列表
        List<int> keyFrameList = new List<int>() { 15 };
        motionBase.OnAttackHitEvent = (int _frame) =>
        {
            Dictionary<int, List<int>> oneRoundDamage = damageList[keyFrameList.IndexOf(_frame)];
            foreach (var kvp in oneRoundDamage)
            {
                int targetId = kvp.Key;
                List<int> damageValues = kvp.Value;
                BattleObject targetObj = battleField.battleObjMgr.GetBattleObject(targetId);
                if (targetObj != null && !targetObj.IsDead())
                {
                    targetObj.TakeDamage(damageValues);
                }
            }
        };
        motionBase.OnAttackAnimationComplete = () =>
        {
            _onComplete?.Invoke();
            motionBase.OnAttackHitEvent = null;
            motionBase.OnAttackAnimationComplete = null;
            //  死亡确定其实不应该在这里进行触发 应该由服务器下发 YYL TODO
#if UNITY_EDITOR
            //  暂时的处理
            HashSet<int> hitTargets = new HashSet<int>();
            foreach (var dmgDict in damageList)
            {
                foreach (var kvp in dmgDict)
                {
                    int targetId = kvp.Key;
                    hitTargets.Add(targetId);
                }
            }
            foreach (int targetId in hitTargets)
            {
                BattleObject targetObj = battleField.battleObjMgr.GetBattleObject(targetId);
                if (targetObj != null && targetObj.IsDead())
                {
                    targetObj.OnDeath();
                }
            }
#endif
        };
        motionBase.PlayAnimationEx(MotionName.attack, false, keyFrameList);
    }
#if UNITY_EDITOR
    public void EditorRevive()
    {
        teamHero.curHp = 100;
        heroGo.SetActive(true);
        motionBase.PlayAnimation(MotionName.idle, true);
    }
    public List<int> TryAttack(BattleObject obj, SkillConfig skillConfig)
    {
        List<int> damageList = new List<int>();
        int totalDamage = teamHero.attack - obj.teamHero.defense;
        damageList.Add(totalDamage);
        return damageList;
    }
#endif
}
Main/System/Battle/BattleObject/BattleObjectFactory.cs
@@ -5,19 +5,24 @@
public class BattleObjectFactory
{
    public static BattleObject CreateBattleObject(TeamHero teamHero)
    //  本意是要在这里做池的内容的 但是想了一下 利用效率有点差 最多做一下红色方的缓存 蓝色方的即时用 即时删除 或者缓存上一次战斗的就行
    private static int AutoIncrementID = 100000;
    public static BattleObject CreateBattleObject(BattleField _battleField, List<GameObject> posNodeList, TeamHero teamHero, BattleCamp _Camp)
    {
        BattleObject battleObject = null;
        // switch (teamCard.cardInfo.cardConfig.)
        // {
        // }
        HeroSkinConfig skinCfg = teamHero.heroInfo.skinConfig;
        GameObject battleGO = ResManager.Instance.LoadAsset<GameObject>("Hero/SpineRes", "Hero_001"/*skinCfg.SpineRes*/);
        GameObject goParent = posNodeList[teamHero.heroIndex];
        BattleObject battleObject = new BattleObject(_battleField);
        battleObject.BattleObjectId = AutoIncrementID++;
        battleGO.name = battleObject.BattleObjectId.ToString();
        battleObject.Init(GameObject.Instantiate(battleGO, goParent.transform), teamHero, _Camp);
        return battleObject;
    }
    public static void DestroyBattleObject(BattleObject battleObj)
    public static void DestroyBattleObject(int key, BattleObject battleObj)
    {
        battleObj.Destroy();
        battleObj = null;
    }
}
Main/System/Battle/BattleWin.cs
New file
@@ -0,0 +1,72 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using DG.Tweening;
using Cysharp.Threading.Tasks;
public class BattleWin : UIBase
{
    // 组件引用
    public Transform mountPoint;
    private BattleRootNode battleRootNode = null;
    // 生命周期
    protected override void InitComponent()
    {
        base.InitComponent();
        // 初始化组件引用 绑定按钮等UI组件事件
    }
    protected override void OnPreOpen()
    {
        base.OnPreOpen();
        SetBattleField(BattleManager.Instance.storyBattleField);
    }
    protected override void OnPreClose()
    {
        base.OnPreClose();
    }
    protected override void OnOpen()
    {
        base.OnOpen();
    }
    protected override void OnClose()
    {
        base.OnClose();
        if (battleRootNode != null)
        {
            battleRootNode.transform.SetParent(null);
        }
    }
    protected override void NextFrameAfterOpen()
    {
        base.NextFrameAfterOpen();
    }
    protected override void CompleteClose()
    {
        base.CompleteClose();
    }
    public void SetBattleField(BattleField battleField)
    {
        if (battleRootNode != null)
        {
            battleRootNode.transform.SetParent(Launch.Instance.transform);
        }
        battleRootNode = battleField.battleRootNode;
        battleRootNode.transform.SetParent(mountPoint);
        battleRootNode.transform.localPosition = Vector3.zero;
        battleRootNode.transform.localScale = Vector3.one;
    }
}
Main/System/Battle/BattleWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9436c20bbc05d7443a4a55bdd8225747
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/Buff.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fe16e4ea643c0f141869bc215e72e46f
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/Define.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d98f48e6efd31894f920108e541b4f69
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/Define/DamageType.cs
New file
@@ -0,0 +1,16 @@
public enum DamageType
{
    Normal,    //普通伤害
    Dodge,     //闪避
    Heal,    //治疗
    Continuous,//持续伤害
    Block,    //格挡
    ReverseInjury,//反伤
    Recovery,    //吸血
    Crit,    //暴击
    Combo,    //连击
    Stuned,    //击晕
}
Main/System/Battle/Define/DamageType.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d7487e4b249bbbb4b8504bbc03f47c82
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/Define/SkillTargetRangeType.cs
New file
@@ -0,0 +1,21 @@
// 2、目标类型2
// a)前排,1、2、3号为前排,前排全部阵亡后,4、5、6号即是前排也是后排
// b)后排,4、5、6号为后排,后排全部阵亡后,1、2、3号即是前排也是后排
// c)随机
// d)全体
// e)攻击最高:有多个目标,优先对位对应号位目标,按顺序从1号开始选择
// f)生命最低:有多个目标,优先对位对应号位目标,按顺序从1号开始选择
// g)死亡目标:有多个目标,按顺序从1号开始选择
public enum SkillTargetRangeType
{
    Front,
    Back,
    Random,
    All,
    HighestAttack,
    LowestHP,
    Deadman
}
Main/System/Battle/Define/SkillTargetRangeType.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d7a05b1f4236c944585478475734d089
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/Define/SkillTargetType.cs
New file
@@ -0,0 +1,14 @@
// 技能释放,需要根据技能配置,选择目标进行释放
// 1、目标类型1
// a)自身
// b)己方
// c)敌方
// d)除自身外的己方
public enum SkillTargetType
{
    Self = 0,    //自己
    Own,    //己方
    Enemy,    //地方
    OwnExceptSelf, //除自身外的己方
}
Main/System/Battle/Define/SkillTargetType.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1af57ceed7e65c549897d7220d060c61
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/Motion/MotionBase.cs
@@ -19,7 +19,7 @@
        public WaitingTask(List<int> triggerFrame, MotionName motionName, Action<MotionName, int> _callback)
        {
            this.triggerFrame = triggerFrame;
            this.triggerFrame = new List<int>(triggerFrame);
            this.motionName = motionName;
            this.currentFrame = 0;
            this.callback = _callback;
@@ -38,8 +38,9 @@
                
                if (currentFrame >= triggerFrame[0])
                {
                    int frame = triggerFrame[0];
                    triggerFrame.RemoveAt(0);
                    callback?.Invoke(motionName, currentFrame);
                    callback?.Invoke(motionName, frame);
                }
            }
        }
@@ -48,6 +49,7 @@
    // 动画事件
    public Action OnAttackAnimationComplete;
    public Action OnHitAnimationComplete;
    public Action<MotionName> OnOtherAnimationComplete;
    public Action<int> OnAttackHitEvent; //trigger index
    #region 组件引用
@@ -61,12 +63,14 @@
    #region 动画设置
    
    // 动画混合时间
    protected float defaultMixDuration = 0.2f;
    protected float defaultMixDuration = 0f;
    
    #endregion
    
    protected List<WaitingTask> waitingTaskList = new List<WaitingTask>();
    protected List<WaitingTask> removeList = new List<WaitingTask>();
    private Spine.TrackEntry currentTrackEntry;
    #region 初始化方法
    
@@ -101,10 +105,27 @@
        }
    }
    
    public virtual void Release()
    {
        if (spineAnimationState != null)
        {
            spineAnimationState.Complete -= OnAnimationComplete;
            spineAnimationState.ClearTracks();
            spineAnimationState = null;
        }
        skeletonGraphic = null;
        skeleton = null;
        currentTrackEntry = null;
        waitingTaskList.Clear();
        removeList.Clear();
    }
    #endregion
    #region 动画控制
    /// <summary>
    /// 播放指定动画
    /// </summary>
@@ -114,51 +135,10 @@
    public virtual Spine.TrackEntry PlayAnimation(MotionName motionName, bool loop)
    {
        if (spineAnimationState == null) return null;
        // 直接使用 ToString() 而不是调用 GetAnimationName
        return spineAnimationState.SetAnimation(0, motionName.ToString(), loop);
    }
    /// <summary>
    /// 播放指定动画(使用字符串名称)
    /// </summary>
    /// <param name="animationName">动画名称</param>
    /// <param name="loop">是否循环</param>
    /// <returns>动画轨道条目</returns>
    public virtual Spine.TrackEntry PlayAnimation(string animationName, bool loop)
    {
        if (spineAnimationState == null) return null;
        return spineAnimationState.SetAnimation(0, animationName, loop);
    }
    /// <summary>
    /// 添加动画到队列
    /// </summary>
    /// <param name="motionName">动画枚举</param>
    /// <param name="loop">是否循环</param>
    /// <param name="delay">延迟时间</param>
    /// <returns>动画轨道条目</returns>
    public virtual Spine.TrackEntry AddAnimation(MotionName motionName, bool loop, float delay)
    {
        if (spineAnimationState == null) return null;
        // 直接使用 ToString() 而不是调用 GetAnimationName
        return spineAnimationState.AddAnimation(0, motionName.ToString(), loop, delay);
    }
    /// <summary>
    /// 添加动画到队列(使用字符串名称)
    /// </summary>
    /// <param name="animationName">动画名称</param>
    /// <param name="loop">是否循环</param>
    /// <param name="delay">延迟时间</param>
    /// <returns>动画轨道条目</returns>
    public virtual Spine.TrackEntry AddAnimation(string animationName, bool loop, float delay)
    {
        if (spineAnimationState == null) return null;
        return spineAnimationState.AddAnimation(0, animationName, loop, delay);
        currentTrackEntry = spineAnimationState.SetAnimation(0, motionName.ToString(), loop);
        return currentTrackEntry;
    }
    
    /// <summary>
@@ -180,8 +160,8 @@
        string animation = trackEntry.Animation.Name;
        
        // 攻击动画完成后恢复到待机状态
        if (animation == MotionName.atk1.ToString() ||
            animation == MotionName.atk2.ToString())
        if (animation == MotionName.attack.ToString() ||
            animation == MotionName.angerSkill.ToString())
        {
            OnAttackAnimationComplete?.Invoke();
            PlayAnimation(MotionName.idle, true);
@@ -191,6 +171,10 @@
        {
            OnHitAnimationComplete?.Invoke();
            PlayAnimation(MotionName.idle, true);
        }
        else
        {
            OnOtherAnimationComplete?.Invoke((MotionName)Enum.Parse(typeof(MotionName), animation));
        }
    }
    
@@ -242,6 +226,19 @@
        removeList.Clear();
    }
    public virtual void Pause()
    {
        if (currentTrackEntry != null)
            currentTrackEntry.TimeScale = 0f;
    }
    public virtual void Resume()
    {
        if (currentTrackEntry != null)
            currentTrackEntry.TimeScale = 1f;
    }
    #endregion
    
}
Main/System/Battle/Motion/MotionName.cs
@@ -1,10 +1,19 @@
// 每个武将都需有:
// 待机
// 跑步
// 被击
// 死亡
// 怒气技能动作
// 普攻动作
public enum MotionName
{
    atk1,
    atk2,
    hit,
    idle,
    run,
    idle,//待机
    run,//跑步
    hit,//被击
    dead,//死亡
    angerSkill,//怒气技能
    attack,//普攻
}
Main/System/Battle/RecordPlayer/RecordAction.cs
@@ -5,15 +5,25 @@
public class RecordAction
{
    public RecordActionType actionType;
    public int casterId;
    protected BattleField battleField;
    public bool IsFinished()
    protected BattleObject battleObject;
    public RecordAction(RecordActionType _actionType, BattleField _battleField, BattleObject _battleObj)
    {
        actionType = _actionType;
        battleField = _battleField;
        battleObject = _battleObj;
    }
    public RecordActionType actionType;
    public virtual bool IsFinished()
    {
        return false;
    }
    public void Run()
    public virtual void Run()
    {
        
    }
Main/System/Battle/RecordPlayer/RecordActionType.cs
@@ -2,9 +2,7 @@
public enum RecordActionType
{
    None,
    Attack,//攻击
    Heal,//治疗
    Buff,//增益&减益
    Guard,//格挡
    Skill,//技能
    Death,//死亡
}
Main/System/Battle/RecordPlayer/RecordPlayer.cs
@@ -15,6 +15,11 @@
        battleField = _battleField;
    }
    public bool IsPlaying()
    {
        return currentRecordAction != null || recordActionQueue.Count > 0;
    }
    public void PlayRecord(RecordAction recordAction)
    {
        recordActionQueue.Enqueue(recordAction);
@@ -30,20 +35,42 @@
    public virtual void Run()
    {
        if (recordActionQueue.Count == 0)
        if (currentRecordAction == null)
        {
            if (recordActionQueue.Count <= 0)
            {
                return;
            }
        }
        if (currentRecordAction != null && !currentRecordAction.IsFinished())
        {
            currentRecordAction.Run();
            return;
        }
        if (currentRecordAction == null || currentRecordAction.IsFinished())
        if (currentRecordAction != null && currentRecordAction.IsFinished())
        {
            currentRecordAction = recordActionQueue.Dequeue();
            currentRecordAction = null;
        }
        if (currentRecordAction != null)
        if (currentRecordAction == null)
        {
            currentRecordAction.Run();
            if (recordActionQueue.Count > 0)
            {
                currentRecordAction = recordActionQueue.Dequeue();
            }
        }
    }
    //  先预留 感觉用的上
    public virtual void ResumeGame()
    {
    }
    public virtual void PauseGame()
    {
    }
}
Main/System/Battle/Skill.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a1576f20f23a41249a6fd9f71fa49efa
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/Skill/DirectlyDamageSkill.cs
New file
@@ -0,0 +1,49 @@
using System.Collections.Generic;
public class DirectlyDamageSkill : SkillBase
{
    public DirectlyDamageSkill(SkillConfig _skillCfg) : base(_skillCfg)
    {
    }
    public override void Run()
    {
        base.Run();
    }
    public override void Cast(BattleObject _caster, BattleField _battleField, List<Dictionary<int, List<int>>> damageList)
    {
        _caster.PlaySkill(skillConfig, damageList, OnSkillAnimationFinished);
    }
    protected void OnSkillAnimationFinished()
    {
        isFinished = true;
    }
#if UNITY_EDITOR
    //    伤害列表理应由服务器发给客户端 这边只做粗浅模拟
    public override List<Dictionary<int, List<int>>> GetDamageList(BattleObject _caster, BattleField battleField)
    {
        List<Dictionary<int, List<int>>> damageList = new List<Dictionary<int, List<int>>>();
        List<BattleObject> affectList = GetTargetList(_caster, battleField);
        Dictionary<int, List<int>> oneRoundDamage = new Dictionary<int, List<int>>();
        for (int j = 0; j < affectList.Count; j++)
        {
            BattleObject obj = affectList[j];
            List<int> tryDmgList = _caster.TryAttack(obj, skillConfig);
            oneRoundDamage.Add(obj.BattleObjectId, tryDmgList);
        }
        damageList.Add(oneRoundDamage);
        return damageList;
    }
#endif
}
Main/System/Battle/Skill/DirectlyDamageSkill.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6c38b8acedc80dc4594072a10e7df9d2
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/Skill/SkillBase.cs
New file
@@ -0,0 +1,52 @@
using System.Collections.Generic;
using UnityEngine;
public class SkillBase
{
    protected SkillConfig skillConfig;
    protected bool isFinished = false;
    public SkillBase(SkillConfig _skillCfg)
    {
        skillConfig = _skillCfg;
    }
    public virtual void Run()
    {
    }
    public virtual void Cast(BattleObject _caster, BattleField battleField, List<Dictionary<int, List<int>>> damageList)
    {
        Debug.LogError("SkillBase Cast should be overridden by derived class");
    }
    public virtual bool IsFinished()
    {
        return isFinished;
    }
    public virtual void ForceFinished()
    {
        isFinished = true;
    }
#if UNITY_EDITOR
    public virtual List<BattleObject> GetTargetList(BattleObject _caster, BattleField battleField)
    {
        SkillTargetType targetType = SkillTargetType.Enemy;
        SkillTargetRangeType rangeType = SkillTargetRangeType.LowestHP;
        List<BattleObject> affectList = battleField.battleObjMgr.GetTargetList(_caster, targetType, rangeType);
        return affectList;
    }
    public virtual List<Dictionary<int, List<int>>> GetDamageList(BattleObject _caster, BattleField battleField)
    {
        Debug.LogError("SkillBase GetDamageList should be overridden by derived class");
        return null;
    }
#endif
}
Main/System/Battle/Skill/SkillBase.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 29aa0d4b5b5830a4990d8538740b9355
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/Skill/SkillFactory.cs
New file
@@ -0,0 +1,70 @@
using UnityEngine;
public static class SkillFactory
{
// SkillType
// 技能类型    定义
// 特殊   0
// 攻击类   1    主动会造成瞬间伤害技能类型为1
// 恢复类   2    主动会恢复生命值的技能类型为2
// 持续增益BUFF  3    主动一段时间内间隔时间给予增益buff技能类型为3,比如持续回血
// 持续减益BUFF  4    主动一段时间内间隔时间给予减益buff技能类型为4,比如中毒
// 增益BUFF 5    主动持续一段时间给予增益buff,不会出现间隔时间buff类型为5,比如麒麟盾
// 减益BUFF 6    主动持续一段时间给予减益buff,不会出现间隔时间buff类型为6,比如减速
// 被动技   7    被动触发的技能类型为7
// 复活     8    牧师复活队友技能,暂时无用
// 增值技能(不可清除)9      和增益技能类似,无法点击图标取消,暂时无用
// 光环技能  10    队友共享该技能的光环,类似魔兽争霸的强击光环,荆棘光环,暂时无这样技能
// 装备技能  11    装备上附加了技能,比如套装附加攻击+50%,暂时无这样技能
// 区域技能  12    "布怪器里 有个配置技能ID  比如配个火区域灼烧
// "
// 召唤      13    主动召唤出一个怪物,则配置为13,暂时无这样的技能
// 控制型BUFF 14    比如眩晕,定身技能需要配置控制型buff
// 多段伤害buff攻击类型(类xp技能) 15    多段伤害主动每秒伤害buff技能类型为15
// 被动触发增益类buff 16    被动触发持续一段时间给予增益buff,不会出现间隔时间buff类型为16,如(50065疾风)
// 被动触发减益类buff 17    被动触发持续一段时间给予减益buff,不会出现间隔时间buff类型为17,如(50235负伤)
// 被动触发的控制类buff 18    被动触发持续一段时间的控制技能为17,如(50365激怒)
// 属性类技能 20(如坐骑属性,宠物属性)    被动增加了属性效果值,长期的技能为20,如(50605守护)
// 被动buff 19(暂时不知道干啥的)
// 被动触发持续类增益类buff 21    被动一段时间内间隔时间给予增益buff技能类型为3,比如(50635祝福)
// 被动触发持续类减益类buff 22    被动一段时间内间隔时间给予减益buff技能类型为4,比如毒龙嗜天
// 攻击技能:本回合对敌人武将造成伤害
// 治疗技能:本回合对已方武将回复生命值,回复生命值不可超过生命上限
// 辅助技能:增加怒气、召唤、光环等
// BUFF技能:提升已方属性的增益BUFF(加攻、加血、加状态等),降低敌方属性的减益BUFF(减攻、减血、控制等),持续多回合
// 复活技能:复活已方已死武将并回复X生命值,复活:继承死亡前的所有状态(各种状态、各种BUFF、怒气值等),复活后错过本回合攻击时机则下一回合才能出手
    public static SkillBase CreateSkill(SkillConfig _skillConfig)
    {
        SkillBase skill = null;
        switch (_skillConfig.SkillType)
        {
            case 1:
                skill = new DirectlyDamageSkill(_skillConfig);
                break;
            case 2:
                // skill = new DirectlyHealSkill(_skillConfig);
                break;
            case 3:
                // skill = new SupportSkill(_skillConfig);
                break;
            case 4:
                // skill = new MountBuffSkill(_skillConfig);
                break;
            case 5:
                // skill = new ReviveSkill(_skillConfig);
                break;
            default:
                Debug.LogError("超出了技能类型范围 请检查配置");
                break;
        }
        return skill;
    }
}
Main/System/Battle/Skill/SkillFactory.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e2a0e020a4b71ca48aa80d5cb0536792
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Hero/HeroInfo.Properties.cs
@@ -47,6 +47,42 @@
    public int recoverResist = 0;
    //  特殊属性(待补充)
    //  最终伤害
    public int finalDamageIncrease = 0;
    //  最终免伤
    public int finalDamageReduce;
    //  爆伤
    public int critDamageIncrease;
    //  减少爆伤
    public int critDamageReduce;
    //  治疗增益
    public int healIncrease;
    //  治疗减益
    public int healReduce;
    //  物理增伤
    public int damageIncrease;
    //  减少物伤
    public int damageReduce;
    //  法术增伤
    public int magicIncrease;
    //  减少法伤
    public int magicReduce;
    //  普攻增伤
    public int normalAttackIncrease;
    //  减少普攻伤害
    public int normalAttackReduce;
    //  增加技能伤害
    public int rageSkillAttackIncrease;
    //  减少技能伤害
    public int rageSkillAttackReduce;
    //  增加持续伤害的百分比
    public int continousSkillIncrease;
    //  减少持续伤害的百分比
    public int continousSkillReduce;
    //  增加护盾百分比
    public int shieldSkillIncrease;
    //  减少护盾百分比
    public int shieldSkillReduce;
    //计算个人/职业/种族养成属性加成
Main/System/Hero/HeroInfo.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using UnityEngine;
using LitJson;
public partial class HeroInfo
{
@@ -11,6 +12,13 @@
    {
        get
        {
            #if UNITY_EDITOR
            if (null == itemHero)
            {
                return 520001;
            }
            #endif
            return itemHero.config.ID;
        }
    }
@@ -44,9 +52,9 @@
        }
    }
    public readonly ItemModel itemHero;
    public ItemModel itemHero;
    public readonly CB122_tagSCHeroInfo.tagSCHero scHeroInfo;
    // public readonly CB122_tagSCHeroInfo.tagSCHero scHeroInfo;
    //  武将配置
    public HeroConfig heroConfig;
@@ -67,12 +75,44 @@
    public List<HeroTalentInfo> talentList = new List<HeroTalentInfo>();
    public HeroInfo(CB122_tagSCHeroInfo.tagSCHero _scHeroInfo, ItemModel _itemHero)
    public HeroInfo(/*CB122_tagSCHeroInfo.tagSCHero _scHeroInfo, */ItemModel _itemHero)
    {
        scHeroInfo = _scHeroInfo;
        itemHero = _itemHero;
        // scHeroInfo = _scHeroInfo;
        UpdateHero(_itemHero);
        InitConfigs();
    }
    #if UNITY_EDITOR
    public HeroInfo()
    {
        heroLevel = 1;
        heroStar = 1;
        breakLevel = 1;
        awakeLevel = 1;
        SkinIndex = 0;
        heroConfig = HeroConfig.Get(heroId);
        awakeConfig = HeroAwakeConfig.GetHeroAwakeConfig(heroId, awakeLevel);
        breakConfig = HeroBreakConfig.GetHeroBreakConfig(heroId, breakLevel);
        qualityAwakeConfig = HeroQualityAwakeConfig.GetQualityAwakeConfig(Quality, awakeLevel);
        qualityConfig = HeroQualityConfig.Get(Quality);
        qualityBreakConfig = HeroQualityBreakConfig.GetQualityBreakConfig(Quality, awakeLevel);
        CalculateProperties();
    }
    #endif
    // public HeroInfo Clone() => JsonMapper.ToObject<HeroInfo>(JsonMapper.ToJson(this));
    //  图鉴信息
    public void UpdateSCHero(CB122_tagSCHeroInfo.tagSCHero _scHeroInfo)
    {
    }
    public void UpdateHero(ItemModel _itemHero)
    {
        itemHero = _itemHero;
        // HeroConfigUtility
        // 70 # 英雄等级
@@ -86,12 +126,15 @@
        // 78 # 英雄使用的皮肤索引
        SkinIndex = itemHero.GetUseData(78)[0];
        // 71 # 英雄天赋ID列表
        List<int> talentSkillList = itemHero.GetUseData(71);
        // 73 # 英雄天赋ID等级列表,对应71天赋ID的等级
        List<int> talentLvList = itemHero.GetUseData(73);
        // 75 # 英雄天赋洗炼锁定索引列表,对应71天赋ID索引
        List<int> talentLockList = itemHero.GetUseData(75);
        InitConfigs();
        if (talentLockList.Count != talentLvList.Count || talentLvList.Count != talentSkillList.Count)
        {
@@ -115,8 +158,6 @@
// 77 # 英雄天赋洗炼随机ID列表
// 79 # 英雄觉醒时随机天赋选项ID列表
// 80 # 主阵型上阵位置
    }
    protected void InitConfigs()
Main/System/Hero/HeroManager.cs
@@ -1,20 +1,27 @@
using System.Collections.Generic;
using UnityEngine;
using System;
public class HeroManager : GameSystemManager<HeroManager>
{
    protected Dictionary<long, HeroInfo> heroInfoDict = new Dictionary<long, HeroInfo>();
    protected Dictionary<string, HeroInfo> heroInfoDict = new Dictionary<string, HeroInfo>();
    public Action<HeroInfo> onNewHeroEvent;
    public Action<HeroInfo> onHeroChangeEvent;
    public override void Init()
    {
        base.Init();
        //  注册一点事件
        PackManager.Instance.refrechPackEvent += refrechPackEvent;
    }
    public override void Release()
    {
        base.Release();
        PackManager.Instance.refrechPackEvent -= refrechPackEvent;
    }
    public override void RequestNessaryData()
@@ -24,9 +31,41 @@
        
    }
    public void UpdateHeroInfo()
    public void refrechPackEvent(PackType packType)
    {
        if (packType == PackType.Hero)
        {
            // bool change = false;
            bool isNew = false;
            //  如果有分批次初始化可能还要麻烦一点?先看看
            bool isInit = heroInfoDict.Count >= 0;
            SinglePack heroPack = PackManager.Instance.GetSinglePack(packType);
            Dictionary<int, ItemModel> heroes = heroPack.GetAllItems();
            foreach (ItemModel hero in heroes.Values)
            {
                HeroInfo heroInfo = null;
                if (!heroInfoDict.TryGetValue(hero.guid, out heroInfo))
                {
                    heroInfo = new HeroInfo(hero);
                    heroInfoDict.Add(hero.guid, heroInfo);
                    if (!isInit)
                    {
                        isNew = true;
                        onNewHeroEvent?.Invoke(heroInfo);
                    }
                }
                else
                {
                    heroInfo.UpdateHero(hero);
                    //  也有可能不是change
                    // change = true;
                    // onHeroChangeEvent?.Invoke(heroInfo);
                }
            }
        }
    }
    public List<HeroInfo> GetPowerfulHeroList()
Main/System/Main/MainWin.cs
@@ -180,6 +180,8 @@
            case 4:
                //currentSubUI = UIManager.Instance.OpenWindow<PlaceWin>();
                Debug.Log("打开冒险界面");
                BattleWin battleWin = UIManager.Instance.OpenWindow<BattleWin>();
                currentSubUI = battleWin;
                break;
            default:
                Debug.LogWarning("未知的标签索引: " + index);
Main/System/Team/TeamBase.Properties.cs
@@ -6,6 +6,8 @@
    //  阵型内卡牌的羁绊增益
    public int fightPower = 0;
    protected void UpdateProperties()
    {
        //    羁绊
@@ -35,6 +37,6 @@
    public void CalculatePower()
    {
        // fightPower//的计算
    }
}
Main/System/Team/TeamBase.cs
@@ -5,7 +5,7 @@
public partial class TeamBase
{
    public TeamHero[] teamHeros = new TeamHero[TeamConst.MaxTeamHeroCount];
    public TeamHero[] teamHeros = new TeamHero[TeamConst.MaxTeamSlotCount];
    public int GetTeamHeroCount()
    {
@@ -19,7 +19,7 @@
        }
        return count;
    }
    }
    public bool SwapTeamHero(int index1, int index2)
    {
@@ -93,4 +93,21 @@
    {
        
    }
#if UNITY_EDITOR
    public void FillWithFakeData()
    {
        for (int i = 0; i < TeamConst.MaxTeamHeroCount; i++)
        {
            TeamHero hero = new TeamHero();
            hero.curHp = 100;
            hero.attack = UnityEngine.Random.Range(300, 500);
            hero.defense = UnityEngine.Random.Range(80, 100);
            hero.heroInfo = new HeroInfo();
            hero.teamBase = this;
            hero.heroIndex = i;
            teamHeros[i] = hero;
        }
    }
#endif
}
Main/System/Team/TeamConst.cs
@@ -2,5 +2,6 @@
public class TeamConst
{
    public const int MaxTeamHeroCount = 6;
    public const int MaxTeamHeroCount = 6;//最大布阵数量
    public const int MaxTeamSlotCount = 7;//最大槽位数量
}
Main/System/Team/TeamHero.Properties.cs
New file
@@ -0,0 +1,57 @@
public partial class TeamHero
{
    // 基础属性
    // 生命
    public int hp = 0;
    // 攻击力
    public int attack = 0;
    // 防御力
    public int defense = 0;
    //战斗属性 击晕、暴击、连击、格挡、反击、吸血
    //眩晕概率
    public int stunRate = 0;
    //暴击概率
    public int critRate = 0;
    //连击概率
    public int comboRate = 0;
    //格挡概率
    public int blockRate = 0;
    //反击概率
    public int counterAttackRate = 0;
    //攻击目标时,造成伤害转化成生命的百分比数值提升
    public int recoverRate = 0;
    //战斗抵抗属性
    //眩晕抵抗
    public int stunResist = 0;
    //暴击抵抗
    public int critResist = 0;
    //连击抵抗
    public int comboResist = 0;
    //格挡抵抗
    public int blockResist = 0;
    //反击抵抗
    public int counterAttackResist = 0;
    //减少攻击时吸血转化成生命的百分比数值
    public int recoverResist = 0;
    //  当前属性
    // 怒气值
    public int rage = 0;
    //  当前血量
    public int curHp;
    //  最大血量
    public int maxHp;
}
Main/System/Team/TeamHero.Properties.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2f2a7e0a26d12c945829628eb982b0e4
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Team/TeamHero.State.cs
New file
@@ -0,0 +1,33 @@
public partial class TeamHero
{
// 状态说明
// 正常状态:可以正常进行战斗。
// 控制状态:有眩晕、石化、冰冻等状态,持续X回合;其中冰冻状态中被攻击X次,可提前解除控制状态; 当角色处于控制状态时,武将无法进行普攻、无法释技能、不可触发释反击、追击等
// 沉默状态:不可释放技能,可普攻
// 缴械状态:无法进行普攻、追击、连击,可释放技能
// 无敌状态:武将所受的伤害不扣血,可被攻击、治疗、添加BUFF
// 死亡状态:武将生命值为0时,从战斗消失,无法继续战斗。
    public bool isStunned = false;
    public bool isStoned = false;
    public bool isFrozen = false;
    public bool isSlient = false;
    public bool isDisarmed = false;
    public bool isInvinceble = false;
    public bool isDead
    {
        get
        {
            return curHp <= 0;
        }
    }
}
Main/System/Team/TeamHero.State.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61b6dabe91e01264984e600d39ee34fe
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Team/TeamHero.cs
@@ -1,17 +1,15 @@
public class TeamHero
public partial class TeamHero
{
    public HeroInfo heroInfo;
    public TeamBase teamBase;
    public int heroIndex;
    public void MergeProperties()
    {
        if (heroInfo == null)
        {
            return;
        }
    //  最终属性 当前属性应该是要在这一层的
    }
    public int GetPower()
    {
        return heroInfo.CalculatePower();
    }
}
Main/System/Team/TeamManager.cs
@@ -23,22 +23,9 @@
        if (!teamDict.TryGetValue(teamType, out team))
        {
            team = GetStoryTeam();
            teamDict.Add(teamType, team);
        }
        return team;
    }
    public TeamBase GetStoryTeam()
    {
        TeamBase team = null;
        if (!teamDict.TryGetValue(TeamType.Story, out team))
        {
            team = new TeamBase();
            team.AddTeamHeros(HeroManager.Instance.GetPowerfulHeroList());
            teamDict.Add(TeamType.Story, team);
            teamDict.Add(teamType, team);
        }
        return team;
Main/Utility/UniTaskExtension.cs
@@ -6,17 +6,27 @@
{
    public static void DelayFrame(this GameObject go, Action action)
    {
        DelayFrameInternal(action);
        DelayFrameInternal(1, action);
    }
    public static void DelayFrame(this Component cmp, Action action)
    {
        DelayFrameInternal(action);
        DelayFrameInternal(1, action);
    }
    private async static UniTask DelayFrameInternal(Action action)
    private async static UniTask DelayFrameInternal(int frame, Action action)
    {
        await UniTask.DelayFrame(1);
        await UniTask.DelayFrame(frame);
        action?.Invoke();
    }
    public static void DelayFrames(this Component cmp, int frames, Action action)
    {
        DelayFrameInternal(frames, action);
    }
    public static void DelayFrames(this GameObject go, int frames, Action action)
    {
        DelayFrameInternal(frames, action);
    }
}
Main/Utility/VesselExtension.cs
@@ -6,6 +6,8 @@
public static class VesselExtension
{
    public static System.Random rng = new System.Random();
    public static bool IsNullOrEmpty<T>(this List<T> vessel)
    {
        return vessel == null || vessel.Count == 0;
@@ -102,4 +104,14 @@
        return list[randomIndex];
    }
    public static List<T> Shuffle<T>(this IList<T> list)
    {
        var shuffled = new List<T>(list); // 创建副本
        for (int i = shuffled.Count - 1; i > 0; i--)
        {
            int j = rng.Next(i + 1);
            (shuffled[i], shuffled[j]) = (shuffled[j], shuffled[i]);
        }
        return shuffled;
    }
}