USA version.
-- RNG addresses
function readRNGs()
return memory.readdword(0x021376A4), memory.readdword(0x021474AC), memory.readdword(0x0215B384), memory.readdword(0x0215E034) -- USA version
end
-- RNG calculations
function RNGStep(iRNG)
local High1 = math.floor(iRNG / 65536)
local Low1 = math.floor(iRNG % 65536)
local High2 = math.floor(1566083941 / 65536)
local Low2 = math.floor(1566083941 % 65536)
local NewHigh = (High1 * Low2 + High2 * Low1) % 65536
local NewLow = Low1 * Low2
return (NewHigh * 65536 + NewLow + 2531011) % 4294967296
--return (1566083941 * iRNG + 2531011) % 4294967296
end
function RNGSteps(iRNG, steps)
for i = 1, steps do
iRNG = RNGStep(iRNG)
end
return iRNG
end
function getNumSteps(oldRNG, newRNG, maxSearch)
if oldRNG == newRNG then
return 0
end
for i = 1, maxSearch do
oldRNG = RNGStep(oldRNG)
if oldRNG == newRNG then
return i
end
end
return -1
end
--[[
a = 1747795628
b = 1027477479
print(getNumSteps(a, b, 10000))
]]
function InvRNGStep(iRNG)
local High1 = math.floor(iRNG / 65536)
local Low1 = math.floor(iRNG % 65536)
local High2 = math.floor(1786162797 / 65536)
local Low2 = math.floor(1786162797 % 65536)
local NewHigh = (High1 * Low2 + High2 * Low1) % 65536
local NewLow = Low1 * Low2
return (NewHigh * 65536 + NewLow + 3284393209) % 4294967296
--return (1786162797 * iRNG + 3284393209) % 4294967296
end
function InvRNGSteps(iRNG, steps)
for i = 1, steps do
iRNG = InvRNGStep(iRNG)
end
return iRNG
end
--[[
c = 2147483648
d = 1
print(InvRNGSteps(c, d))
]]
voiceThreshold = 1431699456
function GetStepsUntilVoice(iRNG, maxSearch)
for i = 1, maxSearch do
iRNG = RNGStep(iRNG)
if iRNG < voiceThreshold then
return i, iRNG
end
end
return -1, "N/A"
end
function GetConsecutiveVoices(iRNG, maxSearch)
for i = 1, maxSearch do
if GetStepsUntilVoice(iRNG, maxSearch) ~= 1 then
return i
end
iRNG = RNGStep(iRNG)
end
return maxSearch
end
hit99Threshold = 4252041215
function GetStepsUntil99Miss(iRNG, maxSearch)
for i = 1, maxSearch do
iRNG = RNGStep(iRNG)
if iRNG > hit99Threshold then
return i
end
end
return -1
end
encounterThreshold = 2147483647
function GetStepsUntilForcedEncounter(iRNG, maxSearch)
for i = 1, maxSearch do
iRNG = RNGStep(iRNG)
if iRNG > encounterThreshold then
return i, iRNG
end
end
return -1, "N/A"
end
function GetConsecutiveEncounters(iRNG, maxSearch)
for i = 1, maxSearch do
if GetStepsUntilForcedEncounter(iRNG, maxSearch) ~= 1 then
return i
end
iRNG = RNGStep(iRNG)
end
return maxSearch
end
function EstimateSafeHitRate(iRNG)
local temp1 = math.floor(RNGStep(iRNG) / 65536)
local temp2 = 100 * temp1
return math.ceil(temp2 / 65536)
end
function EstimateAttackBonusRoll(iRNG)
local temp1 = RNGStep(iRNG)
local temp2 = math.floor(RNGStep(temp1) / 65536)
return temp2 / 1285020
end
function EstimateTechBonusRoll(iRNG)
local temp1 = RNGStep(iRNG)
local temp2 = math.floor(RNGStep(temp1) / 65536)
return temp2 / 780192
end
function EstimateMagicBonusRoll(iRNG)
local temp1 = RNGStep(iRNG)
local temp2 = math.floor(RNGStep(temp1) / 65536)
return temp2 / 978164
end
encounterRNG = -1
nextForcedEncounterRNG = -1
dmgHitRNG = -1
movementRNG = -1
voiceRNG = -1
nextForcedVoiceRNG = -1
stepsUntilForcedEncounter = "N/A"
consecutiveEncounters = "N/A"
stepsUntil99Miss = "N/A"
estimatedSafeHitRate = "N/A"
estimatedAttackBonusRoll = "N/A"
estimatedTechBonusRoll = "N/A"
estimatedMagicBonusRoll = "N/A"
stepsUntilVoice = "N/A"
consecutiveVoices = "N/A"
function printRNGChanges()
Frame = memory.readdword(0x023FFC3C) -- USA version
newEncounterRNG, newDmgHitRNG, newMovementRNG, newVoiceRNG = readRNGs()
if encounterRNG ~= newEncounterRNG then
numSteps = getNumSteps(encounterRNG, newEncounterRNG, 1000)
if numSteps ~= -1 then
print("Encounter RNG: " .. newEncounterRNG .. " (" .. numSteps .. ")" .. " at frame " .. Frame)
-- Unknown advance
else print("Encounter RNG: " .. newEncounterRNG .. " at frame " .. Frame)
end
encounterRNG = newEncounterRNG
stepsUntilForcedEncounter, nextForcedEncounterRNG = GetStepsUntilForcedEncounter(encounterRNG, 1000)
consecutiveEncounters = GetConsecutiveEncounters(nextForcedEncounterRNG, 1000)
end
if dmgHitRNG ~= newDmgHitRNG then
numSteps = getNumSteps(dmgHitRNG, newDmgHitRNG, 1000)
if numSteps ~= -1 then
print("Damage/hit RNG: " .. newDmgHitRNG .. " (" .. numSteps .. ")" .. " at frame " .. Frame)
-- Unknown advance
else print("Damage/hit RNG: " .. newDmgHitRNG .. " at frame " .. Frame)
end
dmgHitRNG = newDmgHitRNG
stepsUntil99Miss = GetStepsUntil99Miss(dmgHitRNG, 1000)
estimatedSafeHitRate = EstimateSafeHitRate(dmgHitRNG)
estimatedAttackBonusRoll = string.format("%.3f" , EstimateAttackBonusRoll(dmgHitRNG))
estimatedTechBonusRoll = string.format("%.3f" , EstimateTechBonusRoll(dmgHitRNG))
estimatedMagicBonusRoll = string.format("%.3f" , EstimateMagicBonusRoll(dmgHitRNG))
end
if movementRNG ~= newMovementRNG then
numSteps = getNumSteps(movementRNG, newMovementRNG, 1000)
if numSteps ~= -1 then
print("Movement RNG: " .. newMovementRNG .. " (" .. numSteps .. ")" .. " at frame " .. Frame)
-- Unknown advance
else print("Movement RNG: " .. newMovementRNG .. " at frame " .. Frame)
end
movementRNG = newMovementRNG
end
if voiceRNG ~= newVoiceRNG then
numSteps = getNumSteps(voiceRNG, newVoiceRNG, 1000)
if numSteps ~= -1 then
print("Voice RNG: " .. newVoiceRNG .. " (" .. numSteps .. ")" .. " at frame " .. Frame)
-- Unknown advance
else print("Voice RNG: " .. newVoiceRNG .. " at frame " .. Frame)
end
voiceRNG = newVoiceRNG
stepsUntilVoice, nextForcedVoiceRNG = GetStepsUntilVoice(voiceRNG, 1000)
consecutiveVoices = GetConsecutiveVoices(nextForcedVoiceRNG, 1000)
end
end
--memory.registerwrite(0x0215B384, printRNGChanges)
function drawGUI()
gui.text(1,5, "Estimated melee roll: " .. estimatedAttackBonusRoll .. "x")
gui.text(1,15, "Estimated ranged roll: " .. estimatedTechBonusRoll .. "x")
gui.text(1,25, "Estimated spell roll: " .. estimatedMagicBonusRoll .. "x")
gui.text(1,35, "Estimated safe hit rate: " .. estimatedSafeHitRate .. "%")
gui.text(1,45, "Steps to 99% miss: " .. stepsUntil99Miss)
gui.text(1,65, "Steps to extra voice x" .. consecutiveVoices .. ": " .. stepsUntilVoice)
gui.text(1,85, "Steps to forced encounter x".. consecutiveEncounters .. ": " .. stepsUntilForcedEncounter)
end
-- Main loop
function main()
printRNGChanges()
end
emu.registerbefore(main)
gui.register(drawGUI)