This commit is contained in:
2026-10-08 05:01:13 +08:00
parent b8d546a374
commit 5062398e77
8 changed files with 239 additions and 124 deletions
@@ -21,6 +21,8 @@ public class ConstEventString
public const string BaoJiangEnd = "BaoJiangEnd";
/// <summary>钻头蟹/激光蟹释放帧同步(zuanTouRelease):击杀者点击(或超时)发射,所有客户端(含击杀者回广播)统一时刻发射钻头/激光</summary>
public const string SyncGameData_ZuanTouRelease = "SyncGameData_ZuanTouRelease";
/// <summary>加金币帧同步(addGold):刮刮卡等 HTTP 途径获得金币后广播,各客户端给对应座位加金币并刷新显示</summary>
public const string SyncGameData_AddGold = "SyncGameData_AddGold";
// ================================================================
// 服务端 → 客户端事件 (新协议)
@@ -20,6 +20,9 @@ public class BullitMove : MonoBehaviour
MonsterContral target;
public Transform targetTra;
public string bulletID;
/// <summary>该发子弹的实际扣费炮倍(双倍炮=2倍炮倍)。击中结算时作为 KillFish 的 paoBei 上报,
/// 后端按它算奖励 → 双倍炮奖励随之×2。0=未记录(回退发射者座位炮倍)</summary>
public long fireGold = 0;
// 转向参数
public float maxTurnSpeed = 15f; // 最大转向速度(度/秒)
@@ -319,8 +322,12 @@ public class BullitMove : MonoBehaviour
if (userid == GameManager.Instance.user.id)
{
// 真人玩家击杀
// ⭐ paoBei 用该发实际扣费炮倍(双倍炮=2倍),后端按它结算 → 奖励×2;
// 未记录时回退当前座位炮倍(兼容旧逻辑)
long paoBei = fireGold > 0 ? fireGold
: CreateFishManager.Instance.currGameType.currSitData.consumeGoldNum;
var v2 = GameManager.Instance.gameData.currRoomData;
WebSocketSendList.KillFish(v2.roomId, userid, monster.monsterData.fishTypeConfig.fishNumber, monster.guid, (int)CreateFishManager.Instance.currGameType.currSitData.consumeGoldNum, bulletID, "63215f0afa3f5b25");
WebSocketSendList.KillFish(v2.roomId, userid, monster.monsterData.fishTypeConfig.fishNumber, monster.guid, (int)paoBei, bulletID, "63215f0afa3f5b25");
}
else if (!string.IsNullOrEmpty(userid) && userid.StartsWith("bot_"))
{
@@ -61,6 +61,8 @@ namespace Assets.MyGame.Scripts.Net.WebResponses
biaoQing=14,
/// <summary>钻头蟹/激光蟹释放:击杀者点击(或超时)发射钻头/激光,广播给房间所有客户端(含发送者回广播),各端统一时刻发射</summary>
zuanTouRelease=15,
/// <summary>加金币:某玩家通过刮刮卡等 HTTP 途径获得金币(服务端不加房间推送),发送端本地加好后广播,各客户端给对应座位加金币</summary>
addGold=16,
}
[Serializable]
public class FireCannonSendData
@@ -185,6 +187,19 @@ namespace Assets.MyGame.Scripts.Net.WebResponses
public long score;
}
/// <summary>
/// 加金币帧数据(frameType=addGold)。
/// 刮刮卡等 HTTP 途径获得金币后,由获得者客户端广播,各客户端给对应座位(sync.sitPos)加金币并刷新显示。
/// </summary>
[Serializable]
public class FrameData_AddGold : FrameData
{
/// <summary>增加的金币数</summary>
public long gold;
/// <summary>来源描述(金币流水日志用,如 "GuaGuaKa")</summary>
public string source;
}
/// <summary>
/// 表情包类型:spine 动画表情 / 文字表情
/// </summary>
@@ -408,6 +408,10 @@ namespace Assets.MyGame.Scripts.Net
case FrameDataType.zuanTouRelease:
EventCenter.Instance.EventTrigger<SyncGameData>(ConstEventString.SyncGameData_ZuanTouRelease, syncGameData);
break;
// ⭐ 加金币:刮刮卡等 HTTP 途径获得金币后广播,各客户端给对应座位加金币并刷新显示
case FrameDataType.addGold:
EventCenter.Instance.EventTrigger<SyncGameData>(ConstEventString.SyncGameData_AddGold, syncGameData);
break;
default:
break;
}
@@ -1689,7 +1689,7 @@ CircleCollider2D:
m_CallbackLayers:
serializedVersion: 2
m_Bits: 4294967295
m_IsTrigger: 0
m_IsTrigger: 1
m_UsedByEffector: 0
m_UsedByComposite: 0
m_Offset: {x: -0.046641767, y: 0.013882924}
@@ -1,4 +1,5 @@
using Assets.MyGame.Scripts.Net;
using Assets.MyGame.Scripts.Net.APIResponses;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
@@ -49,6 +50,8 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler
private string currentAward;
private bool isRevealed;
private bool isScratching;
/// <summary>本次抽奖结果(领取时按 prizeType 判断是否给游戏内座位加金币)</summary>
private ScratchCardResult drawResult;
private Vector2 lastUV;
private bool hasLastUV;
@@ -62,6 +65,12 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler
/// </summary>
public static bool SuspendWsRefresh;
/// <summary>
/// 领取时刮出金币触发(参数 = 金币数):游戏内 GameMainPanel_FishBase 订阅后
/// 给本地座位加金币并帧同步给房间其他玩家;主界面(无游戏面板)不订阅不触发。
/// </summary>
public static event System.Action<long> OnScratchGoldAwarded;
public override void Awake()
{
base.Awake();
@@ -73,6 +82,10 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler
private void OnGetClick()
{
SuspendWsRefresh = false;
// ⭐ 刮出金币:通知游戏内给本地座位加金币并帧同步给房间其他玩家(主界面没订阅不触发)
if (drawResult != null && drawResult.prizeType == 1 && drawResult.count > 0)
OnScratchGoldAwarded?.Invoke(drawResult.count);
drawResult = null;
string userId = GameManager.Instance?.user?.id;
if (!string.IsNullOrEmpty(userId))
APIRequestList.GetUser(userId, a => GameManager.Instance.UpdataUserData(a));
@@ -145,6 +158,7 @@ public class GuaGuaLeGPU : SubUIBase, IPointerDownHandler, IDragHandler
{
if (result == null || giftPrefab == null) return;
drawResult = result; // 保存抽奖结果:领取时按 prizeType 判断是否给游戏内座位加金币
currentAward = result.prizeName ?? "谢谢参与";
// 清除旧的奖励物品
@@ -207,9 +207,10 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
public float lockPathMax = 0.9f;
// ⭐ 双倍开火:toggle_Shuang 开启后计时 shuangDuration 秒自动关闭(DaoJiShi 驱动),
// child0 的 Image(Filled 360°) 做环形倒计时显示(GetShuangFillImage 懒获取)
float shuangDuration = 15f;
// ⭐ 双倍开火:玩家手动开关的持久模式(同三射/锁定),不自动关闭、不消耗道具。
// child0 的 Image(Filled 360°) 做环形转圈展示(GetShuangFillImage 懒获取):
// 开启后环耗尽一圈从头继续转(循环动画),关闭时停转清环。
float shuangDuration = 15f; // 环转一圈的时长(纯视觉,不控制功能开关)
public float currShuangTime = 0f;
private Image _shuangFillImage;
public Toggle toggle_BaoZou;
@@ -729,6 +730,11 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
EventCenter.Instance.AddEventListener<SyncGameData>(ConstEventString.SyncGameData_ChangeZhanShen, SyncGameData_ChangeZhanShen);
// ⭐ 表情包帧同步(biaoQing):其他玩家发送表情,对应座位显示
EventCenter.Instance.AddEventListener<SyncGameData>(ConstEventString.SyncGameData_BiaoQing, SyncGameData_BiaoQing);
// ⭐ 加金币帧同步(addGold):其他玩家刮刮卡等 HTTP 途径获得金币,对应座位加金币刷新显示
EventCenter.Instance.AddEventListener<SyncGameData>(ConstEventString.SyncGameData_AddGold, SyncGameData_AddGold);
// ⭐ 刮刮卡领取金币:本地座位加金币并帧同步给房间其他玩家(先减防重复订阅)
GuaGuaLeGPU.OnScratchGoldAwarded -= OnScratchGoldAwarded;
GuaGuaLeGPU.OnScratchGoldAwarded += OnScratchGoldAwarded;
// SyncGameData_FreezeFish 已废弃:冰冻改由服务端 FishFrozen 事件统一触发
EventCenter.Instance.AddEventListener(ConstEventString.FishFrozen, OnFishFrozen);
// ⭐ 召唤卡召唤通知:某玩家使用召唤卡,服务端已创建召唤鱼(仅播提示,实际鱼由 OnFishSpawn 创建)
@@ -964,6 +970,9 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
EventCenter.Instance.RemoveEventListener<SyncGameData>(ConstEventString.SyncGameData_ChangeWing, SyncGameData_ChangeWing);
EventCenter.Instance.RemoveEventListener<SyncGameData>(ConstEventString.SyncGameData_ChangeZhanShen, SyncGameData_ChangeZhanShen);
EventCenter.Instance.RemoveEventListener<SyncGameData>(ConstEventString.SyncGameData_BiaoQing, SyncGameData_BiaoQing);
// ⭐ 加金币帧同步 + 刮刮卡领取金币订阅随面板销毁解除
EventCenter.Instance.RemoveEventListener<SyncGameData>(ConstEventString.SyncGameData_AddGold, SyncGameData_AddGold);
GuaGuaLeGPU.OnScratchGoldAwarded -= OnScratchGoldAwarded;
// SyncGameData_FreezeFish 已废弃:冰冻改由服务端 FishFrozen 事件统一触发
EventCenter.Instance.RemoveEventListener(ConstEventString.FishFrozen, OnFishFrozen);
EventCenter.Instance.RemoveEventListener<SummonCardFishNoticeData>(ConstEventString.SummonCardFishNotice, OnSummonCardFishNotice);
@@ -1094,7 +1103,8 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
GameManager.Instance.user.id,
"40003", 0);
});
// ⭐ 双倍开火开关:开启(重新)计时 15 秒 + 满环开始倒计时,关闭停表清环。
// ⭐ 双倍开火开关:持久模式(玩家手动开关,不自动关闭)。
// 开启=满环开始循环转圈(DaoJiShi 驱动,转完一圈从头继续),关闭=停转清环。
// isDouble 不需要同步开关状态:每次开火随 SyncFire 的 twoRTruect 传给服务端,
// 三处开火入口(TryFire/HandleAutoFire/OnFlyTurretUpwardFire)都实时读 isOn
if (toggle_Shuang != null)
@@ -1793,6 +1803,57 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
ShowBiaoQing(dispPos, data.biaoQingType, data.spineIndex, data.content);
}
/// <summary>
/// 刮刮卡领取金币回调(GuaGuaLeGPU.OnScratchGoldAwarded):
/// 服务端已把金币加到大厅数据(游戏内房间不推),给本地座位显示层加金币,
/// 并帧同步(addGold)广播给房间其他玩家。
/// </summary>
public void OnScratchGoldAwarded(long gold)
{
if (currSitData == null || gold <= 0) return;
AddGoldToSeat(currSitData, gold, "GuaGuaKa");
// ⭐ 帧同步给房间其他玩家(自己回广播在 SyncGameData_AddGold 里跳过,防止双重加)
SyncGameData sgd = new SyncGameData
{
sitPos = SeatMirror.ToServer(currSitData.posID),
frameType = FrameDataType.addGold,
time = BeijingTimeManager.Instance.CurrentTimestampMs,
frameData = new FrameData_AddGold { gold = gold, source = "GuaGuaKa" }
};
WebSocketSendList.SyncGameData(sgd);
}
/// <summary>
/// 收到其他玩家的加金币帧(addGold):给对应座位显示层加金币并刷新金币文本。
/// 座位镜像:服务端座位先转显示座位再找场景座位;本地座位跳过(发送时已加)。
/// </summary>
public void SyncGameData_AddGold(SyncGameData sync)
{
var data = FrameDataParser.Parse<FrameData_AddGold>(sync.frameData);
if (data == null || data.gold <= 0) return;
// ⭐ 座位镜像:服务端座位转显示座位
int dispPos = SeatMirror.ToDisplay(sync.sitPos);
if (currSitData == null || dispPos == currSitData.posID) return; // 本地座位已在 OnScratchGoldAwarded 加过
var sit = list_Sits.Find(s => s != null && s.posID == dispPos);
if (sit == null) return;
AddGoldToSeat(sit, data.gold, string.IsNullOrEmpty(data.source) ? "addGold" : data.source);
}
/// <summary>给座位显示层加金币并刷新金币文本 + 记录金币流水(服务端已加钱,这里纯表现层,与杀鱼 onScoreAdd 同惯例)</summary>
private void AddGoldToSeat(SitPosData sit, long gold, string source)
{
long oldGold = sit.goldNum;
sit.goldNum += gold;
if (sit.tMP_GoldNum != null)
sit.tMP_GoldNum.text = sit.goldNum.ToString();
// ⭐ 记录金币流水:已加钱(刮刮卡等途径,本地已执行)
GameManager.LogGoldFlowAppliedGain(source,
$"加金币=+{gold} 座位={sit.posID} 修正前金币={oldGold} 剩余金币={sit.goldNum} 房间={GameManager.Instance.gameData?.currRoomData?.roomId}");
}
#endregion
#region 大喇叭/召唤卡(Left道具快捷按钮)
@@ -2735,7 +2796,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
}
// ⭐ 本地金币校验:没钱不切换 Attack 状态,也不广播,避免无效请求
if (!HasEnoughGoldToFire(toggle_Three.isOn))
if (!HasEnoughGoldToFire(toggle_Three.isOn, toggle_Shuang != null && toggle_Shuang.isOn))
return;
// 按下即进入 Attack:短按→射击,松开后回 Idle
currSitData.ChangeState(TurretState.Attack);
@@ -3066,23 +3127,21 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
}
}
// ⭐ 双倍开火倒计时:child0 的环形填充图(Image Filled 360°)随时间耗尽,
// 15 秒后自动关闭。SetIsOnWithoutNotify 不触发 onValueChanged(避免重置计时逻辑);
// 关闭后三处开火入口读 isOn=false,后续 SyncFire 的 twoRTruect 自动恢复单倍
// ⭐ 双倍开火转圈环:纯展示效果,不是倒计时。
// 双倍是玩家手动开关的持久模式(同三射/锁定),倒计时结束不许关闭功能——
// 环耗尽一圈后从头继续转(循环动画),只有玩家手动关 toggle 才停转清环
// (关闭走 onValueChanged:currShuangTime=0、fill=0)。
// 功能开关由玩家手动控制;三处开火入口实时读 isOn,SyncFire 的 gold 随之×2/×1。
if (toggle_Shuang != null && toggle_Shuang.isOn && shuangDuration > 0)
{
var fill = GetShuangFillImage();
if (fill != null)
fill.fillAmount = Mathf.Clamp01(currShuangTime / shuangDuration);
currShuangTime -= Time.deltaTime;
if (currShuangTime <= 0f)
currShuangTime = shuangDuration; // 转完一圈从头继续转
if (currShuangTime <= 0)
{
toggle_Shuang.SetIsOnWithoutNotify(false);
currShuangTime = 0f;
if (fill != null) fill.fillAmount = 0f;
}
if (fill != null)
fill.fillAmount = Mathf.Clamp01(currShuangTime / shuangDuration);
}
}
@@ -3113,7 +3172,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
// ⭐ 本地金币校验:没钱直接返回,不发送开炮请求
// clickTime 保持满,金币恢复后立即开火
if (!HasEnoughGoldToFire(toggle_Three.isOn))
if (!HasEnoughGoldToFire(toggle_Three.isOn, toggle_Shuang != null && toggle_Shuang.isOn))
return;
// ⭐ 子弹上限校验(先于扣费和状态切换)
@@ -3152,7 +3211,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
{
if (currSitData == null || _isLeavingCountdown) return;
if (currSitData.isDrillActive) return;
if (!HasEnoughGoldToFire(false)) return;
if (!HasEnoughGoldToFire(false, toggle_Shuang != null && toggle_Shuang.isOn)) return;
if (IsBulletLimitReached(currSitData.user)) return;
// 0° = 正上方;起飞炮台不支持三连
@@ -3326,7 +3385,10 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
return; // 没钱,后续不发
MonsterContral target = targets.Count > 0 ? targets[Mathf.Min(i, targets.Count - 1)] : null;
StartCoroutine(LaserHitRoutine(sit, target, bullitIDs[i]));
// ⭐ 该发实际扣费炮倍(服务端权威优先,回退本地计算:双倍×2),
// 结算 KillFish 的 paoBei 用 → 双倍激光奖励×2
long useConsume = gold > 0 ? gold : sit.consumeGoldNum * (isDouble ? 2 : 1);
StartCoroutine(LaserHitRoutine(sit, target, bullitIDs[i], useConsume));
}
if (sit.posID == currSitData.posID)
@@ -3348,7 +3410,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
/// 激光命中协程:延迟 laserHitDelay 后结算(不开实体子弹)。
/// 结算逻辑与 BullitMove.AttackFish 一致:本人发 KillFish、bot 由房主发 BotKillFish、本地播 OnHurt。
/// </summary>
private System.Collections.IEnumerator LaserHitRoutine(SitPosData sit, MonsterContral target, string bulletId)
private System.Collections.IEnumerator LaserHitRoutine(SitPosData sit, MonsterContral target, string bulletId, long fireGold = 0)
{
if (laserHitDelay > 0f)
yield return new WaitForSeconds(laserHitDelay);
@@ -3362,10 +3424,11 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
if (sit.user == GameManager.Instance.user.id)
{
// 真人玩家击杀:直接发后端
// ⭐ paoBei 用该发实际扣费炮倍(双倍=2倍),后端按它结算 → 奖励×2
var v2 = GameManager.Instance.gameData.currRoomData;
WebSocketSendList.KillFish(v2.roomId, sit.user,
target.monsterData.fishTypeConfig.fishNumber, target.guid,
(int)sit.consumeGoldNum, bulletId, "63215f0afa3f5b25");
(int)(fireGold > 0 ? fireGold : sit.consumeGoldNum), bulletId, "63215f0afa3f5b25");
}
else if (!string.IsNullOrEmpty(sit.user) && sit.user.StartsWith("bot_"))
{
@@ -3454,7 +3517,7 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
// ⭐ 本地金币校验:没钱直接返回,不切换攻击状态、不发送开炮请求
// autoFireTimer 保持满,金币恢复后立即开火
if (!HasEnoughGoldToFire(toggle_Three.isOn))
if (!HasEnoughGoldToFire(toggle_Three.isOn, toggle_Shuang != null && toggle_Shuang.isOn))
return;
// ⭐ 子弹上限校验(先于状态切换和扣费)
@@ -4426,11 +4489,13 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
/// 弹出后设 false,仅在金币恢复到够最小炮倍时才重置 true,
/// 期间无论弹窗是否关闭、RequestLeaveRoom 是否异步等待,都不会再弹。
/// </summary>
private bool HasEnoughGoldToFire(bool isSanShe)
private bool HasEnoughGoldToFire(bool isSanShe, bool isDouble = false)
{
if (currSitData == null) return false;
int count = isSanShe ? 3 : 1;
long need = currSitData.consumeGoldNum * count;
// ⭐ 双倍开火每发按 2 倍炮倍扣费(与 SyncFire 的 unitGold 对齐),
// 否则金币只够单倍时仍发双倍请求,后端扣费失败/扣成负数
long need = currSitData.consumeGoldNum * count * (isDouble ? 2 : 1);
if (currSitData.goldNum >= need)
{
// 金币够当前炮倍:可正常开火,重置弹窗标志
@@ -4516,6 +4581,9 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
bullet.userid = sit.user;
bullet.playerID = sit.user;
bullet.bulletID = id;
// ⭐ 记录该发实际扣费炮倍(服务端权威金额优先,回退本地计算:双倍×2),
// 击中时 BullitMove.AttackFish 用它作 KillFish 的 paoBei → 双倍炮奖励×2
bullet.fireGold = fireConsumeGold > 0 ? fireConsumeGold : sit.consumeGoldNum * (isDouble ? 2 : 1);
if (isLock)
{
@@ -4590,6 +4658,11 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
var roomdata = GameManager.Instance.gameData.currRoomData;
var user = GameManager.Instance.user;
// ⭐ 双倍开火:一发子弹按 2 倍炮倍扣费。FireCannon 后端总扣费 = gold(单价) × count(发数),
// 双倍体现在单价×2(子弹仍是一颗),与本地 ConsumeGold(isDouble?2:1) 对齐,
// 否则后端只扣单倍,本地显示被后端权威数据覆盖 → 消耗没有×2
long unitGold = currSitData.consumeGoldNum * (isDouble ? 2 : 1);
// 三射 = 3 发,否则 = 1 发
int count = isSanShe ? 3 : 1;
@@ -4597,13 +4670,13 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
long timespan = BeijingTimeManager.Instance.CurrentTimestampMs; // 毫秒
long timestamp = timespan / 1000; // 秒级
string sign = WebSocketSendList.MakeFireCannonSign(
roomdata.roomId, user.id, currSitData.consumeGoldNum, count, timestamp, "63215f0afa3f5b25");
roomdata.roomId, user.id, unitGold, count, timestamp, "63215f0afa3f5b25");
// FireCannon:roomId, userId, gold, count, timestamp, sign, extra
WebSocketSendList.FireCannon(
roomdata.roomId,
user.id,
currSitData.consumeGoldNum,
unitGold,
count,
timestamp,
sign,
@@ -1485,18 +1485,18 @@ public class GameMainPanel_XJMH : GameMainPanel_FishBase
},
imgs = new[] { "27|83|0.8|Assets/Bundles/PW/PW_Sprite/Common/zd_jn_ss.png" },
},
new HelpItem2Cfg
{
w = 270, h = 398, name = "起飞技能", nameX = -20, nameY = 185,
des = new[]
{
"16|80|<size=19>点击炮台右侧<color=#EEB548>“起飞”</color></size>",
"-7|37|<size=19>按钮, 玩家可以自</size>",
"-11|7|<size=19>由切换飞机和炮台</size>",
"-15|-23|<size=19>这两种形态<color=#EEB548>自由</color></size>",
"-20|-53|<size=19><color=#EEB548>切形, 趣味无穷</color></size>",
},
},
//new HelpItem2Cfg
//{
// w = 270, h = 398, name = "起飞技能", nameX = -20, nameY = 185,
// des = new[]
// {
// "16|80|<size=19>点击炮台右侧<color=#EEB548>“起飞”</color></size>",
// "-7|37|<size=19>按钮, 玩家可以自</size>",
// "-11|7|<size=19>由切换飞机和炮台</size>",
// "-15|-23|<size=19>这两种形态<color=#EEB548>自由</color></size>",
// "-20|-53|<size=19><color=#EEB548>切形, 趣味无穷</color></size>",
// },
//},
};
/// <summary>玩法说明(原版 PW_Config.PlayMethod,12 条)</summary>
@@ -1623,90 +1623,90 @@ public class GameMainPanel_XJMH : GameMainPanel_FishBase
},
imgs = new[] { "-21|90|0.4|Assets/Bundles/PW/PW_Sprite/Handbook/tj_ts_zp.png" },
},
new HelpItem2Cfg
{
w = 310, h = 398, name = "免费模式玩法", nameX = -30, nameY = 185,
fishNumber = 12025, // 图鉴:弹药箱
des = new[]
{
"0|80|<size=19>击毁“ ”, 可获得</size>",
"-10.2|55|<size=19><color=#EEB548>8~12秒</color>免费模式时间; </size>",
"-7.8|1.9|<size=19>击毁“ ”, 可获得</size>",
"-18.3825|-24.4|<size=19>3组免费子弹, 共<color=#EEB548>24~36</color></size>",
"-49.3|-50.9|<size=19><color=#EEB548>秒</color>免费模式时间; </size>",
"-63.7|-78.2|<size=19>免费模式期间: </size>",
"-13.2|-104.56|<size=19>1.发射速度比普通模式高1倍</size>",
"-47.7|-129|<size=19>2.无法调整炮台倍数</size>",
},
imgs = new[]
{
"-13|92|0.4|Assets/Bundles/PW/PW_Sprite/Handbook/tj_ts_jzx.png",
"-22.2|13.3|0.4|Assets/Bundles/PW/PW_Sprite/Handbook/tj_flboss.png",
},
},
new HelpItem2Cfg
{
w = 300, h = 398, name = "分裂属性: ", nameX = -30, nameY = 185,
des = new[]
{
"6.7|89.29|<size=19>分裂: 击中目标后, <color=#EEB548>有概率</color></size>",
"4.720001|61.7|<size=19><color=#EEB548>分裂出多发子弹</color>, 攻击附近</size>",
"-80.7|32.2|<size=19>敌机</size>",
"-5.8|-2.92|<size=19>1级分裂: <color=#EEB548>8%概率</color>触发分裂</size>",
"-10.8|-32.13|<size=19>2级分裂(大对子): <color=#EEB548>20%</color></size>",
"-62.8|-57.64|<size=19><color=#EEB548>概率</color>触发分裂</size>",
"-15.19|-83.6|<size=19>3级分裂(大三元): <color=#EEB548>50%</color></size>",
"-68.1|-108.7|<size=19><color=#EEB548>概率</color>触发分裂</size>",
},
imgs = new[] { "93.53|187.5|0.6|Assets/Bundles/PW/PW_Sprite/FreeModel/PW_FreeItem_1.png" },
},
new HelpItem2Cfg
{
w = 300, h = 398, name = "连电属性: ", nameX = -30, nameY = 185,
des = new[]
{
"6.7|89.29|<size=19>连电: 击中目标后, <color=#EEB548>有概率</color></size>",
"4.720001|61.7|<size=19><color=#EEB548>触发连电效果</color>, 攻击屏幕内</size>",
"-80.7|32.2|<size=19>敌机</size>",
"-5.8|-2.92|<size=19>1级连电: <color=#EEB548>8%概率</color>触发连电</size>",
"-10.8|-32.13|<size=19>2级连电(大对子): <color=#EEB548>20%</color></size>",
"-62.8|-57.64|<size=19><color=#EEB548>概率</color>触发连电</size>",
"-15.19|-83.6|<size=19>3级连电(大三元): <color=#EEB548>50%</color></size>",
"-68.1|-108.7|<size=19><color=#EEB548>概率</color>触发连电</size>",
},
imgs = new[] { "93.53|187.5|0.6|Assets/Bundles/PW/PW_Sprite/FreeModel/PW_FreeItem_2.png" },
},
new HelpItem2Cfg
{
w = 300, h = 398, name = "暴击属性: ", nameX = -30, nameY = 185,
des = new[]
{
"6.699997|89.29|<size=19>暴击: 击毁目标, 有概率</size>",
"-18.6|61.7|<size=19>触发<color=#EEB548>多倍奖励暴击</color></size>",
"3.8|31.2|<size=19>1级暴击: <color=#EEB548>20%概率</color>触发<color=#EEB548>2倍</color></size>",
"-69.16|7.1|<size=19><color=#EEB548>奖励暴击</color></size>",
"-4.4|-21.84|<size=19>2级暴击(大对子): <color=#EEB548>40%</color></size>",
"-17.1|-46.6|<size=19><color=#EEB548>概率</color>触发<color=#EEB548>2~3倍奖励暴击</color></size>",
"-11.2|-78.6|<size=19>3级暴击(大三元): <color=#EEB548>80%</color></size>",
"-23.7|-105.1|<size=19>概率触发<color=#EEB548>3~5倍奖励暴击</color></size>",
},
imgs = new[] { "93.53|187.5|0.6|Assets/Bundles/PW/PW_Sprite/FreeModel/PW_FreeItem_3.png" },
},
new HelpItem2Cfg
{
w = 300, h = 398, name = "加速属性: ", nameX = -30, nameY = 185,
des = new[]
{
"6.699997|89.29|<size=19>加速: <color=#EEB548>提升免费模式期间</color></size>",
"-22.89|61.7|<size=19>发射子弹的速度</size>",
"-7.4|27.11|<size=19>1级加速: 攻速<color=#EEB548>提升20%</color></size>",
"-2.94|-3.8|<size=19>2级加速(大对子): 攻速</size>",
"-72.68|-30.1|<size=19><color=#EEB548>提升80%</color></size>",
"-6.68|-56.7|<size=19>3级加速(大三元): 攻速</size>",
"-70.52|-80.08|<size=19><color=#EEB548>提升300%</color></size>",
},
imgs = new[] { "93.53|187.5|0.6|Assets/Bundles/PW/PW_Sprite/FreeModel/PW_FreeItem_4.png" },
},
//new HelpItem2Cfg
//{
// w = 310, h = 398, name = "免费模式玩法", nameX = -30, nameY = 185,
// fishNumber = 12025, // 图鉴:弹药箱
// des = new[]
// {
// "0|80|<size=19>击毁“ ”, 可获得</size>",
// "-10.2|55|<size=19><color=#EEB548>8~12秒</color>免费模式时间; </size>",
// "-7.8|1.9|<size=19>击毁“ ”, 可获得</size>",
// "-18.3825|-24.4|<size=19>3组免费子弹, 共<color=#EEB548>24~36</color></size>",
// "-49.3|-50.9|<size=19><color=#EEB548>秒</color>免费模式时间; </size>",
// "-63.7|-78.2|<size=19>免费模式期间: </size>",
// "-13.2|-104.56|<size=19>1.发射速度比普通模式高1倍</size>",
// "-47.7|-129|<size=19>2.无法调整炮台倍数</size>",
// },
// imgs = new[]
// {
// "-13|92|0.4|Assets/Bundles/PW/PW_Sprite/Handbook/tj_ts_jzx.png",
// "-22.2|13.3|0.4|Assets/Bundles/PW/PW_Sprite/Handbook/tj_flboss.png",
// },
//},
//new HelpItem2Cfg
//{
// w = 300, h = 398, name = "分裂属性: ", nameX = -30, nameY = 185,
// des = new[]
// {
// "6.7|89.29|<size=19>分裂: 击中目标后, <color=#EEB548>有概率</color></size>",
// "4.720001|61.7|<size=19><color=#EEB548>分裂出多发子弹</color>, 攻击附近</size>",
// "-80.7|32.2|<size=19>敌机</size>",
// "-5.8|-2.92|<size=19>1级分裂: <color=#EEB548>8%概率</color>触发分裂</size>",
// "-10.8|-32.13|<size=19>2级分裂(大对子): <color=#EEB548>20%</color></size>",
// "-62.8|-57.64|<size=19><color=#EEB548>概率</color>触发分裂</size>",
// "-15.19|-83.6|<size=19>3级分裂(大三元): <color=#EEB548>50%</color></size>",
// "-68.1|-108.7|<size=19><color=#EEB548>概率</color>触发分裂</size>",
// },
// imgs = new[] { "93.53|187.5|0.6|Assets/Bundles/PW/PW_Sprite/FreeModel/PW_FreeItem_1.png" },
//},
//new HelpItem2Cfg
//{
// w = 300, h = 398, name = "连电属性: ", nameX = -30, nameY = 185,
// des = new[]
// {
// "6.7|89.29|<size=19>连电: 击中目标后, <color=#EEB548>有概率</color></size>",
// "4.720001|61.7|<size=19><color=#EEB548>触发连电效果</color>, 攻击屏幕内</size>",
// "-80.7|32.2|<size=19>敌机</size>",
// "-5.8|-2.92|<size=19>1级连电: <color=#EEB548>8%概率</color>触发连电</size>",
// "-10.8|-32.13|<size=19>2级连电(大对子): <color=#EEB548>20%</color></size>",
// "-62.8|-57.64|<size=19><color=#EEB548>概率</color>触发连电</size>",
// "-15.19|-83.6|<size=19>3级连电(大三元): <color=#EEB548>50%</color></size>",
// "-68.1|-108.7|<size=19><color=#EEB548>概率</color>触发连电</size>",
// },
// imgs = new[] { "93.53|187.5|0.6|Assets/Bundles/PW/PW_Sprite/FreeModel/PW_FreeItem_2.png" },
//},
//new HelpItem2Cfg
//{
// w = 300, h = 398, name = "暴击属性: ", nameX = -30, nameY = 185,
// des = new[]
// {
// "6.699997|89.29|<size=19>暴击: 击毁目标, 有概率</size>",
// "-18.6|61.7|<size=19>触发<color=#EEB548>多倍奖励暴击</color></size>",
// "3.8|31.2|<size=19>1级暴击: <color=#EEB548>20%概率</color>触发<color=#EEB548>2倍</color></size>",
// "-69.16|7.1|<size=19><color=#EEB548>奖励暴击</color></size>",
// "-4.4|-21.84|<size=19>2级暴击(大对子): <color=#EEB548>40%</color></size>",
// "-17.1|-46.6|<size=19><color=#EEB548>概率</color>触发<color=#EEB548>2~3倍奖励暴击</color></size>",
// "-11.2|-78.6|<size=19>3级暴击(大三元): <color=#EEB548>80%</color></size>",
// "-23.7|-105.1|<size=19>概率触发<color=#EEB548>3~5倍奖励暴击</color></size>",
// },
// imgs = new[] { "93.53|187.5|0.6|Assets/Bundles/PW/PW_Sprite/FreeModel/PW_FreeItem_3.png" },
//},
//new HelpItem2Cfg
//{
// w = 300, h = 398, name = "加速属性: ", nameX = -30, nameY = 185,
// des = new[]
// {
// "6.699997|89.29|<size=19>加速: <color=#EEB548>提升免费模式期间</color></size>",
// "-22.89|61.7|<size=19>发射子弹的速度</size>",
// "-7.4|27.11|<size=19>1级加速: 攻速<color=#EEB548>提升20%</color></size>",
// "-2.94|-3.8|<size=19>2级加速(大对子): 攻速</size>",
// "-72.68|-30.1|<size=19><color=#EEB548>提升80%</color></size>",
// "-6.68|-56.7|<size=19>3级加速(大三元): 攻速</size>",
// "-70.52|-80.08|<size=19><color=#EEB548>提升300%</color></size>",
// },
// imgs = new[] { "93.53|187.5|0.6|Assets/Bundles/PW/PW_Sprite/FreeModel/PW_FreeItem_4.png" },
//},
};
// ==================== 免费模式框(原版 PW_Battery_FreeFrame_L/R) ====================