jboondock

AC Overtake Mode

Jun 30th, 2022 (edited)
1,293
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local requiredSpeed = 95
  2. local PBlink = 'http' .. 's://www.myinstants.com/media/sounds/holy-shit.mp3'
  3. local collideLink = 'http' .. 's://www.myinstants.com/media/sounds/classic_hurt.mp3'
  4.  
  5. local killingSpree = 'http' ..
  6.     's://cdn.discordapp.com/attachments/140183723348852736/1001011172641878016/killingSpree.mp3'
  7.  
  8. local killingFrenzy = 'http' ..
  9.     's://cdn.discordapp.com/attachments/140183723348852736/1001011172335702096/KillingFrenzy.mp3'
  10.  
  11. local runningRiot = 'http' .. 's://cdn.discordapp.com/attachments/140183723348852736/1001011170272100352/RunningRiot.mp3'
  12. local rampage = 'http' .. 's://cdn.discordapp.com/attachments/140183723348852736/1001011169944932453/Rampage.mp3'
  13. local untouchable = 'http' .. 's://cdn.discordapp.com/attachments/140183723348852736/1001011170959954060/untouchable.mp3'
  14. local invincible = 'http' .. 's://cdn.discordapp.com/attachments/140183723348852736/1001011171974983710/invincible.mp3'
  15. local inconcievable = 'http' ..
  16.     's://cdn.discordapp.com/attachments/140183723348852736/1001011171236782160/inconceivable.mp3'
  17. local unfriggenbelievable = 'http' ..
  18.     's://cdn.discordapp.com/attachments/140183723348852736/1001011170574094376/unfriggenbelievable.mp3'
  19.  
  20.  
  21. local noti = 'http' .. 's://cdn.discordapp.com/attachments/140183723348852736/1000988999877394512/pog_noti_sound.mp3'
  22. local mediaPlayer = ui.MediaPlayer()
  23. local mediaPlayer2 = ui.MediaPlayer()
  24. local mediaPlayer3 = ui.MediaPlayer()
  25.  
  26. local hasPlayedSpree = false
  27. local hasPlayedFrenzy = false
  28. local hasPlayedRiot = false
  29. local hasPlayedRampage = false
  30. local hasPlayedUntouchable = false
  31. local hasPlayedInvincible = false
  32. local hasPlayedInconcievable = false
  33. local hasPlayedUnfriggenbelievable = false
  34.  
  35.  
  36. function script.prepare(dt)
  37.     return ac.getCarState(1).speedKmh > 60
  38. end
  39.  
  40. local timePassed = 0
  41. local speedMessageTimer = 0
  42. local mackMessageTimer = 0
  43. local totalScore = 0
  44. local comboMeter = 1
  45. local comboColor = 0
  46. local dangerouslySlowTimer = 0
  47. local carsState = {}
  48. local wheelsWarningTimeout = 0
  49. local personalBest = 0
  50. local MackMessages = { 'MAAAACK!!!!', 'M A C K S A U C E', 'You Hesitated....', 'bRUH', 'No Shot...',
  51.     'Ain\'t no way you were makin that.' }
  52. local CloseMessages = { 'IN THAT!!!!! 3x', 'IN THERE. 3x', 'D I V E 3x', 'SKRRT!!! 3x' }
  53.  
  54. local muteToggle = true
  55. local lastMuteKeyState = false
  56. local messageState = false
  57. function script.update(dt)
  58.     local muteKeyState = ac.isKeyDown(ac.KeyIndex.M)
  59.     if muteKeyState and lastMuteKeyState ~= muteKeyState then
  60.         muteToggle = not muteToggle
  61.         if messageState then
  62.             addMessage('Sounds on', -1)
  63.             messageState = false
  64.         else
  65.             addMessage('Sounds off', -1)
  66.             messageState = true
  67.         end
  68.  
  69.         lastMuteKeyState = muteKeyState
  70.     elseif not muteKeyState then
  71.         lastMuteKeyState = false
  72.  
  73.     end
  74.  
  75.  
  76.     if timePassed == 0 then
  77.         addMessage(ac.getCarName(0), 0)
  78.         addMessage('Made by Boon', 2)
  79.         addMessage('CTRL + D to toggle UI', -1)
  80.         addMessage('M to toggle sounds', -1)
  81.         addMessage('Delete to re-orient car', -1)
  82.     end
  83.  
  84.  
  85.  
  86.  
  87.     local player = ac.getCarState(1)
  88.     if player.engineLifeLeft < 1 then
  89.         ac.console('Overtake score: ' .. totalScore)
  90.         return
  91.     end
  92.  
  93.     local playerPos = player.position
  94.     local playerDir = ac.getCameraForward()
  95.     if ac.isKeyDown(ac.KeyIndex.Delete) and player.speedKmh < 15 then
  96.         physics.setCarPosition(0, playerPos, playerDir)
  97.  
  98.     end
  99.  
  100.     timePassed = timePassed + dt
  101.     speedMessageTimer = speedMessageTimer + dt
  102.     mackMessageTimer = mackMessageTimer + dt
  103.  
  104.  
  105.  
  106.     local comboFadingRate = 0.5 * math.lerp(1, 0.1, math.lerpInvSat(player.speedKmh, 80, 200)) + player.wheelsOutside
  107.     comboMeter = math.max(1, comboMeter - dt * comboFadingRate)
  108.  
  109.     local sim = ac.getSim()
  110.     while sim.carsCount > #carsState do
  111.         carsState[#carsState + 1] = {}
  112.     end
  113.  
  114.     if wheelsWarningTimeout > 0 then
  115.         wheelsWarningTimeout = wheelsWarningTimeout - dt
  116.     elseif player.wheelsOutside > 0 then
  117.         if wheelsWarningTimeout == 0 then
  118.         end
  119.         addMessage('Car is Out Of Zone', -1)
  120.         wheelsWarningTimeout = 60
  121.     end
  122.  
  123.     if player.speedKmh < requiredSpeed then
  124.  
  125.         if dangerouslySlowTimer > 3 then
  126.             ac.console('Overtake score: ' .. totalScore)
  127.             comboMeter = 1
  128.             totalScore = 0
  129.  
  130.             hasPlayedSpree = false
  131.             hasPlayedFrenzy = false
  132.             hasPlayedRiot = false
  133.             hasPlayedRampage = false
  134.             hasPlayedUntouchable = false
  135.             hasPlayedInvincible = false
  136.             hasPlayedInconcievable = false
  137.             hasPlayedUnfriggenbelievable = false
  138.             -- if totalScore > personalBest then
  139.             --     personalBest = totalScore
  140.             --     ac.sendChatMessage('just scored a ' .. personalBest)
  141.             -- end
  142.         else
  143.             if dangerouslySlowTimer < 3 then
  144.                 if speedMessageTimer > 5 and not timePassed == 0 then
  145.                     addMessage('3 Seconds until score reset!', -1)
  146.                     speedMessageTimer = 0
  147.                 end
  148.             end
  149.  
  150.             if dangerouslySlowTimer == 0 and not timePassed == 0 then
  151.                 addMessage('Speed up!', -1)
  152.             end
  153.  
  154.         end
  155.         dangerouslySlowTimer = dangerouslySlowTimer + dt
  156.         comboMeter = 1
  157.         if totalScore > personalBest and dangerouslySlowTimer > 3 then
  158.             personalBest = totalScore
  159.             if muteToggle then
  160.                 mediaPlayer:setSource(PBlink)
  161.                 mediaPlayer:setVolume(.25)
  162.                 mediaPlayer:play()
  163.             else
  164.                 mediaPlayer:setSource(PBlink)
  165.                 mediaPlayer:setVolume(0)
  166.                 mediaPlayer:pause()
  167.             end
  168.  
  169.             ac.sendChatMessage('just scored a ' .. personalBest)
  170.         end
  171.  
  172.         return
  173.     else
  174.         dangerouslySlowTimer = 0
  175.     end
  176.  
  177.     if player.collidedWith == 0 then
  178.  
  179.         if totalScore >= personalBest then
  180.             personalBest = totalScore
  181.             if muteToggle then
  182.                 mediaPlayer:setSource(PBlink)
  183.                 mediaPlayer:setVolume(.25)
  184.                 mediaPlayer:play()
  185.             else
  186.                 mediaPlayer:setSource(PBlink)
  187.                 mediaPlayer:setVolume(0)
  188.                 mediaPlayer:pause()
  189.             end
  190.             ac.sendChatMessage('just scored a ' .. personalBest)
  191.         end
  192.         comboMeter = 1
  193.         totalScore = 0
  194.  
  195.         hasPlayedSpree = false
  196.         hasPlayedFrenzy = false
  197.         hasPlayedRiot = false
  198.         hasPlayedRampage = false
  199.         hasPlayedUntouchable = false
  200.         hasPlayedInvincible = false
  201.         hasPlayedInconcievable = false
  202.         hasPlayedUnfriggenbelievable = false
  203.  
  204.         if mackMessageTimer > 1 then
  205.             if muteToggle then
  206.                 mediaPlayer2:setSource(collideLink)
  207.                 mediaPlayer2:setVolume(1)
  208.                 mediaPlayer2:play()
  209.             else
  210.                 mediaPlayer:setSource(collideLink)
  211.                 mediaPlayer:setVolume(0)
  212.                 mediaPlayer:pause()
  213.             end
  214.  
  215.             addMessage(MackMessages[math.random(1, #MackMessages)], -1)
  216.             mackMessageTimer = 0
  217.  
  218.         end
  219.     end
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.     if comboMeter >= 25 then
  227.  
  228.         if muteToggle then
  229.             if not hasPlayedSpree then
  230.                 mediaPlayer2:setSource(killingSpree)
  231.                 mediaPlayer2:setVolume(.25)
  232.                 mediaPlayer2:play()
  233.                 hasPlayedSpree = true
  234.             end
  235.         else
  236.             mediaPlayer2:setVolume(0)
  237.             mediaPlayer2:pause()
  238.         end
  239.     end
  240.  
  241.     if comboMeter >= 50 and comboMeter <= 51 then
  242.         if not hasPlayedFrenzy then
  243.             if muteToggle then
  244.                 mediaPlayer2:setSource(killingFrenzy)
  245.                 mediaPlayer2:setVolume(.25)
  246.                 mediaPlayer2:play()
  247.                 hasPlayedFrenzy = true
  248.             else
  249.                 mediaPlayer2:setVolume(0)
  250.                 mediaPlayer2:pause()
  251.             end
  252.         end
  253.     end
  254.  
  255.     if comboMeter >= 75 and comboMeter <= 76 then
  256.         if not hasPlayedRiot then
  257.             if muteToggle then
  258.                 mediaPlayer2:setSource(runningRiot)
  259.                 mediaPlayer2:setVolume(.25)
  260.                 mediaPlayer2:play()
  261.                 hasPlayedRiot = true
  262.             else
  263.                 mediaPlayer2:setVolume(0)
  264.                 mediaPlayer2:pause()
  265.             end
  266.         end
  267.     end
  268.  
  269.     if comboMeter >= 100 and comboMeter <= 101 then
  270.         if not hasPlayedRampage then
  271.             if muteToggle then
  272.                 mediaPlayer2:setSource(rampage)
  273.                 mediaPlayer2:setVolume(.25)
  274.                 mediaPlayer2:play()
  275.                 hasPlayedRampage = true
  276.             else
  277.                 mediaPlayer2:setVolume(0)
  278.                 mediaPlayer2:pause()
  279.             end
  280.         end
  281.     end
  282.  
  283.     if comboMeter >= 150 and comboMeter <= 151 then
  284.         if not hasPlayedUntouchable then
  285.             if muteToggle then
  286.                 mediaPlayer2:setSource(untouchable)
  287.                 mediaPlayer2:setVolume(.25)
  288.                 mediaPlayer2:play()
  289.                 hasPlayedUntouchable = true
  290.             else
  291.                 mediaPlayer2:setVolume(0)
  292.                 mediaPlayer2:pause()
  293.             end
  294.         end
  295.     end
  296.  
  297.     if comboMeter >= 200 and comboMeter <= 201 then
  298.         if not hasPlayedInvincible then
  299.             if muteToggle then
  300.                 mediaPlayer2:setSource(invincible)
  301.                 mediaPlayer2:setVolume(.25)
  302.                 mediaPlayer2:play()
  303.                 hasPlayedInvincible = true
  304.             else
  305.                 mediaPlayer2:setVolume(0)
  306.                 mediaPlayer2:pause()
  307.             end
  308.         end
  309.     end
  310.  
  311.     if comboMeter >= 250 and comboMeter <= 251 then
  312.         if not hasPlayedInconcievable then
  313.             if muteToggle then
  314.                 mediaPlayer2:setSource(inconcievable)
  315.                 mediaPlayer2:setVolume(.25)
  316.                 mediaPlayer2:play()
  317.                 hasPlayedInconcievable = true
  318.             else
  319.                 mediaPlayer2:setVolume(0)
  320.                 mediaPlayer2:pause()
  321.             end
  322.         end
  323.     end
  324.  
  325.     if comboMeter >= 300 and comboMeter <= 301 then
  326.         if not hasPlayedUnfriggenbelievable then
  327.             if muteToggle then
  328.                 mediaPlayer2:setSource(unfriggenbelievable)
  329.                 mediaPlayer2:setVolume(.25)
  330.                 mediaPlayer2:play()
  331.                 hasPlayedUnfriggenbelievable = true
  332.             else
  333.                 mediaPlayer2:setVolume(0)
  334.                 mediaPlayer2:pause()
  335.             end
  336.         end
  337.     end
  338.  
  339.  
  340.  
  341.  
  342.  
  343.  
  344.  
  345.     -- local car = ac.getCarState(1)
  346.     -- if car.pos:closerToThan(player.pos,2.5) then
  347.  
  348.     -- end
  349.  
  350.     for i = 2, ac.getSim().carsCount do
  351.         local car = ac.getCarState(i)
  352.         local state = carsState[i]
  353.  
  354.  
  355.         -- ac.debug(car.collidedWith .. " COLLISION")
  356.  
  357.         if car.position:closerToThan(player.position, 7) then
  358.             local drivingAlong = math.dot(car.look, player.look) > 0.2
  359.             if not drivingAlong then
  360.                 state.drivingAlong = false
  361.  
  362.                 if not state.nearMiss and car.position:closerToThan(player.position, 3) then
  363.                     state.nearMiss = true
  364.  
  365.  
  366.                 end
  367.             end
  368.  
  369.             -- if car.collidedWith == 0 and not state.collided then
  370.             --     comboMeter = 1
  371.             --     totalScore = 0
  372.             --     addMessage('WEINER!!!', 1)
  373.             --     state.collided = true
  374.             -- end
  375.  
  376.             if not state.overtaken and not state.collided and state.drivingAlong then
  377.                 local posDir = (car.position - player.position):normalize()
  378.                 local posDot = math.dot(posDir, car.look)
  379.                 state.maxPosDot = math.max(state.maxPosDot, posDot)
  380.                 if posDot < -0.5 and state.maxPosDot > 0.5 then
  381.                     totalScore = totalScore + math.ceil(10 * comboMeter)
  382.                     comboMeter = comboMeter + 1
  383.                     comboColor = comboColor + 90
  384.                     if muteToggle then
  385.                         mediaPlayer3:setSource(noti)
  386.                         mediaPlayer3:setVolume(1)
  387.                         mediaPlayer3:play()
  388.                     else
  389.                         mediaPlayer3:setSource(noti)
  390.                         mediaPlayer3:setVolume(0)
  391.                         mediaPlayer3:pause()
  392.                     end
  393.  
  394.                     addMessage('Overtake 1x', comboMeter > 50 and 1 or 0)
  395.                     state.overtaken = true
  396.  
  397.                     if car.position:closerToThan(player.position, 3) then
  398.                         comboMeter = comboMeter + 3
  399.                         comboColor = comboColor + math.random(1, 90)
  400.                         comboColor = comboColor + 90
  401.                         if muteToggle then
  402.                             mediaPlayer3:setSource(noti)
  403.                             mediaPlayer3:setVolume(1)
  404.                             mediaPlayer3:play()
  405.                         else
  406.                             mediaPlayer3:setSource(noti)
  407.                             mediaPlayer3:setVolume(0)
  408.                             mediaPlayer3:pause()
  409.                         end
  410.  
  411.                         addMessage(CloseMessages[math.random(#CloseMessages)], 2)
  412.                     end
  413.  
  414.                 end
  415.             end
  416.  
  417.         else
  418.             state.maxPosDot = -1
  419.             state.overtaken = false
  420.             state.collided = false
  421.             state.drivingAlong = true
  422.             state.nearMiss = false
  423.         end
  424.     end
  425. end
  426.  
  427. local messages = {}
  428. local glitter = {}
  429. local glitterCount = 0
  430.  
  431. function addMessage(text, mood)
  432.     for i = math.min(#messages + 1, 4), 2, -1 do
  433.         messages[i] = messages[i - 1]
  434.         messages[i].targetPos = i
  435.     end
  436.     messages[1] = { text = text, age = 0, targetPos = 1, currentPos = 1, mood = mood }
  437.     if mood == 1 then
  438.         for i = 1, 60 do
  439.             local dir = vec2(math.random() - 0.5, math.random() - 0.5)
  440.             glitterCount = glitterCount + 1
  441.             glitter[glitterCount] = {
  442.                 color = rgbm.new(hsv(math.random() * 360, 1, 1):rgb(), 1),
  443.                 pos = vec2(80, 140) + dir * vec2(40, 20),
  444.                 velocity = dir:normalize():scale(0.2 + math.random()),
  445.                 life = 0.5 + 0.5 * math.random()
  446.             }
  447.         end
  448.     end
  449. end
  450.  
  451. local function updateMessages(dt)
  452.     comboColor = comboColor + dt * 10 * comboMeter
  453.     if comboColor > 360 then comboColor = comboColor - 360 end
  454.     for i = 1, #messages do
  455.         local m = messages[i]
  456.         m.age = m.age + dt
  457.         m.currentPos = math.applyLag(m.currentPos, m.targetPos, 0.8, dt)
  458.     end
  459.     for i = glitterCount, 1, -1 do
  460.         local g = glitter[i]
  461.         g.pos:add(g.velocity)
  462.         g.velocity.y = g.velocity.y + 0.02
  463.         g.life = g.life - dt
  464.         g.color.mult = math.saturate(g.life * 4)
  465.         if g.life < 0 then
  466.             if i < glitterCount then
  467.                 glitter[i] = glitter[glitterCount]
  468.             end
  469.             glitterCount = glitterCount - 1
  470.         end
  471.     end
  472.     if comboMeter > 10 and math.random() > 0.98 then
  473.         for i = 1, math.floor(comboMeter) do
  474.             local dir = vec2(math.random() - 0.5, math.random() - 0.5)
  475.             glitterCount = glitterCount + 1
  476.             glitter[glitterCount] = {
  477.                 color = rgbm.new(hsv(math.random() * 360, 1, 1):rgb(), 1),
  478.                 pos = vec2(195, 75) + dir * vec2(40, 20),
  479.                 velocity = dir:normalize():scale(0.2 + math.random()),
  480.                 life = 0.5 + 0.5 * math.random()
  481.             }
  482.         end
  483.     end
  484. end
  485.  
  486. local speedWarning = 0
  487. local UIToggle = true
  488. local LastKeyState = false
  489. function script.drawUI()
  490.     local keyState = ac.isKeyDown(ac.KeyIndex.Control) and ac.isKeyDown(ac.KeyIndex.D)
  491.     if keyState and LastKeyState ~= keyState then
  492.         UIToggle = not UIToggle
  493.         LastKeyState = keyState
  494.     elseif not keyState then
  495.         LastKeyState = false
  496.     end
  497.     if UIToggle then
  498.         local uiState = ac.getUiState()
  499.         updateMessages(uiState.dt)
  500.  
  501.         local speedRelative = math.saturate(math.floor(ac.getCarState(1).speedKmh) / requiredSpeed)
  502.         speedWarning = math.applyLag(speedWarning, speedRelative < 1 and 1 or 0, 0.5, uiState.dt)
  503.  
  504.         local colorDark = rgbm(0.4, 0.4, 0.4, 1)
  505.         local colorGrey = rgbm(0.7, 0.7, 0.7, 1)
  506.         local colorAccent = rgbm.new(hsv(speedRelative * 120, 1, 1):rgb(), 1)
  507.         local colorCombo = rgbm.new(hsv(comboColor, math.saturate(comboMeter / 10), 1):rgb(),
  508.             math.saturate(comboMeter / 4))
  509.  
  510.         local function speedMeter(ref)
  511.             ui.drawRectFilled(ref + vec2(0, -4), ref + vec2(180, 5), colorDark, 1)
  512.             ui.drawLine(ref + vec2(0, -4), ref + vec2(0, 4), colorGrey, 1)
  513.             ui.drawLine(ref + vec2(requiredSpeed, -4), ref + vec2(requiredSpeed, 4), colorGrey, 1)
  514.  
  515.             local speed = math.min(ac.getCarState(1).speedKmh, 180)
  516.             if speed > 1 then
  517.                 ui.drawLine(ref + vec2(0, 0), ref + vec2(speed, 0), colorAccent, 4)
  518.             end
  519.         end
  520.  
  521.         ui.beginTransparentWindow('overtakeScore', vec2(uiState.windowSize.x * 0.5 - 600, 100), vec2(1400, 1400), true)
  522.         ui.beginOutline()
  523.  
  524.         ui.pushStyleVar(ui.StyleVar.Alpha, 1 - speedWarning)
  525.         ui.pushFont(ui.Font.Title)
  526.         ui.text('Shmoovin\'')
  527.         -- ui.sameLine(0, 20)
  528.         ui.pushFont(ui.Font.Huge)
  529.         ui.textColored('PB:' .. personalBest .. ' pts', colorCombo)
  530.         ui.popFont()
  531.         ui.popStyleVar()
  532.  
  533.         ui.pushFont(ui.Font.Huge)
  534.         ui.text(totalScore .. ' pts')
  535.         ui.sameLine(0, 40)
  536.         ui.beginRotation()
  537.         ui.textColored(math.ceil(comboMeter * 10) / 10 .. 'x', colorCombo)
  538.         if comboMeter > 20 then
  539.             ui.endRotation(math.sin(comboMeter / 180 * 3141.5) * 3 * math.lerpInvSat(comboMeter, 20, 30) + 90)
  540.         end
  541.         if comboMeter > 50 then
  542.             ui.endRotation(math.sin(comboMeter / 220 * 3141.5) * 3 * math.lerpInvSat(comboMeter, 20, 30) + 90)
  543.         end
  544.         if comboMeter > 100 then
  545.             ui.endRotation(math.sin(comboMeter / 260 * 3141.5) * 3 * math.lerpInvSat(comboMeter, 20, 30) + 90)
  546.         end
  547.         if comboMeter > 250 then
  548.             ui.endRotation(math.sin(comboMeter / 360 * 3141.5) * 3 * math.lerpInvSat(comboMeter, 20, 30) + 90)
  549.         end
  550.  
  551.         ui.popFont()
  552.         ui.endOutline(rgbm(0, 0, 0, 0.3))
  553.  
  554.         ui.offsetCursorY(20)
  555.         ui.pushFont(ui.Font.Title)
  556.         local startPos = ui.getCursor()
  557.         for i = 1, #messages do
  558.             local m = messages[i]
  559.             local f = math.saturate(4 - m.currentPos) * math.saturate(8 - m.age)
  560.             ui.setCursor(startPos + vec2(20 + math.saturate(1 - m.age * 10) ^ 2 * 100, (m.currentPos - 1) * 30))
  561.             ui.textColored(m.text, m.mood == 1 and rgbm(0, 1, 0, f)
  562.                 or m.mood == -1 and rgbm(1, 0, 0, f) or m.mood == 2 and rgbm(100, 84, 0, f) or rgbm(1, 1, 1, f))
  563.         end
  564.         for i = 1, glitterCount do
  565.             local g = glitter[i]
  566.             if g ~= nil then
  567.                 ui.drawLine(g.pos, g.pos + g.velocity * 4, g.color, 2)
  568.             end
  569.         end
  570.         ui.popFont()
  571.         ui.setCursor(startPos + vec2(0, 4 * 30))
  572.  
  573.         ui.pushStyleVar(ui.StyleVar.Alpha, speedWarning)
  574.         ui.setCursorY(0)
  575.         ui.pushFont(ui.Font.Main)
  576.         ui.textColored('Keep speed above ' .. requiredSpeed .. ' km/h:', colorAccent)
  577.         speedMeter(ui.getCursor() + vec2(-9, 4))
  578.         ui.popFont()
  579.         ui.popStyleVar()
  580.  
  581.         ui.endTransparentWindow()
  582.     else
  583.         ui.text('')
  584.  
  585.     end
  586.  
  587.  
  588.  
  589. end
  590.  
RAW Paste Data Copied