Post: [TUTORIAL] Step-By-Step Guide On How To Make A Basic GSC Mod Menu
05-27-2012, 03:58 PM #1
IVI40A3Fusionz
Former Gaming Squad Member
(adsbygoogle = window.adsbygoogle || []).push({});
NOTE: This was originally wrote by me for Black Ops!
You must login or register to view this content.

I've seen alot of people using the same bases lately so in this tutorial i will show you all how to make a basic mod menu with sub menus and hopefully it will teach some of you a few things and encourage you to make your own menu bases in the future. I will also leave the finish product in the thread for people to use if they wish, let’s get started.

Step 1: Making the buttons function

First you want to set out your menu buttons I prefer to have them in a function called BuildMenu() which I also thread from onPlayerSpawned().
So firstly you want to make your function name.
    
BuildMenu()
{
}



Step 2: Adding and laying out the buttons

Now to make the actual button system, this is an old way to do it but is very effective as it never fails, firstly you want to make a little for loop inside your BuildMenu() function like this.
    
BuildMenu()
{
for(;Winky Winky
{
}
}

Now we are going to add our buttons using if statements and the button name.
You don't have to use the exact layout for the buttons that i use but i prefer to have them this way.
    
BuildMenu()
{
for(;Winky Winky
{
if(self FragButtonPressed())
{
wait .2;
}
if(self AttackButtonPressed())
{
wait .2;
}
if(self AdsButtonPressed())
{
wait .2;
}
if(self UseButtonPressed())
{
wait .2;
}
if(self MeleeButtonPressed())
{
}
wait .001;
}
}

You must always have a wait time at the end on the for loop otherwise your game will lag out and crash.
You can (it's recommended) that you use a wait time for each button like shown above it just makes it easier when using the menu i go with wait .2; as i find this the best one to use.


Step 3: Extra add ons for the buttons

Now like alot of other people i like to make my menu stable by making it so when the menu is open you can only use R1, L1, Square and Melee (unless you've used other buttons) to do this i use a simple variable.
I also use endons to tell the game when to stop the function this also make is more stable.
    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.MenuOpened = true;
self.Scroll = 0;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
self.MenuOpened = false;
}
}
}

Now i've used self.MenuOpened as my variable to decide when to activate functions when i press the buttons, i have to toggle it on and off using false/true or 0/1 and i do this by adding it to MeleeButtonPressed and FragButtonPressed as shown above.


Step 4: Making the options

After i've set up my buttons i like to make my menu options as it helps out with the text making and finishing off the buttons.
I am going to split this up into a few steps also.
Step 1: Creating the function

I'm going to name this function addOption().
    
addOption()
{
}



Step 2: Laying it out

As we are using sub menu we are going to have to add a Menu input.
I have used Number to define the scroll number, it will help out later in this tutorial and you will understand why.
    
addOption(Menu, Number, Text, Function, Input)
{
}



Step 3: Completing the addOption Function

Now some of you may be wondering 2 things.
Why have i got the if statement if(IsDefined(Input))? Answer: This if statement tells the game is the variable Input is defined then it will fun that part of the function.
Why have you put [Menu][Number] for each line? Answer: You need them so the game can determine what menu you are on and what option you are on so it then knows what option to run.
    
addOption(Menu, Number, Text, Function, Input)
{
self.MenuText[Menu][Number]=Text;
self.MenuFunction[Menu][Number]=Function;
if(IsDefined(Input))self.MenuInput[Menu][Number]=Input;
}




Step 5: Making the text function

Now we have our buttons set out and our options set out we need to make out text function as we want our text to show up, now there's two ways to do this one using '\n' which puts all the text into 1 string and saves strings it is mainly used in COD4 as the games unstable, the other way you can do it is by making the game create a new string for every option and im going to show you both ways.
Firstly we need to name our texts i'm going to use self.Menu["Text"].
Way 1: Using '\n'

    
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++) Text += self.MenuText[Menu][i]+"\n";
self.Menu["Text"] = createFontString("default",1.5);
self.Menu["Text"] setPoint("LEFT","",-370,-200);
self.Menu["Text"].alpha=3;
self.Menu["Text"].sort=3;
self.Menu["Text"] setText(Text);
self thread UpdateMenu(self.Menu["Text"]);
}


Way 2: Without '\n'

    
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++)
{
self.Menu["Text"][i] = createFontString("default",1.5);
self.Menu["Text"][i] setPoint("LEFT","",-370,-200);
self.Menu["Text"][i].alpha=3;
self.Menu["Text"][i].sort=3;
self.Menu["Text"][i] setText(self.MenuText[Menu][i]);
self thread UpdateMenu(self.Menu["Text"][i]);
}
}


Now alpha is how faded you want your text 1 = no fade and 0 = lots of fade so much you can't see the options.
The higher the sort the more huds it will go through.
setPoint = (Align,Relative,X,Y).
createFontString = (Fontname,Fontsize).
setText = The text you want displayed.

Extra Step: Setting up the UpdateMenu function

    
UpdateMenu(i)
{
self waittill("MenuUpdated");
i destroy();
}


We are going to be using a waittill named MenuUpdated and when we close the menu or enter a sub menu we will notify this.


Step 6: Making the sub menu function

From here we are going to be making the sub menu function which we will call from our menu when we select the relevant option, i'm going to name my sub menu function Sub Menu, i am also going to leave this one into a few steps.
Step 1: Creating the function layout

    
SubMenu(Menu)
{
}


Step 2: Adding the contents

Remember our friend the waitill we made earlier? We are going to use him in this function.
    
SubMenu(Menu)
{
self notify("MenuUpdated");
self.Scroll = 0;
self thread MenuText(Menu);
self.Scrollbar.y = self.Scroll*18-200;
}

You may have noticed i used self.Scrollbar i am going to call my scrollbar that when i create it later in the tutorial.



Step 7: Creating the shaders

For this you will need this function.
    
CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha)
{
CShader=newClientHudElem(self);
CShader.children=[];
CShader.elemType="bar";
CShader.sort=sort;
CShader.color=color;
CShader.alpha=alpha;
CShader setParent(level.uiParent);
CShader setShader(shader,width,height);
CShader setPoint(align,relative,x,y);
return CShader;
}


To create them you simply do this.
    
self.Scrollbar = CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha);
self.Background = CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha);


Here are some examples.
    
self.Scrollbar=CreateShader("CENTER","",-550,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-550,0,200,1000,(0,0,0),"white",1,1);

We will put these under the FragButtonPressed if statement later on.


Step 8: Creating the options

This function i will call iniMenu() and we will call this on BuildMenu()
    
iniMenu()
{
addOption("Main", 0, "Sub Menu 1", ::SubMenu, "SubM1");
addOption("Main", 1, "Sub Menu 2", ::SubMenu, "SubM2");
addOpti0n("Main", 2, "Sub Option 1", ::Test, "");
addOpti0n("Main", 3, "Sub Option 2", ::Test, "");
addOpti0n("Main", 4, "Sub Option 3", ::Test, "");
}

As you can see i have called a function called Test, and here it is created.
    
Test()
{
self iPrintln("Test");
}



Step 9: Finishing the buttons

I am going to split this ste pup into different section.
Step 1: Completing the FragButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
self.MenuOpened = false;
wait .2;
}
wait .001;
}
}

As you can see i have added the huds that we made earlier and i have threaded our SubMenu function and i have also added self thread iniMenu(); before the for loop like i said to do earlier.

Step 2: Completing the MeleeButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

As you can see i've just added destroys.

Step 3: Completing the AttackButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

As you can see i've just added destroys.

Step 4: Completing the AdsButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

For the AdsButtonPressed i've just done what i've done to the AttackButtonPressed but changed a few things, take a look and you will see what i've done.

Step 5: Completing the UseButtonPressed

This is the bit that alot of people usually find the hardest part to complete with the buttons however it's very easy once you get the hold of it.
It basically goes like this.
    
self thread [[Your self function name][Scroll counter]](You self input name[Scroll counter]);

So ours wills be like this.
    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
self thread [[self.MenuFunction[self.ParentMenu][self.Scroll]]](self.MenuInput[self.ParentMenu][self.Scroll]);
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

And that's our buttons complete!



Well that's the tutorial not a very in-depth one as i didn't explain everything to the full extent i could have however it gives a few pointers that i hope will allow some of you to make your own menu bases from scratch and thus make you better coders :y:!

Here's the final script just in-case you would like to test:

Without '\n':

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
self thread [[self.MenuFunction[self.ParentMenu][self.Scroll]]](self.MenuInput[self.ParentMenu][self.Scroll]);
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}
CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha)
{
CShader=newClientHudElem(self);
CShader.children=[];
CShader.elemType="bar";
CShader.sort=sort;
CShader.color=color;
CShader.alpha=alpha;
CShader setParent(level.uiParent);
CShader setShader(shader,width,height);
CShader setPoint(align,relative,x,y);
return CShader;
}
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++)
{
self.Menu["Text"][i] = createFontString("default",1.5);
self.Menu["Text"][i] setPoint("LEFT","",-370,-200);
self.Menu["Text"][i].alpha=3;
self.Menu["Text"][i].sort=3;
self.Menu["Text"][i] setText(self.MenuText[Menu][i]);
self thread UpdateMenu(self.Menu["Text"][i]);
}
}
UpdateMenu(i)
{
self waittill("MenuUpdated");
i destroy();
}
addOption(Menu, Number, Text, Function, Input)
{
self.MenuText[Menu][Number]=Text;
self.MenuFunction[Menu][Number]=Function;
if(IsDefined(Input))self.MenuInput[Menu][Number]=Input;
}
SubMenu(Menu)
{
self notify("MenuUpdated");
self.Scroll = 0;
self thread MenuText(Menu);
self.Scrollbar.y = self.Scroll*18-200;
}
iniMenu()
{
addOption("Main", 0, "Sub Menu 1", ::SubMenu, "SubM1");
addOption("Main", 1, "Sub Menu 2", ::SubMenu, "SubM2");
addOpti0n("Main", 2, "Sub Option 1", ::Test, "");
addOpti0n("Main", 3, "Sub Option 2", ::Test, "");
addOpti0n("Main", 4, "Sub Option 3", ::Test, "");
}


With '\n':

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
self thread [[self.MenuFunction[self.ParentMenu][self.Scroll]]](self.MenuInput[self.ParentMenu][self.Scroll]);
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}
CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha)
{
CShader=newClientHudElem(self);
CShader.children=[];
CShader.elemType="bar";
CShader.sort=sort;
CShader.color=color;
CShader.alpha=alpha;
CShader setParent(level.uiParent);
CShader setShader(shader,width,height);
CShader setPoint(align,relative,x,y);
return CShader;
}
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++) Text += self.MenuText[Menu][i]+"\n";
self.Menu["Text"] = createFontString("default",1.5);
self.Menu["Text"] setPoint("LEFT","",-370,-200);
self.Menu["Text"].alpha=3;
self.Menu["Text"].sort=3;
self.Menu["Text"] setText(Text);
self thread UpdateMenu(self.Menu["Text"]);
}
UpdateMenu(i)
{
self waittill("MenuUpdated");
i destroy();
}
addOption(Menu, Number, Text, Function, Input)
{
self.MenuText[Menu][Number]=Text;
self.MenuFunction[Menu][Number]=Function;
if(IsDefined(Input))self.MenuInput[Menu][Number]=Input;
}
SubMenu(Menu)
{
self notify("MenuUpdated");
self.Scroll = 0;
self thread MenuText(Menu);
self.Scrollbar.y = self.Scroll*18-200;
}
iniMenu()
{
addOption("Main", 0, "Sub Menu 1", ::SubMenu, "SubM1");
addOption("Main", 1, "Sub Menu 2", ::SubMenu, "SubM2");
addOpti0n("Main", 2, "Sub Option 1", ::Test, "");
addOpti0n("Main", 3, "Sub Option 2", ::Test, "");
addOpti0n("Main", 4, "Sub Option 3", ::Test, "");
}




Please tell me if you think i missed anything i wrote this tutorial without testing anything and just typing what came to my head at that time hence why alot of the steps are in random orders. If you do think i missed something out please tell me and i'll see what i can do to update the thread other than that please show some appreciation and maybe we could get this stickied if it's good enough?
(adsbygoogle = window.adsbygoogle || []).push({});

The following 18 users say thank you to IVI40A3Fusionz for this useful post:

:HIGH:, 247Yamato, AndreeU, Baby-panama, Dreamcather, GAMIPR, Harry, Callumeleyy, INSAN3LY_D34TH, itsSorrow, JakeModz, KingcreekS, User23434, Restxrt Modz, ThreeSixtyyy, tylerallmighty, xePixTvx
07-04-2012, 07:23 PM #20
Kellis
LoanWolf
This is such a helpful post... :y:
07-27-2012, 04:48 PM #21
tylerallmighty
Human After All
Originally posted by IVI40A3Fusionz View Post
NOTE: This was originally wrote by me for Black Ops!
You must login or register to view this content.

I've seen alot of people using the same bases lately so in this tutorial i will show you all how to make a basic mod menu with sub menus and hopefully it will teach some of you a few things and encourage you to make your own menu bases in the future. I will also leave the finish product in the thread for people to use if they wish, let’s get started.

Step 1: Making the buttons function

First you want to set out your menu buttons I prefer to have them in a function called BuildMenu() which I also thread from onPlayerSpawned().
So firstly you want to make your function name.
    
BuildMenu()
{
}



Step 2: Adding and laying out the buttons

Now to make the actual button system, this is an old way to do it but is very effective as it never fails, firstly you want to make a little for loop inside your BuildMenu() function like this.
    
BuildMenu()
{
for(;Winky Winky
{
}
}

Now we are going to add our buttons using if statements and the button name.
You don't have to use the exact layout for the buttons that i use but i prefer to have them this way.
    
BuildMenu()
{
for(;Winky Winky
{
if(self FragButtonPressed())
{
wait .2;
}
if(self AttackButtonPressed())
{
wait .2;
}
if(self AdsButtonPressed())
{
wait .2;
}
if(self UseButtonPressed())
{
wait .2;
}
if(self MeleeButtonPressed())
{
}
wait .001;
}
}

You must always have a wait time at the end on the for loop otherwise your game will lag out and crash.
You can (it's recommended) that you use a wait time for each button like shown above it just makes it easier when using the menu i go with wait .2; as i find this the best one to use.


Step 3: Extra add ons for the buttons

Now like alot of other people i like to make my menu stable by making it so when the menu is open you can only use R1, L1, Square and Melee (unless you've used other buttons) to do this i use a simple variable.
I also use endons to tell the game when to stop the function this also make is more stable.
    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.MenuOpened = true;
self.Scroll = 0;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
self.MenuOpened = false;
}
}
}

Now i've used self.MenuOpened as my variable to decide when to activate functions when i press the buttons, i have to toggle it on and off using false/true or 0/1 and i do this by adding it to MeleeButtonPressed and FragButtonPressed as shown above.


Step 4: Making the options

After i've set up my buttons i like to make my menu options as it helps out with the text making and finishing off the buttons.
I am going to split this up into a few steps also.
Step 1: Creating the function

I'm going to name this function addOption().
    
addOption()
{
}



Step 2: Laying it out

As we are using sub menu we are going to have to add a Menu input.
I have used Number to define the scroll number, it will help out later in this tutorial and you will understand why.
    
addOption(Menu, Number, Text, Function, Input)
{
}



Step 3: Completing the addOption Function

Now some of you may be wondering 2 things.
Why have i got the if statement if(IsDefined(Input))? Answer: This if statement tells the game is the variable Input is defined then it will fun that part of the function.
Why have you put [Menu][Number] for each line? Answer: You need them so the game can determine what menu you are on and what option you are on so it then knows what option to run.
    
addOption(Menu, Number, Text, Function, Input)
{
self.MenuText[Menu][Number]=Text;
self.MenuFunction[Menu][Number]=Function;
if(IsDefined(Input))self.MenuInput[Menu][Number]=Input;
}




Step 5: Making the text function

Now we have our buttons set out and our options set out we need to make out text function as we want our text to show up, now there's two ways to do this one using '\n' which puts all the text into 1 string and saves strings it is mainly used in COD4 as the games unstable, the other way you can do it is by making the game create a new string for every option and im going to show you both ways.
Firstly we need to name our texts i'm going to use self.Menu["Text"].
Way 1: Using '\n'

    
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++) Text += self.MenuText[Menu][i]+"\n";
self.Menu["Text"] = createFontString("default",1.5);
self.Menu["Text"] setPoint("LEFT","",-370,-200);
self.Menu["Text"].alpha=3;
self.Menu["Text"].sort=3;
self.Menu["Text"] setText(Text);
self thread UpdateMenu(self.Menu["Text"]);
}


Way 2: Without '\n'

    
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++)
{
self.Menu["Text"][i] = createFontString("default",1.5);
self.Menu["Text"][i] setPoint("LEFT","",-370,-200);
self.Menu["Text"][i].alpha=3;
self.Menu["Text"][i].sort=3;
self.Menu["Text"][i] setText(self.MenuText[Menu][i]);
self thread UpdateMenu(self.Menu["Text"][i]);
}
}


Now alpha is how faded you want your text 1 = no fade and 0 = lots of fade so much you can't see the options.
The higher the sort the more huds it will go through.
setPoint = (Align,Relative,X,Y).
createFontString = (Fontname,Fontsize).
setText = The text you want displayed.

Extra Step: Setting up the UpdateMenu function

    
UpdateMenu(i)
{
self waittill("MenuUpdated");
i destroy();
}


We are going to be using a waittill named MenuUpdated and when we close the menu or enter a sub menu we will notify this.


Step 6: Making the sub menu function

From here we are going to be making the sub menu function which we will call from our menu when we select the relevant option, i'm going to name my sub menu function Sub Menu, i am also going to leave this one into a few steps.
Step 1: Creating the function layout

    
SubMenu(Menu)
{
}


Step 2: Adding the contents

Remember our friend the waitill we made earlier? We are going to use him in this function.
    
SubMenu(Menu)
{
self notify("MenuUpdated");
self.Scroll = 0;
self thread MenuText(Menu);
self.Scrollbar.y = self.Scroll*18-200;
}

You may have noticed i used self.Scrollbar i am going to call my scrollbar that when i create it later in the tutorial.



Step 7: Creating the shaders

For this you will need this function.
    
CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha)
{
CShader=newClientHudElem(self);
CShader.children=[];
CShader.elemType="bar";
CShader.sort=sort;
CShader.color=color;
CShader.alpha=alpha;
CShader setParent(level.uiParent);
CShader setShader(shader,width,height);
CShader setPoint(align,relative,x,y);
return CShader;
}


To create them you simply do this.
    
self.Scrollbar = CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha);
self.Background = CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha);


Here are some examples.
    
self.Scrollbar=CreateShader("CENTER","",-550,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-550,0,200,1000,(0,0,0),"white",1,1);

We will put these under the FragButtonPressed if statement later on.


Step 8: Creating the options

This function i will call iniMenu() and we will call this on BuildMenu()
    
iniMenu()
{
addOption("Main", 0, "Sub Menu 1", ::SubMenu, "SubM1");
addOption("Main", 1, "Sub Menu 2", ::SubMenu, "SubM2");
addOpti0n("Main", 2, "Sub Option 1", ::Test, "");
addOpti0n("Main", 3, "Sub Option 2", ::Test, "");
addOpti0n("Main", 4, "Sub Option 3", ::Test, "");
}

As you can see i have called a function called Test, and here it is created.
    
Test()
{
self iPrintln("Test");
}



Step 9: Finishing the buttons

I am going to split this ste pup into different section.
Step 1: Completing the FragButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
self.MenuOpened = false;
wait .2;
}
wait .001;
}
}

As you can see i have added the huds that we made earlier and i have threaded our SubMenu function and i have also added self thread iniMenu(); before the for loop like i said to do earlier.

Step 2: Completing the MeleeButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

As you can see i've just added destroys.

Step 3: Completing the AttackButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

As you can see i've just added destroys.

Step 4: Completing the AdsButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

For the AdsButtonPressed i've just done what i've done to the AttackButtonPressed but changed a few things, take a look and you will see what i've done.

Step 5: Completing the UseButtonPressed

This is the bit that alot of people usually find the hardest part to complete with the buttons however it's very easy once you get the hold of it.
It basically goes like this.
    
self thread [[Your self function name][Scroll counter]](You self input name[Scroll counter]);

So ours wills be like this.
    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
self thread [[self.MenuFunction[self.ParentMenu][self.Scroll]]](self.MenuInput[self.ParentMenu][self.Scroll]);
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

And that's our buttons complete!



Well that's the tutorial not a very in-depth one as i didn't explain everything to the full extent i could have however it gives a few pointers that i hope will allow some of you to make your own menu bases from scratch and thus make you better coders :y:!

Here's the final script just in-case you would like to test:

Without '\n':

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
self thread [[self.MenuFunction[self.ParentMenu][self.Scroll]]](self.MenuInput[self.ParentMenu][self.Scroll]);
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}
CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha)
{
CShader=newClientHudElem(self);
CShader.children=[];
CShader.elemType="bar";
CShader.sort=sort;
CShader.color=color;
CShader.alpha=alpha;
CShader setParent(level.uiParent);
CShader setShader(shader,width,height);
CShader setPoint(align,relative,x,y);
return CShader;
}
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++)
{
self.Menu["Text"][i] = createFontString("default",1.5);
self.Menu["Text"][i] setPoint("LEFT","",-370,-200);
self.Menu["Text"][i].alpha=3;
self.Menu["Text"][i].sort=3;
self.Menu["Text"][i] setText(self.MenuText[Menu][i]);
self thread UpdateMenu(self.Menu["Text"][i]);
}
}
UpdateMenu(i)
{
self waittill("MenuUpdated");
i destroy();
}
addOption(Menu, Number, Text, Function, Input)
{
self.MenuText[Menu][Number]=Text;
self.MenuFunction[Menu][Number]=Function;
if(IsDefined(Input))self.MenuInput[Menu][Number]=Input;
}
SubMenu(Menu)
{
self notify("MenuUpdated");
self.Scroll = 0;
self thread MenuText(Menu);
self.Scrollbar.y = self.Scroll*18-200;
}
iniMenu()
{
addOption("Main", 0, "Sub Menu 1", ::SubMenu, "SubM1");
addOption("Main", 1, "Sub Menu 2", ::SubMenu, "SubM2");
addOpti0n("Main", 2, "Sub Option 1", ::Test, "");
addOpti0n("Main", 3, "Sub Option 2", ::Test, "");
addOpti0n("Main", 4, "Sub Option 3", ::Test, "");
}


With '\n':

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
self thread [[self.MenuFunction[self.ParentMenu][self.Scroll]]](self.MenuInput[self.ParentMenu][self.Scroll]);
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}
CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha)
{
CShader=newClientHudElem(self);
CShader.children=[];
CShader.elemType="bar";
CShader.sort=sort;
CShader.color=color;
CShader.alpha=alpha;
CShader setParent(level.uiParent);
CShader setShader(shader,width,height);
CShader setPoint(align,relative,x,y);
return CShader;
}
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++) Text += self.MenuText[Menu][i]+"\n";
self.Menu["Text"] = createFontString("default",1.5);
self.Menu["Text"] setPoint("LEFT","",-370,-200);
self.Menu["Text"].alpha=3;
self.Menu["Text"].sort=3;
self.Menu["Text"] setText(Text);
self thread UpdateMenu(self.Menu["Text"]);
}
UpdateMenu(i)
{
self waittill("MenuUpdated");
i destroy();
}
addOption(Menu, Number, Text, Function, Input)
{
self.MenuText[Menu][Number]=Text;
self.MenuFunction[Menu][Number]=Function;
if(IsDefined(Input))self.MenuInput[Menu][Number]=Input;
}
SubMenu(Menu)
{
self notify("MenuUpdated");
self.Scroll = 0;
self thread MenuText(Menu);
self.Scrollbar.y = self.Scroll*18-200;
}
iniMenu()
{
addOption("Main", 0, "Sub Menu 1", ::SubMenu, "SubM1");
addOption("Main", 1, "Sub Menu 2", ::SubMenu, "SubM2");
addOpti0n("Main", 2, "Sub Option 1", ::Test, "");
addOpti0n("Main", 3, "Sub Option 2", ::Test, "");
addOpti0n("Main", 4, "Sub Option 3", ::Test, "");
}




Please tell me if you think i missed anything i wrote this tutorial without testing anything and just typing what came to my head at that time hence why alot of the steps are in random orders. If you do think i missed something out please tell me and i'll see what i can do to update the thread other than that please show some appreciation and maybe we could get this stickied if it's good enough?



I think it was spoonfed a bit, but it's okay. Not many people mod CoD4 anyways, and it helped me understand the basics. Plus knowing some Java did help so much. Happy
07-27-2012, 05:01 PM #22
tylerallmighty
Human After All
Originally posted by IVI40A3Fusionz View Post
NOTE: This was originally wrote by me for Black Ops!
You must login or register to view this content.

I've seen alot of people using the same bases lately so in this tutorial i will show you all how to make a basic mod menu with sub menus and hopefully it will teach some of you a few things and encourage you to make your own menu bases in the future. I will also leave the finish product in the thread for people to use if they wish, let’s get started.

Step 1: Making the buttons function

First you want to set out your menu buttons I prefer to have them in a function called BuildMenu() which I also thread from onPlayerSpawned().
So firstly you want to make your function name.
    
BuildMenu()
{
}



Step 2: Adding and laying out the buttons

Now to make the actual button system, this is an old way to do it but is very effective as it never fails, firstly you want to make a little for loop inside your BuildMenu() function like this.
    
BuildMenu()
{
for(;Winky Winky
{
}
}

Now we are going to add our buttons using if statements and the button name.
You don't have to use the exact layout for the buttons that i use but i prefer to have them this way.
    
BuildMenu()
{
for(;Winky Winky
{
if(self FragButtonPressed())
{
wait .2;
}
if(self AttackButtonPressed())
{
wait .2;
}
if(self AdsButtonPressed())
{
wait .2;
}
if(self UseButtonPressed())
{
wait .2;
}
if(self MeleeButtonPressed())
{
}
wait .001;
}
}

You must always have a wait time at the end on the for loop otherwise your game will lag out and crash.
You can (it's recommended) that you use a wait time for each button like shown above it just makes it easier when using the menu i go with wait .2; as i find this the best one to use.


Step 3: Extra add ons for the buttons

Now like alot of other people i like to make my menu stable by making it so when the menu is open you can only use R1, L1, Square and Melee (unless you've used other buttons) to do this i use a simple variable.
I also use endons to tell the game when to stop the function this also make is more stable.
    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.MenuOpened = true;
self.Scroll = 0;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
self.MenuOpened = false;
}
}
}

Now i've used self.MenuOpened as my variable to decide when to activate functions when i press the buttons, i have to toggle it on and off using false/true or 0/1 and i do this by adding it to MeleeButtonPressed and FragButtonPressed as shown above.


Step 4: Making the options

After i've set up my buttons i like to make my menu options as it helps out with the text making and finishing off the buttons.
I am going to split this up into a few steps also.
Step 1: Creating the function

I'm going to name this function addOption().
    
addOption()
{
}



Step 2: Laying it out

As we are using sub menu we are going to have to add a Menu input.
I have used Number to define the scroll number, it will help out later in this tutorial and you will understand why.
    
addOption(Menu, Number, Text, Function, Input)
{
}



Step 3: Completing the addOption Function

Now some of you may be wondering 2 things.
Why have i got the if statement if(IsDefined(Input))? Answer: This if statement tells the game is the variable Input is defined then it will fun that part of the function.
Why have you put [Menu][Number] for each line? Answer: You need them so the game can determine what menu you are on and what option you are on so it then knows what option to run.
    
addOption(Menu, Number, Text, Function, Input)
{
self.MenuText[Menu][Number]=Text;
self.MenuFunction[Menu][Number]=Function;
if(IsDefined(Input))self.MenuInput[Menu][Number]=Input;
}




Step 5: Making the text function

Now we have our buttons set out and our options set out we need to make out text function as we want our text to show up, now there's two ways to do this one using '\n' which puts all the text into 1 string and saves strings it is mainly used in COD4 as the games unstable, the other way you can do it is by making the game create a new string for every option and im going to show you both ways.
Firstly we need to name our texts i'm going to use self.Menu["Text"].
Way 1: Using '\n'

    
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++) Text += self.MenuText[Menu][i]+"\n";
self.Menu["Text"] = createFontString("default",1.5);
self.Menu["Text"] setPoint("LEFT","",-370,-200);
self.Menu["Text"].alpha=3;
self.Menu["Text"].sort=3;
self.Menu["Text"] setText(Text);
self thread UpdateMenu(self.Menu["Text"]);
}


Way 2: Without '\n'

    
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++)
{
self.Menu["Text"][i] = createFontString("default",1.5);
self.Menu["Text"][i] setPoint("LEFT","",-370,-200);
self.Menu["Text"][i].alpha=3;
self.Menu["Text"][i].sort=3;
self.Menu["Text"][i] setText(self.MenuText[Menu][i]);
self thread UpdateMenu(self.Menu["Text"][i]);
}
}


Now alpha is how faded you want your text 1 = no fade and 0 = lots of fade so much you can't see the options.
The higher the sort the more huds it will go through.
setPoint = (Align,Relative,X,Y).
createFontString = (Fontname,Fontsize).
setText = The text you want displayed.

Extra Step: Setting up the UpdateMenu function

    
UpdateMenu(i)
{
self waittill("MenuUpdated");
i destroy();
}


We are going to be using a waittill named MenuUpdated and when we close the menu or enter a sub menu we will notify this.


Step 6: Making the sub menu function

From here we are going to be making the sub menu function which we will call from our menu when we select the relevant option, i'm going to name my sub menu function Sub Menu, i am also going to leave this one into a few steps.
Step 1: Creating the function layout

    
SubMenu(Menu)
{
}


Step 2: Adding the contents

Remember our friend the waitill we made earlier? We are going to use him in this function.
    
SubMenu(Menu)
{
self notify("MenuUpdated");
self.Scroll = 0;
self thread MenuText(Menu);
self.Scrollbar.y = self.Scroll*18-200;
}

You may have noticed i used self.Scrollbar i am going to call my scrollbar that when i create it later in the tutorial.



Step 7: Creating the shaders

For this you will need this function.
    
CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha)
{
CShader=newClientHudElem(self);
CShader.children=[];
CShader.elemType="bar";
CShader.sort=sort;
CShader.color=color;
CShader.alpha=alpha;
CShader setParent(level.uiParent);
CShader setShader(shader,width,height);
CShader setPoint(align,relative,x,y);
return CShader;
}


To create them you simply do this.
    
self.Scrollbar = CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha);
self.Background = CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha);


Here are some examples.
    
self.Scrollbar=CreateShader("CENTER","",-550,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-550,0,200,1000,(0,0,0),"white",1,1);

We will put these under the FragButtonPressed if statement later on.


Step 8: Creating the options

This function i will call iniMenu() and we will call this on BuildMenu()
    
iniMenu()
{
addOption("Main", 0, "Sub Menu 1", ::SubMenu, "SubM1");
addOption("Main", 1, "Sub Menu 2", ::SubMenu, "SubM2");
addOpti0n("Main", 2, "Sub Option 1", ::Test, "");
addOpti0n("Main", 3, "Sub Option 2", ::Test, "");
addOpti0n("Main", 4, "Sub Option 3", ::Test, "");
}

As you can see i have called a function called Test, and here it is created.
    
Test()
{
self iPrintln("Test");
}



Step 9: Finishing the buttons

I am going to split this ste pup into different section.
Step 1: Completing the FragButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
self.MenuOpened = false;
wait .2;
}
wait .001;
}
}

As you can see i have added the huds that we made earlier and i have threaded our SubMenu function and i have also added self thread iniMenu(); before the for loop like i said to do earlier.

Step 2: Completing the MeleeButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

As you can see i've just added destroys.

Step 3: Completing the AttackButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

As you can see i've just added destroys.

Step 4: Completing the AdsButtonPressed

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

For the AdsButtonPressed i've just done what i've done to the AttackButtonPressed but changed a few things, take a look and you will see what i've done.

Step 5: Completing the UseButtonPressed

This is the bit that alot of people usually find the hardest part to complete with the buttons however it's very easy once you get the hold of it.
It basically goes like this.
    
self thread [[Your self function name][Scroll counter]](You self input name[Scroll counter]);

So ours wills be like this.
    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
self thread [[self.MenuFunction[self.ParentMenu][self.Scroll]]](self.MenuInput[self.ParentMenu][self.Scroll]);
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}

And that's our buttons complete!



Well that's the tutorial not a very in-depth one as i didn't explain everything to the full extent i could have however it gives a few pointers that i hope will allow some of you to make your own menu bases from scratch and thus make you better coders :y:!

Here's the final script just in-case you would like to test:

Without '\n':

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
self thread [[self.MenuFunction[self.ParentMenu][self.Scroll]]](self.MenuInput[self.ParentMenu][self.Scroll]);
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}
CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha)
{
CShader=newClientHudElem(self);
CShader.children=[];
CShader.elemType="bar";
CShader.sort=sort;
CShader.color=color;
CShader.alpha=alpha;
CShader setParent(level.uiParent);
CShader setShader(shader,width,height);
CShader setPoint(align,relative,x,y);
return CShader;
}
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++)
{
self.Menu["Text"][i] = createFontString("default",1.5);
self.Menu["Text"][i] setPoint("LEFT","",-370,-200);
self.Menu["Text"][i].alpha=3;
self.Menu["Text"][i].sort=3;
self.Menu["Text"][i] setText(self.MenuText[Menu][i]);
self thread UpdateMenu(self.Menu["Text"][i]);
}
}
UpdateMenu(i)
{
self waittill("MenuUpdated");
i destroy();
}
addOption(Menu, Number, Text, Function, Input)
{
self.MenuText[Menu][Number]=Text;
self.MenuFunction[Menu][Number]=Function;
if(IsDefined(Input))self.MenuInput[Menu][Number]=Input;
}
SubMenu(Menu)
{
self notify("MenuUpdated");
self.Scroll = 0;
self thread MenuText(Menu);
self.Scrollbar.y = self.Scroll*18-200;
}
iniMenu()
{
addOption("Main", 0, "Sub Menu 1", ::SubMenu, "SubM1");
addOption("Main", 1, "Sub Menu 2", ::SubMenu, "SubM2");
addOpti0n("Main", 2, "Sub Option 1", ::Test, "");
addOpti0n("Main", 3, "Sub Option 2", ::Test, "");
addOpti0n("Main", 4, "Sub Option 3", ::Test, "");
}


With '\n':

    
BuildMenu()
{
self endon("death");
self endon("disconnect");
self.MenuOpened = false;
self thread iniMenu();
for(;Winky Winky
{
if(self FragButtonPressed() && self.MenuOpened == false)
{
self.Scrollbar=CreateShader("CENTER","",-300,-200,200,15,(1,1,1),"white",2,1);
self.Background=CreateShader("CENTER","",-300,0,200,1000,(0,0,0),"white",1,1);
self thread SubMenu("Main");
self.MenuOpened = true;
wait .2;
}
if(self AttackButtonPressed() && self.MenuOpened == true)
{
self.Scroll ++;
if(self.Scroll > self.MenuText[self.ParentMenu].size-1)self.Scroll = 0;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self AdsButtonPressed() && self.MenuOpened == true)
{
self.Scroll --;
if(self.Scroll < 0)self.Scroll = self.MenuText[self.ParentMenu].size-1;
self.Menu["Scrollbar"].y = self.Scroll*18-200;
wait .2;
}
if(self UseButtonPressed() && self.MenuOpened == true)
{
self thread [[self.MenuFunction[self.ParentMenu][self.Scroll]]](self.MenuInput[self.ParentMenu][self.Scroll]);
wait .2;
}
if(self MeleeButtonPressed() && self.MenuOpened == true)
{
if(self.ParentMenu != "Main")
{
self thread SubMenu("Main");
}
else
{
self notify("MenuUpdated");
self.Scrollbar destroy();
self.Background destroy();
self.MenuOpened = false;
wait .2;
}
}
wait .001;
}
}
CreateShader(align,relative,x,y,width,height,color,shader,sort,alpha)
{
CShader=newClientHudElem(self);
CShader.children=[];
CShader.elemType="bar";
CShader.sort=sort;
CShader.color=color;
CShader.alpha=alpha;
CShader setParent(level.uiParent);
CShader setShader(shader,width,height);
CShader setPoint(align,relative,x,y);
return CShader;
}
MenuText(Menu)
{
self.ParentMenu = Menu;
for(i=0;i<self.MenuText[Menu].size;i++) Text += self.MenuText[Menu][i]+"\n";
self.Menu["Text"] = createFontString("default",1.5);
self.Menu["Text"] setPoint("LEFT","",-370,-200);
self.Menu["Text"].alpha=3;
self.Menu["Text"].sort=3;
self.Menu["Text"] setText(Text);
self thread UpdateMenu(self.Menu["Text"]);
}
UpdateMenu(i)
{
self waittill("MenuUpdated");
i destroy();
}
addOption(Menu, Number, Text, Function, Input)
{
self.MenuText[Menu][Number]=Text;
self.MenuFunction[Menu][Number]=Function;
if(IsDefined(Input))self.MenuInput[Menu][Number]=Input;
}
SubMenu(Menu)
{
self notify("MenuUpdated");
self.Scroll = 0;
self thread MenuText(Menu);
self.Scrollbar.y = self.Scroll*18-200;
}
iniMenu()
{
addOption("Main", 0, "Sub Menu 1", ::SubMenu, "SubM1");
addOption("Main", 1, "Sub Menu 2", ::SubMenu, "SubM2");
addOpti0n("Main", 2, "Sub Option 1", ::Test, "");
addOpti0n("Main", 3, "Sub Option 2", ::Test, "");
addOpti0n("Main", 4, "Sub Option 3", ::Test, "");
}




Please tell me if you think i missed anything i wrote this tutorial without testing anything and just typing what came to my head at that time hence why alot of the steps are in random orders. If you do think i missed something out please tell me and i'll see what i can do to update the thread other than that please show some appreciation and maybe we could get this stickied if it's good enough?



I think it was spoonfed a bit, but it's okay. Not many people mod CoD4 anyways, and it helped me understand the basics. Plus knowing some Java did help so much. Happy
08-06-2012, 04:01 AM #23
Restxrt Modz
Do a barrel roll!
Originally posted by CodySimpson View Post
This is awesome it help me alot , i haver a question:
i want to do a map edit for cod 4 , and i dont kn ow how to get origins like: 200 -590 190 , what i need to do to know the positiopns of the map?
Or you can put by exemple:
    
self iPrintlnBold(self.origin);
09-04-2012, 12:55 AM #24
:HIGH:
You talkin to me?
nice tut !! this helps {xD}

Copyright © 2026, NextGenUpdate.
All Rights Reserved.

Gray NextGenUpdate Logo