diff --git a/code/hud/hudsquadmsg.cpp b/code/hud/hudsquadmsg.cpp index 7d793d7116f..2a3dc2dbae3 100644 --- a/code/hud/hudsquadmsg.cpp +++ b/code/hud/hudsquadmsg.cpp @@ -104,8 +104,7 @@ int Menu_pgdn_coords[GR_NUM_RESOLUTIONS][2] = { // following defines/vars are used to build menus that are used in messaging mode char Squad_msg_title[256] = ""; -mmode_item MsgItems[MAX_MENU_ITEMS]; -int Num_menu_items = -1; // number of items for a message menu +std::optional> MsgItems; static int First_menu_item = -1; // index of first item in the menu. This tracks what element of comms options collection is displayed as first option, and displays the next 9 options. Changes only by +/- MAX_MENU_ITEMS (10) static int Selected_menu_item = First_menu_item; //!< index of selected item in the menu. Possible index range: 0 - 9, assuming MAX_MENU_ITEMS == 10, and First_menu_item gets initialized @@ -218,7 +217,7 @@ void hud_squadmsg_start() Msg_key = -1; Msg_key_set_from_scripting = false; - Num_menu_items = -1; // reset the menu items + MsgItems.reset(); // reset the menu items First_menu_item = 0; Selected_menu_item = First_menu_item; // make first menu item a selected object Display_selector = false; @@ -376,11 +375,7 @@ int hud_squadmsg_count_ships(int add_to_menu) count++; if (add_to_menu) { - Assert ( Num_menu_items < MAX_MENU_ITEMS ); - MsgItems[Num_menu_items].text = shipp->get_display_name(); - MsgItems[Num_menu_items].instance = SHIP_INDEX(shipp); - MsgItems[Num_menu_items].active = 1; - Num_menu_items++; + MsgItems.value().emplace_back(SHIP_INDEX(shipp), 1, shipp->get_display_name()); } } @@ -431,11 +426,7 @@ int hud_squadmsg_count_wings( int add_to_menu ) if ( hud_squadmsg_wing_valid(&Wings[wingnum]) ) { count++; if ( add_to_menu ) { - Assert ( Num_menu_items < MAX_MENU_ITEMS ); - MsgItems[Num_menu_items].text = Wings[wingnum].get_display_name(); - MsgItems[Num_menu_items].instance = wingnum; - MsgItems[Num_menu_items].active = 1; - Num_menu_items++; + MsgItems.value().emplace_back(wingnum, 1, Wings[wingnum].get_display_name()); } } } @@ -452,11 +443,7 @@ int hud_squadmsg_count_wings( int add_to_menu ) if ( hud_squadmsg_wing_valid(&Wings[i]) ) { count++; if ( add_to_menu ) { - Assert ( Num_menu_items < MAX_MENU_ITEMS ); - MsgItems[Num_menu_items].text = Wings[i].get_display_name(); - MsgItems[Num_menu_items].instance = i; - MsgItems[Num_menu_items].active = 1; - Num_menu_items++; + MsgItems.value().emplace_back(i, 1, Wings[i].get_display_name()); } } } @@ -469,15 +456,15 @@ int hud_squadmsg_count_wings( int add_to_menu ) void hud_squadmsg_do_mode( int mode ) { Squad_msg_mode = mode; - Num_menu_items = -1; + MsgItems.reset(); First_menu_item = 0; } void hud_squadmsg_page_down() { - if ( (First_menu_item + MAX_MENU_DISPLAY) < Num_menu_items ) { + if ( (First_menu_item + MAX_MENU_DISPLAY) < (MsgItems ? (int)MsgItems.value().size() : -1) ) { First_menu_item += MAX_MENU_DISPLAY; - Assert ( First_menu_item < Num_menu_items ); + Assert ( First_menu_item < (MsgItems ? (int)MsgItems.value().size() : -1) ); } } @@ -505,14 +492,14 @@ void hud_squadmsg_selection_move_down() { //Move to next page if we went outside of current one if (Selected_menu_item == MAX_MENU_DISPLAY - && (First_menu_item + MAX_MENU_DISPLAY < Num_menu_items)) + && (First_menu_item + MAX_MENU_DISPLAY < (MsgItems ? (int)MsgItems.value().size() : -1))) { hud_squadmsg_page_down(); Selected_menu_item = 0; } //Select the first menu item if we went outside items range, so we can loop around - if (First_menu_item + Selected_menu_item >= Num_menu_items) + if (First_menu_item + Selected_menu_item >= (MsgItems ? (int)MsgItems.value().size() : -1)) { First_menu_item = 0; Selected_menu_item = First_menu_item; @@ -546,8 +533,8 @@ void hud_squadmsg_selection_move_up() { //Assuming MAX_MENU_DISPLAY = 10, set First_menu_item to the nearest lower multiple of 10 //So if we have 85 items in comms menu, looping back from 1st page to last would set First_menu_item to 80 //exactly like pageUp/pageDown does - First_menu_item = ((Num_menu_items - 1) / MAX_MENU_DISPLAY) * MAX_MENU_DISPLAY; - Selected_menu_item = Num_menu_items - 1 - First_menu_item; + First_menu_item = (((MsgItems ? (int)MsgItems.value().size() : -1) - 1) / MAX_MENU_DISPLAY) * MAX_MENU_DISPLAY; + Selected_menu_item = (MsgItems ? (int)MsgItems.value().size() : -1) - 1 - First_menu_item; } } } @@ -560,7 +547,7 @@ void hud_squadmsg_selection_select() { if (Player->flags & PLAYER_FLAGS_MSG_MODE) { //Check if selected option is even active - if ((MsgItems[Selected_menu_item + First_menu_item].active > 0)) + if (((MsgItems ? (int)MsgItems.value().size() : -1) > Selected_menu_item + First_menu_item) && (MsgItems.value()[Selected_menu_item + First_menu_item].active > 0)) { Msg_key_used = 1; Msg_key = Selected_menu_item + 2; //+1 because menu items on actual menu start from 1, not 0 @@ -579,7 +566,7 @@ int hud_squadmsg_get_total_keys() int num_keys_used; num_keys_used = MAX_KEYS_NO_SCROLL; - if ( Num_menu_items > MAX_MENU_DISPLAY ) + if ( (MsgItems ? (int)MsgItems.value().size() : -1) > MAX_MENU_DISPLAY ) num_keys_used = MAX_KEYS_USED; return num_keys_used; @@ -669,15 +656,16 @@ int hud_squadmsg_get_key() } else if ( k == KEY_ESC ) { hud_squadmsg_toggle(); return -1; - } else if ( (i < Num_menu_items) && (Squad_msg_mode == SM_MODE_REINFORCEMENTS) ) // return any key if selecting reinforcement + } else if ( (i < (MsgItems ? (int)MsgItems.value().size() : -1)) && (Squad_msg_mode == SM_MODE_REINFORCEMENTS) ) { // return any key if selecting reinforcement return i; + } // play general fail sound if inactive item hit. - else if ((i + First_menu_item < Num_menu_items) && (MsgItems[i + First_menu_item].active == 0)) { + else if ((i + First_menu_item < (MsgItems ? (int)MsgItems.value().size() : -1)) && (MsgItems.value()[i + First_menu_item].active == 0)) { gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL); } - else if ((i + First_menu_item < Num_menu_items) && (MsgItems[i + First_menu_item].active > 0)) { // only return keys that are associated with menu items + else if ((i + First_menu_item < (MsgItems ? (int)MsgItems.value().size() : -1)) && (MsgItems.value()[i + First_menu_item].active > 0)) { // only return keys that are associated with menu items return i + First_menu_item; } @@ -1779,50 +1767,51 @@ void hud_squadmsg_type_select( ) num_order_types += (int)lua_cat_list.size(); + MsgItems = SCP_vector(); + // Add the items for (i = 0; i < num_order_types; i++) { + if (i < NUM_COMM_ORDER_TYPES) { - MsgItems[i].text = Comm_order_types[i]; + MsgItems.value().emplace_back(0, 1, Comm_order_types[i]); // assume active } else { - MsgItems[i].text = lua_cat_list[i - NUM_COMM_ORDER_TYPES]; - } - MsgItems[i].active = 1; // assume active + MsgItems.value().emplace_back(0, 1, lua_cat_list[i - NUM_COMM_ORDER_TYPES]); // assume active + } } - Num_menu_items = num_order_types; // check to see if the player is a traitor. If so, then he will not // be able to do anything from this menu if ((Player_ship != NULL) && (Player_ship->team == Iff_traitor)) { - for (i = 0; i < MAX_MENU_ITEMS; i++ ) - MsgItems[i].active = 0; + for (auto &item : MsgItems.value()) + item.active = 0; goto do_main_menu; } // based on ship counts, wing counts, shortcut active, grey out possible menu choices if ( !hud_squadmsg_count_ships(0) ) - MsgItems[TYPE_SHIP_ITEM].active = 0; + MsgItems.value()[TYPE_SHIP_ITEM].active = 0; if ( !hud_squadmsg_count_wings(0) ) - MsgItems[TYPE_WING_ITEM].active = 0; + MsgItems.value()[TYPE_WING_ITEM].active = 0; // check to be sure that we have some fighters/bombers on the players team that we // can message if ( !hud_squadmsg_exist_fighters() ){ - MsgItems[TYPE_ALL_FIGHTERS_ITEM].active = 0; + MsgItems.value()[TYPE_ALL_FIGHTERS_ITEM].active = 0; } if ((Player_ship != NULL) && !hud_squadmsg_reinforcements_available(Player_ship->team)) { - MsgItems[TYPE_REINFORCEMENT_ITEM].active = 0; + MsgItems.value()[TYPE_REINFORCEMENT_ITEM].active = 0; } - MsgItems[TYPE_REPAIR_REARM_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 1; - MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 0; + MsgItems.value()[TYPE_REPAIR_REARM_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 1; + MsgItems.value()[TYPE_REPAIR_REARM_ABORT_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 0; for(const auto& cat : lua_cat_list){ if (ai_lua_get_general_orders(false, false, cat).size() == 0) { - MsgItems[NUM_COMM_ORDER_TYPES + lua_order_count].active = 0; + MsgItems.value()[NUM_COMM_ORDER_TYPES + lua_order_count].active = 0; } lua_order_count++; } @@ -1833,51 +1822,51 @@ void hud_squadmsg_type_select( ) // // also, only allow support ship if this player is not allowed to messaage. if ( (hud_communications_state(Player_ship) != COMM_OK) || ((Game_mode & GM_MULTIPLAYER) && !multi_can_message(Net_player)) ) { - for ( i = 0; i < MAX_MENU_ITEMS; i++ ){ - MsgItems[i].active = 0; + for (auto &item : MsgItems.value()){ + item.active = 0; } - MsgItems[TYPE_REPAIR_REARM_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 1; + MsgItems.value()[TYPE_REPAIR_REARM_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 1; } // check to see if the player is awaiting repair or being repaired. Active the abort and inactive the repair items // check to see if the player is scheduled to be repaired by incoming ship if (Ai_info[Ships[Player_obj->instance].ai_index].ai_flags.any_of(AI::AI_Flags::Being_repaired,AI::AI_Flags::Awaiting_repair)) { - MsgItems[TYPE_REPAIR_REARM_ITEM].active = 0; - MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = 1; + MsgItems.value()[TYPE_REPAIR_REARM_ITEM].active = 0; + MsgItems.value()[TYPE_REPAIR_REARM_ABORT_ITEM].active = 1; } else if ( mission_is_repair_scheduled(Player_obj) ) { - MsgItems[TYPE_REPAIR_REARM_ITEM].active = 0; - MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = 1; + MsgItems.value()[TYPE_REPAIR_REARM_ITEM].active = 0; + MsgItems.value()[TYPE_REPAIR_REARM_ABORT_ITEM].active = 1; } // if no support available, can't call one in else if ( !is_support_allowed(Player_obj) ) { - MsgItems[TYPE_REPAIR_REARM_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 0; - MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 0; + MsgItems.value()[TYPE_REPAIR_REARM_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 0; + MsgItems.value()[TYPE_REPAIR_REARM_ABORT_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 0; } // de-activate the rearm/repair item if the player has a full load of missiles and // all subsystems at full strength. We will only check if this item hasn't been marked // inactive because of some other reason - if ( MsgItems[TYPE_REPAIR_REARM_ITEM].active > 0 ) { + if ( MsgItems.value()[TYPE_REPAIR_REARM_ITEM].active > 0 ) { if ( !hud_squadmsg_can_rearm(Player_ship) ){ - MsgItems[TYPE_REPAIR_REARM_ITEM].active = 0; + MsgItems.value()[TYPE_REPAIR_REARM_ITEM].active = 0; } } // if using keyboard shortcut, these items are always inactive or hidden if ( Msg_shortcut_command != -1 ) { - MsgItems[TYPE_REINFORCEMENT_ITEM].active = 0; - MsgItems[TYPE_REPAIR_REARM_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 0; - MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 0; + MsgItems.value()[TYPE_REINFORCEMENT_ITEM].active = 0; + MsgItems.value()[TYPE_REPAIR_REARM_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 0; + MsgItems.value()[TYPE_REPAIR_REARM_ABORT_ITEM].active = Hide_main_rearm_items_in_comms_gauge ? -1 : 0; } do_main_menu: strcpy_s(Squad_msg_title, XSTR( "Message What", 316)); k = hud_squadmsg_get_key(); if ( k != -1 ) { // when k != -1, we have a key that associates with menu item - Assert ( k < Num_menu_items ); + Assert ( k < (MsgItems ? (int)MsgItems.value().size() : -1) ); if ( k == TYPE_SHIP_ITEM ){ hud_squadmsg_do_mode( SM_MODE_SHIP_SELECT ); } else if ( k == TYPE_WING_ITEM ) { @@ -1907,8 +1896,8 @@ void hud_squadmsg_ship_select() { int k; - if ( Num_menu_items == -1 ) { - Num_menu_items = 0; + if ( !MsgItems ) { + MsgItems = SCP_vector(); hud_squadmsg_count_ships( 1 ); } @@ -1916,13 +1905,13 @@ void hud_squadmsg_ship_select() k = hud_squadmsg_get_key(); if ( k != -1 ) { // if true, we have selected a ship. if ( Msg_shortcut_command == -1 ) { - Msg_instance = MsgItems[k].instance; // store the instance id in a global + Msg_instance = MsgItems.value()[k].instance; // store the instance id in a global hud_squadmsg_do_mode( SM_MODE_SHIP_COMMAND ); // and move to a new mode } else { // we must convert the Msg_shortcut_command value to a value that the message // system normally uses to select a command. Since the menu //Assert( Msg_shortcut_command != IGNORE_TARGET_ITEM ); - hud_squadmsg_send_ship_command( MsgItems[k].instance, Msg_shortcut_command, 1, SQUADMSG_HISTORY_ADD_ENTRY); + hud_squadmsg_send_ship_command( MsgItems.value()[k].instance, Msg_shortcut_command, 1, SQUADMSG_HISTORY_ADD_ENTRY); hud_squadmsg_toggle(); } } @@ -1934,8 +1923,8 @@ void hud_squadmsg_wing_select() { int k; - if ( Num_menu_items == -1 ) { - Num_menu_items = 0; + if ( !MsgItems ) { + MsgItems = SCP_vector(); hud_squadmsg_count_wings( 1 ); } @@ -1943,11 +1932,11 @@ void hud_squadmsg_wing_select() k = hud_squadmsg_get_key(); if ( k != -1 ) { // if true, we have selected a ship. if ( Msg_shortcut_command == -1 ) { // do normal menu stuff when no hoykey active - Msg_instance = MsgItems[k].instance; // store the instance id in a global + Msg_instance = MsgItems.value()[k].instance; // store the instance id in a global hud_squadmsg_do_mode( SM_MODE_WING_COMMAND ); // and move to a new mode } else { //Assert( Msg_shortcut_command != IGNORE_TARGET_ITEM ); - hud_squadmsg_send_wing_command( MsgItems[k].instance, Msg_shortcut_command, 1, SQUADMSG_HISTORY_ADD_ENTRY ); + hud_squadmsg_send_wing_command( MsgItems.value()[k].instance, Msg_shortcut_command, 1, SQUADMSG_HISTORY_ADD_ENTRY ); hud_squadmsg_toggle(); } } @@ -2045,8 +2034,8 @@ void hud_squadmsg_call_reinforcement(reinforcements &reinforcement, int /*playe // function to display a list of reinforcements available to the player void hud_squadmsg_reinforcement_select() { - if ( Num_menu_items == -1 ) { - Num_menu_items = 0; + if ( !MsgItems ) { + MsgItems = SCP_vector(); int i = -1; for (const auto &reinforcement: Reinforcements) { @@ -2092,16 +2081,7 @@ void hud_squadmsg_reinforcement_select() r_name = p_objp->get_display_name(); // this will handle getting rid of the hash if necessary } - Assert ( Num_menu_items < MAX_MENU_ITEMS ); - MsgItems[Num_menu_items].text = r_name; - MsgItems[Num_menu_items].instance = i; - MsgItems[Num_menu_items].active = 0; - - if ( reinforcement.flags & RF_IS_AVAILABLE ) { - MsgItems[Num_menu_items].active = 1; - } - - Num_menu_items++; + MsgItems.value().emplace_back(i, (reinforcement.flags & RF_IS_AVAILABLE), r_name); // set the item to active if reinforcement is available } } @@ -2113,11 +2093,11 @@ void hud_squadmsg_reinforcement_select() hud_squadmsg_toggle(); // take us out of message mode - rnum = MsgItems[k].instance; + rnum = MsgItems.value()[k].instance; // check to see if trying to call a reinforcement not yet available. If so, maybe play message, but // definately bail - if ( MsgItems[k].active == 0 ) { + if ( MsgItems.value()[k].active == 0 ) { return; } @@ -2158,25 +2138,22 @@ void hud_squadmsg_ship_command() default_orders.insert(default_messages.cbegin(), default_messages.cend()); } - Num_menu_items = 0; + MsgItems = SCP_vector(); for(size_t order_id : default_orders) { - Assert (Num_menu_items < MAX_MENU_ITEMS); - MsgItems[Num_menu_items].text = Player_orders[order_id].localized_name; - MsgItems[Num_menu_items].instance = (int)order_id; - MsgItems[Num_menu_items].active = 0; + MsgItems.value().emplace_back((int)order_id, 0, Player_orders[order_id].localized_name); // check the bit to see if the command is active if (orders.find(order_id) != orders.end()) - MsgItems[Num_menu_items].active = 1; + MsgItems.value().back().active = 1; // if the order cannot be carried out by the ship, then item should be inactive if ((Msg_instance != MESSAGE_ALL_FIGHTERS) && !hud_squadmsg_ship_order_valid(Msg_instance, (int)order_id)) - MsgItems[Num_menu_items].active = 0; + MsgItems.value().back().active = 0; // do some other checks to possibly gray out other items. // if no target, remove any items which are associated with the players target if (!hud_squadmsg_is_target_order_valid(order_id, nullptr)) - MsgItems[Num_menu_items].active = 0; + MsgItems.value().back().active = 0; // if messaging all fighters, see if we should gray out the order if no one will accept it, // or modify the text if only some of the ships will accept it @@ -2208,14 +2185,13 @@ void hud_squadmsg_ship_command() if (!all_accept) { // either modify the text if a partial accept, or grey it out if no one accepts if (partial_accept) { - MsgItems[Num_menu_items].text += XSTR("(*)", 320); + MsgItems.value().back().text += XSTR("(*)", 320); } else { - MsgItems[Num_menu_items].active = 0; + MsgItems.value().back().active = 0; } } } - Num_menu_items++; } @@ -2225,13 +2201,13 @@ void hud_squadmsg_ship_command() // when we get a valid goal, we must add the goal to the ai ship's goal list if ( k != -1 ) { - Assert ( k < Num_menu_items ); + Assert ( k < (MsgItems ? (int)MsgItems.value().size() : -1) ); // when messaging all fighters or ignoring target, call the send_to_all_fighters routine // Goober5000 - ignore no longer sends to all fighters if (Msg_instance == MESSAGE_ALL_FIGHTERS) - hud_squadmsg_send_to_all_fighters(MsgItems[k].instance); + hud_squadmsg_send_to_all_fighters(MsgItems.value()[k].instance); else - hud_squadmsg_send_ship_command(Msg_instance, MsgItems[k].instance, 1, SQUADMSG_HISTORY_ADD_ENTRY); + hud_squadmsg_send_ship_command(Msg_instance, MsgItems.value()[k].instance, 1, SQUADMSG_HISTORY_ADD_ENTRY); hud_squadmsg_toggle(); } @@ -2241,9 +2217,8 @@ void hud_squadmsg_msg_general() { int k; - Num_menu_items = 0; + MsgItems = SCP_vector(); for (size_t order_id = 0; order_id < Player_orders.size(); order_id++) { - Assert(Num_menu_items < MAX_MENU_ITEMS); if (Player_orders[order_id].lua_id <= 0) { continue; @@ -2263,17 +2238,12 @@ void hud_squadmsg_msg_general() //Only add it if it is enabled for the mission if (lua_porder->cur_enabled) { - - MsgItems[Num_menu_items].text = Player_orders[order_id].localized_name; - MsgItems[Num_menu_items].instance = Player_orders[order_id].lua_id; - MsgItems[Num_menu_items].active = (int)lua_porder->cur_valid; + MsgItems.value().emplace_back(Player_orders[order_id].lua_id, (int)lua_porder->cur_valid, Player_orders[order_id].localized_name); // do some other checks to possibly gray out other items. // if no target, remove any items which are associated with the players target if (!hud_squadmsg_is_target_order_valid(order_id, nullptr)) - MsgItems[Num_menu_items].active = 0; - - Num_menu_items++; + MsgItems.value().back().active = 0; } } @@ -2283,9 +2253,9 @@ void hud_squadmsg_msg_general() // when we get a valid goal, we must add the goal to the ai ship's goal list if (k != -1) { - Assert(k < Num_menu_items); + Assert(k < (MsgItems ? (int)MsgItems.value().size() : -1)); - ai_lua_start_general(MsgItems[k].instance, Player_ai->target_objnum); + ai_lua_start_general(MsgItems.value()[k].instance, Player_ai->target_objnum); hud_squadmsg_toggle(); } @@ -2314,7 +2284,7 @@ void hud_squadmsg_wing_command() default_orders.erase(CAPTURE_TARGET_ITEM); // we cannot capture any target with a wing. - Num_menu_items = 0; + MsgItems = SCP_vector(); shipnum = wingp->ship_index[wingp->special_ship]; Assertion(shipnum >= 0, "Special ship (%d) for wing '%s' has a negative ship_index (%d). This should not happen; get a coder!\n", wingp->special_ship, wingp->name, shipnum); orders = Ships[shipnum].orders_accepted; // get the orders that the wing leader will accept @@ -2322,24 +2292,21 @@ void hud_squadmsg_wing_command() for ( size_t order_id : default_orders ) { // add the set of default orders to the comm menu. We will currently allow all messages // to be available in the wing. - Assert ( Num_menu_items < MAX_MENU_ITEMS ); - MsgItems[Num_menu_items].text = Player_orders[order_id].localized_name; - MsgItems[Num_menu_items].instance = (int)order_id; - MsgItems[Num_menu_items].active = 0; + MsgItems.value().emplace_back((int)order_id, 0, Player_orders[order_id].localized_name); // possibly grey out the menu item depending on whether or not the "wing" will accept this order // the "wing" won't accept the order if the first ship in the wing doesn't accept it. if ( orders.find(order_id) != orders.end() ) - MsgItems[Num_menu_items].active = 1; + MsgItems.value().back().active = 1; // do some other checks to possibly gray out other items. // if no target, remove any items which are associated with the players target if ( !hud_squadmsg_is_target_order_valid((int)order_id, 0, true) ) - MsgItems[Num_menu_items].active = 0; + MsgItems.value().back().active = 0; // if no ship in the wing can depart then gray out the departure order if (order_id == DEPART_ITEM) { - if (MsgItems[Num_menu_items].active > 0) { + if (MsgItems.value().back().active > 0) { int active = 0; for (int i = 0; i < wingp->current_count; i++) { if (hud_squadmsg_ship_order_valid(wingp->ship_index[i], (int)order_id)) { @@ -2347,12 +2314,9 @@ void hud_squadmsg_wing_command() break; } } - MsgItems[Num_menu_items].active = active; + MsgItems.value().back().active = active; } - } - - Num_menu_items++; - + } } @@ -2365,7 +2329,7 @@ void hud_squadmsg_wing_command() if (MsgItems[k].instance == IGNORE_TARGET_ITEM) hud_squadmsg_send_to_all_fighters(MsgItems[k].instance); else */ - hud_squadmsg_send_wing_command(Msg_instance, MsgItems[k].instance, 1); + hud_squadmsg_send_wing_command(Msg_instance, MsgItems.value()[k].instance, 1); hud_squadmsg_toggle(); } @@ -2906,13 +2870,13 @@ void HudGaugeSquadMessage::render(float /*frametime*/, bool config) int nitems; if (!config) { - if (Num_menu_items < MAX_MENU_DISPLAY) - nitems = Num_menu_items; + if ((MsgItems ? (int)MsgItems.value().size() : -1) < MAX_MENU_DISPLAY) + nitems = (MsgItems ? (int)MsgItems.value().size() : -1); else { if (First_menu_item == 0) // First_menu_item == 0 means first page of items nitems = MAX_MENU_DISPLAY; - else if ((Num_menu_items - First_menu_item) <= MAX_MENU_DISPLAY) // check if remaining items fit on one page - nitems = Num_menu_items - First_menu_item; + else if (((MsgItems ? (int)MsgItems.value().size() : -1) - First_menu_item) <= MAX_MENU_DISPLAY) // check if remaining items fit on one page + nitems = (MsgItems ? (int)MsgItems.value().size() : -1) - First_menu_item; else { nitems = MAX_MENU_DISPLAY; } @@ -2941,7 +2905,7 @@ void HudGaugeSquadMessage::render(float /*frametime*/, bool config) char text[256]; if (!config) { - strcpy_s(text, MsgItems[First_menu_item + i].text.c_str()); + strcpy_s(text, MsgItems.value()[First_menu_item + i].text.c_str()); } else { // in config mode, so create just the first page of the Comms Menu // as other functions, such as hud_squadmsg_type_select() will not be run in config mode @@ -2954,7 +2918,7 @@ void HudGaugeSquadMessage::render(float /*frametime*/, bool config) }; strcpy_s(text, temp_comm_order_types[i]); if (Hide_main_rearm_items_in_comms_gauge && (i == TYPE_REPAIR_REARM_ITEM || i == TYPE_REPAIR_REARM_ABORT_ITEM)) { - MsgItems[First_menu_item + i].active = -1; + MsgItems.value()[First_menu_item + i].active = -1; } } @@ -2966,7 +2930,7 @@ void HudGaugeSquadMessage::render(float /*frametime*/, bool config) by += fl2i(Item_h * scale); // set the text color - if (!config && (MsgItems[First_menu_item + i].active > 0)) { + if (!config && (MsgItems.value()[First_menu_item + i].active > 0)) { setGaugeColor(HUD_C_BRIGHT, config); } else if (isSelectedItem) { @@ -2976,7 +2940,7 @@ void HudGaugeSquadMessage::render(float /*frametime*/, bool config) setGaugeColor(HUD_C_DIM, config); } - if (MsgItems[First_menu_item + i].active >= 0) { + if (MsgItems.value()[First_menu_item + i].active >= 0) { // first print an icon to indicate selected item item_num = (i + 1) % MAX_MENU_DISPLAY; if (isSelectedItem && Display_selector) { @@ -2995,13 +2959,13 @@ void HudGaugeSquadMessage::render(float /*frametime*/, bool config) // if we have at least one item active, then set the variable so we don't display any // message about no active items - if (config || (MsgItems[First_menu_item+i].active > 0) ) + if (config || (MsgItems.value()[First_menu_item+i].active > 0) ) none_valid = false; } // maybe draw an extra line in to make room for [pgdn], or for the 'no active items' // display - if (!config && (!messaging_allowed || none_valid || ((First_menu_item + nitems) < Num_menu_items) || (Msg_shortcut_command != -1))) { + if (!config && (!messaging_allowed || none_valid || ((First_menu_item + nitems) < (MsgItems ? (int)MsgItems.value().size() : -1)) || (Msg_shortcut_command != -1))) { // blit the background setGaugeColor(HUD_C_NONE, config); if ( Mbox_gauge[1].first_frame >= 0 ) { @@ -3026,7 +2990,7 @@ void HudGaugeSquadMessage::render(float /*frametime*/, bool config) renderPrintf(x + fl2i(Pgup_offsets[0] * scale), y + fl2i(Pgup_offsets[1] * scale), scale, config, "%s", XSTR( "[pgup]", 312) ); } - if ( (First_menu_item + nitems) < Num_menu_items ) { + if ( (First_menu_item + nitems) < (MsgItems ? (int)MsgItems.value().size() : -1) ) { renderPrintf(x + fl2i(Pgdn_offsets[0] * scale), y + fl2i(Pgdn_offsets[1] * scale), scale, config, "%s", XSTR( "[pgdn]", 313)); } diff --git a/code/hud/hudsquadmsg.h b/code/hud/hudsquadmsg.h index 7cf6eb016c2..5db8031ef9f 100644 --- a/code/hud/hudsquadmsg.h +++ b/code/hud/hudsquadmsg.h @@ -62,7 +62,6 @@ struct reinforcements; // used for Message box gauge #define NUM_MBOX_FRAMES 3 -#define MAX_MENU_ITEMS 50 // max number of items in the menu #define MAX_MENU_DISPLAY 10 // max number that can be displayed // following are defines and character strings that are used as part of messaging mode @@ -80,11 +79,15 @@ typedef struct mmode_item { int instance; // instance in Ships/Wings array of this menu item int active; // active items are in bold text (1) -- inactive items greyed out (0) -- hidden objects not rendered (-1) SCP_string text; // text to display on the menu + mmode_item(int param_instance, int param_active, SCP_string param_text) { + instance = param_instance; + active = param_active; + text = std::move(param_text); + }; } mmode_item; extern char Squad_msg_title[256]; -extern mmode_item MsgItems[MAX_MENU_ITEMS]; -extern int Num_menu_items; // number of items for a message menu +extern std::optional> MsgItems; typedef struct player_order { private: diff --git a/code/parse/sexp/LuaAISEXP.cpp b/code/parse/sexp/LuaAISEXP.cpp index 0e9bc995672..045a66877bf 100644 --- a/code/parse/sexp/LuaAISEXP.cpp +++ b/code/parse/sexp/LuaAISEXP.cpp @@ -154,13 +154,6 @@ void LuaAISEXP::parseTable() { // Now get a list of all lua categories to add. Meow. SCP_vector lua_cat_list = ai_lua_get_general_order_categories(); - // If we have too many categories then we have an oopsie! - if ((int)lua_cat_list.size() > (MAX_MENU_ITEMS - NUM_COMM_ORDER_TYPES)) { - Warning(LOCATION, "Too many defined Lua General Order Categories! Setting order to first available: %s", lua_cat_list[0].c_str()); - - order.category = lua_cat_list[0]; - } - // General orders explicitely do not show up in FRED as sexps because they // they are only meant for the comms board _return_type = OPR_NONE; diff --git a/code/scripting/api/libs/mission.cpp b/code/scripting/api/libs/mission.cpp index 14df3af0562..ad1a69454d7 100644 --- a/code/scripting/api/libs/mission.cpp +++ b/code/scripting/api/libs/mission.cpp @@ -343,7 +343,7 @@ ADE_INDEXER(l_Mission_Comm_Items, // convert from lua index idx--; - if ((idx < 0) || idx >= MAX_MENU_ITEMS) + if ((idx < 0)) return ade_set_args(L, "o", l_Comm_Item.Set(-1)); return ade_set_args(L, "o", l_Comm_Item.Set(idx)); @@ -356,7 +356,7 @@ ADE_FUNC(__len, "number", "Number of comm orders in the mission. 0 if comm menu is closed") { - return ade_set_args(L, "i", Num_menu_items); + return ade_set_args(L, "i", (MsgItems ? (int)MsgItems.value().size() : -1)); } //****SUBLIBRARY: Mission/Debris diff --git a/code/scripting/api/objs/comm_order.cpp b/code/scripting/api/objs/comm_order.cpp index fe18f0da567..f75913f5004 100644 --- a/code/scripting/api/objs/comm_order.cpp +++ b/code/scripting/api/objs/comm_order.cpp @@ -17,8 +17,11 @@ ADE_VIRTVAR(Name, l_Comm_Item, nullptr, "The name of the comm item", "string", " if (ADE_SETTING_VAR) { LuaError(L, "This property is read only."); } - - return ade_set_args(L, "s", MsgItems[current].text.c_str()); + SCP_string message = "Invalid comm item!"; + if ((MsgItems ? (int)MsgItems.value().size() : -1) > current) { + message = MsgItems.value()[current].text; + }; + return ade_set_args(L, "s", message.c_str()); } ADE_VIRTVAR(Active, l_Comm_Item, nullptr, "Whether or not the item is active", "boolean", "The active status") @@ -32,7 +35,7 @@ ADE_VIRTVAR(Active, l_Comm_Item, nullptr, "Whether or not the item is active", " LuaError(L, "This property is read only."); } - if (MsgItems[current].active > 0) { + if ((MsgItems ? (int)MsgItems.value().size() : -1) > current && MsgItems.value()[current].active > 0) { return ADE_RETURN_TRUE; } @@ -60,7 +63,7 @@ ADE_FUNC(selectItem, l_Comm_Item, nullptr, "Selects the item and either proceeds if (!ade_get_args(L, "o", l_Comm_Item.Get(¤t))) return ADE_RETURN_FALSE; - if (current < 0 || current >= Num_menu_items) { + if (current < 0 || current >= (MsgItems ? (int)MsgItems.value().size() : -1)) { LuaError(L, "Lua tried to select squad message that is not valid!"); return ADE_RETURN_FALSE; } @@ -77,7 +80,7 @@ ADE_FUNC(isValid, l_Comm_Item, nullptr, "Detect if the handle is valid", "boolea if (!ade_get_args(L, "o", l_Comm_Item.Get(¤t))) return ADE_RETURN_FALSE; - return ade_set_args(L, "b", (current >= 0) && (current < Num_menu_items)); + return ade_set_args(L, "b", (current >= 0) && (current < (MsgItems ? (int)MsgItems.value().size() : -1))); } } // namespace scripting::api