Go Back   UnKnoWnCheaTs - Multiplayer Game Hacks and Cheats > First-Person Shooters > Other FPS Games > Medal Of Honor Series > Allied Assault

- Sponsored Advertisement -
http://www.myfpscheats.com/

Welcome to the UnKnoWnCheaTs - Multiplayer Game Hacks and Cheats.
You have to register before you can post and see and access any of the advanced forum features, please click the register link to proceed to the registration form. To start viewing threads or posts, select a forum that you want to visit from the selection below.
Allied Assault
hacks cheats tutorials downloads source code
You are Unregistered, please register to gain Full access.    
Reply
 
Thread Tools

Creating a MOHAA Menu
Old 01-25-2009, 03:07 PM   #1


m0d hipp„'s Avatar

Join Date: Jun 2005
Posts: 1,362
Reputation: 8369
Rep Power: 0
m0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATS
Cliff Diver Champion
Last Achievements
Creating a MOHAA Menu

Here is my first menu I have ever created for MOHAA. After tedious amount of work, trial & errors, crashes and compile errors, I have finally established a solid based MOHAA Menu, that I would like to share how to create from scratch using the MOHAA cgame wrapper.

Tools needed:
A c++ compiler (I used Visual C++)
Cgamex Wrapper found here (http://mohdev.mods-r-us.net/index.php?id=cgame)
Props to wombat for this awesome hook.

That's pretty much all you need. Now this tutorial will be based off copy\paste code, but to understand it properly you need some c++ programming exposure as well as understanding how MOHAA works. Also you will have to reverse the classes\structs yourself.

First thing I did was create a custom cvar. I declared it globally like so:
Code:
cvar_t *menu;
Next in CG_Init (which was already added by wombat), you will need to define your cvar & its parameters in here. So wombat already added a test cvar called "testcvar" underneath we will add ours.
Code:
	menu = cgi.Cvar_Get( "menu", "0", CVAR_ARCHIVE );

In the client wrapper you will find a function that looks like this:
Code:
void CG_Draw2D( void ) 
{
	CG_DrawTime();
	cge.CG_Draw2D();
}
This is where all the drawing will take place, however to keep code maintained and semi organized what we did is we referenced the function where our menu will be called from within this function.

The function where we will draw our menu is "CG_DrawTime()", you can see it being referenced above.

Now I modified the original code from Wombat's, so it looks a bit different because he doesn't have a menu in his wrapper. Here is how my code looks. I will try and walk you through each part.
Code:
void CG_DrawTime()
{
	time_t rawtime;
	struct tm * timeinfo;
	time( &rawtime );
	timeinfo = localtime( &rawtime );

	char buff[100];

	/*Draw the menu*/
	if(menu->integer)
	{
		DrawMouse(); //Draw the mouse
		mouseClicks();
		/*Widgets*/

//-------------First Widget---------------------
		cgi.R_SetColor( colorWhite ); //outer outline will be white
		cgi.R_DrawBox(10, 160, 101, 16);
		cgi.R_SetColor( colorDarkRed ); //inner red box
		cgi.R_DrawBox(11, 161, 99, 14);
		cgi.R_SetColor( colorWhite ); //font color
		cgi.R_DrawString( verdana12, "First Widget", 12, 161, -1, 0 );

//-------------Second Widget---------------------
		cgi.R_SetColor( colorWhite ); //outer outline will be white
		cgi.R_DrawBox(10, 180, 101, 16);
		cgi.R_SetColor( colorDarkRed ); //inner red box
		cgi.R_DrawBox(11, 181, 99, 14);
		cgi.R_SetColor( colorWhite ); //font color
		cgi.R_DrawString( verdana12, "Second Widget", 12, 181, -1, 0 );

//-------------Third Widget---------------------
		cgi.R_SetColor( colorWhite ); //outer outline will be white
		cgi.R_DrawBox(10, 200, 101, 16);
		cgi.R_SetColor( colorDarkRed ); //inner red box
		cgi.R_DrawBox(11, 201, 99, 14);
		cgi.R_SetColor( colorWhite ); //font color
		cgi.R_DrawString( verdana12, "Third Widget", 12, 201, -1, 0 );

//-------------Fourth Widget---------------------
		cgi.R_SetColor( colorWhite ); //outer outline will be white
		cgi.R_DrawBox(10, 220, 101, 16);
		cgi.R_SetColor( colorDarkRed ); //inner red box
		cgi.R_DrawBox(11, 221, 99, 14);
		cgi.R_SetColor( colorWhite ); //font color
		cgi.R_DrawString( verdana12, "Fourth Widget", 12, 221, -1, 0 );

//-------------Time---------------------

		int h = timeinfo->tm_hour;
		int m = timeinfo->tm_min;

		static char const * const AM = "AM";
		static char const* const PM = "PM";
		char const *suffix = "AM";

		if (h >= 12 && h < 24) 
		{
			if (h != 12) 
			{ 
				h = h % 12; 
			}
			suffix = "PM";
		}

		else 
		{
			if (h == 0 || h == 24) 
			{ 
				h = 12; 
			}
		}

		cgi.R_SetColor( colorWhite );

		sprintf( buff, "%02i:%02i:%02i %s", h, m, timeinfo->tm_sec, suffix);
		cgi.R_DrawString( verdana12, buff, 12, 241, 12, 0 );	
	}
		cgi.R_SetColor( NULL );
}
First part you see is this:
Code:
	time_t rawtime;
	struct tm * timeinfo;
	time( &rawtime );
	timeinfo = localtime( &rawtime );
These re just some functions originally added by wombat to create an ingame clock. These will be used when we draw the time.

Next you see the character buffer. You can think of the buffer as a temporary storage area where we will store characters "letters, numbers" and then output the buffer using sprintf().

The next part is where all the magic takes place. This is where we toggle the menu. The default value we had the set to was 0, however if you want the menu to come up as soon as you are on the map you would change this code in CG_Init()
Code:
	menu = cgi.Cvar_Get( "menu", "1", CVAR_ARCHIVE );
Continuing.

So we want to toggle the menu. We can do so with the following if statement:
Code:
if(menu->integer)
This basically says if you assign a value to menu it will turn on, otherwise if it's set to 0, it will be turned off.
You can also write it like this
Code:
if(menu->integer == 1)
//turn on
else if(menu->integer == 0)
//turn off
Anywho that's the beginning of it. Next you see a call to DrawMouse().
For simplicity, that should be pretty obvious what that does. That function will draw the mouse, because obviously what good will a menu do if you can interact with it?

After that you see mouseClicks(), this function checks what was clicked. So once the mouse is clicked it will send some kind of event to the game saying it was.

Alright the next bunch of code is kind of repetitive.
The main portion of code is this bit
Code:
		cgi.R_SetColor( colorWhite ); //outer outline will be white
		cgi.R_DrawBox(10, 160, 101, 16);
		cgi.R_SetColor( colorDarkRed ); //inner red box
		cgi.R_DrawBox(11, 161, 99, 14);
		cgi.R_SetColor( colorWhite ); //font color
		cgi.R_DrawString( verdana12, "First Widget", 12, 161, -1, 0 );
The color parameters have also been added by wombat globally in our .cpp file. If you scroll up, you will see this:
Code:
// colours
vec4_t		colorBlack		= {0, 0, 0, 1};
vec4_t		colorRed		= {1, 0, 0, 1};
vec4_t		colorGreen		= {0, 1, 0, 1};
vec4_t		colorBlue		= {0, 0, 1, 1};
vec4_t		colorDkRed		= {0.5, 0, 0, 1};
vec4_t		colorDkGreen	= {0, 0.5, 0, 1};
vec4_t		colorDkBlue		= {0, 0, 0.5, 1};
vec4_t		colorLtRed		= {1, 0.5, 0.5, 1};
vec4_t		colorLtGreen	= {0.5, 1, 0.5, 1};
vec4_t		colorLtBlue		= {0.5, 0.5, 1, 1};
vec4_t		colorAlBlue		= {0, 0, 1, 0.25};
vec4_t		colorAlRed		= {1, 0, 0, 0.25};
vec4_t		colorYellow		= {1, 1, 0, 1};
vec4_t		colorMagenta	= {1, 0, 1, 1};
vec4_t		colorCyan		= {0, 1, 1, 1};
vec4_t		colorWhite		= {1, 1, 1, 1};
vec4_t		colorLtzzTEST	= {1, 1, 1, 0.25};
vec4_t		colorLtGrey		= {0.75, 0.75, 0.75, 1};
vec4_t		colorMdGrey		= {0.5, 0.5, 0.5, 1};
vec4_t		colorDkGrey		= {0.25, 0.25, 0.25, 1};
vec4_t		alphaLight		= { 0, 0, 0, 0.25 };
vec4_t		alphaMid		= { 0, 0, 0, 0.5 };
vec4_t		alphaDark		= { 0, 0, 0, 0.75 };
vec4_t		colorTransRed	= { 1, 0, 0, 0.5 };
vec4_t		colorTransBlue	= { 0, 0, 1, 0.5 };
vec4_t		colorTransWhite	= { 1, 1, 1, 0.5 };
vec4_t		colorDarkRed  	= { 0.34117647058823529411764705882353, 0.035294117647058823529411764705882, 0.035294117647058823529411764705882, 1 };
Your colors may be a bit different because I added custom ones for my interface, but the idea is the same.
Anywho, First we need to set the color of our shape we are drawing, I'm there are other ways of doing this, but since this is my first menu this is how I did it.
After you assign the color you want, you draw the box, now I have a outer white box that is alittle bit bigger than the inner box, and that gives it that white outline which looks nicer.
After you do that you assign the coordinates for the box. The box is drawn using:
Code:
cgi.R_DrawBox(10, 160, 101, 16);
Where the parameters are as follows:
Code:
cgi.R_DrawBox(x coordinate, y coordinate, width of box, height of box);
So as I mentioned for personal taste I drew a box in a box, thats what the following code does:
Code:
		cgi.R_SetColor( colorWhite ); //outer outline will be white
		cgi.R_DrawBox(10, 160, 101, 16);
		cgi.R_SetColor( colorDarkRed ); //inner red box
		cgi.R_DrawBox(11, 161, 99, 14);
Next we set a color for our font, I chose white, and then we want to draw the font inside of the box within the box (the dark red box), however we want to indent it a little so instead of starting at the first x coordinate 11, we will start at 12.
That gives you the following code here:
Code:
cgi.R_SetColor( colorWhite ); //font color
cgi.R_DrawString( verdana12, "First Widget", 12, 161, -1, 0 );
Regarding the width & height, I don't think that applies for us, because we defined the font that we're using, and the font is only set to a specific font size.

BTW, The default font is facfont 20, if you want to use any of the other ones, do the following.
if you scroll up in the cpp file you will see how facfont is declared, you will declare the others like so:
Code:
fontHeader_t *facfont20;
fontHeader_t *courier16;
fontHeader_t *courier18;
fontHeader_t *courier20;
fontHeader_t *handle16;
fontHeader_t *handle18;
fontHeader_t *marlett;
fontHeader_t *verdana12;
fontHeader_t *verdana14;
Remember how we told the menu how to behave as a cvar in CG_Init, we will do the same for the font. If you go to the function you should already see facfont declared, you will do the same for the others:
Code:
	//fonts
	facfont20 = cgi.R_LoadFont( "facfont-20" );
	courier16 = cgi.R_LoadFont( "courier-16" );
	courier18 = cgi.R_LoadFont( "courier-18" );
	courier20 = cgi.R_LoadFont( "courier-20" );
	handle16 = cgi.R_LoadFont( "handle-16" ); 
	handle18 = cgi.R_LoadFont( "handle-18" );
	marlett = cgi.R_LoadFont( "marlett" );
	verdana12 = cgi.R_LoadFont( "verdana-12" );
	verdana14 = cgi.R_LoadFont( "verdana-14" );
Now you should be able to use the other font, however heads up, marlett is gibberish so don't use it unless you only want your font to look weird haha.

Continuing after you draw all the widgets\boxes you want to space them out I gave my boxes 20 pixels of space on the y axis. You can see that if you scroll up where I posted the source for the function above.

After the boxes are drawn I wanted to show the time. I think it's a cool feature & wombat already did the hard work to get it working so why not. Now, I don't know about all the Europeans, but we Americans are lazy and don't understand military time, so I rewrote the function so our eyes appreciate the numbers a little better. Here is basically how it works:

Code:
		int h = timeinfo->tm_hour;
		int m = timeinfo->tm_min;

		static char const * const AM = "AM";
		static char const* const PM = "PM";
		char const *suffix = "AM";

		if (h >= 12 && h < 24) 
		{
			if (h != 12) 
			{ 
				h = h % 12; 
			}
			suffix = "PM";
		}

		else 
		{
			if (h == 0 || h == 24) 
			{ 
				h = 12; 
			}
		}

		cgi.R_SetColor( colorWhite );

		sprintf( buff, "%02i:%02i:%02i %s", h, m, timeinfo->tm_sec, suffix);
		cgi.R_DrawString( verdana12, buff, 12, 241, 12, 0 );	
	}
		cgi.R_SetColor( NULL );
Basically I check to see if the time is between 1-12 or 13 & 24, if it's 12 (midday) it shows up as 00 because we did %12 we don't want that so we force it to be 12 :P
Similarly when it's midnight the time shows 24:00 so we just set it to 12. I also went through the hassle of making it easy by it saying whether or not it's AM or PM.

You will also see that this is where the buffer comes in handy. It stores the time & label and we output what's stored in the buffer using sprintf.
Lastly, we are done drawing so we do
Code:
cgi.R_SetColor( NULL );
Ok, now here is the hard part, atleast this was for me.

You remember the drawmouse() function I had above, I tried using Windows API, and while the method worked I didn't use it because I couldn't figure out a way to draw a legit mouse\game mouse. Here is my previous code that I left commented out.
Code:
/* Not using this, but may come in handy for the future for emulating a mouse
static int x;
static int y;

LRESULT CALLBACK _WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
WNDPROC wndProc = (WNDPROC)SetWindowLong(FindWindow(0, "Medal of Honor Allied Assault"), GWL_WNDPROC, (long)_WndProc);


LRESULT CALLBACK _WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{
	x=(short)LOWORD(lParam);
	y=(short)HIWORD(lParam);

	return CallWindowProc(wndProc, hWnd, uMsg, wParam, lParam);
}
*/
the variables x & y are globally declared and then we needed to hook wndProc & setWindowLong.

I drew my retarded mouse as a small white box by using
Code:
		cgi.R_SetColor( colorWhite );
		cgi.R_DrawBox(100, 100, 5, 5);
Anywho, the method I used in game required some debugging. I had to do some seraching through memory and I came across the offset that determines when the mouse is enabled or disabled, and that lead me to the following code:
Code:
void DrawMouse()
{
	HWND GameWindow = FindWindow( 0, "Medal of Honor Allied Assault" );

    if( GameWindow )
    { 
		DWORD ProcessID; 
        GetWindowThreadProcessId( GameWindow, &ProcessID ); 
        HANDLE Process = OpenProcess( PROCESS_ALL_ACCESS, FALSE, ProcessID ); 

        if(Process)
        { 
        	BYTE data[]={0x01}; 
           	DWORD datasize = sizeof(data);
			DWORD dwOldProt;
			/*DRAW Mouse*/
			//write
			VirtualProtect((void *)0x012F6FF8, datasize, PAGE_EXECUTE_READWRITE, &dwOldProt); 
			WriteProcessMemory(GetCurrentProcess(),(void *)0x012F6FF8, &data, datasize, 0); 
			VirtualProtect((void *)0x012F6FF8, datasize, dwOldProt, 0);

			//read
			VirtualProtect((void *)0x012F6FF8, datasize, PAGE_EXECUTE_READWRITE, &dwOldProt); 
			WriteProcessMemory(GetCurrentProcess(),(void *)0x012F6FF8, &data, datasize, 0); 
			VirtualProtect((void *)0x012F6FF8, datasize, dwOldProt, 0);

			//cheat
			VirtualProtect((void *)0x012F6FF8, datasize, PAGE_EXECUTE_READWRITE, &dwOldProt); 
			WriteProcessMemory(GetCurrentProcess(),(void *)0x012F6FF8, &data, datasize, 0); 
			VirtualProtect((void *)0x012F6FF8, datasize, dwOldProt, 0);

			CloseHandle( Process ); 
		}
	}
}
When it comes to WINAPI code, there's really no better way of explaining how it works than to just look at the definition & examples that come on MSDN.

http://msdn.microsoft.com/en-us/libr...74(VS.85).aspx
http://msdn.microsoft.com/en-us/libr...98(VS.85).aspx

Anywho this will enable the mouse & draw the cursor ingame for you.

The last function required was the mouseClicks(), this tells the game what we clicked.

This part of the code also required some modifications. I was running into issues with the cursor coordinates being off sync with the actual game coordinates, so I had to do more debugging to figure out where the x,y coordinates were stored in memory. I then let the mouse position = to those values stored in those offsets.

That lead me to this code here:
Code:
	POINT myPos;
	myPos.x = *(int*)0x10FFDEC;
	myPos.y = *(int*)0x10FFDF0;
POINT is a Windows data type that defines the mouse positions.

At this point in time I did some checks to make sure we are clicking the buttons and nothing else. Now we declared the size & offsets of our buttons so we know how big they are, but now we need to tell the game where they are.

I have the following piece of code that checks for 3 things.
1. We are in MOHAA & our menu is enabled
2. Whether or not we are in full screen mode or windowed mode
3. Are we clicking the left mouse button

Code:
	if(FindWindow( 0, "Medal of Honor Allied Assault" ) && menu->integer)
	{
		if(cgs->glConfig.isFullscreen == true)
		{
			if(GetAsyncKeyState(VK_LBUTTON)&1) 
			{
				if((myPos.x >= 11)&&(myPos.x <= 110)&&(myPos.y >= 161)&&(myPos.y <= 175))
					cgi.Printf("I clicked the first widget \n");
			}
		}
		else if(cgs->glConfig.isFullscreen == false)
		{
			if(GetAsyncKeyState(VK_LBUTTON)&1) 
			{
				if((myPos.x >= 11)&&(myPos.x <= 110)&&(myPos.y >= 161)&&(myPos.y <= 175))
					cgi.Printf("I clicked the first widget \n");
			}

		}
	}
If all of the statements I mentioned above are true the next thing we do is define the coordinates.

We know that these are the coordinated of the box we are interested in:
Code:
cgi.R_DrawBox(11, 161, 99, 14);
So, what we do is this.
1. Check if the mouse position is greater than or equal to 11, since our coordinate starts at 11.
2. Assuming #1 is correct is the mouse pointer less than or equal to width of the button + the 11 pixels we are offset by? (11 + 99= 110)
3. Assuming the above are correct we now check the y axis. So is the mouse cursor greater than or equal to 161?
4. Assuming the above 3 statements are correct, is our cursor less than or equal to thebutton height + the y axis offset (161 + 14 = 175)

If all of the above requirements are true, then the game knows our cursor is within the first button\widget, so to tell ourselves that this works & to test it we will print out "I clicked the first widget" using:
Code:
cgi.Printf("I clicked the first widget \n");
Obviously for whatever reason you use the menu for you will replace the printf function with whatever you want the first button even to do whether it's to enable\disable a feature,event, toggle something whatever the case.

I hope everyone finds this useful, and can seriously learn from it. I agree with everyone else here you can't learn from simply copy pasting, however from personal experience I learn best from examples so I figure you can use my work as an example.

I want to thank the following individuals for helping me out with this code. If I forgot anyone, let me know.

Wombat
Okidoki
bobbysing
roverturbo
quicktime
klownterfit
paulius
learn_more
heiko

Edit:
Here is an image of how the menu looks, despite the fact that in the image the PM & AM didn't print out, in the code above it was fixed.
http://x-null.net/menu.JPG
__________________
[SIGPIC][/SIGPIC]

Last edited by m0d hipp„; 01-25-2009 at 05:03 PM.
m0d hipp„ is offline

Reply With Quote


Old 01-25-2009, 05:27 PM   #2


Roverturbo's Avatar

