hch
6 天以前 1f7675733af28f2cdf393956705de0d399e9be10
117 【武将】武将系统 - 培养; 特效相加模式下 动态加载材质
50个文件已修改
1个文件已删除
29个文件已添加
1 文件已重命名
3270 ■■■■ 已修改文件
Main/Component/UI/Common/AdaptiveLayout.cs 434 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Common/ClickScreenOtherSpace.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Common/LayoutElementSizeClamp.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Effect/EffectPlayer.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Effect/UIEffectPlayer.cs 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/ConfigManager.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/EffectConfig.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/GetItemWaysConfig.cs 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroConfig.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroQualityAwakeConfig.cs 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/HeroQualityConfig.cs 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/PlayerPropertyConfig.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/WindowSearchConfig.cs 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/Configs/WindowSearchConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/HeroAwakeConfig.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/HeroQualityAwakeConfig.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/HeroQualityBreakConfig.cs 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/HeroQualityLVConfig.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/HeroQualityLVConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Config/PartialConfigs/PlayerPropertyConfig.cs 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB239_tagCSHeroRebirth.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB239_tagCSHeroRebirth.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB240_tagCSHeroDismiss.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB240_tagCSHeroDismiss.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/H07_PlayerItem/DTC0722_tagItemDeadLockRefresh.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HB1_Role/DTCB125_tagSCPlayerHeroInfo.cs 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DTCFile/ServerPack/HB1_Role/DTCB125_tagSCPlayerHeroInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HA8_Item/HA801_tagMCGiveAwardInfo.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HB1_Role/HB125_tagSCPlayerHeroInfo.cs 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Core/NetworkPackage/ServerPack/HB1_Role/HB125_tagSCPlayerHeroInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/ResModule/UILoader.cs 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HappyXB/HappyXBModel.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Hero/HeroInfo.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Hero/HeroManager.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Hero/UIHeroController.cs 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroAllAttrWin.cs 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroAllAttrWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroCardCell.cs 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroConnectionCell.cs 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroConnectionHeadCell.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroFormationCell.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroHeadBaseCell.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroLVBreakSuccessWin.cs 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroLVBreakSuccessWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroLVBreakWin.cs 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroLVBreakWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroListWin.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroPosHeadCell.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroScenePosCell.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroSkillWin.cs 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroSkillWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroTrainWin.cs 437 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroTrainWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/HeroUI/HeroUIManager.cs 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/ItemTip/BoxGetItemModel.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/ItemTip/ItemTipUtility.cs 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/ItemTip/ItemTipWayWin.cs 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/ItemTip/ItemTipWayWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/ItemTip/SmallTipWin.cs 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/ItemTip/SmallTipWin.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/KnapSack/Logic/ItemLogicUtility.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/KnapSack/Logic/SinglePack.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/KnapSack/New/CommonItemBaisc.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/KnapSack/PackManager.cs 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Message/HrefAnalysis.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Message/RichNormalEvent.cs 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Message/RichText.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/PhantasmPavilion/PhantasmPavilionModel.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/SkillUI/SkillBaseCell.cs 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Tip/ConfirmCancel.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Tip/ItemsConfirmWin.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/UIBase/UIBase.cs 78 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/UIBase/UIJumpManager.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/UIBase/UIJumpManager.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/CommonFunc.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/CommonFunc.cs.meta 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/ComponentExtersion.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/MathUtility.cs 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/MathUtils.cs 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/UIHelper.cs 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Component/UI/Common/AdaptiveLayout.cs
@@ -5,236 +5,236 @@
using System;
using Cysharp.Threading.Tasks;
    [ExecuteAlways]
    public class AdaptiveLayout : MonoBehaviour
[ExecuteAlways]
public class AdaptiveLayout : MonoBehaviour
{
    [SerializeField] HorizonOrVertical m_HorizonOrVerticle;
    [SerializeField] CanvasGroup m_CanvasGroup;
    [SerializeField] List<AdaptiveElement> m_AdapElements;
    [SerializeField] bool m_AutoIncludeChild=false;
    [SerializeField] float m_LeastHeight = 0f;
    [SerializeField] float m_LeastWidth = 0f;
    [SerializeField] float m_MaxHeight = 0f;
    [SerializeField] float m_MaxWidth = 0f;
    [NonSerialized] RectTransform m_Rect;
    public RectTransform rectTransform
    {
        [SerializeField] HorizonOrVertical m_HorizonOrVerticle;
        [SerializeField] CanvasGroup m_CanvasGroup;
        [SerializeField] List<AdaptiveElement> m_AdapElements;
        [SerializeField] bool m_AutoIncludeChild=false;
        [SerializeField] float m_LeastHeight = 0f;
        [SerializeField] float m_LeastWidth = 0f;
        [SerializeField] float m_MaxHeight = 0f;
        [SerializeField] float m_MaxWidth = 0f;
        [NonSerialized] RectTransform m_Rect;
        public RectTransform rectTransform
        get
        {
            if (m_Rect == null)
            {
                m_Rect = GetComponent<RectTransform>();
            }
            return m_Rect;
        }
    }
    public float Size
    {
        get
        {
            return m_HorizonOrVerticle == HorizonOrVertical.Horizon ? rectTransform.sizeDelta.x : rectTransform.sizeDelta.y;
        }
    }
    public event Action adaptiveUpdateEvent;
    private void OnEnable()
    {
        if (m_AdapElements == null)
        {
            enabled = false;
            return;
        }
        if (m_CanvasGroup != null)
        {
            m_CanvasGroup.alpha = 0;
            m_CanvasGroup.interactable = true;
            Co_DelayShow();
        }
    }
    private void TrackerRect(RectTransform _rect)
    {
        var _pivot = _rect.pivot;
        var _anchorMax = _rect.anchorMax;
        var _anchorMin = _rect.anchorMin;
        if (m_HorizonOrVerticle == HorizonOrVertical.Horizon)
        {
            _pivot.x = 0; _pivot.y = 0.5f;
            _anchorMax.x = 0; _anchorMax.y = 0.5f;
            _anchorMin.x = 0; _anchorMin.y = 0.5f;
        }
        else
        {
            _pivot.x = 0.5f; _pivot.y = 1f;
            _anchorMax.x = 0.5f; _anchorMax.y = 1;
            _anchorMin.x = 0.5f; _anchorMin.y = 1;
        }
        if (_rect.pivot != _pivot || _rect.anchorMax != _anchorMax || _rect.anchorMin != _anchorMin)
        {
            _rect.pivot = _pivot;
            _rect.anchorMax = _anchorMax;
            _rect.anchorMin = _anchorMin;
        }
    }
    private void CalculateLayout()
    {
        var _offset = 0.0f;
        var _horizon = m_HorizonOrVerticle == HorizonOrVertical.Horizon;
        for (int i = 0; i < m_AdapElements.Count; i++)
        {
            if (m_AdapElements[i].rect == null || !m_AdapElements[i].rect.gameObject.activeInHierarchy)
            {
                continue;
            }
            _offset += _horizon ? m_AdapElements[i].padding.left : m_AdapElements[i].padding.top;
            var _pos = m_AdapElements[i].rect.localPosition;
            if (_horizon)
            {
                _pos.x = _offset;
            }
            else
            {
                _pos.y = -_offset;
            }
            if (m_AdapElements[i].rect.localPosition != _pos)
            {
                m_AdapElements[i].rect.localPosition = _pos;
            }
            _offset += _horizon ? m_AdapElements[i].rect.sizeDelta.x : m_AdapElements[i].rect.sizeDelta.y;
            _offset += _horizon ? m_AdapElements[i].padding.right : m_AdapElements[i].padding.bottom;
        }
        var _sizeDelta = rectTransform.sizeDelta;
        if (_horizon)
        {
            if (m_LeastWidth > 1f)
            {
                _offset = Mathf.Max(_offset, m_LeastWidth);
            }
            if (m_MaxWidth > 1f)
            {
                _offset = Mathf.Min(_offset, m_MaxWidth);
            }
            _sizeDelta.x = _offset;
        }
        else
        {
            if (m_LeastHeight > 1f)
            {
                _offset = Mathf.Max(_offset, m_LeastHeight);
            }
            if (m_MaxHeight > 1f)
            {
                _offset = Mathf.Min(_offset, m_MaxHeight);
            }
            _sizeDelta.y = _offset;
        }
        if (rectTransform.sizeDelta != _sizeDelta)
        {
            rectTransform.sizeDelta = _sizeDelta;
            if (adaptiveUpdateEvent != null)
            {
                adaptiveUpdateEvent();
            }
        }
    }
    private void LateUpdate()
    {
        if (m_AdapElements == null)
        {
            return;
        }
        TrackerRect(rectTransform);
        for (int i = 0; i < m_AdapElements.Count; i++)
        {
            if (m_AdapElements[i].rect == null)
            {
                continue;
            }
            TrackerRect(m_AdapElements[i].rect);
        }
        CalculateLayout();
    }
    private void OnTransformChildrenChanged()
    {
        if (m_AutoIncludeChild)
        {
            AutoIncludeChild();
        }
    }
    private void AutoIncludeChild()
    {
        var _index = 0;
        foreach (Transform _child in transform)
        {
            if (m_AdapElements == null)
            {
                m_AdapElements = new List<AdaptiveElement>();
            }
            var _rect = m_AdapElements.Find((x) =>
                {
                    return x.rect == _child;
                });
            var _rectOffset= _child.GetComponent<AdaptiveRectOffset>();
            if (_rect == null)
            {
                m_AdapElements.Insert(_index, new AdaptiveElement(_child as RectTransform, _rectOffset));
            }
            _index++;
        }
        if (m_AdapElements != null)
        {
            m_AdapElements.RemoveAll((x) =>
            {
                return x.rect == null;
            });
        }
        LateUpdate();
    }
    async UniTask Co_DelayShow()
    {
        await UniTask.Delay(100);
        if (m_CanvasGroup != null)
        {
            m_CanvasGroup.alpha = 1;
        }
    }
    public enum HorizonOrVertical
    {
        Horizon,
        Vertical,
    }
    [Serializable]
    public class AdaptiveElement
    {
        [SerializeField] RectTransform m_Rect;
        public RectTransform rect
        {
            get
            {
                if (m_Rect == null)
                {
                    m_Rect = GetComponent<RectTransform>();
                }
                return m_Rect;
            }
        }
        public float Size
        [SerializeField] RectOffset m_Padding;
        public RectOffset padding
        {
            get
            {
                return m_HorizonOrVerticle == HorizonOrVertical.Horizon ? rectTransform.sizeDelta.x : rectTransform.sizeDelta.y;
                return m_Padding;
            }
        }
        public event Action adaptiveUpdateEvent;
        private void OnEnable()
        public AdaptiveElement(RectTransform _rect, AdaptiveRectOffset _offset)
        {
            if (m_AdapElements == null)
            {
                enabled = false;
                return;
            }
            if (m_CanvasGroup != null)
            {
                m_CanvasGroup.alpha = 0;
                m_CanvasGroup.interactable = true;
                Co_DelayShow();
            }
            m_Rect = _rect;
            m_Padding = _offset == null ? new RectOffset() : _offset.rectOffset;
        }
    }
        private void TrackerRect(RectTransform _rect)
        {
            var _pivot = _rect.pivot;
            var _anchorMax = _rect.anchorMax;
            var _anchorMin = _rect.anchorMin;
            if (m_HorizonOrVerticle == HorizonOrVertical.Horizon)
            {
                _pivot.x = 0; _pivot.y = 0.5f;
                _anchorMax.x = 0; _anchorMax.y = 0.5f;
                _anchorMin.x = 0; _anchorMin.y = 0.5f;
            }
            else
            {
                _pivot.x = 0.5f; _pivot.y = 1f;
                _anchorMax.x = 0.5f; _anchorMax.y = 1;
                _anchorMin.x = 0.5f; _anchorMin.y = 1;
            }
            if (_rect.pivot != _pivot || _rect.anchorMax != _anchorMax || _rect.anchorMin != _anchorMin)
            {
                _rect.pivot = _pivot;
                _rect.anchorMax = _anchorMax;
                _rect.anchorMin = _anchorMin;
            }
        }
        private void CalculateLayout()
        {
            var _offset = 0.0f;
            var _horizon = m_HorizonOrVerticle == HorizonOrVertical.Horizon;
            for (int i = 0; i < m_AdapElements.Count; i++)
            {
                if (m_AdapElements[i].rect == null || !m_AdapElements[i].rect.gameObject.activeInHierarchy)
                {
                    continue;
                }
                _offset += _horizon ? m_AdapElements[i].padding.left : m_AdapElements[i].padding.top;
                var _pos = m_AdapElements[i].rect.localPosition;
                if (_horizon)
                {
                    _pos.x = _offset;
                }
                else
                {
                    _pos.y = -_offset;
                }
                if (m_AdapElements[i].rect.localPosition != _pos)
                {
                    m_AdapElements[i].rect.localPosition = _pos;
                }
                _offset += _horizon ? m_AdapElements[i].rect.sizeDelta.x : m_AdapElements[i].rect.sizeDelta.y;
                _offset += _horizon ? m_AdapElements[i].padding.right : m_AdapElements[i].padding.bottom;
            }
            var _sizeDelta = rectTransform.sizeDelta;
            if (_horizon)
            {
                if (m_LeastWidth > 1f)
                {
                    _offset = Mathf.Max(_offset, m_LeastWidth);
                }
                if (m_MaxWidth > 1f)
                {
                    _offset = Mathf.Min(_offset, m_MaxWidth);
                }
                _sizeDelta.x = _offset;
            }
            else
            {
                if (m_LeastHeight > 1f)
                {
                    _offset = Mathf.Max(_offset, m_LeastHeight);
                }
                if (m_MaxHeight > 1f)
                {
                    _offset = Mathf.Min(_offset, m_MaxHeight);
                }
                _sizeDelta.y = _offset;
            }
            if (rectTransform.sizeDelta != _sizeDelta)
            {
                rectTransform.sizeDelta = _sizeDelta;
                if (adaptiveUpdateEvent != null)
                {
                    adaptiveUpdateEvent();
                }
            }
        }
        private void LateUpdate()
        {
            if (m_AdapElements == null)
            {
                return;
            }
            TrackerRect(rectTransform);
            for (int i = 0; i < m_AdapElements.Count; i++)
            {
                if (m_AdapElements[i].rect == null)
                {
                    continue;
                }
                TrackerRect(m_AdapElements[i].rect);
            }
            CalculateLayout();
        }
        private void OnTransformChildrenChanged()
        {
            if (m_AutoIncludeChild)
            {
                AutoIncludeChild();
            }
        }
        private void AutoIncludeChild()
        {
            var _index = 0;
            foreach (Transform _child in transform)
            {
                if (m_AdapElements == null)
                {
                    m_AdapElements = new List<AdaptiveElement>();
                }
                var _rect = m_AdapElements.Find((x) =>
                 {
                     return x.rect == _child;
                 });
                var _rectOffset= _child.GetComponent<AdaptiveRectOffset>();
                if (_rect == null)
                {
                    m_AdapElements.Insert(_index, new AdaptiveElement(_child as RectTransform, _rectOffset));
                }
                _index++;
            }
            if (m_AdapElements != null)
            {
                m_AdapElements.RemoveAll((x) =>
                {
                    return x.rect == null;
                });
            }
            LateUpdate();
        }
        async UniTask Co_DelayShow()
        {
            await UniTask.Delay(100);
            if (m_CanvasGroup != null)
            {
                m_CanvasGroup.alpha = 1;
            }
        }
        public enum HorizonOrVertical
        {
            Horizon,
            Vertical,
        }
        [Serializable]
        public class AdaptiveElement
        {
            [SerializeField] RectTransform m_Rect;
            public RectTransform rect
            {
                get
                {
                    return m_Rect;
                }
            }
            [SerializeField] RectOffset m_Padding;
            public RectOffset padding
            {
                get
                {
                    return m_Padding;
                }
            }
            public AdaptiveElement(RectTransform _rect, AdaptiveRectOffset _offset)
            {
                m_Rect = _rect;
                m_Padding = _offset == null ? new RectOffset() : _offset.rectOffset;
            }
        }
    }
}
Main/Component/UI/Common/ClickScreenOtherSpace.cs
@@ -41,13 +41,13 @@
                switch (m_RespondType) {
                    case RespondType.In:
                        if (RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, sp, CameraManager.uiCamera)) {
                            m_ClickOtherEvent.Invoke();
                            m_ClickOtherEvent?.Invoke();
                            this.SetActive(!m_DeActiveSelf);
                        }
                        break;
                    case RespondType.Out:
                        if (!RectTransformUtility.RectangleContainsScreenPoint(this.transform as RectTransform, sp, CameraManager.uiCamera)) {
                            m_ClickOtherEvent.Invoke();
                            m_ClickOtherEvent?.Invoke();
                            this.SetActive(!m_DeActiveSelf);
                        }
                        break;
Main/Component/UI/Common/LayoutElementSizeClamp.cs
@@ -1,9 +1,8 @@
using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
//控制目标的最大最小尺寸
[ExecuteAlways]
public class LayoutElementSizeClamp : LayoutElement
{
@@ -15,21 +14,34 @@
    [SerializeField] RectTransform m_Target;
    Vector2 targetSizeRef = Vector2.zero;
    private void LateUpdate()
    protected override void OnEnable()
    {
        base.OnEnable();
        if (clampEnable && m_Target != null)
        {
            if (targetSizeRef != m_Target.sizeDelta)
            {
                preferredHeight = Mathf.Clamp(m_Target.rect.height, m_Clamp.minY, m_Clamp.maxY);
                preferredWidth = Mathf.Clamp(m_Target.rect.width, m_Clamp.minX, m_Clamp.maxX);
                targetSizeRef = new Vector2(preferredWidth, preferredHeight);
            }
            UpdateRect().Forget();
        }
    }
    async UniTask UpdateRect()
    {
        await UniTask.DelayFrame(1);
        preferredHeight = -1;
        preferredWidth = -1;
        //频繁调用ForceRebuildLayoutImmediate的原因是
        // 如Text要自适应宽高又要限制宽高, 先要处理宽度刷新后才能计算换行
        // 强制重新计算布局
        LayoutRebuilder.ForceRebuildLayoutImmediate(transform.parent as RectTransform);
        preferredWidth = Mathf.Clamp(m_Target.rect.width, m_Clamp.minX, m_Clamp.maxX);
        // 强制重新计算布局
        LayoutRebuilder.ForceRebuildLayoutImmediate(transform.parent as RectTransform);
        preferredHeight = Mathf.Clamp(m_Target.rect.height, m_Clamp.minY, m_Clamp.maxY);
    }
    [System.Serializable]
    public struct Clamp
    {
Main/Component/UI/Effect/EffectPlayer.cs
@@ -40,7 +40,7 @@
    [Header("播放完毕立即回收")]
    public bool isReleaseImmediately = true;  //界面特效一般不需要自我销毁,跟随界面或者父对象销毁就行
    public bool isReleaseImmediately = false;  //界面特效一般不需要自我销毁,跟随界面或者父对象销毁就行
    public Action<EffectPlayer> onDestroy;
Main/Component/UI/Effect/UIEffectPlayer.cs
@@ -5,23 +5,29 @@
using UnityEngine;
using Spine;
using UnityEngine.UI;
using Cysharp.Threading.Tasks;
//UI特效播放器,spine特效直接加载无需提前做预制体
//UI特效大部分情况不会改变特效,无需销毁
public class UIEffectPlayer : EffectPlayer
{
    [Header("是否循环播放spine特效")]
    public bool isPlaySpineLoop = false;
    [Header("是否在显示时播放")]
    public bool isPlayOnEnable = false;
    [Header("延迟播放(毫秒)")]
    public int playDelayTime = 0;
    int playSpineAnimIndex = -1; //播放spine特效动画索引,
    protected override void OnEnable()
    {
        playSpineAnimIndex = -1;
        if (isPlayOnEnable)
        {
            Play(false);
            PlayAsync(false).Forget();
        }
        else if (spineComp != null)
        {
@@ -43,6 +49,10 @@
            if (!this.gameObject.activeSelf)
            {
                this.gameObject.SetActive(true);
            }
            if (effectConfig.isSpine != 0)
            {
                PlayerTheSpineAnim();
            }
            return;
        }
@@ -90,6 +100,18 @@
            spineComp.skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("UIEffect/" + effectConfig.packageName, effectConfig.fxName);
            spineComp.raycastTarget = false;
            spineComp.Initialize(true);
            // 检查动画是否有相加模式
            bool hasAdditiveBlend = CheckForAdditiveBlend(spineComp.Skeleton);
            if (hasAdditiveBlend)
            {
                spineComp.material = ResManager.Instance.LoadAsset<Material>("UIEffect/" + effectConfig.packageName, effectConfig.fxName.Split('_')[0] + "_Material-Additive");
            }
            else
            {
                spineComp.material = null;
            }
            spineAnimationState = spineComp.AnimationState;
            spineAnimationState.Data.DefaultMix = 0f;
            spineAnimationState.Complete -= OnSpineAnimationComplete;
@@ -97,18 +119,42 @@
        }
        spineComp.enabled = true;
        PlayerFistSpineAnim();
        PlayerTheSpineAnim();
    }
    private bool CheckForAdditiveBlend(Spine.Skeleton skeleton)
    {
        // 遍历所有插槽,检查是否有相加模式
        foreach (var slot in skeleton.Slots)
        {
            if (slot.Data.BlendMode == Spine.BlendMode.Additive)
            {
                return true;
            }
        }
        return false;
    }
    // 播放第一个动画(作为默认动画)
    void PlayerFistSpineAnim()
    public void Play(int index, bool showLog = true)
    {
        playSpineAnimIndex = index;
        PlayAsync(showLog).Forget();
    }
    async UniTask PlayAsync(bool showLog = true)
    {
        await UniTask.Delay(playDelayTime);
        Play(showLog);
    }
    // 播放指定动画
    void PlayerTheSpineAnim()
    {
        spineComp.enabled = true;
        var skeletonData = spineComp.Skeleton.Data;
        if (skeletonData.Animations.Count > 0)
        {
            string defaultAnimationName = skeletonData.Animations.Items[0].Name;
            string defaultAnimationName = skeletonData.Animations.Items[playSpineAnimIndex == -1 ? effectConfig.animIndex : playSpineAnimIndex].Name;
            spineAnimationState.SetAnimation(0, defaultAnimationName, isPlaySpineLoop);
        }
        else
@@ -137,6 +183,7 @@
    }
    //  创建后的特效会自动隐藏 需要手动调用Play才能播放
    public static UIEffectPlayer CreateEffect(int effectId, Transform parent, bool createNewChild = false)
    {
Main/Config/ConfigManager.cs
@@ -40,6 +40,7 @@
        HashSet<Type> configTypes = new HashSet<Type>() {
            typeof(ChestsAwardConfig),
            typeof(CTGConfig),
            typeof(DamageNumConfig),
            typeof(DirtyWordConfig),
            typeof(EquipGSParamConfig),
            typeof(FaceConfig),
@@ -52,6 +53,7 @@
            typeof(NPCExConfig),
            typeof(NPCLineupConfig),
            typeof(OrderInfoConfig),
            typeof(PlayerAttrConfig),
            typeof(PlayerFaceConfig),
            typeof(StoreConfig),
            typeof(SuccessConfig),
@@ -59,6 +61,7 @@
            typeof(TitleStarUpConfig),
            typeof(TreasureSetConfig),
            typeof(TreeLVConfig),
            typeof(WindowSearchConfig),
            typeof(XBGetItemConfig)
        };
@@ -213,6 +216,8 @@
        ClearConfigDictionary<ChestsAwardConfig>();
        // 清空 CTGConfig 字典
        ClearConfigDictionary<CTGConfig>();
        // 清空 DamageNumConfig 字典
        ClearConfigDictionary<DamageNumConfig>();
        // 清空 DirtyWordConfig 字典
        ClearConfigDictionary<DirtyWordConfig>();
        // 清空 EquipGSParamConfig 字典
@@ -237,6 +242,8 @@
        ClearConfigDictionary<NPCLineupConfig>();
        // 清空 OrderInfoConfig 字典
        ClearConfigDictionary<OrderInfoConfig>();
        // 清空 PlayerAttrConfig 字典
        ClearConfigDictionary<PlayerAttrConfig>();
        // 清空 PlayerFaceConfig 字典
        ClearConfigDictionary<PlayerFaceConfig>();
        // 清空 StoreConfig 字典
@@ -251,6 +258,8 @@
        ClearConfigDictionary<TreasureSetConfig>();
        // 清空 TreeLVConfig 字典
        ClearConfigDictionary<TreeLVConfig>();
        // 清空 WindowSearchConfig 字典
        ClearConfigDictionary<WindowSearchConfig>();
        // 清空 XBGetItemConfig 字典
        ClearConfigDictionary<XBGetItemConfig>();
    }
Main/Config/Configs/EffectConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年8月5日
//    [  Date ]:           2025年8月7日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -20,7 +20,7 @@
    public string packageName;
    public int isSpine;
    public string fxName;
    public string animName;
    public int animIndex;
    public int audio;
    public string nodeName;
    public int notShow;
@@ -45,7 +45,7 @@
            fxName = tables[3];
            animName = tables[4];
            int.TryParse(tables[4],out animIndex);
            int.TryParse(tables[5],out audio); 
Main/Config/Configs/GetItemWaysConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年8月5日
//    [  Date ]:           2025年8月10日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -18,12 +18,8 @@
    public int ID;
    public string name;
    public string Icon;
    public string Text;
    public int OpenpanelId;
    public int FuncOpenId;
    public int ActiveType;
    public int customize;
    public int WinJumpID;
    public override int LoadKey(string _key)
    {
@@ -39,17 +35,9 @@
            name = tables[1];
            Icon = tables[2];
            Text = tables[2];
            Text = tables[3];
            int.TryParse(tables[4],out OpenpanelId);
            int.TryParse(tables[5],out FuncOpenId);
            int.TryParse(tables[6],out ActiveType);
            int.TryParse(tables[7],out customize);
            int.TryParse(tables[3],out WinJumpID);
        }
        catch (Exception exception)
        {
Main/Config/Configs/HeroConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年8月5日
//    [  Date ]:           Wednesday, August 6, 2025
//--------------------------------------------------------
using System.Collections.Generic;
@@ -20,8 +20,8 @@
    public string Name;
    public int Country;
    public int Quality;
    public int AtkDistType;
    public int Class;
    public int Position;
    public int[] SkinIDList;
    public int AtkSkillID;
    public int AngerSkillID;
@@ -31,6 +31,7 @@
    public string BatAttrDict;
    public int[] FetterIDList;
    public float UIScale;
    public string Desc;
    public override int LoadKey(string _key)
    {
@@ -50,9 +51,9 @@
            int.TryParse(tables[3],out Quality); 
            int.TryParse(tables[4],out AtkDistType);
            int.TryParse(tables[4],out Class);
            int.TryParse(tables[5],out Class);
            int.TryParse(tables[5],out Position);
            if (tables[6].Contains("["))
            {
@@ -95,6 +96,8 @@
            }
            float.TryParse(tables[14],out UIScale); 
            Desc = tables[15];
        }
        catch (Exception exception)
        {
Main/Config/Configs/HeroQualityAwakeConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年8月5日
//    [  Date ]:           2025年8月7日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -20,6 +20,7 @@
    public int Quality;
    public int AwakeLV;
    public int[] UPCostItem;
    public int RebirthCostMoney;
    public override int LoadKey(string _key)
    {
@@ -50,6 +51,8 @@
                     int.TryParse(UPCostItemStringArray[i],out UPCostItem[i]);
                }
            }
            int.TryParse(tables[4],out RebirthCostMoney);
        }
        catch (Exception exception)
        {
Main/Config/Configs/HeroQualityConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年8月5日
//    [  Date ]:           2025年8月7日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -27,6 +27,7 @@
    public int BookInitAddPer;
    public int BookStarAddPer;
    public int BookBreakLVAddPer;
    public int[][] DismissReturnItems;
    public override int LoadKey(string _key)
    {
@@ -83,6 +84,8 @@
            int.TryParse(tables[9],out BookStarAddPer); 
            int.TryParse(tables[10],out BookBreakLVAddPer); 
            DismissReturnItems = JsonMapper.ToObject<int[][]>(tables[11].Replace("(", "[").Replace(")", "]"));
        }
        catch (Exception exception)
        {
Main/Config/Configs/PlayerPropertyConfig.cs
@@ -1,6 +1,6 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           Tuesday, August 5, 2025
//    [  Date ]:           2025年8月9日
//--------------------------------------------------------
using System.Collections.Generic;
@@ -20,7 +20,6 @@
    public string Name;
    public string ShowName;
    public int ISPercentage;
    public int type;
    public int decimalCount;
    public int showType;
    public int showSequence;
@@ -45,17 +44,15 @@
            int.TryParse(tables[3],out ISPercentage); 
            int.TryParse(tables[4],out type);
            int.TryParse(tables[4],out decimalCount);
            int.TryParse(tables[5],out decimalCount);
            int.TryParse(tables[5],out showType);
            int.TryParse(tables[6],out showType);
            int.TryParse(tables[6],out showSequence);
            int.TryParse(tables[7],out showSequence);
            desc = tables[7];
            desc = tables[8];
            Parameter = tables[9];
            Parameter = tables[8];
        }
        catch (Exception exception)
        {
Main/Config/Configs/WindowSearchConfig.cs
New file
@@ -0,0 +1,53 @@
//--------------------------------------------------------
//    [Author]:           YYL
//    [  Date ]:           2025年8月10日
//--------------------------------------------------------
using System.Collections.Generic;
using System;
using UnityEngine;
using LitJson;
public partial class WindowSearchConfig : ConfigBase<int, WindowSearchConfig>
{
    static WindowSearchConfig()
    {
        // 访问过静态构造函数
        visit = true;
    }
    public int ID;
    public string WinName;
    public int ActiveType;
    public int FuncID;
    public int TabIndex;
    public string Extra;
    public override int LoadKey(string _key)
    {
        int key = GetKey(_key);
        return key;
    }
    public override void LoadConfig(string input)
    {
        try {
        string[] tables = input.Split('\t');
        int.TryParse(tables[0],out ID);
            WinName = tables[1];
            int.TryParse(tables[2],out ActiveType);
            int.TryParse(tables[3],out FuncID);
            int.TryParse(tables[4],out TabIndex);
            Extra = tables[5];
        }
        catch (Exception exception)
        {
            Debug.LogError(exception);
        }
    }
}
Main/Config/Configs/WindowSearchConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3466e463eaa5cc7468dd902fe89f1741
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/PartialConfigs/HeroAwakeConfig.cs
@@ -4,11 +4,7 @@
//--------------------------------------------------------
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System;
using UnityEngine;
using LitJson;
public partial class HeroAwakeConfig : ConfigBase<int, HeroAwakeConfig>
{
@@ -30,15 +26,7 @@
            configDics.Add(HeroID, tempDic);
        }
        if (tempDic.ContainsKey(AwakeLV))
        {
            // 覆盖,防止二次初始化出错
            tempDic[AwakeLV] = this;
        }
        else
        {
            tempDic.Add(AwakeLV, this);
        }
        tempDic[AwakeLV] = this;
    }
    public static HeroAwakeConfig GetHeroAwakeConfig(int heroID, int awakeLv)
@@ -56,7 +44,7 @@
        return config;
    }
    public static bool IsReachMax(int heroID, int awakeLv)
    public static bool CanAwake(int heroID, int awakeLv)
    {
        return GetHeroAwakeConfig(heroID, awakeLv) == null;
    }
Main/Config/PartialConfigs/HeroQualityAwakeConfig.cs
@@ -24,16 +24,7 @@
        }
        if (tempDic.ContainsKey(AwakeLV))
        {
            //    覆盖 这里怕有代码写错 二次初始化配置 导致出问题
            //    当是防错 性能上也不算太耗 因为表就没多少数据
            tempDic[AwakeLV] = this;
        }
        else
        {
            tempDic.Add(AwakeLV, this);
        }
        tempDic[AwakeLV] = this;
    }
    public static HeroQualityAwakeConfig GetQualityAwakeConfig(int quality, int awakeLv)
Main/Config/PartialConfigs/HeroQualityBreakConfig.cs
@@ -3,12 +3,8 @@
public partial class HeroQualityBreakConfig : ConfigBase<int, HeroQualityBreakConfig>
{
    // public int Quality;
    // public int BreakLV;
    // Quality, Dictionary<BreakLV, HeroQualityBreakConfig>
    public static Dictionary<int, Dictionary<int, HeroQualityBreakConfig>> configDics = new Dictionary<int, Dictionary<int, HeroQualityBreakConfig>>();
    public static Dictionary<int, int> maxlvDic = new Dictionary<int, int>();
    protected override void OnConfigParseCompleted()
    {
        base.OnConfigParseCompleted();
@@ -20,14 +16,12 @@
            configDics.Add(Quality, tempDic);
        }
        if (tempDic.ContainsKey(BreakLV))
        tempDic[BreakLV] = this;
        if (!maxlvDic.ContainsKey(LVMax) || LVMax > maxlvDic[Quality])
        {
            tempDic[BreakLV] = this;
            maxlvDic[Quality] = LVMax;
        }
        else
        {
            tempDic.Add(BreakLV, this);
        }
    }
    public static HeroQualityBreakConfig GetQualityBreakConfig(int quality, int breakLv)
