# Thread: OpenGL - A Beginner's Scripting Tutorial

1. ## OpenGL - A Beginner's Scripting Tutorial

by @Clarity and @Obscurity

Last updated on November 30th, 2015

GLX v3.7 | ogLib v1.0a | ogLib Development | Beginner's Tutorial | ID Highlight Tool

What is OpenGL Scripting?

Like injection, reflection, and color, OpenGL scripting is yet another alternative method of creating RS3 macro programs. After reading this tutorial, you will be able to create powerful and flawless scripts, capable of complex tasks usually discarded as too difficult for color only. Pending an ogLib update to support SRL-6, You will also learn how to incorporate both color and OpenGL methods into your scripts, combining the two scripting approaches to get the best of both worlds.

Without going into unnecessary detail, OpenGL allows us to examine the information being sent to your computer's graphics card, giving information on models, textures, chars, and more. We can script in resizable mode, easily interact with environments regardless of camera angle, and even get perfectly accurate player minimap and 3D world locations. It is not without its flaws, however, when used correctly and cleverly, OpenGL can accomplish some awesome things!

It is highly recommended to first familiarize yourself with SRL-6 scripting before learning OpenGL, as the combined information will give you many more creative options. This tutorial assumes basic understanding of Lape and beginner SRL-6 scripting concepts. If you have any questions, feel free to post.

Part 1 :: Setting up OpenGL

OpenGL scripting and program execution requires some modified dynamic link libraries (.DLLs) for RS3 and Simba to use. Additionally, we use a different set of includes (ogLib) to develop OpenGL scripts. This library currently supports RS3 - EoC only.

Automatic Installation
Download Attachment 27083 and place it into Simba\Scripts\. Open and run the script.

Manual Installation
Download the OpenGL32.dll and GLX.dll plugins, developed by @Brandon, here: GLX v3.7
Download the ogLib includes, a library designed and developed by @Clarity and @Obscurity, here: ogLib v1.0a

Note that ogLib is an ongoing project, and contributions are welcomed! Some elements have yet to be added, such as in-depth mouse movement and SRL-6 compatibility. We are tackling the priority elements first, such as interfaces, mapping, and combat.

Once you have extracted the contents, copy OpenGL32.dll and GLX.dll into your C:\...\Simba\Plugins\ directory. Next, copy the ogLib\ folder into your C:\...\Simba\Includes\ directory. It's that simple!

Part 2 :: OpenGL Data Types

Before we go any further, you've got to know the basics of OpenGL and the various data types. Unique to OpenGL, these types are:

• glChar / glCharArray - {TEXTUREID = 0, COLOUR = 0, X = 0, Y = 0, LETTER = , SHADOW = False, TRANSLATE = [0, 0, 0], BOUNDS = {X1 = 0, Y1 = 0, X2 = 0, Y2 = 0}}
Description: Each and every character on screen, be it a letter, number, or special character, may be viewed as a glChar. The glChar record contains vital information regarding each character; Things like color, font, and location on screen.
Record:
• TextureID:
Think of a character's texture ID as its font. Much like Comic Sans MS, for example, a right click menu typically uses the fonts 17 and 91.
• Colour:
This property simply contains the colour of the character. The orange colour from hovering over a chat option, for example, is 37083.
• X / Y:
The position at which a character can be found on screen can be viewed in its X and Y properties. This coordinate is to the center-point of the character.
• Letter:
This is likely the most important property of a glChar. Letter contains the character which was found. This will always be a single character and could consist of any alphanumeric or special character.
The shadow property, which is very rarely true, is quite simply whether or not the text contains a shadow. Although some text appears to have a shadow, it may not. Take the following image for example:

Surely each one of those characters has a black shadow? This is incorrect. While they appear to have shadows, it's simply a 200 drawn ontop of a slightly offset, black 200. Therefore, the total number of characters in the image is 6.
• Bounds:
The bounds of a glChar simply contain the coordinates of each corner. Calculating the center-point of them would result in the glChar's X / Y, as mentioned earlier.

• glModel / glModelArray - {ID = 0, TID = 0, X = 0, Y = 0}
Description: For the most part, it's fairly safe to assume that any 3D object or any item that appears in the 3D plane of RuneScape is a glModel; From players, to monsters, to target reticles, to the animated flag shown on screen while waiting for a Pest Control game to start. They're all models.
Record:
• ID:
Each model in RuneScape has an ID. These typically tend to remain constant. For example, it's fairly safe to assume that if you check and see that a Rorarius has an ID of 3227299924, it'll always have that ID.
• TID:
A model's triangle count. Essentially, it should "technically" be "almost" as accurate as the ID.
• X / Y:
The position at which a model can be found on screen can be viewed in its X and Y properties. Keep in mind that if drawn on the 3D plane, the model's X and Y will be located at the base of the model. Take the following image for example:

In this case, the model's X and Y is positioned at the base of the player near the feet.

