Cruelty Squad

Cruelty Squad

View Stats:
fredg1 Jun 27, 2022 @ 7:43pm
Fishing AutoHotKey script, based on sound !!
Made an AutoHotKey script to help with fishing, because like any good CEO, when things don't go your way, you... cheat... ... Wait that can't be right...

Anyway, this script works by listening for the loud sound effect that plays when a fish takes the bait.
Just make sure you have AutoHotKey installed, save this in a
.ahk
file wherever you want, and follow the instructions.

#NoEnv SendMode Input ; ------------ HOW TO USE ------------- ; 1- Take a minute to read the description of the variables below, and to set them ; according to your preferences/situation. ; 2- Turn off the game's Music Volume (but make sure the Master Volume is at max). ; 3- Turn off other sources of sound from your device (music, other games, etc.). ; 4- Enter a level. ; 5- Get in front of a fish-able liquid, with your fishing rod out. ; 6- Run this script. ; 7- Press Space. ; 8- Profit. ; *- If there is a problem, you can use Enter and Backspace to manually toggle the "listening" state. ; (Space does nothing when already in the "listening" state) ; *- Cruelty Squad always needs to be/stay in focus, of course. ; Modify this if you've assigned "shoot" to something other than the LMB. ; See https://www.autohotkey.com/docs/KeyList.htm global SHOOT_KEY := "Click" ; The volume that should be considered to be a fish biting your line. ; Is amply sufficient normally, but needs to be lowered if you're fishing from far away. ; Results in more false positives. global AUDIO_THRESHOLD := 0.95 ; If true, will automatically take care of reeling the fish and casting back the line ; as soon as a sound is heard. ; Make sure AUDIO_THRESHOLD and REEL_WAIT_TIME are set correctly before using this. ; If false, hearing a sound will instead pause the game (which, conveniently, makes no sound). ; You then have the choice to either press Space to immediately unpause and reel the fish in, ; or press "n" to ignore the fish, and keep waiting (useful if this was a false positive) ; NOT recommended when it's raining, as the thunder sound effect will always result in a false positive. global AUTO_CATCH := false ; If true (and you're not using AUTO_CATCH), pressing Space will take care of both reeling the fish in, ; and of casting the line again, based on REEL_WAIT_TIME. ; If false (and you're not using AUTO_CATCH), the line will be thrown when you release Space. ; Recommended global AUTO_RECAST_LINE := true ; If using either AUTO_CATCH or AUTO_RECAST_LINE, represents the amount of time, in milliseconds, ; to wait for a fish to be reeled in. ; 500 is pretty much the minimum, and 5000 is starting to be overkill. global REEL_WAIT_TIME := 1000 ;--------------------------------------------------------- global listening := false global gotFish := false Loop { While(!listening or !IsAudioPlaying()) Sleep, 50 ; We picked up a sound listening := false if(AUTO_CATCH) ReelFish() else { SendInput {Esc} gotFish := true ; The user now needs to press Space (or "n" to let go) } } return Space:: if(!listening) { if(gotFish) { ; Unpause... SendInput {Esc} Sleep, 5 gotFish := false ReelFish() } else CastLineAndStartListening() listening := true } else TrayTip,, % "This does nothing when already listening", 1 return ReelFish() { SendInput {%SHOOT_KEY%, Down} if(AUTO_CATCH or AUTO_RECAST_LINE) { Sleep, REEL_WAIT_TIME CastLineAndStartListening() } ; otherwise, they trigger the casting manually by letting go of Space } Space up:: if(!AUTO_CATCH and !AUTO_RECAST_LINE and !listening) CastLineAndStartListening() return CastLineAndStartListening() { ; Check if this function was called on its own, rather than following ReelFish() if(!GetKeyState(SHOOT_KEY)) { SendInput {%SHOOT_KEY%, Down} Sleep, 500 ; ignore REEL_WAIT_TIME since we're just winding up the "melee attack" } SendInput {%SHOOT_KEY%, Up} Sleep, 500 ; wait for the melee attack sound effect to end before starting to listen listening := true } Enter:: ; Manually start listening if(!listening) TrayTip,, % "Now listening", 1 listening := true gotFish := false return Backspace:: ; Manually stop listening if(listening) TrayTip,, % "No longer listening", 1 listening := false gotFish := false return n:: ; Let go of a caught fish (or ignore a false positive), unpausing and continuing to listen if(!listening and gotFish) { SendInput {Esc} gotFish := false Sleep, 500 ; the "caught a fish" sound is probably still playing... listening := true } return ;--------------------------------------------------------- ;credits to https://www.autohotkey.com/boards/viewtopic.php?p=183523#p183523 for everything past this point IsAudioPlaying() { AudioLevel := 0.0 VA_IAudioMeterInformation_GetPeakValue(VA_GetAudioMeter(), AudioLevel) return (Round(AudioLevel, 4) > AUDIO_THRESHOLD) } ;--------------------------------------------------------- ;VA code credited to Lexikos, I merely cut it down to the minimum I needed. VA_GetAudioMeter(device_desc="playback") { if ! device := VA_GetDevice(device_desc) return 0 VA_IMMDevice_Activate(device, "{C02216F6-8C67-4B5B-9D00-D008E73E0064}", 7, 0, audioMeter) ObjRelease(device) return audioMeter } VA_GetDevice(device_desc="playback") { static CLSID_MMDeviceEnumerator := "{BCDE0395-E52F-467C-8E3D-C4579291692E}" , IID_IMMDeviceEnumerator := "{A95664D2-9614-4F35-A746-DE8DB63617E6}" if !(deviceEnumerator := ComObjCreate(CLSID_MMDeviceEnumerator, IID_IMMDeviceEnumerator)) return 0 device := 0 if VA_IMMDeviceEnumerator_GetDevice(deviceEnumerator, device_desc, device) = 0 goto VA_GetDevice_Return if device_desc is integer { m2 := device_desc if m2 >= 4096 ; Probably a device pointer, passed here indirectly via VA_GetAudioMeter or such. { ObjAddRef(device := m2) goto VA_GetDevice_Return } } else RegExMatch(device_desc, "(.*?)\s*(?::(\d+))?$", m) if m1 in playback,p m1 := "", flow := 0 ; eRender else if m1 in capture,c m1 := "", flow := 1 ; eCapture else if (m1 . m2) = "" ; no name or number specified m1 := "", flow := 0 ; eRender (default) else flow := 2 ; eAll if (m1 . m2) = "" ; no name or number (maybe "playback" or "capture") { VA_IMMDeviceEnumerator_GetDefaultAudioEndpoint(deviceEnumerator, flow, 0, device) goto VA_GetDevice_Return } VA_IMMDeviceEnumerator_EnumAudioEndpoints(deviceEnumerator, flow, 1, devices) if m1 = { VA_IMMDeviceCollection_Item(devices, m2-1, device) goto VA_GetDevice_Return } VA_IMMDeviceCollection_GetCount(devices, count) index := 0 Loop % count if VA_IMMDeviceCollection_Item(devices, A_Index-1, device) = 0 if InStr(VA_GetDeviceName(device), m1) && (m2 = "" || ++index = m2) goto VA_GetDevice_Return else ObjRelease(device), device:=0 VA_GetDevice_Return: ObjRelease(deviceEnumerator) if (devices) ObjRelease(devices) return device ; may be 0 } VA_GetDeviceName(device) { static PKEY_Device_FriendlyName if !VarSetCapacity(PKEY_Device_FriendlyName) VarSetCapacity(PKEY_Device_FriendlyName, 20) ,VA_GUID(PKEY_Device_FriendlyName :="{A45C254E-DF1C-4EFD-8020-67D146A850E0}") ,NumPut(14, PKEY_Device_FriendlyName, 16) VarSetCapacity(prop, 16) VA_IMMDevice_OpenPropertyStore(device, 0, store) ; store->GetValue(.., [out] prop) DllCall(NumGet(NumGet(store+0)+5*A_PtrSize), "ptr", store, "ptr", &PKEY_Device_FriendlyName, "ptr", &prop) ObjRelease(store) VA_WStrOut(deviceName := NumGet(prop,8)) return deviceName } VA_WStrOut(ByRef str) { str := StrGet(ptr := str, "UTF-16") DllCall("ole32\CoTaskMemFree", "ptr", ptr) ; FREES THE STRING. } VA_GUID(ByRef guid_out, guid_in="%guid_out%") { if (guid_in == "%guid_out%") guid_in := guid_out if guid_in is integer return guid_in VarSetCapacity(guid_out, 16, 0) DllCall("ole32\CLSIDFromString", "wstr", guid_in, "ptr", &guid_out) return &guid_out } VA_IMMDevice_OpenPropertyStore(this, Access, ByRef Properties) { return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Access, "ptr*", Properties) } VA_IMMDevice_Activate(this, iid, ClsCtx, ActivationParams, ByRef Interface) { return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr", VA_GUID(iid), "uint", ClsCtx, "uint", ActivationParams, "ptr*", Interface) } VA_IMMDeviceEnumerator_GetDevice(this, id, ByRef Device) { return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "wstr", id, "ptr*", Device) } VA_IMMDeviceEnumerator_GetDefaultAudioEndpoint(this, DataFlow, Role, ByRef Endpoint) { return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "int", DataFlow, "int", Role, "ptr*", Endpoint) } VA_IMMDeviceEnumerator_EnumAudioEndpoints(this, DataFlow, StateMask, ByRef Devices) { return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "int", DataFlow, "uint", StateMask, "ptr*", Devices) } VA_IMMDeviceCollection_GetCount(this, ByRef Count) { return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "uint*", Count) } VA_IMMDeviceCollection_Item(this, Index, ByRef Device) { return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Index, "ptr*", Device) } VA_IAudioMeterInformation_GetPeakValue(this, ByRef Peak) { return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "float*", Peak) }
< >
Showing 1-6 of 6 comments
cutie. Jun 27, 2022 @ 8:44pm 
Originally posted by fredg1:
Made an AutoHotKey script to help with fishing, because like any good CEO, when things don't go your way, you... cheat... ... Wait that can't be right...

Anyway, this script works by listening for the loud sound effect that plays when a fish takes the bait.
Just make sure you have AutoHotKey installed, save this in a
.ahk
file wherever you want, and follow the instructions.

#NoEnv SendMode Input ; ------------ HOW TO USE ------------- ; 1- Take a minute to read the description of the variables below, and to set them ; according to your preferences/situation. ; 2- Turn off the game's Music Volume (but make sure the Master Volume is at max). ; 3- Turn off other sources of sound from your device (music, other games, etc.). ; 4- Enter a level. ; 5- Get in front of a fish-able liquid, with your fishing rod out. ; 6- Run this script. ; 7- Press Space. ; 8- Profit. ; *- If there is a problem, you can use Enter and Backspace to manually toggle the "listening" state. ; (Space does nothing when already in the "listening" state) ; *- Cruelty Squad always needs to be/stay in focus, of course. ; Modify this if you've assigned "shoot" to something other than the LMB. ; See https://www.autohotkey.com/docs/KeyList.htm global SHOOT_KEY := "Click" ; The volume that should be considered to be a fish biting your line. ; Is amply sufficient normally, but needs to be lowered if you're fishing from far away. ; Results in more false positives. global AUDIO_THRESHOLD := 0.95 ; If true, will automatically take care of reeling the fish and casting back the line ; as soon as a sound is heard. ; Make sure AUDIO_THRESHOLD and REEL_WAIT_TIME are set correctly before using this. ; If false, hearing a sound will instead pause the game (which, conveniently, makes no sound). ; You then have the choice to either press Space to immediately unpause and reel the fish in, ; or press "n" to ignore the fish, and keep waiting (useful if this was a false positive) ; NOT recommended when it's raining, as the thunder sound effect will always result in a false positive. global AUTO_CATCH := false ; If true (and you're not using AUTO_CATCH), pressing Space will take care of both reeling the fish in, ; and of casting the line again, based on REEL_WAIT_TIME. ; If false (and you're not using AUTO_CATCH), the line will be thrown when you release Space. ; Recommended global AUTO_RECAST_LINE := true ; If using either AUTO_CATCH or AUTO_RECAST_LINE, represents the amount of time, in milliseconds, ; to wait for a fish to be reeled in. ; 500 is pretty much the minimum, and 5000 is starting to be overkill. global REEL_WAIT_TIME := 1000 ;--------------------------------------------------------- global listening := false global gotFish := false Loop { While(!listening or !IsAudioPlaying()) Sleep, 50 ; We picked up a sound listening := false if(AUTO_CATCH) ReelFish() else { SendInput {Esc} gotFish := true ; The user now needs to press Space (or "n" to let go) } } return Space:: if(!listening) { if(gotFish) { ; Unpause... SendInput {Esc} Sleep, 5 gotFish := false ReelFish() } else CastLineAndStartListening() listening := true } else TrayTip,, % "This does nothing when already listening", 1 return ReelFish() { SendInput {%SHOOT_KEY%, Down} if(AUTO_CATCH or AUTO_RECAST_LINE) { Sleep, REEL_WAIT_TIME CastLineAndStartListening() } ; otherwise, they trigger the casting manually by letting go of Space } Space up:: if(!AUTO_CATCH and !AUTO_RECAST_LINE and !listening) CastLineAndStartListening() return CastLineAndStartListening() { ; Check if this function was called on its own, rather than following ReelFish() if(!GetKeyState(SHOOT_KEY)) { SendInput {%SHOOT_KEY%, Down} Sleep, 500 ; ignore REEL_WAIT_TIME since we're just winding up the "melee attack" } SendInput {%SHOOT_KEY%, Up} Sleep, 500 ; wait for the melee attack sound effect to end before starting to listen listening := true } Enter:: ; Manually start listening if(!listening) TrayTip,, % "Now listening", 1 listening := true gotFish := false return Backspace:: ; Manually stop listening if(listening) TrayTip,, % "No longer listening", 1 listening := false gotFish := false return n:: ; Let go of a caught fish (or ignore a false positive), unpausing and continuing to listen if(!listening and gotFish) { SendInput {Esc} gotFish := false Sleep, 500 ; the "caught a fish" sound is probably still playing... listening := true } return ;--------------------------------------------------------- ;credits to https://www.autohotkey.com/boards/viewtopic.php?p=183523#p183523 for everything past this point IsAudioPlaying() { AudioLevel := 0.0 VA_IAudioMeterInformation_GetPeakValue(VA_GetAudioMeter(), AudioLevel) return (Round(AudioLevel, 4) > AUDIO_THRESHOLD) } ;--------------------------------------------------------- ;VA code credited to Lexikos, I merely cut it down to the minimum I needed. VA_GetAudioMeter(device_desc="playback") { if ! device := VA_GetDevice(device_desc) return 0 VA_IMMDevice_Activate(device, "{C02216F6-8C67-4B5B-9D00-D008E73E0064}", 7, 0, audioMeter) ObjRelease(device) return audioMeter } VA_GetDevice(device_desc="playback") { static CLSID_MMDeviceEnumerator := "{BCDE0395-E52F-467C-8E3D-C4579291692E}" , IID_IMMDeviceEnumerator := "{A95664D2-9614-4F35-A746-DE8DB63617E6}" if !(deviceEnumerator := ComObjCreate(CLSID_MMDeviceEnumerator, IID_IMMDeviceEnumerator)) return 0 device := 0 if VA_IMMDeviceEnumerator_GetDevice(deviceEnumerator, device_desc, device) = 0 goto VA_GetDevice_Return if device_desc is integer { m2 := device_desc if m2 >= 4096 ; Probably a device pointer, passed here indirectly via VA_GetAudioMeter or such. { ObjAddRef(device := m2) goto VA_GetDevice_Return } } else RegExMatch(device_desc, "(.*?)\s*(?::(\d+))?$", m) if m1 in playback,p m1 := "", flow := 0 ; eRender else if m1 in capture,c m1 := "", flow := 1 ; eCapture else if (m1 . m2) = "" ; no name or number specified m1 := "", flow := 0 ; eRender (default) else flow := 2 ; eAll if (m1 . m2) = "" ; no name or number (maybe "playback" or "capture") { VA_IMMDeviceEnumerator_GetDefaultAudioEndpoint(deviceEnumerator, flow, 0, device) goto VA_GetDevice_Return } VA_IMMDeviceEnumerator_EnumAudioEndpoints(deviceEnumerator, flow, 1, devices) if m1 = { VA_IMMDeviceCollection_Item(devices, m2-1, device) goto VA_GetDevice_Return } VA_IMMDeviceCollection_GetCount(devices, count) index := 0 Loop % count if VA_IMMDeviceCollection_Item(devices, A_Index-1, device) = 0 if InStr(VA_GetDeviceName(device), m1) && (m2 = "" || ++index = m2) goto VA_GetDevice_Return else ObjRelease(device), device:=0 VA_GetDevice_Return: ObjRelease(deviceEnumerator) if (devices) ObjRelease(devices) return device ; may be 0 } VA_GetDeviceName(device) { static PKEY_Device_FriendlyName if !VarSetCapacity(PKEY_Device_FriendlyName) VarSetCapacity(PKEY_Device_FriendlyName, 20) ,VA_GUID(PKEY_Device_FriendlyName :="{A45C254E-DF1C-4EFD-8020-67D146A850E0}") ,NumPut(14, PKEY_Device_FriendlyName, 16) VarSetCapacity(prop, 16) VA_IMMDevice_OpenPropertyStore(device, 0, store) ; store->GetValue(.., [out] prop) DllCall(NumGet(NumGet(store+0)+5*A_PtrSize), "ptr", store, "ptr", &PKEY_Device_FriendlyName, "ptr", &prop) ObjRelease(store) VA_WStrOut(deviceName := NumGet(prop,8)) return deviceName } VA_WStrOut(ByRef str) { str := StrGet(ptr := str, "UTF-16") DllCall("ole32\CoTaskMemFree", "ptr", ptr) ; FREES THE STRING. } VA_GUID(ByRef guid_out, guid_in="%guid_out%") { if (guid_in == "%guid_out%") guid_in := guid_out if guid_in is integer return guid_in VarSetCapacity(guid_out, 16, 0) DllCall("ole32\CLSIDFromString", "wstr", guid_in, "ptr", &guid_out) return &guid_out } VA_IMMDevice_OpenPropertyStore(this, Access, ByRef Properties) { return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Access, "ptr*", Properties) } VA_IMMDevice_Activate(this, iid, ClsCtx, ActivationParams, ByRef Interface) { return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr", VA_GUID(iid), "uint", ClsCtx, "uint", ActivationParams, "ptr*", Interface) } VA_IMMDeviceEnumerator_GetDevice(this, id, ByRef Device) { return DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "wstr", id, "ptr*", Device) } VA_IMMDeviceEnumerator_GetDefaultAudioEndpoint(this, DataFlow, Role, ByRef Endpoint) { return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "int", DataFlow, "int", Role, "ptr*", Endpoint) } VA_IMMDeviceEnumerator_EnumAudioEndpoints(this, DataFlow, StateMask, ByRef Devices) { return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "int", DataFlow, "uint", StateMask, "ptr*", Devices) } VA_IMMDeviceCollection_GetCount(this, ByRef Count) { return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "uint*", Count) } VA_IMMDeviceCollection_Item(this, Index, ByRef Device) { return DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", Index, "ptr*", Device) } VA_IAudioMeterInformation_GetPeakValue(this, ByRef Peak) { return DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "float*", Peak) }
big sad but good work.
could just have cheated the savefile
Shamo Jun 28, 2022 @ 1:17am 
im no programmer but this looks like a lot of code just to react to a sound, should i have my google play gift cards ready and wait for a call after i use this?
BOT Anna Jun 28, 2022 @ 2:13pm 
tbh at this point just hack the fish into a save file, youre basically cheating anyways
fredg1 Jun 28, 2022 @ 3:07pm 
Originally posted by lavamariner93:
tbh at this point just hack the fish into a save file, youre basically cheating anyways
There's a difference between printing money, and robbing a bank.
Wait, bad analogy...

There's a difference between cheating at a test, and... bribing the... teacher..?
BOT Anna Jun 28, 2022 @ 3:32pm 
Originally posted by fredg1:
Originally posted by lavamariner93:
tbh at this point just hack the fish into a save file, youre basically cheating anyways
There's a difference between printing money, and robbing a bank.
Wait, bad analogy...

There's a difference between cheating at a test, and... bribing the... teacher..?
either way, all the effort for a dumb code to instantly catch fish, just cheat them in
not like youre putting in the effort to get them yourself anyways
Last edited by BOT Anna; Jun 28, 2022 @ 3:34pm
That's pretty impressive not gonna lie.
I'm not gonna test it, considering I already have all fish and have no idea how to use it properly, but still, wow

Also I hope you put effort into this for fun too, not very worth of pouring in your soul into it, as others said.
Last edited by Jetther Terminae [on a break]; Jun 28, 2022 @ 4:05pm
< >
Showing 1-6 of 6 comments
Per page: 1530 50

Date Posted: Jun 27, 2022 @ 7:43pm
Posts: 6