using System.Collections.Generic;
using UnityEngine;
public static class PRD
{
// 预计算的 C 值查找表 (Key: 目标概率 0~1, Value: C常数)
// 常用值:25% -> 0.085, 15% -> 0.032, etc.
// 实际项目中建议预计算存入 Dictionary 或 Array
private static readonly Dictionary<int, float> C_Constants = new Dictionary<int, float>()
{
{ 5, 0.0038f },
{ 10, 0.0147f },
{ 15, 0.0322f },
{ 20, 0.0557f },
{ 25, 0.0847f },
{ 30, 0.1189f },
{ 35, 0.1579f },
{ 40, 0.2015f },
{ 45, 0.2493f },
{ 50, 0.3021f },
{ 60, 0.4226f },
{ 70, 0.5714f },
{ 80, 0.7500f },
// 更多值可查阅 Design/Numerical_Manual.md 或在线计算
};
/// <summary>
/// PRD 状态追踪器
/// 每个需要计算 PRD 的实体(如一个英雄的暴击)都需要一个实例
/// </summary>
public class Tracker
{
private int _counter = 1;
/// <summary>
/// 尝试触发事件
/// </summary>
/// <param name="targetProbability">目标概率 (0.0 ~ 1.0)</param>
/// <returns>是否触发</returns>
public bool Roll(float targetProbability)
{
// 1. 获取 C 值 (简单起见,这里做线性插值或直接取整查找)
// 实际优化:可以将 targetProbability 转为 int (0-100) 查表
float c = GetC(targetProbability);
// 2. 计算当前概率
float currentP = c * _counter;
// 3. 随机判定
if (Random.value < currentP)
{
_counter = 1; // 重置
return true;
}
else
{
_counter++; // 累积
return false;
}
}
}
private static float GetC(float p)
{
int pInt = Mathf.RoundToInt(p * 100);
if (C_Constants.TryGetValue(pInt, out float c)) return c;
// 简单回退:如果查不到表,使用真随机作为兜底
// 或者实现二分查找插值
return p; // 这里仅作示例,实际上应当报错或计算
}
}