• glTexture / glTextureArray - {ID = 0, ColourID = 0, FullColourID = 0, X = 0, Y = 0, BOUNDS = {X1 = 0, Y1 = 0, X2 = 0, Y2 = 0}}
Description: Almost everything that seems 2D in RuneScape can be retrieved as a glTexture. These are most often used for buttons, icons, interfaces, inventory items, equipped items, abilities, and anything in-between.
Record:
• ID:
glTextures, like glModels, always have an ID. However, this ID is rarely unique, making relying on solely this property for locating items and objects unreliable. For example, different potion flasks, summoning pouches, runes, tend to share a texture ID. Take the following GIF for example:

Here we can see that a Super restore (6) shares a texture ID with an Overload flask (1).
• ColourID:
As mentioned before, textures can share a TextureID. To distinguish between these textures, we often use the ColourID. For now, lets just call it a summary of all colours within the texture.
• X / Y:
The position at which a texture can be found on screen can be viewed in its X and Y properties. This is coordinate is the center-point of the texture.
• Bounds:
The bounds of a glTexture simply contain the coordinates of each corner. Calculating the center-point of them would result in the glTexture's X / Y, as mentioned earlier.

Part 3 :: Spawning and Saving SMART with ogLib

Before we do anything requiring OpenGL, you need to spawn a SMART client with the OpenGL plugin. To do this, you have to setup ogLib using ogl.setup(). See the sample Script 3.1 below:
Simba Code:
program ogLib;{$i ogLib\lib\core\core.simba}begin ogl.setup([800, 600], [0, 0, 800, 600]);end. ogl.setup() requires two sets of parameters. The first set, consisting of two integers, sets the dimensions of the client. The second set, consisting of four integers, sets the bounding coordinates of your viewport. Client Size vs. Viewport Size The client size is the size of the entire RuneScape game within the SMART client. This is commonly 800x600. The viewport is the size of the 3D world within RuneScape, usually referred to in SRL-6 terms as the mainscreen. For accurate model positioning to work, you need to ensure your viewport is correctly set with ogLib. If you do not do this, debugged model IDs will be vastly offset from their actual positions. If using resizable mode without any special alterations, your viewport will match the client size. The following images demonstrate this concept: Understanding Viewport Sizes By default, ogLib assumes 800x600 client dimensions, and a viewport of the same size (resizable mode). These default values can be more easily called by simply writing ogl.setup() without any parameters. The default values can be changed using ogl.setDefaultClientHeight() and ogl.setDefaultClientWidth(). When ogLib is set up, it loads the default cache time, color tolerance, controls - auto-retaliate, familiar action, quick heal, quick prayer, and size, if needed. These can be changed with ogl.setDefaultCacheTime(), ogl.setDefaultControlAutoRetaliate(), et cetera. To save all of the current SMART's parameters, mentioned above, as defaults, use ogl.save(). Part 4 :: Retrieving Chars, Models, and Textures What makes OpenGL and ogLib so powerful is their ability to instantly locate chars, models, and textures on the screen. Or, equally important, it can be used to tell you if something is not present on the screen. To do this, we have the vital methods ogl.getChars(), ogl.getModels(), and ogl.getTextures(). Each of the above methods can be used to find their respective types on the screen. See the sample Script 4.1 below. Simba Code: program ogLib;{$i ogLib\lib\core\core.simba}procedure mainLoop;var  textureArray: glTextureArray;begin  textureArray := ogl.getTextures(1275);  writeln(textureArray);end;begin  ogl.setup([800, 600], [0, 0, 800, 600]);  repeat    mainLoop;  until false;end.

In the example above, 1275 is the texture ID of the red flag that appears whenever a player is moving or beginning an interaction with a game object. You can also get every char, model, or texture currently on the screen by not using any limiting search parameter. A returned texture array might look something like this:

Code:
[{ID = 33556, COLOURID = 2432529, FULLCOLOURID = 2630421, X = 912, Y = 528, BOUNDS = {X1 = 0, Y1 = 0, X2 = 1824, Y2 = 1057}},
{ID = 57120, COLOURID = 2894355, FULLCOLOURID = 2631441, X = 912, Y = 457, BOUNDS = {X1 = 884, Y1 = 455, X2 = 940, Y2 = 460}}]
To visually debug texture and model IDs, you can use the ID Highlighting Tool. Or, you can use ogLib's debug functions, shown in the sample Script 4.2 below:
Simba Code:
program ogLib;{$i ogLib\lib\core\core.simba}begin ogl.setup([800, 600], [0, 0, 800, 600]); ogl.setDebugMode('none'); ogl.setDebugMode('texture'); ogl.setDebugMode('model'); ogl.setDebugMode('font'); ogl.setDebugMode('nones'); ogl.setDebugMode('textures'); ogl.setDebugMode('models'); ogl.setDebugMode('fonts'); ogl.setDebugMode('N'); ogl.setDebugMode('T'); ogl.setDebugMode('M'); ogl.setDebugMode('F'); ogl.setDebugMode(0); ogl.setDebugMode(1); ogl.setDebugMode(2); ogl.setDebugMode(3);end. ogl.setDebugMode() is very flexible in what it accepts: if you want to debug onscreen models, you can use ogl.setDebugMode('models'), ogl.setDebugMode('M'), or ogl.setDebugMode(2), whichever you find more convenient! Doing so will cause these IDs to appear on SMART's debug: Depending on your screen resolution, the green ID numbers may appear differently. Use ingame zooming and camera movement to see the numbers more clearly if needed. If too many models are stacked on top of each other, you will need to use text debugging methods such as writeln(ogl.getModels()). Part 5 :: Basic Scripting with OpenGL To start off with, scripting with OpenGL can be much different then using colour. Before continuing, we highly recommend reading @Kevin's thread on Function Pointers, as we'll be touching on it a lot throughout this tutorial. His methods are fantastic when used with OpenGL. So, let's make our first very basic auto-fighter. For learning's sake, head to the Troll Brutes in Burthorpe. • Step 1 - Starting the OpenGL plugin To start using the OpenGL plugin, we need to create a basic script, beginning with our basic setup call mentioned earlier. Script 5.1 Simba Code: program ogLib;{$i ogLib\lib\core\core.simba}begin  ogl.setup([800, 600], [0, 0, 800, 600]);end.
• Step 2 - Setting graphics settings
To use the OpenGL plugin, our client must be also be using OpenGL. You'll need to make your graphics settings match the following image:
Figure 5.1
• Step 3 - Debugging models
Now that we've correctly loaded the client, we need to debug some models in order to locate the Troll brutes.
Script 5.2
Simba Code:
program ogLib;{$i ogLib\lib\core\core.simba}begin ogl.setup([800, 600], [0, 0, 800, 600]); ogl.setDebugMode('models');end. Using this, we can then locate the correct model IDs. These have been highlighted in the image below: Figure 5.2 • Step 4 - Locating models Now it's time to find the trolls using ogl.getModels() and their model ID of 403123861. Script 5.3 Simba Code: program ogLib;{$i ogLib\lib\core\core.simba}procedure mainLoop;var  trollBrutes: glModelArray;begin  trollBrutes := ogl.getModels(403123861);  clearDebug;  if trollBrutes.isEmpty() then    writeln('No troll brutes were found.')  else  begin    writeln(trollBrutes.indexes(),' troll brutes were found:');    writeln(trollBrutes);  end;  wait(150);end;begin  ogl.setup([800, 600], [0, 0, 800, 600]);  ogl.setDebugMode('models');  repeat    mainLoop;  until false;end.

This script should print something along the lines of:
Figure 5.3
Code:
8 Troll brutes found:
[{ID = 403123861, TID = 706, X = 658, Y = 670}, {ID = 403123861, TID = 706, X = -20, Y = 414}, {ID = 403123861, TID = 706, X = 352, Y = 348}, {ID = 403123861, TID = 706, X = 629, Y = 364}, {ID = 403123861, TID = 706, X = 367, Y = 207}, {ID = 403123861, TID = 706, X = 261, Y = 184}, {ID = 403123861, TID = 706, X = 301, Y = 151}, {ID = 403123861, TID = 706, X = 278, Y = 133}]
• Step 5 - Interacting with models
Now that we know how to locate the trolls, let's start attacking the closest to the center.
Script 5.4
Simba Code:
program ogLib;{$i ogLib\lib\core\core.simba}procedure mainLoop;var trollBrutes: glModelArray;begin trollBrutes := ogl.getModels(403123861); clearDebug; if trollBrutes.isEmpty() then writeln('No troll brutes were found.') else mouse.click(clientCenter.closest(trollBrutes)[0].randomizePointEllipse(15)); wait(random(1000, 2000));end;begin ogl.setup([800, 600], [0, 0, 800, 600]); clientCenter := ogl.getClientMidPoint(); repeat mainLoop; until false;end. • Step 6 - Debugging advanced models While Script 5.4 attacks the Troll brutes, it doesn't stop once in combat. To fix this, we need to also detect the target reticule models. There are two indicating that we are in combat: • Red: Target. • Red and Yellow: Retaliating target. • Yellow: Aggressive monster. The image below shows that visually debugging models isn't always easy: Figure 5.4 Therefore, we need to resort to the debug window and use ogl.getModels() to its full potential - retrieving all models on screen. As you can see from Figure 2.3, there can be thousands of models on screen, so attempt to zoom in to narrow the search as much as possible and edit the script. Script 5.5 Simba Code: program ogLib;{$i ogLib\lib\core\core.simba}var  clientCenter: TPoint;procedure mainLoop;var  allModels, trollBrutes: glModelArray;begin  allModels := ogl.getModels();  clearDebug;  writeln(allModels);  wait(250);  {  trollBrutes := ogl.getModels(403123861);  if trollBrutes.isEmpty() then    writeln('No Troll brutes found.')  else    mouse.click(clientCenter.closest(trollBrutes)[0].randomizePointEllipse(15));  wait(random(1000, 2000));  }end;begin  ogl.setup([800, 600], [0, 0, 800, 600]);  clientCenter := ogl.getClientMidPoint();  repeat    mainLoop;  until false;end.

Figure 5.5

If done correctly, your debug window should contain something similar to the following figure. Copy the contents into Notepad or any text editor.
Figure 5.5
Code:
[{ID = 487932993, TID = 107, X = -197, Y = 669}, {ID = 208265157, TID = 84, X = -28, Y = 591}, {ID = 528332493, TID = 195, X = 780, Y = 695}, {ID = 2410841246, TID = 121, X = 539, Y = 603}, {ID = 3258171939, TID = 53, X = 249, Y = 597}, {ID = 3587280739, TID = 248, X = 798, Y = 462}, {ID = 4105139511, TID = 59, X = 265, Y = 452}, {ID = 545440014, TID = 60, X = 277, Y = 326}, {ID = 403123861, TID = 706, X = -87, Y = 141}, {ID = 3097012422, TID = 135, X = 239, Y = 173}, {ID = 545440014, TID = 45, X = 93, Y = 135}, {ID = 4105139511, TID = 59, X = -1, Y = 143}, {ID = 2477500689, TID = 49, X = -68, Y = 66}, {ID = 427589626, TID = 80, X = 687, Y = 90}, {ID = 1580736461, TID = 57, X = 4, Y = -1}, {ID = 4105139511, TID = 29, X = 853, Y = 20}, {ID = 2297058922, TID = 62, X = 323, Y = -58}, {ID = 528332493, TID = 130, X = 450, Y = -72}, {ID = 1279548371, TID = 49, X = 827, Y = -36}, {ID = 0, TID = 0, X = 0, Y = 0}, {ID = 0, TID = 0, X = 2821, Y = -1545}, {ID = 403123861, TID = 706, X = 520, Y = 336}, {ID = 1452224228, TID = 21, X = 520, Y = 336}, {ID = 1212609603, TID = 1444, X = 400, Y = 331}, {ID = 2209194569, TID = 18, X = 45, Y = -122}, {ID = 0, TID = 0, X = -2278, Y = -5033}]

We know the model ID of the troll and it appears to share the exact coordinate of the reticule, so first find the glModel entry belonging to the troll. In this case, you'll see that its coordinates are (520, 336). You can quite literally copy the "X = 520, Y = 336" and search the record for an exact match, belonging to the ID 1452224228.
• Step 7 - Extracting models
Now that we have the ID for the target reticule, we need to detect when it exists and only attack if it does not.
Script 5.6
Simba Code:
program ogLib;{$i ogLib\lib\core\core.simba}var allModels, targetReticules, trollBrutes: glModelArray; canAttack: tCountDown; clientCenter: TPoint;procedure mainLoop;begin allModels := ogl.getModels([1452224228,403123861]); targetReticules := allModels.getModels(1452224228); trollBrutes := allModels.getModels(403123861); if trollBrutes.isEmpty() then writeln('No Troll brutes found.') else if targetReticules.isEmpty() then mouse.click(clientCenter.closest(trollBrutes)[0].randomizePointEllipse(15));end;begin ogl.setup([800, 600], [0, 0, 800, 600]); clientCenter := ogl.getClientMidPoint(); repeat mainLoop; until false;end. • Step 8 - Delaying reactions The script will now correctly only attack if you are currently not in combat. However, it still tends to rapidly click until the reticule appears. So lets split the attacking into a reaction procedure and only call it if a given time has passed. To do this, we're going to use a procedure pointer and a tCountDown. A countDown is a custom type in ogLib, similar to the countDown in SRL-6, keeping track of time for various activities. This allows the script to continue functioning without static waits like wait(random(5000)); Script 5.7 Simba Code: program ogLib;{$i ogLib\lib\core\core.simba}var  allModels, targetReticules, trollBrutes: glModelArray;  canAttack: tCountDown;  clientCenter: TPoint;procedure attackTrollBrute;begin  mouse.click(clientCenter.closest(trollBrutes)[0].randomizePointEllipse(15));  canAttack.setTime(random(250, 1500));end;procedure doNothing;begin  writeln('We did nothing!');end;procedure mainLoop;var  reaction: procedure() = @doNothing;begin  allModels := ogl.getModels([1452224228, 403123861]);  targetReticules := allModels.getModels(1452224228);  trollBrutes := allModels.getModels(403123861);  if trollBrutes.isEmpty() then    writeln('No Troll brutes found.')  else if targetReticules.isEmpty() and canAttack.isFinished() then    reaction := @attackTrollBrute;  reaction();end;begin  ogl.setup([800, 600], [0, 0, 800, 600]);  clientCenter := ogl.getClientMidPoint();  repeat    mainLoop;  until false;end.
• Step 9 - Using multiple reactions
Script 5.7 works very well. However, what happens when there are no troll brutes visible, or the closest one happens to be behind an interface such as the inventory? We need to find more by rotating the compass and changing the camera angle. For this, we need to add a new reaction.
Script 5.8
Simba Code:
program ogLib;{$i ogLib\lib\core\core.simba}var allModels, targetReticules, trollBrutes: glModelArray; canAttack: tCountDown; clientCenter: TPoint;procedure attackTrollBrute;begin mouse.click(clientCenter.closest(trollBrutes)[0].randomizePointEllipse(15)); canAttack.setTime(random(250, 1500));end;procedure doNothing;begin writeln('We did nothing!');end;procedure rotateCamera;begin minimap.setDegrees(random(45, 90)); end;procedure mainLoop;var reaction: procedure() = @doNothing;begin allModels := ogl.getModels([1452224228,403123861]); targetReticules := allModels.getModels(1452224228); trollBrutes := allModels.getModels(403123861); if trollBrutes.isEmpty() or clientCenter.closest(trollBrutes)[0].isVisible() then reaction := @rotateCamera else if targetReticules.isEmpty() and canAttack.isFinished() then reaction := @attackTrollBrute; reaction();end;begin ogl.setup([800, 600], [0, 0, 800, 600]); clientCenter := ogl.getClientMidPoint(); repeat mainLoop; until false;end. • Step 10 - Debugging textures Now that our bot fights and correctly searches for trolls, we need to start picking up and interacting with drops. For now, we'll pick up and bury bones. To do so, you'd get the model ID of bones in the same way you got the Troll brute ID. To save some time, their model ID is 2406257549. It's time to start debugging some textures. Tip: When debugging inventory items, it's much easier to temporarily switch to Legacy mode. Script 5.9 Simba Code: program ogLib;{$i ogLib\lib\core\core.simba}var  allModels, targetReticules, trollBrutes: glModelArray;  canAttack: tCountDown;  clientCenter: TPoint;procedure attackTrollBrute;begin  mouse.click(clientCenter.closest(trollBrutes)[0].randomizePointEllipse(15));  canAttack.setTime(random(250, 1500));end;procedure doNothing;begin  writeln('We did nothing!');end;procedure rotateCamera;begin  minimap.setDegrees(random(45, 90)); end;procedure mainLoop;var  reaction: procedure() = @doNothing;begin  allModels := ogl.getModels([1452224228,403123861]);  targetReticules := allModels.getModels(1452224228);  trollBrutes := allModels.getModels(403123861);  if trollBrutes.isEmpty() or not clientCenter.closest(trollBrutes)[0].isVisible() then    reaction := @rotateCamera  else if targetReticules.isEmpty() and canAttack.isFinished() then    reaction := @attackTrollBrute;  reaction();end;begin  ogl.setup(800, 600);  clientCenter := ogl.getClientMidPoint();  ogl.setDebugMode('textures');  {  repeat    mainLoop;  until false;  }end.

Script 5.9 will change your debug mode from models to textures, changing our client to look like the following image:
Figure 2.6

