Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- **** Superswim Script ****
- 1.) Attach Dolphin to CE process
- 2.) Edit the Global Variables
- a.) 'swimOffset' -
- specifies how off center the swim is, you should probably leave this alone.
- 0 = no offset (Link will swim directly back and forth and won't move)
- 22 = roughly the maximum offset before inconsistencies appear
- b.) 'endX' -
- This value will represent the X coordinate of the final destination
- Look this value up in the CE table.
- c.) 'endY' -
- This value will represent the Y coordinate of the final destination
- Look this value up in the CE table
- 3.) Specify hotkeys
- Whatever hotkey you use for Dolphin's frame advance you need to specify in
- the 'frameAdvance() ' function (it's the first function)
- You will edit the 'VK_A' value, use this as reference:
- http://wiki.cheatengine.org/index.php?title=Virtual-Key_Code
- 4.) Make a save state to anything EXCEPT states 1 and 2
- 5.) Click 'Execute script' at the bottom of this page
- 6.) You have two seconds to tab over to Dolphin, make sure Dolphin is highest level process
- ]]
- ----- GLOBAL VARIABLES -----
- swimOffset = 20.25
- endX = 301517.8125
- endY = 104112.1016
- endY = endY * (-1)
- ----------------------------
- angle = 0 -- This global is pretty unnecessary, should probably fix one of the functions to not need it
- rad = 0.0174532925 -- Lua's math library is bad, need to specify radians
- startFrame = 0
- function tonumberFix(value) -- The version of Lua CE uses has a broken 'tonumber' function. This fixes it
- local result = tonumber(value)
- if string.sub(value,1,1) == "-" then
- if result > 0 then
- result = -result
- end
- end
- return result
- end
- function saveState1()
- doKeyPress(VK_F10)
- --sleep(200)
- keyDown(VK_SHIFT)
- keyDown(VK_F1)
- keyUp(VK_SHIFT)
- keyUp(VK_F1)
- sleep(500)
- doKeyPress(VK_F10)
- end
- function saveState2()
- doKeyPress(VK_F10)
- --sleep(2000)
- keyDown(VK_SHIFT)
- keyDown(VK_F2)
- keyUp(VK_SHIFT)
- keyUp(VK_F2)
- sleep(500)
- doKeyPress(VK_F10)
- end
- function loadState1()
- local frames = getFrameCount()
- doKeyPress(VK_F10)
- --sleep(200)
- frame = getFrameCount()
- doKeyPress(VK_F1)
- while(getFrameCount() == frames) do
- sleep(1)
- end
- sleep(500)
- doKeyPress(VK_F10)
- end
- function loadState2()
- local frames = getFrameCount()
- doKeyPress(VK_F10)
- --sleep(200)
- frame = getFrameCount()
- doKeyPress(VK_F2)
- while(getFrameCount() == frames) do
- sleep(1)
- end
- sleep(500)
- doKeyPress(VK_F10)
- end
- function getX() -- returns Link's X-Coordinate
- addresslist = getAddressList()
- description1 = [[X Coordinate]]
- memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
- value = memoryrecord_getValue(memoryrec1)
- return tonumberFix(value)
- end
- function getY() -- returns Link's Y-Coordinate
- addresslist = getAddressList()
- description1 = [[Y Coordinate]]
- memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
- value = memoryrecord_getValue(memoryrec1)
- return -1 * tonumberFix(value)
- end
- function getAir() -- returns how much air is left in the gauge
- addresslist = getAddressList()
- description1 = [[Air Meter]]
- memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
- value = memoryrecord_getValue(memoryrec1)
- return tonumber(value)
- end
- function getFrameCount() -- returns total frame count
- addresslist = getAddressList()
- description1 = [[Game Frames]]
- memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
- value = memoryrecord_getValue(memoryrec1)
- return tonumber(value)
- end
- function getCameraAngle() -- returns the facing direction (in degrees) of the camera
- addresslist = getAddressList()
- description1 = [[Camera X]]
- description2 = [[Camera Y]]
- memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
- memoryrec2 = addresslist_getMemoryRecordByDescription(addresslist, description2)
- x = memoryrecord_getValue(memoryrec1)
- y = memoryrecord_getValue(memoryrec2)
- x = tonumberFix(x)
- y = tonumberFix(y)
- return (getAngle(0,0,x,y))%360
- end
- function getFacingDirection() -- returns the direction (in degrees) Link is facing
- addresslist = getAddressList()
- description1 = [[Facing Direction]]
- memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
- value = memoryrecord_getValue(memoryrec1)
- value = tonumber(value)
- return ((value/182.0444444444444) - 90)%360
- end
- function getSpeed() -- returns Link's speed
- addresslist = getAddressList()
- description1 = [[Links Speed]]
- memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
- value = memoryrecord_getValue(memoryrec1)
- return tonumberFix(value)
- end
- function writeDirection(x, y) -- writes the two integer values to the left joystick
- addresslist = getAddressList()
- description1 = [[Main Stick X]]
- description2 = [[Main Stick Y]]
- memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
- memoryrec2 = addresslist_getMemoryRecordByDescription(addresslist, description2)
- memoryrecord_setValue(memoryrec1, x)
- memoryrecord_setValue(memoryrec2, y)
- end
- function getStickX() -- returns the value of the X position of the left joystick
- addresslist = getAddressList()
- description1 = [[Main Stick X]]
- memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
- local value = memoryrecord_getValue(memoryrec1)
- return tonumber(value)
- end
- function getStickY() -- returns the value of the Y position of the left joystick
- addresslist = getAddressList()
- description1 = [[Main Stick Y]]
- memoryrec1 = addresslist_getMemoryRecordByDescription(addresslist, description1)
- value = memoryrecord_getValue(memoryrec1)
- return tonumber(value)
- end
- function getAngle(x1,y1,x2,y2) -- returns the angle (in degrees) of the coordinates (x1,y1) and (x2,y2)
- local dX = x2 - x1
- local dY = y2 - y1
- if dX == 0 and dY == 0 then
- return 0
- end
- local angle = math.deg(math.asin( dY / math.sqrt( math.pow(dX,2) + math.pow(dY,2) ) ) )
- if x2 < x1 then
- angle = 180 - angle
- elseif y2 < y1 then
- angle = 360 + angle
- end
- return angle
- end
- function checkAngle(min, max, myAngle) -- checks to see if the specified angle is within the boundaries of the min and max
- local i = min
- while true do
- local angleCheck = math.abs(i - myAngle)
- if angleCheck > 0 and angleCheck <= 1 then
- return true
- end
- if math.abs(i - max) > 0 and math.abs(i - max) <= 1 then
- break
- end
- i = (i + 1)%360
- end
- return false
- end
- function getDistance() -- returns the distance from Link's current position to the end distination
- local x = getX()
- local y = getY()
- local dx = endX - x
- local dy = endY - y
- return math.sqrt(math.pow(dx,2) + math.pow(dy,2) )
- end
- function avgAngle(a, b) -- returns the average of two angles
- local avg
- if (math.abs(a - b) >= 180) then
- avg = (a + b)/2
- avg = (avg + 180)%360
- else
- avg = (a+b)/2
- end
- return avg
- end
- function subAngle(a, b) -- subtracts two angles
- if(a > b) then
- return a - b
- else
- return (a - b) + 360
- end
- end
- function frameAdvance() -- advances one frame
- --local timeCheck = 0
- local currentFrame = getFrameCount()
- --doKeyPress(VK_A)
- while (getFrameCount() == currentFrame) do
- if isKeyPressed(VK_SPACE) == true then
- break
- end
- --[[sleep(10)
- timeCheck = timeCheck + 10
- if (timeCheck >= 500) then
- frameAdvance()
- end]]
- sleep(1)
- end
- end
- function setDirection(val) -- converts the angle specified into the joystick layout
- local cameraOffset = getCameraAngle()
- val = (subAngle(val, cameraOffset) + 90 )%360
- x = math.cos(val * rad) * 128
- y = math.sin(val * rad) * 128
- if (math.ceil(x) - x <= 0.5) then
- x = math.ceil(x)
- else
- x = math.floor(x)
- end
- if (math.ceil(y) - y <= 0.5) then
- y = math.ceil(y)
- else
- y = math.floor(y)
- end
- x = x + 128
- y = y + 128
- if (x >= 256) then
- x = 255
- end
- if (y >= 256) then
- y = 255
- end
- writeDirection(x,y)
- frameAdvance()
- end
- function getArrivalFrame(a, b, c) -- uses quadratic formula to find earliest arrive frame
- a = (0.5) * a
- p1 = (-1 * b)
- p2 = math.pow(b,2)
- p3 = (4 * a * c)
- p4 = (2 * a)
- if (p2 - p3) < 0 then -- not enough air to make the swim, returns arbritrarily large value
- return 100000
- end
- local solution1 = math.ceil( (p1 - math.sqrt(p2 - p3) )/p4 )
- local solution2 = math.ceil( (p1 + math.sqrt(p2 - p3) )/p4 )
- if (solution1 >= 0 and solution2 >= 0) then
- if solution1 >= solution2 then
- return solution2
- else
- return solution1
- end
- end
- if (solution1 < 0) then
- return solution2
- else
- return solution1
- end
- end
- function predictDistanceTraveled(x) -- polynomial that represents distance traveled over time
- return math.pow(0.246546279480303,2) + (13.2142797537203 * x) - 3131.93496414071
- end
- function predictSpeed(x) -- polynomial that represents speed over time
- return (-1.83504248304368 * x) + 62.6814046091721
- end
- function predictBestSpeed() -- predicts the which frame/speed needs to be obtained for best arrival time
- local distance = getDistance()
- local bestFrame = 10000
- local bestArrive = 10000
- local bestSpeed = 0
- for i = 0,900 do -- predicts arrival time for every frame
- local newDistance = distance - predictDistanceTraveled(i)
- local speed = predictSpeed(i)
- local arrive = getArrivalFrame(2, speed, newDistance)
- arrive = arrive + i
- if(arrive < bestArrive and arrive ~= i) then
- bestFrame = i
- bestSpeed = speed
- bestArrive = arrive
- end
- end
- return bestSpeed
- end
- function startSwim() -- Reorientates Link to be in the proper position to superswim
- local myX = getX()
- local myY = getY()
- local endAngle = getAngle(myX, myY, endX, endY)
- local desiredRight = (endAngle - 90 - (swimOffset/2))%360
- local desiredLeft = (endAngle + 90 + (swimOffset/2))%360
- local myAngle = 0
- local myOffset = 0
- myAngle = getFacingDirection()
- while (getSpeed() >= 0 and isKeyPressed(VK_SPACE) == false) do
- setDirection(myAngle)
- setDirection( (myAngle + 180)%360)
- end
- myAngle = (myAngle + 180)%360
- local minimumIterations = 0
- local subLeft = 0
- local subRight = 0
- if subAngle(myAngle, desiredLeft) <= subAngle(desiredLeft, myAngle) then
- subLeft = subAngle(myAngle, desiredLeft)
- else
- subLeft = subAngle(desiredLeft, myAngle)
- turnLeft = false
- end
- if subAngle(myAngle, desiredRight) <= subAngle(desiredRight, myAngle) then
- subRight = subAngle(myAngle, desiredRight)
- turnLeft = false
- else
- subRight = subAngle(desiredRight, myAngle)
- end
- startFrame = getFrameCount()
- if subLeft <= subRight then
- minimumIterations = math.ceil(subLeft / swimOffset)
- if minimumIterations%2 == 1 then
- minimumIterations = minimumIterations + 1
- startFrame = startFrame + 1
- end
- myOffset = -(subLeft/(minimumIterations))
- else
- minimumIterations = math.ceil(subRight / swimOffset)
- if minimumIterations%2 == 1 then
- minimumIterations = minimumIterations + 1
- startFrame = startFrame + 1
- end
- myOffset = (subRight/(minimumIterations))
- end
- local i = 0
- while i < minimumIterations and isKeyPressed(VK_SPACE) == false do
- myAngle = (myAngle + 180 + myOffset)%360
- setDirection(myAngle)
- i = i + 1
- end
- end
- function swim() -- Turns Link left or right depending on frame
- local myX = getX()
- local myY = getY()
- local myAngle = getAngle(myX,myY,endX,endY)
- if (getFrameCount()-startFrame)%2 == 0 then -- Left
- myAngle = (myAngle + 90)%360
- myAngle = (myAngle + swimOffset)%360
- else
- myAngle = (myAngle - 90)%360 -- Right
- myAngle = (myAngle - swimOffset)%360
- end
- angle = myAngle
- setDirection(myAngle)
- end
- function releaseSwim() -- Positions Link towards the end destination
- doKeyPress(VK_F10)
- local myX = getX()
- local myY = getY()
- local finalAngle = getAngle(myX, myY, endX, endY)
- local myAngle = (angle + 180)%360
- myAngle = avgAngle(myAngle, finalAngle)
- doKeyPress(VK_F10)
- setDirection(myAngle)
- doKeyPress(VK_F10)
- myAngle = (finalAngle + 180)%360
- doKeyPress(VK_F10)
- setDirection(myAngle)
- writeDirection(128,128)
- end
- ----- MAIN CODE -----
- sleep(2000)
- local bestFrame = 10000
- local mySpeed = 0
- local totalFrames = 0
- local bestSpeed = predictBestSpeed()
- if bestSpeed >= 0 then -- Warns user that the destination they selected will not be reachable with current air
- print('Not enough air for this swim!')
- return
- end
- local error = bestSpeed * 0.025 -- Factors in a small chance of error to search for
- startSwim()
- while( mySpeed > (bestSpeed - error) and getAir() > 0 and isKeyPressed(VK_SPACE) == false) do -- swim until near best speed
- mySpeed = getSpeed()
- swim()
- end
- bestSpeed = -10000
- while getAir() > 0 and isKeyPressed(VK_SPACE) == false do
- saveState2()
- releaseSwim()
- frameAdvance()
- frameAdvance()
- frameAdvance()
- local speed = getSpeed()
- local distance = getDistance()
- local arrivalFrame = getArrivalFrame(2, speed, distance) -- Calculate arrival frame
- arrivalFrame = arrivalFrame + totalFrames
- if arrivalFrame < bestFrame then -- Best frame found so far
- bestFrame = arrivalFrame
- bestSpeed = speed
- saveState1() -- Make a save state
- else -- If Link was going faster but wasn't arriving sooner, we know we can stop looking
- if speed - error <= bestSpeed then
- loadState1()
- writeDirection(128,128)
- break
- end
- end
- loadState2() -- Continue searching...
- swim()
- totalFrames = totalFrames + 1
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement