SRL Archive - OSR Help

Advanced combat detection


EngageTheRage

2013-06-03 06:12:24

For OldSchool

ok, do in my fighter script i check whether the player is on combat by creating a box around where the player dot is on the MM (and checking for hp Bar in that box), i then check the closest NPC to see if they are in combat also (by checking for hp bar), this means that you exit combat as soon as you kill the monster as opposed to waiting for your hp bar to disappear.

i also check if a monster is in combat before attacking by check ing if they have a hp bar in the area just above where i have found the matching colors (this works well).

this works great if you are alone, however as soon as someone else comes into the mix it slows down drastically and starts to look bot like.


so what im after?

has anyone any ideas on how to improve the combat detection so that it is still accurate when there are other players around?

Rich

2013-06-03 06:20:27

What about the combat tab, where it tells you if you're in combat or not? That's assuming this is for EOC though.

EngageTheRage

2013-06-03 06:24:10

From: Rich
What about the combat tab, where it tells you if you're in combat or not? That's assuming this is for EOC though.


sorry completely forgot to say which … this is for oldschool

rj

2013-06-03 08:25:17

You could make an atpa of your player using armour color and hair color and check for pixel shift inside that box to check if the player is in combat, then just check for the monsters hp bar in your minsters atpa

EngageTheRage

2013-06-03 08:46:56

Yeah i was considering that … The problem is I don't want the user to have to select any colours themselves, I want everything to be selectable from the form.

Sk1nyNerd

2013-06-03 17:46:44

From: EngageTheRage
Yeah i was considering that … The problem is I don't want the user to have to select any colours themselves, I want everything to be selectable from the form.


u shouldn't have to use armour and hair color? that will help sort it but if ur making a box and ur characters always on top there's no need for that. I use pixel shift for combat detection in my range script and a couple private o es, works very well. u might have troubles destincting walking/running from combat so ull have to think of something to seperate that such as a wait until notmoving

EngageTheRage

2013-06-03 18:06:37

surely searching for pixel shift is just the same as searching for a hp bar, because i will have to use the same function to get the box around the character … the only difference being when you are actually directly on top of the other character …

rj

2013-06-03 18:17:23

From: ibot_dung11
u shouldn't have to use armour and hair color? that will help sort it but if ur making a box and ur characters always on top there's no need for that. I use pixel shift for combat detection in my range script and a couple private o es, works very well. u might have troubles destincting walking/running from combat so ull have to think of something to seperate that such as a wait until notmoving


Using a static box for pixel shift can have false posit rs if its not exactly correct, if the compass rotates then then other things can I Terrence with it so it has to be in a exact spot were your chatactor is always at

Sk1nyNerd

2013-06-03 18:17:30

From: EngageTheRage
surely searching for pixel shift is just the same as searching for a hp bar, because i will have to use the same function to get the box around the character … the only difference being when you are actually directly on top of the other character …



I believe it searches the mainscreen center so u don't have to make a box. search it, I think Flight had a guide on it. don't have my laptop sorry. try it out, if anything u learn how to use pixel shifts :P

Haxz

2013-06-03 18:30:12

If you wanna be user-friendly, then maybe you could make them choose which armor they're wearing, and the list of armours will have the armour color already set in the script. It's kinda hard to make scripts to be all user-friendly, but IMO everyone should learn how to use ACA, I believe a 5 year old can understand and know how to use ACA, not sure if its the same with leechers.

I had these in my figher script and I think its already too much for a common leecher to handle.

HairCol = 7892049;
HairTol = 7;
HairHue = 0.07;
HairSat = 0.05;

MonCTS = 2;
MonCol = [3294795];
MonTol = [8];
MonHue = [0.09];
MonSat = [0.14];
MonWidth = 30;
MonLength = 60;
MonName = 'iant';

LootCol = 11250869;
LootTol = 17;
LootHue = 0.10;
LootSat = 0.13;

UseColorLoot = True;

Food := 'Trout';

LootList := ['cut', 'lack', 'rrow', 'oins', 'ones', 'Law', 'Nature', 'Death', 'Chaos R']

EngageTheRage

2013-06-03 18:51:37

That sounds good actually :)

I just want my script to only require the user to fill out a form with mainly drop down lists :)

Flight

2013-06-03 21:13:23

Yes I made a target-finding function with these specifics, finding NPCs that aren't already in combat, determining when our current target is dead without waiting for the HP bar to fade, and so on…

Check out this page for some ideas:
http://villavu.com/forum/showthread.php?t=73316

Thanatos

2013-06-03 21:32:05

From: Flight
Yes I made a target-finding function with these specifics, finding NPCs that aren't already in combat, determining when our current target is dead without waiting for the HP bar to fade, and so on…

Check out this page for some ideas:
http://villavu.com/forum/showthread.php?t=73316


I believe that page is members+

Flight

2013-06-03 21:41:32

From: Thanatos
I believe that page is members+


Ah yes indeed it is… I'll post it here:



First off, I worked really hard on this believe it or not, so if you use it in a script please do give credits… With that being said, thanks again Markus for helping me with that 'Range check error'. :duh:

What this function does is finds available (not in combat) NPCs on your screen (based on your input), and returns a TPA with each point containing the middle of each of those NPCs, sorted from the center of the screen.

