void ShipSelectionScreen::update(float delta) { if (game_client && game_client->getStatus() == GameClient::Disconnected) { destroy(); disconnectFromServer(); returnToMainMenu(); return; } for(int n=0; n<GameGlobalInfo::max_player_ships; n++) { P<PlayerSpaceship> ship = gameGlobalInfo->getPlayerShip(n); if (ship) { if (player_ship_list->indexByValue(string(n)) == -1) { int index = player_ship_list->addEntry(ship->ship_type_name + " " + ship->getCallSign(), string(n)); if (my_spaceship == ship) player_ship_list->setSelectionIndex(index); } }else{ if (player_ship_list->indexByValue(string(n)) != -1) player_ship_list->removeEntry(player_ship_list->indexByValue(string(n))); } } if (player_ship_list->entryCount() > 0) { no_ships_label->hide(); }else{ no_ships_label->show(); } }
void TutorialGame::finish() { script->destroy(); destroy(); disconnectFromServer(); returnToMainMenu(); }
void CrewStationScreen::update(float delta) { if (game_client && game_client->getStatus() == GameClient::Disconnected) { destroy(); disconnectFromServer(); returnToMainMenu(); return; } }
void TopDownScreen::update(float delta) { // If this is a client and it is disconnected, exit. if (game_client && game_client->getStatus() == GameClient::Disconnected) { destroy(); disconnectFromServer(); returnToMainMenu(); return; } // Enable mouse wheel zoom. float mouse_wheel_delta = InputHandler::getMouseWheelDelta(); if (mouse_wheel_delta != 0.0) { camera_position.z = camera_position.z * (1.0 - (mouse_wheel_delta) * 0.1f); if (camera_position.z > 10000) camera_position.z = 10000; if (camera_position.z < 1000) camera_position.z = 1000; } // Add and remove entries from the player ship list. for(int n=0; n<GameGlobalInfo::max_player_ships; n++) { P<PlayerSpaceship> ship = gameGlobalInfo->getPlayerShip(n); if (ship) { if (camera_lock_selector->indexByValue(string(n)) == -1) camera_lock_selector->addEntry(ship->getTypeName() + " " + ship->getCallSign(), string(n)); }else{ if (camera_lock_selector->indexByValue(string(n)) != -1) camera_lock_selector->removeEntry(camera_lock_selector->indexByValue(string(n))); } } // Enforce a top-down view with up pointing toward heading 0. camera_yaw = -90.0f; camera_pitch = 90.0f; // If locked onto a player ship, move the camera along with it. if (camera_lock_toggle->getValue() && target) { sf::Vector2f target_position = target->getPosition(); camera_position.x = target_position.x; camera_position.y = target_position.y; } }
void WindowScreen::update(float delta) { if (game_client && game_client->getStatus() == GameClient::Disconnected) { destroy(); disconnectFromServer(); returnToMainMenu(); return; } if (my_spaceship) { camera_yaw = my_spaceship->getRotation() + angle; camera_pitch = 0.0f; sf::Vector2f position = my_spaceship->getPosition() + sf::rotateVector(sf::Vector2f(my_spaceship->getRadius(), 0), camera_yaw); camera_position.x = position.x; camera_position.y = position.y; camera_position.z = 0.0; } }
ServerBrowserMenu::ServerBrowserMenu(SearchSource source) { scanner = new ServerScanner(VERSION_NUMBER); if (source == Local) scanner->scanLocalNetwork(); else scanner->scanMasterServer("http://daid.eu/ee/list.php"); (new GuiButton(this, "BACK", "Back", [this]() { destroy(); returnToMainMenu(); }))->setPosition(50, -50, ABottomLeft)->setSize(300, 50); connect_button = new GuiButton(this, "CONNECT", "Connect", [this]() { new JoinServerScreen(sf::IpAddress(manual_ip->getText())); destroy(); }); connect_button->setPosition(-50, -50, ABottomRight)->setSize(300, 50); manual_ip = new GuiTextEntry(this, "IP", ""); manual_ip->setPosition(-50, -120, ABottomRight)->setSize(300, 50); server_list = new GuiListbox(this, "SERVERS", [this](int index, string value) { manual_ip->setText(value); }); scanner->addCallbacks([this](sf::IpAddress address, string name) { //New server found server_list->addEntry(name + " (" + address.toString() + ")", address.toString()); if (manual_ip->getText() == "") manual_ip->setText(address.toString()); }, [this](sf::IpAddress address) { //Server removed from list server_list->removeEntry(server_list->indexByValue(address.toString())); }); server_list->setPosition(0, 50, ATopCenter)->setSize(700, 600); }
int main(int argc, char** argv) { #ifdef __APPLE__ // TODO: Find a proper solution. // Seems to be non-NULL even outside of a proper bundle. CFBundleRef bundle = CFBundleGetMainBundle(); if (bundle) { char bundle_path[PATH_MAX], exe_path[PATH_MAX]; CFURLRef bundleURL = CFBundleCopyBundleURL(bundle); CFURLGetFileSystemRepresentation(bundleURL, true, (unsigned char*)bundle_path, PATH_MAX); CFRelease(bundleURL); uint32_t size = sizeof(exe_path); if (_NSGetExecutablePath(exe_path, &size) != 0) { fprintf(stderr, "Failed to get executable path.\n"); return 1; } char *exe_realpath = realpath(exe_path, NULL); char *exe_dir = dirname(exe_realpath); if (strcmp(exe_dir, bundle_path)) { char resources_path[PATH_MAX]; CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle); CFURLGetFileSystemRepresentation(resourcesURL, true, (unsigned char*)resources_path, PATH_MAX); CFRelease(resourcesURL); chdir(resources_path); } else { chdir(exe_dir); } free(exe_realpath); free(exe_dir); } #endif #ifdef DEBUG Logging::setLogLevel(LOGLEVEL_DEBUG); #else Logging::setLogLevel(LOGLEVEL_INFO); #endif #if defined(__WIN32__) && !defined(DEBUG) Logging::setLogFile("EmptyEpsilon.log"); #endif #ifdef RESOURCE_BASE_DIR PreferencesManager::load(RESOURCE_BASE_DIR "options.ini"); #endif if (getenv("HOME")) PreferencesManager::load(string(getenv("HOME")) + "/.emptyepsilon/options.ini"); else PreferencesManager::load("options.ini"); for(int n=1; n<argc; n++) { char* value = strchr(argv[n], '='); if (!value) continue; *value++ = '\0'; PreferencesManager::set(string(argv[n]).strip(), string(value).strip()); } new Engine(); if (PreferencesManager::get("mod") != "") { string mod = PreferencesManager::get("mod"); if (getenv("HOME")) { new DirectoryResourceProvider(string(getenv("HOME")) + "/.emptyepsilon/resources/mods/" + mod); PackResourceProvider::addPackResourcesForDirectory(string(getenv("HOME")) + "/.emptyepsilon/resources/mods/" + mod); } new DirectoryResourceProvider("resources/mods/" + mod); PackResourceProvider::addPackResourcesForDirectory("resources/mods/" + mod); } #ifdef RESOURCE_BASE_DIR new DirectoryResourceProvider(RESOURCE_BASE_DIR "resources/"); new DirectoryResourceProvider(RESOURCE_BASE_DIR "scripts/"); new DirectoryResourceProvider(RESOURCE_BASE_DIR "packs/SolCommand/"); PackResourceProvider::addPackResourcesForDirectory(RESOURCE_BASE_DIR "packs"); #endif if (getenv("HOME")) { new DirectoryResourceProvider(string(getenv("HOME")) + "/.emptyepsilon/resources/"); new DirectoryResourceProvider(string(getenv("HOME")) + "/.emptyepsilon/scripts/"); new DirectoryResourceProvider(string(getenv("HOME")) + "/.emptyepsilon/packs/SolCommand/"); } new DirectoryResourceProvider("resources/"); new DirectoryResourceProvider("scripts/"); new DirectoryResourceProvider("packs/SolCommand/"); PackResourceProvider::addPackResourcesForDirectory("packs"); textureManager.setDefaultSmooth(true); textureManager.setDefaultRepeated(true); textureManager.setAutoSprite(false); textureManager.getTexture("Tokka_WalkingMan.png", sf::Vector2i(6, 1)); //Setup the sprite mapping. if (PreferencesManager::get("httpserver").toInt() != 0) { int port_nr = PreferencesManager::get("httpserver").toInt(); if (port_nr < 10) port_nr = 80; LOG(INFO) << "Enabling HTTP script access on port: " << port_nr; LOG(INFO) << "NOTE: This is potentially a risk!"; HttpServer* server = new HttpServer(port_nr); server->addHandler(new HttpRequestFileHandler("www")); server->addHandler(new HttpScriptHandler()); } colorConfig.load(); if (PreferencesManager::get("headless") == "") { //Setup the rendering layers. backgroundLayer = new RenderLayer(); objectLayer = new RenderLayer(backgroundLayer); effectLayer = new RenderLayer(objectLayer); hudLayer = new RenderLayer(effectLayer); mouseLayer = new RenderLayer(hudLayer); glitchPostProcessor = new PostProcessor("glitch", mouseLayer); glitchPostProcessor->enabled = false; warpPostProcessor = new PostProcessor("warp", glitchPostProcessor); warpPostProcessor->enabled = false; defaultRenderLayer = objectLayer; int width = 1200; int height = 900; int fsaa = 0; bool fullscreen = PreferencesManager::get("fullscreen", "1").toInt(); if (PreferencesManager::get("fsaa").toInt() > 0) { fsaa = PreferencesManager::get("fsaa").toInt(); if (fsaa < 2) fsaa = 2; } P<WindowManager> window_manager = new WindowManager(width, height, fullscreen, warpPostProcessor, fsaa); window_manager->setAllowVirtualResize(true); engine->registerObject("windowManager", window_manager); } if (PreferencesManager::get("touchscreen").toInt()) { InputHandler::touch_screen = true; } if (!InputHandler::touch_screen) { engine->registerObject("mouseRenderer", new MouseRenderer()); } new DebugRenderer(); if (PreferencesManager::get("touchcalibfile") != "") { FILE* f = fopen(PreferencesManager::get("touchcalibfile").c_str(), "r"); if (f) { float m[6]; if (fscanf(f, "%f %f %f %f %f %f", &m[0], &m[1], &m[2], &m[3], &m[4], &m[5]) == 6) InputHandler::mouse_transform = sf::Transform(m[0], m[1], m[2], m[3], m[4], m[5], 0, 0, 1); fclose(f); } } soundManager->setMusicVolume(PreferencesManager::get("music_volume", "50").toFloat()); if (PreferencesManager::get("disable_shaders").toInt()) PostProcessor::setEnable(false); P<ResourceStream> main_font_stream = getResourceStream("gui/fonts/BebasNeue Regular.otf"); main_font = new sf::Font(); main_font->loadFromStream(**main_font_stream); P<ResourceStream> bold_font_stream = getResourceStream("gui/fonts/BebasNeue Bold.otf"); bold_font = new sf::Font(); bold_font->loadFromStream(**bold_font_stream); if (sf::Shader::isAvailable()) { objectShader = new sf::Shader(); simpleObjectShader = new sf::Shader(); basicShader = new sf::Shader(); billboardShader = new sf::Shader(); P<ResourceStream> vertexStream = getResourceStream("objectShader.vert"); P<ResourceStream> fragmentStream = getResourceStream("objectShader.frag"); objectShader->loadFromStream(**vertexStream, **fragmentStream); vertexStream = getResourceStream("simpleObjectShader.vert"); fragmentStream = getResourceStream("simpleObjectShader.frag"); simpleObjectShader->loadFromStream(**vertexStream, **fragmentStream); vertexStream = getResourceStream("basicShader.vert"); fragmentStream = getResourceStream("basicShader.frag"); basicShader->loadFromStream(**vertexStream, **fragmentStream); vertexStream = getResourceStream("billboardShader.vert"); fragmentStream = getResourceStream("billboardShader.frag"); billboardShader->loadFromStream(**vertexStream, **fragmentStream); } { P<ScriptObject> modelDataScript = new ScriptObject("model_data.lua"); if (modelDataScript->getError() != "") exit(1); modelDataScript->destroy(); P<ScriptObject> shipTemplatesScript = new ScriptObject("shipTemplates.lua"); if (shipTemplatesScript->getError() != "") exit(1); shipTemplatesScript->destroy(); P<ScriptObject> factionInfoScript = new ScriptObject("factionInfo.lua"); if (factionInfoScript->getError() != "") exit(1); factionInfoScript->destroy(); fillDefaultDatabaseData(); P<ScriptObject> scienceInfoScript = new ScriptObject("science_db.lua"); if (scienceInfoScript->getError() != "") exit(1); scienceInfoScript->destroy(); //Find out which model data isn't used by ship templates and output that to log. std::set<string> used_model_data; for(string template_name : ShipTemplate::getAllTemplateNames()) used_model_data.insert(ShipTemplate::getTemplate(template_name)->model_data->getName()); for(string name : ModelData::getModelDataNames()) { if (used_model_data.find(name) == used_model_data.end()) { LOG(INFO) << "Model data: " << name << " is not used by any ship template"; } } } P<HardwareController> hardware_controller = new HardwareController(); #ifdef RESOURCE_BASE_DIR hardware_controller->loadConfiguration(RESOURCE_BASE_DIR "hardware.ini"); #endif if (getenv("HOME")) hardware_controller->loadConfiguration(string(getenv("HOME")) + "/.emptyepsilon/hardware.ini"); else hardware_controller->loadConfiguration("hardware.ini"); returnToMainMenu(); engine->runMainLoop(); P<WindowManager> windowManager = engine->getObject("windowManager"); if (windowManager) { PreferencesManager::set("fsaa", windowManager->getFSAA()); PreferencesManager::set("fullscreen", windowManager->isFullscreen() ? 1 : 0); } PreferencesManager::set("music_volume", soundManager->getMusicVolume()); PreferencesManager::set("disable_shaders", PostProcessor::isEnabled() ? 0 : 1); if (PreferencesManager::get("headless") == "") { #ifndef _MSC_VER // MFC TODO: Fix me -- save prefs to user prefs dir on Windows. if (getenv("HOME")) { #ifdef __WIN32__ mkdir((string(getenv("HOME")) + "/.emptyepsilon").c_str()); #else mkdir((string(getenv("HOME")) + "/.emptyepsilon").c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); #endif PreferencesManager::save(string(getenv("HOME")) + "/.emptyepsilon/options.ini"); }else #endif { PreferencesManager::save("options.ini"); } } delete engine; return 0; }
ServerCreationScreen::ServerCreationScreen() { assert(game_server); new GuiOverlay(this, "", colorConfig.background); (new GuiOverlay(this, "", sf::Color::White))->setTextureTiled("gui/BackgroundCrosses"); // Set defaults from preferences. gameGlobalInfo->player_warp_jump_drive_setting = EPlayerWarpJumpDrive(PreferencesManager::get("server_config_warp_jump_drive_setting", "0").toInt()); gameGlobalInfo->long_range_radar_range = PreferencesManager::get("server_config_long_range_radar_range", "30000").toInt(); gameGlobalInfo->scanning_complexity = EScanningComplexity(PreferencesManager::get("server_config_scanning_complexity", "2").toInt()); gameGlobalInfo->use_beam_shield_frequencies = PreferencesManager::get("server_config_use_beam_shield_frequencies", "1").toInt(); gameGlobalInfo->use_system_damage = PreferencesManager::get("server_config_use_system_damage", "1").toInt(); gameGlobalInfo->allow_main_screen_tactical_radar = PreferencesManager::get("server_config_allow_main_screen_tactical_radar", "1").toInt(); gameGlobalInfo->allow_main_screen_long_range_radar = PreferencesManager::get("server_config_allow_main_screen_long_range_radar", "1").toInt(); // Create a two-column layout. GuiElement* container = new GuiAutoLayout(this, "", GuiAutoLayout::ELayoutMode::LayoutVerticalColumns); container->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); GuiElement* left_container = new GuiElement(container, ""); GuiElement* right_container = new GuiElement(container, ""); GuiElement* left_panel = new GuiAutoLayout(left_container, "", GuiAutoLayout::LayoutVerticalTopToBottom); left_panel->setPosition(0, 20, ATopCenter)->setSize(550, GuiElement::GuiSizeMax); GuiElement* right_panel = new GuiAutoLayout(right_container, "", GuiAutoLayout::LayoutVerticalTopToBottom); right_panel->setPosition(0, 20, ATopCenter)->setSize(550, GuiElement::GuiSizeMax); // Left column contents. // General section. (new GuiLabel(left_panel, "GENERAL_LABEL", "Server configuration", 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50); // Server name row. GuiElement* row = new GuiAutoLayout(left_panel, "", GuiAutoLayout::LayoutHorizontalLeftToRight); row->setSize(GuiElement::GuiSizeMax, 50); (new GuiLabel(row, "NAME_LABEL", "Server name: ", 30))->setAlignment(ACenterRight)->setSize(250, GuiElement::GuiSizeMax); (new GuiTextEntry(row, "SERVER_NAME", game_server->getServerName()))->callback([](string text){game_server->setServerName(text);})->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); // Server password row. row = new GuiAutoLayout(left_panel, "", GuiAutoLayout::LayoutHorizontalLeftToRight); row->setSize(GuiElement::GuiSizeMax, 50); (new GuiLabel(row, "PASSWORD_LABEL", "Server password: "******"SERVER_PASSWORD", ""))->callback([](string text){game_server->setPassword(text);})->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); // Server IP row. row = new GuiAutoLayout(left_panel, "", GuiAutoLayout::LayoutHorizontalLeftToRight); row->setSize(GuiElement::GuiSizeMax, 50); (new GuiLabel(row, "IP_LABEL", "Server IP: ", 30))->setAlignment(ACenterRight)->setSize(250, GuiElement::GuiSizeMax); (new GuiLabel(row, "IP", sf::IpAddress::getLocalAddress().toString(), 30))->setAlignment(ACenterLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); // LAN/Internet row. row = new GuiAutoLayout(left_panel, "", GuiAutoLayout::LayoutHorizontalLeftToRight); row->setSize(GuiElement::GuiSizeMax, 50); (new GuiLabel(row, "LAN_INTERNET_LABEL", "Server visibility: ", 30))->setAlignment(ACenterRight)->setSize(250, GuiElement::GuiSizeMax); (new GuiSelector(row, "LAN_INTERNET_SELECT", [](int index, string value) { if (index == 1) game_server->registerOnMasterServer("http://daid.eu/ee/register.php"); else game_server->stopMasterServerRegistry(); }))->setOptions({"LAN only", "Internet"})->setSelectionIndex(0)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); // Player Ships section. (new GuiLabel(left_panel, "PLAYER_SHIP_LABEL", "Player ship options", 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50); // Warp/Jump drive row. row = new GuiAutoLayout(left_panel, "", GuiAutoLayout::LayoutHorizontalLeftToRight); row->setSize(GuiElement::GuiSizeMax, 50); (new GuiLabel(row, "WARP_JUMP_LABEL", "Warp/Jump: ", 30))->setAlignment(ACenterRight)->setSize(250, GuiElement::GuiSizeMax); (new GuiSelector(row, "WARP_JUMP_SELECT", [](int index, string value) { gameGlobalInfo->player_warp_jump_drive_setting = EPlayerWarpJumpDrive(index); }))->setOptions({"Ship default", "Warp drive", "Jump drive", "Both", "Neither"})->setSelectionIndex((int)gameGlobalInfo->player_warp_jump_drive_setting)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); // Radar range limit row. row = new GuiAutoLayout(left_panel, "", GuiAutoLayout::LayoutHorizontalLeftToRight); row->setSize(GuiElement::GuiSizeMax, 50); (new GuiLabel(row, "RADAR_LABEL", "Radar range: ", 30))->setAlignment(ACenterRight)->setSize(250, GuiElement::GuiSizeMax); (new GuiSelector(row, "RADAR_SELECT", [](int index, string value) { gameGlobalInfo->long_range_radar_range = index * 5000 + 10000; }))->setOptions({"10U", "15U", "20U", "25U", "30U", "35U", "40U", "45U", "50U"})->setSelectionIndex((gameGlobalInfo->long_range_radar_range - 10000.0) / 5000.0)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); // Main screen section. (new GuiLabel(left_panel, "MAIN_SCREEN_LABEL", "Main screen options", 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50); // Radar row. row = new GuiAutoLayout(left_panel, "", GuiAutoLayout::LayoutHorizontalLeftToRight); row->setSize(GuiElement::GuiSizeMax, 50); (new GuiToggleButton(row, "MAIN_TACTICAL_TOGGLE", "Tactical radar", [](bool value) { gameGlobalInfo->allow_main_screen_tactical_radar = value == 1; }))->setValue(gameGlobalInfo->allow_main_screen_tactical_radar)->setSize(275, GuiElement::GuiSizeMax)->setPosition(0, 0, ACenterLeft); (new GuiToggleButton(row, "MAIN_LONG_RANGE_TOGGLE", "Long range radar", [](bool value) { gameGlobalInfo->allow_main_screen_long_range_radar = value == 1; }))->setValue(gameGlobalInfo->allow_main_screen_long_range_radar)->setSize(275, GuiElement::GuiSizeMax)->setPosition(0, 0, ACenterRight); // Game rules section. (new GuiLabel(left_panel, "GAME_RULES_LABEL", "Game rules", 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50); // Science scan complexity selector. row = new GuiAutoLayout(left_panel, "", GuiAutoLayout::LayoutHorizontalLeftToRight); row->setSize(GuiElement::GuiSizeMax, 50); (new GuiLabel(row, "GAME_SCANNING_COMPLEXITY_LABEL", "Scan complexity: ", 30))->setAlignment(ACenterRight)->setSize(250, GuiElement::GuiSizeMax); (new GuiSelector(row, "GAME_SCANNING_COMPLEXITY", [](int index, string value) { gameGlobalInfo->scanning_complexity = EScanningComplexity(index); }))->setOptions({"None (delay)", "Simple", "Normal", "Advanced"})->setSelectionIndex((int)gameGlobalInfo->scanning_complexity)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); // Frequency and system damage row. row = new GuiAutoLayout(left_panel, "", GuiAutoLayout::LayoutHorizontalLeftToRight); row->setSize(GuiElement::GuiSizeMax, 50); (new GuiToggleButton(row, "GAME_FREQUENCIES_TOGGLE", "Beam/shield frequencies", [](bool value) { gameGlobalInfo->use_beam_shield_frequencies = value == 1; }))->setValue(gameGlobalInfo->use_beam_shield_frequencies)->setSize(275, GuiElement::GuiSizeMax)->setPosition(0, 0, ACenterLeft); (new GuiToggleButton(row, "GAME_SYS_DAMAGE_TOGGLE", "Per-system damage", [](bool value) { gameGlobalInfo->use_system_damage = value == 1; }))->setValue(gameGlobalInfo->use_system_damage)->setSize(275, GuiElement::GuiSizeMax)->setPosition(0, 0, ACenterRight); // Right column contents. // Scenario section. (new GuiLabel(right_panel, "SCENARIO_LABEL", "Scenario", 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50); // List each scenario derived from scenario_*.lua files in Resources. GuiListbox* scenario_list = new GuiListbox(right_panel, "SCENARIO_LIST", [this](int index, string value) { selectScenario(value); }); scenario_list->setSize(GuiElement::GuiSizeMax, 300); // Show the scenario description text. GuiPanel* panel = new GuiPanel(right_panel, "SCENARIO_DESCRIPTION_BOX"); panel->setSize(GuiElement::GuiSizeMax, 200); scenario_description = new GuiScrollText(panel, "SCENARIO_DESCRIPTION", ""); scenario_description->setTextSize(24)->setMargins(15)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); // If the scenario has variations, show and select from them. variation_container = new GuiAutoLayout(right_panel, "VARIATION_CONTAINER", GuiAutoLayout::LayoutVerticalTopToBottom); variation_container->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); row = new GuiAutoLayout(variation_container, "", GuiAutoLayout::LayoutHorizontalLeftToRight); row->setSize(GuiElement::GuiSizeMax, 50); (new GuiLabel(row, "VARIATION_LABEL", "Variation: ", 30))->setAlignment(ACenterRight)->setSize(250, GuiElement::GuiSizeMax); variation_selection = new GuiSelector(row, "VARIATION_SELECT", [this](int index, string value) { gameGlobalInfo->variation = variation_names_list.at(index); variation_description->setText(variation_descriptions_list.at(index)); }); variation_selection->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); panel = new GuiPanel(variation_container, "VARIATION_DESCRIPTION_BOX"); panel->setSize(GuiElement::GuiSizeMax, 150); variation_description = new GuiScrollText(panel, "VARIATION_DESCRIPTION", ""); variation_description->setTextSize(24)->setMargins(15)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); // Buttons beneath the columns. // Close server button. (new GuiButton(left_container, "CLOSE_SERVER", "Close server", [this]() { destroy(); disconnectFromServer(); returnToMainMenu(); }))->setPosition(0, -50, ABottomCenter)->setSize(300, 50); // Start server button. (new GuiButton(right_container, "START_SERVER", "Start scenario", [this]() { startScenario(); }))->setPosition(0, -50, ABottomCenter)->setSize(300, 50); // Fetch and sort all Lua files starting with "scenario_". std::vector<string> scenario_filenames = findResources("scenario_*.lua"); std::sort(scenario_filenames.begin(), scenario_filenames.end()); // For each scenario file, extract its name, then add it to the list. for(string filename : scenario_filenames) { ScenarioInfo info(filename); scenario_list->addEntry(info.name, filename); } // Select the first scenario in the list by default. scenario_list->setSelectionIndex(0); selectScenario(scenario_list->getSelectionValue()); gameGlobalInfo->reset(); }
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(); }
void ShipSelectionScreen::update(float delta) { // If this is a client and is disconnected from the server, destroy the // screen and return to the main menu. if (game_client && game_client->getStatus() == GameClient::Disconnected) { destroy(); disconnectFromServer(); returnToMainMenu(); return; } // Update the player ship list with all player ships. for(int n = 0; n < GameGlobalInfo::max_player_ships; n++) { P<PlayerSpaceship> ship = gameGlobalInfo->getPlayerShip(n); if (ship) { string ship_name = ship->getFaction() + " " + ship->getTypeName() + " " + ship->getCallSign(); // If a player ship isn't in already in the list, add it. if (player_ship_list->indexByValue(string(n)) == -1) { int index = player_ship_list->addEntry(ship_name, string(n)); if (my_spaceship == ship) player_ship_list->setSelectionIndex(index); } // If the ship is crewed, count how many positions are filled. int ship_position_count = 0; for (int n = 0; n < max_crew_positions; n++) { if (ship->hasPlayerAtPosition(ECrewPosition(n))) ship_position_count += 1; } player_ship_list->setEntryName(n, ship_name + " (" + string(ship_position_count) + ")"); }else{ if (player_ship_list->indexByValue(string(n)) != -1) player_ship_list->removeEntry(player_ship_list->indexByValue(string(n))); } } // If a position already has a player on the currently selected player ship, // indicate that on the button. for(int n = 0; n < max_crew_positions; n++) { string button_text = getCrewPositionName(ECrewPosition(n)); if (my_spaceship) { if (my_spaceship->hasPlayerAtPosition(ECrewPosition(n))) { crew_position_button[n]->setText(button_text + " (occupied)"); } else { crew_position_button[n]->setText(button_text); } } } // If there aren't any player ships, show a label stating so. if (player_ship_list->entryCount() > 0) { no_ships_label->hide(); }else{ no_ships_label->show(); } // Update the Ready button's state, which might have changed based on the // presence or absence of player ships. updateReadyButton(); }
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(); }