ShipSelectionScreen::ShipSelectionScreen() { //Easiest place to ensure that positional sound is disabled on console views. As soon as a 3D view is rendered positional sound is enabled again. soundManager->disablePositionalSound(); (new GuiLabel(this, "CREW_POSITION_SELECT_LABEL", "Select your station", 30))->addBox()->setPosition(-50, 50, ATopRight)->setSize(460, 50); (new GuiBox(this, "CREW_POSITION_SELECT_BOX"))->setPosition(-50, 50, ATopRight)->setSize(460, 560); GuiAutoLayout* stations_layout = new GuiAutoLayout(this, "CREW_POSITION_BUTTON_LAYOUT", GuiAutoLayout::LayoutVerticalTopToBottom); stations_layout->setPosition(-80, 100, ATopRight)->setSize(400, 500); main_screen_button = new GuiToggleButton(stations_layout, "MAIN_SCREEN_BUTTON", "Main screen", [this](bool value) { for(int n=0; n<max_crew_positions; n++) { crew_position_button[n]->setValue(false); my_player_info->setCrewPosition(ECrewPosition(n), crew_position_button[n]->getValue()); } updateReadyButton(); }); main_screen_button->setSize(GuiElement::GuiSizeMax, 50); for(int n=0; n<max_crew_positions; n++) { crew_position_button[n] = new GuiToggleButton(stations_layout, "CREW_" + getCrewPositionName(ECrewPosition(n)) + "_BUTTON", getCrewPositionName(ECrewPosition(n)), [this, n](bool value){ main_screen_button->setValue(false); my_player_info->setCrewPosition(ECrewPosition(n), value); updateReadyButton(); }); crew_position_button[n]->setSize(GuiElement::GuiSizeMax, 50); } main_screen_controls_button = new GuiToggleButton(stations_layout, "MAIN_SCREEN_CONTROLS_ENABLE", "Main screen controls", [](bool value) { my_player_info->setMainScreenControl(value); }); main_screen_controls_button->setValue(my_player_info->main_screen_control)->setSize(GuiElement::GuiSizeMax, 50); game_master_button = new GuiToggleButton(stations_layout, "GAME_MASTER_BUTTON", "Game master", [this](bool value) { window_button->setValue(false); topdown_button->setValue(false); updateReadyButton(); }); game_master_button->setSize(GuiElement::GuiSizeMax, 50); window_button = new GuiToggleButton(stations_layout, "WINDOW_BUTTON", "Ship window", [this](bool value) { game_master_button->setValue(false); topdown_button->setValue(false); updateReadyButton(); }); window_button->setSize(GuiElement::GuiSizeMax, 50); window_angle = new GuiSelector(stations_layout, "WINDOW_ANGLE", nullptr); for(int n=0; n<360; n+=15) window_angle->addEntry(string(n) + " degrees", string(n)); window_angle->setSelectionIndex(0); window_angle->setSize(GuiElement::GuiSizeMax, 50); topdown_button = new GuiToggleButton(stations_layout, "TOP_DOWN_3D_BUTTON", "Top down 3D", [this](bool value) { game_master_button->setValue(false); window_button->setValue(false); updateReadyButton(); }); topdown_button->setSize(GuiElement::GuiSizeMax, 50); crew_type_selector = new GuiSelector(this, "CREW_TYPE_SELECTION", [this](int index, string value) { updateCrewTypeOptions(); }); crew_type_selector->setOptions({"6/5 player crew", "4/3 player crew", "1 player crew/extras", "Alternative options"})->setPosition(-50, 560, ATopRight)->setSize(460, 50); (new GuiLabel(this, "SHIP_SELECTION_LABEL", "Select ship:", 30))->addBox()->setPosition(50, 50, ATopLeft)->setSize(550, 50); no_ships_label = new GuiLabel(this, "SHIP_SELECTION_NO_SHIPS_LABEL", "Waiting for server to spawn a ship", 30); no_ships_label->setPosition(80, 100, ATopLeft)->setSize(460, 50); (new GuiBox(this, "SHIP_SELECTION_BOX"))->setPosition(50, 50, ATopLeft)->setSize(550, 560); player_ship_list = new GuiListbox(this, "PLAYER_SHIP_LIST", [this](int index, string value) { my_spaceship = gameGlobalInfo->getPlayerShip(value.toInt()); if (my_spaceship) { my_player_info->setShipId(my_spaceship->getMultiplayerId()); }else{ my_player_info->setShipId(-1); } updateReadyButton(); }); player_ship_list->setPosition(80, 100, ATopLeft)->setSize(490, 500); if (game_server) { (new GuiBox(this, "CREATE_SHIP_BOX"))->setPosition(50, 50, ATopLeft)->setSize(550, 700); GuiSelector* ship_template_selector = new GuiSelector(this, "CREATE_SHIP_SELECTOR", nullptr); std::vector<string> template_names = ShipTemplate::getPlayerTemplateNameList(); std::sort(template_names.begin(), template_names.end()); ship_template_selector->setOptions(template_names)->setSelectionIndex(0); ship_template_selector->setPosition(80, 630, ATopLeft)->setSize(490, 50); (new GuiButton(this, "CREATE_SHIP_BUTTON", "Spawn player ship", [this, ship_template_selector]() { my_spaceship = new PlayerSpaceship(); if (my_spaceship) { my_spaceship->setShipTemplate(ship_template_selector->getSelectionValue()); my_spaceship->setRotation(random(0, 360)); my_spaceship->target_rotation = my_spaceship->getRotation(); my_spaceship->setPosition(sf::Vector2f(random(-100, 100), random(-100, 100))); my_player_info->setShipId(my_spaceship->getMultiplayerId()); } updateReadyButton(); }))->setPosition(80, 680, ATopLeft)->setSize(490, 50); } (new GuiButton(this, "DISCONNECT", game_server ? "Close server" : "Disconnect", [this]() { destroy(); disconnectFromServer(); returnToMainMenu(); }))->setPosition(150, -50, ABottomLeft)->setSize(300, 50); ready_button = new GuiButton(this, "READY_BUTTON", "Ready", [this]() {this->onReadyClick();}); ready_button->setPosition(-150, -50, ABottomRight)->setSize(300, 50); crew_type_selector->setSelectionIndex(0); updateReadyButton(); updateCrewTypeOptions(); }
ShipSelectionScreen::ShipSelectionScreen() { new GuiOverlay(this, "", colorConfig.background); (new GuiOverlay(this, "", sf::Color::White))->setTextureTiled("gui/BackgroundCrosses"); // Easiest place to ensure that positional sound is disabled on console // views. As soon as a 3D view is rendered, positional sound is re-enabled. soundManager->disablePositionalSound(); // Draw a container with two columns. container = new GuiAutoLayout(this, "", GuiAutoLayout::ELayoutMode::LayoutVerticalColumns); container->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); left_container = new GuiElement(container, ""); right_container = new GuiElement(container, ""); // List the station types and stations in the right column. GuiAutoLayout* stations_layout = new GuiAutoLayout(right_container, "CREW_POSITION_BUTTON_LAYOUT", GuiAutoLayout::LayoutVerticalTopToBottom); stations_layout->setPosition(0, 50, ATopCenter)->setSize(400, 500); (new GuiLabel(stations_layout, "CREW_POSITION_SELECT_LABEL", "Select your station", 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50); // Crew type selector crew_type_selector = new GuiSelector(stations_layout, "CREW_TYPE_SELECTION", [this](int index, string value) { updateCrewTypeOptions(); }); crew_type_selector->setOptions({"6/5 player crew", "4/3 player crew", "1 player crew/extras", "Alternative options"})->setSize(GuiElement::GuiSizeMax, 50); // Main screen button main_screen_button = new GuiToggleButton(stations_layout, "MAIN_SCREEN_BUTTON", "Main screen", [this](bool value) { for(int n=0; n<max_crew_positions; n++) { crew_position_button[n]->setValue(false); my_player_info->commandSetCrewPosition(ECrewPosition(n), crew_position_button[n]->getValue()); } }); main_screen_button->setSize(GuiElement::GuiSizeMax, 50); // Crew position buttons, with icons if they have them for(int n = 0; n < max_crew_positions; n++) { crew_position_button[n] = new GuiToggleButton(stations_layout, "CREW_" + getCrewPositionName(ECrewPosition(n)) + "_BUTTON", getCrewPositionName(ECrewPosition(n)), [this, n](bool value){ main_screen_button->setValue(false); my_player_info->commandSetCrewPosition(ECrewPosition(n), value); }); crew_position_button[n]->setSize(GuiElement::GuiSizeMax, 50); crew_position_button[n]->setIcon(getCrewPositionIcon(ECrewPosition(n))); } // Main screen controls button main_screen_controls_button = new GuiToggleButton(stations_layout, "MAIN_SCREEN_CONTROLS_ENABLE", "Main screen controls", [](bool value) { my_player_info->commandSetMainScreenControl(value); }); main_screen_controls_button->setValue(my_player_info->main_screen_control)->setSize(GuiElement::GuiSizeMax, 50); // Game master button game_master_button = new GuiToggleButton(stations_layout, "GAME_MASTER_BUTTON", "Game master", [this](bool value) { window_button->setValue(false); topdown_button->setValue(false); cinematic_view_button->setValue(false); }); game_master_button->setSize(GuiElement::GuiSizeMax, 50); // Ship window button and angle slider window_button_row = new GuiAutoLayout(stations_layout, "", GuiAutoLayout::LayoutHorizontalLeftToRight); window_button_row->setSize(GuiElement::GuiSizeMax, 50); window_button = new GuiToggleButton(window_button_row, "WINDOW_BUTTON", "Ship window", [this](bool value) { game_master_button->setValue(false); topdown_button->setValue(false); cinematic_view_button->setValue(false); }); window_button->setSize(175, 50); window_angle = new GuiSlider(window_button_row, "WINDOW_ANGLE", 0.0, 359.0, 0.0, [this](float value) { window_angle_label->setText(string(int(window_angle->getValue())) + " degrees"); }); window_angle->setSize(GuiElement::GuiSizeMax, 50); window_angle_label = new GuiLabel(window_angle, "WINDOW_ANGLE_LABEL", "0 degrees", 30); window_angle_label->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); // Top-down view button topdown_button = new GuiToggleButton(stations_layout, "TOP_DOWN_3D_BUTTON", "Top-down 3D view", [this](bool value) { game_master_button->setValue(false); window_button->setValue(false); cinematic_view_button->setValue(false); }); topdown_button->setSize(GuiElement::GuiSizeMax, 50); // Cinematic view button cinematic_view_button = new GuiToggleButton(stations_layout, "CINEMATIC_VIEW_BUTTON", "Cinematic view", [this](bool value) { game_master_button->setValue(false); window_button->setValue(false); topdown_button->setValue(false); }); cinematic_view_button->setSize(GuiElement::GuiSizeMax, 50); // If this is the server, add a panel to create player ships. if (game_server) { (new GuiPanel(left_container, "CREATE_SHIP_BOX"))->setPosition(0, 50, ATopCenter)->setSize(550, 700); } // Player ship selection panel (new GuiPanel(left_container, "SHIP_SELECTION_BOX"))->setPosition(0, 50, ATopCenter)->setSize(550, 560); (new GuiLabel(left_container, "SHIP_SELECTION_LABEL", "Select ship", 30))->addBackground()->setPosition(0, 50, ATopCenter)->setSize(510, 50); no_ships_label = new GuiLabel(left_container, "SHIP_SELECTION_NO_SHIPS_LABEL", "Waiting for server to spawn a ship", 30); no_ships_label->setPosition(0, 100, ATopCenter)->setSize(460, 50); // Player ship list player_ship_list = new GuiListbox(left_container, "PLAYER_SHIP_LIST", [this](int index, string value) { P<PlayerSpaceship> ship = gameGlobalInfo->getPlayerShip(value.toInt()); // If the selected item is a ship ... if (ship) { // ... and it has a control code, ask the player for it. if (ship->control_code.length() > 0) { LOG(INFO) << "Player selected " << ship->getCallSign() << ", which has a control code."; // Hide the ship selection UI temporarily to deter sneaky ship thieves. left_container->hide(); right_container->hide(); // Show the control code entry dialog. password_overlay->show(); } // Otherwise, select and set this ship ID in the player info. else { my_player_info->commandSetShipId(ship->getMultiplayerId()); } // If the selected item isn't a ship, reset the ship ID in player info. }else{ my_player_info->commandSetShipId(-1); } }); player_ship_list->setPosition(0, 100, ATopCenter)->setSize(490, 500); // If this is the server, add buttons and a selector to create player ships. if (game_server) { GuiSelector* ship_template_selector = new GuiSelector(left_container, "CREATE_SHIP_SELECTOR", nullptr); // List only ships with templates designated for player use. std::vector<string> template_names = ShipTemplate::getTemplateNameList(ShipTemplate::PlayerShip); std::sort(template_names.begin(), template_names.end()); for(string& template_name : template_names) { P<ShipTemplate> ship_template = ShipTemplate::getTemplate(template_name); ship_template_selector->addEntry(template_name + " (" + ship_template->getClass() + ":" + ship_template->getSubClass() + ")", template_name); } ship_template_selector->setSelectionIndex(0); ship_template_selector->setPosition(0, 630, ATopCenter)->setSize(490, 50); // Spawn a ship of the selected template near 0,0 and give it a random // heading. (new GuiButton(left_container, "CREATE_SHIP_BUTTON", "Spawn player ship", [this, ship_template_selector]() { P<PlayerSpaceship> ship = new PlayerSpaceship(); if (ship) { ship->setTemplate(ship_template_selector->getSelectionValue()); ship->setRotation(random(0, 360)); ship->target_rotation = ship->getRotation(); ship->setPosition(sf::Vector2f(random(-100, 100), random(-100, 100))); my_player_info->commandSetShipId(ship->getMultiplayerId()); } }))->setPosition(0, 680, ATopCenter)->setSize(490, 50); // If this is the server, the "back" button goes to the scenario // selection/server creation screen. (new GuiButton(left_container, "DISCONNECT", "Scenario selection", [this]() { destroy(); new ServerCreationScreen(); }))->setPosition(0, -50, ABottomCenter)->setSize(300, 50); }else{ // If this is a client, the "back" button disconnects from the server // and returns to the main menu. (new GuiButton(left_container, "DISCONNECT", "Disconnect", [this]() { destroy(); disconnectFromServer(); returnToMainMenu(); }))->setPosition(0, -50, ABottomCenter)->setSize(300, 50); } // The "Ready" button. ready_button = new GuiButton(right_container, "READY_BUTTON", "Ready", [this]() { this->onReadyClick(); }); ready_button->setPosition(0, -50, ABottomCenter)->setSize(300, 50); // Set the crew type selector's default to 6/5 person crew screens. crew_type_selector->setSelectionIndex(0); updateCrewTypeOptions(); // Control code entry dialog. password_overlay = new GuiOverlay(this, "PASSWORD_OVERLAY", sf::Color::Black - sf::Color(0, 0, 0, 192)); password_overlay->hide(); password_entry_box = new GuiPanel(password_overlay, "PASSWORD_ENTRY_BOX"); password_entry_box->setPosition(0, 350, ATopCenter)->setSize(600, 200); password_label = new GuiLabel(password_entry_box, "PASSWORD_LABEL", "Enter this ship's control code:", 30); password_label->setPosition(0, 40, ATopCenter); password_entry = new GuiTextEntry(password_entry_box, "PASSWORD_ENTRY", ""); password_entry->setPosition(20, 0, ACenterLeft)->setSize(400, 50); password_cancel = new GuiButton(password_entry_box, "PASSWORD_CANCEL_BUTTON", "Cancel", [this]() { // Reset the dialog. password_label->setText("Enter this ship's control code:"); password_entry->setText(""); // Hide the password overlay and show the ship selection screen. password_overlay->hide(); left_container->show(); right_container->show(); // Unselect player ship if cancelling. player_ship_list->setSelectionIndex(-1); my_player_info->commandSetShipId(-1); }); password_cancel->setPosition(0, -20, ABottomCenter)->setSize(300, 50); // Control code entry button. password_entry_ok = new GuiButton(password_entry_box, "PASSWORD_ENTRY_OK", "Ok", [this]() { P<PlayerSpaceship> ship = gameGlobalInfo->getPlayerShip(player_ship_list->getEntryValue(player_ship_list->getSelectionIndex()).toInt()); if (ship) { // Get the password. string password = password_entry->getText(); string control_code = ship->control_code; if (password != control_code) { // Password doesn't match. Unset the player ship selection. LOG(INFO) << "Password doesn't match control code. Attempt: " << password; my_player_info->commandSetShipId(-1); // Notify the player. password_label->setText("Incorrect control code. Re-enter code for " + ship->getCallSign() + ":"); // Reset the dialog. password_entry->setText(""); } else { // Password matches. LOG(INFO) << "Password matches control code."; // Set the player ship. my_player_info->commandSetShipId(ship->getMultiplayerId()); // Notify the player. password_label->setText("Control code accepted.\nGranting access to " + ship->getCallSign() + "."); // Reset and hide the password field. password_entry->setText(""); password_entry->hide(); password_cancel->hide(); password_entry_ok->hide(); // Show a confirmation button. password_confirmation->show(); } } }); password_entry_ok->setPosition(420, 0, ACenterLeft)->setSize(160, 50); // Control code confirmation button password_confirmation = new GuiButton(password_entry_box, "PASSWORD_CONFIRMATION_BUTTON", "OK", [this]() { // Reset the dialog. password_entry->show(); password_cancel->show(); password_entry_ok->show(); password_label->setText("Enter this ship's control code:")->setPosition(0, 40, ATopCenter); password_confirmation->hide(); // Hide the dialog. password_overlay->hide(); // Show the UI. left_container->show(); right_container->show(); }); password_confirmation->setPosition(0, -20, ABottomCenter)->setSize(250, 50)->hide(); }