taultunleashed logoPOE - Bot - Autoflasks and AutoQuit : Path Of Exile Discussions | Submissions
newtopic  postreply
 [ 4 posts ] 
blue large dot

POE - Bot - Autoflasks and AutoQuit : Path Of Exile Discussions | Submissions

Posted: March 11th, 2013, 11:10 am
 
DJRockingIt

Total Posts: 19
Joined: March 11th, 2013, 9:45 am
DJRockingIt's Reps: 16
User avatar
premium
Requires Autohotkey_L to run
http://l.autohotkey.net/AutoHotkey_L_Install.exe

Autohotkey_L installed should be exactly Unicode x32 version(you get to choose and on Win x64 it defaults to x64 version, i think that may mean calling 64-bit dllcalls which would screw this script up).

Uses passive memory reading & keypress sending.

It reads basic flasks properties like flask type/current charges/charges per use/recovery duration to try and optimally use your Mana/Health/Hybrid flasks(well for now it'll just use them from left to right but won't spam/waste them, will use hp flasks if you need hp, mana flasks if you need mana, hybrid - for either)

It does not read out prefixes/suffixes(it actually really only cares for ones that affect recovery speed) but allows you to easily specify such differences in by-character-name Flaskconfig.

Also allows you to specify min life/nshield % to auto-quit on hardcore.

Currently most use from this can be gained if used for multiboxing, it'll manage all your open PoE windows.

Default toggle hotkey - F1


In case of a new client update you can try commenting out this line to let it try to find new offset
baseMgrPtr:=
comment it out like this
; baseMgrPtr:=

Update:
Fixed multiple drinking/spamming potions.
Default requested process rights changed to VM_READ only since it's been reported to fix script not working for some.
Default autoQuit method changed to quit to main menu, resolution independent, should succeed in case of lags too.
Some additional checks and fixes to make sure it doesn't auto-quit forever if auto-quit is enabled.
Hybrid flasks now considered for both regen queues regardless of which resource type(hp/mana) they're initially used for
Fixed bug with not reading energy shield.
0.10.1f bptr updated, built-in AoB successfully scans for it too but wouldn't use it right away unless you followed it's advice and saved it to script.
Fixed incorrect reading of reserved mana amount(read reserved hp instead)
Further fixes to reservation cases : turns out flat value auras and % reserved are stored separately

Multiple fixes and additions:
BasePointer scan immediate use of found value was still bugged.

In multiboxing environment 1 dead/non-ingame toon could prevent script from checking out other windows since it used break on client windows iteration loop instead of continue.

Further attempt at fixing excessive quitting(closing game window when already at login menu/trying to log back in).
Quit mechanism reworked to also send "Space" - close all panels key, will get you out in case for example some mob sneaks up on you while you're looking at passive skilltree or whatever

Added tolerance time for soft-quit to mainmenu method "autoQuitSoftToleranceBeforeKill", in case it doesn't get out to mainmenu within tolerance time for whatever reason it'll resort to ending process.

Basic granite flask support added with configurable life/nshield tresholds. Since NShield regen kicks in after quite a while it's likely to waste some charges on all granite CI toons by drinking some of that flasks even after mobs are dead, but it should work well on otherwise hp-flask using toons(either for hp regen or nshield regen through zealot's oath).

Some vars/arrays renamed to better reflect their purpose, a bit of streamlining/cleanup done.

Since it seems to be easy enough on resources for this to decrease performance in any noticeable way and this greatly increases chances of you getting saved from death, reduced default watchdog period to 100 ms from 1000ms.
Now defaults to "On" state when run since it seems to adequately handle distinguishing between menu/ingame states & alive/dead toons at this point.

Some basic error messages for critical error cases instead of silent failures, will also auto-quit script in that cases:
Running script on AutoHotkey 64-bit
Failure to obtain moduleBase, moduleSize
Failure to obtain valid process handle for client
(AoBScan failure produced notification, will auto-quit now in addition to make it clear script can't work in that case)

Fixed a bug that would lead to script cpu-hogging while in mainmenu(which in turn exposed whole design flaw with sleeping between drinking potions related to multiboxing, since that "sleep" accidentally wound up in main loop that basically meant sequential only & not parallel drinking of potions...)

Flask timers are now reset in case you get to 100% of respective resource.


As usual test autoquit to menu by pressing F4

PoE_AutoFlasks.ahk
(!empty($user->lang['CODE'])) ? $user->lang['CODE'] : ucwords(strtolower(str_replace('_', ' ', 'CODE'))):
SetBatchLines, -1
DetectHiddenWindows, On

cliname=Path of Exile
cliexe=Client.exe
trayNotifications:=true ;display tray notifications about script actions : drinking potions, autoquitting
autoPotionsWatchdogPeriod:=100 ;milliseconds, decrease this value to have script recheck life/mana/flasks availability more often/increase chances of getting saved from death in time
lagCompensation:=50

autoQuitMode:=1 ; default autoQuit method : 0 =winKill, 1 = exit to login screen
autoQuitPauseBeforeClick:=50
autoQuitSoftToleranceBeforeKill:=2000 ; try to quit to loginscreen at most milliseconds before killing game window(in case we can't quit by clicking menu option for some reason)

PlayerConfig:={}
PlayerConfig["Default"]:={minLifeRatioToDrink: 0.45, minManaRatioToDrink: 0.55, minManaToDrink: 40, minLifeRatioToPopGranite: 0.65, minLifeRatioToQuit: 0.35} ;  disableAutoPotions:true, minLifeRatioToQuit:, minNShieldRatioToQuit: , HasZealotsOath: false, }

PlayerConfig["Default"].FlaskConfig:=[]

PlayerConfig["Default"].FlaskConfig[1]:={Hotkey:"{1}"} ; ,OverrideFlaskDuration:70, instantRecoveryOnLowLife: true, }  ; if flask has special faster/slower recovery affixes/suffixes, specify override recovery time in deciseconds, e.g. 7 seconds = 70
PlayerConfig["Default"].FlaskConfig[2]:={Hotkey:"{2}"}
PlayerConfig["Default"].FlaskConfig[3]:={Hotkey:"{3}"}
PlayerConfig["Default"].FlaskConfig[4]:={Hotkey:"{4}"}
PlayerConfig["Default"].FlaskConfig[5]:={Hotkey:"{5}"}

PlayerConfig["YourHardcorePlayerName"]:={minLifeRatioToDrink: 0.7, minManaRatioToDrink: 0.35, minManaToDrink: 70, minLifeRatioToQuit: 0.4}
PlayerConfig["YourHardcorePlayerName"].FlaskConfig:=[]
PlayerConfig["YourHardcorePlayerName"].FlaskConfig[1]:={Hotkey:"{1}"}
PlayerConfig["YourHardcorePlayerName"].FlaskConfig[2]:={Hotkey:"{2}"}
PlayerConfig["YourHardcorePlayerName"].FlaskConfig[3]:={Hotkey:"{3}"}
PlayerConfig["YourHardcorePlayerName"].FlaskConfig[4]:={Hotkey:"{4}"}
PlayerConfig["YourHardcorePlayerName"].FlaskConfig[5]:={Hotkey:"{5}"}

autoPotionsState:=true

WindowQueuedFlaskEffects:=[] ;keyed by "%hwnd%%CurrPid%", hpQueueEndtime, manaQueueEndtime

baseMgrPtr:=0x68ce7C ;0.10.4, delete for script to try to auto-scan for it in newer versions, scan takes 4-5 seconds

basePtrAoBArray:=[0x6A,0xFF,0x68,"?","?","?","?",0x50,0x64,"?","?","?","?","?","?",0xA1,"?","?","?","?",0x81,0xEC,"?","?","?","?",0x53,0x55,0x56,0x57,0x33,0xFF,0x3B,0xC7]
basePtrAobOffset:=0x10

WindowBasicsCache:=[] ; keyed by "%hwnd%%CurrPid%", entries are objects with properties processHandle, moduleBase, moduleSize, baseFramePtr

#Include AutoHotkeyMemoryLib.ahk

Loop
{
   AutoPotions()
}

GetWindowBasics(hwnd, byref mB="", byref pH="", byref mS="")
{
   
   global WindowBasicsCache
   global cliexe
   
   WinGet, CurrPid, PID, ahk_id %hwnd%
   
   k="%hwnd%%CurrPid%"
   
   mB:=WindowBasicsCache[k].mBase
   mS:=WindowBasicsCache[k].mSize
   
   if mB=
   {
      WindowBasicsCache[k]:=Object()
      GetModuleInfo(cliexe, CurrPid, mB, mS)
      if (mB="" || mS="")
      {
         MsgBox, Failed to obtain moduleBase or moduleSize for PID %CurrPid%, script will now terminate
         ExitApp
      }      
      WindowBasicsCache[k].mBase:=mB
      WindowBasicsCache[k].mSize:=mS
   }

   pH:=WindowBasicsCache[k].ProcessHandle
   if pH=
   {
      pH:=GetProcessHandle(CurrPid)
      if (pH="" || pH=-1)
      {
         MsgBox, Invalid process handle obtained for PID %CurrPid%, script will now terminate
         ExitApp
      }      
      WindowBasicsCache[k].ProcessHandle:=pH
   }
}

ScanBaseMgrPtr(mBase,pH,moduleSize)
{
   global basePtrAoBArray
   global basePtrAobOffset
   global baseMgrPtr
   aobResult:=AobScan(pH,mBase,moduleSize,basePtrAoBArray)

   if aobResult
   {
      SetFormat, IntegerFast, hex
      baseMgrPtr:=ReadMemUInt(pH,mBase+aobResult+basePtrAobOffset)-mBase
      MsgBox, PoE Base ptr found with AoB Scan baseMgrPtr = %baseMgrPtr%, save this value to script for quick startup
      SetFormat, IntegerFast, dec
   }
   else
   {
      MsgBox, baseMgrPtr not found with AoBScan, script will now terminate
      ExitApp
   }   
}

GetFrameBase(hwnd)
{
   global baseMgrPtr
   global WindowBasicsCache

   WinGet, CurrPid, PID, ahk_id %hwnd%
   k="%hwnd%%CurrPid%"

   fB:=WindowBasicsCache[k].fBase

   if fB=
   {
      GetWindowBasics(hwnd, mBase, pH, mSize)

      if baseMgrPtr=
      {
         ScanBaseMgrPtr(mBase, pH, mSize)
      }

      fB:=GetMultilevelPointer(pH,[mBase+baseMgrPtr,4,0x7C,0x94])
      WindowBasicsCache[k].fBase:=fB
   }
   return fB
}

GetUiBase(hwnd)
{
   global baseMgrPtr

      GetWindowBasics(hwnd, mBase, pH, mSize)
      
      if baseMgrPtr=
      {
         ScanBaseMgrPtr(mBase, pH, mSize)
      }
      
   return GetMultilevelPointer(pH,[mBase+baseMgrPtr,4,0xFC,0x94,0x50])
}

ReadClientResolution(hwnd, ByRef w, ByRef h)
{
   GetWindowBasics(hwnd,mBase,pH)
   if (mBase!=0 && pH && pH!=-1)
   {
      FrameBase:=GetFrameBase(hwnd)
      w:=ReadMemUInt(pH,FrameBase+0x1368)
      h:=ReadMemUInt(pH,FrameBase+0x136C)
      return true
   }   
}

ReadPlayerStats(hwnd, byRef PlayerStats)
{
   GetWindowBasics(hwnd, mBase, pH)
   fBase:=GetFrameBase(hwnd)
   PlayerBase:=GetMultilevelPointer(pH,[fBase+0xb4,0x51C])
   PlayerMain:=ReadMemUInt(pH,PlayerBase+4)
   PlayerStatsOffset:=ReadMemUInt(pH,PlayerMain+0xC)
   PlayerStats.MaxHP:=ReadMemUInt(pH,PlayerStatsOffset+0x24)
   PlayerStats.CurrHP:=ReadMemUInt(pH,PlayerStatsOffset+0x28)   
   PlayerStats.ReservedHPFlat:=ReadMemUInt(pH,PlayerStatsOffset+0x30)
   PlayerStats.ReservedHPPercent:=ReadMemUInt(pH,PlayerStatsOffset+0x34)
   PlayerStats.MaxMana:=ReadMemUInt(pH,PlayerStatsOffset+0x48)
   PlayerStats.ReservedManaFlat:=ReadMemUInt(pH,PlayerStatsOffset+0x54)
   PlayerStats.ReservedManaPercent:=ReadMemUInt(pH,PlayerStatsOffset+0x58)
   PlayerStats.CurrMana:=ReadMemUInt(pH,PlayerStatsOffset+0x4C)
   PlayerStats.MaxNShield:=ReadMemUInt(pH,PlayerStatsOffset+0x6C)
   PlayerStats.CurrNShield:=ReadMemUInt(pH,PlayerStatsOffset+0x70)
   
   if (ReadMemUInt(pH, ReadMemUInt(pH,PlayerMain+0x14)+0x24)<8) ;names shorter than 7 chars are stored immediately in component
      PlayerStats.Name:=ReadMemStr(pH, ReadMemUint(pH,PlayerMain+0x14)+0x10,30,"UTF-16") ;immediate name in component
   else
      PlayerStats.Name:=ReadMemStr(pH, GetMultilevelPointer(pH,[PlayerMain+0x14,0x10]),30,"UTF-16") ; otherwise pointer to name is stored
}

ReadFlasksData(hwnd, byRef FlasksData)
{
   GetWindowBasics(hwnd, mBase, pH)
   
   UiBase:=GetUiBase(hwnd)
   
   if (!UiBase) ;not InGame
      return
   
   FlaskInvBase:=GetMultilevelPointer(pH,[UiBase+0x8d0,0x8e8,0x28])

   Loop, 5
   {
      currFlaskPtr:=ReadMemUInt(pH,FlaskInvBase+(A_Index-1)*4)
      if (currFlaskPtr!=0) ; there's a flask in said slot
      {
         FlasksData[A_Index]:={}

         FlaskChargesPtr:=GetMultilevelPointer(ph,[currFlaskPtr,4,0x1C,4,4,0xC])
         FlasksData[A_Index].ChargesCurrent:=ReadMemUInt(pH,FlaskChargesPtr+0xC)
         FlasksData[A_Index].ChargesPerUse:=ReadMemUInt(pH,ReadMemUInt(pH,FlaskChargesPtr+8)+0xC)
         
         if (FlasksData[A_Index].ChargesCurrent < FlasksData[A_Index].ChargesPerUse) ; not enough charges in this flask to use it, don't bother
            continue

         FlaskMetadataPtr:=GetMultilevelPointer(ph,[currFlaskPtr,0,8])
         FlaskMetadataStr:=ReadMemStr(ph,FlaskMetadataPtr,70,"UTF-16")
         FlaskTypeStr:=SubStr(FlaskMetadataStr,23)
         FlasksData[A_Index].type:=FlaskTypeStr
         
         FlaskLocalstatsPtr:=GetMultilevelPointer(ph,[currFlaskPtr,4,0x18,0x20,0xC])
         
         if InStr(FlaskTypeStr, "Life")
         {
            FlasksData[A_Index].HPRegAmount:=ReadMemUInt(pH,FlaskLocalstatsPtr+4)
            FlasksData[A_Index].EffectDuration:=ReadMemUInt(pH,FlaskLocalstatsPtr+0xC)
         }

         if InStr(FlaskTypeStr, "Mana")
         {
            FlasksData[A_Index].ManaRegAmount:=ReadMemUInt(pH,FlaskLocalstatsPtr+4)
            FlasksData[A_Index].EffectDuration:=ReadMemUInt(pH,FlaskLocalstatsPtr+0xC)
         }
         
         if InStr(FlaskTypeStr, "Hybrid")
         {
            FlasksData[A_Index].HPRegAmount:=ReadMemUInt(pH,FlaskLocalstatsPtr+4)
            FlasksData[A_Index].ManaRegAmount:=ReadMemUInt(pH,FlaskLocalstatsPtr+0xC)
            FlasksData[A_Index].EffectDuration:=ReadMemUInt(pH,FlaskLocalstatsPtr+0x14)
         }

         if InStr(FlaskTypeStr, "FlaskUtility")
         {
            FlasksData[A_Index].EffectDuration:=ReadMemUInt(pH,FlaskLocalstatsPtr+0x4)
         }
      }
   }
}

IsInGame(hwnd)
{
   ubase:=GetUiBase(hwnd)
   if ((ubase="") || ubase=0)
      return false
   else
      return true
}

ReadCursorScreenPosition(hwnd,ByRef cX, ByRef cY)
{
   GetWindowBasics(hwnd,mBase,pH)
   if (mBase!=0 && pH && pH!=-1)
   {
      FrameBase:=GetFrameBase(hwnd)
      cX:=ReadMemSInt(pH,FrameBase+0x157C)
      cY:=ReadMemSInt(pH,FrameBase+0x1580)
      return true
   }   
}

ScreenToClient(hwnd, ByRef x, ByRef y)
{
    VarSetCapacity(pt, 8)
    NumPut(x, pt, 0)
    NumPut(y, pt, 4)
    DllCall("ScreenToClient", "uint", hwnd, "uint", &pt)
    x := NumGet(pt, 0, "int")
    y := NumGet(pt, 4, "int")
   VarSetCapacity(pt, 0)
}

GetClientCoords(byRef mx, byRef my)
{
   hwnd:=WinActive("A")   
   CoordMode, Mouse, Screen
   MouseGetPos, mx, my
   ScreenToClient(hwnd,mx,my) ;get mouse pos relative to window client rect
}

GetFractionalCoords(ByRef fX, ByRef fY)
{
   hwnd:=WinActive("A")
   
   if (!IsInGame(hwnd))
      GetClientCoords(mx,my)
   else
      ReadCursorScreenPosition(hwnd,mx,my)
   
   ReadClientResolution(hwnd,w,h)
   
   fX:=mx/w
   fY:=my/h
}

GetClientCoordsFromFractional(hwnd, fX,fY, ByRef cX, ByRef cY)
{
   ReadClientResolution(hwnd,w,h)
   cX:=fX*w
   cY:=fY*h      
}

QuitToLoginScreen(hwnd)
{
   global autoQuitPauseBeforeClick
   global autoQuitSoftToleranceBeforeKill

   if (!IsInGame(hwnd))
   {
      return
   }

   TrayTip, PoE quit to loginscreen, %A_Space% , 2

   ReadClientResolution(hwnd,w,h)
   cX:=0.5*w
   cY:=0.4*h
   p := cY << 16 | (cX & 0xffff)
   
   quitStartTC:=A_TickCount
   while (IsInGame(hwnd))
   {
      if ((A_TickCount-quitStartTC)>=autoQuitSoftToleranceBeforeKill)
         WinKill, % "ahk_id" hwnd
      ControlSend,,{Space}, ahk_id %hwnd%   
      ControlSend,,{Esc}, ahk_id %hwnd%
      sleep, autoQuitPauseBeforeClick      
      PostMessage, 0x201, 1 , p, , ahk_id %hwnd%
      PostMessage, 0x202, 0 , p, , ahk_id %hwnd%
      sleep, autoQuitPauseBeforeClick
   }
}

AutoPotions()
{
   global autoPotionsWatchdogPeriod
   global lagCompensation
   global PlayerConfig
   global WindowQueuedFlaskEffects
   global cliname
   global cliexe
   global trayNotifications
   global autoQuitMode
   
   if (autoPotionsState!=true)
      return

   WinGet, WinID, List, %cliname%
   
   Loop, %WinID%
   {
      
      WinGet, ProcModuleName, ProcessName,  % "ahk_id" WinID%A_Index%
      
      If(ProcModuleName!=cliexe) ; got a window with title "Path of Exile" but exe is not Client.exe, perhaps we have browser window open with PoE site, ignore it
         continue
      
      if (!IsInGame(WinID%A_Index%)) ;not ingame
         continue
      
      PlayerStats:={}
      ReadPlayerStats(WinID%A_Index%, PlayerStats)
      
      if (PlayerStats.MaxHP<1 || PlayerStats.CurrHP=0)
         continue

      if (PlayerConfig.HasKey(PlayerStats.Name))
         CurrentConfig:=PlayerConfig[PlayerStats.Name]
      else
         CurrentConfig:=PlayerConfig["Default"]
         
      
      if PlayerStats.MaxNShield>0
      {
         currNShieldRatio:=PlayerStats.CurrNShield/PlayerStats.MaxNShield
      }
      
      if (PlayerStats.MaxHP>1)
      {
         currLifeRatio:=PlayerStats.CurrHP/(PlayerStats.MaxHP-PlayerStats.ReservedHPFlat-PlayerStats.MaxHP*PlayerStats.ReservedHPPercent/100)
      }
      
      if CurrentConfig.HasZealotsOath
      {
         currLifeRatio:=currNShieldRatio
      }
         
      if (PlayerStats.MaxMana>0)
      {
         currManaRatio:=PlayerStats.CurrMana/(PlayerStats.MaxMana-PlayerStats.ReservedManaFlat-PlayerStats.MaxMana*PlayerStats.ReservedManaPercent/100)
      }
      
      if (currLifeRatio<CurrentConfig.minLifeRatioToQuit || currNShieldRatio<CurrentConfig.minNShieldRatioToQuit)
      {
         if (autoQuitMode=0)
         {
            TrayTip, PoE autoPotions AutoQuit by closing window, specified min life reached, %A_Space% , 2
            WinKill, % "ahk_id" WinID%A_Index%
         }
         else if (autoQuitMode=1)
         {
            QuitToLoginScreen(WinID%A_Index%)         
         }
         continue
      }
      
      if (CurrentConfig.disableAutoPotions)
         continue
      
      FlasksData:=[]
      ReadFlasksData(WinID%A_Index%,FlasksData)
      
      WinGet, CurrPID, PID,  % "ahk_id" WinID%A_Index%
      hwnd:=WinID%A_Index%
      k="%hwnd%%CurrPid%"
      if (!WindowQueuedFlaskEffects.HasKey(k))
      {
         WindowQueuedFlaskEffects[k]:={}
      }
      
      if (currLifeRatio<CurrentConfig.minLifeRatioToPopGranite || currNShieldRatio<CurrentConfig.minNShieldRatioToPopGranite)
         if ((!WindowQueuedFlaskEffects[k].HasKey("graniteQueueEndtime")) || (A_TickCount>=(WindowQueuedFlaskEffects[k].graniteQueueEndtime-lagCompensation)))
            Loop, 5
               if (FlasksData[A_Index].type="FlaskUtility5") ; granite flask
               {
                  if CurrentConfig.FlaskConfig[A_Index].HasKey("OverrideFlaskDuration")
                     EffectDuration:=CurrentConfig.FlaskConfig[A_Index].OverrideFlaskDuration
                  else
                     EffectDuration:=FlasksData[A_Index].EffectDuration
                     
                  WindowQueuedFlaskEffects[k].graniteQueueEndtime:=A_TickCount+EffectDuration*100

                  if (trayNotifications)
                  {
                     pname:=PlayerStats.Name
                     TrayTip, PoE autoPotions popping Granite flask %A_Index% on %pname%, %A_Space% , 2
                  }
                  hKey:=CurrentConfig.FlaskConfig[A_Index].Hotkey
                  ControlSend,,%hkey%, % "ahk_id" hwnd
                  break
               }
               
      if (currLifeRatio=1)
         WindowQueuedFlaskEffects[k].hpQueueEndtime:=A_TickCount
      
      if (currManaRatio=1)
         WindowQueuedFlaskEffects[k].ManaQueueEndtime:=A_TickCount
      
      if (currLifeRatio<CurrentConfig.minLifeRatioToDrink || (PlayerStats.MaxHP>1 && PlayerStats.CurrHP<CurrentConfig.minLifeToDrink))
         if ((!WindowQueuedFlaskEffects[k].HasKey("hpQueueEndtime")) || (A_TickCount>=(WindowQueuedFlaskEffects[k].hpQueueEndtime-lagCompensation)))
            Loop, 5
               if (FlasksData[A_Index].HasKey("HPRegAmount"))
               {
                  if CurrentConfig.FlaskConfig[A_Index].HasKey("OverrideFlaskDuration")
                     EffectDuration:=CurrentConfig.FlaskConfig[A_Index].OverrideFlaskDuration
                  else
                     EffectDuration:=FlasksData[A_Index].EffectDuration
                  
                  if ((CurrentConfig.FlaskConfig[A_Index].instantRecoveryOnLowLife) && ((PlayerStats.CurrHP/PlayerStats.MaxHP)<=0.35)) ; "Low life" can be caused by auras hp reservation from blood magic
                     EffectDuration:=lagCompensation
                     
                  WindowQueuedFlaskEffects[k].hpQueueEndtime:=A_TickCount+EffectDuration*100
                  if (FlasksData[A_Index].HasKey("ManaRegAmount")) ; hybrid flask
                     WindowQueuedFlaskEffects[k].ManaQueueEndtime:=A_TickCount+EffectDuration*100

                  if (trayNotifications)
                  {
                     pname:=PlayerStats.Name
                     TrayTip, PoE autoPotions sipping HP flask %A_Index% on %pname%, %A_Space% , 2
                  }
                  hKey:=CurrentConfig.FlaskConfig[A_Index].Hotkey
                  ControlSend,,%hkey%, % "ahk_id" hwnd
                  break
               }

      if (PlayerStats.MaxMana>0 && (currManaRatio<CurrentConfig.minManaRatioToDrink || PlayerStats.CurrMana<CurrentConfig.minManaToDrink))      
         if ((!WindowQueuedFlaskEffects[k].HasKey("ManaQueueEndtime")) || (A_TickCount>=(WindowQueuedFlaskEffects[k].ManaQueueEndtime-lagCompensation)))
            Loop, 5
               if (FlasksData[A_Index].HasKey("ManaRegAmount"))
               {
                  if CurrentConfig.FlaskConfig[A_Index].HasKey("OverrideFlaskDuration")
                     {
                        EffectDuration:=CurrentConfig.FlaskConfig[A_Index].OverrideFlaskDuration
                     }
                  else
                     EffectDuration:=FlasksData[A_Index].EffectDuration

                  if ((CurrentConfig.FlaskConfig[A_Index].instantRecoveryOnLowLife) && ((PlayerStats.CurrHP/PlayerStats.MaxHP)<=0.35))
                     EffectDuration:=lagCompensation
                  
                  WindowQueuedFlaskEffects[k].ManaQueueEndtime:=A_TickCount+EffectDuration*100
                  if (FlasksData[A_Index].HasKey("HPRegAmount")) ; hybrid flask
                     WindowQueuedFlaskEffects[k].hpQueueEndtime:=A_TickCount+EffectDuration*100
                  
                  hKey:=CurrentConfig.FlaskConfig[A_Index].Hotkey
                  if (trayNotifications)
                  {
                     pname:=PlayerStats.Name
                     TrayTip, PoE autoPotions sipping mana flask %A_Index% on %pname%, %A_Space% , 2
                  }
                  ControlSend,,%hkey%, % "ahk_id" hwnd
                  break
               }      
   }
   Sleep, %autoPotionsWatchdogPeriod%   
}

F1::
   global autoPotionsState
   global trayNotifications
   autoPotionsState:=not autoPotionsState
   if (trayNotifications)
   {
      if (autoPotionsState=true)
         TrayTip, PoE autoPotions is on, %A_Space% , 2
      else
         TrayTip, PoE autoPotions is off, %A_Space%  , 2
   }
return

F2::
   GetClientCoords(mx,my)
   GetFractionalCoords(fx,fy)
   msgbox, mx=%mx% my=%my% fx=%fx% fy=%fy%
return

F4::
   QuitToLoginScreen(WinActive("A"))
return






AutoHotkeyMemoryLib.ahk
(!empty($user->lang['CODE'])) ? $user->lang['CODE'] : ucwords(strtolower(str_replace('_', ' ', 'CODE'))):
if (A_PtrSize != 4)
{
   MsgBox, You are not running 32-bit version of Autohotkey L, reinstall correct version. Script will now terminate.
   ExitApp   
}
GetModuleInfo(ModuleName, PID, byRef mBase="", byRef mSize="")
{
    TH32CS_SNAPMODULE := 0x00000008
    INVALID_HANDLE_VALUE = -1
    VarSetCapacity(me32, 548, 0)
    NumPut(548, me32)
   
    snapMod := DllCall("CreateToolhelp32Snapshot", "Uint", TH32CS_SNAPMODULE, "Uint", PID)
   
    If (snapMod = INVALID_HANDLE_VALUE) {
        Return 0
    }
   
    If (DllCall("Module32First", "Uint", snapMod, "Uint", &me32)){
      
      If StrGet(&me32 + 32, "cp0")=ModuleName
      {
                mBase:=NumGet(&me32 + 20)
            mSize:=NumGet(&me32 + 24)
                DllCall("CloseHandle", "UInt", snapMod)
            Return

      }
            
        while(DllCall("Module32Next", "Uint", snapMod, "UInt", &me32))
      {
            If StrGet(&me32 + 32, "cp0")=ModuleName
         {
                mBase:=NumGet(&me32 + 20)
            mSize:=NumGet(&me32 + 24)
                DllCall("CloseHandle", "UInt", snapMod)
                Return
            }
        }
    }
   
    DllCall("CloseHandle", "Uint", snapMod)
}

GetProcessHandle(pid)
{
   return DllCall("OpenProcess", "UInt", 0x10, "UInt", 0, "UInt", pid, "UInt")
}

ReadMemFloat(ProcessHandle, MADDRESS)
{
   if DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Float*",MVALUE,"UInt",4,"UInt*",0)!=0
   {
      return MVALUE
   }   
}

ReadMemUInt(ProcessHandle, MADDRESS)
{
   if DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"UInt*",MVALUE,"UInt",4,"UInt*",0)!=0
   {
      return MVALUE
   }   
}

ReadMemSInt(ProcessHandle, MADDRESS)
{
   if DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Int*",MVALUE,"UInt",4,"UInt*",0)!=0
   {
      return MVALUE
   }   
}

WriteMemUInt(ProcessHandle, MADDRESS, val)
{
   DllCall("WriteProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"UInt*",val,"UInt",4,"UInt*",0)!=0
}

WriteMemSInt(ProcessHandle, MADDRESS, val)
{
   DllCall("WriteProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Int*",val,"UInt",4,"UInt*",0)!=0
}

WriteMemFloat(ProcessHandle, MADDRESS, val)
{
   DllCall("WriteProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Float*",val,"UInt",4,"UInt*",0)!=0
}

ReadMemStr(ProcessHandle, MADDRESS, maxlen=255, cp="cp0")
{
   
   VarSetCapacity(MVALUE,maxlen)
   
   if DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"PTR",&MVALUE,"UInt",maxlen,"UInt*",bytesread)!=0
   {
      Str:=StrGet(&MVALUE,cp)
      VarSetCapacity(MVALUE,0)
      return Str
   }
   
   VarSetCapacity(MVALUE,0)   
}

GetMultilevelPointer(ProcessHandle, PARRAY)
{      
   if PARRAY._MaxIndex()<2
      return
   
   if (DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",PARRAY[1],"UInt*",currOffset,"UInt",4,"UInt*",0)!=0)   
   {

      i:=2
      while (i<=PARRAY._MaxIndex() && DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",currOffset+PARRAY[i],"UInt*",currOffset,"UInt",4,"UInt*",0)!=0)
      {
         i:=i+1
      }
      
      if (i>PARRAY._MaxIndex())
      {
         return currOffset
      }
   }
}

AobScan(ProcessHandle,mBase,mSize, ByRef patternArray)
{
   if (patternArray._MaxIndex()>mSize)
   {
      MsgBox, aobscan fail : pattern array is larger than module size
      return
   }

   VarSetCapacity(ClientCodeSegment,mSize)
   
   if (DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",mBase,"PTR",&ClientCodeSegment,"UInt",mSize,"UInt*",bytesread)!=0)
   {
      
      pLen:=patternArray._MaxIndex()      
      if (bytesread<>mSize)
      {
         VarSetCapacity(ClientCodeSegment,0)
         MsgBox, aobscan fail : mSize=%mSize%  bytesread=%bytesread%
         return
      }      
      i:=0
      
      while (i<=mSize-pLen-1)
      {
         j:=1
         while (j<=pLen)
         {
            if (patternArray[j]="?" || NumGet(ClientCodeSegment, i+j-1, "UChar")=patternArray[j])
            {
               j:=j+1
            }
            else
            {
               break
            }
         }
         
         if (j>pLen)
         {
            VarSetCapacity(ClientCodeSegment,0)
            return i
         }
         i:=i+1         
      }   
   }
   MsgBox, aobscan fail : pattern not found
   VarSetCapacity(ClientCodeSegment,0)


Reply with quote
Posted: March 20th, 2013, 7:19 pm
 
DJRockingIt

Total Posts: 19
Joined: March 11th, 2013, 9:45 am
DJRockingIt's Reps: 16
User avatar
premium
Updated to 0.10.2, besides basepointer changing, flasks pointerpath changed a bit
Updated for 0.10.3, just a basepointer change, fixed yet another minor bug with using scanned bptr right away.
Updated to 0.10.4, bptr change, player entity ptr change 0x49C > 0x51C. Fixed quit to loginscreen > client resolution ptrs shifted by +8.


Reply with quote
Posted: March 20th, 2013, 7:19 pm
 
DJRockingIt

Total Posts: 19
Joined: March 11th, 2013, 9:45 am
DJRockingIt's Reps: 16
User avatar
premium
If you like this, give me some +rep.. I want premium!!!


Reply with quote
Posted: October 27th, 2013, 3:54 pm
 
shadowtrap

Total Posts: 3
Joined: October 13th, 2013, 5:16 am
shadowtrap's Reps: 2
User avatar
well im stupid so i cant seem to figur how to work this... can it be simple??


Reply with quote
Want Advertisements After The Last Post Removed? Create A Free Account!

blue large dot Who is online
Users browsing this forum: No registered users and 3 guests

Popular Sections
SWTOR Cheats
Guild Wars 2 Cheats
Guild Wars 2 Hacks
Guild Wars 2 Bots
Diablo 3 Cheats
Guild Wars 2 Mods

Popular Sections
WoW Cataclysm Cheats & Exploits
WoW Cataclysm Hacks & Bots
Star Wars The Old Republic Cheats
SWTOR Mods
Torchlight 2 Cheats
SWTOR Space Mission Bots
Site Nav and RSS
RSS Feed of Path Of Exile Discussions | Submissions RSS Feed 
Sitemap of Path Of Exile Discussions | Submissions Sitemap 
SitemapIndex SitemapIndex
RSS Feed RSS Feed
Channel list Channel list
left bottom corner Site and Contents Copyright 2001-2012 All Rights Reserved TaultUnleashed.com bottom corner
top left
top right
createaccount
Username:   Password:   Remember Me?