#Recovery Mode

User Tag List

Results 1 to 3 of 3

[Tut] How to code your own bot

This is a discussion on [Tut] How to code your own bot within the Tutorials & Guides forums, part of the Programming & Reversing category; This is a tutorial to teach players how to create simple bots that help enhance MapleStory gameplay. It does not ...

  1. 07-14-2012, 01:05 AM
    #1

    Leecher

    Expand


    • My Statistics

    Default [Tut] How to code your own bot

    This is a tutorial to teach players how to create simple bots that help enhance MapleStory gameplay. It does not showcase techniques that read into process memory to do various hacks like Godmode.

    For an easier time, you will require:
    - Basic knowledge of programming


    What is a bot?
    Bots are generally harder to catch compared to other types of hacks. This is because the victim application cannot detect if the bot is a human or a computer. This is perfect for users who don't want to be banned.

    Let's take a simple bot: auto looting. Auto looting is basically spamming the loot key whenever there is an item on the ground. The bot does not care whether if there is an item on the ground. It just spams the LOOT key every X milliseconds.

    Of course, you can extend an autoloot bot to read process memory to modify the drops or increase the item drop speed. But that is not covered in this tutorial. This type of hack is harder to make. Sometimes, these hacks are just not possible because the MapleStory server checks the client data. If I am not wrong, drops are controlled by the server.


    Case study
    Do you know why MouseFly teleport auto DCs after a few minutes? This is because it reads the client's process memory for the character position and replaces it with the mouse position. This hack did not DC in early Maple, and as a result, you can see hackers VAC-ing on the top right/left side of the map.

    However, MapleStory's developers are smarter now. The server checks the character position every few minutes. If the character is always flying, the server knows the something is wrong and you get DC'ed. It doesn't check too often though, because what if the player is legit, but is lagging very badly.


    Then, how do you code an autoloot?
    In Windows, you have the Win32 API. This API allows you to stimulate keyboard, mouse or joystick input. There are different APIs for different operating systems. Let's talk Windows.

    Code:
    INPUT input;
    input.ki.wVk = key;
    input.ki.wScan = MapVirtualKey(key, MAPVK_VK_TO_VSC);
    input.ki.dwFlags = 0; // KEYEVENTIF_KEYUP
    input.ki.time = 0;
    input.ki.dwExtraInfo = 0;
    input.type = INPUT_KEYBOARD;
    SendInput(1, &input, sizeof(INPUT));
    The code above sends an input event to the active window. Some notes:
    - You can send multiple events at once
    - You can send either a KEYUP event or KEYDOWN event.
    - A key remains down until you release it via another KEYUP event.
    - It does not require you to have a handle to the MapleStory window.

    Most autoloot programs do not use SendInput() to stimulate input (at least not autoloot). They use:

    Code:
    HWND inputWindow = FindWindow(NULL, TEXT("MapleStory"));
    PostMessage(inputWindow, WM_KEYDOWN, key, (MapVirtualKey(key, MAPVK_VK_TO_VSC) << 16) + 1);
    PostMessage() requires you to have a handle to the MapleStory window. It is perfect for single keypresses like autoloot.

    You must keep in mind however, that stimulating input in an executable does not work. This is because MapleStory does not read input from external applications. You must package your "executable" as a DLL to be injected into the MapleStory client.

    Another thing about injection, injection basically hooks a third-party program to an executable. You can inject anything as long as it can be executed. Thus, all files that you download can contain a virus. A simple AutoIt script can contain a virus - it is not an executable, but plain text, yet it could be a virus. Windows is generally very safe, this is because all application memory has DEP (data execution protection) but the average joe doesn't know which applications need access rights and which don't. Thus, when you accept a UAC dialog, you might have grant a third-party program access to read another program's memory space. E.g. Your MapleStory login can be read from memory without even using a keylogger. Be careful!


    Delay - something very important
    You need to know how to delay the program. If you keep spamming input to the MapleStory, you will hog your CPU for nothing. Most of your bot's time should be spent waiting. No use spamming, MapleStory input (and in fact most game's input) is highly based on timing.

    Code:
    Sleep(timeInMilliseconds);

    Putting it together
    Generally, you want to create a DLL to inject into MapleStory. I'm giving a barebones code to those who are starting from scratch. I wrote this from the top of my head. Don't blame me for any errors.

    Code:
    #include  <string>
    #include  <windows.h>
    #include  <windowsx.h>
     
    #define  INPUT_WINDOW    TEXT("MapleStory")
     
    DWORD WINAPI dialogThread(LPVOID);
     
    HINSTANCE hInstance;
    HANDLE hDialogThread;
    bool isRunning;
     
    BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
      if(ul_reason_for_call == DLL_PROCESS_ATTACH) {
        hInstance = hModule;
        DisableThreadLibraryCalls(hModule);
        isRunning = true;
        hDialogThread = CreateThread(NULL, 0, dialogThread, NULL, 0, NULL);
      }
      else if(ul_reason_for_call == DLL_PROCESS_DETACH) {
        isRunning = false;
      }
      return TRUE;
    }
     
    DWORD WINAPI dialogThread(LPVOID) {
      hInputWindow = FindWindow(NULL, INPUT_WINDOW);
      // you can check if MapleStory window is open
      // you can create your own dialog or forms here
      // you can spawn more threads here
      while(isRunning) {
        // terminate when MapleStory window doesn't exist
        hInputWindow = FindWindow(NULL, INPUT_WINDOW);
        if(hInputWindow == NULL) {
          isRunning = false;
          break;
        }
     
        // message processing if you have a dialog
        // do other stuff here
        Sleep(50); // runs the loop at 20 iterations per second
      }
     
      // free up stuff
      CloseHandle(hDialogThread);
      return 0;
    }
    Another note, if you are actually going to inject a DLL into MapleStory across multiple computers (not only on your development machine), I highly recommend you do so using the Multi-Threaded DLL runtime instead of the Debug runtime. It should increase performance by 2x - 100x depending on your code since it uses the optimized version of the standard library instead of the debug verbose version.

    To do this, go to "Microsoft VS >> (right-click your project in Solution Explorer) >> Config Properties >>> C/C++ >>> Code Generation >>> Runtime Library >>> select /MD option".
    Or alternatively, the default MSVC project already includes a release mode that configures everything nicely for you with Program optimization (LTCG) and whatnot. Use that instead of Debug when compiling your DLL.


    Moving on to complicated bots - an example
    Now, let's say you have a Demon Slayer character and you want to:
    1. Move your character left.
    2. Use the basic attack 4 times (hit the full attack).
    3. Jump down to next platform.
    4. Perform basic attack (x4) again.

    All this, while autolooting at the same time, and autopotting as well.

    To do this, I create two threads in DllMain(). One "MainThread" is for doing the main stuffs (1-4). The other "SpamThread" is for doing autoloot and autopot. I will explain the SpamThread first because it is simpler.

    Autoloot is simple. I spam PostMessage() every let's say 100 milliseconds. GetTickCount() is Win32 API version of a high-resolution timer. Example:

    Code:
    if(autoLootTicks < GetTickCount()) {
       // press autoloot via PostMessage()
       autoLootTicks = GetTickCount() + 100; // next update at 100 ms
    }

    Now the question is, How do I autopot?
    There are two types of autopotting in MapleStory: one is to read from process memory for current HP value. Another is to take a screenshot and check the pixel value of the MapleStory HP/MP bar. Since this tutorial does not read process memory. I will teach you the latter.

    This is how you take a screen capture of a MapleStory window. This does not work in fullscreen mode because in fullscreen mode, the Win32 API doesn't output to GDI (for DirectX applications) anymore, but DirectX's frame buffers. Involving DirectX is out of the scope of this tutorial.

    Code:
    HBITMAP getScreenShot(HWND hWnd) {
      int w = getWindowWidth(hWnd);
      int h = getWindowHeight(hWnd);
     
      HDC hInputWindowDC = GetDC(hWnd);
      HDC hCompatibleDC = CreateCompatibleDC(hInputWindowDC);
     
      HBITMAP hResultBitmap = (HBITMAP)SelectObject(hCompatibleDC, CreateCompatibleBitmap(hInputWindowDC, w, h));
      BitBlt(hCompatibleDC, 0, 0, w, h, hInputWindowDC, 0, 0, SRCCOPY);
      hResultBitmap = (HBITMAP)SelectObject(hCompatibleDC, hResultBitmap);
     
      DeleteDC(hCompatibleDC);
      DeleteDC(hInputWindowDC);
      return hResultBitmap;
    }
    It's scary how simple this function is. Imagine a hacker taking a screenshot 150x150 pixels around your mouse everytime you click when you log into MapleStory.

    After you get the screenshot, you will want to read the pixel value on the HP bar. This is an example...

    Code:
    #define  HPBAR_X 267 // at 10% pixel mark of HP bar
    #define  HPBAR_Y 25
     
    #define  MPBAR_X 438 // at 10% pixel mark of MP bar
    #define  MPBAR_Y 25
     
    int w = getWindowWidth(hInputWindow);
    int h = getWindowHeight(hInputWindow);
     
    int hpBarX = HPBAR_X;
    int hpBarY = h - HPBAR_Y;
    int mpBarX = MPBAR_X;
    int mpBarY = h - MPBAR_Y;
     
    SelectObject(hDC, hBitmap);
    if(GetRValue(GetPixel(hDC, hpBarX, hpBarY)) < 0xcc) {
      // press HP pot button via PostMessage()
    }
    if(GetBValue(GetPixel(hDC, mpBarX, mpBarY)) < 0xcc) {
      // press MP pot button via PostMessage()
    }
    DeleteObject(hBitmap);
    I made it simple, you just read one pixel on the HP and MP bar. If it blinks (HP/MP alert), you need to repot your HP via PostMessage(). This works on both 1024x768 and 800x600, but it needs to update often (maybe 100ms). You can optimize this by taking a screenshot of 1x1 pixel. The following code is more optimized by taking a screenshot of only the HP and MP bar.

    Code:
    HBITMAP getScreenCapture(HWND hWnd, int x, int y, int w, int h) {
      HDC hInputWindowDC = GetDC(hWnd);
      HDC hCompatibleDC = CreateCompatibleDC(hInputWindowDC);
      HBITMAP hResultBitmap = (HBITMAP)SelectObject(hCompatibleDC, CreateCompatibleBitmap(hInputWindowDC, w, h));
      BitBlt(hCompatibleDC, 0, 0, w, h, hInputWindowDC, x, y, SRCCOPY);
      hResultBitmap = (HBITMAP)SelectObject(hCompatibleDC, hResultBitmap);
      DeleteDC(hCompatibleDC);
      DeleteDC(hInputWindowDC);
      return hResultBitmap;
    }
    HBITMAP getScreenShot(HWND hWnd) {
      return getScreenCapture(hWnd, 0, 0, getWindowWidth(hWnd), getWindowHeight(hWnd));
    }
    HBITMAP getHPBar(HWND hWnd) {
      return getScreenCapture(hWnd, 250, getWindowHeight(hWnd) - 33, 141, 14);
    }
    HBITMAP getMPBar(HWND hWnd) {
      return getScreenCapture(hWnd, 421, getWindowHeight(hWnd) - 33, 141, 14);
    }

    So that's settled, how do I code for the MainThread?
    Well, the thing about MapleStory, the arrow keys and some skills do not use PostMessage() and there is a delay time you must meet. Skills do not cast properly if you do not meet the correct character "posture" and delay.

    For example, jump time is around 200-300ms before you can double jump (FJ, Demon Slayer high jump). If you just spam jump at 50 ms, you are going to have a very random action when your bot has complex actions. And the reason why I chose Demon Slayer as an example is because it's 4 basic attacks have a timing. To execute the full attack, you have to figure out the timing between each attack.

    Another example: Mercedes's Leaf Tornado... you can bot it, but you need to cast Leaf Tornado only 200 ms after the initial jump. Some buff skills need longer time to cast, while some are faster. Doing it on a rope usually increases the cast speed.

    Somemore hints: Do not move when attacking or buffing. If you move, the bot becomes more unpredictable. You can't just spam a single button repeatedly.

    1. Move your character left for 1000ms (about 300pixels).
    keydown LEFT, delay 1000ms, keyup LEFT, delay 1000ms.

    2. Use the basic attack 4 times (hit the full attack).
    keydown C, delay 100ms, keyup C, delay 150ms.
    keydown C, delay 100ms, keyup C, delay 150ms.
    keydown C, delay 100ms, keyup C, delay 200ms.
    keydown C, delay 100ms, keyup C, delay 500ms.

    3. Jump down to next platform.
    keydn DOWN, delay 50
    press SPACE, delay 50
    keyup DOWN

    4. Perform basic attack (x4) again.

    This is by far the most tedious part to complete. But it is the most enjoying. With 100% stance in Adventurer warriors, Demon Slayer and mechanics, you can train without being at the computer and nobody would know you are a bot!!

    Tip: When you code a bot, set a spot (bottom left, or bottom right is good) to "reset" your bot. For example, you start at bottom right, you should end at bottom right with some degree for error. Move left 1 second, move right 1.1 seconds. This ensures that even if left occurs for an extra 0.1 seconds, you still start at your original spot.


    Bonus, how to text message?
    I realise a lot of people like to translate the message themselves. Which is really really stupid.

    Code:
    std::wstring x = L"The quick brown fox jumps over the lazy GM.";
    for(size_t i=0; i<x.size(); ++i) {
      PostMessage(inputWindow, WM_CHAR, x[i], (MapVirtualKey(x[i], MAPVK_VK_TO_VSC) << 16) + 1);
      Sleep(20);
    }
    You must press ENTER once before texting, and ENTER twice after texting.


    Background of this tutorial
    I wrote this tutorial based on a realtime scriptable MapleStory bot that I wrote by myself. It started when I got sick of picking up items during training (I wanted an autoloot originally). I found either every MapleStory trainer connected to the Internet (for no reason), or could not configure to the autoloot key I wanted. So I decided to make my own bot.

    I hated the idea of hardcoding my bots. So I created a scriptable engine with a simple dialog opened next to the MapleStory window for realtime updates via the F1 key.

    Eventually, I was tempted to learn how to move my character in-game so that I can train my character more easily. Then, I thought, hey, Demon Slayers cannot be knocked backed, so I thought, could it be used for training? Yup, MapleSEA just recently released Demon Slayer.

    Thus, I decided to help people who like me, want simple and highly configurable bots (not just for MapleStory), but not want to deal with the trainers or other weird bots. Everything I found out is based on trial and error, and a little research on MSDN.

    Just to give you ideas, my scriptable bot is like Lua, XML, INI, but much much simpler. These are the functions:
    spam KEY DELAY <<< in it's own spam thread
    # << comment
    keyseq KEY DELAY_TIME_BEFORE_KEYUP DELAY_TIME_AFTER_KEYUP << combination of keydn, delay, keyup, delay
    keydn KEY
    keyup KEY
    delay MS
    text MESSAGE
    begin_section TOGGLE_KEY N_RUNS <<< 0 N_RUNS = toggle on/off, otherwise, run N times when key is pressed. It launches another child thread to run the script section in parallel. Useful for skill casts (HS mule anyone?).
    end_section
    autohp KEY <<< presses a key once (delay of 500ms) when the HP bar is blinking
    automp KEY

    Press F1 in the main program to toggle on/off.

    This is a sample of my realtime scriptable bot. My key settings are: F- attack, A - loot, B - raven storm, C - booster, Z - vengeance, X - black heart strength, D - thrust, G - vortex of doom, H - poison breath thingy. Some long delays are because of skill cast timings. I ran the Elin Forest script on VMware and managed to train from levels 97 - 106 while doing my other work on the computer in about 10 hours. This bot is not a miracle trainer.

    Code:
    # Hacker KS bot
    # Irritates hackers that come into your map. You must be present to entertain the hacker though.
    # auto loot
    spam A 100
    # start at hacker left
    # cast buffs
    keyseq C 800 1000
    keyseq Z 800 1000
    keyseq X 800 1000
    # heal
    delay 500
    keyseq B 500 1000
    # right attack
    keyseq RIGHT 1000 1000
    keyseq LEFT 100 100
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    # left attack
    keyseq LEFT 1000 1000
    keyseq RIGHT 100 100
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    # heal
    delay 500
    keyseq B 500 1000
    # right attack
    keyseq RIGHT 1000 1000
    keyseq LEFT 100 100
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    # left attack
    keyseq LEFT 1000 1000
    keyseq RIGHT 100 100
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    # heal
    delay 500
    keyseq B 500 1000
    # right attack
    keyseq RIGHT 1000 1000
    keyseq LEFT 100 100
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    # left attack
    keyseq LEFT 1000 1000
    keyseq RIGHT 100 100
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    # heal
    delay 500
    keyseq B 500 1000
    # right attack
    keyseq RIGHT 1000 1000
    keyseq LEFT 100 100
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    # left attack
    keyseq LEFT 1000 1000
    keyseq RIGHT 100 100
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    # heal
    delay 500
    keyseq B 500 1000
    # right attack
    keyseq RIGHT 1000 1000
    keyseq LEFT 100 100
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    # left attack
    keyseq LEFT 1000 1000
    keyseq RIGHT 100 100
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 500
    delay 1000
    Code:
    # Ellin Forest - Mossy Tree Forest Entrance
    # auto loot
    spam A 100
    # auto pot
    # spam DELETE 90000
    # start from bottom right
    keyseq LEFT 1200 500
    # jump to platform
    keyseq SPACE 100 0
    keyseq UP 2000 0
    # at middle right platform
    # cast buffs
    keyseq C 500 1000
    keyseq X 500 1000
    keyseq Z 500 1000
    keyseq B 500 200
    # move to top platform
    keydn LEFT
    keydn UP
    delay 2000
    keyup UP
    keyup LEFT
    keyseq UP 1000 200
    # at top platform
    # attack 1
    keyseq LEFT 1500 1000
    keyseq G 500 1000
    keyseq H 1500 1000
    keyseq LEFT 500 1000
    # move to middle platform
    delay 1000
    keydn DOWN
    delay 50
    press SPACE
    delay 50
    keyup DOWN
    # at middle platform
    # attack 2
    keyseq RIGHT 2000 1000
    keyseq LEFT 200 1000
    keyseq D 200 200
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 200
    # attack 3
    keyseq LEFT 800 1000
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 200
    keyseq LEFT 2000 200
    # at bottom left
    # attack 4
    keyseq RIGHT 200 1000
    keyseq D 200 200
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 200
    # attack 5
    keyseq RIGHT 500 1000
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 200
    # attack 6
    keyseq RIGHT 1200 1000
    keyseq D 200 200
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 200
    # attack 7
    keyseq RIGHT 500 1000
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 200
    # attack 8
    keyseq RIGHT 1200 1000
    keyseq D 200 200
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 200
    # attack 9
    keyseq LEFT 500 1000
    keyseq F 100 150
    keyseq F 100 150
    keyseq F 100 200
    keyseq F 100 200
    keyseq RIGHT 2000 1000

    I don't hold any responsibility if the code does not work or crashes your computer. Good luck creating your own bots.
    Last edited by fellowusertoo; 07-14-2012 at 08:37 PM.

  2. The Following 3 Users Say Thank You to fellowusertoo For This Useful Post:

    helvetica (07-14-2012), Numa (09-11-2012), Veigar (07-19-2012)

  3. 07-19-2012, 01:42 AM
    #2

    The New Guy

    Expand


    • My Statistics

    Default Re: [Tut] How to code your own bot

    There is no reason to spawn a new thread. Use a
    [Dear Visitor, you're restricted from viewing links until you are registered & logged on.
    Click Here To Register Today
    or another event-driven mechanism instead.

  4. 04-28-2013, 09:13 AM
    #3

    The New Guy

    Expand


    • My Statistics
    2
    SoapSkillz
    Male Male
    Created: 04-27-13
    Type: Partially Cracked Egg
    88%

    Default Re: [Tut] How to code your own bot

    Thx man

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •