bool MenuPanel::KeyDown(SDL_Keycode key, Uint16 mod, const Command &command) { if(!isReady) return false; if(player.IsLoaded() && (key == 'e' || command.Has(Command::MENU))) GetUI()->Pop(this); else if(key == 'p') GetUI()->Push(new PreferencesPanel()); else if(key == 'l') GetUI()->Push(new LoadPanel(player, gamePanels)); else if(key == 'n' || key == 'e') { // The "New Pilot" and "Enter Ship" buttons are in the same place. GameData::Revert(); player.New(); ConversationPanel *panel = new ConversationPanel( player, *GameData::Conversations().Get("intro")); GetUI()->Push(panel); panel->SetCallback(this, &MenuPanel::OnCallback); } else if(key == 'q') GetUI()->Quit(); else return false; return true; }
bool LoadPanel::KeyDown(SDL_Keycode key, Uint16 mod, const Command &command) { if(key == 'n') { GameData::Revert(); player.New(); Messages::Reset(); ConversationPanel *panel = new ConversationPanel( player, *GameData::Conversations().Get("intro")); GetUI()->Push(panel); panel->SetCallback(this, &LoadPanel::OnCallback); } else if(key == 'd' && !selectedPilot.empty()) { GetUI()->Push(new Dialog(this, &LoadPanel::DeletePilot, "Are you sure you want to delete the selected pilot, \"" + selectedPilot + "\", and all their saved games?")); } else if(key == 'a') { string wasSelected = selectedPilot; auto it = files.find(selectedPilot); if(it == files.end() || it->second.empty() || it->second.front().size() < 4) return false; GetUI()->Push(new Dialog(this, &LoadPanel::SnapshotCallback, "Enter a name for this snapshot, or leave the name empty to use the current date:")); } else if(key == 'r' && !selectedFile.empty()) { GetUI()->Push(new Dialog(this, &LoadPanel::DeleteSave, "Are you sure you want to delete the selected saved game file, \"" + selectedFile + "\"?")); } else if(key == 'l' || key == 'e') { // Is the selected file a snapshot or the pilot's main file? string fileName = selectedFile.substr(selectedFile.rfind('/') + 1); if(fileName == selectedPilot + ".txt") LoadCallback(); else GetUI()->Push(new Dialog(this, &LoadPanel::LoadCallback, "If you load this snapshot, it will overwrite your current game. " "Any progress will be lost, unless you have saved other snapshots. " "Are you sure you want to do that?")); } else if(key == 'b' || command.Has(Command::MENU) || (key == 'w' && (mod & (KMOD_CTRL | KMOD_GUI)))) GetUI()->Pop(this); else if((key == SDLK_DOWN || key == SDLK_UP) && !files.empty()) { auto pit = files.find(selectedPilot); if(sideHasFocus) { auto it = files.begin(); for( ; it != files.end(); ++it) if(it->first == selectedPilot) break; if(key == SDLK_DOWN) { ++it; if(it == files.end()) it = files.begin(); } else { if(it == files.begin()) it = files.end(); --it; } selectedPilot = it->first; selectedFile = it->second.front(); } else if(pit != files.end()) { auto it = pit->second.begin(); for( ; it != pit->second.end(); ++it) if(*it == selectedFile) break; if(key == SDLK_DOWN) { ++it; if(it == pit->second.end()) it = pit->second.begin(); } else { if(it == pit->second.begin()) it = pit->second.end(); --it; } selectedFile = *it; } loadedInfo.Load(Files::Saves() + selectedFile); } else if(key == SDLK_LEFT) sideHasFocus = true; else if(key == SDLK_RIGHT) sideHasFocus = false; else return false; return true; }
bool LoadPanel::KeyDown(SDL_Keycode key, Uint16 mod, const Command &command) { if(key == 'n') { GameData::Revert(); player.New(); Messages::Reset(); ConversationPanel *panel = new ConversationPanel( player, *GameData::Conversations().Get("intro")); GetUI()->Push(panel); panel->SetCallback(this, &LoadPanel::OnCallback); } else if(key == 'd' && !selectedPilot.empty()) { GetUI()->Push(new Dialog(this, &LoadPanel::DeletePilot, "Are you sure you want to delete the selected pilot, \"" + selectedPilot + "\", and all their saved games?")); } else if(key == 'a') { string wasSelected = selectedPilot; auto it = files.find(selectedPilot); if(it == files.end() || it->second.empty() || it->second.front().size() < 4) return false; // Extract the date from this pilot's most recent save. string date = "~0000-00-00.txt"; string from = Files::Saves() + it->second.front(); DataFile file(from); for(const DataNode &node : file) if(node.Token(0) == "date") { int year = node.Value(3); int month = node.Value(2); int day = node.Value(1); date[1] += (year / 1000) % 10; date[2] += (year / 100) % 10; date[3] += (year / 10) % 10; date[4] += year % 10; date[6] += (month / 10) % 10; date[7] += month % 10; date[9] += (day / 10) % 10; date[10] += day % 10; } // Copy the autosave to a new, named file. string to = from.substr(0, from.size() - 4) + date; Files::Copy(from, to); UpdateLists(); selectedPilot = wasSelected; selectedFile = Files::Name(to); loadedInfo.Load(Files::Saves() + selectedFile); } else if(key == 'r' && !selectedFile.empty()) { GetUI()->Push(new Dialog(this, &LoadPanel::DeleteSave, "Are you sure you want to delete the selected saved game file, \"" + selectedFile + "\"?")); } else if(key == 'e') { // First, make sure the previous MainPanel has been deleted, so // its background thread is no longer running. gamePanels.Reset(); GameData::Revert(); player.Load(loadedInfo.Path()); player.ApplyChanges(); Messages::Reset(); GetUI()->Pop(this); GetUI()->Pop(GetUI()->Root().get()); gamePanels.Push(new MainPanel(player)); } else if(key == 'b' || command.Has(Command::MENU)) GetUI()->Pop(this); else if((key == SDLK_DOWN || key == SDLK_UP) && !files.empty()) { auto pit = files.find(selectedPilot); if(sideHasFocus) { auto it = files.begin(); for( ; it != files.end(); ++it) if(it->first == selectedPilot) break; if(key == SDLK_DOWN) { ++it; if(it == files.end()) it = files.begin(); } else { if(it == files.begin()) it = files.end(); --it; } selectedPilot = it->first; selectedFile = it->second.front(); } else if(pit != files.end()) { auto it = pit->second.begin(); for( ; it != pit->second.end(); ++it) if(*it == selectedFile) break; if(key == SDLK_DOWN) { ++it; if(it == pit->second.end()) it = pit->second.begin(); } else { if(it == pit->second.begin()) it = pit->second.end(); --it; } selectedFile = *it; } loadedInfo.Load(Files::Saves() + selectedFile); } else if(key == SDLK_LEFT) sideHasFocus = true; else if(key == SDLK_RIGHT) sideHasFocus = false; else return false; return true; }
void MissionAction::Do(PlayerInfo &player, UI *ui, const System *destination) const { bool isOffer = (trigger == "offer"); if(!conversation.IsEmpty()) { ConversationPanel *panel = new ConversationPanel(player, conversation, destination); if(isOffer) panel->SetCallback(&player, &PlayerInfo::MissionCallback); ui->Push(panel); } else if(!dialogText.empty()) { map<string, string> subs; subs["<first>"] = player.FirstName(); subs["<last>"] = player.LastName(); if(player.Flagship()) subs["<ship>"] = player.Flagship()->Name(); string text = Format::Replace(dialogText, subs); if(isOffer) ui->Push(new Dialog(text, player, destination)); else ui->Push(new Dialog(text)); } else if(isOffer && ui) player.MissionCallback(Conversation::ACCEPT); Ship *flagship = player.Flagship(); for(const auto &it : gifts) { int count = it.second; string name = it.first->Name(); if(!count || name.empty()) continue; string message; if(abs(count) == 1) { char c = tolower(name.front()); bool isVowel = (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'); message = (isVowel ? "An " : "A ") + name + " was "; } else message = to_string(abs(count)) + " " + name + "s were "; if(count > 0) message += "added to your "; else message += "removed from your "; bool didCargo = false; bool didShip = false; int cargoCount = player.Cargo().Get(it.first); if(count < 0 && cargoCount) { int moved = min(cargoCount, -count); count += moved; player.Cargo().Transfer(it.first, moved); didCargo = true; } while(flagship && count) { int moved = (count > 0) ? 1 : -1; if(flagship->Attributes().CanAdd(*it.first, moved)) { flagship->AddOutfit(it.first, moved); didShip = true; } else break; count -= moved; } if(count > 0) { player.Cargo().Transfer(it.first, -count); didCargo = true; if(count > 0) { string special = "The " + name + (count == 1 ? " was" : "s were"); special += " put in your cargo hold because there is not enough space to install "; special += (count == 1) ? "it" : "them"; special += " in your ship."; ui->Push(new Dialog(special)); } } if(didCargo && didShip) message += "cargo hold and your flagship."; else if(didCargo) message += "cargo hold."; else message += "flagship."; Messages::Add(message); } if(payment) player.Accounts().AddCredits(payment); for(const auto &it : events) player.AddEvent(*GameData::Events().Get(it.first), player.GetDate() + it.second); conditions.Apply(player.Conditions()); }
bool LoadPanel::KeyDown(SDL_Keycode key, Uint16 mod, const Command &command) { if(key == 'n') { GameData::Revert(); player.New(); Messages::Reset(); ConversationPanel *panel = new ConversationPanel( player, *GameData::Conversations().Get("intro")); GetUI()->Push(panel); panel->SetCallback(this, &LoadPanel::OnCallback); } else if(key == 'd' && !selectedPilot.empty()) { GetUI()->Push(new Dialog(this, &LoadPanel::DeletePilot, "Are you sure you want to delete the selected pilot, \"" + selectedPilot + "\", and all their saved games?")); } else if(key == 'a') { string wasSelected = selectedPilot; auto it = files.find(selectedPilot); if(it == files.end() || it->second.empty() || it->second.front().size() < 4) return false; GetUI()->Push(new Dialog(this, &LoadPanel::SnapshotCallback, "Enter a name for this snapshot, or leave the name empty to use the current date:")); } else if(key == 'r' && !selectedFile.empty()) { GetUI()->Push(new Dialog(this, &LoadPanel::DeleteSave, "Are you sure you want to delete the selected saved game file, \"" + selectedFile + "\"?")); } else if(key == 'e') { // First, make sure the previous MainPanel has been deleted, so // its background thread is no longer running. gamePanels.Reset(); GameData::Revert(); player.Load(loadedInfo.Path()); player.ApplyChanges(); Messages::Reset(); GetUI()->Pop(this); GetUI()->Pop(GetUI()->Root().get()); gamePanels.Push(new MainPanel(player)); } else if(key == 'b' || command.Has(Command::MENU) || (key == 'w' && (mod & (KMOD_CTRL | KMOD_GUI)))) GetUI()->Pop(this); else if((key == SDLK_DOWN || key == SDLK_UP) && !files.empty()) { auto pit = files.find(selectedPilot); if(sideHasFocus) { auto it = files.begin(); for( ; it != files.end(); ++it) if(it->first == selectedPilot) break; if(key == SDLK_DOWN) { ++it; if(it == files.end()) it = files.begin(); } else { if(it == files.begin()) it = files.end(); --it; } selectedPilot = it->first; selectedFile = it->second.front(); } else if(pit != files.end()) { auto it = pit->second.begin(); for( ; it != pit->second.end(); ++it) if(*it == selectedFile) break; if(key == SDLK_DOWN) { ++it; if(it == pit->second.end()) it = pit->second.begin(); } else { if(it == pit->second.begin()) it = pit->second.end(); --it; } selectedFile = *it; } loadedInfo.Load(Files::Saves() + selectedFile); } else if(key == SDLK_LEFT) sideHasFocus = true; else if(key == SDLK_RIGHT) sideHasFocus = false; else return false; return true; }
void MissionAction::Do(PlayerInfo &player, UI *ui, const System *destination) const { bool isOffer = (trigger == "offer"); if(!conversation.IsEmpty() && ui) { ConversationPanel *panel = new ConversationPanel(player, conversation, destination); if(isOffer) panel->SetCallback(&player, &PlayerInfo::MissionCallback); ui->Push(panel); } else if(!dialogText.empty() && ui) { map<string, string> subs; subs["<first>"] = player.FirstName(); subs["<last>"] = player.LastName(); if(player.Flagship()) subs["<ship>"] = player.Flagship()->Name(); string text = Format::Replace(dialogText, subs); if(isOffer) ui->Push(new Dialog(text, player, destination)); else ui->Push(new Dialog(text)); } else if(isOffer && ui) player.MissionCallback(Conversation::ACCEPT); // If multiple outfits are being transferred, first remove them before // adding any new ones. for(const auto &it : gifts) if(it.second < 0) DoGift(player, it.first, it.second, ui); for(const auto &it : gifts) if(it.second > 0) DoGift(player, it.first, it.second, ui); if(payment) player.Accounts().AddCredits(payment); for(const auto &it : events) player.AddEvent(*GameData::Events().Get(it.first), player.GetDate() + it.second); if(!fail.empty()) { // Failing missions invalidates iterators into the player's mission list, // but does not immediately delete those missions. So, the safe way to // iterate over all missions is to make a copy of the list before we // begin to remove items from it. vector<const Mission *> failedMissions; for(const Mission &mission : player.Missions()) if(fail.count(mission.Identifier())) failedMissions.push_back(&mission); for(const Mission *mission : failedMissions) player.RemoveMission(Mission::FAIL, *mission, ui); } // Check if applying the conditions changes the player's reputations. player.SetReputationConditions(); conditions.Apply(player.Conditions()); player.CheckReputationConditions(); }