After looking into the code snippets beneficial to my SQL Shaiya database, it has come to my attention that doing this project in c++ will have a much better outcome than VB.net. I've been playing with c++ GetPixel() and SetPixel() and have decided that it would come in really handy for players that dont like playing in windowed mode.

GetPixel() retrieves an RGB value of a pixel at any coordinate of your chosing. The script i designed to test my theory works by asking the player for an umber of Pixel locations by pressing CTRL when the mouse is hovering over the destination, and again for each instance. After all pixel locations have been set, the program runs a continuous loop to read those same pixels until the color changes (at this point, it doesn't care what color it is, was, or will be, it just flags when it has changed, and for each instance).

In Lamens terms, If you set 3 pixel watchers in the game, 1 for HP minimum, 1 for MP minimum, 1 for Stamina minimum, the program would raise a flag when the color was no longer what it was (for this instance, it was Red, now it's Black (almost dead). You could easily add the function "emulate keypress (Z or X) for whichever hot-key would recover the missing stat.

In 2nd example, If you set up a point-to-point loop to check every pixel from coordinate 1 to coordinate 2, you could retrieve (for instance) what % exp you have every minute (rather than every loop cycle). have it store the last 30 values, average them, and then give you a time frame of how long it would take to level at the same rate. Limiting this by 30 minutes allows you to keep it accurate after you go afk.

Now, I've also determined that SetPixel() could be used to re-draw the minimap with a better detailed, pre-defined version. For instance... I can use GetPixel() around the in-game coordinate (toggled on/off with H key) and match the numbers to pre-set bitmaps, the program could determine where you are, hide your minimap, and draw a new one pixel-by-pixel from your coordinates, and draw friendlies using the same program on it as well... Not to mention the availability of a Quest Tracker addon function later programmed, with color-codes to show the player where he/she should be grinding.

This would of course lead to the function of "run to location" using key-coordinated pre-defined routes in order to get to wherever it is you wanted to get to. ^.^ yay for botting.

heres the source so far... c++ Win32 Console


Code:

#include <windows.h>
#include <iostream>
using namespace std;
#define MAXCOORDS 2

POINT pt;
struct coord {
   int x;
   int y;
};

struct RGBcolor {
   int RED;
   int GREEN;
   int BLUE;
};
struct pixel {
   coord Loc;
   RGBcolor Now;
   RGBcolor Was;
};
pixel PLoc[MAXCOORDS];

coord GetMouse(void) {
   coord cCoord;
   
   GetCursorPos(&pt);
   cCoord.x = (pt.x);
   cCoord.y = (pt.y);

   return cCoord;
}
RGBcolor GetPixelRGB(coord Dest) {
   RGBcolor retVal;
   HDC hdcScreen = GetDC(0);
   COLORREF crPixel = GetPixel(hdcScreen,Dest.x,Dest.y);
   ReleaseDC(0,hdcScreen);

   retVal.RED = GetRValue(crPixel);
   retVal.GREEN = GetGValue(crPixel);
   retVal.BLUE = GetBValue(crPixel);

   return retVal;
}
short CTRLStateNow = 0, CTRLStateThen = 0;
int CNTRLPressed(void) {
   int CTRLPressed = 0;
   CTRLStateNow = GetAsyncKeyState(VK_CONTROL);
   if (CTRLStateNow != CTRLStateThen) { // key state changed
      //cout << "Value= " << CTRLPressed << "." << endl;
      if (CTRLStateThen == 0) { // key down
         CTRLPressed = 1;
      } else { // key held or released
         if (CTRLStateNow == 0) { // released
            CTRLPressed = 3;
         } else { // held
            CTRLPressed = 2;
         }
      }
      CTRLStateThen = CTRLStateNow;
   }
   return CTRLPressed;
}
int main()
{
   for (int a=0;a<MAXCOORDS;a++) {
      cout << "Hover on coordinate " << a+1 << ", then press CTRL..." << endl;
      while (true) {
         if (CNTRLPressed() == 3) { break; }
      }
         // get pixel location
         PLoc[a].Loc = GetMouse();
         // get pixel color
         RGBcolor GotRGB = GetPixelRGB(PLoc[a].Loc);
         PLoc[a].Now = GotRGB;
         // print data
         cout << "C" << a+1 << "(" << PLoc[a].Loc.x << ", " << PLoc[a].Loc.y << ") = r" << PLoc[a].Now.RED << "g" << PLoc[a].Now.GREEN << "b" << PLoc[a].Now.BLUE << ";" << endl;
   }

   while (true) {
      RGBcolor GotRGB;
      for(int i=0;i<MAXCOORDS;i++) {
         GotRGB = GetPixelRGB(PLoc[i].Loc);
         if (GotRGB.RED != PLoc[i].Was.RED || GotRGB.GREEN != PLoc[i].Was.GREEN || GotRGB.BLUE != PLoc[i].Was.BLUE) { // pixel changed
            cout << "Pixel " << i+1 << " changed!" << endl;
            PLoc[i].Was = PLoc[i].Now;
            PLoc[i].Now = GotRGB;
         }
      }
   }
   system("pause");

   //DeleteDC(hdcScreen);

   return 0;

}
GetPixel is not a C++ feature, it's a Windows function. Off the top of my head, here's how you can use it from VB:


Code:
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As IntPtr, ByVal X As Int32, ByVal Y As Int32) As Int32
Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As IntPtr) As IntPtr
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Boolean

