2026-08-16 00:38:45 +08:00
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
// 文件:BossKillParam.cs
|
|
|
|
|
|
// 职责:Boss 爆奖(击杀奖励)param 的客户端专用解析模型。
|
|
|
|
|
|
// 对应《Boss爆浆数据前端对接文档》第三节各 Boss 的 param 结构。
|
|
|
|
|
|
// 所有数据由服务端 RoomKillNotice.param 直接下发,客户端只负责
|
|
|
|
|
|
// 解析和渲染,不做任何随机计算(旧 BossConfig 的 GetResponse 已全部删除)。
|
|
|
|
|
|
//
|
|
|
|
|
|
// param 结构速查(按 Boss 类型):
|
|
|
|
|
|
// 1. 幸运轮盘/小丑扑克/弹药箱 → { res:[{optionId,triggerRate,score}], count } 总倍数=score之和
|
|
|
|
|
|
// 2. 幸运飞碟 → { res:[内层,外层], count:2 } 总倍数=内层×外层
|
|
|
|
|
|
// 3. 星际巡航/烈焰风暴 → { isKill, beishu, fishId } 多次死亡
|
|
|
|
|
|
// 4. 破坏球 → { beishu, type } type=2 为最终死亡
|
|
|
|
|
|
// 5. 神龙转盘 → { res:{ option:[...], beizhu } } beizhu=最终倍数
|
|
|
|
|
|
// 6. 概率击杀 → param 直接是整数(倍数)
|
|
|
|
|
|
// 7. 全屏/范围秒怪 → param = null
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
|
|
namespace Assets.MyGame.Scripts.Net.WebResponses
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>Boss 爆奖 param 类型(由 BossKillParamParser.DetectType 判定)</summary>
|
|
|
|
|
|
public enum BossKillParamType
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>无 param(普通鱼 / 全屏秒怪 / 范围秒怪)</summary>
|
|
|
|
|
|
None = 0,
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>选项数组类:幸运轮盘 / 小丑扑克 / 幸运飞碟 / 弹药箱(res 是数组)</summary>
|
|
|
|
|
|
Options = 1,
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>多次死亡:星际巡航 / 烈焰风暴(含 isKill + fishId)</summary>
|
|
|
|
|
|
MultiDeath = 2,
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>破坏球(含 type,无 isKill)</summary>
|
|
|
|
|
|
Bomb = 3,
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>神龙转盘(res 是对象,含 option 数组)</summary>
|
|
|
|
|
|
Dragon = 4,
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>概率击杀(param 直接是整数倍数)</summary>
|
|
|
|
|
|
Probability = 5,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 选项数组项:幸运轮盘/小丑扑克/幸运飞碟/弹药箱的 res 数组元素。
|
|
|
|
|
|
/// JSON: { "optionId": 2, "triggerRate": 30, "score": 3 }
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class BossKillOption
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>选项编号(转盘位置/扑克牌编号/飞碟内外层索引)</summary>
|
|
|
|
|
|
public double optionId;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>触发权重(客户端一般用不到,仅透传)</summary>
|
|
|
|
|
|
public int triggerRate;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>该项倍数/分值</summary>
|
|
|
|
|
|
public double score;
|
|
|
|
|
|
|
|
|
|
|
|
public BossKillOption() { }
|
|
|
|
|
|
|
|
|
|
|
|
public BossKillOption(double optionId, int triggerRate, double score = 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.optionId = optionId;
|
|
|
|
|
|
this.triggerRate = triggerRate;
|
|
|
|
|
|
this.score = score;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 选项数组类 param:幸运轮盘/小丑扑克/幸运飞碟/弹药箱。
|
|
|
|
|
|
/// JSON: { "res": [...], "count": N }
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class BossOptionsParam
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>选中的选项数组(长度=转动/抽取次数;飞碟固定2:res[0]=内层 res[1]=外层)</summary>
|
|
|
|
|
|
public List<BossKillOption> res = new List<BossKillOption>();
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>选项个数(= res.Length)</summary>
|
|
|
|
|
|
public int count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 多次死亡 param:星际巡航(最多3次)/ 烈焰风暴(最多2次)。
|
|
|
|
|
|
/// JSON: { "isKill": true, "beishu": 155, "fishId": "13009-3-3" }
|
2026-08-16 21:40:22 +08:00
|
|
|
|
/// 机械蝎(12028/12029)另带 animId:1=不死只播BJEndUI,2/3/4=带死亡的爆奖
|
2026-08-16 00:38:45 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class BossMultiDeathParam
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>true=最终击杀(鱼死亡爆炸);false=未死(鱼复活继续打)</summary>
|
|
|
|
|
|
public bool isKill;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>本次奖励倍数</summary>
|
|
|
|
|
|
public int beishu;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>鱼ID,格式:原ID-总次数-当前次数(如 13009-3-2)</summary>
|
|
|
|
|
|
public string fishId = "";
|
|
|
|
|
|
|
2026-08-16 21:40:22 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 机械蝎专用:死亡/状态动画 ID。
|
|
|
|
|
|
/// 1 = 不死(只显示 BJEndUI,Boss 保留继续打)
|
|
|
|
|
|
/// 2/3/4 = 带死亡的爆奖(三种表现,Boss 消失)
|
|
|
|
|
|
/// 其他 Boss 无此字段(默认 0)。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public int animId;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>是否带死亡的爆奖(animId >= 2;机械蝎判定用,优先于 isKill)</summary>
|
|
|
|
|
|
public bool IsDeathAward => animId >= 2;
|
|
|
|
|
|
|
2026-08-16 00:38:45 +08:00
|
|
|
|
/// <summary>从 fishId 解析总死亡次数(解析失败返回 0)</summary>
|
|
|
|
|
|
public int TotalCount
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
var parts = fishId?.Split('-');
|
|
|
|
|
|
return parts != null && parts.Length >= 3 && int.TryParse(parts[1], out int v) ? v : 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>从 fishId 解析当前第几次死亡(解析失败返回 0)</summary>
|
|
|
|
|
|
public int CurrentCount
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
var parts = fishId?.Split('-');
|
|
|
|
|
|
return parts != null && parts.Length >= 3 && int.TryParse(parts[2], out int v) ? v : 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 破坏球 param。
|
|
|
|
|
|
/// JSON: { "beishu": 420, "type": 1 }
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class BossBombParam
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>本次奖励倍数</summary>
|
|
|
|
|
|
public int beishu;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>死亡类型:1=第一次死亡(鱼继续存活),2=第二次死亡(最终死亡,鱼爆炸)</summary>
|
|
|
|
|
|
public int type;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>是否最终死亡(type==2)</summary>
|
|
|
|
|
|
public bool IsFinalKill => type >= 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 神龙转盘 param。
|
|
|
|
|
|
/// JSON: { "res": { "option": [80, 160], "beizhu": 160 } }
|
|
|
|
|
|
/// option 数组长度=停靠圈数(1~3):外圈先判定,-1 则继续中圈,再 -1 判定内圈。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class BossDragonParam
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>转盘结果(内层结构)</summary>
|
|
|
|
|
|
public DragonRes res = new DragonRes();
|
|
|
|
|
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class DragonRes
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>各圈数值结果(外→中→内,-1 表示未停靠该圈)</summary>
|
|
|
|
|
|
public List<int> option = new List<int>();
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>最终倍数(取最内层已停靠圈的数值)</summary>
|
|
|
|
|
|
public int beizhu;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
// 解析器
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// BossKillNotice.param 解析器(客户端专用,只解析不随机)。
|
|
|
|
|
|
/// 用法:
|
|
|
|
|
|
/// var type = BossKillParamParser.DetectType(notice.param);
|
|
|
|
|
|
/// switch (type) {
|
|
|
|
|
|
/// case BossKillParamType.MultiDeath: var p = BossKillParamParser.ParseMultiDeath(notice.param); ...
|
|
|
|
|
|
/// }
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static class BossKillParamParser
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 判定 param 类型(对齐文档第四节 JS 判定逻辑)。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static BossKillParamType DetectType(JToken param)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (param == null || param.Type == JTokenType.Null)
|
|
|
|
|
|
return BossKillParamType.None;
|
|
|
|
|
|
|
|
|
|
|
|
// 整数 = 概率击杀
|
|
|
|
|
|
if (param.Type == JTokenType.Integer || param.Type == JTokenType.Float)
|
|
|
|
|
|
return BossKillParamType.Probability;
|
|
|
|
|
|
|
|
|
|
|
|
if (param is JObject obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 多次死亡:isKill + fishId
|
|
|
|
|
|
if (obj["isKill"] != null && obj["fishId"] != null)
|
|
|
|
|
|
return BossKillParamType.MultiDeath;
|
|
|
|
|
|
|
|
|
|
|
|
// 破坏球:type
|
|
|
|
|
|
if (obj["type"] != null)
|
|
|
|
|
|
return BossKillParamType.Bomb;
|
|
|
|
|
|
|
|
|
|
|
|
// 神龙转盘:res 是对象且含 option
|
|
|
|
|
|
if (obj["res"] is JObject resObj && resObj["option"] != null)
|
|
|
|
|
|
return BossKillParamType.Dragon;
|
|
|
|
|
|
|
|
|
|
|
|
// 选项数组类:res 是数组
|
|
|
|
|
|
if (obj["res"] is JArray)
|
|
|
|
|
|
return BossKillParamType.Options;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return BossKillParamType.None;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>解析选项数组类(幸运轮盘/小丑扑克/幸运飞碟/弹药箱),失败返回空对象</summary>
|
|
|
|
|
|
public static BossOptionsParam ParseOptions(JToken param)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (param is JObject obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = obj.ToObject<BossOptionsParam>();
|
|
|
|
|
|
if (result != null) return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
UnityEngine.Debug.LogWarning($"[BossKillParam] ParseOptions 失败: {e.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
return new BossOptionsParam();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>解析多次死亡(星际巡航/烈焰风暴),失败返回 null</summary>
|
|
|
|
|
|
public static BossMultiDeathParam ParseMultiDeath(JToken param)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (param is JObject obj)
|
|
|
|
|
|
return obj.ToObject<BossMultiDeathParam>();
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
UnityEngine.Debug.LogWarning($"[BossKillParam] ParseMultiDeath 失败: {e.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>解析破坏球,失败返回 null</summary>
|
|
|
|
|
|
public static BossBombParam ParseBomb(JToken param)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (param is JObject obj)
|
|
|
|
|
|
return obj.ToObject<BossBombParam>();
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
UnityEngine.Debug.LogWarning($"[BossKillParam] ParseBomb 失败: {e.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>解析神龙转盘,失败返回 null</summary>
|
|
|
|
|
|
public static BossDragonParam ParseDragon(JToken param)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (param is JObject obj)
|
|
|
|
|
|
return obj.ToObject<BossDragonParam>();
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
UnityEngine.Debug.LogWarning($"[BossKillParam] ParseDragon 失败: {e.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>解析概率击杀(param 直接是整数倍数),失败返回 0</summary>
|
|
|
|
|
|
public static int ParseProbability(JToken param)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (param != null && (param.Type == JTokenType.Integer || param.Type == JTokenType.Float))
|
|
|
|
|
|
return (int)param.Value<double>();
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
UnityEngine.Debug.LogWarning($"[BossKillParam] ParseProbability 失败: {e.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|