Advertisement
biosp4rk

Zero Mission - Drops Predictor

Feb 13th, 2016
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.40 KB | None | 0 0
  1. --Makeshift droptype enum
  2. local None, Bomb, Super, Missile, Small, Large = 0,1,2,3,4,5
  3.  
  4. neededDrop = None
  5.  
  6. rns = {13, 2, 6, 8, 7, 9, 14, 10, 2, 4, 14, 4, 12, 15, 13, 12, 11, 1, 3, 15, 0, 6, 7, 8, 11, 5, 0, 3, 5, 1, 9, 10}
  7. enHealth = { }
  8.  
  9. chosenEnemyIndex = -1
  10. clickBoxSize = 8
  11. prevClick = false
  12. pause = false
  13.  
  14. -- functions for displaying drop
  15. function DrawHighlight(x, y)    -- displays a box
  16.     gui.line(x-clickBoxSize, y-clickBoxSize, x+clickBoxSize, y-clickBoxSize, "green")
  17.     gui.line(x-clickBoxSize, y-clickBoxSize, x-clickBoxSize, y+clickBoxSize, "green")
  18.     gui.line(x-clickBoxSize, y+clickBoxSize, x+clickBoxSize, y+clickBoxSize, "green")
  19.     gui.line(x+clickBoxSize, y-clickBoxSize, x+clickBoxSize, y+clickBoxSize, "green")
  20. end
  21.  
  22. function DrawNone(x, y)     -- displays an X for no drop
  23.     gui.line(1+x, 1+y, 6+x, 6+y, "white")
  24.     gui.line(1+x, 6+y, 6+x, 1+y, "white")
  25. end
  26.  
  27. function DrawSmall(x, y)    -- displays a small health drop
  28.     gui.line(3+x, 1+y, 4+x, 1+y, "#D030D0")
  29.     gui.pixel(2+x, 2+y, "#D030D0")
  30.     gui.pixel(5+x, 2+y, "#D030D0")
  31.     gui.line(1+x, 3+y, 1+x, 4+y, "#D030D0")
  32.     gui.box(3+x, 3+y, 4+x, 4+y, "#D030D0")
  33.     gui.line(6+x, 3+y, 6+x, 4+y, "#D030D0")
  34.     gui.pixel(2+x, 5+y, "#D030D0")
  35.     gui.pixel(5+x, 5+y, "#D030D0")
  36.     gui.line(3+x, 6+y, 4+x, 6+y, "#D030D0")
  37. end
  38.  
  39. function DrawLarge(x, y)    -- displays a large health drop
  40.     gui.line(2+x, y, 5+x, y, "#D030D0")
  41.     gui.pixel(1+x, 1+y, "#D030D0")
  42.     gui.pixel(6+x, 1+y, "#D030D0")
  43.     gui.line(x, 2+y, x, 5+y, "#D030D0")
  44.     gui.line(3+x, 2+y, 4+x, 2+y, "#D030D0")
  45.     gui.line(2+x, 3+y, 2+x, 4+y, "#D030D0")
  46.     gui.line(5+x, 3+y, 5+x, 4+y, "#D030D0")
  47.     gui.line(3+x, 5+y, 4+x, 5+y, "#D030D0")
  48.     gui.line(7+x, 2+y, 7+x, 5+y, "#D030D0")
  49.     gui.pixel(1+x, 6+y, "#D030D0")
  50.     gui.pixel(6+x, 6+y, "#D030D0")
  51.     gui.line(2+x, 7+y, 5+x, 7+y, "#D030D0")
  52. end
  53.  
  54. function DrawMissile(x, y)  -- displays a missile drop
  55.     gui.box(3+x, y, 4+x, 1+y, "#D030D0")
  56.     gui.box(3+x, 2+y, 4+x, 4+y, "#A0A0A0")
  57.     gui.line(2+x, 5+y, 5+x, 5+y, "#A0A0A0")
  58.     gui.box(1+x, 6+y, 6+x, 7+y, "#A0A0A0")
  59. end
  60.  
  61. function DrawSuper(x, y)    -- displays a super missile drop
  62.     gui.line(2+x, y, 5+x, y, "#30D030")
  63.     gui.line(1+x, 1+y, 6+x, 1+y, "#30D030")
  64.     gui.box(1+x, 2+y, 6+x, 4+y, "#A0A0A0")
  65.     gui.box(2+x, 5+y, 5+x, 6+y, "#A0A0A0")
  66.     gui.line(3+x, 7+y, 4+x, 7+y, "#A0A0A0")
  67. end
  68.  
  69. function DrawBomb(x, y)     -- displays a power bomb drop
  70.     gui.line(2+x, 1+y, 5+x, 1+y, "#A0A0A0")
  71.     gui.line(1+x, 2+y, 1+x, 5+y, "#A0A0A0")
  72.     gui.line(2+x, 2+y, 2+x, 5+y, "#D030D0")
  73.     gui.line(3+x, 2+y, 4+x, 2+y, "white")
  74.     gui.box(3+x, 3+y, 4+x, 4+y, "#A0A0A0")
  75.     gui.line(3+x, 5+y, 4+x, 5+y, "white")
  76.     gui.line(5+x, 2+y, 5+x, 5+y, "#D030D0")
  77.     gui.line(6+x, 2+y, 6+x, 5+y, "#A0A0A0")
  78.     gui.line(2+x, 6+y, 5+x, 6+y, "#A0A0A0")
  79. end
  80.  
  81. function DrawPause(x, y)        -- displays a pause sign
  82.     local color = "#000000A0"
  83.     if(pause) then
  84.         color = "#00FFFFFF"
  85.     end
  86.    
  87.     gui.box(  x, y-1, x+7, y+8, color)
  88.     gui.box(2+x, 1+y, 2+x, 6+y, "white")
  89.     gui.box(5+x, 1+y, 5+x, 6+y, "white")
  90. end
  91.  
  92. function DrawArrow(x, y)    -- displays an arrow
  93.     gui.line(10+x, 4+y, 16+x, 4+y, "red")
  94.     gui.line(9+x, 4+y, 12+x, 1+y, "red")
  95.     gui.line(9+x, 4+y, 12+x, 7+y, "red")
  96. end
  97.  
  98. function DrawMenu()
  99.     local x = 10
  100.     local y = 10
  101.    
  102.     DrawDrop(Small, x, y, (neededDrop == Small))
  103.     DrawDrop(Large, x+10, y, (neededDrop == Large))
  104.     DrawDrop(Missile, x+20, y, (neededDrop == Missile))
  105.     DrawDrop(Super, x+30, y, (neededDrop == Super))
  106.     DrawDrop(Bomb, x+40, y, (neededDrop == Bomb))
  107.     DrawPause(x+50, y)
  108. end
  109.  
  110. function PerformMenu(mouseX, mouseY)
  111.     local hit = false
  112.    
  113.     local x = 14
  114.     local y = 14
  115.    
  116.     local selectedDrop = None
  117.    
  118.     if math.abs(mouseX - x) < 4 and math.abs(mouseY - y) < 4 then
  119.         selectedDrop = Small
  120.         hit = true
  121.     end
  122.    
  123.     if math.abs(mouseX - (x + 10)) < 4 and math.abs(mouseY - y) < 4 then
  124.         selectedDrop = Large
  125.         hit = true
  126.     end
  127.    
  128.     if math.abs(mouseX - (x + 20)) < 4 and math.abs(mouseY - y) < 4 then
  129.         selectedDrop = Missile
  130.         hit = true
  131.     end
  132.    
  133.     if math.abs(mouseX - (x + 30)) < 4 and math.abs(mouseY - y) < 4 then
  134.         selectedDrop = Super
  135.         hit = true
  136.     end
  137.    
  138.     if math.abs(mouseX - (x + 40)) < 4 and math.abs(mouseY - y) < 4 then
  139.         selectedDrop = Bomb
  140.         hit = true
  141.     end
  142.    
  143.     --Pause
  144.     if math.abs(mouseX - (x + 50)) < 4 and math.abs(mouseY - y) < 4 then
  145.         pause = (pause == false)
  146.         hit = true
  147.     end
  148.    
  149.     if selectedDrop ~= None then
  150.         if neededDrop == selectedDrop then
  151.             neededDrop = None
  152.         else
  153.             neededDrop = selectedDrop
  154.         end
  155.     end
  156.    
  157.     return hit
  158. end
  159.  
  160. function DrawDrop(dropType, posX, posY, highlight)
  161.     local color = "#000000A0"
  162.     if(highlight) then
  163.         color = "#FFFF00FF"
  164.     end
  165.    
  166.     gui.box(posX, posY-1, posX+7, posY+8, color, color)
  167.     if dropType == Bomb then
  168.         DrawBomb(posX, posY)
  169.     elseif dropType == Super then
  170.         DrawSuper(posX, posY)
  171.     elseif dropType == Missile then
  172.         DrawMissile(posX, posY)
  173.     elseif dropType == Large then
  174.         DrawLarge(posX, posY)
  175.     elseif dropType == Small then
  176.         DrawSmall(posX, posY)
  177.     else
  178.         DrawNone(posX, posY)
  179.     end
  180. end
  181.  
  182. function GetDrop(enID, enProp, dropRN)
  183.  
  184.     -- get necessary values
  185.     local maxHealth = memory.readword(0x3001530)
  186.     local maxMissiles = memory.readbyte(0x3001532)
  187.     local maxSupers = memory.readbyte(0x3001534)
  188.     local maxBombs = memory.readbyte(0x3001535)
  189.    
  190.     local currHealth = memory.readword(0x3001536)
  191.     local currMissiles = memory.readbyte(0x3001538)
  192.     local currSupers = memory.readbyte(0x300153A)
  193.     local currBombs = memory.readbyte(0x300153B)
  194.     local fullHealth = (currHealth == maxHealth)
  195.    
  196.     -- get drop rates
  197.     local offset
  198.     if enProp < 0x80 then
  199.         offset = 0x82B0D70 + (enID * 18)
  200.     else
  201.         offset = 0x82B1BEC + (enID * 18)
  202.     end
  203.    
  204.     local cmpBomb = 1024 - memory.readword(offset + 8)
  205.     local cmpSuper = cmpBomb - memory.readword(offset + 6)
  206.     local cmpMissile = cmpSuper - memory.readword(offset + 4)
  207.     local cmpLarge = cmpMissile - memory.readword(offset + 2)
  208.     local cmpSmall = cmpLarge - memory.readword(offset)
  209.        
  210.     if dropRN > cmpBomb then
  211.         if maxBombs > currBombs then
  212.             return Bomb
  213.         elseif fullHealth == false then
  214.             return Large
  215.         elseif maxBombs == 0 then
  216.             return Small
  217.         else
  218.             return Bomb
  219.         end
  220.     elseif dropRN > cmpSuper then
  221.         if maxSupers > currSupers then
  222.             return Super
  223.         elseif fullHealth == false then
  224.             return Large
  225.         elseif maxSupers == 0 then
  226.             return Small
  227.         else
  228.             return Super
  229.         end
  230.     elseif dropRN > cmpMissile then
  231.         if maxMissiles > currMissiles then
  232.             return Missile
  233.         elseif fullHealth == false then
  234.             return Large
  235.         elseif maxMissiles == 0 then
  236.             return Small
  237.         else
  238.             return Missile
  239.         end
  240.     elseif dropRN > cmpLarge then
  241.         if fullHealth == false then
  242.             return Large
  243.         elseif maxMissiles > currMissiles then
  244.             return Missile
  245.         else
  246.             return Large
  247.         end
  248.     elseif dropRN > cmpSmall then
  249.         if fullHealth == false then
  250.             return Small
  251.         elseif maxMissiles > currMissiles then
  252.             return Missile
  253.         else
  254.             return Small
  255.         end
  256.     else
  257.         return None
  258.     end
  259. end
  260.  
  261. while true do
  262.  
  263.     -- get necessary values
  264.     local frame1 = (memory.readbyte(0x3000C77) + 1) % 256
  265.     local frame2 = (memory.readword(0x3000002) + 1) % 65536
  266.  
  267.     local cameraX, cameraY = memory.readword(0x30013B8), memory.readword(0x30013BA)
  268.    
  269.     --Check mouse status
  270.     local nowClick = input.get()["leftclick"]
  271.  
  272.     local mouseX
  273.     local mouseY
  274.     local clicked = (nowClick and prevClick ~= true)
  275.    
  276.     prevClick = nowClick
  277.    
  278.     if clicked then
  279.         mouseX = input.get()["xmouse"]
  280.         mouseY = input.get()["ymouse"]
  281.         if(PerformMenu(mouseX, mouseY)) then
  282.             clicked = false
  283.         end
  284.     end
  285.        
  286.        
  287.     --Display Enemy Info
  288.     for i=0,23 do
  289.         local status = memory.readbyte(0x30001AC + i*56)
  290.         local enID = memory.readbyte(0x30001C9 + i*56)
  291.         local enProp = memory.readbyte(0x30001DE + i*56)
  292.        
  293.         -- handle second part of metroids
  294.         local isMetroid = (enID == 26 and enProp >= 0x80)
  295.         if isMetroid then
  296.             enID = 101
  297.             enProp = 0
  298.         end
  299.        
  300.         local dropNone
  301.         if enProp < 0x80 then
  302.             dropNone = memory.readword(0x82B0D6E + (enID * 18))
  303.         else
  304.             dropNone = memory.readword(0x82B1BEA + (enID * 18))
  305.         end
  306.        
  307.         if status > 0 and dropNone < 0x400 then        
  308.             -- update enemy's past/current health
  309.             local pastHealth = enHealth[i+1]
  310.             local enemyHealth = memory.readword(0x30001C0 + i*56)
  311.             enHealth[i+1] = enemyHealth
  312.            
  313.             local enemyX, enemyY = memory.readword(0x30001B0 + i*56), memory.readword(0x30001AE + i*56)
  314.             local posX, posY = bit.arshift(enemyX - cameraX, 2), bit.arshift(enemyY - cameraY, 2)
  315.        
  316.             if isMetroid then
  317.                 posX = posX - 10
  318.             end
  319.            
  320.             --Select Enemy
  321.             if clicked and math.abs(mouseX - posX) < clickBoxSize and math.abs(mouseY - posY) < clickBoxSize then
  322.                 if chosenEnemyIndex == i then
  323.                     chosenEnemyIndex = -1
  324.                 else
  325.                     chosenEnemyIndex = i
  326.                 end
  327.             end
  328.            
  329.             --draw enemy highlight
  330.             if chosenEnemyIndex == i then
  331.                 DrawHighlight(posX, posY)
  332.             end
  333.            
  334.             --draw enemy modPos
  335.             if not isMetroid then
  336.                 gui.text(posX, posY+8, (enemyX + enemyY) % 32, "#E04040")      
  337.             end
  338.            
  339.             --Calculate drop RNG and draw drop
  340.             local enRN = rns[((frame1 + bit.rshift(frame2, 4) + i + enemyX + enemyY) % 32) + 1]
  341.             local dropRN = (frame1 + frame2 + enRN*256) % 1024
  342.             if dropRN == 0 then
  343.                 dropRN = 1
  344.             end
  345.            
  346.             DrawDrop(GetDrop(enID, enProp, dropRN), posX, posY)
  347.            
  348.             -- draw arrow to indicate drop
  349.             if pastHealth ~= enemyHealth and enemyHealth == 0 then
  350.                 DrawArrow(posX, posY)
  351.             end
  352.            
  353.             --Find viable position for chosen enemy and droptype
  354.             if(i == chosenEnemyIndex) then
  355.            
  356.                 acceptedRNs = {}
  357.  
  358.                 local modVal = ((frame1 + bit.rshift(frame2, 4) + chosenEnemyIndex) % 32) + 1
  359.                    
  360.                 --Find indexes in rn list that would yield desired result
  361.                 for i=1,#rns do
  362.                     local dropRN = (frame1 + frame2 + rns[i]*256) % 1024
  363.                     if dropRN == 0 then
  364.                         dropRN = 1 
  365.                     end
  366.                                
  367.                     if GetDrop(enID, enProp, dropRN) == neededDrop then
  368.                         table.insert(acceptedRNs, (i - modVal) % 32)
  369.                     end
  370.                 end
  371.  
  372.                 --Figure out and print required modPos for viable index to occur
  373.                 if(#acceptedRNs > 0) then
  374.                     local concatString = ""
  375.                    
  376.                     local count = 0
  377.                     table.sort(acceptedRNs)
  378.                     for key, val in ipairs(acceptedRNs) do
  379.                         concatString = concatString .. val .. " "
  380.                         count = count + 1
  381.                         if(count > 7) then
  382.                             concatString = concatString .. "\n"
  383.                             count = 0
  384.                         end
  385.                     end
  386.                    
  387.                     gui.text(posX, posY+16, concatString, "#40E040")
  388.                    
  389.                     if(pause == true) then
  390.                         vba.pause()
  391.                     end
  392.                 end
  393.             end
  394.         end
  395.     end
  396.    
  397.     DrawMenu();
  398.    
  399.     vba.frameadvance()
  400. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement