--[[
.----------------.  .----------------.  .-----------------. .----------------.  .----------------.  .----------------. 
| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. |
| |  ____  ____  | || |  _________   | || | ____  _____  | || |  _________   | || |      __      | || |     _____    | |
| | |_   ||   _| | || | |_   ___  |  | || ||_   \|_   _| | || | |  _   _  |  | || |     /  \     | || |    |_   _|   | |
| |   | |__| |   | || |   | |_  \_|  | || |  |   \ | |   | || | |_/ | | \_|  | || |    / /\ \    | || |      | |     | |
| |   |  __  |   | || |   |  _|  _   | || |  | |\ \| |   | || |     | |      | || |   / ____ \   | || |      | |     | |
| |  _| |  | |_  | || |  _| |___/ |  | || | _| |_\   |_  | || |    _| |_     | || | _/ /    \ \_ | || |     _| |_    | |
| | |____||____| | || | |_________|  | || ||_____|\____| | || |   |_____|    | || ||____|  |____|| || |    |_____|   | |
| |              | || |              | || |              | || |              | || |              | || |              | |
| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' |
'----------------'  '----------------'  '----------------'  '----------------'  '----------------'  '----------------' 

.----------------.  .-----------------. .-----------------. .----------------.  .----------------.
| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. |
| |      __      | || | ____  _____  | || | ____  _____  | || |     _____    | || |  _________   | |
| |     /  \     | || ||_   \|_   _| | || ||_   \|_   _| | || |    |_   _|   | || | |_   ___  |  | |
| |    / /\ \    | || |  |   \ | |   | || |  |   \ | |   | || |      | |     | || |   | |_  \_|  | |
| |   / ____ \   | || |  | |\ \| |   | || |  | |\ \| |   | || |      | |     | || |   |  _|  _   | |
| | _/ /    \ \_ | || | _| |_\   |_  | || | _| |_\   |_  | || |     _| |_    | || |  _| |___/ |  | |
| ||____|  |____|| || ||_____|\____| | || ||_____|\____| | || |    |_____|   | || | |_________|  | |
| |              | || |              | || |              | || |              | || |              | |
| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' |
'----------------'  '----------------'  '----------------'  '----------------'  '----------------'      
--]]
--ver. 1.22

if myHero.charName ~= "Annie" then return end

require "VPrediction"
local VP = VPrediction()
local version = "1.22"
local LocalVersion = 1.22
local scriptname = "Hentai Annie"
local developer = "remembermyhentai"
local contact = "skype xd_kikass"
local RREADY = false
local TibbersPartyHard = false
local Tibbers = nil
local lastAA = 0
local lastWnd = 64
local RECALLING = false
local REGEN = false
local POTS = {"ItemCrystalFlask", "RegenerationPotion", "ItemMiniRegenPotion", "ItemCrystalFlaskJungle", "ItemDarkCrystalFlask"}
local ATTACKITEMS = {"ItemWillBoltSpellBase"}
local BOLT, BOLTSLOT
local VARS = {
  W = {RANGE = 625, ANGLE = 50, SPEED = math.huge, DELAY = 0.2},
  R = {RANGE = 600, RADIUS = 225, DELAY = 0.3, SPEED = math.huge}
}

local PussyOut = 
{
["KatarinaR"] = true,
["AlZaharNetherGrasp"] = true,
["TwistedFateR"] = true,
["VelkozR"] = true,
["InfiniteDuress"] = true,
["JhinR"] = true,
["CaitlynAceintheHole"] = true,
["UrgotSwap2"] = true,
["LucianR"] = true,
["GalioIdolOfDurand"] = true,
["MissFortuneBulletTime"] = true,
["XerathLocusPulse"] = true
}

function OnLoad()
	dts = TargetSelector(TARGET_LESS_CAST, 625, DAMAGE_MAGIC)
	rts = TargetSelector(TARGET_LESS_CAST, 850, DAMAGE_MAGIC)
	tts = TargetSelector(TARGET_LESS_CAST, 1500, DAMAGE_MAGIC)
	tts1 = TargetSelector(TARGET_CLOSEST, 1500, DAMAGE_MAGIC)

	KatarinaUpdate(
    Version,
    'raw.githubusercontent.com', 
    '/remembermyhentai/BoL/master/Annie/HentaiAnnie.version',
    '/remembermyhentai/BoL/master/Annie/HentaiAnnie.lua', 
    SCRIPT_PATH.._ENV.FILE_NAME, 
    function() PrintChat('<font color = \"#B13070\">[HENTAI ANNIE]</font> <font color = \"#4DFF4D\">SCRIPT UPDATED. RESTART BOL (2xF9)</font>') end, 
    function() PrintChat('<font color = \"#B13070\">[HENTAI ANNIE]</font> <font color = \"#4DFF4D\">LOADED VERSION //</font>'..version) end, 
    function() PrintChat(Menu.update and '<font color = \"#B13070\">[HENTAI ANNIE]</font> <font color = \"#4DFF4D\">NEW VERSION, WAIT...</font>' or
     '<font color = \"#B13070\">[HENTAI ANNIE]</font> <font color = \"#4DFF4D\">NEW VERSION, DOWNLOAD IT MANUALLY FROM FORUM</font>') end, 
    function() PrintChat('<font color = \"#B13070\">[HENTAI ANNIE]</font> <font color = \"#4DFF4D\">UPDATE ERROR, DOWNLOAD IT MANUALLY FROM FORUM</font>') end)

	AddApplyBuffCallback(function(unit, target, buff) ApplyBuff(unit, target, buff) end)
	AddUpdateBuffCallback(function(unit, buff, stacks) UpdateBuff(unit, buff, stacks) end)
	AddRemoveBuffCallback(function(unit, buff) RemoveBuff(unit, buff) end)
	AddCreateObjCallback(TibbersLogic)
	AddDeleteObjCallback(haveYouSeenMyTibbersDelete)
	AddApplyBuffCallback(Buff_Add)
	AddRemoveBuffCallback(Buff_Rem)

	spellData = 
	{
	  [_Q] = {mana = function () return 55 + 5*myHero:GetSpellData(_Q).level end},
	  [_W] = {mana = function () return 60 + 10*myHero:GetSpellData(_W).level end},
	  [_E] = {mana = 20},
	  [_R] = {mana = 100},
	}

	Menu = scriptConfig("[Hentai Annie]", "HentaiAnnie")
	Menu:addSubMenu("[Key Binds]", "Key")
	Menu.Key:addParam("lasthit", "Lasthit", SCRIPT_PARAM_ONKEYDOWN, false, string.byte("X"))
	Menu.Key:addParam("combo", "Combo", SCRIPT_PARAM_ONKEYDOWN, false, string.byte(" "))
	Menu.Key:addParam("harras", "Harras", SCRIPT_PARAM_ONKEYDOWN, false, string.byte("C"))
	Menu.Key:addParam("burst", "Burst", SCRIPT_PARAM_ONKEYDOWN, false, string.byte("Z"))
	Menu.Key:addParam("laneclear", "Laneclear", SCRIPT_PARAM_ONKEYDOWN, false, string.byte("V"))
	Menu.Key:addParam("lasthitQstacks", "Dont farm if stun is up", SCRIPT_PARAM_ONKEYTOGGLE, true, string.byte("T"))
	Menu.Key:addParam("AutoHarras", "Auto Harras", SCRIPT_PARAM_ONKEYTOGGLE, false, string.byte("N"))
	Menu.Key:addParam("AutoFarm", "Auto Farm with Q", SCRIPT_PARAM_ONKEYTOGGLE, false, string.byte("M"))

	Menu:addSubMenu("[Combo]", "Combo")
	Menu.Combo:addParam("useGLP", "Use GLP-800", SCRIPT_PARAM_ONOFF, true)
	Menu.Combo:addParam("comboRmax", "Use R at max range", SCRIPT_PARAM_ONOFF, true)
	Menu.Combo:addParam("comboRstun", "Use R only if Stun is up", SCRIPT_PARAM_ONOFF, false)
	Menu.Combo:addParam("HitChance", "R HitChance", SCRIPT_PARAM_SLICE, 2, 1, 5, 0)

	Menu:addSubMenu("[Harras]", "Harras")
	Menu.Harras:addParam("useQ", "Use Q for harras", SCRIPT_PARAM_ONOFF, true)
	Menu.Harras:addParam("useW", "Use W for harras", SCRIPT_PARAM_ONOFF, true)

	Menu:addSubMenu("[Burst]", "Burst")
	Menu.Burst:addParam("flashburst", "Use Flash in burst", SCRIPT_PARAM_ONOFF, true)

	Menu:addSubMenu("[Farm]", "Farm")
	Menu.Farm:addSubMenu("[Lasthit]", "lasthit")
	Menu.Farm.lasthit:addParam("lasthitQ", "Use Q for lasthit", SCRIPT_PARAM_ONOFF, true)
	Menu.Farm:addSubMenu("[Laneclear]", "laneclear")
	Menu.Farm.laneclear:addParam("laneclearQ", "Use Q for laneclear", SCRIPT_PARAM_ONOFF, true)

	Menu:addSubMenu("[Move]", "Move")
	Menu.Move:addParam("MoveLasthit", "Move to mouse in Lasthit mode", SCRIPT_PARAM_ONOFF, false)
	Menu.Move:addParam("MoveCombo", "Move to mouse in Combo mode", SCRIPT_PARAM_ONOFF, false)
	Menu.Move:addParam("MoveHarras", "Move to mouse in Harras mode", SCRIPT_PARAM_ONOFF, false)
	Menu.Move:addParam("MoveBurst", "Move to mouse in Burst mode", SCRIPT_PARAM_ONOFF, true)
	Menu.Move:addParam("MoveLaneClear", "Move to mouse in Laneclear mode", SCRIPT_PARAM_ONOFF, false)

	Menu:addSubMenu("[Draws]", "Draws")
	Menu.Draws:addParam("drawQ", "Draw Q range", SCRIPT_PARAM_ONOFF, true)
	Menu.Draws:addParam("drawW", "Draw W range", SCRIPT_PARAM_ONOFF, false)
	Menu.Draws:addParam("drawR", "Draw R range", SCRIPT_PARAM_ONOFF, false)
	Menu.Draws:addParam("drawRmax", "Draw R max range", SCRIPT_PARAM_ONOFF, false)
	Menu.Draws:addParam("drawAuto", "Draw Auto options status", SCRIPT_PARAM_ONOFF, true)

	Menu:addSubMenu("[Auto]", "Auto")
	Menu.Auto:addParam("autoInterrupt", "Auto Interrupt important enemy spells", SCRIPT_PARAM_ONOFF, true)
	Menu.Auto:addParam("AutoR", "Auto R Stun", SCRIPT_PARAM_ONOFF, true)
	Menu.Auto:addParam("AutoRx", "# enemies (R)", SCRIPT_PARAM_SLICE, 3, 1, 5, 0)
	Menu.Auto:addParam("AutoW", "Auto W Stun", SCRIPT_PARAM_ONOFF, false)
	Menu.Auto:addParam("AutoWx", "# enemies (W)", SCRIPT_PARAM_SLICE, 2, 1, 5, 0)
	Menu.Auto:addParam("AutoE", "Auto E stack", SCRIPT_PARAM_ONOFF, true)
	Menu.Auto:addParam("AutoEx", "% Mana for Auto E", SCRIPT_PARAM_SLICE, 80, 0, 100, 0)
	Menu.Auto:addParam("autoPots", "Auto potion usage", SCRIPT_PARAM_ONOFF, false)
	Menu.Auto:addParam("autoPotsHealth", "% Health for autopots", SCRIPT_PARAM_SLICE, 75, 0, 100, 0)

	Menu:addSubMenu("[Killsteal]", "KS")
	Menu.KS:addParam("ksON", "Enable KS", SCRIPT_PARAM_ONOFF, true)
	Menu.KS:addParam("KSq", "Use Q for KS", SCRIPT_PARAM_ONOFF, true)
	Menu.KS:addParam("KSw", "Use W for KS", SCRIPT_PARAM_ONOFF, true)
	Menu.KS:addParam("KSr", "Use R for KS", SCRIPT_PARAM_ONOFF, true)
	Menu.KS:addParam("KSignite", "Use Ignite for KS", SCRIPT_PARAM_ONOFF, true)

	Menu:addSubMenu("[Tibbers]", "TibbersLogic")
	Menu.TibbersLogic:addParam("TibbersON", "Enable Tibbers", SCRIPT_PARAM_ONOFF, true)
	Menu.TibbersLogic:addParam("Target", "Target", SCRIPT_PARAM_LIST, 2, {"Closest", "TS"})
	Menu.TibbersLogic:addParam("TibbersRange", "Target follow range", SCRIPT_PARAM_SLICE, 1500, 625, 1500, 0)

	Menu:addParam("info1", "", SCRIPT_PARAM_INFO, "")
  Menu:addParam("info2", ""..scriptname.." [ver. "..version.."]", SCRIPT_PARAM_INFO, "")
  Menu:addParam("update", "Enable Auto Update", SCRIPT_PARAM_ONOFF, true)
  Menu:addParam("info5", "", SCRIPT_PARAM_INFO, "")
  Menu:addParam("info3", "Created by "..developer.."", SCRIPT_PARAM_INFO, "")
  Menu:addParam("info4", "Contact me: "..contact.."", SCRIPT_PARAM_INFO, "")


	flashslot = FindSlotByName("summonerflash")
	igniteslot = FindSlotByName("summonerdot")
end

function OnTick()
  dts:update()
  rts:update()
  
  RREADY = myHero:CanUseSpell(_R) == READY and myHero:GetSpellData(_R).name ~= "InfernalGuardianGuide"
  
  if Menu.Key.AutoFarm and not (Menu.Key.combo or Menu.Key.burst or Menu.Key.harras) then
    Autofarm()
  end

  if Menu.Key.AutoHarras then
    Autoharras()
  end
  
  if (Menu.Key.lasthit) then
    Lasthit()
    if (Menu.Move.MoveLasthit) then
      myHero:MoveTo(mousePos.x,mousePos.z)
    end
  end
  
  if (Menu.Key.laneclear) then
    Laneclear()
    if (Menu.Move.MoveLaneClear) then 
      myHero:MoveTo(mousePos.x,mousePos.z)
    end
  end
  
  if (Menu.Key.combo) then
    Combo()
    if (Menu.Move.MoveCombo) then
      myHero:MoveTo(mousePos.x,mousePos.z)
    end
  end
  
  if (Menu.Key.harras) then
    Harras()
    if (Menu.Move.MoveHarras) then
      myHero:MoveTo(mousePos.x,mousePos.z)
    end
  end
  
  if (Menu.Key.burst) then
    local target = GetTarget()
    if (target ~= nil and target.type == myHero.type) then
      Burst(myHero.x, myHero.z, target.x, target.z)
    end
    if (Menu.Move.MoveBurst) then
      myHero:MoveTo(mousePos.x,mousePos.z)
    end
  end
  
  if Menu.KS.ksON then
    Killsteal()
  end
  
  if Menu.Auto.AutoR then
    AutoUlt()
  end
  if Menu.Auto.AutoW then
    AutoWstun()
  end

  if Menu.Auto.AutoE then
    AutoEstack()
  end

  if (Menu.KS.KSignite) then
    AutoIgnite()
  end
  
  if myHero:CanUseSpell(_R) == READY and myHero:GetSpellData(_R).name == "InfernalGuardianGuide" and Menu.TibbersLogic.TibbersON then
    if Menu.TibbersLogic.Target == 1 then
      tts1:update()
      TibbersControl()
    elseif Menu.TibbersLogic.Target == 2 then
      tts:update()
      TibbersControl()
    end
    
    FindItems()
  end
  
  if Menu.Auto.autoPots and not REGEN then
    AutoPotion()
  end  
end

function OnDraw()
  if not myHero.dead then
    if Menu.Draws.drawQ then
      DrawFPSCircle(myHero.x, myHero.z, 625, ARGB(255,193,61,255), 24)
    end
    if Menu.Draws.drawW then
      DrawFPSCircle(myHero.x, myHero.z, VARS.W.RANGE, ARGB(255,193,61,255), 24)
    end
    if Menu.Draws.drawR then
      DrawFPSCircle(myHero.x, myHero.z, VARS.R.RANGE, ARGB(255,193,61,255), 24)
    end
    if Menu.Draws.drawRmax then
      DrawFPSCircle(myHero.x, myHero.z, 850, ARGB(255,193,61,255), 24)
    end
    
    local target = GetTarget()
    if (target ~= nil and target.type == myHero.type and target.team ~= myHero.team) then
      DrawFPSCircle(target.x, target.z, 150, ARGB(255,255,0,0), 4)
    end
    if (myHero:CanUseSpell(_Q) == READY and myHero:CanUseSpell(_W) == READY and RREADY and myHero:CanUseSpell(flashslot) == READY and 
      flashslot ~= nil and Menu.Burst.flashburst and StunUP) then
      DrawFPSCircle(myHero.x, myHero.z, 1045, ARGB(255,255,0,0), 4)
    end
    
    for i, HPbarEnemyChamp in pairs(GetEnemyHeroes()) do
      local dmg = myHero:CalcDamage(HPbarEnemyChamp, myHero.totalDamage)
      if myHero:CanUseSpell(_Q) == READY and not HPbarEnemyChamp.dead then
        dmg = dmg + GetQDamage(HPbarEnemyChamp)
      end
      if myHero:CanUseSpell(_W) == READY and not HPbarEnemyChamp.dead then
        dmg = dmg + GetWDamage(HPbarEnemyChamp)
      end
      if RREADY and not HPbarEnemyChamp.dead then
        dmg = dmg + GetRDamage(HPbarEnemyChamp)
      end
      if igniteslot ~= nil then
        if myHero:CanUseSpell(igniteslot) == READY then
          dmg = dmg + (50 + 20*myHero.level)
        end
      end
      DrawLineHPBar(dmg, "", HPbarEnemyChamp, HPbarEnemyChamp.team)
    end 
  end
  
  if (Menu.Key.lasthitQstacks) then
    DrawText ("SAVE STUN [T]", 20, 150, 100, 0xFF00FF00)
  else 
    DrawText ("DON'T SAVE STUN [T]", 20, 150, 100, 0xFFFF0000)
  end
  
  if Menu.Draws.drawAuto then
    if Menu.Key.AutoHarras then
      DrawText ("AUTO HARRAS ON [N]", 20, 150, 80, 0xFF00FF00)
    else 
      DrawText ("AUTO HARRAS OFF [N]", 20, 150, 80, 0xFFFF0000)
    end
    if Menu.Key.AutoFarm then
      DrawText ("AUTO FARM ON [M]", 20, 150, 60, 0xFF00FF00)
    else 
      DrawText ("AUTO FARM OFF [M]", 20, 150, 60, 0xFFFF0000)
    end
  end
end

function FindItems()
  GetBolt()
end

function GetBolt()
  local slot = GetItem(ATTACKITEMS[1])
  if (slot ~= nil) then
    BOLT = true
    BOLTSLOT = slot
  else
    BOLT = false
  end
end

function CastBOLT(unit)
  if BOLT then
    CastSpell(BOLTSLOT, unit)
  end
end

function Autofarm()
  qFarm()
end

function Autoharras()
  if ValidTarget(dts.target, 625) and not dts.target.dead then
    CastQ(dts.target)
  end
