This is because the target position is off the bottom of the screen for the cursor that was active before moving (due to the changing hotspot affecting the position). One way to fix this would be to switch (everywhere) to using the hotspot-independent coordinates that you would get if getcur() uses readwordsigned(0x7E04DC),readwordsigned(0x7E04DE) instead of readbyte(0x7E0226), readbyte(0x7E0227). That would probably also allow the script to run faster overall (due to fewer retries when the cursor changes). Another way that appears to work fine is to put in a hack like this:
Language: lua
local sendx,sendy = 128,127
local click = false
local curx,cury = "?","?"
local function getcur()
curx,cury = memory.readbyte(0x7E0226), memory.readbyte(0x7E0227)
local absx = memory.readwordsigned(0x7E04DC)
if absx < 64 and curx > 192 then curx = curx - 256 end
if absx > 192 and curx < 64 then curx = curx + 256 end
end
local function isbusy()
return memory.readbyte(0x7E016A) == 0
end
local function ismousedown()
return memory.readbyte(0x7E00DE) >= 0x40
end
local function next()
joypad.set(1, { x = sendx, y = sendy, left=click } )
emu.frameadvance()
if isbusy() then
local s3 = savestate.create(3)
repeat
savestate.save(s3)
joypad.set(1, { x = sendx, y = sendy, left=click } )
emu.frameadvance()
until not isbusy()
savestate.load(s3)
joypad.set(1, { x = sendx, y = sendy, left=click } )
end
getcur()
local valid_location = AND(memory.readbyte(0x7E0426),1)
gui.text(10,160, "cur="..curx..","..cury..";send="..sendx..","..sendy..",valid="..valid_location)
end
function mousegoto(x,y)
local s = savestate.create(1)
local s2 = savestate.create(2)
savestate.save(s)
local joy = joypad.get(1)
sendx,sendy = joy.x, joy.y
getcur()
if y > 195 and AND(memory.readbyte(0x7E0426),0x12) == 0x12 then -- screen bottom hotspot hack
curx,cury = memory.readwordsigned(0x7E04DC), memory.readwordsigned(0x7E04DE)
end
for attempt=1,8 do
xoff,yoff = x-curx, y-cury
sendx,sendy = sendx + xoff, sendy + yoff
for frame=1,6 do
if curx == x and cury == y then
if frame ~= 1 and not isbusy() then -- TODO: sometimes this is safe even when isbusy() is true.
savestate.load(s2) -- save 1 frame
end
return true -- success
end
savestate.save(s2)
next()
if y > 195 and AND(memory.readbyte(0x7E0426),0x12) == 0x12 then -- screen bottom hotspot hack
curx,cury = memory.readwordsigned(0x7E04DC), memory.readwordsigned(0x7E04DE)
end
end
-- we landed in the wrong place.
-- this will happen if the hotspot changed on us,
-- or if some unknown force is preventing our motion.
-- we'll adjust our target and try again a few more times.
savestate.load(s)
if xoff == x-curx then
if x-curx < 0 then
curx = curx + 127
elseif x-curx > 0 then
curx = curx - 127
end
end
if yoff == y-cury then
if y-cury < 0 then
cury = cury + 127
elseif y-cury > 0 then
cury = cury - 127
end
end
end
print('mousegoto('..x..','..y..') failed. it could only get to '..curx..','..cury..'. rolled back.')
-- failure
end
function clickat(x,y)
click = false
if mousegoto(x,y) then
while ismousedown() do next() end
click = true
while not ismousedown() do next() end
click = false
while ismousedown() do next() end
end
end