hch
2 天以前 43c7968a67336472d883fb343387b7fba3fc0694
515 【挑战】PVP群英榜
14个文件已修改
24个文件已添加
1650 ■■■■■ 已修改文件
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB210_tagCSQunyingMatch.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB210_tagCSQunyingMatch.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/H03_MainCharacter/DTC0320_tagFBEnd.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HA9_Function/DTCA924_tagSCQunyingMatchList.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HA9_Function/DTCA924_tagSCQunyingMatchList.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HA9_Function/DTCA925_tagSCQunyingPlayerInfo.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HA9_Function/DTCA925_tagSCQunyingPlayerInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HA9_Function/HA924_tagSCQunyingMatchList.cs 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HA9_Function/HA924_tagSCQunyingMatchList.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HA9_Function/HA925_tagSCQunyingPlayerInfo.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HA9_Function/HA925_tagSCQunyingPlayerInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Main.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleConst.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/QYBattleField.cs 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleField/QYBattleField.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleFieldFactory.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Battle/BattleManager.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/BillboardRank/RankModel.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/ChallengeTab/QunyingTabHandler.cs 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/FuncPreset/FuncPresetManager.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYBattleFailWin.cs 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYBattleFailWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYBattleVictoryWin.cs 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYBattleVictoryWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYBattleWin.cs 306 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYBattleWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYFighterCell.cs 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYFighterCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYPlayerTop3Cell.cs 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYPlayerTop3Cell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYWin.cs 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QYWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Qunying/QunyingManager.cs 275 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Settlement/BattleSettlementManager.cs 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Store/StoreModel.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/ViewNPC/ViewNPCManager.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/EnumHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB210_tagCSQunyingMatch.cs
New file
@@ -0,0 +1,18 @@
using UnityEngine;
using System.Collections;
// B2 10 群英榜匹配玩家 #tagCSQunyingMatch
public class CB210_tagCSQunyingMatch : GameNetPackBasic {
    public byte IsRefresh;    // 0-打开界面时查询,1-强制刷新匹配列表
    public CB210_tagCSQunyingMatch () {
        combineCmd = (ushort)0x03FE;
        _cmd = (ushort)0xB210;
    }
    public override void WriteToBytes () {
        WriteBytes (IsRefresh, NetDataType.BYTE);
    }
}
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB210_tagCSQunyingMatch.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 809fff7a1e32fed408b8f79146ede0c5
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DTCFile/ServerPack/H03_MainCharacter/DTC0320_tagFBEnd.cs
@@ -9,5 +9,6 @@
        H0320_tagFBEnd vNetData = vNetPack as H0320_tagFBEnd;
        BoneFieldManager.Instance.UpdateFBEnd(vNetData);
        TianziBillboradManager.Instance.UpdateFBEnd(vNetData);
        QunyingManager.Instance.UpdateFBEnd(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HA9_Function/DTCA924_tagSCQunyingMatchList.cs
New file
@@ -0,0 +1,12 @@
using UnityEngine;
using System.Collections;
// A9 24 群英榜匹配玩家列表 #tagSCQunyingMatchList
public class DTCA924_tagSCQunyingMatchList : DtcBasic {
    public override void Done(GameNetPackBasic vNetPack) {
        base.Done(vNetPack);
        HA924_tagSCQunyingMatchList vNetData = vNetPack as HA924_tagSCQunyingMatchList;
        QunyingManager.Instance.UpdateQunyingMatchInfo(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HA9_Function/DTCA924_tagSCQunyingMatchList.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ff9bbc83b46795c4fa7c9acf79289dcb
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DTCFile/ServerPack/HA9_Function/DTCA925_tagSCQunyingPlayerInfo.cs
New file
@@ -0,0 +1,12 @@
using UnityEngine;
using System.Collections;
// A9 25 群英榜玩家信息 #tagSCQunyingPlayerInfo
public class DTCA925_tagSCQunyingPlayerInfo : DtcBasic {
    public override void Done(GameNetPackBasic vNetPack) {
        base.Done(vNetPack);
        HA925_tagSCQunyingPlayerInfo vNetData = vNetPack as HA925_tagSCQunyingPlayerInfo;
        QunyingManager.Instance.UpdateQunyingInfo(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HA9_Function/DTCA925_tagSCQunyingPlayerInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 960c25e4865aa4d4c894e9bf02f76dd0
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs
@@ -159,6 +159,8 @@
        Register(typeof(HAA20_tagSCActSignPlayerInfo), typeof(DTCAA20_tagSCActSignPlayerInfo));
        Register(typeof(HAA21_tagSCActHeroAppearInfo), typeof(DTCAA21_tagSCActHeroAppearInfo));
        Register(typeof(HAA22_tagSCActHeroAppearPlayerInfo), typeof(DTCAA22_tagSCActHeroAppearPlayerInfo));
        Register(typeof(HA924_tagSCQunyingMatchList), typeof(DTCA924_tagSCQunyingMatchList));
        Register(typeof(HA925_tagSCQunyingPlayerInfo), typeof(DTCA925_tagSCQunyingPlayerInfo));
    }
    //主工程注册封包
Main/Core/NetworkPackage/ServerPack/HA9_Function/HA924_tagSCQunyingMatchList.cs
New file
@@ -0,0 +1,51 @@
using UnityEngine;
using System.Collections;
// A9 24 群英榜匹配玩家列表 #tagSCQunyingMatchList
public class HA924_tagSCQunyingMatchList : GameNetPackBasic {
    public byte MatchCount;
    public  tagSCQunyingMatchInfo[] MatchList;    // 匹配列表,从高分到低分
    public HA924_tagSCQunyingMatchList () {
        _cmd = (ushort)0xA924;
    }
    public override void ReadFromBytes (byte[] vBytes) {
        TransBytes (out MatchCount, vBytes, NetDataType.BYTE);
        MatchList = new tagSCQunyingMatchInfo[MatchCount];
        for (int i = 0; i < MatchCount; i ++) {
            MatchList[i] = new tagSCQunyingMatchInfo();
            TransBytes (out MatchList[i].Rank, vBytes, NetDataType.WORD);
            TransBytes (out MatchList[i].PlayerID, vBytes, NetDataType.DWORD);
            TransBytes (out MatchList[i].PlayerName, vBytes, NetDataType.Chars, 33);
            TransBytes (out MatchList[i].LV, vBytes, NetDataType.WORD);
            TransBytes (out MatchList[i].RealmLV, vBytes, NetDataType.WORD);
            TransBytes (out MatchList[i].FightPower, vBytes, NetDataType.DWORD);
            TransBytes (out MatchList[i].FightPowerEx, vBytes, NetDataType.DWORD);
            TransBytes (out MatchList[i].Face, vBytes, NetDataType.DWORD);
            TransBytes (out MatchList[i].FacePic, vBytes, NetDataType.DWORD);
            TransBytes (out MatchList[i].TitleID, vBytes, NetDataType.DWORD);
            TransBytes (out MatchList[i].ModelMark, vBytes, NetDataType.DWORD);
            TransBytes (out MatchList[i].EquipShowSwitch, vBytes, NetDataType.DWORD);
            TransBytes (out MatchList[i].ServerID, vBytes, NetDataType.DWORD);
        }
    }
    public class tagSCQunyingMatchInfo {
        public ushort Rank;        //排名,从1开始
        public uint PlayerID;        //目标玩家ID
        public string PlayerName;
        public ushort LV;        // 玩家等级
        public ushort RealmLV;        //境界,机器人读境界表取等级对应境界
        public uint FightPower;        //战力求余亿部分
        public uint FightPowerEx;        //战力整除亿部分
        public uint Face;        //基本脸型
        public uint FacePic;        //头像框
        public uint TitleID;        //称号
        public uint ModelMark;        //变形模型mark
        public uint EquipShowSwitch;        //其他外观信息
        public uint ServerID;
    }
}
Main/Core/NetworkPackage/ServerPack/HA9_Function/HA924_tagSCQunyingMatchList.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 641ac365694c83f4db552c0105d7c26f
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/ServerPack/HA9_Function/HA925_tagSCQunyingPlayerInfo.cs
New file
@@ -0,0 +1,23 @@
using UnityEngine;
using System.Collections;
// A9 25 群英榜玩家信息 #tagSCQunyingPlayerInfo
public class HA925_tagSCQunyingPlayerInfo : GameNetPackBasic {
    public uint RefreshCnt;    // 本周已刷新匹配次数
    public uint LastRecoverTime;    // 上次免费恢复挑战令时间戳,为0时可不用倒计时
    public ushort RankHighest;    // 历史最高名次,第1名为最高
    public uint RankSuccAward;    // 历史最高名次成就领奖记录,按奖励记录索引位运算记录是否已领取
    public HA925_tagSCQunyingPlayerInfo () {
        _cmd = (ushort)0xA925;
    }
    public override void ReadFromBytes (byte[] vBytes) {
        TransBytes (out RefreshCnt, vBytes, NetDataType.DWORD);
        TransBytes (out LastRecoverTime, vBytes, NetDataType.DWORD);
        TransBytes (out RankHighest, vBytes, NetDataType.WORD);
        TransBytes (out RankSuccAward, vBytes, NetDataType.DWORD);
    }
}
Main/Core/NetworkPackage/ServerPack/HA9_Function/HA925_tagSCQunyingPlayerInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 49ebce4603fc8bd439702371212c21d1
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Main.cs
@@ -110,6 +110,7 @@
        managers.Add(SmallFuncManager.Instance);
        managers.Add(HeroDebutManager.Instance);
        managers.Add(GeneralActInfoManager.Instance);
        managers.Add(QunyingManager.Instance);
        foreach (var manager in managers)
        {
Main/System/Battle/BattleConst.cs
@@ -14,6 +14,7 @@
        typeof(TianziBillboradBattleWin),
        typeof(WarlordPavilionBattleWin),
        typeof(PreviewBattleWin),
        typeof(QYBattleWin),
    };
    // 战场名称
@@ -24,6 +25,7 @@
    public const string TianziBillboradBattleField = "TianziBillboradBattleField";
    public const string WarlordPavilionBattleField = "WarlordPavilionBattleField";
    public const string PriviewBattleField = "PriviewBattleField";  //预览战斗
    public const string QYBattleField = "QYBattleField";
    public static Dictionary<string, string> battleNameToWinName = new Dictionary<string, string>()
    {
@@ -34,6 +36,7 @@
        { TianziBillboradBattleField, "TianziBillboradBattleWin" },
        { WarlordPavilionBattleField, "WarlordPavilionBattleWin" },
        { PriviewBattleField, "PreviewBattleWin" },
        { QYBattleField, "QYBattleWin" },
    };
    // 索引配置用
@@ -45,6 +48,7 @@
        { TianziBillboradBattleField, 4 },
        { WarlordPavilionBattleField, 5 },
        { PriviewBattleField, 6 },
        { QYBattleField, 7 },
    };
    //和 CreateBattleField 里的对应
@@ -57,12 +61,14 @@
        {30020, TianziBillboradBattleField},
        {30030, WarlordPavilionBattleField},
        {30000, PriviewBattleField},
        {32000, QYBattleField},
    };
    //pvp战斗的战场,不在这个列表的视为pve类型的战场
    public static List<string> pvpBattleNameDic = new List<string>()
    {
        ArenaBattleField,
        QYBattleField,
    };
    
Main/System/Battle/BattleField/QYBattleField.cs
New file
@@ -0,0 +1,106 @@
using System;
using LitJson;
using UnityEngine;
using System.Collections.Generic;
public class QYBattleField : BattleField
{
    public QYBattleField(string _guid) : base(_guid)
    {
    }
    public override void Init(int MapID, int FuncLineID, JsonData _extendData,
        List<TeamBase> _redTeamList, List<TeamBase> _blueTeamList, byte turnMax)
    {
        base.Init(MapID, FuncLineID, _extendData, _redTeamList, _blueTeamList, turnMax);
        SetBattleMode(BattleMode.Record);
    }
    public override void AutoSetBattleMode()
    {
        SetBattleMode(BattleMode.Record);
    }
    public override void TurnFightState(int TurnNum, int State,
        uint FuncLineID, JsonData extendData)
    {
        base.TurnFightState(TurnNum, State, FuncLineID, extendData);
        switch (State)
        {
            //  起始状态标记
            case 0:
                break;
            case 1://准备完毕
                break;
            case 2://战斗中
                break;
            case 3://战斗结束
                break;
            case 4://结算奖励
                break;
            case 5://结束状态标记
                break;
            default:
                BattleDebug.LogError("recieve a unknown State");
                break;
        }
    }
    protected override void OnSettlement(JsonData turnFightStateData)
    {
        base.OnSettlement(turnFightStateData);
    }
    public override void WhaleFall()
    {
        AutoFightModel.Instance.isPause = false;
        Destroy();
        // 切出战斗界面不弹演武场界面
        if (UIManager.Instance.IsOpened<QYBattleWin>())
        {
            UIManager.Instance.CloseWindow<QYBattleWin>();
            QunyingManager.Instance.openQYWinNeedRoll = false;
            UIManager.Instance.OpenWindow<QYWin>();
        }
    }
    public override void Run()
    {
        if (operationAgent == null)
        {
            //防范异常
            return;
        }
        base.Run();
    }
    public override void DistributeNextPackage()
    {
        if (IsBattleFinish)
            return;
        //  不要调用base的函数
        BattleManager.Instance.DistributeNextReportPackage(guid);
    }
    public override void ShowWindow(HB424_tagSCTurnFightInit vNetData)
    {
        QYBattleWin fsBattleWin = UIManager.Instance.GetUI<QYBattleWin>();// as FullScreenBattleWin;
        if (null == fsBattleWin)
        {
            fsBattleWin = UIManager.Instance.OpenWindow<QYBattleWin>();
        }
        fsBattleWin.SetBattleField(this);
        if (UIManager.Instance.IsOpened<QYWin>())
        {
            UIManager.Instance.CloseWindow<QYWin>();
        }
    }
}
Main/System/Battle/BattleField/QYBattleField.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3754873d62465ca43987e130db4a0303
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Battle/BattleFieldFactory.cs
@@ -35,6 +35,9 @@
            case 30000:
                battleField = new PriviewBattleField(guid);
                break;
            case 32000:
                battleField = new QYBattleField(guid);
                break;
            default:
                break;
        }
Main/System/Battle/BattleManager.cs
@@ -650,7 +650,7 @@
    //发进入战斗包
    private float lastTime = 0f;
    private float turnCoolDown = 0.5f; // 冷却时间
    public void SendTurnFight(uint mapID, uint funcLineID = 0, byte tagType = 0, uint tagID = 0, uint[] valueList = null)
    public void SendTurnFight(uint mapID, uint funcLineID = 0, byte tagType = 0, uint tagID = 0, uint[] valueList = null, bool showLoading = true)
    {
        // 连续频繁发包,触发提示
        float currentTime = Time.time;
@@ -673,7 +673,7 @@
        }
        GameNetSystem.Instance.SendInfo(pack);
        Debug.Log("战斗时序 发起 " + Time.time);
        if (mapID != 1)
        if (mapID != 1 && showLoading)
        {
            UIManager.Instance.OpenWindow<MapLoadingWin>();
        }
Main/System/BillboardRank/RankModel.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using LitJson;
using UnityEngine;
// 支持分页查询排行榜, 本服/跨服统一使用 参考QueryRankByPage  新封包 DTCA130_tagMCViewBillboardRet
@@ -81,6 +82,13 @@
        data.cmpValue2 = serverData.CmpValue2;
        data.cmpValue3 = serverData.CmpValue3;
        data.userData = serverData.UserData;
        var userData = JsonMapper.ToObject(serverData.UserData);
        if (userData.ContainsKey("FightPower"))
        {
            long.TryParse(userData["FightPower"].ToString(), out data.fightPower);
        }
        data.rank = serverData.Rank;
        data.type = type;
        data.index = serverData.Index;
@@ -178,6 +186,13 @@
        data.cmpValue2 = serverData.CmpValue2;
        data.cmpValue3 = serverData.CmpValue3;
        data.userData = serverData.UserData;
        var userData = JsonMapper.ToObject(serverData.UserData);
        if (userData.ContainsKey("FightPower"))
        {
            long.TryParse(userData["FightPower"].ToString(), out data.fightPower);
        }
        data.rank = serverData.Rank;
        data.index = serverData.Index;
        data.type = type;   //与服务端一致的跨服排行榜类型,外部自行处理不同分组分赛季等情况
@@ -433,6 +448,7 @@
    public uint cmpValue2;
    public uint cmpValue3;
    public string userData;
    public long fightPower;
    public int rank;   // 排名从1开始,代表第1名
    public int index;    //数据在榜单列表中的索引,从0开始 非排名 分页查询会用到 
}
Main/System/ChallengeTab/QunyingTabHandler.cs
@@ -17,33 +17,34 @@
    protected override Action GetOnClickAction()
    {
        return HandleArenaNavigation;
        return HandleNavigation;
    }
    private void HandleArenaNavigation()
    private void HandleNavigation()
    {
        if (!FuncOpen.Instance.IsFuncOpen(GetFuncId(), true))
            return;
        UIManager.Instance.CloseWindow<ChallengeTabWin>();
        
        // BattleField battle = BattleManager.Instance.GetBattleFieldByMapID(32000);
        // if (battle != null)
        // {
        //     ArenaBattleWin battleWin;
        //     if (!UIManager.Instance.IsOpened<ArenaBattleWin>())
        //     {
        //         battleWin = UIManager.Instance.OpenWindow<ArenaBattleWin>();
        //     }
        //     else
        //     {
        //         battleWin = UIManager.Instance.GetUI<ArenaBattleWin>();
        //     }
        //     battleWin.SetBattleField(battle);
        // }
        // else
        // {
        //     UIManager.Instance.OpenWindow<ArenaWin>();
        // }
        BattleField battle = BattleManager.Instance.GetBattleFieldByMapID(QunyingManager.DataMapID);
        if (battle != null)
        {
            QYBattleWin battleWin;
            if (!UIManager.Instance.IsOpened<QYBattleWin>())
            {
                battleWin = UIManager.Instance.OpenWindow<QYBattleWin>();
            }
            else
            {
                battleWin = UIManager.Instance.GetUI<QYBattleWin>();
            }
            battleWin.SetBattleField(battle);
        }
        else
        {
            QunyingManager.Instance.openQYWinNeedRoll = true;
            UIManager.Instance.OpenWindow<QYWin>();
        }
    }
    protected override void SubscribeToSpecificEvents()
Main/System/FuncPreset/FuncPresetManager.cs
@@ -400,9 +400,10 @@
//战斗功能区分对应存储全局方案ID,如演武场防守用哪个全局方案ID的分类
public enum BattlePreSetType
{
    None = 0,
    Story = 1, //主线
    Arena = 2,  //演武场防守
    None = 0,
    Story = 1, //主线
    Arena = 2,  //演武场防守
    Qunying = 3, //群英战防守
}
Main/System/Qunying/QYBattleFailWin.cs
New file
@@ -0,0 +1,99 @@
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using LitJson;
using UnityEngine;
using UnityEngine.UI;
public class QYBattleFailWin : UIBase
{
    [SerializeField] AvatarCell myAvatarCell;
    [SerializeField] AvatarCell enemyAvatarCell;
    [SerializeField] TextEx txtMyName;
    [SerializeField] TextEx txtEnemyName;
    [SerializeField] TextEx txtFuncName;
    [SerializeField] Button tipHeroCultivateBtn;
    [SerializeField] Button tipEquipBtn;
    [SerializeField] Button tipHeroPosBtn;
    [SerializeField] ButtonEx detailBtn;
    JsonData jsonData;
    string battleName = BattleConst.QYBattleField;
    protected override void InitComponent()
    {
        detailBtn.SetListener(() =>
        {
            BattleSettlementManager.Instance.OpenBattleDetailWin(battleName);
        });
        tipHeroCultivateBtn.AddListener(() =>
        {
            CloseWindow();
        });
        tipEquipBtn.AddListener(() =>
        {
            CloseWindow();
        });
        tipHeroPosBtn.AddListener(() =>
        {
            CloseWindow();
            UIManager.Instance.OpenWindow<HeroPosWin>();
        });
    }
    protected override void OnPreOpen()
    {
        jsonData = BattleSettlementManager.Instance.GetBattleSettlement(battleName);
        if (jsonData == null)
        {
            DelayCloseWindow().Forget();
            return;
        }
        Display();
        if (!FirstChargeManager.Instance.GetLocalFail())
        {
            FirstChargeManager.Instance.SetLocalFail();
        }
        FirstChargeManager.Instance.TryPopWin();
    }
    protected override void OnPreClose()
    {
        BattleSettlementManager.Instance.WinShowOver(battleName);
    }
    // B4 20 回合制战斗状态 #tagMCTurnFightState  通用的结算状态 State 4-结算奖励
    // Msg 中额外信息
    // "tagPlayerID":对战的目标ID,
    // "atkAddScore":发起方增加的积分,可能为0,
    // "defDecScore":被击方减少的积分,可能为0,
    // itemInfo:奖励物品列表,可能为空
    void Display()
    {
        if (!jsonData.ContainsKey("tagID"))
            return;
        uint tagPlayerID = (uint)jsonData["tagID"];
        if (!QunyingManager.Instance.TryGetPlayerInfo(tagPlayerID, out QunyingMatchInfo info))
            return;
        uint enemyFace = info.Face;
        uint enemyFacePic = info.FacePic;
        myAvatarCell.InitUI(AvatarHelper.GetAvatarModel((int)PlayerDatas.Instance.baseData.PlayerID,
                                                PlayerDatas.Instance.baseData.face,
                                                PlayerDatas.Instance.baseData.facePic));
        enemyAvatarCell.InitUI(AvatarHelper.GetAvatarModel((int)tagPlayerID, (int)enemyFace, (int)enemyFacePic));
        enemyAvatarCell.SetListener(() =>
        {
            AvatarHelper.TryViewOtherPlayerInfo((int)tagPlayerID, viewPlayerLineupType: (int)BattlePreSetType.Qunying);
        });
        txtMyName.text = PlayerDatas.Instance.baseData.PlayerName;
        txtEnemyName.text = UIHelper.ServerStringTrim(info.PlayerName);
        int funcId = (int)FuncOpenEnum.Qunying;
        txtFuncName.text = FuncOpenLVConfig.HasKey(funcId) ? FuncOpenLVConfig.Get(funcId).Name : string.Empty;
    }
}
Main/System/Qunying/QYBattleFailWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 123ef991d6043894482acaa49a2b7776
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Qunying/QYBattleVictoryWin.cs
New file
@@ -0,0 +1,141 @@
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using LitJson;
using UnityEngine;
public class QYBattleVictoryWin : UIBase
{
    [SerializeField] AvatarCell myAvatarCell;
    [SerializeField] AvatarCell enemyAvatarCell;
    [SerializeField] TextEx txtMyName;
    [SerializeField] TextEx txtEnemyName;
    [SerializeField] TextEx winInfo;
    [SerializeField] TextEx quickWinInfo;
    [SerializeField] TextEx txtFuncName;
    [SerializeField] ScrollerController scroller;
    [SerializeField] ButtonEx detailBtn;
    JsonData jsonData;
    string battleName = BattleConst.QYBattleField;
    protected override void InitComponent()
    {
        detailBtn.SetListener(() =>
        {
            BattleSettlementManager.Instance.OpenBattleDetailWin(battleName);
        });
    }
    protected override void OnPreOpen()
    {
        scroller.OnRefreshCell += OnRefreshCell;
        jsonData = BattleSettlementManager.Instance.GetBattleSettlement(battleName);
        if (jsonData == null && QunyingManager.Instance.quickCnt == 0)
        {
            DelayCloseWindow().Forget();
            return;
        }
        Display();
        CreateScroller();
    }
    protected override void OnPreClose()
    {
        scroller.OnRefreshCell -= OnRefreshCell;
        BattleSettlementManager.Instance.WinShowOver(battleName);
        QunyingManager.Instance.quickCnt = 0;
        QunyingManager.Instance.itemInfos.Clear();
    }
    // B4 20 回合制战斗状态 #tagMCTurnFightState  通用的结算状态 State 4-结算奖励
    // Msg 中额外信息
    // "tagPlayerID":对战的目标ID,
    // "atkAddScore":发起方增加的积分,可能为0,
    // "defDecScore":被击方减少的积分,可能为0,
    // itemInfo:奖励物品列表,可能为空
    void Display()
    {
        int quickCnt = QunyingManager.Instance.quickCnt;
        uint tagPlayerID = quickCnt == 0 ? (uint)jsonData["tagPlayerID"] : (uint)QunyingManager.Instance.tagPlayerID;
        if (!QunyingManager.Instance.TryGetPlayerInfo(tagPlayerID, out QunyingMatchInfo info))
            return;
        uint enemyFace = info.Face;
        uint enemyFacePic = info.FacePic;
        myAvatarCell.InitUI(AvatarHelper.GetAvatarModel((int)PlayerDatas.Instance.baseData.PlayerID,
                                                PlayerDatas.Instance.baseData.face,
                                                PlayerDatas.Instance.baseData.facePic));
        enemyAvatarCell.InitUI(AvatarHelper.GetAvatarModel((int)tagPlayerID, (int)enemyFace, (int)enemyFacePic));
        enemyAvatarCell.SetListener(() =>
        {
            AvatarHelper.TryViewOtherPlayerInfo((int)tagPlayerID, viewPlayerLineupType: (int)BattlePreSetType.Qunying);
        });
        txtMyName.text = PlayerDatas.Instance.baseData.PlayerName;
        txtEnemyName.text = UIHelper.ServerStringTrim(info.PlayerName);
        if (quickCnt == 0)
        {
            winInfo.SetActive(true);
            quickWinInfo.SetActive(false);
            winInfo.text = QunyingManager.Instance.tagRank.ToString();
        }
        else
        {
            winInfo.SetActive(false);
            quickWinInfo.SetActive(true);
            quickWinInfo.text = Language.Get("Qunying16", quickCnt);
        }
        int funcId = (int)FuncOpenEnum.Qunying;
        txtFuncName.text = FuncOpenLVConfig.HasKey(funcId) ? FuncOpenLVConfig.Get(funcId).Name : string.Empty;
    }
    List<Item> showItems = new List<Item>();
    void CreateScroller()
    {
        showItems.Clear();
        scroller.Refresh();
        if (QunyingManager.Instance.quickCnt == 0)
        {
            if (!jsonData.ContainsKey("itemInfo"))
            {
                return;
            }
            var resultStr = jsonData["itemInfo"];
            for (int i = 0; i < resultStr.Count; i++)
            {
                showItems.Add(new Item((int)resultStr[i]["ItemID"], (long)resultStr[i]["Count"]));
            }
        }
        else
        {
            for (int i = 0; i < QunyingManager.Instance.itemInfos.Count; i++)
            {
                showItems.Add(QunyingManager.Instance.itemInfos[i]);
            }
        }
        showItems.Sort(SortItem);
        for (int i = 0; i < showItems.Count; i++)
        {
            scroller.AddCell(ScrollerDataType.Header, i);
        }
        scroller.Restart();
    }
    int SortItem(Item itemA, Item itemB)
    {
        var itemConfigA = ItemConfig.Get(itemA.id);
        var itemConfigB = ItemConfig.Get(itemB.id);
        return itemConfigB.ItemColor - itemConfigA.ItemColor;
    }
    void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var _cell = cell as SettlementAwardCell;
        var item = showItems[cell.index];
        _cell?.Display(item.id, item.countEx);
    }
}
Main/System/Qunying/QYBattleVictoryWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cf3dc1591a467cf4a90a3fe1b5a42cc4
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Qunying/QYBattleWin.cs
New file
@@ -0,0 +1,306 @@
using System.Collections.Generic;
using LitJson;
using UnityEngine;
using UnityEngine.UI;
public class QYBattleWin : BaseBattleWin
{
    [SerializeField] Transform transButtons;
    [SerializeField] HeroCountryComponent myCountry;
    [SerializeField] TextEx txtMyLV;
    [SerializeField] TextEx txtMyName;
    [SerializeField] TextEx txtMyHp;
    [SerializeField] ImageEx imgMyHp;
    [SerializeField] TextEx txtMyFightPonit;
    [SerializeField] AvatarCell myAvatarCell;
    [SerializeField] List<ArenaHeroHead> myHeroHeads;
    [SerializeField] HeroCountryComponent enemyCountry;
    [SerializeField] TextEx txtEnemyLV;
    [SerializeField] TextEx txtEnemyName;
    [SerializeField] TextEx txtEnemyHp;
    [SerializeField] ImageEx imgEnemyHp;
    [SerializeField] TextEx txtEnemyFightPonit;
    [SerializeField] AvatarCell enemyAvatarCell;
    [SerializeField] List<ArenaHeroHead> enemyHeroHeads;
    [SerializeField] Text funcName;
    protected override void RegisterBattleEvents()
    {
        base.RegisterBattleEvents();
        EventBroadcast.Instance.AddListener<string, JsonData>(EventName.BATTLE_END, OnBattleEnd);
    }
    protected override void UnregisterBattleEvents()
    {
        base.UnregisterBattleEvents();
        EventBroadcast.Instance.RemoveListener<string, JsonData>(EventName.BATTLE_END, OnBattleEnd);
    }
    protected virtual void OnBattleEnd(string guid, JsonData endData)
    {
        if (battleField != null && guid == battleField.guid)
        {
            DisplayHpInfo();
        }
    }
    protected override void OnPreOpen()
    {
        base.OnPreOpen();
        MainWin.TabChangeEvent += OnTabChangeEvent;
        UIManager.Instance.OnOpenWindow += OnOpenWindow;
        bool isOpenBattleChangeTab = IsOpenBattleChangeTab();
        transButtons.localPosition = new Vector3(0, isOpenBattleChangeTab ? 130 : 0, 0);
        if (isOpenBattleChangeTab)
        {
            UIManager.Instance.GetUI<MainWin>()?.CloseSubUI();
        }
        else
        {
            UIManager.Instance.CloseWindow<MainWin>();
        }
        isClickSkip = false;
        int funcId = (int)FuncOpenEnum.Qunying;
        funcName.text = FuncOpenLVConfig.HasKey(funcId) ? FuncOpenLVConfig.Get(funcId).Name : string.Empty;
    }
    protected override void OnPreClose()
    {
        base.OnPreClose();
        MainWin.TabChangeEvent -= OnTabChangeEvent;
        UIManager.Instance.OnOpenWindow -= OnOpenWindow;
        bool isOpenBattleChangeTab = IsOpenBattleChangeTab();
        if (isOpenBattleChangeTab)
        {
            UIManager.Instance.GetUI<MainWin>()?.RestoreSubUI();
        }
        else
        {
            UIManager.Instance.OpenWindow<MainWin>();
        }
        if (isClickSkip)
        {
            isClickSkip = false;
            TryPass();
        }
    }
    void OnOpenWindow(UIBase win)
    {
        if (win is QYBattleVictoryWin || win is QYBattleFailWin)
        {
            isClickSkip = false;
        }
    }
    bool isClickSkip = false;
    protected override void OnClickPass()
    {
        if (!IsPass())
            return;
        isClickSkip = true;
        clickTime = Time.time;  // 记录点击时间
        battleField.ForceFinish();
    }
    float stayTime = 2f;
    float clickTime = 0f;
    void LateUpdate()
    {
        if (isClickSkip && Time.time - clickTime >= stayTime)
        {
            isClickSkip = false;
            TryPass();
        }
    }
    private void TryPass()
    {
        if (UIManager.Instance.IsOpened<QYBattleVictoryWin>() ||
            UIManager.Instance.IsOpened<QYBattleFailWin>())
            return;
        CloseWindow();
        Debug.LogError($"OnBattleEnd 异常关闭");
        BattleSettlementManager.Instance.WinShowOver(BattleConst.QYBattleField);
    }
    private void OnTabChangeEvent()
    {
        CloseWindow();
    }
    protected override void OnDamageTaken(BattleDmgInfo damageInfo)
    {
        base.OnDamageTaken(damageInfo);
        if (battleField == null)
            return;
        if (damageInfo.battleFieldGuid == battleField.guid)
        {
            DisplayHpInfo();
        }
    }
    protected override void OnCreateBattleField(string guid, BattleField field)
    {
        if (field is QYBattleField)
        {
            SetBattleField(field);
        }
    }
    protected override void RefreshSpecific()
    {
        DisplayHpInfo();
        DisplayPlayerInfo();
    }
    private void DisplayHpInfo()
    {
        if (battleField == null)
            return;
        // 获取我方(红方)队伍数据
        List<BattleObject> myTeam = battleField.battleObjMgr.GetBattleObjList(BattleCamp.Red);
        // 获取敌方(蓝方)队伍数据
        List<BattleObject> enemyTeam = battleField.battleObjMgr.GetBattleObjList(BattleCamp.Blue);
        ulong myMaxHp = GetMaxHP(myTeam);
        ulong enemyMaxHp = GetMaxHP(enemyTeam);
        ulong myNowHp = GetNowHP(myTeam);
        ulong enemyNowHp = GetNowHP(enemyTeam);
        txtMyHp.text = Language.Get("BoneField09", UIHelper.ReplaceLargeNum(myNowHp), UIHelper.ReplaceLargeNum(myMaxHp));
        txtEnemyHp.text = Language.Get("BoneField09", UIHelper.ReplaceLargeNum(enemyNowHp), UIHelper.ReplaceLargeNum(enemyMaxHp));
        imgMyHp.fillAmount = Mathf.Clamp01((myMaxHp > 0) ? (float)myNowHp / myMaxHp : 0f);
        imgEnemyHp.fillAmount = Mathf.Clamp01((enemyMaxHp > 0) ? (float)enemyNowHp / enemyMaxHp : 0f);
    }
    private long GetFightPonit(List<BattleObject> Team)
    {
        if (Team.IsNullOrEmpty())
        {
            return 0;
        }
        long res = 0;
        foreach (var obj in Team)
        {
            if (obj is not HeroBattleObject)
                continue;
            res += obj.GetFightPower();
        }
        return res;
    }
    private void DisplayPlayerInfo()
    {
        if (battleField == null)
            return;
        if (!QunyingManager.Instance.TryGetPlayerInfo(QunyingManager.Instance.atkPlayerId, out QunyingMatchInfo info))
            return;
        // 获取我方(红方)队伍数据
        List<BattleObject> myTeam = battleField.battleObjMgr.GetBattleObjList(BattleCamp.Red);
        // 获取敌方(蓝方)队伍数据
        List<BattleObject> enemyTeam = battleField.battleObjMgr.GetBattleObjList(BattleCamp.Blue);
        txtEnemyLV.text = Language.Get("Arena22", info.LV);
        txtEnemyName.text = UIHelper.ServerStringTrim(info.PlayerName);
        txtEnemyFightPonit.text = UIHelper.ReplaceLargeArtNum(GetFightPonit(enemyTeam));
        enemyAvatarCell.InitUI(AvatarHelper.GetAvatarModel((int)info.PlayerID, (int)info.Face, (int)info.FacePic));
        enemyAvatarCell.SetListener(() =>
        {
            AvatarHelper.TryViewOtherPlayerInfo((int)info.PlayerID, viewPlayerLineupType: (int)BattlePreSetType.Qunying);
        });
        var team = GetTeamHeroList(enemyTeam);
        enemyCountry.RefreshOnTeamCountry(team, true);
        txtMyLV.text = Language.Get("Arena22", PlayerDatas.Instance.baseData.LV);
        txtMyName.text = PlayerDatas.Instance.baseData.PlayerName;
        long myFightPower = GetFightPonit(myTeam);
        txtMyFightPonit.text = UIHelper.ReplaceLargeArtNum(myFightPower);
        myAvatarCell.InitUI(AvatarHelper.GetAvatarModel((int)PlayerDatas.Instance.baseData.PlayerID, PlayerDatas.Instance.baseData.face, PlayerDatas.Instance.baseData.facePic));
        team = GetTeamHeroList(myTeam);
        myCountry.RefreshOnTeamCountry(team, true);
        for (int i = 0; i < myHeroHeads.Count; i++)
        {
            if (i < myTeam.Count && myTeam[i] is HeroBattleObject heroBattleObject)
            {
                myHeroHeads[i].SetActive(true);
                var teamHero = heroBattleObject.teamHero;
                myHeroHeads[i].Display(teamHero.heroId, teamHero.SkinID, teamHero.level);
            }
            else
            {
                myHeroHeads[i].SetActive(false);
            }
        }
        // 敌方英雄显示(从右到左)
        for (int i = enemyHeroHeads.Count - 1; i >= 0; i--)
        {
            int teamIndex = enemyHeroHeads.Count - 1 - i;  // 建立反向映射
            if (teamIndex < enemyTeam.Count && enemyTeam[teamIndex] is HeroBattleObject heroBattleObject)
            {
                enemyHeroHeads[i].SetActive(true);
                var teamHero = heroBattleObject.teamHero;  // 使用映射后的索引
                enemyHeroHeads[i].Display(teamHero.heroId, teamHero.SkinID, teamHero.level);
            }
            else
            {
                enemyHeroHeads[i].SetActive(false);
            }
        }
    }
    ulong GetMaxHP(List<BattleObject> battleObjects)
    {
        ulong sun = 0;
        if (!battleObjects.IsNullOrEmpty())
        {
            for (int i = 0; i < battleObjects.Count; i++)
            {
                sun += (ulong)battleObjects[i].GetMaxHp();
            }
        }
        return sun;
    }
    ulong GetNowHP(List<BattleObject> battleObjects)
    {
        ulong sun = 0;
        if (!battleObjects.IsNullOrEmpty())
        {
            for (int i = 0; i < battleObjects.Count; i++)
            {
                sun += (ulong)battleObjects[i].GetCurHp();
            }
        }
        return sun;
    }
    List<TeamHero> GetTeamHeroList(List<BattleObject> teams)
    {
        List<TeamHero> teamHeroes = new List<TeamHero>();
        if (teams.IsNullOrEmpty())
            return teamHeroes;
        foreach (var item in teams)
        {
            if (item is HeroBattleObject heroBattleObject)
            {
                teamHeroes.Add(heroBattleObject.teamHero);
            }
        }
        return teamHeroes;
    }
    bool IsOpenBattleChangeTab()
    {
        return FuncOpen.Instance.IsFuncOpen(ArenaManager.Instance.BattleChangeTabFuncId);
    }
}
Main/System/Qunying/QYBattleWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2fea3a4b19e88144eb09b61bf7bc4e78
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Qunying/QYFighterCell.cs
New file
@@ -0,0 +1,173 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
// 群英挑战
public class QYFighterCell : MonoBehaviour
{
    [SerializeField] HorseController model;
    [SerializeField] OfficialTitleCell officialTitleCell;
    [SerializeField] Text fightPowerText;
    [SerializeField] Text nameText;
    [SerializeField] Text serverText;
    [SerializeField] Button queryPlayerBtn; //后续添加点击查看玩家详情
    [SerializeField] Text rankText;
    [SerializeField] Transform myMark;
    [SerializeField] Button challengeBtn;
    [SerializeField] Transform quickObj;
    [SerializeField] Button quickChallengeBtn;
    [SerializeField] Button quickChallengeMoreBtn;
    [SerializeField] Text quickChallengeMoreText;
    QunyingMatchInfo matchInfo;
    void Start()
    {
        challengeBtn.SetListener(() =>
        {
            if (matchInfo == null)
                return;
            if (!UIHelper.CheckMoneyCount(QunyingManager.challengeMoneyType, 1, 1))
            {
                StoreModel.Instance.ShowBuyItem(QunyingManager.challengeShopID, 0);
                return;
            }
            QunyingManager.Instance.atkPlayerId = matchInfo.PlayerID;
            QunyingManager.Instance.tagRank = matchInfo.Rank;
            BattleManager.Instance.SendTurnFight(QunyingManager.DataMapID, 0, 1, matchInfo.PlayerID, new uint[] { matchInfo.Rank, 0 });
        });
        queryPlayerBtn.AddListener(() =>
        {
            if (matchInfo.PlayerID < 1000000) return;
            AvatarHelper.TryViewOtherPlayerInfo((int)matchInfo.PlayerID, viewPlayerLineupType: (int)BattlePreSetType.Qunying);
        });
        quickChallengeBtn.AddListener(() =>
        {
            if (matchInfo == null)
                return;
            if (!UIHelper.CheckMoneyCount(QunyingManager.challengeMoneyType, 1, 1))
            {
                StoreModel.Instance.ShowBuyItem(QunyingManager.challengeShopID, 0);
                return;
            }
            QunyingManager.Instance.atkPlayerId = matchInfo.PlayerID;
            BattleManager.Instance.SendTurnFight(QunyingManager.DataMapID, 0, 1, matchInfo.PlayerID, new uint[] { matchInfo.Rank, 1 }, false);
        });
        quickChallengeMoreBtn.AddListener(() =>
        {
            if (matchInfo == null)
                return;
            //最低显示两次,但可以最低挑战1次
            var cnt = Math.Max(1, Math.Min(5, UIHelper.GetMoneyCnt(QunyingManager.challengeMoneyType)));
            if (!UIHelper.CheckMoneyCount(QunyingManager.challengeMoneyType, cnt, 1))
            {
                StoreModel.Instance.ShowBuyItem(QunyingManager.challengeShopID, 0);
                return;
            }
            QunyingManager.Instance.atkPlayerId = matchInfo.PlayerID;
            BattleManager.Instance.SendTurnFight(QunyingManager.DataMapID, 0, 1, matchInfo.PlayerID, new uint[] { matchInfo.Rank, (uint)cnt }, false);
        });
    }
    public void Display(int index)
    {
        var myMatch = QunyingManager.Instance.GetMyMatchInfo(out int myIndex);
        var list = QunyingManager.Instance.matchInfoList;
        if (list.IsNullOrEmpty() || index < 0 || index >= list.Count)
        {
            if (myMatch != null)
            {
                this.SetActive(false);
                return;
            }
            if (myMatch == null && index != 4)
            {
                this.SetActive(false);
                return;
            }
            //自己未上版的 在第5位补
        }
        this.SetActive(true);
        if (myMatch == null && index == 4)
        {
            //填充自己的
            matchInfo = new QunyingMatchInfo
            {
                Rank = 0,
                PlayerID = PlayerDatas.Instance.baseData.PlayerID,
                PlayerName = PlayerDatas.Instance.baseData.PlayerName,
                LV = PlayerDatas.Instance.baseData.LV,
                RealmLV = PlayerDatas.Instance.baseData.realmLevel,
                FightPower = (ulong)PlayerDatas.Instance.baseData.FightPower,
                TitleID = (uint)PlayerDatas.Instance.baseData.TitleID,
                ModelMark = (uint)PlayerDatas.Instance.baseData.modelMark,
                EquipShowSwitch = PlayerDatas.Instance.baseData.equipShowSwitch,
                ServerID = (uint)ServerListCenter.Instance.currentServer.region_flag,
            };
        }
        else
        {
            matchInfo = list[index];
        }
        nameText.text = UIHelper.ServerStringTrim(matchInfo.PlayerName);
        if (matchInfo.ServerID == 0)
        {
            serverText.text = Language.Get("Qunying15");
        }
        else
        {
            serverText.text = ServerListCenter.Instance.GetServerName((int)matchInfo.ServerID);
        }
        fightPowerText.text = UIHelper.ReplaceLargeArtNum(matchInfo.FightPower);
        officialTitleCell.InitUI(matchInfo.RealmLV, (int)matchInfo.TitleID);
        int modelMark = (int)matchInfo.ModelMark;
        if (modelMark == 0)
        {
            modelMark = QunyingManager.Instance.robotModelIDs[matchInfo.PlayerID % QunyingManager.Instance.robotModelIDs.Length];
        }
        model.Create((int)matchInfo.EquipShowSwitch % 1000, modelMark, 0.9f);
        rankText.text = matchInfo.Rank > 0 ? $"{matchInfo.Rank}" : Language.Get("L1125");
        myMark.SetActive(matchInfo.PlayerID == PlayerDatas.Instance.baseData.PlayerID);
        var ticketCnt = Math.Max(2, Math.Min(5, UIHelper.GetMoneyCnt(QunyingManager.challengeMoneyType)));
        if (myMatch != null && myMatch.Rank < matchInfo.Rank)
        {
            //低于自己的
            quickObj.SetActive(true);
            challengeBtn.SetActive(false);
            quickChallengeMoreText.text = Language.Get("Qunying9", ticketCnt);
        }
        else if ((myMatch == null && index == 4) || (myMatch != null && myMatch.Rank == matchInfo.Rank))
        {
            //是自己,分是否上榜情况
            quickObj.SetActive(false);
            challengeBtn.SetActive(false);
        }
        else
        {
            quickObj.SetActive(false);
            challengeBtn.SetActive(true);
        }
    }
}
Main/System/Qunying/QYFighterCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8a72c6bf947ee7e4eab339e27e21d7c7
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Qunying/QYPlayerTop3Cell.cs
New file
@@ -0,0 +1,53 @@
using UnityEngine;
using UnityEngine.UI;
// 群英排行榜 玩家排行榜 前三名
public class QYPlayerTop3Cell : MonoBehaviour
{
    [SerializeField] HorseController model;
    [SerializeField] OfficialTitleCell officialTitleCell;
    [SerializeField] Text fightPowerText;
    [SerializeField] Text nameText;
    [SerializeField] Text serverText;
    [SerializeField] Button queryPlayerBtn; //后续添加点击查看玩家详情
    public void Display(int rankType, int rank)
    {
        var rankData = RankModel.Instance.GetRankDataByRank(rankType, rank);
        if (rankData == null)
        {
            serverText.text = "";
            nameText.text = Language.Get("L1124");
            officialTitleCell.SetActive(false);
            fightPowerText.text = "";
            return;
        }
        officialTitleCell.SetActive(true);
        var sid = UIHelper.GetServerIDByAccount(rankData.name2);
        if (sid == 0)
        {
            serverText.text = Language.Get("Qunying15");
        }
        else
        {
            serverText.text = ServerListCenter.Instance.GetServerName(UIHelper.GetServerIDByAccount(rankData.name2));
        }
        nameText.text = rankData.name1;
        officialTitleCell.InitUI((int)rankData.value1, (int)rankData.value2);
        model.Create(HorseManager.Instance.GetOtherPlayerHorseSkinID((int)rankData.value6), (int)rankData.value5, 0.9f);
        queryPlayerBtn.SetListener(() =>
        {
            if (rankData.id < 1000000) return;
            AvatarHelper.TryViewOtherPlayerInfo((int)rankData.id, viewPlayerLineupType: (int)BattlePreSetType.Qunying);
        });
        fightPowerText.text = UIHelper.ReplaceLargeArtNum(rankData.fightPower);
    }
}
Main/System/Qunying/QYPlayerTop3Cell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dc373890f5310614f894283a67b58cc2
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Qunying/QYWin.cs
New file
@@ -0,0 +1,117 @@
using System;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
//群英主界面
//QunyingManager.Instance.openQYWinNeedRoll 默认开启的时候滚动展示
public class QYWin : UIBase
{
    [SerializeField] QYPlayerTop3Cell[] playerTop3Cells;
    [SerializeField] QYFighterCell[] FighterCells;
    [SerializeField] ScrollRect battleScrollRect;
    [SerializeField] Button closeBtn;
    protected override void InitComponent()
    {
        closeBtn.AddListener(CloseWindow);
    }
    protected override void OnPreOpen()
    {
        if (!QunyingManager.Instance.openQYWinNeedRoll)
        {
            var myMatch = QunyingManager.Instance.GetMyMatchInfo(out int index);
            battleScrollRect.verticalNormalizedPosition = (4 - index) * 0.15f + 0f;
        }
        else
        {
            battleScrollRect.verticalNormalizedPosition = 1f;
        }
        RankModel.Instance.ResetQueryParam();
        RankModel.Instance.QueryRankByPage(QunyingManager.rankType, 0, 3);
        QunyingManager.Instance.RequestRefreshFighters(0);
        RankModel.Instance.onRankRefresh += OnRankRefresh;
        QunyingManager.Instance.OnMatchListEvent += OnMatchListEvent;
        Display();
    }
    async UniTask SmoothScrollToBottom(float targetPos)
    {
        //等待
        await UniTask.Delay(100);
        float duration = 0.3f;
        float elapsed = 0f;
        float startPos = battleScrollRect.verticalNormalizedPosition;
        while (elapsed < duration)
        {
            elapsed += Time.deltaTime;
            float t = elapsed / duration;
            battleScrollRect.verticalNormalizedPosition = Mathf.Lerp(startPos, targetPos, t);
            await UniTask.Yield();
        }
        battleScrollRect.verticalNormalizedPosition = targetPos;
    }
    protected override void OnPreClose()
    {
        RankModel.Instance.onRankRefresh -= OnRankRefresh;
        QunyingManager.Instance.OnMatchListEvent -= OnMatchListEvent;
        QunyingManager.Instance.openQYWinNeedRoll = true;
    }
    void Display()
    {
        DisplayFighers();
        DisplayPlayerTop3();
    }
    void DisplayPlayerTop3()
    {
        for (int i = 0; i < playerTop3Cells.Length; i++)
        {
            playerTop3Cells[i].Display(QunyingManager.rankType, i + 1);
        }
    }
    void OnRankRefresh(int type)
    {
        if (type != QunyingManager.rankType)
            return;
        DisplayPlayerTop3();
    }
    void DisplayFighers()
    {
        for (int i = 0; i < FighterCells.Length; i++)
        {
            FighterCells[i].Display(i);
        }
    }
    void OnMatchListEvent()
    {
        //滚动到自己的位置
        if (QunyingManager.Instance.openQYWinNeedRoll)
        {
            var myMatch = QunyingManager.Instance.GetMyMatchInfo(out int index);
            SmoothScrollToBottom(myMatch == null ? 0.1f : (4 - index) * 0.15f + 0f).Forget();
        }
        DisplayFighers();
    }
}
Main/System/Qunying/QYWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 252aa1b571920694dba4932aaa4210be
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Qunying/QunyingManager.cs
@@ -6,11 +6,29 @@
public class QunyingManager : GameSystemManager<QunyingManager>
{
    public const int challengeMoneyType = 56;
    public const int challengeShopID = 16;
    public const int rankType = 10;
    public const int recType = 312;  // 挑战记录类型
    public const int DataMapID = 32000;
    public event Action OnMatchListEvent;
    public List<QunyingMatchInfo> matchInfoList = new List<QunyingMatchInfo>();
    //用于用来拿战斗胜利失败的头像信息
    public Dictionary<uint, QunyingMatchInfo> allFaceInfoDict = new Dictionary<uint, QunyingMatchInfo>();
    public Dictionary<uint, List<QunyingGameRec>> gameRecDict = new Dictionary<uint, List<QunyingGameRec>>(); // <RecID,QunyingGameRec>
    public uint atkPlayerId;
    public int tagRank; //挑战目标的排名 结果显示用
    public event Action OnUpdateGameRecInfo;
    public bool openQYWinNeedRoll = true; //打开群英界面需要滚动的情况
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += BeforePlayerDataInitializeEventOnRelogin;
        PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefresh;
        InitTable();
    }
    public override void Release()
@@ -19,8 +37,44 @@
        PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefresh;
    }
    public int resetOpenDay; //重置天8,如第一周如果是周5开服的不会重置
    public int[] robotModelIDs;
    public int challengeMaxCnt;
    public int restoreTicketMinute;
    public int refreshMoneyType;
    public int refreshMoneyValue;
    public int refreshMaxCnt;
    public Dictionary<int, int[][]> dayRankAwards = new Dictionary<int, int[][]>();
    public Dictionary<int, int[][]> weekRankAwards = new Dictionary<int, int[][]>();
    public Dictionary<int, int[][]> achievementAwards = new Dictionary<int, int[][]>();
    public Dictionary<int, int> achievementIndexs = new Dictionary<int, int>();
    void InitTable()
    {
        var config = FuncConfigConfig.Get("QunyingSet");
        resetOpenDay = int.Parse(config.Numerical1);
        robotModelIDs = JsonMapper.ToObject<int[]>(config.Numerical2);
        config = FuncConfigConfig.Get("QunyingChallenge");
        challengeMaxCnt = int.Parse(config.Numerical1);
        restoreTicketMinute = int.Parse(config.Numerical2);
        config = FuncConfigConfig.Get("QunyingMatch");
        var moneyInfo = ConfigParse.GetMultipleStr<int>(config.Numerical2);
        refreshMoneyType = moneyInfo[0];
        refreshMoneyValue = moneyInfo[1];
        refreshMaxCnt = int.Parse(config.Numerical3);
        config = FuncConfigConfig.Get("QunyingAward");
        dayRankAwards = ConfigParse.ParseIntArray2Dict(config.Numerical1);
        weekRankAwards = ConfigParse.ParseIntArray2Dict(config.Numerical2);
        achievementAwards = ConfigParse.ParseIntArray2Dict(config.Numerical3);
        achievementIndexs = ConfigParse.ParseIntDict(config.Numerical4);
    }
    public void BeforePlayerDataInitializeEventOnRelogin()
    {
        matchInfoList.Clear();
    }
    
    private void PlayerDataRefresh(PlayerDataType type)
@@ -33,5 +87,226 @@
    }
    public void UpdateQunyingMatchInfo(HA924_tagSCQunyingMatchList vNetData)
    {
        if (vNetData == null || vNetData.MatchList.IsNullOrEmpty())
            return;
        matchInfoList.Clear();
        foreach (var item in vNetData.MatchList)
        {
            var matchInfo = new QunyingMatchInfo
            {
                Rank = item.Rank,
                PlayerID = item.PlayerID,
                PlayerName = item.PlayerName,
                LV = item.LV,
                RealmLV = item.RealmLV,
                FightPower = (ulong)item.FightPowerEx * 100000000 + (ulong)item.FightPower,
                Face = item.Face,
                FacePic = item.FacePic,
                TitleID = item.TitleID,
                ModelMark = item.ModelMark,
                EquipShowSwitch = item.EquipShowSwitch,
                ServerID = item.ServerID,
            };
            matchInfoList.Add(matchInfo);
            allFaceInfoDict[item.PlayerID] = matchInfo;
        }
        matchInfoList.Sort((a, b) => a.Rank.CompareTo(b.Rank));
        OnMatchListEvent?.Invoke();
    }
    public void UpdateQunyingInfo(HA925_tagSCQunyingPlayerInfo vNetData)
    {
    }
    public void UpdateGameRecInfo(HA009_tagSCGameRecInfo vNetData)
    {
        if (vNetData == null || vNetData.RecType != recType)
            return;
        gameRecDict.Clear();
        uint recID = vNetData.RecID;
        if (!gameRecDict.ContainsKey(recID))
            gameRecDict[recID] = new List<QunyingGameRec>();
        foreach (var rec in vNetData.RecList)
        {
            try
            {
                var userData = JsonMapper.ToObject(rec.UserData);
                string name = userData["Name"].ToString();
                int curRank = int.Parse(userData["CurRank"].ToString());
                int tagRank = int.Parse(userData["TagRank"].ToString());
                var gameRec = new QunyingGameRec
                {
                    Time = rec.Time,
                    Value1 = rec.Value1,
                    Value2 = rec.Value2,
                    Value3 = rec.Value3,
                    Value4 = rec.Value4,
                    Value5 = rec.Value5,
                    Value6 = rec.Value6,
                    Value7 = rec.Value7,
                    Value8 = rec.Value8,
                    Name = name,
                    CurRank = curRank,
                    TagRank = tagRank
                };
                gameRecDict[recID].Add(gameRec);
                if (recID == PlayerDatas.Instance.baseData.PlayerID)
                {
                    allFaceInfoDict[rec.Value3] = new QunyingMatchInfo
                    {
                        Rank = (ushort)tagRank,
                        PlayerID = rec.Value3,
                        PlayerName = name,
                        LV = (ushort)rec.Value8,
                        RealmLV = (ushort)rec.Value7,
                        Face = rec.Value5,
                        FacePic = rec.Value6,
                        ServerID = rec.Value1,
                    };
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"JSON解析错误: {ex.Message}, UserData: {rec.UserData}");
                continue;
            }
        }
        OnUpdateGameRecInfo?.Invoke();
    }
    public bool TryGetPlayerInfo(uint playerID, out QunyingMatchInfo info)
    {
        return allFaceInfoDict.TryGetValue(playerID, out info);
    }
    // 获取匹配信息中我的部分
    public QunyingMatchInfo GetMyMatchInfo(out int index)
    {
        index = 0;
        for (int i = 0; i < matchInfoList.Count; i++)
        {
            if (matchInfoList[i].PlayerID == PlayerDatas.Instance.baseData.PlayerID)
            {
                index = i;
                return matchInfoList[i];
            }
        }
        return null;
    }
    //向服务器请求刷新挑战对象
    // 0-打开界面时查询,1-强制刷新匹配列表
    public void RequestRefreshFighters(int refreshType)
    {
        var pack = new CB210_tagCSQunyingMatch();
        pack.IsRefresh = (byte)refreshType;
        GameNetSystem.Instance.SendInfo(pack);
    }
    public List<Item> itemInfos = new List<Item>();
    public int quickCnt;
    public int tagPlayerID;
    public void UpdateFBEnd(H0320_tagFBEnd vNetData)
    {
        if (vNetData.Msg == null)
            return;
        JsonData jsonData = JsonMapper.ToObject(vNetData.Msg);
        int dataMapID = int.Parse(jsonData["dataMapID"].ToString());
        if (dataMapID != DataMapID)
            return;
        quickCnt = int.Parse(jsonData["quickCnt"].ToString());
        tagPlayerID = int.Parse(jsonData["tagID"].ToString());
        itemInfos.Clear();
        if (jsonData["itemInfo"] != null && jsonData["itemInfo"].IsArray)
        {
            for (int i = 0; i < jsonData["itemInfo"].Count; i++)
            {
                JsonData itemData = jsonData["itemInfo"][i];
                Item itemInfo = new Item((int)itemData["ItemID"], (long)itemData["Count"]);
                itemInfos.Add(itemInfo);
            }
        }
        UIManager.Instance.OpenWindow<QYBattleVictoryWin>();
    }
    //是否本周开启,周几开启
    public bool TryGetOpenWeek(out bool isThisWeek, out int weekDay)
    {
        weekDay = 0;
        var openServerDay = TimeUtility.OpenDay + 1;    //今天是第几个开服天
        var openFuncDay = FuncOpenLVConfig.Get((int)FuncOpenEnum.Qunying).OpenDay;  //功能开启在第几个开服天开放
        //判断功能是否已开启
        if (openServerDay < openFuncDay - 1)
        {
            isThisWeek = false;
            return true;
        }
        //计算本周自然周开始是开服天范围
        //今天周几
        int theWeekDay = (int)TimeUtility.ServerNow.DayOfWeek == 0 ? 7 : (int)TimeUtility.ServerNow.DayOfWeek;
        int currentWeekStart = openServerDay - theWeekDay + 1;
        int currentWeekEnd = currentWeekStart + 6;
        //判断功能开启天是否在当前周内
        isThisWeek = openFuncDay >= currentWeekStart && openFuncDay <= currentWeekEnd;
        if (isThisWeek)
        {
            weekDay = openFuncDay - currentWeekStart + 1;
        }
        return true;
    }
}
public class QunyingMatchInfo
{
    public ushort Rank;        //排名,从1开始
    public uint PlayerID;        //目标玩家ID
    public string PlayerName;
    public ushort LV;        // 玩家等级
    public ushort RealmLV;        //境界,机器人读境界表取等级对应境界
    public ulong FightPower;        //战力
    public uint Face;        //基本脸型
    public uint FacePic;        //头像框
    public uint TitleID;        //称号
    public uint ModelMark;        //变形模型mark
    public uint EquipShowSwitch;        //其他外观信息
    public uint ServerID;
}
public class QunyingGameRec
{
    public uint Time;        //战斗时间戳
    public uint Value1;        //无
    public uint Value2;        //攻击类型 1-发起攻击的,2-被攻击的
    public uint Value3;        //相对攻击类型的目标玩家ID
    public uint Value4;        //是否获胜 1-获胜;2-失败
    public uint Value5;        //目标头像
    public uint Value6;        //目标头像框
    public uint Value7;        //目标官职
    public uint Value8;        //目标等级
    public string Name;         //目标名称
    public int CurRank;
    public int TagRank;
}
Main/System/Settlement/BattleSettlementManager.cs
@@ -54,6 +54,9 @@
                WarlordPavilionManager.Instance.isAutoNext = isWin;
                PopupWindowsProcessor.Instance.Add(isWin ? "WarlordPavilionVictoryWin" : "WarlordPavilionFailWin", false, BattleConst.WarlordPavilionBattleField);
                break;
            case BattleConst.QYBattleField:
                PopupWindowsProcessor.Instance.Add(isWin ? "QYBattleVictoryWin" : "QYBattleFailWin", false, BattleConst.QYBattleField);
                break;
            default:
                PopupWindowsProcessor.Instance.Add(isWin ? "BattleVictoryWin" : "BattleFailWin", false, BattleConst.StoryBossBattleField);
                break;
