[SCAR] DTMs For Dummies

Discussion in 'Code Snippets and Tutorials' started by Dusk412, Aug 2, 2008.

  1. Dusk412

    Dusk412 Level I

    Joined:
    Aug 2, 2008
    Messages:
    88
    Likes Received:
    9
    [​IMG]

    Table Of Contents:
    - Background Information
    - Tools You Will Need
    - When To Use DTMs
    - How To Make A DTM
    - How To Use DTMs
    - Conclusion

    NOTE: This tutorial was originally made at SRL-Forums.com and all the examples pertain to Runescape. Sorry, but it should still get the point across.

    Background Information:

    What is a DTM you ask?
    - Well, DTM stands for “Deformable Template Model.” Now that may sound like complex programmer language to you, but the truth is that DTMs are one of the simplest, yet most useful and efficient tools for scripting on SRL Forums.

    How does a DTM work?
    - A DTM will use one main point (or the parent) and several subpoints (sometimes called the children). The script will then look in the area you specify for this point (the main point) in relation to its distance from other points (the subpoints). It finds these points using their color.

    Tools You Will Need:

    All you need to create DTMs are these three things:

    1. The window with the picture of the item or location you would like to click (I will use Runescape).
    2. A picture editor (I will use Microsoft Paint).
    3. SCAR

    When To Use DTMs:

    DTMs will ONLY work if the point/item/location we are looking for is static (unchanging). This means that on the mainscreen of Runescape, where what objects look like changes when you change the camera direction or angle or color (which Jagex does to keep us scripters away), you really cannot use DTMs. Then where can you use DTMs you ask? They are basically used in just three ways:

    1. In your inventory – Because each item is outlines in black, the shade of which never changes.
    2. In the bank – For the same reason as the inventory.
    3. On the minimap – Because certain places have areas or things that do not move (for example, the yellow dots of bankers in a bank).

    How To Make A DTM:

    Step 1: Get a picture of the item/thing/place you would like to find:

    In the following examples I will use Runescape and will get a picture of an item in the inventory and of a bank. Log in to your Runescape account and make sure that the item is on the screen. Next, find the Print Screen key on your keyboard. This key is normally found near the Backspace button (on my keyboard it is up and to the right, between F12 and Scroll Lock) but every keyboard is different. Now press the button.

    [​IMG]

    [​IMG]

    Step 2: Edit the picture:

    Go to your picture editing software and hit Ctrl + v or right click and hit paste. You will get something like this:

    Example 1:

    [​IMG]

    Example 2:

    [​IMG]

    Next choose the tool that can select an area of the picture to cut out or move. In Paint it is called 'select' and looks like this:

    [​IMG]

    Cut your image down until it is a little bit bigger than the image on all sides. Here are the pictures from my two examples:

    Example 1:

    [​IMG]

    Example 2:

    [​IMG]

    Step 3: Open up SCAR. Make Scar minimized by clicking this button:

    [​IMG]

    Now drag SCAR so that you can see the top fourth of SCAR but the rest you can see your picture and picture editor like this:

    The picture is rather large so here is a link:
    http://i235.photobucket.com/albums/ee171/Dusk412/HalfScreen.jpg

    Now click drag the crosshairs onto your picture. Here is a picture of how to drag the crosshairs:

    The picture is rather large so here is a link:
    http://i235.photobucket.com/albums/ee171/Dusk412/DragCrosshairs.jpg

    Step 4: Now go to SCAR and click on Tools. Then click on DTM Editor...

    [​IMG]

    Now a screen should come up that looks like this:

    Large picture so just check it out here:
    http://i235.photobucket.com/albums/ee171/Dusk412/DTMEditorScreen.jpg

    Let me take a moment to explain this screen. As you can see, there is a small box in the upper left that shows you a zoomed-in version of where your mouse is. This is so you can choose your points with perfect accuracy because that red square in the center will be the pixel you choose. For your main point, though, being a pixel off usually doesn't matter. This comes in to play more with the subpoints.

    [​IMG]

    Slightly to the right there are three options, make sure that 'Mouse click creates point' is chosen.

    [​IMG]

    The white box in the upper right is where you will see a list of your points. Further down on the right you see the two options Add and Delete. Add will make a point come up that looks like this {0, 0, 0}. The first number is the points x-coordinate. The second number is the points y-coordinate. The third number is the points color. You can edit this point manually using the options below (although I never have, it is much more efficient to use the mouse and click the picture). Beneath the Add and Delete are 6 options and it may seem overwhelming but almost always you will only need to touch 2 of them: Tolerance and Area Size. For explanatory purposes here is what they all are:

    X: The x-coordinate of the point
    Y: The y-coordinate of the point
    Area Size: The area that the color should take up (Area Size of 4 would be 2 pixels by 2 pixels).
    Area Shape: The shape that the color should take up. Value can be Rectangle, Cross, or Diagonal Cross.
    Tolerance: Value can be from 0-255. How close the set color must be to the one the script finds.
    Color: The color of the point

    Beneath this is a small box where the color is shown (so you can be sure you picked the correct point). Underneath that is a something that says 'Found if color is matched.' Just make sure that the box next to it is checked. Beneath that is a small box preceded by 'Parent:'. This is where you can make sure that the main point (remember it is also known as the parent) is in the right spot. On your picture your main point will always be a little flashy-looking pixel.

    And here is a picture of the side with all the stuff I just talked about:

    [​IMG]

    Phew that was long. If you need to stand and stretch or get a glass of water, feel free. Now on to the next step.

    Step 5: Now click on the center of your item (for bank or inventory) or where you want to click (for minimap). This will create the main point and is what the script will look for in the DTM. For example in these pictures you would want to click where the center of the red X is:

    Example 1:

    [​IMG]

    Example 2:

    [​IMG]

    Now we have our main point chosen. On the picture the only point should be a little flashy-looking pixel thing (remember from above that means it is our main point). On the right side of the screen find Tolerance and set it to 255 (max). This means that the color of our main point does not matter. This means that if the script finds the other subpoints the right distance away from this point (and therefore each other) and they are the right color, then you can find this item!

    [​IMG]

    [​IMG]

    Step 6: Now is where this splits a little. This is different depending on what type of DTM you are making. If you are doing an item in the inventory or the bank go to Example 1. If you are doing a location on the minimap go to Example 2. If you want to master DTMs, read them both.

    Example 1: For an item in the inventory or the bank, as I mentioned earlier, they are outlined (conveniently) by runescape in black and that color never changes and neither does its position. This means that our subpoints will all be along the outline of our object. This is why you need that handy zoom box - to make sure that your subpoint is on the black line. So go and click several points around the object, I recommend about 5 or 6. (Note here: if you are going to be dealing with the bank or stackable items, it is necessary to avoid the upper left hand corner or sometimes the whole top part of the object because there will be numbers here which are NOT black and therefore will not work properly because if the number of items ever change, the colors around the top change. Phew long note...). Once you have all your points selected your item will look like an item covered with little red criss-cross lines. To double-check that you got the black line, look at the upper right box and, except for the top point, all the points should have the same color, 65536.

    [​IMG]

    Example 2: For an item on the minimap, while the item is static and does not move, it is not outlined in black. This means that our subpoints will need to be colors. In this example, I will use the bankers as my subpoints and I will create one for each banker. The bankers do not move, and are therefore suitable subpoints. Now click on each of the places you want a subpoint. Once you have all your points selected your item will look like an item covered with little red criss-cross lines.

    [​IMG]

    Because our subpoints are colors, this is where the process differs from above. Now we will use the two options I said you would probably use, Area Size and Tolerance. I will explain Tolerance first because it is easier. Tolerance, remember, is a number from 0-255 that is how much the point, our subpoints, can be off from the color we picked. Most often the colors in Runescape will change only slightly and if we set the Tolerance somewhere between 10-20 the script will find it. This becomes a delicate balance of making the tolerance high enough that the script can find it, but small enough that the script doesn't detect other colors and therefore the wrong points. I usually use 15. Now on to Area Size. This is the amount of space that the color should take up. An area size of 4 means 2 pixels by 2 pixels. I recommend usually just 3-4 here, I will use 3 in this case.

    [​IMG]

    Step 7: Now look at your final red criss-crossed picture and make sure that the flashy-looking pixel is in the center. If it is not, you will need to use the Parent box I mentioned earlier.

    Step 8: Now go to File. Then click Save. Now save your DTM anywhere you want but title it something relevant such as, like my two examples, BucketDTM or EastFaladorBankDTM.

    [​IMG]

    Step 9: Close the DTM Editor. Now go back to Tools and go to DTM Editor again (See Step 4 if you have forgotten already).

    [​IMG]

    Step 10: Go to Test. Then click on Find DTM...

    [​IMG]

    Now find the location where you saved your DTM and click it then click open or just double click it. SCAR will pause for a moment and then one of two things will happen. One, a box will pop up that says "Not found. Time take: 300" or something like that. This means that the DTM Editor could not find the DTM in the exact picture it was taken from and that means that you did not make it properly. I sugges going back and following my guide step by step. It will look like this:

    [​IMG]

    The other thing that could happen is that a box will pop up that says "Found. Time taken: 10. Position: 100, 200. Do you want current DTM to be moved to this position?" or something like that. There will also be a a red X across your picture. Just hit 'No' or 'Cancel' and feel proud. This means that you created your first DTM successfully.

    [​IMG]

    Step 11: Now go to File. Then go to Open.

    [​IMG]

    Now find your DTM and open it (if it asks you would you like to save, say no). Now go to File and then hit DTM to Text.

    [​IMG]

    Now you may Exit the DTM editor!

    [​IMG]

    Step 12: The Final Step! First, maximize SCAR.

    [​IMG]

    Now Look at the bottom in the Debug box and you will see something that looks like this:

    [​IMG]

    Highlight all the information and copy it. You have now officially made your first DTM!

    How To Use DTMs:

    I am only going to do this with my first example because the basic method is the same in any case. There are several ways to use DTMS and here is what I will cover:
    - The Basics
    - FindDTM
    - FindDTMRotated
    - DTMRotated

    The Basics:

    Code (Text):
    1.  
    2. program FindingTheBucket; // The Title Of Our Sample Program
    3. {.include SRL/SRL.scar}   // I Always Include SRL First Thing!
    4.  
    5. var
    6.   x, y : Integer;         // Almost Every Script You Will Ever Make Uses x And y To Click On A Location
    7.   BucketDTM : Integer;
    8.  
    9. procedure ClickBucket;    // The Name Of Our Procedure That Will Click The Bucket
    10. begin
    11.   BucketDTM := DTMFromString('78DA63F462606070664001C93E52609A11CA6' +
    12.        '70C01128E0C688011554D1090F027A0C6134804115003724B0001' +
    13.        '3520B7B8E05703004EAA0451');
    14.   // Our Procedure
    15.   FreeDTM(BucketDTM);
    16. end;
    17.  
    18. begin
    19. SetupSRL;                 // Always Important That You Setup SRL
    20. ActivateClient;           // I Always Activate My Client :D
    21. ClickBucket;              // Then We Run Our Procedure To Click Our Bucket
    22. end.
    23.  
    Okay I explained a few basic things in the comments, but the important stuff I will right here. First thing is that we need to declare our DTM as an integer under variables (var). I used "BucketDTM : Integer;" Then beneath it we give our DTM a value using that long bit of text that we copied as the last step when we created our DTM. Then right away, so you NEVER forget, do FreeDTM(WhateverYourDTMIs) because otherwise your script will end up lagging alot. This is an important technique here at SRL Forums.

    FindDTM:

    The first method for finding a DTM that I will discuss is FindDTM.
    Code (Text):
    1. function FindDTM(DTM: Integer; var x, y: Integer; x1, y1, x2, y2: Integer): Boolean;
    DTM: Integer --> The DTM we declared (For me it is BucketDTM)
    var x, y: Integer --> If it finds our DTM, it will save its coordinates here
    x1, y1, x2, y2: Integer --> The box in which it will look for our DTM (I will use MIx1, MIy1, MIx2, MIy2 which are Main Inventory coordinates built into SRL. If you were doing something in the bankscreen you would use MSx1, MSy1, MSx2, MSy2 which are Main Screen coordinates. If you were finding a bank on a minimap you would use MMx1, MMy1, MMx2, MMy2 which are MiniMap coordinates).
    Boolean --> This means that if it finds our DTM this whole function will equal True, if it doesn't find the DTM this whole function will equal False.

    Code (Text):
    1.  program FindingTheBucket; // The Title Of Our Sample Program
    2. {.include SRL/SRL.scar}
    3. // I Always Include SRL First Thing!
    4.  
    5. var
    6.   x, y : Integer;         // Almost Every Script You Will Ever Make Uses x And y To Click On A Location
    7.   BucketDTM : Integer;
    8.  
    9. procedure ClickBucket;    // The Name Of Our Procedure That Will Click The Bucket
    10. begin
    11.   BucketDTM := DTMFromString('78DA63F462606070664001C93E52609A11CA6' +
    12.        '70C01128E0C688011554D1090F027A0C6134804115003724B0001' +
    13.        '3520B7B8E05703004EAA0451');
    14.   if (FindDTM(BucketDTM, x, y, MIx1, MIy1, MIx2, MIy2) then
    15.   begin
    16.     // Our Procedure
    17.   end;
    18.   FreeDTM(BucketDTM);
    19. end;
    20.  
    21. begin
    22. SetupSRL;                 // Always Important That You Setup SRL
    23. ActivateClient;           // I Always Activate My Client :D
    24. ClickBucket;              // Then We Run Our Procedure To Click Our Bucket
    25. end.
    What I have now added is the if-then statement. This means that if FindDTM returns True as its value (meaning we found our DTM) then we will run our procedure.

    Code (Text):
    1. program FindingTheBucket; // The Title Of Our Sample Program
    2. {.include SRL/SRL.scar}
    3. // I Always Include SRL First Thing!
    4.  
    5. var
    6.   x, y : Integer;         // Almost Every Script You Will Ever Make Uses x And y To Click On A Location
    7.   BucketDTM : Integer;
    8.  
    9. procedure ClickBucket;    // The Name Of Our Procedure That Will Click The Bucket
    10. begin
    11.   BucketDTM := DTMFromString('78DA63F462606070664001C93E52609A11CA6' +
    12.        '70C01128E0C688011554D1090F027A0C6134804115003724B0001' +
    13.        '3520B7B8E05703004EAA0451');
    14.   if (FindDTM(BucketDTM, x, y, MIX1, MIy1, MIx2, MIy2) then
    15.   begin
    16.     Wait(500+random(150));
    17.     Mouse(x, y, 3, 3, False);
    18.   end;
    19.   FreeDTM(BucketDTM);
    20. end;
    21.  
    22. begin
    23. SetupSRL;                 // Always Important That You Setup SRL
    24. ActivateClient;           // I Always Activate My Client :D
    25. ClickBucket;              // Then We Run Our Procedure To Click Our Bucket
    26. end.
    I have now added two things. First is Wait(500+random(150)). This will wait 500 milliseconds plus a random number of milliseconds between 0 and 150. This is really useful for antiban and just allowing for a little lag as the script runs because no person can really move that fast and efficiently. Then next line is Mouse(x, y, 3, 3, False). This means it will move the mouse to coordinates x, y (which remember is our DTM coordinates thanks to FindDTM) but it will move the mouse with a random 3 pixels in any direction because no human hits perfectly accurately in the center of a DTM every time. True means that the mouse will left click (False would be right click).

    FindDTMRotated:

    This next method looks something like this:
    Code (Text):
    1. function FindDTMRotated(DTM: Integer; var x, y: Integer; x1, y1, x2, y1: Integer; StartAngle, EndAngle, AngleStep: Extended; var Angle: Extended): Boolean;
    There are four new things to learn here, but this starts using geometry and perhaps a little trigonometry.

    Here is a chart to help you:
    Code (Text):
    1.  
    2.                  0 degrees or 0 radians
    3.                360 degrees or 2*Pi radians
    4.                             |
    5.                             |
    6. 270 degrees or 3*Pi/2 ______|______ 90 degrees or Pi/2 radians
    7.                             |
    8.                             |
    9.                             |
    10.                180 degrees or Pi radians
    11.  

    Now onto the new terms:
    StartAngle --> The angle in radians where it starts rotating the DTM from. Make this negative so that it starts looking from a little counterclockwise of north.
    EndAngle --> The angle in radians where it stops rotating the DTM. Make this positive so that it ends looking a little clockwise from north.
    AngleStep --> How much the function increments the angle by every time it searches. The smaller the number, the more times it must increment the angle in order to reach the EndAngle thus the more times it must search for the DTM therefore the more accurate but also the more lag. (Thanks ZephyrsFury :D)
    Angle --> A variable in which the angle at which the DTM was found is stored. Pretty much useless but is required for the function to work. (Thanks again ZephyrsFury :D)

    Okay. So now you see a function that is way more complicated but seems to have no practical application. Well, when you log in to runescape, Jagex rotates the minimap slightly so that North no longer points directly north because Jagex does not like us to cheat lol. So this function is mainly for use on the Minimap. So here is what we have:

    Code (Text):
    1. program FindingTheBank; // The Title Of Our Sample Program
    2. {.include SRL/SRL.scar}
    3.  
    4. var
    5.   x, y : Integer;         // Almost Every Script You Will Ever Make Uses x And y To Click On A Location
    6.   BankDTM : Integer;
    7.   DTMAngle : Extended;
    8.  
    9. procedure ClickBank;    // The Name Of Our Procedure That Will Click The Bank
    10. begin
    11.   BankDTM := DTMFromString('78DA63F462606070664001C93E52609A11CA6' +
    12.        '70C01128E0C688011554D1090F027A0C6134804115003724B0001' +
    13.        '3520B7B8E05703004EAA0451');
    14.   MakeCompass('N');
    15.   if (FindDTMRotated(BankDTM, x, y, MMx1, MMy1, MMx2, MMy1, -(1/36)*Pi, (1/36)*Pi, (1/360)*Pi, DTMAngle)) then
    16.   begin
    17.     Wait(500+random(150));
    18.     Mouse(x, y, 3, 3, True);
    19.   end;
    20.   FreeDTM(BankDTM);
    21. end;
    22.  
    23. begin
    24. SetupSRL;                 // Always Important That You Setup SRL
    25. ActivateClient;           // I Always Activate My Client :D
    26. ClickBank;                // Then We Run Our Procedure To Click Our Bank
    27. end.
    I changed the word Bucket to Bank because now we are looking for something on the minimap. Then I added MakeCompass('N') so that the minimap is facing as close to exact north as possible. The next thing you must do is add a variable to your script to go in for Angle. I called mine DTMAngle. Then I made StartAngle = -(1/36)*Pi and EndAngle = (1/36)*Pi (or -5 degrees and 5 degress). I then made AngleStep = (1/360)*Pi (or 0.1 degrees).

    DTMRotated:

    Now that you know FindDTMRotated, I can teach you this next function, which performs basically the same task but requires fewer parameters because it does most of the work for you. In almost every scenario, you can use this function rather than the more complex FindDTMRotated function. I would like to pause here to thank Yakman, the creator of the DTMRotated function, because I love it :D.

    Code (Text):
    1. function DTMRotated(DTM: LongInt; var x: LongInt; var y: LongInt; x1: LongInt; y1: LongInt; x2: LongInt; y2: LongInt): Boolean;
    There are no new terms to learn for this function. It is pretty basic in its use. I shall explain them all again just so you don’t have to scroll up so much.

    DTM: Integer --> The DTM we declared (For me it is BucketDTM)
    var x, y: Integer --> If it finds our DTM, it will save its coordinates here
    x1, y1, x2, y2: Integer --> The box in which it will look for our DTM (I will use MIx1, MIy1, MIx2, MIy2 which are Main Inventory coordinates built into SRL. If you were doing something in the bankscreen you would use MSx1, MSy1, MSx2, MSy2 which are Main Screen coordinates. If you were finding a bank on a minimap you would use MMx1, MMy1, MMx2, MMy2 which are MiniMap coordinates).
    Boolean --> This means that if it finds our DTM this whole function will equal True, if it doesn't find the DTM this whole function will equal False.

    I am now going to explain exactly how this function works in comparison to FindDTMRotated because I believe it is important to understand why all of a sudden we have this much simpler function and why FindDTMRotated was created at all. This new function is not just a better function, it instead just uses the FindDTMRotated function and fills in all the angle details for you. What the function does is slowly increases the angle to check through (to a certain point) and repeats the FindDTMRotated function a couple times. I am not going to bore you and go into detail, I just wanted you to know a little bit about how it works.

    Code (Text):
    1. program FindingTheBank; // The Title Of Our Sample Program
    2. {.include SRL/SRL.scar}
    3.  
    4. var
    5.   x, y : Integer;         // Almost Every Script You Will Ever Make Uses x And y To Click On A Location
    6.   BankDTM : Integer;
    7.  
    8. procedure ClickBank;    // The Name Of Our Procedure That Will Click The Bank
    9. begin
    10.   BankDTM := DTMFromString('78DA63F462606070664001C93E52609A11CA6' +
    11.        '70C01128E0C688011554D1090F027A0C6134804115003724B0001' +
    12.        '3520B7B8E05703004EAA0451');
    13.   MakeCompass('N');
    14.   if (DTMRotated(BankDTM, x, y, MMx1, MMy1, MMx2, MMy1)) then
    15.   begin
    16.     Wait(500+random(150));
    17.     Mouse(x, y, 3, 3, True);
    18.   end;
    19.   FreeDTM(BankDTM);
    20. end;
    21.  
    22. begin
    23. SetupSRL;                 // Always Important That You Setup SRL
    24. ActivateClient;           // I Always Activate My Client :D
    25. ClickBank;                // Then We Run Our Procedure To Click Our Bank
    26. end.
    As you can see it is much simpler to use and understand. All I did was take the FindDTMRotated function and delete some excess stuff about angles and radians and such.

    Conclusion:

    That is all, and I mean ALL, you need to know for DTMs! If you have mastered this and are looking for the next step I recommend finding a tutorial on DDTMs or RadialWalking. If you find any mistakes (even a grammar error) PM or post here and I will fix it. I made this to be the most comprehensive DTM tutorial and I hope I succeeded. If I helped you in anyway please post. And if you REALLY love me or my tutorial feel free to rep me :D.
     
    Phee and Zer0 like this.
  2. Zer0

    Zer0 Level IV

    Joined:
    Mar 2, 2008
    Messages:
    3,037
    Likes Received:
    180
    Location:
    Home sweet home
    Re: Complete DTM Tutorial

    Nice guide, I liked all the pictures and in-depth explanations. I suppose this is your guide from here: http://www.srl-forums.com/forum/dtm05-d ... 33647.html
    Maybe its just me, but perhaps a simple link would suffice since the formatting would be preserved.

    Either way, +rep :)
     
  3. Dusk412

    Dusk412 Level I

    Joined:
    Aug 2, 2008
    Messages:
    88
    Likes Received:
    9
    Re: Complete DTM Tutorial

    Good point, I reformatted it all so no worries. But most forums do not appreciate anyone advertising any other forum. The fact that I said its name and URL alone could potentially get people angry. And since I just registered less than 20 minutes ago, I am trying to keep a low profile :D.
     
  4. Zer0

    Zer0 Level IV

    Joined:
    Mar 2, 2008
    Messages:
    3,037
    Likes Received:
    180
    Location:
    Home sweet home
    Re: Complete DTM Tutorial

    Ah, the formatting is much better now :)
    I would recommend putting in a link to the original tutorial and making a note that you were the original author as well (even though its obvious due to your username). That'll clear up suspicion of plagiarism.

    EDIT: Oh, I forgot to mention this earlier, but this post should go in this forum: viewforum.php?f=15 instead ;)
     
  5. Dusk412

    Dusk412 Level I

    Joined:
    Aug 2, 2008
    Messages:
    88
    Likes Received:
    9
    Re: Complete DTM Tutorial

    Dang. I wasn't sure. I saw other stickied tuts in here so I didn't know. Oh well, maybe a mod will move it for me? Also, I will be sure to link to it. Also, about that PM you sent, totally did not notice that lol. It was only like 20 posts down, I guess people are not that active in the SCAR area lol.
     
  6. Zer0

    Zer0 Level IV

    Joined:
    Mar 2, 2008
    Messages:
    3,037
    Likes Received:
    180
    Location:
    Home sweet home
    Re: Complete DTM Tutorial

    Don't worry about it, its fine, a mod will move it if they so feel like it.
    And yeah, these forums aren't exactly very active. Checking the post date of the original poster is a good idea, because its usually a time-sensitive issue. Again, don't worry about it, if worst comes to worst, you'll get an official warning, which doesn't mean much until they add up.
     
  7. Phee

    Phee Moderator
    Staff Member

    Joined:
    Aug 18, 2007
    Messages:
    6,206
    Likes Received:
    101
    Re: Complete DTM Tutorial

    SRL isn't really the same genre as NF, so it should be fine. Nice tut. :)
     
  8. Dusk412

    Dusk412 Level I

    Joined:
    Aug 2, 2008
    Messages:
    88
    Likes Received:
    9
    Re: Complete DTM Tutorial

    Thanks, I will write/post some more later.