hch
2025-12-26 c54824adb88b100995a54b44089b1ddde5dff257
351 【内政】红颜系统 - 可配置游历
2个文件已添加
6个文件已修改
535 ■■■■■ 已修改文件
Main/System/BeautyMM/BeautyMMCell.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/BeautyMM/BeautyMMManager.Travel.cs 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/BeautyMM/BeautyMMManager.cs 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/BeautyMM/BeautyMMShowWin.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/BeautyMM/BeautyMMTravelCell.cs 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/BeautyMM/BeautyMMTravelCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/BeautyMM/BeautyMMTravelWin.cs 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Utility/EnumHelper.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/BeautyMM/BeautyMMCell.cs
@@ -47,7 +47,7 @@
        }
        //先显示天赋属性,再显示天赋特性
        var attrs = BeautyMMManager.Instance.GetMMTalentAttr(mmID, true);
        var attrs = BeautyMMManager.Instance.GetMMTalentAttrForUI(mmID, true);
        int talentIndex = 0;
        if (attrs.IsNullOrEmpty())
        {
Main/System/BeautyMM/BeautyMMManager.Travel.cs
@@ -15,10 +15,14 @@
    public byte m_SceneryRow;    //景观左上角所在行,从1开始
    public byte m_SceneryCol;    //景观左上角所在列,从1开始
    public uint m_SceneryLVInfo;    //景观升级信息:0-还未处理景观升级;个位数-第1次升级成功与否,1-成功,2-失败;十位-第2次 ...
    public byte m_Result;    //后端处理:0-无;1-常规;2-马车炸弹;3-传送门;4-景观;5-重置开始
    public byte m_Result;    //后端处理:0-无;1-常规;2-马车炸弹;3-传送门;4-景观;5-重置开始;!!!重登会变成0,只做即时判断用
    Dictionary<Int2, TravelGrid> m_GridDict = new Dictionary<Int2, TravelGrid>();
    public event Action OnTravelInfoUpdate;
    public List<Int2> openChangeGridList = new List<Int2>(); // 前后对比,有变化的格子 ,打开前面前需清理
    public event Action<int> OnTravelInfoUpdate;
    public int maxGirds = 0;
    public Int2 clickGirdPos = new Int2();
    public void UpdateTravelInfo(HB040_tagSCTravelInfo netPack)
    {
@@ -30,6 +34,7 @@
        m_SceneryCol = netPack.SceneryCol;
        m_SceneryLVInfo = netPack.SceneryLVInfo;
        m_Result = netPack.Result;
        openChangeGridList.Clear();
        for (int i = 0; i < netPack.GridCnt; i++)
        {
@@ -37,17 +42,90 @@
            var key = new Int2(grid.Row, grid.Col);
            if (m_GridDict.ContainsKey(key))
            {
                if (m_GridDict[key].State != grid.State)
                {
                    openChangeGridList.Add(key);
                }
                m_GridDict[key].State = grid.State;
                m_GridDict[key].Multi = grid.Multi;
                m_GridDict[key].EventID = grid.EventID;
            }
            else
            {
                if (grid.State != 0)
                {
                    openChangeGridList.Add(key);
                }
                m_GridDict.Add(key, new TravelGrid() { State = grid.State, Multi = grid.Multi, EventID = grid.EventID });
            }
        }
        OnTravelInfoUpdate?.Invoke();
        OnTravelInfoUpdate?.Invoke(m_Result);
        UpdateTravelRedpoint();
    }
    //index从0开始,转格子坐标(1,1)开始
    public Int2 ChangeIndexToGrid(int index)
    {
        int row = index / travelRowCol[1] + 1;
        int col = index % travelRowCol[1] + 1;
        return new Int2(row, col);
    }
    public TravelGrid GetGrid(Int2 gridPos)
    {
        if (m_GridDict.ContainsKey(gridPos))
        {
            return m_GridDict[gridPos];
        }
        return null;
    }
    public bool CanOpenBuild()
    {
        if (m_SceneryType == 0)
        {
            return false;
        }
        //判断建筑格子是否全开,计算数量
        int cnt = 0;
        foreach (var grid in m_GridDict)
        {
            if (grid.Value.State == 1 && grid.Value.EventID > 0 && grid.Value.EventID < (int)GirdEventType.Door)
            {
                cnt++;
            }
        }
        return cnt >= m_SceneryType;
    }
    public bool HasDoor()
    {
        if (m_SceneryType == 0)
        {
            return false;
        }
        foreach (var grid in m_GridDict)
        {
            if (grid.Value.EventID == (int)GirdEventType.Door)
            {
                return true;
            }
        }
        return false;
    }
    Redpoint redpointTravel = new Redpoint(MainRedDot.Redpoint_BeautyMM, MainRedDot.Redpoint_BeautyMM * 10 + 2);
    void UpdateTravelRedpoint()
    {
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.BeautyMM))
        {
            return;
        }
        redpointTravel.state = m_Energy > 0 ? RedPointState.Simple : RedPointState.None;
    }
}
@@ -58,4 +136,12 @@
    public ushort EventID;        //事件ID
}
//低于99的为建筑格子 大于200的为物品格子
public enum GirdEventType
{
    None = 0,
    Door = 99,      // 门
    Empty = 100,    // 空格子
    Horse = 101,    // 马匹
}
Main/System/BeautyMM/BeautyMMManager.cs
@@ -43,6 +43,7 @@
        beautyMMIDSortList.Clear();
        beautyMMDataDict.Clear();
        beautyMMSkinDataDict.Clear();
        m_GridDict.Clear();
    }
    void ParseConfig()