end

function ApplyBuff(unit, target, buff)
  if not unit.isMe then return end
  if unit and unit.isMe and buff and buff.name == "pyromania_particle" then
    StunUP = true
  end
end

function UpdateBuff(unit, buff, stacks)
  if unit and unit.isMe and buff and buff.name == "pyromania" then
    passiveStacks = stacks
  end
end

function RemoveBuff(unit, buff)
  if not unit.isMe then return end
  if unit and unit.isMe and buff and buff.name == "pyromania" then
    passiveStacks = 0
  end
  if unit and unit.isMe and buff and buff.name == "pyromania_particle" then
    StunUP = false 
  end
end

function Combo()
  if ValidTarget(rts.target, 850) and (CanCast(_Q) or CanCast(_W) or CanCast(_R)) and GetRastoyanie(myHero,rts.target) > 600 then
    OrbsOff()
  end
  if ValidTarget(rts.target, 850) then
    if (StunUP) then
      if RREADY then
        CastR(rts.target, myHero.x, myHero.z, rts.target.x, rts.target.z)
      end
      if (ValidTarget(dts.target, 625)) then
        if CanCast(_W) then
          CastW(dts.target)
        end
        if CanCast(_Q) then
          CastQ(dts.target)
        end
      end
      if (not Menu.Combo.comboRstun and ValidTarget(dts.target, 625)) then
        if RREADY then
          CastR(dts.target, myHero.x, myHero.z, dts.target.x, dts.target.z)
        end
        if CanCast(_W) then
          CastW(dts.target)
        end
        if CanCast(_Q) then
          CastQ(dts.target)
        end
      end
      if Menu.Combo.useGLP and BOLT then
        if CanCast(BOLTSLOT) then
          CastBOLT(rts.target)
        end
      end
    end
    if (not StunUP) then
      if (passiveStacks == 3 and Menu.Combo.comboRstun) then
        if (myHero:CanUseSpell(_E) == READY) then
          CastE()
        end
      end
      if (ValidTarget(dts.target, 625)) then
        if CanCast(_W) then
          CastW(dts.target)
        end
        if CanCast(_Q) then
          CastQ(dts.target)
        end
        if (not StunUP) then
          CastE()
        end
        if RREADY and not Menu.Combo.comboRstun then
          CastR(dts.target, myHero.x, myHero.z, dts.target.x, dts.target.z)
        end
      end
      if ValidTarget(rts.target, 850) then
        if Menu.Combo.useGLP and BOLT then
          if CanCast(BOLTSLOT) then
            CastBOLT(rts.target)
          end
        end
      end
    end
  end 
end

function CanCast(spell)
  return myHero:CanUseSpell(spell) == READY
end

function OrbsOff()
  if SAC then
    _G.AutoCarry.MyHero:AttacksEnabled(false)
    DelayAction(function()
      _G.AutoCarry.MyHero:AttacksEnabled(true)
    end, 1)
  end
  if MMA then
    _G.MMA_StopAttacks(false)
    DelayAction(function()
      _G.MMA_StopAttacks()
    end, 1)
  end
  if WOLFY then
    _G.NebelwolfisOrbWalker:SetAA(false)
    DelayAction(function()
      _G.NebelwolfisOrbWalker:SetAA(true)
    end, 1)
  end
  if PEW then
    _Pewalk.AllowAttack(false)
    DelayAction(function()
      _Pewalk.AllowAttack(true)
    end, 1)
  end
  if SXORB then
    SxOrb:DisableAttacks()
    DelayAction(function()
      SxOrb:EnableAttacks()
    end, 1)
  end
end

function Harras()
  if (ValidTarget(dts.target, 625) and rts.target.type == myHero.type) then
    if Menu.Harras.useW then
      CastW(dts.target)
    end
    if Menu.Harras.useQ then
      CastQ(dts.target)
    end
  end
end

function Burst(myX, myZ, enemyX, enemyZ)
  local target = GetTarget()
  if target == nil then
    PrintChat("Choose target for burst!")
    return 0
  end
  local BurstMana = spellData[_Q].mana() + spellData[_W].mana() + spellData[_R].mana
  local rastoyanie = math.sqrt((enemyX-myX)*(enemyX-myX) + (enemyZ-myZ)*(enemyZ-myZ))
  if (target ~= nil and target.type == myHero.type and myHero:CanUseSpell(_Q) == READY and myHero:CanUseSpell(_W) == READY and RREADY and
    target.team ~= myHero.team and rastoyanie <= 1040 and StunUP and rastoyanie >= 625 and myHero.mana > BurstMana) then
    if (Menu.Burst.flashburst and myHero:CanUseSpell(flashslot) == READY and flashslot ~= nil) then 
      local a = (enemyX-myX)/rastoyanie * 425 + myX
      local b = (enemyZ-myZ)/rastoyanie * 425 + myZ
      CastSpell(flashslot, a, b)
    end
  end
  if (ValidTarget(target, 625) and target ~= nil) then
    CastR(target, myHero.x, myHero.z, target.x, target.z)
    CastW(target)
    CastQ(target)
    if (not StunUP) then
      CastE()
    end
  end
end

function Killsteal()
  for i,enemy in pairs(GetEnemyHeroes()) do
    if isValid(enemy, 835) and not CheckInvul(enemy) then
      local rastoyanie = math.sqrt((enemy.x-myHero.x)*(enemy.x-myHero.x) + (enemy.z-myHero.z)*(enemy.z-myHero.z))
      if ValidTarget(enemy, 835) then
        if rastoyanie <= 835 and rastoyanie > 625 then
          if RREADY and Menu.KS.KSr then
            local RDmg = GetRDamage(enemy)
            if RDmg >= enemy.health then
              CastR(enemy, myHero.x, myHero.z, enemy.x, enemy.z)
            end
          end
        elseif rastoyanie <= 625 then  
          if myHero:CanUseSpell(_Q) == READY and Menu.KS.KSq then
            local QDmg = GetQDamage(enemy)
            if QDmg >= enemy.health then
              CastQ(enemy)
            end
          elseif myHero:CanUseSpell(_W) == READY and Menu.KS.KSw then
            local WDmg = GetWDamage(enemy)
            if WDmg >= enemy.health then
              CastW(enemy)
            end
          elseif RREADY and Menu.KS.KSr then
            local RDmg = GetRDamage(enemy)
            if RDmg >= enemy.health then
              CastR(enemy, myHero.x, myHero.z, enemy.x, enemy.z)
            end
          end 
        end 
      end
    end
  end
end

