This commit is contained in:
2026-10-14 19:39:24 +08:00
parent 4fd5a3bd45
commit 8498afd5cf
202 changed files with 12624 additions and 236 deletions
@@ -0,0 +1,76 @@
using System;
using UnityEngine;
using System.Collections.Generic;
public class LayeredPool
{
// ⭐ 网络发送回调:由游戏侧(CreateFishManager)注入,框架层不再反向依赖 CreateFishManager
public static Action<int, List<RedPacketRecord>, Vector3, int> OnSendRandomDieFishID;
public static Action<List<RedPacketRecord>, Vector3, int> OnSendRandomCoinFX;
public LayeredPool(int poolNum,int prizeCount)
{
game = new CascadeRedPacketInt(poolNum, prizeCount);
}
CascadeRedPacketInt game;
public List<RedPacketRecord> BossGlodCoin(int count,Vector3 v3Point, int killerSitPos = -1)
{
if (game.HasNext())
{
int currentSubCount = count;
// 传入动态的个数
List<RedPacketRecord> result = game.GrabFullCycle(currentSubCount);
OnSendRandomDieFishID?.Invoke(currentSubCount, result, v3Point, killerSitPos);
return result;
}
return null;
}
public List<RedPacketRecord> BossGlodCoinNotFish(int count)
{
if (game.HasNext())
{
int currentSubCount = count;
// 传入动态的个数
List<RedPacketRecord> result = game.GrabFullCycle(currentSubCount);
return result;
}
return null;
}
public List<RedPacketRecord> BossGlodCoinRandrom(Vector3 v3Point, int min=3,int max=8, int killerSitPos = -1)
{
if (game.HasNext())
{
// --- 模拟动态逻辑 ---
// 假设:第1个人裂变成3个包,第2个人裂变成10个包...
// 这里用随机数模拟每次裂变个数不同 (3 到 8 之间)
int currentSubCount = UnityEngine.Random.Range(min, max + 1);
// 传入动态的个数
List<RedPacketRecord> result = game.GrabFullCycle(currentSubCount);
OnSendRandomDieFishID?.Invoke(currentSubCount, result, v3Point, killerSitPos);
return result;
}
return null;
}
/// <summary>
/// 随机分包 + 随机爆金币但不死鱼:
/// 发 randomDieFish 帧(guids 为空),所有客户端只播屏幕随机位置的金币特效,场上鱼不死亡。
/// </summary>
public List<RedPacketRecord> BossGlodCoinRandromNotFish(Vector3 v3Point, int min=3, int max=8, int killerSitPos = -1)
{
if (game.HasNext())
{
int currentSubCount = UnityEngine.Random.Range(min, max + 1);
List<RedPacketRecord> result = game.GrabFullCycle(currentSubCount);
OnSendRandomCoinFX?.Invoke(result, v3Point, killerSitPos);
return result;
}
return null;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 21c16f4f5a7d9af4cafd5dd3608547b7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
[Serializable]
/// <summary>
/// 纯整数红包记录
/// 金额单位:分 (int)
/// </summary>
public class RedPacketRecord
{
public int Phase { get; set; } // 阶段:1 或 2
public int Index { get; set; } // 第几个包
public long Amount { get; set; } // 金额(单位:分,纯整数)
// 方便调试看日志的格式化方法
public string GetMoneyString()
{
return (Amount / 100) + "." + (Amount % 100).ToString("D2");
}
}
/// <summary>
/// 纯整数版级联红包算法(支持动态裂变个数)
/// </summary>
public class CascadeRedPacketInt
{
private Random _random;
private const int MIN_AMOUNT = 1; // 最小 1 分钱
// --- 第一阶段配置 ---
private int _phase1TotalAmount; // 总金额(分)
private int _phase1Count; // 第一阶段总人数
private int _phase1Grabbed = 0; // 已抢人数
public CascadeRedPacketInt(int totalMoneyCents, int phase1Count, int? seed = null)
{
_random = seed.HasValue ? new Random(seed.Value) : new Random();
_phase1TotalAmount = totalMoneyCents;
_phase1Count = phase1Count;
}
/// <summary>
/// 核心方法:执行一次完整的“抢大包 -> 拆小包”
/// </summary>
/// <param name="subCount">【动态参数】第二轮要裂变出的红包个数</param>
/// <returns>该用户最终获得的一堆小红包列表</returns>
public List<RedPacketRecord> GrabFullCycle(int subCount)
{
// 1. 第一阶段:从大奖池抢一个金额
int phase1Amount = GrabPhase1();
if (phase1Amount <= 0) return null;
// 2. 第二阶段:把这个金额拆分成 subCount 个小包
return SplitPhase2(phase1Amount, subCount);
}
/// <summary>
/// 第一阶段逻辑(不变)
/// </summary>
private int GrabPhase1()
{
if (_phase1Grabbed >= _phase1Count) return -1;
int amount;
int remainingCount = _phase1Count - _phase1Grabbed;
if (_phase1Grabbed == _phase1Count - 1)
{
amount = _phase1TotalAmount;
}
else
{
int avg = _phase1TotalAmount / remainingCount;
int max = avg * 2;
int safeMax = _phase1TotalAmount - (remainingCount * MIN_AMOUNT);
if (max > safeMax) max = safeMax;
if (max < MIN_AMOUNT) max = MIN_AMOUNT;
amount = _random.Next(MIN_AMOUNT, max + 1);
}
_phase1TotalAmount -= amount;
_phase1Grabbed++;
return amount;
}
/// <summary>
/// 第二阶段逻辑(修改点:接收动态个数)
/// </summary>
/// <param name="seedAmount">种子金额(第一阶段抢到的钱)</param>
/// <param name="subCount">要拆分的个数</param>
private List<RedPacketRecord> SplitPhase2(int seedAmount, int subCount)
{
List<RedPacketRecord> subPackets = new List<RedPacketRecord>();
int remainingAmount = seedAmount;
// 如果要求的个数小于等于0,直接把钱全给用户(或者你可以选择报错)
if (subCount <= 0)
{
subPackets.Add(new RedPacketRecord { Phase = 2, Index = 1, Amount = seedAmount });
return subPackets;
}
for (int i = 1; i <= subCount; i++)
{
int amount;
int remainingCount = subCount - i;
if (remainingCount == 0)
{
// 最后一个包,兜底拿走所有剩余
amount = remainingAmount;
}
else
{
// 二倍均值法
int avg = remainingAmount / remainingCount;
int max = avg * 2;
// 边界保护
int safeMax = remainingAmount - (remainingCount * MIN_AMOUNT);
if (max > safeMax) max = safeMax;
if (max < MIN_AMOUNT) max = MIN_AMOUNT;
amount = _random.Next(MIN_AMOUNT, max + 1);
}
remainingAmount -= amount;
subPackets.Add(new RedPacketRecord { Phase = 2, Index = i, Amount = amount });
}
return subPackets;
}
public bool HasNext()
{
return _phase1Grabbed < _phase1Count;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8c4ad3c4505490040b83415c4716b1d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: