DemiseScythe
2014-04-16 18:53:16
By DemiseScythe
Section 1: OGL Introduction.
Some of you might be familiar with the full capabilities of the OpenGL plugin developed by Brandon. For those who aren't, OGL is just another style of Runescape botting such as color, reflection and injection. Unlike the Java types, OGL doesn't modify game data at all making this style just as detectable as color and/or Smart itself. The GLX plugin allows the user to intersect the graphical data sent to your graphic card from Runescape so it can only see what is being displayed on the screen. However, the safety of this method far makes up for the inconvenience of only seeing displayed data and with a well designed script you will look just like another human player. I have personally managed to bot over 170M experience using OGL without bans so it is a safe method compared to reflection or injection and way more reliable than color. You could imagine the GLX plugin being your eyes, the script being your brain, Simba being your body and SMART being your hands; then you should be able to code a script that can play the game in the same manner as humans do. When a human plays he gets visual feedback from the screen and reacts accordingly using the knowledge stored in his brain and his hands to control your player. In the same manner, the GLX plugin will tell Simba what it sees and your script will respond with the encoded procedures that can be carried out by Smart to control your player.
Section 2: OGL Data.
Most 3-dimensional models, icons or images in Runescape has an unique OGL ID that is calculated based on its shape. Items with the same shape such as Uncut Gems can be differentiated by their ColorIDs which are calculated based on the color of the pixels in the image. The GLX plugin allows you to obtain these IDs as well as other information such as compass angle, text, equipment and even animations that include tools. Once a model or texture is detected by giving the plugin its OGL ID to the plugin, the following information becomes available to the user:
[{ID = 11270, COLOURID = 2362638, FULLCOLOURID = 5912620, X = 398, Y = 250, BOUNDS = {X1 = 390, Y1 = 242, X2 = 406, Y2 = 258}}]
For Models, the following Array is generated:
[{ID = 572370030, TID = 24, X = 123, Y = 412}]
For Textures or Images one can find their ID and ColorID as well as its X, Y position and the Bounds of the image. For Models one can find their ID as well as the X, Y position where the object stands. FullColorID and T[exture]ID are not necessary for identification. Using the IDs and their position we can detect, differentiate and locate objects or models on the screen allowing scripting to be possible.
Section 3: OGL Potential.
Some of you might be wondering just how powerful OGL really is. Based on the data the plugin returns above, OGL doesn't seem to be able to do a lot of fancy things like reflection/injection can. If you got the scripting ability, time, effort and will, OGL is capable of making a full Slayer script or any other script you can think of. Keep in mind that the complexity of the script is relative to the time and effort needed to develop it. Below are some nice mementos of my Slayer script which are meant to display the potential OGL scripting can have:
Video: http://www.youtube.com/watch?v=FDjAsnEZOuM
Images:






Section 4: OGL Requirements.
In order to run the OGL include and operate the plugin efficiently, your interpreter needs to be in Lape mode. As such you will need to know how to code Lape although you can script in a Pascal-like fashion as long as your code compiles. You should use a different Simba install folder for OGL to keep your folders separate and prevent compatibility lost with SRL6 and Brandon's includes. Something like C:\Simba\ and C:\SimbaOGL\ is fine. You need the correct plugins, my customized version of Brandon's include, and my DemiseGLZ include in the C:\SimbaOGL\ folder. I have only tried it in Windows so I am unsure how well it will run on other OS. Finally, you will need to rearrange your interphases but I will elaborate more on that later.
Section 5: OGL Installation.
To install and use OGL you must use Simba on a separate folder. Copy your Simba folder into the same place where it is installed and rename the copy to "SimbaOGL" Then delete the plugins and include folders and extract the contents of the download rar file to the SimbaOGL folder. Open the Simba.exe in the SimbaOGL folder and turn off the updater to prevent Simba SRL from updating and replacing your GLHook plugin with the regular OGL plugin. If an update happened, re-extract to overwrite again. Set the interpreter to Lape and the test script should work.
File Download: http://puu.sh/8ADqd.rar Updated: 5/5/14
I used to have a .pdf file with pictures but got deleted along with my old server so if I can get a copy of it from XoL. I'll upload it here. The general instructions provided above are not great but the pdf explanation is. If he doesn't have it either, I will add a better installation instruction.
Note: To open .simba files using the OGL install, you need to open \SimbaOGL\Simba.exe and go to File > Open > FileName.simba since this is the only way in which the .simba file will open using the correct folder due to association issues in the Windows OS.
Section 6: DemiseGLZ Include.
The DemiseGLZ include is a simplified version of my personal DemiseGLX include that has functions necessary to simplify OGL scripting. This include is necessary since my code is incompatible with SRL6. It contains simple functions normally found in SRL such as TypeSend, all the login procedures including time sensitive world choosing, some boolean functions, working FindFlag, custom functions to generate and define bounds as well as to draw them, printing functions, item/model finding and interaction, XPcounter, level stats and a new makecompass. The functions are self-explanatory but feel free to ask if there are any questions on usage. All functions are tested except the pin since I am in the process of adding the pin on my account so I can check it but it should work.
Section 1: Screen Areas.
Finally, we have reached the interesting part of this tutorial. Here is where you will actually learn how to code with OGL efficiently. The first concept that you need to grasp is that the screen is divided into Areas to simplify scripting. Just like back in the day when we had MainScreen, Minimap, Chatbox and Inventory areas, I have partitioned the screen into useful sections. First, in RS you should adjust one present of your interphases to look as below so that you can use my OGL include with it. No transparency and try to keep the inventory at 4x7 dimensions while making it half the height of the screen. The chat box should show 4 lines of text. Finally lock the interphases and thin the title bars. Your screen should look more or less than mine and the draw function should draw the areas on your screen correctly. Keep in mind I run OGL at 1350 x 760 dimensions but my test script should load SMART in those directions so that you can set your interphases this way and everything should work correctly.
These TBoxes can be fed to most functions making scripting incredibly efficient. The SS refers to the largest rectangular main screen area and you should look for models only in this area. The SZ is a smaller square version of SS centered around the player avatar and it can be useful to detect models near the player. The SM refers to the Minimap area and is it helpful to search for icon textures. There are two special constants SMCX and SMCY which are the x and y coordinates of the center of the Minimap. The ST refers to the Tab area above the Inventory and it is helpful to search for tab textures. The SI refers to the Inventory area and it is helpful to search for item textures. The SC refers to the Chat box area and it is helpful to search for text in it. SB[1] through SB[12] refer to the boxes around the 12 action bar slots in case someone wants to search for textures inside some of these. The only two areas that do not appear in this picture are the Bank related areas. SBM can be searched to find item textures inside the bank window and SBI can be searched to find item textures in the inventory that appears next to the bank window. Those are all the areas that you need to learn and they are not that difficult. Overtime, they will become second nature to you and you will be able to script efficiently.
Section 2: Visual Approach.
As the title suggest, you are able to collect OGL IDs using a Visual approach. Now I will bring your attention to the procedure VDebug(S: String); This command can be use to enable or disable the display of real time OGL IDs on the screen. When the parameter entered is 'N', it will remove the IDs as they can make it hard to see the screen although disabling Debug in SMART is another option. 'M' will display all Model IDs and 'T' will display all Textude IDs. There are limitations to this approach since all it displays is the main OGL ID and not all of the data. For texture finding and interaction, the ColorID is also needed but these IDs can be fed into the Printing functions allowing you to efficiently collect data. Another issue is that sometimes the ID will overlap making them hard to read. At that point the only approach you can do is the printing one.