function GetRastoyanie(a, b)
	if not b then
		return GetRastoyanie(myHero,a)
	end
  local rastoyanie = math.sqrt((b.x-a.x)*(b.x-a.x) + (b.z-a.z)*(b.z-a.z))
  return rastoyanie
end

function AutoIgnite()
  if igniteslot == nil then return end
  for i,enemy in pairs(GetEnemyHeroes()) do
    if not enemy.dead and enemy.visible then
      local rastoyanie = math.sqrt((enemy.x-myHero.x)*(enemy.x-myHero.x) + (enemy.z-myHero.z)*(enemy.z-myHero.z))
      if rastoyanie <= 600 then
        if ((50 + (20*myHero.level)) >= enemy.health and igniteslot ~= nil and myHero:CanUseSpell(igniteslot) == READY and
          ValidTarget(enemy, 600)) then 
          CastSpell(igniteslot, enemy)
        end
      end 
    end
  end
end

function AutoPotion()
  for i=1, 5 do
    local pot = GetItem(POTS[i])
    if (pot ~= nil) then
      if (((myHero.health*100)/myHero.maxHealth) <= Menu.Auto.autoPotsHealth and not REGEN) then
        CastSpell(pot)
      end
    end
  end
end

function Lasthit()
  if (Menu.Farm.lasthit.lasthitQ) then
    qFarm()
  end
end

function Laneclear()
  if (Menu.Farm.laneclear.laneclearQ) then
    qFarm()
  end
end

function AutoUlt()
  if (StunUP and RREADY and Menu.Auto.AutoR) then
    for i,enemy in pairs(GetEnemyHeroes()) do
      if ValidTarget(enemy, 600) then
        local mainCastPosition, mainHitChance, numPoints, mainPosition = VP:GetCircularAOECastPosition(enemy, VARS.R.DELAY, VARS.R.RADIUS, VARS.R.RANGE, VARS.R.SPEED, myHero, false)
        if (numPoints ~= nil) then
          if (numPoints >= Menu.Auto.AutoRx) then
            CastSpell(_R, mainCastPosition.x, mainCastPosition.z)
          end
        end
      end
    end
  end
  if (passiveStacks == 3 and RREADY and Menu.Auto.AutoR) then
    for i,enemy in pairs(GetEnemyHeroes()) do
      if ValidTarget(enemy, 600) then
        local mainCastPosition, mainHitChance, numPoints, mainPosition = VP:GetCircularAOECastPosition(enemy, VARS.R.DELAY, VARS.R.RADIUS, VARS.R.RANGE, VARS.R.SPEED, myHero, false)
        if (numPoints ~= nil) then
          if (numPoints >= Menu.Auto.AutoRx and myHero:CanUseSpell(_E) == READY) then
            CastE()
            CastSpell(_R, mainCastPosition.x, mainCastPosition.z)
          end
        end  
      end
    end
  end      
end          

function AutoWstun()
  if (StunUP and myHero:CanUseSpell(_W) == READY and Menu.Auto.AutoW) then
    for i,enemy in pairs(GetEnemyHeroes()) do
      if ValidTarget(enemy, 625) then
        local mainCastPosition, mainHitChance, numPoints = VP:GetConeAOECastPosition(unit, VARS.W.DELAY, VARS.W.ANGLE, VARS.W.RANGE, VARS.W.SPEED, myHero, false)
        if (numPoints ~= nil) then
          if (numPoints >= Menu.Auto.AutoWx) then
            CastSpell(_W, mainCastPosition.x, mainCastPosition.z)
          end
        end
      end
    end   
  end  
end

function qFarm()
  if ((Menu.Farm.lasthit.lasthitQ or Menu.Farm.laneclear.laneclearQ) and not Menu.Key.lasthitQstacks) then
    for _, minion in pairs(minionManager(MINION_ENEMY, 625, myHero, MINION_SORT_HEALTH_ASC).objects) do
      local qDmg = GetQDamage(minion)
      local hp = VP:GetPredictedHealth(minion, GetDistance(minion)/2000 + 0.250)
      if (myHero:CanUseSpell(_Q) == READY and hp < qDmg) then
        CastQ(minion)
      end
    end
  end
  if ((Menu.Farm.lasthit.lasthitQ or Menu.Farm.laneclear.laneclearQ) and Menu.Key.lasthitQstacks) then
    if (not StunUP) then
      for _, minion in pairs(minionManager(MINION_ENEMY, 625, myHero, MINION_SORT_HEALTH_ASC).objects) do
        local qDmg = GetQDamage(minion)
        local hp = VP:GetPredictedHealth(minion, GetDistance(minion)/2000 + 0.250)
        if (myHero:CanUseSpell(_Q) == READY and hp < qDmg) then
          CastQ(minion)
        end
      end
    end
  end 
end

function Buff_Add(unit, target, buff)
  if not unit.isMe then return end
  if (buff.name == "OdinRecall" or buff.name == "recall") then
    RECALLING = true
  end
  for i=1, 5 do
    if (buff.name == POTS[i] and unit.isMe) then
      REGEN = true
    end
  end
end

function Buff_Rem(unit, buff)
  if not unit.isMe then return end
  if (buff.name == "OdinRecall" or buff.name == "recall") then
    RECALLING = false
  end
  for i=1, 5 do
    if (buff.name == POTS[i] and unit.isMe) then
      REGEN = false
    end
  end
end

function CastQ(unit)
  if myHero:CanUseSpell(_Q) == READY and ValidTarget(unit, 625) then
    CastSpell(_Q, unit)
  end
end

function CastW(unit)
  if VP and isValid(unit, 625) then
    local mainCastPosition, mainHitChance, numPoints = VP:GetConeAOECastPosition(unit, VARS.W.DELAY, VARS.W.ANGLE, VARS.W.RANGE, VARS.W.SPEED, myHero, false)
    if numPoints >= 1 and mainHitChance >=2 then
      CastSpell(_W, mainCastPosition.x, mainCastPosition.z)
    end
  end
end

function CastE()
  if (myHero:CanUseSpell(_E) == READY) then
    CastSpell(_E)
  end
end

