From 1321ed6c018fac439f1a80a7fedf0a15e8a3ab98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A3=AE2003?= <2384017988@qq.com> Date: Wed, 7 Oct 2026 01:55:53 +0800 Subject: [PATCH] 1 --- .../Scripts/Manager/CreateFishManager.cs | 46 +++++++++-- Assets/MyGame/Scripts/Turret/SitPosData.cs | 7 +- .../Game/FLZY/BOSS/BaoJiangNotSelfHandler.cs | 8 ++ .../aa/UI/Game/GameMainPanel_FishBase.cs | 81 +++++++++++++++++-- .../aa/UI/Game/XJMH/GameMainPanelXJMH.prefab | 9 ++- 5 files changed, 131 insertions(+), 20 deletions(-) diff --git a/Assets/MyGame/Scripts/Manager/CreateFishManager.cs b/Assets/MyGame/Scripts/Manager/CreateFishManager.cs index d24bb0334..3f42ee709 100644 --- a/Assets/MyGame/Scripts/Manager/CreateFishManager.cs +++ b/Assets/MyGame/Scripts/Manager/CreateFishManager.cs @@ -1957,6 +1957,19 @@ public class CreateFishManager : MonoSingleton var killFish = JsonConvert.DeserializeObject>(msg) .arguments[0]; + // ⭐ 掉落道具推送去重:服务端把"击杀爆奖"和"掉落道具"拆成两条 RoomKillNotice 下发, + // 第二条与击杀消息同 fishId/killtime/gold,但只有 drop、没有 param。 + // Boss 鱼 DieFish 是延迟回收(字典未即时移除),第二条若按击杀再处理一次: + // ① not-self 模式下 _pending[key] 被覆盖 → 前一个"爆奖中"BJEndUI 失去引用、永久残留在座位上; + // ② 重复克隆爆奖特效、重复走 DieFish → 特效/音效/爆奖双份。 + // 客户端目前没有掉落弹窗逻辑(见 RoomKillNotice.drop 注释),直接跳过;将来做掉落 UI 时在此处理。 + if (killFish.drop != null && killFish.param == null) + { + NetLog.Log($"[CreateFishManager] 掉落道具推送(跳过击杀处理):fishId={killFish.fishId} " + + $"prop={killFish.drop.propNumber}×{killFish.drop.count}"); + return; + } + NetLog.Log($"[CreateFishManager] 杀鱼延迟:{DateTimeOffset.Now.ToUnixTimeSeconds() - killFish.timespan}s"); SitPosData sitData = null; //击杀玩家座位数据 foreach (var item in currGameType.list_Sits) @@ -2079,7 +2092,7 @@ public class CreateFishManager : MonoSingleton // 不克隆 effect_DieAward,在 killer 座位显示 img_BaoJiangZhong, // 等待帧同步 baoJiangEnd(机器人由房主延迟 5~10 秒代发)后显示最终 BJEndUI + 加分 bool isSelfKill_Boss = sitData.user == GameManager.Instance.user.id; - if (GameManager.Instance.useNotSelfBaoJiangMode + if (UseNotSelfBaoJiangFlow && !isSelfKill_Boss && monster.effect_DieAward != null && BaoJiangNotSelfHandler.ShowInProgress( @@ -2167,7 +2180,7 @@ public class CreateFishManager : MonoSingleton // ⚠️ 排除重写了 SetCoinCount 的子类(如炸弹蟹 HHWK_ZDX_DieEvent): // 这些鱼有特殊爆炸/范围杀鱼玩法,必须走原流程,不能跳过 SetCoinCount bool isSelfKill_TSY = sitData.user == GameManager.Instance.user.id; - if (GameManager.Instance.useNotSelfBaoJiangMode + if (UseNotSelfBaoJiangFlow && !isSelfKill_TSY && monster.effect_DieAward != null) { @@ -2297,7 +2310,7 @@ public class CreateFishManager : MonoSingleton // ⭐ not-self 分流:非自己击杀(含机器人)且开启新模式 → 走 not-self 流程 bool isSelfKill_TBoss = sitData.user == GameManager.Instance.user.id; - if (GameManager.Instance.useNotSelfBaoJiangMode + if (UseNotSelfBaoJiangFlow && !isSelfKill_TBoss && monster.effect_DieAward != null && BaoJiangNotSelfHandler.ShowInProgress( @@ -2379,6 +2392,27 @@ public class CreateFishManager : MonoSingleton + // ================================================================ + // not-self 爆奖分流开关(按房间区分) + // ================================================================ + + /// + /// 当前房间是否启用 not-self 爆奖分流(其他玩家击杀只在座位显示"爆奖中"面板, + /// 等 baoJiangEnd 帧同步再显示最终 BJEndUI + 加分)。 + /// ⭐ XJMH 例外:星际迷航各 Boss 爆奖(幸运轮/扑克/飞碟/星舰巡航等)已实现完整的 + /// isSelf=false 分支(他人视角银币结算、PW_Effect_Settle_*_Other_* 结算特效), + /// 所有玩家都要走完整爆奖流程,不参与 not-self 简化分流,也不发送/等待 baoJiangEnd。 + /// + private bool UseNotSelfBaoJiangFlow + { + get + { + var gm = GameManager.Instance; + if (gm == null || !gm.useNotSelfBaoJiangMode) return false; + return gm.gameData == null || gm.gameData.currGameType != GameType.XJMH; + } + } + // ================================================================ // 工具:包装 JiaFen 回调,self 流程加分完成后发送 baoJiangEnd 帧同步 // ================================================================ @@ -2395,11 +2429,9 @@ public class CreateFishManager : MonoSingleton // 1. 执行原加分逻辑 onScoreAdd?.Invoke(p); - // 2. self 流程:本地玩家击杀且开启 not-self 模式时,发送 baoJiangEnd 帧同步 + // 2. self 流程:本地玩家击杀且当前房间启用 not-self 模式时,发送 baoJiangEnd 帧同步 // (机器人击杀由房主延迟代发,不在这里发) - if (isSelfKill - && GameManager.Instance != null - && GameManager.Instance.useNotSelfBaoJiangMode) + if (isSelfKill && UseNotSelfBaoJiangFlow) { BaoJiangNotSelfHandler.SendBaoJiangEnd( killFish.userId, diff --git a/Assets/MyGame/Scripts/Turret/SitPosData.cs b/Assets/MyGame/Scripts/Turret/SitPosData.cs index fa6020d5b..a1c8a720e 100644 --- a/Assets/MyGame/Scripts/Turret/SitPosData.cs +++ b/Assets/MyGame/Scripts/Turret/SitPosData.cs @@ -266,9 +266,14 @@ public class SitPosData : MonoBehaviour, IPointerDownHandler, IPointerUpHandler if (btn_TurretMinus != null) btn_TurretMinus.onClick.AddListener(() => ChangeTurretMinusConsumeNum()); - // ⭐ 自动攻击开关:关闭时本地座位炮台切回 Idle(原 GameMainPanel 的 toggle_SkillAuto 监听逻辑) + // ⭐ 自动攻击开关:先检测自身 GameObject 激活状态,没激活就激活(预制体/外部可能把它藏了, + // 隐藏状态下点不到,自动攻击无法开关);再挂监听:关闭时本地座位炮台切回 Idle(原 GameMainPanel 的 toggle_SkillAuto 逻辑) if (toggle_AutoAttack != null) + { + if (!toggle_AutoAttack.gameObject.activeSelf) + toggle_AutoAttack.gameObject.SetActive(true); toggle_AutoAttack.onValueChanged.AddListener(OnAutoAttackToggleChanged); + } // ⭐ 炮倍选择面板:按钮开/关;Awake 记录面板原始高度(动画还原目标值,之后会被压到 0) if (btn_SelectPaoBei != null) diff --git a/Assets/MyGame/aa/Game/FLZY/BOSS/BaoJiangNotSelfHandler.cs b/Assets/MyGame/aa/Game/FLZY/BOSS/BaoJiangNotSelfHandler.cs index 75c154be5..a1fa9740e 100644 --- a/Assets/MyGame/aa/Game/FLZY/BOSS/BaoJiangNotSelfHandler.cs +++ b/Assets/MyGame/aa/Game/FLZY/BOSS/BaoJiangNotSelfHandler.cs @@ -113,6 +113,14 @@ public static class BaoJiangNotSelfHandler || (!string.IsNullOrEmpty(killerUserId) && killerUserId.StartsWith("bot_")); string key = MakeKey(killerUserId, fishId); + + // ⭐ 防御:同一条鱼(同 key)重复进入在途(重复消息/重发/MultiDeath 多段击杀)时, + // 先销毁上一个"爆奖中"面板,否则旧 BJEndUI 失去引用后会永久残留在座位上 + if (_pending.TryGetValue(key, out var oldEntry) && oldEntry.endUI != null && oldEntry.endUI != endUI) + { + UnityEngine.Object.Destroy(oldEntry.endUI.gameObject); + } + _pending[key] = new PendingEntry { endUI = endUI, diff --git a/Assets/MyGame/aa/UI/Game/GameMainPanel_FishBase.cs b/Assets/MyGame/aa/UI/Game/GameMainPanel_FishBase.cs index 792caefee..fd4a19c98 100644 --- a/Assets/MyGame/aa/UI/Game/GameMainPanel_FishBase.cs +++ b/Assets/MyGame/aa/UI/Game/GameMainPanel_FishBase.cs @@ -4519,6 +4519,25 @@ public class GameMainPanel_FishBase : GameMainPanel_Base return; } var targetSit = list_Sits[dispPos]; + + // ⭐⭐ 战神散射(三发+锁定):发送端每发都带 isSanShe/isSuoDing 和3个激光目标GUID(monsterIDs) + // → 其他玩家的座位跟着补齐3个锁位 + 刷新散射标记:3条激光 + 2个散射起点球 + // (JGFXLeftParent/JGFXRightParent) 一起显示。 + // ⭐ 这条路是"自动凑满3个目标"时唯一的信号(自动补位/自动凑目标不会走锁定同步), + // 只在锁定同步里处理的话,不开手动点鱼别人就看不到散射表现。 + // ⚠ 只处理别人的座位:本地座位自己的三发锁位由本地锁定系统维护,不能被网络数据覆盖 + if (targetSit != currSitData && targetSit.currentZhanShenData != null) + { + bool scatter = data.isSanShe && data.isSuoDing; + if (targetSit.isScatterLaserOn != scatter) + { + targetSit.isScatterLaserOn = scatter; + // 退出散射:清掉远端多出来的锁位(主锁保留,仍显示1条激光 + 主锁定圈) + if (!scatter) targetSit.HideTripleLockIcons(); + } + if (scatter) ApplyTripleLockSlotsFromGuids(targetSit, data.monsterIDs); + } + // ⭐ 座位镜像:网络角度是"源角度"(发送方下方座位系),按该座位显示位置还原成世界角度 FireBullet(targetSit, SeatMirror.SourceAngleToWorld(data.angle, targetSit.IsFlipped), data.isSanShe, data.twoRTruuect, data.isSuoDing, sync.bulletIds, data.monsterIDs, bulletGolds); @@ -4552,21 +4571,67 @@ public class GameMainPanel_FishBase : GameMainPanel_Base if (dispPos == currSitData.posID) return; var data = FrameDataParser.Parse(sync.frameData); + var sit = list_Sits[dispPos]; - if (data.targetGuid == null) + if (data.targetGuid == null || data.targetGuid.Count == 0) { - list_Sits[dispPos].ClearLock(); + sit.ClearLock(); return; } - MonsterContral monster = CreateFishManager.Instance.fishDatas_hashCodekey[data.targetGuid[0]]; + // ⭐⭐ 战神三发散射:发送端把3个锁位一起同步过来([0]=主锁目标,[1]/[2]=散射目标)。 + // 以前只取了 [0],远端锁位永远只有1个 → 远端激光只有1条, + // 散射左右起点球(JGFXLeftParent/JGFXRightParent)不激活 → 别人的视角看不到两个小球。 + // 这里按整份列表补齐远端锁位:远端表现与发送端一致(3条激光 + 2个起点球 + 2个额外锁定圈)。 + // 注:统一用 ResolveLockTransform(colliderList 第一个活跃 → lockPoint → transform), + // 网络同步过来的 colliderIndex 不再使用(客户端之间 colliderList 顺序可能不一致) + var targets = new List<(MonsterContral monster, Transform hitPos)>(); + foreach (var guid in data.targetGuid) + { + if (string.IsNullOrEmpty(guid)) continue; + if (!CreateFishManager.Instance.fishDatas_hashCodekey.TryGetValue(guid, out var m) || m == null) continue; + targets.Add((m, ResolveLockTransform(m))); + } - // ⭐ 统一用 ResolveLockTransform:colliderList 第一个活跃 → lockPoint → transform - // 注:网络同步过来的 colliderIndex 在统一逻辑下不再使用,因为客户端之间 - // colliderList 顺序可能不一致,统一用"第一个活跃"更稳定 - Transform hitPos = ResolveLockTransform(monster); + if (targets.Count > 1) + { + sit.SetTripleLockTargets(targets); + } + else + { + // 单发锁定:清掉三发锁位(远端不再显示散射起点球/额外激光/额外锁定圈) + sit.HideTripleLockIcons(); + if (targets.Count == 1) + sit.SetLockTarget(targets[0].monster, targets[0].hitPos); + else + sit.ClearLock(); + } + } - list_Sits[dispPos].SetLockTarget(monster, hitPos); + /// + /// ⭐ 按 guid 列表给座位补齐"三发锁位"(远端散射表现用): + /// 有效目标>1 → SetTripleLockTargets(3条激光 + 2个散射起点球 + 2个额外锁定圈一起出来); + /// 否则清掉三发锁位(该座位按单发显示,主锁不动)。 + /// ⚠ 只给其他玩家的座位用:本地座位的三发锁位由本地锁定系统维护,绝不能被网络数据覆盖。 + /// + private void ApplyTripleLockSlotsFromGuids(SitPosData sit, List guids) + { + var targets = new List<(MonsterContral monster, Transform hitPos)>(); + if (guids != null) + { + foreach (var guid in guids) + { + if (string.IsNullOrEmpty(guid)) continue; + if (!CreateFishManager.Instance.fishDatas_hashCodekey.TryGetValue(guid, out var m) || m == null) continue; + if (m.isDead || !m.gameObject.activeInHierarchy) continue; + targets.Add((m, ResolveLockTransform(m))); + } + } + + if (targets.Count > 1) + sit.SetTripleLockTargets(targets); + else + sit.HideTripleLockIcons(); } public void SyncGameData_RendromDieFish(SyncGameData sync) diff --git a/Assets/MyGame/aa/UI/Game/XJMH/GameMainPanelXJMH.prefab b/Assets/MyGame/aa/UI/Game/XJMH/GameMainPanelXJMH.prefab index 75275c682..22e6fcbc8 100644 --- a/Assets/MyGame/aa/UI/Game/XJMH/GameMainPanelXJMH.prefab +++ b/Assets/MyGame/aa/UI/Game/XJMH/GameMainPanelXJMH.prefab @@ -4410,6 +4410,7 @@ MonoBehaviour: freeModeFishNumbers: - 12025 freeModeFallbackSeconds: 10 + freeFrameEnabled: 0 nukeItemStagger: 0.1 nukeItemPopTime: 0.1 popupOpenTime: 0.2 @@ -12574,12 +12575,12 @@ MonoBehaviour: sprite_VipLevelBG: [] goldNum: 0 consumeGoldNum: 0 - tMP_GoldNum: {fileID: 7476772685813225121} - goldNum_UGUI: {fileID: 0} + tMP_GoldNum: {fileID: 0} + goldNum_UGUI: {fileID: 4940904714095200078} tMP_DiamondNum: {fileID: 0} diamondNum_UGUI: {fileID: 0} - tMP_TurretConsumeNum: {fileID: 3975431389740620247} - turretConsumeNum_UGUI: {fileID: 0} + tMP_TurretConsumeNum: {fileID: 0} + turretConsumeNum_UGUI: {fileID: 5737219766169527111} wingParent: {fileID: 0} zhanShenParent: {fileID: 0} currentZhanShenNumber: 0