1 /***************************************************************************
2 manager.c - description
4 begin : Thu Sep 20 2001
5 copyright : (C) 2001 by Michael Speck
6 email : kulkanie@gmx.net
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
19 #include "../game/game.h"
24 #include "../gui/stk.h"
28 extern SDL_Surface
*stk_display
;
30 extern List
*menus
; /* list of menus */
31 int menu_x
= 54, menu_y
= 220, menu_w
= 256, menu_h
= 256, menu_border
= 16; /* default region where menu is displayed centered */
32 int cx
= 384, cy
= 220, cw
= 256, ch
= 200; /* center charts here */
33 Menu
*cur_menu
; /* current menu */
34 extern SDL_Surface
*mbkgnd
; /* menu background */
35 extern StkFont
*mfont
, *mhfont
, *mcfont
; /* font, highlight font, caption font */
37 List
*levelset_names
= 0; /* all names in home & install directory */
38 char **levelset_names_home
= 0; /* home directory sets */
39 int levelset_count_home
= 0;
40 char **levelset_names_local
; /* non-network levelsets */
41 int levelset_count_local
;
42 char *edit_set
= 0; /* selected set in editor menu */
43 extern int stk_quit_request
;
45 extern StkSound
*wav_menu_click
;
46 extern StkSound
*wav_menu_motion
;
48 /* some items we need to know to assign name lists later */
49 Item
*item_set
, *item_theme
, *item_resume_0
;
51 int chart_id
= 0; /* current chart displayed */
53 extern char **theme_names
;
54 extern int theme_count
;
58 #define HINT_QUIT _("There's nasty work out there waiting for you... better stay here!")
59 #define HINT_ANIM _("If you turn animations low there'll be less details which will speed up the game a great deal.")
60 #define HINT_TRP _("Enable/disable transparency of bonuses and animations.")
61 #define HINT_SHADOW _("If you disable shadows it will speed up the game but won't look that good. ;-)")
62 #define HINT_BONUS_INFO _("If this is enabled you'll see the time left for all bonuses and penalties at the right side of the screen.")
63 #define HINT_DISPLAY _("You may run LBreakout2 either fullscreen or windowed. This switch may be done anywhere by pressing 'f'.")
64 #define HINT_FPS _("You you don't want LBreakout2 to consume all of your CPU (best performance) limit the frame rate.")
65 #define HINT_CONVEX _("As long as this option is enabled the paddle is treated as convex allowing easy aiming. If you "\
66 "disable this option the real physics will show up and you'll have to influence the ball by paddle movement "\
67 "and the hemispherical ends. For cracks only!")
68 #define HINT_BALLLEVEL _("If you can't see the ball because of thousands of bonuses coming down set this option to 'Above Bonuses'")
69 #define HINT_DEBRISLEVEL _("If you can't see the ball because of all the debris coming down set this option to 'Below Balls'")
70 #define HINT_USEHINTS _("Enable/disable these quick hints. See the manual for more information about how to use LBreakout2!")
71 #define HINT_KEYSPEED _("Adjust the paddle speed for movement by keys. (pixels per second)")
72 #define HINT_PLAYERS _("These are the number of players and their names. If one player looses a ball or restarts the level it's the next player's turn.")
73 #define HINT_DIFF _("KIDS:#Lives: 9 (max. 12)#Paddle Size: 252 (max. 396)#Ball Speed: 100-200#Bonus: -50% (no penalties, no bad speech)##"\
74 "EASY:#Lives: 6 (max. 9)#Paddle Size: 72 (max. 180)#Ball Speed: 240-400 pixels/sec#Bonus: -20%##"\
75 "MEDIUM:#Lives: 5 (max. 7)#Paddle Size: 54 (max. 144)#Ball Speed: 270-430 pixels/sec##"\
76 "HARD:#Lives: 4 (max. 5)#Paddle Size: 54 (max. 108)#Ball Speed: 300-450 pixels/sec#Bonus: +30%")
77 #define HINT_START_LBR _("Play the original LBreakout2 levelset.")
78 #define HINT_START_CUSTOM _("Play an additional levelset.")
79 #define HINT_EDITOR_SET _("This is the list of the levelsets found in ~/.lgames/lbreakout2-levels which you may edit. If you "\
80 "choose <CREATE SET> and click on 'Edit Set' below you'll be asked to enter a levelsetname and the new levelset " \
81 "will be saved in a file by this name.")
82 #define HINT_EDITOR_EDIT _("Click here to edit the levelset chosen above.##NOTE: To switch to the bonus set you'll have to right-click on the brick set and vice versa!")
83 #define HINT_EDITOR_DELETE _("Click here to delete the chosen levelset (after confirmation).")
84 #define HINT_KEYS _("If you use the keyboard for input these are the keys for moving the paddle ('Paddle Turbo' will double the speed while pressed.), firing balls/shots and returning the ball to paddle after a timeout of ten seconds.##Note: If balls are fired at a random angle (which has become the default) "\
85 "there is no difference between the left or right fire key. A sticky paddle stops a ball until "\
86 "any fire button is pressed but the movement angle is the one from the normal reflection. To "\
87 "reset the movement angle to -50 or +50 degrees check out 'Ball Fire Angle' in 'Advanced Options'.##"\
88 "While pressed, the 'Ball Turbo' will bring all balls to the maximum speed defined in 'Advanced Options'.")
89 #define HINT_MOD _("This modifies the relative motion of the mouse. (percent) "\
90 "The higher this value is the faster the mouse moves.")
91 #define HINT_INVERT _("If for some reason your mouse movement is inverted you can fix it with this option.")
92 #define HINT_RETURN _("If a ball does not damage a brick within ten seconds it is allowed to return to the paddle. If this option is set "\
93 "to 'Auto' it will automatically return and if this option is set to 'By Click' you'll have to press the middle mouse"\
94 "button or the 'back'-key (default is Backspace).")
95 #define HINT_APPLY _("Click here to apply the theme you selected above. Please check the manual at lgames.sf.net for information on how to " \
97 #define HINT_HOST _("IP address of the game server as xxx.xxx.xxx.xxx.#DO NOT use 'localhost' if you run the server on your computer. You won't be able to challenge others. Use your IP queried by /sbin/ifconfig instead.")
98 #define HINT_PORT _("Port the game server is bound to.")
99 #define HINT_USERNAME _("If you're successfully connected to the game server this is your nickname there.")
100 #define HINT_CONNECT _("Connect to game server.")
101 #define HINT_LOCAL _("A local game with up to 4 alternating players.")
102 #define HINT_NETWORK _("A two-player or deathmatch game via Internet or LAN.")
104 char hint_levelset
[1024]; /* information about version and author of selected levelset */
105 #define HINT_LEVELSET_APPENDIX _("This is the levelset you actually want to play. Note, that each levelset got it's own highscore chart (left/right-click on the chart on the right)." \
106 " A levelset is either load from ~/.lgames/lbreakout2-levels or the installation directory.")
107 char hint_theme
[512]; /* theme information */
108 #define HINT_THEME_APPENDIX _("This is the list of available themes. Choose any theme and click 'Apply' to select it")
109 #define HINT_WARP_LIMIT _("After you destroyed this percentage of bricks you MAY warp to the next level by pressing 'w'. That is indicated by a small icon at the bottom right-hand side of the screen.#If you set this option to 0 you may instantly warp whereas 100 means you have to destroy all bricks.##"\
110 "Note, that this option does not apply for the levelsets 'Original' and 'LBreakout1'!")
111 #define HINT_THEME _("In this menu you can change the appearance of LBreakout. Included to the release are the three winning themes from the Linux Game Tome contest 'absoluteB','Oz' and 'Moiree' along with the old graphics as theme 'Classic'.#For more themes check out http://lgames.sf.net.")
112 #define HINT_CORNER _("Linear:#++ There is no chance for balls to get infinitely stuck in a brick bounce combo.#"\
113 "-- It is quite hard for balls to enter narrow passages.##Spherical:#"\
114 "++ Feels better and balls can easily pass through small gaps.#"\
115 "-- There is a chance for balls to get infinitely stuck within a series of indestructible "\
116 "brick reflections if the level is too wrinkled. However, with the auto return option this "\
117 "is no problem so 'Spherical' is the default.")
118 #define HINT_LOCAL_PORT _("Network communication is handled by a single UDP socket which will be "\
119 "bound to this port number.")
120 #define HINT_RANDOM_ANGLE _("If '50' the ball is shot at an angle of 50 degrees to the left or "\
121 "right, depending on which fire button has been pressed. If it is set to 'random' the "\
122 "ball is fired at a random angle. In this case a sticky paddle simply halts "\
123 "the normal reflection until any fire button has been pressed.")
124 #define HINT_MAXBALLSPEED _("While you keep the middle mouse button pressed (or the acceleration key) "\
125 "all balls will go this velocity. (in pixels per second)")
126 #define HINT_BONUS_LEVELS _("If on, normal levelsets will have a random bonus level every four normal levels.##"\
127 "Note: You can skip a bonus level any time by loosing the ball. This will not "\
128 "loose a life but bring you directly to the next level.")
129 #define HINT_FREAKOUT _("Play *ALL* available levels in a random order.")
130 #define HINT_LBREAKOUT1 _("The complete levelset of LBreakout1 with just minor modifications.")
131 #define HINT_JUMPING_JACK _("There is only one brick with a limited lifetime. Your task is to hit "\
132 "it before it vanishes. If you succeed, the brick is reset somewhere else "\
133 "with less lifetime. If you don't, the game is over. The faster you hit "\
134 "a brick, the more score you will gain. How much seconds a brick is still "\
135 "there, you can see at the lower right-hand side of the screen.##"\
136 "Loosing your ball means going to the next level.##"\
137 "HAVE 'ACC. BALL SPEED' SET TO 900 IN 'ADVANCED OPTIONS AND "\
138 "MAKE EXCESSIVE USE OF YOUR MIDDLE MOUSE BUTTON! Otherwise you won't "\
139 "stand a chance as these levels require a lot of skill!")
140 #define HINT_OUTBREAK _("Your task is to prevent an outbreak by clearing all bricks. Every few seconds "\
141 "a new one will appear somewhere, forcing you to act quickly. If you succeed "\
142 "in clearing a level, it is reset to five bricks, but this time new ones will "\
143 "spring into existence faster. You loose, if you cannot manage to clear the "\
144 "screen before 50 bricks were created (which does not mean 50 bricks are on "\
145 "the screen!). How far you are away from that limit you can see in the "\
146 "lower right-hand side of the screen. Score is only gained for a complete "\
147 "clearance, not for destroying single bricks! The farther you are way from "\
148 "the 50 bricks limit the more it will be.##"\
149 "Loosing your ball means going to the next level.##"\
150 "HAVE 'ACC. BALL SPEED' SET TO 900 IN 'ADVANCED OPTIONS AND "\
151 "MAKE EXCESSIVE USE OF YOUR MIDDLE MOUSE BUTTON! Otherwise you won't "\
152 "stand a chance as these levels require a lot of skill!")
153 #define HINT_BARRIER _("This time you have to crush through a wall and hit some bricks behind it. "\
154 "If you succeed the wall is reset and one line bigger next time. The earlier "\
155 "you manage to break through, the more score you'll get. No surprise, is it? "\
156 "What makes this fun, is the fact that the wall is moving towards you. If it "\
157 "reaches your paddle, you are out. Whenever you successfully broke through, the "\
158 "ball will return the paddle and get attached. You then have to fire it again. "\
159 "The wall cannot grow bigger than 12 lines. How many lines the barrier is away from "\
160 "your paddle, is shown in the lower right-hand side of the screen.##"\
161 "Loosing your ball means going to the next level.##"\
162 "HAVE 'ACC. BALL SPEED' SET TO 900 IN 'ADVANCED OPTIONS AND "\
163 "MAKE EXCESSIVE USE OF YOUR MIDDLE MOUSE BUTTON! Otherwise you won't "\
164 "stand a chance as these levels require a lot of skill!")
165 #define HINT_SITTING_DUCKS _("There are eight bricks and the ball is attached in the middle at the "\
166 "ceiling. When it is released, one brick is highlighted and your task "\
167 "is to hit this brick. If you manage to do so, you'll get some score "\
168 "and the situation is reset. If you do not hit the highlighted brick "\
169 "AS THE VERY FIRST THING, it will be destroyed until all bricks are gone. "\
170 "The more bricks you hit in a row, the more score you will get for the next "\
171 "one. The score's worth of the next brick you can see in the lower right-hand "\
172 "side of the screen.##"\
173 "Loosing your ball means going to the next level.")
174 #define HINT_HUNTER _("Your task is to hunt down bricks by moving a chaos brick indirectly. Therefore "\
175 "each side of the playing field has a brick color and you can hit small pads bearing these colors. "\
176 "When you hit one, the chaos brick will move toward the appropriate side. You must not hit "\
177 "the bordering bricks and you must get to the brick within a time limit, as always "\
178 "displayed in the lower right-hand side of the screen. The faster you are, the more score "\
180 "Loosing your ball means going to the next level.##"\
181 "HAVE 'ACC. BALL SPEED' SET TO 900 IN 'ADVANCED OPTIONS AND "\
182 "MAKE EXCESSIVE USE OF YOUR MIDDLE MOUSE BUTTON! Otherwise you won't "\
183 "stand a chance as these levels require a lot of skill!")
184 #define HINT_DEFENDER _("Stop the invading brick waves! Each waves consists of 50 bricks which will get "\
185 "faster and faster. Each brick will give you some score. If you clear the screen completely, "\
186 "the wave will also be over and you will receive some extra score depending on the number of remaining wave bricks. "\
187 "One way or the other, if a wave is over, the next one will start with higher speed and more score until you let "\
188 "a brick come down to paddle level.##"\
189 "Loosing your ball means going to the next level.##"\
190 "HAVE 'ACC. BALL SPEED' SET TO 900 IN 'ADVANCED OPTIONS AND "\
191 "MAKE EXCESSIVE USE OF YOUR MIDDLE MOUSE BUTTON! Otherwise you won't "\
192 "stand a chance as these levels require a lot of skill!")
195 ====================================================================
196 Levelset names functions.
197 ====================================================================
200 ====================================================================
201 Check if this levelset's name declare it as network set.
202 ====================================================================
204 int levelset_is_network( char *name
)
206 if ( name
== 0 ) return 0;
207 if ( name
[0] == '~' ) name
++;
208 if ( name
[0] == 'N' && name
[1] == '_' ) return 1;
212 ====================================================================
213 Get/delete list of all valid levelsets in data directory or
215 ====================================================================
217 void levelsets_delete_names()
219 if ( levelset_names
) {
220 list_delete( levelset_names
);
223 if ( levelset_names_home
) {
224 free( levelset_names_home
);
225 levelset_names_home
= 0;
227 if ( levelset_names_local
) {
228 free( levelset_names_local
);
229 levelset_names_local
= 0;
232 void levelsets_load_names()
238 int default_set_count
= 8;
239 char *default_sets
[] = {
245 _("!SITTING_DUCKS!"),
250 /* clear previous lists */
251 levelsets_delete_names();
252 /* gather all names in install&home directory to levelset_names */
253 levelset_names
= list_create( LIST_AUTO_DELETE
, LIST_NO_CALLBACK
);
254 /* parse install directory */
255 sprintf( level_dir
, "%s/levels", SRC_DIR
);
256 if ( ( text
= get_file_list( level_dir
, 0, level_dir
) ) ) {
257 for ( i
= 0; i
< text
->count
; i
++ ) {
259 if ( text
->lines
[i
][0] == '*' ) continue;
260 if ( strequal( text
->lines
[i
], "Makefile.am" ) ) continue;
261 if ( strequal( text
->lines
[i
], "Makefile.in" ) ) continue;
262 if ( strequal( text
->lines
[i
], "Makefile" ) ) continue;
264 if ( strequal( text
->lines
[i
], "LBreakout2" ) ) continue;
265 if ( strequal( text
->lines
[i
], "LBreakout1" ) ) continue;
267 if ( strequal( text
->lines
[i
], "Original" ) ) continue;
268 if ( strequal( text
->lines
[i
], "AddOn-1" ) ) continue;
269 if ( strequal( text
->lines
[i
], "AddOn-2" ) ) continue;
270 /* default sets are at the beginning of the list thus
272 for ( j
= 0; j
< default_set_count
; j
++ )
273 if ( STRCMP( default_sets
[j
], text
->lines
[i
] ) )
276 list_add( levelset_names
, strdup( text
->lines
[i
] ) );
280 /* parse home directory */
281 snprintf( level_dir
, sizeof(level_dir
)-1, "%s/%s/lbreakout2-levels", (getenv( "HOME" )?getenv( "HOME" ):"."), CONFIG_DIR_NAME
);
282 if ( ( text
= get_file_list( level_dir
, 0, level_dir
) ) ) {
283 for ( i
= 0; i
< text
->count
; i
++ ) {
285 if ( text
->lines
[i
][0] == '*' ) continue;
287 sprintf( file_name
, "~%s", text
->lines
[i
] );
288 list_add( levelset_names
, strdup( file_name
) );
292 /* create static home list */
293 list_reset( levelset_names
);
294 levelset_count_home
= 1;
295 while ( ( name
= list_next( levelset_names
) ) )
296 if ( name
[0] == '~' )
297 levelset_count_home
++;
298 levelset_names_home
= calloc( levelset_count_home
, sizeof( char* ) );
299 list_reset( levelset_names
); i
= 1;
300 while ( ( name
= list_next( levelset_names
) ) )
301 if ( name
[0] == '~' )
302 levelset_names_home
[i
++] = name
+ 1;
303 levelset_names_home
[0] = NEW_SET
;
304 /* create static local set list */
305 list_reset( levelset_names
);
306 levelset_count_local
= default_set_count
;
307 while ( ( name
= list_next( levelset_names
) ) )
308 if ( !levelset_is_network( name
) )
309 levelset_count_local
++;
310 levelset_names_local
= calloc( levelset_count_local
, sizeof( char* ) );
311 list_reset( levelset_names
); i
= default_set_count
;
312 while ( ( name
= list_next( levelset_names
) ) )
313 if ( !levelset_is_network( name
) )
314 levelset_names_local
[i
++] = name
;
316 for ( i
= 0; i
< default_set_count
; i
++ )
317 levelset_names_local
[i
] = default_sets
[i
];
319 if ( config
.levelset_count_home
!= levelset_count_home
) {
320 config
.levelset_id_home
= 0;
321 config
.levelset_count_home
= levelset_count_home
;
326 ====================================================================
327 Callbacks of menu items.
328 ====================================================================
330 /* Disable/enable sound */
333 stk_audio_enable_sound( config
.sound
);
339 stk_audio_set_sound_volume( config
.volume
* 16 );
342 /* toggle fullscreen */
343 void cb_fullscreen() {
350 /* do not delete <CREATE SET> file */
351 if ( strequal( NEW_SET
, levelset_names_home
[config
.levelset_id_home
] ) ) {
352 printf( _("You cannot delete '%s'!\n"),NEW_SET
);
355 /* get file name + path */
356 snprintf( fname
, sizeof(fname
)-1,"%s/%s/lbreakout2-levels/%s", getenv( "HOME" ), CONFIG_DIR_NAME
, levelset_names_home
[config
.levelset_id_home
] );
358 levelsets_load_names(); /* reinit name lists and configs indices */
359 /* reassign these name lists as position in memory has changed */
360 value_set_new_names( item_set
->value
, levelset_names_home
, levelset_count_home
);
362 /* adjust set list */
363 void cb_adjust_set_list()
365 /* reinit name lists and configs indices */
366 levelsets_load_names();
367 /* reassign these name lists as position in memory has changed */
368 value_set_new_names( item_set
->value
, levelset_names_home
, levelset_count_home
);
370 /* set key speed from i_key_speed */
371 void cb_set_keyspeed()
373 config
.key_speed
= 0.001 * config
.i_key_speed
;
375 /* if hints where disabled hide actual hint */
378 if ( !config
.use_hints
)
382 void cb_change_theme()
385 theme_load( theme_names
[config
.theme_id
] );
386 hint_set_bkgnd( mbkgnd
);
387 /* apply the new background to all items */
389 while ( ( menu
= list_next( menus
) ) ) {
390 menu_set_bkgnd( menu
, mbkgnd
);
391 menu_set_fonts( menu
, mcfont
, mfont
, mhfont
);
393 stk_surface_blit( mbkgnd
, 0,0,-1,-1, stk_display
, 0,0 );
394 stk_display_update( STK_UPDATE_ALL
);
396 /* update hint of theme by feeding it with the ABOUT file */
397 void cb_update_theme_hint()
399 theme_get_info( theme_names
[config
.theme_id
], hint_theme
, 255 );
400 strcat( hint_theme
, "##" ); strcat( hint_theme
, HINT_THEME_APPENDIX
);
401 hint_set_contents( item_theme
->hint
, hint_theme
);
402 hint_set( item_theme
->hint
); /* redraw the hint */
404 /* update config::motion_mod */
405 void cb_set_motion_mod()
407 config
.motion_mod
= 0.01 * config
.i_motion_mod
;
409 /* update pointer edit_set which is the name of the selected set in editor menu */
410 void cb_update_edit_set()
412 edit_set
= levelset_names_home
[config
.levelset_id_home
];
414 void cb_maxballspeed()
416 config
.maxballspeed_float
= (float)config
.maxballspeed_int1000
/ 1000;
421 ====================================================================
422 Load/delete background and create and link all menus
423 ====================================================================
425 void manager_create()
430 int filter
[SDLK_LAST
]; /* key filter */
431 /* constant contence of switches */
432 char *str_fps
[] = { _("No Limit"), _("100 FPS") };
433 char *str_anim
[] = { _("Off"), _("Low"), _("Medium"), _("High") };
434 char *str_diff
[] = { _("Kids"), _("Easy"), _("Medium"), _("Hard") };
492 Menu
*confirm_delete
= 0;
495 /* load levelset names */
496 levelsets_load_names();
497 cb_update_edit_set();
499 /* hints will be displayed on menu background */
500 hint_set_bkgnd( mbkgnd
);
503 filter_clear( filter
);
504 filter_set( filter
, SDLK_a
, SDLK_z
, 1 );
505 filter
[SDLK_BACKSPACE
] = 1;
506 filter
[SDLK_SPACE
] = 1;
507 filter
[SDLK_RSHIFT
] = 1;
508 filter
[SDLK_LSHIFT
] = 1;
509 filter
[SDLK_LALT
] = 1;
510 filter
[SDLK_RALT
] = 1;
511 filter
[SDLK_LCTRL
] = 1;
512 filter
[SDLK_RCTRL
] = 1;
514 filter
[SDLK_DOWN
] = 1;
515 filter
[SDLK_LEFT
] = 1;
516 filter
[SDLK_RIGHT
] = 1;
526 /* menus are added to this list for deleting later */
527 menus
= list_create( LIST_AUTO_DELETE
, menu_delete
);
529 _main
= menu_create( _("Menu"), MENU_LAYOUT_CENTERED
, menu_x
, menu_y
, menu_w
, menu_h
, menu_border
, 1 );
531 options
= menu_create( _("Options"), MENU_LAYOUT_CENTERED
, menu_x
, menu_y
, menu_w
, menu_h
, menu_border
, 1 );
533 gfx
= menu_create( _("Graphics"), MENU_LAYOUT_CENTERED
, menu_x
, menu_y
, menu_w
, menu_h
, menu_border
, 1 );
534 game
= menu_create( _("Local Game"), MENU_LAYOUT_CENTERED
, menu_x
, menu_y
, menu_w
, menu_h
, menu_border
, 1 );
535 cont
= menu_create( _("Controls"), MENU_LAYOUT_CENTERED
, menu_x
, menu_y
, menu_w
, menu_h
, menu_border
, 1 );
536 adv
= menu_create( _("Advanced Options"), MENU_LAYOUT_CENTERED
, menu_x
, menu_y
, menu_w
, menu_h
, menu_border
, 1 );
538 audio
= menu_create( _("Audio"), MENU_LAYOUT_CENTERED
, menu_x
, menu_y
, menu_w
, menu_h
, menu_border
, 1 );
540 editor
= menu_create( _("Editor"), MENU_LAYOUT_CENTERED
, menu_x
, menu_y
, menu_w
, menu_h
, menu_border
, 1 );
541 confirm_delete
= menu_create( _("Delete Set"), MENU_LAYOUT_CENTERED
, menu_x
, menu_y
, menu_w
, menu_h
, menu_border
, 1 );
542 theme
= menu_create( _("Select Theme"), MENU_LAYOUT_CENTERED
, menu_x
, menu_y
, menu_w
, menu_h
, menu_border
, 1 );
545 menu_add( _main
, item_create_link ( _("Local Game"), HINT_LOCAL
, game
) );
546 #ifdef NETWORK_ENABLED
547 menu_add( _main
, item_create_action ( _("Network Game"), HINT_NETWORK
, ACTION_CLIENT
) );
549 menu_add( _main
, item_create_action ( _("Quick Help"), HINT_
, ACTION_QUICK_HELP
) );
550 // menu_add( _main, item_create_link ( _("Select Theme"), HINT_THEME, theme ) );
551 menu_add( _main
, item_create_separator ( "" ) );
553 menu_add( _main
, item_create_link ( _("Options"), options
) );
555 menu_add( _main
, item_create_link ( _("Controls"), HINT_
, cont
) );
556 menu_add( _main
, item_create_link ( _("Graphics"), HINT_
, gfx
) );
558 menu_add( _main
, item_create_link ( _("Audio"), HINT_
,audio
) );
560 menu_add( _main
, item_create_separator ( _("Audio") ) );
562 menu_add( _main
, item_create_link ( _("Advanced Options"), HINT_
, adv
) );
563 menu_add( _main
, item_create_separator ( "" ) );
564 menu_add( _main
, item_create_link ( _("Editor"), HINT_
, editor
) );
565 menu_add( _main
, item_create_separator ( "" ) );
566 menu_add( _main
, item_create_action ( _("Quit"), HINT_QUIT
, ACTION_QUIT
) );
569 menu_add( options
, item_create_link( _("Controls"), HINT_
, cont
) );
570 menu_add( options
, item_create_link( _("Graphics"), HINT_
, gfx
) );
571 menu_add( options
, item_create_link( _("Audio"), HINT_
, audio
) );
572 menu_add( options
, item_create_separator( _("Audio") ) );
573 menu_add( options
, item_create_separator( "" ) );
574 menu_add( options
, item_create_link( _("Back"), _main
) );
578 item
= item_create_switch( _("Sound:"), HINT_
, &config
.sound
, _("Off"), _("On") );
579 item
->callback
= cb_sound
;
580 menu_add( audio
, item
);
581 menu_add( audio
, item_create_switch( _("Speech:"), HINT_
, &config
.speech
, _("Off"), _("On") ) );
582 item
= item_create_range( _("Volume:"), HINT_
, &config
.volume
, 1, 8, 1 );
583 item
->callback
= cb_volume
;
584 menu_add( audio
, item
);
585 menu_add( audio
, item_create_separator( "" ) );
586 menu_add( audio
, item_create_link( _("Back"), HINT_
, _main
) );
589 menu_add( gfx
, item_create_switch_x( _("Animations:"), HINT_ANIM
, &config
.anim
, str_anim
, 4 ) );
590 menu_add( gfx
, item_create_switch( _("Bonus Info:"), HINT_BONUS_INFO
, &config
.bonus_info
, _("Off"), _("On") ) );
591 menu_add( gfx
, item_create_separator( "" ) );
592 item
= item_create_switch( _("Display:"), HINT_DISPLAY
, &config
.fullscreen
, _("Window"), _("Fullscreen") );
593 item
->callback
= cb_fullscreen
;
594 menu_add( gfx
, item
);
595 menu_add( gfx
, item_create_switch_x( _("Frame Rate:"), HINT_FPS
, &config
.fps
, str_fps
, 2 ) );
596 menu_add( gfx
, item_create_separator( "" ) );
597 menu_add( gfx
, item_create_link( _("Select Theme"), HINT_THEME
, theme
) );
598 menu_add( gfx
, item_create_separator( "" ) );
599 menu_add( gfx
, item_create_link( _("Back"), HINT_
, _main
) );
601 item_resume_0
= item_create_action( _("Resume Last Game"), "???", ACTION_RESUME_0
);
602 menu_add( game
, item_resume_0
);
603 slot_update_hint( 0, item_resume_0
->hint
);
604 menu_add( game
, item_create_action( _("Start Original Set"), HINT_START_LBR
, ACTION_PLAY_LBR
) );
605 menu_add( game
, item_create_action( _("Start AddOn"), HINT_START_CUSTOM
, ACTION_PLAY_CUSTOM
) );
606 menu_add( game
, item_create_separator( "" ) );
607 menu_add( game
, item_create_switch_x( _("Difficulty:"), HINT_DIFF
, &config
.diff
, str_diff
, DIFF_COUNT
) );
608 menu_add( game
, item_create_separator( "" ) );
609 menu_add( game
, item_create_range( _("Players:"), HINT_PLAYERS
, &config
.player_count
, 1, 4, 1 ) );
610 menu_add( game
, item_create_edit( _("1st:"), HINT_PLAYERS
, config
.player_names
[0], 12 ) );
611 menu_add( game
, item_create_edit( _("2nd:"), HINT_PLAYERS
, config
.player_names
[1], 12 ) );
612 menu_add( game
, item_create_edit( _("3rd:"), HINT_PLAYERS
, config
.player_names
[2], 12 ) );
613 menu_add( game
, item_create_edit( _("4th:"), HINT_PLAYERS
, config
.player_names
[3], 12 ) );
614 menu_add( game
, item_create_separator( "" ) );
615 menu_add( game
, item_create_link( _("Back"), HINT_
, _main
) );
617 keys
[0] = item_create_key( _("Left:"), HINT_KEYS
, &config
.k_left
, filter
);
618 keys
[1] = item_create_key( _("Right:"), HINT_KEYS
, &config
.k_right
, filter
);
619 keys
[2] = item_create_key( _("Left Fire:"), HINT_KEYS
, &config
.k_lfire
, filter
);
620 keys
[3] = item_create_key( _("Right Fire:"), HINT_KEYS
, &config
.k_rfire
, filter
);
621 keys
[4] = item_create_key( _("Paddle Turbo:"), HINT_KEYS
, &config
.k_turbo
, filter
);
622 keys
[5] = item_create_key( _("Ball Turbo:"), HINT_KEYS
, &config
.k_maxballspeed
, filter
);
623 keys
[6] = item_create_key( _("Return:"), HINT_KEYS
, &config
.k_return
, filter
);
624 // keys[6] = item_create_key( _("Warp:"), HINT_KEYS, &config.k_warp, filter );
625 for ( i
= 0; i
< 7; i
++ )
626 menu_add( cont
, keys
[i
] );
627 /* dynamic restriction */
628 for ( i
= 0; i
< 7; i
++ )
629 for ( j
= 0; j
< 7; j
++ )
631 value_add_other_key( keys
[i
]->value
, keys
[j
]->value
);
632 /* other control stuff */
633 menu_add( cont
, item_create_separator( "" ) );
634 item
= item_create_range( _("Key Speed:"), HINT_KEYSPEED
, &config
.i_key_speed
, 100, 1000, 50 );
635 item
->callback
= cb_set_keyspeed
;
636 menu_add( cont
, item
);
637 item
= item_create_range( _("Motion Modifier:"), HINT_MOD
, &config
.i_motion_mod
, 40, 160, 5 );
638 item
->callback
= cb_set_motion_mod
;
639 menu_add( cont
, item
);
640 menu_add( cont
, item_create_switch( _("Invert Motion:"), HINT_INVERT
, &config
.invert
, _("Off"), _("On") ) );
641 menu_add( cont
, item_create_separator( "" ) );
642 menu_add( cont
, item_create_link( _("Back"), HINT_
, _main
) );
643 /* advanced options */
644 menu_add( adv
, item_create_switch( _("Convex Paddle:"), HINT_CONVEX
, &config
.convex
, _("Off"), _("On") ) );
645 //menu_add( adv, item_create_switch( _("Corner:"), HINT_CORNER, &config.linear_corner, _("Spherical"), _("Linear") ) );
647 item_create_switch( _("Ball Fire Angle:"),
648 HINT_RANDOM_ANGLE
, &config
.random_angle
,
649 "50", _("Random") ) );
650 menu_add( adv
, item_create_switch( _("Balls:"), HINT_BALLLEVEL
, &config
.ball_level
, _("Below Bonuses"), _("Above Bonuses") ) );
651 menu_add( adv
, item_create_switch( _("Debris:"), HINT_DEBRISLEVEL
, &config
.debris_level
, _("Below Balls"), _("Above Balls") ) );
652 menu_add( adv
, item_create_switch( _("Return Balls:"), HINT_RETURN
, &config
.return_on_click
, _("Auto"), _("By Click") ) );
653 item
= item_create_switch( _("Use Hints:"), HINT_USEHINTS
, &config
.use_hints
, _("Off"), _("On") );
654 item
->callback
= cb_hints
;
655 menu_add( adv
, item
);
656 menu_add( adv
, item_create_range( _("Warp Limit:"), HINT_WARP_LIMIT
, &config
.rel_warp_limit
, 0, 100, 10 ) );
657 menu_add( adv
, item_create_edit( _("Local UDP Port:"), HINT_LOCAL_PORT
, config
.local_port
, 6 ) );
658 item
= item_create_range( _("Acc. Ball Speed:"), HINT_MAXBALLSPEED
, &config
.maxballspeed_int1000
, 600, 900, 20 );
659 item
->callback
= cb_maxballspeed
;
660 menu_add( adv
, item
);
661 menu_add( adv
, item_create_switch( _("Add Bonus Levels:"), HINT_BONUS_LEVELS
, &config
.addBonusLevels
, _("Off"), _("On") ) );
662 menu_add( adv
, item_create_separator( "" ) );
663 menu_add( adv
, item_create_link( _("Back"), HINT_
, _main
) );
665 item_set
= item_create_switch_x(
666 _("Set:"), HINT_EDITOR_SET
,
667 &config
.levelset_id_home
, levelset_names_home
,
668 levelset_count_home
);
669 item_set
->callback
= cb_update_edit_set
;
670 menu_add( editor
, item_set
);
671 menu_add( editor
, item_create_action( _("Edit Set"), HINT_EDITOR_EDIT
, ACTION_EDIT
) );
672 menu_add( editor
, item_create_link( _("Delete Set"), HINT_EDITOR_DELETE
, confirm_delete
) );
673 menu_add( editor
, item_create_separator( "" ) );
674 menu_add( editor
, item_create_link( _("Back"), HINT_
, _main
) );
675 /* confirm_delete set */
676 item
= item_create_link( _("Yes"), HINT_
,editor
);
677 item
->callback
= cb_delete_set
;
678 menu_add( confirm_delete
, item
);
679 menu_add( confirm_delete
, item_create_link( _("No"), HINT_
, editor
) );
681 item_theme
= item_create_switch_x( _("Theme:"), "", &config
.theme_id
, theme_names
, theme_count
);
682 menu_add( theme
, item_theme
);
683 item_theme
->callback
= cb_update_theme_hint
;
684 cb_update_theme_hint();
685 menu_add( theme
, item_create_separator( "" ) );
686 item
= item_create_link( _("Apply"), HINT_APPLY
, gfx
);
687 item
->callback
= cb_change_theme
;
688 menu_add( theme
, item
);
689 menu_add( theme
, item_create_link( _("Cancel"), HINT_
, gfx
) );
691 /* adjust all menus */
692 menu_adjust( _main
);
694 menu_adjust( options
);
697 menu_adjust( audio
);
703 menu_adjust( editor
);
704 menu_adjust( confirm_delete
);
705 menu_adjust( theme
);
706 /* set main menu as current */
707 menu_select( _main
);
709 void manager_delete()
711 list_delete( menus
);
713 /* free levelset names */
714 levelsets_delete_names();
717 ====================================================================
718 Run menu until request sent
719 ====================================================================
724 int result
= ACTION_NONE
;
726 /* draw highscores */
727 chart_show( chart_set_query_id( chart_id
), cx
, cy
, cw
, ch
);
730 while ( result
== ACTION_NONE
&& !stk_quit_request
) {
731 menu_hide( cur_menu
);
733 /* fullscreen if no item selected */
734 if ( SDL_PollEvent( &event
) ) {
735 if ( cur_menu
->cur_item
== 0 ||
736 (cur_menu
->cur_item
->type
!= ITEM_EDIT
&& cur_menu
->cur_item
->type
!= ITEM_KEY
) )
737 if ( event
.type
== SDL_KEYDOWN
)
738 if ( event
.key
.keysym
.sym
== SDLK_f
) {
739 config
.fullscreen
= !config
.fullscreen
;
740 stk_display_apply_fullscreen( config
.fullscreen
);
741 stk_surface_blit( mbkgnd
, 0,0,-1,-1, stk_display
, 0,0 );
742 stk_display_update( STK_UPDATE_ALL
);
744 result
= menu_handle_event( cur_menu
, &event
);
747 menu_handle_event( cur_menu
, 0 ); /* update motion */
748 ms
= stk_timer_get_time();
749 menu_update( cur_menu
, ms
);
751 menu_show( cur_menu
);
752 chart_show( chart_set_query_id( chart_id
), cx
, cy
, cw
, ch
);
754 stk_display_update( STK_UPDATE_RECTS
);
760 ====================================================================
761 Fade in/out background of menu
762 ====================================================================
764 void manager_fade( int type
)
766 if ( type
== STK_FADE_IN
)
767 stk_surface_blit( mbkgnd
, 0,0,-1,-1, stk_display
, 0,0 );
768 stk_display_fade( type
, STK_FADE_DEFAULT_TIME
);
771 ====================================================================
772 Update screen without menu itself as this is shown next frame.
773 ====================================================================
777 stk_display_apply_fullscreen( config
.fullscreen
);
778 stk_surface_blit( mbkgnd
, 0,0,-1,-1, stk_display
, 0,0 );
779 chart_show( chart_set_query_id( chart_id
), cx
, cy
, cw
, ch
);
780 stk_display_update( STK_UPDATE_ALL
);
784 ====================================================================
785 Update set list when creating a new file for editor.
786 ====================================================================
788 void manager_update_set_list()
790 cb_adjust_set_list(); /* hacky but shiiiit how cares? */