Main/Config/PartialConfigs/HeroQualityLVConfig.cs
New file
@@ -0,0 +1,33 @@
using System.Collections.Generic;
using UnityEngine;
public partial class HeroQualityLVConfig : ConfigBase<int, HeroQualityLVConfig>
{
    public static Dictionary<int, Dictionary<int, HeroQualityLVConfig>> configDics = new Dictionary<int, Dictionary<int, HeroQualityLVConfig>>();
    protected override void OnConfigParseCompleted()
    {
        Dictionary<int, HeroQualityLVConfig> tempDic = null;
        if (!configDics.TryGetValue(Quality, out tempDic))
        {
            tempDic = new Dictionary<int, HeroQualityLVConfig>();
            configDics.Add(Quality, tempDic);
        }
        tempDic.Add(HeroLV, this);
    }
    public static HeroQualityLVConfig GetQualityLVConfig(int quality, int lv)
    {
        Dictionary<int, HeroQualityLVConfig> tempDic = null;
        if (!configDics.TryGetValue(quality, out tempDic))
        {
            return null;
        }
        HeroQualityLVConfig config = null;
        tempDic.TryGetValue(lv, out config);
        return config;
    }
}
Main/Config/PartialConfigs/HeroQualityLVConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3a3a6fceebbdfe6448e73e82a8cd45c4
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Config/PartialConfigs/PlayerPropertyConfig.cs
@@ -5,29 +5,28 @@
public partial class PlayerPropertyConfig : ConfigBase<int, PlayerPropertyConfig>
{
    private static Dictionary<int, List<PlayerPropertyConfig>> m_PropCfgs = new Dictionary<int, List<PlayerPropertyConfig>>();
    private static Dictionary<int, List<int>> outputDict = new Dictionary<int, List<int>>();
    public static int[] baseAttrs = { 6, 7, 8 };    //攻防血
    public static int[] basePerAttrs = { 16, 17, 18 };    //攻防血 百分比
    protected override void OnConfigParseCompleted()
    // 按显示类型分
    private static Dictionary<int, List<int>> m_PlayerPropertyDict = new Dictionary<int, List<int>>();
    public static Dictionary<int, List<int>> playerPropertyDict
    {
        List<PlayerPropertyConfig> list = null;
        m_PropCfgs.TryGetValue(type, out list);
        if (list != null)
        get
        {
            list.Add(this);
        }
        else
        {
            list = new List<PlayerPropertyConfig>();
            list.Add(this);
            m_PropCfgs.Add(type, list);
            if (m_PlayerPropertyDict.IsNullOrEmpty())
                RefreshShowDict();
            return m_PlayerPropertyDict;
        }
    }
    public static Dictionary<int, List<int>> GetShowDict()
    public static int[] inheritAttrs = playerPropertyDict[5].ToArray();    //攻防血 继承的百分比
    public static int[] basePerAttrs = playerPropertyDict[6].ToArray();    //攻防血 加成百分比
    public const int baseType = 1;  //基础属性
    public const int fightType = 2; //战斗属性
    public const int fightAntiType = 3; //战斗抗性
    public const int specialType = 4; //特殊属性
    private static Dictionary<int, List<int>> RefreshShowDict()
    {
        if (outputDict.IsNullOrEmpty())
        if (m_PlayerPropertyDict.IsNullOrEmpty())
        {
            var keys = GetKeys();
            for (int i = 0; i < keys.Count; i++)
@@ -36,23 +35,21 @@
                int showType = Get(id).showType;
                if (showType == 0)  //为0时不显示
                    continue;
                if (!outputDict.ContainsKey(showType))
                if (!m_PlayerPropertyDict.ContainsKey(showType))
                {
                    outputDict[showType] = new List<int> { id };
                    m_PlayerPropertyDict[showType] = new List<int> { id };
                }
                else
                {
                    outputDict[showType].Add(id);
                    m_PlayerPropertyDict[showType].Add(id);
                }
            }
            var outputList = outputDict.Keys.ToList();
            for (int i = 0; i < outputList.Count; i++)
            foreach (var showType in m_PlayerPropertyDict.Keys)
            {
                int showType = outputList[i];
                outputDict[showType].Sort(cmp);
                m_PlayerPropertyDict[showType].Sort(cmp);
            }
        }
        return outputDict;
        return m_PlayerPropertyDict;
    }
    static int cmp(int id1, int id2)
@@ -63,12 +60,6 @@
        return config1.showSequence.CompareTo(config2.showSequence);
    }
    public static List<PlayerPropertyConfig> GetPropByType(int type)
    {
        List<PlayerPropertyConfig> list = null;
        m_PropCfgs.TryGetValue(type, out list);
        return list;
    }
    public static string GetFullDescription(Int2 property)
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB239_tagCSHeroRebirth.cs
New file
@@ -0,0 +1,18 @@
using UnityEngine;
using System.Collections;
// B2 39 武将重生 #tagCSHeroRebirth
public class CB239_tagCSHeroRebirth : GameNetPackBasic {
    public ushort ItemIndex;    //武将物品所在武将背包位置索引
    public CB239_tagCSHeroRebirth () {
        combineCmd = (ushort)0x03FE;
        _cmd = (ushort)0xB239;
    }
    public override void WriteToBytes () {
        WriteBytes (ItemIndex, NetDataType.WORD);
    }
}
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB239_tagCSHeroRebirth.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8003dc9310623ad43a8835fe9221d9ce
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB240_tagCSHeroDismiss.cs
New file
@@ -0,0 +1,20 @@
using UnityEngine;
using System.Collections;
// B2 40 武将遣散 #tagCSHeroDismiss
public class CB240_tagCSHeroDismiss : GameNetPackBasic {
    public ushort Count;
    public  ushort[] ItemIndexList;    // 武将物品所在武将背包位置索引列表
    public CB240_tagCSHeroDismiss () {
        combineCmd = (ushort)0x03FE;
        _cmd = (ushort)0xB240;
    }
    public override void WriteToBytes () {
        WriteBytes (Count, NetDataType.WORD);
        WriteBytes (ItemIndexList, NetDataType.WORD, Count);
    }
}
Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB240_tagCSHeroDismiss.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 53d619f99407d824cb6b4ac819f0caa3
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DTCFile/ServerPack/H07_PlayerItem/DTC0722_tagItemDeadLockRefresh.cs
@@ -1,11 +1,13 @@
using UnityEngine;
using System.Collections;
using UnityEngine;
using System.Collections;
//07 22 物品死锁#tagItemDeadLockRefresh
public class DTC0722_tagItemDeadLockRefresh : DtcBasic {
    public override void Done(GameNetPackBasic vNetPack) {
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        H0722_tagItemDeadLockRefresh vNetData = vNetPack as H0722_tagItemDeadLockRefresh;
        PackManager.Instance.UpdateItemLockState(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HB1_Role/DTCB125_tagSCPlayerHeroInfo.cs
New file
@@ -0,0 +1,13 @@
using UnityEngine;
using System.Collections;
// B1 25 玩家武将公共信息 #tagSCPlayerHeroInfo
public class DTCB125_tagSCPlayerHeroInfo : DtcBasic {
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HB125_tagSCPlayerHeroInfo vNetData = vNetPack as HB125_tagSCPlayerHeroInfo;
        HeroUIManager.Instance.UpdateHeroInfo(vNetData);
    }
}
Main/Core/NetworkPackage/DTCFile/ServerPack/HB1_Role/DTCB125_tagSCPlayerHeroInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b8aea40fcee94ca4f8ffed1b039c8fd0
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs
@@ -104,6 +104,8 @@
        Register(typeof(HB427_tagSCUseSkill), typeof(DTCB427_tagSCUseSkill));
        Register(typeof(HB124_tagSCLineupInfo), typeof(DTCB124_tagSCLineupInfo));
        Register(typeof(HA207_tagSCPackBuyInfo), typeof(DTCA207_tagSCPackBuyInfo));
        Register(typeof(H0722_tagItemDeadLockRefresh), typeof(DTC0722_tagItemDeadLockRefresh));
        Register(typeof(HB125_tagSCPlayerHeroInfo), typeof(DTCB125_tagSCPlayerHeroInfo));
    }
    //主工程注册封包
Main/Core/NetworkPackage/ServerPack/HA8_Item/HA801_tagMCGiveAwardInfo.cs
@@ -37,6 +37,7 @@
            ItemList[i] = new tagMCGiveAwardItem();
            TransBytes (out ItemList[i].ItemID, vBytes, NetDataType.DWORD);
            TransBytes (out ItemList[i].Count, vBytes, NetDataType.DWORD);
            TransBytes (out ItemList[i].CountEx, vBytes, NetDataType.DWORD);
            TransBytes (out ItemList[i].IsBind, vBytes, NetDataType.BYTE);
        }
        TransBytes (out DataLen, vBytes, NetDataType.WORD);
@@ -50,7 +51,8 @@
    public struct tagMCGiveAwardItem {
        public uint ItemID;
        public uint Count;
        public uint Count;        // 求余亿部分,个别功能单次汇总可能超20亿,如批量遣散,固统一规则
        public uint CountEx;        // 整除亿部分
        public byte IsBind;
    }
Main/Core/NetworkPackage/ServerPack/HB1_Role/HB125_tagSCPlayerHeroInfo.cs
New file
@@ -0,0 +1,17 @@
using UnityEngine;
using System.Collections;
// B1 25 玩家武将公共信息 #tagSCPlayerHeroInfo
public class HB125_tagSCPlayerHeroInfo : GameNetPackBasic {
    public byte AwakeRebirthCnt;    // 今日觉醒过的武将已重生次数
    public HB125_tagSCPlayerHeroInfo () {
        _cmd = (ushort)0xB125;
    }
    public override void ReadFromBytes (byte[] vBytes) {
        TransBytes (out AwakeRebirthCnt, vBytes, NetDataType.BYTE);
    }
}
Main/Core/NetworkPackage/ServerPack/HB1_Role/HB125_tagSCPlayerHeroInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ca0dbb77a3bf332449047d97572422f2
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/ResModule/UILoader.cs
@@ -38,7 +38,7 @@
    public static Sprite LoadSprite(string _folder, string _file)
    {
        return ResManager.Instance.LoadAsset<Sprite>(StringUtility.Contact(ResourcesPath.UI_SPRITE_SUFFIX, "/", _folder) , _file);
        return ResManager.Instance.LoadAsset<Sprite>(StringUtility.Contact(ResourcesPath.UI_SPRITE_SUFFIX, "/", _folder), _file);
    }
    public static void UnLoadSprite(string _iconKey)
@@ -53,11 +53,21 @@
    public static Font LoadFont(string _fontName)
    {
        return ResManager.Instance.LoadAsset<Font>(ResourcesPath.UI_FONT_SUFFIX, _fontName);
        return ResManager.Instance.LoadAsset<Font>(ResourcesPath.UI_FONT_SUFFIX, _fontName);
    }
    public static void UnLoadFont(string _fontName)
    {
        ResManager.Instance.UnloadAsset(ResourcesPath.UI_FONT_SUFFIX, _fontName);
    }
    public static Texture2D LoadTexture2D(string _iconKey)
    {
        var iconConfig = IconConfig.Get(_iconKey);
        if (iconConfig == null)
        {
            return null;
        }
        return ResManager.Instance.LoadAsset<Texture2D>(StringUtility.Contact(ResourcesPath.UI_SPRITE_SUFFIX, "/" + iconConfig.folder), iconConfig.sprite);
    }
}
Main/System/HappyXB/HappyXBModel.cs
@@ -747,7 +747,7 @@
        XBFuncSet funcSet = GetXBFuncSet(type);
        if (funcSet == null) return false;
        int toolCnt = PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.costToolIds[0]);
        int toolCnt = (int)PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.costToolIds[0]);
        if (toolCnt >= funcSet.costToolNums[0])
        {
            return true;
@@ -764,7 +764,7 @@
        XBFuncSet funcSet = GetXBFuncSet(type);
        if (funcSet == null) return false;
        toolCnt = PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.costToolIds[1]);
        toolCnt = (int)PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.costToolIds[1]);
        needToolCnt = funcSet.costToolNums[1];
        if (toolCnt > 0)
        {
@@ -783,7 +783,7 @@
        XBFuncSet funcSet = GetXBFuncSet(type);
        if (funcSet == null) return false;
        toolCnt = PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.costToolIds[1]);
        toolCnt = (int)PackManager.Instance.GetItemCountByID(PackType.Item, funcSet.costToolIds[1]);
        needToolCnt = funcSet.costToolNums[1];
        if (toolCnt > 0)
Main/System/Hero/HeroInfo.cs
@@ -112,7 +112,7 @@
        qualityConfig = HeroQualityConfig.Get(Quality);
        //  品质突破配置
        qualityBreakConfig = HeroQualityBreakConfig.GetQualityBreakConfig(Quality, awakeLevel);
        qualityBreakConfig = HeroQualityBreakConfig.GetQualityBreakConfig(Quality, breakLevel);
    }
Main/System/Hero/HeroManager.cs
@@ -147,9 +147,12 @@
    public int GetHeroCount()
    {
    {
        return heroInfoDict.Count;
    }
    public bool HasHero(int heroID)
    {
        return PackManager.Instance.GetSinglePack(PackType.Hero).HasItem(heroID);
    }
}
Main/System/Hero/UIHeroController.cs
@@ -2,8 +2,7 @@
using System;
using Spine.Unity;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public class UIHeroController : MonoBehaviour
{
    private GameObjectPoolManager.GameObjectPool pool;
@@ -14,7 +13,7 @@
    private GameObject instanceGO;
    private Action onComplete;
    public void Create(int _skinID, float scale = 1f, Action _onComplete = null)
    public void Create(int _skinID, float scale = 1f, Action _onComplete = null, string motionName = "idle", bool isLh = false)
    {
        if (skinID == _skinID)
        { 
@@ -44,12 +43,21 @@
        skeletonGraphic = instanceGO.GetComponentInChildren<SkeletonGraphic>(true);
        var skinConfig = HeroSkinConfig.Get(skinID);
        skeletonGraphic.skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("Hero/SpineRes/", skinConfig.SpineRes);
        if (isLh)
        {
            skeletonGraphic.skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("Hero/SpineRes/", skinConfig.Tachie);
        }
        else
        {
            skeletonGraphic.skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("Hero/SpineRes/", skinConfig.SpineRes);
        }
        skeletonGraphic.Initialize(true);
        this.transform.localScale = Vector3.one * scale;
        spineAnimationState = skeletonGraphic.AnimationState;
        spineAnimationState.Data.DefaultMix = 0f;
        PlayAnimation(MotionName.idle, true);
        if (motionName == "")
            motionName = GetFistSpineAnim();
        PlayAnimation(motionName, true);
        spineAnimationState.Complete -= OnAnimationComplete;
        spineAnimationState.Complete += OnAnimationComplete;
    }
@@ -70,12 +78,27 @@
    }
    public virtual void PlayAnimation(MotionName motionName, bool loop = false)
    public virtual void PlayAnimation(string motionName, bool loop = false)
    {
        if (spineAnimationState == null) return;
        // 直接使用 ToString() 而不是调用 GetAnimationName
        spineAnimationState.SetAnimation(0, motionName.ToString(), loop);
    }
    // 播放第一个动画(作为默认动画)
    string GetFistSpineAnim()
    {
        var skeletonData = skeletonGraphic.Skeleton.Data;
        if (skeletonData.Animations.Count > 0)
        {
            return skeletonData.Animations.Items[0].Name;
        }
        else
        {
            Debug.LogError("Spine 数据中没有找到任何动画!武将皮肤:" + skinID);
        }
        return "";
    }
    /// <summary>
@@ -84,6 +107,6 @@
    protected virtual void OnAnimationComplete(Spine.TrackEntry trackEntry)
    {
        onComplete?.Invoke();
    }
    }
}
Main/System/HeroUI/HeroAllAttrWin.cs
New file
@@ -0,0 +1,125 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 武将属性界面: functionOrder 用来传递武将背包索引
/// </summary>
public class HeroAllAttrWin : UIBase
{
    [SerializeField] GameObject baseAttrGroup;
    [SerializeField] GameObject fightAttrGroup;
    [SerializeField] GameObject fightAntiAttrGroup;
    [SerializeField] GameObject specialAttrGroup;
    Dictionary<int, Button> attrBtns = new Dictionary<int, Button>();
    protected override void InitComponent()
    {
        //找出所有子组件名字为attr的GameObject
        Button[] attrComponents = baseAttrGroup.GetComponentsInChildren<Button>(true)
        .Where(c => c.gameObject.name == "attr").ToArray();
        var attrIDList = PlayerPropertyConfig.playerPropertyDict[PlayerPropertyConfig.baseType];
        for (int i = 0; i < attrComponents.Length; i++)
        {
            if (i < attrIDList.Count)
            {
                attrComponents[i].SetActive(true);
                attrBtns.Add(attrIDList[i], attrComponents[i]);
            }
            else
            {
                attrComponents[i].SetActive(false);
            }
        }
        attrComponents = fightAttrGroup.GetComponentsInChildren<Button>(true)
            .Where(c => c.gameObject.name == "attr").ToArray();
        attrIDList = PlayerPropertyConfig.playerPropertyDict[PlayerPropertyConfig.fightType];
        for (int i = 0; i < attrComponents.Length; i++)
        {
            if (i < attrIDList.Count)
            {
                attrComponents[i].SetActive(true);
                attrBtns.Add(attrIDList[i], attrComponents[i]);
            }
            else
            {
                attrComponents[i].SetActive(false);
            }
        }
        attrComponents = fightAntiAttrGroup.GetComponentsInChildren<Button>(true)
            .Where(c => c.gameObject.name == "attr").ToArray();
        attrIDList = PlayerPropertyConfig.playerPropertyDict[PlayerPropertyConfig.fightAntiType];
        for (int i = 0; i < attrComponents.Length; i++)
        {
            if (i < attrIDList.Count)
            {
                attrComponents[i].SetActive(true);
                attrBtns.Add(attrIDList[i], attrComponents[i]);
            }
            else
            {
                attrComponents[i].SetActive(false);
            }
        }
        attrComponents = specialAttrGroup.GetComponentsInChildren<Button>(true)
            .Where(c => c.gameObject.name == "attr").ToArray();
        attrIDList = PlayerPropertyConfig.playerPropertyDict[PlayerPropertyConfig.specialType];
        for (int i = 0; i < attrComponents.Length; i++)
        {
            if (i < attrIDList.Count)
            {
                attrComponents[i].SetActive(true);
                attrBtns.Add(attrIDList[i], attrComponents[i]);
            }
            else
            {
                attrComponents[i].SetActive(false);
            }
        }
        //设置回调
        foreach (var kv in attrBtns)
        {
            int id = kv.Key;
            kv.Value.AddListener(() =>
            {
                SmallTipWin.showText = PlayerPropertyConfig.Get(id).desc;
                SmallTipWin.worldPos = CameraManager.uiCamera.ScreenToWorldPoint(Input.mousePosition);
                UIManager.Instance.OpenWindow<SmallTipWin>();
            });
        }
    }
    protected override void OnPreOpen()
    {
        var item = PackManager.Instance.GetItemByIndex(PackType.Hero, functionOrder);
        if (item == null)
            return;
        var hero = HeroManager.Instance.GetHero(item.guid);
        if (hero == null)
            return;
        foreach (var kv in attrBtns)
        {
            //每个按钮下有两个Text:name 和 value
            var id = kv.Key;
            var button = kv.Value;
            Text nameText = button.transform.Find("name").GetComponent<Text>();
            Text valueText = button.transform.Find("value").GetComponent<Text>();
            nameText.text = PlayerPropertyConfig.Get(id).ShowName;
            valueText.text = PlayerPropertyConfig.GetValueDescription(id, 123);
        }
    }
}
Main/System/HeroUI/HeroAllAttrWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 62b2672487e30c24f97012135a1ffcf8
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroUI/HeroCardCell.cs
@@ -19,15 +19,17 @@
    [SerializeField] Text awakeLVText;
    [SerializeField] List<Image> starImgList;
    string guid;
    public void Display(int index)
    {
        var hero = HeroManager.Instance.GetHero(HeroUIManager.Instance.heroSortList[index]);
        guid = HeroUIManager.Instance.heroSortList[index];
        var hero = HeroManager.Instance.GetHero(guid);
        if (hero == null)
        {
            this.gameObject.SetActive(false);
            return;
        }
        this.gameObject.SetActive(true);
        heroCardBG.SetSprite("herocardbg" + hero.Quality);
        if (glowMaterial != null)
@@ -36,15 +38,15 @@
        }
        lvText.text = Language.Get("L1094") + hero.heroLevel.ToString();
        var heroConfig = hero.heroConfig;
        countryImg.SetSprite("herocountry" + heroConfig.Country);
        jobImg.SetSprite("herojob" + heroConfig.Class);
        countryImg.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
        jobImg.SetSprite(HeroUIManager.Instance.GetJobIconName(heroConfig.Class));
        heroModel.Create(heroConfig.SkinIDList[hero.SkinIndex], heroConfig.UIScale);
        onStateImg.SetActive(hero.IsInTeamByTeamType(TeamType.Story));
        redpoint.redpointId = MainRedDot.HeroCardRedpoint * 1000 + hero.itemHero.gridIndex;
        var funcState = hero.funcState;
        if (funcState > 0)
        {
        {
            trainStateImg.SetActive(true);
            trainStateImg.SetSprite("herofuncstate" + hero.funcState);
        }
@@ -67,13 +69,19 @@
            else if ((hero.heroStar - 1) % starImgList.Count >= i)
            {
                starImgList[i].SetActive(true);
                starImgList[i].SetSprite("herostar" +  (((hero.heroStar - 1)/starImgList.Count)+1)*starImgList.Count);
                starImgList[i].SetSprite("herostar" + (((hero.heroStar - 1) / starImgList.Count) + 1) * starImgList.Count);
            }
            else
            {
                starImgList[i].SetActive(false);
            }
        }
        heroCardBtn.AddListener(() =>
        {
            HeroUIManager.Instance.selectHeroGuid = guid;
            UIManager.Instance.OpenWindow<HeroTrainWin>();
        });
    }
}
Main/System/HeroUI/HeroConnectionCell.cs
@@ -7,15 +7,26 @@
    [SerializeField] HeroConnectionHeadCell[] heros;
    [SerializeField] Text connAttrText;
    public void Display(int fetterID)
    /// <summary>
    /// 羁绊图片展示
    /// </summary>
    /// <param name="fetterID"></param>
    /// <param name="showStr">属性文字排版</param>
    /// <param name="showCollect">是否按收集显示置灰状态</param>
    /// <param name="guid">切换皮肤用</param>
    public void Display(int fetterID, string showStr = "", bool showCollect = false, string guid = "")
    {
        HeroFetterConfig heroFetterConfig = HeroFetterConfig.Get(fetterID);
        int fromHeroID = HeroManager.Instance.GetHero(guid).heroId;
        int _skinID = HeroManager.Instance.GetHero(guid).SkinID;
        for (int i = 0; i < heros.Length; i++)
        {
            if (i < heroFetterConfig.HeroIDList.Length)
            {
                heros[i].SetActive(true);
                heros[i].Display(heroFetterConfig.HeroIDList[i], i);
                heros[i].Display(heroFetterConfig.HeroIDList[i], i, showCollect,
                fromHeroID == heroFetterConfig.HeroIDList[i] ? _skinID : 0);
            }
            else
            {
@@ -27,7 +38,14 @@
        {
            attrStr += PlayerPropertyConfig.GetFullDescription(heroFetterConfig.AttrIDList[i], heroFetterConfig.AttrValueList[i]) + " ";
        }
        connAttrText.text = Language.Get("L1100", heroFetterConfig.FetterName, UIHelper.AppendColor(TextColType.lightYellow, attrStr));
        if (string.IsNullOrEmpty(showStr))
        {
            connAttrText.text = Language.Get("L1100", heroFetterConfig.FetterName, UIHelper.AppendColor(TextColType.lightYellow, attrStr));
        }
        else
        {
            connAttrText.text = showStr + attrStr;
        }
    }
}
Main/System/HeroUI/HeroConnectionHeadCell.cs
@@ -5,7 +5,7 @@
public class HeroConnectionHeadCell : MonoBehaviour
{
    [SerializeField] Image qualityImg;
    [SerializeField] Image heroIcon;
    [SerializeField] ImageEx heroIcon;
    [SerializeField] Text nameText;
    [SerializeField] Image connMarkImg; //链接的锁图标,第一个不显示
@@ -14,20 +14,18 @@
    /// </summary>
    /// <param name="heroID"></param>
    /// <param name="index"> 只是为了让第一个不显示锁图标用</param>
    /// <param name="guid">部分界面显示不同皮肤图标</param>
    public void Display(int heroID, int index, string guid = "")
    /// <param name="showCollect">是否按收集显示置灰状态</param>
    /// <param name="_skinID">指定皮肤</param>
    public void Display(int heroID, int index, bool showCollect = false,  int _skinID = 0)
    {
        int skinID = 0;
        HeroConfig heroConfig;
        if (!string.IsNullOrEmpty(guid))
        HeroConfig heroConfig = HeroConfig.Get(heroID);
        if (_skinID != 0)
        {
            var hero = HeroManager.Instance.GetHero(guid);
            skinID = hero.SkinID;
            heroConfig = hero.heroConfig;
            skinID = _skinID;
        }
        else
        {
            heroConfig = HeroConfig.Get(heroID);
            skinID = heroConfig.SkinIDList[0];  //默认第一个图鉴展示
        }
@@ -45,6 +43,13 @@
            heroIcon.overrideSprite = sprite;
        }
        if (showCollect)
        {
            //未获得武将要置灰
            heroIcon.gray = !HeroManager.Instance.HasHero(heroID);
        }
        connMarkImg.SetActive(index != 0);
    }
}
Main/System/HeroUI/HeroFormationCell.cs
@@ -55,7 +55,7 @@
            string lineText = string.Empty;
            bool isActive = sameCountry && count <= result.y;
            string countStr = isActive ? UIHelper.AppendColor(TextColType.Green, count.ToString()) : count.ToString();
            lineText = (k == 0 ? "" : "</r>") + Language.Get("herocard37", countStr, RichTextMsgReplaceConfig.GetRichReplace("Country", index + 1));
            lineText = (k == 0 ? "" : "</r>") + Language.Get("herocard37", countStr, HeroUIManager.Instance.GetJobName(index + 1));
            var attrConfig = attrDict[count];
            for (int i = 0; i < attrConfig.AttrIDList.Length; i++)
            {
Main/System/HeroUI/HeroHeadBaseCell.cs
@@ -194,7 +194,7 @@
            }
        }
        countryImg.SetSprite("herocountry" + heroConfig.Country);
        countryImg.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
        lvText.text = lv == 0 ? "": Language.Get("L1094") + lv;
        awakeLvRect.SetActive(awakelv > 0);
Main/System/HeroUI/HeroLVBreakSuccessWin.cs
New file
@@ -0,0 +1,86 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 武将突破界面
/// </summary>
public class HeroLVBreakSuccessWin : UIBase
{
    [SerializeField] Text breakLVText;
    [SerializeField] Text nextBreakLVText;
    [SerializeField] Text lvText;
    [SerializeField] Text nextLVText;
    [SerializeField] Text[] attrPerTextArr;
    [SerializeField] Text[] nextAttrPerTextArr;
    [SerializeField] Text potentialText;
    [SerializeField] Button okBtn;
    string guid;
    HeroInfo hero;
    protected override void InitComponent()
    {
        okBtn.AddListener(CloseWindow);
    }
    protected override void OnPreOpen()
    {
        guid = HeroUIManager.Instance.waitResponse.guid;
        if (string.IsNullOrEmpty(guid))
            return;
        hero = HeroManager.Instance.GetHero(guid);
        Refresh();
    }
    protected override void OnPreClose()
    {
    }
    public override void Refresh()
    {
        breakLVText.text = "+" + (hero.breakLevel - 1);
        nextBreakLVText.text = "+" + hero.breakLevel;
        var beforeBreakLVConfig = HeroQualityBreakConfig.GetQualityBreakConfig(hero.Quality, hero.breakLevel - 1);
        lvText.text = beforeBreakLVConfig.LVMax.ToString();
        nextLVText.text = hero.qualityBreakConfig.LVMax.ToString();
        for (int i = 0; i < attrPerTextArr.Length; i++)
        {
            attrPerTextArr[i].text = PlayerPropertyConfig.GetValueDescription(PlayerPropertyConfig.basePerAttrs[i],
            hero.qualityConfig.BreakLVAddPer * (hero.breakLevel - 1));
        }
        for (int i = 0; i < nextAttrPerTextArr.Length; i++)
        {
            nextAttrPerTextArr[i].text = PlayerPropertyConfig.GetValueDescription(PlayerPropertyConfig.basePerAttrs[i],
            hero.qualityConfig.BreakLVAddPer * hero.breakLevel);
        }
        var nextQualityBreakConfig = HeroBreakConfig.GetHeroBreakConfig(hero.heroId, hero.breakLevel);
        if (nextQualityBreakConfig == null)
        {
            potentialText.text = "";
            return;
        }
        List<string> attrStrArr = new List<string>();
        for (int i = 0; i < nextQualityBreakConfig.AttrIDList.Length; i++)
        {
            attrStrArr.Add(PlayerPropertyConfig.GetFullDescription(nextQualityBreakConfig.AttrIDList[i], nextQualityBreakConfig.AttrValueList[i]));
        }
        if (nextQualityBreakConfig.SkillID != 0)
        {
            attrStrArr.Add(SkillConfig.Get(nextQualityBreakConfig.SkillID).Description);
        }
        potentialText.text = Language.Get("L1100", Language.Get("herocard56"), string.Join(Language.Get("L1112"), attrStrArr));
    }
}
Main/System/HeroUI/HeroLVBreakSuccessWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6d272e748e1ddd741965ae96a8ede01d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroUI/HeroLVBreakWin.cs
New file
@@ -0,0 +1,105 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 武将突破界面
/// </summary>
public class HeroLVBreakWin : UIBase
{
    [SerializeField] Text breakLVText;
    [SerializeField] Text nextBreakLVText;
    [SerializeField] Text lvText;
    [SerializeField] Text nextLVText;
    [SerializeField] Text[] attrPerTextArr;
    [SerializeField] Text[] nextAttrPerTextArr;
    [SerializeField] Text potentialText;
    [SerializeField] Image moneyIcon;
    [SerializeField] Text moneyText;
    [SerializeField] Button breakBtn;
    string guid;
    HeroInfo hero;
    protected override void InitComponent()
    {
        breakBtn.AddListener(BreakLV);
    }
    protected override void OnPreOpen()
    {
        guid = HeroUIManager.Instance.selectHeroGuid;
        hero = HeroManager.Instance.GetHero(guid);
        Refresh();
    }
    protected override void OnPreClose()
    {
    }
    public override void Refresh()
    {
        breakLVText.text = "+" + hero.breakLevel;
        nextBreakLVText.text = "+" + (hero.breakLevel + 1);
        lvText.text = hero.qualityBreakConfig.LVMax.ToString();
        var nextBreakLVConfig = HeroQualityBreakConfig.GetQualityBreakConfig(hero.Quality, hero.breakLevel + 1);
        nextLVText.text = nextBreakLVConfig.LVMax.ToString();
        for (int i = 0; i < attrPerTextArr.Length; i++)
        {
            attrPerTextArr[i].text = PlayerPropertyConfig.GetValueDescription(PlayerPropertyConfig.basePerAttrs[i],
            hero.qualityConfig.BreakLVAddPer * hero.breakLevel);
        }
        for (int i = 0; i < nextAttrPerTextArr.Length; i++)
        {
            nextAttrPerTextArr[i].text = PlayerPropertyConfig.GetValueDescription(PlayerPropertyConfig.basePerAttrs[i],
            hero.qualityConfig.BreakLVAddPer * (hero.breakLevel + 1));
        }
        moneyIcon.SetOrgSprite(ItemConfig.Get(nextBreakLVConfig.UPCostItem[0]).IconKey);
        moneyText.text = UIHelper.ShowUseItem(PackType.Item, nextBreakLVConfig.UPCostItem[0], (ulong)nextBreakLVConfig.UPCostItem[1]);
        var nextQualityBreakConfig = HeroBreakConfig.GetHeroBreakConfig(hero.heroId, hero.breakLevel + 1);
        if (nextQualityBreakConfig == null)
        {
            potentialText.text = "";
            return;
        }
        List<string> attrStrArr = new List<string>();
        for (int i = 0; i < nextQualityBreakConfig.AttrIDList.Length; i++)
        {
            attrStrArr.Add(PlayerPropertyConfig.GetFullDescription(nextQualityBreakConfig.AttrIDList[i], nextQualityBreakConfig.AttrValueList[i]));
        }
        if (nextQualityBreakConfig.SkillID != 0)
        {
            attrStrArr.Add(SkillConfig.Get(nextQualityBreakConfig.SkillID).Description);
        }
        potentialText.text = Language.Get("L1100", Language.Get("herocard56"), string.Join(Language.Get("L1112"), attrStrArr));
    }
    void BreakLV()
    {
        if (ItemLogicUtility.CheckItemCount(PackType.Item, hero.qualityBreakConfig.UPCostItem[0], (ulong)hero.qualityBreakConfig.UPCostItem[1], 2))
        {
            var pack = new CB232_tagCSHeroBreak();
            pack.ItemIndex = (ushort)hero.itemHero.gridIndex;
            GameNetSystem.Instance.SendInfo(pack);
            CloseWindow();
            //设置个等待回复的标识 显示成功界面
            HeroUIManager.Instance.waitResponse = new WaitHeroFuncResponse()
            {
                guid = guid,
                type = HeroFuncType.Break,
                time = Time.time
            };
        }
    }
}
Main/System/HeroUI/HeroLVBreakWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b01967255da52584984f8c394f186c0f
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroUI/HeroListWin.cs
@@ -33,6 +33,10 @@
            HeroUIManager.Instance.selectTeamType = TeamType.Story;
            UIManager.Instance.OpenWindow<HeroPosWin>();
        });
        attrOnTipBtn.AddListener(() =>
        {
            attrOnTip.SetActive(!attrOnTip.activeSelf);
        });
    }
Main/System/HeroUI/HeroPosHeadCell.cs
@@ -22,7 +22,7 @@
        });
        nameText.text = hero.breakLevel == 0 ? hero.heroConfig.Name : Language.Get("herocardbreaklv", hero.heroConfig.Name, hero.breakLevel);
        
        jobImg.SetSprite("herojob" + hero.heroConfig.Class);
        jobImg.SetSprite(HeroUIManager.Instance.GetJobIconName(hero.heroConfig.Class));
    }
    void Click(HeroInfo hero, int index)
Main/System/HeroUI/HeroScenePosCell.cs
@@ -28,19 +28,19 @@
        lvText.text = Language.Get("L1099", hero.heroLevel);
        var heroConfig = hero.heroConfig;
        countryImg.SetSprite("herocountry" + heroConfig.Country);
        countryImg.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
        heroModel.Create(heroConfig.SkinIDList[hero.SkinIndex]);
        nameText.text = hero.breakLevel == 0 ? heroConfig.Name : Language.Get("herocardbreaklv", heroConfig.Name, hero.breakLevel);
        posCircleImg.SetSprite("heroposcircle" + heroConfig.Quality);
        //不是推荐位则提示
        if (heroConfig.AtkDistType == 1 && TeamConst.TeamPos2Array.Contains(index) ||
            heroConfig.AtkDistType == 2 && TeamConst.TeamPos1Array.Contains(index))
        if (heroConfig.Position == 1 && TeamConst.TeamPos2Array.Contains(index) ||
            heroConfig.Position == 2 && TeamConst.TeamPos1Array.Contains(index))
        {
            suggestForm.SetActive(true);
            jobTip.text = RichTextMsgReplaceConfig.GetRichReplace("Class", heroConfig.Class);
            posTip.text = Language.Get("heroAtkDistType" + heroConfig.AtkDistType);
            jobTip.text = HeroUIManager.Instance.GetJobName(heroConfig.Class);
            posTip.text = Language.Get("heroAtkDistType" + heroConfig.Position);
        }
        else
        {
Main/System/HeroUI/HeroSkillWin.cs
New file
@@ -0,0 +1,52 @@
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 武将技能界面
/// </summary>
public class HeroSkillWin : UIBase
{
    [SerializeField] SkillBaseCell normalSkillCell;
    [SerializeField] Text nameText;
    [SerializeField] Text skillTypeText;
    [SerializeField] RichText descText;
    [SerializeField] SkillBaseCell angerSkillCell;
    [SerializeField] Text name2Text;
    [SerializeField] Text skillType2Text;
    [SerializeField] RichText desc2Text;
    int heroID;
    protected override void OnPreOpen()
    {
        heroID = functionOrder;
        Refresh();
    }
    protected override void OnPreClose()
    {
    }
    public override void Refresh()
    {
        var heroConfig = HeroConfig.Get(heroID);
        if (!SkillConfig.HasKey(heroConfig.AtkSkillID))
            return;
        normalSkillCell.Init(heroConfig.AtkSkillID);
        var skillConfig = SkillConfig.Get(heroConfig.AtkSkillID);
        nameText.text = skillConfig.SkillName;
        skillTypeText.text = Language.Get("L1100", Language.Get("L1108"), Language.Get(skillConfig.FuncType == 1 ? "HeroSkillType_1" : "HeroSkillType_2"));
        descText.text = skillConfig.Description;
        angerSkillCell.Init(heroConfig.AngerSkillID);
        var skillConfig2 = SkillConfig.Get(heroConfig.AngerSkillID);
        name2Text.text = skillConfig2.SkillName;
        skillType2Text.text = Language.Get("L1100", Language.Get("L1108"), Language.Get(skillConfig2.FuncType == 1 ? "HeroSkillType_1" : "HeroSkillType_2"));
        desc2Text.text = skillConfig2.Description;
    }
}
Main/System/HeroUI/HeroSkillWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b1a16fb3ae471984c9b77182c3cb88d7
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroUI/HeroTrainWin.cs
New file
@@ -0,0 +1,437 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 武将培养界面
/// </summary>
public class HeroTrainWin : UIBase
{
    [SerializeField] Button showFuncBtn;    //只显示立绘时点击,显示功能
    [SerializeField] Transform funcForm;
    [SerializeField] UIHeroController roleLhModel;    //展示英雄立绘
    [SerializeField] Button rightBtn;
    [SerializeField] Button leftBtn;
    [SerializeField] UIHeroController roleXsModel;  //像素
    [SerializeField] UIEffectPlayer lvupEffect;
    [SerializeField] Image jobImg;
    [SerializeField] Text jobPosNameText;
    [SerializeField] Text descText;
    [SerializeField] Text fightPowerText;   //由客户端自己预算的战力
    [SerializeField] Button lockBtn;
    [SerializeField] Image lockImg;
    [SerializeField] Image unLockImg;
    [SerializeField] HeroConnectionCell connetionForm;  //羁绊
    [SerializeField] Button resetBtn;
    [SerializeField] Button deleteBtn;
    [SerializeField] Button seeLhBtn;   //查看立绘
    [SerializeField] SkillBaseCell normalSkillCell;
    [SerializeField] SkillBaseCell angerSkillCell;
    [SerializeField] Button awakeBtn;
    [SerializeField] Button closeBtn;   //关闭按钮
    [SerializeField] List<Image> starImgList;
    [SerializeField] Text nameText;
    [SerializeField] UIEffectPlayer nameEffect;
    [SerializeField] Image countryImg;
    [SerializeField] Text awakeLVText;
    [SerializeField] Button attrBtn;
    [SerializeField] Image unfoldImg; //展开时按钮的图标
    [SerializeField] Image foldImg; //收起时按钮的图标
    bool unfoldState = false;//是否展开
    [SerializeField] Transform foldPos;
    [SerializeField] Transform unfoldPos;   //展开时的位置
    [SerializeField] RectTransform attrPanel;  //显示的属性栏
    [SerializeField] RectTransform attrScroll;
    [SerializeField] RichText inheritText;   //武将继承描述
    [SerializeField] Text[] inheritAttrText;    //武将会继承的属性
    [SerializeField] RichText heroAddPerText; //主公(上阵)加成描述
    [SerializeField] Text[] heroAddAttrPerText; //主公(上阵)加成
    [SerializeField] Text[] addPerText;    //增加百分比(飘动)
    [SerializeField] PositionTween addPerObject;
    [SerializeField] Image lvupMoneyIcon;
    [SerializeField] Text lvupMoneyText;
    [SerializeField] Text lvupBtnText;
    [SerializeField] LongPressButton lvupBtn;
    [SerializeField] Button allAttrBtn;
    string guid;
    HeroInfo hero;
    protected override void InitComponent()
    {
        showFuncBtn.AddListener(() =>
        {
            funcForm.SetActive(true);
        });
        seeLhBtn.AddListener(() =>
        {
            funcForm.SetActive(false);
        });
        closeBtn.AddListener(CloseWindow);
        rightBtn.AddListener(() =>
        {
            ChangeHero(1);
        });
        leftBtn.AddListener(() =>
        {
            ChangeHero(-1);
        });
        lockBtn.AddListener(SetLockState);
        resetBtn.AddListener(ResetBtnClick);
        deleteBtn.AddListener(DeleteHero);
        awakeBtn.AddListener(() =>
        {
            // UIManager.Instance.OpenWindow<HeroAwakeWin>(hero.heroId);
        });
        inheritText.OnClick = () =>
        {
            SmallTipWin.showText = Language.Get("herocard47");
            SmallTipWin.worldPos = CameraManager.uiCamera.ScreenToWorldPoint(Input.mousePosition);
            UIManager.Instance.OpenWindow<SmallTipWin>();
        };
        heroAddPerText.OnClick = () =>
        {
            SmallTipWin.showText = Language.Get("herocard48");
            SmallTipWin.worldPos = CameraManager.uiCamera.ScreenToWorldPoint(Input.mousePosition);
            UIManager.Instance.OpenWindow<SmallTipWin>();
        };
        attrBtn.AddListener(() =>
        {
            unfoldState = !unfoldState;
            RefreshFoldState();
        });
        allAttrBtn.AddListener(() =>
        {
            UIManager.Instance.OpenWindow<HeroAllAttrWin>(hero.itemHero.gridIndex);
        });
        lvupBtn.AddListener(LVUp);
        lvupBtn.onPress.AddListener(LVUp);
    }
    protected override void OnPreOpen()
    {
        PackManager.Instance.RefreshItemLockEvent += RefreshItemLockEvent;
        HeroManager.Instance.onHeroChangeEvent += RefreshHeroEvent;
        guid = HeroUIManager.Instance.selectHeroGuid;
        hero = HeroManager.Instance.GetHero(guid);
        unfoldState = false;
        addPerObject.SetActive(false);
        Refresh();
    }
    protected override void OnPreClose()
    {
        PackManager.Instance.RefreshItemLockEvent -= RefreshItemLockEvent;
        HeroManager.Instance.onHeroChangeEvent -= RefreshHeroEvent;
    }
    public override void Refresh()
    {
        roleLhModel.Create(hero.SkinID, 0.6f, motionName: "", isLh: true);
        roleXsModel.Create(hero.SkinID);
        jobImg.SetSprite(HeroUIManager.Instance.GetJobIconName(hero.heroConfig.Class));
        jobPosNameText.text = HeroUIManager.Instance.GetJobName(hero.heroConfig.Class);
        descText.text = hero.heroConfig.Desc;
        fightPowerText.text = hero.CalculatePower().ToString();
        lockImg.SetActive(hero.isLock);
        unLockImg.SetActive(!hero.isLock);
        nameText.text = hero.breakLevel == 0 ? hero.heroConfig.Name : Language.Get("herocardbreaklv", hero.heroConfig.Name, hero.breakLevel);
        RefreshConn();
        normalSkillCell.Init(hero.heroConfig.AtkSkillID, () =>
        {
            UIManager.Instance.OpenWindow<HeroSkillWin>(hero.heroId);
        }, true);
        angerSkillCell.Init(hero.heroConfig.AngerSkillID, () =>
        {
            UIManager.Instance.OpenWindow<HeroSkillWin>(hero.heroId);
        }, true);
        awakeBtn.SetActive(HeroAwakeConfig.CanAwake(hero.heroId, 1));
        RefreshName();
        RefreshFoldState();
        RefreshAttr();
    }
    void RefreshItemLockEvent(PackType type, string guid, bool lockState)
    {
        if (type != PackType.Hero)
            return;
        lockImg.SetActive(hero.isLock);
        unLockImg.SetActive(!hero.isLock);
    }
    void RefreshHeroEvent(HeroInfo hero)
    {
        Refresh();
    }
    void RefreshConn()
    {
        if (hero.heroConfig.FetterIDList.Length > 0)
        {
            connetionForm.SetActive(true);
            connetionForm.Display(hero.heroConfig.FetterIDList[0], Language.Get("herocard40"), true, guid);
        }
        else
        {
            connetionForm.SetActive(false);
        }
    }
    void ChangeHero(int changeValue)
    {
        var index = HeroUIManager.Instance.heroSortList.IndexOf(guid);
        if (index == -1)
            return;
        int resultIndex = index + changeValue;
        //循环处理
        if (resultIndex < 0)
        {
            resultIndex = HeroUIManager.Instance.heroSortList.Count - 1;
        }
        else if (resultIndex > HeroUIManager.Instance.heroSortList.Count - 1)
        {
            resultIndex = 0;
        }
        guid = HeroUIManager.Instance.heroSortList[resultIndex];
        hero = HeroManager.Instance.GetHero(guid);
        Refresh();
    }
    void SetLockState()
    {
        var pack = new CB238_tagCSHeroLock();
        pack.ItemIndex = (ushort)hero.itemHero.gridIndex;
        pack.IsLock = hero.isLock ? (byte)0 : (byte)1;
        GameNetSystem.Instance.SendInfo(pack);
    }
    void ResetBtnClick()
    {
        //升级、突破、觉醒
        if (hero.heroLevel == 1 && hero.breakLevel == 0 && hero.awakeLevel == 0)
        {
            SysNotifyMgr.Instance.ShowTip("HeroCanNotReset");
            return;
        }
        List<Item> items = new List<Item>();
        var payBack1 = CommonFunc.AddDict(HeroUIManager.Instance.GetHeroLVPayBack(hero.heroId, hero.heroLevel),
        HeroUIManager.Instance.GetHeroBreakPayBack(hero.heroId, hero.breakLevel));
        //已觉醒的需要消耗货币
        if (hero.awakeLevel == 0)
        {
            items = CommonFunc.ChangeToItemList(payBack1);
            ConfirmCancel.ShowItemsConfirm(items, Language.Get("herocard42"), Language.Get("herocard43"), (bool isOk) =>
            {
                if (isOk)
                {
                    //发包
                    SendReborn(hero.itemHero.gridIndex);
                }
            });
        }
        else
        {
            payBack1 = CommonFunc.AddDict(payBack1, HeroUIManager.Instance.GetHeroQualityAwakePayBack(hero.heroId, hero.awakeLevel));
            items = CommonFunc.ChangeToItemList(payBack1);
            var info2 = Language.Get("herocard44", HeroUIManager.Instance.awakeRebirthCnt);
            ConfirmCancel.ShowItemsConfirm(items, Language.Get("herocard42"), Language.Get("herocard43"), (bool isOk) =>
            {
                if (isOk)
                {
                    //发包
                    SendReborn(hero.itemHero.gridIndex);
                }
            }, info2, "", HeroUIManager.Instance.payBackMoney, HeroUIManager.Instance.payBackMoneyType);
        }
    }
    void SendReborn(int index)
    {
        var pack = new CB239_tagCSHeroRebirth();
        pack.ItemIndex = (ushort)index;
        GameNetSystem.Instance.SendInfo(pack);
    }
    void DeleteHero()
    {
        if (hero.isLock)
        {
            SysNotifyMgr.Instance.ShowTip("UnlockHero");
            return;
        }
    }
    void RefreshStars()
    {
        for (int i = 0; i < starImgList.Count; i++)
        {
            if (hero.heroStar == 0 && i == 0)
            {
                // 无星级 特殊处理
                starImgList[i].SetActive(true);
                starImgList[i].SetSprite("herostar" + hero.heroStar);
            }
            else if ((hero.heroStar - 1) % starImgList.Count >= i)
            {
                starImgList[i].SetActive(true);
                starImgList[i].SetSprite("herostar" + (((hero.heroStar - 1) / starImgList.Count) + 1) * starImgList.Count);
            }
            else
            {
                starImgList[i].SetActive(false);
            }
        }
    }
    void RefreshName()
    {
        RefreshStars();
        nameText.text = hero.breakLevel == 0 ? hero.heroConfig.Name : Language.Get("herocardbreaklv", hero.heroConfig.Name, hero.breakLevel);
        nameText.color = UIHelper.GetUIColorByFunc(hero.Quality);
        if (hero.Quality >= 4)
        {
            nameEffect.SetActive(true);
            nameEffect.Play(hero.Quality == 4 ? 0 : 1);
        }
        else
        {
            nameEffect.SetActive(false);
        }
        countryImg.SetSprite(HeroUIManager.Instance.GetCountryIconName(hero.heroConfig.Country));
        if (hero.awakeLevel == 0)
        {
            awakeLVText.text = Language.Get("L1094") + hero.heroLevel;
            awakeLVText.GetComponent<OutlineEx>().colorType = QualityTextColType.itemcucao;
        }
        else
        {
            awakeLVText.text = Language.Get("L1094") + hero.heroLevel + " " + Language.Get("herocard12", hero.awakeLevel);
            awakeLVText.GetComponent<OutlineEx>().colorType = QualityTextColType.red;
        }
    }
    void RefreshFoldState()
    {
        if (!unfoldState)
        {
            foldImg.SetActive(true);
            unfoldImg.SetActive(false);
            attrPanel.localPosition = foldPos.localPosition;
            attrScroll.sizeDelta = new Vector2(attrScroll.rect.width, 445);
        }
        else
        {
            foldImg.SetActive(false);
            unfoldImg.SetActive(true);
            attrPanel.localPosition = unfoldPos.localPosition;
            attrScroll.sizeDelta = new Vector2(attrScroll.rect.width, 933);
        }
    }
    void RefreshAttr()
    {
        inheritAttrText[0].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[0], hero.heroConfig.AtkInheritPer));
        inheritAttrText[1].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[1], hero.heroConfig.DefInheritPer));
        inheritAttrText[2].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[2], hero.heroConfig.HPInheritPer));
        //上阵属性
        int valuePer = hero.GetOnBattleAddPer();
        for (int i = 0; i < heroAddAttrPerText.Length; i++)
        {
            heroAddAttrPerText[i].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.basePerAttrs[i], valuePer));
        }
        //区分突破和最大等级
        if (!HeroUIManager.Instance.IsLVMax(hero))
        {
            lvupBtnText.text = Language.Get("L1109");
            lvupBtn.interactable = true;
            lvupBtn.SetColorful(null, true);
            lvupMoneyIcon.SetActive(true);
            if (HeroUIManager.Instance.IsLVMaxByBreakLevel(hero))
            {
                lvupBtnText.text = Language.Get("L1111");
                var breakConfig = HeroQualityBreakConfig.GetQualityBreakConfig(hero.Quality, hero.breakLevel);
                lvupMoneyIcon.SetOrgSprite(ItemConfig.Get(breakConfig.UPCostItem[0]).IconKey);
                lvupMoneyText.text = UIHelper.ShowUseItem(PackType.Item, breakConfig.UPCostItem[0], (ulong)breakConfig.UPCostItem[1]);
            }
            else
            {
                lvupBtnText.text = Language.Get("L1109");
                var lvupConfig = HeroQualityLVConfig.GetQualityLVConfig(hero.Quality, hero.heroLevel);
                lvupMoneyIcon.SetOrgSprite(ItemConfig.Get(lvupConfig.UPCostItem[0]).IconKey);
                lvupMoneyText.text = UIHelper.ShowUseItem(PackType.Item, lvupConfig.UPCostItem[0], (ulong)lvupConfig.UPCostItem[1]);
            }
        }
        else
        {
            lvupBtnText.text = Language.Get("L1110");
            lvupBtn.interactable = false;
            lvupBtn.SetColorful(null, false);
            lvupMoneyIcon.SetActive(false);
        }
    }
    void LVUp()
    {
        int itemID = 0;
        ulong needCount = 0;
        if (HeroUIManager.Instance.IsLVMaxByBreakLevel(hero))
        {
            //突破
            if (!UIManager.Instance.IsOpened<HeroLVBreakWin>())
            {
                HeroUIManager.Instance.selectHeroGuid = guid;
                UIManager.Instance.OpenWindow<HeroLVBreakWin>();
            }
        }
        else
        {
            //升级
            var lvupConfig = HeroQualityLVConfig.GetQualityLVConfig(hero.Quality, hero.heroLevel);
            itemID = lvupConfig.UPCostItem[0];
            needCount = (ulong)lvupConfig.UPCostItem[1];
            if (ItemLogicUtility.CheckItemCount(PackType.Item, itemID, needCount, 2))
            {
                var pack = new CB230_tagCSHeroLVUP();
                pack.ItemIndex = (ushort)hero.itemHero.gridIndex;
                GameNetSystem.Instance.SendInfo(pack);
                //预显示
                lvupEffect.Play();
                addPerObject.SetActive(true);
                for (int i = 0; i < addPerText.Length; i++)
                {
                    addPerText[i].text = "+" + PlayerPropertyConfig.GetValueDescription(PlayerPropertyConfig.basePerAttrs[i], hero.qualityConfig.BreakLVAddPer);
                }
                addPerObject.Play(()=>
                {
                    addPerObject.SetActive(false);
                });
            }
        }
    }
}
Main/System/HeroUI/HeroTrainWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b5c5fe2d295e8a1439a4d5b2c223577b
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/HeroUI/HeroUIManager.cs
@@ -1,9 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using dnlib.DotNet;
using UnityEngine;
@@ -11,33 +8,123 @@
public class HeroUIManager : GameSystemManager<HeroUIManager>
{
    #region 武将列表界面
    public List<string> heroSortList { get; private set; } = new List<string>();  //上阵为主线的列表
    public List<string> heroSortList { get; private set; } = new List<string>();  //上阵为主线的 GUID列表
    public int selectHeroListJob = 0;    //武将列表界面 筛选职业
    public int selectHeroListCountry = 0;    //武将列表界面筛选国家
    public string selectHeroGuid; //选中的武将id
    #endregion
    public WaitHeroFuncResponse waitResponse;    //请求武将功能
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize;
        HeroManager.Instance.onHeroChangeEvent += OnHeroChangeEvent;
        ParseConfig();
    }
    public override void Release()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitialize;
        HeroManager.Instance.onHeroChangeEvent -= OnHeroChangeEvent;
    }
    void ParseConfig()
    {
        var config = FuncConfigConfig.Get("HeroRebirth");
        payBackMoneyType = int.Parse(config.Numerical1);
        payBackMoney = int.Parse(config.Numerical2);
    }
    public void OnBeforePlayerDataInitialize()
    {
        heroSortList.Clear();
        heroOnTeamSortList.Clear();
        awakeRebirthCnt = 0;
        waitResponse = default;
    }
    public void OnPlayerLoginOk()
    private void OnHeroChangeEvent(HeroInfo hero)
    {
        if (!DTC0403_tagPlayerLoginLoadOK.finishedLogin)
            return;
        WaitServerResponse(hero);
    }
    public override void Init()
    private void WaitServerResponse(HeroInfo hero)
    {
        if (waitResponse.Equals(default(WaitHeroFuncResponse)))
        {
            return;
        }
        // 等待超过5秒 不处理
        var nowTime = Time.time;
        if (waitResponse.time > 0f && waitResponse.time + 5 < nowTime)
        {
            waitResponse = default;
            return;
        }
        if (hero.itemHero.guid != waitResponse.guid)
        {
            return;
        }
        if (waitResponse.type == HeroFuncType.Break)
        {
            UIManager.Instance.OpenWindow<HeroLVBreakSuccessWin>();
        }
        waitResponse = default;
    }
    public override void Release()
    #region 武将UI常用接口
    public string GetCountryName(int index)
    {
        return RichTextMsgReplaceConfig.GetRichReplace("Country", index);
    }
    public string GetJobName(int index)
    {
        return RichTextMsgReplaceConfig.GetRichReplace("Class", index);
    }
    public string GetCountryIconName(int index)
    {
        return StringUtility.Contact("herocountry", index);
    }
    public string GetJobIconName(int index)
    {
        return StringUtility.Contact("herojob", index);
    }
    public int GetMaxLV(int quality)
    {
        return HeroQualityBreakConfig.maxlvDic[quality];
    }
    //是否达到最高级
    public bool IsLVMax(HeroInfo hero)
    {
        return hero.heroLevel >= GetMaxLV(hero.Quality);
    }
    //突破限制的最高等级
    public int GetMaxLVByBreakLV(int quality, int breakLevel)
    {
        return HeroQualityBreakConfig.GetQualityBreakConfig(quality, breakLevel).LVMax;
    }
    public bool IsLVMaxByBreakLevel(HeroInfo hero)
    {
        return hero.heroLevel == GetMaxLVByBreakLV(hero.Quality, hero.breakLevel);
    }
    #endregion
    public void QueryUnLockHeroPack()
