This commit is contained in:
2026-09-06 15:51:51 +08:00
parent a5a26714e4
commit 0887d61c5e
18 changed files with 343 additions and 1455 deletions
@@ -120,6 +120,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
public string sceneName;
public GameTypeEnum gameType;
[Header("Left")]
public PropConfigData propConfigData; // 道具菜单配置(Assets右键 Create → MyGame → 左侧道具配置)
public Button btn_Prop;
public GameObject obj_PropItemParent;
public GameObject obj_PropPanel;
@@ -132,6 +133,12 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
public Button zhanhuanka;
public Button huojianpao;
[Header("大喇叭弹幕输入")]
public GameObject obj_DaLaBaPanel; // 大喇叭弹幕输入面板
public TMP_InputField tmp_DaLaBaInput; // 弹幕输入框
public Button btn_DaLaBaSend; // 发送按钮
public Button btn_DaLaBaClose; // 关闭按钮
[Header("Right")]
[Header("设置")]
protected bool isOpenSetting;
@@ -580,15 +587,39 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
if (btn_ChangeRoom != null)
btn_ChangeRoom.onClick.AddListener(StartChangeRoom);
// ⭐ 左侧道具按钮:只做开启/关闭 obj_PropPanel
// (第二层 tmp_PropTwoPanel/tmp_PropTwoItem 等暂不实现,字段先留着)
// ⭐ 左侧道具按钮:开启/关闭 obj_PropPanel(一级列表由 PropConfigData 配置构建,
// 点击一级道具在 tmp_PropTwoPanel 展开二级子道具)
if (btn_Prop != null)
btn_Prop.onClick.AddListener(() =>
{
if (obj_PropPanel != null)
obj_PropPanel.SetActive(!obj_PropPanel.activeSelf);
if (obj_PropPanel == null) return;
bool open = !obj_PropPanel.activeSelf;
obj_PropPanel.SetActive(open);
if (open)
BuildPropList();
else if (tmp_PropTwoPanel != null)
tmp_PropTwoPanel.SetActive(false);
});
// ⭐ 大喇叭:开/关弹幕输入面板
if (dalaba != null)
dalaba.onClick.AddListener(() =>
{
if (obj_DaLaBaPanel != null)
obj_DaLaBaPanel.SetActive(!obj_DaLaBaPanel.activeSelf);
});
if (btn_DaLaBaSend != null)
btn_DaLaBaSend.onClick.AddListener(OnClickDaLaBaSend);
if (btn_DaLaBaClose != null)
btn_DaLaBaClose.onClick.AddListener(() =>
{
if (obj_DaLaBaPanel != null) obj_DaLaBaPanel.SetActive(false);
});
// ⭐ 召唤卡:使用召唤卡召唤Boss
if (zhanhuanka != null)
zhanhuanka.onClick.AddListener(OnClickZhanHuanKa);
// 服务器广播监听
EventCenter.Instance.AddEventListener<SyncGameData>(ConstEventString.SyncGameData_Rotate, SyncGameData_Rotate);
EventCenter.Instance.AddEventListener<FireCannonSendData>(ConstEventString.SyncGameData_FireBullet, SyncGameData_FireBullit);
@@ -1394,6 +1425,174 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
#endregion
#region 大喇叭/召唤卡(Left道具快捷按钮)
/// <summary>
/// 大喇叭发送:输入弹幕 → /api/Hall/SendBroadcast 全服广播
/// (与背包大喇叭 OnClickFaSong 流程一致),发送成功后清空输入框并关闭面板。
/// </summary>
private void OnClickDaLaBaSend()
{
string msg = tmp_DaLaBaInput?.text?.Trim();
if (string.IsNullOrEmpty(msg))
{
UIManager.Instance.ShowBoardError("请输入广播内容");
return;
}
APIRequestList.SendBroadcast("广播:" + msg, (result) =>
{
// 发送成功:清空输入框并关闭面板(广播内容会通过 LoginBroadcast 全服弹幕显示)
if (tmp_DaLaBaInput != null) tmp_DaLaBaInput.text = "";
if (obj_DaLaBaPanel != null) obj_DaLaBaPanel.SetActive(false);
});
}
/// <summary>
/// 使用召唤卡:从背包找到召唤卡道具(type=11)拿道具编号
/// → /api/SummonCard/use 召唤Boss(Boss鱼由服务端 OnFishSpawn 下发给房间所有人)
/// → 显示服务器返回消息 + 拉取最新用户数据同步道具数量。
/// </summary>
private void OnClickZhanHuanKa()
{
var props = GameManager.Instance.user?.props;
if (props != null)
{
foreach (var p in props)
{
if (p.type == (int)PropEnum.召唤卡 && p.count > 0)
{
APIRequestList.UseSummonCard(
new Assets.MyGame.Scripts.Net.APIRequest.Params.SummonCardUseParam { cardNumber = p.number },
(msg) =>
{
UIManager.Instance.ShowBoardError(string.IsNullOrEmpty(msg) ? "使用成功" : msg);
// 刷新用户数据,同步召唤卡剩余数量
APIRequestList.GetUser((user) =>
{
if (user != null)
GameManager.Instance.UpdataUserData(user);
});
});
return;
}
}
}
UIManager.Instance.ShowBoardError("召唤卡数量不足");
}
#endregion
#region 左侧道具菜单(PropConfigData 一级道具 + 二级展开子道具)
private bool _propListBuilt;
/// <summary>
/// 按 PropConfigData 构建一级道具列表(只在首次打开时构建一次)
/// </summary>
private void BuildPropList()
{
if (_propListBuilt) return;
_propListBuilt = true;
if (propConfigData == null || tmp_PropItem == null || obj_PropItemParent == null) return;
// ⭐ 模板是场景内对象时先隐藏(引用指向预制体资产时 scene 无效,不能 SetActive 以免改资产)
if (tmp_PropItem.scene.IsValid()) tmp_PropItem.SetActive(false);
for (int i = 0; i < propConfigData.props.Count; i++)
{
var cfg = propConfigData.props[i];
if (cfg == null) continue;
var item = Instantiate(tmp_PropItem, obj_PropItemParent.transform);
SetPropItemText(item, cfg.name);
SetPropItemIcon(item, cfg.icon);
var data = cfg; // 闭包捕获当前项,避免循环变量被覆盖
var btn = GetPropItemButton(item);
if (btn != null) btn.onClick.AddListener(() => ShowPropTwo(data));
}
}
/// <summary>
/// 点击一级道具:在 tmp_PropTwoPanel 内按配置展开二级子道具列表
/// </summary>
private void ShowPropTwo(PropItemData cfg)
{
if (cfg == null || tmp_PropTwoPanel == null || tmp_PropTwoItem == null || tmp_PropTwoItemParent == null) return;
// 清空上次克隆的子道具(模板本身若是该父对象的子节点则跳过)
for (int i = tmp_PropTwoItemParent.transform.childCount - 1; i >= 0; i--)
{
var child = tmp_PropTwoItemParent.transform.GetChild(i).gameObject;
if (child == tmp_PropTwoItem) continue;
Destroy(child);
}
// ⚠ 注意:这里判断的是 tmp_PropTwoItem(不是 tmp_PropItem)
if (tmp_PropTwoItem.scene.IsValid()) tmp_PropTwoItem.SetActive(false);
foreach (var sub in cfg.subProps)
{
if (sub == null) continue;
var item = Instantiate(tmp_PropTwoItem, tmp_PropTwoItemParent.transform);
SetPropItemText(item, sub.name);
SetPropItemIcon(item, sub.icon);
var data = sub;
var btn = GetPropItemButton(item);
if (btn != null) btn.onClick.AddListener(() => UsePropEffect(data));
}
tmp_PropTwoPanel.SetActive(true);
}
/// <summary>
/// 点击二级子道具:按枚举 effectType 分发效果(未接入的类型统一提示)
/// </summary>
private void UsePropEffect(SubPropData sub)
{
if (sub == null) return;
switch (sub.effectType)
{
case PropEffectType.大喇叭:
if (obj_DaLaBaPanel != null) obj_DaLaBaPanel.SetActive(true);
break;
case PropEffectType.召唤卡:
OnClickZhanHuanKa();
break;
default:
UIManager.Instance.ShowBoardError($"[{sub.effectType}] 效果暂未接入");
break;
}
}
/// <summary>克隆项文本:优先取 child0 的 TMP,再退回自身/子级查找(与表情列表同惯例)</summary>
private void SetPropItemText(GameObject item, string text)
{
if (string.IsNullOrEmpty(text)) return;
var tmp = item.transform.childCount > 0 ? item.transform.GetChild(0).GetComponent<TextMeshProUGUI>() : null;
if (tmp == null) tmp = item.GetComponent<TextMeshProUGUI>();
if (tmp == null) tmp = item.GetComponentInChildren<TextMeshProUGUI>();
if (tmp != null) tmp.text = text;
}
/// <summary>克隆项图标:优先取 child0 的 Image,再退回自身/子级查找(icon 不填则跳过)</summary>
private void SetPropItemIcon(GameObject item, Sprite icon)
{
if (icon == null) return;
var img = item.transform.childCount > 0 ? item.transform.GetChild(0).GetComponent<Image>() : null;
if (img == null) img = item.GetComponent<Image>();
if (img == null) img = item.GetComponentInChildren<Image>();
if (img != null) img.sprite = icon;
}
/// <summary>克隆项按钮:自身优先,其次子级查找</summary>
private Button GetPropItemButton(GameObject item)
{
var btn = item.GetComponent<Button>();
if (btn == null) btn = item.GetComponentInChildren<Button>();
return btn;
}
#endregion
#region 输入系统(InputModule)
private bool IsPointerOverUI(Vector2 pos)
{