1
This commit is contained in:
@@ -1,588 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
// ============================================================
|
||||
// 文件:BossConfig.cs
|
||||
// 职责:Boss 各种死亡爆奖配置(幸运轮盘/小丑扑克/幸运飞碟/破坏球/烈焰风暴/星际巡航/神龙转盘 等)
|
||||
// - 服务端下发配置,客户端解析后用 GetResponse() 取随机结果
|
||||
// - 已将服务端依赖(GlobalRandom/RandomBossOption/BsonIgnoreExtraElements)
|
||||
// 替换为 Unity 客户端兼容实现
|
||||
// ============================================================
|
||||
|
||||
namespace Assets.MyGame.Scripts.Net.APIResponses.GameConfig_SubClass
|
||||
{
|
||||
/// <summary>
|
||||
/// Boss设定配置信息
|
||||
/// </summary>
|
||||
public class BossConfig
|
||||
{
|
||||
/// <summary>幸运轮盘配置信息</summary>
|
||||
public List<LuckWheelConfig> LuckWheel { get; set; } = new List<LuckWheelConfig>();
|
||||
|
||||
/// <summary>小丑扑克</summary>
|
||||
public LuckPokerConfig LuckPoker { get; set; } = new LuckPokerConfig();
|
||||
|
||||
/// <summary>幸运飞碟</summary>
|
||||
public List<LuckFlyDiskConfig> LuckFlyDisk { get; set; } = new List<LuckFlyDiskConfig>();
|
||||
|
||||
/// <summary>全屏秒怪</summary>
|
||||
public BaseBossConfig FullScreen { get; set; } = new BaseBossConfig();
|
||||
|
||||
/// <summary>范围秒怪</summary>
|
||||
public BaseBossConfig Range { get; set; } = new BaseBossConfig();
|
||||
|
||||
/// <summary>弹药箱配置</summary>
|
||||
public AmmunitionBoxConfig AmmunitionBox { get; set; } = new AmmunitionBoxConfig();
|
||||
|
||||
/// <summary>星际巡航配置</summary>
|
||||
public InterstellarCruiseConfig InterstellarCruise { get; set; } = new InterstellarCruiseConfig();
|
||||
|
||||
/// <summary>烈焰风暴-死亡配置</summary>
|
||||
public BossFlameStormConfig FlameStorm { get; set; } = new BossFlameStormConfig();
|
||||
|
||||
/// <summary>破坏球-死亡配置</summary>
|
||||
public BossBombConfig Bomb { get; set; } = new BossBombConfig();
|
||||
|
||||
/// <summary>概率击杀</summary>
|
||||
public List<BossProbabilityConfig> Probability { get; set; } = new List<BossProbabilityConfig>();
|
||||
|
||||
/// <summary>神龙转盘</summary>
|
||||
public List<LuckDragonConfig> LuckDragon { get; set; } = new List<LuckDragonConfig>();
|
||||
|
||||
/// <summary>
|
||||
/// 根据权重随机获取一个 Boss 选项
|
||||
/// </summary>
|
||||
public static int GetBossProbabilityConfigResponse(List<BossProbabilityConfigParam> configParams)
|
||||
{
|
||||
if (configParams == null || configParams.Count == 0) return 0;
|
||||
|
||||
int totalWeight = configParams.Sum(p => p.TriggerRate);
|
||||
if (totalWeight <= 0) return 0;
|
||||
|
||||
int randomValue = GlobalRandom.Next(0, totalWeight);
|
||||
int currentWeightSum = 0;
|
||||
foreach (var param in configParams)
|
||||
{
|
||||
currentWeightSum += param.TriggerRate;
|
||||
if (randomValue < currentWeightSum)
|
||||
{
|
||||
return GlobalRandom.NextInclusive(param.Min, param.Max);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据权重随机获取一个死亡次数配置
|
||||
/// </summary>
|
||||
public static CruiseConfigCount GetRandomCountConfigOption(List<CruiseConfigCount> options)
|
||||
{
|
||||
if (options == null || !options.Any()) return null;
|
||||
|
||||
long totalWeight = options.Sum(o => (long)o.TriggerRate);
|
||||
if (totalWeight <= 0) return null;
|
||||
|
||||
long randomValue = GlobalRandom.NextInt64(0, totalWeight);
|
||||
long currentWeightSum = 0;
|
||||
foreach (var option in options)
|
||||
{
|
||||
currentWeightSum += option.TriggerRate;
|
||||
if (randomValue < currentWeightSum)
|
||||
{
|
||||
return option;
|
||||
}
|
||||
}
|
||||
return options.FirstOrDefault(o => o.TriggerRate > 0);
|
||||
}
|
||||
|
||||
/// <summary>死亡次数配置参数</summary>
|
||||
public class CruiseConfigCount
|
||||
{
|
||||
/// <summary>死亡次数</summary>
|
||||
public int Count { get; set; }
|
||||
|
||||
/// <summary>触发权重</summary>
|
||||
public int TriggerRate { get; set; } = 0;
|
||||
|
||||
/// <summary>击杀权重</summary>
|
||||
public int KillRate { get; set; } = 0;
|
||||
}
|
||||
|
||||
/// <summary>神龙转盘</summary>
|
||||
public class LuckDragonConfig : BaseBossConfig
|
||||
{
|
||||
/// <summary>外圈配置 下一个配置为-1</summary>
|
||||
public List<BossProbabilityConfigParam> OuterConfig { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
/// <summary>中圈配置 下一个配置为-1</summary>
|
||||
public List<BossProbabilityConfigParam> MiddleConfig { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
/// <summary>内圈配置 下一个配置为-1</summary>
|
||||
public List<BossProbabilityConfigParam> InnerConfig { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
/// <summary>获取结果</summary>
|
||||
public (List<int> option, int beizhu) GetResponse()
|
||||
{
|
||||
int beishu = 1;
|
||||
var result = new List<int>();
|
||||
int outerResult = GetBossProbabilityConfigResponse(OuterConfig);
|
||||
result.Add(outerResult);
|
||||
if (outerResult == -1)
|
||||
{
|
||||
int middleResult = GetBossProbabilityConfigResponse(MiddleConfig);
|
||||
result.Add(middleResult);
|
||||
if (outerResult == -1)
|
||||
{
|
||||
int innerResult = GetBossProbabilityConfigResponse(InnerConfig);
|
||||
result.Add(innerResult);
|
||||
beishu = innerResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
beishu = middleResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
beishu = outerResult;
|
||||
}
|
||||
UnityEngine.Debug.Log($"[BossConfig] LuckDragon.GetResponse 选项=[{string.Join(",", result)}] 倍数={beishu}");
|
||||
return (result, beishu);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>破坏球配置参数</summary>
|
||||
public class BossBombConfig : BaseBossConfig
|
||||
{
|
||||
/// <summary>死亡次数配置</summary>
|
||||
public List<CruiseConfigCount> CountConfig { get; set; } = new List<CruiseConfigCount>();
|
||||
|
||||
/// <summary>第一次死亡配置</summary>
|
||||
public List<BossProbabilityConfigParam> OneDeathConfig { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
/// <summary>第二次死亡配置</summary>
|
||||
public List<BossProbabilityConfigParam> TwoDeathConfig { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
/// <summary>获取破坏球配置响应信息</summary>
|
||||
public (int beishu, int type) GetResponse(string fishId)
|
||||
{
|
||||
int beishu = 0;
|
||||
var countConfig = GetRandomCountConfigOption(CountConfig);
|
||||
if (countConfig == null)
|
||||
{
|
||||
UnityEngine.Debug.Log("[BossConfig] Bomb.GetResponse countConfig为null 返回 (1,1)");
|
||||
return (1, 1);
|
||||
}
|
||||
if (countConfig.Count == 1)
|
||||
{
|
||||
beishu = GetBossProbabilityConfigResponse(OneDeathConfig);
|
||||
UnityEngine.Debug.Log($"[BossConfig] Bomb.GetResponse 死亡次数={countConfig.Count} 倍数={beishu} type=1 fishId={fishId}");
|
||||
return (beishu, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
beishu = GetBossProbabilityConfigResponse(TwoDeathConfig);
|
||||
UnityEngine.Debug.Log($"[BossConfig] Bomb.GetResponse 死亡次数={countConfig.Count} 倍数={beishu} type=2 fishId={fishId}");
|
||||
return (beishu, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>烈焰风暴配置</summary>
|
||||
public class BossFlameStormConfig : BaseBossConfig
|
||||
{
|
||||
/// <summary>死亡次数配置</summary>
|
||||
public List<CruiseConfigCount> CountConfig { get; set; } = new List<CruiseConfigCount>();
|
||||
|
||||
/// <summary>第一次死亡配置</summary>
|
||||
public List<BossProbabilityConfigParam> OneDeathConfig { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
/// <summary>第二次死亡配置</summary>
|
||||
public List<BossProbabilityConfigParam> TwoDeathConfig { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
/// <summary>获取烈焰风暴配置响应信息</summary>
|
||||
public (bool isKill, int beishu, string fishId) GetResponse(string fishId)
|
||||
{
|
||||
bool isKill = false;
|
||||
int beishu = 0;
|
||||
int count = 1;
|
||||
int sumcount = 1;
|
||||
|
||||
if (!fishId.Contains("-")) // 首次击杀
|
||||
{
|
||||
var countConfig = GetRandomCountConfigOption(CountConfig);
|
||||
if (countConfig == null)
|
||||
{
|
||||
UnityEngine.Debug.Log($"[BossConfig] FlameStorm.GetResponse 首击 countConfig为null 返回 (true,1,{fishId})");
|
||||
return (true, 1, fishId);
|
||||
}
|
||||
count = countConfig.Count;
|
||||
beishu = GetBossProbabilityConfigResponse(OneDeathConfig);
|
||||
if (count == 1)
|
||||
{
|
||||
isKill = true;
|
||||
UnityEngine.Debug.Log($"[BossConfig] FlameStorm.GetResponse 首击一次死 isKill=true 倍数={beishu} fishId={fishId}-{count}-{sumcount}");
|
||||
return (isKill, beishu, $"{fishId}-{count}-{sumcount}");
|
||||
}
|
||||
else
|
||||
{
|
||||
sumcount = countConfig.Count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var parts = fishId.Split('-');
|
||||
count = int.Parse(parts[1]);
|
||||
sumcount = int.Parse(parts[2]);
|
||||
}
|
||||
if (count == 1)
|
||||
{
|
||||
beishu = GetBossProbabilityConfigResponse(TwoDeathConfig);
|
||||
if (sumcount == 2 && count == 1)
|
||||
{
|
||||
UnityEngine.Debug.Log($"[BossConfig] FlameStorm.GetResponse 二击致死 isKill=true 倍数={beishu} fishId={fishId}-{count + 1}-{sumcount}");
|
||||
return (true, beishu, $"{fishId}-{count + 1}-{sumcount}");
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.Debug.Log($"[BossConfig] FlameStorm.GetResponse 二击未死 isKill=false 倍数={beishu} fishId={fishId}-{count + 1}-{sumcount}");
|
||||
return (false, beishu, $"{fishId}-{count + 1}-{sumcount}");
|
||||
}
|
||||
}
|
||||
UnityEngine.Debug.Log($"[BossConfig] FlameStorm.GetResponse 三击致死 isKill=true 倍数={beishu} fishId={fishId}-{count + 1}-{sumcount}");
|
||||
return (true, beishu, $"{fishId}-{count + 1}-{sumcount}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>星际巡航配置</summary>
|
||||
public class InterstellarCruiseConfig : BaseBossConfig
|
||||
{
|
||||
/// <summary>死亡次数配置</summary>
|
||||
public List<CruiseConfigCount> CountConfig { get; set; } = new List<CruiseConfigCount>();
|
||||
|
||||
/// <summary>第一次死亡配置</summary>
|
||||
public List<BossProbabilityConfigParam> OneDeathConfig { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
/// <summary>第二次死亡配置</summary>
|
||||
public List<BossProbabilityConfigParam> TwoDeathConfig { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
/// <summary>第三次死亡配置</summary>
|
||||
public List<BossProbabilityConfigParam> ThreeDeathConfig { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
/// <summary>获取星际巡航配置响应信息</summary>
|
||||
public (bool isKill, int beishu, string fishId) GetResponse(string fishId)
|
||||
{
|
||||
bool isKill = false;
|
||||
int beishu = 0;
|
||||
int count = 1;
|
||||
int sumcount = 1;
|
||||
|
||||
if (!fishId.Contains("-")) // 首次击杀
|
||||
{
|
||||
var countConfig = GetRandomCountConfigOption(CountConfig);
|
||||
if (countConfig == null)
|
||||
{
|
||||
UnityEngine.Debug.Log($"[BossConfig] Cruise.GetResponse 首击 countConfig为null 返回 (true,1,{fishId})");
|
||||
return (true, 1, fishId);
|
||||
}
|
||||
count = countConfig.Count;
|
||||
beishu = GetBossProbabilityConfigResponse(OneDeathConfig);
|
||||
if (count == 1)
|
||||
{
|
||||
isKill = true;
|
||||
UnityEngine.Debug.Log($"[BossConfig] Cruise.GetResponse 首击一次死 isKill=true 倍数={beishu} fishId={fishId}-{count}-{sumcount}");
|
||||
return (isKill, beishu, $"{fishId}-{count}-{sumcount}");
|
||||
}
|
||||
else
|
||||
{
|
||||
sumcount = countConfig.Count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var parts = fishId.Split('-');
|
||||
count = int.Parse(parts[1]);
|
||||
sumcount = int.Parse(parts[2]);
|
||||
}
|
||||
if (count == 1)
|
||||
{
|
||||
beishu = GetBossProbabilityConfigResponse(TwoDeathConfig);
|
||||
if (sumcount == 2 && count == 1)
|
||||
{
|
||||
UnityEngine.Debug.Log($"[BossConfig] Cruise.GetResponse 二击致死 isKill=true 倍数={beishu} fishId={fishId}-{count + 1}-{sumcount}");
|
||||
return (true, beishu, $"{fishId}-{count + 1}-{sumcount}");
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.Debug.Log($"[BossConfig] Cruise.GetResponse 二击未死 isKill=false 倍数={beishu} fishId={fishId}-{count + 1}-{sumcount}");
|
||||
return (false, beishu, $"{fishId}-{count + 1}-{sumcount}");
|
||||
}
|
||||
}
|
||||
beishu = GetBossProbabilityConfigResponse(ThreeDeathConfig);
|
||||
UnityEngine.Debug.Log($"[BossConfig] Cruise.GetResponse 三击致死 isKill=true 倍数={beishu} fishId={fishId}-{count + 1}-{sumcount}");
|
||||
return (true, beishu, $"{fishId}-{count + 1}-{sumcount}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>概率击杀</summary>
|
||||
public class BossProbabilityConfig : BaseBossConfig
|
||||
{
|
||||
public List<BossProbabilityConfigParam> configParams { get; set; } = new List<BossProbabilityConfigParam>();
|
||||
|
||||
public int GetResponse()
|
||||
{
|
||||
int beishu = GetBossProbabilityConfigResponse(configParams);
|
||||
UnityEngine.Debug.Log($"[BossConfig] Probability.GetResponse 倍数={beishu}");
|
||||
return beishu;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>弹药箱配置</summary>
|
||||
public class AmmunitionBoxConfig : BaseBossConfig
|
||||
{
|
||||
/// <summary>3个一样的</summary>
|
||||
public List<BossOptionBaseParam> OptionList { get; set; } = new List<BossOptionBaseParam>();
|
||||
|
||||
/// <summary>获取随机结果</summary>
|
||||
public List<BossOptionBaseParam> GetResponse()
|
||||
{
|
||||
var opt = RandomBossOption.GetRandomBossOption(OptionList);
|
||||
if (opt == null)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning("[BossConfig] AmmunitionBox.GetResponse 选中为null");
|
||||
return null;
|
||||
}
|
||||
UnityEngine.Debug.Log($"[BossConfig] AmmunitionBox.GetResponse 选项Id={opt.OptionId} 倍数/分值={opt.Score}");
|
||||
return new List<BossOptionBaseParam>() { opt };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>幸运飞碟配置信息</summary>
|
||||
public class LuckFlyDiskConfig : BaseBossConfig
|
||||
{
|
||||
/// <summary>内层配置选项列表</summary>
|
||||
public List<BossOptionBaseParam> InnerOptionList { get; set; } = new List<BossOptionBaseParam>();
|
||||
|
||||
/// <summary>外层配置选项列表</summary>
|
||||
public List<BossOptionBaseParam> OuterOptionList { get; set; } = new List<BossOptionBaseParam>();
|
||||
|
||||
/// <summary>获取随机结果</summary>
|
||||
public List<BossOptionBaseParam> GetResponse()
|
||||
{
|
||||
List<BossOptionBaseParam> result = new List<BossOptionBaseParam>();
|
||||
var opt = RandomBossOption.GetRandomBossOption(InnerOptionList);
|
||||
result.Add(opt);
|
||||
var opt1 = RandomBossOption.GetRandomBossOption(OuterOptionList);
|
||||
result.Add(opt1);
|
||||
UnityEngine.Debug.Log($"[BossConfig] FlyDisk.GetResponse 内层={(opt?.OptionId.ToString() ?? "null")} 外层={(opt1?.OptionId.ToString() ?? "null")}");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>小丑扑克</summary>
|
||||
public class LuckPokerConfig : BaseBossConfig
|
||||
{
|
||||
/// <summary>配置选项列表</summary>
|
||||
public List<BossOptionBaseParam> OptionList { get; set; } = new List<BossOptionBaseParam>();
|
||||
|
||||
/// <summary>获取随机结果</summary>
|
||||
public List<BossOptionBaseParam> GetResponse()
|
||||
{
|
||||
var opt = RandomBossOption.GetRandomBossOption(OptionList);
|
||||
if (opt == null)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning("[BossConfig] Poker.GetResponse 选中为null");
|
||||
return null;
|
||||
}
|
||||
UnityEngine.Debug.Log($"[BossConfig] Poker.GetResponse 选项Id={opt.OptionId} 倍数/分值={opt.Score}");
|
||||
return new List<BossOptionBaseParam>() { opt };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>幸运轮盘配置信息</summary>
|
||||
public class LuckWheelConfig : BaseBossConfig
|
||||
{
|
||||
/// <summary>配置选项列表</summary>
|
||||
public List<BossOptionBaseParam> OptionList { get; set; } = new List<BossOptionBaseParam>();
|
||||
|
||||
/// <summary>配置项数量配置列表</summary>
|
||||
public List<BossOptionBaseParam> CountList { get; set; } = new List<BossOptionBaseParam>();
|
||||
|
||||
/// <summary>获取随机结果</summary>
|
||||
public List<BossOptionBaseParam> GetResponse()
|
||||
{
|
||||
List<double> count = new List<double>();
|
||||
List<BossOptionBaseParam> option = new List<BossOptionBaseParam>();
|
||||
|
||||
foreach (var item in CountList)
|
||||
{
|
||||
if (item.TriggerRate >= 100)
|
||||
{
|
||||
count.Add(item.OptionId);
|
||||
continue;
|
||||
}
|
||||
if (GlobalRandom.Next(100) < item.TriggerRate)
|
||||
{
|
||||
count.Add(item.OptionId);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
foreach (var item in count)
|
||||
{
|
||||
var opt = RandomBossOption.GetRandomBossOption(OptionList);
|
||||
if (opt == null) continue;
|
||||
option.Add(opt);
|
||||
}
|
||||
UnityEngine.Debug.Log($"[BossConfig] Wheel.GetResponse 触发次数={count.Count} 选项Ids=[{string.Join(",", option.Select(o => o.OptionId))}]");
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Boss配置基类</summary>
|
||||
public class BaseBossConfig
|
||||
{
|
||||
/// <summary>鱼编号</summary>
|
||||
public List<string> FishNumber { get; set; } = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>boss 概率配置参数</summary>
|
||||
public class BossProbabilityConfigParam
|
||||
{
|
||||
public BossProbabilityConfigParam() { }
|
||||
|
||||
public BossProbabilityConfigParam(int min, int max, int triggerRate)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
TriggerRate = triggerRate;
|
||||
}
|
||||
|
||||
/// <summary>最小值</summary>
|
||||
public int Min { get; set; }
|
||||
|
||||
/// <summary>最大值</summary>
|
||||
public int Max { get; set; }
|
||||
|
||||
/// <summary>触发权重</summary>
|
||||
public int TriggerRate { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Boss道具掉落配置项</summary>
|
||||
public class BossDropItemConfig
|
||||
{
|
||||
/// <summary>道具编号</summary>
|
||||
public string PropNumber { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>道具名称</summary>
|
||||
public string PropName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>掉落数量</summary>
|
||||
public int Count { get; set; } = 1;
|
||||
|
||||
/// <summary>掉落权重(概率 = Weight / 10000)</summary>
|
||||
public int Weight { get; set; } = 0;
|
||||
}
|
||||
|
||||
/// <summary>Boss道具掉落配置</summary>
|
||||
public class BossDropConfig
|
||||
{
|
||||
/// <summary>不掉落权重(概率 = NoDropWeight / 总权重和)</summary>
|
||||
public int NoDropWeight { get; set; } = 5000;
|
||||
|
||||
/// <summary>掉落道具列表</summary>
|
||||
public List<BossDropItemConfig> DropItems { get; set; } = new List<BossDropItemConfig>();
|
||||
}
|
||||
|
||||
/// <summary>公共选项配置</summary>
|
||||
public class BossOptionBaseParam
|
||||
{
|
||||
public BossOptionBaseParam() { }
|
||||
|
||||
public BossOptionBaseParam(double optionId, int triggerRate, double score = 0)
|
||||
{
|
||||
OptionId = optionId;
|
||||
TriggerRate = triggerRate;
|
||||
Score = score;
|
||||
}
|
||||
|
||||
/// <summary>选项编号</summary>
|
||||
public double OptionId { get; set; }
|
||||
|
||||
/// <summary>触发权重</summary>
|
||||
public int TriggerRate { get; set; } = 0;
|
||||
|
||||
/// <summary>分值</summary>
|
||||
public double Score { get; set; } = 0;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 服务端依赖的 Unity 客户端兼容实现
|
||||
// ============================================================
|
||||
|
||||
/// <summary>
|
||||
/// 线程安全的随机数工具(替代服务端的 GlobalRandom)。
|
||||
/// 全部走 UnityEngine.Random,保证客户端单线程主逻辑使用。
|
||||
/// </summary>
|
||||
public static class GlobalRandom
|
||||
{
|
||||
/// <summary>[min, max) 的随机整数</summary>
|
||||
public static int Next(int min, int max)
|
||||
{
|
||||
return UnityEngine.Random.Range(min, max);
|
||||
}
|
||||
|
||||
/// <summary>[0, max) 的随机整数</summary>
|
||||
public static int Next(int max)
|
||||
{
|
||||
return UnityEngine.Random.Range(0, max);
|
||||
}
|
||||
|
||||
/// <summary>[min, max] 闭区间的随机整数(含两端)</summary>
|
||||
public static int NextInclusive(int min, int max)
|
||||
{
|
||||
// Range 的整数重载是 [min, max) 上界开,这里补 1 实现闭区间
|
||||
if (min > max) return min;
|
||||
return UnityEngine.Random.Range(min, max + 1);
|
||||
}
|
||||
|
||||
/// <summary>[min, max) 的随机 long</summary>
|
||||
public static long NextInt64(long min, long max)
|
||||
{
|
||||
if (min >= max) return min;
|
||||
// UnityEngine.Random 无 long 重载,用 double 映射
|
||||
double t = UnityEngine.Random.value;
|
||||
return (long)(min + (max - min) * t);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Boss 选项权重随机工具(替代服务端的 RandomBossOption)。
|
||||
/// </summary>
|
||||
public static class RandomBossOption
|
||||
{
|
||||
/// <summary>
|
||||
/// 按权重随机选中一个 Boss 选项。
|
||||
/// </summary>
|
||||
public static BossOptionBaseParam GetRandomBossOption(List<BossOptionBaseParam> options)
|
||||
{
|
||||
if (options == null || options.Count == 0) return null;
|
||||
|
||||
long totalWeight = options.Sum(o => (long)o.TriggerRate);
|
||||
if (totalWeight <= 0) return null;
|
||||
|
||||
long randomValue = GlobalRandom.NextInt64(0, totalWeight);
|
||||
long currentWeightSum = 0;
|
||||
foreach (var option in options)
|
||||
{
|
||||
currentWeightSum += option.TriggerRate;
|
||||
if (randomValue < currentWeightSum)
|
||||
{
|
||||
return option;
|
||||
}
|
||||
}
|
||||
return options.FirstOrDefault(o => o.TriggerRate > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
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" }
|
||||
/// </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 = "";
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69ace07c67208384189ccb057cbecba5
|
||||
guid: 46b52b22a0770114bbc78dada374f6fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -38,12 +38,14 @@ namespace Assets.MyGame.Scripts.Net.WebResponses
|
||||
public long fishScore;
|
||||
|
||||
/// <summary>
|
||||
/// Boss 爆奖结果(服务端按 Boss 类型下发不同结构)。
|
||||
/// 调用方按鱼类型用 ToObject<T>() 解析为具体结构:
|
||||
/// - LuckDragon: 取 option(int 数组)、beishu
|
||||
/// - Bomb: 取 beishu、type
|
||||
/// - FlameStorm/Cruise: 取 isKill、beishu、fishId
|
||||
/// - 选项类(Wheel/Poker/FlyDisk/AmmunitionBox): List<BossOptionBaseParam>
|
||||
/// Boss 爆奖结果(服务端按 Boss 类型下发不同结构,客户端只解析不随机)。
|
||||
/// 用 BossKillParamParser.DetectType(param) 判定类型后按结构解析:
|
||||
/// - Options : ParseOptions → BossOptionsParam(幸运轮盘/小丑扑克/幸运飞碟/弹药箱)
|
||||
/// - MultiDeath : ParseMultiDeath → BossMultiDeathParam(星际巡航/烈焰风暴 isKill/beishu/fishId)
|
||||
/// - Bomb : ParseBomb → BossBombParam(破坏球 beishu/type)
|
||||
/// - Dragon : ParseDragon → BossDragonParam(神龙转盘 res.option/res.beizhu)
|
||||
/// - Probability : ParseProbability → int(概率击杀,param 直接是倍数)
|
||||
/// - None : 普通鱼 / 全屏秒怪 / 范围秒怪
|
||||
/// </summary>
|
||||
public JToken param;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user