Jump to content

Join our Slack

Talk to other users and have a great time
Slack Server

Welcome to our Community

Click here to get your Exiled Bot license
Donation Store
alkpone

Wrongusername's Autoflask script updated (1.0.0d)

Recommended Posts

Alk, any chance you could update these scripts again when you get a chance? I don't mind sending a few bucks your way for the the trouble. Can't stand having to spam pots all the time!

Share this post


Link to post
Share on other sites

Even though it´s not bot related, I pray it will be updated by Someone with da Brains.)

Alternatively, A feature in the bot, for elites, could be to turn of movement/attack Ai off, so that the bot would manage your pots, and in time also Granites etc..D

Share this post


Link to post
Share on other sites

Even though it´s not bot related, I pray it will be updated by Someone with da Brains.)

Alternatively, A feature in the bot, for elites, could be to turn of movement/attack Ai off, so that the bot would manage your pots, and in time also Granites etc..D

Same here. It would be an awesome elite feature, I know a lot of folks would pay for that.

Share this post


Link to post
Share on other sites

Even though it´s not bot related, I pray it will be updated by Someone with da Brains.)

Alternatively, A feature in the bot, for elites, could be to turn of movement/attack Ai off, so that the bot would manage your pots, and in time also Granites etc..D

Same here. It would be an awesome elite feature, I know a lot of folks would pay for that.

+1

Share this post


Link to post
Share on other sites

How it works exactly ?

How should i launch this script ? Do i need to install an additionnal software to launch akh script ?

Do I need to setup some values, how the script know when to trigger the granite flask for ex.?

Can it work together with the thresold value from the exiledbot ?

By advance really thanks for your help and your knowledge.

Share this post


Link to post
Share on other sites

I have tryed renaming

cliexe=PathOfExile.exe into cliexe=PathOfExileSteam.exe, but still dossent seem to work on the steam client ..

oh well, good i have both installed :)

Share this post


Link to post
Share on other sites

Can anyone outline a dummies guide to this script?

I have tried to google it up, but honestly I really just need a step by step guide. If that is possible I would be incredibly appreciative.

By the way Alk, you are the man brother :)

Share this post


Link to post
Share on other sites

How it works exactly ?

How should i launch this script ? Do i need to install an additionnal software to launch akh script ?

Do I need to setup some values, how the script know when to trigger the granite flask for ex.?

Can it work together with the thresold value from the exiledbot ?

By advance really thanks for your help and your knowledge.

Needing the same advice, too stupid to get it to work without a guide :oops:

Share this post


Link to post
Share on other sites

Requires Autohotkey_L to run

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).

Go google that, install that, get the unicode x32 version, run the script with that program, open poe, enjoy autoflask!

Share this post


Link to post
Share on other sites

It works with default configurations as expected but i'm

Wondering what I'm doing wrong with changing the config file.

It wont treat instant recovery flasks as instant... It still has a lengthy time delay between drinks.

Part I modified to try and make it work:

PlayerConfig["Default"].FlaskConfig[1]:={Hotkey:"{1 Down 1 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, } ;specify override recovery time in deciseconds, e.g. 7 seconds = 70
PlayerConfig["Default"].FlaskConfig[2]:={Hotkey:"{2 Down 2 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, }
PlayerConfig["Default"].FlaskConfig[3]:={Hotkey:"{3 Down 3 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, }
PlayerConfig["Default"].FlaskConfig[4]:={Hotkey:"{4 Down 4 UP}"} ;this is a granite flask
PlayerConfig["Default"].FlaskConfig[5]:={Hotkey:"{5 Down 5 UP}"} ;this is a mana flask

Full Config (with chicken function commented out because I don't want it):

SetBatchLines, -1
DetectHiddenWindows, On

cliname=Path of Exile
cliexe=PathOfExile.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:=100
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.65, minManaRatioToDrink: 0.35, minManaToDrink: 50, minLifeRatioToPopGranite: 0.75, minLifeRatioToQuit: 0.35} ;  disableAutoPotions:true, minLifeRatioToQuit:, minNShieldRatioToQuit: , HasZealotsOath: false, }

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

PlayerConfig["Default"].FlaskConfig[1]:={Hotkey:"{1 Down 1 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, } ;specify override recovery time in deciseconds, e.g. 7 seconds = 70
PlayerConfig["Default"].FlaskConfig[2]:={Hotkey:"{2 Down 2 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, }
PlayerConfig["Default"].FlaskConfig[3]:={Hotkey:"{3 Down 3 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, }
PlayerConfig["Default"].FlaskConfig[4]:={Hotkey:"{4 Down 4 UP}"} ;this is a granite flask
PlayerConfig["Default"].FlaskConfig[5]:={Hotkey:"{5 Down 5 UP}"} ;this is a mana flask

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

autoPotionsState:=true

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

baseMgrPtr:=0x785BB4 ; 0.11.3b 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)
      }
      
	FrameBase:=GetFrameBase(hwnd)
	if (FrameBase="" || FrameBase=0)
		return
	uiBase:=GetMultilevelPointer(pH,[FrameBase+0xBC,0xA4,0x50])
	return uiBase
}

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

ReadPlayerStats(hwnd, byRef PlayerStats)
{
   GetWindowBasics(hwnd, mBase, pH)
   fBase:=GetFrameBase(hwnd)
   PlayerBase:=GetMultilevelPointer(pH,[fBase+0xBC,0x59C])
   PlayerMain:=ReadMemUInt(pH,PlayerBase+4)
   PlayerStatsOffset:=ReadMemUInt(pH,PlayerMain+0xC)
	PlayerStats.MaxHP:=ReadMemUInt(pH,PlayerStatsOffset+0x50)
	PlayerStats.CurrHP:=ReadMemUInt(pH,PlayerStatsOffset+0x54)	
	PlayerStats.ReservedHPFlat:=ReadMemUInt(pH,PlayerStatsOffset+0x5C)
	PlayerStats.ReservedHPPercent:=ReadMemUInt(pH,PlayerStatsOffset+0x60)
	PlayerStats.MaxMana:=ReadMemUInt(pH,PlayerStatsOffset+0x74)
	PlayerStats.ReservedManaFlat:=ReadMemUInt(pH,PlayerStatsOffset+0x80)
	PlayerStats.ReservedManaPercent:=ReadMemUInt(pH,PlayerStatsOffset+0x84)
	PlayerStats.CurrMana:=ReadMemUInt(pH,PlayerStatsOffset+0x78)
	PlayerStats.MaxNShield:=ReadMemUInt(pH,PlayerStatsOffset+0x98)
	PlayerStats.CurrNShield:=ReadMemUInt(pH,PlayerStatsOffset+0x9C)
   
   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,100,"UTF-16") ;immediate name in component
   else
      PlayerStats.Name:=ReadMemStr(pH, GetMultilevelPointer(pH,[PlayerMain+0x14,0x10]),100,"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+0x8e8,0x900,0x20])

   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)
{
	if (hwnd=0 || hwnd="")
		return false
	GetWindowBasics(hwnd,mBase,pH)
	if (mBase="" || mBase=0 || pH="" || pH=-1)
		return false
	fBase:=GetFrameBase(hwnd)
	if (fBase="" || fBase=0)
		return false
	localConnection:=ReadMemUInt(pH,fBase+0xc0)
	if (localConnection=0 || localConnection="")
		return false
	else
		return true
}

SetGameStateMenu(hwnd)
{
	if (hwnd=0 || hwnd="")
		return false
	GetWindowBasics(hwnd,mBase,pH)
	if (mBase="" || mBase=0 || pH="" || pH=-1)
		return false
	fBase:=GetFrameBase(hwnd)
	if (fBase="" || fBase=0)
		return false
	localConnection:=ReadMemUInt(pH,fBase+0xc0)
	if (localConnection!="" && localConnection!=0)
	{
		WriteMemUInt(pH,localConnection+0x2578,1)
	}
}

ReadCursorScreenPosition(hwnd,ByRef cX, ByRef cY)
{
   GetWindowBasics(hwnd,mBase,pH)
   if (mBase!=0 && pH && pH!=-1)
   {
      FrameBase:=GetFrameBase(hwnd)
      cX:=ReadMemSInt(pH,FrameBase+0x155c)
      cY:=ReadMemSInt(pH,FrameBase+0x1560)
      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)
{	
	if (!IsInGame(hwnd))
	{
		return
	}
	SetGameStateMenu(hwnd)
}

GetMaxChargesFlaskOfType(ByRef FlasksData,TypeStr)
{
   currMaxCharges:=0
   Loop, 5
      if (InStr(FlasksData[A_Index].type,TypeStr))
      {
         if FlasksData[A_Index].ChargesCurrent>currMaxCharges
         {
            currMaxI:=A_Index
            currMaxCharges:=FlasksData[A_Index].ChargesCurrent
         }
      }
   return currMaxI
}

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
		 
	if (WinID%A_Index%=WinActive("A"))
	   ThisID:=WinActive("A")
      
      PlayerStats:={}
      ReadPlayerStats(WinID%A_Index%, PlayerStats)
      
      if (PlayerStats.MaxHP<1 || PlayerStats.CurrHP=0) ;dead, don't bother
         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%)
      ;   }
;autoQuit:=1
      ;   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)))
            {
               flaskNum:=GetMaxChargesFlaskOfType(FlasksData,"FlaskUtility5") ; granite flask
               if (flaskNum!="")
               {
                  if CurrentConfig.FlaskConfig[flaskNum].HasKey("OverrideFlaskDuration")
                     EffectDuration:=CurrentConfig.FlaskConfig[flaskNum].OverrideFlaskDuration
                  else
                     EffectDuration:=FlasksData[flaskNum].EffectDuration
                     
                  WindowQueuedFlaskEffects[k].graniteQueueEndtime:=A_TickCount+EffectDuration*100

                  if (trayNotifications)
                  {
                     pname:=PlayerStats.Name
                     TrayTip, PoE autoPotions popping Granite flask %flaskNum% on %pname%, %A_Space% , 2
                  }
                  hKey:=CurrentConfig.FlaskConfig[flaskNum].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.CurrHP<CurrentConfig.minLifeToDrink))
         if ((!WindowQueuedFlaskEffects[k].HasKey("hpQueueEndtime")) || (A_TickCount>=(WindowQueuedFlaskEffects[k].hpQueueEndtime-lagCompensation)))
         {
                  tflaskNum1:=GetMaxChargesFlaskOfType(FlasksData,"FlaskLife")
                  tflaskNum2:=GetMaxChargesFlaskOfType(FlasksData,"FlaskHybrid")
                  if ((tflaskNum1!=) && (tflaskNum2!=))
                     flaskNum:=(FlasksData[tflaskNum1].ChargesCurrent>FlasksData[tflaskNum2].ChargesCurrent) ? tflaskNum1 : tflaskNum2
                  else
                  {
                     if (tflaskNum1!="")
                        flaskNum:=tflaskNum1
                     if (tflaskNum2!="")
                        flaskNum:=tflaskNum2
                  }
                  if (flaskNum!="")
                  {
                     if CurrentConfig.FlaskConfig[flaskNum].HasKey("OverrideFlaskDuration")
                        EffectDuration:=CurrentConfig.FlaskConfig[flaskNum].OverrideFlaskDuration
                     else
                        EffectDuration:=FlasksData[flaskNum].EffectDuration
                     
                     if ((CurrentConfig.FlaskConfig[flaskNum].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[flaskNum].HasKey("ManaRegAmount")) ; hybrid flask
                        WindowQueuedFlaskEffects[k].ManaQueueEndtime:=A_TickCount+EffectDuration*100

                     if (trayNotifications)
                     {
                        pname:=PlayerStats.Name
                        TrayTip, PoE autoPotions sipping HP flask %flaskNum% on %pname%, %A_Space% , 2
                     }
                     hKey:=CurrentConfig.FlaskConfig[flaskNum].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)))
         {
               tflaskNum1:=GetMaxChargesFlaskOfType(FlasksData,"FlaskMana")
               tflaskNum2:=GetMaxChargesFlaskOfType(FlasksData,"FlaskHybrid")
               
               if ((tflaskNum1!=) && (tflaskNum2!=))
                  flaskNum:=(FlasksData[tflaskNum1].ChargesCurrent>FlasksData[tflaskNum2].ChargesCurrent) ? tflaskNum1 : tflaskNum2
               else
               {
                  if (tflaskNum1!="")
                     flaskNum:=tflaskNum1
                  if (tflaskNum2!="")
                     flaskNum:=tflaskNum2
               }

               if (flaskNum!="")
               {
                  if CurrentConfig.FlaskConfig[flaskNum].HasKey("OverrideFlaskDuration")
                     {
                        EffectDuration:=CurrentConfig.FlaskConfig[flaskNum].OverrideFlaskDuration
                     }
                  else
                     EffectDuration:=FlasksData[flaskNum].EffectDuration

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

   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

Share this post


Link to post
Share on other sites

It works with default configurations as expected but i'm

Wondering what I'm doing wrong with changing the config file.

It wont treat instant recovery flasks as instant... It still has a lengthy time delay between drinks.

Part I modified to try and make it work:

PlayerConfig["Default"].FlaskConfig[1]:={Hotkey:"{1 Down 1 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, } ;specify override recovery time in deciseconds, e.g. 7 seconds = 70
PlayerConfig["Default"].FlaskConfig[2]:={Hotkey:"{2 Down 2 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, }
PlayerConfig["Default"].FlaskConfig[3]:={Hotkey:"{3 Down 3 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, }
PlayerConfig["Default"].FlaskConfig[4]:={Hotkey:"{4 Down 4 UP}"} ;this is a granite flask
PlayerConfig["Default"].FlaskConfig[5]:={Hotkey:"{5 Down 5 UP}"} ;this is a mana flask

Full Config (with chicken function commented out because I don't want it):

SetBatchLines, -1
DetectHiddenWindows, On

cliname=Path of Exile
cliexe=PathOfExile.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:=100
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.65, minManaRatioToDrink: 0.35, minManaToDrink: 50, minLifeRatioToPopGranite: 0.75, minLifeRatioToQuit: 0.35} ;  disableAutoPotions:true, minLifeRatioToQuit:, minNShieldRatioToQuit: , HasZealotsOath: false, }

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

PlayerConfig["Default"].FlaskConfig[1]:={Hotkey:"{1 Down 1 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, } ;specify override recovery time in deciseconds, e.g. 7 seconds = 70
PlayerConfig["Default"].FlaskConfig[2]:={Hotkey:"{2 Down 2 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, }
PlayerConfig["Default"].FlaskConfig[3]:={Hotkey:"{3 Down 3 UP}" , OverrideFlaskDuration:0, instantRecoveryOnLowLife:true, }
PlayerConfig["Default"].FlaskConfig[4]:={Hotkey:"{4 Down 4 UP}"} ;this is a granite flask
PlayerConfig["Default"].FlaskConfig[5]:={Hotkey:"{5 Down 5 UP}"} ;this is a mana flask

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

autoPotionsState:=true

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

baseMgrPtr:=0x785BB4 ; 0.11.3b 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)
      }
      
	FrameBase:=GetFrameBase(hwnd)
	if (FrameBase="" || FrameBase=0)
		return
	uiBase:=GetMultilevelPointer(pH,[FrameBase+0xBC,0xA4,0x50])
	return uiBase
}

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

ReadPlayerStats(hwnd, byRef PlayerStats)
{
   GetWindowBasics(hwnd, mBase, pH)
   fBase:=GetFrameBase(hwnd)
   PlayerBase:=GetMultilevelPointer(pH,[fBase+0xBC,0x59C])
   PlayerMain:=ReadMemUInt(pH,PlayerBase+4)
   PlayerStatsOffset:=ReadMemUInt(pH,PlayerMain+0xC)
	PlayerStats.MaxHP:=ReadMemUInt(pH,PlayerStatsOffset+0x50)
	PlayerStats.CurrHP:=ReadMemUInt(pH,PlayerStatsOffset+0x54)	
	PlayerStats.ReservedHPFlat:=ReadMemUInt(pH,PlayerStatsOffset+0x5C)
	PlayerStats.ReservedHPPercent:=ReadMemUInt(pH,PlayerStatsOffset+0x60)
	PlayerStats.MaxMana:=ReadMemUInt(pH,PlayerStatsOffset+0x74)
	PlayerStats.ReservedManaFlat:=ReadMemUInt(pH,PlayerStatsOffset+0x80)
	PlayerStats.ReservedManaPercent:=ReadMemUInt(pH,PlayerStatsOffset+0x84)
	PlayerStats.CurrMana:=ReadMemUInt(pH,PlayerStatsOffset+0x78)
	PlayerStats.MaxNShield:=ReadMemUInt(pH,PlayerStatsOffset+0x98)
	PlayerStats.CurrNShield:=ReadMemUInt(pH,PlayerStatsOffset+0x9C)
   
   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,100,"UTF-16") ;immediate name in component
   else
      PlayerStats.Name:=ReadMemStr(pH, GetMultilevelPointer(pH,[PlayerMain+0x14,0x10]),100,"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+0x8e8,0x900,0x20])

   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)
{
	if (hwnd=0 || hwnd="")
		return false
	GetWindowBasics(hwnd,mBase,pH)
	if (mBase="" || mBase=0 || pH="" || pH=-1)
		return false
	fBase:=GetFrameBase(hwnd)
	if (fBase="" || fBase=0)
		return false
	localConnection:=ReadMemUInt(pH,fBase+0xc0)
	if (localConnection=0 || localConnection="")
		return false
	else
		return true
}

SetGameStateMenu(hwnd)
{
	if (hwnd=0 || hwnd="")
		return false
	GetWindowBasics(hwnd,mBase,pH)
	if (mBase="" || mBase=0 || pH="" || pH=-1)
		return false
	fBase:=GetFrameBase(hwnd)
	if (fBase="" || fBase=0)
		return false
	localConnection:=ReadMemUInt(pH,fBase+0xc0)
	if (localConnection!="" && localConnection!=0)
	{
		WriteMemUInt(pH,localConnection+0x2578,1)
	}
}

ReadCursorScreenPosition(hwnd,ByRef cX, ByRef cY)
{
   GetWindowBasics(hwnd,mBase,pH)
   if (mBase!=0 && pH && pH!=-1)
   {
      FrameBase:=GetFrameBase(hwnd)
      cX:=ReadMemSInt(pH,FrameBase+0x155c)
      cY:=ReadMemSInt(pH,FrameBase+0x1560)
      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)
{	
	if (!IsInGame(hwnd))
	{
		return
	}
	SetGameStateMenu(hwnd)
}

GetMaxChargesFlaskOfType(ByRef FlasksData,TypeStr)
{
   currMaxCharges:=0
   Loop, 5
      if (InStr(FlasksData[A_Index].type,TypeStr))
      {
         if FlasksData[A_Index].ChargesCurrent>currMaxCharges
         {
            currMaxI:=A_Index
            currMaxCharges:=FlasksData[A_Index].ChargesCurrent
         }
      }
   return currMaxI
}

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
		 
	if (WinID%A_Index%=WinActive("A"))
	   ThisID:=WinActive("A")
      
      PlayerStats:={}
      ReadPlayerStats(WinID%A_Index%, PlayerStats)
      
      if (PlayerStats.MaxHP<1 || PlayerStats.CurrHP=0) ;dead, don't bother
         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%)
      ;   }
;autoQuit:=1
      ;   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)))
            {
               flaskNum:=GetMaxChargesFlaskOfType(FlasksData,"FlaskUtility5") ; granite flask
               if (flaskNum!="")
               {
                  if CurrentConfig.FlaskConfig[flaskNum].HasKey("OverrideFlaskDuration")
                     EffectDuration:=CurrentConfig.FlaskConfig[flaskNum].OverrideFlaskDuration
                  else
                     EffectDuration:=FlasksData[flaskNum].EffectDuration
                     
                  WindowQueuedFlaskEffects[k].graniteQueueEndtime:=A_TickCount+EffectDuration*100

                  if (trayNotifications)
                  {
                     pname:=PlayerStats.Name
                     TrayTip, PoE autoPotions popping Granite flask %flaskNum% on %pname%, %A_Space% , 2
                  }
                  hKey:=CurrentConfig.FlaskConfig[flaskNum].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.CurrHP<CurrentConfig.minLifeToDrink))
         if ((!WindowQueuedFlaskEffects[k].HasKey("hpQueueEndtime")) || (A_TickCount>=(WindowQueuedFlaskEffects[k].hpQueueEndtime-lagCompensation)))
         {
                  tflaskNum1:=GetMaxChargesFlaskOfType(FlasksData,"FlaskLife")
                  tflaskNum2:=GetMaxChargesFlaskOfType(FlasksData,"FlaskHybrid")
                  if ((tflaskNum1!=) && (tflaskNum2!=))
                     flaskNum:=(FlasksData[tflaskNum1].ChargesCurrent>FlasksData[tflaskNum2].ChargesCurrent) ? tflaskNum1 : tflaskNum2
                  else
                  {
                     if (tflaskNum1!="")
                        flaskNum:=tflaskNum1
                     if (tflaskNum2!="")
                        flaskNum:=tflaskNum2
                  }
                  if (flaskNum!="")
                  {
                     if CurrentConfig.FlaskConfig[flaskNum].HasKey("OverrideFlaskDuration")
                        EffectDuration:=CurrentConfig.FlaskConfig[flaskNum].OverrideFlaskDuration
                     else
                        EffectDuration:=FlasksData[flaskNum].EffectDuration
                     
                     if ((CurrentConfig.FlaskConfig[flaskNum].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[flaskNum].HasKey("ManaRegAmount")) ; hybrid flask
                        WindowQueuedFlaskEffects[k].ManaQueueEndtime:=A_TickCount+EffectDuration*100

                     if (trayNotifications)
                     {
                        pname:=PlayerStats.Name
                        TrayTip, PoE autoPotions sipping HP flask %flaskNum% on %pname%, %A_Space% , 2
                     }
                     hKey:=CurrentConfig.FlaskConfig[flaskNum].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)))
         {
               tflaskNum1:=GetMaxChargesFlaskOfType(FlasksData,"FlaskMana")
               tflaskNum2:=GetMaxChargesFlaskOfType(FlasksData,"FlaskHybrid")
               
               if ((tflaskNum1!=) && (tflaskNum2!=))
                  flaskNum:=(FlasksData[tflaskNum1].ChargesCurrent>FlasksData[tflaskNum2].ChargesCurrent) ? tflaskNum1 : tflaskNum2
               else
               {
                  if (tflaskNum1!="")
                     flaskNum:=tflaskNum1
                  if (tflaskNum2!="")
                     flaskNum:=tflaskNum2
               }

               if (flaskNum!="")
               {
                  if CurrentConfig.FlaskConfig[flaskNum].HasKey("OverrideFlaskDuration")
                     {
                        EffectDuration:=CurrentConfig.FlaskConfig[flaskNum].OverrideFlaskDuration
                     }
                  else
                     EffectDuration:=FlasksData[flaskNum].EffectDuration

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

   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

I figured out the problem...

Working:

PlayerConfig["Default"].FlaskConfig[1]:={Hotkey:"{1 Down 1 UP}"  ,OverrideFlaskDuration:1, instantRecoveryOnLowLife:true } ;specify override recovery time in deciseconds, e.g. 7 seconds = 70
PlayerConfig["Default"].FlaskConfig[2]:={Hotkey:"{2 Down 2 UP}"  ,OverrideFlaskDuration:1, instantRecoveryOnLowLife:true } ;specify override recovery time in deciseconds, e.g. 7 seconds = 70
PlayerConfig["Default"].FlaskConfig[3]:={Hotkey:"{3 Down 3 UP}"  ,OverrideFlaskDuration:1, instantRecoveryOnLowLife:true } ;specify override recovery time in deciseconds, e.g. 7 seconds = 70
PlayerConfig["Default"].FlaskConfig[4]:={Hotkey:"{4 Down 4 UP}"} ;this is a granite flask
PlayerConfig["Default"].FlaskConfig[5]:={Hotkey:"{5 Down 5 UP}"} ;this is a mana flask

The problem was caused by the extra comma at the end here

PlayerConfig["Default"].FlaskConfig[1]:={Hotkey:"{1 Down 1 UP}"} ; ,OverrideFlaskDuration:70, instantRecoveryOnLowLife:true, } ;specify override recovery time in

delete that comma and delete the semicolon after {Hotkey:"{1 Down 1 UP}"}, set your time in deciseconds and it works.

why that last comma was there to begin with is beyond me... It's in the original source.

I also had to increase time to drink to 1 from 0 because 0 would double drink potions sometimes without need for doing so. Lag issue probably. Setting to 1 works.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...