Index: code/menuui/mainhallmenu.cpp =================================================================== --- code/menuui/mainhallmenu.cpp (revision 10870) +++ code/menuui/mainhallmenu.cpp (working copy) @@ -33,6 +33,7 @@ #include "menuui/fishtank.h" #include "mission/missioncampaign.h" #include "parse/parselo.h" +#include "parse/scripting.h" #include "network/multiui.h" #include "network/multiutil.h" #include "network/multi_voice.h" @@ -151,8 +152,7 @@ // ---------------------------------------------------------------------------- // SNAZZY MENU stuff // -#define NUM_MAIN_HALL_REGIONS 10 -#define NUM_MAIN_HALL_MOUSE_REGIONS 6 +#define NUM_MAIN_HALL_MAX_REGIONS 20 // region mask #'s (identifiers) #define EXIT_REGION 0 @@ -165,9 +165,32 @@ #define LOAD_MISSION_REGION 11 #define QUICK_START_REGION 12 #define SKILL_LEVEL_REGION 13 +#define SCRIPT_REGION 14 +#define START_REGION 15 +struct main_hall_region_info { + int mask; + char *name; +}; + +main_hall_region_info Main_hall_region_map[] = { + { EXIT_REGION, "Exit" }, + { BARRACKS_REGION, "Barracks" }, + { READY_ROOM_REGION, "Readyroom" }, + { TECH_ROOM_REGION, "Techroom" }, + { OPTIONS_REGION, "Options" }, + { CAMPAIGN_ROOM_REGION, "Campaigns" }, + { MULTIPLAYER_REGION, "Multiplayer" }, + { LOAD_MISSION_REGION, "Load Mission" }, + { QUICK_START_REGION, "Quickstart" }, + { SKILL_LEVEL_REGION, "Skilllevel" }, + { SCRIPT_REGION, "Script" }, + { START_REGION, "Start" }, + { -1, NULL } +}; + // all the menu regions in the main hall -MENU_REGION Main_hall_region[NUM_MAIN_HALL_REGIONS]; +MENU_REGION Main_hall_region[NUM_MAIN_HALL_MAX_REGIONS]; // # of regions (options) on this screen. parsed from a table int Main_hall_num_options; @@ -395,7 +418,6 @@ } int idx; - char temp[100], whee[100]; SCP_string main_hall_to_load; // reparse the table here if the relevant cmdline flag is set @@ -423,20 +445,27 @@ // create the snazzy interface and load up the info from the table snazzy_menu_init(); - read_menu_tbl(NOX("MAIN HALL"), temp, whee, Main_hall_region, &Main_hall_num_options, 0); - + // assign the proper main hall data Assert(main_hall_get_pointer(main_hall_to_load) != NULL); Main_hall = main_hall_get_pointer(main_hall_to_load); - // tooltip strings - Main_hall->region_descript.at(0) = XSTR( "Exit FreeSpace 2", 353); - Main_hall->region_descript.at(1) = XSTR( "Barracks - Manage your FreeSpace 2 pilots", 354); - Main_hall->region_descript.at(2) = XSTR( "Ready room - Start or continue a campaign", 355); - Main_hall->region_descript.at(3) = XSTR( "Tech room - View specifications of FreeSpace 2 ships and weaponry", 356); - Main_hall->region_descript.at(4) = XSTR( "Options - Change your FreeSpace 2 options", 357); - Main_hall->region_descript.at(5) = XSTR( "Campaign Room - View all available campaigns", 358); - Main_hall->region_descript.at(6) = XSTR( "Multiplayer - Start or join a multiplayer game", 359); + // check if we have to change the ready room's description + if(Main_hall->default_readyroom) { + if (Player->flags & PLAYER_FLAGS_IS_MULTI) { + Main_hall->regions.at(2).description = XSTR( "Multiplayer - Start or join a multiplayer game", 359); + } else { + Main_hall->regions.at(2).description = XSTR( "Ready room - Start or continue a campaign", 355); + } + } + + // Read the menu regions from mainhall.tbl + main_hall_region *region; + for (idx = 0; idx < (int) Main_hall->regions.size(); idx++) { + region = &Main_hall->regions.at(idx); + snazzy_menu_add_region(Main_hall_region + idx, (char*) region->description.c_str(), region->mask, region->key, -1); + } + Main_hall_num_options = Main_hall->regions.size(); // init tooltip shader // nearly black gr_create_shader(&Main_hall_tooltip_shader, 5, 5, 5, 168); @@ -637,7 +666,7 @@ */ void main_hall_do(float frametime) { - int code, key, snazzy_action; + int idx, code, key, snazzy_action, region_action = -1; // set the screen scale to the main hall's dimensions gr_set_screen_scale(Main_hall_bitmap_w, Main_hall_bitmap_h, Main_hall->zoom_area_width, Main_hall->zoom_area_height); @@ -692,11 +721,38 @@ // do any processing based upon what happened to the snazzy menu switch (snazzy_action) { case SNAZZY_OVER: - main_hall_handle_mouse_location(code); + for (idx = 0; idx < (int) Main_hall->regions.size(); idx++) { + if (Main_hall->regions.at(idx).mask == code) { + break; + } + } + + main_hall_handle_mouse_location(idx); break; case SNAZZY_CLICKED: - switch (code) { + if (code == ESC_PRESSED) { + region_action = ESC_PRESSED; + } else { + for (idx = 0; idx < (int) Main_hall->regions.size(); idx++) { + if (Main_hall->regions.at(idx).mask == code) { + region_action = Main_hall->regions.at(idx).action; + break; + } + } + + if (region_action == -1) { + Error(LOCATION, "Region %d doesn't have an action!", code); + } else if (region_action == START_REGION) { + if (Player->flags & PLAYER_FLAGS_IS_MULTI) { + region_action = MULTIPLAYER_REGION; + } else { + region_action = READY_ROOM_REGION; + } + } + } + + switch (region_action) { // clicked on the exit region case EXIT_REGION: gamesnd_play_iface(SND_IFACE_MOUSE_CLICK); @@ -705,17 +761,16 @@ // clicked on the readyroom region case READY_ROOM_REGION: - if (Player->flags & PLAYER_FLAGS_IS_MULTI) { - gamesnd_play_iface(SND_IFACE_MOUSE_CLICK); - main_hall_do_multi_ready(); + // Make sure we aren't in multi mode. + Player->flags &= ~PLAYER_FLAGS_IS_MULTI; + Game_mode = GM_NORMAL; + + if (strlen(Main_hall_campaign_cheat)) { + gameseq_post_event(GS_EVENT_CAMPAIGN_CHEAT); } else { - if (strlen(Main_hall_campaign_cheat)) { - gameseq_post_event(GS_EVENT_CAMPAIGN_CHEAT); - } else { - gameseq_post_event(GS_EVENT_NEW_CAMPAIGN); - } - gamesnd_play_iface(SND_IFACE_MOUSE_CLICK); + gameseq_post_event(GS_EVENT_NEW_CAMPAIGN); } + gamesnd_play_iface(SND_IFACE_MOUSE_CLICK); break; // clicked on the tech room region @@ -732,23 +787,20 @@ // clicked on the campaign toom region case CAMPAIGN_ROOM_REGION: - if (Player->flags & PLAYER_FLAGS_IS_MULTI) { - gamesnd_play_iface(SND_IFACE_MOUSE_CLICK); - main_hall_set_notify_string(XSTR( "Campaign Room not valid for multiplayer pilots", 366)); - } else { - gamesnd_play_iface(SND_IFACE_MOUSE_CLICK); - gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM); - } + gamesnd_play_iface(SND_IFACE_MOUSE_CLICK); + gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM); break; // clicked on the multiplayer region case MULTIPLAYER_REGION: - if (Player->flags & PLAYER_FLAGS_IS_MULTI) { - // NOTE : this isn't a great thing to be calling this anymore. But we'll leave it for now - gameseq_post_event(GS_EVENT_MULTI_JOIN_GAME); - } else { - main_hall_set_notify_string(XSTR( "Not a valid multiplayer pilot!!", 367)); - } + // Make sure we are in multi mode. + Player->flags |= PLAYER_FLAGS_IS_MULTI; + Game_mode = GM_MULTIPLAYER; + + main_hall_do_multi_ready(); + + // NOTE : this isn't a great thing to be calling this anymore. But we'll leave it for now + gameseq_post_event(GS_EVENT_MULTI_JOIN_GAME); break; // load mission key was pressed @@ -758,20 +810,16 @@ // quick start a game region case QUICK_START_REGION: #if !defined(NDEBUG) - if (Player->flags & PLAYER_FLAGS_IS_MULTI) { - main_hall_set_notify_string(XSTR( "Quick Start not valid for multiplayer pilots", 369)); + if (Num_recent_missions > 0) { + strcpy_s(Game_current_mission_filename, Recent_missions[0]); } else { - if (Num_recent_missions > 0) { - strcpy_s(Game_current_mission_filename, Recent_missions[0]); - } else { - if (mission_load_up_campaign()) { - main_hall_set_notify_string(XSTR( "Campaign file is currently unavailable", 1606)); - } - strcpy_s(Game_current_mission_filename, Campaign.missions[0].name); + if (mission_load_up_campaign()) { + main_hall_set_notify_string(XSTR( "Campaign file is currently unavailable", 1606)); } - Campaign.current_mission = -1; - gameseq_post_event(GS_EVENT_START_GAME_QUICK); + strcpy_s(Game_current_mission_filename, Campaign.missions[0].name); } + Campaign.current_mission = -1; + gameseq_post_event(GS_EVENT_START_GAME_QUICK); #endif break; @@ -799,11 +847,17 @@ help_overlay_set_state(Main_hall_overlay_id,gr_screen.res,0); } break; + + // custom action + case SCRIPT_REGION: + char *lua = (char*) Main_hall->regions.at(idx).lua_action.c_str(); + Script_system.EvalString(lua, NULL, NULL, lua); + break; } // END switch (code) // if the escape key wasn't pressed handle any mouse position related events if (code != ESC_PRESSED) { - main_hall_handle_mouse_location(code); + main_hall_handle_mouse_location((region_action == -1 ? -1 : idx)); } break; @@ -1211,8 +1265,8 @@ if (Main_hall_frame_skip) { return; } - - if (cur_region > NUM_MAIN_HALL_MOUSE_REGIONS) { + + if (cur_region > (int)Main_hall->regions.size() - 1) { // MWA -- inserted return since Int3() was tripped when hitting L from main menu. return; } @@ -1262,7 +1316,7 @@ } // don't do anything if there are no animations to play - else if(Main_hall_door_anim.size() == 0) + else if(region > (int) Main_hall_door_anim.size() - 1) { return; } @@ -1303,7 +1357,7 @@ } // don't do anything if there are no animations to play - else if(Main_hall_door_anim.size() == 0) + else if(region > (int) Main_hall_door_anim.size() - 1) { return; } @@ -1351,7 +1405,7 @@ if (!Main_hall_right_click) { if (mouse_down(MOUSE_RIGHT_BUTTON)) { // cycle through the available regions - if (Main_hall_last_clicked_region == NUM_MAIN_HALL_MOUSE_REGIONS - 1) { + if (Main_hall_last_clicked_region == (int) Main_hall_door_anim.size() - 1) { new_region = 0; } else { new_region = Main_hall_last_clicked_region + 1; @@ -1579,31 +1633,25 @@ */ void main_hall_maybe_blit_tooltips() { - int w, h, text_index; + int w, h; // if we're over no region - don't blit anything if (Main_hall_mouse_region < 0) { return; } - - // get the index of the proper text to be using - if (Main_hall_mouse_region == READY_ROOM_REGION) { - // if this is a multiplayer pilot, the ready room region becomes the multiplayer region - if (Player->flags & PLAYER_FLAGS_IS_MULTI){ - text_index = NUM_REGIONS - 1; - } else { - text_index = READY_ROOM_REGION; - } - } else { - text_index = Main_hall_mouse_region; + + if (Main_hall_mouse_region >= (int) Main_hall->regions.size()) { + Error(LOCATION, "Missing region description for index %d!\n", Main_hall_mouse_region); } // set the color and blit the string if (!help_overlay_active(Main_hall_overlay_id)) { int old_font = gr_get_current_fontnum(); + const char *desc = Main_hall->regions.at(Main_hall_mouse_region).description.c_str(); + gr_set_font(Main_hall->font); // get the width of the string - gr_get_string_size(&w, &h, Main_hall->region_descript.at(text_index)); + gr_get_string_size(&w, &h, desc); int text_y; if (Main_hall->region_yval == -1) { text_y = gr_screen.max_h_unscaled - ((gr_screen.max_h_unscaled - gr_screen.max_h_unscaled_zoomed) / 2) - Main_hall->tooltip_padding - h; @@ -1616,7 +1664,7 @@ gr_shade(0, shader_y, gr_screen.max_w_unscaled, (gr_screen.max_h_unscaled - shader_y), GR_RESIZE_MENU); gr_set_color_fast(&Color_bright_white); - gr_string((gr_screen.max_w_unscaled - w)/2, text_y, Main_hall->region_descript.at(text_index), GR_RESIZE_MENU); + gr_string((gr_screen.max_w_unscaled - w)/2, text_y, desc, GR_RESIZE_MENU); gr_set_font(old_font); } @@ -1876,7 +1924,6 @@ m.door_anim_coords.clear(); m.door_sounds.clear(); m.door_sound_pan.clear(); - m.region_descript.clear(); } SCP_vector temp; @@ -1901,12 +1948,30 @@ // door_sound_pan m.door_sound_pan.push_back(0.0f); } +} - // region_descript - for (idx = 0; idx < NUM_REGIONS; idx++) { - m.region_descript.push_back(NULL); +void region_info_init(main_hall_defines &m) +{ + if (Cmdline_reparse_mainhall) { + m.regions.clear(); } - + + main_hall_region defaults[] = { + {0, 0, XSTR( "Exit FreeSpace 2", 353), EXIT_REGION, ""}, + {1, 'B', XSTR( "Barracks - Manage your FreeSpace 2 pilots", 354), BARRACKS_REGION, ""}, + {2, 'R', XSTR( "Ready room - Start or continue a campaign", 355), START_REGION, ""}, + {3, 'T', XSTR( "Tech room - View specifications of FreeSpace 2 ships and weaponry", 356), TECH_ROOM_REGION, ""}, + {4, 0, XSTR( "Options - Change your FreeSpace 2 options", 357), OPTIONS_REGION, ""}, + {5, 'C', XSTR( "Campaign Room - View all available campaigns", 358), CAMPAIGN_ROOM_REGION, ""}, + {6, 'G', "Quick start", QUICK_START_REGION, ""} + }; + + for (int idx = 0; idx < 7; idx++) { + m.regions.push_back(defaults[idx]); + } + + // XSTR( "Multiplayer - Start or join a multiplayer game", 359) + m.default_readyroom = true; } /** @@ -1935,6 +2000,7 @@ int num_resolutions = 2; unsigned int count; char temp_string[MAX_FILENAME_LEN]; + SCP_string temp_scp_string; if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", filename, rval)); @@ -2165,7 +2231,9 @@ m->misc_anim_sound_flag.at(idx).push_back(0); } } - + + region_info_init(*m); + // door animations required_string("+Num Door Animations:"); stuff_int(&m->num_door_animations); @@ -2207,6 +2275,83 @@ m->font = FONT1; } + int mask; + for (idx = 0; optional_string("+Door mask value:"); idx++) { + // door mask + stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN); + + mask = (int) strtol(temp_string, NULL, 0); + mask = 255 - mask; + + if ((int) m->regions.size() <= idx) { + m->regions.resize(idx + 1); + } + + m->regions.at(idx).mask = mask; + } + + for (idx = 0; optional_string("+Door action:"); idx++) { + // door action + + if ((int) m->regions.size() <= idx) { + m->regions.resize(idx + 1); + } + + if (optional_string("Script")) { + m->regions.at(idx).action = SCRIPT_REGION; + stuff_string(m->regions.at(idx).lua_action, F_RAW); + } else { + stuff_string(temp_scp_string, F_RAW); + + int action = -1; + for (int i = 0; Main_hall_region_map[i].name != NULL; i++) { + if (temp_scp_string == Main_hall_region_map[i].name) { + action = Main_hall_region_map[i].mask; + break; + } + } + + if (action == -1) { + SCP_string err_msg = ""; + for (int i = 0; Main_hall_region_map[i].name != NULL; i++) { + err_msg += ", "; + err_msg += Main_hall_region_map[i].name; + } + + Error(LOCATION, "Unkown Door Region '%s'! Expected one of: %s", temp_scp_string.c_str(), err_msg.substr(2).c_str()); + } + + m->regions.at(idx).action = action; + } + } + + for (idx = 0; optional_string("+Door key:"); idx++) { + // door key + stuff_string(temp_string, F_RAW, MAX_FILENAME_LEN); + + if ((int) m->regions.size() <= idx) { + m->regions.resize(idx + 1); + } + m->regions.at(idx).key = (int) temp_string[0]; + } + + for (idx = 0; optional_string("+Door description:"); idx++) { + // region description (tooltip) + stuff_string(temp_scp_string, F_MESSAGE); + + if (temp_scp_string != "default") { + if ((int) m->regions.size() <= idx) { + m->regions.resize(idx + 1); + } + + m->regions.at(idx).description = temp_scp_string; + + if (idx == 2) { + m->default_readyroom = false; + } + } + } + // tooltip padding if (optional_string("+Tooltip Padding:")) { stuff_int(&m->tooltip_padding); Index: code/menuui/mainhallmenu.h =================================================================== --- code/menuui/mainhallmenu.h (revision 10870) +++ code/menuui/mainhallmenu.h (working copy) @@ -16,6 +16,14 @@ // CommanderDJ - this is now dynamic // #define MAIN_HALLS_MAX 10 +typedef struct main_hall_region { + int mask; + int key; + SCP_string description; + int action; + SCP_string lua_action; +} main_hall_region; + typedef struct main_hall_defines { // mainhall name identifier SCP_string name; @@ -115,8 +123,10 @@ // font used for the tooltips, version number, etc. int font; - // text (tooltip) description - SCP_vector region_descript; + // action + SCP_vector regions; + + bool default_readyroom; // num pixels shader is above/below tooltip text int tooltip_padding;