Code:
SetBatchLines, -1
DetectHiddenWindows, On
cliname=Path of Exile
cliexe=PathOfExile.exe
trayNotifications:=true ;display tray notifications about script actions : drinking potions, autoquitting
autoPotionsWatchdogPeriod:=10 ;milliseconds, decrease this value to have script recheck life/mana/flasks availability more often/increase chances of getting saved from death in time
lagCompensation:=20
autoQuitMode:=1 ; default autoQuit method : 0 =winKill, 1 = exit to login screen, 2 = exit to character selection, 3 = Use Portal
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.80, minManaToDrink: 50, minLifeRatioToPopGranite: 0.65, minLifeRatioToPopJade: 0.65, minLifeRatioToQuit: 0.40} ; disableAutoPotions:true, minNShieldRatioToPopGranite: , minLifeRatioToPopJade: , minNShieldRatioToPopJade: , minNShieldRatioToQuit: , HasZealotsOath: false, }
PlayerConfig["Default"].FlaskConfig:=[]
PlayerConfig["Default"].FlaskConfig[1]:={Hotkey:"{1 Down 1 UP}"} ; ,OverrideFlaskDuration: 70, instantRecoveryOnLowLife:true, } ;specify override recovery time in deciseconds, e.g. 7 seconds = 70
PlayerConfig["Default"].FlaskConfig[2]:={Hotkey:"{2 Down 2 UP}"}
PlayerConfig["Default"].FlaskConfig[3]:={Hotkey:"{3 Down 3 UP}"}
PlayerConfig["Default"].FlaskConfig[4]:={Hotkey:"{4 Down 4 UP}"}
PlayerConfig["Default"].FlaskConfig[5]:={Hotkey:"{5 Down 5 UP}"}
PlayerConfig["YourHardcorePlayerName"]:={minLifeRatioToDrink: 0.75, minManaRatioToDrink: 0.25, minManaToDrink: 10, minLifeRatioToPopGranite: 0.80, minLifeRatioToPopJade: 0.80, minLifeRatioToQuit: 0.35}
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:= ;1.0.1b delete for script to try to auto-scan for it in newer versions, scan takes 4-5 seconds
basePtrAoBArray:=[0x53,0x55,0x56,0x57,0x33,0xFF,0x3B,0xC7]
basePtrAobOffset:=-0x0A
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
TrayTip, Autoflask Script Attached, baseMgrPtr = %baseMgrPtr%
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+0x1458)
h:=ReadMemUInt(pH,FrameBase+0x145C)
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+0x968,0x980,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, "FlaskLife")
{
FlasksData[A_Index].HPRegAmount:=ReadMemUInt(pH,FlaskLocalstatsPtr+4)
FlasksData[A_Index].EffectDuration:=ReadMemUInt(pH,FlaskLocalstatsPtr+0xC)
}
if InStr(FlaskTypeStr, "FlaskMana")
{
FlasksData[A_Index].ManaRegAmount:=ReadMemUInt(pH,FlaskLocalstatsPtr+4)
FlasksData[A_Index].EffectDuration:=ReadMemUInt(pH,FlaskLocalstatsPtr+0xC)
}
if InStr(FlaskTypeStr, "FlaskHybrid")
{
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+0x2678,1)
}
}
ReadHeroPos(hwnd,ByRef x, ByRef y)
{
GetWindowBasics(hwnd,mBase,pH)
if (mBase!=0 && pH && pH!=-1)
{
FrameBase:=GetFrameBase(hwnd)
x:=ReadMemFloat(pH,FrameBase+0x16ac)
y:=ReadMemFloat(pH,FrameBase+0x16b0)
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) ; x 580 y 435
}
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%)
}
else if (autoQuitMode=2)
{
ExitToCharacterSelection()
}
else if (autoQuitMode=3)
{
UsePortal()
}
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<CurrentConfig.minLifeRatioToPopJade || currNShieldRatio<CurrentConfig.minNShieldRatioToPopJade)
if ((!WindowQueuedFlaskEffects[k].HasKey("jadeQueueEndtime")) || (A_TickCount>=(WindowQueuedFlaskEffects[k].jadeQueueEndtime-lagCompensation)))
{
flaskNum:=GetMaxChargesFlaskOfType(FlasksData,"FlaskUtility9") ; jade flask
if (flaskNum!="")
{
if CurrentConfig.FlaskConfig[flaskNum].HasKey("OverrideFlaskDuration")
EffectDuration:=CurrentConfig.FlaskConfig[flaskNum].OverrideFlaskDuration
else
EffectDuration:=FlasksData[flaskNum].EffectDuration
WindowQueuedFlaskEffects[k].jadeQueueEndtime:=A_TickCount+EffectDuration*100
if (trayNotifications)
{
pname:=PlayerStats.Name
TrayTip, PoE autoPotions popping Jade 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%
}
UsePortal()
{
BlockInput On
SendMode Input
hwnd:=WinActive("A")
GetKeyState, stateR, RButton, P
if stateR = D
{
Send {RButton up}
}
GetKeyState, stateL, LButton, P
if stateL = D
{
Send {LButton up}
}
GetKeyState, stateM, MButton, P
if stateM = D
{
Send {MButton up}
}
GetKeyState, stateQ, Q, P
if stateQ = D
{
Send {Q up}
}
GetKeyState, stateW, W, P
if stateW = D
{
Send {W up}
}
GetKeyState, stateE, E, P
if stateE = D
{
Send {E up}
}
GetKeyState, stateR, R, P
if stateR = D
{
Send {R up}
}
GetKeyState, stateT, T, P
if stateT = D
{
Send {T up}
}
GetKeyState, stateI, I, P
if stateI = D
{
Send {I up}
}
GetKeyState, stateSP, SPACE, P
if stateSP = D
{
Send {SPACE up}
}
GetKeyState, stateSH, SHIFT, P
if stateSH = D
{
Send {SHIFT up}
}
ReadClientResolution(hwnd,w,h)
Send {SPACE}
Send {ENTER}
Send {Raw} /oos
Send {ENTER}
Send {i}
ErrorLevel = 1
Sleep, 50
PixelSearch, ScrollX, ScrollY, w/2, h/2, w, h, 0xFFFFFF, 0, fast
If ErrorLevel = 0
MouseMove, (ScrollX), (ScrollY),0
else
{
BlockInput Off
return
}
Send {RButton}
Send {SPACE}
Sleep, 50
MouseMove, (w/2), (h/2),0
Sleep, 50
Send {LButton}
sleep, 250
Loop
{
ErrorLevel = 1
PixelSearch, PixX, PixY, (w/4), (h/10), ((w/4)*3), h, 0xddbb30, 34, fast ;0xdcc8c8 text color
if ErrorLevel = 0
{
MouseMove, (PixX), (PixY),0
Sleep, 20
Send {LButton}
Loop ;only search for portals when not moving
{
ReadHeroPos(hwnd,PosX1,PosY1)
sleep, 30
ReadHeroPos(hwnd,PosX2,PosY2)
if PosX1 = %PosX2%
{
If PosY1 = %PosY2%
{
break
}
}
else
sleep, 30
}
}
else
{
Break
}
}
Sleep, 50
MouseMove, (w/2), (h/2),0
Sleep, 50
Send {LButton}
Sleep, 50
BlockInput Off
}
ExitToCharacterSelection()
{
BlockInput On
SendMode Input
hwnd:=WinActive("A")
GetKeyState, stateR, RButton, P
if stateR = D
{
Send {RButton up}
}
GetKeyState, stateL, LButton, P
if stateL = D
{
Send {LButton up}
}
GetKeyState, stateM, MButton, P
if stateM = D
{
Send {MButton up}
}
GetKeyState, stateQ, Q, P
if stateQ = D
{
Send {Q up}
}
GetKeyState, stateW, W, P
if stateW = D
{
Send {W up}
}
GetKeyState, stateE, E, P
if stateE = D
{
Send {E up}
}
GetKeyState, stateR, R, P
if stateR = D
{
Send {R up}
}
GetKeyState, stateT, T, P
if stateT = D
{
Send {T up}
}
GetKeyState, stateI, I, P
if stateI = D
{
Send {I up}
}
GetKeyState, stateSP, SPACE, P
if stateSP = D
{
Send {SPACE up}
}
GetKeyState, stateSH, SHIFT, P
if stateSH = D
{
Send {SHIFT up}
}
Send {SPACE}
Send {ESC}
ReadClientResolution(hwnd,w,h)
MouseMove, (w/2), ((h/2)- ((h-674.4)/6.24)) ;Might have to change the height in this line to work.
Send {LButton}
Sleep, 500
BlockInput Off
}
TradeChat()
{
BlockInput On
SendMode Input
loop
{
Send {ENTER}
Send /trade %A_Index%
Send {ENTER}
Send {ENTER}
Send {Up 2}
Sleep, 150
Send {ENTER}
If A_Index = 10
Break
else
Sleep, 100
}
BlockInput Off
}
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::
UsePortal()
return
F3::
ExitToCharacterSelection()
return
F4::
QuitToLoginScreen(WinActive("A"))
return
F10::
TradeChat()
return