Join Date: Feb 2005
Posts: 5,035
Reputation: 92245
Rep Power: 1108
Roverturbo has a huge epeen!Roverturbo has a huge epeen!Roverturbo has a huge epeen!Roverturbo has a huge epeen!Roverturbo has a huge epeen!Roverturbo has a huge epeen!Roverturbo has a huge epeen!Roverturbo has a huge epeen!Roverturbo has a huge epeen!Roverturbo has a huge epeen!Roverturbo has a huge epeen!
Recognitions:
Members who have contributed financial support towards UnKnoWnCheaTs. Donation (?)
I am GOD? Hmm K. God
Points: 69,888, Level: 38
Points: 69,888, Level: 38 Points: 69,888, Level: 38 Points: 69,888, Level: 38
Activity: 19.5%
Activity: 19.5% Activity: 19.5% Activity: 19.5%
Last Achievements
Nice, guess the fix worked. Thanks for sharing your work and writing up a tutorial for people.

Plus reputation.
__________________


I've learned that something constructive comes from every defeat.

Sometimes i say things i shouldn't, and sometimes i say what other people are thinking.

Real programmer's don't document, if it was hard to write, it should be hard to understand.

First learn computer science and all the theory, next develop a programming style, then forget all that and just hack.

Roverturbo is online now

Reply With Quote

Old 01-25-2009, 05:41 PM   #3


m0d hipp„'s Avatar

Threadstarter
Join Date: Jun 2005
Posts: 1,362
Reputation: 8369
Rep Power: 0
m0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATS
Cliff Diver Champion
Last Achievements
thanks alot man, yeah basically the code I was trying to figure out when I was debugging & working with you was these 2 lines:
Code:
myPos.x = *(int*)0x10FFDEC;
myPos.y = *(int*)0x10FFDF0;
haha I tested everything in full screen & windowed mode and it works flawlessly. I really appreciate your help rover, and everyones I mentioned above.
__________________
[SIGPIC][/SIGPIC]
m0d hipp„ is offline

Reply With Quote

Old 01-25-2009, 09:27 PM   #4
Level 3

KorUpt's Avatar

Join Date: Nov 2007
Posts: 196
Reputation: 783
Rep Power: 62
KorUpt should have carpal tunnelKorUpt should have carpal tunnelKorUpt should have carpal tunnelKorUpt should have carpal tunnelKorUpt should have carpal tunnelKorUpt should have carpal tunnelKorUpt should have carpal tunnel
Very nice indeed

alot of people will learn from this.
KorUpt is offline

Reply With Quote

Old 02-16-2009, 06:06 PM   #5
Level 3

maximanimo's Avatar

Join Date: Dec 2007
Posts: 14
Reputation: 10
Rep Power: 51
maximanimo has made posts that are generally average in quality
Points: 2,981, Level: 5
Points: 2,981, Level: 5 Points: 2,981, Level: 5 Points: 2,981, Level: 5
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
Last Achievements
Thanks again mod for another great tut !
This will help me alot

lange
maximanimo is offline

Reply With Quote

Old 03-01-2009, 03:58 AM   #6


m0d hipp„'s Avatar

Threadstarter
Join Date: Jun 2005
Posts: 1,362
Reputation: 8369
Rep Power: 0
m0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATSm0d hipp„ DEFINES UNKNOWNCHEATS
Cliff Diver Champion
Last Achievements
Regarding the tutorial above, some asked me for an update to add submenu's so here it is.

I just tried this out myself, and these are the following changes that need to be done depending on how many sub menus you want.

Globally declare the variables:
Code:
bool isSubMenu1Active = false;
bool isSubMenu2Active = false;
bool isSubMenu3Active = false;
bool widget1Active = false;
bool widget2Active = false;
bool widget3Active = false;
Now in mouseClicks() I added more "stuff". Here is the updated code:
Code:
void mouseClicks()
{
    POINT myPos;
    myPos.x = *(int*)0x10FFDEC;
    myPos.y = *(int*)0x10FFDF0;
   
    if(FindWindow( 0, "Medal of Honor Allied Assault" ) && menu->integer)
    {
        if(cgs->glConfig.isFullscreen = true)
        {
            if(GetAsyncKeyState(VK_LBUTTON)&1)
            {
                if((myPos.x >= 11)&&(myPos.x <= 110)&&(myPos.y >= 161)&&(myPos.y <= 175))
                {
                    widget1Active = true;
                    isSubMenu1Active = true;
                    widget2Active = false;
                    isSubMenu2Active = false;
                    widget3Active = false;
                    isSubMenu3Active = false;

                    CG_DrawTime();
                }
                else if((myPos.x >= 11)&&(myPos.x <= 110)&&(myPos.y >= 181)&&(myPos.y <= 195))
                {
                    widget2Active = true;
                    isSubMenu2Active = true;
                    widget1Active = false;
                    isSubMenu1Active = false;
                    widget3Active = false;
                    isSubMenu3Active = false;

                    CG_DrawTime();
                }
                else if((myPos.x >= 11)&&(myPos.x <= 110)&&(myPos.y >= 201)&&(myPos.y <= 215))
                {
                    widget3Active = true;
                    isSubMenu3Active = true;
                    widget2Active = false;
                    isSubMenu2Active = false;
                    widget1Active = false;
                    isSubMenu1Active = false;

                    CG_DrawTime();
                }
            }
        }

        else if(cgs->glConfig.isFullscreen = false)
        {
            if(GetAsyncKeyState(VK_LBUTTON)&1)
            {
                if((myPos.x >= 11)&&(myPos.x <= 110)&&(myPos.y >= 161)&&(myPos.y <= 175))
                {
                    widget1Active = true;
                    isSubMenu1Active = true;
                    widget2Active = false;
                    isSubMenu2Active = false;
                    widget3Active = false;
                    isSubMenu3Active = false;

                    CG_DrawTime();
                }
                else if((myPos.x >= 11)&&(myPos.x <= 110)&&(myPos.y >= 181)&&(myPos.y <= 195))
                {
                    widget2Active = true;
                    isSubMenu2Active = true;
                    widget1Active = false;
                    isSubMenu1Active = false;
                    widget3Active = false;
                    isSubMenu3Active = false;

                    CG_DrawTime();
                }
                else if((myPos.x >= 11)&&(myPos.x <= 110)&&(myPos.y >= 201)&&(myPos.y <= 215))
                {
                    widget3Active = true;
                    isSubMenu3Active = true;
                    widget2Active = false;
                    isSubMenu2Active = false;
                    widget1Active = false;
                    isSubMenu1Active = false;

                    CG_DrawTime();
                }
            }
        }
    }
}
Finally in CG_DrawTime, underneath where the time is drawn & right above "cgi.R_SetColor( NULL );", add this bit:
Code:
    //Submenu Stuff
    //First Submenu
    if((isSubMenu1Active == true) && (widget1Active == true))
    {
        isSubMenu2Active = false;
        isSubMenu3Active = false;
        widget2Active = false;
        widget3Active = false;

//-------------First Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 160, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 161, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "First Widget", 122, 161, -1, 0 );
//-------------Second Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 180, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 181, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Second Widget", 122, 181, -1, 0 );

    }
    //Second Submenu
    else if((isSubMenu2Active == true) && (widget2Active == true))
    {
        isSubMenu1Active = false;
        isSubMenu3Active = false;
        widget1Active = false;
        widget3Active = false;

//-------------First Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 180, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 181, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Second Widget", 122, 181, -1, 0 );

//-------------Second Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 200, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 201, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Third Widget", 122, 201, -1, 0 );

    }
    //Third Submenu
    else if((isSubMenu3Active == true) && (widget3Active == true))
    {
        isSubMenu2Active = false;
        isSubMenu1Active = false;
        widget2Active = false;
        widget1Active = false;

//-------------First Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 200, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 201, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Second Widget", 122, 201, -1, 0 );

//-------------Second Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 220, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 221, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Third Widget", 122, 221, -1, 0 );

    }
