少年修仙传客户端代码仓库
client_Zxw
2019-03-21 b700988d5cc605850dc903c17719c1af663cf9cc
Merge branch 'master' of http://192.168.0.87:10010/r/snxxz_scripts
1 文件已复制
7个文件已删除
3 文件已重命名
4个文件已添加
37个文件已修改
7998 ■■■■■ 已修改文件
Core/GameEngine/Model/Player/Character/PlayerExtersionData.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/GameEngine/Model/Player/PlayerDatas.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/NetworkPackage/DTCFile/ServerPack/HA2_Package/DTCA204_tagMCVPackRefresh.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/NetworkPackage/DTCFile/ServerPack/HA2_Package/DTCA205_tagMCVPackClear.cs 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA31F_tagMCRuneInfo.cs 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA3BA_tagMCTrialTowerInfo.cs 60 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Lua/Gen/SnxxzUIRolePromoteModelWrap.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Lua/Gen/SnxxzUIRuneModelWrap.cs 2622 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Lua/Gen/SnxxzUIRuneModelWrap.cs.meta 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Lua/Gen/XLuaGenAutoRegister.cs 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/DailyQuest/DailyQuestModel.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Dungeon/DungeonFightWin.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Dungeon/DungeonRuneTowerVictoryWin.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/FriendSystem/MailPanel.cs 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/GatheringSoul/GatheringSoulModel.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/GatheringSoul/VirtualPackModel.cs 113 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/HappyXB/HappyXBModel.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/KnapSack/Logic/ItemTipsModel.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/KnapSack/Logic/SelectBoxItemCell.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/NewBieGuidance/NewBieCenter.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rank/RankModel.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/RoleParticulars/ViewFuncCell.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/RolePromote/RolePromoteModel.cs 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneBothAttrCell.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneBreakCell.cs 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneBreakWin.cs 335 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneComposeModel.cs 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneComposeWin.cs 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneHoleBehaviour.cs 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneHoleBehaviour.cs.meta 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneModel.cs 2034 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneModel.cs.meta 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneMosaicWin.cs 830 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RunePackCell.cs 168 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RunePackWin.cs 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RunePanel.cs 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RunePreviewCell.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneResolveCell.cs 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneResolveCell.cs.meta 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneResolveModel.cs 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneResolveModel.cs.meta 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneResolveWin.cs 375 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Rune/RuneResolveWin.cs.meta 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/RuneTower/RunePreviewBehaviour.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/RuneTower/RuneTowerModel.cs 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/RuneTower/RuneTowerPassedInfoPanel.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Store/RuneCell.cs 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Store/RuneCell.cs.meta 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Store/RuneStoreWin.cs 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/Store/StoreModel.cs 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/WindowBase/ModelCenter.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Utility/UIHelper.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/GameEngine/Model/Player/Character/PlayerExtersionData.cs
@@ -60,6 +60,8 @@
    public int ComboDamPer;//连击伤害163
    public int MaxProDef;//最大防护值 164
    public int PetDamPer;  //灵兽增加伤害 152
    public int runeEssence;//符印精华 169
    public int runeChip;//符印碎片 170
    public int realmPoint;//境界修炼点 171
    public int magicEssence;//魔精
    public int pkState;//是否在pk中 175 1--进入状态 2--退出状态
Core/GameEngine/Model/Player/PlayerDatas.cs
@@ -665,10 +665,10 @@
                baseData.ExpPoint = value;
                break;
            case PlayerDataType.Rune:
                ModelCenter.Instance.GetModel<RuneModel>().SetRuneChip((int)value);
                extersion.runeChip = (int)value;
                break;
            case PlayerDataType.RuneSplinters:
                ModelCenter.Instance.GetModel<RuneModel>().SetRuneSplinters((int)value);
                extersion.runeEssence = (int)value;
                break;
            case PlayerDataType.FamilyContribution:
                method.CepaContribution((int)value);
Core/NetworkPackage/DTCFile/ServerPack/HA2_Package/DTCA204_tagMCVPackRefresh.cs
@@ -17,12 +17,6 @@
        base.Done(vNetPack);
        HA204_tagMCVPackRefresh vNetData = vNetPack as HA204_tagMCVPackRefresh;
        if (vNetData != null && vNetData.PackType == (int)PackType.RunePack)
        {
            ModelCenter.Instance.GetModel<RuneModel>().OnRunePackRefresh(vNetData);
        }
        virtualPackModel.OnReceiveServerPack(vNetData);
    }
Core/NetworkPackage/DTCFile/ServerPack/HA2_Package/DTCA205_tagMCVPackClear.cs
@@ -6,24 +6,17 @@
public class DTCA205_tagMCVPackClear : DtcBasic {
public class DTCA205_tagMCVPackClear : DtcBasic
{
    public override void Done(GameNetPackBasic vNetPack) {
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HA205_tagMCVPackClear vNetData = vNetPack as HA205_tagMCVPackClear;
        if (vNetData != null) {
            switch ((PackType)vNetData.PackType) {
                case PackType.RunePack:
                    ModelCenter.Instance.GetModel<RuneModel>().OnRunePackClear(vNetData);
                    break;
                default:
                    ModelCenter.Instance.GetModel<VirtualPackModel>().OnReceiveServerPack(vNetData);
                    break;
            }
        }
        ModelCenter.Instance.GetModel<VirtualPackModel>().OnReceiveServerPack(vNetData);
    }
}
Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA31F_tagMCRuneInfo.cs
@@ -1,23 +1,23 @@
using UnityEngine;
using System.Collections;
using Snxxz.UI;
// A3 1F 玩家符印信息 #tagMCRuneInfo
public class DTCA31F_tagMCRuneInfo : DtcBasic {
    public override void Done(GameNetPackBasic vNetPack) {
        base.Done(vNetPack);
        HA31F_tagMCRuneInfo vNetData = vNetPack as HA31F_tagMCRuneInfo;
        if (vNetData != null) {
            ModelCenter.Instance.GetModel<RuneModel>().OnRuneHoleRefresh(vNetData);
        }
    }
}
using UnityEngine;
using System.Collections;
using Snxxz.UI;
// A3 1F 玩家符印信息 #tagMCRuneInfo
public class DTCA31F_tagMCRuneInfo : DtcBasic
{
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HA31F_tagMCRuneInfo vNetData = vNetPack as HA31F_tagMCRuneInfo;
        ModelCenter.Instance.GetModel<RuneModel>().ReceivePackage(vNetData);
    }
}
Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA3BA_tagMCTrialTowerInfo.cs
@@ -1,30 +1,30 @@
using UnityEngine;
using System.Collections;
using Snxxz.UI;
// A3 BA 通知试炼之塔过关数 #tagMCTrialTowerInfo
public class DTCA3BA_tagMCTrialTowerInfo : DtcBasic
{
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HA3BA_tagMCTrialTowerInfo vNetData = vNetPack as HA3BA_tagMCTrialTowerInfo;
        if (vNetData != null)
        {
            ModelCenter.Instance.GetModel<RuneModel>().OnRuneTowerRefresh(vNetData);
            ModelCenter.Instance.GetModel<RuneTowerModel>().yesterdayPassFloor = (int)vNetData.YesterDayPassLV;
        }
    }
}
using UnityEngine;
using System.Collections;
using Snxxz.UI;
// A3 BA 通知试炼之塔过关数 #tagMCTrialTowerInfo
public class DTCA3BA_tagMCTrialTowerInfo : DtcBasic
{
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HA3BA_tagMCTrialTowerInfo vNetData = vNetPack as HA3BA_tagMCTrialTowerInfo;
        if (vNetData != null)
        {
            ModelCenter.Instance.GetModel<RuneModel>().ReceivePackage(vNetData);
            ModelCenter.Instance.GetModel<RuneTowerModel>().yesterdayPassFloor = (int)vNetData.YesterDayPassLV;
        }
    }
}
Lua/Gen/SnxxzUIRolePromoteModelWrap.cs
@@ -33,7 +33,6 @@
            Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetPromoteState", _m_GetPromoteState);
            Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetPresentRoleStronger", _m_GetPresentRoleStronger);
            Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetEquipCnt", _m_GetEquipCnt);
            Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetRuneCnt", _m_GetRuneCnt);
            Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetMountCnt", _m_GetMountCnt);
            Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetMountTotallv", _m_GetMountTotallv);
            Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetPetCnt", _m_GetPetCnt);
@@ -368,38 +367,6 @@
                    
                    
                    return 1;
                }
            } catch(System.Exception gen_e) {
                return LuaAPI.luaL_error(L, "c# exception:" + gen_e);
            }
        }
        [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
        static int _m_GetRuneCnt(RealStatePtr L)
        {
            try {
                ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L);
                Snxxz.UI.RolePromoteModel gen_to_be_invoked = (Snxxz.UI.RolePromoteModel)translator.FastGetCSObj(L, 1);
                {
                    int __tatalLv = LuaAPI.xlua_tointeger(L, 2);
                    int __count;
                        bool gen_ret = gen_to_be_invoked.GetRuneCnt( __tatalLv, out __count );
                        LuaAPI.lua_pushboolean(L, gen_ret);
                    LuaAPI.xlua_pushinteger(L, __count);
                    return 2;
                }
                
            } catch(System.Exception gen_e) {
Lua/Gen/SnxxzUIRuneModelWrap.cs
File was deleted
Lua/Gen/SnxxzUIRuneModelWrap.cs.meta
File was deleted
Lua/Gen/XLuaGenAutoRegister.cs
@@ -1323,9 +1323,6 @@
            translator.DelayWrapLoader(typeof(Snxxz.UI.RuneComposeModel), SnxxzUIRuneComposeModelWrap.__Register);
        
        
            translator.DelayWrapLoader(typeof(Snxxz.UI.RuneModel), SnxxzUIRuneModelWrap.__Register);
            translator.DelayWrapLoader(typeof(Snxxz.UI.RuneTowerModel), SnxxzUIRuneTowerModelWrap.__Register);
        
        
System/DailyQuest/DailyQuestModel.cs
@@ -954,7 +954,7 @@
                if (runeTowerModel.yesterdayPassFloor <= 0)
                {
                    var runeModel = ModelCenter.Instance.GetModel<RuneModel>();
                    if (runeModel.RuneTowerOpenLV > 0)
                    if (runeModel.passRuneTowerFloor > 0)
                    {
                        description = Language.Get("DailyQuestwin4");
                    }
System/Dungeon/DungeonFightWin.cs
@@ -340,7 +340,7 @@
                        if (!runeTowerModel.allTowerCompleted)
                        {
                            var config = RuneTowerFloorConfig.Get(runeTowerModel.currentFloor);
                            var lastFloor = (int)ModelCenter.Instance.GetModel<RuneModel>().RuneTowerOpenLV;
                            var lastFloor = (int)ModelCenter.Instance.GetModel<RuneModel>().passRuneTowerFloor;
                            var lastFloorConfig = RuneTowerFloorConfig.Get(lastFloor);
                            if (model.dungeonResult.isPass == 1 && config.TowerId == lastFloorConfig.TowerId && lastFloorConfig.AutoExit == 0)
                            {
System/Dungeon/DungeonRuneTowerVictoryWin.cs
@@ -53,7 +53,7 @@
            if (!runeTowerModel.allTowerCompleted)
            {
                var config = RuneTowerFloorConfig.Get(runeTowerModel.currentFloor);
                var lastFloor = (int)ModelCenter.Instance.GetModel<RuneModel>().RuneTowerOpenLV;
                var lastFloor = (int)ModelCenter.Instance.GetModel<RuneModel>().passRuneTowerFloor;
                var lastFloorConfig = RuneTowerFloorConfig.Get(lastFloor);
                m_RuneTowerNext.gameObject.SetActive(lastFloorConfig.AutoExit == 0 && config.TowerId == lastFloorConfig.TowerId);
@@ -121,7 +121,7 @@
            {
                m_UnLockRuneHoleContainer.gameObject.SetActive(true);
                var nextHole = runeTowerModel.GetAccumulativeUnLockHoleCount((int)runeModel.RuneTowerOpenLV);
                var nextHole = runeTowerModel.GetAccumulativeUnLockHoleCount((int)runeModel.passRuneTowerFloor);
                var currentHole = nextHole - 1;
                m_CurrentUnLockRuneHole.text = currentHole.ToString();
                m_NextUnLockRuneHole.text = nextHole.ToString();
System/FriendSystem/MailPanel.cs
@@ -67,12 +67,6 @@
    private MailInfo _currentMailInfo;
    private int curMail = 0;
    RuneModel _runeModel;
    RuneModel runeModel
    {
        get { return _runeModel ?? (_runeModel = ModelCenter.Instance.GetModel<RuneModel>()); }
    }
    ItemTipsModel _itemTipsModel;
    ItemTipsModel itemTipsModel
    {
@@ -691,17 +685,13 @@
        foreach (var key in GetPackItemDcit.Keys)
        {
            int remainCount = 0;
            switch (key)
            if (virtualPackModel.IsVirtualPack(key))
            {
                case PackType.GatherSoul:
                    remainCount = virtualPackModel.GetPackRemainCount(key);
                    break;
                case PackType.RunePack:
                    remainCount = runeModel.SurplusRunePackCnt;
                    break;
                default:
                    remainCount = playerPack.GetEmptyGridCount(key);
                    break;
                remainCount = virtualPackModel.GetPackRemainCount(key);
            }
            else
            {
                remainCount = playerPack.GetEmptyGridCount(key);
            }
            int getCount = GetPackItemDcit[key];
System/GatheringSoul/GatheringSoulModel.cs
@@ -1731,6 +1731,12 @@
            }
        }
        public override void Release()
        {
            base.Release();
            placeType = 0;
        }
        public bool ExistSameProperty(int compareId)
        {
            if (!model.gatherSoulPropertys.ContainsKey(compareId)
System/GatheringSoul/VirtualPackModel.cs
@@ -13,6 +13,8 @@
        Dictionary<PackType, List<VirtualPackItem>> virtualPackItems
            = new Dictionary<PackType, List<VirtualPackItem>>();
        Dictionary<PackType, ObjectPool<VirtualPackItem>> m_VirtualItemPool
            = new Dictionary<PackType, ObjectPool<VirtualPackItem>>();
        Dictionary<PackType, int> virtualPackCapacityDict = new Dictionary<PackType, int>();
        public event Action<PackType> virtualPackRefresh;
@@ -20,10 +22,21 @@
        public override void Init()
        {
            ParseConfig();
            m_VirtualItemPool.Add(PackType.GatherSoul, new ObjectPool<VirtualPackItem>(OnGetItem, OnReleaseItem));
            m_VirtualItemPool.Add(PackType.RunePack, new ObjectPool<VirtualPackItem>(OnGetItem, OnReleaseItem));
        }
        public void OnBeforePlayerDataInitialize()
        {
            foreach (var packType in virtualPackItems.Keys)
            {
                var pool = m_VirtualItemPool[packType];
                var items = virtualPackItems[packType];
                foreach (var item in items)
                {
                    pool.Release(item);
                }
            }
            virtualPackItems.Clear();
        }
@@ -38,10 +51,20 @@
        void ParseConfig()
        {
            var funcConfig = FuncConfigConfig.Get("GatherSoulPackCount");
            if (funcConfig != null)
            virtualPackCapacityDict.Add(PackType.GatherSoul, int.Parse(funcConfig.Numerical1));
            funcConfig = FuncConfigConfig.Get("RunePackageNum");
            virtualPackCapacityDict.Add(PackType.RunePack, int.Parse(funcConfig.Numerical1));
        }
        public bool IsVirtualPack(PackType packType)
        {
            switch (packType)
            {
                virtualPackCapacityDict.Add(PackType.GatherSoul, int.Parse(funcConfig.Numerical1));
                case PackType.GatherSoul:
                case PackType.RunePack:
                    return true;
            }
            return false;
        }
        public int GetPackCapacity(PackType packType)
@@ -56,11 +79,16 @@
        public int GetPackRemainCount(PackType packType)
        {
            var capacity = GetPackCapacity(packType);
            return capacity - GetPackItemCount(packType);
        }
        public int GetPackItemCount(PackType packType)
        {
            if (virtualPackItems.ContainsKey(packType))
            {
                return capacity - virtualPackItems[packType].Count;
                return virtualPackItems[packType].Count;
            }
            return capacity;
            return 0;
        }
        public int GetItemCountById(PackType packType, int id)
@@ -80,6 +108,19 @@
                }
            }
            return count;
        }
        public void GetItemIndexs(PackType packType, ref List<int> list)
        {
            list.Clear();
            List<VirtualPackItem> _list;
            if (virtualPackItems.TryGetValue(packType, out _list))
            {
                for (int i = 0; i < _list.Count; i++)
                {
                    list.Add(_list[i].index);
                }
            }
        }
        public bool TryGetItems(PackType packType, out List<int> list)
@@ -118,12 +159,9 @@
        public void OnReceiveServerPack(HA204_tagMCVPackRefresh package)
        {
            var packType = (PackType)package.PackType;
            switch (packType)
            if (!IsVirtualPack(packType))
            {
                case PackType.GatherSoul:
                    break;
                default:
                    return;
                return;
            }
            List<VirtualPackItem> list;
            if (!virtualPackItems.TryGetValue(packType, out list))
@@ -140,26 +178,38 @@
        public void OnReceiveServerPack(HA205_tagMCVPackClear package)
        {
            List<VirtualPackItem> list;
            if (virtualPackItems.TryGetValue((PackType)package.PackType, out list))
            var packType = (PackType)package.PackType;
            if (!IsVirtualPack(packType))
            {
                return;
            }
            List<VirtualPackItem> list;
            if (virtualPackItems.TryGetValue(packType, out list))
            {
                var pool = m_VirtualItemPool[packType];
                for (int i = 0; i < package.Count; i++)
                {
                    var index = package.ItemPlaceList[i];
                    list.RemoveAll((x) =>
                    var items = list.FindAll((x) =>
                    {
                        return x.index == index;
                    });
                    foreach (var item in items)
                    {
                        list.Remove(item);
                        pool.Release(item);
                    }
                }
                if (virtualPackRefresh != null)
                {
                    virtualPackRefresh((PackType)package.PackType);
                    virtualPackRefresh(packType);
                }
            }
        }
        void SetVirtualItem(PackType packType, ref List<VirtualPackItem> list, HA204_tagMCVPackRefresh.tagMCVPackItem[] items)
        {
            var pool = m_VirtualItemPool[packType];
            for (int i = 0; i < items.Length; i++)
            {
                var item = list.Find((x) =>
@@ -168,13 +218,33 @@
                });
                if (item != null)
                {
                    list.Remove(item);
                    item = null;
                    item.Release();
                }
                item = VirtualPackItem.Get(packType);
                list.Add(item);
                else
                {
                    if (pool.inactivedCount > 0)
                    {
                        item = pool.Get();
                        list.Add(item);
                    }
                }
                if (item == null)
                {
                    item = VirtualPackItem.Get(packType);
                    list.Add(item);
                }
                item.ParsePackItem(items[i].ItemPlace, items[i].ItemData);
            }
        }
        static void OnGetItem(VirtualPackItem item)
        {
        }
        static void OnReleaseItem(VirtualPackItem item)
        {
            item.Release();
        }
    }
@@ -186,7 +256,7 @@
        public int level { get; private set; }
        protected string dataString { get; private set; }
        protected string dataString { get; set; }
        protected static StringBuilder sb = new StringBuilder();
@@ -204,12 +274,19 @@
            level = int.Parse(dataString.Substring(2, 3)) + 1;
        }
        public virtual void Release()
        {
            dataString = null;
        }
        public static VirtualPackItem Get(PackType packType)
        {
            switch (packType)
            {
                case PackType.GatherSoul:
                    return new GatherSoulItem();
                case PackType.RunePack:
                    return new RuneItem();
            }
            return null;
        }
System/HappyXB/HappyXBModel.cs
@@ -580,8 +580,8 @@
                    }
                    break;
                case PackType.RunePack:
                    var runeModel = ModelCenter.Instance.GetModel<RuneModel>();
                    if (runeModel.SurplusRunePackCnt < needGrid)
                    var virtualPackModel = ModelCenter.Instance.GetModel<VirtualPackModel>();
                    if (virtualPackModel.GetPackRemainCount(PackType.RunePack) < needGrid)
                    {
                        SysNotifyMgr.Instance.ShowTip("RuneBagFull");
                        return false;
System/KnapSack/Logic/ItemTipsModel.cs
@@ -1884,17 +1884,13 @@
            if (itemTipsModel.randomRuneIds.Contains(this.itemId))
            {
                Dictionary<int, List<int>> unlockRuneDict = runeModel.GetAllUnlockRuneIdlist();
                List<int> unlockRunes = runeModel.GetUnlockRunes();
                List<string> extraInfos = new List<string>();
                if (unlockRuneDict != null)
                foreach (var runeId in unlockRunes)
                {
                    foreach (var key in unlockRuneDict.Keys)
                    {
                        int runeId = unlockRuneDict[key][0];
                        ItemConfig runeConfig = ItemConfig.Get(runeId);
                        string effectDes = StringUtility.Contact(UIHelper.AppendColor(TextColType.Green, runeConfig.ItemName), ":", Language.Get(StringUtility.Contact("RuneTypeDesc_", runeConfig.Effect1)));
                        extraInfos.Add(effectDes);
                    }
                    ItemConfig runeConfig = ItemConfig.Get(runeId);
                    string effectDes = StringUtility.Contact(UIHelper.AppendColor(TextColType.Green, runeConfig.ItemName), ":", Language.Get(StringUtility.Contact("RuneTypeDesc_", runeConfig.Effect1)));
                    extraInfos.Add(effectDes);
                }
                SetExtraInfos(extraInfos.ToArray());
            }
System/KnapSack/Logic/SelectBoxItemCell.cs
@@ -43,8 +43,6 @@
            switch(packType)
            {
                case PackType.RunePack:
                    haveCnt = ModelCenter.Instance.GetModel<RuneModel>().GetRuneCountById(id);
                    break;
                case PackType.GatherSoul:
                    haveCnt = ModelCenter.Instance.GetModel<VirtualPackModel>().GetItemCountById(packType,id);
                    break;
System/NewBieGuidance/NewBieCenter.cs
@@ -301,7 +301,7 @@
                case GuideTriggerType.ManualFunctionOpen:
                    return FuncOpen.Instance.IsFuncOpen(config.Condition);
                case GuideTriggerType.RuneInlay:
                    return FuncOpen.Instance.IsFuncOpen(config.Condition) && runeModel.RuneCount > 0;
                    return FuncOpen.Instance.IsFuncOpen(config.Condition) && runeModel.GetRuneTotalCount(RuneModel.RUNE_TYPE) > 0;
                case GuideTriggerType.Level:
                    return PlayerDatas.Instance.baseData.LV >= config.Condition;
                case GuideTriggerType.EquipQuality:
System/Rank/RankModel.cs
@@ -85,7 +85,7 @@
            {
                foreach (var item in rankDatas)
                {
                    m_RankDataPool.Add(item);
                    m_RankDataPool.Release(item);
                }
            }
            m_RankDatas.Clear();
@@ -191,7 +191,7 @@
            {
                RankData data = rankDatas[i];
                rankDatas.RemoveAt(i);
                m_RankDataPool.Add(data);
                m_RankDataPool.Release(data);
            }
            if (onRankRefresh != null)
            {
System/RoleParticulars/ViewFuncCell.cs
@@ -191,7 +191,7 @@
                        targetValue = viewPlayerData.rolePlusData.GetGodWeaponLevel(2);
                        break;
                    case FuncPowerType.Rune:
                        selfValue = ModelCenter.Instance.GetModel<RuneModel>().GetHoleRuneCnt();
                        selfValue = ModelCenter.Instance.GetModel<RuneModel>().GetRuneInlayCount();
                        targetValue = viewPlayerData.rolePlusData.Rune;
                        break;
                    case FuncPowerType.Human:
System/RolePromote/RolePromoteModel.cs
@@ -79,12 +79,11 @@
            }
        }
        RuneModel m_RuneModel;
        RuneModel runeModel
        {
            get
            {
                return m_RuneModel ?? (m_RuneModel = ModelCenter.Instance.GetModel<RuneModel>());
                return ModelCenter.Instance.GetModel<RuneModel>();
            }
        }
        PetModel m_petModel;
@@ -237,20 +236,6 @@
                }
            }
            return _count;
        }
        #endregion
        #region 符印
        public bool GetRuneCnt(int _tatalLv, out int _count)
        {
            int totalLv = 0;
            var _runeHoleDatas = runeModel.GetAllRuneData();
            foreach (var _rune in _runeHoleDatas.Values)
            {
                totalLv += _rune.lv;
            }
            _count = totalLv >= _tatalLv ? _runeHoleDatas.Count : 0;
            return totalLv >= _tatalLv;
        }
        #endregion
@@ -442,7 +427,7 @@
                _id == MainRedDot.RedPoint_MountPackKey ||
                _id == MainRedDot.Instance.redPonintPetFunc2.id ||
                _id == MainRedDot.Instance.redPointWashFunc.id ||
                _id == runeModel.runeMosaicRedpoint.id ||
                _id == runeModel.redpoint.id ||
                _id == magicianModel.magicianRedpoint.id ||
                _id == methodData.fairyHeartRedpoint.id ||
                _id == realmModel.levelUpRedpoint.id ||
@@ -469,7 +454,7 @@
                case PromoteDetailType.Pet:
                    return MainRedDot.Instance.redPonintPetFunc2.state == RedPointState.Simple;
                case PromoteDetailType.RuneMosaic:
                    return runeModel.runeMosaicRedpoint.state == RedPointState.Simple;
                    return runeModel.redpoint.state == RedPointState.Simple;
                case PromoteDetailType.GodWeapon:
                    return magicianModel.magicianRedpoint.state == RedPointState.Simple;
                case PromoteDetailType.TreasurePotential:
System/Rune/RuneBothAttrCell.cs
@@ -23,12 +23,11 @@
            }
        }
        RuneModel m_RuneModel;
        RuneModel runeModel
        {
            get
            {
                return m_RuneModel ?? (m_RuneModel = ModelCenter.Instance.GetModel<RuneModel>());
                return ModelCenter.Instance.GetModel<RuneModel>();
            }
        }
        public override void Refresh(CellView cell)
