SRL Archive - MSI Archives

TO DO: AIO Fisher


3Garrett3

2010-08-08 15:13:36

[INDENT]Just follow How to make a TScript Record.

  • Draynor
  • Barbarian Village
  • Al Kaharid
  • Karamja
  • Guild Fisher
  • Catherby
  • Shilo Village
  • Lumbridge Crayfish

Have fun,
The MSI Team[/INDENT]

Blumblebee

2010-08-08 18:46:40

I'll get on it :)

edit: Okay so I'll just do some brainstorming and then go try some stuff.

So basically you need to determine where the fishing spot is in correlation to the player, then turn that into a tBox?

Could we not just divide the screen up into four sections, search for the tool color/fishing spot color once the player has stopped moving/ is fishing. Once we get those co-ords we find which area it falls in, once we have that we simply covert the section to correspond with a tBox and viola!

I'll try to get something working along those lines and you can tell me what you think.

3Garrett3

2010-08-08 21:12:07

From: Blumblebee
I'll get on it :)

edit: Okay so I'll just do some brainstorming and then go try some stuff.

So basically you need to determine where the fishing spot is in correlation to the player, then turn that into a tBox?

Could we not just divide the screen up into four sections, search for the tool color/fishing spot color once the player has stopped moving/ is fishing. Once we get those co-ords we find which area it falls in, once we have that we simply covert the section to correspond with a tBox and viola!

I'll try to get something working along those lines and you can tell me what you think.


Well I have the search boxes optimized already. You need to search the function for it though.

Colour searching after the player stops moving could be pretty unreliable, but it might work. I was thinking of following the fish spot by updating a Tpoint and then using that as a reference to where the player would be facing. I don't have the time to do it tonight though, it might happen tomorrow after work though.

NCDS

2010-08-08 21:17:51

From: 3Garrett3

Colour searching after the player stops moving could be pretty unreliable, but it might work.


I do it in every code I write :p

Take's time/tweaks but it can most certainly be stable :)

3Garrett3

2010-08-08 21:43:02

From: NCDS
I do it in every code I write :p

Take's time/tweaks but it can most certainly be stable :)


Well I mean the colours for all of the fishing gear can result in many false positives. All of the gear is generally a brown colour, and there is a lot of that in almost all objects. Think boots, gloves, wood etc. Searching for a fishing spot colour after movement is unreliable because there are generally tons of fishing spots in an area. The most reliable solution seems to be tracking it right after clicking on it, during movement, and then seeing where it is when you stop moving.

NCDS

2010-08-08 21:46:01

From: 3Garrett3
Well I mean the colours for all of the fishing gear can result in many false positives. All of the gear is generally a brown colour, and there is a lot of that in almost all objects. Think boots, gloves, wood etc. Searching for a fishing spot colour after movement is unreliable because there are generally tons of fishing spots in an area. The most reliable solution seems to be tracking it right after clicking on it, during movement, and then seeing where it is when you stop moving.


Find al points in a tpa, then split them into an ATPA by width and height, Sort for the closest array, Check UpText, if it matches then click, otherwise move on the the next array.

Then just put a Flag; and search for a fishing spot within a small box around your char and that's your spot, no?

3Garrett3

2010-08-08 21:53:53

From: NCDS
Find al points in a tpa, then split them into an ATPA by width and height, Sort for the closest array, Check UpText, if it matches then click, otherwise move on the the next array.

Then just put a Flag; and search for a fishing spot within a small box around your char and that's your spot, no?


Not necessarily, look at karamja, so much stuff can get messed up if you just do that approach.

Blumblebee

2010-08-08 21:59:32

I know I used just color when I wrote my fisher back in the day. Fishing detecting wasn't 100% but I'd throw it near 70-80%. Run it through a I := 0 to 5 cycle and it worked well for me.

NCDS

2010-08-08 23:36:16

From: 3Garrett3
Not necessarily, look at karamja, so much stuff can get messed up if you just do that approach.


I'm guaranteeing you right now that I can and will make a script there just to prove this point :)

With the use of arrays, color finding just as effective as anything else, if done correctly.

Usuaully takes quite a while to get everything 'perfect', but once it's there, it's there ;)

3Garrett3

2010-08-09 14:30:17

From: NCDS
I'm guaranteeing you right now that I can and will make a script there just to prove this point :)

With the use of arrays, color finding just as effective as anything else, if done correctly.

Usuaully takes quite a while to get everything 'perfect', but once it's there, it's there ;)


Well mine is all colour so far :p.

I just need a function to follow the exact fishing spot, I don't want any guess work about it. MSI deserves a waiting function that works at least 90% of the time, and has some kind of failsafe system. The tree one is generally the same, and it pumps out something like 70-80% accuracy from what I've noticed in testing. It is harder to make than a fishing spot one, so the fishing spot follower had better get at least 80%.

Blumblebee

2010-08-13 02:02:43

Well I had a bit of a brainwave, well it could be totally out to lunch but anyways.

I've been doing some thinking on how to do this, and I've come to the conclusion that we're going about this the wrong way.

Fishing is unlike other skills I think. I do not think that a function to determine if a player is fishing can be broad enough to find every fishing style and concise enough to be completely accurate.

So what do we do? More functions and pointers. Basically we will have X amount (net, rod, harpoon, cage, and anymore I'm missing) of functions that are set via a pointer.

IsFishing now becomes a variable, not a function. Well a pointer would be the better way to put it.

A simple example

program new;

var
IsFishing: function Boolean();

function isHarpoonFishing(): Boolean;
begin

end;

function isRodFishing(): Boolean;
begin

end;

function isNetFishing(): Boolean;
begin

end;

function isCageFishing(): Boolean;
begin

end;

function setFishingFunction: Boolean;
begin
case Players[CurrentPlayer].Strings[FISHING_STYLE] of
'Harpoon, Shark, Tuna, SwordFish': IsFishing := @isHarpoonFishing();
'etc': IsFishing := @ThisFunction;
end;
end;

begin
end.

I feel like this will be the best way to keep it organized and specific. It will also allow for the flexibility and custom functions that we need.

But again this is simply just a thought, seeing as TrackObject_MSI is becoming difficult to finish.

Coh3n

2010-08-13 11:04:46

From: Blumblebee
Well I had a bit of a brainwave, well it could be totally out to lunch but anyways.

I've been doing some thinking on how to do this, and I've come to the conclusion that we're going about this the wrong way.

Fishing is unlike other skills I think. I do not think that a function to determine if a player is fishing can be broad enough to find every fishing style and concise enough to be completely accurate.

So what do we do? More functions and pointers. Basically we will have X amount (net, rod, harpoon, cage, and anymore I'm missing) of functions that are set via a pointer.

IsFishing now becomes a variable, not a function. Well a pointer would be the better way to put it.

A simple example

program new;

var
IsFishing: function Boolean();

function isHarpoonFishing(): Boolean;
begin

end;

function isRodFishing(): Boolean;
begin

end;

function isNetFishing(): Boolean;
begin

end;

function isCageFishing(): Boolean;
begin

end;

function setFishingFunction: Boolean;
begin
case Players[CurrentPlayer].Strings[FISHING_STYLE] of
'Harpoon, Shark, Tuna, SwordFish': IsFishing := @isHarpoonFishing();
'etc': IsFishing := @ThisFunction;
end;
end;

begin
end.

I feel like this will be the best way to keep it organized and specific. It will also allow for the flexibility and custom functions that we need.

But again this is simply just a thought, seeing as TrackObject_MSI is becoming difficult to finish.

I actually really like that idea, nice job. :)

marpis

2010-08-13 12:09:41

Me too. That sounds like a terrific idea. That way we can really get different functions from different people for different fishingtool. :) I had quite perfect cage fishing detector in my Catherby lobster fisher, but I think it's gone in the bit heaven :(

EDIT: Actually, we don't need pointers.

function MSI_IsFishing(SpotID: integer): boolean;
// Note: TMSObject contains X, Y properties
var
script: TScript;
i, tmpX, tmpY: integer;
begin
script := MSI_Scripts[MSI_Players[CurrentPlayer].Scripts[CurrentScript]];
tmpX := MSI_Objects[SpotID].X; // <-- These have been stored in MSI_FindObject. Does that already.
tmpY := MSI_Objects[SpotID].Y;

case script.ObjectConstants[0] of // Always the first one, we only seek for one type of spot per script, right?
FISHSPOT_NET:
Result := isNetFishing(tmpX, tmpY);
FISHSPOT_LURE, FISHSPOT_BAIT:
Result := isRodFishing(tmpX, tmpY);
FISHSPOT_CAGE:
Result := isCageFishing(tmpX, tmpY);
FISHSPOT_HARPOON:
Result := isHarpoonFishing(tmpX, tmpY);
end;
end;

That's so damn easy and simple, and the ultimate best way to make it :)
One thing has to be common with all the "isFishing"-functions: they need to figure out if we are fishing by using the X, Y of the fishing spot. Shouldn't be a problem though.

Dang, we need to get the MSI_TrackObject working perfectly! I'm quite stuck with it! Help me out! :D

Coh3n

2010-08-13 12:30:13

From: marpis
Me too. That sounds like a terrific idea. That way we can really get different functions from different people for different fishingtool. :) I had quite perfect cage fishing detector in my Catherby lobster fisher, but I think it's gone in the bit heaven :(

EDIT: Actually, we don't need pointers.

function MSI_IsFishing(SpotID: integer): boolean;
// Note: TMSObject contains X, Y properties
var
script: TScript;
i, tmpX, tmpY: integer;
begin
script := MSI_Scripts[MSI_Players[CurrentPlayer].Scripts[CurrentScript]];
tmpX := MSI_Objects[SpotID].X; // <-- These have been stored in MSI_FindObject. Does that already.
tmpY := MSI_Objects[SpotID].Y;

case script.ObjectConstants[0] of // Always the first one, we only seek for one type of spot per script, right?
FISHSPOT_NET:
Result := isNetFishing(tmpX, tmpY);
FISHSPOT_LURE, FISHSPOT_BAIT:
Result := isRodFishing(tmpX, tmpY);
FISHSPOT_CAGE:
Result := isCageFishing(tmpX, tmpY);
FISHSPOT_HARPOON:
Result := isHarpoonFishing(tmpX, tmpY);
end;
end;

That's so damn easy and simple, and the ultimate best way to make it :)
One thing has to be common with all the "isFishing"-functions: they need to figure out if we are fishing by using the X, Y of the fishing spot. Shouldn't be a problem though.

Dang, we need to get the MSI_TrackObject working perfectly! I'm quite stuck with it! Help me out! :D

Yeah that works too. The functions would have to have the same parameters if we were to use pointers so that's not really an issue. And no, we want multiple fishing spot support. We'll need to add something in the player setup procedure to exclude the fishing spot if we don't have the required tools, but that shouldn't be too hard.

Also, since I'm moving in a couple weeks, I've been spending a lot more time with my girlfriend, but she works later so I can help you out with the TrackObject function. PM me your MSN and we can talk. :)

3Garrett3

2010-08-13 14:04:13

But we only need two case statements. My variable TPixle (which is listed as an int, should be boolean) is set in the setup statements, and all of the variables are set in the setup, it just needs to either pixel or colour count and compare to set values, it could literally be a single If…then statement.

Blumblebee

2010-08-13 15:02:07

From: marpis
Me too. That sounds like a terrific idea. That way we can really get different functions from different people for different fishingtool. :) I had quite perfect cage fishing detector in my Catherby lobster fisher, but I think it's gone in the bit heaven :(

EDIT: Actually, we don't need pointers.

function MSI_IsFishing(SpotID: integer): boolean;
// Note: TMSObject contains X, Y properties
var
script: TScript;
i, tmpX, tmpY: integer;
begin
script := MSI_Scripts[MSI_Players[CurrentPlayer].Scripts[CurrentScript]];
tmpX := MSI_Objects[SpotID].X; // <-- These have been stored in MSI_FindObject. Does that already.
tmpY := MSI_Objects[SpotID].Y;

case script.ObjectConstants[0] of // Always the first one, we only seek for one type of spot per script, right?
FISHSPOT_NET:
Result := isNetFishing(tmpX, tmpY);
FISHSPOT_LURE, FISHSPOT_BAIT:
Result := isRodFishing(tmpX, tmpY);
FISHSPOT_CAGE:
Result := isCageFishing(tmpX, tmpY);
FISHSPOT_HARPOON:
Result := isHarpoonFishing(tmpX, tmpY);
end;
end;

That's so damn easy and simple, and the ultimate best way to make it :)
One thing has to be common with all the "isFishing"-functions: they need to figure out if we are fishing by using the X, Y of the fishing spot. Shouldn't be a problem though.

Dang, we need to get the MSI_TrackObject working perfectly! I'm quite stuck with it! Help me out! :D


like the idea too. I merely suggested a pointer because then you to set the function once, instead of running through a case statement everytime you call on the function.

@Garrett: I just thought that instead of having to generalize the isFishing between two functions we can make completely unique functions for each situation, which in theory should give us more accurate results.

I am off camping for the next few days with my friends as we're all moving away in the next few weeks. I will do some serious brainstorming while there, and if you guys haven't sorted through everything already without me I can be of further assistance.

3Garrett3

2010-08-13 15:10:52

From: Blumblebee
@Garrett: I just thought that instead of having to generalize the isFishing between two functions we can make completely unique functions for each situation, which in theory should give us more accurate results.



I'll probably end up doing this in the end, but I think that doing it the if…then way might be better to at least get fishing launched..

Coh3n

2010-08-13 15:54:08

From: Blumblebee
like the idea too. I merely suggested a pointer because then you to set the function once, instead of running through a case statement everytime you call on the function.

@Garrett: I just thought that instead of having to generalize the isFishing between two functions we can make completely unique functions for each situation, which in theory should give us more accurate results.

I agree with both these. I say use the pointers. It may not seem like it now, but I have a feeling it will save a lot of trouble. This same concept can be used for other skills as well when needed.

3Garrett3

2010-08-14 22:07:35

So when I use the pointers, it's going to make it harder to change the variables after the functions have been made. Using locals for the data makes more sense than to implement them into separate functions. Should I leave it the way it is, and then have something like:


IsHarpoon(All tool vars)

So that it imports the vars into the functions?

Edit:

Here is something I whipped up, doubt it compiles, dunno if it's what everyone wants. It should work, the data is all the same, and even though it looks gross, if someone wants to make sure it compiles, and adds a tracker for the fishing spot, we'll have something to test.


{Box_BELOW:
IntToBox(246, 196, 272, 217);
Box_ABOVE
IntToBox(243, 128, 266, 155);
Box_RIGHT Use these variables in the creation of the boxes.
IntToBox(270, 148, 296, 180);
Box_LEFT
IntToBox(227, 166, 258, 184);
}

Function MSI_FishPixels(TWait, TCount : Integer; TTBox : TBox) : Boolean;
var
Shifts, FinalCount, Waiting : Integer;
ShiftsArray : TIntegerArray;
begin
MarkTime(Waiting);
While TimeFromMark(Waiting) <= TWait do
begin
Shifts := PixelShift(TTBox, 500);
CombineIntArray(ShiftsArray, [ShiftsArray]);
Wait(RandomRange(50,75));
end;

FinalCount := AverageTIA(ShiftsArray);
Result := (FinalCount >= TCount);
end;

Function MSI_FishGear(TColour, TTol, TCount, TWait : Integer; THue, TSat : Extended; TTBox : TBox) : Boolean;
var
Tools, FinalCount, Waiting, cts : Integer;
ToolAmount : TIntegerArray;
begin
cts := GetColorToleranceSpeed;
ColorToleranceSpeed(2);
SetToleranceSpeed2Modifiers(THue, TSat);

MarkTime(Waiting);
While TimeFromMark(Waiting) <= TWait do
begin
FindColorsSpiralTolerance(MMCX, MMCY, Tools, TColour, TTBox.X1, TTBox.Y1, TTBox.X2, TTBox.Y2, TTol);
CombineIntArray(ToolAmount, [Length(Tools)]);
Wait(RandomRange(50,75));
end;

FinalCount := AverageTIA(ToolAmount);
Result := (FinalCount >= TCount);
ColorToleranceSpeed(cts);
end;

{******************************************************************************}
{ Procedure MSI_WaitWhileFishing }
{ By: 3Garrett3 }
{ Date: 25 July 2010 }
{ Description: Waits while fishing }
{******************************************************************************}
procedure MSI_WaitWhileFishing;
var
OldInvCount, WaitTime, InvTimer, cts, i : Integer;
MyChar : TBox;
script: TScript;
TColour, TTol, TCount, TWait : Integer;
THue, TSat : Extended;
TPixel, Fishing : Boolean;
begin
Flag;
Wait(RandomRange(300, 450));
if InvFull then
Exit;

MyChar := IntToBox(0,0,0,0); // Function for tracking goes here....


script := MSI_Scripts[MSI_Players[CurrentPlayer].Scripts[CurrentScript]];
TPixel := False;

case (script.ObjectConstants[i]) of
FISHSPOT_NET:
begin
TPixel := True;
TCount := 150;
TWait := 3300;
end;

FISHSPOT_BAIT:
begin
TColour:= 727589;
TTol := 4;
THue := 0.17;
TSat := 0.65;
TCount := 50;
TWait := 4000;
end;

FISHSPOT_LURE:
begin
TColour:= 859433;
TTol := 3;
THue := 0.19;
TSat := 1.11;
TCount := 50;
TWait := 4000;
end;

FISHSPOT_CAGE:
begin
TPixel := True;
TCount := 150;
TWait := 3600;
end;

FISHSPOT_HARPOON:
begin
TPixel := True;
TCount := 160;
TWait := 3000;
end;
end;

WaitTime := GetSystemTime + 90000;
OldInvCount := InvCount;
MarkTime(InvTimer);

repeat

MSI_FindRandoms;
MSI_AntiBan(RandomRange(0, 3000), ANTI_BAN_CHANCE);

if InvFull then break;

if (TimeFromMark(InvTimer) > 30000) then // If no new fish in inv after 30 seconds, spot probably moved
if (OldInvCount = InvCount) then break
else begin
OldInvCount := InvCount;
MarkTime(InvTimer);
end;

if TPixel then
Fishing := MSI_FishPixels
else
Fishing := MSI_FishGear;
if not Fishing then break;

Wait(RandomRange(200, 500));

until(WaitTime > GetSystemTime)
end;

Heavenguard

2010-08-14 23:14:02

From: 3Garrett3
So when I use the pointers, it's going to make it harder to change the variables after the functions have been made. Using locals for the data makes more sense than to implement them into separate functions. Should I leave it the way it is, and then have something like:


IsHarpoon(All tool vars)

So that it imports the vars into the functions?

Edit:

Here is something I whipped up, doubt it compiles, dunno if it's what everyone wants. It should work, the data is all the same, and even though it looks gross, if someone wants to make sure it compiles, and adds a tracker for the fishing spot, we'll have something to test.


{Box_BELOW:
IntToBox(246, 196, 272, 217);
Box_ABOVE
IntToBox(243, 128, 266, 155);
Box_RIGHT Use these variables in the creation of the boxes.
IntToBox(270, 148, 296, 180);
Box_LEFT
IntToBox(227, 166, 258, 184);
}

Function MSI_FishPixels(TWait, TCount : Integer; TTBox : TBox) : Boolean;
var
Shifts, FinalCount, Waiting : Integer;
ShiftsArray : TIntegerArray;
begin
MarkTime(Waiting);
While TimeFromMark(Waiting) <= TWait do
begin
Shifts := PixelShift(TTBox, 500);
CombineIntArray(ShiftsArray, [ShiftsArray]);
Wait(RandomRange(50,75));
end;

FinalCount := AverageTIA(ShiftsArray);
Result := (FinalCount >= TCount);
end;

Function MSI_FishGear(TColour, TTol, TCount, TWait : Integer; THue, TSat : Extended; TTBox : TBox) : Boolean;
var
Tools, FinalCount, Waiting, cts : Integer;
ToolAmount : TIntegerArray;
begin
cts := GetColorToleranceSpeed;
ColorToleranceSpeed(2);
SetToleranceSpeed2Modifiers(THue, TSat);

MarkTime(Waiting);
While TimeFromMark(Waiting) <= TWait do
begin
FindColorsSpiralTolerance(MMCX, MMCY, Tools, TColour, TTBox.X1, TTBox.Y1, TTBox.X2, TTBox.Y2, TTol);
CombineIntArray(ToolAmount, [Length(Tools)]);
Wait(RandomRange(50,75));
end;

FinalCount := AverageTIA(ToolAmount);
Result := (FinalCount >= TCount);
ColorToleranceSpeed(cts);
end;

{******************************************************************************}
{ Procedure MSI_WaitWhileFishing }
{ By: 3Garrett3 }
{ Date: 25 July 2010 }
{ Description: Waits while fishing }
{******************************************************************************}
procedure MSI_WaitWhileFishing;
var
OldInvCount, WaitTime, InvTimer, cts, i : Integer;
MyChar : TBox;
script: TScript;
TColour, TTol, TCount, TWait : Integer;
THue, TSat : Extended;
TPixel, Fishing : Boolean;
begin
Flag;
Wait(RandomRange(300, 450));
if InvFull then
Exit;

MyChar := IntToBox(0,0,0,0); // Function for tracking goes here....


script := MSI_Scripts[MSI_Players[CurrentPlayer].Scripts[CurrentScript]];
TPixel := False;

case (script.ObjectConstants[i]) of
FISHSPOT_NET:
begin
TPixel := True;
TCount := 150;
TWait := 3300;
end;

FISHSPOT_BAIT:
begin
TColour:= 727589;
TTol := 4;
THue := 0.17;
TSat := 0.65;
TCount := 50;
TWait := 4000;
end;

FISHSPOT_LURE:
begin
TColour:= 859433;
TTol := 3;
THue := 0.19;
TSat := 1.11;
TCount := 50;
TWait := 4000;
end;

FISHSPOT_CAGE:
begin
TPixel := True;
TCount := 150;
TWait := 3600;
end;

FISHSPOT_HARPOON:
begin
TPixel := True;
TCount := 160;
TWait := 3000;
end;
end;

WaitTime := GetSystemTime + 90000;
OldInvCount := InvCount;
MarkTime(InvTimer);

repeat

MSI_FindRandoms;
MSI_AntiBan(RandomRange(0, 3000), ANTI_BAN_CHANCE);

if InvFull then break;

if (TimeFromMark(InvTimer) > 30000) then // If no new fish in inv after 30 seconds, spot probably moved
if (OldInvCount = InvCount) then break
else begin
OldInvCount := InvCount;
MarkTime(InvTimer);
end;

if TPixel then
Fishing := MSI_FishPixels
else
Fishing := MSI_FishGear;
if not Fishing then break;

Wait(RandomRange(200, 500));

until(WaitTime > GetSystemTime)
end;


Looks Good ^^

Coh3n

2010-08-15 00:48:01

From: 3Garrett3
So when I use the pointers, it's going to make it harder to change the variables after the functions have been made.

What variables would you have to change? It's just a separate function for each type of fishing so there would be no need to changing of variables.

case FishSpotType of
LURE:
IsFishing := @IsLureFishing;

NET:
IsFishing := @IsNetFishing;
end;

while (IsFishing) do
begin
//...
end;
I still think we should use the pointer thing, but if we were to go with what you have we should at least make a new type for the variables and load them with a different function.

3Garrett3

2010-08-15 11:51:50

From: Coh3n
What variables would you have to change? It's just a separate function for each type of fishing so there would be no need to changing of variables.

case FishSpotType of
LURE:
IsFishing := @IsLureFishing;

NET:
IsFishing := @IsNetFishing;
end;

while (IsFishing) do
begin
//...
end;
I still think we should use the pointer thing, but if we were to go with what you have we should at least make a new type for the variables and load them with a different function.


Well either way it is easier to load the variables separately. I loaded them locally because I don't really like global variables, and they are still pretty easy to find. Making a custom type for it (IE "FishingTool") then using a system like


Result.Colour
Result.Hue
Result.Count
etc

Would work, in my mind. I'm just aiming for something that actually functions so we can test the data.

Blumblebee

2010-08-15 17:03:24

I just think loading things locally takes time and decreases readability. I just see pointers organizing code much more efficiently and being much easier to read.

Nonetheless, lets get things into practice and tested/testing. Garrett you've made a good start to the code, can I ask if any of it's been tested yet?

3Garrett3

2010-08-15 20:26:53

From: Blumblebee
I just think loading things locally takes time and decreases readability. I just see pointers organizing code much more efficiently and being much easier to read.

Nonetheless, lets get things into practice and tested/testing. Garrett you've made a good start to the code, can I ask if any of it's been tested yet?


I've tested the experimental data (TCount, TWait, TColour, etc) a few times now, and all seems to be in working order. I can't test the whole thing fully without all the functions yet though, so until then it will remain untested.

Coh3n

2010-08-16 15:40:57

The way you have it setup now, it would be easier to just create a type. Wouldn't take long either.

Tniffoc

2010-08-16 15:56:39

I have an interesting way of fishing spot finding if anybody cares. I really don't have the time right now to implement it into MSI myself but I tell you its pretty cool. I can send the methods to you if you would like to take a look at them but I really don't have the time to implement them at least for a few months.

Coh3n

2010-08-16 15:59:47

From: Tniffoc
I have an interesting way of fishing spot finding if anybody cares. I really don't have the time right now to implement it into MSI myself but I tell you its pretty cool. I can send the methods to you if you would like to take a look at them but I really don't have the time to implement them at least for a few months.

Can you just post them here? :)

Tniffoc

2010-08-16 16:20:51

I'll explain WHAT its doing when I get home. (6 hrs?)


function AmaxIndex(a: array of Integer): Integer;
var
m,runner: Integer;
begin
Result := 0;
m := a[0];
for runner:=0 to High(a) do
begin
if a[runner] > m then
begin
m := a[runner];
Result := runner;
end;
end;
end;
function AminIndex(a: array of Integer): Integer;
var
m,runner: Integer;
begin
Result := 0;
m := a[0];
for runner:=0 to High(a) do
begin
if a[runner] < m then
begin
m := a[runner];
Result := runner;
end;
end;
end;
function GetRCircle(TPA: TPointArray): Extended;
var
x,y,distances: TIntegerArray;
i,ii,iii,davg,stdd: Integer;
xleft,xtop,xright,xbottom,center: TPoint;
begin
SetLength(x,Length(TPA));
SetLength(y,Length(TPA));
for i:=0 to High(TPA) do
begin
x[i] := TPA[i].x;
y[i] := TPA[i].y;
end;
i := AmaxIndex(x);
xright := TPA[i];
i := AmaxIndex(y);
xtop := TPA[i];
i := AminIndex(x);
xleft := TPA[i];
i := AminIndex(y);
xbottom := TPA[i];
center := Point((xright.x+xtop.x+xleft.x+xbottom.x) div 4,(xright.y+xtop.y+xleft.y+xbottom.y) div 4);
SetLength(distances,Length(TPA));
for i:=0 to High(TPA) do
begin
ii := TPA[i].x - center.x;
iii := TPA[i].y - center.y;
ii := ii*ii
iii := iii*iii;
distances[i] := Round(sqrt(ii+iii));
end;
davg := 0;
for i:=0 to High(distances) do
begin
IncEx(davg,distances[i]);
end;
davg := davg div Length(distances);
stdd := 0;
for i:=0 to High(distances) do
begin
stdd := stdd + ((distances[i] - davg)*(distances[i] - davg));
end;
stdd := stdd div Length(distances);
Result := sqrt(stdd);
end;
procedure SortATPAByRCircle(var ATPA: T2DPointArray);
var
rs: TExtendedArray;
i,lastPlace,maxLoc: Integer;
temp: TPointArray;
etemp: Extended;
begin
SetLength(rs,Length(ATPA));
for i:=0 to High(ATPA) do
rs[i] := GetRCircle(ATPA[i]);
for lastPlace:=0 to High(rs) do
begin
maxLoc := 0;
for i:=High(rs) downto lastPlace+1 do
begin
if rs[i] > rs[maxLoc] then
maxLoc := i;
end;
etemp := rs[maxLoc];
rs[maxLoc] := rs[lastPlace];
rs[lastPlace] := etemp;
temp := ATPA[maxLoc];
ATPA[maxLoc] := ATPA[lastPlace];
ATPA[lastPlace] := temp;
end;
end;
function FindFishingSpot: TPoint;
var
rgb: T2DIntegerArray;
xyz,hsl: T2DExtendedArray;
hsmods: TExtendedArray;
cts,i,mix,miy: Integer;
tol,col: TIntegerArray;
TPA: TPointArray;
ATPA: T2DPointArray;
begin
if not ShouldContinue then
Exit;
SetLength(hsmods,2);
SetLength(tol,1);
SetLength(col,1);
Result := Point(0,0);
cts := GetColorToleranceSpeed;
GetColorArrayInfo([10787734,10919578,11117986],col,tol,hsmods,rgb,hsl,xyz);
ColorToleranceSpeed(2);
SetColorSpeed2Modifiers(hsmods[0],hsmods[1]);
FindColorsSpiralTolerance(MSCX,MSCY,TPA,col[0],MSX1,MSY1,MSX2,MSY2,tol[0]);
if Length(TPA) > 8 then
begin
ATPA := SplitTPAEx(TPA,8,8);
SortATPAByRCircle(ATPA);
for i:=0 to High(ATPA) do
begin
MiddleTPAEx(ATPA[i],mix,miy);
MMouse(mix,miy,2,2);
Wait(200 + random(300));
if IsUpText('ish') then
begin
GetMousePos(mix, miy);
Result := Point(mix,miy);
ColorToleranceSpeed(cts);
Exit;
end;
end;
end else
begin
for i:=0 to High(TPA) do
begin
MMouse(TPA[i].x,TPA[i].y,2,2);
Wait(200 + random(300));
if IsUpTextMultiCustom(['hing','ish','pot']) then
begin
GetMousePos(mix,miy);
ColorToleranceSpeed(cts);
Result := Point(mix,miy);
Exit;
end;
end;
end;
ColorToleranceSpeed(cts);
end;

3Garrett3

2010-08-16 19:15:23

From: Tniffoc
I'll explain WHAT its doing when I get home. (6 hrs?)


function AmaxIndex(a: array of Integer): Integer;
var
m,runner: Integer;
begin
Result := 0;
m := a[0];
for runner:=0 to High(a) do
begin
if a[runner] > m then
begin
m := a[runner];
Result := runner;
end;
end;
end;
function AminIndex(a: array of Integer): Integer;
var
m,runner: Integer;
begin
Result := 0;
m := a[0];
for runner:=0 to High(a) do
begin
if a[runner] < m then
begin
m := a[runner];
Result := runner;
end;
end;
end;
function GetRCircle(TPA: TPointArray): Extended;
var
x,y,distances: TIntegerArray;
i,ii,iii,davg,stdd: Integer;
xleft,xtop,xright,xbottom,center: TPoint;
begin
SetLength(x,Length(TPA));
SetLength(y,Length(TPA));
for i:=0 to High(TPA) do
begin
x[i] := TPA[i].x;
y[i] := TPA[i].y;
end;
i := AmaxIndex(x);
xright := TPA[i];
i := AmaxIndex(y);
xtop := TPA[i];
i := AminIndex(x);
xleft := TPA[i];
i := AminIndex(y);
xbottom := TPA[i];
center := Point((xright.x+xtop.x+xleft.x+xbottom.x) div 4,(xright.y+xtop.y+xleft.y+xbottom.y) div 4);
SetLength(distances,Length(TPA));
for i:=0 to High(TPA) do
begin
ii := TPA[i].x - center.x;
iii := TPA[i].y - center.y;
ii := ii*ii
iii := iii*iii;
distances[i] := Round(sqrt(ii+iii));
end;
davg := 0;
for i:=0 to High(distances) do
begin
IncEx(davg,distances[i]);
end;
davg := davg div Length(distances);
stdd := 0;
for i:=0 to High(distances) do
begin
stdd := stdd + ((distances[i] - davg)*(distances[i] - davg));
end;
stdd := stdd div Length(distances);
Result := sqrt(stdd);
end;
procedure SortATPAByRCircle(var ATPA: T2DPointArray);
var
rs: TExtendedArray;
i,lastPlace,maxLoc: Integer;
temp: TPointArray;
etemp: Extended;
begin
SetLength(rs,Length(ATPA));
for i:=0 to High(ATPA) do
rs[i] := GetRCircle(ATPA[i]);
for lastPlace:=0 to High(rs) do
begin
maxLoc := 0;
for i:=High(rs) downto lastPlace+1 do
begin
if rs[i] > rs[maxLoc] then
maxLoc := i;
end;
etemp := rs[maxLoc];
rs[maxLoc] := rs[lastPlace];
rs[lastPlace] := etemp;
temp := ATPA[maxLoc];
ATPA[maxLoc] := ATPA[lastPlace];
ATPA[lastPlace] := temp;
end;
end;
function FindFishingSpot: TPoint;
var
rgb: T2DIntegerArray;
xyz,hsl: T2DExtendedArray;
hsmods: TExtendedArray;
cts,i,mix,miy: Integer;
tol,col: TIntegerArray;
TPA: TPointArray;
ATPA: T2DPointArray;
begin
if not ShouldContinue then
Exit;
SetLength(hsmods,2);
SetLength(tol,1);
SetLength(col,1);
Result := Point(0,0);
cts := GetColorToleranceSpeed;
GetColorArrayInfo([10787734,10919578,11117986],col,tol,hsmods,rgb,hsl,xyz);
ColorToleranceSpeed(2);
SetColorSpeed2Modifiers(hsmods[0],hsmods[1]);
FindColorsSpiralTolerance(MSCX,MSCY,TPA,col[0],MSX1,MSY1,MSX2,MSY2,tol[0]);
if Length(TPA) > 8 then
begin
ATPA := SplitTPAEx(TPA,8,8);
SortATPAByRCircle(ATPA);
for i:=0 to High(ATPA) do
begin
MiddleTPAEx(ATPA[i],mix,miy);
MMouse(mix,miy,2,2);
Wait(200 + random(300));
if IsUpText('ish') then
begin
GetMousePos(mix, miy);
Result := Point(mix,miy);
ColorToleranceSpeed(cts);
Exit;
end;
end;
end else
begin
for i:=0 to High(TPA) do
begin
MMouse(TPA[i].x,TPA[i].y,2,2);
Wait(200 + random(300));
if IsUpTextMultiCustom(['hing','ish','pot']) then
begin
GetMousePos(mix,miy);
ColorToleranceSpeed(cts);
Result := Point(mix,miy);
Exit;
end;
end;
end;
ColorToleranceSpeed(cts);
end;


I can't make heads nor tails with this code XD. I hate criticizing standards, but I can't read any of this :p.

I'll await your explanation, or some free time to look over it better.

i luffs yeww

2010-08-16 20:35:55


function AMaxIndex(a: array of Integer): Integer;
var
m, Runner: Integer;
begin
Result := 0;
m := a[0];
for Runner := 0 to High(a) do
begin
if(a[Runner] > m)then
begin
m := a[Runner];
Result := Runner;
end;
end;
end;

function AMinIndex(a: array of Integer): Integer;
var
m, Runner: Integer;
begin
Result := 0;
m := a[0];
for Runner := 0 to High(a) do
begin
if(a[Runner] < m)then
begin
m := a[Runner];
Result := Runner;
end;
end;
end;

function GetRCircle(TPA: TPointArray): Extended;
var
x, y, Distances: TIntegerArray;
i, ii, iii, davg, stdd: Integer;
xLeft, xTop, xRight, xBottom, Center: TPoint;
begin
SetLength(x, Length(TPA));
SetLength(y, Length(TPA));
for i := 0 to High(TPA) do
begin
x[i] := TPA[i].x;
y[i] := TPA[i].y;
end;
i := AMaxIndex(x);
xRight := TPA[i];
i := AMaxIndex(y);
xTop := TPA[i];
i := AMinIndex(x);
xLeft := TPA[i];
i := AMinIndex(y);
xBottom := TPA[i];
Center := Point((xRight.x + xTop.x + xLeft.x + xBottom.x) div 4, (xRight.y + xTop.y + xLeft.y + xBottom.y) div 4);
SetLength(Distances, Length(TPA));
for i := 0 to High(TPA) do
begin
ii := TPA[i].x - Center.x;
iii := TPA[i].y - Center.y;
ii := ii * ii;
iii := iii * iii;
Distances[i] := Round(Sqrt(ii + iii));
end;
davg := 0;
for i := 0 to High(Distances) do
IncEx(davg, Distances[i]);
davg := davg div Length(Distances);
stdd := 0;
for i := 0 to High(Distances) do
stdd := stdd + Sqr(Distances[i] - davg);
stdd := stdd div Length(Distances);
Result := Sqrt(stdd);
end;

procedure SortATPAByRCircle(var ATPA: T2DPointArray);
var
rs: TExtendedArray;
i, LastPlace, MaxLoc: Integer;
Temp: TPointArray;
eTemp: Extended;
begin
SetLength(rs, Length(ATPA));
for i := 0 to High(ATPA) do
rs[i] := GetRCircle(ATPA[i]);
for LastPlace := 0 to High(rs) do
begin
MaxLoc := 0;
for i := High(rs) downto (LastPlace + 1) do
if rs[i] > rs[MaxLoc] then
MaxLoc := i;
eTemp := rs[MaxLoc];
rs[MaxLoc] := rs[LastPlace];
rs[LastPlace] := eTemp;
Temp := ATPA[MaxLoc];
ATPA[MaxLoc] := ATPA[LastPlace];
ATPA[LastPlace] := Temp;
end;
end;

function FindFishingSpot: TPoint;
var
RGB: T2DIntegerArray;
XYZ, HSL: T2DExtendedArray;
HSMods: TExtendedArray;
CTS, i, MIX, MIY: Integer;
Tol, Col: TIntegerArray;
TPA: TPointArray;
ATPA: T2DPointArray;
begin
if(not(ShouldContinue))then
Exit;
SetLength(HSMods, 2);
SetLength(tol, 1);
SetLength(Col, 1);
Result := Point(0, 0);
CTS := GetColorToleranceSpeed;
GetColorArrayInfo([10787734, 10919578, 11117986], Col, Tol, HSMods, RGB, HSL, XYZ);
ColorToleranceSpeed(2);
SetColorSpeed2Modifiers(HSMods[0], HSMods[1]);
FindColorsSpiralTolerance(MSCX, MSCY, TPA, Col[0], MSX1, MSY1, MSX2, MSY2, Tol[0]);
if(Length(TPA) > 8)then
begin
ATPA := SplitTPAEx(TPA, 8, 8);
SortATPAByRCircle(ATPA);
for i := 0 to High(ATPA) do
begin
MiddleTPAEx(ATPA[i], MIX, MIY);
MMouse(MIX, MIY, 2, 2);
Wait(200 + Random(300));
if(IsUpText('ish'))then
begin
GetMousePos(MIX, MIY);
Result := Point(MIX, MIY);
ColorToleranceSpeed(CTS);
Exit;
end;
end;
end else
begin
for i := 0 to High(TPA) do
begin
MMouse(TPA[i].x, TPA[i].y, 2, 2);
Wait(200 + Random(300));
if(IsUpTextMultiCustom(['hing','ish','pot']))then
begin
GetMousePos(MIX, MIY);
ColorToleranceSpeed(CTS);
Result := Point(MIX, MIY);
Exit;
end;
end;
end;
ColorToleranceSpeed(CTS);
end;

Standardized it.. Really wasn't anything wrong, just capitalization.

If you meant commenting it I could do it but I dunno what you mean.

Also, Tniffoc, can you post ShouldContinue?

Tniffoc

2010-08-16 21:37:43

Oops. ShouldContinue is just a thing from the script I took the methods out of. Ignore it entirely. I just checked if we were logged in and the currentplayer was active and that did some other little checks (i.e. randoms).

Explanation coming soon. I'm writing it as you're reading this.

Description
A(max|min)Index -
Description: These methods find the index of the maximum or minimum value in an array. These are just used by GetRCircle.
GetRCircle(TPA: TPointArray): Extended -
Arguments:
TPA: A TPointArray representing a prospective fishing spot.
Description:: This gets the correlation coefficient of the set of points to a circle. Basically, this is a number that represents how close the points are to being a perfect circle.
SortATPAByRCircle(var ATPA: T2DPointArray) -
Description: This simply sorts an ATPA with the TPA who's points are closest to a true circle first and so on.
FindFishingSpot: TPoint -
Description: This returns the TPoint at the center of a fishing spot. It will search for bubbles that are closest to a perfect circle first.

——————–

The way I decided to represent how close a set of points was to a perfect circle was as follows.
  1. Find the "center" of the circle by averaging the x and y values of the topmost, bottommost, and both sidemost points in the TPA.
  2. Find the distance from the "center" to all the points.
  3. Find the standard deviation of the distances of the points. A higher standard deviation means the collection of points is less like a circle.
VOILA!

Just some math I cooked up one day.

Coh3n

2010-08-16 23:26:28

From: Tniffoc
Oops. ShouldContinue is just a thing from the script I took the methods out of. Ignore it entirely. I just checked if we were logged in and the currentplayer was active and that did some other little checks (i.e. randoms).

Explanation coming soon. I'm writing it as you're reading this.

Description
A(max|min)Index -
Description: These methods find the index of the maximum or minimum value in an array. These are just used by GetRCircle.
GetRCircle(TPA: TPointArray): Extended -
Arguments:
TPA: A TPointArray representing a prospective fishing spot.
Description:: This gets the correlation coefficient of the set of points to a circle. Basically, this is a number that represents how close the points are to being a perfect circle.
SortATPAByRCircle(var ATPA: T2DPointArray) -
Description: This simply sorts an ATPA with the TPA who's points are closest to a true circle first and so on.
FindFishingSpot: TPoint -
Description: This returns the TPoint at the center of a fishing spot. It will search for bubbles that are closest to a perfect circle first.

——————–

The way I decided to represent how close a set of points was to a perfect circle was as follows.
  1. Find the "center" of the circle by averaging the x and y values of the topmost, bottommost, and both sidemost points in the TPA.
  2. Find the distance from the "center" to all the points.
  3. Find the standard deviation of the distances of the points. A higher standard deviation means the collection of points is less like a circle.
VOILA!

Just some math I cooked up one day.

That sounds like it's a good way to track an object, but our biggest problem is that sometimes there's fishing spots under fishing spots. So, if the one you're fishing at has disappeared, there may be one underneath which would make the script think that it's still there.

Although, how often does this really happen? If it's rare, the inventory failsafe may be enough.

i luffs yeww

2010-08-17 00:01:16


Mouse(x, y, 2, 2, False);
if(not(ChooseOption('something')))then
Writeln('wat');

Problem solved? :)

Tniffoc

2010-08-17 00:03:42

Ya. You could just change my clicking routine. Mine came from a Draynor fisher so there's only one kind of fishing spot; therefore regular clicking was faster.

EDIT: @Coh3n if you're thinking that I'm using the location of the fishing spot to detect that I am fishing, you would be mistaken. if you want I can post my epic collection of WhileFishing procedures for all the different kinds of equiptment. All are flawless in my approximation. I'll have them posted later tonight. Have to finish some homework ATM though.

Coh3n

2010-08-17 00:32:28

From: Tniffoc
Ya. You could just change my clicking routine. Mine came from a Draynor fisher so there's only one kind of fishing spot; therefore regular clicking was faster.

EDIT: @Coh3n if you're thinking that I'm using the location of the fishing spot to detect that I am fishing, you would be mistaken. if you want I can post my epic collection of WhileFishing procedures for all the different kinds of equiptment. All are flawless in my approximation. I'll have them posted later tonight. Have to finish some homework ATM though.

My bad, I didn't realize that your description was detecting the fishing spot, not a WaitWhileFishing type deal. But yes, please post your WhileFishing functions. :)

Tniffoc

2010-08-17 00:36:32

yes. The entire point of all that math is to ENSURE more accurate clicking when finding the fishing spot. I'm collecting my WhileFishing methods from all my fishers. Can't seem to find the rod one but I'll have them up as soon as I find it.

marpis

2010-08-17 02:22:44

From: Tniffoc

  1. Find the "center" of the circle by averaging the x and y values of the topmost, bottommost, and both sidemost points in the TPA.
  2. Find the distance from the "center" to all the points.


What if the "center" is actually very far from the real center?
In the case that there's one point far from others and it stretches TPA boundaries?

Tniffoc

2010-08-17 16:52:47

From: marpis
What if the "center" is actually very far from the real center?
In the case that there's one point far from others and it stretches TPA boundaries?


Well the theory is that because the TPA is split at the size of the bubble, there won't be any points that far off balance. Anyway, the method will work fine without the math its just the math insures less "mis-hovers". As long as the TPA is just the size of a bubble, it will be fine.

Coh3n

2010-08-17 17:40:24

From: Tniffoc
Well the theory is that because the TPA is split at the size of the bubble, there won't be any points that far off balance. Anyway, the method will work fine without the math its just the math insures less "mis-hovers". As long as the TPA is just the size of a bubble, it will be fine.

Regardless, you should do a length check to skip the TPAs with Length < 20 or whatever.

Tniffoc

2010-08-17 22:38:01

From: Coh3n
Regardless, you should do a length check to skip the TPAs with Length < 20 or whatever.


Well I mean TPA size as the width and height that the points contained in the TPA are located in. This is achieved when using "SplitTPA(ex)?".

I could however make the function ignore a point if there are no points within 5 pixels of it. How does that sound as a fix?

Coh3n

2010-08-17 22:45:26

From: Tniffoc
I could however make the function ignore a point if there are no points within 5 pixels of it. How does that sound as a fix?

That's what I'm saying. :p

When you use SplitTPA, you create an ATPA. You'd skip ones by having:

if (Length(ATPA[i]) < 20) then
Continue

Tniffoc

2010-08-17 23:49:21

Ahh. Good idea. But that's not quite what I was saying in my last post. Whatever.

Coh3n

2010-08-18 01:13:53

From: Tniffoc
Ahh. Good idea. But that's not quite what I was saying in my last post. Whatever.

You were saying to ignore a point if there isn't 5 others around it, which is the same idea as what I said - it ignores points that may be "bad" (i.e. way off on the other side of the screen).

Tniffoc

2010-08-18 01:25:07

I thought you were just saying to ignore TPAs that aren't long enough. Whatever. I'm going to be totally out of commission for the next week but I'll get around to putting some of these fixes in hopefully over the weekend or early next week.

Coh3n

2010-08-18 14:56:49

Alright guys we're kind of having a lot of ideas thrown around here, and we're not really getting anywhere. I've been talking to Nava2 and in his Karamja Fisher (SRL Member's only) and what he did was look for a color from the tool in the inventory in a box around the center of the main screen.

He said there was a correlation between the two where a color or colors on the item were exactly the same as the object on the main screen. The colors are dynamic, but the points are static meaning that the color on same point (on both the item and main screen) change to the same color.

If you didn't really understand that - There's always a similar color on both the inventory item and the main screen object.