function CastR(unit, myX, myZ, enemyX, enemyZ)
  local rastoyanie = math.sqrt((enemyX-myX)*(enemyX-myX) + (enemyZ-myZ)*(enemyZ-myZ))
  if RREADY and Menu.Combo.comboRmax and ValidTarget(unit, 850) and rastoyanie <= 845 and
    rastoyanie >= 600 then
    local a = (enemyX-myX)/rastoyanie * 600 + myX
    local b = (enemyZ-myZ)/rastoyanie * 600 + myZ
    CastSpell(_R, a, b)
  elseif RREADY and ValidTarget(unit, 850) then
    local CastPosition, HitChance = VP:GetCircularCastPosition(unit, VARS.R.DELAY, VARS.R.RADIUS, VARS.R.RANGE, VARS.R.SPEED, myHero, false)
      if HitChance >= Menu.Combo.HitChance then
        CastSpell(_R, CastPosition.x, CastPosition.z)
      end
    end
  end

  function TibbersLogic(obj)
    if obj.name == nil then return end
    if obj.name == "Tibbers" then
      Tibbers = obj
      TibbersPartyHard = true
    end
  end

  function haveYouSeenMyTibbersDelete(obj)
    if obj.name == "Tibbers" then
      TibbersPartyHard = false
    end
  end

  function TibbersControl()
    if TibbersPartyHard then
      if Menu.TibbersLogic.Target == 1 then
        if ValidTarget(tts1.target, 1500) and myHero.type == tts1.target.type and not RREADY then     
          AttackByTibbers(tts1.target)
        end
        if math.sqrt((Tibbers.x - myHero.x)*(Tibbers.x - myHero.x) + (Tibbers.z - myHero.z)*(Tibbers.z - myHero.z)) > Menu.TibbersLogic.TibbersRange
          and myHero:GetSpellData(_R).name == "InfernalGuardianGuide" then
          CastSpell(_R, myHero.x, myHero.z)
        end
      end
      if Menu.TibbersLogic.Target == 2 then
        if ValidTarget(tts.target, 1500) and myHero.type == tts.target.type and not RREADY then
          AttackByTibbers(tts.target)
        end
        if math.sqrt((Tibbers.x - myHero.x)*(Tibbers.x - myHero.x) + (Tibbers.z - myHero.z)*(Tibbers.z - myHero.z)) > Menu.TibbersLogic.TibbersRange
          and myHero:GetSpellData(_R).name == "InfernalGuardianGuide" then
          CastSpell(_R, myHero.x, myHero.z)
        end
      end
    end
  end

  function AttackByTibbers(unit)
    if GetTickCount() > lastAA + lastWnd + 720 then
      CastSpell(_R, unit)
      lastAA = GetTickCount()
    end
  end

  function OnAnimation(unit, animation)
    if unit == tibbers and animation:lower():find("attack") then
      lastAA = GetTickCount()
    end
  end

  function OnProcessAttack(unit, spell)
    if unit == tibbers and spell.name:lower():find("attack") then
      lastWnd = spell.windUpTime
    end
  end

function GetQDamage(unit)
  local Qlvl = myHero:GetSpellData(_Q).level
  if Qlvl < 1 then return 0 end
  local QDmg = {80, 115, 150, 185, 220}
  local QDmgMod = 0.8
  local DmgRaw = QDmg[Qlvl] + myHero.ap * QDmgMod
  local Dmg = myHero:CalcMagicDamage(unit, DmgRaw)
  return Dmg
end

function GetWDamage(unit)
  local Wlvl = myHero:GetSpellData(_W).level
  if Wlvl < 1 then return 0 end
  local WDmg = {70, 115, 160, 205, 250}
  local WDmgMod = 0.85
  local DmgRaw = WDmg[Wlvl] + myHero.ap * WDmgMod
  local Dmg = myHero:CalcMagicDamage(unit, DmgRaw)
  return Dmg
end

function GetRDamage(unit)
  local Rlvl = myHero:GetSpellData(_R).level
  if Rlvl < 1 then return 0 end
  local RDmg = {150, 275, 400}
  local RDmgMod = 0.65
  local DmgRaw = RDmg[Rlvl] + myHero.ap * RDmgMod
  local Dmg = myHero:CalcMagicDamage(unit, DmgRaw)
  return Dmg
end

function FindSlotByName(name)
  if name ~= nil then
    for i=0, 12 do
      if string.lower(myHero:GetSpellData(i).name) == string.lower(name) then
        return i
      end
    end
  end  
  return nil
end

function OnProcessSpell(unit, spell)
  if Menu.Auto.autoInterrupt and unit and spell then
    if unit.team ~= myHero.team and PussyOut[spell.name] ~= nil and isValid(unit) then
      if StunUP then
      CastQ(unit)
      CastW(unit, myHero.x, myHero.z, unit.x, unit.z)
      end
    end
  end
end

function isValid(object, range)
  return object ~= nil and object.valid and object.visible and not object.dead and object.bInvulnerable == 0
   and object.bTargetable and (range == nil or GetRastoyanie(object, myHero) <= range)
end

local invul = {"undyingrage", "sionpassivezombie", "aatroxpassivedeath", "chronoshift", "judicatorintervention"}

function CheckInvul(unit)
  for i,buff in pairs(invul) do
    if TargetHaveBuff(buff, unit) then
      return true
    end
  end
    return false
end

function DrawLineA(x1, y1, x2, y2, color)
  DrawLine(x1, y1, x2, y2, 1, color)
end

function DrawFPSCircle(xCoordinate, zCoordinate, radius, color, quality)
  DrawCircle3D(xCoordinate, myHero.y, zCoordinate, radius, 2, color, quality)
end

function GetHPBarPos(enemy)
  enemy.barData = {PercentageOffset = {x = -0.05, y = 0}}
  local barPos = GetUnitHPBarPos(enemy)
  local barPosOffset = GetUnitHPBarOffset(enemy)
  local barOffset = { x = enemy.barData.PercentageOffset.x, y = enemy.barData.PercentageOffset.y }
  local barPosPercentageOffset = { x = enemy.barData.PercentageOffset.x, y = enemy.barData.PercentageOffset.y }
  local BarPosOffsetX = -50
  local BarPosOffsetY = 46
  local CorrectionY = 39
  local StartHpPos = 31 
  barPos.x = math.floor(barPos.x + (barPosOffset.x - 0.5 + barPosPercentageOffset.x) * BarPosOffsetX + StartHpPos)
  barPos.y = math.floor(barPos.y + (barPosOffset.y - 0.5 + barPosPercentageOffset.y) * BarPosOffsetY + CorrectionY)
  local StartPos = Vector(barPos.x , barPos.y, 0)
  local EndPos = Vector(barPos.x + 108 , barPos.y , 0)    
  return Vector(StartPos.x, StartPos.y, 0), Vector(EndPos.x, EndPos.y, 0)
end

function DrawLineHPBar(damage, text, unit, enemyteam)
  if unit.dead or not unit.visible then return end
  local p = WorldToScreen(D3DXVECTOR3(unit.x, unit.y, unit.z))
  if not OnScreen(p.x, p.y) then return end
  local thedmg = 0
  local line = 2
  local linePosA  = {x = 0, y = 0 }
  local linePosB  = {x = 0, y = 0 }
  local TextPos   = {x = 0, y = 0 }

  if damage >= unit.health then
    thedmg = unit.health - 1
    text = "KILLABLE!"
  else
    thedmg = damage
    text = "Possible Damage"
  end

  thedmg = math.round(thedmg)

  local StartPos, EndPos = GetHPBarPos(unit)
  local Real_X = StartPos.x + 24
  local Offs_X = (Real_X + ((unit.health - thedmg) / unit.maxHealth) * (EndPos.x - StartPos.x - 2))
  if Offs_X < Real_X then Offs_X = Real_X end 
  local mytrans = 350 - math.round(255*((unit.health-thedmg)/unit.maxHealth))
  if mytrans >= 255 then mytrans=254 end
  local my_bluepart = math.round(400*((unit.health-thedmg)/unit.maxHealth))
  if my_bluepart >= 255 then my_bluepart=254 end

  if enemyteam then
    linePosA.x = Offs_X-150
    linePosA.y = (StartPos.y-(30+(line*15)))    
    linePosB.x = Offs_X-150
    linePosB.y = (StartPos.y-10)
    TextPos.x = Offs_X-148
    TextPos.y = (StartPos.y-(30+(line*15)))
  else
    linePosA.x = Offs_X-125
    linePosA.y = (StartPos.y-(30+(line*15)))    
    linePosB.x = Offs_X-125
    linePosB.y = (StartPos.y-15)

    TextPos.x = Offs_X-122
    TextPos.y = (StartPos.y-(30+(line*15)))
  end

  DrawLine(linePosA.x, linePosA.y, linePosB.x, linePosB.y , 2, ARGB(mytrans, 255, my_bluepart, 0))
  DrawText(tostring(thedmg).." "..tostring(text), 15, TextPos.x, TextPos.y , ARGB(mytrans, 255, my_bluepart, 0))
end

function AutoEstack()
  if (myHero:CanUseSpell(_E) == READY and ((myHero.mana*100)/myHero.maxMana) >= Menu.Auto.AutoEx  and not StunUP and not RECALLING) then
    CastE()
  end
end

function GetItem(name)
  local slot = FindSlotByName(name)
  return slot 
end

class 'KatarinaUpdate'
  
function KatarinaUpdate:__init(LocalVersion, Host, VersionPath, ScriptPath, SavePath, CallbackUpdate, CallbackNoUpdate, CallbackNewVersion, CallbackError) 
  self.LocalVersion = LocalVersion
  self.Host = Host
  self.VersionPath = '/BoL/TCPUpdater/GetScript5.php?script='..self:Base64Encode(self.Host..VersionPath)..'&rand='..math.random(99999999)
  self.ScriptPath = '/BoL/TCPUpdater/GetScript5.php?script='..self:Base64Encode(self.Host..ScriptPath)..'&rand='..math.random(99999999)
  self.SavePath = SavePath
  self.CallbackUpdate = CallbackUpdate
  self.CallbackNoUpdate = CallbackNoUpdate
  self.CallbackNewVersion = CallbackNewVersion
  self.CallbackError = CallbackError
  self:CreateSocket(self.VersionPath)
  self.DownloadStatus = 'Connect to Server for VersionInfo'
  AddTickCallback(function() self:GetOnlineVersion() end)
end

function KatarinaUpdate:OnDraw()
  local bP = {['x1'] = WINDOW_W - (WINDOW_W - 390),['x2'] = WINDOW_W - (WINDOW_W - 20),['y1'] = WINDOW_H / 2,['y2'] = (WINDOW_H / 2) + 20,}
  local text = 'Download Status: '..(self.DownloadStatus or 'Unknown')
  DrawLine(bP.x1, bP.y1 + 10, bP.x2,  bP.y1 + 10, 18, ARGB(0x7D,0xE1,0xE1,0xE1))
  local xOff
  if self.File and self.Size then
    local c = math.round(100/self.Size*self.File:len(),2)/100
    xOff = c < 1 and math.ceil(370 * c) or 370
  else
    xOff = 0
  end
  DrawLine(bP.x2 + xOff, bP.y1 + 10, bP.x2, bP.y1 + 10, 18, ARGB(255, 5, 117, 1))
  DrawLines2({D3DXVECTOR2(bP.x1, bP.y1),D3DXVECTOR2(bP.x2, bP.y1),D3DXVECTOR2(bP.x2, bP.y2),D3DXVECTOR2(bP.x1, bP.y2),D3DXVECTOR2(bP.x1, bP.y1),}, 3, ARGB(255, 86, 6, 62))
  DrawText(text, 16, WINDOW_W - (WINDOW_W - 205) - (GetTextArea(text, 16).x / 2), bP.y1 + 2, ARGB(255, 8, 224, 52))
end

function KatarinaUpdate:CreateSocket(url)
    if not self.LuaSocket then
        self.LuaSocket = require("socket")
    else
        self.Socket:close()
        self.Socket = nil
        self.Size = nil
        self.RecvStarted = false
    end
    self.LuaSocket = require("socket")
    self.Socket = self.LuaSocket.tcp()
    self.Socket:settimeout(0, 'b')
    self.Socket:settimeout(99999999, 't')
    self.Socket:connect('sx-bol.eu', 80)
    self.Url = url
    self.Started = false
    self.LastPrint = ""
    self.File = ""
end

