// Get a string to show if this mission is "blocked" from being offered // because it requires you to have more passenger or cargo space free. After // calling this function, any future calls to it will return an empty string // so that you do not display the same message multiple times. string Mission::BlockedMessage(const PlayerInfo &player) { if(blocked.empty()) return ""; int extraCrew = 0; if(player.Flagship()) extraCrew = player.Flagship()->Crew() - player.Flagship()->RequiredCrew(); int cargoNeeded = cargoSize - (player.Cargo().Free() + player.Cargo().CommoditiesSize()); int bunksNeeded = passengers - (player.Cargo().Bunks() + extraCrew); if(cargoNeeded < 0 && bunksNeeded < 0) return ""; map<string, string> subs; subs["<first>"] = player.FirstName(); subs["<last>"] = player.LastName(); if(player.Flagship()) subs["<ship>"] = player.Flagship()->Name(); ostringstream out; if(bunksNeeded > 0) out << (bunksNeeded == 1 ? "another bunk" : to_string(bunksNeeded) + " more bunks"); if(bunksNeeded > 0 && cargoNeeded > 0) out << " and "; if(cargoNeeded > 0) out << (cargoNeeded == 1 ? "another ton" : to_string(cargoNeeded) + " more tons") << " of cargo space"; subs["<capacity>"] = out.str(); string message = Format::Replace(blocked, subs); blocked.clear(); return message; }
bool Mission::HasSpace(const PlayerInfo &player) const { int extraCrew = 0; if(player.Flagship()) extraCrew = player.Flagship()->Crew() - player.Flagship()->RequiredCrew(); return (cargoSize <= player.Cargo().Free() + player.Cargo().CommoditiesSize() && passengers <= player.Cargo().Bunks() + extraCrew); }
// Check if this action can be completed right now. It cannot be completed // if it takes away money or outfits that the player does not have. bool MissionAction::CanBeDone(const PlayerInfo &player) const { if(player.Accounts().Credits() < -payment) return false; const Ship *flagship = player.Flagship(); for(const auto &it : gifts) { if(it.second > 0) continue; // The outfit can be taken from the player's cargo or from the flagship. int available = player.Cargo().Get(it.first); for(const auto &ship : player.Ships()) available += ship->Cargo().Get(it.first); if(flagship) available += flagship->OutfitCount(it.first); // If the gift "count" is 0, that means to check that the player has at // least one of these items. if(available < -it.second + !it.second) 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()); }