include("addresses.lua"); include("settings.lua"); local windowList = findWindowList("Grand Fantasia", "DJO_CLASS"); function getWin() if( __WIN == nil ) then __WIN = windowList[1] end return __WIN; end function getProc() if( __PROC == nil or not windowValid(__WIN) ) then if( __PROC ) then closeProcess(__PROC) end; __PROC = openProcess( findProcessByWindow(getWin()) ); end return __PROC; end function memoryReadRepeat(_type, proc, address, offset) local readfunc; local ptr = false; local val; if( type(proc) ~= "userdata" ) then error("Invalid proc", 2); end if( type(address) ~= "number" ) then error("Invalid address", 2); end if( _type == "int" ) then readfunc = memoryReadInt; elseif( _type == "uint" ) then readfunc = memoryReadUInt; elseif( _type == "float" ) then readfunc = memoryReadFloat; elseif( _type == "byte" ) then readfunc = memoryReadByte; elseif( _type == "string" ) then readfunc = memoryReadString; elseif( _type == "intptr" ) then readfunc = memoryReadIntPtr; ptr = true; elseif( _type == "uintptr" ) then readfunc = memoryReadUIntPtr; ptr = true; elseif( _type == "byteptr" ) then readfunc = memoryReadBytePtr; ptr = true; else return nil; end for i = 1, 10 do if( ptr ) then val = readfunc(proc, address, offset); else val = readfunc(proc, address); end if( val ~= nil ) then return val; end end end targethp = 100 targetname = "" -- I changed a lot here to get the bot working. The pointers commented out don't work (or aren't used) -- Also, in the proccess of getting the bot to work I found the "casting" flag in the combat status function playerupdate() havetarget = memoryReadRepeat("int", getProc(), addresses.havetarget ) if havetarget == 1 then targetbase = memoryReadRepeat("int", getProc(), addresses.targetbase); targethpaddress = memoryReadRepeat("int", getProc(), targetbase + addresses.pawndata_offset) targethp = memoryReadRepeat("int", getProc(), targethpaddress + addresses.HP_offset) or 0 targetX = memoryReadRepeat("float", getProc(), targetbase + addresses.X_offset) targetY = memoryReadRepeat("float", getProc(), targetbase + addresses.Y_offset) --targetnameaddress = memoryReadRepeat("intptr", getProc(), addresses.targetnamebase, {addresses.targetnamebase_offset,addresses.targetname_offset}) --targetname = memoryReadRepeat("string", getProc(), targetnameaddress) end --mouseX = memoryReadRepeat("int", getProc(), addresses.mouseX) -- left right 1,1 is top left --mouseY = memoryReadRepeat("int", getProc(), addresses.mouseY) -- up and down playerName = memoryReadRepeat("string", getProc(), addresses.playerName) playerAddress = memoryReadRepeat("intptr", getProc(), addresses.baseAddress, addresses.pawndata_offset) playerX = memoryReadRepeat("float", getProc(), playerAddress + addresses.X_offset) -- left right 1,1 is bottom left playerY = memoryReadRepeat("float", getProc(), playerAddress + addresses.Y_offset) -- up and down playerlvl = memoryReadRepeat("int", getProc(), playerAddress + addresses.lvl_offset) --playercasting = memoryReadRepeat("int", getProc(), playerAddress - 0x13D28 ) -- needs work playerHP = memoryReadRepeat("int", getProc(), playerAddress + addresses.HP_offset) playerMAXHP = memoryReadRepeat("int", getProc(), playerAddress + addresses.MAXHP_offset) playerMP = memoryReadRepeat("int", getProc(), playerAddress + addresses.MP_offset) playerMAXMP = memoryReadRepeat("int", getProc(), playerAddress + addresses.MAXMP_offset) playerskillcharges = memoryReadRepeat("int", getProc(), playerAddress + addresses.skillcharges_offset) playerGold = memoryReadRepeat("int", getProc(), playerAddress + addresses.Gold_offset) playerxp = memoryReadRepeat("int", getProc(), playerAddress + addresses.xp_offset) end function spriteupdate() sprite1Address = memoryReadRepeat("intptr", getProc(), addresses.sprite1baseAddress, addresses.spriteAddress_offset) sprite3Address = memoryReadRepeat("intptr", getProc(), addresses.sprite3baseAddress, addresses.spriteAddress_offset) sprite1stamina = memoryReadRepeat("int", getProc(), sprite1Address + addresses.spritestamina_offset) sprite3stamina = memoryReadRepeat("int", getProc(), sprite3Address + addresses.spritestamina_offset) end -- Oh, I see what this is now, sorry, didn't update it cause I was confused function targetupdate() --targettype = memoryReadRepeat("int", getProc(), playerAddress + addresses.targettype_offset) -- 3 quest npc -- 4 merchant -- 6 quest npc -- 7 players -- 12 mob (spider) -- 13 mob (bird) -- 14 mob (wasp) -- 17 mob (wolf) -- 22 mob (grey armadilo) -- 25 mob (red armadilo) -- might be target icon, actually no idea. end playerupdate() --spriteupdate() --targetupdate() _time = os.time() gainedxp = 0 killed = 0 gold = playerGold pot = 0 startxp = playerxp function distance(x1, y1, x2, y2) if( x1 == nil or y1 == nil or x2 == nil or y2 == nil ) then error("Error: nil value passed to distance()", 2); end return string.sub( math.sqrt( (y2-y1)*(y2-y1) + (x2-x1)*(x2-x1) ),1,4) end function potions() playerupdate() if ( playerMAXMP - playerMP ) > 200 then keyboardPress(key.VK_8) pot = pot + 1 end if ( playerMAXHP - playerHP ) > 1000 then keyboardPress(key.VK_9) pot = pot + 1 end end function fight() keyboardPress(key.VK_TAB) rest(300) playerupdate() rest(200) incombat = getstatus() if incombat == 1 then print("In Combat") elseif incombat == -1 then print("Resting") elseif incombat == 0 then print("Idle") end if havetarget == 1 then keyboardPress(key.VK_1) rest(500) keyboardPress(settings.hotkeys.MOVE_FORWARD.key) keyboardPress(settings.hotkeys.ROTATE_LEFT.key) _print = true repeat playerupdate() rest(300) dist = distance(playerX,playerY,targetX,targetY) _hp = targethp if _print == true then cprintf(cli.green,"Target HP: "..targethp.."\tTarget distance: "..dist.."\tTarget Name: "..targetname.."\n") _print = false end if 5 >= playerlvl then keyboardPress(key.VK_1) elseif playerskillcharges == 5 then keyboardPress(key.VK_7) rest(300) else keyboardPress(key.VK_6) rest(300) playerupdate() rest(200) end if _hp ~= targethp then _print = true end until not (getstatus() == 1) -- Ended the repeat with leaving combat instead of waiting for the corpse to vanish (loot drops outside anyways) -- Added some looting after combat keyboardPress(key.VK_2) rest(1000) keyboardPress(key.VK_2) rest(1000) newtargettime = os.time() killed = killed + 1 playerupdate() if playerxp - startxp > 0 then gainedxp = ( playerxp - startxp) + gainedxp end print("killed: "..killed.." \tTime: "..os.time() - _time.." \tXP: "..gainedxp.." \tGold: "..playerGold - gold.." \tPots used: "..pot) end if newtargettime and os.time() - newtargettime >= 10 then print("No target for 5 seconds, turning to find more") -- I changed my keys to work like RoM, thats' why I changed these (feel free to change them back to default) keyboardHold(key.VK_Q) rest(1000) keyboardRelease(key.VK_Q) keyboardHold(key.VK_W) rest(1000) keyboardRelease(key.VK_W) end end function box(xbig,xsmall,ybig,ysmall) playerupdate() if playerX >= xbig or xsmall >= playerX or playerY >= ybig or ysmall >= playerY then if _ttime == nil or os.time() - _ttime >= 10 then print("We have moved outside the box limit, turning to try and go back into box") _ttime = os.time() keyboardHold(key.VK_A) rest(1300) keyboardRelease(key.VK_A) keyboardHold(key.VK_W) rest(2000) keyboardRelease(key.VK_W) end end end function checkwindows() windows = memoryReadRepeat("intptr", getProc(), addresses.windowsaddress, addresses.windowsaddress_offset) if windows ~= 0 then print("Number of windows detected: "..windows) --keyboardPress(settings.hotkeys.ESCAPE.key) end end -- So far I've found 4 statuses but this needs updating to account for "unable to attack" situations. -- The game is designed for you to not run into those but it can still happen in a glitchy spot function getstatus() combataddr = memoryReadRepeat("intptr", getProc(), addresses.baseAddress, addresses.combatbase_offset) if DEBUGADDR then cprintf(cli.yellow,"DEBUG: combataddr = 0x%x \n",combataddr) end combatrest = (memoryReadRepeat("int", getProc(), combataddr + addresses.combat_offset) - 0x01000000) if DEBUGADDR then cprintf(cli.yellow,"DEBUG: combatrest = 0x%x \n",combatrest) end if combatrest == 0x00000000 then return 0 end -- Standing, no combat if combatrest == 0x00020000 then return 1 end -- In combat if combatrest == 0x00022000 then return 1 end -- In combat, casting spell if combatrest == 0x00002000 then return 1 end -- Casting spell, no combat yet if combatrest == 0x00008000 then return -1 end -- Sitting, no combat cprintf(cli.lightred,"ERROR: Unexpected value at combat/rest address. Values may have changed.") end