function KatarinaUpdate:Base64Encode(data)
    local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    return ((data:gsub('.', function(x)
        local r,b='',x:byte()
        for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
        return r;
    end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
        if (#x < 6) then return '' end
        local c=0
        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
        return b:sub(c+1,c+1)
    end)..({ '', '==', '=' })[#data%3+1])
end

function KatarinaUpdate:GetOnlineVersion()
    if self.GotScriptVersion then return end

    self.Receive, self.Status, self.Snipped = self.Socket:receive(1024)
    if self.Status == 'timeout' and not self.Started then
        self.Started = true
        self.Socket:send("GET "..self.Url.." HTTP/1.1\r\nHost: sx-bol.eu\r\n\r\n")
    end
    if (self.Receive or (#self.Snipped > 0)) and not self.RecvStarted then
        self.RecvStarted = true
        self.DownloadStatus = 'Downloading VersionInfo (0%)'
    end

    self.File = self.File .. (self.Receive or self.Snipped)
    if self.File:find('</s'..'ize>') then
        if not self.Size then
            self.Size = tonumber(self.File:sub(self.File:find('<si'..'ze>')+6,self.File:find('</si'..'ze>')-1))
        end
        if self.File:find('<scr'..'ipt>') then
            local _,ScriptFind = self.File:find('<scr'..'ipt>')
            local ScriptEnd = self.File:find('</scr'..'ipt>')
            if ScriptEnd then ScriptEnd = ScriptEnd - 1 end
            local DownloadedSize = self.File:sub(ScriptFind+1,ScriptEnd or -1):len()
            self.DownloadStatus = 'Downloading VersionInfo ('..math.round(100/self.Size*DownloadedSize,2)..'%)'
        end
    end
    if self.File:find('</scr'..'ipt>') then
        self.DownloadStatus = 'Downloading VersionInfo (100%)'
        local a,b = self.File:find('\r\n\r\n')
        self.File = self.File:sub(a,-1)
        self.NewFile = ''
        for line,content in ipairs(self.File:split('\n')) do
            if content:len() > 5 then
                self.NewFile = self.NewFile .. content
            end
        end
        local HeaderEnd, ContentStart = self.File:find('<scr'..'ipt>')
        local ContentEnd, _ = self.File:find('</scr'..'ipt>')
        if not ContentStart or not ContentEnd then
            if self.CallbackError and type(self.CallbackError) == 'function' then
                self.CallbackError()
            end
        else
            self.OnlineVersion = (Base64Decode(self.File:sub(ContentStart + 1,ContentEnd-1)))
            self.OnlineVersion = tonumber(self.OnlineVersion)
            if self.OnlineVersion and self.OnlineVersion > LocalVersion then
                if self.CallbackNewVersion and type(self.CallbackNewVersion) == 'function' then
                    self.CallbackNewVersion(self.OnlineVersion,self.LocalVersion)
                end
        if not Menu.update then return end
        AddDrawCallback(function() self:OnDraw() end)
                self:CreateSocket(self.ScriptPath)
                self.DownloadStatus = 'Connect to Server for ScriptDownload'
                AddTickCallback(function() self:DownloadUpdate() end)
            else
                if self.CallbackNoUpdate and type(self.CallbackNoUpdate) == 'function' then
                    self.CallbackNoUpdate(self.LocalVersion)
                end
            end
        end
        self.GotScriptVersion = true
    end
end

function KatarinaUpdate:DownloadUpdate()
    if self.GotScriptUpdate then return end
    self.Receive, self.Status, self.Snipped = self.Socket:receive(1024)
    if self.Status == 'timeout' and not self.Started then
        self.Started = true
        self.Socket:send("GET "..self.Url.." HTTP/1.1\r\nHost: sx-bol.eu\r\n\r\n")
    end
    if (self.Receive or (#self.Snipped > 0)) and not self.RecvStarted then
        self.RecvStarted = true
        self.DownloadStatus = 'Downloading Script (0%)'
    end

    self.File = self.File .. (self.Receive or self.Snipped)
    if self.File:find('</si'..'ze>') then
        if not self.Size then
            self.Size = tonumber(self.File:sub(self.File:find('<si'..'ze>')+6,self.File:find('</si'..'ze>')-1))
        end
        if self.File:find('<scr'..'ipt>') then
            local _,ScriptFind = self.File:find('<scr'..'ipt>')
            local ScriptEnd = self.File:find('</scr'..'ipt>')
            if ScriptEnd then ScriptEnd = ScriptEnd - 1 end
            local DownloadedSize = self.File:sub(ScriptFind+1,ScriptEnd or -1):len()
            self.DownloadStatus = 'Downloading Script ('..math.round(100/self.Size*DownloadedSize,2)..'%)'
        end
    end
    if self.File:find('</scr'..'ipt>') then
        self.DownloadStatus = 'Downloading Script (100%)'
        local a,b = self.File:find('\r\n\r\n')
        self.File = self.File:sub(a,-1)
        self.NewFile = ''
        for line,content in ipairs(self.File:split('\n')) do
            if content:len() > 5 then
                self.NewFile = self.NewFile .. content
            end
        end
        local HeaderEnd, ContentStart = self.NewFile:find('<scr'..'ipt>')
        local ContentEnd, _ = self.NewFile:find('</scr'..'ipt>')
        if not ContentStart or not ContentEnd then
            if self.CallbackError and type(self.CallbackError) == 'function' then
        print('Error1')
        self.CallbackError()
            end
        else
            local newf = self.NewFile:sub(ContentStart+1,ContentEnd-1)
            local newf = newf:gsub('\r','')
            if newf:len() ~= self.Size then
                if self.CallbackError and type(self.CallbackError) == 'function' then
          print('Error2')
                    self.CallbackError()
                end
                return
            end
            local newf = Base64Decode(newf)
            if not self.isSprite and type(load(newf)) ~= 'function' then
                if self.CallbackError and type(self.CallbackError) == 'function' then
          print('Error2')
                    self.CallbackError()
                end
            else
                local f = io.open(self.SavePath,"w+b")
        if f then
          f:write(newf)
          f:close()
          if self.CallbackUpdate and type(self.CallbackUpdate) == 'function' then
            self.CallbackUpdate(self.OnlineVersion,self.LocalVersion)
          end
        end
            end
        end
        self.GotScriptUpdate = true
    end
end

class "SxWebResulter"

function SxWebResulter:__init(Host, Path, cbComplete, cbError)
    self.Host = Host
    self.Path = Path
    self.Callback = cbComplete
  self.Error = cbError
    self.LuaSocket = require("socket")

    self.Socket = self.LuaSocket.connect(Host, 80)
    self.Socket:send("GET "..self.Path.." HTTP/1.0\r\nHost: "..Host.."\r\n\r\n")
    self.Socket:settimeout(0, 'b')
    self.Socket:settimeout(99999999, 't')

    self.LastPrint = ""
    self.File = ""
    AddDrawCallback(function() self:GetResult() end)
end

function SxWebResulter:GetResult()
    if self.Status == 'closed' then return end
    self.Receive, self.Status, self.Snipped = self.Socket:receive(1024)
    if self.Receive then
        if self.LastPrint ~= self.Receive then
            self.LastPrint = self.Receive
            self.File = self.File .. self.Receive
        end
    end

    if self.Snipped ~= "" and self.Snipped then
        self.File = self.File .. self.Snipped
    end
    if self.Status == 'closed' then
        local HeaderEnd, ContentStart = self.File:find('\r\n\r\n')
        if HeaderEnd and ContentStart then
            self.Callback(self.File:sub(ContentStart + 1))
        else
            self.Error()
        end
    end
end