/// </inheritdoc> public double?RollStatistic(Statistic stat, Character character, bool useEffects = false) { StatisticValue sv = character?.GetStatistic(stat, useEffects); if (character == null || sv == null) { return(null); } int rng = GameRandom.Between(1, 100); double maxSuccessRoll; int statNum = sv.Value; if (statNum <= 0) { return(-999); } if (stat is Attribute) { maxSuccessRoll = Math.Round(32.2 * Math.Sqrt(statNum) - 7); } else { maxSuccessRoll = Math.Round(10 * Math.Sqrt(statNum) - 0.225 * statNum - 1); } Attribute luckStat = character.Statistics.Select(x => x.Statistic).OfType <Attribute>().FirstOrDefault(x => x.Aliases.ContainsIgnoreCase("luck")); double luckInfluence = 1.0; int luckDifference = 0; if (luckStat != null) { // each point of LCK above/below 5 prolly shoulda been +/-1% flat chance max // Do that, but ALSO make each point in luck a +/-0.1% chance for mega crit int luckValue = character.GetStatistic(luckStat, useEffects).Value; luckDifference = luckValue - 5; luckInfluence += luckDifference * 0.01; maxSuccessRoll *= luckInfluence; } maxSuccessRoll = Math.Min(maxSuccessRoll, HIGHEST_MAX_SUCCESS_ROLL); double resultPercent = (maxSuccessRoll - rng) / maxSuccessRoll; int critRng = GameRandom.Between(1, 1000); // Success if (resultPercent >= 0) { double maxCritSuccessRoll = 1 + (1 * luckDifference); // Minimum 1, maximum 10 maxCritSuccessRoll = Math.Max(1, Math.Min(maxCritSuccessRoll, 10)); if (critRng <= maxCritSuccessRoll) { return(999); } } // Failure else { double maxCritFailRoll = 6 - (1 * luckDifference); maxCritFailRoll = Math.Min(maxCritFailRoll, 10); if (critRng <= maxCritFailRoll) { return(-999); } } return(Math.Round(resultPercent * 100.0, 1)); }