Main/System/HeroUI/HeroUIManager.cs
@@ -2,39 +2,188 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jace.Operations;
using LitJson;
using UnityEngine;
//武将相关界面的操作数据管理
public class HeroUIManager : GameSystemManager<HeroUIManager>
public partial 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
    public int[] heroRedpointItemList;  //有影响红点的道具
    #endregion
    public WaitHeroFuncResponse waitResponse;    //请求武将功能,与服务端交互
    //用于非上阵武将战力变化时 武将ID:上次战力
    //使用方法:其他功能界面设置该值即可
    public KeyValuePair<string, long> lastFightPower = new KeyValuePair<string, long>();
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitialize;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnLoginLoadOK;
        HeroManager.Instance.onHeroChangeEvent += OnHeroChangeEvent;
        GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
        PackManager.Instance.RefreshItemEvent += RefreshItemEvent;
        TeamManager.Instance.OnTeamChange += OnTeamChangeEvent;
        ParseConfig();
        InitHeroOnTeamRedpointList();
        InitHeroBookRedpointList();
    }
    public override void Release()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitialize;
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnLoginLoadOK;
        HeroManager.Instance.onHeroChangeEvent -= OnHeroChangeEvent;
        GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
        PackManager.Instance.RefreshItemEvent -= RefreshItemEvent;
        TeamManager.Instance.OnTeamChange -= OnTeamChangeEvent;
    }
    void ParseConfig()
    {
        var config = FuncConfigConfig.Get("HeroRebirth");
        payBackMoneyType = int.Parse(config.Numerical1);
        rebornAwakeHeroMaxCount = int.Parse(config.Numerical2);
        rebornFormula = config.Numerical3;
        rebornPayBackPer = int.Parse(config.Numerical4);
        deletePayBackPer = int.Parse(config.Numerical5);
        ParseGiftConfig();
        config = FuncConfigConfig.Get("HeroRedpoint");
        heroRedpointItemList = JsonMapper.ToObject<int[]>(config.Numerical1);
    }
    public void OnBeforePlayerDataInitialize()
    {
        heroSortList.Clear();
        heroOnTeamSortList.Clear();
        awakeRebirthCnt = 0;
        waitResponse = default;
        heroCollectInfoDic.Clear();
        newHeroIDList.Clear();
    }
    public void OnPlayerLoginOk()
    void OnLoginLoadOK()
    {
        UpdateHeroCardRedpoint();
    }
    public override void Init()
    private void OnHeroChangeEvent(HeroInfo hero)
    {
        if (!DTC0403_tagPlayerLoginLoadOK.finishedLogin)
            return;
        WaitServerResponse(hero);
        refreshRedPoint = true;
    }
    public override void Release()
    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>();
        }
        else if (waitResponse.type == HeroFuncType.Gift)
        {
            UIManager.Instance.OpenWindow<HeroGiftEatSuccessWin>();
        }
        else if (waitResponse.type == HeroFuncType.Awake)
        {
            var config = HeroAwakeConfig.GetHeroAwakeConfig(hero.heroId, hero.awakeLevel);
            if (hero.talentAwakeRandomIDList.Count > 0)
            {
                UIManager.Instance.OpenWindow<HeroAwakeSelectGiftWin>();
            }
            else if (config.SkillID != 0 || config.UnlockTalentSlot != 0)
            {
                UIManager.Instance.OpenWindow<HeroAwakeSuccessWin>();
            }
        }
        waitResponse = default;
    }
    #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)
    {
        for (int i = breakLevel; i >= 0; i--)
        {
            var config = HeroQualityBreakConfig.GetQualityBreakConfig(quality, i);
            if (config == null)
            {
                continue;
            }
            return config.LVMax;
        }
        return 0;
    }
    public bool IsLVMaxByBreakLevel(HeroInfo hero)
    {
        return hero.heroLevel == GetMaxLVByBreakLV(hero.Quality, hero.breakLevel);
    }
    #endregion
    public void QueryUnLockHeroPack()
@@ -46,18 +195,27 @@
            return;
        }
        var buyInfo = PackManager.Instance.BuyPackGirdNeedData(PackType.Hero);
        ConfirmCancel.ShowPopConfirm(Language.Get("Mail101"),
        Language.Get("HeroPack1", GeneralDefine.MoneyDisplayModel[1],1, 1), (bool isOK)=>
        {
        });
        Language.Get("HeroPack1", UIHelper.GetIconNameWithMoneyType(buyInfo[0]), buyInfo[1], buyInfo[2]),
            (bool isOK) =>
            {
                if (isOK)
                {
                    if (UIHelper.GetMoneyCnt(buyInfo[0]) < buyInfo[1])
                    {
                        SysNotifyMgr.Instance.ShowTip("LackMoney", buyInfo[0]);
                        return;
                    }
                    PackManager.Instance.BuyPackGird(PackType.Hero);
                }
            });
    }
    //刷新时机, 打开武将界面 或者 关闭功能界面
    public void SortHeroList()
    {
        heroSortList = HeroManager.Instance.GetHeroGuidList();
        heroSortList = HeroManager.Instance.GetHeroGuidList(selectHeroListJob, selectHeroListCountry);
        heroSortList.Sort(CmpHero);
    }
@@ -94,83 +252,7 @@
        {
            return heroA.Quality > heroB.Quality ? -1 : 1;
        }
        if (heroA.heroStar != heroA.heroStar)
        {
            return heroA.heroStar > heroB.heroStar ? -1 : 1;
        }
        return heroA.heroId.CompareTo(heroB.heroId);
    }
    #region 布阵界面
    public List<string> heroOnTeamSortList { get; private set; } = new List<string>();    //不同上阵的列表排序
    private TeamType m_SelectTeamType = TeamType.Story; //当前选中的是哪个阵容, 布阵相关逻辑使用
    public TeamType selectTeamType
    {
        get { return m_SelectTeamType; }
        set
        {
            if (m_SelectTeamType == value)
                return;
            //上一个阵容需要恢复到原状态
            if (m_SelectTeamType != TeamType.None)
            {
                TeamManager.Instance.GetTeam(m_SelectTeamType).RestoreTeam();
            }
            m_SelectTeamType = value;
        }
    }
    public int selectTeamPosJob = 0;    //布阵界面 筛选职业
    public int selectTeamPosCountry = 0;    //布阵界面 筛选国家
    public const float clickFlyPosTime = 0.5f;  //点击列表中的武将图标时, 飞入布阵的时间
    public event Action<List<int>, int, Vector3> OnTeamPosChangeEvent; //布阵变化 位置,列表的起飞索引,起飞坐标
    public void SortHeroOnTeamList()
    {
        heroOnTeamSortList = HeroManager.Instance.GetHeroGuidList(selectTeamPosJob, selectTeamPosCountry);
        heroOnTeamSortList.Sort(CmpHeroByTeamType);
    }
    int CmpHeroByTeamType(string guidA, string guidB)
    {
        HeroInfo heroA = HeroManager.Instance.GetHero(guidA);
        HeroInfo heroB = HeroManager.Instance.GetHero(guidB);
        if (heroA == null || heroB == null)
        {
            return 0;
        }
        // 排序规则:上阵>武将等级>突破等级>武将觉醒阶级>武将品质>武将吞噬星级>武将ID
        bool isInTeamA = heroA.IsInTeamByTeamType(selectTeamType);
        bool isInTeamB = heroB.IsInTeamByTeamType(selectTeamType);
        if (isInTeamA != isInTeamB)
        {
            return isInTeamA ? -1 : 1;
        }
        if (heroA.heroLevel != heroB.heroLevel)
        {
            return heroA.heroLevel > heroB.heroLevel ? -1 : 1;
        }
        if (heroA.breakLevel != heroB.breakLevel)
        {
            return heroA.breakLevel > heroB.breakLevel ? -1 : 1;
        }
        if (heroA.awakeLevel != heroB.awakeLevel)
        {
            return heroA.awakeLevel > heroB.awakeLevel ? -1 : 1;
        }
        if (heroA.Quality != heroB.Quality)
        {
            return heroA.Quality > heroB.Quality ? -1 : 1;
        }
        if (heroA.heroStar != heroA.heroStar)
        if (heroA.heroStar != heroB.heroStar)
        {
            return heroA.heroStar > heroB.heroStar ? -1 : 1;
        }
@@ -180,138 +262,298 @@
    #region 招募
    //上阵队伍中各个国家的武将数量
    public Dictionary<HeroCountry, int> GetCountryHeroCountByTeamType(TeamType teamType)
    public HappXBTitle selectCallType;  //寻宝枚举类型
    public int selectCallIndex;//0:1抽 1:10抽 对应配置顺序
    public const string skipKey = "SkipHeroCall";
    //积分招募预览
    public List<int> heroCallSortList { get; private set; } = new List<int>();  //积分招募列表
    public int selectHeroCallListJob = 0;    //筛选职业
    public int selectHeroCallListCountry = 0;    //筛选国家
    public List<int> newHeroIDList = new List<int>();  //新武将列表
    public bool IsNewHero(int heroID)
    {
        Dictionary<HeroCountry, int> heroCountryCount = new Dictionary<HeroCountry, int>();
        var team = TeamManager.Instance.GetTeam(teamType);
        if (team != null)
        HB122_tagSCHeroInfo.tagSCHero bookInfo;
        if (TryGetHeroBookInfo(heroID, out bookInfo))
        {
            for (int i = 0; i < team.tempHeroes.Length; i++)
            if (bookInfo.BookInitState < 2)
            {
                if (team.tempHeroes[i] == null)
                    continue;
                var country = (HeroCountry)team.tempHeroes[i].heroConfig.Country;
                if (!heroCountryCount.ContainsKey(country))
                //更精准的 需要比较本次抽的同武将个数 和 背包里有的个数再比较
                if (HappyXBModel.Instance.GetCountInResult(heroID) >= HeroManager.Instance.GetHeroCountByID(heroID))
                {
                    heroCountryCount.Add(country, 1);
                    AddNewHero(heroID);
                    return true;
                }
                else
                {
                    heroCountryCount[country] = heroCountryCount[country] + 1;
                    return false;
                }
            }
        }
        return heroCountryCount;
    }
    //获得上阵中武将数量最大的国家和数量
    public Int2 GetMaxCountHeroCountry(TeamType teamType)
    {
        var countryCount = GetCountryHeroCountByTeamType(teamType);
        //找到最大的国家和数量
        HeroCountry country = HeroCountry.None;
        int maxValue = 0;
        foreach (var data in countryCount)
        {
            if (data.Value > maxValue)
            else
            {
                country = data.Key;
                maxValue = data.Value;
                return false;
            }
        }
        return new Int2((int)country, maxValue);
        AddNewHero(heroID);
        return true;
    }
    //在不同页签下选AttackType 0 攻击阵容 1 防守阵容
    public int GetSelectTeamTypeByAttackType(int AttackType)
    public void AddNewHero(int heroID)
    {
        if (selectTeamType == TeamType.Arena || selectTeamType == TeamType.ArenaDefense)
        if (newHeroIDList.Contains(heroID))
        {
            return AttackType == 0 ? (int)TeamType.Arena : (int)TeamType.ArenaDefense;
            return;
        }
        return (int)TeamType.Story;
        newHeroIDList.Add(heroID);
    }
    public void NotifyOnTeamPosChangeEvent(List<int> posList, int flyIndex, Vector3 startPos)
    public void RemoveNewHero(int heroID)
    {
        OnTeamPosChangeEvent?.Invoke(posList, flyIndex, startPos);
        if (!newHeroIDList.Contains(heroID))
        {
            return;
        }
        newHeroIDList.Remove(heroID);
        refreshRedPoint = true;
    }
    //推荐阵容
    public List<string> SelectRecommend()
    List<int> allHeroCallScoreList = new List<int>();  //积分招募列表
    public void SortHeroCallList()
    {
        //推荐阵容的算法逻辑
        //自动选择优先级:武将等级>突破等级>武将觉醒阶级>武将品质>武将吞噬星级>武将ID
        var tmpList = HeroManager.Instance.GetHeroGuidList();
        tmpList.Sort(CmpHeroRecommend);
        //推荐最多6个,存在相同heroid,则跳过
        List<string> selectHeroList = new List<string>();
        List<int> selectHeroIDList = new List<int>();
        for (int i = 0; i < tmpList.Count; i++)
        if (allHeroCallScoreList.IsNullOrEmpty())
        {
            if (selectHeroList.Count >= TeamConst.MaxTeamHeroCount)
                break;
            string guid = tmpList[i];
            HeroInfo heroInfo = HeroManager.Instance.GetHero(guid);
            if (selectHeroIDList.Contains(heroInfo.heroId))
                continue;
            //如果重复了,跳过
            if (selectHeroList.Contains(guid))
                continue;
            selectHeroList.Add(guid);
            selectHeroIDList.Add(heroInfo.heroId);
            allHeroCallScoreList = HappyXBModel.Instance.GetAllGridLibItemIDByType((int)HappXBTitle.HeroCallScore);
        }
        return selectHeroList;
        heroCallSortList = new List<int>();
        if (selectHeroCallListJob == 0 && selectHeroCallListCountry == 0)
        {
            heroCallSortList = allHeroCallScoreList;
        }
        else
        {
            foreach (var item in allHeroCallScoreList)
            {
                HeroConfig heroConfig = HeroConfig.Get(item);
                if (heroConfig == null)
                {
                    continue;
                }
                if (selectHeroCallListJob != 0 && selectHeroCallListJob != heroConfig.Class)
                {
                    continue;
                }
                if (selectHeroCallListCountry != 0 && selectHeroCallListCountry != heroConfig.Country)
                {
                    continue;
                }
                heroCallSortList.Add(item);
            }
        }
        heroCallSortList.Sort(CmpHeroID);
    }
    int CmpHeroRecommend(string guidA, string guidB)
    int CmpHeroID(int idA, int idB)
    {
        HeroInfo heroA = HeroManager.Instance.GetHero(guidA);
        HeroInfo heroB = HeroManager.Instance.GetHero(guidB);
        if (heroA == null || heroB == null)
        {
            return 0;
        }
        HeroConfig heroA = HeroConfig.Get(idA);
        HeroConfig heroB = HeroConfig.Get(idB);
        // 排序规则:武将等级>突破等级>武将觉醒阶级>武将品质>武将吞噬星级>武将ID
        if (heroA.heroLevel != heroB.heroLevel)
        {
            return heroA.heroLevel > heroB.heroLevel ? -1 : 1;
        }
        if (heroA.breakLevel != heroB.breakLevel)
        {
            return heroA.breakLevel > heroB.breakLevel ? -1 : 1;
        }
        if (heroA.awakeLevel != heroB.awakeLevel)
        {
            return heroA.awakeLevel > heroB.awakeLevel ? -1 : 1;
        }
        // 排序规则:武将品质>武将ID
        if (heroA.Quality != heroB.Quality)
        {
            return heroA.Quality > heroB.Quality ? -1 : 1;
        }
        if (heroA.heroStar != heroA.heroStar)
        return heroA.HeroID.CompareTo(heroB.HeroID);
    }
    #endregion
    // 优先功能提醒类型:1觉醒 2升星 3突破 4升级
    // 主线上阵武将才需要提醒  觉醒>升星>突破>升级
    public int GetFuncState(HeroInfo hero)
    {
        if (!hero.IsInTeamByTeamType(TeamType.Story))
        {
            return heroA.heroStar > heroB.heroStar ? -1 : 1;
            return 0;
        }
        return heroA.heroId.CompareTo(heroB.heroId);
        var heroCnt = PackManager.Instance.GetItemCountByID(PackType.Hero, hero.heroId);
        var itemPack = PackManager.Instance.GetSinglePack(PackType.Item);
        //5星后才能觉醒
        if (hero.heroStar < starLevelCanAwake)
        {
            if (heroCnt > 1) return 2;
        }
        else
        {
            //判断觉醒材料是否足够
            var maxAwakeLV = HeroAwakeConfig.GetMaxAwakeLV(hero.heroId);
            if (hero.awakeLevel < maxAwakeLV)
            {
                var config = HeroQualityAwakeConfig.GetQualityAwakeConfig(hero.Quality, hero.awakeLevel);
                if (itemPack.GetCountById(config.UPCostItem[0]) >= config.UPCostItem[1])
                {
                    return 1;
                }
            }
        }
        if (heroCnt > 1) return 2;
        var maxBreakLV = HeroBreakConfig.GetMaxBreakLv(hero.heroId);
        if (hero.breakLevel < maxBreakLV)
        {
            if (IsLVMaxByBreakLevel(hero))
            {
                var breakConfig = HeroQualityBreakConfig.GetQualityBreakConfig(hero.Quality, hero.breakLevel);
                if (itemPack.GetCountById(breakConfig.UPCostItem[0]) >= breakConfig.UPCostItem[1])
                {
                    return 3;
                }
            }
        }
        if (!IsLVMax(hero))
        {
            var lvupConfig = HeroQualityLVConfig.GetQualityLVConfig(hero.Quality, hero.heroLevel);
            if (itemPack.GetCountById(lvupConfig.UPCostItem[0]) >= lvupConfig.UPCostItem[1])
            {
                return 4;
            }
        }
        return 0;
    }
    #region 红点
    public bool refreshRedPoint = false;
    List<Redpoint> heroOnTeamRedpointList = new List<Redpoint>();   //上阵的武将红点
    List<Redpoint> heroBookRedpointList = new List<Redpoint>(); //图鉴所有武将红点
    //新标识的红点 所有武将统一个
    Redpoint newMarkRedPoint = new Redpoint(MainRedDot.HeroCardRedpoint, MainRedDot.HeroCardRedpoint * 10 + 9);
    void InitHeroOnTeamRedpointList()
    {
        heroOnTeamRedpointList.Clear();
        for (int i = 0; i < TeamConst.MaxTeamHeroCount; i++)
        {
            heroOnTeamRedpointList.Add(new Redpoint(MainRedDot.HeroCardRedpoint, MainRedDot.HeroCardRedpoint * 10 + i));
        }
    }
    //武将卡的红点:只给上阵武将刷红点(含新标识),非上阵武将的新图标按图片处理不归类为红点
    void UpdateHeroCardRedpoint()
    {
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Hero))
            return;
        var team = TeamManager.Instance.GetTeam(TeamType.Story);
        for (int i = 0; i < heroOnTeamRedpointList.Count; i++)
        {
            var redpoint = heroOnTeamRedpointList[i];
            var teamHero = team.GetServerHeroByIndex(i);
            if (teamHero != null)
            {
                var hero = HeroManager.Instance.GetHero(teamHero.guid);
                if (hero != null)
                {
                    if (GetFuncState(hero) > 0)
                    {
                        redpoint.state = RedPointState.Simple;
                        continue;
                    }
                }
            }
            redpoint.state = RedPointState.None;
        }
        newMarkRedPoint.state = newHeroIDList.Count > 0 ? RedPointState.New : RedPointState.None;
    }
    void InitHeroBookRedpointList()
    {
        heroBookRedpointList.Clear();
        foreach (var key in HeroConfig.GetKeys())
        {
            var config = HeroConfig.Get(key);
            if (config.PlayerCanUse == 0)
                continue;
            heroBookRedpointList.Add(new Redpoint(MainRedDot.HeroCardCollectRedpoint, MainRedDot.HeroCardCollectRedpoint * 10000000 + key));
        }
    }
    void UpdateHeroBookRedpoint()
    {
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Hero))
            return;
        foreach (var redpoint in heroBookRedpointList)
        {
            var heroID = redpoint.id % 10000000;
            var state = GetHeroBookState(heroID, HeroConfig.Get(heroID).Quality);
            if (state == 1 || state == 3 || state == 4)
            {
                redpoint.state = RedPointState.Simple;
                continue;
            }
            redpoint.state = RedPointState.None;
        }
    }
    void OnSecondEvent()
    {
        if (refreshRedPoint)
        {
            UpdateHeroCardRedpoint();
            refreshRedPoint = false;
        }
    }
    void RefreshItemEvent(PackType packType, int index, int itemID)
    {
        if (packType != PackType.Item)
            return;
        if (heroRedpointItemList.Contains(itemID))
        {
            refreshRedPoint = true;
        }
    }
    void OnTeamChangeEvent(TeamType teamType)
    {
        if (teamType == TeamType.Story)
        {
            refreshRedPoint = true;
        }
    }
    #endregion
}
#region 等待服务端响应
public struct WaitHeroFuncResponse
{
    public HeroFuncType type;
    public string guid;
    public float time;
}
//武将功能类型
public enum HeroFuncType
{
    None = 0,   //无功能
    Break = 1,  //突破
    Gift  = 2,  //天赋吞噬
    Awake = 3,  //觉醒
}
#endregion