hch
2025-10-22 af6e207c6d185ed66125e85e18c02c63bea597f9
Main/System/HappyXB/HappyXBModel.cs
@@ -8,349 +8,101 @@
public class HappyXBModel : GameSystemManager<HappyXBModel>
{
    private Dictionary<string, XBGetItemConfig> xbGetItemDict = new Dictionary<string, XBGetItemConfig>();
    private Dictionary<int, List<XBGetItemConfig>> xbTypeItemDict = new Dictionary<int, List<XBGetItemConfig>>();
    private Dictionary<string, Dictionary<int, XBGetItem>> jobXBItemDict = new Dictionary<string, Dictionary<int, XBGetItem>>();
    private Dictionary<int, XBFuncSet> xbFuncSetDict = new Dictionary<int, XBFuncSet>();
    public Dictionary<int, int> XBCostTypeDict = new Dictionary<int, int>();
    public HappXBTitle title = HappXBTitle.Best;
    //寻宝产出库
    private Dictionary<int, Dictionary<int, XBGetItemConfig>> xbGetItemDict = new Dictionary<int, Dictionary<int, XBGetItemConfig>>(); //奖池的所有物品(按类型+等级)
    private Dictionary<int, List<XBGetItemConfig>> xbTypeItemDict = new Dictionary<int, List<XBGetItemConfig>>(); //奖池的所有物品(按类型)
    float xbLastTime = 0;   //等待服务端回复 如果太长就重置为不等待
    bool m_IsWaitServerXB = false;  // 等待服务端回复
    public bool isXBCoolTime
    {
        get
        {
            #if UNITY_EDITOR
            if (Time.time - xbLastTime > 1)
            #else
            if (Time.time - xbLastTime > 10)
            #endif
            {
                m_IsWaitServerXB = false;
                return m_IsWaitServerXB;
            }
    public string USETOOLXBKey = string.Empty;
    public static string HAPPYXBITEMKEY;
    public List<ArrayList> XBNotifyParms = new List<ArrayList>();
    public bool isXBCoolTime { get; set; }
            return m_IsWaitServerXB;
        }
    public bool isJumpBestXB { get; set; }
    public bool isJumpRuneXB { get; set; }
    public bool isJumpGubaoXB { get; set; }
    public bool isJumpGatherSoulXB { get; set; } //聚魂寻宝:是否跳过动画
        set
        {
            m_IsWaitServerXB = value;
            xbLastTime = Time.time;
        }
    }
    private Dictionary<int, XBTypeInfo> xbTypeInfoDict = new Dictionary<int, XBTypeInfo>(); //抽奖状态相关的 服务器记录
    public int lhQuality;
    public override void Init()
    {
        isJumpBestXB = false;
        isJumpRuneXB = false;
        isJumpGubaoXB = false;
        isJumpGatherSoulXB = false;
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize;
        FuncOpen.Instance.OnFuncStateChangeEvent += UpdateFuncState;
        PackManager.Instance.RefreshItemEvent += RefreshXBTool;
        TimeMgr.Instance.OnDayEvent += OnDayEvent;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnPlayerLoginOk;
        InvestModel.Instance.onInvestUpdate += OnInvestUpdate;
        xbGetItemDict.Clear();
        xbTypeItemDict.Clear();
        xbFuncSetDict.Clear();
        List<XBGetItemConfig> list = XBGetItemConfig.GetValues();
        for (int i = 0; i < list.Count; i++)
        {
            string key = StringUtility.Contact(list[i].TreasureType, list[i].MinLV);
            if (!xbGetItemDict.ContainsKey(key))
            if (!xbGetItemDict.ContainsKey(list[i].TreasureType))
            {
                xbGetItemDict.Add(key, list[i]);
                xbGetItemDict.Add(list[i].TreasureType, new Dictionary<int, XBGetItemConfig>());
            }
            xbGetItemDict[list[i].TreasureType].Add(list[i].MinLV, list[i]);
            if (!xbTypeItemDict.ContainsKey(list[i].TreasureType))
            {
                List<XBGetItemConfig> typeItemlist = new List<XBGetItemConfig>();
                typeItemlist.Add(list[i]);
                xbTypeItemDict.Add(list[i].TreasureType, typeItemlist);
                xbTypeItemDict.Add(list[i].TreasureType, new List<XBGetItemConfig>());
            }
            else
            {
                xbTypeItemDict[list[i].TreasureType].Add(list[i]);
            }
            xbTypeItemDict[list[i].TreasureType].Add(list[i]);
        }
        SetXBFuncDict(1);
        SetXBFuncDict(2);
        var treasureIDArr = JsonMapper.ToObject<int[]>(FuncConfigConfig.Get("TreasureLuckyDraw").Numerical1);
        for (int i = 0; i < treasureIDArr.Length; i++)
        {
            int type = XBGetItemConfig.Get(treasureIDArr[i]).TreasureType;
            SetXBFuncDict(type);
        }
        var config = FuncConfigConfig.Get("HeroCall");
        lhQuality = int.Parse(config.Numerical1);
    }
        SetXBFuncDict(105);
        SetXBFuncDict(106);
        SetXBFuncDict(107);
        SetXBFuncDict(108);
        SysNotifyMgr.Instance.RegisterCondition("HappyXB", SatisfyNotifyCondition);
        XBCostTypeDict.Clear();
        XBCostTypeDict[(int)HappXBTitle.Best] = TreasureSetConfig.Get(1).CostMoneyType;
        XBCostTypeDict[(int)HappXBTitle.Rune] = TreasureSetConfig.Get(2).CostMoneyType;
        for (int i = 0; i < treasureIDArr.Length; i++)
        {
            int type = XBGetItemConfig.Get(treasureIDArr[i]).TreasureType;
            XBCostTypeDict[(int)HappXBTitle.Gubao1 + i] = TreasureSetConfig.Get(type).CostMoneyType;
        }
        XBCostTypeDict[(int)HappXBTitle.YunShi1] = TreasureSetConfig.Get(105).CostMoneyType;
        XBCostTypeDict[(int)HappXBTitle.YunShi2] = TreasureSetConfig.Get(106).CostMoneyType;
        XBCostTypeDict[(int)HappXBTitle.YunShi3] = TreasureSetConfig.Get(107).CostMoneyType;
        XBCostTypeDict[(int)HappXBTitle.YunShi4] = TreasureSetConfig.Get(108).CostMoneyType;
    public override void Release()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitialize;
        FuncOpen.Instance.OnFuncStateChangeEvent -= UpdateFuncState;
        PackManager.Instance.RefreshItemEvent -= RefreshXBTool;
        TimeMgr.Instance.OnDayEvent -= OnDayEvent;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk;
        InvestModel.Instance.onInvestUpdate -= OnInvestUpdate;
    }
    public void OnBeforePlayerDataInitialize()
    void OnBeforePlayerDataInitialize()
    {
        PlayerDatas.Instance.playerDataRefreshEvent -= RefreshStoreScore;
        FuncOpen.Instance.OnFuncStateChangeEvent -= UpdateFuncState;
        PackManager.Instance.refreshItemCountEvent -= RefreshXBTool;
        isXBCoolTime = false;
        XBNotifyParms.Clear();
        xbTypeInfoDict.Clear();
    }
    public void OnAfterPlayerDataInitialize()
    void OnPlayerLoginOk()
    {
        SetXBGetItemModel();
    }
    public void OnPlayerLoginOk()
    {
        int playerId = (int)PlayerDatas.Instance.baseData.PlayerID;
        HAPPYXBITEMKEY = StringUtility.Contact(playerId, "HappyXBItemTime");
        USETOOLXBKey = StringUtility.Contact(playerId, "UseToolXB");
        XBWarehouseRedPoint();
        PlayerDatas.Instance.playerDataRefreshEvent += RefreshStoreScore;
        PackManager.Instance.refreshItemCountEvent += RefreshXBTool;
        FuncOpen.Instance.OnFuncStateChangeEvent += UpdateFuncState;
        HeroCallRedPoint();
    }
    /// <summary>
    /// 检测自身玩家是否需要信息提示
    /// </summary>
    /// <param name="key"></param>
    /// <param name="paramArray"></param>
    /// <returns></returns>
    private bool SatisfyNotifyCondition(string key, ArrayList paramArray)
    void OnInvestUpdate(int type)
    {
        switch (title)
        {
            case HappXBTitle.Best:
                if (isJumpBestXB)
                {
                    return true;
                }
                break;
            case HappXBTitle.Rune:
                if (isJumpRuneXB)
                {
                    return true;
                }
                break;
            case HappXBTitle.Gubao1:
            case HappXBTitle.Gubao2:
            case HappXBTitle.Gubao3:
            case HappXBTitle.Gubao4:
                if (isJumpGubaoXB)
                {
                    return true;
                }
                break;
            case HappXBTitle.GatherSoul:
                if (isJumpGatherSoulXB)
                {
                    return true;
                }
                break;
            case HappXBTitle.YunShi1:
            case HappXBTitle.YunShi2:
            case HappXBTitle.YunShi3:
            case HappXBTitle.YunShi4:
                // if (ModelCenter.Instance.GetModelEx<YunShiXBActModel>().isSkipXB)
                // {
                //     return true;
                // }
                break;
        }
        XBNotifyParms.Add(new ArrayList(paramArray));
        if (paramArray != null && paramArray.Count > 0 &&
            paramArray[0].Equals(UIHelper.ServerStringTrim(PlayerDatas.Instance.baseData.PlayerName)))
        {
            return false;
        }
        return true;
        if (type == 7)
            HeroCallRedPoint();
    }
    public void GetNotifyResult(int itemId, int itemCount)
    {
        int notifyIndex = 0;
        if (CheckNotifyItemByIdAndCnt(itemId, itemCount, out notifyIndex))
        {
            SysNotifyMgr.Instance.ShowTip("HappyXB", XBNotifyParms[notifyIndex].ToArray());
        }
    }
    private bool CheckNotifyItemByIdAndCnt(int itemId, int itemCnt, out int notifyIndex)
    {
        notifyIndex = 0;
        for (int i = 0; i < XBNotifyParms.Count; i++)
        {
            if (XBNotifyParms[i] != null && XBNotifyParms[i].Count > 3)
            {
                int notifyItemId = 0;
                int.TryParse(XBNotifyParms[i][1].ToString(), out notifyItemId);
                int notifyItemCnt = 0;
                int.TryParse(XBNotifyParms[i][3].ToString(), out notifyItemCnt);
                if (notifyItemId == itemId && notifyItemCnt == itemCnt)
                {
                    notifyIndex = i;
                    return true;
                }
            }
        }
        return false;
    }
    private void SetXBFuncDict(int type)
    {
        var treasureSetCfg = TreasureSetConfig.Get(type);
        if (!xbFuncSetDict.ContainsKey(type))
        {
            XBFuncSet funcSet = new XBFuncSet();
            funcSet.xbType = type;
            funcSet.xbNums = treasureSetCfg.TreasureCountList;
            funcSet.xbPrices = treasureSetCfg.CostMoneyList;
            funcSet.costToolIds = new int[] { treasureSetCfg.CostItemID, treasureSetCfg.CostItemID };
            funcSet.costToolNums = treasureSetCfg.CostItemCountList;
            funcSet.dailyFreeCount = treasureSetCfg.DailyFreeCount;
            funcSet.xbScores = new int[] { treasureSetCfg.AwardMoneyValue, treasureSetCfg.AwardMoneyValue * treasureSetCfg.TreasureCountList[1] };
            xbFuncSetDict.Add(funcSet.xbType, funcSet);
        }
    }
    public XBFuncSet GetXBFuncSet(int type)
    {
        XBFuncSet funcSet = null;
        xbFuncSetDict.TryGetValue(type, out funcSet);
        return funcSet;
    }
    //默认优先使用道具寻宝
    public bool IsUseToolXB()
    {
        return true;
        //if (!PlayerPrefs.HasKey(USETOOLXBKey))
        //{
        //    LocalSave.SetBool(USETOOLXBKey, true);
        //    return true;
        //}
        //else
        //{
        //    return LocalSave.GetBool(USETOOLXBKey);
        //}
    }
    public void SetUseToolXB(bool isToolXB)
    {
        //LocalSave.SetBool(USETOOLXBKey, isToolXB);
    }
    private void SetXBGetItemModel()
    {
        jobXBItemDict.Clear();
        Dictionary<int, XBGetItem> getItemDict = new Dictionary<int, XBGetItem>();
        Dictionary<int, List<int>> jobItemDict = new Dictionary<int, List<int>>();
        int playerJob = PlayerDatas.Instance.baseData.Job;
        foreach (var key in xbGetItemDict.Keys)
        {
            getItemDict.Clear();
            jobItemDict.Clear();
            Dictionary<int, XBGetItem> jobGetItemDict = new Dictionary<int, XBGetItem>();
            XBGetItemConfig getItemConfig = xbGetItemDict[key];
            jobXBItemDict.Add(key, jobGetItemDict);
            JsonData getItemJson = JsonMapper.ToObject(getItemConfig.GridItemInfo);
            foreach (var grid in getItemJson.Keys)
            {
                int id = int.Parse(getItemJson[grid][0].ToString());
                int count = int.Parse(getItemJson[grid][1].ToString());
                XBGetItem getItem = new XBGetItem();
                getItem.SetModel(int.Parse(grid), id, count);
                getItemDict.Add(getItem.gridIndex, getItem);
            }
            JsonData jobReplaceJson = JsonMapper.ToObject(getItemConfig.JobItemList);
            if (jobReplaceJson.IsArray)
            {
                for (int i = 0; i < jobReplaceJson.Count; i++)
                {
                    List<int> itemIdlist = new List<int>();
                    jobItemDict.Add(i, itemIdlist);
                    if (jobReplaceJson[i].IsArray)
                    {
                        for (int j = 0; j < jobReplaceJson[i].Count; j++)
                        {
                            int id = int.Parse(jobReplaceJson[i][j].ToString());
                            itemIdlist.Add(id);
                        }
                    }
                }
            }
            foreach (var model in getItemDict.Values)
            {
                ItemConfig itemConfig = ItemConfig.Get(model.itemId);
                if (itemConfig.JobLimit == 0)
                {
                    jobGetItemDict.Add(model.gridIndex, model);
                }
                else
                {
                    bool isReplace = false;
                    foreach (var list in jobItemDict.Values)
                    {
                        if (list.Contains(model.itemId))
                        {
                            for (int i = 0; i < list.Count; i++)
                            {
                                int equipJob = int.Parse(list[i].ToString().Substring(0, 1));
                                if (playerJob == equipJob)
                                {
                                    isReplace = true;
                                    XBGetItem getItem = new XBGetItem();
                                    getItem.SetModel(model.gridIndex, list[i], model.count);
                                    jobGetItemDict.Add(getItem.gridIndex, getItem);
                                    break;
                                }
                            }
                            break;
                        }
                    }
                    if (!isReplace)
                    {
                        jobGetItemDict.Add(model.gridIndex, model);
                    }
                }
            }
        }
    }
    public Dictionary<int, XBGetItem> GetXBGetItemByID(int type)
    {
        int lv = 0;
        List<XBGetItemConfig> configlist = null;
        xbTypeItemDict.TryGetValue(type, out configlist);
        if (configlist != null)
        {
            for (int i = configlist.Count - 1; i > -1; i--)
            {
                if (PlayerDatas.Instance.baseData.LV >= configlist[i].MinLV)
                {
                    lv = configlist[i].MinLV;
                    break;
                }
            }
        }
        string key = StringUtility.Contact(type, lv);
        Dictionary<int, XBGetItem> dict = null;
        jobXBItemDict.TryGetValue(key, out dict);
        return dict;
    }
    public XBGetItemConfig GetXBItemConfigByType(int type)
    {
        int lv = 0;
@@ -363,14 +115,11 @@
                if (PlayerDatas.Instance.baseData.LV >= configlist[i].MinLV)
                {
                    lv = configlist[i].MinLV;
                    break;
                    return configlist[i];
                }
            }
        }
        XBGetItemConfig xbItemConfig = null;
        string key = StringUtility.Contact(type, lv);
        xbGetItemDict.TryGetValue(key, out xbItemConfig);
        return xbItemConfig;
        return null;
    }
    #region 处理服务端数据
@@ -379,10 +128,9 @@
    public int addXBScore { get; private set; }
    public int addXBScoreType { get; private set; } //寻宝积分货币类型
    public int addXBLuckValue { get; private set; }
    private Dictionary<int, XBGetItem> xbResultDict = new Dictionary<int, XBGetItem>();
    public Dictionary<int, XBGetItem> xbResultDict { get; private set; } = new Dictionary<int, XBGetItem>(); //奖品顺序:奖品
    public void GetServerXBResult(HA350_tagMCTreasureResult result)
    {
        XBNotifyParms.Clear();
        xbResultDict.Clear();
        addXBScore = result.AddMoneyValue;
        addXBScoreType = result.AddMoneyType;
@@ -410,105 +158,41 @@
                }
            }
        }
        SetXBResultRecord();
        isXBCoolTime = false;
        if (RefreshXBResultAct != null)
        {
            RefreshXBResultAct();
        }
        if (!UIManager.Instance.IsOpened<HeroCallResultWin>())
        {
            UIManager.Instance.OpenWindow<HeroCallResultWin>();
        }
    }
    List<string> itemGetTimeArray = new List<string>();
    List<string> getNewItemLoglist = new List<string>();
    List<XBGetItem> xbItemRecordlist = new List<XBGetItem>();
    public void SetXBResultRecord()
    {
        if (PlayerPrefs.HasKey(HAPPYXBITEMKEY))
    public int GetCountInResult(int itemID)
    {
        int count = 0;
        if (xbResultDict != null && xbResultDict.Count > 0)
        {
            itemGetTimeArray = LocalSave.GeStringArray(HappyXBModel.HAPPYXBITEMKEY).ToList();
        }
        else
        {
            itemGetTimeArray.Clear();
        }
        xbItemRecordlist.Clear();
        getNewItemLoglist.Clear();
        xbItemRecordlist.AddRange(GetXBResultlist());
        if (xbItemRecordlist != null)
        {
            int remianLogNum = (itemGetTimeArray.Count + xbItemRecordlist.Count) - 30;
            if (remianLogNum > 0)
            foreach (var item in xbResultDict)
            {
                int startIndex = itemGetTimeArray.Count - remianLogNum;
                itemGetTimeArray.RemoveRange(startIndex, remianLogNum);
                if (item.Value.itemId == itemID)
                {
                    count++;
                }
            }
            xbItemRecordlist.Sort(CompareByTime);
            for (int i = 0; i < xbItemRecordlist.Count; i++)
            {
                string log = Language.Get("HappyXBGetItemTime", xbItemRecordlist[i].createTimeStr, UIHelper.ServerStringTrim(PlayerDatas.Instance.baseData.PlayerName),
                    xbItemRecordlist[i].itemId, xbItemRecordlist[i].count);
                getNewItemLoglist.Add(log);
            }
            if (getNewItemLoglist.Count > 0)
            {
                itemGetTimeArray.InsertRange(0, getNewItemLoglist);
                LocalSave.SetStringArray(HappyXBModel.HAPPYXBITEMKEY, itemGetTimeArray.ToArray());
            }
        }
        return count;
    }
    public int CompareByTime(XBGetItem start, XBGetItem end)
    {
        DateTime startTime = start.createTime;
        DateTime endTime = end.createTime;
        if (startTime.CompareTo(endTime) != 0) return -startTime.CompareTo(endTime);
        return 0;
    }
    public List<XBGetItem> rangelist = new List<XBGetItem>();
    List<int> index = new List<int>();
    public List<XBGetItem> GetXBResultlist()
    {
        rangelist.Clear();
        index.Clear();
        List<XBGetItem> xbItemlist = xbResultDict.Values.ToList();
        for (int i = 0; i < xbItemlist.Count; i++)
        {
            index.Add(i);
        }
        SetRandomList(xbItemlist);
        return rangelist;
    }
    public void SetRandomList(List<XBGetItem> xbItemlist)
    {
        int currentRandom = UnityEngine.Random.Range(0, index.Count);
        XBGetItem current = xbItemlist[index[currentRandom]];
        if (!rangelist.Contains(current))
        {
            rangelist.Add(current);
            index.Remove(index[currentRandom]);
        }
        if (index.Count > 0)
        {
            SetRandomList(xbItemlist);
        }
    }
    public Dictionary<int, XBGetItem> GetXbResultDict()
    {
        return xbResultDict;
    }
    public void ClearXBRusltData()
    {
        xbResultDict.Clear();
    }
    private Dictionary<int, XBTypeInfo> xbTypeInfoDict = new Dictionary<int, XBTypeInfo>();
    public void GetServerXBInfo(HA351_tagMCTreasureInfo info)
    {
        for (int i = 0; i < info.InfoCount; i++)
@@ -556,7 +240,7 @@
            RefreshXBTypeInfoAct();
        }
        BestAndRuneXBRedPoint();
        HeroCallRedPoint();
    }
    public XBTypeInfo GetXBInfoByType(int type)
@@ -567,14 +251,16 @@
    }
    /// <summary>
    /// type 1 极品寻宝 2 符印寻宝  index 0 单次寻宝 1 多次寻宝
    ///costType 0-默认仙玉;1-免费次数;2-寻宝道具
    /// 请求寻宝
    /// </summary>
    /// <param name="type"></param>
    /// <param name="index"></param>
    /// <param name="type">寻宝类型</param>
    /// <param name="index">0 单次寻宝 1 多次寻宝</param>
    /// <param name="costType">0-货币;1-免费次数;2-寻宝道具</param>
    public event Action<int> StartXBEvent;
    public void SendXBQuest(int type, int index, int costType)
    {
        if (isXBCoolTime) return;
        isXBCoolTime = true;
        CA568_tagCMRequestTreasure treasure = new CA568_tagCMRequestTreasure();
        treasure.TreasureType = (byte)type;
@@ -593,14 +279,14 @@
    {
        switch (type)
        {
            case PackType.Treasure:
                SinglePack singlePack = PackManager.Instance.GetSinglePack(type);
                if (GeneralDefine.maxXBGridCount - singlePack.GetAllItems().Count < needGrid)
                {
                    SysNotifyMgr.Instance.ShowTip("XBWarehouseFull");
                    return false;
                }
                break;
            // case PackType.Treasure:
            //     SinglePack singlePack = PackManager.Instance.GetSinglePack(type);
            //     if (GeneralDefine.maxXBGridCount - singlePack.GetAllItems().Count < needGrid)
            //     {
            //         SysNotifyMgr.Instance.ShowTip("XBWarehouseFull");
            //         return false;
            //     }
            //     break;
            case PackType.Item:
                if (PackManager.Instance.GetEmptyGridCount(type) < needGrid)
                {
@@ -608,11 +294,19 @@
                    return false;
                }
                break;
            case PackType.Hero:
                if (PackManager.Instance.GetEmptyGridCount(type) < needGrid)
                {
                    SysNotifyMgr.Instance.ShowTip("HeroBagFull");
                    return false;
                }
                break;
        }
        return true;
    }
    public void SendOneXBQuest(PackType type, int xbType)
    public void SendOneXBQuest(int xbType)
    {
        var config = TreasureSetConfig.Get(xbType);
        if (GetXBInfoByType(xbType).treasureCountToday + config.TreasureCountList[0] > config.DailyMaxCount)
@@ -621,38 +315,54 @@
            return;
        }
        var funcSet = GetXBFuncSet(xbType);
        if (CheckIsEmptyGrid(type))
        var funcSet = TreasureSetConfig.Get(xbType);
        if (CheckIsEmptyGrid((PackType)config.PackType))
        {
            if (IsHaveOneXBTool(xbType))
            //道具寻宝
            if (funcSet.CostItemID != 0 && IsHaveOneXBTool(xbType))
            {
                SendXBQuest(xbType, 0, 2);
                return;
            }
            int moneyType = XBCostTypeDict[xbType];
            int xbOneMoney = funcSet.xbPrices[0];
            if (UIHelper.GetMoneyCnt(moneyType) >= (ulong)xbOneMoney)
            //货币寻宝
            int moneyType = funcSet.CostMoneyType;
            int xbOneMoney = funcSet.CostMoneyList[0];
            //暂定充值货币需要二次确认
            if (moneyType == 1)
            {
                StoreModel.Instance.UseMoneyCheck(xbOneMoney, () =>
                StoreModel.Instance.UseMoneyCheck(xbOneMoney, moneyType, () =>
                {
                    SendXBQuest(xbType, 0, 0);
                }, xbType == 1 ? 5 : 6, fullTip: Language.Get("TreasurePavilion08", xbOneMoney, moneyType, funcSet.costToolIds[0], 1));
                    if (UIHelper.GetMoneyCnt(moneyType) >= xbOneMoney)
                    {
                        SendXBQuest(xbType, 0, 0);
                    }
                    else
                    {
                        ItemTipUtility.ShowMoneyTip(moneyType);
                    }
                }, (int)BuyStoreItemCheckType.HeroCall, fullTip: Language.Get("CostMoneyForItem", funcSet.CostItemID, xbOneMoney,
                UIHelper.GetIconNameWithMoneyType(moneyType), funcSet.CostItemCountList[0]));
            }
            else
            {
                SysNotifyMgr.Instance.ShowTip("LackMoney", moneyType);
                if (UIHelper.GetMoneyCnt(moneyType) >= xbOneMoney)
                {
                    SendXBQuest(xbType, 0, 0);
                }
                else
                {
                    ItemTipUtility.ShowMoneyTip(moneyType);
                }
            }
        }
    }
    public void SendXBManyQuest(PackType type, int xbType)
    public void SendXBManyQuest(int xbType)
    {
        var config = TreasureSetConfig.Get(xbType);
        if (GetXBInfoByType(xbType).treasureCountToday + config.TreasureCountList[1] > config.DailyMaxCount)
        {
@@ -660,83 +370,120 @@
            return;
        }
        var funcSet = GetXBFuncSet(xbType);
        if (CheckIsEmptyGrid(type))
        var funcSet = TreasureSetConfig.Get(xbType);
        if (CheckIsEmptyGrid((PackType)config.PackType, 10))
        {
            int toolCnt = 0;
            int needToolCnt = 0;
            int needMoney = 0;
            if (IsHaveManyXBToolEx(xbType, out toolCnt, out needToolCnt, out needMoney))
            {
                if (toolCnt >= needToolCnt)
                {
                    CheckXBManyLimit(0, xbType, 2);
                    return;
                }
                SendXBQuest(xbType, 1, 2);
            }
            int moneyType = XBCostTypeDict[xbType];
            int xbManyMoney = needMoney == 0 ? funcSet.xbPrices[1] : needMoney;
            //货币寻宝
            int moneyType = funcSet.CostMoneyType;
            if (UIHelper.GetMoneyCnt(moneyType) >= (ulong)xbManyMoney)
            //暂定充值货币需要二次确认
            if (moneyType == 1)
            {
                StoreModel.Instance.UseMoneyCheck(xbManyMoney, () =>
                StoreModel.Instance.UseMoneyCheck(needMoney, moneyType, () =>
                {
                    SendXBQuest(xbType, 1, toolCnt > 0 ? 2 : 0);
                }, xbType == 1 ? 5 : 6, fullTip: Language.Get("TreasurePavilion08", xbManyMoney, moneyType, funcSet.costToolIds[1], needToolCnt - toolCnt));
                    //只要有道具就是道具寻宝,不足部分服务端扣货币
                    if (UIHelper.GetMoneyCnt(moneyType) >= needMoney)
                    {
                        SendXBQuest(xbType, 1, toolCnt > 0 ? 2 : 0);
                    }
                    else
                    {
                        ItemTipUtility.ShowMoneyTip(moneyType);
                    }
                }, (int)BuyStoreItemCheckType.HeroCall, fullTip: Language.Get("CostMoneyForItem", funcSet.CostItemID, needMoney,
                UIHelper.GetIconNameWithMoneyType(moneyType), needToolCnt - toolCnt));
            }
            else
            {
                SysNotifyMgr.Instance.ShowTip("LackMoney", moneyType);
                if (UIHelper.GetMoneyCnt(moneyType) >= needMoney)
                {
                    SendXBQuest(xbType, 1, toolCnt > 0 ? 2 : 0);
                }
                else
                {
                    ItemTipUtility.ShowMoneyTip(moneyType);
                }
            }
        }
    }
    public void CheckXBManyLimit(int needMoney, int xbtype, int costType)
    {
        int moneyType = XBCostTypeDict[xbtype];
        if (UIHelper.GetMoneyCnt(moneyType) >= (ulong)needMoney)
        {
            SendXBQuest(xbtype, 1, costType);
        }
        else
        {
            //WindowCenter.Instance.Open<RechargeTipWin>();
            SysNotifyMgr.Instance.ShowTip("LackMoney", moneyType);
        }
    }
    #endregion
    public bool IsHaveFreeXB(int type)
    {
        int freeCountToday = 0;
        XBTypeInfo typeInfo = GetXBInfoByType(type);
        if (typeInfo == null)
        if (typeInfo != null)
        {
            typeInfo = new XBTypeInfo()
            {
                xbType = type,
                luckValue = 0,
                freeCountToday = 0,
                treasureCount = 0,
            };
            freeCountToday = typeInfo.freeCountToday;
        }
        //判断是否有免费次数,且免费次数是否用完
        var funcSet = GetXBFuncSet(type);
        return typeInfo.freeCountToday < funcSet.dailyFreeCount;
        var funcSet = TreasureSetConfig.Get(type);
        return freeCountToday < funcSet.DailyFreeCount;
    }
    public int GetFreeCountToday(int type)
    {
        XBTypeInfo typeInfo = GetXBInfoByType(type);
        if (typeInfo != null)
        {
            return typeInfo.freeCountToday;
        }
        return 0;
    }
    public int GetDailyFreeCount(int type)
    {
        return TreasureSetConfig.Get(type).DailyFreeCount;
    }
    //获取还需多少次可得幸运奖励
    public int GetNextXBCountForBigAward(int type, out List<int> qualityList)
    {
        qualityList = new List<int>();
        XBTypeInfo typeInfo = GetXBInfoByType(type);
        if (typeInfo == null)
        {
            return 0;
        }
        var xbConfig = GetXBItemConfigByType(type);
        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
        luckList.Sort();
        //按阶梯显示
        for (int i = 0; i < luckList.Count; i++)
        {
            if (typeInfo.luckValue < luckList[i])
            {
                //把二维数组里的所有第二个元素组成新列表
                qualityList = xbConfig.LuckyItemRateInfo[luckList[i]].Select(x => x[1]).ToList();
                qualityList.Sort();
                return luckList[i] - typeInfo.luckValue;
            }
        }
        return 0;
    }
    public bool CheckIsXBTool(int itemId, int type)
    {
        XBFuncSet funcSet = GetXBFuncSet(type);
        var funcSet = TreasureSetConfig.Get(type);
        if (funcSet == null) return false;
        if (funcSet.costToolIds.Contains(itemId))
        if (funcSet.CostItemID == itemId)
        {
            return true;
        }
@@ -744,11 +491,11 @@
    }
    public bool IsHaveOneXBTool(int type)
    {
        XBFuncSet funcSet = GetXBFuncSet(type);
        var funcSet = TreasureSetConfig.Get(type);
        if (funcSet == null) return false;
        int toolCnt = PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.costToolIds[0]);
        if (toolCnt >= funcSet.costToolNums[0])
        int toolCnt = (int)PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.CostItemID);
        if (toolCnt >= funcSet.CostItemCountList[0])
        {
            return true;
        }