This method was also used a long time ago, so it may not work, but it's worth a shot. If it doesn't work, I'd like to hold a vote for the pointer method suggested by blumblee as there's no doubt it will be easy updateable, easy to understand and more organized.

Take a look at these two functions from his fisher:

procedure SetupPlayer;
var
s: TStringArray;
i, ii, l: Integer;
p, pp: TPoint;
t: TPointArray;
begin
if not xLoggedIn then
begin
LoginPlayer;
Wait(800);
end;
with Players[CurrentPlayer] do
begin
if not Booleans[99] then
begin
// Fishing Info
//--------------

// What Type?
Strings[0] := LowerCase(Strings[0]);
s := ['et ', 'ait', 'arp', 'age'];
t := [Point(585, 225), Point(574, 229), Point(583, 221), Point(578, 240)];
case Strings[0] of
'net', 'shrimp', 'anchovies' : i := 0;
'bait', 'sardine', 'herring' : i := 1;
'tuna', 'swordfish', 'swordy', 'harpoon': i := 2;
'cage', 'lobster', 'lobby' : i := 3;
end;
pp := t[i];
Strings[1] := s[i];
if InIntArray([0, 1], i) then
Strings[2] := 'et '
else
if InIntArray([2, 3], i) then
Strings[2] := 'age';

// Setting Up DTMs for Equiptment and Fish
for ii := 0 to 3 do
begin
Booleans[20 + ii] := DTMLoaded[i][ii];
if DTMLoaded[i][ii] then
Integers[20 + ii] := DTMArray[i][ii];
end;
Integers[25] := 2;
if Booleans[21] then
Inc(Integers[25]);

// Setup Inventory
//-----------------
// Place coins in last spot
GameTab(4);

if FindCoins(p.x, p.y, 'inv') then
begin
l := CoordsToItem(p.x, p.y);
if l <> 28 then
begin
DragItem(l, 28);
Wait(RandomRange(500, 700));
end;
end;

// Place equiptment in spots 1 and 2.
for l := 1 to 2 do
if Booleans[19 + l] then
if FindItem(p.x, p.y, 'dtm', Integers[19 + l], MIX1, MIY1, MIX2, MIY2, []) then
begin
ii := CoordsToItem(p.x, p.y);
if ii <> l then
DragItem(ii, l);
Wait(RandomRange(300, 500));
end;

// Gets the Colour of the Equiptment to look for while fishing
if CheckEquiptment then
Integers[24] := GetColor(pp.x, pp.y)
else
begin
Writeln('Could not find equiptment in SetupPlayer.');
LogOut;
end;

{$IFDEF DEBUG}
Writeln('Player ' + IntToStr(CurrentPlayer) + ' Info:');
for ii := 0 to 2 do
Writeln(IntToStr(ii) + ' ' + Strings[ii]);
Writeln('Loading DTM Index: ' + IntToStr(i));
Writeln('IsFishing Colour: ' + IntToStr(Integers[24]));
Writeln('Player LoggedIn: ' + BoolToStr(xLoggedIn));
{$ENDIF}

Name := Capitalize(LowerCase(Name));
Booleans[99] := True;
end;

Calibrate;
end;
end;

function IsFishing(x, y: Integer): Boolean;
var
wTime, c: Integer;
t: TPointArray;
{$IFDEF DEBUG}
Line: Integer;
s: String;
{$ENDIF}
begin
Result := False;
if not xLoggedIn then Exit;
wTime := GetTimeRunning + 6000;
c := GetColorToleranceSpeed;
ColorToleranceSpeed(2);
while (wTime > GetTimeRunning) and (not Result) do
begin
if FindColorsTolerance(t, Players[CurrentPlayer].Integers[24], x - 40, y - 40, x + 40, y + 40, 6) then
Result := High(t) > 6;
{$IFDEF DEBUG}
s := 'IsFishing: Found ' + IntToStr(Length(t)) + ' occurances of equiptment colour.';
Line := FindDebugLine(' occurances of e');
if Line = (GetDebugLineCount - 2) then
begin
ReplaceDebugLine(Line, s);
ReplaceDebugLine(Line + 1, 'IsFishing = ' + BoolToStr(Result));
end else
begin
Writeln(s);
Writeln('IsFishing = ' + BoolToStr(Result));
end;
{$ENDIF}
Wait(400);
end;
ColorToleranceSpeed(c);
Wait(RandomRange(400, 600));
end;

3Garrett3

2010-08-18 15:58:03

From: Coh3n
Alright guys we're kind of having a lot of ideas thrown around here, and we're not really getting anywhere. I've been talking to Nava2 and in his Karamja Fisher (SRL Member's only) and what he did was look for a color from the tool in the inventory in a box around the center of the main screen.

He said there was a correlation between the two where a color or colors on the item were exactly the same as the object on the main screen. The colors are dynamic, but the points are static meaning that the color on same point (on both the item and main screen) change to the same color.

If you didn't really understand that - There's always a similar color on both the inventory item and the main screen object.

This method was also used a long time ago, so it may not work, but it's worth a shot. If it doesn't work, I'd like to hold a vote for the pointer method suggested by blumblee as there's no doubt it will be easy updateable, easy to understand and more organized.

Take a look at these two functions from his fisher:

procedure SetupPlayer;
var
s: TStringArray;
i, ii, l: Integer;
p, pp: TPoint;
t: TPointArray;
begin
if not xLoggedIn then
begin
LoginPlayer;
Wait(800);
end;
with Players[CurrentPlayer] do
begin
if not Booleans[99] then
begin
// Fishing Info
//--------------

// What Type?
Strings[0] := LowerCase(Strings[0]);
s := ['et ', 'ait', 'arp', 'age'];
t := [Point(585, 225), Point(574, 229), Point(583, 221), Point(578, 240)];
case Strings[0] of
'net', 'shrimp', 'anchovies' : i := 0;
'bait', 'sardine', 'herring' : i := 1;
'tuna', 'swordfish', 'swordy', 'harpoon': i := 2;
'cage', 'lobster', 'lobby' : i := 3;
end;
pp := t[i];
Strings[1] := s[i];
if InIntArray([0, 1], i) then
Strings[2] := 'et '
else
if InIntArray([2, 3], i) then
Strings[2] := 'age';

// Setting Up DTMs for Equiptment and Fish
for ii := 0 to 3 do
begin
Booleans[20 + ii] := DTMLoaded[i][ii];
if DTMLoaded[i][ii] then
Integers[20 + ii] := DTMArray[i][ii];
end;
Integers[25] := 2;
if Booleans[21] then
Inc(Integers[25]);

// Setup Inventory
//-----------------
// Place coins in last spot
GameTab(4);

if FindCoins(p.x, p.y, 'inv') then
begin
l := CoordsToItem(p.x, p.y);
if l <> 28 then
begin
DragItem(l, 28);
Wait(RandomRange(500, 700));
end;
end;

// Place equiptment in spots 1 and 2.
for l := 1 to 2 do
if Booleans[19 + l] then
if FindItem(p.x, p.y, 'dtm', Integers[19 + l], MIX1, MIY1, MIX2, MIY2, []) then
begin
ii := CoordsToItem(p.x, p.y);
if ii <> l then
DragItem(ii, l);
Wait(RandomRange(300, 500));
end;

// Gets the Colour of the Equiptment to look for while fishing
if CheckEquiptment then
Integers[24] := GetColor(pp.x, pp.y)
else
begin
Writeln('Could not find equiptment in SetupPlayer.');
LogOut;
end;

{$IFDEF DEBUG}
Writeln('Player ' + IntToStr(CurrentPlayer) + ' Info:');
for ii := 0 to 2 do
Writeln(IntToStr(ii) + ' ' + Strings[ii]);
Writeln('Loading DTM Index: ' + IntToStr(i));
Writeln('IsFishing Colour: ' + IntToStr(Integers[24]));
Writeln('Player LoggedIn: ' + BoolToStr(xLoggedIn));
{$ENDIF}

Name := Capitalize(LowerCase(Name));
Booleans[99] := True;
end;

Calibrate;
end;
end;

function IsFishing(x, y: Integer): Boolean;
var
wTime, c: Integer;
t: TPointArray;
{$IFDEF DEBUG}
Line: Integer;
s: String;
{$ENDIF}
begin
Result := False;
if not xLoggedIn then Exit;
wTime := GetTimeRunning + 6000;
c := GetColorToleranceSpeed;
ColorToleranceSpeed(2);
while (wTime > GetTimeRunning) and (not Result) do
begin
if FindColorsTolerance(t, Players[CurrentPlayer].Integers[24], x - 40, y - 40, x + 40, y + 40, 6) then
Result := High(t) > 6;
{$IFDEF DEBUG}
s := 'IsFishing: Found ' + IntToStr(Length(t)) + ' occurances of equiptment colour.';
Line := FindDebugLine(' occurances of e');
if Line = (GetDebugLineCount - 2) then
begin
ReplaceDebugLine(Line, s);
ReplaceDebugLine(Line + 1, 'IsFishing = ' + BoolToStr(Result));
end else
begin
Writeln(s);
Writeln('IsFishing = ' + BoolToStr(Result));
end;
{$ENDIF}
Wait(400);
end;
ColorToleranceSpeed(c);
Wait(RandomRange(400, 600));
end;


So you want to just search a general box for the tool… if I understand correctly.

Here is what i think you mean:

Find a point that is the same colour as the gear (Ie brown for rod) and then find a point that matches the colour and is in an acceptable range (the points are always the same distance) ? I don't think it would work 100% for a general case. Lots of false positives turn up with colour searching for anything other than a rod/harpoon, and the pixelshift is much more reliable.