@@ -103,6 +106,16 @@
            case BattleConst.PriviewBattleField:
                UIManager.Instance.CloseWindow<PreviewBattleWin>();
                break;
            case BattleConst.QYBattleField:
                if (isWin)
                {
                    UIManager.Instance.OpenWindow<QYBattleVictoryWin>();
                }
                else
                {
                    UIManager.Instance.OpenWindow<QYBattleFailWin>();
                }
                break;
            default:
                if (isWin)
                {
Main/System/Store/StoreModel.cs
@@ -583,6 +583,30 @@
        }
        return true;
    }
    // 弹出购买框,不足则提示已售罄
    public void ShowBuyItem(int shopID, int tipType = 0)
    {
        var cfg = StoreConfig.Get(shopID);
        if (!TryGetIsSellOut(cfg, out var cnt))
        {
            buyShopID = shopID;
            UIManager.Instance.OpenWindow<BuyItemWin>();
        }
        else
        {
            if (tipType == 0)
            {
                //售罄
                SysNotifyMgr.Instance.ShowTip("StoreTip1");
            }
            else if (tipType == 1)
            {
                //物品不足提示
                SysNotifyMgr.Instance.ShowTip("ItemNotEnough", ItemConfig.Get(cfg.ItemID).ItemName);
            }
        }
    }
}
public enum StoreFunc
Main/System/ViewNPC/ViewNPCManager.cs
@@ -67,7 +67,11 @@
            {
                case BattleConst.ArenaBattleField:
                    int playerId = (int)ArenaManager.Instance.atkPlayerId;
                    OtherPlayerDetailManager.Instance.ViewPlayerDetail(playerId, 0, (int)ViewPlayerType.viewArenaBattleEnemyHero, (int)BattlePreSetType.Arena);
                    OtherPlayerDetailManager.Instance.ViewPlayerDetail(playerId, 0, (int)ViewPlayerType.viewPVPBattleEnemyHero, (int)BattlePreSetType.Arena);
                    break;
                case BattleConst.QYBattleField:
                    playerId = (int)QunyingManager.Instance.atkPlayerId;
                    OtherPlayerDetailManager.Instance.ViewPlayerDetail(playerId, 0, (int)ViewPlayerType.viewPVPBattleEnemyHero, (int)BattlePreSetType.Qunying);
                    break;
            }
            return;
@@ -89,13 +93,13 @@
    {
        switch (viewPlayerType)
        {
            case (int)ViewPlayerType.viewArenaBattleEnemyHero:
                ViewArenaBattleEnemyHero(playerID);
            case (int)ViewPlayerType.viewPVPBattleEnemyHero:
                ViewPVPBattleEnemyHero(playerID);
                break;
        }
    }
    private void ViewArenaBattleEnemyHero(int playerID)
    private void ViewPVPBattleEnemyHero(int playerID)
    {
        int presetID = otherPlayerManager.GetFuncPresetID(playerID, OtherPlayerDetailManager.Instance.viewPreSetType, (int)FuncPresetType.Global);
        var heroList = otherPlayerManager.GetHeroDataSortList(playerID, presetID);
Main/Utility/EnumHelper.cs
@@ -1831,5 +1831,5 @@
{
    viewPlayerData = 0,  //查看玩家基本信息,公用打开界面
    viewGuildLeader = 1,  //查看玩家的公会族长信息
    viewArenaBattleEnemyHero = 2,  //查看竞技场战斗敌方英雄信息
    viewPVPBattleEnemyHero = 2,  //查看竞技场战斗敌方英雄信息
}