@@ -756,22 +503,6 @@
        return false;
    }
    //needToolCnt 为配表中需要的道具数量
    public bool IsHaveManyXBTool(int type, out int toolCnt, out int needToolCnt)
    {
        toolCnt = 0;
        needToolCnt = 0;
        XBFuncSet funcSet = GetXBFuncSet(type);
        if (funcSet == null) return false;
        toolCnt = PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.costToolIds[1]);
        needToolCnt = funcSet.costToolNums[1];
        if (toolCnt > 0)
        {
            return true;
        }
        return false;
    }
    //needToolCnt 为配表中需要的道具数量
    // 可获得真正需要补足购买道具的金额
@@ -780,240 +511,133 @@
        toolCnt = 0;
        needToolCnt = 0;    //配置中需要的道具数量
        needMoney = 0;  //真正需要补足购买道具的金额
        XBFuncSet funcSet = GetXBFuncSet(type);
        var funcSet = TreasureSetConfig.Get(type);
        if (funcSet == null) return false;
        toolCnt = PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.costToolIds[1]);
        needToolCnt = funcSet.costToolNums[1];
        toolCnt = (int)PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.CostItemID);
        needToolCnt = funcSet.CostItemCountList[1];
        if (toolCnt > 0)
        if (toolCnt >= needToolCnt)
        {
            if (toolCnt < needToolCnt)
            {
                needMoney = funcSet.xbPrices[1] / needToolCnt * (needToolCnt - toolCnt);
            }
            //道具足够
            return true;
        }
        if (funcSet.CostMoneyType != 0)
        {
            if (toolCnt != 0 && toolCnt < needToolCnt)
            {
                //部分不足的按单次价格算
                needMoney = funcSet.CostMoneyList[0] * (needToolCnt - toolCnt);
            }
            else
            {
                //全部不足的按多次价格算 可能配置了折扣
                needMoney = funcSet.CostMoneyList[1];
            }
        }
        return false;
    }
    public event Action<float> RefreshBestXBTimeAct;
    public event Action<float> RefreshRuneXBTimeAct;
    public void RefreshBestXBTime(float time)
    public int GetCostType(int type)
    {
        if (RefreshBestXBTimeAct != null)
        {
            RefreshBestXBTimeAct(time);
        }
        if (time <= 0)
        {
            BestAndRuneXBRedPoint();
        }
    }
    public void RefreshRuneXBTime(float time)
    {
        if (RefreshRuneXBTimeAct != null)
        {
            RefreshRuneXBTimeAct(time);
        }
        if (time <= 0)
        {
            BestAndRuneXBRedPoint();
        }
        var funcSet = TreasureSetConfig.Get(type);
        if (funcSet == null) return 0;
        return funcSet.CostMoneyType;
    }
    public event Action<HappXBTitle, int> RefreshAgainXBAct;
    /// <summary>
    /// xbtype 0-单次 1 多次
    /// </summary>
    /// <param name="xBTitle"></param>
    /// <param name="xbType"></param>
    public void SetAgainXBEvent(HappXBTitle xBTitle, int xbType)
    {
        if (RefreshAgainXBAct != null)
        {
            RefreshAgainXBAct(xBTitle, xbType);
        }
    public int GetCostItemID(int type)
    {
        var funcSet = TreasureSetConfig.Get(type);
        if (funcSet == null) return 0;
        return funcSet.CostItemID;
    }
    #region 红点逻辑
    public const int HappyXB_RedKey = 203;
    public const int BestXB_RedKey = 20301;
    public const int RuneXB_RedKey = 20302;
    public const int XBStore_RedKey = 20303;
    public const int XBWarehouse_RedKey = 20304;
    public const int BestXB_OneRedKey = 20301001;
    public const int BestXB_ManyRedKey = 20301002;
    public const int BestXB_FreeRedKey = 20301003;
    public const int RuneXB_OneRedKey = 20302001;
    public const int RuneXB_ManyRedKey = 20302002;
    public const int RuneXB_FreeRedKey = 20302003;
    public const int XBHeroCall1_RedKey = 20300;    //武将免费召唤
    public const int XBHeroCall10_RedKey = 20301;    //武将10召唤
    public const int XBHeroCallScore_RedKey = 20302;    //武将积分召唤
    public Redpoint happyXBRed = new Redpoint(HappyXB_RedKey);
    public Redpoint bestXBRed = new Redpoint(HappyXB_RedKey, BestXB_RedKey);
    public Redpoint runeXBRed = new Redpoint(HappyXB_RedKey, RuneXB_RedKey);
    public Redpoint xbStoreRed = new Redpoint(HappyXB_RedKey, XBStore_RedKey);
    public Redpoint xbWarehouseRed = new Redpoint(HappyXB_RedKey, XBWarehouse_RedKey);
    public Redpoint bestXBOneRed = new Redpoint(BestXB_RedKey, BestXB_OneRedKey);
    public Redpoint bestXBManyRed = new Redpoint(BestXB_RedKey, BestXB_ManyRedKey);
    public Redpoint bestXBFreeRed = new Redpoint(BestXB_RedKey, BestXB_FreeRedKey);
    public Redpoint runeXBOneRed = new Redpoint(RuneXB_RedKey, RuneXB_OneRedKey);
    public Redpoint runeXBManyRed = new Redpoint(RuneXB_RedKey, RuneXB_ManyRedKey);
    public Redpoint runeXBFreeRed = new Redpoint(RuneXB_RedKey, RuneXB_FreeRedKey);
    public Redpoint happyXBRed = new Redpoint(MainRedDot.MainHerosRedpoint, HappyXB_RedKey);
    public Redpoint bestXBFreeRed = new Redpoint(HappyXB_RedKey, XBHeroCall1_RedKey);
    public Redpoint bestXB10Red = new Redpoint(HappyXB_RedKey, XBHeroCall10_RedKey);
    public Redpoint bestXBScoreRed = new Redpoint(HappyXB_RedKey, XBHeroCallScore_RedKey);
    private void UpdateFuncState(int funcId)
    {
        if (funcId == (int)FuncOpenEnum.HappyFindTreasure
            || funcId == 184)
        {
            XBWarehouseRedPoint();
            BestAndRuneXBRedPoint();
            XBStoreRedPoint();
        }
        HeroCallRedPoint();
    }
    public void RefreshXBWarehouse()
    {
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.HappyFindTreasure)) return;
        xbWarehouseRed.state = RedPointState.Simple;
    }
    public void XBWarehouseRedPoint()
    {
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.HappyFindTreasure)) return;
        SinglePack singlePack = PackManager.Instance.GetSinglePack(PackType.Treasure);
        if (singlePack == null) return;
        if (singlePack.GetAllItems().Count > 0)
        {
            xbWarehouseRed.state = RedPointState.Simple;
        }
        else
        {
            xbWarehouseRed.state = RedPointState.None;
        }
    }
    private void RefreshXBTool(PackType type, int index, int id)
    {
        if (type != PackType.Item) return;
        if (!CheckIsXBTool(id, 1) && !CheckIsXBTool(id, 2)) return;
        BestAndRuneXBRedPoint();
        if (!CheckIsXBTool(id, (int)HappXBTitle.HeroCallAdvanced))
            return;
        HeroCallRedPoint();
    }
    public void BestAndRuneXBRedPoint()
    {
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.HappyFindTreasure)) return;
    void OnDayEvent()
    {
        HeroCallRedPoint();
    }
        int xbtoolCnt = 0;
        int needtoolCnt = 0;
        if (IsHaveFreeXB(1))
    //英雄招募
    public void HeroCallRedPoint()
    {
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.HappyFindTreasure))
            return;
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Hero))
            return;
        // 免费 10连 积分
        bestXB10Red.state = RedPointState.None;
        bestXBFreeRed.state = RedPointState.None;
        bestXBScoreRed.state = RedPointState.None;
        if (IsHaveFreeXB((int)HappXBTitle.HeroCallAdvanced))
        {
            bestXBFreeRed.state = RedPointState.Simple;
        }
        else
        if (IsHaveManyXBToolEx((int)HappXBTitle.HeroCallAdvanced, out int xbtoolCnt, out int needtoolCnt, out int needMoney))
        {
            bestXBFreeRed.state = RedPointState.None;
            bestXB10Red.state = RedPointState.Simple;
            return;
        }
        if (IsHaveManyXBTool(1, out xbtoolCnt, out needtoolCnt))
        {
            if (xbtoolCnt >= needtoolCnt)
            {
                bestXBManyRed.state = RedPointState.Simple;
            }
            else
            {
                bestXBManyRed.state = RedPointState.None;
            }
            bestXBOneRed.state = RedPointState.Simple;
        }
        else
        {
            bestXBOneRed.state = RedPointState.None;
            bestXBManyRed.state = RedPointState.None;
        //积分足够
        if ((InvestModel.Instance.IsInvested(InvestModel.monthCardType)
        || GetXBInfoByType((int)HappXBTitle.HeroCallScore)?.treasureCount == 0)
        && UIHelper.GetMoneyCnt(51) >= TreasureSetConfig.Get((int)HappXBTitle.HeroCallScore).CostMoneyList[0])
        {
            bestXBScoreRed.state = RedPointState.Simple;
        }
        if (FuncOpen.Instance.IsFuncOpen(184) && IsHaveFreeXB(2))
        {
            runeXBFreeRed.state = RedPointState.Simple;
        }
        else
        {
            runeXBFreeRed.state = RedPointState.None;
        }
        if (FuncOpen.Instance.IsFuncOpen(184) &&
            IsHaveManyXBTool(2, out xbtoolCnt, out needtoolCnt))
        {
            if (xbtoolCnt >= needtoolCnt)
            {
                runeXBManyRed.state = RedPointState.Simple;
            }
            else
            {
                runeXBManyRed.state = RedPointState.None;
            }
            runeXBOneRed.state = RedPointState.Simple;
        }
        else
        {
            runeXBOneRed.state = RedPointState.None;
            runeXBManyRed.state = RedPointState.None;
        }
    }
    private void RefreshStoreScore(PlayerDataType type)
    //按格子库配置的奖池 获得获取物品
    public List<int> GetAllGridLibItemIDByType(int type)
    {
        if (type != PlayerDataType.CDBPlayerRefresh_TreasureScore) return;
        XBStoreRedPoint();
    }
    private List<StoreModel.StoreData> storelist = null;
    public void XBStoreRedPoint()
    {
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.HappyFindTreasure)) return;
        ulong moneyNum = UIHelper.GetMoneyCnt(25);
        for (int i = 11; i < 14; i++)
        List<int> itemIDListTemp = new List<int>();
        foreach (var kv in GetXBItemConfigByType(type).GridLibInfo)
        {
            storelist = StoreModel.Instance.TryGetStoreDatas((StoreFunc)i);
            if (storelist.Count > 0)
            {
                List<StoreModel.StoreData> orderlist = new List<StoreModel.StoreData>();
                orderlist.AddRange(storelist);
                orderlist.Sort(CompareByMoney);
                if (moneyNum >= (ulong)orderlist[0].storeConfig.MoneyNumber)
                {
                    xbStoreRed.state = RedPointState.Simple;
                    return;
                }
            }
            itemIDListTemp.AddRange(TreasureItemLibConfig.GetItemIDList(kv.Value));
        }
        xbStoreRed.state = RedPointState.None;
    }
        return itemIDListTemp.Distinct().ToList();
    public int CompareByMoney(StoreModel.StoreData start, StoreModel.StoreData end)
    {
        int money1 = start.storeConfig.MoneyNumber;
        int money2 = end.storeConfig.MoneyNumber;
        if (money1.CompareTo(money2) != 0) return money1.CompareTo(money2);
        int index1 = storelist.IndexOf(start);
        int index2 = storelist.IndexOf(end);
        if (index1.CompareTo(index2) != 0) return index1.CompareTo(index2);
        return 0;
    }
    #endregion
}
    }
