Sorry, but I ended up finding yet another improvement; this time its the celestial globe stage. Turns out using the front porch to clip into the house is faster than using the kid.
Edit: Globe is now 2990 frames. This also gets rid of the only other source of randomness in the game since there's no need to manipulate the food from messing up the walk cycle except in the odd case RJ throws very far away.
Link to video
I did it. I improved the last part of the last stage. :D
Even though this part was sub-optimal, it still saved 200 frames. I'm not going to submit this (yet), since it got me thinking other stages can be improved.
I think I found how the addresses move around. Sorta. The pointers seems to be
02161DB4, 021625C4
The first one works fine on reset and garden areas, but glitches badly in certain spots + if you have more than 1 character at a time. The second pointer does not seem to always work, but it changes to another character only if you swap, unlike the first address. I tried to make it not update falsely, but I haven't managed yet. At least no more needing to refind addresses.
Download display.lua
Language: lua
--pointer may be 02161DB4, 02161DB8, 021625C4
--first one works shit when on certain stages, but works fine-ish elsewise
--second is wonky on reset and garden areas
local pointer1 = 0x21625C4
local pointer2 = 0x2161DB4
local pointer3 = 0x2161DB8
--Declarations here
player = {direction = 0, x = 0, y = 0, z = 0, speed = 0, run = 0, cooldown = 0} --first pointer
names = {[0x211E66C] = "RJ", [0x211EE94] = "Verne", [0x211CE70] = "Hammy"}
--[[the following offsets from above, in hex
ptr + 0x18 = direction
ptr + 0x30 = x
ptr + 0x34 = y
ptr + 0x38 = z
ptr + 0x84 = speed
ptr + 0x460 = Hammy run
ptr + 0x464 = Hammy run cooldown
The pointer should point to an address 0x18 before the direction address. That address should be the following:
211E66C - RJ
211EE94 - Verne
211CE70 - Hammy
Anything else then something is wrong.
0212BE48,02131B3C determines what char you are
1 Verne, 2 RJ, 3 Hammy
]]--
--both for single player; just sanity test
function update(state, pointer)
--Results from reading the pointer; this should be a value that when read again, should point to the character
local ptr = pointer
if (state == p1) then
player.direction = memory.readlongsigned(ptr + 0x18)
player.x = memory.readlongsigned(ptr+0x30)
player.y = memory.readlongsigned(ptr + 0x34)
player.z = memory.readlongsigned(ptr + 0x38)
player.speed = memory.readlongsigned(ptr + 0x84)
player.run = memory.readlongsigned(ptr + 0x460)
player.cooldown = memory.readlongsigned(ptr + 0x464)
end
if (state == p2) then
player.direction = memory.readlongsigned(ptr + 0x18)
player.x = memory.readlongsigned(ptr + 0x30)
player.y = memory.readlongsigned(ptr + 0x34)
player.z = memory.readlongsigned(ptr + 0x38)
player.speed = memory.readlongsigned(ptr + 0x84)
player.run = memory.readlongsigned(ptr + 0x460)
player.cooldown = memory.readlongsigned(ptr + 0x464)
end
if (state == p3) then
player.direction = memory.readlongsigned(ptr + 0x18)
player.x = memory.readlongsigned(ptr + 0x30)
player.y = memory.readlongsigned(ptr + 0x34)
player.z = memory.readlongsigned(ptr + 0x38)
player.speed = memory.readlongsigned(ptr + 0x84)
player.run = memory.readlongsigned(ptr + 0x460)
player.cooldown = memory.readlongsigned(ptr + 0x464)
else
player1 = {direction = 0, x = 0, y = 0, z = 0, speed = 0, run = 0}
end
end
function fn()
local ptr1 = memory.readlongsigned(pointer1)
local ptr2 = memory.readlongsigned(pointer2)
local ptr3 = memory.readlongsigned(pointer3)
local char = memory.readlongsigned(0x212BE48)
--Testing if it points to char
if (memory.readlongsigned(ptr1) == 0x211E66C and char == 2) or (memory.readlongsigned(ptr1) == 0x211EE94 and char == 1) or (memory.readlongunsigned(ptr1) == 0x211CE70 and char == 3) then
update(p1,ptr1)
gui.drawtext(0,60,"p1")
end
if (memory.readlongsigned(ptr2) == 0x211E66C and char == 2) or (memory.readlongsigned(ptr2) == 0x211EE94 and char == 1) or (memory.readlongunsigned(ptr2) == 0x211CE70 and char == 3) then
update(p2,ptr2)
gui.drawtext(10,60,"p2")
end
if (memory.readlongsigned(ptr3) == 0x211E66C and char == 2) or (memory.readlongsigned(ptr3) == 0x211EE94 and char == 1) or (memory.readlongunsigned(ptr3) == 0x211CE70 and char == 3) then
update(p3,ptr3)
gui.drawtext(20,60,"p3")
else
end
gui.drawtext(0,0,"Player: ("..string.format('%.6f',player.x/65536.0)..","..string.format('%.6f',player.y/65536.0)..","..string.format('%.6f',player.z/65536.0)..")\nDirection:"..string.format('%.6f',player.direction/65536.0).."Speed:"..string.format('%.6f',player.speed/65536.0*100))
--debug; ptr# + ofset for x/y/z; "ptr result" is pointer -> ptr -> character things
gui.drawtext(0,30,"Ptr1: "..string.format('%.8x',ptr1).." "..(names[memory.readlongsigned(ptr1)] ~= nil and names[memory.readlongsigned(ptr1)] or ' '))
gui.drawtext(0,40,"Ptr2: "..string.format('%.8x',ptr2).." "..(names[memory.readlongsigned(ptr2)] ~= nil and names[memory.readlongsigned(ptr2)] or ' '))
gui.drawtext(0,50,"Ptr3: "..string.format('%.8x',ptr3).." "..(names[memory.readlongsigned(ptr3)] ~= nil and names[memory.readlongsigned(ptr3)] or ' '))
gui.drawtext(0,70,"Frame: "..movie.framecount()+18)
gui.drawtext(0,80,"Run: "..player.run.."("..player.cooldown..")")
end
gui.register(fn)
Edit: Rewrote the code to make use of 0212BE48 which determines what character you're using to prevent using the wrong pointer.
I noticed that some safes such as the one in the rocking chair stage if unlocked also acts as switches.
The apple at the globe stage that's out of bounds (I walk past it during the TAS) seems unreachable; it immediately unloads if I walk towards it.
In some stages, there's adults. While all of them will use a phone to call the Taxidermist if attacked, some stages are bugged, such as the calculator stage.
I haven't managed to trigger the crashes that plagued me like hell on console. Basically, while TASing, I noticed if I "quick exit" a bunch of certain stages, it crashes the next time I enter a different stage. Quick exit as in achieve the goal, then leave the stage by Start menu like the Any%.