You've not seen progress, but I worked 2 hours on this last night, I'm getting very close. I can't get a working TrackFishSpot that is reliable, because the distance that it moves is usually very short. I'm thinking of making a function that just guesses based on the original spot and then verifies if there is a fishing spot in that area, then initiates waitWhileFishing, and if it guessed the wrong spot, it will return false. Works?

Coh3n

2010-08-18 16:16:27

From: 3Garrett3
So you want to just search a general box for the tool… if I understand correctly.

Here is what i think you mean:

Find a point that is the same colour as the gear (Ie brown for rod) and then find a point that matches the colour and is in an acceptable range (the points are always the same distance) ? I don't think it would work 100% for a general case. Lots of false positives turn up with colour searching for anything other than a rod/harpoon, and the pixelshift is much more reliable.

From what Nava found out, there's always a color on the equipment (when it's being used) that is the EXACT same as a color on the item in the inventory. All you have to do is get the color from the inventory, and search for it around the player. However, I was just thinking that it may not work now because the cage/harpoon/nets go completely under the water.

Here's my final conclusion:
  • Use a type! You have everything you need, and like you said, the pixel shifting is reliable and should work well with the inventory failsafe.

  • const
    SPOT_NET = 0;
    SPOT_HARPOON = 1;

    type
    TFishSpot = record
    Color : Integer;
    Tol : Integer;
    Hue, Sat: Extended;
    Count : Integer;
    WaitTime: Integer;
    end;

    function MSI_GetFishSpot(Which: Integer): TFishSpot;
    begin
    case Which of
    SPOT_NET:
    with Result do
    begin
    end;

    SPOT_HARPOON:
    with Result do
    begin
    end;
    end;
    end;

    procedure MSI_WaitWhileFishing;
    var
    OldInvCount, WaitTime, InvTimer, cts, CheckTime, i : Integer;
    MyChar : TBox;
    script: TScript;
    Tools : TPointArray;
    ToolAmount : TIntegerArray;
    Spot : TFishSpot;
    begin
    Flag;
    Wait(RandomRange(300, 450));
    if InvFull then
    Exit;
    cts := GetColorToleranceSpeed;
    ColorToleranceSpeed(2);
    MyChar := IntToBox(205, 121, 338, 219);
    script := MSI_Scripts[MSI_Players[CurrentPlayer].Scripts[CurrentScript]];

    Spot := MSI_GetFishSpot(FishSpot);

    SetToleranceSpeed2Modifiers(Spot.Hue, Spot.TSat); // Set the vars and such
    WaitTime := GetSystemTime + 90000;
    OldInvCount := InvCount;
    MarkTime(InvTimer);

    repeat

    MSI_FindRandoms;
    MSI_AntiBan(RandomRange(0, 3000), ANTI_BAN_CHANCE);

    if (TimeFromMark(InvTimer) > 30000) then // If no new fish in inv after 30 seconds, spot probably moved
    if (OldInvCount = InvCount) then break
    else begin
    OldInvCount := InvCount;
    MarkTime(InvTimer);
    end;

    MarkTime(CheckTime);
    repeat // Counts the occurance of a tool colour on the MS
    FindColorsSpiralTolerance(MMCX, MMCY, Tools, Spot.Colour, MyChar.X1, MyChar.Y1, MyChar.X2, MyChar.Y2, Spot.Tol);
    CombineIntArray(ToolAmount, [Length(Tools)]); // adds the length of the tool array (how many instances found)
    Wait(55);
    until(TimefromMark(CheckTime) > Spot.Wait)
    AvCount := AverageTIA(ToolAmount);
    if AvCount < Spot.Count then break; // If count of tool on MS is less, it should be done fishing

    Wait(RandomRange(200, 500));

    until(WaitTime > GetSystemTime)

    ColorToleranceSpeed(cts);
    end;

    That will at lease give us something we can test.

3Garrett3

2010-08-18 16:19:19

For finding the custom box, do you like my idea? A general box wont work with colour searching or pixel shift.

Coh3n

2010-08-18 16:22:55

From: 3Garrett3
For finding the custom box, do you like my idea? A general box wont work with colour searching or pixel shift.

I thought it worked really well with the box Shuttleu posted on the other thread?

3Garrett3

2010-08-18 16:31:42

From: Coh3n
I thought it worked really well with the box Shuttleu posted on the other thread?


That was for facing one direction (down I believe).

I made boxes for the other directions, they've been tested and work.

Coh3n

2010-08-18 16:39:19

From: 3Garrett3
That was for facing one direction (down I believe).

I made boxes for the other directions, they've been tested and work.

Oh perfect. Then yeah, a function which detects where the fishing spot is would be perfect. Even moving the camera so it's always facing the same direction relative to the fishing spot would work.

Blumblebee

2010-08-18 18:03:09

I still don't understand why we don't simply refind the fishing spot once the player stops moving and has started fishing? Then you can easily tell what hemisphere of the Mainscreen the spot is in.

Tniffoc

2010-08-18 19:36:14

From: Blumblebee
I still don't understand why we don't simply refind the fishing spot once the player stops moving and has started fishing? Then you can easily tell what hemisphere of the Mainscreen the spot is in.


This is not for following the fishing spot. My methods were for more accurately identifying the fishing spot initially.

Blumblebee

2010-08-18 19:37:45

sorry I didn't quote coh3n when I said that but I was referring to his post, not your functions.

Tniffoc

2010-08-18 19:45:07

Oh cool beans. How ya been Blumble?

3Garrett3

2010-08-18 20:32:10

From: Blumblebee
I still don't understand why we don't simply refind the fishing spot once the player stops moving and has started fishing? Then you can easily tell what hemisphere of the Mainscreen the spot is in.


Go to Karamja, tell me how you'd locate which out of the 10000 fishing spots it is? ;)

"I'm thinking of making a function that just guesses based on the original spot and then verifies if there is a fishing spot in that area, then initiates waitWhileFishing, and if it guessed the wrong spot, it will return false."

I just made this up when I was typing that post a while ago and there is no code written for it, but it seems like a solid idea.

@Cohen,

I was thinking the exact same thing. Being on a side view (fishing spot is to the north, turn cam east/west) might be the easiest thing. Only one box to worry about, and it should yield better results. It might be detectable though, I'm not sure, and it would have to return the compass to north again before walking, which isn't a big deal.

Nava2

2010-08-18 20:44:06

I did it from any angle, you just need to make sure you are not facing the same way as the fishing spots.

On Karajama, you can face North and you have no issues, most ifshing spots will have something similar.

Coh3n

2010-08-18 22:16:58

From: 3Garrett3
@Cohen,

I was thinking the exact same thing. Being on a side view (fishing spot is to the north, turn cam east/west) might be the easiest thing. Only one box to worry about, and it should yield better results. It might be detectable though, I'm not sure, and it would have to return the compass to north again before walking, which isn't a big deal.

Doubt it'd be detectable, I'd always put the camera to the same angle when I fish.

3Garrett3

2010-08-24 10:51:28

So there really hasn't been any progress on this for almost a week. I'm working on the waitwhilefishing right now. I guess I'll detect the direction of the fishing spot somehow, none of these ideas have been 100% solid from what I've seen. The problem is accurately deciding which direction the spot is before you get there.

3Garrett3

2010-08-24 19:09:46

I'm just going to throw this double post in here, to let everyone watching this thread know that I'm done with it, it compiles, ready to test, but it freezes Simba when I use it…

http://villavu.com/forum/showthread.php?t=58554

Sir R. M8gic1an

2010-08-31 22:27:39


const
MAX_FISH_WAIT = 30000;

{******************************************************************************}
{ Procedure MSI_WaitWhileFishing }
{ By: 3Garrett3 }
{ Date: 25 July 2010 }
{ Description: Waits while fishing }
{******************************************************************************}
procedure MSI_WaitWhileFishing;
var
OldInvCount, WaitTime, InvTimer, cts, i : Integer;
SearchBox : TBox;
script: TScript;
TColour, TTol, TCount, TWait : Integer;
THue, TSat : Extended;
TPixel, Fishing : Boolean;
begin

if InvFull then exit;

MSI_AddHeader('MSI_WaitWhileFishing');

Flag;
Wait(RandomRange(300, 450));

MSI_Debug('Detecting Side');
SearchBox := IntToBox(270, 148, 296, 180);
MakeCompass(MSI_DetectSide);

MSI_Debug('Getting Script Information');
script := MSI_Scripts[MSI_Players[CurrentPlayer].Scripts[CurrentScript]];
TPixel := False;

case (script.Objects[i]) of
FISHSPOT_NET:
begin
TPixel := True;
TCount := 150;
TWait := 3300;
end;

FISHSPOT_BAIT:
begin
TColour:= 727589;
TTol := 4;
THue := 0.17;
TSat := 0.65;
TCount := 50;
TWait := 4000;
end;

FISHSPOT_LURE:
begin
TColour:= 859433;
TTol := 3;
THue := 0.19;
TSat := 1.11;
TCount := 50;
TWait := 4000;
end;

FISHSPOT_CAGE:
begin
TPixel := True;
TCount := 150;
TWait := 3600;
end;

FISHSPOT_HARPOON:
begin
TPixel := True;
TCount := 160;
TWait := 3000;
end;
end;

MSI_Debug('Initializing vars');
WaitTime := GetSystemTime + 90000;
OldInvCount := InvCount;
MarkTime(InvTimer);

MSI_AddHeader('Starting Loop');
repeat
MSI_Debug('Randoms Check');
MSI_FindRandoms;
MSI_AntiBan(RandomRange(0, 3000), ANTI_BAN_CHANCE);

