SRL Archive - Reflection Development

Object Finding - Reflection


Bobarkinator

2008-08-22 23:26:38

We have all been waiting for it and it's finally here. The use of finding objects through reflection.

Some quick notes before we release the code

  • Right now SCAR doesn't free the objects it uses which means that over time, SCAR will will be using more memory. We don't free them because most of the time it will cause SCAR to crash, if anyone can circumvent this, please say so
  • This won't work for doors, doors are off in their own little world…just use tiles for doors. I'll be working on them in the mean time
  • I replaced Objects.scar
  • Always check to be sure the tile that FindObject returns is on the Mainscreen, and if it's not then you need to walk to it.

Even though I have kinda left n3ss3s out of the loop for the past few major improvements, he was a big part of this. BenLand100 was also a big part in helping us weed out glitches and getting the project working.

//------------------------------------------------------------------\\
//-- Scar Non-Standard Resource Library --||
//-- ยป Reflection Routines - Objects --||
//------------------------------------------------------------------//
// * Function GetObjectType(UID: Long): Integer;
// * Function GetObjectTile(UID: Long): TPoint;
// * Function GetUIDAt(TileX, TileY: Integer): UID;
// * Function FindObject(Var Tile: TPoint; objType: Integer): Boolean;
// * Procedure DumpAllObjects;

Type
Long = Record
High, Low: Integer;
End;

UID = Record
objType: Integer;
UID: Long;
End;

Const
getGroundArray = 'ck.d';

getObject1 = 's';
getObject2 = 'z';
getObject3 = 'M';
getObject4 = 'u';

getObject5Array = 'H';

getUID1 = 'j'; //j
getUID2 = 't'; //t
getUID3 = 'm'; //m
getUID4 = 'd'; //d
getUID5 = 'k'; //k

{*******************************************************************************
Function GetObjectType(UID: Long): Integer;
By: Bobarkinator
Description: Returns object type of a UID

*******************************************************************************}

Function GetObjectType(UID: Long): Integer;

Begin
Result := UID.High And $7fffffff;
End;

{*******************************************************************************
Function GetObjectTile(UID: Long): TPoint;
By: Bobarkinator
Description: Returns tile of a UID

*******************************************************************************}

Function GetObjectTile(UID: Long): TPoint;

Begin
Result.X:= (SmartGetFieldInt(0, BaseX) + (UID.Low And $7f));
Result.Y:= (SmartGetFieldInt(0, BaseY) + ((UID.Low Shr 7) And $7f));
End;

{*******************************************************************************
Function GetUIDAt(TileX, TileY: Integer): UID;
By: n3ss3s and Bobarkinator
Description: Returns the information about the object at a give tile

*******************************************************************************}

Function GetObjectAt(TileX, TileY: Integer): UID;

Var
X, Y, Z, I, obj, C, Q: Integer;
getObj, getUIDs: TStringArray;
Begin
X := TileX - SmartGetFieldInt(0, BaseX);
Y := TileY - SmartGetFieldInt(0, BaseY);
getObj := [getObject1, getObject2, getObject3, getObject4, getObject5Array];
getUIDs := [getUID1, getUID2, getUID3, getUID4, getUID5];
For Q := 0 To 3 Do
Begin
Z := SmartGetFieldArray3DObject(0, getGroundArray, Q, X, Y);
If Z = 0 Then Continue;
For I := 0 To 4 Do
If I < 4 Then
Begin
obj := SmartGetFieldObject(Z, getObj[I]);
//WriteLn('Object is '+inttostr(obj)+' on getObject1 in '+inttostr(Q)+' ground layer');
If obj <> 0 Then
Begin
Result.UID.High := SmartGetFieldLongH(obj, getUIDs[I]);
Result.UID.Low := SmartGetFieldLongL(obj, getUIDs[I]);
Result.objType := GetObjectType(Result.UID);
//SmartFreeObject(obj);
//SmartFreeObject(Z);
Exit;
End;
End Else
For C := 0 To SmartGetFieldArraySize(Z, getObject5Array) - 1 Do
Begin
obj := SmartGetFieldArrayObject(Z, getObject5Array, C);
//WriteLn('Object is ' + IntToStr(Obj) + ' on Object5Array');
If obj <> 0 Then
Begin
Result.UID.High := SmartGetFieldLongH(obj, getUID5);
Result.UID.Low := SmartGetFieldLongL(obj, getUID5);
Result.objType := GetObjectType(Result.UID);
//SmartFreeObject(obj);
//SmartFreeObject(o5a);
//SmartFreeObject(z);
Exit;
End;
End;
End;
Result.objType := 0;
End;

{*******************************************************************************
Function FindObject(Var Tile: TPoint; objType: Integer): Boolean;
By: n3ss3s and Bobarkinator
Description: Returns True if objType is found. Tile of objType is returned in
Tile. Make sure to check thatthe Tile is on the MS, if not, walk to it

*******************************************************************************}

Function FindObject(Var Tile: TPoint; objType: Integer): Boolean;
// Yakman's spiral algorithm =]

Var
Dir, tLength, f, X, Y: Integer;
TP: TPoint;
TileObject: UID;
Begin
TP := GetMyPos;
X := TP.X;
Y := TP.Y;
Dir := 0;
tLength := 1;
While (tLength < 9) Do
Begin
For F := 0 To tLength - 1 Do
Begin
Case Dir of
0: Y := Y - 1;
1: X := X + 1;
2: Y := Y + 1;
3: X := X - 1;
End;
TileObject := GetObjectAt(X, Y);
If TileObject.objType = objType Then
Begin
//Writeln('Found Type ' + IntToStr(objType) + ' at X ' + IntToStr(X) +
//' Y ' + IntToStr(Y));
Result := True;
TP := GetObjectTile(TileObject.UID);
Tile.X := TP.X
Tile.Y := TP.Y;
Exit;
End Else
//Writeln('X: '+IntToStr(X)+' Y:'+IntToStr(Y)+ ' '+IntToStr(TileObject.objType));
End;
Dir := Dir + 1;
dir := dir Mod 4;
If Dir Mod 2 = 0 Then
tLength := tLength + 1;
End;
End;

{*******************************************************************************
Procedure DumpAllObjects;
By: Bobarkinator
Description: Prints out all the objects on the current map(104 x 104)

*******************************************************************************}

Procedure DumpAllObjects;

Var
BaseTileX, BaseTileY, X, Y: Integer;
O: UID;
Begin
BaseTileX := SmartGetFieldInt(0, BaseX);
BaseTileY := SmartGetFieldInt(0, BaseY);
For X := BaseTileX To 104 + BaseTileX Do
For Y := BaseTileY To 104 + BaseTileY Do
Begin
O := GetObjectAt(X, Y);
WriteLn('X ' + IntToStr(X) + ' Y ' + IntToStr(Y) + ' Type ' + IntToStr(O.objType));
End;
End;

Enjoy
- n3ss3s and Bobarkinator

NiCbaZ

2008-08-22 23:41:06

Yay, very nice w00t.

lordsaturn

2008-08-23 00:14:28

Wow, revolutionary.

Thank you. :D

n3ss3s

2008-08-23 05:36:29

We kick ass, so the L and H meant Low and High :)

Now, we can start on some ass kicking scripts x)


Wait a minute, L are the 'low' 32 bytes and H are the 'high' 32 bytes?

*Prayer skillcape emote IRL*

Naike

2008-08-23 05:42:46

Me loves you 2 :D

MylesMadness

2008-08-23 08:37:13

Don't you need to find a type, not a uid?

n3ss3s

2008-08-23 08:50:36


Function GetObjectAt(TileX, TileY: Integer): UID;


UID = Record
objType: Integer;
UID: Long;
End;



Don't you need to find a type, not a uid?


Whale fale.

MylesMadness

2008-08-23 09:15:02

Right…

Lee Lok Hin

2008-08-23 09:19:10

/me has added to repoistory

MylesMadness

2008-08-23 09:39:32

From: Lee Lok Hin
/me has added to repoistory
Well you didn't do it right, your forgot to include it in reflection.scar

Lee Lok Hin

2008-08-23 09:52:09

Fudck me, I could swear I did.

I did? Didn't I?

MylesMadness

2008-08-23 09:57:16

You did, it just when I hit ctrl+space it would show up in the list so I though it was because it wasn't included. It was though

Bobarkinator

2008-08-23 11:20:03

From: n3ss3s
We kick ass, so the L and H meant Low and High :)

Now, we can start on some ass kicking scripts x)


Wait a minute, L are the 'low' 32 bytes and H are the 'high' 32 bytes?

*Prayer skillcape emote IRL*


It's weird, it's like backwards… Low is the last part of the UID, High is the first part of the UID, that is, if I was understanding what Ben was saying. Either way, it works right now :)

mastaraymond

2008-08-23 11:26:44

From: Bobarkinator
It's weird, it's like backwards… Low is the last part of the UID, High is the first part of the UID, that is, if I was understanding what Ben was saying. Either way, it works right now :)

Big-endian way of memory :p

nobody u kno

2008-08-23 20:59:32

Whats the ID for a gate? I ran the NPC finder cuz it tells you the ID's, but it didnt come up cuz a gate isnt an NPC. I went to that Rune Locus site and typed in gate and there was like a hundred ID's for gate. So idk which one to use?

Method

2008-08-23 21:35:57

From: nobody u kno
Whats the ID for a gate? I ran the NPC finder cuz it tells you the ID's, but it didnt come up cuz a gate isnt an NPC. I went to that Rune Locus site and typed in gate and there was like a hundred ID's for gate. So idk which one to use?


Use GetObjectAt with the tiles of the gate and you'll get back the UID for it.

Bobarkinator

2008-08-24 00:08:32

From: nobody u kno
Whats the ID for a gate? I ran the NPC finder cuz it tells you the ID's, but it didnt come up cuz a gate isnt an NPC. I went to that Rune Locus site and typed in gate and there was like a hundred ID's for gate. So idk which one to use?


A simple way is to get your current position and stand right under the gate, then do GetObjectAt(Yourcurrentposition.x, yourcurrentposition.y + 1)
then do WriteLn(theobjectitreturned.objtype);

n3ss3s

2008-08-24 02:43:38

For everyone's information by the way, in a function, if you do

GetObjectAt(..).objType, you'll end up with Out of Global Vars Range -runtime errors, so make a new variable, Z: UID; do Z := GetObjectAt(..); and then do Z.objType :)

Bobarkinator

2008-08-24 14:50:12

From: n3ss3s
For everyone's information by the way, in a function, if you do

GetObjectAt(..).objType, you'll end up with Out of Global Vars Range -runtime errors, so make a new variable, Z: UID; do Z := GetObjectAt(..); and then do Z.objType :)


I <3 Java for that.

Nava2

2008-08-24 15:39:23

Okay, well since there is a TileTool, I figured, there should be a Object Finding tool. I wrote one up, but I keep getting errors. Can you help out?

Here is the script:

program ObjShit;
{.include SRL/SRL/misc/smart.scar}
{.include SRL\SRL.Scar}
{.include SRL/SRL/reflection/reflection.scar}

var
I : integer;
P : TPoint;
AUID : Array of UID;

begin
SmartSetupEx(115, true, true, false);
SetTargetDC(SmartGetDC);
SetupSRL;
Writeln('');
Writeln('');
Repeat
Wait(1);
If (IsFKeyDown(2)) Then
Begin
GetMousePos(P.x, P.y);
P := MMToTile(P);
SetLength(AUID, Length(AUID) + 1);
AUID[i] := GetObjectAt(P.x, P.y);
Inc(i);
While (IsFKeyDown(2)) Do
Wait(1);
End;
until IsFKeyDown(3);
Writeln('function SetupUIDs : Array of UID;');
Writeln('');
Writeln('begin');
Writeln(' SetArrayLength(Result, ' + IntToStr(Length(AUID)) + ');');
Writeln('');
for I := 0 to High(AUID) do
begin
Writeln(' Result[' + IntToStr(i) + '].objtype := ' + IntToStr(AUID[i].Objtype) + ';');
Writeln(' Result[' + IntToStr(i) + '].UID.High := ' + IntToStr(AUID[i].UID.High) + ';');
Writeln(' Result[' + IntToStr(i) + '].UID.Low := ' + IntToStr(AUID[i].UID.Low) + ';');
Writeln('');
end;
Writeln('end;');
end.

You mouse over the object on the minimap and it returns the uid at that place. Theoretically. Then it writelns all the objects you pick as an array. But, I can only get it to writeln 0's.

Any advice?

Bobarkinator

2008-08-24 20:14:12

From: Nava2
Okay, well since there is a TileTool, I figured, there should be a Object Finding tool. I wrote one up, but I keep getting errors. Can you help out?

Here is the script:

program ObjShit;
{.include SRL/SRL/misc/smart.scar}
{.include SRL\SRL.Scar}
{.include SRL/SRL/reflection/reflection.scar}

var
I : integer;
P : TPoint;
AUID : Array of UID;

begin
SmartSetupEx(115, true, true, false);
SetTargetDC(SmartGetDC);
SetupSRL;
Writeln('');
Writeln('');
Repeat
Wait(1);
If (IsFKeyDown(2)) Then
Begin
GetMousePos(P.x, P.y);
P := MMToTile(P);
SetLength(AUID, Length(AUID) + 1);
AUID[i] := GetObjectAt(P.x, P.y);
Inc(i);
While (IsFKeyDown(2)) Do
Wait(1);
End;
until IsFKeyDown(3);
Writeln('function SetupUIDs : Array of UID;');
Writeln('');
Writeln('begin');
Writeln(' SetArrayLength(Result, ' + IntToStr(Length(AUID)) + ');');
Writeln('');
for I := 0 to High(AUID) do
begin
Writeln(' Result[' + IntToStr(i) + '].objtype := ' + IntToStr(AUID[i].Objtype) + ';');
Writeln(' Result[' + IntToStr(i) + '].UID.High := ' + IntToStr(AUID[i].UID.High) + ';');
Writeln(' Result[' + IntToStr(i) + '].UID.Low := ' + IntToStr(AUID[i].UID.Low) + ';');
Writeln('');
end;
Writeln('end;');
end.

You mouse over the object on the minimap and it returns the uid at that place. Theoretically. Then it writelns all the objects you pick as an array. But, I can only get it to writeln 0's.

Any advice?


No offense, but that setup UID's is a useless function. You never need to "setup" UIDs. The only thing you need to know about an object is it objType, then all you need to do is FindObject(Tile, theObjType);. So for instance, when developing my script, I'll find out that the objType of a tin rock is 12345(made up). Then in my script when I want to find a tin rock, I do "FindObject(Tile, 12345);" and it will find the nearest tin rock.

Nava2

2008-08-24 22:06:33

From: Bobarkinator
No offense, but that setup UID's is a useless function. You never need to "setup" UIDs. The only thing you need to know about an object is it objType, then all you need to do is FindObject(Tile, theObjType);. So for instance, when developing my script, I'll find out that the objType of a tin rock is 12345(made up). Then in my script when I want to find a tin rock, I do "FindObject(Tile, 12345);" and it will find the nearest tin rock.


To be honest with you, I was just kinda writing it out. Haha, I just wanted to make a function to Find UIDs and ObjTypes easily. Thats all.

welcome

2008-08-25 00:31:57

If (IsFKeyDown(2)) Then
Begin
SetLength(AUID, Length(AUID) + 1);
AUID := GetObjectAt(2976, 3369);
Inc(i);
While (IsFKeyDown(2)) Do
Wait(1);
End;

I don't know if this works right or not but I just figured on my own where the object is (Falador Furnace) and ran this and got

SetArrayLength(Result, 1);

Result[0].objtype := 2742;
Result[0].UID.High := -2147480906;
Result[0].UID.Low := 1078302904;

end;

Not sure if that is right or not

Bobarkinator

2008-08-25 08:13:05

Yeah it's right, all you need to remember is the objType, and from now on, when you want to find the furnace in your script just call FindObject(TPointToStoreTileIn, 2742); And it will give you the location of the furnace in the TPoint

Nava2

2008-08-25 10:04:21

I actually fixed mine but instead, I just input Tiles :).