public class XBTypeInfo
{
@@ -1026,17 +650,7 @@
    public Dictionary<int, int> gridLimitCntDict;        //<有限制抽取次数的格子编号,已抽到次数> 有限制抽取次数的格子次数信息
}
public class XBFuncSet
{
    public int xbType;// 1 极品寻宝 2 符印寻宝
    public int[] xbNums;
    public int[] xbPrices;
    public int[] costToolIds;
    public int[] costToolNums;
    public int[] xbFreeCDs;
    public int[] xbScores;
    public int dailyFreeCount;
}
public class XBGetItem
{
@@ -1044,7 +658,6 @@
    public int itemId;
    public int count;
    public DateTime createTime;
    public string createTimeStr;
    public void SetModel(int index, int id, int count)
    {
@@ -1052,7 +665,6 @@
        this.itemId = id;
        this.count = count;
        createTime = TimeUtility.ServerNow;
        createTimeStr = TimeUtility.ServerNow.ToString("yyyy-MM-dd HH:mm:ss");
    }
}
@@ -1067,6 +679,9 @@
    Gubao2 = 6,
    Gubao3 = 7,
    Gubao4 = 8,
    HeroCallNormal = 11,    //11-普通招募
    HeroCallAdvanced = 12,  //12-高级招募
    HeroCallScore = 13, //13-积分招募
    YunShi1 = 105,
    YunShi2 = 106,
    YunShi3 = 107,