Since George hasn't done it yet, I'll add the cascade function as a reply to this thread as well, converted from lua to kotlin for those who might struggle with it.
Code:
fun interpolate(low: Int, high: Int, level: Int) : Double {
val value = floor(low * (99 - level) / 98.0) + floor(high * (level - 1) / 98.0) + 1
return min(max((value / 256), 0.0), 1.0)
}
fun cascadeInterpolate(elements: Array<Element>, level: Int, index: Int) : Double {
assert(elements contentEquals elements.copyOf().sortedByDescending { it.req }.toTypedArray()) { "Elements array is not sorted." }
var rate = 1.0
for (i in elements.indices) {
val v = elements[i]
if (i == index) {
rate *= interpolate(v.low, v.high, level)
return rate
}
if (level >= v.req) {
rate *= 1 - interpolate(v.low, v.high, level)
}
}
throw IllegalStateException("Index out of bounds")
}
data class Element(val low: Int, val high: Int, val req: Int)
Example usage:
Code:
val successProbability = cascadeInterpolate(elements, playerLevel, indexOfElementInArray)//returns a double from 0 to 1, giving the probability of the given action succeeding.
Note: When the array of elements is passed to the cascade function, the array must have been sorted in descending order, starting with the highest level element. If they're out of order, you will receive invalid probabilities. All the examples in Wikia I could find had them in descending order, starting with the highest level one. Thus the assertion at the top of the cascade function.
The formula is, as Scu11 mentioned above, from Skilling Success Chart.