Some examples of beta tests on Giant Rats behind Lumbridge castle: (Using CTS3, for what it's worth)



I explained out exactly how this function works, so maybe it would be good for some to learn from. The parameters are obvious, and if you're reading this post then you've already proven you have enough knowledge to understand what each parameter means, if not just ask questions here. For the record, I already know that it's a bit messy. :p


Function FindFreeTargets(Color, Tol, CTS, MinCount, Width, Height: Integer): TPointArray;
var
NPCBox,HPZone: TBox;
TopPoint,MiddleHPZone,
MiddleNPCBox: TPoint;
TPA,GreenPointsA,RedPointsA,
GreenPointsB,RedPointsB,
RTPA: TPointArray;
L,i,CTS_Old,R: Integer;
ATPA: T2DPointArray;
begin
CTS_Old := GetColorToleranceSpeed;
{Find NPC colors}
ColorToleranceSpeed(CTS);
FindColorsSpiralTolerance(MSCX, MSCY, TPA, Color, MSX1, MSY1, MSX2, MSY2, Tol);

if (Length(TPA) < 1) then
begin
ColorToleranceSpeed(CTS_Old);
Exit;
end;
{Split TPA's into boxes defined by 'Width' & 'Height'}
ATPA := SplitTPAEx(TPA, Width, Height); //In this instance, I prefer SplitTPA
L := High(ATPA);
SetArrayLength(ATPA, L+1);
{Loop through each box}
for i := 0 to L do
begin
{If the # of color points found inside the box is >= to 'MinCount'}
if (Length(ATPA[i]) >= MinCount) then
NPCBox := GetTPABounds(ATPA[i]);
{Inside each valid NPC box}
with NPCBox do
begin
{Get middle top point of the box}
TopPoint := Point(((NPCBox.X1+NPCBox.X2)/2), NPCBox.Y1);

if (TopPoint.X < MSX1) then
TopPoint.X := MSX1;
if (TopPoint.Y < MSY1) then
TopPoint.Y := MSY1;
{Using 'TopPoint', specify a static region in which a health bar would be present}
HPZone := IntToBox(TopPoint.X-30, TopPoint.Y-40, TopPoint.X+30, TopPoint.Y);

if (HPZone.X1 < MSX1) then
HPZone.X1 := MSX1;
if (HPZone.X2 > MSX2) then
HPZone.X2 := MSX2;
if (HPZone.Y1 < MSY1) then
HPZone.Y1 := MSY1;
if (HPZone.Y2 > MSY2) then
HPZone.Y1 := MSY2;
{These two aren't really needed}
MiddleHPZone := Point(((HPZone.x1+HPZone.x2)/2), ((HPZone.y1+HPZone.y2)/2));
MiddleNPCBox := Point(((NPCBox.x1+NPCBox.x2)/2), ((NPCBox.y1+NPCBox.y2)/2));

{Search within both the 'NPCBox' and the HPZone for both red & green colors}
ColorToleranceSpeed(3);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, GreenPointsA, 49242, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, RedPointsA, 524459, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, GreenPointsB, 49242, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, RedPointsB, 524459, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
ColorToleranceSpeed(CTS_Old);

{If no red or green is found within the NPCBox and HPZone}
if ((Length(GreenPointsA) = 0) and (Length(RedPointsA) = 0)
and (Length(GreenPointsB) = 0) and (Length(RedPointsB) = 0)) then
begin
{Add the center of the NPCBox to 'RTPA'}
SetArrayLength(RTPA, (Length(RTPA)+1));
RTPA[R] := MiddleNPCBox;
Inc(R);
end;

end;

end;

{Sort the 'RTPA' from the center of the screen}
SortTPAFrom(RTPA, Point(MSCX, MSCY));
{RTPA now holds the center point for each NPCBox of 'avaiable' targets}
Result := RTPA;

end;

Here's a quick script I threw together to fight level 10 Minotaurs in Stronghold of Security:

program MinotaurMasher;

{$DEFINE SRL5}
{$DEFINE SMART}

{$i SRL/srl.simba}
{$i SRL/SRL/misc/paintsmart.simba}


Const
WeaponSpeed = 'Fast';
Training = 'Strength';
HPLevel = 80;

Var
KillCount,Exp,HPExp,
WeaponTimer: Integer;


Procedure DeclarePlayers;
begin
HowManyPlayers := 1;
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0;
with Players[0] do
begin
Name := '';
Pass := '';
Level[SKILL_HITPOINTS] := HPLevel;
BoxRewards := ['XP','xp','lamp'];
LampSkill := 'Mining';
Active := True;
end;
end;

Procedure LoadVars;
begin

case Lowercase(WeaponSpeed) of
'fast': WeaponTimer := 800;
'normal': WeaponTimer := 1500;
'slow': WeaponTimer := 3000;
end;

end;

Procedure OnScreen;
var
XPH,XPH2,TTB,
KPH: Integer;
begin

XPH := Round((Exp * 3600) / (GetTimeRunning / 1000));
XPH2 := Round((HPExp * 3600) / (GetTimeRunning / 1000));
KPH := Round((KillCount * 3600) / (GetTimeRunning / 1000));
//TTB := (((w) + (y) + BreakRounds)-GetTimeRunning);

SMART_DrawTextMulti(True, True, ['Minotaur Masher 1.0 by Flight','',
''+MsToTime(GetTimeRunning, Time_Abbrev),'',
''+Capitalize(Training)+' XP: '+IntToStr(Exp)+' ('+IntToStr(XPH)+' / hour)','',
'Hitpoints XP: '+IntToStr(HPExp)+' ('+IntToStr(XPH2)+' / hour)','',
'Kills: '+IntToStr(KillCount)+' ('+IntToStr(KPH)+' / hour)'],
Point(10, 200), SmallCharsNS, 16777215);

//SMART_DrawTextMulti(False, True, ['Time till break: '+MsToTime(TTB,Time_Bare)], Point(570, 445), SmallCharsNS, 65280);
end;

Procedure HumanMMouse(eX, eY, ranX, ranY: Integer);
var
randSpeed: extended;
X,Y,X2,Y2,A,Dist,MP: integer;
begin
A := MouseSpeed;
GetMousePos(X, Y);
Dist := Distance(X, Y, eX, eY);
MP := Round(Dist/150);
if MP < 0 then
MP := 1;

randSpeed := (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0;
X2 := RandomRange(eX-(A*MP), eX+(A*MP));
Y2 := RandomRange(eY-(A*MP), eY+(A*MP));
WindMouse(X, Y, X2, Y2, 11, 8, 10.0 / randSpeed, 12.0 / randSpeed, 10.0 * randSpeed, 10.0 * randSpeed);
GetMousePos(X, Y);
MMouse(eX, eY, ranX, ranY);
MouseSpeed := A;
end;

Procedure HumanRandomMouse;
var
randSpeed: extended;
x, y, firstSpeed: integer;
begin
case(Random(10)) of
2..8:
begin
firstSpeed := mouseSpeed;

mouseSpeed := RandomRange(5,10);
randSpeed := (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0;
GetMousePos(x, y);
WindMouse(x, y, RandomRange(x - 75, x + 75), RandomRange(y - 75, y + 75),
30, 55, 10.0 / randSpeed, 12.0 / randSpeed, 10.0 * randSpeed, 10.0 * randSpeed);

mouseSpeed := firstSpeed;
end;
end;
end;

Function IsMoving_F: Boolean;
begin
Result := PixelShift(IntToBox(MMCX-30, MMCY-30, MMCX+30, MMCY+30), 200) > 200;
end;

Function Attacking: Boolean;
var
PBox: TBox;
begin
PBox := IntToBox(245, 135, 280, 185);
Result := (AveragePixelShift(PBox, 250, 500) > 500);
end;

Procedure GetShiftCount;
var
PBox: TBox;
begin
PBox := IntToBox(245, 135, 280, 185);
Writeln(IntToStr(AveragePixelShift(PBox, 250, 500)));
end;

Function DidAntiban: Boolean;
var
i: Integer;
begin
Result := False;
if not LoggedIn then Exit;

i := Random(450);
case i of
1..45:
begin
HumanRandomMouse;
Result := True;
end;
46:
begin
HoverSkill('Strength', False);
Result := True;
end;
47:
begin
HoverSkill('Attack', False);
Result := True;
end;
48:
begin
HoverSkill('Hitpoints', False);
Result := True;
end;
49..450: Exit;
end;

end;

Function Eat: Boolean;
var
i: Integer;
begin
Result := False;

if Not LoggedIn then Exit;
if InvEmpty then Exit;
if (HPPercent >= 60) then Exit;

for i := 0 to 28 do
begin
FindNormalRandoms;

if ExistsItem(i) then
begin
InvMouse(i, mouse_move);

if WaitUpText('Eat', 300) then
begin
ClickMouse2(True);
Wait(RandomRange(875, 990));
if (HPPercent >= 90) then
Exit;
end;

if (i = 28) then
Exit;

end;

end;
end;

Function FindFreeTargets(Color, Tol, CTS, MinCount, Width, Height: Integer): TPointArray;
var
NPCBox,HPZone: TBox;
TopPoint,MiddleHPZone,
MiddleNPCBox: TPoint;
TPA,GreenPointsA,RedPointsA,
GreenPointsB,RedPointsB,
RTPA: TPointArray;
L,i,CTS_Old,R: Integer;
ATPA: T2DPointArray;
begin
CTS_Old := GetColorToleranceSpeed;
{Find NPC colors}
ColorToleranceSpeed(CTS);
FindColorsSpiralTolerance(MSCX, MSCY, TPA, Color, MSX1, MSY1, MSX2, MSY2, Tol);

if (Length(TPA) < 1) then
begin
ColorToleranceSpeed(CTS_Old);
Exit;
end;
{Split TPA's into boxes defined by 'Width' & 'Height'}
ATPA := SplitTPAEx(TPA, Width, Height);
L := High(ATPA);
SetArrayLength(ATPA, L+1);
{Loop through each box}
for i := 0 to L do
begin
{If the # of color points found inside the box is >= to 'MinCount'}
if (Length(ATPA[i]) >= MinCount) then
NPCBox := GetTPABounds(ATPA[i]);
{Inside each valid NPC box}
with NPCBox do
begin
{Get middle top point of the box}
TopPoint := Point(((NPCBox.X1+NPCBox.X2)/2), NPCBox.Y1);

if (TopPoint.X < MSX1) then
TopPoint.X := MSX1;
if (TopPoint.Y < MSY1) then
TopPoint.Y := MSY1;
{Using 'TopPoint', specify a static region in which a health bar would be present}
HPZone := IntToBox(TopPoint.X-30, TopPoint.Y-40, TopPoint.X+30, TopPoint.Y);

if (HPZone.X1 < MSX1) then
HPZone.X1 := MSX1;
if (HPZone.X2 > MSX2) then
HPZone.X2 := MSX2;
if (HPZone.Y1 < MSY1) then
HPZone.Y1 := MSY1;
if (HPZone.Y2 > MSY2) then
HPZone.Y1 := MSY2;
{These two aren't really needed}
MiddleHPZone := Point(((HPZone.x1+HPZone.x2)/2), ((HPZone.y1+HPZone.y2)/2));
MiddleNPCBox := Point(((NPCBox.x1+NPCBox.x2)/2), ((NPCBox.y1+NPCBox.y2)/2));

{Search within both the 'NPCBox' and the HPZone for both red & green colors}
ColorToleranceSpeed(3);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, GreenPointsA, 49242, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, RedPointsA, 524459, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, GreenPointsB, 49242, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, RedPointsB, 524459, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
ColorToleranceSpeed(CTS_Old);

{If no red or green is found within the NPCBox and HPZone}
if ((Length(GreenPointsA) = 0) and (Length(RedPointsA) = 0)
and (Length(GreenPointsB) = 0) and (Length(RedPointsB) = 0)) then
begin
{Add the center of the NPCBox to 'RTPA'}
SetArrayLength(RTPA, (Length(RTPA)+1));
RTPA[R] := MiddleNPCBox;
Inc(R);
end;

end;

end;

{Sort the 'RTPA' from the center of the screen}
SortTPAFrom(RTPA, Point(MSCX, MSCY));
{RTPA now holds the center point for each NPCBox of 'avaiable' targets}
Result := RTPA;

end;

procedure AttackMinotaur;
var
T: Integer;
GoOn: Boolean;
TPA: TPointArray;
label
Search;
begin
if not LoggedIn then Exit;
Eat;

Search:
GoOn := False;
MouseSpeed := RandomRange(14, 22);
TPA := FindFreeTargets(10594473, 3, 3, 10, 20, 20);

if (Length(TPA) > 0) then
begin
HumanMMouse(TPA[0].X, TPA[0].Y, 5, 5);
if WaitUpTextMulti(['ck M','inot', 'taur'], 300) then
begin
ClickMouse2(True);
if not DidRedClick then
goto Search;
end else
goto Search;

FFlag(0);
While IsMoving_F do
Wait(1);

MarkTime(T);
repeat
if not LoggedIn then Exit;
FindNormalRandoms;

if (TimeFromMark(T) > 3000) then
Exit;

if Attacking then
break;

if FindBlackChatMessage('omeone else is fighting') then
break;

until(false)

if FindBlackChatMessage('omeone else is fighting') then
goto Search;

GoOn := True;
MarkTime(T);
repeat
if not LoggedIn then Exit;
FindNormalRandoms;
Eat;

//if (Attacking or DidAntiBan) then
if Attacking then
MarkTime(T);

if (TimeFromMark(T) > WeaponTimer) then
break;
until(false)

if GoOn then
begin
GoOn := False;
Inc(KillCount);
IncEx(Exp, 40);
IncEx(HPExp, 14);
//Inc(KillCount_C);
OnScreen;
end;

end;
end;

begin
Smart_Server := 86;
Smart_Members := True;
Smart_Signed := True;
Smart_SuperDetail := False;

setupSRL();
DeclarePlayers;

LoadVars;
Smart_ClearCanvas;
Wait(RandomRange(500, 675));
OnScreen;

Repeat

//GetShiftCount;
if not LoggedIn then
begin
LoginPlayer;
ClickNorth(SRL_ANGLE_HIGH);
end;

FindNormalRandoms;
AttackMinotaur;

Until(False)

end.


Sk1nyNerd

2013-06-03 22:27:00

From: Flight
Ah yes indeed it is… I'll post it here:



First off, I worked really hard on this believe it or not, so if you use it in a script please do give credits… With that being said, thanks again Markus for helping me with that 'Range check error'. :duh:

What this function does is finds available (not in combat) NPCs on your screen (based on your input), and returns a TPA with each point containing the middle of each of those NPCs, sorted from the center of the screen.

Some examples of beta tests on Giant Rats behind Lumbridge castle: (Using CTS3, for what it's worth)



I explained out exactly how this function works, so maybe it would be good for some to learn from. The parameters are obvious, and if you're reading this post then you've already proven you have enough knowledge to understand what each parameter means, if not just ask questions here. For the record, I already know that it's a bit messy. :p


Function FindFreeTargets(Color, Tol, CTS, MinCount, Width, Height: Integer): TPointArray;
var
NPCBox,HPZone: TBox;
TopPoint,MiddleHPZone,
MiddleNPCBox: TPoint;
TPA,GreenPointsA,RedPointsA,
GreenPointsB,RedPointsB,
RTPA: TPointArray;
L,i,CTS_Old,R: Integer;
ATPA: T2DPointArray;
begin
CTS_Old := GetColorToleranceSpeed;
{Find NPC colors}
ColorToleranceSpeed(CTS);
FindColorsSpiralTolerance(MSCX, MSCY, TPA, Color, MSX1, MSY1, MSX2, MSY2, Tol);

if (Length(TPA) < 1) then
begin
ColorToleranceSpeed(CTS_Old);
Exit;
end;
{Split TPA's into boxes defined by 'Width' & 'Height'}
ATPA := SplitTPAEx(TPA, Width, Height); //In this instance, I prefer SplitTPA
L := High(ATPA);
SetArrayLength(ATPA, L+1);
{Loop through each box}
for i := 0 to L do
begin
{If the # of color points found inside the box is >= to 'MinCount'}
if (Length(ATPA[i]) >= MinCount) then
NPCBox := GetTPABounds(ATPA[i]);
{Inside each valid NPC box}
with NPCBox do
begin
{Get middle top point of the box}
TopPoint := Point(((NPCBox.X1+NPCBox.X2)/2), NPCBox.Y1);

if (TopPoint.X < MSX1) then
TopPoint.X := MSX1;
if (TopPoint.Y < MSY1) then
TopPoint.Y := MSY1;
{Using 'TopPoint', specify a static region in which a health bar would be present}
HPZone := IntToBox(TopPoint.X-30, TopPoint.Y-40, TopPoint.X+30, TopPoint.Y);

if (HPZone.X1 < MSX1) then
HPZone.X1 := MSX1;
if (HPZone.X2 > MSX2) then
HPZone.X2 := MSX2;
if (HPZone.Y1 < MSY1) then
HPZone.Y1 := MSY1;
if (HPZone.Y2 > MSY2) then
HPZone.Y1 := MSY2;
{These two aren't really needed}
MiddleHPZone := Point(((HPZone.x1+HPZone.x2)/2), ((HPZone.y1+HPZone.y2)/2));
MiddleNPCBox := Point(((NPCBox.x1+NPCBox.x2)/2), ((NPCBox.y1+NPCBox.y2)/2));

{Search within both the 'NPCBox' and the HPZone for both red & green colors}
ColorToleranceSpeed(3);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, GreenPointsA, 49242, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, RedPointsA, 524459, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, GreenPointsB, 49242, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, RedPointsB, 524459, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
ColorToleranceSpeed(CTS_Old);

{If no red or green is found within the NPCBox and HPZone}
if ((Length(GreenPointsA) = 0) and (Length(RedPointsA) = 0)
and (Length(GreenPointsB) = 0) and (Length(RedPointsB) = 0)) then
begin
{Add the center of the NPCBox to 'RTPA'}
SetArrayLength(RTPA, (Length(RTPA)+1));
RTPA[R] := MiddleNPCBox;
Inc(R);
end;

end;

end;

{Sort the 'RTPA' from the center of the screen}
SortTPAFrom(RTPA, Point(MSCX, MSCY));
{RTPA now holds the center point for each NPCBox of 'avaiable' targets}
Result := RTPA;

end;

Here's a quick script I threw together to fight level 10 Minotaurs in Stronghold of Security:

program MinotaurMasher;

{$DEFINE SRL5}
{$DEFINE SMART}

{$i SRL/srl.simba}
{$i SRL/SRL/misc/paintsmart.simba}


Const
WeaponSpeed = 'Fast';
Training = 'Strength';
HPLevel = 80;

Var
KillCount,Exp,HPExp,
WeaponTimer: Integer;


Procedure DeclarePlayers;
begin
HowManyPlayers := 1;
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0;
with Players[0] do
begin
Name := '';
Pass := '';
Level[SKILL_HITPOINTS] := HPLevel;
BoxRewards := ['XP','xp','lamp'];
LampSkill := 'Mining';
Active := True;
end;
end;

Procedure LoadVars;
begin

case Lowercase(WeaponSpeed) of
'fast': WeaponTimer := 800;
'normal': WeaponTimer := 1500;
'slow': WeaponTimer := 3000;
end;

end;

Procedure OnScreen;
var
XPH,XPH2,TTB,
KPH: Integer;
begin

XPH := Round((Exp * 3600) / (GetTimeRunning / 1000));
XPH2 := Round((HPExp * 3600) / (GetTimeRunning / 1000));
KPH := Round((KillCount * 3600) / (GetTimeRunning / 1000));
//TTB := (((w) + (y) + BreakRounds)-GetTimeRunning);

SMART_DrawTextMulti(True, True, ['Minotaur Masher 1.0 by Flight','',
''+MsToTime(GetTimeRunning, Time_Abbrev),'',
''+Capitalize(Training)+' XP: '+IntToStr(Exp)+' ('+IntToStr(XPH)+' / hour)','',
'Hitpoints XP: '+IntToStr(HPExp)+' ('+IntToStr(XPH2)+' / hour)','',
'Kills: '+IntToStr(KillCount)+' ('+IntToStr(KPH)+' / hour)'],
Point(10, 200), SmallCharsNS, 16777215);

//SMART_DrawTextMulti(False, True, ['Time till break: '+MsToTime(TTB,Time_Bare)], Point(570, 445), SmallCharsNS, 65280);
end;

Procedure HumanMMouse(eX, eY, ranX, ranY: Integer);
var
randSpeed: extended;
X,Y,X2,Y2,A,Dist,MP: integer;
begin
A := MouseSpeed;
GetMousePos(X, Y);
Dist := Distance(X, Y, eX, eY);
MP := Round(Dist/150);
if MP < 0 then
MP := 1;

randSpeed := (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0;
X2 := RandomRange(eX-(A*MP), eX+(A*MP));
Y2 := RandomRange(eY-(A*MP), eY+(A*MP));
WindMouse(X, Y, X2, Y2, 11, 8, 10.0 / randSpeed, 12.0 / randSpeed, 10.0 * randSpeed, 10.0 * randSpeed);
GetMousePos(X, Y);
MMouse(eX, eY, ranX, ranY);
MouseSpeed := A;
end;

Procedure HumanRandomMouse;
var
randSpeed: extended;
x, y, firstSpeed: integer;
begin
case(Random(10)) of
2..8:
begin
firstSpeed := mouseSpeed;

mouseSpeed := RandomRange(5,10);
randSpeed := (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0;
GetMousePos(x, y);
WindMouse(x, y, RandomRange(x - 75, x + 75), RandomRange(y - 75, y + 75),
30, 55, 10.0 / randSpeed, 12.0 / randSpeed, 10.0 * randSpeed, 10.0 * randSpeed);

mouseSpeed := firstSpeed;
end;
end;
end;

Function IsMoving_F: Boolean;
begin
Result := PixelShift(IntToBox(MMCX-30, MMCY-30, MMCX+30, MMCY+30), 200) > 200;
end;

Function Attacking: Boolean;
var
PBox: TBox;
begin
PBox := IntToBox(245, 135, 280, 185);
Result := (AveragePixelShift(PBox, 250, 500) > 500);
end;

Procedure GetShiftCount;
var
PBox: TBox;
begin
PBox := IntToBox(245, 135, 280, 185);
Writeln(IntToStr(AveragePixelShift(PBox, 250, 500)));
end;

Function DidAntiban: Boolean;
var
i: Integer;
begin
Result := False;
if not LoggedIn then Exit;

i := Random(450);
case i of
1..45:
begin
HumanRandomMouse;
Result := True;
end;
46:
begin
HoverSkill('Strength', False);
Result := True;
end;
47:
begin
HoverSkill('Attack', False);
Result := True;
end;
48:
begin
HoverSkill('Hitpoints', False);
Result := True;
end;
49..450: Exit;
end;

end;

Function Eat: Boolean;
var
i: Integer;
begin
Result := False;

if Not LoggedIn then Exit;
if InvEmpty then Exit;
if (HPPercent >= 60) then Exit;

for i := 0 to 28 do
begin
FindNormalRandoms;

if ExistsItem(i) then
begin
InvMouse(i, mouse_move);

if WaitUpText('Eat', 300) then
begin
ClickMouse2(True);
Wait(RandomRange(875, 990));
if (HPPercent >= 90) then
Exit;
end;

if (i = 28) then
Exit;

end;

end;
end;

Function FindFreeTargets(Color, Tol, CTS, MinCount, Width, Height: Integer): TPointArray;
var
NPCBox,HPZone: TBox;
TopPoint,MiddleHPZone,
MiddleNPCBox: TPoint;
TPA,GreenPointsA,RedPointsA,
GreenPointsB,RedPointsB,
RTPA: TPointArray;
L,i,CTS_Old,R: Integer;
ATPA: T2DPointArray;
begin
CTS_Old := GetColorToleranceSpeed;
{Find NPC colors}
ColorToleranceSpeed(CTS);
FindColorsSpiralTolerance(MSCX, MSCY, TPA, Color, MSX1, MSY1, MSX2, MSY2, Tol);

if (Length(TPA) < 1) then
begin
ColorToleranceSpeed(CTS_Old);
Exit;
end;
{Split TPA's into boxes defined by 'Width' & 'Height'}
ATPA := SplitTPAEx(TPA, Width, Height);
L := High(ATPA);
SetArrayLength(ATPA, L+1);
{Loop through each box}
for i := 0 to L do
begin
{If the # of color points found inside the box is >= to 'MinCount'}
if (Length(ATPA[i]) >= MinCount) then
NPCBox := GetTPABounds(ATPA[i]);
{Inside each valid NPC box}
with NPCBox do
begin
{Get middle top point of the box}
TopPoint := Point(((NPCBox.X1+NPCBox.X2)/2), NPCBox.Y1);

if (TopPoint.X < MSX1) then
TopPoint.X := MSX1;
if (TopPoint.Y < MSY1) then
TopPoint.Y := MSY1;
{Using 'TopPoint', specify a static region in which a health bar would be present}
HPZone := IntToBox(TopPoint.X-30, TopPoint.Y-40, TopPoint.X+30, TopPoint.Y);

if (HPZone.X1 < MSX1) then
HPZone.X1 := MSX1;
if (HPZone.X2 > MSX2) then
HPZone.X2 := MSX2;
if (HPZone.Y1 < MSY1) then
HPZone.Y1 := MSY1;
if (HPZone.Y2 > MSY2) then
HPZone.Y1 := MSY2;
{These two aren't really needed}
MiddleHPZone := Point(((HPZone.x1+HPZone.x2)/2), ((HPZone.y1+HPZone.y2)/2));
MiddleNPCBox := Point(((NPCBox.x1+NPCBox.x2)/2), ((NPCBox.y1+NPCBox.y2)/2));

{Search within both the 'NPCBox' and the HPZone for both red & green colors}
ColorToleranceSpeed(3);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, GreenPointsA, 49242, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, RedPointsA, 524459, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, GreenPointsB, 49242, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, RedPointsB, 524459, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
ColorToleranceSpeed(CTS_Old);

{If no red or green is found within the NPCBox and HPZone}
if ((Length(GreenPointsA) = 0) and (Length(RedPointsA) = 0)
and (Length(GreenPointsB) = 0) and (Length(RedPointsB) = 0)) then
begin
{Add the center of the NPCBox to 'RTPA'}
SetArrayLength(RTPA, (Length(RTPA)+1));
RTPA[R] := MiddleNPCBox;
Inc(R);
end;

end;

end;

{Sort the 'RTPA' from the center of the screen}
SortTPAFrom(RTPA, Point(MSCX, MSCY));
{RTPA now holds the center point for each NPCBox of 'avaiable' targets}
Result := RTPA;

end;

procedure AttackMinotaur;
var
T: Integer;
GoOn: Boolean;
TPA: TPointArray;
label
Search;
begin
if not LoggedIn then Exit;
Eat;

Search:
GoOn := False;
MouseSpeed := RandomRange(14, 22);
TPA := FindFreeTargets(10594473, 3, 3, 10, 20, 20);

if (Length(TPA) > 0) then
begin
HumanMMouse(TPA[0].X, TPA[0].Y, 5, 5);
if WaitUpTextMulti(['ck M','inot', 'taur'], 300) then
begin
ClickMouse2(True);
if not DidRedClick then
goto Search;
end else
goto Search;

FFlag(0);
While IsMoving_F do
Wait(1);

MarkTime(T);
repeat
if not LoggedIn then Exit;
FindNormalRandoms;

if (TimeFromMark(T) > 3000) then
Exit;

if Attacking then
break;

if FindBlackChatMessage('omeone else is fighting') then
break;

until(false)

if FindBlackChatMessage('omeone else is fighting') then
goto Search;

GoOn := True;
MarkTime(T);
repeat
if not LoggedIn then Exit;
FindNormalRandoms;
Eat;

//if (Attacking or DidAntiBan) then
if Attacking then
MarkTime(T);

if (TimeFromMark(T) > WeaponTimer) then
break;
until(false)

if GoOn then
begin
GoOn := False;
Inc(KillCount);
IncEx(Exp, 40);
IncEx(HPExp, 14);
//Inc(KillCount_C);
OnScreen;
end;

end;
end;

begin
Smart_Server := 86;
Smart_Members := True;
Smart_Signed := True;
Smart_SuperDetail := False;

setupSRL();
DeclarePlayers;

LoadVars;
Smart_ClearCanvas;
Wait(RandomRange(500, 675));
OnScreen;

Repeat

//GetShiftCount;
if not LoggedIn then
begin
LoginPlayer;
ClickNorth(SRL_ANGLE_HIGH);
end;

FindNormalRandoms;
AttackMinotaur;

Until(False)

end.



:wow:
can't wait to get my laptop back and see try this! comments were great, not messy at all

EngageTheRage

2013-06-03 22:46:52

From: Flight
Ah yes indeed it is… I'll post it here:



First off, I worked really hard on this believe it or not, so if you use it in a script please do give credits… With that being said, thanks again Markus for helping me with that 'Range check error'. :duh:

What this function does is finds available (not in combat) NPCs on your screen (based on your input), and returns a TPA with each point containing the middle of each of those NPCs, sorted from the center of the screen.



I explained out exactly how this function works, so maybe it would be good for some to learn from. The parameters are obvious, and if you're reading this post then you've already proven you have enough knowledge to understand what each parameter means, if not just ask questions here. For the record, I already know that it's a bit messy. :p




whats amazing is how similar our methods are! here is mine:


procedure FindMonster;
var
tmpCTS, k, len, i: Integer;
monsterTPA: TPointArray;
tmp1ATPA, tmp2ATPA, transfer: T2DPointArray;
tmpBox: TBox;
centre:TPoint;
begin
MyDeBug('Started FindMonster');
setlength(monsterATPA,0);
tmpCTS := GetToleranceSpeed;

/////////////////////
setColorToleranceSpeed(2);
setToleranceSpeed2Modifiers(StrToFloat(monsters[monsterPrimary][2]), StrToFloat(monsters[monsterPrimary][3]));
if FindColorsTolerance(monsterTPA, StrToInt(monsters[monsterPrimary][4]), MSX1, MSY1, MSX2, MSY2, StrToInt(monsters[monsterPrimary][5])) then
begin
tmp1ATPA := SplitTPAEx(monsterTPA, 3, 3);
for k := 0 to length(tmp1ATPA)-1 do
begin
tmpBox := GetTPABounds(tmp1ATPA[k]);

setToleranceSpeed2Modifiers(StrToFloat(monsters[monsterPrimary][6]), StrToFloat(monsters[monsterPrimary][7]));
if FindColorsTolerance(monsterTPA, StrToInt(monsters[monsterPrimary][8]), tmpBox.X1, tmpBox.Y1, tmpBox.X2, tmpBox.Y2, StrToInt(monsters[monsterPrimary][9])) then
begin
len := length(monsterATPA);
transfer := CopyATPA(monsterATPA);
setLength(monsterATPA, len+1);
for i := 0 to len-1 do
begin
monsterATPA[i] := transfer[i];
end;
monsterATPA[len] := tmp1ATPA[k];
end;
end;
end;
//////////////////////////////
if (monsterSecondary > -1) then
begin
setToleranceSpeed2Modifiers(StrToFloat(monsters[monsterSecondary][2]), StrToFloat(monsters[monsterSecondary][3]));
if (FindColorsTolerance(monsterTPA, StrToInt(monsters[monsterSecondary][4]), MSX1, MSY1, MSX2, MSY2, StrToInt(monsters[monsterSecondary][5]))) then // this finds different colored same monster
begin
tmp2ATPA := SplitTPAEx(monsterTPA, 3, 3);
for k := 0 to length(tmp2ATPA)-1 do
begin
tmpBox := GetTPABounds(tmp2ATPA[k]);

setToleranceSpeed2Modifiers(StrToFloat(monsters[monsterSecondary][6]), StrToFloat(monsters[monsterSecondary][7]));
if FindColorsTolerance(monsterTPA, StrToInt(monsters[monsterSecondary][8]), tmpBox.X1, tmpBox.Y1, tmpBox.X2, tmpBox.Y2, StrToInt(monsters[monsterSecondary][9])) then
begin
len := length(monsterATPA);
transfer := CopyATPA(monsterATPA);
setLength(monsterATPA, len+1);
for i := 0 to len-1 do
begin
monsterATPA[i] := transfer[i];
end;
monsterATPA[len] := tmp2ATPA[k];
end;
end;
end;
end;
////////////////////////////////
SetColorToleranceSpeed(tmpCTS); // now we have our ATPA, we need to combine
SetToleranceSpeed2Modifiers(0.02, 0.02); // some of the TPA's, as they may be in both colors
centre := Point((MSX1 + MSX2) / 2, (MSY1 + MSY2) / 2);
monsterTPA := MergeATPA(monsterATPA); // to the same moss giant.
monsterATPA := SplitTPAEx(monsterTPA, 25, 25); // so we merge the whole ATPA and then split
SortATPAFromMidPoint(monsterATPA, centre); // it again making sure no overlaps
//SMART_ClearCanvasArea(IntToBox(MSX1, MSY1, MSX2, MSY2));
//SMART_DebugATPA(false, monsterATPA);
end;

procedure AttackMonster;
var
bounds: TBox;
i, cx, cy: Integer;
theUpText: String;
begin
MyDeBug('started AttackMonster');
i := 0;
FindMonster;
while (i < length(monsterATPA)) do
begin
bounds := getTPABounds(monsterATPA[i]);
if(bounds.Y1 > 10) then
begin // add in check for hit splats ass well
if(FindColor(cx, cy, 255, bounds.X1, bounds.y1-10, bounds.X2, bounds.Y1 + 30)) then
begin
MyDeBug('that monster in combat');
AreNoobsTalking;
wait(randomrange(200,500));
inc(i);
continue;
end else
begin
MMouse((bounds.X1 +bounds.X2) /2, (bounds.Y1 +bounds.Y2) / 2, 5, 5);
theUpText := GetTextAtExWrap(55, 2, 94, 21, 0, 6, 2, 122074, 40, 'UpChars07');
MyDeBug('up text over monster is: ' + theUpText);

if (ExecRegExpr('.*'+monsters[monsterPrimary][1]+'.*', theUpText)) then
begin
clickmouse2(true);
MyDeBug('just clicked a monster');
wait(randomrange(2000, 6000));
AreNoobsTalking;
break;
end;
end;
end;
inc(i);
end;
wait(randomrange(1000, 3000));
//SMART_ClearCanvasArea(IntToBox(MSX1, MSY1, MSX2, MSY2));
end;


ive split it into 2 functions but its essentially the same, except where you count colors to check its the monster, i check for a secondary color.

however, it is not this area i am having problems with, it is establishing whether my character is in combat with a npc.

i think from the suggestions, i am going to have to select colors from the character in order accurately determine where the character is on screen ..

Sk1nyNerd

2013-06-03 23:43:01

From: EngageTheRage
whats amazing is how similar our methods are! here is mine:


procedure FindMonster;
var
tmpCTS, k, len, i: Integer;
monsterTPA: TPointArray;
tmp1ATPA, tmp2ATPA, transfer: T2DPointArray;
tmpBox: TBox;
centre:TPoint;
begin
MyDeBug('Started FindMonster');
setlength(monsterATPA,0);
tmpCTS := GetToleranceSpeed;

/////////////////////
setColorToleranceSpeed(2);
setToleranceSpeed2Modifiers(StrToFloat(monsters[monsterPrimary][2]), StrToFloat(monsters[monsterPrimary][3]));
if FindColorsTolerance(monsterTPA, StrToInt(monsters[monsterPrimary][4]), MSX1, MSY1, MSX2, MSY2, StrToInt(monsters[monsterPrimary][5])) then
begin
tmp1ATPA := SplitTPAEx(monsterTPA, 3, 3);
for k := 0 to length(tmp1ATPA)-1 do
begin
tmpBox := GetTPABounds(tmp1ATPA[k]);

setToleranceSpeed2Modifiers(StrToFloat(monsters[monsterPrimary][6]), StrToFloat(monsters[monsterPrimary][7]));
if FindColorsTolerance(monsterTPA, StrToInt(monsters[monsterPrimary][8]), tmpBox.X1, tmpBox.Y1, tmpBox.X2, tmpBox.Y2, StrToInt(monsters[monsterPrimary][9])) then
begin
len := length(monsterATPA);
transfer := CopyATPA(monsterATPA);
setLength(monsterATPA, len+1);
for i := 0 to len-1 do
begin
monsterATPA[i] := transfer[i];
end;
monsterATPA[len] := tmp1ATPA[k];
end;
end;
end;
//////////////////////////////
if (monsterSecondary > -1) then
begin
setToleranceSpeed2Modifiers(StrToFloat(monsters[monsterSecondary][2]), StrToFloat(monsters[monsterSecondary][3]));
if (FindColorsTolerance(monsterTPA, StrToInt(monsters[monsterSecondary][4]), MSX1, MSY1, MSX2, MSY2, StrToInt(monsters[monsterSecondary][5]))) then // this finds different colored same monster
begin
tmp2ATPA := SplitTPAEx(monsterTPA, 3, 3);
for k := 0 to length(tmp2ATPA)-1 do
begin
tmpBox := GetTPABounds(tmp2ATPA[k]);

setToleranceSpeed2Modifiers(StrToFloat(monsters[monsterSecondary][6]), StrToFloat(monsters[monsterSecondary][7]));
if FindColorsTolerance(monsterTPA, StrToInt(monsters[monsterSecondary][8]), tmpBox.X1, tmpBox.Y1, tmpBox.X2, tmpBox.Y2, StrToInt(monsters[monsterSecondary][9])) then
begin
len := length(monsterATPA);
transfer := CopyATPA(monsterATPA);
setLength(monsterATPA, len+1);
for i := 0 to len-1 do
begin
monsterATPA[i] := transfer[i];
end;
monsterATPA[len] := tmp2ATPA[k];
end;
end;
end;
end;
////////////////////////////////
SetColorToleranceSpeed(tmpCTS); // now we have our ATPA, we need to combine
SetToleranceSpeed2Modifiers(0.02, 0.02); // some of the TPA's, as they may be in both colors
centre := Point((MSX1 + MSX2) / 2, (MSY1 + MSY2) / 2);
monsterTPA := MergeATPA(monsterATPA); // to the same moss giant.
monsterATPA := SplitTPAEx(monsterTPA, 25, 25); // so we merge the whole ATPA and then split
SortATPAFromMidPoint(monsterATPA, centre); // it again making sure no overlaps
//SMART_ClearCanvasArea(IntToBox(MSX1, MSY1, MSX2, MSY2));
//SMART_DebugATPA(false, monsterATPA);
end;

procedure AttackMonster;
var
bounds: TBox;
i, cx, cy: Integer;
theUpText: String;
begin
MyDeBug('started AttackMonster');
i := 0;
FindMonster;
while (i < length(monsterATPA)) do
begin
bounds := getTPABounds(monsterATPA[i]);
if(bounds.Y1 > 10) then
begin // add in check for hit splats ass well
if(FindColor(cx, cy, 255, bounds.X1, bounds.y1-10, bounds.X2, bounds.Y1 + 30)) then
begin
MyDeBug('that monster in combat');
AreNoobsTalking;
wait(randomrange(200,500));
inc(i);
continue;
end else
begin
MMouse((bounds.X1 +bounds.X2) /2, (bounds.Y1 +bounds.Y2) / 2, 5, 5);
theUpText := GetTextAtExWrap(55, 2, 94, 21, 0, 6, 2, 122074, 40, 'UpChars07');
MyDeBug('up text over monster is: ' + theUpText);

if (ExecRegExpr('.*'+monsters[monsterPrimary][1]+'.*', theUpText)) then
begin
clickmouse2(true);
MyDeBug('just clicked a monster');
wait(randomrange(2000, 6000));
AreNoobsTalking;
break;
end;
end;
end;
inc(i);
end;
wait(randomrange(1000, 3000));
//SMART_ClearCanvasArea(IntToBox(MSX1, MSY1, MSX2, MSY2));
end;


ive split it into 2 functions but its essentially the same, except where you count colors to check its the monster, i check for a secondary color.

however, it is not this area i am having problems with, it is establishing whether my character is in combat with a npc.

i think from the suggestions, i am going to have to select colors from the character in order accurately determine where the character is on screen ..



u could use an array for ur colors, tolerances, hues and sats too shorten ur code up. something neat I just found out not too long ago

EngageTheRage

2013-06-04 00:07:23

From: ibot_dung11
u could use an array for ur colors, tolerances, hues and sats too shorten ur code up. something neat I just found out not too long ago


I have used a 2D array for them all if you look …

Haxz

2013-06-04 01:59:11

From: Flight
Ah yes indeed it is… I'll post it here:



First off, I worked really hard on this believe it or not, so if you use it in a script please do give credits… With that being said, thanks again Markus for helping me with that 'Range check error'. :duh:

What this function does is finds available (not in combat) NPCs on your screen (based on your input), and returns a TPA with each point containing the middle of each of those NPCs, sorted from the center of the screen.

Some examples of beta tests on Giant Rats behind Lumbridge castle: (Using CTS3, for what it's worth)



I explained out exactly how this function works, so maybe it would be good for some to learn from. The parameters are obvious, and if you're reading this post then you've already proven you have enough knowledge to understand what each parameter means, if not just ask questions here. For the record, I already know that it's a bit messy. :p


Function FindFreeTargets(Color, Tol, CTS, MinCount, Width, Height: Integer): TPointArray;
var
NPCBox,HPZone: TBox;
TopPoint,MiddleHPZone,
MiddleNPCBox: TPoint;
TPA,GreenPointsA,RedPointsA,
GreenPointsB,RedPointsB,
RTPA: TPointArray;
L,i,CTS_Old,R: Integer;
ATPA: T2DPointArray;
begin
CTS_Old := GetColorToleranceSpeed;
{Find NPC colors}
ColorToleranceSpeed(CTS);
FindColorsSpiralTolerance(MSCX, MSCY, TPA, Color, MSX1, MSY1, MSX2, MSY2, Tol);

if (Length(TPA) < 1) then
begin
ColorToleranceSpeed(CTS_Old);
Exit;
end;
{Split TPA's into boxes defined by 'Width' & 'Height'}
ATPA := SplitTPAEx(TPA, Width, Height); //In this instance, I prefer SplitTPA
L := High(ATPA);
SetArrayLength(ATPA, L+1);
{Loop through each box}
for i := 0 to L do
begin
{If the # of color points found inside the box is >= to 'MinCount'}
if (Length(ATPA[i]) >= MinCount) then
NPCBox := GetTPABounds(ATPA[i]);
{Inside each valid NPC box}
with NPCBox do
begin
{Get middle top point of the box}
TopPoint := Point(((NPCBox.X1+NPCBox.X2)/2), NPCBox.Y1);

if (TopPoint.X < MSX1) then
TopPoint.X := MSX1;
if (TopPoint.Y < MSY1) then
TopPoint.Y := MSY1;
{Using 'TopPoint', specify a static region in which a health bar would be present}
HPZone := IntToBox(TopPoint.X-30, TopPoint.Y-40, TopPoint.X+30, TopPoint.Y);

if (HPZone.X1 < MSX1) then
HPZone.X1 := MSX1;
if (HPZone.X2 > MSX2) then
HPZone.X2 := MSX2;
if (HPZone.Y1 < MSY1) then
HPZone.Y1 := MSY1;
if (HPZone.Y2 > MSY2) then
HPZone.Y1 := MSY2;
{These two aren't really needed}
MiddleHPZone := Point(((HPZone.x1+HPZone.x2)/2), ((HPZone.y1+HPZone.y2)/2));
MiddleNPCBox := Point(((NPCBox.x1+NPCBox.x2)/2), ((NPCBox.y1+NPCBox.y2)/2));

{Search within both the 'NPCBox' and the HPZone for both red & green colors}
ColorToleranceSpeed(3);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, GreenPointsA, 49242, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, RedPointsA, 524459, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, GreenPointsB, 49242, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, RedPointsB, 524459, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
ColorToleranceSpeed(CTS_Old);

{If no red or green is found within the NPCBox and HPZone}
if ((Length(GreenPointsA) = 0) and (Length(RedPointsA) = 0)
and (Length(GreenPointsB) = 0) and (Length(RedPointsB) = 0)) then
begin
{Add the center of the NPCBox to 'RTPA'}
SetArrayLength(RTPA, (Length(RTPA)+1));
RTPA[R] := MiddleNPCBox;
Inc(R);
end;

end;

end;

{Sort the 'RTPA' from the center of the screen}
SortTPAFrom(RTPA, Point(MSCX, MSCY));
{RTPA now holds the center point for each NPCBox of 'avaiable' targets}
Result := RTPA;

end;

Here's a quick script I threw together to fight level 10 Minotaurs in Stronghold of Security:

program MinotaurMasher;

{$DEFINE SRL5}
{$DEFINE SMART}

{$i SRL/srl.simba}
{$i SRL/SRL/misc/paintsmart.simba}


Const
WeaponSpeed = 'Fast';
Training = 'Strength';
HPLevel = 80;

Var
KillCount,Exp,HPExp,
WeaponTimer: Integer;


Procedure DeclarePlayers;
begin
HowManyPlayers := 1;
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0;
with Players[0] do
begin
Name := '';
Pass := '';
Level[SKILL_HITPOINTS] := HPLevel;
BoxRewards := ['XP','xp','lamp'];
LampSkill := 'Mining';
Active := True;
end;
end;

Procedure LoadVars;
begin

case Lowercase(WeaponSpeed) of
'fast': WeaponTimer := 800;
'normal': WeaponTimer := 1500;
'slow': WeaponTimer := 3000;
end;

end;

Procedure OnScreen;
var
XPH,XPH2,TTB,
KPH: Integer;
begin

XPH := Round((Exp * 3600) / (GetTimeRunning / 1000));
XPH2 := Round((HPExp * 3600) / (GetTimeRunning / 1000));
KPH := Round((KillCount * 3600) / (GetTimeRunning / 1000));
//TTB := (((w) + (y) + BreakRounds)-GetTimeRunning);

SMART_DrawTextMulti(True, True, ['Minotaur Masher 1.0 by Flight','',
''+MsToTime(GetTimeRunning, Time_Abbrev),'',
''+Capitalize(Training)+' XP: '+IntToStr(Exp)+' ('+IntToStr(XPH)+' / hour)','',
'Hitpoints XP: '+IntToStr(HPExp)+' ('+IntToStr(XPH2)+' / hour)','',
'Kills: '+IntToStr(KillCount)+' ('+IntToStr(KPH)+' / hour)'],
Point(10, 200), SmallCharsNS, 16777215);

//SMART_DrawTextMulti(False, True, ['Time till break: '+MsToTime(TTB,Time_Bare)], Point(570, 445), SmallCharsNS, 65280);
end;

Procedure HumanMMouse(eX, eY, ranX, ranY: Integer);
var
randSpeed: extended;
X,Y,X2,Y2,A,Dist,MP: integer;
begin
A := MouseSpeed;
GetMousePos(X, Y);
Dist := Distance(X, Y, eX, eY);
MP := Round(Dist/150);
if MP < 0 then
MP := 1;

randSpeed := (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0;
X2 := RandomRange(eX-(A*MP), eX+(A*MP));
Y2 := RandomRange(eY-(A*MP), eY+(A*MP));
WindMouse(X, Y, X2, Y2, 11, 8, 10.0 / randSpeed, 12.0 / randSpeed, 10.0 * randSpeed, 10.0 * randSpeed);
GetMousePos(X, Y);
MMouse(eX, eY, ranX, ranY);
MouseSpeed := A;
end;

Procedure HumanRandomMouse;
var
randSpeed: extended;
x, y, firstSpeed: integer;
begin
case(Random(10)) of
2..8:
begin
firstSpeed := mouseSpeed;

mouseSpeed := RandomRange(5,10);
randSpeed := (random(MouseSpeed) / 2.0 + MouseSpeed) / 10.0;
GetMousePos(x, y);
WindMouse(x, y, RandomRange(x - 75, x + 75), RandomRange(y - 75, y + 75),
30, 55, 10.0 / randSpeed, 12.0 / randSpeed, 10.0 * randSpeed, 10.0 * randSpeed);

mouseSpeed := firstSpeed;
end;
end;
end;

Function IsMoving_F: Boolean;
begin
Result := PixelShift(IntToBox(MMCX-30, MMCY-30, MMCX+30, MMCY+30), 200) > 200;
end;

Function Attacking: Boolean;
var
PBox: TBox;
begin
PBox := IntToBox(245, 135, 280, 185);
Result := (AveragePixelShift(PBox, 250, 500) > 500);
end;

Procedure GetShiftCount;
var
PBox: TBox;
begin
PBox := IntToBox(245, 135, 280, 185);
Writeln(IntToStr(AveragePixelShift(PBox, 250, 500)));
end;

Function DidAntiban: Boolean;
var
i: Integer;
begin
Result := False;
if not LoggedIn then Exit;

i := Random(450);
case i of
1..45:
begin
HumanRandomMouse;
Result := True;
end;
46:
begin
HoverSkill('Strength', False);
Result := True;
end;
47:
begin
HoverSkill('Attack', False);
Result := True;
end;
48:
begin
HoverSkill('Hitpoints', False);
Result := True;
end;
49..450: Exit;
end;

end;

Function Eat: Boolean;
var
i: Integer;
begin
Result := False;

if Not LoggedIn then Exit;
if InvEmpty then Exit;
if (HPPercent >= 60) then Exit;

for i := 0 to 28 do
begin
FindNormalRandoms;

if ExistsItem(i) then
begin
InvMouse(i, mouse_move);

if WaitUpText('Eat', 300) then
begin
ClickMouse2(True);
Wait(RandomRange(875, 990));
if (HPPercent >= 90) then
Exit;
end;

if (i = 28) then
Exit;

end;

end;
end;

Function FindFreeTargets(Color, Tol, CTS, MinCount, Width, Height: Integer): TPointArray;
var
NPCBox,HPZone: TBox;
TopPoint,MiddleHPZone,
MiddleNPCBox: TPoint;
TPA,GreenPointsA,RedPointsA,
GreenPointsB,RedPointsB,
RTPA: TPointArray;
L,i,CTS_Old,R: Integer;
ATPA: T2DPointArray;
begin
CTS_Old := GetColorToleranceSpeed;
{Find NPC colors}
ColorToleranceSpeed(CTS);
FindColorsSpiralTolerance(MSCX, MSCY, TPA, Color, MSX1, MSY1, MSX2, MSY2, Tol);

if (Length(TPA) < 1) then
begin
ColorToleranceSpeed(CTS_Old);
Exit;
end;
{Split TPA's into boxes defined by 'Width' & 'Height'}
ATPA := SplitTPAEx(TPA, Width, Height);
L := High(ATPA);
SetArrayLength(ATPA, L+1);
{Loop through each box}
for i := 0 to L do
begin
{If the # of color points found inside the box is >= to 'MinCount'}
if (Length(ATPA[i]) >= MinCount) then
NPCBox := GetTPABounds(ATPA[i]);
{Inside each valid NPC box}
with NPCBox do
begin
{Get middle top point of the box}
TopPoint := Point(((NPCBox.X1+NPCBox.X2)/2), NPCBox.Y1);

if (TopPoint.X < MSX1) then
TopPoint.X := MSX1;
if (TopPoint.Y < MSY1) then
TopPoint.Y := MSY1;
{Using 'TopPoint', specify a static region in which a health bar would be present}
HPZone := IntToBox(TopPoint.X-30, TopPoint.Y-40, TopPoint.X+30, TopPoint.Y);

if (HPZone.X1 < MSX1) then
HPZone.X1 := MSX1;
if (HPZone.X2 > MSX2) then
HPZone.X2 := MSX2;
if (HPZone.Y1 < MSY1) then
HPZone.Y1 := MSY1;
if (HPZone.Y2 > MSY2) then
HPZone.Y1 := MSY2;
{These two aren't really needed}
MiddleHPZone := Point(((HPZone.x1+HPZone.x2)/2), ((HPZone.y1+HPZone.y2)/2));
MiddleNPCBox := Point(((NPCBox.x1+NPCBox.x2)/2), ((NPCBox.y1+NPCBox.y2)/2));

{Search within both the 'NPCBox' and the HPZone for both red & green colors}
ColorToleranceSpeed(3);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, GreenPointsA, 49242, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleNPCBox.X, MiddleNPCBox.Y, RedPointsA, 524459, NPCBox.X1, NPCBox.Y1, NPCBox.X2, NPCBox.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, GreenPointsB, 49242, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
FindColorsSpiralTolerance(MiddleHPZone.X, MiddleHPZone.Y, RedPointsB, 524459, HPZone.X1, HPZone.Y1, HPZone.X2, HPZone.Y2, 2);
ColorToleranceSpeed(CTS_Old);

{If no red or green is found within the NPCBox and HPZone}
if ((Length(GreenPointsA) = 0) and (Length(RedPointsA) = 0)
and (Length(GreenPointsB) = 0) and (Length(RedPointsB) = 0)) then
begin
{Add the center of the NPCBox to 'RTPA'}
SetArrayLength(RTPA, (Length(RTPA)+1));
RTPA[R] := MiddleNPCBox;
Inc(R);
end;

end;

end;

{Sort the 'RTPA' from the center of the screen}
SortTPAFrom(RTPA, Point(MSCX, MSCY));
{RTPA now holds the center point for each NPCBox of 'avaiable' targets}
Result := RTPA;

end;

procedure AttackMinotaur;
var
T: Integer;
GoOn: Boolean;
TPA: TPointArray;
label
Search;
begin
if not LoggedIn then Exit;
Eat;

Search:
GoOn := False;
MouseSpeed := RandomRange(14, 22);
TPA := FindFreeTargets(10594473, 3, 3, 10, 20, 20);

if (Length(TPA) > 0) then
begin
HumanMMouse(TPA[0].X, TPA[0].Y, 5, 5);
if WaitUpTextMulti(['ck M','inot', 'taur'], 300) then
begin
ClickMouse2(True);
if not DidRedClick then
goto Search;
end else
goto Search;

FFlag(0);
While IsMoving_F do
Wait(1);

MarkTime(T);
repeat
if not LoggedIn then Exit;
FindNormalRandoms;

if (TimeFromMark(T) > 3000) then
Exit;

if Attacking then
break;

if FindBlackChatMessage('omeone else is fighting') then
break;

until(false)

if FindBlackChatMessage('omeone else is fighting') then
goto Search;

GoOn := True;
MarkTime(T);
repeat
if not LoggedIn then Exit;
FindNormalRandoms;
Eat;

//if (Attacking or DidAntiBan) then
if Attacking then
MarkTime(T);

if (TimeFromMark(T) > WeaponTimer) then
break;
until(false)

if GoOn then
begin
GoOn := False;
Inc(KillCount);
IncEx(Exp, 40);
IncEx(HPExp, 14);
//Inc(KillCount_C);
OnScreen;
end;

end;
end;

begin
Smart_Server := 86;
Smart_Members := True;
Smart_Signed := True;
Smart_SuperDetail := False;

setupSRL();
DeclarePlayers;

LoadVars;
Smart_ClearCanvas;
Wait(RandomRange(500, 675));
OnScreen;

Repeat

//GetShiftCount;
if not LoggedIn then
begin
LoginPlayer;
ClickNorth(SRL_ANGLE_HIGH);
end;

FindNormalRandoms;
AttackMinotaur;

Until(False)

end.



SRL mems section being restricted is so bad, we could have learnt and know about scripting so much more if it was open :(

Btw, those are some badass advanced codes!

Sk1nyNerd

2013-06-04 10:06:53

From: EngageTheRage
I have used a 2D array for them all if you look …


yup cause I like to post random things on random threads. ill show u what I mean when I get my comp back. u won't have to look for a primary and secondary color, u can do all of it in one step

Flight

2013-06-04 10:20:42

From: EngageTheRage
whats amazing is how similar our methods are! here is mine:

ive split it into 2 functions but its essentially the same, except where you count colors to check its the monster, i check for a secondary color.

however, it is not this area i am having problems with, it is establishing whether my character is in combat with a npc.

i think from the suggestions, i am going to have to select colors from the character in order accurately determine where the character is on screen ..


Yes it's a bit old as you can tell and for certain NPC targets I'd also go with a dual-color searching function if the situation calls for it.


From: Haxz
SRL mems section being restricted is so bad, we could have learnt and know about scripting so much more if it was open :(

Btw, those are some badass advanced codes!


Not at all friend, giving out teasers like this ideally should encourage you to work towards applying for Members. :)