Advertisement
TrogWW

TWW superswim script

Jul 14th, 2015
406
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.71 KB | None | 0 0
  1. --[[
  2.  
  3.     **** Superswim Script ****
  4.  
  5.  
  6. 1.) Attach Dolphin to CE process
  7. 2.) Edit the Global Variables
  8.     a.) 'swimOffset' -
  9.                 specifies how off center the swim is, you should probably leave this alone.
  10.                 0 = no offset (Link will swim directly back and forth and won't move)
  11.                 22 = roughly the maximum offset before inconsistencies appear
  12.     b.) 'endX' -
  13.                This value will represent the X coordinate of the final destination
  14.                Look this value up in the CE table.
  15.     c.) 'endY' -
  16.                This value will represent the Y coordinate of the final destination
  17.                Look this value up in the CE table
  18. 3.) Specify hotkeys
  19.             Whatever hotkey you use for Dolphin's frame advance you need to specify in
  20.             the 'frameAdvance() ' function (it's the first function)
  21.             You will edit the 'VK_A' value, use this as reference:
  22.                 http://wiki.cheatengine.org/index.php?title=Virtual-Key_Code
  23.  
  24. 4.) Make a save state to anything EXCEPT states 1 and 2
  25. 5.) Click 'Execute script' at the bottom of this page
  26. 6.) You have two seconds to tab over to Dolphin, make sure Dolphin is highest level process
  27.  
  28.  
  29. ]]
  30.  
  31. ----- GLOBAL VARIABLES -----
  32. swimOffset = 20.25
  33.  
  34.  
  35. endX = 301517.8125
  36. endY = 104112.1016
  37.  
  38. endY = endY * (-1)
  39.  
  40. ----------------------------
  41.  
  42.  
  43. angle = 0           -- This global is pretty unnecessary, should probably fix one of the functions to not need it
  44. rad = 0.0174532925      -- Lua's math library is bad, need to specify radians
  45. startFrame = 0
  46.  
  47.  
  48. function tonumberFix(value)     -- The version of Lua CE uses has a broken 'tonumber' function. This fixes it
  49.          local result = tonumber(value)
  50.          if string.sub(value,1,1) == "-" then
  51.              if result > 0 then
  52.                 result = -result
  53.              end
  54.          end
  55.  
  56.          return result
  57. end
  58.  
  59. function saveState1()
  60.          doKeyPress(VK_F10)
  61.          --sleep(200)
  62.          keyDown(VK_SHIFT)
  63.          keyDown(VK_F1)
  64.          keyUp(VK_SHIFT)
  65.          keyUp(VK_F1)
  66.          sleep(500)
  67.          doKeyPress(VK_F10)
  68. end
  69. function saveState2()
  70.          doKeyPress(VK_F10)
  71.          --sleep(2000)
  72.          keyDown(VK_SHIFT)
  73.          keyDown(VK_F2)
  74.          keyUp(VK_SHIFT)
  75.          keyUp(VK_F2)
  76.          sleep(500)
  77.          doKeyPress(VK_F10)
  78. end
  79. function loadState1()
  80.          local frames = getFrameCount()
  81.          doKeyPress(VK_F10)
  82.          --sleep(200)
  83.          frame = getFrameCount()
  84.          doKeyPress(VK_F1)
  85.          while(getFrameCount() == frames) do
  86.                sleep(1)
  87.          end
  88.          sleep(500)
  89.          doKeyPress(VK_F10)
  90. end
  91. function loadState2()
  92.          local frames = getFrameCount()
  93.          doKeyPress(VK_F10)
  94.          --sleep(200)
  95.          frame = getFrameCount()
  96.          doKeyPress(VK_F2)
  97.          while(getFrameCount() == frames) do
  98.                sleep(1)
  99.          end
  100.          sleep(500)
  101.          doKeyPress(VK_F10)
  102. end
  103.  
  104. function getX()                                 -- returns Link's X-Coordinate
  105.          addresslist = getAddressList()
  106.          description1 = [[X Coordinate]]
  107.          memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
  108.  
  109.          value = memoryrecord_getValue(memoryrec1)
  110.          return tonumberFix(value)
  111. end
  112. function getY()                                 -- returns Link's Y-Coordinate
  113.          addresslist = getAddressList()
  114.          description1 = [[Y Coordinate]]
  115.          memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
  116.  
  117.          value = memoryrecord_getValue(memoryrec1)
  118.          return -1 * tonumberFix(value)
  119. end
  120.  
  121. function getAir()                               -- returns how much air is left in the gauge
  122.          addresslist = getAddressList()
  123.          description1 = [[Air Meter]]
  124.          memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
  125.  
  126.          value = memoryrecord_getValue(memoryrec1)
  127.          return tonumber(value)
  128. end
  129.  
  130. function getFrameCount()                         -- returns total frame count
  131.          addresslist = getAddressList()
  132.          description1 = [[Game Frames]]
  133.          memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
  134.  
  135.          value = memoryrecord_getValue(memoryrec1)
  136.          return tonumber(value)
  137. end
  138.  
  139. function getCameraAngle()                        -- returns the facing direction (in degrees) of the camera
  140.          addresslist = getAddressList()
  141.          description1 = [[Camera X]]
  142.          description2 = [[Camera Y]]
  143.  
  144.          memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
  145.          memoryrec2 = addresslist_getMemoryRecordByDescription(addresslist, description2)
  146.  
  147.          x = memoryrecord_getValue(memoryrec1)
  148.          y = memoryrecord_getValue(memoryrec2)
  149.  
  150.          x = tonumberFix(x)
  151.          y = tonumberFix(y)
  152.          return (getAngle(0,0,x,y))%360
  153. end
  154. function getFacingDirection()                    -- returns the direction (in degrees) Link is facing
  155.          addresslist = getAddressList()
  156.          description1 = [[Facing Direction]]
  157.          memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
  158.  
  159.          value = memoryrecord_getValue(memoryrec1)
  160.          value = tonumber(value)
  161.          return ((value/182.0444444444444) - 90)%360
  162. end
  163. function getSpeed()           -- returns Link's speed
  164.          addresslist = getAddressList()
  165.          description1 = [[Links Speed]]
  166.          memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
  167.  
  168.          value = memoryrecord_getValue(memoryrec1)
  169.          return tonumberFix(value)
  170. end
  171. function writeDirection(x, y) -- writes the two integer values to the left joystick
  172.          addresslist = getAddressList()
  173.  
  174.          description1 = [[Main Stick X]]
  175.          description2 = [[Main Stick Y]]
  176.  
  177.          memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
  178.          memoryrec2 = addresslist_getMemoryRecordByDescription(addresslist, description2)
  179.  
  180.          memoryrecord_setValue(memoryrec1, x)
  181.          memoryrecord_setValue(memoryrec2, y)
  182. end
  183. function getStickX()                             -- returns the value of the X position of the left joystick
  184.          addresslist = getAddressList()
  185.          description1 = [[Main Stick X]]
  186.          memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
  187.  
  188.          local value = memoryrecord_getValue(memoryrec1)
  189.          return tonumber(value)
  190. end
  191.  
  192. function getStickY()                            -- returns the value of the Y position of the left joystick
  193.          addresslist = getAddressList()
  194.          description1 = [[Main Stick Y]]
  195.          memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
  196.  
  197.          value = memoryrecord_getValue(memoryrec1)
  198.          return tonumber(value)
  199. end
  200.  
  201.  
  202. function getAngle(x1,y1,x2,y2)              -- returns the angle (in degrees) of the coordinates (x1,y1) and (x2,y2)
  203.          local dX = x2 - x1
  204.          local dY = y2 - y1
  205.          if dX == 0 and dY == 0 then
  206.             return 0
  207.          end
  208.          local angle = math.deg(math.asin( dY / math.sqrt( math.pow(dX,2) + math.pow(dY,2) ) ) )
  209.          if x2 < x1 then
  210.             angle = 180 - angle
  211.          elseif y2 < y1 then
  212.             angle = 360 + angle
  213.          end
  214.          return angle
  215. end
  216.  
  217. function checkAngle(min, max, myAngle)  -- checks to see if the specified angle is within the boundaries of the min and max
  218.          local i = min
  219.          while true do
  220.              local angleCheck = math.abs(i - myAngle)
  221.              if angleCheck > 0 and angleCheck <= 1 then
  222.                  return true
  223.              end
  224.              if math.abs(i - max) > 0 and math.abs(i - max) <= 1 then
  225.                  break
  226.              end
  227.              i = (i + 1)%360
  228.          end
  229.          return false
  230. end
  231.  
  232. function getDistance()               -- returns the distance from Link's current position to the end distination
  233.          local x = getX()
  234.          local y = getY()
  235.          local dx = endX - x
  236.          local dy = endY - y
  237.          return math.sqrt(math.pow(dx,2) + math.pow(dy,2) )
  238. end
  239.  
  240. function avgAngle(a, b)             -- returns the average of two angles
  241.          local avg
  242.          if (math.abs(a - b) >= 180) then
  243.             avg = (a + b)/2
  244.             avg = (avg + 180)%360
  245.          else
  246.              avg = (a+b)/2
  247.          end
  248.          return avg
  249. end
  250.  
  251. function subAngle(a, b)             -- subtracts two angles
  252.          if(a > b) then
  253.                return a - b
  254.          else
  255.                return  (a - b) + 360
  256.          end
  257. end
  258.  
  259. function frameAdvance()             -- advances one frame
  260.          --local timeCheck = 0
  261.          local currentFrame = getFrameCount()
  262.  
  263.          --doKeyPress(VK_A)
  264.          while (getFrameCount() == currentFrame) do
  265.                if isKeyPressed(VK_SPACE) == true then
  266.                   break
  267.                end
  268.                --[[sleep(10)
  269.                timeCheck = timeCheck + 10
  270.                if (timeCheck >= 500) then
  271.                   frameAdvance()
  272.                end]]
  273.                sleep(1)
  274.          end
  275. end
  276.  
  277. function setDirection(val)          -- converts the angle specified into the joystick layout
  278.         local cameraOffset = getCameraAngle()
  279.         val = (subAngle(val, cameraOffset) + 90 )%360
  280.  
  281.          x = math.cos(val * rad) * 128
  282.          y = math.sin(val * rad) * 128
  283.  
  284.          if (math.ceil(x) - x <= 0.5) then
  285.              x = math.ceil(x)
  286.          else
  287.              x = math.floor(x)
  288.          end
  289.          if (math.ceil(y) - y <= 0.5) then
  290.              y = math.ceil(y)
  291.          else
  292.              y = math.floor(y)
  293.          end
  294.  
  295.          x = x + 128
  296.          y = y + 128
  297.  
  298.          if (x >= 256) then
  299.             x = 255
  300.          end
  301.          if (y >= 256) then
  302.             y = 255
  303.          end
  304.  
  305.          writeDirection(x,y)
  306.          frameAdvance()
  307. end
  308.  
  309. function getArrivalFrame(a, b, c)            -- uses quadratic formula to find earliest arrive frame
  310.          a = (0.5) * a
  311.          p1 = (-1 * b)
  312.          p2 = math.pow(b,2)
  313.          p3 = (4 * a * c)
  314.          p4 = (2 * a)
  315.  
  316.          if (p2 - p3) < 0 then               -- not enough air to make the swim, returns arbritrarily large value
  317.             return 100000
  318.          end
  319.          local solution1 = math.ceil( (p1 - math.sqrt(p2 - p3) )/p4 )
  320.          local solution2 = math.ceil( (p1 + math.sqrt(p2 - p3) )/p4 )
  321.          if (solution1 >= 0 and solution2 >= 0) then
  322.             if solution1 >= solution2 then
  323.                 return solution2
  324.             else
  325.                 return solution1
  326.             end
  327.          end
  328.  
  329.          if (solution1 < 0) then
  330.              return solution2
  331.          else
  332.              return solution1
  333.          end
  334. end
  335.  
  336. function predictDistanceTraveled(x)                     -- polynomial that represents distance traveled over time
  337.          return math.pow(0.246546279480303,2) + (13.2142797537203 * x) - 3131.93496414071
  338. end
  339.  
  340. function predictSpeed(x)                                 -- polynomial that represents speed over time
  341.          return (-1.83504248304368 * x) + 62.6814046091721
  342. end
  343. function predictBestSpeed() -- predicts the which frame/speed needs to be obtained for best arrival time
  344.          local distance = getDistance()
  345.          local bestFrame = 10000
  346.          local bestArrive = 10000
  347.          local bestSpeed = 0
  348.          for i = 0,900 do  -- predicts arrival time for every frame
  349.              local newDistance = distance - predictDistanceTraveled(i)
  350.              local speed = predictSpeed(i)
  351.              local arrive = getArrivalFrame(2, speed, newDistance)
  352.              arrive = arrive + i
  353.              if(arrive < bestArrive and arrive ~= i) then
  354.                        bestFrame = i
  355.                        bestSpeed = speed
  356.                        bestArrive = arrive
  357.              end
  358.          end
  359.          return bestSpeed
  360. end
  361.  
  362. function startSwim()                -- Reorientates Link to be in the proper position to superswim
  363.          local myX = getX()
  364.          local myY = getY()
  365.          local endAngle = getAngle(myX, myY, endX, endY)
  366.          local desiredRight = (endAngle - 90 - (swimOffset/2))%360
  367.          local desiredLeft = (endAngle + 90 + (swimOffset/2))%360
  368.          local myAngle = 0
  369.          local myOffset = 0
  370.          myAngle = getFacingDirection()
  371.  
  372.          while (getSpeed() >= 0 and isKeyPressed(VK_SPACE) == false) do
  373.                setDirection(myAngle)
  374.                setDirection( (myAngle + 180)%360)
  375.          end
  376.  
  377.          myAngle = (myAngle + 180)%360
  378.  
  379.          local minimumIterations = 0
  380.          local subLeft = 0
  381.          local subRight = 0
  382.  
  383.          if subAngle(myAngle, desiredLeft) <= subAngle(desiredLeft, myAngle) then
  384.                subLeft = subAngle(myAngle, desiredLeft)
  385.          else
  386.                subLeft = subAngle(desiredLeft, myAngle)
  387.                turnLeft = false
  388.          end
  389.          if subAngle(myAngle, desiredRight) <= subAngle(desiredRight, myAngle) then
  390.                subRight = subAngle(myAngle, desiredRight)
  391.                turnLeft = false
  392.          else
  393.                subRight = subAngle(desiredRight, myAngle)
  394.  
  395.          end
  396.  
  397.          startFrame = getFrameCount()
  398.          if subLeft <= subRight then
  399.                minimumIterations = math.ceil(subLeft / swimOffset)
  400.                if minimumIterations%2 == 1 then
  401.                      minimumIterations = minimumIterations + 1
  402.                      startFrame = startFrame + 1
  403.                end
  404.                myOffset = -(subLeft/(minimumIterations))
  405.          else
  406.                minimumIterations = math.ceil(subRight / swimOffset)
  407.                if minimumIterations%2 == 1 then
  408.                      minimumIterations = minimumIterations + 1
  409.                      startFrame = startFrame + 1
  410.                end
  411.                myOffset = (subRight/(minimumIterations))
  412.          end
  413.  
  414.          local i = 0
  415.          while i < minimumIterations and isKeyPressed(VK_SPACE) == false do
  416.                myAngle = (myAngle + 180 + myOffset)%360
  417.                setDirection(myAngle)
  418.                i = i + 1
  419.          end
  420. end
  421.  
  422. function swim()                          -- Turns Link left or right depending on frame
  423.          local myX = getX()
  424.          local myY = getY()
  425.          local myAngle = getAngle(myX,myY,endX,endY)
  426.  
  427.          if (getFrameCount()-startFrame)%2 == 0 then -- Left
  428.              myAngle = (myAngle + 90)%360
  429.              myAngle = (myAngle + swimOffset)%360
  430.          else
  431.              myAngle = (myAngle - 90)%360            -- Right
  432.              myAngle = (myAngle - swimOffset)%360
  433.          end
  434.          angle = myAngle
  435.          setDirection(myAngle)
  436. end
  437.  
  438. function releaseSwim()                   -- Positions Link towards the end destination
  439.          doKeyPress(VK_F10)
  440.          local myX = getX()
  441.          local myY = getY()
  442.          local finalAngle = getAngle(myX, myY, endX, endY)
  443.  
  444.          local myAngle = (angle + 180)%360
  445.          myAngle = avgAngle(myAngle, finalAngle)
  446.  
  447.          doKeyPress(VK_F10)
  448.          setDirection(myAngle)
  449.          doKeyPress(VK_F10)
  450.  
  451.          myAngle = (finalAngle + 180)%360
  452.  
  453.          doKeyPress(VK_F10)
  454.          setDirection(myAngle)
  455.  
  456.          writeDirection(128,128)
  457. end
  458.  
  459.  
  460.  
  461.         ----- MAIN CODE -----
  462. sleep(2000)
  463. local bestFrame = 10000
  464. local mySpeed = 0
  465. local totalFrames = 0
  466. local bestSpeed = predictBestSpeed()
  467.  
  468. if bestSpeed >= 0 then          -- Warns user that the destination they selected will not be reachable with current air
  469.    print('Not enough air for this swim!')
  470.    return
  471. end
  472.  
  473. local error = bestSpeed * 0.025     -- Factors in a small chance of error to search for
  474.  
  475. startSwim()
  476.  
  477. while( mySpeed > (bestSpeed - error) and getAir() > 0 and isKeyPressed(VK_SPACE) == false) do   -- swim until near best speed
  478.        mySpeed = getSpeed()
  479.        swim()
  480. end
  481.  
  482. bestSpeed = -10000
  483.  
  484. while getAir() > 0 and isKeyPressed(VK_SPACE) == false do
  485.       saveState2()
  486.  
  487.       releaseSwim()
  488.       frameAdvance()
  489.       frameAdvance()
  490.       frameAdvance()
  491.  
  492.       local speed = getSpeed()
  493.       local distance = getDistance()
  494.       local arrivalFrame = getArrivalFrame(2, speed, distance)           -- Calculate arrival frame
  495.  
  496.       arrivalFrame = arrivalFrame + totalFrames
  497.  
  498.       if arrivalFrame < bestFrame then                           -- Best frame found so far
  499.             bestFrame = arrivalFrame
  500.             bestSpeed = speed
  501.             saveState1()                                           -- Make a save state
  502.       else              -- If Link was going faster but wasn't arriving sooner, we know we can stop looking
  503.             if speed - error <= bestSpeed then  
  504.                      loadState1()
  505.                      writeDirection(128,128)
  506.                      break
  507.             end
  508.       end
  509.       loadState2()              -- Continue searching...
  510.       swim()
  511.       totalFrames = totalFrames + 1
  512. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement