Code:
#WinActivateForce
;warn
global FAddress := "0x00A43F04" ; Defailt address.
global IniFile := "NippysFishBot.ini" ;Save Filename
global BotList := Object() ;The array where the clients are added.
;Global ClientsListtoRecast := Object() ;buffer Array for recast.
;Global ReportedIDs = Object() ;Budder away for hung/not fishing clients.
;Ini Settings load.
IfNotExist, %A_ScriptDir%/%IniFile%
{
;Default Settings.
IniWrite, %FAddress%, %A_ScriptDir%/%IniFile%, Nippys Fish Bot, Offset
}
IniRead, FAddress, %A_ScriptDir%/%IniFile%, Nippys Fish Bot, Offset
;InitialSetup so it does not get ran again. Its not neded but make it look more pro.
If !InitialSetup
{
;Making sure it is ran as admin.
If NOT A_IsAdmin
{
Run *RunAs "%A_ScriptFullPath%"
ExitApp
}
;Switchs toggle to on
FishBiteMemoryScanToggle := !FishBiteMemoryScanToggle
SetTimer, ActiveClientScan, 5000
;Starts Memory Scan/Recast buffer.
SetTimer, FishBiteMemoryScan, 1000
SetTimer, Recast, 4000
InitialSetup = 1
Goto, ActiveClientScan
}
NumpadMult::Reload
;Debugging stuff.
Numpad4::
Text =
for index, element in BotList
{
Text .= "`n`nIndexMain:[" . index . "]`n"
for index2, element2 in BotList[index]
{
Text .= "Index: [" . index2 . "] Element:[" . element2 . "]`n"
for index3, element3 in BotList[index][index]
{
Text .= "Index: [" . index3 . "] of [" . index2 . "] Element:[" . element3 . "]`n"
}
}
}
ToolTipDisplay(Text)
Return
NumPad1:: ;Sart and stop Fishing for active foreground client.
;Getting the pID and Handle that is used for memory scans.
WinGet, pidn, PID, A
pID := pidn
WinGet, hwnds, ID, A
Handle := hwnds
;First cast also to detect liquid type.
ControlSend, , {f down}, ahk_pid %pID%
RandSleep(86,100)
ControlSend, , {f up}, ahk_pid %pID%
;Setting up addresses for Memory scan
Base := getProcessBaseAddress(Handle)
WaterAddress := GetAddressWater(Base, FAddress, pid)
Sleep 200
LavaAddress := GetAddressLava(Base, FAddress, pid)
ChocoAddress := GetAddressChoco(Base, FAddress, pid)
Sleep 200
GetFishingStateWaterAddress := GetFishingStateWaterAddress(Base, FAddress, pid)
GetFishingStateLavaAddress := GetFishingStateLavaAddress(Base, FAddress, pid)
Sleep 200
GetFishingStateChocoAddress := GetFishingStateChocoAddress(Base, FAddress, pid)
;Detecting Liquid type via memory read.
DetectedLiquidType := 0 ;Default = for unknown type.
If (ReadMemory(GetFishingStateWaterAddress,pid) = 1)
DetectedLiquidType := 1
Else If (ReadMemory(GetFishingStateLavaAddress,pid) = 1)
DetectedLiquidType := 2
Else If (ReadMemory(GetFishingStateChocoAddress,pid) = 1)
DetectedLiquidType := 3
;Adding bot to botlist array
StartTime := a_now
LastReelCast := a_now
ActiveFishing := 1 ;Turns it on.
Recast := 0
ErrorCount := 0
ReelinCount := 0
RecastCount := 0
;Updating Bot List with new info
for index, element in BotList
{
;Searching for pID match to know which bot to update with memory info.
If (BotList[index, 1] = pID)
{
;BotList[index, 1] := pID ;These get added by auto detect client
;BotList[index, 2] := Handle ;These get added by auto detect client
BotList[index, 3] := Base
BotList[index, 4] := WaterAddress
BotList[index, 5] := LavaAddress
BotList[index, 6] := ChocoAddress
BotList[index, 7] := StartTime
BotList[index, 8] := LastReelCast
BotList[index, 9] := GetFishingStateWaterAddress
BotList[index, 10] := GetFishingStateLavaAddress
BotList[index, 11] := GetFishingStateChocoAddress
BotList[index, 12] := DetectedLiquidType
BotList[index, 13] := ActiveFishing
BotList[index, 14] := Recast
BotList[index, 15] := ErrorCount
;BotList[index, 16] := ClientDetectedTime ;These get added by auto detect client
BotList[index, 17] := ReelinCount ; Total Cought?
BotList[index, 18] := RecastCount ; Recast Counter to be used to tell if it is over using lures.
}
}
If (DetectedLiquidType = 1) ;Water found scan only water type
LiquidType = Water
Else If (DetectedLiquidType = 2) ;Lava found scan only lava type
LiquidType = Lava
Else If (DetectedLiquidType = 3) ;Choco found only scan Choco type
LiquidType = Chocolate
Else
LiquidType = Unknown
ToolTipDisplay("This Client has started fishing.`npID: [" . pid . "] Liquid type: [" . LiquidType . "]")
Return
^NumPad1::
ToolTipDisplay("Mass fishing started. Please wait...")
Clientlist =
WinGet, TroveList, List, ahk_exe trove.exe
While TroveList%a_index%
{
WinGet, pid, PID, % "ahk_id " TroveList%a_index%
WinGet, Handle, ID, % "ahk_id " TroveList%a_index%
;First cast also to detect liquid type.
RandSleep(100,200)
ControlSend, , {f down}, ahk_pid %pid%
RandSleep(86,100)
ControlSend, , {f up}, ahk_pid %pid%
Sleep 400
;Setting up addresses for next scan.
Base := getProcessBaseAddress(Handle)
WaterAddress := GetAddressWater(Base, FAddress, pid)
Sleep 100
LavaAddress := GetAddressLava(Base, FAddress, pid)
ChocoAddress := GetAddressChoco(Base, FAddress, pid)
Sleep 100
GetFishingStateWaterAddress := GetFishingStateWaterAddress(Base, FAddress, pid)
GetFishingStateLavaAddress := GetFishingStateLavaAddress(Base, FAddress, pid)
Sleep 100
GetFishingStateChocoAddress := GetFishingStateChocoAddress(Base, FAddress, pid)
Sleep 200
;Detecting Liquid type via memory read.
DetectedLiquidType := 0 ;Default = for unknown type.
If (ReadMemory(GetFishingStateWaterAddress,pid) = 1)
DetectedLiquidType := 1
Else If (ReadMemory(GetFishingStateLavaAddress,pid) = 1)
DetectedLiquidType := 2
Else If (ReadMemory(GetFishingStateChocoAddress,pid) = 1)
DetectedLiquidType := 3
;Adding bot to botlist array
;Adding bot to botlist array
StartTime := a_now
LastReelCast := a_now
ActiveFishing := 1 ;Turns it on.
Recast := 0
ErrorCount := 0
ReelinCount := 0
RecastCount := 0
;Updating Bot List with new info
for index, element in BotList
{
;Searching for pID match to know which bot to update with memory info.
If (BotList[index, 1] = pID)
{
;BotList[index, 1] := pID ;These get added by auto detect client
;BotList[index, 2] := Handle ;These get added by auto detect client
BotList[index, 3] := Base
BotList[index, 4] := WaterAddress
BotList[index, 5] := LavaAddress
BotList[index, 6] := ChocoAddress
BotList[index, 7] := StartTime
BotList[index, 8] := LastReelCast
BotList[index, 9] := GetFishingStateWaterAddress
BotList[index, 10] := GetFishingStateLavaAddress
BotList[index, 11] := GetFishingStateChocoAddress
BotList[index, 12] := DetectedLiquidType
BotList[index, 13] := ActiveFishing
BotList[index, 14] := Recast
BotList[index, 15] := ErrorCount
;BotList[index, 16] := ClientDetectedTime ;These get added by auto detect client
BotList[index, 17] := ReelinCount ; Total Cought?
BotList[index, 18] := RecastCount ; Recast Counter to be used to tell if it is over using lures.
}
}
;This to change the detectedliqidtype from a number to the word for displaying
If (DetectedLiquidType = 1) ;Water found scan only water type
LiquidType = Water
Else If (DetectedLiquidType = 2) ;Lava found scan only lava type
LiquidType = Lava
Else If (DetectedLiquidType = 3) ;Choco found only scan Choco type
LiquidType = Chocolate
Else
LiquidType = Unknown
Clientlist .= "pID: [" . pid . "] Liquid type: [" . LiquidType . "]`n"
}
ToolTipDisplay("Mass start fishing finshed.`n`nThe followling clients have started fishing.`n" . Clientlist)
Return
NumPad3::
RemoveClient:
;To remove active window from client list.
WinGet, pidn, PID, A
pid := pidn
WinGet, hwnds, ID, A
Handle := hwnds
for index, element in BotList
{
If (BotList[index][1] = pid)
{
BotList[index][13] := 0
ToolTipDisplay("This client has been deactivated from fishing.`nIndexID: [" . index . "] pID: [" . pid . "]")
Return
}
}
ToolTipDisplay("This client was not set to active fishing.`npID: [" . pid . "]")
Return
^NumPad3::
global BotList := Object()
ToolTipDisplay("Removed all clients from client the list." )
Return
+^NumPadSub::
If !FishBiteMemoryScanToggle {
SetTimer, FishBiteMemoryScan, 1000
SetTimer, Recast, 2000
SoundPlay, %A_WinDir%\Media\Windows Ding.wav
} Else {
SetTimer, FishBiteMemoryScan, Off
SetTimer, Recast, Off
SoundPlay, %A_WinDir%\Media\Windows Ding.wav
Sleep 100
SoundPlay, %A_WinDir%\Media\Windows Ding.wav
}
FishBiteMemoryScanToggle := !FishBiteMemoryScanToggle
Return
ActiveClientScan:
WinGet, TroveList, List, ahk_exe trove.exe ;Scans all trove.exe files and adds to array
While TroveList%a_index% ;Loops the array.
{
WinGet, pID, PID, % "ahk_id " TroveList%a_index%
WinGet, Handle, ID, % "ahk_id " TroveList%a_index%
If (pID = "" or Handle = "")
Return
TotalClientsOnList := BotList.MaxIndex()
;If(TotalClientsOnList = "")
; TotalClientsOnList := 1
AddClient := 1
Loop, %TotalClientsOnList%
{
If (BotList[a_index, 1] = pID) {
AddClient = 0
}
}
If (AddClient = 1) {
;Adding bot to botlist array
ClientDetectedTime := a_now
BotList.Insert(Array(pID ,Handle, "0", "0", "0", "0", "0", "0", "0", "0", "0" ,"0" ,"0", "0", "0" ,ClientDetectedTime))
TotalClientsOnList := BotList.MaxIndex()
ToolTipDisplay("New Trove client window found. Added the follow to the client list.`npID: [" . pid . "]`n`nTotal Clients Detected:[" . TotalClientsOnList . "]")
}
}
Return
FishBiteMemoryScan:
for index, element in BotList
{
;TotalClientsOnList := BotList.MaxIndex()
;loop, %TotalClientsOnList%
; {
;index := a_index
;Setting Current time of scan. Used to compair for bot erro han
CurrentTime = %a_now%
WinID :=
;Checking to make sure the next scan that the client is running. If not found it will auto remove form the list and move on to next.
WinID := BotList[index, 2]
;If (WinID = "")
; Return
IfWinNotExist, ahk_id %WinID%
{
ToolTipDisplay("Client no longer found Removing.`nIndexID: [" . index . "] pID: [" . BotList[index, 1] . "]")
BotList.Remove(index)
Return
}
WinGetTitle, CurrentTitle, % "ahk_pid " BotList[index, 1] ;Lets get the current title name.
If (BotList[index, 13] = 1) ; Checking ot make sure the fishing flag and the recast flag are both set to 1 being on.
{
;Fishing is Active on pID
NewTitle := "pID:[" . BotList[index, 1] . "] Fishing Active:[Yes]"
If (NewTitle <> CurrentTitle)
WinSetTitle, % "ahk_pid " BotList[index, 1], , % NewTitle
} Else {
;Fishing is not active on pID
NewTitle := "pID:[" . BotList[index, 1] . "] Fishing Active:[No]"
If (NewTitle <> CurrentTitle)
WinSetTitle, % "ahk_pid " BotList[index, 1], , % "pID:[" . pID . "] Fishing Active:[No]"
}
;Checking if bot the bot to make sure it has the active fish flag. If set 0 means it is not fishing. So returns to do next scan.
If (BotList[index, 13] <> 0)
{
;Checking last cast on record with currnet time.
LastCastTime := BotList[index, 8]
EnvSub, CurrentTime, LastCastTime, Seconds ;Converting last last cast time to Seconds.
;Error handling to check to make sure it is still fishing.
If (8 < CurrentTime && CurrentTime < 11 or 45 < CurrentTime)
{
FishingState := "0"
;Checking all 3 fishing states.
CaughtFishingStateWater := ReadMemory(BotList[index, 9],BotList[index, 1])
CaughtFishingStateLava := ReadMemory(BotList[index, 10],BotList[index, 1])
CaughtFishingStateChoco := ReadMemory(BotList[index, 11],BotList[index, 1])
;If fishing state = 1 ignores the error logging. 15
If (CaughtFishingStateWater = 1 or CaughtFishingStateLava = 1 or CaughtFishingStateChoco = 1)
{
FishingState := "1"
BotList[index, 15] := "0" ;Since fishing is detected it will wipe out the Error Count.
}
If (FishingState = 0)
{
If (BotList[index, 14] <> 1) { ;If recast is not 1 it trigers the Error Report.
SetTimer, Recast, Off
BotList[index, 15] := BotList[index, 15] + 1 ; Adds 1 for each time it is found not fishing.
bID := BotList[index, 1]
BotList[index, 14] := 1 ;Turning on the recast flag.
SetTimer, Recast, 4000
If (BotList[index, 15] > 2)
{
Text := "The client on index[" . index . "] pID[" . BotList[index, 1] . "] seems to be not be fishing. Possible causes could be frozen client/character or full inventory. Click this window to remove client from list and bring the window to the foregRound."
TransSplashText_On("Error",Text,600,"Arial","Black",0,10,,,7000)
}
;Fix this by adding a var yes or no to skip next parts do not use return Return
}
}
}
;Memory scan for current client to check for fish bite
If (12 < CurrentTime) ;Wont start a memory scan till 12Seconds has passed. This is to Lower cpu usage.
{
If (BotList[index, 12] = 1) ;Water type found scan only water type
CaughtWater := ReadMemory(BotList[index, 4],BotList[index, 1])
Else If (BotList[index, 12] = 2) ;Lava type found scan only lava type
CaughtLava := ReadMemory(BotList[index, 5],BotList[index, 1])
Else If (BotList[index, 12] = 3) ;Choco type found only scan Choco type
CaughtChoco := ReadMemory(BotList[index, 6],BotList[index, 1])
Else {
;Unknown type so we can all 3. This will use more cpu.
CaughtWater := ReadMemory(BotList[index, 4],BotList[index, 1])
CaughtLava := ReadMemory(BotList[index, 5],BotList[index, 1])
CaughtChoco := ReadMemory(BotList[index, 6],BotList[index, 1])
}
} Else {
CaughtWater := 0
CaughtLava := 0
CaughtChoco := 0
}
;Preforming reelin
If (CaughtWater = 1 or CaughtLava = 1 or CaughtChoco = 1)
{
;Checking to see if the bot is already recasting. And if so it will ignore below.
If (BotList[index, 14] <> 1) {
SetTimer, Recast, Off
RandSleep(100,200)
ControlSend, , {f down}, % "ahk_pid " BotList[index, 1]
RandSleep(86,100)
ControlSend, , {f up}, % "ahk_pid " BotList[index, 1]
Sleep 200
BotList[index, 14] := 1 ;Turning on the recast flag.
BotList[index, 17] := BotList[index, 17] + 1 ;Padding the reeled in Counter.
SetTimer, Recast, 4000
}
}
}
}
Return
Recast:
TotalClientsOnList := BotList.MaxIndex()
Loop, %TotalClientsOnList%
{
If (BotList[a_index, 14] = 1) ; Checking ot make sure the fishing flag and the recast flag are both set to 1 being on.
{
BotList[a_index, 18] := BotList[a_index, 18] + 1 ;Pading the recast Count by 1
pID := BotList[a_index, 1] ;Setting pID for Control Send.
RandSleep(1000,2000) ; Random wait time Between casts. Gives a more real feel.
ControlSend, , {f down}, % "ahk_pid " BotList[a_index, 1]
RandSleep(86,100)
ControlSend, , {f up}, % "ahk_pid " BotList[a_index, 1]
BotList[a_index, 14] := "0" ;Reseting the recast it recasted.
BotList[a_index, 8] := a_now ;Setting the last cast time to current time.
}
}
Return
getProcessBaseAddress(Handle)
{
Return DllCall( A_PtrSize = 4
? "GetWindowLong"
: "GetWindowLongPtr"
, "Ptr", Handle
, "Int", -6
, "Int64")
}
GetAddressWater(Base, Address, pid) {
pointerBase := base + Address
y1 := ReadMemory(pointerBase,pid)
y2 := ReadMemory(y1 + 0x144,pid)
y3 := ReadMemory(y2 + 0xe4,pid)
Return WaterAddress := (y3 + 0x70)
}
GetAddressLava(Base, Address, pid) {
pointerBase := base + Address
y1 := ReadMemory(pointerBase,pid)
y2 := ReadMemory(y1 + 0x144,pid)
y3 := ReadMemory(y2 + 0xe4,pid)
Return LavaAddress := (y3 + 0x514)
}
GetAddressChoco(Base, Address, pid) {
pointerBase := base + Address
y1 := ReadMemory(pointerBase,pid)
y2 := ReadMemory(y1 + 0x144,pid)
y3 := ReadMemory(y2 + 0xe4,pid)
Return ChocoAddress := (y3 + 0x2c0)
}
GetFishingStateWaterAddress(Base, Address, PID) {
pointerBase := base + Address
y1 := ReadMemory(pointerBase,PID)
y2 := ReadMemory(y1 + 0x5d8,PID)
y3 := ReadMemory(y2 + 0x7d4,PID)
Return FishingStateWater := (y3 + 0x5a0)
}
GetFishingStateChocoAddress(Base, Address, PID) {
pointerBase := base + Address
y1 := ReadMemory(pointerBase,PID)
y2 := ReadMemory(y1 + 0x5d8,PID)
y3 := ReadMemory(y2 + 0x7d8,PID)
Return FishingStateChoco := (y3 + 0x684)
}
GetFishingStateLavaAddress(Base, Address, PID) {
pointerBase := base + Address
y1 := ReadMemory(pointerBase,PID)
y2 := ReadMemory(y1 + 0x5d8,PID)
y3 := ReadMemory(y2 + 0x7d8,PID)
Return FishingStateLava := (y3 + 0x1e4)
}
ReadMemory(MADDRESS, pid) {
VarSetCapacity(MVALUE,4,0)
ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "UInt")
DllCall("ReadProcessMemory", "UInt", ProcessHandle, "Ptr", MADDRESS, "Ptr", &MVALUE, "Uint",4)
Loop 4
result += *(&MVALUE + A_Index-1) << 8*(A_Index-1)
Return, result
}
RandSleep(x,y) {
Random, rand, %x%, %y%
Sleep %rand%
}
ToolTipDisplay(Message) {
ToolTip, %Message%
SetTimer, RemoveToolTip, 5000
Return
}
RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
Return
TransSplashText_On(Title="",Text="",Width="",Font="",TC="",SC="",TS="",xPos="",yPos="",TimeOut="") {
TransSplashText_Off()
If Title =
Title = %A_ScriptName%
If Text =
Text = TransSplashText
If Width =
Width = 200
If Font =
Font = Impact
If TC =
TC = White
If SC =
SC = 828284
If TS =
TS = 20
If xPos =
xPos = Center
If yPos =
yPos = Center
If TimeOut =
TimeOut = 0
If SC != 0
{
Gui, 99:Font, S%TS% C%SC%, %Font%
Gui, 99:Add, Text, x7 y7 w%Width%, %Text%
}
Gui, 99:Font, S%TS% C%TC%, %Font%
Gui, 99:Add, Text, x5 y5 w%Width% gGUITextClick, %Text%
;Gui, 99:Color, EEAA99
Gui, 99:+LastFound +AlwaysOnTop +ToolWindow ;-Caption
;WinSet, TransColor, EEAA99
Gui, 99:Show, x%xPos% y%yPos% AutoSize, %Title%
If TimeOut != 0
{
SetTimer, TextOff, %TimeOut%
Return
TextOff:
TransSplashText_Off()
Return
}
}
GUITextClick:
TransSplashText_Off() ;Turns off any active splash Screens.
TotalClientsOnList := BotList.MaxIndex()
Loop, %TotalClientsOnList%
{
If (1 < BotList[a_index, 15]) ;If client has any erors Counts it will automatic remove form active fishing when Gui is Clicked
{
ClientWindow := BotList[a_index, 2]
WinActivate, ahk_id %ClientWindow% ;Brings the erroed client to the foregound.
BotList[a_index, 13] := 0 ;Removing client from active scan list.
BotList[a_index, 15] := 0 ;Resetting errot Count as it is no longer on the active list.
BotList[a_index, 14] := 0 ;Removing Recast just incase. If it is activly fishing it wont try and recast lure.
ToolTipDisplay("Removed client from active fishing list.`nIndexID: [" . a_index . "] pID: [" . BotList[a_index, 1] . "]")
}
}
Return
TransSplashText_Off() {
Gui, 99:Destroy
SetTimer, TextOff, Off
}