Key topic: Finding ObjectsSo you can't click that rock? Can't open that door? Can't climb up that ladder? Want to interact with anything that has a dropdown menu when you right click?
Well read on and you can.Everything in Runescape has their own ID. This is an object ID, and when you find the ID you can do a lot with it. The cool thing is, each 'state' has it's own ID… making your life easier.
For example, a rock with some iron in it may have an ID of 3849. The rock next to it with iron will probably have an ID like 3857. Each object has it's own ID, so you can't just take one ID from a rock in fally and consider it the same for everywhere.
But this is great, because with object finding you can target one specific thing only. What's even better, is different states have different ID's, so you won't need failsafes as much (but please, DO make them).
Example:
Door open ID: 3434
Door shut ID: 3949
//Pseduo code
if (Door.ID = 3434) then OpenDoor;
if (Door.ID = 3949) then WalkRightOnIn;
Isn't that cool? If its closed, open it, if it returns false (I just added some code in to see if its open), then walk on in ;)
This is great when irritating things stand in your way. Watch now as your bot opens the door, leaving all opponents with their mouth on the floor. They will never stop you now.
//Pseduo code
if (Rock.ID = 4445) then Mine; //4445 is a rock with ore
if (Rock.ID = 43894) then FindNewRock; //43894 is rock 4445 but mined
Well that's cool, we don't even need failsafes for rocks now technically. If it doesn't find an array of ID's that you get on your own (I'll show you how to later) then we know it's been mined.
What about that irritating ladder?
Well I don't need to make code because you get the point.
Object summary:Objects are made of 3 things. Lets look at this piece of code:
function NewObject(ID, objType: integer; T: TTile): TRSObject;
begin
Result.ID := ID;
Result.objType := objType;
Result.Tile := T;
end;
So when you define some new object, it has to have
1) an ID (some number UNIQUE for each item in runescape)
2) objType (object type), there are only 4 and it's easy to use, I'll explains soon
3) A tile (quite useful for us, just do a TileTo
MS [
Main
Screen] and we can pretty much find that object with no problem)
Detail time:
- ID
Each item has it's own unique ID. If you want to debug it, open TriBot or RSBot and then turn on the objects debug. This will show you all the ID's in runescape. This way you don't have to use my (or your own made) debugging script for walking around finding them.
[*]Object Type
There are four object types:
- OBJECT_TYPE_INTERACTABLE = 0;
This is the one you're going to use all the time. Interactable objects are things like trees, doors, rocks…etc.
If it is an object, I'd say 97% of the time you will be using this. If it's part of a wall then you know it's going to be the next one…etc
- OBJECT_TYPE_WALLOBJECT = 1;
I never have used this [yet], this is probably wall switches. If I ever tackle randoms, this will save our asses in the abyssal random.
- OBJECT_TYPE_WALLDECOR = 2;
I guess a good failsafe? If candle in room during quest and you see candle, then you = on the right track
- OBJECT_TYPE_FLOORDECOR = 3;
Same as above
[*]Tile
Self explanatory, you know this now ;) (if not go up a post)
So how do I make code? What is this "Object_type_interactable"? I'm confused at how to use this…Alright go find your rock, and lets do some code.
Key: When we use functions, they return them as a TRSObject (Type RuneScape Object). Don't worry, they're easy to use. Remember types? Like TPoint.x, TPoint.y, Tile.x…etc? Its the EXACT same, except it is like this:
TRSObjectVariableName.ID = some integer;
TRSObjectVariableName.Tile = stored Tile(x,y);
TRSObjectVariableName.ObjType = numbers 0, 1, 2 or 3
Now a lot of you right now are going "what the hell!? why is TRSObjectVariableName.ObjType = numbers 0, 1, 2 or 3?? How do I know which number to use!?"
Ask yourself which one of these four is it?
- OBJECT_TYPE_INTERACTABLE = 0;
- OBJECT_TYPE_WALLOBJECT = 1;
- OBJECT_TYPE_WALLDECOR = 2;
- OBJECT_TYPE_FLOORDECOR = 3;
So you found out your trying to do a rock? Well when you get the object, it's going to return:
TRSObjectVariableName.ObjType = 0;
A rock is not a wall object, and doesn't decorate the floor. We can interact with it (like mine) so it's clearly type 0.
But that doesn't really help you too much here, these constants become useful when you're
finding an object ;)
So lets get to some code now, I want to find an object!I want you to do this with the following code:
** If you just want to analyze the code without testing it, I will do that so you don't need to actually log in:
program ObjectFinder;
{$DEFINE SMART}
{$i srl\srl.scar}
{$i reflection\reflection.simba}
const
{---SMART Setup Constants---}
WORLD = 32;
MEMBERS = false;
SIGNED = true;
{---------------------------}
var
NPCs: TNPCArray;
i, ii, x, y: Integer;
FishTP : TPoint;
Me: TMe;
Procedure DeclarePlayers;
Begin
HowManyPlayers := 1;
NumberOfPlayers(HowManyPlayers);
CurrentPlayer := 0;
With Players[0] Do
Begin
Name := '';
Pass := '';
Nick := '';
Active := True;
Integers[0] := 0;
Pin := '';
End;
End;
// Get objects near you
//function GetInteractObjIDAdjacent (Tile : TTile) : Integer;
procedure FindObjNear;
var myObj : TRSObject;
myTile, newTile : TTile;
i : Integer;
begin
if not LoggedIn then exit;
myTile := GetMyPos;
writeln ('[--Objects--]');
newTile := Tile((myTile.x-1),myTile.y);
MyObj := GetObjectAt(newTile, OBJECT_TYPE_INTERACTABLE);
if MyObj.ID > 0 then
begin
writeln ('(W)');
writeln ('ID: '+inttostr(MyObj.ID)+', Tile('+inttostr(MyObj.Tile.x)+','+inttostr(MyObj.Tile.y)+')');
end;
newTile := Tile((myTile.x),myTile.y-1);
MyObj := GetObjectAt(newTile, OBJECT_TYPE_INTERACTABLE);
if MyObj.ID > 0 then
begin
writeln ('(S)');
writeln ('ID: '+inttostr(MyObj.ID)+', Tile('+inttostr(MyObj.Tile.x)+','+inttostr(MyObj.Tile.y)+')');
end;
newTile := Tile((myTile.x+1),myTile.y);
MyObj := GetObjectAt(newTile, OBJECT_TYPE_INTERACTABLE);
if MyObj.ID > 0 then
begin
writeln ('(E)');
writeln ('ID: '+inttostr(MyObj.ID)+', Tile('+inttostr(MyObj.Tile.x)+','+inttostr(MyObj.Tile.y)+')');
end;
newTile := Tile((myTile.x),myTile.y+1);
MyObj := GetObjectAt(newTile, OBJECT_TYPE_INTERACTABLE);
if MyObj.ID > 0 then
begin
writeln ('(N)');
writeln ('ID: '+inttostr(MyObj.ID)+', Tile('+inttostr(MyObj.Tile.x)+','+inttostr(MyObj.Tile.y)+')');
end;
end;
procedure MainLoop;
begin
if not LoggedIn then exit;
SetAngle (true);
MakeCompass ('n');
SetRun (true);
wait (random(500));
repeat
FindObjNear;
wait (1000);
cleardebug;
until (false)
end;
begin
Smart_Members := MEMBERS;
Smart_Server := WORLD;
Smart_Signed := SIGNED;
SetupSRL;
DeclarePlayers;
LoginPlayer;
cleardebug;
MainLoop;
end.
Okay with this, go stand next to your favorite rock, or tree.
THIS IS ASSUMING YOU DON'T WANT TO USE RSBOT/TRIBOT/Any bot TO EASILY GET YOU THE ID.
Yes I made this just for you :)
Only works on the tiles N/S/E/West of your character though, no NE/SE/SW/NW… sorry…
The code declares a TRSObject;, then searches N/S/E/W of you, and debugs what they are. Explore it a bit and get a feel ;)
Got any quick code for me if I know the tile?
var myObject : TRSObject;
myObject := GetInteractableAt (YOUR TILE HERE);
This will get whatever object is at the tile you input.
Okay I know how to get it, but how do I move my mouse to it? That's the most important part!Be inventive, remember, we know the tile (it has to be on a tile, and we have to get it from a tile…), so call something like this:
TP := TileToMS (TILE_HERE, 1); // Height of 1, if it doesn't work, change the height or check your tile
// Now we have turned the tile into a TPoint on the mainscreen
Mouse (TP.x, TP.y, 2, 2, false);
if R_ChooseOption ('option here') then writeln ('Function carried out');
So there you go.
Now of course we have cool procedures like this:
{*******************************************************************************
function GetObjectByID(ID: Integer; objType, MaxDist: Integer): TRSObject;
By: Drags111
Description: Returns the nearest object with the ID. Sorted from closest
to your character to farthest.
MaxDist: This is the maximum distance from your player you wish to
search. The smaller the number, the faster the search is
completed. The maximum is 52.
*******************************************************************************}
If you know your ID (I gave you 2-3 ways to find it), and know your ObjType, you're set. I don't know what MaxDist is… maybe it's tiles? I doubt it's pixels. Experiment with this.
So lets say you want to find Door ID #4599, but it could be anywhere on the map. Do this:
1) What is my ID?
4599
2) What type is it?
interactable
So I'm going to use the
constant value OBJECT_TYPE_INTERACTABLE so when other people read my code they know its interactable
3) Lets just assume 52 for the hell of it
MyObject := GetObjectByID (4599, OBJECT_TYPE_INTERACTABLE, 52);
So why do I use that constant instead of the number 1? Because it's readable code. Always use this unless you have a good reason otherwise.
A good reason could be you putting a variable in there, and debugging from 0 –> 3.
These are the basics, if you're still lost, post here. Check out the Objects.simba file and learn!
Remember:
1) Your object is always defined with a XXX.Tile, XXX.ID, XXX.ObjType
2) You need to know where the object is usually (unless you use a specialized function like above) before you can do stuff with it.
ChatChat has everything to do with that box at the bottom. This is mainly for player to player chat, if you want to do NPC to player chat you need to go to the interfaces section, but it wouldn't hurt to read here since some functions are covered.
If you're interested in an autotalker, this is the section for you. All the text players say you can extract and run through your own response machine if you're good enough. This can also get the difference between private messages and in game chat. Cool!From now on in, it's going to be a bit tighter since I rarely use these (until the next post). I'll tell them as it is, though I'm sure if you read everything up till now and have a good SRL grasp, these won't be a problem.
This is more of a show and tell since these are really self-explanatory if you look at the code
function GetChatMessages(ChatType: string; Visible, NoName: Boolean): TStringArray;
{
Valid ChatType Params:
'chat', 'normal': Normal chat
'pm', 'private': Private messages
'trade': Trade chat
'black', 'message': Black chat messages
'all': All of the above
}
Based on the parameters, you'll see that you just call something like this:
TSA = TStringArray okay?
TSA := GetChatMessages('chat', true, true);
I'm telling the function
a) 'chat' = get the chat box messages only
b) 'Visible = true' I assume this means if it's in the chat box?
c) 'NoName = true' probably don't attach a name to it
Then you invoke your TStringArray reading tools to find out what you want.
NPC chat:
function FindNPCText(text: string): boolean;
By: Drags111
Description: Searches through the known talking interfaces to search for the
inputed text.
This returns true if you find text from that NPC. Quite useful, and so is this:
{*******************************************************************************
function R_ClickToContinue: boolean;
By: Drags111
Description: Does as the name suggests. Clicks the 'click here to continue' crap
*******************************************************************************}
I wish I found this earlier, I kept coding my own "click continue" and it was starting to piss me off.
Well there's more in the chat file, go have a look :)
Lastly before we leave this topic, if you start finding <p=34394> or some number before the text, that's probably java color code. If you want, there is a way to get rid of it through string manipulation. I forget how though… there's a few tricks. I made a post (and so did Bad Boy) in the SRL public help section, if you want… search it with advanced search at the top.
EquipmentIf you want to find your ammo amount or see if you're wearing armor, this is the section for you. I personally didn't find much use of this section since most players normally equip their bots with the items and then run a specialized script… but who knows, maybe you're going to make that all in one script and will need to check if the armor is on, or how much ammo you need.As I said, unfortunately this section isn't nearly as useful as tiles or finding NPC's are. Regardless, awesome failsafes are here.
What if you run out of arrows?
Lets mess around with some basic functions in equipment.simba:
// Use this logic flow
if IsEquippedName('Bronze arrows') and R_GetAmmoCount > 0 then ContinueFiring;
Make sure your ranger not only has a type of arrow, but can fire it.
Remember, you can make a TStringArray and check all types or arrows:
var StuffToFire : TStringArray;
function DoWeHaveAmmo : Boolean;
var i : Integer;
begin
result := false;
StuffToFire := ['Bronze arrows','Iron arrows','Steel arrows','Mithril arrows']; // No one is going to use addy/rune arrows for training, will they?
for i:=0 to high(StuffToFire) do
begin
if IsEquippedName (StuffToFire[i]) then result := true;
end;
if result then writeln ('We have arrows!') else writeln ('We do not have arrows! Oh no!');
end;
Of course though, we always have someone one step ahead of me:
{*******************************************************************************
function IsEquippedNameEx(Names: TStringArray): boolean;
By: Drags111
Description: Returns true if there is an item equipped with one of the Names.
*******************************************************************************}
What about this equipment items set? How can I debug my own namesWell lets look at some definitions…
By the way, this area I'm really weak in. Sorry, I'll do the best I can.
function GetEquipment: TEquipmentSet;
So this function appears tor return a TEquipmentSet, so we'd have to call:
var MyEqSet : TEquipmentSet;
Call that somewhere. I assume you just run it like this:
var MyEqSet : TEquipmentSet;
MyEqSet := GetEquipment; // Woot, another one line of code
I assume that's enough to be good to go. I haven't tried this yet :(
Now once we have it, the file seems to define it as the following types:
Result.Items[i].ID := SmartGetFieldInt(child, hook_interface_GetID);
Result.Items[i].Name := TrimItemName(GetJavaString(textbytes, 255));
Result.Items[i].Count := SmartGetFieldInt(child, hook_interface_GetStack);
Result.Items[i].isAmmo := (Result.Items[i].Count > 1);
Therefore the items probably have something like this to be called:
var MyEqSet : TEquipmentSet;
MyEqSet := GetEquipment;
writeln (ToStr(MyEqSet.Name)); // I haven't run this, experiment with it :)
Unfortunately this area is not to well documented, and I do not see anywhere in the file of the chart that Drags111 mentioned, nor do I see any other function that uses it.
Looks like your innovation will grow if you can learn this. Practice, this will be great for exercising type knowledge! Sorry I can be of no further help.
GametabThis is for useful things like run energy, stat experience, if you're running or not (and how much energy to rest to), getting skill levels…etc.
If you understand interfaces (the next big topic I will be covering), then this section is not totally necessary. The codes I will show you are more or less specific developed functions rather than something standalone like tiles.Well if you thought equipment was a letdown, prepare to have your letdown drop to an even lower level.
Just look at the function names and they honestly tell you exactly what they do.
1) procedure R_Rest(MaxEnergy: integer);
2) function R_IsRunning: boolean;
3) function R_IsResting: boolean;
4) function R_GetMMLevels(Which: string): Integer;
This is cool because you can use it like this:
{
'hitpoints', 'hp': Result := StrToInt(GetInterfaceText(748, 8));
'prayer', 'pp' : Result := StrToInt(GetInterfaceText(749, 4));
'run', 'energy' : Result := StrToInt(GetInterfaceText(750, 5)); }
if R_GetMMLevels('hitpoints') < 100 then RunFromFight;
Great for a fighter script!
Lastly, the best part which I have no clue how to use are skill harvesting stats:
{*******************************************************************************
function R_GetSkillLevel(skill: variant): Integer;
By: Nava2
Description: Gets the Level stored at skill. Skill can be the string or const.
The const is significantly faster.
*******************************************************************************}
I don't quite understand the code or how to use this. Maybe try entering "Fishing" as the skill, or try the number 10. That seems to be the fishing number from previous scripts.
This can be useful for proggys :)
Alright, time to get onto some serious topics again that are important. Check out the next post! Hopefully I'll have interfaces done soon!