@@ -62,6 +63,7 @@
        baseTravelEnergy = int.Parse(config.Numerical1);
        recoverTravelEnergyTime = int.Parse(config.Numerical2);
        travelRowCol = ConfigParse.GetMultipleStr<int>(config.Numerical3);
        maxGirds = travelRowCol[0] * travelRowCol[1];
        
    }
@@ -190,7 +192,7 @@
    }
    // 获取MM天赋属性属性, defaultAttr 是否使用默认属性
    public Dictionary<int, int> GetMMTalentAttr(int mmID, bool defaultAttr = false)
    public Dictionary<int, int> GetMMTalentAttrForUI(int mmID, bool defaultAttr = false)
    {
        var _dict = new Dictionary<int, int>();
        if (beautyMMDataDict.ContainsKey(mmID))
@@ -237,6 +239,80 @@
        return _dict;
    }
    // 真实属性
    public Dictionary<int, int> GetMMTalentAttr(int mmID)
    {
        var _dict = new Dictionary<int, int>();
        if (beautyMMDataDict.ContainsKey(mmID))
        {
            var _beauty = beautyMMDataDict[mmID];
            if (_beauty.State == 1)
            {
                var config = BeautyConfig.Get(mmID);
                if (config != null)
                {
                    //初始天赋属性
                    for (int i = 0; i < config.TalentAttrIDList.Length; i++)
                    {
                        _dict[config.TalentAttrIDList[i]] = config.TalentAttrValueList[i];
                    }
                    //按x级好感度提升一级天赋效果
                    var _lv = _beauty.LV;
                    var _addLV = _lv / needLVForTalent;
                    if (_addLV > 0)
                    {
                        for (int i = 0; i < config.TalentAttrIDList.Length; i++)
                        {
                            _dict[config.TalentAttrIDList[i]] += _addLV * config.TalentPerLVAddList[i];
                        }
                    }
                }
                return _dict;
            }
        }
        return _dict;
    }
    public int GetMMTalentEffectForUI(int mmID, bool defaultAttr = true)
    {
        int _effect = 0;
        if (beautyMMDataDict.ContainsKey(mmID))
        {
            var _beauty = beautyMMDataDict[mmID];
            if (_beauty.State == 1)
            {
                var config = BeautyConfig.Get(mmID);
                if (config != null)
                {
                    //初始天赋效果
                    _effect = config.EffValue;
                    //按x级好感度提升一级天赋效果
                    var _lv = _beauty.LV;
                    var _addLV = _lv / needLVForTalent;
                    if (_addLV > 0)
                    {
                        _effect += _addLV * config.EffPerLVAdd;
                    }
                }
                return _effect;
            }
        }
        if (defaultAttr)
        {
            var config = BeautyConfig.Get(mmID);
            if (config != null)
            {
                //初始天赋效果
                _effect = config.EffValue;
            }
        }
        return _effect;
    }
    // 获取MM天赋效果
    public int GetMMTalentEffect(int mmID)
    {
@@ -272,7 +348,7 @@
    Redpoint redpointMMKnown = new Redpoint((MainRedDot.Redpoint_BeautyMM * 10 + 1) * 10, (MainRedDot.Redpoint_BeautyMM * 10 + 1) * 10 + 1);
    Redpoint redpointMMUnKnown = new Redpoint((MainRedDot.Redpoint_BeautyMM * 10 + 1) * 10, (MainRedDot.Redpoint_BeautyMM * 10 + 1) * 10 + 2);
    
    Redpoint redpointTravel = new Redpoint(MainRedDot.Redpoint_BeautyMM, MainRedDot.Redpoint_BeautyMM * 10 + 2);
@@ -282,7 +358,10 @@
    {
        redpointMMKnown.state = RedPointState.None;
        redpointMMUnKnown.state = RedPointState.None;
        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.BeautyMM))
        {
            return;
        }
        var _list = BeautyConfig.GetValues();
        foreach (var beauty in _list)
        {
Main/System/BeautyMM/BeautyMMShowWin.cs
@@ -284,7 +284,7 @@
    void ShowTalent()
    {
        //先显示天赋属性,再显示天赋特性
        var attrs = BeautyMMManager.Instance.GetMMTalentAttr(mmID, true);
        var attrs = BeautyMMManager.Instance.GetMMTalentAttrForUI(mmID, true);
        int talentIndex = 0;
        if (attrs.IsNullOrEmpty())
        {
@@ -309,7 +309,7 @@
        }
        var talentValue = BeautyMMManager.Instance.GetMMTalentEffect(mmID);
        var talentValue = BeautyMMManager.Instance.GetMMTalentEffectForUI(mmID);
        for (int i = talentIndex; i < talentTexts.Length; i++)
        {
            if (i == talentIndex && mmConfig.EffType != 0)
Main/System/BeautyMM/BeautyMMTravelCell.cs
New file
@@ -0,0 +1,148 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BeautyMMTravelCell : MonoBehaviour
{
    [SerializeField] Button clickGirdBtn; //根据状态决定
    [SerializeField] Image itemImage;
    [SerializeField] Text multiText;
    [SerializeField] Image horseImg;
    [SerializeField] Image notOpenImg;
    [SerializeField] Image crackImg;    // 破碎图标
    [SerializeField] UIEffectPlayer openEffect;
    [SerializeField] UIEffectPlayer boomEffect;
    [SerializeField] UIEffectPlayer gateEffect;
    public void Display(int index)
    {
        Int2 girdPos = BeautyMMManager.Instance.ChangeIndexToGrid(index);
        var grid = BeautyMMManager.Instance.GetGrid(girdPos);
        clickGirdBtn.AddListener(() =>
        {
            ClickGird(girdPos, grid);
        });
        if (grid == null)
        {
            notOpenImg.SetActive(true);
            itemImage.SetActive(false);
            horseImg.SetActive(false);
            crackImg.SetActive(false);
            gateEffect.SetActive(false);
            return;
        }
        ////状态:0-未点击;1-已开启;2-裂纹
        if (grid.State == 0 || grid.State == 2)
        {
            notOpenImg.SetActive(true);
            itemImage.SetActive(false);
            horseImg.SetActive(false);
            crackImg.SetActive(grid.State == 2);
            gateEffect.SetActive(false);
            return;
        }
        notOpenImg.SetActive(false);
        // 99            -    代表该格是 传送门
        // 100          -    代表该格是 空格子
        // 101          -    代表该格是 马匹
        // 大于200 对应表里的 物品
        if (grid.EventID == 99)
        {
            gateEffect.SetActive(true);
            gateEffect.Play();
            itemImage.SetActive(false);
            horseImg.SetActive(false);
            crackImg.SetActive(false);
        }
        else if (grid.EventID == 100)
        {
            itemImage.SetActive(false);
            horseImg.SetActive(false);
            crackImg.SetActive(false);
            gateEffect.SetActive(false);
        }
        else if (grid.EventID == 101)
        {
            itemImage.SetActive(false);
            horseImg.SetActive(true);
            crackImg.SetActive(false);
            gateEffect.SetActive(false);
        }
        else if (grid.EventID > 200)
        {
            itemImage.SetActive(true);
            horseImg.SetActive(false);
            crackImg.SetActive(false);
            gateEffect.SetActive(false);
            itemImage.SetItemSprite(TravelEventConfig.Get(grid.EventID).AwardItemID);
            if (grid.Multi > 1)
            {
                multiText.text = $"x{grid.Multi}";
            }
            else
            {
                multiText.text = "";
            }
        }
        else
        {
            itemImage.SetActive(false);
            horseImg.SetActive(false);
            crackImg.SetActive(false);
            gateEffect.SetActive(false);
        }
        if (BeautyMMManager.Instance.openChangeGridList.Contains(girdPos))
        {
            openEffect.Play();
        }
    }
    // 99            -    代表该格是 传送门
    // 100          -    代表该格是 空格子
    // 101          -    代表该格是 马匹
    // 大于200 对应表里的 物品
    void ClickGird(Int2 girdPos, TravelGrid grid)
    {
        ////状态:0-未点击;1-已开启;2-裂纹
        if (grid.State == 0 || grid.State == 2)
        {
            SoundPlayer.Instance.PlayUIAudio(25);
        }
        if (grid.EventID == 100)
        {
            // 空格子
            return;
        }
        if (grid.EventID < 99 && grid.EventID > 0)
        {
            //判断建筑是否都开全了没
            if (!BeautyMMManager.Instance.CanOpenBuild())
            {
                SysNotifyMgr.Instance.ShowTip("BeautyMM3");
                return;
            }
        }
        if (grid.EventID == 101)
        {
            boomEffect.Play();
        }
        var pack = new CB040_tagCSTravelClick();
        pack.Row = (byte)girdPos.x;
        pack.Col = (byte)girdPos.y;
        GameNetSystem.Instance.SendInfo(pack);
        BeautyMMManager.Instance.clickGirdPos = girdPos;
    }
}
Main/System/BeautyMM/BeautyMMTravelCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 71e82a96c3e36af4f97b52bcebc58d36
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/BeautyMM/BeautyMMTravelWin.cs
@@ -1,10 +1,202 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class BeautyMMTravelWin : UIBase
{
    [SerializeField] Button rateTipBtn;
    [SerializeField] Transform rateTipRect;
    [SerializeField] Text[] rateNameText;
    [SerializeField] Text[] rateText;
    [SerializeField] Text horseRateText;
    [SerializeField] Image[] buildImgs;
    [SerializeField] GameObject girdsGo;
    [SerializeField] UIEffectPlayer boomRowEffect;
    [SerializeField] UIEffectPlayer boomColEffect;
    [SerializeField] Image processImg;
    [SerializeField] Text processText;
    [SerializeField] Text timeText;
    List<BeautyMMTravelCell> girds;
    [SerializeField] Button buildResultBtn;
    [SerializeField] UIEffectPlayer buildResultEffect;
    [SerializeField] Image[] whatImgs;
    [SerializeField] Image[] rightImgs;
    [SerializeField] Image[] wrongImgs;
    float gridWidth = 0;
    float gridHeight = 0;
    protected override void InitComponent()
    {
        girds = girdsGo.GetComponentsInChildren<BeautyMMTravelCell>().ToList();
        rateTipBtn.AddListener(() =>
        {
            rateTipRect.SetActive(true);
        });
        DisplyRate();
        buildResultBtn.AddListener(BuildLVUP);
    }
    protected override void OnPreOpen()
    {
        BeautyMMManager.Instance.OnTravelInfoUpdate += OnTravelInfoUpdate;
        BeautyMMManager.Instance.openChangeGridList.Clear();
        UIManager.Instance.OnCloseWindow += OnCloseWindow;
        rateTipRect.SetActive(false);
        Display();
        DisplayBuildResult();
    }
    protected override void OnPreClose()
    {
        BeautyMMManager.Instance.OnTravelInfoUpdate -= OnTravelInfoUpdate;
        UIManager.Instance.OnCloseWindow -= OnCloseWindow;
    }
    void OnTravelInfoUpdate(int result)
    {
        //后端处理:0-无;1-常规;2-马车炸弹;3-传送门;4-景观;5-重置开始
        Display();
        if (result == 2)
        {
            //BeautyMMManager.Instance.clickGirdPos
            boomRowEffect.transform.localPosition = new Vector3(0,
            -((BeautyMMManager.Instance.clickGirdPos.x - 1) * gridHeight + gridHeight / 2), 0);
            boomRowEffect.Play();
            boomColEffect.transform.localPosition = new Vector3((BeautyMMManager.Instance.clickGirdPos.y - 1) * gridWidth + gridWidth / 2, boomColEffect.transform.localPosition.y, 0);
            boomColEffect.Play();
        }
        DisplayBuildResult();
    }
    void Display()
    {
        for (int i = 0; i < girds.Count; i++)
        {
            girds[i].Display(i);
        }
        var showIndex = -1;
        if (BeautyMMManager.Instance.m_SceneryType == 1)
        {
            showIndex = 0;
        }
        else if (BeautyMMManager.Instance.m_SceneryType == 4)
        {
            showIndex = 1;
        }
        else if (BeautyMMManager.Instance.m_SceneryType == 6)
        {
            showIndex = 2;
        }
        var hasDoor = BeautyMMManager.Instance.HasDoor();
        for (int i = 0; i < buildImgs.Length; i++)
        {
            if (i == showIndex && !hasDoor)
            {
                buildImgs[i].SetActive(true);
                //根据父组件的宽高,和格子坐标计算起点坐标
                if (gridWidth == 0 || gridHeight == 0)
                {
                    var parentRect = buildImgs[i].transform.parent.GetComponent<RectTransform>();
                    var parentWidth = parentRect.rect.width;
                    var parentHeight = parentRect.rect.height;
                    gridWidth = parentWidth / BeautyMMManager.Instance.travelRowCol[1];
                    gridHeight = parentHeight / BeautyMMManager.Instance.travelRowCol[0];
                }
                var x = (BeautyMMManager.Instance.m_SceneryCol - 1) * gridWidth + 2;
                var y = (BeautyMMManager.Instance.m_SceneryRow - 1) * gridHeight + 2;
                buildImgs[i].transform.localPosition = new Vector3(x, -y, 0);
            }
            else
            {
                buildImgs[i].SetActive(false);
            }
        }
    }
    void DisplyRate()
    {
        rateTipRect.SetActive(false);
        var keys = TravelEventConfig.GetKeys();
        var index = 0;
        for (int i = 0; i < keys.Count; i++)
        {
            var config = TravelEventConfig.Get(keys[i]);
            if (config.EventID < 200)
            {
                continue;
            }
            rateNameText[index].text = ItemConfig.Get(config.AwardItemID).ItemName + "x" + config.AwardItemCnt;
            rateText[index].text = config.ShowRate;
            index++;
        }
        horseRateText.text = TravelEventConfig.Get(101).ShowRate;
    }
    //建筑特效品质 1-1073 2-1078 3-1083
    Dictionary<int, int> buildEffectDic = new Dictionary<int, int>()
    {
        {1, 1073},
        {2, 1078},
        {3, 1083}
    };
    void DisplayBuildResult()
    {
        if (!IsShowBuildUpgradeUI())
        {
            buildResultBtn.SetActive(false);
            return;
        }
        buildResultBtn.SetActive(true);
    }
    void BuildLVUP()
    {
        var pack = new CB041_tagCSTravelSceneryUP();
        GameNetSystem.Instance.SendInfo(pack);
    }
    //是否显示建筑升级UI
    bool IsShowBuildUpgradeUI()
    {
        //重登后 m_Result 是0 ,依然要遍历判断
        //如果已经有门了
        if (BeautyMMManager.Instance.HasDoor())
        {
            return false;
        }
        //m_Result 只用于即时判断
        if (BeautyMMManager.Instance.m_SceneryLVInfo == 0 && BeautyMMManager.Instance.m_Result != 4)
        {
            return false;
        }
        return true;
    }
    void OnCloseWindow(UIBase ui)
    {
        if (ui is CommonGetItemWin)
        {
            var gird = BeautyMMManager.Instance.GetGrid(BeautyMMManager.Instance.clickGirdPos);
            if (gird != null && gird.EventID == (int)GirdEventType.Door)
            {
                //默认请求下一局
                var pack = new CB040_tagCSTravelClick();
                pack.Row = (byte)BeautyMMManager.Instance.clickGirdPos.x;
                pack.Col = (byte)BeautyMMManager.Instance.clickGirdPos.y;
                GameNetSystem.Instance.SendInfo(pack);
            }
        }
    }
}
Main/Utility/EnumHelper.cs
@@ -823,6 +823,7 @@
    Hero = 1,//武将
    Challenge = 2,//挑战
    Official = 3,//内政
    BeautyMM = 7,//红颜
    GoldRush = 8, //淘金
    Realm = 10, //境界 官职
    Guild = 11,// 公会