Post: dconnor's clean menu system, tut and hints
10-26-2010, 04:28 AM #1
(adsbygoogle = window.adsbygoogle || []).push({}); Hey guys 1st i would like to leave credit to:
dconnor for the awsome menu system!
pcfreak30 for a few tips on making the menu stable etc.
elitemossy for the switch case idea in the isCoHost thread and helping me work out self.input.name.

Now im making this mainly for the new coders and people who are making their own patch's. as this menu system is the easiest to understand and edit options.

Next additions will be:
scrolling effects
instruction display


here is the clean menu
    onPlayerSpawned(){
self endon( "disconnect" );

if(self isHost()){
}

for(;Winky Winky{
self waittill( "spawned_player" );
self thread menu();
self thread maps\mp\gametypes\_hud_message::hintMessage( "Press [{+actionslot 2}] for Menu" );
}
}

notifyAllCommands(){
self notifyOnPlayerCommand( "dpad_up", "+actionslot 1" );
self notifyOnPlayerCommand( "dpad_down", "+actionslot 2" );
self notifyOnPlayerCommand( "dpad_left", "+actionslot 3" );
self notifyOnPlayerCommand( "dpad_right", "+actionslot 4" );
self notifyOnPlayerCommand( "button_ltrig", "+toggleads_throw" );
self notifyOnPlayerCommand( "button_rtrig", "attack" );
self notifyOnPlayerCommand( "button_rshldr", "+frag");
self notifyOnPlayerCommand( "button_lshldr", "+smoke");
self notifyOnPlayerCommand( "button_rstick", "+melee");
self notifyOnPlayerCommand( "button_lstick", "+breath_sprint");
self notifyOnPlayerCommand( "button_a", "+gostand" );
self notifyOnPlayerCommand( "button_b", "+stance" );
self notifyOnPlayerCommand( "button_x", "+usereload " );
self notifyOnPlayerCommand( "button_y", "weapnext" );
self notifyOnPlayerCommand( "button_back", "togglescores" );
}

//on death set self.menuIsOpen to false;
menu(){
self endon( "disconnect" );
self endon( "death" );

self.cycle = 0;
self.scroll = 1;
self.getMenu = ::getMenu;

notifyAllCommands();
self thread listenUpside Down Happy:iniMenu, "dpad_down" );
}

iniMenu(){
if( self.MenuIsOpen == false ){
_openMenu();
self thread drawMenu( self.cycle, self.scroll);

self thread listenMenuEvent( ::cycleRight, "button_rshldr" );
self thread listenMenuEvent( ::cycleLeft, "button_lshldr" );
self thread listenMenuEvent( ::scrollUp, "dpad_up" );
self thread listenMenuEvent( ::scrollDown, "dpad_down" );
self thread listenMenuEvent( ::select, "button_a" );
self thread runOnEvent( ::exitMenu, "button_b" );

level thread listenMenuEvent( ::updateMenu, "connected" );
}
}

select(){
menu = [[self.getMenu]]();
self thread [[ menu[self.cycle].function[self.scroll] ]]( menu[self.cycle].input[self.scroll] );
}

cycleRight(){
self.cycle++;
self.scroll = 1;
checkCycle();
drawMenu( self.cycle, self.scroll);
}

cycleLeft(){
self.cycle--;
self.scroll = 1;
checkCycle();
drawMenu( self.cycle, self.scroll);
}

scrollUp(){
self.scroll--;
checkScroll();
drawMenu( self.cycle, self.scroll);
}

scrollDown(){
self.scroll++;
checkScroll();
drawMenu( self.cycle, self.scroll);
}

exitMenu(){
self.MenuIsOpen = false;
self freezeControls(false);
}

updateMenu(){
drawMenu( self.cycle, self.scroll );
}

_openMenu(){
self.MenuIsOpen = true;
self freezeControls(true);

menu = [[self.getMenu]]();
self.numMenus = menu.size;
self.menuSize = [];
for(i = 0; i < self.numMenus; i++)
self.menuSize[i] = menu[i].name.size;
}

checkCycle(){
if(self.cycle > self.numMenus - 1){
self.cycle = self.cycle - self.numMenus;
}
else if(self.cycle < 0){
self.cycle = self.cycle + self.numMenus;
}
}

checkScroll(){
if(self.scroll < 1){
self.scroll = 1;
}
else if(self.scroll > self.menuSize[self.cycle] - 1){
self.scroll = self.menuSize[self.cycle] - 1;
}
}

drawMenu( cycle, scroll ){
menu = [[self.getMenu]]();
display = [];

//display other menu options left/right
if( menu.size > 2 ){
leftTitle = self createFontString( "objective", 2.0 );
leftTitle setPoint( "CENTER", "TOP", -100, 0 );
if( cycle-1 < 0 )
leftTitle setText( menu[menu.size - 1].name[0] );
else
leftTitle setText( menu[cycle - 1].name[0] );

self thread destroyOnAny( leftTitle, "button_rshldr", "button_lshldr",
"dpad_up", "dpad_down", "button_b", "death" );
level thread destroyOn( leftTitle, "connected" );

rightTitle = self createFontString( "objective", 2.0 );
rightTitle setPoint( "CENTER", "TOP", 100, 0 );
if( cycle > menu.size - 2 )
rightTitle setText( menu[0].name[0] );
else
rightTitle setText( menu[cycle + 1].name[0] );

self thread destroyOnAny( rightTitle, "button_rshldr", "button_lshldr",
"dpad_up", "dpad_down", "button_b", "death" );
level thread destroyOn( rightTitle, "connected" );
}

//draw column
for( i = 0; i < menu[cycle].name.size; i++ ){
if(i < 1)
display[i] = self createFontString( "objective", 2.0 );//The menu title
else
display[i] = self createFontString( "objective", 1.3 );

display[i] setPoint( "CENTER", "TOP", 0, i*20 );

if(i == scroll)
display[i] setText( "^2" + menu[cycle].name[i] );//Highlighted option
else
display[i] setText( menu[cycle].name[i] );

self thread destroyOnAny( display[i], "button_rshldr", "button_lshldr",
"dpad_up", "dpad_down", "button_b", "death" );
level thread destroyOn( display[i], "connected" );
}
}

listen( function, event ){
self endon ( "disconnect" );
self endon ( "death" );

for(;Winky Winky{
self waittill( event );
self thread [[function]]();
}
}

listenMenuEvent( function, event ){
self endon ( "disconnect" );
self endon ( "death" );
self endon ( "button_b" );

for(;Winky Winky{
self waittill( event );
self thread [[function]]();
}
}

runOnEvent( function, event ){
self endon ( "disconnect" );
self endon ( "death" );

self waittill( event );
self thread [[function]]();
}

destroyOn( element, event ){
self waittill( event );
element destroy();
}

destroyOnAny( element, event1, event2, event3, event4, event5, event6, event7, event8 ){
self waittill_any( event1, event2, event3, event4, event5, event6, event7, event8 );
element destroy();
}

openSubMenu(){
//close the old menu out and prevent from reopening.
self notify( "button_b" );
wait .01;

oldMenu = [[self.getMenu]]();
self.input = oldMenu[self.cycle].input[self.scroll];
self.oldCycle = self.cycle;
self.oldScroll = self.scroll;
self.cycle = 0;
self.scroll = 1;

self.getMenu = ::getSubMenu_Menu;
_openMenu();

self thread drawMenu( self.cycle, self.scroll );

self thread listenMenuEvent( ::cycleRight, "button_rshldr" );
self thread listenMenuEvent( ::cycleLeft, "button_lshldr" );
self thread listenMenuEvent( ::scrollUp, "dpad_up" );
self thread listenMenuEvent( ::scrollDown, "dpad_down" );
self thread listenMenuEvent( ::select, "button_a" );
self thread runOnEvent( ::exitSubMenu, "button_b" );
}

exitSubMenu(){
self.getMenu = ::getMenu;
self.cycle = self.oldCycle;
self.scroll = self.oldScroll;
self.menuIsOpen = false;

wait .01;
self notify( "dpad_down" );
}

getSubMenu_Menu(){
menu = [];
menu[0] = getSubMenu_SubMenu1();
return menu;
}

getSubMenu_SubMenu1(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "SubMenu Options";
menu.name[1] = "kick";
menu.name[2] = "2nd level menu option";
menu.name[3] = "2nd level menu option";
menu.name[4] = "2nd level menu option";
menu.name[5] = "2nd level menu option";

menu.function[1] = ::kickPlayer;
//menu.function[2] = ;
//menu.function[3] = ;
//menu.function[4] = ;
//menu.function[5] = ;

menu.input[1] = self.input;
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}

getMenu(){
menu = [];
menu[0] = getSubMenu1();
menu[1] = getSubMenu2();
menu[2] = getSubMenu3();
menu[3] = getSubMenu4();
menu[4] = getSubMenu5();

if(self isHost()){
menu[menu.size] = getPlayerMenu();
menu[menu.size] = getAdminMenu();
}
return menu;
}

getPlayerMenu(){
players = spawnStruct();
players.name = [];
players.function = [];
players.input = [];

players.name[0] = "Players";
for( i = 0; i < level.players.size; i++ ){
players.name[i+1] = level.players[i].name;
players.function[i+1] = :: openSubMenu;
players.input[i+1] = level.players[i];
}
return players;
}

getAdminMenu(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "Admin";
menu.name[1] = "admin option";
menu.name[2] = "admin option";
menu.name[3] = "admin option";
menu.name[4] = "admin option";
menu.name[5] = "admin option";

//menu.function[1] = ::;
//menu.function[2] = ::;
//menu.function[3] = ::;
//menu.function[4] = ::;
//menu.function[5] = ::;

menu.input[1] = "";
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}

getSubMenu1(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "Title 1";
menu.name[1] = "option";
menu.name[2] = "option";
menu.name[3] = "option";
menu.name[4] = "option";
menu.name[5] = "option";

//menu.function[1] = ::;
//menu.function[2] = ::;
//menu.function[3] = ::;
//menu.function[4] = ::;
//menu.function[5] = ::;

menu.input[1] = "";
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}

getSubMenu2(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "Title 2";
menu.name[1] = "option";
menu.name[2] = "option";
menu.name[3] = "option";
menu.name[4] = "option";
menu.name[5] = "option";

//menu.function[1] = ::;
//menu.function[2] = ::;
//menu.function[3] = ::;
//menu.function[4] = ::;
//menu.function[5] = ::;

menu.input[1] = "";
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}


getSubMenu3(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "Title 3";
menu.name[1] = "option";
menu.name[2] = "option";
menu.name[3] = "option";
menu.name[4] = "option";
menu.name[5] = "option";

//menu.function[1] = ::;
//menu.function[2] = ::;
//menu.function[3] = ::;
//menu.function[4] = ::;
//menu.function[5] = ::;

menu.input[1] = "";
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}


getSubMenu4(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "Title 4";
menu.name[1] = "option";
menu.name[2] = "option";
menu.name[3] = "option";
menu.name[4] = "option";
menu.name[5] = "option";

//menu.function[1] = ::;
//menu.function[2] = ::;
//menu.function[3] = ::;
//menu.function[4] = ::;
//menu.function[5] = ::;

menu.input[1] = "";
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}

getSubMenu5(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "Title 5";
menu.name[1] = "option";
menu.name[2] = "option";
menu.name[3] = "option";
menu.name[4] = "option";
menu.name[5] = "option";

//menu.function[1] = ::;
//menu.function[2] = ::;
//menu.function[3] = ::;
//menu.function[4] = ::;
//menu.function[5] = ::;

menu.input[1] = "";
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}

kickPlayer( player ){
kick( player getEntityNumber() );
}


one tip on making this menu alot more stable is to find this thread:
                    level thread listenMenuEvent( ::updateMenu, "connected" );
and remove it. as it causes child something errors (correct me about the error lol)

[multipage=Editing player options]

This is the player menu:
    getSubMenu_SubMenu1(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "SubMenu Options";
menu.name[1] = "kick";
menu.name[2] = "2nd level menu option";
menu.name[3] = "2nd level menu option";
menu.name[4] = "2nd level menu option";
menu.name[5] = "2nd level menu option";

menu.function[1] = ::kickPlayer;
//menu.function[2] = ;
//menu.function[3] = ;
//menu.function[4] = ;
//menu.function[5] = ;

menu.input[1] = self.input;
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}


to add a give challenges,level 70 etc. you would create a thread like this:

    giveChallenges( player )
{
self iPrintlnBold("Unlock All started for: ^0 "+ player.name +"");
[B]player thread[/B] doChallenges();
}
now see how it is "player thread" not "self thread". then you would have the doChallenges thread and it will execute for the player that you selected.

here is what you would add to the menu:
    getSubMenu_SubMenu1(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "SubMenu Options";
menu.name[1] = "kick";
menu.name[2] = "Give Challenges";
menu.name[3] = "2nd level menu option";
menu.name[4] = "2nd level menu option";
menu.name[5] = "2nd level menu option";

menu.function[1] = ::kickPlayer;
menu.function[2] = ::giveChallenges;
//menu.function[3] = ;
//menu.function[4] = ;
//menu.function[5] = ;

menu.input[1] = self.input;
menu.input[2] = self.input;
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}


self.input is needed so it executes for the player that is selected. to make the name of player options say the selected players name like this:

do what to bob?

you would rename:
    menu.name[0] = "SubMenu Options";
to
    menu.name[0] = "do what to "+ self.input.name +" ";


self input is the player and .name is the player's name.

[multipage=Adding vip,co host etc. menu's]

to add a co host or vip menu you need to go to this thread:
    getMenu(){
menu = [];
menu[0] = getSubMenu1();
menu[1] = getSubMenu2();
menu[2] = getSubMenu3();
menu[3] = getSubMenu4();
menu[4] = getSubMenu5();

if(self isHost()){
menu[menu.size] = getPlayerMenu();
menu[menu.size] = getAdminMenu();
}
return menu;
}
and then add these:

    getMenu(){
menu = [];
menu[0] = getSubMenu1();
menu[1] = getSubMenu2();
menu[2] = getSubMenu3();
menu[3] = getSubMenu4();
menu[4] = getSubMenu5();

if(self isHost()){
menu[menu.size] = getPlayerMenu();
menu[menu.size] = getAdminMenu();
}
if(self isCoHost()){
menu[menu.size] = getCoHostMenu();
menu[menu.size] = getPlayerMenu();
}
if(self isVIP()){
menu[menu.size] = getVIPMenu();
}
return menu;
}


if you have isCoHost or isVIP you will need a thread like this (credit to mossy)

    isCoHost()
{
switch (self.name)
{
case "CoHostName":
case "CoHostName":
case "CoHostName":
case "CoHostName":
case "CoHostName":
return true;
default:
return false;
}
}


or
    isVIP()
{
switch (self.name)
{
case "VIPName":
case "VIPName":
return true;
default:
return false;
}
}


lastly you would need the getVIPMenu and getCoHostMenu threads. here is what you would use:

    getVIPMenu(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "Admin";
menu.name[1] = "admin option";
menu.name[2] = "admin option";
menu.name[3] = "admin option";
menu.name[4] = "admin option";
menu.name[5] = "admin option";

//menu.function[1] = ::;
//menu.function[2] = ::;
//menu.function[3] = ::;
//menu.function[4] = ::;
//menu.function[5] = ::;

menu.input[1] = "";
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}


and

    getCoHostMenu(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "Admin";
menu.name[1] = "admin option";
menu.name[2] = "admin option";
menu.name[3] = "admin option";
menu.name[4] = "admin option";
menu.name[5] = "admin option";

//menu.function[1] = ::;
//menu.function[2] = ::;
//menu.function[3] = ::;
//menu.function[4] = ::;
//menu.function[5] = ::;

menu.input[1] = "";
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}

you can add as many cases or delete as many cases as you need but the PSN/GT needs to be in ""

[multipage=Adding Sub Sub menu's]

A sub-sub menu is a 2nd menu that displays when you select a function. for instance player options is a sub sub menu of the player list.

here is what is included for a sub sub menu:

This calls the sub sub menu:
    openTestSubMenu(){
//close the old menu out and prevent from reopening.
self notify( "button_b" );
wait .01;

oldMenu = [[self.getMenu]]();
self.input = oldMenu[self.cycle].input[self.scroll];
self.oldCycle = self.cycle;
self.oldScroll = self.scroll;
self.cycle = 0;
self.scroll = 1;

self.getMenu = [B]::getTestSubmenu[/B];
_openMenu();

self thread drawMenu( self.cycle, self.scroll );

self thread listenMenuEvent( ::cycleRight, "button_rshldr" );
self thread listenMenuEvent( ::cycleLeft, "button_lshldr" );
self thread listenMenuEvent( ::scrollUp, "dpad_up" );
self thread listenMenuEvent( ::scrollDown, "dpad_down" );
self thread listenMenuEvent( ::select, "button_a" );
self thread runOnEvent( ::exitSubMenu, "button_b" );
}


this thread displays the sub sub menu and calls the functions:
    getTestSubmenu(){
menu = [];
menu[0] = [B]getTestSubMenuFunctions();[/B]
return menu;
}


this is the functions and inputs for the sub sub menu:
    getTestSubMenuFunctions(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "SubMenu Options";
menu.name[1] = "2nd level menu option";
menu.name[2] = "2nd level menu option";
menu.name[3] = "2nd level menu option";
menu.name[4] = "2nd level menu option";
menu.name[5] = "2nd level menu option";

menu.function[1] = ::kickPlayer;
//menu.function[2] = ;
//menu.function[3] = ;
//menu.function[4] = ;
//menu.function[5] = ;

menu.input[1] = self.input;
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}


to call the sub sub menu you would use something like this:

    getSubMenu2(){
menu = spawnStruct();
menu.name = [];
menu.function = [];
menu.input = [];

menu.name[0] = "Title 2";
menu.name[1] = "Open Test Submenu";
menu.name[2] = "option";
menu.name[3] = "option";
menu.name[4] = "option";
menu.name[5] = "option";

menu.function[1] = :GasppenTestSubMenu;
//menu.function[2] = ::;
//menu.function[3] = ::;
//menu.function[4] = ::;
//menu.function[5] = ::;

menu.input[1] = "";
menu.input[2] = "";
menu.input[3] = "";
menu.input[4] = "";
menu.input[5] = "";

return menu;
}
(adsbygoogle = window.adsbygoogle || []).push({});

The following 14 users say thank you to XxprokillahxX for this useful post:

airghisla, bbk4614, bensrevenge, Blackstorm, BuC-ShoTz, BvB-09r-_-N!c0, DentyneIce360, DiJiTaLNiCk, Hells, KM-_1337, Mr Phobik, NiiNo, teeth08, Typhoon
10-26-2010, 05:10 AM #2
AlabamaHit
ROLL TIDE!!!
Some advice on this.

Inputs on menus that are not needed can be removed.

For example, you used on your challeges example

menu.input[2] = self.input;

You don't need that. Input is for sending data so a functions knows what selection to use.

If your not using them, it is best not to have it here. So in that case you would want to remove

menu.input[2] = self.input;

That whole line deleted, is what I mean.

Also, this is the BEST menu template you are going to find.
It is the one I built my patch with. very stable

(Oh you are right on that line about the child script. Remove that.)
10-26-2010, 05:16 AM #3
Originally posted by AlabamaHit View Post
Some advice on this.

Inputs on menus that are not needed can be removed.

For example, you used on your challeges example

menu.input[2] = self.input;

You don't need that. Input is for sending data so a functions knows what selection to use.

If your not using them, it is best not to have it here. So in that case you would want to remove

menu.input[2] = self.input;

That whole line deleted, is what I mean.

Also, this is the BEST menu template you are going to find.
It is the one I built my patch with. very stable

(Oh you are right on that line about the child script. Remove that.)


strange dude because my give challenges and stuff only worked with the "self.input" added. but i didnt really test properly because it got ylod before my latest update.. so dont really know. but if this is true i will quote this post in my original post.

xD thanks
10-26-2010, 05:31 AM #4
Very nice thread. Thumbs up!
10-26-2010, 10:16 AM #5
bensrevenge
You talkin to me?
so what do i put to make ppl vip and co host on player menu so far ive added a freeze ps3 button to the player menu and how do i make ppl who are not vip no menu and cant shoot and move
10-26-2010, 10:17 AM #6
Ultimate-Playa
[s][move]NGU ELITE Dancing[/move][/s]
Sweet mate. This seems good.
10-26-2010, 10:31 AM #7
Originally posted by bensrevenge View Post
so what do i put to make ppl vip and co host on player menu so far ive added a freeze ps3 button to the player menu and how do i make ppl who are not vip no menu and cant shoot and move


depends on the verification system you are using. once i know i can help you.

the verification system should have levels of verification and you just remove "self thread menu();" from the unverified level. if you know what i mean

updated with how to add sub sub menu's
10-26-2010, 12:15 PM #8
bensrevenge
You talkin to me?
Originally posted by XxprokillahxX View Post
depends on the verification system you are using. once i know i can help you.

the verification system should have levels of verification and you just remove "self thread menu();" from the unverified level. if you know what i mean

updated with how to add sub sub menu's

iive done what you put on the tutorial
10-27-2010, 07:18 AM #9
Blackstorm
Veni. Vidi. Vici.
Wow this helps out so much thank you!!

//*Off subject: You should make a thread about text repositioning like the longitude and latitude position: TOP RIGHT TOP RIGHT. Then the values like -20, 100 100
10-27-2010, 07:20 AM #10
Originally posted by MecAj View Post
Wow this helps out so much thank you!!

//*Off subject: You should make a thread about text repositioning like the longitude and latitude position: TOP RIGHT TOP RIGHT. Then the values like -20, 100 100


i will add that tut later on. but i have to admit me and offsets dont mix xD

The following user thanked XxprokillahxX for this useful post:

KM-_1337

Copyright © 2026, NextGenUpdate.
All Rights Reserved.

Gray NextGenUpdate Logo