welcome

2008-08-25 15:02:34

From: Bobarkinator
Yeah it's right, all you need to remember is the objType, and from now on, when you want to find the furnace in your script just call FindObject(TPointToStoreTileIn, 2742); And it will give you the location of the furnace in the TPoint


Thanks, I'll see if I can get it working and maybe finish this damn script today lol.

Bobarkinator

2008-08-25 16:14:52

From: Nava2
I actually fixed mine but instead, I just input Tiles :).


Sorry, I never actually looked at your code :redface:

welcome

2008-08-25 18:30:52

Is there item numbers for items in INV and a way to access the items? I can't seem to figure it out if there is.

Method

2008-08-25 18:57:32

From: welcome
Is there item numbers for items in INV and a way to access the items? I can't seem to figure it out if there is.


There are, but there isn't any finding for them right now included in the reflection SVN.

Bobarkinator

2008-08-25 19:43:13

n3ss3s and I have started on Interfaces, the inventory array (your items) is included in that. They are as difficult as objects :p

welcome

2008-08-25 22:08:35

Awesome, Thanks! You guys are doing an amazing job btw.

turbobk

2008-08-28 02:45:24

Hey guys…
This is ownage, but I cannot figure out how to use it.

Lets say Im making a fisher, how would I get it to find the fishing spot on the MS?

Thanks alot,
TurboBk. :)

Bobarkinator

2008-08-28 08:08:01

From: turbobk
Hey guys…
This is ownage, but I cannot figure out how to use it.

Lets say Im making a fisher, how would I get it to find the fishing spot on the MS?

Thanks alot,
TurboBk. :)


First you would get the Object Type of a fishing spot. Then all you need to do is call FindObject(TPoint, ObjectTypeOfFishingSpot);

turbobk

2008-08-28 08:23:17

From: Bobarkinator
First you would get the Object Type of a fishing spot. Then all you need to do is call FindObject(TPoint, ObjectTypeOfFishingSpot);


Oh ok, and is the object type the Number of the item?

So for example:

If FindObject(Tiles, 4321) Then
Begin
MMouse(Tiles.X, Tiles.Y, 3, 3);

Is that correct?

Method

2008-08-28 11:00:10

From: turbobk
Oh ok, and is the object type the Number of the item?

So for example:

If FindObject(Tiles, 4321) Then
Begin
MMouse(Tiles.X, Tiles.Y, 3, 3);

Is that correct?


Fishing spots are NPCs, so you'd have to use FindNPC or one of its related NPC finding functions instead.

Bobarkinator

2008-08-28 14:59:18

From: Method
Fishing spots are NPCs, so you'd have to use FindNPC or one of its related NPC finding functions instead.


I forgot :p.

You would use FindNPC for the fishing spot. But when finding objects, you had it right except. Before you do Tiles.X, you need to find the MSCoords of the Tile. So do TileToMS

turbobk

2008-08-28 23:46:51

Oh ok I get it now..

Thanks alot guys!! :)

Nava2

2008-08-29 00:50:02

By the way, if anyone wants this, here is the object type finder I use.

program ObjShit;
{.include SRL/SRL/misc/smart.scar}
{.include SRL\SRL.Scar}
{.include SRL/SRL/reflection/reflection.scar}

Const
TileX = 3312;
TileY = 3254;

World = 1;

var
UID : UID;

begin
SmartSetupEx(World, true, true, false);
SetTargetDC(SmartGetDC);
SetupSRL;

While not R_LoggedIn do
Wait(1);
UID := GetObjectAt(TileX, TileY);

Writeln('FindObject(T, ' + IntToStr(GetObjectType(UID.UID)) + '); ' + 'Tile is: ' + IntToStr(TileX) + ', ' + IntToStr(TileY));
end.

Just put in the Coords in TileX, and TileY. Also, make sure you set the world.

Cheers.

Claymore

2008-08-29 12:46:19

Does it find the ground items? Or just objects like …… objects XD

Bobarkinator

2008-08-29 16:22:41

From: Deathscytex
Does it find the ground items? Or just objects like …… objects XD


Their is a separate release for GroundItems that is in another thread. They are separate from objects.