From this, we can see that Bones, while in the inventory, have a texture ID of 52275.
• Step 11 - Interacting with textures
Now that we've got the texture ID of Bones, let's have it take and bury bones while fighting Troll brutes.
Script 5.10
Simba Code:
program ogLib;{$i ogLib\lib\core\core.simba}var allModels, bonesModels, targetReticules, trollBrutes: glModelArray; bonesTextures: glTextureArray; canAttackTrollBrute, canBuryBones, canTakeBones: tCountDown; clientCenter: TPoint;procedure attackTrollBrute;var clickPoint: TPoint;begin clickPoint := clientCenter.closest(trollBrutes)[0].randomizePointEllipse(15); if random(2) then mouse.click(clickPoint) else mouse.rightClickOption(clickPoint, 'Attack'); canAttackTrollBrute.setTime(random(1000, 5000)); canTakeBones.setTime(random(1000, 5000));end;procedure buryBones;var clickPoint: TPoint;begin clickPoint := mouse.getPoint().closest(bonesTextures)[0].randomizePointEllipse(36); if random(2) then mouse.click(clickPoint) else mouse.rightClickOption(clickPoint, 'Bury'); canBuryBones.setTime(random(250, 1500));end;procedure doNothing;begin writeln('We did nothing!');end;procedure rotateCamera;begin minimap.setDegrees(random(45, 90));end;procedure takeBones;var clickPoint: TPoint;begin clickPoint := clientCenter.closest(bonesModels)[0].randomizePointEllipse(15); mouse.rightClickOption(clickPoint, 'Take Bones'); canTakeBones.setTime(random(1000, 5000)); canAttackTrollBrute.setTime(random(1000, 5000));end;procedure mainLoop;var reaction: procedure() = @doNothing;begin allModels := ogl.getModels([1452224228, 2406257549, 403123861]); bonesModels := allModels.getModels(2406257549); targetReticules := allModels.getModels(1452224228); trollBrutes := allModels.getModels(403123861); bonesTextures := ogl.getTextures(52275); if (not bonesTextures.isEmpty()) and canBuryBones.isFinished() then reaction := @buryBones else if (not bonesModels.isEmpty()) and canTakeBones.isFinished() then reaction := @takeBones else if trollBrutes.isEmpty() or not clientCenter.closest(trollBrutes)[0].isVisible() then reaction := @rotateCamera else if targetReticules.isEmpty() and canAttackTrollBrute.isFinished() then reaction := @attackTrollBrute; reaction();end;begin ogl.setup(800, 600); clientCenter := ogl.getClientMidPoint(); repeat mainLoop; until false;end. If you followed along correctly, your bot should function like this YouTube video. Part 6 :: ogLib Development Thread The official development thread for ogLib can be found here: ogLib Development. This thread will serve as a reference for the continuing improvement and development of ogLib. Any questions or suggestions regarding development should be posted there - any educational questions related to using the library should be posted on this tutorial thread! Part 7 :: Conclusion We hope that you have as much fun trying your hand at OpenGL as we have! As said before, the ogLib project is a work in progress. Updates to the plugins themselves, as well as to ogLib, are under way to allow even more capabilities within the 3D world. This tutorial's function list will be maintained with the latest changes. Eventually, we plan to have an include library as comprehensive and complete as SRL-6. Feel free to offer your thoughts on the thread! ogLib GitHub: https://github.com/ObscuritySRL/ogLib Best of luck with your botting endeavors! Clarity & Obscurity Last edited by Obscurity; 07-05-2016 at 04:21 PM. 2. Very helpful, nice tut! 3. Administrator Join Date Mar 2007 Posts 5,110 Mentioned 275 Post(s) Quoted 900 Post(s) Fantastic work @Clarity; and @Obscurity; Will be using this in the future to make some complex scripts! 4. Just a correction for glModel: TID: A model's TID, although rarely used, points to its texture ID. Should be: is a model's TriangleCount (Not Texture ID). Essentially, it should "technically" be "almost" as accurate as the ID. Other than that, this is amazing! Nice massive library too. +1 to both of you. Last edited by Brandon; 03-28-2015 at 01:34 PM. 5. I do believe something is missing... Because the example scripts do not compile... Regardless, THANK YOU. THANK YOU THANK YOU THANK YOU THANK YOU. I wuv you. So hard. Example of the types of errors I have been getting: Code: Error: Unknown declaration "clientWidth"... Error: No default value for parameter 3 found (This is an error with the clickMouse function)... 6. WOOO Great tutorial. I read through it and started trying to use the sample scripts so I could see what went down. Unfortunately none of the sample scripts appear to compile with the version of the include linked in the top of the tutorial. So I have to do a little fiddling to figure out the best way to click, since the clicking stuff is what doesn't compile. Also client.Height doesn't appear to be a thing so I'm going to resort to smart.height or something for now. 7. The scripts were just copied from our obscurityLibrary tutorial, so he may have just forgot one or two things. I'll work on it when I finally manage to get out of bed. :-P. 8. K. Pushed an update to the library with the functions required. The working script is: Simba Code: program ogLib;{$i ogl\lib\core\core.simba}var  allModels, bonesModels, targetReticules, trollBrutes: glModelArray;  bonesTextures: glTextureArray;  canAttackTrollBrute, canBuryBones, canTakeBones: countDown = [0];  clientCenter: TPoint;  clientHeight, clientWidth: int32;procedure attackTrollBrute;var  clickPoint:tPoint;begin  clickPoint:=clientCenter.closest(trollBrutes)[0].randomizePointEllipse(15);  if random(2) then    clickMouse(clickPoint.x, clickPoint.y, 1)  else    mouse.rightClickOption(clickPoint, 'Attack');  canAttackTrollBrute.setTime(random(1000,5000));  canTakeBones.setTime(random(1000, 5000));end;procedure buryBones;var  clickPoint:tPoint;begin  clickPoint:=mouse.getPoint().closest(bonesTextures)[0].randomizePoint(36, 32);  if random(2) then    clickMouse(clickPoint.x, clickPoint.y, 1)  else    mouse.rightClickOption(clickPoint, 'Bury');  canBuryBones.setTime(random(250, 1500));end;procedure doNothing;begin  writeln('We did nothing!');end;procedure rotateCamera;begin  minimap.setDegrees(random(45, 90));end;procedure takeBones;var  clickPoint:tPoint;begin  clickPoint:=clientCenter.closest(bonesModels)[0].randomizePointEllipse(15);  mouse.rightClickOption(clickPoint, 'Take Bones');  canTakeBones.setTime(random(1000, 5000));  canAttackTrollBrute.setTime(random(1000, 5000));end;procedure mainLoop;var  reaction: procedure() = @doNothing;begin  allModels := ogl.getModels(tCardinalArray([1452224228, 2406257549, 403123861]));  bonesModels := allModels.getModels(2406257549);  targetReticules := allModels.getModels(1452224228);  trollBrutes := allModels.getModels(403123861);  bonesTextures := ogl.getTextures(52275);  if (not bonesTextures.isEmpty()) and canBuryBones.isFinished() then    reaction := @buryBones  else if (not bonesModels.isEmpty()) and canTakeBones.isFinished() then    reaction := @takeBones  else if trollBrutes.isEmpty() or clientCenter.closest(trollBrutes)[0].isBehindInterface() then    reaction := @rotateCamera  else if targetReticules.isEmpty() and canAttackTrollBrute.isFinished() then    reaction := @attackTrollBrute;  reaction();end;begin  clientWidth:=800;  clientHeight:=600;  ogl.setup(clientWidth,clientHeight);  clientCenter := [round(clientWidth / 2), round(clientHeight / 2)];  repeat    mainLoop;  until false;end.

9. Sorry about the confusion guys! Updating the scripts so they should all work fine Obscurity added ogl.getClientMidPoint() for convenience, as well as mouse.click(). Please update your ogLib!

Originally Posted by Brandon
Just a correction for glModel:

TID:
A model's TID, although rarely used, points to its texture ID.

Should be:
is a model's TriangleCount (Not Texture ID). Essentially, it should "technically" be "almost" as accurate as the ID.

Other than that, this is amazing! Nice massive library too. +1 to both of you.
Fooled us both, learning something new every day. Fixed!
Last edited by Clarity; 03-28-2015 at 08:02 PM.

10. As a heads up... ogl library was renamed to ogLib. This affects the DIR, but all includes have been fixed to take this into account.

11. Registered User
Join Date
Feb 2015
Posts
26
Mentioned
0 Post(s)
Quoted
8 Post(s)
This is a great guide, thank you so much!
It will make creating bots so much easier.

12. SRL Junior Member
Join Date
Jul 2014
Location
My computer
Posts
78
Mentioned
8 Post(s)
Quoted
21 Post(s)
Awesome tut! Been waiting for this for a while. Gonna try it out as soon as I get the chance

13. If there are any other topics you would like covered, please let us know!
We will soon be moving the function list to a new development progress thread in the Unofficial Development forum.

14. Originally Posted by Clarity
If there are any other topics you would like covered, please let us know!
How would you handle walking to different locations? e.g. pest control: walking from the lander to a portal.
Also, is there any way to include ogLib AND SRL 6?

15. Originally Posted by evilcitrus
How would you handle walking to different locations? e.g. pest control: walking from the lander to a portal.
Also, is there any way to include ogLib AND SRL 6?
@Obscurity created a pest control script awhile ago, he may want to weigh in on that specifically if you are looking for PC help. Currently, minimap.simba offers:

function minimap.clickDegrees(funcDegrees: int32): boolean;

We will be porting over the easier movement functions from obscurityLibrary soon! @the bank also developed a version of SPS for use with ogLib. I'm not sure if he is going to share that or not.

I will be adding SRL-6 Compatibility when ogLib is mostly finished. As we haven't had a personal need for it yet, we haven't added it. You should be able to accomplish pretty much anything right now, but in the interest of being flexible and compatible, I will be happy to add this in soon!

This will be achievable, like in Brandon's old include, by adding {\$DEFINE SRLCompatibility} to the top of any script.

16. Originally Posted by Clarity
@Obscurity created a pest control script awhile ago, he may want to weigh in on that specifically if you are looking for PC help. Currently, minimap.simba offers:

function minimap.clickDegrees(funcDegrees: int32): boolean;
obscurityLibrary was able to get your position on the loaded map tile. ogLib will soon be able to as well.

But with obscurityLibrary, you could specify a point on the minimap. Say the 400x400th tile. It would return where that would be on your screen (since the minimap is rotated). You could then get the angle of that to your player and click that direction on the minimap.

But for my PC script, I just had it follow the masses of people. Blend in, right? . To do this:
Simba Code:
//~ Stuff here...      dotArray:=textureArray.extractID(3570);      if (not dotArray.isEmpty()) then        for index to (maxIndex:=dotArray.maxIndex()) do          begin            dotPosition:=dotArray[maxIndex-index].obsLocalMap(true);            if dotPosition.y<75 then              dotArray.delete(maxIndex-index);          end;//~ Stuff here...              mapBounds:=obsGetMiniMapBounds(textureArray);              mapMiddle.x:=round(mapBounds.x1+mapBounds.width()/2);              mapMiddle.y:=round(mapBounds.y1+mapBounds.height()/2);              furthestMapDot:=mapMiddle.furthest(dotArray)[0];              furthestAngle:=360-round(arcTan2(furthestMapDot.y-mapMiddle.y,furthestMapDot.x-mapMiddle.x)*180/pi)-90;              furthestAngle:=(furthestAngle-floor(furthestAngle/360)*360);              obsMiniMapClickAngle(furthestAngle,15,false,textureArray);

17. Thanks! You guys are both awesome.

In regards to SRL-6 compatibility, I just need to stop being lazy and learn new things

18. Originally Posted by evilcitrus
In regards to SRL-6 compatibility, I just need to stop being lazy and learn new things
SRL-6 has a lot of useful math functions in math.simba. We might copy those over. Apart from those, ogLib should have everything you need to make what you want! Nevertheless I will work on SRLCompatibility when I have time.

19. SRL Member
Join Date
May 2012
Posts
491
Mentioned
23 Post(s)
Quoted
227 Post(s)
Can't wait for all of this to be finalised!
Being able to loot items on ID is going to be awesome.

No more searching for colors on fighters, less chance of messing up if colors match.

And the ogLib seems great so far! Will be using the banking functions to finalise my farm.

function mouse.rightClickOption(funcPoint:tPoint;funcOption :ansiString):boolean;
ansiString is the text from the option we want to click? Whats the funcPoint?

20. SRL Junior Member
Join Date
Jul 2014
Location
My computer
Posts
78
Mentioned
8 Post(s)
Quoted
21 Post(s)
I noticed the mouse functions are quite basic, for example the mouse.click() just uses clickMouse(), and I was wondering how safe do you think this is? Have you had any bans on any ogl scripts you've written or should it be safe enough to use for extended periods of time?

21. Originally Posted by lovebotter
Can't wait for all of this to be finalised!
Being able to loot items on ID is going to be awesome.

No more searching for colors on fighters, less chance of messing up if colors match.

And the ogLib seems great so far! Will be using the banking functions to finalise my farm.

function mouse.rightClickOption(funcPoint:tPoint;funcOption :ansiString):boolean;
ansiString is the text from the option we want to click? Whats the funcPoint?
ansiString is the option, funcPoint is the TPoint to right click on. Glad you are enjoying the library

Originally Posted by HKbotz
I noticed the mouse functions are quite basic, for example the mouse.click() just uses clickMouse(), and I was wondering how safe do you think this is? Have you had any bans on any ogl scripts you've written or should it be safe enough to use for extended periods of time?
0. We have run scripts for months with absolutely no mouse movement. However, we take great care to randomize timing, since mouse movements = time. I often add in mouse movements not to have movement, but to create realistic timing between clicks.

22. SRL Member
Join Date
May 2012
Posts
491
Mentioned
23 Post(s)
Quoted
227 Post(s)
Originally Posted by Clarity
ansiString is the option, funcPoint is the TPoint to right click on. Glad you are enjoying the library

0. We have run scripts for months with absolutely no mouse movement. However, we take great care to randomize timing, since mouse movements = time. I often add in mouse movements not to have movement, but to create realistic timing between clicks.
What do you mean no mouse movement? Would your mouse just hop between clicking locations?
Might try and implement some ogl fuctions in bonsai's basic fighter (npc detection and looting) to get familiar with all of this.

also would spawning a smaller client lower resources needed?

23. SRL Junior Member
Join Date
Jul 2014
Location
My computer
Posts
78
Mentioned
8 Post(s)
Quoted
21 Post(s)
Originally Posted by Clarity
0. We have run scripts for months with absolutely no mouse movement. However, we take great care to randomize timing, since mouse movements = time. I often add in mouse movements not to have movement, but to create realistic timing between clicks.

24. I don't mean to encourage simplifying/cutting back on your scripts' unique randomizations/mouse styles. We've just found that Jagex doesn't detect whether the mouse is moving, only the time/location (and respective trends) associated with clicks. Perhaps if your account is flagged, they start tracking mouse movement as well in a biometric analysis manner. No way to say for sure. If it is easiest for you, continue using mouse movements. They will be added to ogLib for consistency with SRL-6 when the priority things are complete

Originally Posted by lovebotter
What do you mean no mouse movement? Would your mouse just hop between clicking locations?
Might try and implement some ogl fuctions in bonsai's basic fighter (npc detection and looting) to get familiar with all of this.

also would spawning a smaller client lower resources needed?
Yes, the red dot would jump around the screen. Although if you do this with no time in between jumps you will likely be flagged immediately.

Yes, smaller client sizes improve FPS and lessen the load on your computer
Last edited by Clarity; 04-02-2015 at 12:12 AM.

25. SRL Junior Member
Join Date
Jul 2014
Location
My computer
Posts
78
Mentioned
8 Post(s)
Quoted
21 Post(s)
Having an issue where the model IDs and actual models don't line up, and the ID is way off centered from the model, so when I click it clicks where the ID is, which is nowhere close to the model.

Any ideas why this is and how to fix it?

The model for the chicken I want is circled along with the ID and as you can see it's way off.

oglbeingdumb.png