diff --git a/Assets/MyGame/aa/UI/Game/XJMH/GameMainPanel_XJMH.cs b/Assets/MyGame/aa/UI/Game/XJMH/GameMainPanel_XJMH.cs index 43a14371e..a8584adc0 100644 --- a/Assets/MyGame/aa/UI/Game/XJMH/GameMainPanel_XJMH.cs +++ b/Assets/MyGame/aa/UI/Game/XJMH/GameMainPanel_XJMH.cs @@ -39,6 +39,21 @@ public class GameMainPanel_XJMH : GameMainPanel_FishBase // 按钮与列表索引的映射(顺序固定:Green=0, Blue=1, Gold=2, VIP=3) private Button[] _ptButtons; + [Header("炮台解锁限制(索引=按钮顺序 0绿/1蓝/2金/3VIP;非VIP只能用第一个)")] + [Tooltip("每个炮台所需贵族(VIP)等级,0=不限制。当前规则:只要是 VIP(≥1),后面三个都能用")] + public int[] ptUnlockVipLevel = { 0, 1, 1, 1 }; + [Tooltip("每个炮台是否额外要求月卡在有效期内(当前规则不启用月卡限制,需要时把第 4 个勾上)")] + public bool[] ptUnlockNeedMonthCard = { false, false, false, false }; + [Tooltip("贵族等级不足时按钮 LimitTip 的提示文案,{0}=所需贵族等级(原版 LevelLimit)")] + public string ptLockTipVipFormat = "贵族{0}解锁"; + [Tooltip("需要月卡时按钮 LimitTip 的提示文案(原版 MemberBattery2)")] + public string ptLockTipMonthCard = "月卡专属"; + [Tooltip("未解锁炮台按钮上的遮挡灰幕颜色(半透明灰)")] + public Color ptLockMaskColor = new Color(0f, 0f, 0f, 0.55f); + + // 每个按钮的未解锁灰幕(懒创建后缓存复用;面板销毁时随之销毁) + private readonly Dictionary _ptLockMasks = new Dictionary(); + // ⭐ 原版 PW_SelectBatteryView 的三个滑动节点(预制体里就是原版界面结构): // mGOContent(内容)从下方滑入滑出;mBtnUserInfo(头像)/ mGOGirl(看板娘)从左侧滑入滑出 private RectTransform _ptContent; @@ -348,6 +363,22 @@ public class GameMainPanel_XJMH : GameMainPanel_FishBase if (_ptButtons[i] == null) continue; bool available = i < count && list[i] != null; _ptButtons[i].gameObject.SetActive(available); + if (!available) continue; + + // ⭐ 解锁限制(原版 PW_SelectBatteryView:InitBattery):未解锁 → 按钮上 LimitTip 显示提示文案 + // 非 VIP 玩家后面几个炮台不解锁,只能切第一个(点击时再拦一次,见 OnPTButtonClicked) + string lockTip = GetPTLockTip(i); + bool locked = lockTip != null; + + var limitTip = FindChildByName(_ptButtons[i].transform, "LimitTip"); + if (limitTip != null) + { + if (limitTip.gameObject.activeSelf != locked) limitTip.gameObject.SetActive(locked); + if (locked) SetTextContent(limitTip, lockTip); + } + + // ⭐ 未解锁再压一层半透明灰幕遮挡(纯视觉,不挡点击;压在 LimitTip 下面保证提示可见) + SetPTLockMask(_ptButtons[i], locked); } ChangePTPanel.SetActive(true); @@ -466,6 +497,22 @@ public class GameMainPanel_XJMH : GameMainPanel_FishBase return; } + // ⭐ 解锁限制:未解锁(贵族等级不足 / 需要月卡)不允许切换,保持面板打开 + // (原版 SelectBattery:等级不够 → HallShowTip(LevelNotEnough) 后 return) + string lockTip = GetPTLockTip(index); + if (lockTip != null) + { + var btn = index >= 0 && index < _ptButtons.Length ? _ptButtons[index] : null; + var tipNode = btn != null ? FindChildByName(btn.transform, "LimitTip") : null; + if (tipNode != null) + { + if (!tipNode.gameObject.activeSelf) tipNode.gameObject.SetActive(true); + SetTextContent(tipNode, lockTip); + } + Debug.Log($"[XJMH] 炮台{index}未解锁({lockTip}),不切换。当前贵族等级={GetLocalVipLevel()}"); + return; + } + int prevIndex = currSitData.currentTurretIndex; bool success = currSitData.SwitchTurretByIndex(index); if (!success) @@ -484,6 +531,79 @@ public class GameMainPanel_XJMH : GameMainPanel_FishBase HidePTPanel(); } + /// 本地玩家贵族(VIP)等级(0=非VIP) + private static int GetLocalVipLevel() + { + var u = GameManager.Instance != null ? GameManager.Instance.user : null; + return u != null && u.assets != null ? u.assets.vipLevel : 0; + } + + /// 本地玩家月卡是否在有效期内(userCardEndTime;兼容秒/毫秒时间戳) + private static bool HasMonthCard() + { + var u = GameManager.Instance != null ? GameManager.Instance.user : null; + if (u == null || u.assets == null) return false; + long end = u.assets.userCardEndTime; + if (end <= 0) return false; + if (end < 100000000000L) end *= 1000L; // 秒 → 毫秒 + long now = BeijingTimeManager.Instance != null ? BeijingTimeManager.Instance.CurrentTimestampMs : 0L; + return end > now; + } + + /// + /// 该索引炮台的解锁提示文案:未解锁返回提示文字(显示在按钮 LimitTip 上并禁止切换),已解锁返回 null。 + /// 判定顺序:月卡限制 → 贵族(VIP)等级限制(对应面板上的 ptUnlockNeedMonthCard / ptUnlockVipLevel)。 + /// + private string GetPTLockTip(int index) + { + if (ptUnlockNeedMonthCard != null && index < ptUnlockNeedMonthCard.Length + && ptUnlockNeedMonthCard[index] && !HasMonthCard()) + return string.IsNullOrEmpty(ptLockTipMonthCard) ? "月卡专属" : ptLockTipMonthCard; + + int need = (ptUnlockVipLevel != null && index < ptUnlockVipLevel.Length) ? ptUnlockVipLevel[index] : 0; + if (GetLocalVipLevel() < need) + return string.IsNullOrEmpty(ptLockTipVipFormat) ? $"VIP{need}解锁" : string.Format(ptLockTipVipFormat, need); + + return null; + } + + /// + /// 设置按钮上的"未解锁灰幕"显隐(懒创建:半透明灰 Image 铺满按钮,纯视觉、不挡点击)。 + /// 灰幕压在 LimitTip 下面,保证"贵族X解锁"提示仍然可见。 + /// + private void SetPTLockMask(Button btn, bool show) + { + if (btn == null) return; + + if (!_ptLockMasks.TryGetValue(btn, out var mask) || mask == null) + { + var go = new GameObject("[PTLockMask]", typeof(RectTransform), typeof(Image)); + var rt = (RectTransform)go.transform; + rt.SetParent(btn.transform, false); + rt.anchorMin = Vector2.zero; + rt.anchorMax = Vector2.one; + rt.offsetMin = Vector2.zero; + rt.offsetMax = Vector2.zero; + + var img = go.GetComponent(); + img.color = ptLockMaskColor; + img.raycastTarget = false; // 纯遮挡:点击仍能落到按钮上走"未解锁"提示 + + // 排在 LimitTip 之前(层级更低),提示文字不会被灰幕盖住 + var tip = FindChildByName(btn.transform, "LimitTip"); + if (tip != null) rt.SetSiblingIndex(Mathf.Max(0, tip.GetSiblingIndex())); + + mask = go; + _ptLockMasks[btn] = mask; + } + + // 颜色每次同步(Play 模式下面板上改完立即生效) + var maskImg = mask.GetComponent(); + if (maskImg != null && maskImg.color != ptLockMaskColor) maskImg.color = ptLockMaskColor; + + if (mask.activeSelf != show) mask.SetActive(show); + } + // ==================== 金币柱 ==================== ///