@@ -58,7 +145,7 @@
                {
                    if (UIHelper.GetMoneyCnt(buyInfo[0]) < (ulong)buyInfo[1])
                    {
                        SysNotifyMgr.Instance.ShowTip("LackMoney",buyInfo[0]);
                        SysNotifyMgr.Instance.ShowTip("LackMoney", buyInfo[0]);
                        return;
                    }
                    PackManager.Instance.BuyPackGird(PackType.Hero);
@@ -119,7 +206,7 @@
    private TeamType m_SelectTeamType = TeamType.Story; //当前选中的是哪个阵容, 布阵相关逻辑使用
    public TeamType selectTeamType
    {
    {
        get { return m_SelectTeamType; }
        set
        {
@@ -133,7 +220,7 @@
            m_SelectTeamType = value;
        }
    }
    }
    public int selectTeamPosJob = 0;    //布阵界面 筛选职业
    public int selectTeamPosCountry = 0;    //布阵界面 筛选国家
@@ -326,4 +413,90 @@
    #endregion
    #region 重生 遣散
    public int awakeRebirthCnt { get; private set; }
    public int payBackMoneyType;
    public int payBackMoney;
    public Dictionary<int, ulong> GetHeroLVPayBack(int quality, int lv)
    {
        //汇总返还总数量
        Dictionary<int, ulong> itemCounDic = new Dictionary<int, ulong>();
        for (int i = 1; i < lv; i++)
        {
            var config = HeroQualityLVConfig.GetQualityLVConfig(quality, lv);
            var itemID = config.UPCostItem[0];
            var count = (ulong)config.UPCostItem[1];
            if (!itemCounDic.ContainsKey(itemID))
            {
                itemCounDic[itemID] = count;
            }
            itemCounDic[itemID] = itemCounDic[itemID] + count;
        }
        return itemCounDic;
    }
    public Dictionary<int, ulong> GetHeroBreakPayBack(int quality, int lv)
    {
        //汇总返还总数量
        Dictionary<int, ulong> itemCounDic = new Dictionary<int, ulong>();
        for (int i = 0; i < lv; i++)
        {
            var config = HeroQualityBreakConfig.GetQualityBreakConfig(quality, lv);
            var itemID = config.UPCostItem[0];
            var count = (ulong)config.UPCostItem[1];
            if (!itemCounDic.ContainsKey(itemID))
            {
                itemCounDic[itemID] = count;
            }
            itemCounDic[itemID] = itemCounDic[itemID] + count;
        }
        return itemCounDic;
    }
    public Dictionary<int, ulong> GetHeroQualityAwakePayBack(int quality, int lv)
    {
        //汇总返还总数量
        Dictionary<int, ulong> itemCounDic = new Dictionary<int, ulong>();
        for (int i = 0; i < lv; i++)
        {
            var config = HeroQualityAwakeConfig.GetQualityAwakeConfig(quality, lv);
            var itemID = config.UPCostItem[0];
            var count = (ulong)config.UPCostItem[1];
            if (!itemCounDic.ContainsKey(itemID))
            {
                itemCounDic[itemID] = count;
            }
            itemCounDic[itemID] = itemCounDic[itemID] + count;
        }
        return itemCounDic;
    }
    public void UpdateHeroInfo(HB125_tagSCPlayerHeroInfo netPack)
    {
        awakeRebirthCnt = netPack.AwakeRebirthCnt;
    }
    #endregion
}
public struct WaitHeroFuncResponse
{
    public HeroFuncType type;
    public string guid;
    public float time;
}
//武将功能类型
public enum HeroFuncType
{
    None = 0,   //无功能
    Break = 1,  //突破
}
Main/System/ItemTip/BoxGetItemModel.cs
@@ -103,7 +103,9 @@
        {
            for (int i = 0; i < netPack.ItemLen; i++)
            {
                showItems.Add(new Item((int)netPack.ItemList[i].ItemID, netPack.ItemList[i].Count, netPack.ItemList[i].IsBind));
                showItems.Add(new Item((int)netPack.ItemList[i].ItemID,
                netPack.ItemList[i].Count + netPack.ItemList[i].CountEx * Constants.ExpPointValue,
                netPack.ItemList[i].IsBind));
            }
        }
Main/System/ItemTip/ItemTipUtility.cs
@@ -223,7 +223,7 @@
    public static TipData mainTipData { get; private set; }     // 注意当递进点击打开多个tip界面会变更数据,不能依赖此值
    public static TipData secondaryData { get; private set; }
    public static void Show(int itemId)
    public static void Show(int itemId, bool showGetWay = false)
    {
        if (!ItemConfig.HasKey(itemId))
        {
@@ -234,6 +234,7 @@
        Show(new ItemViewInfo()
        {
            itemId = itemId,
            unfoldGetWay = showGetWay
        });
    }
@@ -281,31 +282,38 @@
        }
        mainTipData.getWay.defaultUnfold = item.unfoldGetWay;
        switch (tipType)
        if (mainTipData.getWay.defaultUnfold)
        {
            case TipType.Equip:
                // WindowCenter.Instance.Open<EquipTipWin>();
                break;
            // case TipType.PetMount:
            //      WindowCenter.Instance.Open<PetMountTipWin>();
            //     break;
            case TipType.BoxItem:
                UIManager.Instance.OpenWindow<BoxItemWin>();
                break;
            case TipType.BoxChooseItem:
                UIManager.Instance.OpenWindow<ChooseItemsWin>();
                break;
            case TipType.TreasurePavilion:
                // TreasurePavilionModel.Instance.selectGubao = config.EffectValueA1;
                // TreasurePavilionModel.Instance.showTipFromPiece = config.ID;
                // WindowCenter.Instance.OpenIL<TreasurePavilionTipWin>();
                break;
            default:
                UIManager.Instance.OpenWindow<ItemTipWin>();
                break;
            UIManager.Instance.OpenWindow<ItemTipWayWin>(itemId);
            return;
        }
        switch (tipType)
            {
                case TipType.Equip:
                    // WindowCenter.Instance.Open<EquipTipWin>();
                    break;
                // case TipType.PetMount:
                //      WindowCenter.Instance.Open<PetMountTipWin>();
                //     break;
                case TipType.BoxItem:
                    UIManager.Instance.OpenWindow<BoxItemWin>();
                    break;
                case TipType.BoxChooseItem:
                    UIManager.Instance.OpenWindow<ChooseItemsWin>();
                    break;
                case TipType.TreasurePavilion:
                    // TreasurePavilionModel.Instance.selectGubao = config.EffectValueA1;
                    // TreasurePavilionModel.Instance.showTipFromPiece = config.ID;
                    // WindowCenter.Instance.OpenIL<TreasurePavilionTipWin>();
                    break;
                default:
                    UIManager.Instance.OpenWindow<ItemTipWin>();
                    break;
            }
    }
    public static void Show(string guid, bool operatable = true)
Main/System/ItemTip/ItemTipWayWin.cs
New file
@@ -0,0 +1,64 @@

using UnityEngine;
using UnityEngine.UI;
public class ItemTipWayWin : UIBase
{
    [SerializeField] ItemCell itemCell;
    [SerializeField] Text nameText;
    [SerializeField] Text descText;
    [SerializeField] ScrollerController scroller;
    int itemID;
    protected override void OnPreOpen()
    {
        scroller.OnRefreshCell += OnRefreshCell;
        itemID = functionOrder;
        itemCell.Init(new ItemCellModel(itemID, false, 0));
        var itemConfig = ItemConfig.Get(itemID);
        nameText.text = itemConfig.ItemName;
        descText.text = itemConfig.Description;
        CreateScroller();
    }
    protected override void OnPreClose()
    {
        scroller.OnRefreshCell -= OnRefreshCell;
    }
    void CreateScroller()
    {
        var itemConfig = ItemConfig.Get(itemID);
        scroller.Refresh();
        for (int i = 0; i < itemConfig.GetWay.Length; i++)
        {
            scroller.AddCell(ScrollerDataType.Header, itemConfig.GetWay[i]);
        }
        scroller.Restart();
    }
    void OnRefreshCell(ScrollerDataType type, CellView cell)
    {
        var way = GetItemWaysConfig.Get(cell.index);
        var nameText = cell.FindComponent("Text", "name") as Text;
        nameText.text = way.name;
        var descText = cell.FindComponent("Text", "way") as Text;
        descText.text = way.Text;
        cell.GetComponent<Button>().AddListener(()=>
        {
            UIJumpManager.Instance.OpenWindow(way.WinJumpID);
        });
    }
}
Main/System/ItemTip/ItemTipWayWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 873e79fb0b0d62d4993b62fedc63e337
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/ItemTip/SmallTipWin.cs
New file
@@ -0,0 +1,72 @@
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 文本提示界面
/// </summary>
public class SmallTipWin : UIBase
{
    [SerializeField] RectTransform rectTransform;
    [SerializeField] RectTransform arrowImage;
    [SerializeField] Text descText;
    public static Vector3 worldPos; //世界坐标系位置
    public static string showText;
    protected override void OnPreOpen()
    {
        descText.text = showText;
        rectTransform.position = new Vector3(100, 100, 100);   //初始化时,屏幕范围外
    }
    protected override void OnOpen()
    {
        UpdatePos().Forget();
    }
    async UniTask UpdatePos()
    {
        await UniTask.DelayFrame(3);
        // 限制在屏幕范围内
        Vector3[] corners = new Vector3[4];
        rectTransform.GetWorldCorners(corners);
        float minY = corners[0].y;
        float maxY = corners[0].y;
        for (int i = 1; i < corners.Length; i++)
        {
            if (corners[i].y < minY) minY = corners[i].y;
            if (corners[i].y > maxY) maxY = corners[i].y;
        }
        float screenHeight = maxY - minY;
        Vector2 adjustedPos = new Vector2(worldPos.x, worldPos.y + screenHeight * 0.5f);
        Vector2 screenAdjustedPos = CameraManager.uiCamera.WorldToScreenPoint(adjustedPos);
        screenAdjustedPos.x = Mathf.Clamp(screenAdjustedPos.x, rectTransform.rect.width * 0.5f, Screen.width - rectTransform.rect.width * 0.5f);
        screenAdjustedPos.y = Mathf.Clamp(screenAdjustedPos.y, rectTransform.rect.height * 0.5f, Screen.height - rectTransform.rect.height * 0.5f - 15);
        adjustedPos = CameraManager.uiCamera.ScreenToWorldPoint(screenAdjustedPos);
        rectTransform.position = adjustedPos;
        rectTransform.localPosition = new Vector3(rectTransform.localPosition.x, rectTransform.localPosition.y + 15, rectTransform.localPosition.z);
        rectTransform.GetWorldCorners(corners);
        float minX = corners[0].x;
        float maxX = corners[0].x;
        for (int i = 1; i < corners.Length; i++)
        {
            if (corners[i].x < minX) minX = corners[i].x;
            if (corners[i].x > maxX) maxX = corners[i].x;
        }
        //显示arrowImage 的x轴上的位置,和worldPos同步,但不超过minX 和 maxX范围
        Vector3 arrowImagePosition = arrowImage.position;
        arrowImagePosition.x = Mathf.Clamp(worldPos.x, minX, maxX);
        arrowImage.position = arrowImagePosition;
    }
}
Main/System/ItemTip/SmallTipWin.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b032869b3ea6c248a6e7c7cbb6c66c2
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/KnapSack/Logic/ItemLogicUtility.cs
@@ -354,11 +354,11 @@
        int startLockIndex = singlePack.unlockedGridCount - PackManager.Instance.initBagGridCount;
        FuncConfigConfig _tagFuncModel = FuncConfigConfig.Get("OpenBagItem");
        int haveCount = packModel.GetItemCountByID(PackType.Item, itemId);
        var haveCount = packModel.GetItemCountByID(PackType.Item, itemId);
        Equation.Instance.Clear();
        Equation.Instance.AddKeyValue("index", startLockIndex + 1);
        int needTool = Equation.Instance.Eval<int>(_tagFuncModel.Numerical2);
        if (haveCount >= needTool)
        if (haveCount >= (ulong)needTool)
        {
            return true;
        }
@@ -372,30 +372,28 @@
    /// <param name="packType 背包类型"></param>
    /// <param name="itemId 物品ID"></param>
    /// <param name="needCount 需要数量"></param>
    /// <param name="needTips 是否需要提示"></param>
    /// <param name="needTips">0 不响应 1 弹提示 2 弹获取途径tips</param>
    /// <returns></returns>
    public static bool CheckItemCount(PackType packType, int itemId, int needCount, bool needTips = false)
    public static bool CheckItemCount(PackType packType, int itemId, ulong needCount, int needTips = 0)
    {
        if (needCount <= 0)
        {
            return true;
        }
        int haveCount = PackManager.Instance.GetItemCountByID(packType, itemId);
        var haveCount = PackManager.Instance.GetItemCountByID(packType, itemId);
        bool isEnough = haveCount >= needCount;
        if (!isEnough && needTips)
        if (!isEnough)
        {
            var itemConfig = ItemConfig.Get(itemId);
            if (null != itemConfig)
            if (needTips == 1)
            {
                //  是否有获取途径
                //  是 弹出获取途径
                //  否 显示物品数量不足
                // SysNotifyMgr.Instance.ShowTip();
                // YYL TODO
                SysNotifyMgr.Instance.ShowTip("ItemNotEnough", itemId);
            }
            else if (needTips == 2)
            {
                ItemTipUtility.Show(itemId, true);
            }
        }
@@ -415,12 +413,7 @@
        if (!isEnough && needTips)
        {
            //  是否有获取途径
            //  是 弹出获取途径
            //  否 显示物品数量不足
            // SysNotifyMgr.Instance.ShowTip();
            // YYL TODO
            Debug.LogError("货币不足 " + moneyType);
            SysNotifyMgr.Instance.ShowTip("LackMoney", moneyType);
        }
        return isEnough;
Main/System/KnapSack/Logic/SinglePack.cs
@@ -181,21 +181,16 @@
        return list;
    }
    public int GetCountById(int itemId, bool includeAuction = true)
    public ulong GetCountById(int itemId, bool includeAuction = true)
    {
        var count = 0;
        //foreach (var item in items.Values)
        //{
        //    if (!includeAuction && item.isAuction)
        //    {
        //        continue;
        //    }
        ulong count = 0;
        //    if (item.itemId == itemId)
        //    {
        //        count += item.count;
        //    }
        //}
        //部分货币和物品绑定
        if (GeneralDefine.itemMoneyCountDict.ContainsKey(itemId))
        {
            //展示货币数量的物品
            count = UIHelper.GetMoneyCnt(GeneralDefine.itemMoneyCountDict[itemId]);
        }
        if (itemIDs.ContainsKey(itemId))
        {
@@ -206,7 +201,7 @@
                {
                    continue;
                }
                count += item.count;
                count += (ulong)item.count;
            }
        }
        return count;
Main/System/KnapSack/New/CommonItemBaisc.cs
@@ -216,7 +216,6 @@
        itemIcon.SetActive(true);
        bgIcon.SetActive(true);
        itemIcon.SetOrgSprite(config.IconKey);
        ItemConfig itemConfig = ItemConfig.Get(itemId);
        bgIcon.SetItemBackGround(ItemLogicUtility.Instance.GetItemQuality(itemId, useDataDic));
        if (packModel.gameCashShow.Contains(itemId))
        {
@@ -274,7 +273,7 @@
        {
            var heroConfig = HeroConfig.Get(itemId);
            countryIcon.SetActive(true);
            countryIcon.SetSprite("herocountry" + heroConfig.Country);
            countryIcon.SetSprite(HeroUIManager.Instance.GetCountryIconName(heroConfig.Country));
        }
        else
Main/System/KnapSack/PackManager.cs
@@ -24,6 +24,7 @@
    public event Action<int> refreshItemDayUseCountEvent;  //刷新物品每日使用数量
    public event Action<int> refreshItemSumUseCountEvent;  //刷新物品总使用数量
    public event Action<PackType, string, bool> RefreshItemLockEvent; //物品锁定刷新 背包类型,guid,锁定状态
    public bool isPlayBetterEquipEffect { get; set; }  //整理背包时是否播放特效
@@ -57,7 +58,6 @@
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize;
        DTC0102_tagCDBPlayer.afterPlayerDataInitializeEvent += OnAfterPlayerDataInitialize;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnPlayerLoginOk;
        ParseConfig();
        //SysNotifyMgr.Instance.sysNotifyEvent += RefreshSysInfo;
@@ -89,7 +89,6 @@
    public override void Release()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitialize;
        DTC0102_tagCDBPlayer.afterPlayerDataInitializeEvent -= OnAfterPlayerDataInitialize;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk;
        FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
        // SysNotifyMgr.Instance.sysNotifyEvent -= RefreshSysInfo;
@@ -111,13 +110,11 @@
        itemDayUseCntDict.Clear();
        itemSumUseCntDict.Clear();
        itemGUIDDict.Clear();
        PackGirdServerBuyCountDict.Clear();
        isPlayBetterEquipEffect = false;
    }
    public void OnAfterPlayerDataInitialize()
    {
    }
    public void OnPlayerLoginOk()
    {
@@ -257,10 +254,22 @@
    }
    public void UpdateItemLockState(H0722_tagItemDeadLockRefresh netPack)
    {
        var singlePack = GetSinglePack((PackType)netPack.PackType);
        var item = singlePack.GetItemByIndex(netPack.ItemIndex);
        if (item == null)
        {
            return;
        }
        item.itemInfo.isLock = netPack.IsLock == 1;
        RefreshItemLockEvent?.Invoke((PackType)netPack.PackType, item.guid, item.itemInfo.isLock);
    }
    public void UpdateBuyPackGirdCount(HA207_tagSCPackBuyInfo netPack)
    {
        for (int i = 0; i < netPack.BuyInfoList.Length; i++)
        {
        {
            PackGirdServerBuyCountDict[netPack.BuyInfoList[i].PackType] = netPack.BuyInfoList[i].BuyCnt;
        }
    }
@@ -306,6 +315,8 @@
        UpdatePackRedpoint(type);
    }
    public void RefreshItemCount(H0707_tagItemCountRefresh refresh)
    {
@@ -765,14 +776,14 @@
    /// <summary>
    /// 得到ID相同的物品数量
    /// 得到ID相同的物品数量; 也可以获得部分货币和物品绑定的数量
    /// </summary>
    /// <param name="type"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public int GetItemCountByID(PackType type, int id, bool includeAuction = true)
    public ulong GetItemCountByID(PackType type, int id, bool includeAuction = true)
    {
        int count = 0;
        ulong count = 0;
        var singlePack = GetSinglePack(type);
        if (singlePack != null)
        {
@@ -913,22 +924,23 @@
    public void SetLookIndex(string guid, int singleRowCount = 5)
    {
        if (string.IsNullOrEmpty(guid) || guid == "")
        {
            lookLineIndex = -1;
            lookItemGUID = "";
        }
        else
        {
            int index = GetItemByGuid(guid).gridIndex;
            lookLineIndex = index / singleRowCount;
            lookItemGUID = guid;
        }
        return;
        // if (string.IsNullOrEmpty(guid) || guid == "")
        // {
        //     lookLineIndex = -1;
        //     lookItemGUID = "";
        // }
        // else
        // {
        //     int index = GetItemByGuid(guid).gridIndex;
        //     lookLineIndex = index / singleRowCount;
        //     lookItemGUID = guid;
        // }
        if (lookEquipEvent != null)
        {
            lookEquipEvent();
        }
        // if (lookEquipEvent != null)
        // {
        //     lookEquipEvent();
        // }
    }
    public event Action RefreshBagEvent;
Main/System/Message/HrefAnalysis.cs
@@ -30,7 +30,7 @@
            presentHrefInfo = hrefInfo;
            if (RichTextMgr.Inst.presentRichText != null)
            {
                presentHrefInfo.unlineColor = UIHelper.GetUIColor(TextColType.Green, RichTextMgr.Inst.presentRichText.colorType == RichText.ColorType.Bright);
                presentHrefInfo.unlineColor = RichTextMgr.Inst.presentRichText.color;
            }
            m_StringBuilder.Append(val.Substring(index, match.Groups[1].Index - index));
            insertIndex = m_StringBuilder.Length - 3;
Main/System/Message/RichNormalEvent.cs
@@ -94,29 +94,29 @@
            //         }
            //     }
            //     break;
            // case RichTextEventEnum.OPENUI:
            //     {
            //         int id = 0;
            //         if (int.TryParse(href.mSplits["openui"], out id))
            //         {
            //             WindowJumpMgr.Instance.WindowJumpTo((JumpUIType)id);
            //         }
            //         else
            //         {
            //             var list = href.mSplits["openui"].Split('_');
            //             int funcOrder = 0;
            //             if (list.Length != 1)
            //             {
            //                 funcOrder = int.Parse(list[1]);
            //             }
            //             WindowJumpMgr.Instance.WindowJumpToEx(list[0], 1, 0, funcOrder);
            //             if (list.Length > 2)
            //             {
            //                 ModelCenter.Instance.GetModel<RoleModel>().openUIMark = int.Parse(list[2]);
            //             }
            //         }
            //     }
            //     break;
            case RichTextEventEnum.OPENUI:
                {
                    // int id = 0;
                    // if (int.TryParse(href.mSplits["openui"], out id))
                    // {
                    //     WindowJumpMgr.Instance.WindowJumpTo((JumpUIType)id);
                    // }
                    // else
                    // {
                    //     var list = href.mSplits["openui"].Split('_');
                    //     int funcOrder = 0;
                    //     if (list.Length != 1)
                    //     {
                    //         funcOrder = int.Parse(list[1]);
                    //     }
                    //     WindowJumpMgr.Instance.WindowJumpToEx(list[0], 1, 0, funcOrder);
                    //     if (list.Length > 2)
                    //     {
                    //         ModelCenter.Instance.GetModel<RoleModel>().openUIMark = int.Parse(list[2]);
                    //     }
                    // }
                }
                break;
            // case RichTextEventEnum.OPENURL:
            //     {
            //         var url = href.mSplits["openurl"];
Main/System/Message/RichText.cs
@@ -619,6 +619,7 @@
    #region 执行事件
    public void OnPointerClick(PointerEventData eventData)
    {
        OnClick?.Invoke();
        if (HrefClick)
        {
            Vector2 lp;
@@ -640,7 +641,6 @@
                }
            }
        }
        if (OnClick != null) OnClick();
    }
    public void OnImgClick()
Main/System/PhantasmPavilion/PhantasmPavilionModel.cs
@@ -429,8 +429,8 @@
            if (itemConfig.UseLV > PlayerDatas.Instance.baseData.LV)
                return 0;
            //激活物品数量不足
            int hasCnt = PackManager.Instance.GetItemCountByID(PackType.Item, itemId);
            if (hasCnt < count)
            var hasCnt = PackManager.Instance.GetItemCountByID(PackType.Item, itemId);
            if (hasCnt < (ulong)count)
                return 0;
            return 1;
        }
Main/System/SkillUI/SkillBaseCell.cs
@@ -50,15 +50,31 @@
        LoadPrefab();
    }
    private void Init(int skillID, UnityAction onclick, bool showType = false)
    public void Init(int skillID, UnityAction onclick = null, bool showType = false)
    {
        var config = SkillConfig.Get(skillID);
        skillIcon.SetSprite(config.IconName);
        skillBtn.AddListener(onclick);
        if (config == null)
        {
            Debug.LogErrorFormat("技能未配置 : {0}", skillID);
            return;
        }
        skillIcon.SetOrgSprite(config.IconName, "SkillIcon");
#if UNITY_EDITOR
        if (string.IsNullOrEmpty(config.IconName))
        {
            //内网测试
            skillIcon.SetOrgSprite("skillicondefault", "SkillIcon");
        }
#endif
        skillBtn.AddListener(()=>
        {
            onclick?.Invoke();
        });
        if (showType)
        {
            skillType.text = Language.Get(config.FuncType == 23 ? "HeroSkillType_1" : "HeroSkillType_2");
            skillType.text = Language.Get(config.FuncType == 1 ? "HeroSkillType_1" : "HeroSkillType_2");
        }
        else
        { 
Main/System/Tip/ConfirmCancel.cs
@@ -259,19 +259,18 @@
    public static string generalItemTip;
    public static string generalItemTip2;
    public static Action ItemConfirmEvent;
    public static List<Item> getItems { get; private set; }
    //多物品确认框
    public static void ShowItemsConfirm(List<Item> items, string tiltle, string info, string info2, string btnText, Action func, int moneyCnt = 0, int type = 0)
    public static void ShowItemsConfirm(List<Item> items, string tiltle, string info, Action<bool> func,
        string info2 = "", string btnText = "", int moneyCnt = 0, int type = 0)
    {
        getItems = items;
        generalTitle = tiltle;
        generalItemTip = info;
        generalItemTip2 = info2;
        ItemConfirmEvent = func;
        OKName = btnText;
        ItemConfirmEvent = func;
        OnPopConfirmClickEvent = func;
        moneyType = type;
        moneyNeedCount = moneyCnt;
        if (!UIManager.Instance.IsOpened<ItemsConfirmWin>())
Main/System/Tip/ItemsConfirmWin.cs
@@ -9,6 +9,7 @@
    [SerializeField] Text m_Info2;  //物品列表下方提示
    [SerializeField] ScrollerController m_Scroller;
    [SerializeField] Button m_ConfirmBtn;
    [SerializeField] Button m_CancleBtn;
    [SerializeField] Text m_BtnText;
    [SerializeField] Transform moneyObj;
    [SerializeField] Text moneyText;
@@ -21,24 +22,21 @@
    protected override void InitComponent()
    {
        m_ConfirmBtn.AddListener(ConfirmBtn);
        m_CancleBtn.AddListener( ()=>
        {
            ConfirmCancel.OnPopConfirmClickEvent?.Invoke(false);
            CloseWindow();
        });
    }
    protected override void OnPreOpen()
    {
        m_Title.text = ConfirmCancel.generalTitle;
        m_Info.text = ConfirmCancel.generalItemTip;
        if (string.IsNullOrEmpty(ConfirmCancel.generalItemTip2))
        {
            m_Info2.SetActive(false);
        }
        else
        {
            m_Info2.SetActive(true);
            m_Info2.text = ConfirmCancel.generalItemTip2;
        }
        m_Info2.text = ConfirmCancel.generalItemTip2;
        m_Scroller.OnRefreshCell += OnRefreshCell;
        CreateScroller();
        m_BtnText.text = ConfirmCancel.OKName;
        m_BtnText.text = string.IsNullOrEmpty(ConfirmCancel.OKName) ? Language.Get("L1001") : ConfirmCancel.OKName;
        if (ConfirmCancel.moneyNeedCount == 0)
        {
            moneyObj.SetActive(false);
@@ -46,9 +44,7 @@
        else
        {
            moneyObj.SetActive(true);
            moneyText.text = UIHelper.AppendColor((ulong)ConfirmCancel.moneyNeedCount > UIHelper.GetMoneyCnt(ConfirmCancel.moneyType) ? TextColType.Red:TextColType.Green,
                string.Format("{0}/{1}", UIHelper.GetMoneyCnt(ConfirmCancel.moneyType), ConfirmCancel.moneyNeedCount));
            moneyText.text = UIHelper.ShowUseMoney(ConfirmCancel.moneyType, (ulong)ConfirmCancel.moneyNeedCount);
            moneyIcon.SetIconWithMoneyType(ConfirmCancel.moneyType);
        }
    }
@@ -57,16 +53,14 @@
    protected override void OnPreClose()
    {
        m_Scroller.OnRefreshCell -= OnRefreshCell;
    }
    #endregion
    private void ConfirmBtn()
    {
        if (ConfirmCancel.ItemConfirmEvent != null)
        {
            ConfirmCancel.ItemConfirmEvent();
        }
        ConfirmCancel.OnPopConfirmClickEvent?.Invoke(true);
    }
Main/System/UIBase/UIBase.cs
@@ -67,8 +67,8 @@
    [HideInInspector] public UIBase parentUI;
    // 子UI管理
    [HideInInspector] public List<UIBase> childrenUI = new List<UIBase>();
    [HideInInspector] public List<UIBase> childrenUI = new List<UIBase>();
    [Header("所有UI排版应该在此节点内层")]
    [SerializeField] protected RectTransform _rectTransform; //界面默认添加根节点用于表现界面开启关闭动画,或者设置适配用
@@ -126,8 +126,8 @@
            originalPosition = _rectTransform.anchoredPosition;;
        }
        if (screenMask != null)
        if (screenMask != null)
            screenMask.transform.SetAsFirstSibling();
        InitClickEmptySpaceBtn();
    }
@@ -142,33 +142,33 @@
        if (clickEmptySpaceClose)
        {
            //延迟x帧后可点击,防止点击过快立即关闭了
            await UniTask.DelayFrame(5);
            btnClickEmptyClose.interactable = true;
            await UniTask.Delay(200);
            btnClickEmptyClose.enabled = true;
        }
    }
    private void InitClickEmptySpaceBtn()
    {
        if (!clickEmptySpaceClose)
        {
            return;
        }
        btnClickEmptyClose = screenMask.GetComponent<Button>();
        btnClickEmptyClose.AddListener(() =>
        {
            if (btnClickEmptyCloseEvent != null)
            {
                btnClickEmptyCloseEvent();
            }
            else
            {
                CloseWindow();
            }
        });
        btnClickEmptyClose.interactable = false;
    private void InitClickEmptySpaceBtn()
    {
        if (!clickEmptySpaceClose)
        {
            return;
        }
        btnClickEmptyClose = screenMask.GetComponent<Button>();
        btnClickEmptyClose.AddListener(() =>
        {
            if (btnClickEmptyCloseEvent != null)
            {
                btnClickEmptyCloseEvent();
            }
            else
            {
                CloseWindow();
            }
        });
        btnClickEmptyClose.enabled = false;
    }
@@ -260,8 +260,8 @@
            return;
        }
        if ((clickEmptySpaceClose || openMask) && screenMask == null)
        {
        if ((clickEmptySpaceClose || openMask) && screenMask == null)
        {
            Debug.LogError($"界面: {uiName} 缺少遮罩 ");
            return;
        }
@@ -298,10 +298,10 @@
    public void HandleClose()
    {
        // 如果已经在关闭过程中,直接返回
        if (isClosing) return;
        if (clickEmptySpaceClose)
            btnClickEmptyClose.interactable = false;
        if (isClosing) return;
        if (clickEmptySpaceClose)
            btnClickEmptyClose.enabled = false;
        OnPreClose();
        
@@ -413,7 +413,8 @@
    // 播放打开动画
    protected virtual void PlayOpenAnimation()
    {
        //禁用交互会引起点透问题, 后续解决可以考虑EventSystem
        canvasGroup.blocksRaycasts = true;
        if (openAnimationType == UIAnimationType.None)
        {
@@ -432,7 +433,7 @@
                if (canvasGroup != null)
                {
                    canvasGroup.alpha = 0f;
                    canvasGroup.blocksRaycasts = false;
                    // canvasGroup.blocksRaycasts = false;
                }
                if (_rectTransform != null)
                {
@@ -444,7 +445,7 @@
                if (canvasGroup != null)
                {
                    canvasGroup.alpha = 1f;
                    canvasGroup.blocksRaycasts = false;
                    // canvasGroup.blocksRaycasts = false;
                }
                if (_rectTransform != null)
                {
@@ -495,7 +496,8 @@
                if (canvasGroup != null)
                {
                    canvasGroup.alpha = 1f;
                    canvasGroup.blocksRaycasts = false;
                    // 禁用交互会引起点透问题
                    // canvasGroup.blocksRaycasts = false;
                }
                if (_rectTransform != null)
                {
Main/System/UIBase/UIJumpManager.cs
New file
@@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using System;
/// <summary>
/// 关联界面索引表,用于获取途径,富文本打开界面等情况
/// </summary>
public class UIJumpManager : GameSystemManager<UIJumpManager>
{
    public override void Init()
    {
    }
    public bool CanOpenWin(int winID, bool showTip = false)
    {
        var config = WindowSearchConfig.Get(winID);
        if (config == null)
        {
            return false;
        }
        if (config.FuncID !=0 && !FuncOpen.Instance.IsFuncOpen(config.FuncID, showTip))
        {
            return false;
        }
        //活动后续补充
        return true;
    }
    public void OpenWindow(int winID, bool showTip = true)
    {
        if (!CanOpenWin(winID, showTip))
        {
            return;
        }
        var config = WindowSearchConfig.Get(winID);
        UIManager.Instance.OpenWindow(config.WinName, config.TabIndex);
    }
}
Main/System/UIBase/UIJumpManager.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5d826a564bad188478a9626fa1f2dee7
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/Utility/CommonFunc.cs
New file
@@ -0,0 +1,35 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class CommonFunc
{
    public static Dictionary<int, ulong> AddDict(Dictionary<int, ulong> dic1, Dictionary<int, ulong> dic2)
    {
        var resultDic = new Dictionary<int, ulong>(dic1);
        foreach (var data in dic2)
        {
            if (resultDic.ContainsKey(data.Key))
            {
                resultDic[data.Key] = resultDic[data.Key] + data.Value;
                continue;
            }
            resultDic[data.Key] = data.Value;
        }
        return resultDic;
    }
    public static List<Item> ChangeToItemList(Dictionary<int, ulong> dict)
    {
        List<Item> itemlist = new List<Item>();
        if (dict == null)
            return itemlist;
        foreach (var data in dict)
        {
            itemlist.Add(new Item(data.Key, data.Value));
        }
        return itemlist;
    }
}
Main/Utility/CommonFunc.cs.meta
Main/Utility/ComponentExtersion.cs
@@ -80,7 +80,7 @@
        return component;
    }
    public static void AddListener(this Button _button, UnityAction _action)
    {
        if (_button == null)
@@ -92,7 +92,7 @@
        _button.onClick.AddListener(_action);
    }
    public static void RemoveAllListeners(this Button _button)
    {
        if (_button == null)
@@ -102,7 +102,7 @@
        _button.onClick.RemoveAllListeners();
    }
    public static void SetListener(this Button button, UnityAction action)
    {
        if (button == null)
@@ -124,7 +124,7 @@
        _toggle.onValueChanged.AddListener(_action);
    }
    public static void SetListener(this Toggle toggle, UnityAction<bool> action)
    {
        if (toggle == null)
@@ -145,7 +145,7 @@
        _toggle.onValueChanged.RemoveAllListeners();
    }
    public static void AddListener(this Slider _slider, UnityAction<float> _action)
    {
        if (_slider == null)
@@ -155,7 +155,7 @@
        _slider.onValueChanged.AddListener(_action);
    }
    public static void SetListener(this Slider slider, UnityAction<float> action)
    {
        if (slider == null)
@@ -176,7 +176,7 @@
        _slider.onValueChanged.RemoveAllListeners();
    }
    public static void AddListener(this InputField _inputField, UnityAction<string> _action)
    {
        if (_inputField == null)
@@ -197,7 +197,7 @@
        inputField.onValueChanged.AddListener(action);
    }
    public static void RemoveAllListeners(this InputField _inputField)
    {
        if (_inputField == null)
@@ -223,7 +223,7 @@
    //     EnableButtonConfig.SetEnable(_btn, _btnTxt, _enable, _type);
    // }
    public static void SetColorful(this Button _btn, Text _btnTxt, bool _colorful, int pattern = 0)
    {
        if (_btn != null)
@@ -251,7 +251,7 @@
        }
    }
    public static void SetInteractable(this Button _btn, Text _btnText, bool _interactable)
    {
        if (_btn != null)
@@ -282,7 +282,7 @@
        _image.overrideSprite = sprite;
    }
    public static void SetSprite(this TextImage _textImage, string _id)
    {
        if (_textImage == null)
@@ -294,7 +294,7 @@
        _textImage.sprite = sprite;
    }
    //通过图片名加载
    //通过图片名加载, 如物品表 技能表等,节省在Icon表做多余配置
    public static void SetOrgSprite(this Image _image, string iconName, string folderName = "icon")
    {
        if (_image == null)
@@ -321,4 +321,15 @@
        }
    }
    public static void SetTexture2D(this RawImage _image, string _id)
    {
        if (_image == null)
        {
            return;
        }
        var texture = UILoader.LoadTexture2D(_id);
        _image.texture = texture;
    }
}
Main/Utility/MathUtility.cs
@@ -220,5 +220,219 @@
        return 0f;
    }
    public static float GetQuatLength(Quaternion q)
    {
        return Mathf.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w);
    }
    public static Quaternion GetQuatConjugate(Quaternion q)
    {
        return new Quaternion(-q.x, -q.y, -q.z, q.w);
    }
    /// <summary>
    /// Logarithm of a unit quaternion. The result is not necessary a unit quaternion.
    /// </summary>
    public static Quaternion GetQuatLog(Quaternion q)
    {
        Quaternion res = q;
        res.w = 0;
        if (Mathf.Abs(q.w) < 1.0f)
        {
            float theta = Mathf.Acos(q.w);
            float sin_theta = Mathf.Sin(theta);
            if (Mathf.Abs(sin_theta) > 0.0001)
            {
                float coef = theta / sin_theta;
                res.x = q.x * coef;
                res.y = q.y * coef;
                res.z = q.z * coef;
            }
        }
        return res;
    }
    public static Quaternion GetQuatExp(Quaternion q)
    {
        Quaternion res = q;
        float fAngle = Mathf.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
        float fSin = Mathf.Sin(fAngle);
        res.w = Mathf.Cos(fAngle);
        if (Mathf.Abs(fSin) > 0.0001)
        {
            float coef = fSin / fAngle;
            res.x = coef * q.x;
            res.y = coef * q.y;
            res.z = coef * q.z;
        }
        return res;
    }
    /// <summary>
    /// SQUAD Spherical Quadrangle interpolation [Shoe87]
    /// </summary>
    public static Quaternion GetQuatSquad(float t, Quaternion q0, Quaternion q1, Quaternion a0, Quaternion a1)
    {
        float slerpT = 2.0f * t * (1.0f - t);
        Quaternion slerpP = Slerp(q0, q1, t);
        Quaternion slerpQ = Slerp(a0, a1, t);
        return Slerp(slerpP, slerpQ, slerpT);
    }
    public static Quaternion GetSquadIntermediate(Quaternion q0, Quaternion q1, Quaternion q2)
    {
        Quaternion q1Inv = GetQuatConjugate(q1);
        Quaternion p0 = GetQuatLog(q1Inv * q0);
        Quaternion p2 = GetQuatLog(q1Inv * q2);
        Quaternion sum = new Quaternion(-0.25f * (p0.x + p2.x), -0.25f * (p0.y + p2.y), -0.25f * (p0.z + p2.z), -0.25f * (p0.w + p2.w));
        return q1 * GetQuatExp(sum);
    }
    /// <summary>
    /// Smooths the input parameter t.
    /// If less than k1 ir greater than k2, it uses a sin.
    /// Between k1 and k2 it uses linear interp.
    /// </summary>
    public static float Ease(float t, float k1, float k2)
    {
        float f; float s;
        f = k1 * 2 / Mathf.PI + k2 - k1 + (1.0f - k2) * 2 / Mathf.PI;
        if (t < k1)
        {
            s = k1 * (2 / Mathf.PI) * (Mathf.Sin((t / k1) * Mathf.PI / 2 - Mathf.PI / 2) + 1);
        }
        else
            if (t < k2)
            {
                s = (2 * k1 / Mathf.PI + t - k1);
            }
            else
            {
                s = 2 * k1 / Mathf.PI + k2 - k1 + ((1 - k2) * (2 / Mathf.PI)) * Mathf.Sin(((t - k2) / (1.0f - k2)) * Mathf.PI / 2);
            }
        return (s / f);
    }
    /// <summary>
    /// We need this because Quaternion.Slerp always uses the shortest arc.
    /// </summary>
    public static Quaternion Slerp(Quaternion p, Quaternion q, float t)
    {
        Quaternion ret;
        float fCos = Quaternion.Dot(p, q);
        if ((1.0f + fCos) > 0.00001)
        {
            float fCoeff0, fCoeff1;
            if ((1.0f - fCos) > 0.00001)
            {
                float omega = Mathf.Acos(fCos);
                float invSin = 1.0f / Mathf.Sin(omega);
                fCoeff0 = Mathf.Sin((1.0f - t) * omega) * invSin;
                fCoeff1 = Mathf.Sin(t * omega) * invSin;
            }
            else
            {
                fCoeff0 = 1.0f - t;
                fCoeff1 = t;
            }
            ret.x = fCoeff0 * p.x + fCoeff1 * q.x;
            ret.y = fCoeff0 * p.y + fCoeff1 * q.y;
            ret.z = fCoeff0 * p.z + fCoeff1 * q.z;
            ret.w = fCoeff0 * p.w + fCoeff1 * q.w;
        }
        else
        {
            float fCoeff0 = Mathf.Sin((1.0f - t) * Mathf.PI * 0.5f);
            float fCoeff1 = Mathf.Sin(t * Mathf.PI * 0.5f);
            ret.x = fCoeff0 * p.x - fCoeff1 * p.y;
            ret.y = fCoeff0 * p.y + fCoeff1 * p.x;
            ret.z = fCoeff0 * p.z - fCoeff1 * p.w;
            ret.w = p.z;
        }
        return ret;
    }
    #region 进制转换
    private static char[] symbolsArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '+', '/' };
    static string symbolStr = new string(symbolsArray, 0, 64);
    /// <summary>
    /// 讲字符串由64进制转为10进制,前缀没用的可用字符-代替
    /// </summary>
    /// <param name="val"></param>
    /// <returns></returns>
    public static int Convert64To10(string val)
    {
        val=val.Trim('-');
        int result = 0;
        long longResult = 0;
        val = val.Trim();
        if (string.IsNullOrEmpty(val)) {
            return result;
        }
        if (val.Equals("0")) return 0;
        for (int i = 0; i < val.Length; i++) {
            if(!symbolStr.Contains(val[i].ToString())) {
                //DesignDebug.LogError(string.Format("64进制格式错误{0}", val));
                return 0;
            }
            else {
                try {
                    int index = 0;
                    for (int j = 0; j < symbolsArray.Length; j++) {
                        if (symbolsArray[j] == val[val.Length - i - 1]) {
                            index = j;
                        }
                    }
                    longResult += (long)System.Math.Pow(64, i) * index;
                    if(longResult>int.MaxValue) {
                        Debug.LogError("超出Int最大值,尝试转换为long类型");
                        return 0;
                    }
                    result = (int)longResult;
                }
                catch {
                    Debug.LogError("运算溢出");
                    return 0;
                }
            }
        }
        return result;
    }
    static char[] outSymbol = new char[65];
    /// <summary>
    /// 将10进制转为64进制的字符串
    /// </summary>
    /// <param name="val"></param>
    /// <returns></returns>
    public static string Convert10To64(int val)
    {
        if (0 == val) return "0";
        int index = 0;
        long longPositive = Mathf.Abs(val);
        for (index = 0; index <= 64; index++) {
            if (longPositive == 0) break;
            outSymbol[outSymbol.Length - index - 1] = symbolsArray[longPositive % 64];
            longPositive /= 64;
        }
        return new string(outSymbol,outSymbol.Length-index,index);
    }
    #endregion
}
Main/Utility/MathUtils.cs
File was deleted
Main/Utility/UIHelper.cs
@@ -543,7 +543,7 @@
    public static readonly Color s_GrayDanLV5 = new Color32(255, 0, 0, 255); //ff0000
    public static readonly Color s_GrayDanLV6 = new Color32(240, 0, 255, 255); //f000ff
    // public static Color GetDanLVColor(int danLv, bool bright = false)
    // public static Color GetDanLVColor(int danLv, bool bright = true)
    // {
    //     var crossDanLVConfig = CrossServerArenaConfig.Get(danLv);
    //     if (crossDanLVConfig != null)
@@ -569,7 +569,7 @@
    //     return Color.white;
    // }
    // public static string AppendDanLVNameColor(int danLv, bool bright = false)
    // public static string AppendDanLVNameColor(int danLv, bool bright = true)
    // {
    //     var crossDanLVConfig = CrossServerArenaConfig.Get(danLv);
    //     if (crossDanLVConfig == null)
@@ -598,14 +598,14 @@
    // }
    //物品 各功能品质
    public static Color GetUIColorByFunc(int itemColor, bool bright = false)
    public static Color GetUIColorByFunc(int itemColor, bool bright = true)
    {
        return GetUIColor(itemColor + 1, bright);
    }
    //对应品质(树);物品 各功能品质从2开始 用GetUIColorByFunc
    public static Color GetUIColor(int itemColor, bool bright = false)
    public static Color GetUIColor(int itemColor, bool bright = true)
    {
        switch (itemColor)
        {
@@ -641,7 +641,7 @@
        return GetUIColor(TextColType.White, bright);
    }
    public static Color GetUIColor(TextColType type, bool bright = false)
    public static Color GetUIColor(TextColType type, bool bright = true)
    {
        //Bright 和 Dark指背景色系是明还是暗,暗底亮字,亮底暗字的规则
        switch (type)
@@ -776,7 +776,7 @@
    private static Regex m_TextColorRegex = new Regex("<color=#[0-9a-zA-Z]+>(.*)</color>", RegexOptions.Singleline);
    public static string AppendColor(TextColType type, string msg, bool bright = false)
    public static string AppendColor(TextColType type, string msg, bool bright = true)
    {
        // if (m_TextColorRegex.IsMatch(msg) && msg.ToLower().StartsWith("<color=#")
        //     && msg.ToLower().EndsWith("</color>"))
@@ -820,7 +820,7 @@
    }
    //needName 指官职0是否需要名称
    public static string GetRealmName(int realmLv, bool bright = false, bool needName = false)
    public static string GetRealmName(int realmLv, bool bright = true, bool needName = false)
    {
        if (realmLv <= 0 && !needName)
        {
@@ -850,7 +850,7 @@
    //     return GetRealmColorByLv(realmLv, string.Format(strFormat, config.Name), bright);
    // }
    public static string GetRealmColorByLv(int realmLv, string msg, bool bright = false)
    public static string GetRealmColorByLv(int realmLv, string msg, bool bright = true)
    {
        var config = RealmConfig.Get(realmLv);
        if (config == null)
@@ -876,7 +876,7 @@
        }
    }
    public static string AppendColor(int itemColor, string msg, bool bright = false)
    public static string AppendColor(int itemColor, string msg, bool bright = true)
    {
        switch (itemColor)
        {
@@ -1252,6 +1252,19 @@
        return (int)GetMoneyCnt(98) + (int)GetMoneyCnt(99);
    }
    //显示数量, 格式n/m, 足够绿色不足红色
    public static string ShowUseMoney(int moneyType, ulong useCnt, TextColType engoughColor = TextColType.Green)
    {
        ulong cnt = GetMoneyCnt(moneyType);
        return AppendColor(useCnt <= cnt ? engoughColor : TextColType.Red, $"{ReplaceLargeNum(useCnt)}/{ReplaceLargeNum(cnt)}");
    }
    public static string ShowUseItem(PackType type, int itemId, ulong useCnt, TextColType engoughColor = TextColType.Green)
    {
        ulong cnt = PackManager.Instance.GetItemCountByID(type, itemId);
        return AppendColor(useCnt <= cnt ? engoughColor : TextColType.Red, $"{ReplaceLargeNum(useCnt)}/{ReplaceLargeNum(cnt)}");
    }
    #endregion
    #region 得到装备位对应的部位名称
@@ -1371,7 +1384,7 @@
        return count;
    }
    // public static string GetEquipSuitName(int itemId, bool bright = false)
    // public static string GetEquipSuitName(int itemId, bool bright = true)
    // {
    //     if (ItemLogicUtility.Instance.IsSuitEquip(itemId))
    //     {
@@ -1381,7 +1394,7 @@
    //     return string.Empty;
    // }
    // public static string GetItemName(int itmeId, bool bright = false)
    // public static string GetItemName(int itmeId, bool bright = true)
    // {
    //     var itemConfig = ItemConfig.Get(itmeId);
    //     if (itemConfig == null)