Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 34 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A simple World of Warcraft fishbot written in C#.

Introduction

I started this project during my freshman year of college…many, many years ago.
I started this project during my freshman year of college… Many, many years ago.
It’s been years since I’ve played Wow and I no longer have the amounts of free
time I used to. I’ve revised the code a few times since, but I can’t pretend
it’s a shining example of anything; still, it remains a popular project and I
Expand All @@ -14,64 +14,70 @@ some value from this.
Coding Overview

This is originaly written in VB.NET (I know, I know….). It has been now ported
in C#. You can get a free copy of Visual Studio Express.
to C#. You can get a free copy of Visual Studio Community.

The general idea is that the bot works by ‘listening’ to the output from the
game (whereas most bots at the time were reading pixels and trying to find the
bobber, or reading the game’s memory (which means updating the offsets after
each patch). This works with the CoreAudio DLL file – I didn’t write it and
bobber, or reading the game’s memory - which means updating the offsets after
each patch). This works with the CoreAudio DLL file – I didn’t write it and
I don’t believe it works with Windows XP.

The bot uses standard win32 API calls to move the mouse and send keystrokes.
I’ve never had any problems, but I’ve gotten reports from users saying it
doesn’t work on their machine.

It starts by sending the ‘cast’ key, then moving the cursor systematically and
using the GetCursorInfo api call to detect a change in the icon. We assume
that change is the fish bobber. Then it monitors the sound output (via
CoreAudio) until there is a change and we assume that is the splash of a fish.
Then the bot sends the click mouse event. Rinse. Repeat.
using the GetCursorInfo api call to detect a change in the icon. We assume that
that change is the fish bobber. Then it monitors the sound output (via
CoreAudio) until there is a change above a threshold and we assume that this is the splash of a fish.
Then the bot sends the click mouse event. Rinse. Repeat.

There are quite a few ‘nice-to-haves’ I never got around to doing….adding
There are quite a few ‘nice-to-haves’ I never got around to doing… Adding
lures, improving the scanning, ironing out the hearth home functionality…
maybe someone will get a chance.
Maybe someone will get a chance.

Thanks to everyone who supported the project and thanks to anyone reading this
for your interest.

Updated for Mists of Pandaria
Updated for Mists of Pandaria & Warlords of Draenor
=============================

Updated by justanotherprogrammer to support MoP items such as the Ancient
Pandaren Fishing Charm and the Angler's Fishing Raft. Also added support for
people who don't use Auto-loot.

Updated for Warlords of Draenor
===============================

Updated by Henrik Hermansen to support WoD bait.

Updated in C#
===============================

Updated by Pierre Ghiot (Mograine) in C#.

Updated by daniel-widrick
Updated by daniel-widrick & Szabka
===============================
-Hearing optimisation.

Updated by Szabka
===============================
Ear optimisation
Bobber finding and Hearing is parallel threads.
Bobber finding searches differences between before cast and after cast screenshots, than previous bobber positions ordered by occurence.
If bobber not found while fish hearing it searches 2 seconds more for bobber, so has a possibility to catch fish even instant fish hear on cast.
Bobber recheck on hook, so if bobber moves a little it will find again.
Has log file for debugging purposes.
Can capture fishing cursor with hotkey for more precision bobber finding.
Hungarian translation.
Wow window handle searched when starts fishing(and not when fishbot starts).
Hotkey actions disabled in settings screen.
Stop fishing after 10 consequent fish failure.
-Bobber finding and Hearing is put in parallel threads.

-Bobber finding searches the differences between "before cast" and "after cast" screenshots, than previous bobber positions ordered by occurence.

-If bobber is still not found when fish is heard, it searches 2 seconds more for bobber, so that it still has a possibility to catch fish.

-Bobber recheck on hook, so if bobber moves a little it will find the fish again.

-Has log file for debugging purposes.

-Can capture fishing cursor with hotkey for more precision bobber finding.

-Hungarian translation.

-Bulgarian translation.

-Wow window handle searched when starts fishing(and not when fishbot starts).

-Hotkey actions disabled in settings screen.

-Stop fishing after 10 consecutive fish failures.

Happy Fishing!

Expand Down
37 changes: 26 additions & 11 deletions UltimateFishBot/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@
</startup>
<userSettings>
<UltimateFishBot.Properties.Settings>
<setting name="ScanningSteps" serializeAs="String">
<value>10</value>
<setting name="ScanningStepsLow" serializeAs="String">
<value>15</value>
</setting>
<setting name="ScanningDelay" serializeAs="String">
<value>30</value>
<setting name="ScanningDelayLow" serializeAs="String">
<value>23</value>
</setting>
<setting name="ScanningRetries" serializeAs="String">
<value>2</value>
</setting>
<setting name="CastingDelay" serializeAs="String">
<setting name="CastingDelayLow" serializeAs="String">
<value>1500</value>
</setting>
<setting name="LootingDelay" serializeAs="String">
<value>3000</value>
<setting name="LootingDelayLow" serializeAs="String">
<value>2600</value>
</setting>
<setting name="SplashLimit" serializeAs="String">
<value>15</value>
Expand Down Expand Up @@ -79,11 +79,11 @@
<setting name="ShiftLoot" serializeAs="String">
<value>False</value>
</setting>
<setting name="FishWait" serializeAs="String">
<value>22000</value>
<setting name="FishWaitLow" serializeAs="String">
<value>21500</value>
</setting>
<setting name="AudioDevice" serializeAs="String">
<value/>
<value />
</setting>
<setting name="AutoBait" serializeAs="String">
<value>False</value>
Expand Down Expand Up @@ -161,11 +161,26 @@
<value>False</value>
</setting>
<setting name="CursorCaptureHotKey" serializeAs="String">
<value>Ctrl+Shift+C</value>
<value>Alt+Shift+C</value>
</setting>
<setting name="RightClickCast" serializeAs="String">
<value>False</value>
</setting>
<setting name="CastingDelayHigh" serializeAs="String">
<value>1800</value>
</setting>
<setting name="LootingDelayHigh" serializeAs="String">
<value>3000</value>
</setting>
<setting name="FishWaitHigh" serializeAs="String">
<value>22200</value>
</setting>
<setting name="ScanningDelayHigh" serializeAs="String">
<value>32</value>
</setting>
<setting name="ScanningStepsHigh" serializeAs="String">
<value>30</value>
</setting>
</UltimateFishBot.Properties.Settings>
</userSettings>
</configuration>
18 changes: 12 additions & 6 deletions UltimateFishBot/Classes/BodyParts/Eyes.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
Expand All @@ -24,6 +24,9 @@ class Eyes
private Bitmap background;
private Rectangle wowRectangle;

private int a_ScanningSteps = 0;
private int a_ScanningDelay = 0;

public Eyes(IntPtr wowWindow) {
SetWow(wowWindow);
bobberPosDict = new Dictionary<Win32.Point, int>();
Expand All @@ -43,7 +46,6 @@ public void SetWow(IntPtr wowWindow) {
public void updateBackground() {
background = new Grayscale(0.3725, 0.6154, 0.0121).Apply(Win32.CaptureWindow(Wow));
background = new Pixellate().Apply(background);

}

public async Task<Win32.Point> LookForBobber(CancellationToken cancellationToken)
Expand Down Expand Up @@ -84,11 +86,13 @@ public void updateBackground() {
}
}
}
if (bobberPos.x == 0 && bobberPos.y == 0) {
if (bobberPos.x == 0 && bobberPos.y == 0) {
Random rnd = new Random();
a_ScanningSteps = rnd.Next(Properties.Settings.Default.ScanningStepsLow, Properties.Settings.Default.ScanningStepsHigh);
if (Properties.Settings.Default.AlternativeRoute) {
bobberPos = await LookForBobberSpiralImpl(scanArea, bobberPos, Properties.Settings.Default.ScanningSteps, Properties.Settings.Default.ScanningRetries, cancellationToken);
bobberPos = await LookForBobberSpiralImpl(scanArea, bobberPos, a_ScanningSteps, Properties.Settings.Default.ScanningRetries, cancellationToken);
} else {
bobberPos = await LookForBobberImpl(scanArea, bobberPos, Properties.Settings.Default.ScanningSteps, Properties.Settings.Default.ScanningRetries, cancellationToken);
bobberPos = await LookForBobberImpl(scanArea, bobberPos, a_ScanningSteps, Properties.Settings.Default.ScanningRetries, cancellationToken);
}
}
if (bobberPos.x != 0 && bobberPos.y != 0) {
Expand Down Expand Up @@ -247,7 +251,9 @@ private async Task<bool> MoveMouseAndCheckCursor(int x, int y, CancellationToken
Win32.MoveMouse(x, y);

// Pause (give the OS a chance to change the cursor)
await Task.Delay(mpy*Properties.Settings.Default.ScanningDelay, cancellationToken);
Random rnd = new Random();
a_ScanningDelay = rnd.Next(Properties.Settings.Default.ScanningDelayLow, Properties.Settings.Default.ScanningDelayHigh);
await Task.Delay(mpy*a_ScanningDelay, cancellationToken);

Win32.CursorInfo actualCursor = Win32.GetCurrentCursor();

Expand Down
13 changes: 10 additions & 3 deletions UltimateFishBot/Classes/BodyParts/Hands.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Serilog;
using Serilog;
using System;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -15,6 +15,9 @@ class Hands
private IntPtr Wow;
private Random rand;

private int a_CastingDelay = 0;
private int a_LootingDelay = 0;

public Hands()
{
m_baitIndex = 0;
Expand Down Expand Up @@ -56,14 +59,18 @@ public async Task Cast(CancellationToken token)
Win32.SendKey(Properties.Settings.Default.FishKey);
Log.Information("Sent key: " + Properties.Settings.Default.FishKey);
}
await Task.Delay(new Random().Next(0,Properties.Settings.Default.CastingDelay), token);
Random rnd = new Random();
a_CastingDelay = rnd.Next(Properties.Settings.Default.CastingDelayLow, Properties.Settings.Default.CastingDelayHigh);
await Task.Delay(a_CastingDelay, token);
}

public async Task Loot()
{
Win32.SendMouseClick(this.Wow);
Log.Information("Send Loot.");
await Task.Delay(new Random().Next(0,Properties.Settings.Default.LootingDelay));
Random rnd = new Random();
a_LootingDelay = rnd.Next(Properties.Settings.Default.LootingDelayLow, Properties.Settings.Default.LootingDelayHigh);
await Task.Delay(a_LootingDelay);
}

public void ResetBaitIndex()
Expand Down
2 changes: 1 addition & 1 deletion UltimateFishBot/Classes/Helpers/Win32.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
Expand Down
23 changes: 18 additions & 5 deletions UltimateFishBot/Classes/Manager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Serilog;
using Serilog;
using System;
using System.Diagnostics;
using System.Threading;
Expand Down Expand Up @@ -62,11 +62,22 @@ public enum NeededAction
private const int SECOND = 1000;
private const int MINUTE = 60 * SECOND;

/// average
private int a_FishWait = 0;


public Manager(IManagerEventHandler managerEventHandler, IProgress<string> progressHandle)
{
m_managerEventHandler = managerEventHandler;
IntPtr WowWindowPointer = Helpers.Win32.FindWowWindow();

DialogResult result = DialogResult.Cancel;
while (WowWindowPointer == new IntPtr())
{
result = MessageBox.Show("Could not find the the WoW process. Please make sure the game is running.", "Error - WoW not open", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
if (result == DialogResult.Cancel)
Environment.Exit(1);
WowWindowPointer = Helpers.Win32.FindWowWindow();
}
m_eyes = new Eyes(WowWindowPointer);
m_hands = new Hands(WowWindowPointer);
m_ears = new Ears();
Expand Down Expand Up @@ -292,17 +303,19 @@ private async Task Fish(CancellationToken cancellationToken)
"manager",
"LABEL_WAITING",
msecs / SECOND,
Properties.Settings.Default.FishWait / SECOND));
a_FishWait / SECOND));
}
});
var uiUpdateTask = Task.Run(
async () => await UpdateUIWhileWaitingToHearFish(progress, uiUpdateCancelToken),
uiUpdateCancelToken);

Random rnd = new Random();
a_FishWait = rnd.Next(Properties.Settings.Default.FishWaitLow, Properties.Settings.Default.FishWaitHigh);
bool fishHeard = await m_ears.Listen(
Properties.Settings.Default.FishWait,
a_FishWait,
cancellationToken);
//Log.Information("Ear result: "+fishHeard.ToString());
//Log.Information("Ear result: "+a_FishWait.ToString());

uiUpdateCancelTokenSource.Cancel();
try {
Expand Down
4 changes: 2 additions & 2 deletions UltimateFishBot/Forms/frmMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ private async void frmMain_Load(object sender, EventArgs e)
btnClose.Text = Translate.GetTranslate("frmMain", "BUTTON_EXIT");
btnAbout.Text = Translate.GetTranslate("frmMain", "BUTTON_ABOUT");
lblStatus.Text = Translate.GetTranslate("frmMain", "LABEL_STOPPED");
this.Text = "UltimateFishBot - v " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
//this.Text = "UltimateFishBot - v " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
/* Hide ? */
Random r = new Random();
this.Text = this.Text + r.Next(1000, 1000000).ToString();
this.Text = r.Next(1000, 1000000).ToString();
this.Text = this.Text.GetHashCode().ToString();


Expand Down
Loading