Here is the whole code:
Code:
void CG_DrawTime()
{
    time_t rawtime;
    struct tm * timeinfo;
    time( &rawtime );
    timeinfo = localtime( &rawtime );

    char buff[100];

    /*Draw the menu*/
    if(menu->integer)
    {
        DrawMouse(); //Draw the mouse
        mouseClicks();
        /*Widgets*/

//-------------First Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(10, 160, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(11, 161, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "First Widget", 12, 161, -1, 0 );

//-------------Second Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(10, 180, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(11, 181, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Second Widget", 12, 181, -1, 0 );

//-------------Third Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(10, 200, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(11, 201, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Third Widget", 12, 201, -1, 0 );

//-------------Fourth Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(10, 220, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(11, 221, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Fourth Widget", 12, 221, -1, 0 );

//-------------Time---------------------

        int h = timeinfo->tm_hour;
        int m = timeinfo->tm_min;

        static char const * const AM = "AM";
        static char const* const PM = "PM";
        char const *suffix = "AM";

        if (h >= 12 && h < 24)
        {
            if (h != 12)
            {
                h = h % 12;
            }
            suffix = "PM";
        }

        else
        {
            if (h == 0 || h == 24)
            {
                h = 12;
            }
        }

        cgi.R_SetColor( colorWhite );

        sprintf( buff, "%02i:%02i:%02i %s", h, m, timeinfo->tm_sec, suffix);
        cgi.R_DrawString( verdana12, buff, 12, 241, 12, 0 );   
    }

    //Submenu Stuff
    //First Submenu
    if((isSubMenu1Active == true) && (widget1Active == true))
    {
        isSubMenu2Active = false;
        isSubMenu3Active = false;
        widget2Active = false;
        widget3Active = false;

//-------------First Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 160, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 161, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "First Widget", 122, 161, -1, 0 );
//-------------Second Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 180, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 181, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Second Widget", 122, 181, -1, 0 );

    }
    //Second Submenu
    else if((isSubMenu2Active == true) && (widget2Active == true))
    {
        isSubMenu1Active = false;
        isSubMenu3Active = false;
        widget1Active = false;
        widget3Active = false;

//-------------First Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 180, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 181, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Second Widget", 122, 181, -1, 0 );

//-------------Second Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 200, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 201, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Third Widget", 122, 201, -1, 0 );

    }
    //Third Submenu
    else if((isSubMenu3Active == true) && (widget3Active == true))
    {
        isSubMenu2Active = false;
        isSubMenu1Active = false;
        widget2Active = false;
        widget1Active = false;

//-------------First Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 200, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 201, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Second Widget", 122, 201, -1, 0 );

//-------------Second Widget---------------------
        cgi.R_SetColor( colorWhite ); //outer outline will be white
        cgi.R_DrawBox(120, 220, 101, 16);
        cgi.R_SetColor( colorDarkRed ); //inner red box
        cgi.R_DrawBox(121, 221, 99, 14);
        cgi.R_SetColor( colorWhite ); //font color
        cgi.R_DrawString( verdana12, "Third Widget", 122, 221, -1, 0 );

    }

        cgi.R_SetColor( NULL );
}

I also want to add that, it has been brought to my attention my code is different than many others, you will obviously have to modify the structs & classes to match what I have, but to make it easier on yourself, you would just need to make some adjustments in the cpp file from wombat's cgamex wrapper to get the above working.

Either way it's been tested & works great, so enjoy & learn from it!
__________________
[SIGPIC][/SIGPIC]
m0d hipp„ is offline

Reply With Quote

Old 03-28-2009, 07:11 PM   #7


ultimate-tester's Avatar

Join Date: Sep 2008
Location: The Netherlands
Posts: 1,752
Reputation: 9131
Rep Power: 0
ultimate-tester DEFINES UNKNOWNCHEATSultimate-tester DEFINES UNKNOWNCHEATSultimate-tester DEFINES UNKNOWNCHEATSultimate-tester DEFINES UNKNOWNCHEATSultimate-tester DEFINES UNKNOWNCHEATSultimate-tester DEFINES UNKNOWNCHEATSultimate-tester DEFINES UNKNOWNCHEATSultimate-tester DEFINES UNKNOWNCHEATSultimate-tester DEFINES UNKNOWNCHEATSultimate-tester DEFINES UNKNOWNCHEATSultimate-tester DEFINES UNKNOWNCHEATS
Nice work dude Too bad this is game related. It looks good +REP (also +REP for that woman )
ultimate-tester is offline

Reply With Quote
Reply  

  • Submit Thread to Digg
  • Submit Thread to del.icio.us
  • Submit Thread to StumbleUpon
  • Submit Thread to Google
  • Submit Thread to Facebook
  • Submit Thread to My Yahoo!
  • Submit Thread to MySpace
  • Submit Thread to Twitter
  • Submit Thread to Reddit



Tags
creating, menu, mohaa
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off



All times are GMT +1. The time now is 07:37 AM.