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-27-2010, 02:06 PM #11
BuC-ShoTz
TeamMvKâ?¢
very nice tutorial

The following user thanked BuC-ShoTz for this useful post:

XxprokillahxX
10-27-2010, 08:41 PM #12
thanks bucN apart from the original topics i am adding. is there any other tuts about dconnor's i should add?
10-27-2010, 08:49 PM #13
Helped me alot
10-27-2010, 08:57 PM #14
NiiNo
Pokemon Trainer
Thanks, nice thread! thumbs up and + rep .
10-27-2010, 09:26 PM #15
bensrevenge
You talkin to me?
Originally posted by XxprokillahxX View Post
thanks bucN apart from the original topics i am adding. is there any other tuts about dconnor's i should add?


you should add how to add a verification
10-28-2010, 05:16 AM #16
Originally posted by bensrevenge View Post
you should add how to add a verification


the only problem with this is that there is so many verification systems around there wont be only "one" tutorial. i might make a tut for the most basic though

Copyright © 2026, NextGenUpdate.
All Rights Reserved.

Gray NextGenUpdate Logo