Dim desktopDC As IntPtr = GetDC(IntPtr.Zero)
Dim colour As Color = Color.FromArgb(255, Color.FromArgb(GetPixel(desktopDC, 10, 20)))
ReleaseDC(IntPtr.Zero, desktopDC)

Similar rules apply to SetPixel.

Of course, you can still do it in C++ if you're feeling particularly masochistic. Wink
It's "Laymen's terms", by the way. I generally dislike Visual BASIC just out of principle, but if it's easier than C++, I suppose it's no use making your life harder than it needs to be.
hmm, it's more of a matter of simplicity... a VB SQL database can be made in a matter of minutes without much of any complications. this app is actually c++ win32 console (dos console window), but c++ win32 apps aren't technically 'hard', its just annoying getting around the auto-ascii programming (makes using strings hella difficult).

As far as this application goes, so far its teaching me how to manipulate pixels, but a downside is that it eats resources like theres no tomorrow when Shaiya is the main app. I can literally see the cout printing char by char... task man proves its raping my resources, so i gotta find a cure for that.

I wish i could find a better way to scan and compare pictures, since doing pixel-by-pixel might further exhaust resources. It surely wont stay in console format, since there needs to be some things interacted with, but this is good for testing stages to figure out just what the function is capable of.

the code to connect to a SQL database in vb is as follows:



Code:

        Dim conn As New SqlClient.SqlConnection
        Dim sql As New SqlClient.SqlCommand
        Dim adapter As New SqlClient.SqlDataAdapter
        Dim ds As New DataSet
        Dim ConnectionString As String = "Data Source=KITSUNE\SQLEXPRESS;Initial Catalog=Messages;Integrated Security=True;Pooling=False"

        Dim Topics(1) As String
        lbTopics.Items.Clear()
        conn.ConnectionString = ConnectionString
        Try
            sql.CommandText = "SELECT NAME FROM sysobjects WHERE type = 'U'"
            conn.Open()
...


while c++ is as follows (different sql database) give or take, haven't played with it since i reformatted and used microsofts sqlexpress 2008

Code:

...
#define ConnectionString "DSN=GAMING;Uid=windows;Pwd=w1nd0w5;"
...
int main(void){
    // Lets set a string to talk to the SQL
    SQLHANDLE sqlenvhandle;   
    SQLHANDLE sqlconnectionhandle;
    SQLHSTMT sqlstatementhandle;
    SQLRETURN retcode;
   SQLCHAR Name[100];
   SQLINTEGER NameLen;
   int xloc,yloc;

    if(SQL_SUCCESS!=SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &sqlenvhandle))
        goto FINISHED;

    if(SQL_SUCCESS!=SQLSetEnvAttr(sqlenvhandle,SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0))
        goto FINISHED;
   
    if(SQL_SUCCESS!=SQLAllocHandle(SQL_HANDLE_DBC, sqlenvhandle, &sqlconnectionhandle))
        goto FINISHED;
   cout << "Connecting to SQL..." << endl;
    SQLCHAR retconstring[1024];
    switch(SQLDriverConnect (sqlconnectionhandle,
                NULL,
                      (SQLCHAR*)ConnectionString,
            SQL_NTS,
                retconstring,
                1024,
                NULL,
                SQL_DRIVER_COMPLETE)){
        case SQL_SUCCESS_WITH_INFO:
         cout << "Connec() - SQL_SUCCESS_WITH_INFO" << endl;
            show_error(SQL_HANDLE_DBC, sqlconnectionhandle);
            break;
        case SQL_INVALID_HANDLE:
         cout << "Connect() - SQL_INVALID_HANDLE" << endl;
        case SQL_ERROR:
         cout << "Connect() - SQL_ERROR" << endl;
            show_error(SQL_HANDLE_DBC, sqlconnectionhandle);
            goto FINISHED;
        default:
            break;
    }
    cout << "SQL Connected!" << endl;