if InvFull then break;

// If no new fish in inv after 30 seconds, spot probably moved
MSI_Debug('InvTime check');
if (TimeFromMark(InvTimer) > MAX_FISH_WAIT) then
if (OldInvCount = InvCount) then
break
else begin
OldInvCount := InvCount;
MarkTime(InvTimer);
end;

MSI_Debug('TPixel check: ' + BoolToStr(TPixel));
if TPixel then
Fishing := MSI_FishPixels(TWait, TCount, SearchBox)
else
Fishing := MSI_FishGear(TColour, TTol, TCount, TWait, THue, TSat, SearchBox);

if not Fishing then break;

Wait(RandomRange(200, 500));

until(WaitTime > GetSystemTime)
MSI_CloseHeader('Ending Loop');

MSI_CloseHeader('WaitWhileFishing: Exiting');
end;


Can you give this a run please?

~RM

3Garrett3

2010-08-31 22:42:27

From: Sir R. Magician

const
MAX_FISH_WAIT = 30000;

{******************************************************************************}
{ Procedure MSI_WaitWhileFishing }
{ By: 3Garrett3 }
{ Date: 25 July 2010 }
{ Description: Waits while fishing }
{******************************************************************************}
procedure MSI_WaitWhileFishing;
var
OldInvCount, WaitTime, InvTimer, cts, i : Integer;
SearchBox : TBox;
script: TScript;
TColour, TTol, TCount, TWait : Integer;
THue, TSat : Extended;
TPixel, Fishing : Boolean;
begin

if InvFull then exit;

MSI_AddHeader('MSI_WaitWhileFishing');

Flag;
Wait(RandomRange(300, 450));

MSI_Debug('Detecting Side');
SearchBox := IntToBox(270, 148, 296, 180);
MakeCompass(MSI_DetectSide);

MSI_Debug('Getting Script Information');
script := MSI_Scripts[MSI_Players[CurrentPlayer].Scripts[CurrentScript]];
TPixel := False;

case (script.Objects[i]) of
FISHSPOT_NET:
begin
TPixel := True;
TCount := 150;
TWait := 3300;
end;

FISHSPOT_BAIT:
begin
TColour:= 727589;
TTol := 4;
THue := 0.17;
TSat := 0.65;
TCount := 50;
TWait := 4000;
end;

FISHSPOT_LURE:
begin
TColour:= 859433;
TTol := 3;
THue := 0.19;
TSat := 1.11;
TCount := 50;
TWait := 4000;
end;

FISHSPOT_CAGE:
begin
TPixel := True;
TCount := 150;
TWait := 3600;
end;

FISHSPOT_HARPOON:
begin
TPixel := True;
TCount := 160;
TWait := 3000;
end;
end;

MSI_Debug('Initializing vars');
WaitTime := GetSystemTime + 90000;
OldInvCount := InvCount;
MarkTime(InvTimer);

MSI_AddHeader('Starting Loop');
repeat
MSI_Debug('Randoms Check');
MSI_FindRandoms;
MSI_AntiBan(RandomRange(0, 3000), ANTI_BAN_CHANCE);

if InvFull then break;

// If no new fish in inv after 30 seconds, spot probably moved
MSI_Debug('InvTime check');
if (TimeFromMark(InvTimer) > MAX_FISH_WAIT) then
if (OldInvCount = InvCount) then
break
else begin
OldInvCount := InvCount;
MarkTime(InvTimer);
end;

MSI_Debug('TPixel check: ' + BoolToStr(TPixel));
if TPixel then
Fishing := MSI_FishPixels(TWait, TCount, SearchBox)
else
Fishing := MSI_FishGear(TColour, TTol, TCount, TWait, THue, TSat, SearchBox);

if not Fishing then break;

Wait(RandomRange(200, 500));

until(WaitTime > GetSystemTime)
MSI_CloseHeader('Ending Loop');

MSI_CloseHeader('WaitWhileFishing: Exiting');
end;


Can you give this a run please?

~RM


I would gladly if the rest of MSI compiled for me..

Sir R. M8gic1an

2010-08-31 22:48:32

Coh3n was running MSI just yesterday…

~RM

3Garrett3

2010-08-31 23:09:03

From: Sir R. Magician
Coh3n was running MSI just yesterday…

~RM


Oh sorry, if the rest of Fishing.simba compiled for me. I commented out all the crap that made it not compile, because all of the errors just pissed me off when I was that close to figuring out the crash bug..

3Garrett3

2010-09-01 13:42:36

Updated the first post. Lets get someone working on these soon, I'd love to see some public scripts coming out by the end of the week :D

Coh3n

2010-09-02 14:14:41

Glad you got it working. :) A few things, though.
  • In MSI_SetupPlayer I don't think we need to use the GameTab thing seeing as (IIRC) none of the fishing tools can be equipped.
  • POWER_NET should be POWER_FISH, just add all the default objects (all fishing spots) and items. The Items array should also look like this, because shrimp and anchovies both come from small net fishing.

  • Objects := [
    FISHSPOT_NET
    ];

    Items := [
    [FISH_SHRIMP, FISH_ANCHOVIE]
    ];
Awesome job though. :)

From: 3Garrett3
So here is the official list now that there is a working include committed:

  • MSI_FishingTools needs a rewrite, it has to determine the fishing gear based on the inventory, or a user defined variable. Whichever works.

The fishing tools is fine… it should determine the tools based on the spot being fished (i.e. the player objects).

3Garrett3

2010-09-02 20:15:28

The problem with the way of finding the fishing tool is that it finds the objects which are declared. So the user will 100% have to say "THIS IS WHAT I WANT" or it will just pick net (assuming that shrimp/anchovie is the first one in the array). So the user will have to say it no matter what, rather than just letting the script go for it. Is that okay? :\

Sir R. M8gic1an

2010-09-02 22:57:21

From: 3Garrett3
The problem with the way of finding the fishing tool is that it finds the objects which are declared. So the user will 100% have to say "THIS IS WHAT I WANT" or it will just pick net (assuming that shrimp/anchovie is the first one in the array). So the user will have to say it no matter what, rather than just letting the script go for it. Is that okay? :\


If you're powerfishing, you're not at any bank, so wouldn't it just use whatever fishing tools are in your inv..?

~RM

Coh3n

2010-09-03 02:34:44

From: 3Garrett3
The problem with the way of finding the fishing tool is that it finds the objects which are declared. So the user will 100% have to say "THIS IS WHAT I WANT" or it will just pick net (assuming that shrimp/anchovie is the first one in the array). So the user will have to say it no matter what, rather than just letting the script go for it. Is that okay? :\

Didn't really understand that at all.

If you have SCRIPT_POWER_FISH, it will, by default fish at all types of fishing spots and catch all types of fish. For that, the user would have to have all the fishing tools in their inventory. You should be able to check for which tools the user has, then determine the fishing spots depending on that (if they haven't specified in the player's objects array).

Coh3n

2010-09-10 01:46:34

Okay, so I've updated in the latest revision.
  • Updated MSI_SetupPlayer to only look in the inventory and it will find all the tools (no matter how many there are). Previously it only found up to two (yes, I know currently in RS the maximum amount of tools you need is 2).
  • Edited some debugging in MSI_WaitWhileFishing.
  • Made SCRIPT_POWER_FISHER work for all tools/fish spots.
  • Added SCRIPT_DB_FISHER.
I'll update the first post and thread title to match the other skills, and I'll write up a Supported Locations thread. :)

marpis

2010-09-11 02:15:02

Great to see progress! :) I'm starting to be very proud of this project!
And btw, there are some spots at AK, south of bank.

Coh3n

2010-09-11 02:17:05

From: marpis
Great to see progress! :) I'm starting to be very proud of this project!
And btw, there are some spots at AK, south of bank.

Awesome, I'll add that to the list. :)

3Garrett3

2010-09-11 12:26:57

I'm quite happy that someone picked up on this. I'm really sorry that I've been crazy busy lately. I haven't even been on facebook this last week-ish. Frosh week was insane and I've got 28 hours of classes a week, plus 15-20 hours of homework a week. I'll try to get on here as much as I can, I'll likely have a bit of time today to look through whats new when I go sit in the library for some peace and quiet.

Coh3n

2010-09-11 14:56:58

From: 3Garrett3
I'm quite happy that someone picked up on this. I'm really sorry that I've been crazy busy lately. I haven't even been on facebook this last week-ish. Frosh week was insane and I've got 28 hours of classes a week, plus 15-20 hours of homework a week. I'll try to get on here as much as I can, I'll likely have a bit of time today to look through whats new when I go sit in the library for some peace and quiet.

Don't worry, real life comes first. :)

Coh3n

2011-01-12 02:09:24

Added a couple that could be done pretty easily.

3Garrett3

2011-01-12 08:18:11

Does anyone have members accounts for these?

Becks

2011-01-12 11:45:49

From: 3Garrett3
Does anyone have members accounts for these?



I do I can lend for guild fisher.. Everything but sharks but will be getting 76 fishing in the next couple days.
If thats what you are asking..?

Coh3n

2011-03-11 15:13:55

Catherby fisher is up and running thanks to IPwnz. :)

From: Becks
I do I can lend for guild fisher.. Everything but sharks but will be getting 76 fishing in the next couple days.
If thats what you are asking..?

Sorry for the late reply, but if you do have an account that has access to the fishing guild that would be awesome! Let use know and we'll be in contact when we need it.

Coh3n

2011-05-16 22:23:09

Added Shilo Village and Lumbridge Crayfish to the list.