-
[Guide] How to start fishing in theory [no code]
Well, today someone asks me what to do next, when you have a goal, but don't know how to achieve it. My answer was more a guide than some helpful hints, so I decided to write it here. Maybe someone finds this helpful too? :P
This guide is the way I would solve things. There are other ways how you can achieve this too. If you have found one, feel free to post.
[...]Basicly what I am trying to build is a fishbot.
I think if I am able to create a fishbot, then I can move on and start creating a real bot..
But where do I start off with creating a bot? I've got some basic player info and I want to move on.
What's the first step, throwing a rod?[...]
First of all, you need to think in a realy basic manner. Split up you problem into minor subproblems and try to solve them. To get a fishbot, you have to ask yourself, what does someone need to be able to catch a fish? So here is a (maybe incomplete) list of things a bot need to be able to do:
- cast fishing
- find the fishing bobber
- detect the bobbing of the fishing bobber when a fish bites
- interact with the fishing bobber
1. Cast fishing
so, the first one is the easiest but can be achived in multiple ways. The fastest would be a simulated keypress using SendInput. Since SendInput requires the focus to work, it will not work for "background botting". To get background botting work, you need PostMessage or SendMessage. Another way, where the Bot-User dont need to do any keysetup, is the usage of the protected lua functions CastSpell(), CastSpellByName() or CastSpellByID(). But running (a protected) lua function is realy advanced and should not be the first goal in your bot.
2. Find the bobber
Finding the bobber is also not that hard. You need to iterate through your objects in your object manager and find all fishing bobbers. (Maybe there are more, since there could be other players in your range who are fishing too). To get the local players fishing bobber, you have to check the descriptor field "created by". If the GUID inside the descriptor field matches your own GUID, its your bobber.
But how do I know if an object is a fishing bobber?
Well, how do you know this ingame? Either by the name or the unique look. So you can either check the display id or the name!
3. Detecting the bite
Detecting the animation of the bobber is also not that hard. You need to read the animation_state offset of the object (its not a descriptor field in this case!). Read the value while the bobber is doin' nothing. When a fish bites, the value should change. So your bot only has to wait until this happens.
4. Looting the fish
When the bobber is bobbing, you have to interact with it. You can do two things here, to achieve this. You could run the lua function InteractUnit() but this is not realy easy. Another way would be to write the GUID of the fishing bobber into the static offset mouseOverGUID or lastTargetGUID. When you write the GUID into the mouseOverGUID property, you can bind a key to "interact with mouseover" and let you bot press this button using SendInput, SendMessage, PostMessage or whatever is able to fake a keyboard input. When you write the GUID into the lastTargetGUID property, you need to bind a key to "targetLastTarget" and one to "interact with target". Since the bobber is not targetable, this _can_ cause problems, so I would stick to the mouseover method.
congratulations, you have catched your first fish. So now, catch you next one 
How to advance at this point?
Well, adding things like fishing pool detection, movement, combat, whisper detection and other security features may be the next. Ask yourself what you need! It would also be good to have a detection if the bot has looted something, so you can write a counter.
Greetz, Xalcon~
Last edited by xalcon; 01-09-2012 at 08:37 PM.
"Threads should always commit suicide - they should never be murdered" - DirectX SDK
-
Active Member
Write a conceptual finite state machine for the bot logic. Not code, a flowchart figuring out the states and the decisions in the bot logic.
Then figure out what you need to do in code to detect the need for a state change.
Then figure out what you need to do in code perform the current state.
As long as the logic is sound, the rest should be a breeze.
-
Originally Posted by
wraithZX
Write a conceptual finite state machine for the bot logic. Not code, a flowchart figuring out the states and the decisions in the bot logic.
Then figure out what you need to do in code to detect the need for a state change.
Then figure out what you need to do in code perform the current state.
As long as the logic is sound, the rest should be a breeze.
This sounds like I have to know what you are saying... but I've no idea how this could look like. Do you have an example or some articles about this "state machine concept"? Would be interesting.
"Threads should always commit suicide - they should never be murdered" - DirectX SDK
-
Sergeant
Thanks Xalcon, got the logic on how to start doing this now. But there is still one question that remains. How do you catch any changes in values in your WoWclient? In a normal program you would use delegates or Actions to catch any changes and notify the user. But how do I know that for example my health value changed or my bobber animation state changed?
-
check it every X miliseconds?
"Threads should always commit suicide - they should never be murdered" - DirectX SDK
-
Sergeant
Originally Posted by
xalcon
check it every X miliseconds?
No wonder, but what way is most efficient without causing to much memory or performance?
-
Active Member
Code:
while(Bobber.State != changed)
{
Thread.Sleep(100);
}
Thread.Sleep(some rnd wait here,like from 100 to 233 or like this); // makes you react more humanlike(at least from what i think)
Doesn't take too much cpu or memory
-
Sergeant
Originally Posted by
streppel
Code:
while(Bobber.State != changed)
{
Thread.Sleep(100);
}
Thread.Sleep(some rnd wait here,like from 100 to 233 or like this); // makes you react more humanlike(at least from what i think)
Doesn't take too much cpu or memory
Threads are also used for monitoring like health changes? Sounds kinda overkill :/
-
Active Member
it's a fishbot,you want behaviourtrees in it? :P
-
Originally Posted by
Require
Threads are also used for monitoring like health changes? Sounds kinda overkill :/
No, it is not overkill, it is needed! What do you think how an "action" or "event" system works? There is some Data (the Wow memory space) and some mystirious function which dont takes cpu power?
Behind an event system is a function which checks the data in a given interval. When it changes ("ON_HEALTH_CHANGED"), a registered function is fired. And it doesn't need that much cpu usage to read from memory. You should not poll the whole memory every 10 ms, but refreshing the object manager every 100ms seems to okay.
// Edit: and just for your info: the example code from streppel doesn't contains a new thread... its only a "sleep" command.
Last edited by xalcon; 01-10-2012 at 03:39 PM.
"Threads should always commit suicide - they should never be murdered" - DirectX SDK
-
Active Member
you could even do it with 1ms wait,still is not too much cpu ...
did it in my bot but it really was too much of an overkill,still 100ms is just fine,you are right xalcon
-
In regards to a FSM and fish botting, this is how I pull off a very easy fishing bot:
Code:
public class FishingScript : Script
{
public FishingScript()
: base("Fishing", "Bot")
{ }
private int Fishes;
private WoWSpell Fishing;
private DateTime LootTimer;
private DateTime CombatTimer;
private List<string> EventSubscription = new List<string>
{
"LOOT_OPENED",
"LOOT_SLOT_CLEARED",
"LOOT_CLOSED",
"SKILL_LINES_CHANGED",
"PLAYER_REGEN_DISABLED",
"PLAYER_REGEN_ENABLED"
};
private FishingState CurrentState
{
get;
set;
}
public override void OnStart()
{
if (!Manager.IsInGame)
return;
CurrentState = FishingState.Lure;
Fishes = 0;
Fishing = WoWSpellCollection.GetSpell("Fishing");
if (!Fishing.IsValid)
{
Print("You don't know fishing!");
Stop();
}
foreach (var ev in EventSubscription)
Events.Register(ev, HandleFishingEvents);
}
public override void OnTick()
{
if (!Manager.IsInGame)
return;
switch (CurrentState)
{
case FishingState.Lure:
//if (!HasBait)
//{
// // Implement applying lure
//}
CurrentState = FishingState.Cast;
break;
case FishingState.Cast:
Print("Casting Fishing Pole");
Fishing.Cast();
CurrentState = FishingState.Fishing;
Sleep(500); // Force a sleep for the cast
break;
case FishingState.Fishing:
if (IsFishing)
{
if (IsBobbing)
CurrentState = FishingState.Loot;
}
else
CurrentState = FishingState.Lure;
break;
case FishingState.Loot:
Print("Getting Fishing Bobber");
Bobber.Interact();
LootTimer = DateTime.Now;
CurrentState = FishingState.Looting;
break;
case FishingState.Looting:
var span = DateTime.Now - LootTimer;
if (span.TotalSeconds > 3)
{
Print("No loot? Back to fishing then!");
CurrentState = FishingState.Lure;
}
break;
case FishingState.Combat:
if (Manager.LocalPlayer.IsDead)
OnTerminate();
// Not much we can do but wait :(
break;
}
Sleep(200);
}
private void HandleFishingEvents(string ev, List<string> args)
{
//Print("DEBUG - EVENT: {0} ({1})", ev, args);
TimeSpan span;
switch (ev)
{
case "LOOT_OPENED":
Print("We have {0} catches to loot", args[0]);
break;
case "LOOT_SLOT_CLEARED":
//var loot = WoWScript.Execute("GetLootSlotInfo(" + args[0] + ")");
//Print("Looted [{0}]x{1}", loot[1], loot[2]);
break;
case "LOOT_CLOSED":
span = DateTime.Now - LootTimer;
Print("Looting took {0} seconds.", Math.Round(span.TotalSeconds, 1));
Fishes++;
CurrentState = FishingState.Lure;
break;
case "SKILL_LINES_CHANGED":
Print("Seems like we leveled up our fishing!");
break;
case "PLAYER_REGEN_DISABLED":
Print("Seems like we entered combat!");
CombatTimer = DateTime.Now;
if (CanHandleCombat)
Combat.Pulse();
else
Print("... too bad you didn't select a combat brain, now we're going to die");
CurrentState = FishingState.Combat;
break;
case "PLAYER_REGEN_ENABLED":
span = DateTime.Now - CombatTimer;
Print("Combat done after {0} seconds", Math.Round(span.TotalSeconds, 1));
CurrentState = FishingState.Lure;
break;
}
}
public override void OnTerminate()
{
foreach (var ev in EventSubscription)
Events.Remove(ev, HandleFishingEvents);
CurrentState = FishingState.Lure;
Fishing = null;
Print("Fishing season is over! You did however catch {0} fishes.", Fishes);
}
#region Properties
private WoWGameObject Bobber
{
get
{
return Manager.Objects.Where(b => b.IsValid && b.IsGameObject)
.Select(b => b as WoWGameObject)
.Where(b => b.CreatedByMe && b.Name == "Fishing Bobber")
.FirstOrDefault() ?? WoWGameObject.Invalid;
}
}
private bool IsBobbing
{
get { return (Bobber.IsValid ? Helper.Magic.Read<byte>((uint)Bobber.Pointer + (uint)Offsets.IsBobbing) == 1 : false); }
}
private bool IsFishing
{
get { return Manager.LocalPlayer.ChanneledCastingId == Fishing.Id; }
}
private bool HasBait
{
get { return WoWScript.Execute<int>("GetWeaponEnchantInfo()", 0) == 1; }
}
private bool CanHandleCombat
{
get { return Combat.Brain != null; }
}
#endregion
#region FishingState enum
enum FishingState
{
Lure,
Cast,
Fishing,
Loot,
Looting,
Combat
}
#endregion
}
-
Originally Posted by
miceiken
In regards to a FSM and fish botting, this is how I pull off a very easy fishing bot:[...]
Wow, thank you miceiken. This is an very nice example for a statemachine
I like the concept! The last few days I was thinking how I could write my different engines like gathering, combat or fishing and this is EXACTLY what I was looking for. Simple and efficient. Nice! Rep+ to you.
"Threads should always commit suicide - they should never be murdered" - DirectX SDK
-
Sergeant
miceiken: neat code
-
Post Thanks / Like - 1 Thanks
leehun00 (1 members gave Thanks to Require for this useful post)
-
Contributor
http://www.ownedcore.com/forums/general/programming/232703-bot-developers-simple-but-effective-fsm-your-bots.html
"Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live." - Martin Golding
"I cried a little earlier when I had to poop" - Sku