and that just connects, doesn't even ask for data... and on the other hand, the VB environment can be set up in 5 minutes, vs c++ win32 taking 25+ to get things right...
Hey, something i'm finding as a problem... When i run the program beside Shaiya, it suddenly eats up a lot of processes (bounces from 30% to 99%) ultimately lagging my gameplay. Right now it's only being run in a Win32 Console application, does anyone have any idea how to resolve this issue?
Have you tried profiling the application?
No, i don't believe this form of profiling will ultimately benefit the extent of the project. I'm not sure, but i believe a degree of the issue is that it isn't in a window environment, meaning windows doesn't allocate the memory for the app appropriately. I'm looking into the VB.net equivalent to test the theory, but i don't know that my results will be reliable.
Well, it's worth a try anyway; I look forward to the results of you testing your theory.
Komak57 wrote:
Hey, something i'm finding as a problem... When i run the program beside Shaiya, it suddenly eats up a lot of processes (bounces from 30% to 99%) ultimately lagging my gameplay. Right now it's only being run in a Win32 Console application, does anyone have any idea how to resolve this issue?


GetPixel/SetPixel are *sllloooowwwww*.

Avoid like the plague.

Also, posting code helps.

Komak57 wrote:
hmm, it's more of a matter of simplicity... a VB SQL database can be made in a matter of minutes without much of any complications. this app is actually c++ win32 console (dos console window), but c++ win32 apps aren't technically 'hard', its just annoying getting around the auto-ascii programming (makes using strings hella difficult).


lol wut?

Strings are easy, wtf are you doing?
hey kllr, long time to talk >.< and the code is up above :3 very simple win32 console app... ditched vb as it's not fluent enough, spending hours working on c++ win32 window.... its exhausting making it by hand... almost got something working though
Komak57 wrote:
[...] its just annoying getting around the auto-ascii programming (makes using strings hella difficult).
Umm, what? I missed that the first time around; what exactly do you mean? Strings are beyond trivial. What's "auto-ASCII" programming?
ehh, by default, MSVS 2008 (amoungst others) default CreateWindow() to CreateWindowW() (unicode) rather than CreateWindowA() (non unicode). Although there isn't a difference between their functionality or look, CreateWindowW() requires any text, strings, or other character variables to be within TEXT() brackets, or _T() brackets... I had this problem a while back when i attempted to make a win32 mIRC client. I succeeded, but because of all the workarounds, it would error out in the middle of runtime. Never could figure out why, so i dropped the project till i come across new information
Windows NT uses Unicode throughout. If you use any of the ANSI versions of functions then Windows will convert to and from ANSI automatically for you. Think of the ANSI versions as a backwards compatibility workaround, if anything.

CreateWindowW() requires that you pass a "wide" (Unicode) string, which in C or C++ would be denoted L"like this" (as opposed to "like this"). The TEXT() macro will use L"Unicode" or "ANSI" depending on whether UNICODE has been defined, much like the way UNICODE controls whether the CreateWindow macro expands to CreateWindowW or CreateWindowA. Using TEXT() is a matter of convenience, as you can then switch your project between using Unicode or ANSI strings without having to change all the literals.

Really, it's best to just use the Unicode functions throughout your program (unless you're targeting Windows 95 or similar). Visual Studio switched to UNICODE being defined by default with the 2005 version. Bear in mind that some newer functions are only available as Unicode versions (though you can of course manually convert to/from ANSI manually).
Yeah, i ended up finding a workaround some time back when dealing with the irc client... I found that i can let the window run unicode as default, but rewrite the buttons and their commands as ANSI. This helped a lot in the long-haul. But that was some very useful information ^.^ thanks.

Still workin on the project in the parts of my day that aren't consumed by my gf or some headache... Ill get the results to ya when its working.
I've been working on a c++ Win32 application and im coming across some variable conversion issues >.<


Code:

void Cycle() {
   RGBcolor GotRGB;
   for(int i=0;i<MAXCOORDS;i++) {
      GotRGB = GetPixelRGB(PLoc[i].Loc);
      if (GotRGB.RED != PLoc[i].Was.RED || GotRGB.GREEN != PLoc[i].Was.GREEN || GotRGB.BLUE != PLoc[i].Was.BLUE) { // pixel changed
         //cout << "Pixel " << i+1 << " changed!" << endl;
         char PxlColor;
         int cAverage = (PLoc[i].Was.RED + PLoc[i].Was.GREEN + PLoc[i].Was.BLUE) / 3;
         int cMax = PLoc[i].Was.RED; PxlColor = 'R';
         if (PLoc[i].Was.GREEN > cMax) { cMax = PLoc[i].Was.GREEN; PxlColor = 'G'; }
         if (PLoc[i].Was.BLUE > cMax) { cMax = PLoc[i].Was.BLUE; PxlColor = 'B'; }
         int cMin = PLoc[i].Was.RED;
         if (PLoc[i].Was.GREEN < cMax) { cMax = PLoc[i].Was.GREEN; }
         if (PLoc[i].Was.BLUE < cMax) { cMax = PLoc[i].Was.BLUE; }
         if ((cMax - cAverage) < 50) {
            if (cAverage > 200) {
               PxlColor = 'W';
            } else if (cAverage < 100) {
               PxlColor = 'B';
            } else {
               PxlColor = '?';
            }
         }

         //cout << "PXL_" << i+1 << " is now " << PxlColor << endl;
         //cout << "Max " << cMax << ",Avg " << cAverage << endl;
         std::ostringstream sRED, sGREEN, sBLUE;
         sRED << PLoc[0].Now.RED;
         //const char *RED = sRED;
         sGREEN << PLoc[0].Now.GREEN;
         //const char *GREEN = sGREEN;
         sBLUE << PLoc[0].Now.BLUE;
         //const char *BLUE = sBLUE;

         SetDlgItemText( hWnd, 1012, (LPCSTR) PLoc[0].Now.RED);
         SetDlgItemText( hWnd, 1013, (LPCSTR) PLoc[0].Now.GREEN);
         SetDlgItemText( hWnd, 1014, (LPCSTR) PLoc[0].Now.BLUE);
         PLoc[i].Was = PLoc[i].Now;
         PLoc[i].Now = GotRGB;
      }
   }
}


when this cycle runs, the editboxes are empty... Debugging determines that the integers have values, and the SetDlgItemText() function works, but applying the int just isn't working =.= I've looked at a few workarounds like making ostringstream's, sprintf(), but they just refuse to make values =.=
I'm not sure how you arrived at that code, but I suspect the main issue is passing an ANSI string to a Unicode function. I'd recommend using _sntprintf_s to print/format the number to a TCHAR array before passing to SetDlgItemText. Alternatively, if using C++ strings (std::string) you'll need to pass the pointer returned by c_str() to SetDlgItemTextA.
Thanks for your help, Benryves. Smile Komak57, in the future, please try to avoid double-posting, , especially within fewer than three hours like that.
I was thinking about editing the previous post, but thought it would look a lil cleaner in a new one...

Now, come to find out with some pretty deep research, that the function SetDlgItemText() specifically for text... they've got their own function for integers >.> SetDlgItemInt(). Lousy MS =.='
By "pretty deep research" you mean looking at the "See Also" bit at the bottom of the documentation for SetDlgItemText? Razz

You should still have a go at trying to get the string version to work as it seems this is a region of C++ that is causing you difficulties.
lol, yes... that's exactly where i found it... and actually, its the ONLY place i found it... had to rummage through about 30 Google pages between 7 variations of the same search texts to figure it out =.=

Anyways, onto the next topic... I want to figure out EXACTLY how much exp i have, and the only 2 ways to do it, is

A) Manually typing it into the window. This process takes time away from playing to access the calculator bit and is a bit unwanted.

B) Picture/Pixel scanning and converting picture->integers. The only way i can think to do this is GetPixel() around the area where the text is and use a "general match" method to identify where the text is, and what digits are displayed. That function of GetPixel (as told earlier) is REALLY slow.

I'd like some input on other ways to do this. The bar in the bottom left only shows a blue bar, and %. Watching this bar or reading the % text could give me a general idea of how much exp there is, which would indeed give a very estimate in time necessary to level at the current rate, but not much more than that. If you hover your mouse over it, the HAVE/NEED exp is shown in a small tool-tip. And if you open up your character sheet (T) it also shows your exp (with bar).

Knowing that the background of the bar is either multiple shades of blue (vertical color span, lightest in center) or completely black, and the text is always a few shades of white, what recommendations are there for stripping graphic->integer? Or should i stick to reading the color pixels at the bottom of the screen?

Screen-shot of game-play, image too big to display with img tag without obscuring view of other information.
http://img141.imageshack.us/img141/9009/shaiya0010g.jpg
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 2
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement