Trove AutoHotkey Scripts
I'm here, with another release for the multiplayer hacking scene - this time for Trove, aka Cube World as an MMO. I bring you a little AutoHotkey script that can automate some common tasks for you, like being AFK and fishing. Seriously, who thought fishing like this was a good idea? Even old PlayStation 1 games had better fishing mini-games!
[ Credits ]
[ Features ]
[ Source Code ]
Trove.ahk
Example Use
[ Media ]

[ Version History ]
[ Remaining Changes / To Do ]
[ Credits ]
- taejim for the AutoHotkey bot.
- AutoHotkey Forum for helping with the toggle-able Hotkey.
- Fishing List for Trove - looks like it's worth making these bots.
[ Features ]
- Modular
The entire Script is based on one Include-able file, which means that you can easily build your own Hotkeys if you have AutoHotkey installed (It's free and less detectable!). - Anti-AFK Logout
Prevents automatic logout by pressing C to open the character menu. Includes: Anti-Detection Timings, Statistics - Automatic Fishing Bot
Automate your fishing needs with a single Hotkey - just press and do something else. I made over ~120k Glim in one day with this bot. Includes: Anti-Detection Timings, Statistics - Utility/Tool: Anti-Detection Timings
I've measured my own reaction times using custom written software and found that I usually respond within 86 - 111ms of the sound being played (plus driver delays, so actually 116 - 141ms). - Utility/Tool: Statistics
Displays a small Statistics ToolTip at the top-left of the window - useful for anyone needing these.
[ Source Code ]
Trove.ahk
Code:
AntiAFK_Code(Index, Key, ByRef RunningVar, ByRef StopVar)
{
;- Check if the HotKey is already running.
if RunningVar
{
; Let's signal the running thread it to stop.
StopVar := true
return
}
;- Make sure that we actually have a Trove window targeted.
if not WinActive("Trove")
return
;- Signal that we have officially been able to start.
RunningVar := true
;- If it's not running, we'll start by grabbing information about the games window.
WinGet, PID, PID, A
WinGet, HWND, ID, A
; Show a tooltip at the windows position.
CoordMode, ToolTip, Screen
WinGetPos, winX, winY, winW, winH, ahk_pid %PID%
;- The actual loop that does our work.
Timer := 0
Time_Start := A_TickCount
Loop
{
; Avoiding AFK is as simple as opening up the Character menu.
ControlSend, , {c down}, ahk_pid %PID%
Sleep, 86
ControlSend, , {c up}, ahk_pid %PID%
; Sleep in order to not look like a spammer.
Random, SleepTime, 5, 50
Loop %SleepTime%
{
; Check if we should stop.
if StopVar
break 2
; Display AFK time.
CoordMode, ToolTip, Screen
WinGetPos, winX, winY, winW, winH, ahk_pid %PID%
Time := A_TickCount - Time_Start
ToolTipText =
(
Anti-AFK Bot %Index% is running, press %Key% to stop it.
Total Time: %Time% ms.
)
ToolTip, %ToolTipText%, %winX%, %winY%
Random, SleepTime, 86, 111
Sleep, %SleepTime%
Timer := Timer + 1
}
}
; Reset state for re-use.
RunningVar := false
StopVar := false
ToolTip, , , , 1
}
AutoFishing_Code(Index, Key, ByRef RunningVar, ByRef StopVar)
{
;- Check if the HotKey is already running.
if RunningVar
{
; Let's signal the running thread it to stop.
StopVar := true
return
}
;- Make sure that we actually have a Trove window targeted.
if not WinActive("Trove")
return
;- Signal that we're running now.
RunningVar := true
;- If it's not running, we'll start by grabbing information about the games window.
WinGet, PID, PID, A
WinGet, HWND, ID, A
;- Pointers
Base := getProcessBaseAddress(HWND)
WaterAddress := GetAddressWater(PID, Base, 0x009570DC)
LavaAddress := GetAddressLava(PID, Base, 0x009570DC)
ChocoAddress := GetAddressChoco(PID, Base, 0x009570DC)
;- Statistics
Time_Start := A_TickCount
Time := 0
Fishing_Start := A_TickCount
Fishing := 0
Fish := 0
HumanPressButton(b, ahk_pid %PID%)
; The main loop based on a State-Machine.
State=0
Loop
{
; Show a tooltip at the windows position.
CoordMode, ToolTip, Screen
WinGetPos, winX, winY, winW, winH, ahk_pid %PID%
Time := A_TickCount - Time_Start
ToolTipText=
(
Auto-Fishing Bot %Index% is running, press %Key% to stop it.
Total Time: %Time% ms
Total Fish Caught: %Fish%
Fishing Time: %Fishing% ms
State: %State%/%StateNext%
)
ToolTip, %ToolTipText%, %winX%, %winY%, 1s
;- State-Machine
If IsLabel("AutoFishing-" . State)
{
Loop 1 {
Goto AutoFishing-%State%
; State: Anti-AFK
AutoFishing-0:
AutoFishing-AntiAFK-Init:
ControlSend, , {c down}, ahk_pid %PID%
; Advance
State=AntiAFK
StateTimer=0
Break
AutoFishing-AntiAFK:
ControlSend, , {c up}, ahk_pid %PID%
; Advance
State=AntiDetection-Init
StateNext=ThrowHook-Init
StateTimer=0
Break
; State: Throw Hook
AutoFishing-2:
AutoFishing-ThrowHook-Init:
ControlSend, , {f down}, ahk_pid %PID%
; Advance
State=ThrowHook
StateTimer=0
Random, StateMaxTimer, 2, 15
Break
AutoFishing-ThrowHook:
ControlSend, , {f up}, ahk_pid %PID%
; Time Display
Fishing_Start := A_TickCount
; Advance
State=AntiDetection-Init
StateNext=Prepare
Break
; State: Prepare for Check
AutoFishing-Prepare:
; Update Statistics
Fishing := A_TickCount - Fishing_Start
; Read memory to determine if we're in the pool of things (it's 1 until it hits the surface).
CaughtWater := ReadMemory(PID, WaterAddress)
CaughtLava := ReadMemory(PID, LavaAddress)
CaughtChoco := ReadMemory(PID, ChocoAddress)
if !(CaughtWater || CaughtLava || CaughtChoco)
{
State=Check
}
else {
; If 5 seconds have passed, assume we hit the ground and reset.
If (Fishing > 5000)
State=0
}
Break
; State: Check for Fish
AutoFishing-Check:
; Update Statistics
Fishing := A_TickCount - Fishing_Start
; Read memory to determine if we have something hooked or not.
; (Can we do this without reading memory? This is easily detectable, we'd have to mask it like a virus scanner.)
CaughtWater := ReadMemory(PID, WaterAddress)
CaughtLava := ReadMemory(PID, LavaAddress)
CaughtChoco := ReadMemory(PID, ChocoAddress)
if (CaughtWater || CaughtLava || CaughtChoco)
{
Fish := Fish + 1
State=AntiDetection-Init
StateNext=ReelIn-Init
}
else
{
; If 45 seconds have passed, we're bugged so reset.
if (Fishing > 45000)
{
State=AntiDetection-Init
StateNext=ReelIn-Init
}
}
Break
; State: Reel In Hook
AutoFishing-ReelIn-Init:
ControlSend, , {f down}, ahk_pid %PID%
State=ReelIn
Break
AutoFishing-ReelIn:
ControlSend, , {f up}, ahk_pid %PID%
State=CompleteCycle
StateNext=Reset
Break
; State: Complete Cycle
AutoFishing-CompleteCycle-Init:
Random, StateMaxTimer, 8, 16
State=CompleteCycle
StateTimer=0
Break
AutoFishing-CompleteCycle:
StateTimer := StateTimer + 1
if (StateTimer > StateMaxTimer)
{
State=AntiDetection-Init
StateNext=Reset
}
Break
; Reset State
AutoFishing-Reset:
State=0
StateNext=
StateTimer=0
StateMaxTimer=0
Break
; Utility State: Anti-Detection (wait humane amount of time)
AutoFishing-AntiDetection-Init:
Random, StateMaxTimer, 8, 16
State=AntiDetection
StateTimer=0
Break
AutoFishing-AntiDetection:
StateTimer := StateTimer + 1
if (StateTimer > StateMaxTimer)
{
State=%StateNext%
StateNext=
StateTimer=0
}
Break
}
}
; Check if we should stop.
if StopVar
break
HumanLikeSleep()
}
HumanPressButton(b, ahk_pid %PID%)
; Reset state for re-use.
RunningVar := false
StopVar := false
ToolTip, , , , 1
}
HumanPressButton(Button, To)
{
ControlSend, , {%Button% down}, %To%
HumanLikeSleep()
ControlSend, , {%Button% up}, %To%
}
HumanLikeSleep()
{
Random, SleepTime, 66, 122
Sleep, %SleepTime%
}
;- Helpers & Utility
GetAddressWater(PID, Base, Address)
{
pointerBase := base + Address
y1 := ReadMemory(PID, pointerBase)
y2 := ReadMemory(PID, y1 + 0x144)
y3 := ReadMemory(PID, y2 + 0xe4)
Return WaterAddress := (y3 + 0x70)
}
GetAddressLava(PID, Base, Address)
{
pointerBase := base + Address
y1 := ReadMemory(PID, pointerBase)
y2 := ReadMemory(PID, y1 + 0x144)
y3 := ReadMemory(PID, y2 + 0xe4)
Return LavaAddress := (y3 + 0x514)
}
GetAddressChoco(PID, Base, Address)
{
pointerBase := base + Address
y1 := ReadMemory(PID, pointerBase)
y2 := ReadMemory(PID, y1 + 0x144)
y3 := ReadMemory(PID, y2 + 0xe4)
Return ChocoAddress := (y3 + 0x2c0)
}
getProcessBaseAddress(HWND)
{
return DllCall( A_PtrSize = 4
? "GetWindowLong"
: "GetWindowLongPtr"
, "Ptr", HWND
, "Int", -6
, "Int64") ; Use Int64 to prevent negative overflow when AHK is 32 bit and target process is 64bit
; If DLL call fails, returned value will = 0
}
ReadMemory(PID, MADDRESS)
{
VarSetCapacity(MVALUE,4,0)
ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", PID, "UInt")
;DllCall("ReadProcessMemory","UInt",ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)
DllCall("ReadProcessMemory", "UInt", ProcessHandle, "Ptr", MADDRESS, "Ptr", &MVALUE, "Uint",4)
Loop 4
result += *(&MVALUE + A_Index-1) << 8*(A_Index-1)
return, result
}
Code:
#Persistent
#MaxThreadsPerHotKey 3
#WinActivateForce
; Client 1: Hotkeys
^NumpadDiv::
AntiAFK_Code(1, "NumpadDiv", Running, Stop)
return
^NumpadMult::
AutoFishing_Code(1, "NumpadMult", Running, Stop)
return
#Include Trove.ahk

[ Version History ]
- 2015/07/20 (VirusTotal | Jotti's Malware Scan)
Changes:- Fix for 32-bit systems (previously used Unicode 64-bit for compiling).
- 2015/07/19
(VirusTotal | Jotti Virus Scan)
Changes:- Automatic Fishing Bot: Fixed State Corruption caused by low wait times.
- 2015/07/18
(VirusTotal | Jotti Virus Scan)
Changes:- Initial Public Release
[ Remaining Changes / To Do ]
- Avoid reading memory if possible - check screen, sniff network?
20150719_TroveScripts_mpgh.net.zip
20150719_TroveScripts_mpgh.net.zip
20150719_TroveScripts_mpgh.net.zip
20150719_TroveScripts_mpgh.net.zip
TroveScripts_20150719_mpgh.net.zip
TroveScripts_20150719_mpgh.net.zip