@@ -45,7 +44,7 @@
            ItemConfig _itemCfg = ItemConfig.Get(_list[cell.index].TagItemID);
            m_RuneNameTxt.text = _itemCfg.ItemName;
            RuneConfig _runeCfg = RuneConfig.Get(_itemCfg.ID);
            bool _unlockTower = _runeCfg.TowerID <= runeModel.RuneTowerOpenLV;
            bool _unlockTower = _runeCfg.TowerID <= runeModel.passRuneTowerFloor;
            m_LockImg.gameObject.SetActive(!_unlockTower);
            m_RuneTowerTxt.gameObject.SetActive(!_unlockTower);
            var _redpointTypeKey = 10803 * 100 + model.presentSelectRuneQuality;
System/Rune/RuneBreakCell.cs
File was deleted
System/Rune/RuneBreakWin.cs
File was deleted
System/Rune/RuneComposeModel.cs
@@ -8,6 +8,10 @@
    [XLua.LuaCallCSharp]
    public class RuneComposeModel : Model, IPlayerLoginOk
    {
        RuneModel runeModel { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
        VirtualPackModel virtualPackModel { get { return ModelCenter.Instance.GetModel<VirtualPackModel>(); } }
        public override void Init()
        {
            presentSelectRuneQuality = 0;
@@ -15,9 +19,9 @@
            ParseConfig();
            PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefreshInfoEvent;
            runeModel.OnRefreshRuneTowerLv += OnRefreshRune;
            runeModel.OnRefreshRunePack += OnRefreshRune;
            runeModel.OnRefreshRuneHole += OnRefreshRune;
            runeModel.onRuneTowerRefresh += OnRefreshRune;
            virtualPackModel.virtualPackRefresh += VirtualPackRefresh;
            runeModel.onRuneHoleRefresh += OnRefreshRune;
            foreach (var _key in runeComposeDict.Keys)
            {
@@ -35,15 +39,15 @@
        public override void UnInit()
        {
            runeModel.onRuneTowerRefresh -= OnRefreshRune;
            runeModel.onRuneHoleRefresh -= OnRefreshRune;
            virtualPackModel.virtualPackRefresh -= VirtualPackRefresh;
        }
        public void OnPlayerLoginOk()
        {
            UpdateRedpoint();
        }
        RuneModel runeModel { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
        #region 配置
        public Dictionary<int, List<RuneComposeConfig>> runeComposeDict = new Dictionary<int, List<RuneComposeConfig>>();
@@ -96,6 +100,14 @@
            }
        }
        private void VirtualPackRefresh(PackType packType)
        {
            if (packType == PackType.RunePack)
            {
                UpdateRedpoint();
            }
        }
        private void OnRefreshRune()
        {
            UpdateRedpoint();
@@ -124,14 +136,14 @@
                for (int i = 0; i < _list.Count; i++)
                {
                    var _runeConfig = RuneConfig.Get(_list[i].TagItemID);
                    if (runeModel.RuneTowerOpenLV < _runeConfig.TowerID)
                    if (runeModel.passRuneTowerFloor < _runeConfig.TowerID)
                    {
                        continue;
                    }
                    var _runeComposeConfig = RuneComposeConfig.Get(_list[i].TagItemID);
                    RuneData _data;
                    var count1 = runeModel.GetMaxLevelRuneCnt(_runeComposeConfig.NeedItem[0], out _data);
                    var count2 = runeModel.GetMaxLevelRuneCnt(_runeComposeConfig.NeedItem[1], out _data);
                    RuneItem item;
                    var count1 = runeModel.TryGetComposeRuneCount(_runeComposeConfig.NeedItem[0], out item);
                    var count2 = runeModel.TryGetComposeRuneCount(_runeComposeConfig.NeedItem[1], out item);
                    var magicEssence = PlayerDatas.Instance.extersion.magicEssence;
                    if (count1 > 0 && count2 > 0 && magicEssence >= _runeComposeConfig.NeedMJ)
                    {
System/Rune/RuneComposeWin.cs
@@ -48,23 +48,14 @@
        [SerializeField] Button m_ComposeBtn;
        [SerializeField] RedpointBehaviour m_ComposeRedpoint;
        RuneComposeModel m_Model;
        RuneComposeModel model
        {
            get
            {
                return m_Model ?? (m_Model = ModelCenter.Instance.GetModel<RuneComposeModel>());
            }
        }
        RuneComposeModel model { get { return ModelCenter.Instance.GetModel<RuneComposeModel>(); } }
        RuneModel m_RuneModel;
        RuneModel runeModel
        {
            get
            {
                return m_RuneModel ?? (m_RuneModel = ModelCenter.Instance.GetModel<RuneModel>());
            }
        }
        RuneModel runeModel { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
        RuneResolveModel runeResolveModel { get { return ModelCenter.Instance.GetModel<RuneResolveModel>(); } }
        VirtualPackModel virtualPackModel { get { return ModelCenter.Instance.GetModel<VirtualPackModel>(); } }
        #region Built-in
        protected override void BindController()
        {
@@ -87,8 +78,8 @@
        protected override void OnPreOpen()
        {
            runeModel.OnRefreshRuneTowerLv += OnRefreshRuneTowerLv;
            runeModel.OnRefreshRunePack += RefreshRuneCompose;
            runeModel.onRuneTowerRefresh += OnRuneTowerRefresh;
            virtualPackModel.virtualPackRefresh += VirtualPackRefresh;
            PlayerDatas.Instance.playerDataRefreshEvent += OnRefreshPlayerInfo;
            DTC0721_tagMakeItemAnswer.MakeItemAnswerEvent += MakeItemAnswerEvent;
            RefreshRuneType();
@@ -101,8 +92,8 @@
        protected override void OnPreClose()
        {
            runeModel.OnRefreshRuneTowerLv -= OnRefreshRuneTowerLv;
            runeModel.OnRefreshRunePack -= RefreshRuneCompose;
            runeModel.onRuneTowerRefresh -= OnRuneTowerRefresh;
            virtualPackModel.virtualPackRefresh -= VirtualPackRefresh;
            PlayerDatas.Instance.playerDataRefreshEvent -= OnRefreshPlayerInfo;
            DTC0721_tagMakeItemAnswer.MakeItemAnswerEvent -= MakeItemAnswerEvent;
        }
@@ -111,7 +102,7 @@
        {
        }
        #endregion
        private void OnRefreshRuneTowerLv()
        private void OnRuneTowerRefresh()
        {
            scrollerController.m_Scorller.RefreshActiveCellViews();
        }
@@ -168,22 +159,22 @@
                ItemConfig _itemCfg = ItemConfig.Get(_cfg.NeedItem[0]);
                m_Rune1Img.SetSprite(_itemCfg.IconKey);
                RuneData _rune1 = null;
                var _runeCnt = runeModel.GetMaxLevelRuneCnt(_cfg.NeedItem[0], out _rune1);
                RuneItem _rune1 = null;
                var _runeCnt = runeModel.TryGetComposeRuneCount(_cfg.NeedItem[0], out _rune1);
                m_Rune1NumTxt.text = StringUtility.Contact(_runeCnt > 0 ? 
                    UIHelper.AppendColor(TextColType.White, _runeCnt.ToString()) :
                    UIHelper.AppendColor(TextColType.Red, _runeCnt.ToString()), "/", 1);
                m_Rune1NameTxt.text = StringUtility.Contact(_itemCfg.ItemName, " Lv.", _rune1 == null ? 1 : _rune1.lv);
                m_Rune1NameTxt.text = StringUtility.Contact(_itemCfg.ItemName, " Lv.", _rune1 == null ? 1 : _rune1.level);
                m_Rune1NameTxt.color = UIHelper.GetUIColor(_itemCfg.ItemColor, true);
                _itemCfg = ItemConfig.Get(_cfg.NeedItem[1]);
                m_Rune2Img.SetSprite(_itemCfg.IconKey);
                RuneData _rune2 = null;
                _runeCnt = runeModel.GetMaxLevelRuneCnt(_cfg.NeedItem[1], out _rune2);
                RuneItem _rune2 = null;
                _runeCnt = runeModel.TryGetComposeRuneCount(_cfg.NeedItem[1], out _rune2);
                m_Rune2NumTxt.text = StringUtility.Contact(_runeCnt > 0 ? 
                    UIHelper.AppendColor(TextColType.White, _runeCnt.ToString()) :
                    UIHelper.AppendColor(TextColType.Red, _runeCnt.ToString()), "/", 1);
                m_Rune2NameTxt.text = StringUtility.Contact(_itemCfg.ItemName, " Lv.", _rune2 == null ? 1 : _rune2.lv);
                m_Rune2NameTxt.text = StringUtility.Contact(_itemCfg.ItemName, " Lv.", _rune2 == null ? 1 : _rune2.level);
                m_Rune2NameTxt.color = UIHelper.GetUIColor(_itemCfg.ItemColor, true);
                _itemCfg = ItemConfig.Get(_cfg.TagItemID);
@@ -192,20 +183,20 @@
                if (_rune1 != null && _rune2 != null)
                {
                    float _exp = 0;
                    _exp += runeModel.GetRuneBreakExp(_rune1, true);
                    _exp += runeModel.GetRuneBreakExp(_rune2, true);
                    _composeLv = runeModel.GetRuneLevelByExp(_cfg.TagItemID, _exp);
                    _exp += runeResolveModel.GetRuneResolveGetSplinters(_rune1.id, _rune1.level, true);
                    _exp += runeResolveModel.GetRuneResolveGetSplinters(_rune2.id, _rune2.level, true);
                    _composeLv = runeModel.GetRuneLevelBySplinters(_cfg.TagItemID, _exp);
                }
                m_ComposeRuneNameTxt.text = StringUtility.Contact(_itemCfg.ItemName, " Lv.", _composeLv);
                RuneConfig _tagRuneModel = RuneConfig.Get(_itemCfg.ID);
                int[] _runeTypes = _tagRuneModel.AttrType;
                var _propertyCfg = PlayerPropertyConfig.Get(_runeTypes[0]);
                m_ComposeRuneProperty0.text = _propertyCfg.Name;
                m_ComposeRunePropertyValue0.text = StringUtility.Contact("+", UIHelper.ReplacePercentage(runeModel.GetRuneAttrVal(_itemCfg.ID,
                m_ComposeRunePropertyValue0.text = StringUtility.Contact("+", UIHelper.ReplacePercentage(runeModel.GetPropertyValue(_itemCfg.ID,
                    _composeLv, _runeTypes[0]), _propertyCfg.ISPercentage), _propertyCfg.ISPercentage == 1 ? "%" : string.Empty);
                _propertyCfg = PlayerPropertyConfig.Get(_runeTypes[1]);
                m_ComposeRuneProperty1.text = _propertyCfg.Name;
                m_ComposeRunePropertyValue1.text = StringUtility.Contact("+", UIHelper.ReplacePercentage(runeModel.GetRuneAttrVal(_itemCfg.ID,
                m_ComposeRunePropertyValue1.text = StringUtility.Contact("+", UIHelper.ReplacePercentage(runeModel.GetPropertyValue(_itemCfg.ID,
                    _composeLv, _runeTypes[1]), _propertyCfg.ISPercentage), _propertyCfg.ISPercentage == 1 ? "%" : string.Empty);
                m_ComposeRuneNameTxt.color = UIHelper.GetUIColor(_itemCfg.ItemColor, true);
            }
@@ -227,6 +218,15 @@
            }
            scrollerController.Restart();
        }
        private void VirtualPackRefresh(PackType packType)
        {
            if (packType == PackType.RunePack)
            {
                RefreshRuneCompose();
            }
        }
        private void OnComposeRuneClick(CellView cell)
        {
            if (model.presentSelectComposeRune == cell.index)
@@ -239,7 +239,7 @@
                return;
            }
            RuneConfig _runeCfg = RuneConfig.Get(_list[cell.index].TagItemID);
            bool _unlockTower = _runeCfg.TowerID <= runeModel.RuneTowerOpenLV;
            bool _unlockTower = _runeCfg.TowerID <= runeModel.passRuneTowerFloor;
            if (!_unlockTower)
            {
                return;
@@ -262,7 +262,7 @@
            if (_cfg != null)
            {
                var _itemPathModel = ModelCenter.Instance.GetModel<GetItemPathModel>();
                RuneConfig _runeCfg = RuneConfig.Get(_cfg.NeedItem[_index]);
                RuneTowerConfig _towerCfg = null;
                RuneTowerFloorConfig _runeTowerCfg = null;
@@ -271,36 +271,38 @@
                    _runeTowerCfg = RuneTowerFloorConfig.Get(_runeCfg.TowerID);
                    _towerCfg = RuneTowerConfig.Get(_runeTowerCfg.TowerId);
                }
                RuneData _rune = null;
                var _runeCnt = runeModel.GetMaxLevelRuneCnt(_cfg.NeedItem[_index], out _rune);
                _itemPathModel.SetRuneModel(_cfg.NeedItem[_index], _rune != null ? _rune.lv : 1, runeModel.GetRuneAttrStr(_cfg.NeedItem[_index], _rune != null ? _rune.lv : 1),
                    _runeCfg.TowerID == 0 ? Language.Get("L1062") : Language.Get("RuneItemOrigin", _towerCfg.TowerName, _runeTowerCfg.FloorName));
                RuneItem _rune = null;
                var _runeCnt = runeModel.TryGetComposeRuneCount(_cfg.NeedItem[_index], out _rune);
                var propertyDescrition = runeModel.GetRunePropertyDescription(_cfg.NeedItem[_index], _rune != null ? _rune.level : 1);
                var towerLabel = _runeCfg.TowerID == 0 ? Language.Get("L1062") :
                    Language.Get("RuneItemOrigin", _towerCfg.TowerName, _runeTowerCfg.FloorName);
                _itemPathModel.SetRuneModel(_cfg.NeedItem[_index], _rune != null ? _rune.level : 1, propertyDescrition, towerLabel);
            }
        }
        private void OnComposeBtn()
        {
            RuneComposeConfig _cfg = model.GetRuneCompose(model.presentSelectRuneQuality, model.presentSelectComposeRune);
            RuneData _rune1 = null;
            var _runeCnt = runeModel.GetMaxLevelRuneCnt(_cfg.NeedItem[0], out _rune1);
            RuneData _rune2 = null;
            _runeCnt = runeModel.GetMaxLevelRuneCnt(_cfg.NeedItem[1], out _rune2);
            RuneItem _rune1 = null;
            var _runeCnt = runeModel.TryGetComposeRuneCount(_cfg.NeedItem[0], out _rune1);
            RuneItem _rune2 = null;
            _runeCnt = runeModel.TryGetComposeRuneCount(_cfg.NeedItem[1], out _rune2);
            if (PlayerDatas.Instance.extersion.magicEssence < _cfg.NeedMJ)
            {
                return;
            }
            if (_rune1 != null && _rune2 != null)
            {
                CA578_tagCMRuneCompound _pak = new CA578_tagCMRuneCompound();
                _pak.TagItemID = (uint)_cfg.TagItemID;
                _pak.Cnt = 2;
                _pak.PackList = new byte[_pak.Cnt];
                _pak.IndexList = new byte[_pak.Cnt];
                _pak.PackList[0] = _rune1.packtype == (int)PackType.RunePack ? (byte)0 : (byte)1;
                _pak.IndexList[0] = (byte)_rune1.index;
                _pak.PackList[1] = _rune2.packtype == (int)PackType.RunePack ? (byte)0 : (byte)1;
                _pak.IndexList[1] = (byte)_rune2.index;
                GameNetSystem.Instance.SendInfo(_pak);
                CA578_tagCMRuneCompound pak = new CA578_tagCMRuneCompound();
                pak.TagItemID = (uint)_cfg.TagItemID;
                pak.Cnt = 2;
                pak.PackList = new byte[pak.Cnt];
                pak.IndexList = new byte[pak.Cnt];
                pak.PackList[0] = (byte)_rune1.placeType;
                pak.IndexList[0] = (byte)_rune1.index;
                pak.PackList[1] = (byte)_rune2.placeType;
                pak.IndexList[1] = (byte)_rune2.index;
                GameNetSystem.Instance.SendInfo(pak);
            }
        }
System/Rune/RuneHoleBehaviour.cs
New file
@@ -0,0 +1,140 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Snxxz.UI
{
    public class RuneHoleBehaviour : MonoBehaviour
    {
        [SerializeField] Image m_Icon;
        [SerializeField] Text m_Level;
        [SerializeField] Transform m_ContainerRune;
        [SerializeField] Transform m_ContainerLock;
        [SerializeField] Transform m_ContainerSelect;
        [SerializeField] Transform m_ContainerAddSign;
        [SerializeField] UIEffect m_MultiPropertyEffect;
        [SerializeField] Button m_Select;
        [SerializeField] RedpointBehaviour m_Redpoint;
        int hole = 0;
        Coroutine coroutine = null;
        RuneModel model { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
        private void Awake()
        {
            m_Select.AddListener(OnSelect);
        }
        public void Display(int hole)
        {
            this.hole = hole;
            model.onSelectHoleRefresh += OnSelectHoleRefresh;
            model.onOpenNewHole += OnOpenNewHole;
            model.onRuneHoleRefresh += OnRuneHoleRefresh;
            DisplayBase();
            DisplaySelect();
            RuneModel.RuneHoleRedpoint redpoint;
            if (model.TryGetRedpoint(hole, out redpoint))
            {
                m_Redpoint.redpointId = redpoint.redpoint.id;
            }
        }
        public void Dispose()
        {
            model.onSelectHoleRefresh -= OnSelectHoleRefresh;
            model.onOpenNewHole -= OnOpenNewHole;
            model.onRuneHoleRefresh -= OnRuneHoleRefresh;
            if (coroutine != null)
            {
                StopCoroutine(coroutine);
            }
        }
        void DisplayBase()
        {
            var isHoleOpne = model.IsRuneHoleOpen(hole, model.holeState);
            m_ContainerLock.gameObject.SetActive(!isHoleOpne);
            RuneItem runeItem;
            var existRune = model.TryGetRuneHoleItem(hole, out runeItem);
            m_ContainerAddSign.gameObject.SetActive(isHoleOpne && !existRune);
            m_ContainerRune.gameObject.SetActive(isHoleOpne && existRune);
            m_MultiPropertyEffect.StopImediatly();
            if (existRune)
            {
                var config = ItemConfig.Get(runeItem.id);
                m_Icon.SetSprite(config.IconKey);
                m_Level.text = Language.Get("Z1024", runeItem.level);
                m_Level.color = UIHelper.GetUIColor(config.ItemColor);
                if (model.IsMultiPropertyRune(runeItem.id))
                {
                    m_MultiPropertyEffect.Play();
                }
            }
        }
        void DisplaySelect()
        {
            m_ContainerSelect.gameObject.SetActive(model.selectHole == hole);
        }
        private void OnOpenNewHole(int _hole)
        {
            if (hole == _hole && hole == model.specialHole)
            {
                coroutine = StartCoroutine(Co_DisplayHole());
            }
        }
        private void OnRuneHoleRefresh()
        {
            if (hole == model.specialHole && model.unlockingSpecialHole)
            {
                return;
            }
            DisplayBase();
        }
        IEnumerator Co_DisplayHole()
        {
            yield return WaitingForSecondConst.WaitMS800;
            DisplayBase();
            coroutine = null;
        }
        private void OnSelectHoleRefresh()
        {
            DisplaySelect();
        }
        private void OnSelect()
        {
            if (model.IsRuneHoleOpen(hole, model.holeState) || hole == model.specialHole)
            {
                model.selectHole = hole;
            }
            else
            {
                RuneHoleCondition condition;
                if (model.TryGetRuneHoleCondition(hole, out condition))
                {
                    var config = RuneTowerFloorConfig.Get(condition.runeTowerFloor);
                    var tower = RuneTowerConfig.Get(config.TowerId);
                    SysNotifyMgr.Instance.ShowTip("RuneUnlock", StringUtility.Contact(tower.TowerName, config.FloorName));
                }
            }
        }
    }
}
System/Rune/RuneHoleBehaviour.cs.meta
File was renamed from System/Store/RuneStoreWin.cs.meta
@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: 85daa664b183120498a12cba52019f7d
timeCreated: 1505701787
guid: 6be32b223c0045846b34b922d405569e
timeCreated: 1552715451
licenseType: Pro
MonoImporter:
  serializedVersion: 2
System/Rune/RuneModel.cs
@@ -1,398 +1,794 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using UnityEngine;
namespace Snxxz.UI
{
    [XLua.LuaCallCSharp]
    public class RuneModel : Model, IBeforePlayerDataInitialize,IPlayerLoginOk
    [XLua.Hotfix]
    public class RuneModel : Model, IBeforePlayerDataInitialize, IPlayerLoginOk
    {
        RuneComposeModel m_RuneComposeModel;
        RuneComposeModel runeComposeModel {
            get {
                return m_RuneComposeModel ?? (m_RuneComposeModel = ModelCenter.Instance.GetModel<RuneComposeModel>());
            }
        }
        Dictionary<int, RuneItem> m_RuneHoleItems = new Dictionary<int, RuneItem>();
        Dictionary<int, PropertyCompute> m_PropertyComputeDict = new Dictionary<int, PropertyCompute>();
        Dictionary<int, RuneHoleCondition> m_RuneHoleConditions = new Dictionary<int, RuneHoleCondition>();
        Dictionary<int, RuneHoleRedpoint> m_RuneHoleRedpoints = new Dictionary<int, RuneHoleRedpoint>();
        Dictionary<int, List<int>> m_RunePropertys = new Dictionary<int, List<int>>();
        Dictionary<int, float> levelUpFormulaCostDict = new Dictionary<int, float>();
        Dictionary<int, float> levelUpQualityCostModulus;
        Dictionary<int, int> m_QualityMaxLevels;
        Dictionary<int, int> m_MultiPropertyRuneInlayDict;
        List<int> m_MultiPropertyRunes = new List<int>();
        bool playerLevelRefresh = false;
        int[] specialHoleRemindLevels = null;
        public override void Init()
        string levelUpCostFormula = string.Empty;
        float levelUpMultiPropertyModulus = 1f;
        public uint holeState { get; private set; }
        public bool serverInited { get; private set; }
        public int specialHole { get; private set; }
        public int passRuneTowerFloor { get; private set; }
        public bool unlockingSpecialHole { get; set; }
        public readonly Redpoint baseRedpoint = new Redpoint(1, 108);
        public readonly Redpoint redpoint = new Redpoint(108, RUNE_REDPOINT_BASE);
        public readonly Redpoint specialHoleRedpoint = new Redpoint(RUNE_REDPOINT_BASE, redpointIndex++);
        int m_SelectHole = 0;
        public int selectHole
        {
            ParseConfig();
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
            get { return m_SelectHole; }
            set
            {
                Redpoint redpoint = new Redpoint(10801, 1080101 + i);
                runeHoleRedpoints.Add(redpoint);
                redpoint.state = RedPointState.None;
            }
            FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
            PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefreshInfoEvent;
            StageLoad.Instance.onStageLoadFinish += OnStageLoadFinish;
            GlobalTimeEvent.Instance.secondEvent += PerSecond;
        }
        private void PerSecond()
        {
            if (serverInited)
            {
                if (playerLevelRefresh)
                if (m_SelectHole != value)
                {
                    UpdateSpecialHoleRedpoint();
                    playerLevelRefresh = false;
                    m_SelectHole = value;
                    if (onSelectHoleRefresh != null)
                    {
                        onSelectHoleRefresh();
                    }
                }
            }
        }
        private void OnFuncStateChangeEvent(int func)
        {
            if (func == (int)FuncOpenEnum.Rune)
            {
                UpdateRedpoint();
                UpdateBreakRedpoint();
            }
        }
        public const int RUNE_TYPE = 30;
        public const int RUNE_CREAMTYPE = 31;
        public const int RUNE_HOLE_COUNT = 9;
        public const int RUNE_REDPOINT_BASE = 10801;
        public override void UnInit()
        public static int redpointIndex = 1080100;
        public event Action onRuneHoleRefresh;
        public event Action<int> onOpenNewHole;
        public event Action onSelectHoleRefresh;
        public event Action onRuneTowerRefresh;
        public event Action onJumpToCompose;
        static StringBuilder sb = new StringBuilder();
        VirtualPackModel virtualPackModel { get { return ModelCenter.Instance.GetModel<VirtualPackModel>(); } }
        public override void Init()
        {
            ParseConfig();
            virtualPackModel.virtualPackRefresh += VirtualPackRefresh;
            FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
            PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefreshEvent;
        }
        public void OnBeforePlayerDataInitialize()
        {
            ClearRuneData();
            m_RuneHoleItems.Clear();
            serverInited = false;
            playerLevelRefresh = false;
        }
        private void OnStageLoadFinish()
        {
            if (!(StageLoad.Instance.currentStage is DungeonStage))
            {
                specialItemColorMark = false;
            }
        }
        public void OnPlayerLoginOk()
        {
            serverInited = true;
            UpdateSpecialHoleRedpoint();
            RefreshRedpoint();
            RefreshSpecialHoleRedpoint();
        }
        #region 配置
        public const int RUNE_TYPE = 30;
        public const int RUNE_CREAMTYPE = 31;
        public const int RUNE_HOLE_COUNT = 9;
        public Dictionary<int, Dictionary<int, int>> runeBasePropretyDict = new Dictionary<int, Dictionary<int, int>>();
        public Dictionary<int, Dictionary<int, float>> runeAttrDic = new Dictionary<int, Dictionary<int, float>>();
        public Dictionary<int, float> runeAttrAdditionDic = new Dictionary<int, float>();
        public Dictionary<int, float> runeExpDic = new Dictionary<int, float>();
        public Dictionary<int, float> runeEliteAdditonDic = new Dictionary<int, float>();
        Dictionary<int, int> runeQualityMaxLevel;
        public int[] runeUnlockArray { get; private set; }
        public float runeExpAddition { get; private set; }
        public string runeExpFormula { get; private set; }
        public int runePackMaxNum { get; private set; }
        public Dictionary<int, int> doublePropRuneInlayDict { get; private set; }
        public Dictionary<int,SpecialRuneHoleCondition> specialHoles = new Dictionary<int, SpecialRuneHoleCondition>();
        int[] specialRedLevels = null;
        private void ParseConfig()
        public override void UnInit()
        {
            virtualPackModel.virtualPackRefresh -= VirtualPackRefresh;
            FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
            PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefreshEvent;
        }
            System.Threading.ThreadPool.QueueUserWorkItem(
                (object aaa) =>
        void ParseConfig()
        {
            List<int> runeTypes = new List<int>();
            var configs = RuneConfig.GetValues();
            foreach (var config in configs)
            {
                for (int i = 0; i < config.AttrType.Length; i++)
                {
                    foreach (var key in FuncConfigConfig.m_RuneAttrCfgs.Keys)
                    if (!runeTypes.Contains(config.AttrType[i]))
                    {
                        runeAttrDic.Add(key, ConfigParse.GetDic<int, float>(FuncConfigConfig.m_RuneAttrCfgs[key].Numerical2));
                        runeAttrAdditionDic.Add(key, float.Parse(FuncConfigConfig.m_RuneAttrCfgs[key].Numerical3));
                        runeBasePropretyDict.Add(key, ConfigParse.GetDic<int, int>(FuncConfigConfig.m_RuneAttrCfgs[key].Numerical4));
                        runeTypes.Add(config.AttrType[i]);
                    }
                    runeExpDic = ConfigParse.GetDic<int, float>(FuncConfigConfig.GetRuneNeedExpFormula().Numerical2);
                    runeExpAddition = float.Parse(FuncConfigConfig.GetRuneNeedExpFormula().Numerical3);
                    runeEliteAdditonDic = ConfigParse.GetDic<int, float>(FuncConfigConfig.GetRuneNeedExpFormula().Numerical4);
                    runeExpFormula = FuncConfigConfig.GetRuneNeedExpFormula().Numerical1;
                    FuncConfigConfig config = FuncConfigConfig.Get("RuneUnlock");
                    if (config != null)
                    {
                        runeUnlockArray = ConfigParse.GetMultipleStr<int>(config.Numerical1);
                        var costDict = ConfigParse.GetDic<int, int>(config.Numerical2);
                        var levelDict = ConfigParse.GetDic<int, int>(config.Numerical3);
                        foreach (var _hole in costDict.Keys)
                        {
                            specialHoles.Add(_hole, new SpecialRuneHoleCondition()
                            {
                                cost = costDict[_hole],
                                level = levelDict.ContainsKey(_hole) ? levelDict[_hole] : 0,
                            });
                        }
                    }
                    config = FuncConfigConfig.Get("RunePackageNum");
                    runePackMaxNum = int.Parse(config.Numerical1);
                    config = FuncConfigConfig.Get("RuneMaxLV");
                    runeQualityMaxLevel = ConfigParse.GetDic<int, int>(config.Numerical1);
                    var maxlevel = runeQualityMaxLevel != null ? runeQualityMaxLevel.Values.Last() : 0;
                    for (int i = 1; i < maxlevel; i++)
                    {
                        Equation.Instance.Clear();
                        Equation.Instance.AddKeyValue(replaceValStr, i + 1);
                        var _result = Equation.Instance.Eval<float>(runeExpFormula);
                        runeExpResultDict.Add(i + 1, _result);
                    }
                    config = FuncConfigConfig.Get("RuneDoubleInlayCnt");
                    doublePropRuneInlayDict = ConfigParse.GetDic<int, int>(config.Numerical1);
                    config = FuncConfigConfig.Get("RuneSpecialRedLevel");
                    specialRedLevels = ConfigParse.GetMultipleStr<int>(config.Numerical1);
                }
                );
                if (config.AttrType.Length > 1)
                {
                    m_MultiPropertyRunes.Add(config.ID);
                }
                m_RunePropertys.Add(config.ID, new List<int>(config.AttrType));
            }
            foreach (var propertyType in runeTypes)
            {
                var key = StringUtility.Contact("RuneAttr", propertyType);
                if (FuncConfigConfig.Has(key))
                {
                    m_PropertyComputeDict.Add(propertyType, new PropertyCompute(FuncConfigConfig.Get(key)));
                }
            }
            var maxLevelConfig = FuncConfigConfig.Get("RuneMaxLV");
            m_QualityMaxLevels = ConfigParse.GetDic<int, int>(maxLevelConfig.Numerical1);
            var maxLevel = 0;
            foreach (var level in m_QualityMaxLevels.Values)
            {
                if (level > maxLevel)
                {
                    maxLevel = level;
                }
            }
            var levelUpConfig = FuncConfigConfig.Get("RuneExp");
            levelUpCostFormula = levelUpConfig.Numerical1;
            levelUpQualityCostModulus = ConfigParse.GetDic<int, float>(levelUpConfig.Numerical2);
            levelUpMultiPropertyModulus = float.Parse(levelUpConfig.Numerical3);
            {
                var funcConfig = FuncConfigConfig.Get("RuneDoubleInlayCnt");
                m_MultiPropertyRuneInlayDict = ConfigParse.GetDic<int, int>(funcConfig.Numerical1);
                funcConfig = FuncConfigConfig.Get("RuneSpecialRedLevel");
                specialHoleRemindLevels = ConfigParse.GetMultipleStr<int>(funcConfig.Numerical1);
            }
            System.Threading.ThreadPool.QueueUserWorkItem((object _object) =>
            {
                foreach (var propertyCompute in m_PropertyComputeDict.Values)
                {
                    propertyCompute.CacheFormulaResult(maxLevel);
                }
            });
            {
                var funcConfig = FuncConfigConfig.Get("RuneUnlock");
                var towerArray = ConfigParse.GetMultipleStr<int>(funcConfig.Numerical1);
                var diamondDict = ConfigParse.GetDic<int, int>(funcConfig.Numerical2);
                var playerLevelDict = ConfigParse.GetDic<int, int>(funcConfig.Numerical3);
                for (int i = 0; i < RUNE_HOLE_COUNT; i++)
                {
                    m_RuneHoleConditions.Add(i, new RuneHoleCondition()
                    {
                        runeTowerFloor = i < towerArray.Length ? towerArray[i] : 0,
                        diamond = diamondDict.ContainsKey(i) ? diamondDict[i] : 0,
                        playerLevel = playerLevelDict.ContainsKey(i) ? playerLevelDict[i] : 0,
                    });
                }
                specialHole = 8;
            }
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
            {
                m_RuneHoleRedpoints.Add(i, new RuneHoleRedpoint(RUNE_REDPOINT_BASE));
            }
        }
        private static StringBuilder _textBuilder = new StringBuilder();
        static readonly string replaceValStr = "level";
        bool serverInited = false;
        private void PlayerDataRefreshInfoEvent(PlayerDataType refreshType)
        public bool TryGetRuneHoleItem(int hole, out RuneItem runeItem)
        {
            if (refreshType == PlayerDataType.LV)
            {
                playerLevelRefresh = true;
            }
            return m_RuneHoleItems.TryGetValue(hole, out runeItem);
        }
        public int GetRuneMaxLevel(int _itemColor)
        public bool TryGetRuneHoleCondition(int hole, out RuneHoleCondition condition)
        {
            if (runeQualityMaxLevel != null && runeQualityMaxLevel.ContainsKey(_itemColor))
            return m_RuneHoleConditions.TryGetValue(hole, out condition);
        }
        public bool TryGetRunePropertys(int id, out List<int> propertys)
        {
            return m_RunePropertys.TryGetValue(id, out propertys);
        }
        public int TryGetComposeRuneCount(int id, out RuneItem item)
        {
            var count = 0;
            item = null;
            List<int> items = null;
            if (virtualPackModel.TryGetItems(PackType.RunePack, out items))
            {
                return runeQualityMaxLevel[_itemColor];
                foreach (var packIndex in items)
                {
                    RuneItem _item;
                    if (virtualPackModel.TryGetItem(PackType.RunePack, packIndex, out _item)
                        && _item.id == id)
                    {
                        if (item == null || _item.level >= item.level)
                        {
                            item = _item;
                        }
                        count++;
                    }
                }
            }
            if (runeQualityMaxLevel != null)
            foreach (var _item in m_RuneHoleItems.Values)
            {
                return runeQualityMaxLevel.Values.Last();
                if (_item.id == id)
                {
                    if (item == null || _item.level >= item.level)
                    {
                        item = _item;
                    }
                    count++;
                    break;
                }
            }
            return count;
        }
        public bool TryEquipRuneByColor(int itemColor, out int hole)
        {
            if (!ExistEmptyHole(out hole))
            {
                return false;
            }
            virtualPackModel.GetItemIndexs(PackType.RunePack, ref cacheItemIndexs);
            foreach (var index in cacheItemIndexs)
            {
                RuneItem item;
                if (virtualPackModel.TryGetItem(PackType.RunePack, index, out item))
                {
                    var config = ItemConfig.Get(item.id);
                    if (config.ItemColor < itemColor)
                    {
                        continue;
                    }
                    if (SatisfyInlayHole(item, hole))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        public bool TryGetRedpoint(int hole, out RuneHoleRedpoint redpoint)
        {
            return m_RuneHoleRedpoints.TryGetValue(hole, out redpoint);
        }
        public int GetPropertyValue(int id, int level, int type)
        {
            if (m_PropertyComputeDict.ContainsKey(type))
            {
                return m_PropertyComputeDict[type].GetPropertyValue(id, level);
            }
            return 0;
        }
        public int GetRuneMaxLevelByItem(int _itemId)
        public string GetRunePropertyDescription(int id, int level)
        {
            var config = ItemConfig.Get(_itemId);
            return config == null ? 0 : GetRuneMaxLevel(config.ItemColor);
            sb.Length = 0;
            var config = RuneConfig.Get(id);
            for (int i = 0; i < config.AttrType.Length; i++)
            {
                var property = config.AttrType[i];
                var propertyConfig = PlayerPropertyConfig.Get(property);
                var propertyValue = GetPropertyValue(id, level, property);
                var decimalCount = UIHelper.GetPropertyDecimalCount(property);
                var label = StringUtility.Contact(propertyConfig.Name, "+",
                    PlayerPropertyConfig.GetValueDescription(property, propertyValue, decimalCount, false));
                sb.Append(label);
                if (i < config.AttrType.Length - 1)
                {
                    sb.Append('\n');
                }
            }
            return sb.ToString();
        }
        public string GetRuneAttrStr(int id, int level)
        public int GetLevelUpRequireRuneEssence(int id, int level)
        {
            _textBuilder.Length = 0;
            RuneConfig _tagRuneModel = RuneConfig.Get(id);
            int[] runeTypes = _tagRuneModel.AttrType;
            int i = 0;
            for (i = 0; i < runeTypes.Length; i++)
            float requireEssence = 0;
            var itemConfig = ItemConfig.Get(id);
            if (!IsRuneMaxLevel(id, level))
            {
                PlayerPropertyConfig playerPro = PlayerPropertyConfig.Get(runeTypes[i]);
                string _str = StringUtility.Contact(playerPro.Name, "+",
                    UIHelper.ReplacePercentage(GetRuneAttrVal(id, level, runeTypes[i]), playerPro.ISPercentage,
                    UIHelper.GetPropertyDecimalCount(playerPro.ID)),
                    playerPro.ISPercentage == 1 ? "%" : string.Empty, i == runeTypes.Length - 1 ? string.Empty : "\n");
                _textBuilder.Append(_str);
            }
            return _textBuilder.ToString();
        }
        public Dictionary<int, Dictionary<int, float>> runeAttrResultDict = new Dictionary<int, Dictionary<int, float>>();
        public int GetRuneAttrVal(int id, int level, int type)
        {
            ItemConfig _tagChinModel = ItemConfig.Get(id);
            RuneConfig _tagRuneModel = RuneConfig.Get(id);
            float runeValue = 0;
            if (_tagChinModel != null && _tagRuneModel != null)
            {
                float params1 = 0;
                Dictionary<int, float> _dict = null;
                if (runeAttrResultDict.TryGetValue(type, out _dict))
                var _result = 0f;
                if (levelUpFormulaCostDict.ContainsKey(level + 1))
                {
                    if (_dict.ContainsKey(level))
                    {
                        params1 = _dict[level];
                    }
                }
                else
                {
                    _dict = new Dictionary<int, float>();
                    runeAttrResultDict.Add(type, _dict);
                }
                if (params1 == 0 && !_dict.ContainsKey(level))
                {
                    Equation.Instance.Clear();
                    Equation.Instance.AddKeyValue(replaceValStr, level);
                    FuncConfigConfig funcRune = FuncConfigConfig.GetRuneAttrFormula(type);
                    params1 = Equation.Instance.Eval<float>(funcRune.Numerical1);
                    _dict.Add(level, params1);
                }
                int[] runeTypes = _tagRuneModel.AttrType;
                float params2 = runeAttrDic[type][_tagChinModel.ItemColor];
                var baseValue = 0;
                if (runeBasePropretyDict.ContainsKey(type))
                {
                    var dict = runeBasePropretyDict[type];
                    if (dict.ContainsKey(_tagChinModel.ItemColor))
                    {
                        baseValue = dict[_tagChinModel.ItemColor];
                    }
                }
                if (runeTypes.Length > 1)
                {
                    float coe = runeAttrAdditionDic[type];
                    coe = coe == 0 ? 1 : coe;
                    runeValue = (params1 * params2 + baseValue) * coe;
                }
                else
                {
                    runeValue = params1 * params2 + baseValue;
                }
            }
            return Mathf.FloorToInt(runeValue);
        }
        private Dictionary<int, float> runeExpResultDict = new Dictionary<int, float>();
        public int GetRuneNeedExp(int id, int level)
        {
            float _levelUpExp = 0;
            ItemConfig _tagChinModel = ItemConfig.Get(id);
            if (level < GetRuneMaxLevel(_tagChinModel.ItemColor))
            {
                float _result = 0;
                if (runeExpResultDict.ContainsKey(level + 1))
                {
                    _result = runeExpResultDict[level + 1];
                    _result = levelUpFormulaCostDict[level + 1];
                }
                else
                {
                    Equation.Instance.Clear();
                    Equation.Instance.AddKeyValue(replaceValStr, level + 1);
                    _result = Equation.Instance.Eval<float>(runeExpFormula);
                    runeExpResultDict.Add(level + 1, _result);
                    Equation.Instance.AddKeyValue("level", level + 1);
                    _result = Equation.Instance.Eval<float>(levelUpCostFormula);
                    levelUpFormulaCostDict.Add(level + 1, _result);
                }
                RuneConfig cfg = RuneConfig.Get(id);
                if (cfg.AttrType.Length > 1)
                if (IsMultiPropertyRune(id))
                {
                    _levelUpExp = _result * runeExpDic[_tagChinModel.ItemColor] * runeExpAddition;
                    requireEssence = _result * levelUpQualityCostModulus[itemConfig.ItemColor]
                        * levelUpMultiPropertyModulus;
                }
                else
                {
                    _levelUpExp = _result * runeExpDic[_tagChinModel.ItemColor];
                    requireEssence = _result * levelUpQualityCostModulus[itemConfig.ItemColor];
                }
            }
            return Mathf.FloorToInt(_levelUpExp);
            return Mathf.FloorToInt(requireEssence);
        }
        public float GetRuneSoulBreakExp(RuneData _rune)
        public int GetMultiPropertyInlayCount(int tower = 0)
        {
            ItemConfig _itemCfg = ItemConfig.Get(_rune.id);
            var _treasureSoul = ModelCenter.Instance.GetModel<TreasureSoulModel>();
            var _upper = (float)_treasureSoul.GetTreasureSoulValue((int)TreasurePrivilege.RuneBreakExpAdd) / 10000;
            if (_itemCfg.Type == RUNE_CREAMTYPE)
            if (tower != 0 && m_MultiPropertyRuneInlayDict.ContainsKey(tower))
            {
                return _itemCfg.EffectValueA1 * _upper;
                return m_MultiPropertyRuneInlayDict[tower];
            }
            else
            var count = 0;
            foreach (var _key in m_MultiPropertyRuneInlayDict.Keys)
            {
                return runeEliteAdditonDic[_itemCfg.ItemColor] * _upper;
            }
        }
        public float GetRuneBreakExp(RuneData _rune, bool _compose = false)
        {
            float _exp = 0;
            ItemConfig _itemCfg = ItemConfig.Get(_rune.id);
            var _treasureSoul = ModelCenter.Instance.GetModel<TreasureSoulModel>();
            var _upper = (float)_treasureSoul.GetTreasureSoulValue((int)TreasurePrivilege.RuneBreakExpAdd) / 10000;
            if (_itemCfg.Type == RUNE_CREAMTYPE)
            {
                return _itemCfg.EffectValueA1 + _itemCfg.EffectValueA1 * _upper;
            }
            for (int i = 1; i <= _rune.lv; i++)
            {
                if (i == 1 && !_compose)
                if (passRuneTowerFloor >= _key)
                {
                    _exp += runeEliteAdditonDic[_itemCfg.ItemColor] + runeEliteAdditonDic[_itemCfg.ItemColor] * _upper;
                    count = m_MultiPropertyRuneInlayDict[_key];
                }
                else
                {
                    _exp += GetRuneNeedExp(_rune.id, i - 1);
                    break;
                }
            }
            return _exp;
            return count;
        }
        public int GetRuneLevelByExp(int id, float _exp)
        public int GetMultiPropertyHoleCount()
        {
            float _totalExp = 0;
            var maxlevel = runeQualityMaxLevel != null ? runeQualityMaxLevel.Values.Last() : 0;
            var count = 0;
            foreach (var item in m_RuneHoleItems.Values)
            {
                if (IsMultiPropertyRune(item.id))
                {
                    count ++;
                }
            }
            return count;
        }
        public int GetRuneLevelBySplinters(int id, float essence)
        {
            var totalEssence = 0f;
            var config = ItemConfig.Get(id);
            var maxlevel = 0;
            if (m_QualityMaxLevels.ContainsKey(config.ItemColor))
            {
                maxlevel = m_QualityMaxLevels[config.ItemColor];
            }
            for (int i = 1; i < maxlevel; i++)
            {
                _totalExp += GetRuneNeedExp(id, i);
                if (_totalExp > _exp)
                totalEssence += GetLevelUpRequireRuneEssence(id, i);
                if (totalEssence > essence)
                {
                    return i;
                }
            }
            return maxlevel;
        }
        #endregion
        public const int RUNE_REDPOINT_INTERVAL = 100;
        private Redpoint runeRedpoint = new Redpoint(1, 108);
        private Redpoint m_RuneMosaicRedpoint = new Redpoint(108, 10801);
        public Redpoint runeLevelUpRedpoint = new Redpoint(1080120);
        public Redpoint runeReplaceRedpoint = new Redpoint(1080130);
        private List<Redpoint> runeHoleRedpoints = new List<Redpoint>();
        public Redpoint runeMosaicRedpoint { get { return m_RuneMosaicRedpoint; } }
        public Redpoint specialRuneRemindRedpoint = new Redpoint(10801, 1080140);
        public Redpoint GetRedpoint(int _hole)
        public int GetRuneInlayCount()
        {
            return runeHoleRedpoints[_hole];
            return m_RuneHoleItems.Count;
        }
        void UpdateSpecialHoleRedpoint()
        public int GetRuneTotalCount(int itemType = 0)
        {
            specialRuneRemindRedpoint.state = RedPointState.None;
            if (DayRemind.Instance.GetDayRemind(DayRemind.RUNE_SPECIAL_HOLE))
            var count = 0;
            virtualPackModel.GetItemIndexs(PackType.RunePack, ref cacheItemIndexs);
            foreach (var index in cacheItemIndexs)
            {
                return;
            }
            foreach (var hole in specialHoles.Keys)
            {
                if (IsRuneHoleOpen(hole))
                RuneItem item;
                if (virtualPackModel.TryGetItem(PackType.RunePack, index, out item))
                {
                    continue;
                    if (itemType == 0 || item.itemType == itemType)
                    {
                        count++;
                    }
                }
                if (PlayerDatas.Instance.baseData.LV >= specialHoles[hole].level
                    && PlayerDatas.Instance.baseData.LV >= specialRedLevels[0]
                    && PlayerDatas.Instance.baseData.LV < specialRedLevels[1])
            }
            return count;
        }
        public List<int> GetUnlockRunes()
        {
            List<int> ids = new List<int>();
            var configs = RuneConfig.GetValues();
            foreach (var config in configs)
            {
                if (passRuneTowerFloor >= config.TowerID
                    && config.AttrType.Length == 1
                    && ids.Contains(config.ID))
                {
                    specialRuneRemindRedpoint.state = RedPointState.Simple;
                    ids.Add(config.ID);
                }
            }
            return ids;
        }
        public bool IsRuneHoleOpen(int hole, uint state)
        {
            return MathUtility.GetBitValue(state, (ushort)hole);
        }
        public bool IsMultiPropertyRune(int id)
        {
            return m_MultiPropertyRunes.Contains(id);
        }
        public bool IsRuneMaxLevel(int id, int level)
        {
            var config = ItemConfig.Get(id);
            if (config != null)
            {
                if (m_QualityMaxLevels.ContainsKey(config.ItemColor))
                {
                    return level >= m_QualityMaxLevels[config.ItemColor];
                }
            }
            return true;
        }
        public bool IsUnlockAllMultiPropertyInlay(out int tower)
        {
            tower = 0;
            foreach (var _key in m_MultiPropertyRuneInlayDict.Keys)
            {
                if (passRuneTowerFloor < _key)
                {
                    tower = _key;
                    break;
                }
            }
            return tower == 0;
        }
        public void SetDayRemind()
        public bool IsSameWithOtherRuneHole(int id, int hole)
        {
            if (specialRuneRemindRedpoint.state == RedPointState.Simple)
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
            {
                DayRemind.Instance.SetDayRemind(DayRemind.RUNE_SPECIAL_HOLE, true);
                UpdateSpecialHoleRedpoint();
                if (i == hole)
                {
                    continue;
                }
                if (IsSameWithRuneHole(id, i))
                {
                    return true;
                }
            }
            return false;
        }
        public bool IsSameWithRuneHole(int id, int hole)
        {
            RuneItem item;
            if (TryGetRuneHoleItem(hole, out item))
            {
                return item.IsExistSameProperty(id);
            }
            return false;
        }
        public bool IsBetterRuneWithHole(int id, int hole)
        {
            var itemConfig = ItemConfig.Get(id);
            if (itemConfig == null || itemConfig.Type == RUNE_CREAMTYPE)
            {
                return false;
            }
            RuneItem item = null;
            if (!TryGetRuneHoleItem(hole, out item))
            {
                return false;
            }
            if (!item.IsExistSameProperty(id))
            {
                return false;
            }
            var itemHoleConfig = ItemConfig.Get(item.id);
            return itemConfig.ItemColor > itemHoleConfig.ItemColor;
        }
        public bool SatisfyLevelUpHole(int hole)
        {
            if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Rune))
            {
                return false;
            }
            RuneItem item;
            if (TryGetRuneHoleItem(hole, out item))
            {
                var essence = PlayerDatas.Instance.extersion.runeEssence;
                if (!IsRuneMaxLevel(item.id, item.level)
                    && essence >= GetLevelUpRequireRuneEssence(item.id, item.level))
                {
                    return true;
                }
            }
            return false;
        }
        public bool SatisfyInlayHole(int hole)
        {
            if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Rune))
            {
                return false;
            }
            if (!IsRuneHoleOpen(hole, holeState) || m_RuneHoleItems.ContainsKey(hole))
            {
                return false;
            }
            virtualPackModel.GetItemIndexs(PackType.RunePack, ref cacheItemIndexs);
            foreach (var index in cacheItemIndexs)
            {
                RuneItem item;
                if (virtualPackModel.TryGetItem(PackType.RunePack, index, out item))
                {
                    if (SatisfyInlayHole(item, hole))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        public bool SatisfyInlayHole(RuneItem item, int hole)
        {
            if (item.itemType == RUNE_CREAMTYPE
                        || IsSameWithOtherRuneHole(item.id, hole))
            {
                return false;
            }
            if (IsMultiPropertyRune(item.id)
                && GetMultiPropertyInlayCount() <= GetMultiPropertyHoleCount())
            {
                return false;
            }
            return true;
        }
        public bool SatisfyInlayBetterHole(int hole)
        {
            if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Rune))
            {
                return false;
            }
            if (!IsRuneHoleOpen(hole, holeState) || !m_RuneHoleItems.ContainsKey(hole))
            {
                return false;
            }
            var runeHoleItem = m_RuneHoleItems[hole];
            var isDoubleRuneHole = IsMultiPropertyRune(runeHoleItem.id);
            var multiPropertyHoleCount = GetMultiPropertyHoleCount();
            var multiPropertyLimitCount = GetMultiPropertyInlayCount();
            virtualPackModel.GetItemIndexs(PackType.RunePack, ref cacheItemIndexs);
            foreach (var index in cacheItemIndexs)
            {
                RuneItem item;
                if (virtualPackModel.TryGetItem(PackType.RunePack, index, out item))
                {
                    if (!IsBetterRuneWithHole(item.id, hole))
                    {
                        continue;
                    }
                    var isDoubleRune = IsMultiPropertyRune(item.id);
                    if (!isDoubleRuneHole && isDoubleRune)
                    {
                        if (multiPropertyHoleCount >= multiPropertyLimitCount)
                        {
                            continue;
                        }
                    }
                    return true;
                }
            }
            return false;
        }
        public bool ExistEmptyHole(out int hole)
        {
            hole = 0;
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
            {
                if (!m_RuneHoleItems.ContainsKey(i))
                {
                    hole = i;
                    return true;
                }
            }
            return false;
        }
        public void SelectRunePackItem(RuneItem item, int hole)
        {
            RuneItem holeItem = null;
            TryGetRuneHoleItem(hole, out holeItem);
            bool switchOtherSameHole = false;
            List<int> sameHoles = new List<int>();
            if (holeItem == null || IsMultiPropertyRune(holeItem.id)
                || !IsMultiPropertyRune(item.id))
            {
                if (IsSameWithOtherRuneHole(item.id, hole))
                {
                    ServerTipDetails.DisplayNormalTip(Language.Get("L1078"));
                    return;
                }
            }
            else
            {
                for (int i = 0; i < RUNE_HOLE_COUNT; i++)
                {
                    if (IsSameWithRuneHole(item.id, i))
                    {
                        sameHoles.Add(i);
                    }
                }
                if (sameHoles.Count > 0 && !sameHoles.Contains(hole))
                {
                    ServerTipDetails.DisplayNormalTip(Language.Get("L1078"));
                    return;
                }
                if (sameHoles.Count > 1)
                {
                    switchOtherSameHole = true;
                }
            }
            var multiPropertyLimitCount = GetMultiPropertyInlayCount();
            if (IsMultiPropertyRune(item.id) && multiPropertyLimitCount <= GetMultiPropertyHoleCount()
                && (holeItem == null || !IsMultiPropertyRune(holeItem.id)))
            {
                SysNotifyMgr.Instance.ShowTip("RuneGridUnEnough", multiPropertyLimitCount);
                return;
            }
            if (switchOtherSameHole)
            {
                var otherSameHole = sameHoles[0] == hole ? sameHoles[1] : sameHoles[0];
                RuneItem sameHoleItem = null;
                if (TryGetRuneHoleItem(otherSameHole, out sameHoleItem))
                {
                    ConfirmCancel.ShowPopConfirm(Language.Get("Mail101"), Language.Get("SwitchDoublePropertyRune"),(bool isOk) =>
                    {
                        if (isOk)
                        {
                            SwitchRune((int)PackType.InterimPack, otherSameHole, (int)PackType.RunePack, 0);
                            SwitchRune((int)PackType.RunePack, item.index, (int)PackType.InterimPack, hole);
                            WindowCenter.Instance.Close<RunePackWin>();
                        }
                    });
                }
            }
            else
            {
                SwitchRune((int)PackType.RunePack, item.index, (int)PackType.InterimPack, hole);
                WindowCenter.Instance.Close<RunePackWin>();
            }
        }
        void SwitchRune(int srcpackType, int scrIndex, int destpackType, int destIndex)
        {
            C073D_tagCPackItemExchange pak = new C073D_tagCPackItemExchange();
            pak.SrcBackpack = (byte)srcpackType;
            pak.SrcIndex = (ushort)scrIndex;
            pak.DesBackPack = (byte)destpackType;
            pak.DestIndex = (ushort)destIndex;
            GameNetSystem.Instance.SendInfo(pak);
        }
        public void ReceivePackage(HA31F_tagMCRuneInfo package)
        {
            var preholeState = holeState;
            holeState = package.RuneHoleOpenState;
            for (int i = 0; i < package.Count; i++)
            {
                if (package.RuneDataList[i] != 0)
                {
                    RuneItem runeItem = null;
                    if (!m_RuneHoleItems.TryGetValue(i, out runeItem))
                    {
                        runeItem = new RuneItem();
                        m_RuneHoleItems.Add(i, runeItem);
                    }
                    runeItem.ParseHoleItem(i, package.RuneDataList[i]);
                }
                else
                {
                    if (m_RuneHoleItems.ContainsKey(i))
                    {
                        m_RuneHoleItems[i] = null;
                        m_RuneHoleItems.Remove(i);
                    }
                }
            }
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
            {
                if (!serverInited)
                {
                    break;
                }
                var preOpen = IsRuneHoleOpen(i, preholeState);
                var nowOpen = IsRuneHoleOpen(i, holeState);
                if (!preOpen && nowOpen)
                {
                    if (onOpenNewHole != null)
                    {
                        onOpenNewHole(i);
                    }
                }
            }
            if (onRuneHoleRefresh != null)
            {
                onRuneHoleRefresh();
            }
            RefreshRedpoint();
            RefreshSpecialHoleRedpoint();
        }
        public void ReceivePackage(HA3BA_tagMCTrialTowerInfo package)
        {
            passRuneTowerFloor = (int)package.PassLV;
            if (onRuneTowerRefresh != null)
            {
                onRuneTowerRefresh();
            }
        }
        private void VirtualPackRefresh(PackType packType)
        {
            if (packType == PackType.RunePack)
            {
                RefreshRedpoint();
            }
        }
        private void PlayerDataRefreshEvent(PlayerDataType dataType)
        {
            if (dataType == PlayerDataType.RuneSplinters)
            {
                RefreshRedpoint();
            }
            if (dataType == PlayerDataType.LV)
            {
                RefreshSpecialHoleRedpoint();
            }
        }
        private void OnFuncStateChangeEvent(int id)
        {
            if (id == (int)FuncOpenEnum.Rune)
            {
                RefreshRedpoint();
            }
        }
        /// <summary>
        /// 新版符印红点
        ///1.有可操作的时候仅按优先级显示1个红点
        ///2.优先级:可镶嵌>可替换>可升级
        ///3.同时有可镶嵌,可替换,可升级的符印孔时,默认只显示1个红点在镶嵌孔上
@@ -402,539 +798,270 @@
        ///7.右下角操作按钮:可镶嵌时镶嵌按钮红点显示;替换和升级同时满足时,仅替换按钮显示红点;无镶嵌和替换时,升级按钮红点显示
        ///8.选中有红点的符印孔时,符印孔上的红点隐藏不显示
        /// </summary>
        List<int> runelevelUpSorts = new List<int>();
        public void UpdateRedpoint()
        List<int> cacheItemIndexs = new List<int>();
        List<int> levelUpSorts = new List<int>();
        void RefreshRedpoint()
        {
            for (int i = 0; i < runeHoleRedpoints.Count; i++)
            var levelUpHole = 100;
            var replaceHole = 100;
            if (FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Rune))
            {
                runeHoleRedpoints[i].state = RedPointState.None;
            }
            runeLevelUpRedpoint.state = RedPointState.None;
            runeReplaceRedpoint.state = RedPointState.None;
            if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Rune))
            {
                return;
            }
            var _holeCount = runeHoleRedpoints.Count;
            for (int i = 0; i < _holeCount; i++)
            {
                var _data = GetHoleRune(i);
                if (_data == null && CanMosaicRune(i))
                replaceHole = ExistEmptyHoleSatisfyInlay();
                if (replaceHole != 100)
                {
                    runeHoleRedpoints[i].state = RedPointState.Simple;
                    if (sltRuneHole == i)
                    {
                        runeReplaceRedpoint.state = RedPointState.Simple;
                    }
                    RefreshRedpoint(replaceHole, levelUpHole);
                    return;
                }
            }
            for (int i = 0; i < _holeCount; i++)
            {
                var _data = GetHoleRune(i);
                if (_data != null && CanEquipBetterRune(i))
                for (int i = 0; i < RUNE_HOLE_COUNT; i++)
                {
                    runeHoleRedpoints[i].state = RedPointState.Simple;
                    if (sltRuneHole == i)
                    if (SatisfyInlayBetterHole(i))
                    {
                        runeReplaceRedpoint.state = RedPointState.Simple;
                        replaceHole = i;
                        break;
                    }
                }
                if (replaceHole != 100)
                {
                    RefreshRedpoint(replaceHole, levelUpHole);
                    return;
                }
            }
            runelevelUpSorts.Clear();
            for (int i = 0; i < _holeCount; i++)
            {
                var _data = GetHoleRune(i);
                if (_data != null && RuneSplinters >= GetRuneNeedExp(_data.id, _data.lv)
                       && _data.lv < GetRuneMaxLevelByItem(_data.id))
                for (int i = 0; i < RUNE_HOLE_COUNT; i++)
                {
                    runelevelUpSorts.Add(i);
                    if (SatisfyLevelUpHole(i))
                    {
                        levelUpSorts.Add(i);
                    }
                }
                if (levelUpSorts.Count > 0)
                {
                    levelUpSorts.Sort(CompareLevelUp);
                    levelUpHole = levelUpSorts[0];
                }
            }
            if (runelevelUpSorts.Count > 0)
            {
                runelevelUpSorts.Sort(CompareLevelUp);
                runeHoleRedpoints[runelevelUpSorts[0]].state = RedPointState.Simple;
                if (sltRuneHole == runelevelUpSorts[0])
                {
                    runeLevelUpRedpoint.state = RedPointState.Simple;
                }
            }
            RefreshRedpoint(replaceHole, levelUpHole);
        }
        int CompareLevelUp(int x, int y)
        void RefreshRedpoint(int replaceHole, int levelUpHole)
        {
            var _data_x = GetHoleRune(x);
            var _data_y = GetHoleRune(y);
            if (_data_x.lv != _data_y.lv)
            {
                return _data_x.lv.CompareTo(_data_y.lv);
            }
            var _cost_x = GetRuneNeedExp(_data_x.id, _data_x.lv);
            var _cost_y = GetRuneNeedExp(_data_y.id, _data_y.lv);
            if (_cost_x != _cost_y)
            {
                return _cost_x.CompareTo(_cost_y);
            }
            return x.CompareTo(y);
        }
        private Redpoint m_ResolveRedpoint = new Redpoint(108, 10802);
        public void UpdateBreakRedpoint()
        {
            m_ResolveRedpoint.state = RedPointState.None;
            if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Rune))
            {
                return;
            }
            m_ResolveRedpoint.state = runePackData.Count >= runePackMaxNum && !IsEmptyHole() ? RedPointState.Simple : RedPointState.None;
        }
        public bool CanLevelUpRune(int _hole)
        {
            if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Rune))
            {
                return false;
            }
            RuneData runeData = GetHoleRune(_hole);
            if (runeData != null)
            {
                if (RuneSplinters > GetRuneNeedExp(runeData.id, runeData.lv)
                    && runeData.lv < GetRuneMaxLevelByItem(runeData.id))
                {
                    return true;
                }
            }
            return false;
        }
        public bool CanLevelUpRune(out int _hole)
        {
            _hole = 0;
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
            {
                if (CanLevelUpRune(i))
                {
                    _hole = i;
                    return true;
                }
                m_RuneHoleRedpoints[i].SetRedpoint(levelUpHole == i, replaceHole == i);
            }
            return false;
        }
        public bool CanMosaicRune(int _hole)
        int ExistEmptyHoleSatisfyInlay()
        {
            if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Rune))
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
            {
                return false;
            }
            RuneData runeData = GetHoleRune(_hole);
            if (runeData == null && IsRuneHoleOpen(_hole))
            {
                foreach (var rune in runePackData.Values)
                if (SatisfyInlayHole(i))
                {
                    ItemConfig _itemCfg = ItemConfig.Get(rune.id);
                    if (_itemCfg.Type == RUNE_CREAMTYPE)
                    return i;
                }
            }
            return 100;
        }
        int CompareLevelUp(int lhs, int rhs)
        {
            RuneItem lhsItem;
            RuneItem rhsItem;
            if (TryGetRuneHoleItem(lhs, out lhsItem)
                && TryGetRuneHoleItem(rhs, out rhsItem))
            {
                if (lhsItem.level != rhsItem.level)
                {
                    return lhsItem.level.CompareTo(rhsItem.level);
                }
                var _cost_x = GetLevelUpRequireRuneEssence(lhsItem.id, lhsItem.level);
                var _cost_y = GetLevelUpRequireRuneEssence(rhsItem.id, rhsItem.level);
                if (_cost_x != _cost_y)
                {
                    return _cost_x.CompareTo(_cost_y);
                }
            }
            return lhs.CompareTo(rhs);
        }
        public void SetDayRemind()
        {
            if (specialHoleRedpoint.state == RedPointState.Simple)
            {
                DayRemind.Instance.SetDayRemind(DayRemind.RUNE_SPECIAL_HOLE, true);
                RefreshSpecialHoleRedpoint();
            }
        }
        private void RefreshSpecialHoleRedpoint()
        {
            var requireRemind = false;
            if (FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Rune))
            {
                if (!DayRemind.Instance.GetDayRemind(DayRemind.RUNE_SPECIAL_HOLE))
                {
                    RuneHoleCondition condition;
                    if (IsRuneHoleOpen(specialHole, holeState)
                        && TryGetRuneHoleCondition(specialHole, out condition))
                    {
                        continue;
                    }
                    if (!IsSameInHoleRune(_itemCfg.ID, _hole))
                    {
                        if (runeComposeModel.m_RuneBothPropertys.Contains(rune.id)
                        && GetDoublePropLimitCount() <= GetCurrentDoublePropCount())
                        if (PlayerDatas.Instance.baseData.LV >= condition.playerLevel
                        && PlayerDatas.Instance.baseData.LV >= specialHoleRemindLevels[0]
                        && PlayerDatas.Instance.baseData.LV < specialHoleRemindLevels[1])
                        {
                            return false;
                            requireRemind = true;
                        }
                        return true;
                    }
                }
            }
            return false;
            specialHoleRedpoint.state = requireRemind ? RedPointState.Simple : RedPointState.None;
        }
        public int GetDoublePropLimitCount()
        public void JumpToCompose()
        {
            var _count = 0;
            foreach (var _key in doublePropRuneInlayDict.Keys)
            if (onJumpToCompose != null)
            {
                if (RuneTowerOpenLV >= _key)
                {
                    _count = doublePropRuneInlayDict[_key];
                }
                else
                {
                    break;
                }
                onJumpToCompose();
            }
            return _count;
        }
        public int GetCurrentDoublePropCount()
        public class PropertyCompute
        {
            var _count = 0;
            foreach (var _rune in runeHoleData.Values)
            {
                if (runeComposeModel.m_RuneBothPropertys.Contains(_rune.id))
                {
                    _count += 1;
                }
            }
            return _count;
        }
            string formula = string.Empty;
            Dictionary<int, float> qualityModulusDict;
            Dictionary<int, float> multiPropertyModulusDict;
            Dictionary<int, int> qualityBaseProperty;
            Dictionary<int, float> cacheFormulaResult;
        public int SurplusRunePackCnt {
            get {
                return runePackMaxNum - runePackData.Count;
            }
        }
        private Dictionary<int, RuneData> runePackData = new Dictionary<int, RuneData>();
        private Dictionary<int, RuneData> runeHoleData = new Dictionary<int, RuneData>();
        private uint runeTowerOpenLv = 0;
        public uint RuneTowerOpenLV {
            get { return runeTowerOpenLv; }
        }
        public event Action OnRefreshRuneHole;
        public event Action OnRefreshRunePack;
        public event Action OnRefreshRuneExp;
        public event Action OnRefreshRuneChip;
        public event Action OnRefreshRuneTowerLv;
        private uint holeState = 0;
        public int sltRuneHole = -1;
        private int runeSplinters = 0;
        public int RuneSplinters {
            get {
                return runeSplinters;
            }
        }
        private int runeChip = 0;
        public int RuneChip {
            get {
                return runeChip;
            }
        }
        public void SetRuneChip(int val)
        {
            runeChip = val;
            if (OnRefreshRuneChip != null)
                OnRefreshRuneChip();
        }
        public void SetRuneSplinters(int val)
        {
            runeSplinters = val;
            if (OnRefreshRuneExp != null)
            public PropertyCompute(FuncConfigConfig config)
            {
                OnRefreshRuneExp();
                formula = config.Numerical1;
                qualityModulusDict = ConfigParse.GetDic<int, float>(config.Numerical2);
                multiPropertyModulusDict = ConfigParse.GetDic<int, float>(config.Numerical3);
                qualityBaseProperty = ConfigParse.GetDic<int, int>(config.Numerical4);
                cacheFormulaResult = new Dictionary<int, float>();
            }
            UpdateRedpoint();
        }
        public void OnRunePackRefresh(HA204_tagMCVPackRefresh vNetData)
        {
            for (ushort i = 0; i < vNetData.Count; i++)
            {
                HA204_tagMCVPackRefresh.tagMCVPackItem item = vNetData.VPacklItemList[i];
                string runeData = item.ItemData.ToString();
                int dlt = 10 - runeData.Length;
                _textBuilder.Length = 0;
                _textBuilder.Append('0', dlt);
                runeData = runeData.Insert(0, _textBuilder.ToString());
                int id = int.Parse(runeData.Substring(5, 5));
                int lv = int.Parse(runeData.Substring(2, 3)) + 1;
                int sourceType = int.Parse(runeData.Substring(1, 1));
                int packType = vNetData.PackType;
                int index = item.ItemPlace;
                RuneData data = null;
                runePackData.TryGetValue(index, out data);
                if (data == null)
                {
                    data = new RuneData(index, id, lv, packType, sourceType, 0);
                    runePackData.Add(index, data);
                }
                else
                {
                    data.SetRuneData(index, id, lv, packType, sourceType, 0);
                }
            }
            if (OnRefreshRunePack != null)
            {
                OnRefreshRunePack();
            }
            UpdateRedpoint();
            UpdateBreakRedpoint();
        }
        public void OnRunePackClear(HA205_tagMCVPackClear vNetData)
        {
            for (ushort i = 0; i < vNetData.Count; i++)
            {
                int index = vNetData.ItemPlaceList[i];
                if (runePackData.ContainsKey(index))
                {
                    runePackData.Remove(index);
                }
            }
            if (OnRefreshRunePack != null)
            {
                OnRefreshRunePack();
            }
            UpdateRedpoint();
            UpdateBreakRedpoint();
        }
        public event Action<int> openNewHoleEvent;
        public void OnRuneHoleRefresh(HA31F_tagMCRuneInfo vNetData)
        {
            uint oldHoleState = holeState;
            holeState = vNetData.RuneHoleOpenState;
            for (byte i = 0; i < vNetData.Count; i++)
            public int GetPropertyValue(int id, int level)
            {
                RuneData data = null;
                runeHoleData.TryGetValue(i, out data);
                if (IsRuneHoleOpen(i) && vNetData.RuneDataList[i] != 0)
                var itemConfig = ItemConfig.Get(id);
                var runeConfig = RuneConfig.Get(id);
                float result = 0;
                if (itemConfig != null)
                {
                    _textBuilder.Length = 0;
                    string runeData = vNetData.RuneDataList[i].ToString();
                    int dlt = 10 - runeData.Length;
                    _textBuilder.Length = 0;
                    _textBuilder.Append('0', dlt);
                    runeData = runeData.Insert(0, _textBuilder.ToString());
                    int id = int.Parse(runeData.Substring(5, 5));
                    if (id == 0)
                    var formulaResult = 0f;
                    if (cacheFormulaResult.ContainsKey(level))
                    {
                        continue;
                        formulaResult = cacheFormulaResult[level];
                    }
                    int lv = int.Parse(runeData.Substring(2, 3)) + 1;
                    int sourceType = int.Parse(runeData.Substring(1, 1));
                    int placetype = 1;
                    if (data == null)
                    if (!cacheFormulaResult.ContainsKey(level))
                    {
                        data = new RuneData(i, id, lv, (int)PackType.InterimPack, sourceType, placetype);
                        runeHoleData.Add(i, data);
                        Equation.Instance.Clear();
                        Equation.Instance.AddKeyValue("level", level);
                        formulaResult = Equation.Instance.Eval<float>(formula);
                        cacheFormulaResult.Add(level, formulaResult);
                    }
                    var quality = itemConfig.ItemColor;
                    var propertyCount = 1;
                    if (runeConfig != null)
                    {
                        propertyCount = runeConfig.AttrType.Length;
                    }
                    float qualityModulus = qualityModulusDict[quality];
                    var baseValue = 0;
                    if (qualityBaseProperty.ContainsKey(quality))
                    {
                        baseValue = qualityBaseProperty[quality];
                    }
                    if (multiPropertyModulusDict.ContainsKey(propertyCount))
                    {
                        var multiPropertyModulus = multiPropertyModulusDict[propertyCount];
                        result = (formulaResult * qualityModulus + baseValue) * multiPropertyModulus;
                    }
                    else
                    {
                        data.SetRuneData(i, id, lv, (int)PackType.InterimPack, sourceType, placetype);
                        result = formulaResult * qualityModulus + baseValue;
                    }
                }
                else
                return Mathf.FloorToInt(result);
            }
            public void CacheFormulaResult(int level)
            {
                for (int i = 1; i <= level; i++)
                {
                    if (data != null)
                    if (!cacheFormulaResult.ContainsKey(i))
                    {
                        data = null;
                        runeHoleData.Remove(i);
                        Equation.Instance.Clear();
                        Equation.Instance.AddKeyValue("level", i);
                        var result = Equation.Instance.Eval<float>(formula);
                        cacheFormulaResult.Add(i, result);
                    }
                }
            }
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
        }
        public class RuneHoleRedpoint
        {
            public readonly Redpoint redpoint;
            public readonly Redpoint levelUpRedpoint;
            public readonly Redpoint replaceRedpoint;
            public RuneHoleRedpoint(int baseId)
            {
                if (!serverInited)
                redpoint = new Redpoint(baseId, RuneModel.redpointIndex++);
                levelUpRedpoint = new Redpoint(redpoint.id, RuneModel.redpointIndex++);
                replaceRedpoint = new Redpoint(redpoint.id, RuneModel.redpointIndex++);
            }
            public void SetRedpoint(bool levelUp, bool replace)
            {
                levelUpRedpoint.state = levelUp ? RedPointState.Simple : RedPointState.None;
                replaceRedpoint.state = replace ? RedPointState.Simple : RedPointState.None;
            }
        }
    }
    public class RuneItem : VirtualPackItem
    {
        public int placeType { get; private set; }//0-背包 1-孔
        public int sourceType { get; private set; }//来源(老号0,默认1,合成2)
        public int itemType { get; private set; }
        static RuneModel model { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
        public void ParseHoleItem(int index, uint data)
        {
            ParsePackItem(index, data);
            placeType = 1;
        }
        public override void ParsePackItem(int index, uint data)
        {
            base.ParsePackItem(index, data);
            placeType = 0;
            var config = ItemConfig.Get(id);
            itemType = config.Type;
            sourceType = int.Parse(dataString.Substring(1, 1));
        }
        public override void Release()
        {
            base.Release();
        }
        public bool IsExistSameProperty(int _id)
        {
            List<int> propertys;
            if (model.TryGetRunePropertys(id, out propertys))
            {
                var config = RuneConfig.Get(_id);
                if (config != null)
                {
                    break;
                }
                int k = 1 << i;
                var oldOpen = (oldHoleState & k) == k;
                if (!oldOpen && IsRuneHoleOpen(i))
                {
                    if (openNewHoleEvent != null)
                    for (int i = 0; i < config.AttrType.Length; i++)
                    {
                        openNewHoleEvent(i);
                    }
                }
            }
            if (OnRefreshRuneHole != null)
            {
                OnRefreshRuneHole();
            }
            UpdateRedpoint();
            UpdateBreakRedpoint();
            UpdateSpecialHoleRedpoint();
        }
        public void UnlockSpecialHole(int hole)
        {
            if (IsSpeicalHole(hole))
            {
                if (IsRuneHoleOpen(hole))
                {
                    return;
                }
                int error = 0;
                if (!TestUnlockSpeicalHole(hole, out error))
                {
                    ProcessUnlockError(error, specialHoles[hole]);
                    return;
                }
                CA513_tagCMUnlockRuneHole pak = new CA513_tagCMUnlockRuneHole();
                pak.HoleIndex = (byte)hole;
                GameNetSystem.Instance.SendInfo(pak);
            }
        }
        public bool TestUnlockSpeicalHole(int hole, out int error)
        {
            error = 0;
            SpecialRuneHoleCondition speicalHole;
            if (specialHoles.TryGetValue(hole, out speicalHole))
            {
                if (PlayerDatas.Instance.baseData.LV < speicalHole.level)
                {
                    error = 1;
                    return false;
                }
                if (PlayerDatas.Instance.baseData.diamond < speicalHole.cost)
                {
                    error = 2;
                    return false;
                }
                return true;
            }
            return false;
        }
        public void ProcessUnlockError(int error, SpecialRuneHoleCondition specialHole)
        {
            switch (error)
            {
                case 1:
                    SysNotifyMgr.Instance.ShowTip("RuneSpecialHoleLevelError", specialHole.level);
                    break;
                case 2:
                    WindowCenter.Instance.Open<RechargeTipWin>();
                    break;
            }
        }
        public bool ResolveFusionStone(int sourceType)
        {
            if (sourceType == 0 || sourceType == 2)
            {
                return true;
            }
            return false;
        }
        public bool IsSpeicalHole(int hole)
        {
            return specialHoles.ContainsKey(hole);
        }
        public bool IsRuneHoleOpen(int hole)
        {
            if (holeState < 1)
            {
                return false;
            }
            int k = 1 << hole;
            if ((holeState & k) == k)
            {
                return true;
            }
            return false;
        }
        public RuneData GetHoleRune(int hole)
        {
            RuneData data = null;
            runeHoleData.TryGetValue(hole, out data);
            return data;
        }
        public Dictionary<int, RuneData> GetAllRuneData()
        {
            return runeHoleData;
        }
        public int GetHoleRuneCnt()
        {
            return runeHoleData.Count;
        }
        public bool IsEmptyHole()
        {
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
            {
                if (IsRuneHoleOpen(i) && !runeHoleData.ContainsKey(i))
                {
                    return true;
                }
            }
            return false;
        }
        public Dictionary<int, RuneData> GetPackRune()
        {
            return runePackData;
        }
        public int RuneCount {
            get {
                var _count = 0;
                foreach (var _rune in runePackData.Values)
                {
                    if (!_rune.IsRuneCream)
                    {
                        _count++;
                    }
                }
                return _count;
            }
        }
        public int GetRuneCountById(int _itemId)
        {
            var count = 0;
            foreach (var _rune in runePackData.Values)
            {
                if (_rune.id == _itemId)
                {
                    count += 1;
                }
            }
            return count;
        }
        /// <summary>
        ///得到所有的解锁符印Id
        /// </summary>
        /// <returns></returns>
        public Dictionary<int, List<int>> GetAllUnlockRuneIdlist()
        {
            List<RuneConfig> runes = RuneConfig.GetValues();
            if (runes == null) return null;
            Dictionary<int, List<int>> unlockDict = new Dictionary<int, List<int>>();
            for (int i = 0; i < runes.Count; i++)
            {
                int offset = (int)RuneTowerOpenLV - runes[i].TowerID;
                if (offset >= 0 && runes[i].AttrType.Length < 2)
                {
                    if (!unlockDict.ContainsKey(runes[i].TowerID))
                    {
                        List<int> unlocklist = new List<int>();
                        unlocklist.Add(runes[i].ID);
                        unlockDict.Add(runes[i].TowerID, unlocklist);
                    }
                    else
                    {
                        unlockDict[runes[i].TowerID].Add(runes[i].ID);
                    }
                }
            }
            return unlockDict;
        }
        public bool CanEquipRune(int _color, out int _hole)
        {
            _hole = 0;
            foreach (var _rune in runePackData.Values)
            {
                var _itemCfg = ItemConfig.Get(_rune.id);
                if (_itemCfg.Type == RUNE_CREAMTYPE)
                {
                    continue;
                }
                else
                {
                    if (_itemCfg.ItemColor >= _color)
                    {
                        if (CanEquipHoleRune(_itemCfg.ID, _itemCfg.ItemColor, out _hole))
                        if (propertys.Contains(config.AttrType[i]))
                        {
                            return true;
                        }
@@ -943,388 +1070,13 @@
            }
            return false;
        }
        public bool CanEquipBetterRune(int _hole)
        {
            foreach (var rune in runePackData.Values)
            {
                if (IsBetterRune(rune, _hole))
                {
                    return true;
                }
            }
            return false;
        }
        public bool IsBetterRune(RuneData rune, int _hole)
        {
            if (rune.IsRuneCream)
            {
                return false;
            }
            var runeHole = GetHoleRune(_hole);
            if (runeHole == null)
            {
                return false;
            }
            var runeHoleConfig = RuneConfig.Get(runeHole.id);
            var itemHoleConfig = ItemConfig.Get(runeHole.id);
            var propertyType = runeHoleConfig.AttrType[0];
            if (runeHoleConfig == null)
            {
                return false;
            }
            var runeConfig = RuneConfig.Get(rune.id);
            bool same = false;
            for (int i = 0; i < runeConfig.AttrType.Length; i++)
            {
                if (runeConfig.AttrType[i] == propertyType)
                {
                    same = true;
                    break;
                }
            }
            if (!same)
            {
                return false;
            }
            bool isDoubleRuneHole = runeComposeModel.m_RuneBothPropertys.Contains(runeHole.id);
            bool isDoubleRune = runeComposeModel.m_RuneBothPropertys.Contains(rune.id);
            if (isDoubleRuneHole != isDoubleRune)
            {
                return isDoubleRune && GetCurrentDoublePropCount() < GetDoublePropLimitCount();
            }
            var itemConfig = ItemConfig.Get(rune.id);
            return itemConfig.ItemColor > itemHoleConfig.ItemColor;
        }
        public bool CanEquipHoleRune(int id, int _color, out int _hole)
        {
            _hole = 0;
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
            {
                if (!IsRuneHoleOpen(i))
                {
                    return false;
                }
                var _rune = GetHoleRune(i);
                if (runeComposeModel.m_RuneBothPropertys.Contains(id))
                {
                    if (GetDoublePropLimitCount() <= GetCurrentDoublePropCount())
                    {
                        return false;
                    }
                }
                if (_rune == null)
                {
                    if (IsSameInHoleRune(id, i))
                    {
                        continue;
                    }
                    _hole = i;
                    return true;
                }
                else
                {
                    var _itemCfg = ItemConfig.Get(_rune.id);
                    if (_itemCfg.ItemColor < _color && !IsSameInHoleRune(id, i))
                    {
                        _hole = i;
                        return true;
                    }
                }
            }
            return false;
        }
        public RuneData GetPackRune(int index)
        {
            RuneData data = null;
            runePackData.TryGetValue(index, out data);
            return data;
        }
        public List<RuneData> runePackList { get; set; }
        public void OnRuneTowerRefresh(HA3BA_tagMCTrialTowerInfo vNetData)
        {
            if (runeTowerOpenLv != vNetData.PassLV)
            {
                runeTowerOpenLv = vNetData.PassLV;
                if (OnRefreshRuneTowerLv != null)
                {
                    OnRefreshRuneTowerLv();
                }
            }
            UpdateRedpoint();
        }
        public bool IsSameInHoleRune(int id, int hole)
        {
            var _runeConfig = RuneConfig.Get(id);
            for (int i = 0; i < _runeConfig.AttrType.Length; i++)
            {
                if (IsSameRune(_runeConfig.AttrType[i], hole))
                {
                    return true;
                }
            }
            return false;
        }
        public bool IsSameRune(int type, int hole)
        {
            foreach (int key in runeHoleData.Keys)
            {
                if (key == hole)
                {
                    continue;
                }
                RuneConfig _runeCfg = RuneConfig.Get(runeHoleData[key].id);
                for (int i = 0; i < _runeCfg.AttrType.Length; i++)
                {
                    if (type == _runeCfg.AttrType[i])
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        public void IsSameRune(int id, ref List<int> sameHoles)
        {
            sameHoles.Clear();
            var _runeConfig = RuneConfig.Get(id);
            if (_runeConfig == null)
            {
                return;
            }
            for (int i = 0; i < _runeConfig.AttrType.Length; i++)
            {
                var sameHole = SameRuneHole(_runeConfig.AttrType[i]);
                if (sameHole != -1)
                {
                    sameHoles.Add(sameHole);
                }
            }
        }
        public int SameRuneHole(int type)
        {
            foreach (int key in runeHoleData.Keys)
            {
                RuneConfig _runeCfg = RuneConfig.Get(runeHoleData[key].id);
                for (int i = 0; i < _runeCfg.AttrType.Length; i++)
                {
                    if (type == _runeCfg.AttrType[i])
                    {
                        return key;
                    }
                }
            }
            return -1;
        }
        public int GetOpenTowerCnt(bool includeSpecial = false)
        {
            int Cnt = 0;
            for (int i = 0; i < RUNE_HOLE_COUNT; i++)
            {
                if (IsSpeicalHole(i) && !includeSpecial)
                {
                    continue;
                }
                if (IsRuneHoleOpen(i))
                {
                    Cnt++;
                }
                else
                {
                    break;
                }
            }
            return Cnt;
        }
        public void ClearRuneData()
        {
            runePackData.Clear();
            runeHoleData.Clear();
        }
        public event Action JumpToComposeEvent;
        public void JumpToRuneCompose()
        {
            if (WindowCenter.Instance.IsOpen<RunePanel>())
            {
                if (JumpToComposeEvent != null)
                {
                    JumpToComposeEvent();
                }
            }
        }
        #region 符印分解选择品质记录
        bool specialItemColorMark = false;
        public bool IsQualityMark(int itemColor)
        {
            if (itemColor == 4)
            {
                return specialItemColorMark;
            }
            var playerId = PlayerDatas.Instance.baseData.PlayerID;
            return LocalSave.GetBool(StringUtility.Contact("RuneBreakSelect_", playerId, "_", itemColor), itemColor == 1);
        }
        public void SetQualityMark(int itemColor, bool mark)
        {
            if (itemColor == 4)
            {
                specialItemColorMark = mark;
                return;
            }
            var playerId = PlayerDatas.Instance.baseData.PlayerID;
            LocalSave.SetBool(StringUtility.Contact("RuneBreakSelect_", playerId, "_", itemColor), mark);
        }
        #endregion
        #region 符印合成
        public int GetMaxLevelRuneCnt(int _id, out RuneData _runeData)
        {
            int _Cnt = 0;
            _runeData = null;
            foreach (var _rune in runePackData.Values)
            {
                if (_rune.id == _id)
                {
                    if (_runeData == null || _rune.lv >= _runeData.lv)
                    {
                        _runeData = _rune;
                    }
                    _Cnt++;
                }
            }
            foreach (var _rune in runeHoleData.Values)
            {
                if (_rune.id == _id)
                {
                    if (_runeData == null || _rune.lv >= _runeData.lv)
                    {
                        _runeData = _rune;
                    }
                    _Cnt++;
                    break;
                }
            }
            return _Cnt;
        }
        #endregion
        #region 符印分解
        public List<RuneData> runeBreakList { get; set; }
        private Dictionary<int, bool> m_RuneBreakEnableDict = new Dictionary<int, bool>();
        public Dictionary<int, bool> runeBreakEnableDict {
            get {
                return m_RuneBreakEnableDict;
            }
        }
        private List<Transform> m_RuneBreakRects = new List<Transform>();
        public List<Transform> runeBreakRects {
            get {
                return m_RuneBreakRects;
            }
        }
        public event Action OnRefreshBreakRune;
        public void UpdateBreakRune()
        {
            if (OnRefreshBreakRune != null)
            {
                OnRefreshBreakRune();
            }
        }
        #endregion
    }
    public struct SpecialRuneHoleCondition
    public struct RuneHoleCondition
    {
        public int level;
        public int cost;
        public int runeTowerFloor;
        public int playerLevel;
        public int diamond;
    }
    public enum RuneSource
    {
        Normal,
        Compose,
    }
    public class RuneData
    {
        /// <summary>
        /// 符印对应位置索引,若在孔上则对应孔id,若在背包,则对应背包位置索引
        /// </summary>
        private int m_Index = -1;
        public int index { get { return m_Index; } }
        /// <summary>
        /// 符印对应物品id
        /// </summary>
        private int m_Id = -1;
        public int id { get { return m_Id; } }
        /// <summary>
        /// 符印对应强化等级
        /// </summary>
        private int m_Level = 0;
        public int lv { get { return m_Level; } }
        /// <summary>
        /// 预留字段
        /// </summary>
        private int m_Lock = -1;
        public int locked { get { return m_Lock; } }
        /// <summary>
        /// 背包类型,符印背包255
        /// </summary>
        private int m_PackType = -1;
        public int packtype { get { return m_PackType; } }
        /// <summary>
        /// 符印放置位置,默认为符印背包
        /// </summary>
        private int m_PlaceType = 0;
        public int placetype { get { return m_PlaceType; } }
        public int m_SourceType = 0;
        public int sourceType { get { return m_SourceType; } }//来源(老号0,默认1,合成2)
        public bool IsRuneCream { get; private set; }
        public RuneData(int index, int id, int level, int packtype, int sourcetype, int placetype = 0)
        {
            m_Index = index;
            m_Id = id;
            m_Level = level;
            m_PackType = packtype;
            m_PlaceType = placetype;
            m_SourceType = sourcetype;
            var config = ItemConfig.Get(id);
            if (config != null)
            {
                IsRuneCream = config.Type == RuneModel.RUNE_CREAMTYPE;
            }
        }
        public void SetRuneData(int index, int id, int level, int packtype, int sourcetype, int placetype = 0)
        {
            m_Index = index;
            m_Id = id;
            m_Level = level;
            m_PackType = packtype;
            m_PlaceType = placetype;
            m_SourceType = sourcetype;
            var config = ItemConfig.Get(id);
            if (config != null)
            {
                IsRuneCream = config.Type == RuneModel.RUNE_CREAMTYPE;
            }
        }
    }
}
}
System/Rune/RuneModel.cs.meta
@@ -1,7 +1,7 @@
fileFormatVersion: 2
guid: b339eeaa4551e4b4da75c70c0a91a90e
timeCreated: 1510659979
licenseType: Free
guid: 32521d30fc8c0154aa569816a0a3990f
timeCreated: 1552705631
licenseType: Pro
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
System/Rune/RuneMosaicWin.cs
@@ -17,32 +17,28 @@
    public class RuneMosaicWin : Window
    {
        [SerializeField] List<RuneDisplay> runeHoleDatas;
        [SerializeField] List<Button> runeHoleBtns;
        [SerializeField] RectTransform m_ContainerSelectRune;
        [SerializeField] RuneHoleBehaviour[] m_RuneHoles;
        [SerializeField] Button m_RuneLevelUpBtn;
        [SerializeField] Text m_LevelUpBtnTxt;
        [SerializeField] Text m_ReplaceBtnTxt;
        [SerializeField] Button m_RuneReplaceBtn;
        [SerializeField] Button m_RunePreviewBtn;
        [SerializeField] Transform m_ContainerEquiped;
        [SerializeField] Transform m_ContainerGetRune;
        [SerializeField] Transform m_ContainerSpecialLock;
        [SerializeField] Image presentRuneImg;
        [SerializeField] Text presentRuneNameTxt;
        [SerializeField] Text presentRuneAttrTxt;
        [SerializeField] Button m_LevelUp;
        [SerializeField] Text m_LevelUpLabel;
        [SerializeField] Button m_ReplaceRune;
        [SerializeField] Text m_ReplaceLabel;
        [SerializeField] Button m_RunePreview;
        [SerializeField] RedpointBehaviour m_LevelUpRedpoint;
        [SerializeField] RedpointBehaviour m_ReplaceRedpoint;
        //[SerializeField] RectTransform m_ContainerLevelUp;
        [SerializeField] RectTransform m_ContainerLvUp1;
        [SerializeField] RectTransform m_ContainerLvUp2;
        [SerializeField] RectTransform m_ContainerItem;
        [SerializeField] Image m_RuneIcon;
        [SerializeField] Text m_RuneName;
        [SerializeField] Text m_RuneProperty;
        [SerializeField] Transform m_ContainerLevelUp;
        [SerializeField] PropertyBehaviour[] m_Propertys;
        [SerializeField] Text m_CostEssence;
        [SerializeField] RectTransform m_ContaienrMaxLevel;
        [SerializeField] Text runeLevelUpAttr1;
        [SerializeField] Text runeLevelUpAttr2;
        [SerializeField] Text runeLevelUpAttrNum1;
        [SerializeField] Text runeLevelUpAttrNum2;
        [SerializeField] Text runeLevelUpItemNum;
        [SerializeField] RectTransform m_ContainerGetRune;
        [SerializeField] Button m_GotoGetRuneBtn;
        [SerializeField] Button m_GotoFindRune;
@@ -51,86 +47,62 @@
        [SerializeField] Text m_SpecialCostRemind;
        [SerializeField] Text m_SpecialLevelRemind;
        [SerializeField] Text m_RuneUnlockTip;
        [SerializeField] UIEffect m_RuneLvUpEffect;
        [SerializeField] Text m_RuneUnlockRemind;
        [SerializeField] UIEffect m_LevelUpEffect;
        [SerializeField] UIEffect m_SpecialHoleEffect;
        Color m_LevelUpCacheColor;
        bool selectSpeicalHole = false;
        RuneModel m_Model;
        RuneModel model
        {
            get
            {
                return m_Model ?? (m_Model = ModelCenter.Instance.GetModel<RuneModel>());
            }
        }
        bool m_IsRuneLvUp = false;
        int m_SpecialHoleUnlocking = -1;
        RuneHoleState selectHoleState = RuneHoleState.Lock;
        Coroutine m_CacheCoroutine;
        bool doLevelUp = false;
        RuneModel model { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
        #region Built-in
        protected override void BindController()
        {
            m_LevelUpCacheColor = m_LevelUpBtnTxt.color;
        }
        protected override void AddListeners()
        {
            m_RuneReplaceBtn.onClick.AddListener(OnRuneReplaceBtn);
            m_RuneLevelUpBtn.onClick.AddListener(OnRuneUpBtn);
            m_RunePreviewBtn.onClick.AddListener(OnRunePreviewBtn);
            m_ReplaceRune.onClick.AddListener(OpenRunePack);
            m_LevelUp.onClick.AddListener(OnLevelUp);
            m_RunePreview.onClick.AddListener(OpenRunePreview);
            m_GotoGetRuneBtn.onClick.AddListener(OnGotoGetRune);
            m_GotoFindRune.onClick.AddListener(GotoFindRune);
            m_UnlockSpecialHole.onClick.AddListener(UnlockSpecialHole);
            for (int i = 0; i < runeHoleBtns.Count; i++)
            {
                var _index = i;
                runeHoleBtns[i].onClick.AddListener(() =>
                {
                    OnRuneHoleClick(_index);
                });
            }
        }
        protected override void OnPreOpen()
        {
            model.OnRefreshRuneHole += OnRuneHoleRefresh;
            model.OnRefreshRuneExp += OnUpdateRuneHoleInfo;
            model.openNewHoleEvent += OpenNewHoleEvent;
            model.unlockingSpecialHole = false;
            m_RuneLevelUpBtn.gameObject.SetActive(false);
            m_RuneReplaceBtn.gameObject.SetActive(false);
            m_ContainerGetRune.gameObject.SetActive(false);
            m_ContainerSpecial.gameObject.SetActive(false);
            OpenOrCloseSelect(false);
            model.sltRuneHole = -1;
            m_SpecialHoleUnlocking = -1;
            foreach (var _hole in runeHoleDatas)
            {
                _hole.SetSelect(false);
            }
            InitRuneHoles();
            model.onSelectHoleRefresh += OnSelectHoleRefresh;
            model.onRuneHoleRefresh += OnRuneHoleRefresh;
            model.onOpenNewHole += OnOpenNewHole;
            PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefreshEvent;
            Display();
        }
        protected override void OnAfterOpen()
        {
            if (!HandleAchievement())
            {
                OnRuneHoleClick(CheckOpenSelect());
            }
            HandleAchievement();
            model.SetDayRemind();
        }
        protected override void OnPreClose()
        {
            model.OnRefreshRuneHole -= OnRuneHoleRefresh;
            model.OnRefreshRuneExp -= OnUpdateRuneHoleInfo;
            model.openNewHoleEvent -= OpenNewHoleEvent;
            model.onSelectHoleRefresh -= OnSelectHoleRefresh;
            model.onRuneHoleRefresh -= OnRuneHoleRefresh;
            model.onOpenNewHole -= OnOpenNewHole;
            PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefreshEvent;
            m_SpecialHoleUnlocking = -1;
            doLevelUp = false;
            for (int i = 0; i < m_RuneHoles.Length; i++)
            {
                m_RuneHoles[i].Dispose();
            }
            if (m_CacheCoroutine != null)
            {
@@ -144,12 +116,237 @@
        }
        #endregion
        private void OpenNewHoleEvent(int hole)
        void SetDefaultSelect()
        {
            if (model.IsSpeicalHole(hole))
            if (NewBieCenter.Instance.inGuiding)
            {
                m_SpecialHoleUnlocking = hole;
                EffectMgr.Instance.PlayUIEffect(3068, 2500, runeHoleDatas[hole].Container.parent, false);
                model.selectHole = 0;
            }
            if (model.specialHoleRedpoint.state == RedPointState.Simple)
            {
                model.selectHole = model.specialHole;
                return;
            }
            for (int i = 0; i < RuneModel.RUNE_HOLE_COUNT; i++)
            {
                RuneModel.RuneHoleRedpoint redpoint;
                if (model.TryGetRedpoint(i, out redpoint))
                {
                    if (redpoint.redpoint.state == RedPointState.Simple)
                    {
                        model.selectHole = i;
                        return;
                    }
                }
            }
            model.selectHole = 0;
        }
        void Display()
        {
            SetDefaultSelect();
            for (int i = 0; i < m_RuneHoles.Length; i++)
            {
                m_RuneHoles[i].Display(i);
            }
            DisplayHoleDetail();
            DisplayUnlockRemind();
            DisplaySpecialHole();
        }
        void DisplayHoleDetail()
        {
            if (!model.IsRuneHoleOpen(model.selectHole, model.holeState))
            {
                selectHoleState = RuneHoleState.Lock;
            }
            else
            {
                RuneItem item;
                if (!model.TryGetRuneHoleItem(model.selectHole, out item))
                {
                    selectHoleState = RuneHoleState.UnEquip;
                }
                else
                {
                    selectHoleState = RuneHoleState.Equiped;
                }
            }
            RuneModel.RuneHoleRedpoint redpoint;
            if (model.TryGetRedpoint(model.selectHole, out redpoint))
            {
                m_LevelUpRedpoint.redpointId = redpoint.levelUpRedpoint.id;
                m_ReplaceRedpoint.redpointId = redpoint.replaceRedpoint.id;
            }
            m_ContainerEquiped.gameObject.SetActive(selectHoleState == RuneHoleState.Equiped);
            m_ContainerGetRune.gameObject.SetActive(selectHoleState == RuneHoleState.UnEquip);
            m_ContainerSpecialLock.gameObject.SetActive(selectHoleState == RuneHoleState.Lock
                && model.selectHole == model.specialHole);
            m_ReplaceRune.gameObject.SetActive(selectHoleState != RuneHoleState.Lock);
            m_LevelUp.gameObject.SetActive(selectHoleState == RuneHoleState.Equiped);
            switch (selectHoleState)
            {
                case RuneHoleState.Lock:
                    if (model.selectHole == model.specialHole)
                    {
                        DisplaySpecialHoleDetail();
                    }
                    break;
                case RuneHoleState.UnEquip:
                    break;
                case RuneHoleState.Equiped:
                    DisplayEquipedHoleDetail();
                    break;
            }
        }
        void DisplayEquipedHoleDetail()
        {
            RuneItem item;
            model.TryGetRuneHoleItem(model.selectHole, out item);
            var config = RuneConfig.Get(item.id);
            var multiProperty = model.IsMultiPropertyRune(item.id);
            var itemConfig = ItemConfig.Get(item.id);
            m_RuneIcon.SetSprite(itemConfig.IconKey);
            m_RuneProperty.text = model.GetRunePropertyDescription(item.id, item.level);
            m_RuneName.text = StringUtility.Contact(itemConfig.ItemName, Language.Get("Z1024", item.level));
            m_RuneName.color = UIHelper.GetUIColor(itemConfig.ItemColor, true);
            var isMax = model.IsRuneMaxLevel(item.id, item.level);
            m_ContaienrMaxLevel.gameObject.SetActive(isMax);
            m_ContainerLevelUp.gameObject.SetActive(!isMax);
            if (!isMax)
            {
                for (int i = 0; i < m_Propertys.Length; i++)
                {
                    m_Propertys[i].gameObject.SetActive(i < config.AttrType.Length);
                    if (i < config.AttrType.Length)
                    {
                        var propertyValue = model.GetPropertyValue(item.id, item.level, config.AttrType[i]);
                        var upValue = model.GetPropertyValue(item.id, item.level + 1, config.AttrType[i]);
                        m_Propertys[i].DisplayUp(config.AttrType[i], propertyValue, upValue);
                    }
                }
                int requireEssence = model.GetLevelUpRequireRuneEssence(item.id, item.level);
                int essence = PlayerDatas.Instance.extersion.runeEssence;
                var essenceLabel = UIHelper.AppendColor(essence >= requireEssence ? TextColType.Green : TextColType.Red
                           , essence.ToString(), true);
                m_CostEssence.text = StringUtility.Contact(essenceLabel, "/", requireEssence);
            }
            m_LevelUp.SetInteractable(m_LevelUpLabel, !isMax);
            m_LevelUp.gameObject.SetActive(!isMax);
        }
        void DisplaySpecialHoleDetail()
        {
            RuneHoleCondition condition;
            if (model.TryGetRuneHoleCondition(model.selectHole, out condition))
            {
                m_SpecialCostRemind.text = Language.Get("RuneSpecialHoleCost", condition.diamond);
                m_SpecialLevelRemind.text = Language.Get("RuneSpecialHoleLevel", condition.playerLevel);
            }
        }
        void DisplayUnlockRemind()
        {
            var lockHole = -1;
            for (int i = 0; i < RuneModel.RUNE_HOLE_COUNT; i++)
            {
                if (i == model.specialHole)
                {
                    continue;
                }
                if (!model.IsRuneHoleOpen(i, model.holeState))
                {
                    lockHole = i;
                    break;
                }
            }
            if (lockHole != -1)
            {
                RuneHoleCondition condition;
                if (model.TryGetRuneHoleCondition(lockHole, out condition))
                {
                    var config = RuneTowerFloorConfig.Get(condition.runeTowerFloor);
                    var tower = RuneTowerConfig.Get(config.TowerId);
                    m_RuneUnlockRemind.text = Language.Get("RuneUnlock",
                        StringUtility.Contact(tower.TowerName, config.FloorName));
                }
            }
            else
            {
                var _tower = 0;
                if (model.IsUnlockAllMultiPropertyInlay(out _tower))
                {
                    m_RuneUnlockRemind.text = Language.Get("L1060", model.GetMultiPropertyInlayCount());
                }
                else
                {
                    var config = RuneTowerFloorConfig.Get(_tower);
                    var tower = RuneTowerConfig.Get(config.TowerId);
                    m_RuneUnlockRemind.text = Language.Get("RuneDoubleAttr",
                        StringUtility.Contact(tower.TowerName, config.FloorName)
                        , model.GetMultiPropertyInlayCount(_tower));
                }
            }
        }
        void DisplaySpecialHole()
        {
            m_SpecialHoleEffect.StopImediatly();
            if (!model.IsRuneHoleOpen(model.specialHole, model.holeState))
            {
                m_SpecialHoleEffect.Play();
            }
        }
        private void OnSelectHoleRefresh()
        {
            DisplayHoleDetail();
        }
        private void OnRuneHoleRefresh()
        {
            if (model.selectHole == model.specialHole && model.unlockingSpecialHole)
            {
                return;
            }
            DisplayHoleDetail();
            if (doLevelUp)
            {
                m_LevelUpEffect.Play();
                doLevelUp = false;
            }
        }
        private void PlayerDataRefreshEvent(PlayerDataType dataType)
        {
            if (dataType == PlayerDataType.RuneSplinters)
            {
                if (selectHoleState == RuneHoleState.Equiped)
                {
                    DisplayEquipedHoleDetail();
                }
            }
        }
        void OnOpenNewHole(int hole)
        {
            if (model.specialHole == hole)
            {
                model.unlockingSpecialHole = true;
                EffectMgr.Instance.PlayUIEffect(3068, 2500, m_RuneHoles[hole].transform, false);
                m_CacheCoroutine = StartCoroutine(Co_RefreshHole());
            }
        }
@@ -157,13 +354,70 @@
        IEnumerator Co_RefreshHole()
        {
            yield return WaitingForSecondConst.WaitMS800;
            m_SpecialHoleUnlocking = -1;
            OnRuneHoleRefresh();
            model.unlockingSpecialHole = false;
            DisplaySpecialHole();
            if (model.selectHole == model.specialHole)
            {
                DisplayHoleDetail();
            }
        }
        private void UnlockSpecialHole()
        {
            model.UnlockSpecialHole(model.sltRuneHole);
            if (model.selectHole != model.specialHole)
            {
                return;
            }
            if (model.IsRuneHoleOpen(model.selectHole, model.holeState))
            {
                return;
            }
            int error = 0;
            if (!TestUnlockSpeicalHole(model.selectHole, out error))
            {
                ProcessUnlockError(error, model.selectHole);
                return;
            }
            CA513_tagCMUnlockRuneHole pak = new CA513_tagCMUnlockRuneHole();
            pak.HoleIndex = (byte)model.selectHole;
            GameNetSystem.Instance.SendInfo(pak);
        }
        bool TestUnlockSpeicalHole(int hole, out int error)
        {
            error = 0;
            RuneHoleCondition condition;
            if (model.TryGetRuneHoleCondition(hole, out condition))
            {
                if (PlayerDatas.Instance.baseData.LV < condition.playerLevel)
                {
                    error = 1;
                    return false;
                }
                if (PlayerDatas.Instance.baseData.diamond < condition.diamond)
                {
                    error = 2;
                    return false;
                }
            }
            return true;
        }
        void ProcessUnlockError(int error, int hole)
        {
            switch (error)
            {
                case 1:
                    RuneHoleCondition condition;
                    if (model.TryGetRuneHoleCondition(hole, out condition))
                    {
                        SysNotifyMgr.Instance.ShowTip("RuneSpecialHoleLevelError", condition.playerLevel);
                    }
                    break;
                case 2:
                    WindowCenter.Instance.Open<RechargeTipWin>();
                    break;
            }
        }
        private void OnGotoGetRune()
@@ -176,411 +430,91 @@
            WindowJumpMgr.Instance.WindowJumpTo(JumpUIType.RuneXB);
        }
        bool HandleAchievement()
        void HandleAchievement()
        {
            if (AchievementGoto.achievementType == AchievementGoto.RuneLevelUp)
            {
                int _hole = 0;
                if (model.CanLevelUpRune(out _hole))
                for (int i = 0; i < RuneModel.RUNE_HOLE_COUNT; i++)
                {
                    OnRuneHoleClick(_hole);
                    var _effect = AchievementGuideEffectPool.Require(1);
                    _effect.transform.SetParentEx(m_RuneLevelUpBtn.transform, Vector3.zero, Vector3.zero, Vector3.one);
                    return true;
                    if (model.SatisfyLevelUpHole(i))
                    {
                        model.selectHole = i;
                        var _effect = AchievementGuideEffectPool.Require(1);
                        _effect.transform.SetParentEx(m_LevelUp.transform, Vector3.zero, Vector3.zero, Vector3.one);
                        AchievementGoto.achievementType = 0;
                        return;
                    }
                }
                else
                {
                    SysNotifyMgr.Instance.ShowTip("Achievement_45");
                }
                SysNotifyMgr.Instance.ShowTip("Achievement_45");
                AchievementGoto.achievementType = 0;
            }
            var _color = AchievementGoto.guideAchievementId == AchievementGoto.EquipRune1 ? 1 :
                AchievementGoto.guideAchievementId == AchievementGoto.EquipRune2 ? 2 : 0;
            if (_color > 0)
            else
            {
                int _hole = 0;
                if (model.CanEquipRune(_color, out _hole))
                var _color = AchievementGoto.guideAchievementId == AchievementGoto.EquipRune1 ? 1 :
                AchievementGoto.guideAchievementId == AchievementGoto.EquipRune2 ? 2 : 0;
                if (_color > 0)
                {
                    OnRuneHoleClick(_hole);
                    var _effect = AchievementGuideEffectPool.Require(1);
                    _effect.transform.SetParentEx(m_RuneReplaceBtn.transform, Vector3.zero, Vector3.zero, Vector3.one);
                    return true;
                }
                else
                {
                    SysNotifyMgr.Instance.ShowTip("Achievement_44");
                    int _hole = 0;
                    if (model.TryEquipRuneByColor(_color, out _hole))
                    {
                        model.selectHole = _hole;
                        var _effect = AchievementGuideEffectPool.Require(1);
                        _effect.transform.SetParentEx(m_ReplaceRune.transform, Vector3.zero, Vector3.zero, Vector3.one);
                    }
                    else
                    {
                        SysNotifyMgr.Instance.ShowTip("Achievement_44");
                    }
                }
                AchievementGoto.guideAchievementId = 0;
            }
            return false;
        }
        void OpenOrCloseSelect(bool _open)
        private void OpenRunePack()
        {
            m_ContainerSelectRune.gameObject.SetActive(_open);
            m_RuneLevelUpBtn.interactable = _open;
            m_LevelUpBtnTxt.color = _open ? m_LevelUpCacheColor : Color.grey;
        }
        int CheckOpenSelect()
        {
            if (model.specialRuneRemindRedpoint.state == RedPointState.Simple && !NewBieCenter.Instance.inGuiding)
            {
                foreach (var hole in model.specialHoles.Keys)
                {
                    if (!model.IsRuneHoleOpen(hole))
                    {
                        return hole;
                    }
                }
            }
            for (int i = 0; i < RuneModel.RUNE_HOLE_COUNT; i++)
            {
                if (model.GetRedpoint(i).state == RedPointState.Simple)
                {
                    return i;
                }
            }
            return 0;
        }
        void DisSelectAll()
        {
            for (int i = 0; i < RuneModel.RUNE_HOLE_COUNT; i++)
            {
                runeHoleDatas[i].SetSelect(false);
                runeHoleDatas[i].redpoint.gameObject.SetActive(true);
            }
        }
        void OnRuneHoleClick(int _hole)
        {
            if (model.IsRuneHoleOpen(_hole) && m_SpecialHoleUnlocking != _hole)
            {
                for (int i = 0; i < runeHoleDatas.Count; i++)
                {
                    if (i != _hole)
                    {
                        runeHoleDatas[i].SetSelect(false);
                        runeHoleDatas[i].redpoint.gameObject.SetActive(true);
                    }
                }
                model.sltRuneHole = _hole;
                m_RuneUnlockTip.gameObject.SetActive(true);
                m_ContainerSpecial.gameObject.SetActive(false);
                m_RuneLevelUpBtn.gameObject.SetActive(true);
                m_RuneReplaceBtn.gameObject.SetActive(true);
                OnUpdateRuneHoleInfo();
                runeHoleDatas[_hole].SetSelect(true);
                runeHoleDatas[_hole].redpoint.gameObject.SetActive(false);
                m_ReplaceBtnTxt.text = model.GetHoleRune(_hole) != null ? Language.Get("RuneMosaic_6") : Language.Get("KnapS120");
            }
            else
            {
                if (model.IsSpeicalHole(_hole))
                {
                    DisplaySpecialHole(_hole);
                }
                else
                {
                    int[] towerArray = model.runeUnlockArray;
                    RuneTowerFloorConfig cfg = RuneTowerFloorConfig.Get(towerArray[_hole]);
                    var tower = RuneTowerConfig.Get(cfg.TowerId);
                    SysNotifyMgr.Instance.ShowTip("RuneUnlock", StringUtility.Contact(tower.TowerName, cfg.FloorName));
                }
            }
        }
        private void DisplaySpecialHole(int _hole)
        {
            m_ContainerSpecial.gameObject.SetActive(true);
            m_ContainerSelectRune.gameObject.SetActive(false);
            m_ContainerGetRune.gameObject.SetActive(false);
            m_RuneLevelUpBtn.gameObject.SetActive(false);
            m_RuneReplaceBtn.gameObject.SetActive(false);
            m_RuneUnlockTip.gameObject.SetActive(false);
            DisSelectAll();
            model.sltRuneHole = _hole;
            runeHoleDatas[_hole].SetSelect(true);
            var speical = model.specialHoles[_hole];
            m_SpecialCostRemind.text = Language.Get("RuneSpecialHoleCost", speical.cost);
            m_SpecialLevelRemind.text = Language.Get("RuneSpecialHoleLevel", speical.level);
        }
        private void OnUpdateRuneHoleInfo()
        {
            model.runeLevelUpRedpoint.state = RedPointState.None;
            model.runeReplaceRedpoint.state = RedPointState.None;
            if (model.sltRuneHole == -1 || !model.IsRuneHoleOpen(model.sltRuneHole))
            {
                return;
            }
            if (model.sltRuneHole == m_SpecialHoleUnlocking)
            {
                return;
            }
            RuneData data = model.GetHoleRune(model.sltRuneHole);
            var _redpoint = model.GetRedpoint(model.sltRuneHole);
            if (_redpoint.state == RedPointState.Simple)
            {
                if (data == null)
                {
                    model.runeReplaceRedpoint.state = RedPointState.Simple;
                }
                else if (model.CanEquipBetterRune(model.sltRuneHole))
                {
                    model.runeReplaceRedpoint.state = RedPointState.Simple;
                }
                else
                {
                    model.runeLevelUpRedpoint.state = RedPointState.Simple;
                }
            }
            OpenOrCloseSelect(false);
            if (data == null)
            {
                m_ContainerGetRune.gameObject.SetActive(true);
                return;
            }
            m_ContainerGetRune.gameObject.SetActive(false);
            m_LevelUpBtnTxt.color = Color.grey;
            OpenOrCloseSelect(true);
            var _runeCfg = RuneConfig.Get(data.id);
            bool _doubleProperty = _runeCfg.AttrType.Length > 1;
            m_ContainerLvUp2.gameObject.SetActive(_doubleProperty);
            var _itemCfg = ItemConfig.Get(data.id);
            presentRuneImg.SetSprite(_itemCfg.IconKey);
            presentRuneAttrTxt.text = model.GetRuneAttrStr(data.id, data.lv);
            presentRuneNameTxt.text = StringUtility.Contact(_itemCfg.ItemName, Language.Get("Z1024", data.lv));
            presentRuneNameTxt.color = UIHelper.GetUIColor(_itemCfg.ItemColor, true);
            var _propertyCfg = PlayerPropertyConfig.Get(_runeCfg.AttrType[0]);
            var _propertyValue = model.GetRuneAttrVal(data.id, data.lv, _runeCfg.AttrType[0]);
            runeLevelUpAttr1.text = StringUtility.Contact(_propertyCfg.Name, "+", UIHelper.ReplacePercentage(_propertyValue, _propertyCfg.ISPercentage,
                UIHelper.GetPropertyDecimalCount(_propertyCfg.ID)),
                _propertyCfg.ISPercentage == 1 ? "%" : string.Empty);
            bool _isRuneMaxLv = data.lv >= model.GetRuneMaxLevelByItem(data.id);
            runeLevelUpAttrNum1.gameObject.SetActive(!_isRuneMaxLv);
            if (!_isRuneMaxLv)
            {
                _propertyValue = model.GetRuneAttrVal(data.id, data.lv + 1, _runeCfg.AttrType[0]);
                runeLevelUpAttrNum1.text = StringUtility.Contact("+", UIHelper.ReplacePercentage(_propertyValue, _propertyCfg.ISPercentage,
                    UIHelper.GetPropertyDecimalCount(_propertyCfg.ID)),
                            _propertyCfg.ISPercentage == 1 ? "%" : string.Empty);
            }
            if (_doubleProperty)
            {
                _propertyCfg = PlayerPropertyConfig.Get(_runeCfg.AttrType[1]);
                _propertyValue = model.GetRuneAttrVal(data.id, data.lv, _runeCfg.AttrType[1]);
                runeLevelUpAttr2.text = StringUtility.Contact(_propertyCfg.Name, "+", UIHelper.ReplacePercentage(_propertyValue, _propertyCfg.ISPercentage,
                    UIHelper.GetPropertyDecimalCount(_propertyCfg.ID)),
                             _propertyCfg.ISPercentage == 1 ? "%" : string.Empty);
                runeLevelUpAttrNum2.gameObject.SetActive(!_isRuneMaxLv);
                if (!_isRuneMaxLv)
                {
                    _propertyValue = model.GetRuneAttrVal(data.id, data.lv + 1, _runeCfg.AttrType[1]);
                    runeLevelUpAttrNum2.text = StringUtility.Contact("+", UIHelper.ReplacePercentage(_propertyValue, _propertyCfg.ISPercentage,
                        UIHelper.GetPropertyDecimalCount(_propertyCfg.ID)),
                                _propertyCfg.ISPercentage == 1 ? "%" : string.Empty);
                }
            }
            int _levelUpExp = model.GetRuneNeedExp(data.id, data.lv);
            m_RuneLevelUpBtn.interactable = !_isRuneMaxLv /*&& model.RuneSplinters >= _levelUpExp*/;
            m_LevelUpBtnTxt.color = m_RuneLevelUpBtn.interactable ? m_LevelUpCacheColor : Color.grey;
            runeLevelUpItemNum.gameObject.SetActive(!_isRuneMaxLv);
            m_ContainerLvUp1.gameObject.SetActive(!_isRuneMaxLv);
            m_ContainerLvUp2.gameObject.SetActive(!_isRuneMaxLv && _doubleProperty);
            m_ContainerItem.gameObject.SetActive(!_isRuneMaxLv);
            m_RuneLevelUpBtn.gameObject.SetActive(!_isRuneMaxLv);
            //m_ContainerLevelUp.gameObject.SetActive(!_isRuneMaxLv);
            m_ContaienrMaxLevel.gameObject.SetActive(_isRuneMaxLv);
            runeLevelUpItemNum.text = StringUtility.Contact(UIHelper.AppendColor(
                model.RuneSplinters >= _levelUpExp ? TextColType.Green : TextColType.Red
                , model.RuneSplinters.ToString(), true), "/", _levelUpExp);
        }
        void InitRuneHoles()
        {
            int towerCnt = model.GetOpenTowerCnt();
            int[] towerArray = model.runeUnlockArray;
            if (towerCnt >= towerArray.Length)
            {
                var _tower = 0;
                foreach (var _key in model.doublePropRuneInlayDict.Keys)
                {
                    if (model.RuneTowerOpenLV < _key)
                    {
                        _tower = _key;
                        break;
                    }
                }
                if (_tower == 0)
                {
                    m_RuneUnlockTip.text = Language.Get("L1060", model.doublePropRuneInlayDict.Values.Last());
                }
                else
                {
                    RuneTowerFloorConfig cfg = RuneTowerFloorConfig.Get(_tower);
                    var tower = RuneTowerConfig.Get(cfg.TowerId);
                    m_RuneUnlockTip.text = Language.Get("RuneDoubleAttr", StringUtility.Contact(tower.TowerName, cfg.FloorName)
                        , model.doublePropRuneInlayDict[_tower]);
                }
            }
            else
            {
                RuneTowerFloorConfig cfg = RuneTowerFloorConfig.Get(towerArray[towerCnt]);
                var tower = RuneTowerConfig.Get(cfg.TowerId);
                m_RuneUnlockTip.text = Language.Get("RuneUnlock", StringUtility.Contact(tower.TowerName, cfg.FloorName));
            }
            var speicalHole = -1;
            for (int i = 0; i < runeHoleDatas.Count; i++)
            {
                RuneData data = model.GetHoleRune(i);
                runeHoleDatas[i].SetRuneHole(!model.IsRuneHoleOpen(i) || m_SpecialHoleUnlocking == i);
                if (data == null || !model.IsRuneHoleOpen(i))
                {
                    runeHoleDatas[i].Display(0, 0);
                }
                else
                {
                    runeHoleDatas[i].Display(data.id, data.lv);
                }
                if (model.IsSpeicalHole(i))
                {
                    speicalHole = i;
                }
            }
            m_SpecialHoleEffect.StopImediatly();
            if (speicalHole != -1)
            {
                if (!model.IsRuneHoleOpen(speicalHole))
                {
                    m_SpecialHoleEffect.Play();
                }
            }
        }
        void OnRuneHoleRefresh()
        {
            InitRuneHoles();
            OnUpdateRuneHoleInfo();
            if (model.sltRuneHole != -1)
            {
                OnRuneHoleClick(model.sltRuneHole);
            }
            if (m_IsRuneLvUp)
            {
                m_RuneLvUpEffect.Play();
                m_IsRuneLvUp = false;
            }
        }
        private void OnRuneReplaceBtn()
        {
            RunePackWin.selectHole = model.selectHole;
            WindowCenter.Instance.Open<RunePackWin>();
        }
        private void OnRunePreviewBtn()
        private void OpenRunePreview()
        {
            WindowCenter.Instance.Open<RunePreviewWin>();
        }
        void OnRuneUpBtn()
        void OnLevelUp()
        {
            RuneData data = model.GetHoleRune(model.sltRuneHole);
            if (data == null)
            RuneItem item;
            if (!model.TryGetRuneHoleItem(model.selectHole, out item))
            {
                return;
            }
            var _runeCfg = RuneConfig.Get(data.id);
            var _itemCfg = ItemConfig.Get(data.id);
            if (data.lv >= model.GetRuneMaxLevelByItem(data.id))
            if (model.IsRuneMaxLevel(item.id, item.level))
            {
                return;
            }
            float _levelUpExp = model.GetRuneNeedExp(data.id, data.lv);
            if (model.RuneSplinters < _levelUpExp)
            var config = RuneConfig.Get(item.id);
            var itemConfig = ItemConfig.Get(item.id);
            var requireEssence = model.GetLevelUpRequireRuneEssence(item.id, item.level);
            if (PlayerDatas.Instance.extersion.runeEssence < requireEssence)
            {
                SysNotifyMgr.Instance.ShowTip("RuneEssenceLack");
                return;
            }
            m_IsRuneLvUp = true;
            CA565_tagCMRuneUp runeUpPack = new CA565_tagCMRuneUp();
            runeUpPack.PlaceIndex = (ushort)data.index;
            runeUpPack.PlaceType = (byte)data.placetype;
            GameNetSystem.Instance.SendInfo(runeUpPack);
            CA565_tagCMRuneUp pak = new CA565_tagCMRuneUp();
            pak.PlaceIndex = (ushort)item.index;
            pak.PlaceType = (byte)item.placeType;
            GameNetSystem.Instance.SendInfo(pak);
            doLevelUp = true;
        }
        [Serializable]
        public class RuneDisplay
        public enum RuneHoleState
        {
            [SerializeField] Image m_RuneIcon;
            [SerializeField] Image m_RuneUnlock;
            [SerializeField] Text m_RuneNameLvTxt;
            [SerializeField] Image m_RuneSelect;
            [SerializeField] Image m_RuneAdd;
            [SerializeField] UIEffect m_Effect;
            [SerializeField] RedpointBehaviour m_Redpoint;
            RuneModel m_Model;
            RuneModel model { get { return m_Model ?? (m_Model = ModelCenter.Instance.GetModel<RuneModel>()); } }
            RuneComposeModel runeComposeModel { get { return ModelCenter.Instance.GetModel<RuneComposeModel>(); } }
            public RectTransform Container
            {
                get
                {
                    return m_RuneIcon.rectTransform;
                }
            }
            public RedpointBehaviour redpoint { get { return m_Redpoint; } }
            public void Display(int _runeId, int _lv)
            {
                m_RuneIcon.gameObject.SetActive(_runeId != 0);
                m_RuneNameLvTxt.gameObject.SetActive(_runeId != 0);
                m_RuneAdd.gameObject.SetActive(_runeId == 0);
                var _itemCfg = ItemConfig.Get(_runeId);
                if (_itemCfg != null)
                {
                    m_RuneIcon.SetSprite(_itemCfg.IconKey);
                    m_RuneNameLvTxt.color = UIHelper.GetUIColor(_itemCfg.ItemColor);
                }
                m_RuneNameLvTxt.text = Language.Get("Z1024", _lv);
                if (_runeId != 0 && runeComposeModel.m_RuneBothPropertys.Contains(_runeId))
                {
                    if (!m_Effect.IsPlaying)
                    {
                        m_Effect.Play();
                    }
                }
                else
                {
                    if (m_Effect.IsPlaying)
                    {
                        m_Effect.StopImediatly();
                    }
                }
            }
            public void SetRuneHole(bool _lock)
            {
                m_RuneUnlock.gameObject.SetActive(_lock);
                m_RuneAdd.gameObject.SetActive(!_lock);
            }
            public void SetSelect(bool _select)
            {
                m_RuneSelect.gameObject.SetActive(_select);
            }
            Lock,
            UnEquip,
            Equiped,
        }
    }
}
System/Rune/RunePackCell.cs
@@ -6,143 +6,71 @@
using System;
namespace EnhancedUI.EnhancedScroller
namespace Snxxz.UI
{
    public class RunePackCell : ScrollerUI
    [XLua.Hotfix]
    public class RunePackCell : CellView
    {
        [SerializeField] List<Image> m_RuneIcons;
        [SerializeField] List<Text> m_RuneNameLvTxts;
        [SerializeField] List<Text> m_RuneAttrTxts;
        [SerializeField] List<Button> m_RuneBtns;
        [SerializeField] List<Text> m_EquipedImgs;
        [SerializeField] List<Image> m_Redpoints;
        RuneModel m_Model;
        RuneModel model
        [SerializeField] RunePackItem[] m_RunePackItems;
        VirtualPackModel virtualPackModel { get { return ModelCenter.Instance.GetModel<VirtualPackModel>(); } }
        public void Display(int line, List<int> itemIndexs)
        {
            get
            for (int i = 0; i < m_RunePackItems.Length; i++)
            {
                return m_Model ?? (m_Model = ModelCenter.Instance.GetModel<RuneModel>());
                int index = line * m_RunePackItems.Length + i;
                m_RunePackItems[i].SetActive(index < itemIndexs.Count);
                if (index < itemIndexs.Count)
                {
                    m_RunePackItems[i].Display(itemIndexs[index]);
                }
            }
        }
        RuneComposeModel m_ComposeModel;
        RuneComposeModel runeComposeModel
        [Serializable]
        public class RunePackItem
        {
            get
            {
                return m_ComposeModel ?? (m_ComposeModel = ModelCenter.Instance.GetModel<RuneComposeModel>());
            }
        }
            [SerializeField] Transform m_Container;
            [SerializeField] Image m_Icon;
            [SerializeField] Text m_RuneName;
            [SerializeField] Text m_Property;
            [SerializeField] Button m_Select;
            [SerializeField] Transform m_SamePropertySign;
            [SerializeField] Transform m_RedpointSign;
        public override void Refresh(CellView cell)
        {
            if (model.runePackList == null)
            {
                return;
            }
            for (int i = 0; i < 3; i++)
            {
                int index = cell.index * 3 + i;
                Transform child = cell.transform.GetChild(i);
                if (index >= model.runePackList.Count)
                {
                    child.gameObject.SetActive(false);
                    continue;
                }
                else
                {
                    child.gameObject.SetActive(true);
                }
            RuneModel model { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
            VirtualPackModel virtualPackModel { get { return ModelCenter.Instance.GetModel<VirtualPackModel>(); } }
                RuneData data = model.runePackList[index];
                m_RuneBtns[i].onClick.RemoveAllListeners();
                m_RuneBtns[i].onClick.AddListener(() =>
                {
                    OnClickRunePackItem(data);
                });
            public void SetActive(bool acitve)
            {
                m_Container.gameObject.SetActive(acitve);
            }
                ItemConfig item = ItemConfig.Get(data.id);
                m_RuneNameLvTxts[i].text =StringUtility.Contact(item.ItemName," lv.",data.lv);
                m_RuneNameLvTxts[i].color = UIHelper.GetUIColor(item.ItemColor, true);
                m_RuneIcons[i].SetSprite(item.IconKey);
                m_RuneAttrTxts[i].text = StringUtility.Contact(model.GetRuneAttrStr(data.id, data.lv));
                bool _same = model.IsSameInHoleRune(data.id, model.sltRuneHole);
                m_EquipedImgs[i].gameObject.SetActive(_same);
                m_Redpoints[i].gameObject.SetActive(model.IsBetterRune(data, model.sltRuneHole) && !_same);
            }
        }
            public void Display(int index)
            {
                RuneItem item;
                if (virtualPackModel.TryGetItem(PackType.RunePack, index, out item))
                {
                    var config = ItemConfig.Get(item.id);
                    m_RuneName.text = StringUtility.Contact(config.ItemName, " lv.", item.level);
                    m_RuneName.color = UIHelper.GetUIColor(config.ItemColor, true);
                    m_Icon.SetSprite(config.IconKey);
                    m_Property.text = StringUtility.Contact(model.GetRunePropertyDescription(item.id, item.level));
                    bool _same = model.IsSameWithOtherRuneHole(item.id, RunePackWin.selectHole);
                    m_SamePropertySign.gameObject.SetActive(_same);
                    m_RedpointSign.gameObject.SetActive(!_same && model.IsBetterRuneWithHole(item.id, RunePackWin.selectHole));
        private void OnClickRunePackItem(RuneData _rune)
        {
            if (model.sltRuneHole == -1)
            {
                ServerTipDetails.DisplayNormalTip(Language.Get("L1061"));
                return;
            }
            var sltHoleRune = model.GetHoleRune(model.sltRuneHole);
            bool switchOtherSameHole = false;
            List<int> sameHoles = new List<int>();
            if (sltHoleRune == null || runeComposeModel.m_RuneBothPropertys.Contains(sltHoleRune.id)
                || !runeComposeModel.m_RuneBothPropertys.Contains(_rune.id))
            {
                if (model.IsSameInHoleRune(_rune.id, model.sltRuneHole))
                {
                    ServerTipDetails.DisplayNormalTip(Language.Get("L1078"));
                    return;
                }
            }
            else
            {
                model.IsSameRune(_rune.id, ref sameHoles);
                if (sameHoles.Count > 0 && !sameHoles.Contains(model.sltRuneHole))
                {
                    ServerTipDetails.DisplayNormalTip(Language.Get("L1078"));
                    return;
                }
                if (sameHoles.Count > 1)
                {
                    switchOtherSameHole = true;
                    m_Select.SetListener(() =>
                    {
                        OnSelectItem(item);
                    });
                }
            }
            if (runeComposeModel.m_RuneBothPropertys.Contains(_rune.id)
                && model.GetDoublePropLimitCount() <= model.GetCurrentDoublePropCount()
                && (sltHoleRune == null || !runeComposeModel.m_RuneBothPropertys.Contains(sltHoleRune.id)))
            private void OnSelectItem(RuneItem item)
            {
                var _count = model.GetDoublePropLimitCount();
                SysNotifyMgr.Instance.ShowTip("RuneGridUnEnough", _count);
                return;
                model.SelectRunePackItem(item, RunePackWin.selectHole);
            }
            if (switchOtherSameHole)
            {
                var otherSameHole = sameHoles[0] == model.sltRuneHole ? sameHoles[1] : sameHoles[0];
                var otherRune = model.GetHoleRune(otherSameHole);
                ConfirmCancel.ShowPopConfirm(Language.Get("Mail101"), Language.Get("SwitchDoublePropertyRune"), (Action<bool>)((bool isOk) =>
                  {
                      if (isOk)
                      {
                          SwitchRune(otherRune.packtype, otherSameHole, _rune.packtype, 0);
                          SwitchRune(_rune.packtype, _rune.index, (int)PackType.InterimPack, model.sltRuneHole);
                          WindowCenter.Instance.Close<RunePackWin>();
                      }
                  }));
            }
            else
            {
                SwitchRune(_rune.packtype, _rune.index, (int)PackType.InterimPack, model.sltRuneHole);
                WindowCenter.Instance.Close<RunePackWin>();
            }
        }
        void SwitchRune(int srcpackType,int scrIndex,int destpackType,int destIndex)
        {
            C073D_tagCPackItemExchange pak = new C073D_tagCPackItemExchange();
            pak.SrcBackpack = (byte)srcpackType;
            pak.SrcIndex = (ushort)scrIndex;
            pak.DesBackPack = (byte)destpackType;
            pak.DestIndex = (ushort)destIndex;
            GameNetSystem.Instance.SendInfo(pak);
        }
    }
}
System/Rune/RunePackWin.cs
@@ -16,19 +16,24 @@
    public class RunePackWin : Window
    {
        [SerializeField] ScrollerController packController;
        [SerializeField] Text runePackCap;
        [SerializeField] Button runePackClostBtn;
        [SerializeField] Button m_RuneGetBtn;
        [SerializeField] Button m_RuneComposeBtn;
        [SerializeField] ScrollerController m_ScrollController;
        [SerializeField] Text m_Capacity;
        [SerializeField] Button m_GetRune;
        [SerializeField] Button m_Compose;
        [SerializeField] Button m_Close;
        List<int> itemIndexs = new List<int>();
        RuneModel m_Model;
        RuneModel model
        {
            get
            {
                return m_Model ?? (m_Model = ModelCenter.Instance.GetModel<RuneModel>());
            }
        public static int selectHole = 0;
        RuneModel runeModel
        {
            get { return ModelCenter.Instance.GetModel<RuneModel>(); }
        }
        VirtualPackModel model
        {
            get { return ModelCenter.Instance.GetModel<VirtualPackModel>(); }
        }
        #region Built-in
        protected override void BindController()
@@ -37,20 +42,17 @@
        protected override void AddListeners()
        {
            runePackClostBtn.onClick.AddListener(OnRunePackClose);
            m_RuneGetBtn.onClick.AddListener(OnRuneGetBtn);
            m_RuneComposeBtn.onClick.AddListener(OnRuneComposeBtn);
        }
            m_Close.AddListener(CloseClick);
            m_GetRune.AddListener(OnRuneGetBtn);
            m_Compose.AddListener(OnRuneComposeBtn);
        private void OnRunePackClose()
        {
            CloseClick();
        }
            m_ScrollController.OnRefreshCell += OnRefreshCell;
        }
        protected override void OnPreOpen()
        {
            model.OnRefreshRunePack += OnRunePackRefresh;
            OnRunePackRefresh();
            model.virtualPackRefresh += VirtualPackRefresh;
            Display();
        }
        protected override void OnAfterOpen()
@@ -58,77 +60,105 @@
        }
        protected override void OnPreClose()
        {
        {
            model.virtualPackRefresh -= VirtualPackRefresh;
        }
        protected override void OnAfterClose()
        {
            model.OnRefreshRunePack -= OnRunePackRefresh;
        }
        #endregion
        /// <summary>
        /// 对符文背包里进行排序
        /// 1.按品质降序
        /// 2.按等级降序
        /// 3.按id降序
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        private int Compare(RuneData x, RuneData y)
        {
            ItemConfig xItemCfg = ItemConfig.Get(x.id);
            ItemConfig yItemCfg = ItemConfig.Get(y.id);
            bool xSame = model.IsSameInHoleRune(xItemCfg.ID, model.sltRuneHole);
            bool ySame = model.IsSameInHoleRune(yItemCfg.ID, model.sltRuneHole);
            if (xSame.CompareTo(ySame) != 0) return xSame.CompareTo(ySame);
            if (xItemCfg.ItemColor.CompareTo(yItemCfg.ItemColor) != 0) return -xItemCfg.ItemColor.CompareTo(yItemCfg.ItemColor);
            else if (x.lv.CompareTo(y.lv) != 0) return -x.lv.CompareTo(y.lv);
            else if (x.id.CompareTo(y.id) != 0) return -x.id.CompareTo(y.id);
            else return 1;
        }
        void OnRunePackRefresh()
        {
            packController.Refresh();
            if (model.runePackList != null)
            {
                model.runePackList.Clear();
            }
            else
            {
                model.runePackList = new List<RuneData>();
            }
            List<RuneData> list = model.GetPackRune().Values.ToList();
            for (int i = 0; i < list.Count; i++)
            {
                RuneData data = list[i];
                ItemConfig cfg = ItemConfig.Get(data.id);
                if (cfg.Type == 30)
                {
                    model.runePackList.Add(data);
                }
            }
            model.runePackList.Sort(Compare);
            int itemCnt = Mathf.CeilToInt((float)model.runePackList.Count / 3);
            for (int i = 0; i < itemCnt; i++)
            {
                packController.AddCell(ScrollerDataType.Normal, i);
            }
            packController.Restart();
            runePackCap.text = StringUtility.Contact(model.GetPackRune().Count, "/",
                FuncConfigConfig.Get("RunePackageNum").Numerical1);
        void VirtualPackRefresh(PackType packType)
        {
            if (packType == PackType.RunePack)
            {
                Display();
            }
        }
        void Display()
        {
            m_ScrollController.Refresh();
            itemIndexs.Clear();
            List<int> _items = null;
            model.TryGetItems(PackType.RunePack, out _items);
            itemIndexs.AddRange(_items);
            itemIndexs.RemoveAll(ExcludeCream);
            itemIndexs.Sort(Compare);
            int line = Mathf.CeilToInt((float)itemIndexs.Count / 3);
            for (int i = 0; i < line; i++)
            {
                m_ScrollController.AddCell(ScrollerDataType.Normal, i);
            }
            m_ScrollController.Restart();
            m_Capacity.text = StringUtility.Contact(model.GetPackItemCount(PackType.RunePack), "/",
                model.GetPackCapacity(PackType.RunePack));
        }
        private bool ExcludeCream(int index)
        {
            RuneItem item;
            if (model.TryGetItem(PackType.RunePack, index, out item))
            {
                return item.itemType == RuneModel.RUNE_CREAMTYPE;
            }
            return true;
        }
        private void OnRefreshCell(ScrollerDataType type, CellView cell)
        {
            var runePackCell = cell as RunePackCell;
            runePackCell.Display(cell.index, itemIndexs);
        }
        private void OnRuneComposeBtn()
        {
            CloseImmediately();
            model.JumpToRuneCompose();
            runeModel.JumpToCompose();
        }
        private void OnRuneGetBtn()
        {
            CloseImmediately();
            WindowJumpMgr.Instance.WindowJumpTo(JumpUIType.RuneTower);
        }
        int Compare(int lhs, int rhs)
        {
            RuneItem lhsItem;
            RuneItem rhsItem;
            if (model.TryGetItem(PackType.RunePack, lhs, out lhsItem)
                && model.TryGetItem(PackType.RunePack, rhs, out rhsItem))
            {
                var lhsItemConfig = ItemConfig.Get(lhsItem.id);
                var rhsItemConfig = ItemConfig.Get(rhsItem.id);
                bool lhsSame = runeModel.IsSameWithOtherRuneHole(lhsItemConfig.ID, selectHole);
                bool rhsSame = runeModel.IsSameWithOtherRuneHole(rhsItemConfig.ID, selectHole);
                if (lhsSame != rhsSame)
                {
                    return lhsSame.CompareTo(rhsSame);
                }
                if (lhsItemConfig.ItemColor != rhsItemConfig.ItemColor)
                {
                    return -lhsItemConfig.ItemColor.CompareTo(rhsItemConfig.ItemColor);
                }
                if (lhsItem.level != rhsItem.level)
                {
                    return -lhsItem.level.CompareTo(rhsItem.level);
                }
                else if (lhsItem.id != rhsItem.id)
                {
                    return -lhsItem.id.CompareTo(rhsItem.id);
                }
            }
            return 1;
        }
    }
System/Rune/RunePanel.cs
@@ -20,14 +20,7 @@
        [SerializeField] Button rightBtn;
        [SerializeField] Button closeBtn;
        RuneModel m_Model;
        RuneModel model
        {
            get
            {
                return m_Model ?? (m_Model = ModelCenter.Instance.GetModel<RuneModel>());
            }
        }
        RuneModel model { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
        protected override void BindController()
        {
@@ -54,7 +47,7 @@
        {
            CloseChild();
            functionOrder = 1;
            WindowCenter.Instance.Open<RuneBreakWin>();
            WindowCenter.Instance.Open<RuneResolveWin>();
        }
        private void OnRuneMosaic()
@@ -66,7 +59,7 @@
        protected override void OnPreOpen()
        {
            model.JumpToComposeEvent += JumpToComposeEvent;
            model.onJumpToCompose += JumpToComposeEvent;
            CloseChild();
        }
@@ -80,7 +73,7 @@
        }
        protected override void OnPreClose()
        {
            model.JumpToComposeEvent -= JumpToComposeEvent;
            model.onJumpToCompose -= JumpToComposeEvent;
            CloseChild();
        }
        protected override void OnAfterClose()
System/Rune/RunePreviewCell.cs
@@ -62,7 +62,7 @@
                    _runeTowerCfg = RuneTowerFloorConfig.Get(_runeCfg.TowerID);
                    _towerCfg = RuneTowerConfig.Get(_runeTowerCfg.TowerId);
                }
                _itemPathModel.SetRuneModel(itemCfg.ID, 1, model.GetRuneAttrStr(itemCfg.ID, 1),
                _itemPathModel.SetRuneModel(itemCfg.ID, 1, model.GetRunePropertyDescription(itemCfg.ID, 1),
                    _runeCfg.TowerID == 0 ? Language.Get("L1062") : Language.Get("RuneItemOrigin", _towerCfg.TowerName, _runeTowerCfg.FloorName));
            }
        }
System/Rune/RuneResolveCell.cs
New file
@@ -0,0 +1,123 @@
using Snxxz.UI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
namespace Snxxz.UI
{
    [XLua.Hotfix]
    public class RuneResolveCell : CellView
    {
        [SerializeField] RuneResolveItem[] m_ResolveItems;
        RuneResolveModel runeResolveModel { get { return ModelCenter.Instance.GetModel<RuneResolveModel>(); } }
        List<int> itemIndexs { get { return runeResolveModel.itemIndexs; } }
        public void Display(int line)
        {
            for (int i = 0; i < m_ResolveItems.Length; i++)
            {
                var index = line * m_ResolveItems.Length + i;
                m_ResolveItems[i].SetActive(index < itemIndexs.Count);
                if (index < itemIndexs.Count)
                {
                    m_ResolveItems[i].Display(line, index);
                }
            }
        }
    }
    [Serializable]
    public class RuneResolveItem
    {
        [SerializeField] Transform m_Container;
        [SerializeField] Image m_Icon;
        [SerializeField] Text m_RuneName;
        [SerializeField] Text m_Property;
        [SerializeField] Transform m_ContainerSelect;
        [SerializeField] Button m_Select;
        RuneModel model { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
        RuneResolveModel runeResolveModel { get { return ModelCenter.Instance.GetModel<RuneResolveModel>(); } }
        VirtualPackModel virtualPackModel { get { return ModelCenter.Instance.GetModel<VirtualPackModel>(); } }
        List<Transform> resolveObjs { get { return runeResolveModel.resolveObjs; } }
        List<int> itemIndexs { get { return runeResolveModel.itemIndexs; } }
        Dictionary<int, bool> resolveSigns { get { return runeResolveModel.resolveSigns; } }
        public void Display(int line, int index)
        {
            if (index < itemIndexs.Count)
            {
                var packIndex = itemIndexs[index];
                RuneItem item;
                if (!virtualPackModel.TryGetItem(PackType.RunePack, packIndex, out item))
                {
                    return;
                }
                m_Select.SetListener(() =>
                {
                    OnSelect(line, index);
                });
                var config = ItemConfig.Get(item.id);
                if (item.itemType == RuneModel.RUNE_TYPE)
                {
                    m_RuneName.text = StringUtility.Contact(config.ItemName, " lv.", item.level);
                    m_Property.text = model.GetRunePropertyDescription(item.id, item.level);
                }
                else if (item.itemType == RuneModel.RUNE_CREAMTYPE)
                {
                    m_RuneName.text = config.ItemName;
                    m_Property.text = Language.Get("L1079", config.EffectValueA1);
                }
                m_RuneName.color = UIHelper.GetUIColor(config.ItemColor, true);
                m_Icon.SetSprite(config.IconKey);
                bool selected = resolveSigns.ContainsKey(index) && resolveSigns[index];
                m_ContainerSelect.gameObject.SetActive(selected);
                if (selected)
                {
                    if (!resolveObjs.Contains(m_Container))
                    {
                        resolveObjs.Add(m_Container);
                    }
                }
                else
                {
                    if (resolveObjs.Contains(m_Container))
                    {
                        resolveObjs.Remove(m_Container);
                    }
                }
            }
        }
        private void OnSelect(int line, int index)
        {
            if (resolveSigns.ContainsKey(index))
            {
                resolveSigns[index] = !resolveSigns[index];
            }
            runeResolveModel.RefreshResolveSelect(line);
        }
        public void SetActive(bool active)
        {
            m_Container.gameObject.SetActive(active);
            if (!active && resolveObjs.Contains(m_Container))
            {
                resolveObjs.Remove(m_Container);
            }
        }
    }
}
System/Rune/RuneResolveCell.cs.meta
File was renamed from System/Rune/RuneBreakCell.cs.meta
@@ -1,12 +1,12 @@
fileFormatVersion: 2
guid: 03abe2a6e856101419eddf66c4ac3e5f
timeCreated: 1515063903
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
fileFormatVersion: 2
guid: 03abe2a6e856101419eddf66c4ac3e5f
timeCreated: 1515063903
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
System/Rune/RuneResolveModel.cs
New file
@@ -0,0 +1,172 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Snxxz.UI
{
    [XLua.LuaCallCSharp]
    [XLua.Hotfix]
    public class RuneResolveModel : Model, IBeforePlayerDataInitialize, IPlayerLoginOk
    {
        Dictionary<int, float> m_RuneBaseResolveSplinters;
        public List<ushort> resolveItems = new List<ushort>();
        public List<Transform> resolveObjs = new List<Transform>();
        public List<int> itemIndexs = new List<int>();
        public Dictionary<int, bool> resolveSigns = new Dictionary<int, bool>();
        bool specialItemColorSign = false;
        public readonly Redpoint redpoint = new Redpoint(108, 10802);
        public event Action<int> onResolveSelect;
        RuneModel runeModel { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
        VirtualPackModel virtualPackModel { get { return ModelCenter.Instance.GetModel<VirtualPackModel>(); } }
        public override void Init()
        {
            ParseConfig();
            StageLoad.Instance.onStageLoadFinish += OnStageLoadFinish;
            virtualPackModel.virtualPackRefresh += VirtualPackRefresh;
            FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
        }
        public void OnBeforePlayerDataInitialize()
        {
        }
        public void OnPlayerLoginOk()
        {
        }
        public override void UnInit()
        {
            StageLoad.Instance.onStageLoadFinish -= OnStageLoadFinish;
            virtualPackModel.virtualPackRefresh -= VirtualPackRefresh;
            FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
        }
        private void OnFuncStateChangeEvent(int id)
        {
            if (id == (int)FuncOpenEnum.Rune)
            {
                RefreshRedpoint();
            }
        }
        private void OnStageLoadFinish()
        {
            if (!(StageLoad.Instance.currentStage is DungeonStage))
            {
                specialItemColorSign = false;
            }
        }
        void ParseConfig()
        {
            var config = FuncConfigConfig.Get("RuneExp");
            m_RuneBaseResolveSplinters = ConfigParse.GetDic<int, float>(config.Numerical4);
        }
        public bool IsQualitySign(int itemColor)
        {
            if (itemColor == 4)
            {
                return specialItemColorSign;
            }
            var playerId = PlayerDatas.Instance.baseData.PlayerID;
            return LocalSave.GetBool(StringUtility.Contact("RuneBreakSelect_", playerId, "_", itemColor), itemColor == 1);
        }
        public bool IsComposeSource(int sourceType)
        {
            if (sourceType == 0 || sourceType == 2)
            {
                return true;
            }
            return false;
        }
        public float GetRuneResolveGetSplinters(int id, int level, bool fromCompose = false)
        {
            var result = 0f;
            var config = ItemConfig.Get(id);
            var _treasureSoul = ModelCenter.Instance.GetModel<TreasureSoulModel>();
            var _upper = (float)_treasureSoul.GetTreasureSoulValue((int)TreasurePrivilege.RuneBreakExpAdd) / 10000;
            if (config.Type == RuneModel.RUNE_CREAMTYPE)
            {
                return config.EffectValueA1 + config.EffectValueA1 * _upper;
            }
            for (int i = 1; i <= level; i++)
            {
                if (i == 1 && !fromCompose)
                {
                    result += m_RuneBaseResolveSplinters[config.ItemColor] +
                        m_RuneBaseResolveSplinters[config.ItemColor] * _upper;
                }
                else
                {
                    result += runeModel.GetLevelUpRequireRuneEssence(id, i - 1);
                }
            }
            return result;
        }
        public float GetRuneResolveGetSouls(int id)
        {
            ItemConfig config = ItemConfig.Get(id);
            var _treasureSoul = ModelCenter.Instance.GetModel<TreasureSoulModel>();
            var _upper = (float)_treasureSoul.GetTreasureSoulValue((int)TreasurePrivilege.RuneBreakExpAdd) / 10000;
            if (config.Type == RuneModel.RUNE_CREAMTYPE)
            {
                return config.EffectValueA1 * _upper;
            }
            else
            {
                return m_RuneBaseResolveSplinters[config.ItemColor] * _upper;
            }
        }
        public void SetQualityMark(int itemColor, bool mark)
        {
            if (itemColor == 4)
            {
                specialItemColorSign = mark;
                return;
            }
            var playerId = PlayerDatas.Instance.baseData.PlayerID;
            LocalSave.SetBool(StringUtility.Contact("RuneBreakSelect_", playerId, "_", itemColor), mark);
        }
        public void RefreshResolveSelect(int line)
        {
            if (onResolveSelect != null)
            {
                onResolveSelect(line);
            }
        }
        private void VirtualPackRefresh(PackType packType)
        {
            if (packType == PackType.RunePack)
            {
                RefreshRedpoint();
            }
        }
        void RefreshRedpoint()
        {
            var satisfyResolve = false;
            if (FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Rune))
            {
                if (virtualPackModel.GetPackRemainCount(PackType.RunePack) == 0)
                {
                    satisfyResolve = true;
                }
            }
            redpoint.state = satisfyResolve ? RedPointState.Simple : RedPointState.None;
        }
    }
}
System/Rune/RuneResolveModel.cs.meta
copy from System/Store/RuneStoreWin.cs.meta copy to System/Rune/RuneResolveModel.cs.meta
File was copied from System/Store/RuneStoreWin.cs.meta
@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: 85daa664b183120498a12cba52019f7d
timeCreated: 1505701787
guid: 89a6ca1ecdbe4244dbcd205c9827f083
timeCreated: 1552985089
licenseType: Pro
MonoImporter:
  serializedVersion: 2
System/Rune/RuneResolveWin.cs
New file
@@ -0,0 +1,375 @@

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
namespace Snxxz.UI
{
    public class RuneResolveWin : Window
    {
        [SerializeField] Text m_ItemCount0;
        [SerializeField] Text m_ItemCount1;
        [SerializeField] Text m_ItemResolveCount0;
        [SerializeField] Text m_ItemResolveCount1;
        [SerializeField] Button m_Resolve;
        [SerializeField] ScrollerController m_Controller;
        [SerializeField] List<Button> m_CheckBtns;
        [SerializeField] Transform[] m_CheckSigns;
        [SerializeField] UIEffect m_FlutterEffect;
        [SerializeField] UIEffect m_AbsorbEffect;
        [SerializeField] Button m_JumpBtn0;
        [SerializeField] Button m_JumpBtn1;
        [SerializeField] RectTransform m_ContainerRuneSoul;
        [SerializeField] Text m_RuneSoulAdd;
        List<ushort> resolveItems { get { return runeResolveModel.resolveItems; } }
        List<Transform> resolveObjs { get { return runeResolveModel.resolveObjs; } }
        List<int> itemIndexs { get { return runeResolveModel.itemIndexs; } }
        Dictionary<int, bool> resolveSigns { get { return runeResolveModel.resolveSigns; } }
        bool doResolveItem = false;
        RuneModel model { get { return ModelCenter.Instance.GetModel<RuneModel>(); } }
        RuneResolveModel runeResolveModel { get { return ModelCenter.Instance.GetModel<RuneResolveModel>(); } }
        VirtualPackModel virtualPackModel { get { return ModelCenter.Instance.GetModel<VirtualPackModel>(); } }
        TreasureSoulModel treasureSoulModel { get { return ModelCenter.Instance.GetModel<TreasureSoulModel>(); } }
        RuneComposeModel runeComposeModel { get { return ModelCenter.Instance.GetModel<RuneComposeModel>(); } }
        protected override void BindController()
        {
        }
        protected override void AddListeners()
        {
            m_Resolve.onClick.AddListener(OnResolve);
            for (int i = 0; i < m_CheckBtns.Count; i++)
            {
                int itemColor = i + 1;
                m_CheckBtns[i].onClick.AddListener(() =>
                {
                    OnClickCheck(itemColor);
                });
            }
            m_JumpBtn0.onClick.AddListener(OnJumpRuneTower);
            m_JumpBtn1.onClick.AddListener(OnJumpRuneTower);
            m_Controller.OnRefreshCell += OnRefreshCell;
        }
        protected override void OnPreOpen()
        {
            virtualPackModel.virtualPackRefresh += VirtualPackRefresh;
            PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefreshInfoEvent;
            runeResolveModel.onResolveSelect += OnResolveSelect;
            doResolveItem = false;
            DisplayRuneItems();
            m_ContainerRuneSoul.gameObject.SetActive(treasureSoulModel.IsGetTreasureSoul((int)TreasurePrivilege.RuneBreakExpAdd));
        }
        protected override void OnAfterOpen()
        {
            HandleAchievement();
        }
        protected override void OnPreClose()
        {
            doResolveItem = false;
            virtualPackModel.virtualPackRefresh -= VirtualPackRefresh;
            PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefreshInfoEvent;
            runeResolveModel.onResolveSelect -= OnResolveSelect;
            StopAllCoroutines();
        }
        protected override void OnAfterClose()
        {
        }
        private void VirtualPackRefresh(PackType packType)
        {
            if (packType == PackType.RunePack)
            {
                DisplayRuneItems();
                RefreshResolveGetItems();
            }
        }
        private void OnResolve()
        {
            resolveItems.Clear();
            foreach (var key in resolveSigns.Keys)
            {
                if (resolveSigns[key]
                    && key < itemIndexs.Count)
                {
                    var index = itemIndexs[key];
                    RuneItem item;
                    if (virtualPackModel.TryGetItem(PackType.RunePack, index, out item))
                    {
                        resolveItems.Add((ushort)item.index);
                    }
                }
            }
            if (resolveItems.Count < 1)
            {
                ServerTipDetails.DisplayNormalTip(Language.Get("L1059"));
                return;
            }
            var page = Mathf.CeilToInt((float)resolveItems.Count / 50);
            doResolveItem = true;
            for (int i = 0; i < page; i++)
            {
                ushort[] resolves = resolveItems.Skip(i * 50).Take((i < page - 1) ? 50 : (resolveItems.Count - i * 50)).ToArray();
                var pak = new CA566_tagCMRuneDecompose();
                pak.QualityCnt = 0;
                pak.QualityList = new byte[0];
                pak.PlaceIndexList = resolves;
                pak.Count = (byte)resolves.Length;
                GameNetSystem.Instance.SendInfo(pak);
            }
        }
        void OnClickCheck(int itemColor)
        {
            bool check = runeResolveModel.IsQualitySign(itemColor);
            OnCheck(itemColor, !check);
        }
        private void OnCheck(int itemColor, bool check)
        {
            runeResolveModel.SetQualityMark(itemColor, check);
            var checkSign = GetCheckSign(itemColor);
            if (checkSign != null)
            {
                checkSign.gameObject.SetActive(runeResolveModel.IsQualitySign(itemColor));
            }
            for (int i = 0; i < itemIndexs.Count; i++)
            {
                var index = itemIndexs[i];
                RuneItem item;
                if (virtualPackModel.TryGetItem(PackType.RunePack, index, out item))
                {
                    var config = ItemConfig.Get(item.id);
                    if (config.ItemColor == itemColor && config.Type == RuneModel.RUNE_TYPE)
                    {
                        resolveSigns[i] = check;
                    }
                }
            }
            m_Controller.m_Scorller.RefreshActiveCellViews();
            RefreshResolveGetItems();
        }
        void DisplayRuneItems()
        {
            if (resolveObjs.Count > 0 && doResolveItem)
            {
                var _time = 0.0f;
                for (int i = 0; i < resolveObjs.Count; i++)
                {
                    if (resolveObjs[i] != null)
                    {
                        resolveObjs[i].gameObject.SetActive(false);
                        var _uieffect = EffectMgr.Instance.PlayUIEffect(1007, 2500, resolveObjs[i].parent, false);
                        _time = _uieffect != null ? _uieffect.duration : 0.0f;
                        _uieffect.target.transform.localPosition = resolveObjs[i].localPosition;
                    }
                }
                doResolveItem = false;
                StartCoroutine(Co_PlayEffect(_time));
            }
            else
            {
                DisplayResolveItems();
            }
        }
        IEnumerator Co_PlayEffect(float _t)
        {
            yield return WaitingForSecondConst.GetWaitForSeconds(_t);
            DisplayResolveItems();
            m_FlutterEffect.Play();
            m_FlutterEffect.OnComplete = OnFlutterComplete;
        }
        void DisplayResolveItems()
        {
            resolveObjs.Clear();
            DisplayRunes();
            ResetResolveSelect();
        }
        void ResetResolveSelect()
        {
            resolveSigns.Clear();
            for (int i = 0; i < itemIndexs.Count; i++)
            {
                var index = itemIndexs[i];
                RuneItem item;
                if (virtualPackModel.TryGetItem(PackType.RunePack, index, out item))
                {
                    resolveSigns[i] = item.itemType == RuneModel.RUNE_CREAMTYPE;
                }
            }
            OnCheck(1, runeResolveModel.IsQualitySign(1));
            OnCheck(2, runeResolveModel.IsQualitySign(2));
            OnCheck(3, runeResolveModel.IsQualitySign(3));
            OnCheck(4, runeResolveModel.IsQualitySign(4));
        }
        private void OnFlutterComplete()
        {
            m_AbsorbEffect.Play();
        }
        void DisplayRunes()
        {
            m_Controller.Refresh();
            virtualPackModel.GetItemIndexs(PackType.RunePack, ref runeResolveModel.itemIndexs);
            itemIndexs.Sort(Compare);
            int _line = Mathf.CeilToInt((float)itemIndexs.Count / 4);
            for (int i = 0; i < _line; i++)
            {
                m_Controller.AddCell(ScrollerDataType.Normal, i);
            }
            m_Controller.Restart();
        }
        void RefreshResolveGetItems()
        {
            float _itemCnt = 0;
            float _magicCnt = 0;
            float _soulCnt = 0;
            foreach (int key in resolveSigns.Keys)
            {
                if (!resolveSigns[key])
                {
                    continue;
                }
                if (key < itemIndexs.Count)
                {
                    var index = itemIndexs[key];
                    RuneItem item;
                    if (virtualPackModel.TryGetItem(PackType.RunePack, index, out item))
                    {
                        _itemCnt += runeResolveModel.GetRuneResolveGetSplinters(item.id, item.level);
                        _soulCnt += runeResolveModel.GetRuneResolveGetSouls(item.id);
                        if (model.IsMultiPropertyRune(item.id)
                            && runeResolveModel.IsComposeSource(item.sourceType))
                        {
                            var composeConfig = RuneComposeConfig.Get(item.id);
                            _magicCnt += (composeConfig == null ? 0 : composeConfig.NeedMJ);
                        }
                    }
                }
            }
            m_ItemCount1.text = UIHelper.ReplaceLargeNum(PlayerDatas.Instance.extersion.runeEssence);
            m_ItemCount0.text = UIHelper.ReplaceLargeNum(PlayerDatas.Instance.extersion.magicEssence);
            m_ItemResolveCount1.gameObject.SetActive(_itemCnt != 0);
            m_ItemResolveCount0.gameObject.SetActive(_magicCnt != 0);
            m_ItemResolveCount0.text = StringUtility.Contact("+", UIHelper.ReplaceLargeNum(_magicCnt));
            m_ItemResolveCount1.text = StringUtility.Contact("+", UIHelper.ReplaceLargeNum((int)_itemCnt));
            m_RuneSoulAdd.text = Language.Get("RuneSoul", UIHelper.ReplaceLargeNum((int)_soulCnt));
        }
        private void OnRefreshCell(ScrollerDataType type, CellView cell)
        {
            var resolveCell = cell as RuneResolveCell;
            resolveCell.Display(cell.index);
        }
        private void OnJumpRuneTower()
        {
            WindowJumpMgr.Instance.WindowJumpTo(JumpUIType.RuneTower);
        }
        private void PlayerDataRefreshInfoEvent(PlayerDataType type)
        {
            if (type == PlayerDataType.MagicEssence
                || type == PlayerDataType.RuneSplinters)
            {
                RefreshResolveGetItems();
            }
        }
        private void OnResolveSelect(int line)
        {
            m_Controller.RefreshSingleCellView(line);
            RefreshResolveGetItems();
        }
        void HandleAchievement()
        {
            if (AchievementGoto.achievementType == AchievementGoto.RuneResolve)
            {
                var _effect = AchievementGuideEffectPool.Require(1);
                _effect.transform.SetParentEx(m_Resolve.transform, Vector3.zero, Vector3.zero, Vector3.one);
            }
        }
        Transform GetCheckSign(int itemColor)
        {
            switch (itemColor)
            {
                case 1:
                    return m_CheckSigns.Length > 0 ? m_CheckSigns[0] : null;
                case 2:
                    return m_CheckSigns.Length > 1 ? m_CheckSigns[1] : null;
                case 3:
                    return m_CheckSigns.Length > 2 ? m_CheckSigns[2] : null;
                case 4:
                    return m_CheckSigns.Length > 3 ? m_CheckSigns[3] : null;
            }
            return null;
        }
        int Compare(int lhs, int rhs)
        {
            RuneItem lhsItem = null;
            RuneItem rhsItem = null;
            if (virtualPackModel.TryGetItem(PackType.RunePack, lhs, out lhsItem)
                && virtualPackModel.TryGetItem(PackType.RunePack, rhs, out rhsItem))
            {
                var lhsConfig = ItemConfig.Get(lhsItem.id);
                var rhsConfig = ItemConfig.Get(rhsItem.id);
                if (lhsConfig.Type != rhsConfig.Type)
                {
                    return lhsConfig.Type.CompareTo(rhsConfig.Type);
                }
                if (lhsConfig.ItemColor != rhsConfig.ItemColor)
                {
                    return -lhsConfig.ItemColor.CompareTo(rhsConfig.ItemColor);
                }
                if (lhsItem.level != rhsItem.level)
                {
                    return -lhsItem.level.CompareTo(rhsItem.level);
                }
                if (lhsItem.id != rhsItem.id)
                {
                    return -lhsItem.id.CompareTo(rhsItem.id);
                }
            }
            return 1;
        }
    }
}
System/Rune/RuneResolveWin.cs.meta
File was renamed from System/Rune/RuneBreakWin.cs.meta
@@ -1,12 +1,12 @@
fileFormatVersion: 2
guid: ab2286940b7791142b81cd3fdbe82fff
timeCreated: 1502109023
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
fileFormatVersion: 2
guid: ab2286940b7791142b81cd3fdbe82fff
timeCreated: 1502109023
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
System/RuneTower/RunePreviewBehaviour.cs
@@ -49,7 +49,7 @@
            }
            var runeModel = ModelCenter.Instance.GetModel<RuneModel>();
            var propertyValue = runeModel.GetRuneAttrStr(runeId, 1);
            var propertyValue = runeModel.GetRunePropertyDescription(runeId, 1);
            var model = ModelCenter.Instance.GetModel<GetItemPathModel>();
            model.SetRuneModel(runeId, 1, propertyValue, Language.Get("RuneItemOrigin", runeTowerConfig.TowerName, towerFloorConfig.FloorName));
System/RuneTower/RuneTowerModel.cs
@@ -29,7 +29,7 @@
        }
        public bool allTowerCompleted {
            get { return (int)runeModel.RuneTowerOpenLV == sortedFloors[sortedFloors.Count - 1]; }
            get { return (int)runeModel.passRuneTowerFloor == sortedFloors[sortedFloors.Count - 1]; }
        }
        public int currentFloor {
@@ -37,7 +37,7 @@
                var floor = sortedFloors[sortedFloors.Count - 1];
                for (int i = 0; i < sortedFloors.Count; i++)
                {
                    if (sortedFloors[i] > (int)runeModel.RuneTowerOpenLV)
                    if (sortedFloors[i] > (int)runeModel.passRuneTowerFloor)
                    {
                        floor = sortedFloors[i];
                        break;
@@ -112,13 +112,13 @@
        {
            ParseConfig();
            runeModel.OnRefreshRuneTowerLv += OnPassNewTowerFloor;
            runeModel.onRuneTowerRefresh += OnPassNewTowerFloor;
            dailyModel.dailyQuestProgressUpdateEvent += OnRuneTowerSweepTimeChange;
        }
        public override void UnInit()
        {
            runeModel.OnRefreshRuneTowerLv -= OnPassNewTowerFloor;
            runeModel.onRuneTowerRefresh -= OnPassNewTowerFloor;
            dailyModel.dailyQuestProgressUpdateEvent -= OnRuneTowerSweepTimeChange;
        }
@@ -197,7 +197,7 @@
            for (int i = 0; i < sortedFloors.Count; i++)
            {
                var floor = sortedFloors[i];
                if (floor <= (int)ModelCenter.Instance.GetModel<RuneModel>().RuneTowerOpenLV)
                if (floor <= (int)ModelCenter.Instance.GetModel<RuneModel>().passRuneTowerFloor)
                {
                    var config = RuneTowerFloorConfig.Get(floor);
                    if (!passedTowers.Contains(config.TowerId))
@@ -351,13 +351,13 @@
        private void OnPassNewTowerFloor()
        {
            if (serverInited && runeModel.RuneTowerOpenLV != 0)
            if (serverInited && runeModel.passRuneTowerFloor != 0)
            {
                var config = RuneTowerFloorConfig.Get((int)runeModel.RuneTowerOpenLV);
                var config = RuneTowerFloorConfig.Get((int)runeModel.passRuneTowerFloor);
                if (config.UnLockRune > 0)
                {
                    newPassFloor = (int)runeModel.RuneTowerOpenLV;
                    newPassFloor = (int)runeModel.passRuneTowerFloor;
                    PopupWindowsProcessor.Instance.Add("RuneNewGotWin");
                }
System/RuneTower/RuneTowerPassedInfoPanel.cs
@@ -39,7 +39,7 @@
                    }
                    else
                    {
                        var latestPassedFloor = ModelCenter.Instance.GetModel<RuneModel>().RuneTowerOpenLV;
                        var latestPassedFloor = ModelCenter.Instance.GetModel<RuneModel>().passRuneTowerFloor;
                        behaviour.Display(towerId, (int)latestPassedFloor);
                    }
                }
@@ -54,7 +54,7 @@
        private int GetTowerState(int _towerId)
        {
            var latestPassedFloor = ModelCenter.Instance.GetModel<RuneModel>().RuneTowerOpenLV;
            var latestPassedFloor = ModelCenter.Instance.GetModel<RuneModel>().passRuneTowerFloor;
            var lastPassTowerId = -1;
            if (latestPassedFloor > 0)
            {
System/Store/RuneCell.cs
File was deleted
System/Store/RuneCell.cs.meta
File was deleted
System/Store/RuneStoreWin.cs
File was deleted
System/Store/StoreModel.cs
@@ -641,16 +641,10 @@
    public bool TryGetUnlockRune(int runeId)
    {
        Dictionary<int, List<int>> unlockRunelist = runeModel.GetAllUnlockRuneIdlist();
        if (unlockRunelist != null)
        List<int> unlockRunes = runeModel.GetUnlockRunes();
        if (unlockRunes.Contains(runeId))
        {
            foreach (var tower in unlockRunelist.Keys)
            {
                if (unlockRunelist[tower].Contains(runeId))
                {
                    return true;
                }
            }
            return true;
        }
        return false;
    }
@@ -1060,7 +1054,7 @@
    /// <returns></returns>
    public bool IsCanBuyItem(int limitTower)
    {
        int playerTower = (int)runeModel.RuneTowerOpenLV;
        int playerTower = (int)runeModel.passRuneTowerFloor;
        int offset = playerTower - limitTower;
        return offset >= 0;
System/WindowBase/ModelCenter.cs
@@ -103,7 +103,6 @@
            RegisterModel<SkillModel>();
            RegisterModel<StoreModel>();
            RegisterModel<GetItemPathModel>();
            RegisterModel<RuneModel>();
            RegisterModel<TreasureModel>();
            RegisterModel<DailyQuestModel>();
            RegisterModel<FairyLeagueModel>();
@@ -229,6 +228,8 @@
            RegisterModel<AuctionHelpModel>();
            RegisterModel<EquipTrainModel>();
            RegisterModel<EquipStrengthModel>();
            RegisterModel<RuneModel>();
            RegisterModel<RuneResolveModel>();
            inited = true;
        }
Utility/UIHelper.cs
@@ -829,7 +829,7 @@
                }
            case 24:
                {
                    return (ulong)ModelCenter.Instance.GetModel<RuneModel>().RuneChip;
                    return (ulong)PlayerDatas.Instance.extersion.runeChip;
                }
            case 15:
                {