All models with the same shape will have the same ID as seen in the picture above but overlapping models can lead to overlapping IDs which can be problematic as I explained above. The OGL plugin will still be able to see all the IDs without problem but we won't be able to read any of them at one time.
Section 3: Printing Approach.
Other than the Visual approach, OGL ID's can be found using functions. These functions will print the full Texture or Model arrays into the debug box of Simba where information can be read and copied for scripting purposes. The functions relevant to this section are the following:
(*ID Scripting Tools*)
{VDebug('N');{}
{VPrintTextures(X1, Y1, X2, Y2);{}
{VPrintModels(X1, Y1, X2, Y2);{}
{Writeln(glGetTextures(11270));{}
{Writeln(glGetModels(572370030));{}VPrintTextures and VPrintModels can be activated by removing the initial { and running the script. It will print all textures inside the bounds passed to it in X1, Y1, X2, Y2 format. However, this method is to be used in conjunction with the Visual approach. Say for example we see the following ID's on our screen and we want to know all the ID's and OGL data for the models present:

By Making a feeding the VPrintModels(461, 191, 763, 323); the corners of a box around these IDs, all of their information will be printed in the Debug.
Paired with SMART[7864]
{ID = 3774227809, TID = 16, X = 472, Y = 218}
{ID = 3168196654, TID = 20, X = 751, Y = 252}
{ID = 2615586268, TID = 20, X = 751, Y = 252}
{ID = 2079256770, TID = 20, X = 751, Y = 252}
{ID = 4390934, TID = 24, X = 491, Y = 256}
{ID = 572370030, TID = 24, X = 660, Y = 264}
Successfully executed.
There are a few things to be learned from this. First, we can observe the readable Model IDs on the screen were printed as well as those from the Models in the overlapping item pile. It is nice being able to get IDs that are overlapping in a different manner, but this approach exposes an obscure flaw on the plugin's capabilities which I've previously mentioned. Although this is RS's fault and not the plugin's itself. There are actually 5 items in that pile but the plugin can only see three of them: The arrow, and two of the runes. This is because the runes have the same shape and only the most valuable items will show when they are all dropped in the same place. In this case the screen shows the rune arrow, the astral rune and since the plugin can only see what you would see with your eyes. The maximum amount Models' information on an item pile that you can obtain have been determined to be four from testing aslong as at least a part of each of the items is visible. Fortunately for us, RS places the most valuable items at the top and once an item is looted, the 5th item becomes the 4th and then visible to the plugin. This same printing approach can be used for Textures, for example look at the following inventory of the above mentioned items:

By feeding VPrintTextures(1158, 365, 1339, 460) to the script, we receive the following code:
Paired with SMART[7864]
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1173, Y = 382, BOUNDS = {X1 = 1153, Y1 = 364, X2 = 1193, Y2 = 400}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1222, Y = 382, BOUNDS = {X1 = 1202, Y1 = 364, X2 = 1242, Y2 = 400}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1271, Y = 382, BOUNDS = {X1 = 1251, Y1 = 364, X2 = 1291, Y2 = 400}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1320, Y = 382, BOUNDS = {X1 = 1300, Y1 = 364, X2 = 1340, Y2 = 400}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1173, Y = 418, BOUNDS = {X1 = 1153, Y1 = 400, X2 = 1193, Y2 = 436}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1222, Y = 418, BOUNDS = {X1 = 1202, Y1 = 400, X2 = 1242, Y2 = 436}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1271, Y = 418, BOUNDS = {X1 = 1251, Y1 = 400, X2 = 1291, Y2 = 436}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1320, Y = 418, BOUNDS = {X1 = 1300, Y1 = 400, X2 = 1340, Y2 = 436}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1173, Y = 454, BOUNDS = {X1 = 1153, Y1 = 436, X2 = 1193, Y2 = 472}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1222, Y = 454, BOUNDS = {X1 = 1202, Y1 = 436, X2 = 1242, Y2 = 472}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1271, Y = 454, BOUNDS = {X1 = 1251, Y1 = 436, X2 = 1291, Y2 = 472}}
{ID = 88625, COLOURID = 1782589, FULLCOLOURID = 1847612, X = 1320, Y = 454, BOUNDS = {X1 = 1300, Y1 = 436, X2 = 1340, Y2 = 472}}
{ID = 19635, COLOURID = 131072, FULLCOLOURID = 262913, X = 1175, Y = 382, BOUNDS = {X1 = 1157, Y1 = 366, X2 = 1193, Y2 = 398}}
{ID = 132855, COLOURID = 4802351, FULLCOLOURID = 4933937, X = 1224, Y = 382, BOUNDS = {X1 = 1206, Y1 = 366, X2 = 1242, Y2 = 398}}
{ID = 132855, COLOURID = 4735814, FULLCOLOURID = 4867397, X = 1273, Y = 382, BOUNDS = {X1 = 1255, Y1 = 366, X2 = 1291, Y2 = 398}}
{ID = 104295, COLOURID = 1446413, FULLCOLOURID = 1315084, X = 1322, Y = 382, BOUNDS = {X1 = 1304, Y1 = 366, X2 = 1340, Y2 = 398}}
{ID = 132855, COLOURID = 5262412, FULLCOLOURID = 5262667, X = 1175, Y = 418, BOUNDS = {X1 = 1157, Y1 = 402, X2 = 1193, Y2 = 434}}
Successfully executed.
Note that a lot of the code is from the texture of what we humans see as slots but they can be ignored since they are not what we want. Thus ignoring all the 88625 IDs, we now focus on just the actual IDs and ColorIDs for the textures we want. Using the X and Y data, we can see that for example {ID = 104295, COLOURID = 1446413, FULLCOLOURID = 1315084, X = 1322, Y = 382, BOUNDS = {X1 = 1304, Y1 = 366, X2 = 1340, Y2 = 398}} belongs to the Coal. We now know where the OGL ID and ColorID for the Coal texture and will be able to use these IDs to detect and interact with Coal in the future. The presence of Texture IDs will also become extremely useful when it comes to walking as even NPC dots and Minimap icons have Texture IDs as seen below.

All that is left is to talk to the last bit of the ID scripting tools. The most useful ways to use Writeln(glGetTextures(11270)); and Writeln(glGetModels(572370030)); is to use them in one of the following manners:
- OGL ID - Give it an OGL ID as a parameter and it will print all the arrays for visible Items or Models depending on which function was used that have that same OGL ID. This can be helpful to quickly gather the ColorID of a Texture with a Visually obtained Texture OGL ID or to count how many different times does this ID appear on the screen as well as where.
- OGL ID/TBOX - Give it an OGL ID followed by one of the Screen Areas to get all of the Model or Texture data for that specific ID in an specific area of the screen.
- TBOX - Simply feed it a Screen Area to get all of the Model or Texture data found inside that specific area.
Thus we obtain the following results:
Writeln(glGetTextures(3786240));
Paired with SMART[7864]
[{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 1246, Y = 165, BOUNDS = {X1 = 1147, Y1 = 4, X2 = 1346, Y2 = 327}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 1246, Y = 512, BOUNDS = {X1 = 1147, Y1 = 359, X2 = 1346, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 68, Y = 607, BOUNDS = {X1 = 4, Y1 = 549, X2 = 132, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 196, Y = 607, BOUNDS = {X1 = 132, Y1 = 549, X2 = 260, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 324, Y = 607, BOUNDS = {X1 = 260, Y1 = 549, X2 = 388, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 452, Y = 607, BOUNDS = {X1 = 388, Y1 = 549, X2 = 516, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 539, Y = 607, BOUNDS = {X1 = 516, Y1 = 549, X2 = 563, Y2 = 666}}]
Successfully executed.Writeln(glGetTextures(3786240, SC));
Paired with SMART[7864]
[{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 68, Y = 607, BOUNDS = {X1 = 4, Y1 = 549, X2 = 132, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 196, Y = 607, BOUNDS = {X1 = 132, Y1 = 549, X2 = 260, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 324, Y = 607, BOUNDS = {X1 = 260, Y1 = 549, X2 = 388, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 452, Y = 607, BOUNDS = {X1 = 388, Y1 = 549, X2 = 516, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 539, Y = 607, BOUNDS = {X1 = 516, Y1 = 549, X2 = 563, Y2 = 666}}]
Successfully executed.Writeln(glGetTextures(SC));
Paired with SMART[7864]
[{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 68, Y = 607, BOUNDS = {X1 = 4, Y1 = 549, X2 = 132, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 196, Y = 607, BOUNDS = {X1 = 132, Y1 = 549, X2 = 260, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 324, Y = 607, BOUNDS = {X1 = 260, Y1 = 549, X2 = 388, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 452, Y = 607, BOUNDS = {X1 = 388, Y1 = 549, X2 = 516, Y2 = 666}},
{ID = 3786240, COLOURID = 661280, FULLCOLOURID = 661280, X = 539, Y = 607, BOUNDS = {X1 = 516, Y1 = 549, X2 = 563, Y2 = 666}},
{ID = 65081, COLOURID = 131587, FULLCOLOURID = 66050, X = 26, Y = 644, BOUNDS = {X1 = 4, Y1 = 622, X2 = 48, Y2 = 666}},
{ID = 65081, COLOURID = 131587, FULLCOLOURID = 66050, X = 541, Y = 644, BOUNDS = {X1 = 519, Y1 = 622, X2 = 563, Y2 = 666}},
{ID = 9122, COLOURID = 3559773, FULLCOLOURID = 4548727, X = 14, Y = 563, BOUNDS = {X1 = 6, Y1 = 555, X2 = 22, Y2 = 571}},
{ID = 1582, COLOURID = 1708804, FULLCOLOURID = 7822865, X = 34, Y = 563, BOUNDS = {X1 = 26, Y1 = 555, X2 = 42, Y2 = 571}},
{ID = 1405, COLOURID = 526603, FULLCOLOURID = 1382683, X = 54, Y = 563, BOUNDS = {X1 = 46, Y1 = 555, X2 = 62, Y2 = 571}},
{ID = 11475, COLOURID = 3357759, FULLCOLOURID = 2567728, X = 74, Y = 563, BOUNDS = {X1 = 66, Y1 = 555, X2 = 82, Y2 = 571}},
{ID = 6534, COLOURID = 1975334, FULLCOLOURID = 2106921, X = 94, Y = 563, BOUNDS = {X1 = 86, Y1 = 555, X2 = 102, Y2 = 571}},
{ID = 7464, COLOURID = 2304299, FULLCOLOURID = 2172713, X = 114, Y = 563, BOUNDS = {X1 = 106, Y1 = 555, X2 = 122, Y2 = 571}},
{ID = 2566, COLOURID = 790288, FULLCOLOURID = 1646112, X = 134, Y = 563, BOUNDS = {X1 = 126, Y1 = 555, X2 = 142, Y2 = 571}},
{ID = 699, COLOURID = 788482, FULLCOLOURID = 4535304, X = 154, Y = 563, BOUNDS = {X1 = 146, Y1 = 555, X2 = 162, Y2 = 571}},
{ID = 3222, COLOURID = 3022855, FULLCOLOURID = 6573326, X = 174, Y = 563, BOUNDS = {X1 = 166, Y1 = 555, X2 = 182, Y2 = 571}},
{ID = 1565, COLOURID = 724495, FULLCOLOURID = 1777955, X = 194, Y = 563, BOUNDS = {X1 = 186, Y1 = 555, X2 = 202, Y2 = 571}},
{ID = 2582, COLOURID = 1053976, FULLCOLOURID = 2304556, X = 513, Y = 563, BOUNDS = {X1 = 505, Y1 = 555, X2 = 521, Y2 = 571}},
{ID = 3146, COLOURID = 1251354, FULLCOLOURID = 1712163, X = 533, Y = 563, BOUNDS = {X1 = 525, Y1 = 555, X2 = 541, Y2 = 571}},
{ID = 2040, COLOURID = 1643012, FULLCOLOURID = 7560213, X = 553, Y = 563, BOUNDS = {X1 = 545, Y1 = 555, X2 = 561, Y2 = 571}},
{ID = 24990, COLOURID = 8947083, FULLCOLOURID = 8618118, X = 149, Y = 657, BOUNDS = {X1 = 143, Y1 = 652, X2 = 156, Y2 = 662}},
{ID = 10120, COLOURID = 462097, FULLCOLOURID = 462097, X = 555, Y = 614, BOUNDS = {X1 = 547, Y1 = 601, X2 = 563, Y2 = 628}},
{ID = 10120, COLOURID = 462097, FULLCOLOURID = 462097, X = 555, Y = 598, BOUNDS = {X1 = 547, Y1 = 596, X2 = 563, Y2 = 601}},
{ID = 10120, COLOURID = 462097, FULLCOLOURID = 462097, X = 555, Y = 630, BOUNDS = {X1 = 547, Y1 = 628, X2 = 563, Y2 = 633}},
{ID = 8160, COLOURID = 5652498, FULLCOLOURID = 5652498, X = 555, Y = 615, BOUNDS = {X1 = 547, Y1 = 601, X2 = 563, Y2 = 629}},
{ID = 7966, COLOURID = 5455377, FULLCOLOURID = 4929809, X = 555, Y = 598, BOUNDS = {X1 = 547, Y1 = 596, X2 = 563, Y2 = 601}},
{ID = 7497, COLOURID = 4732688, FULLCOLOURID = 4929553, X = 555, Y = 631, BOUNDS = {X1 = 547, Y1 = 629, X2 = 563, Y2 = 634}},
{ID = 8109, COLOURID = 1053198, FULLCOLOURID = 3878419, X = 555, Y = 588, BOUNDS = {X1 = 547, Y1 = 580, X2 = 563, Y2 = 596}},
{ID = 70, COLOURID = 197121, FULLCOLOURID = 3878419, X = 555, Y = 641, BOUNDS = {X1 = 547, Y1 = 633, X2 = 563, Y2 = 649}},
{ID = 20400, COLOURID = 2043447, FULLCOLOURID = 2043447, X = 2, Y = 600, BOUNDS = {X1 = 0, Y1 = 553, X2 = 4, Y2 = 648}},
{ID = 20400, COLOURID = 2043447, FULLCOLOURID = 2043447, X = 565, Y = 600, BOUNDS = {X1 = 563, Y1 = 553, X2 = 567, Y2 = 648}},
{ID = 28550, COLOURID = 1120285, FULLCOLOURID = 659219, X = 11, Y = 659, BOUNDS = {X1 = 0, Y1 = 648, X2 = 22, Y2 = 670}},
{ID = 28550, COLOURID = 1120285, FULLCOLOURID = 659219, X = 556, Y = 659, BOUNDS = {X1 = 545, Y1 = 648, X2 = 567, Y2 = 670}},
{ID = 3060, COLOURID = 1714224, FULLCOLOURID = 2306619, X = 2, Y = 551, BOUNDS = {X1 = 0, Y1 = 549, X2 = 4, Y2 = 553}},
{ID = 3060, COLOURID = 1714224, FULLCOLOURID = 2306619, X = 565, Y = 551, BOUNDS = {X1 = 563, Y1 = 549, X2 = 567, Y2 = 553}},
{ID = 24480, COLOURID = 1648689, FULLCOLOURID = 2175289, X = 305, Y = 551, BOUNDS = {X1 = 48, Y1 = 549, X2 = 563, Y2 = 553}}]
Successfully executed.
This covers the main methods as far as ID collection is concerned. As you all can see, that is quite a bit of data and the real question here is what to do with it. I will cover more on making use of this data on the next chapter as there are a bit more things to discuss.
Section 4: Additional Data.
In addition to all the data that regards Textures and Models as explained above, there is also ways to visually detect worn equipment and animation like humans do, flawless text recognition that do not depend on OCR, and even compass angle detection. First lets discuss animation detection. Your character will always have the same OGL ID as long as you don't change the worn items. Your standing, walking, running, resting, and hand melee ID will always be just dependent on what you are wearing. If you try to fish, your ID will change into your fishing ID as seen in the picture below:

On the left is the regular standing OGL ID for my avatar based on the equipment it is wearing and on the right it is its fishing model ID. As you expected, both as different and now we should discuss why. Your avatar OGL ID is based on the shape and color of all the pieces connected to the avatar. On the right, the fishing rod is now part of your avatar and changes the ID in the same way wielding a 2h sword would. Same concept applies for woodcutting hatches, mining picks so in theory as long as the animation modifies what your character wields, it should be constant, detectable and specific to the action associated with it. Then I can look for the time when the fishing ID disappears and the regular appears in order to determine my avatar has stopped fishing and is now just standing around. If you want to use something like this for your script, you need to setup a standard set of items to wear so that all script users share their avatar OGL IDs with you. Of course a standard will lead to false positives so this is only really useful as far as personal scripts are concerned or if you only search right where your avatar ID is since RS will always show your ID/model above everyone or everything standing under you. When a lot of people fish in one spot, you only see yourself unless someone pulls up one of those dressing booths but since your fishing rod is still visible, your ID should be visible and still the same. Equipment detecting works in the same manner, in the picture below I am just changing from a Dragon Full Helm to a Rune Full Helm but just that manages to change the IDs as seen:

Thus if your script relies in switching between a set of items, you can detect if and which items are equipped simply by comparing the overall IDs for the various combinations. This concept might seem a bit alien at first but play around while having VDebug('M'); turned on and you will get a better grasp of it in no time. Text recognition is hard to understand so let's look at the following function:
function VGetOverallXP: Cardinal;
var
T: glTextureArray;
S: TStringArray;
begin
if (not(GL_LoggedIn)) then
begin
Result := 1000;
Exit;
end;
T := glGetTextures(48705, SS);
if (Length(T) > 0) then
begin
S := glCharsToText(glGetChars(IntToBox(T[0].X-82, T[0].Y-10, T[0].X-13, T[0].Y+10)));
if (Length(S) > 0) then
begin
if (Length(ExtractFromStr(S[0], Numbers)) > 0) then
begin
Result := StrToInt64(ExtractFromStr(S[0], Numbers));
Exit;
end;
end;
end;
Result := 1000;
end;To read text, you need a TStringArray defined. Then you got to find a way to get the coordinates around of what you want to read in either a dynamic fashion as seen above or just hard code them into glCharsToText(glGetChars(X1, Y1, X2, Y2))); and pass them to the TStringArray. You should get the text returned to you in an array. You may then print the array to see what you are reading and then use the text data collected. There are way more complex ways to use Text and you can see a bit of that in the VSelectWorld function where I actually use a glTextArray and glCharsToTexts(glGetChars(IntToBox(X1, Y1, X2, Y2))) but then you should have to access text using glTextArray[index].text and it gets a lot more complicated in no time. The reason why I used the more complicated version on that function is because a glTextArray also stores the X and Y of the text and probably the bounds. This way not only do I see the world number but I know where in the screen it is located so that I can select it. Compass angle is detectable but if you are interested in it you are probably trying to change the compass angle to some specific value. Using VMakeCompass(Degrees); you can easily change the angle to any value between 0 and 360 degrees going counter clockwise from North(0, 360). It has a tolerance of 13 which allows the script enough time to slow down and not go past the desired degree. It will check your compass angle and if the desired is 13 or less away from the actual angle, it will not move. If it isn't, it will move the in the closest direction to the desired angle. Feel free to play with this function a bit so that you get how it works. That is all I can say at this time in regards to detecting different types of data using OGL. There are way more complex ways of collecting data as seen in my Slayer script but a lot of those are just clever thinking and building more advanced functions from the simple functions included in DemiseGLZ.simba and from the modified Brandon include.
Section 1: Finding Textures.
There isn't much to say in terms of finding textures. I have simplified the whole process to one function:
function VFindItem(ID, CID: Cardinal; Area: TBox): Boolean;
function VFindItem(ID, CID, Tol: Cardinal; Area: TBox): Boolean; overload;In this case, the third parameter is optional in the event you want to add some tolerance to the detection. The default tolerance value is 5. The Area parameter takes any of the Screen Areas where you want to search for the texture. As long as you know an Item's OGL ID and ColorID, you will be able to detect its presence. For Coal, the OGL ID is 104295 and the ColorID is 1446413. If we Coal in the inventory and run the following function in our BaseScript we should get True being printed and False if there isn't any Coal in the inventory.
(*Script Start*)
Writeln(VFindItem(104295, 1446413, SI));
TerminateScript;
end.Paired with SMART[4608]
True
Successfully executed.Section 2: Finding Models.
Likewise, Model detection has been reduced to the following function where only the SS and SZ areas are relevant:
function VFindModel(ID: Cardinal; Area: TBox): Boolean; If we look at the cow farm near Lumbridge on 'M' OGL debug mode we will see the cows having the following OGL IDs:

By running the following code we can detect if there is a Cow visible near our player on the screen inside the SZ screen area. Pretty simple right but this ability is extremely useful when using Map Icons to walk. By checking for nearby model IDs, one can check if the avatar did walk where it was intended to walk. If the cow is inside, this function will return True and False if the cow is nowhere near it.
Writeln(VFindModel(3352153657, SZ));Paired with SMART[4608]
True
Successfully executed.
Section 3: Finding Text.
This is a fun and interesting one. I find out which task I have to do by simply reading text. In this case, it is easier to show an example function from my private include and review the relevant part:
function VConfirmTask: Boolean;
var
I: Integer;
T: TStringArray;
begin
if VClickItem(VV[43], VV[44], SI, Mouse_Right, V[6]) then
begin
Wait(350 + Random(50));
T := glCharsToText(glGetChars(SC));
if Between('our ', ' ass', T[1]) = V[7] then
begin
Result := True;
Exit;
end;
end;
if VClickItem(VV[45], VV[46], SI, Mouse_Right, V[6]) then
begin
Wait(350 + Random(50));
T := glCharsToText(glGetChars(SC));
if Between('our ', ' ass', T[1]) = V[7] then
begin
Result := True;
Exit;
end;
end;
end;If we look at a task assignment text message, we find the following text:

This function grabs text as mentioned in the previous chapter using glCharsToText(glGetChars(SC)); which returns all the text in the chat box in the form of an array. Index 0 is the line where your avatar types and has its name. [1] is the first line from your name and so on. By using if Between('our ', ' ass', T[1]) = 'current' then I am checking if the word current is between Your and assignment on the first line of the chat box defined by T[1] in this case. All the rest of the function just right-clicks either a Slayer ring or Slayer gem and selects the 'Kills-left' option. Forcing the above line to appear in the bottom line of the chat box. Likewise, as long as you have the chat box text in an array, you can easily search or modify the strings by using the String functions included in Simba:

The best part about this is that unlike color, this doesn't rely on fonts and you won't have to constantly try different fonts to find the right one nor have to specify text color, spacing and all those bothersome details that are required with color. This text finding is 100% reliable and can lead to the construction of some pretty solid scripts.
Section 4: Texture Interaction.
If we look at Monkfish and obtain its data as mentioned in the previous chapter, we will find out that their OGL ID is 102255 and their ColorID is 2235674. By using the following function, we can then interact with Monkfish in our inventory:
function VClickItem(ID, CID: Cardinal; Area: TBox; Click: Integer; Option: String = 'Cancel'): Boolean;
function VClickItem(ID, CID, Tol: Cardinal; Area: TBox; Click: Integer; Option: String = 'Cancel'): Boolean; overload;By using either case of my simplified function we now try the following cases with several Monkfish in our inventory:
VClickItem(102255, 2235674, SI, Mouse_Left); - Will left-click a Monkfish eating it.
VClickItem(102255, 2235674, SI, Mouse_Right); - Will right-click a Monkfish and choose the Cancel option.
VClickItem(102255, 2235674, SI, Mouse_Right, 'Drop'); - Will right-click a Monkfish and choose the Drop option.
VClickItem(102255, 2235674, 25, SI, Mouse_Right, 'Drop'); - Will have the same effect as the previous case.
From this we learn a few things. First, it will always choose the texture or model closest to the top right corner or (0,0). Second, the tolerance appears to have no effect on this function but items that have the same shape such as Iron ore and Coal will have the same Texture OGL ID but different ColorID. We can take advantage of this by giving because by giving it a high tolerance value, we can basically force the script to interact with the texture regardless of its color.
Section 5: Model Interaction.
Referring back to Section 2 and the cows on the farm. We will write code that interacts with the cows using the following function:
function VClickModel(ID: Cardinal; Area: TBox; Click: Integer; Option: String = 'Cancel'): Boolean;
function VClickModel(ID: Cardinal; Area: TBox; Click: Integer; Option: TStringArray): Boolean; overload;The functions are identical with the only difference being the optional 4th parameter being able to be either a string or a tstringarray. Thus we can have a few cases taking place:
VClickModel(3352153657, SS, Mouse_Left); - Will left-click the Cow if it is on the SS screen area.
VClickModel(3352153657, SS, Mouse_Right); - Will right-click the Cow and choose the Cancel option.
VClickModel(3352153657, SS, Mouse_Right, 'Attack); - Will right-click the Cow and choose the Attack option leading your avatar to attack.
VClickModel(3352153657, SS, Mouse_Right, ['Attack', 'Cow']); - Will have the same effect as the previous case.
Trying each of those should give you a feel for what this function is capable of doing. Of course it will click under the model sometimes since the ID is actually at the base of the model. Combat scripts should create an attack function similar to my VClickModel where the Y in the mouse function has a set amount subtracted making Smart click higher where the actual model is. Depending on the size and height of the model, this value can be anywhere from 0 to 25 pixels and for Gargoyles, it can be as high as 20 since if you visit them you will realize they are actually flying over their ID as seen below.

This is all there is to interacting with Models. By looking through the actual function code, you can get a better idea of how to create advanced functions.
Section 1: ID Collection.
In order to make a script we will need to collect some OGL ID data first. We need the texture data for the Iron ore/uncut gems and the model data for the Iron rocks. By going into the 'T' debug mode and dragging a mined Iron ore into SS, we can clearly read its OGL ID:

We then run that OGL ID with the proper function to obtain that texture's ColorID:
Writeln(glGetTextures(104295, SI));Paired with SMART[6228]
[{ID = 104295, COLOURID = 1643021, FULLCOLOURID = 1511692, X = 1175, Y = 382, BOUNDS = {X1 = 1157, Y1 = 366, X2 = 1193, Y2 = 398}}]
Successfully executed.
Now we know that the OGL ID of Iron ore is 104295 and the ColorID is 1643021. Last we need to get the ID of the ore rocks by going into 'M' debug mode:


Keep in mind that IDs for stationary models are angle dependent in the same way a stair looks different from the front and from the side. Made sure to collect the ID's from the Angle in which the script will run. We got two different ID's for rocks with ore and notice as seen in the second picture that these ID's change when the rock has been mined out and this is what we want. We now know that the ID is the same for all rocks and the two possibilities are 2718818122 and 366615370. We might also want to collect the Uncut Gem ID and ColorID but the process is pretty much the same and optional at this time.
Section 2: Mining Procedure.
function VMineIron: Boolean;
begin
repeat
if not VClickModel(2718818122, IntToBox(604, 318, 746, 406), Mouse_Right, 'Iron') then
VClickModel(366615370, IntToBox(604, 318, 746, 406), Mouse_Right, 'Iron');
Wait(350 + Random(50));
until (GL_InvCount > 2) or (not(GL_LoggedIn));
end;The mining procedure is pretty simple. Since it is faster to drop ores while the rocks respawn instead of mining 28 and dropping the inventory. We want our procedure to stop mining after it has at least three objects in the inventory. We could use Mouse_Left to just left-click the rocks but flying butterflies will get in the way and mess up the script so it is safer this way. If it doesn't find the first two rocks, it will right-click the right rock and choose the Iron option. Since 'Mine Iron ore rocks' is at the top, this option will get chosen by default at the mention of the object's name.
Section 3: Dropping Procedure.
function VDropIron: Boolean;
begin
repeat
VClickItem(104295, 1643021, SI, Mouse_Right, 'Drop');
until (GL_InvEmpty) or (not(GL_LoggedIn));
end;That is all there is to the drop function. It will look for Iron ores in the SI or Inventory area and right-click on the item. It will then chose the 'Drop' option to drop the Iron ore. One thing to notice between the two above functions is that you need to include a wait for the VClickModel choice but the VClickItem already has a Wait included so that it isn't needed. Of course you need to include other lines inside the loop of this function that has the Gem IDs so that those are drop in the event they are mined.
Section 4: Script Completion.
function VMineIron: Boolean;
begin
repeat
if not VClickModel(2718818122, IntToBox(604, 318, 746, 406), Mouse_Right, 'Iron') then
VClickModel(366615370, IntToBox(604, 318, 746, 406), Mouse_Right, 'Iron');
Wait(350 + Random(50));
until (GL_InvCount > 2) or (not(GL_LoggedIn));
end;
function VDropIron: Boolean;
begin
repeat
VClickItem(104295, 1643021, SI, Mouse_Right, 'Drop');
until (GL_InvEmpty) or (not(GL_LoggedIn));
end;
begin
(*Initiation*)
ClearDebug;
Smart.Create(1350, 670, '', ['OpenGL32.dll']);
GLXMapHooks(Smart.ID);
VSettings;
VLogInPlayer;
VBounds;
VDrawBounds;
VSpin;
(*ID Scripting Tools*)
{VDebug('M');{}
{VPrintTextures(1158, 365, 1339, 460);{}
{VPrintModels(461, 191, 763, 323);{}
{Writeln(glGetTextures(104295, SI));{}
{Writeln(glGetModels(572370030));{}
(*Script Start*)
repeat
VMineIron;
VDropIron;
until (not(GL_LoggedIn));
TerminateScript;
end.In less than 20 lines of code I've managed to create a perfectly working Iron power miner. The beauty of OGL scripting is the simplicity of the code. It doesn't have Antirandom or other fancy stuff but that isn't needed. If you test this script there is never any inactive period for the avatar since it is constantly mining and dropping. This simple script is stable enough to run the full 5 hours with the exception of getting an uncut gem from mining. By grabbing the OGL ID for an uncut gem, the ColorID for one of them and raising the tolerance to some ridiculous value like 500, the script will drop any gem it finds in addition to the iron ores allowing this script to run to the 6 hour limit. Add the 6 hour fix and this can run for days. Of course it is missing a few fancy things such as a progress report and settings. I will add those tomorrow an publish a fully terminated script with all the bangles and whistles. As a bonus I will make it cut the gems before dropping them for free crafting experience.

Polishing the script a little with bug fixes, a progress report and 6 hour fix. We obtain the following completed product. To use, stand in the middle of the rocks as shown above and hit play. Have best pick equipped or in tool belt.
program DemiseMiner;
{$DEFINE SMART}
{$include_once GLX/GLXCore.Simba}
{$include_once GLX/Misc/Map.Simba}
{$include_once GLX/Misc/Smart.Simba}
{$include_once GLX/Misc/Graphics.Simba}
{$include_once GLX/Mouse.Simba}
{$include_once GLX/Login.Simba}
{$include_once GLX/Text.Simba}
{$include_once GLX/Bank.Simba}
{$include_once GLX/Inventory.Simba}
{$include_once GLX/Timing.Simba}
{$include_once GLX/Minimap.Simba}
{$include_once GLX/Interfaces.Simba}
{$include_once Demise/DemiseGLZ.Simba}
(*========DemiseMiner========*)
(*========OGL Edition========*)
(*========Version 1.0========*)
var
MT, SXP: Cardinal;
procedure VSettings;
begin
(*Preferences:*)
PlayersName := '';
PlayersPass := '';
BankPin := '1234';
(*Favorite Worlds*)
World[1] := 1;
World[2] := 1;
World[3] := 1;
World[4] := 1;
World[5] := 1;
World[6] := 1;
World[7] := 1;
World[8] := 1;
end;
function VTicket: Boolean;
begin
Result := VClickItem(125205, 5718564, SI, Mouse_Left);
end;
function VMineIron: Boolean;
var
XP, Minutes: Integer
begin
repeat
if not VClickModel(2718818122, IntToBox(604, 318, 746, 406), Mouse_Right, 'Iron') then
VClickModel(366615370, IntToBox(604, 318, 746, 406), Mouse_Right, 'Iron');
Wait(300 + Random(50));
XP := VGetOverallXP - SXP;
Minutes := Round((GetSystemTime - MT)/60000);
if (Minutes = 0) then
Minutes := 1;
ClearDebug;
Writeln('Demise Miner GLX V1.0');
Writeln('Mining Experience Earned: ' + IntToStr(XP));
Writeln('Time Passed: ' + IntToStr(Minutes) + ' Minutes');
Writeln('Mining Xp/Hr: ' + IntToStr(Round((XP*60)/Minutes)));
until (GL_InvCount > 2) or (not(GL_LoggedIn));
end;
function VDropIron: Boolean;
begin
repeat
VClickItem(104295, 1643021, SI, Mouse_Right, 'Drop');
VClickItem(91290, 329256, 400, SI, Mouse_Right, 'Drop');
until (GL_InvEmpty) or (not(GL_LoggedIn));
end;
begin
(*Initiation*)
ClearDebug;
Smart.Create(1350, 670, '', ['OpenGL32.dll']);
GLXMapHooks(Smart.ID);
VSettings;
VLogInPlayer;
VBounds;
VDrawBounds;
VSpin;
(*Script Start*)
VTicket;
MT := GetSystemTime;
SXP := VGetOverallXP;
repeat
repeat
VMineIron;
VTicket;
VDropIron;
until (not(GL_LoggedIn));
SMARTkillClient(Smart.ID);
Smart.Create(1350, 670, '', ['OpenGL32.dll']);
GLXMapHooks(Smart.ID);
VLogInPlayer;
VBounds;
VSpin;
until (not(GL_LoggedIn));
VSoundBase('End');
TerminateScript;
end.















