// Get the value of a ship, along with all its outfits. int64_t Depreciation::Value(const Ship &ship, int day) const { int64_t value = Value(&ship, day); for(const auto &it : ship.Outfits()) value += Value(it.first, day, it.second); return value; }
// Add a ship, and all its outfits, to the depreciation record. void Depreciation::Buy(const Ship &ship, int day, Depreciation *source) { // First, add records for all outfits the ship is carrying. for(const auto &it : ship.Outfits()) for(int i = 0; i < it.second; ++i) Buy(it.first, day, source); // Then, check the base day for the ship chassis itself. const Ship *base = GameData::Ships().Get(ship.ModelName()); if(source) { // Check if the source has any instances of this ship. auto it = source->ships.find(base); if(it != source->ships.end() && !it->second.empty()) { day = source->Sell(it->second); if(it->second.empty()) source->ships.erase(it); } else if(isStock) { // If we're a planet buying from the player, and the player has no // record of how old this ship is, it's fully depreciated. day -= MAX_AGE; } } // Increment our count for this ship on this day. ++ships[base][day]; }
void ShipInfoDisplay::UpdateOutfits(const Ship &ship) { outfitLabels.clear(); outfitValues.clear(); outfitsHeight = 0; int outfitsValue = 0; map<string, map<string, int>> listing; for(const auto &it : ship.Outfits()) { listing[it.first->Category()][it.first->Name()] += it.second; outfitsValue += it.first->Cost() * it.second; } for(const auto &cit : listing) { // Pad by 10 pixels before each category. outfitLabels.push_back(string()); outfitValues.push_back(string()); outfitsHeight += 10; outfitLabels.push_back(cit.first + ':'); outfitValues.push_back(string()); outfitsHeight += 20; for(const auto &it : cit.second) { outfitLabels.push_back(it.first); outfitValues.push_back(to_string(it.second)); outfitsHeight += 20; } } // Pad by 10 pixels on the top and bottom. outfitsHeight += 10; saleLabels.clear(); saleValues.clear(); saleHeight = 0; int totalValue = ship.Attributes().Cost(); saleLabels.push_back(string()); saleValues.push_back(string()); saleHeight += 10; saleLabels.push_back("This ship will sell for:"); saleValues.push_back(string()); saleHeight += 20; saleLabels.push_back("empty hull:"); saleValues.push_back(Format::Number(totalValue - outfitsValue) + " credits"); saleHeight += 20; saleLabels.push_back(" + outfits:"); saleValues.push_back(Format::Number(outfitsValue) + " credits"); saleHeight += 20; saleLabels.push_back("= total:"); saleValues.push_back(Format::Number(totalValue) + " credits"); saleHeight += 20; // Pad by 10 pixels on the top and bottom. saleHeight += 10; }
// Find out how many of these I can take if I have this amount of cargo // space free. bool BoardingPanel::Plunder::CanTake(const Ship &ship) const { // If there's cargo space for this outfit, you can take it. double mass = UnitMass(); if(ship.Cargo().Free() >= mass) return true; // Otherwise, check if it is ammo for any of your weapons. If so, check if // you can install it as an outfit. if(outfit) for(const auto &it : ship.Outfits()) if(it.first != outfit && it.first->Ammo() == outfit && ship.Attributes().CanAdd(*outfit)) return true; return false; }
void ShipInfoDisplay::UpdateAttributes(const Ship &ship) { attributeLabels.clear(); attributeValues.clear(); attributesHeight = 10; const Outfit &attributes = ship.Attributes(); attributeLabels.push_back(string()); attributeValues.push_back(string()); attributesHeight += 10; attributeLabels.push_back("cost:"); attributeValues.push_back(Format::Number(ship.Cost())); attributesHeight += 20; attributeLabels.push_back(string()); attributeValues.push_back(string()); attributesHeight += 10; if(attributes.Get("shield generation")) { attributeLabels.push_back("shields charge / max:"); attributeValues.push_back(Format::Number(60. * attributes.Get("shield generation")) + " / " + Format::Number(attributes.Get("shields"))); } else { attributeLabels.push_back("shields:"); attributeValues.push_back(Format::Number(attributes.Get("shields"))); } attributesHeight += 20; if(attributes.Get("hull repair rate")) { attributeLabels.push_back("hull repair / max:"); attributeValues.push_back(Format::Number(60. * attributes.Get("hull repair rate")) + " / " + Format::Number(attributes.Get("hull"))); } else { attributeLabels.push_back("hull:"); attributeValues.push_back(Format::Number(attributes.Get("hull"))); } attributesHeight += 20; double emptyMass = attributes.Get("mass"); attributeLabels.push_back("mass with no cargo:"); attributeValues.push_back(Format::Number(emptyMass)); attributesHeight += 20; attributeLabels.push_back("cargo space:"); attributeValues.push_back(Format::Number(attributes.Get("cargo space"))); attributesHeight += 20; attributeLabels.push_back("required crew / bunks:"); attributeValues.push_back(Format::Number(ship.RequiredCrew()) + " / " + Format::Number(attributes.Get("bunks"))); attributesHeight += 20; attributeLabels.push_back("fuel capacity:"); attributeValues.push_back(Format::Number(attributes.Get("fuel capacity"))); attributesHeight += 20; double fullMass = emptyMass + attributes.Get("cargo space"); attributeLabels.push_back(string()); attributeValues.push_back(string()); attributesHeight += 10; attributeLabels.push_back((emptyMass == fullMass) ? "movement:" : "movement, full / no cargo:"); attributeValues.push_back(string()); attributesHeight += 20; attributeLabels.push_back("max speed:"); attributeValues.push_back(Format::Number(60. * attributes.Get("thrust") / attributes.Get("drag"))); attributesHeight += 20; attributeLabels.push_back("acceleration:"); if(emptyMass == fullMass) attributeValues.push_back(Format::Number(3600. * attributes.Get("thrust") / fullMass)); else attributeValues.push_back(Format::Number(3600. * attributes.Get("thrust") / fullMass) + " / " + Format::Number(3600. * attributes.Get("thrust") / emptyMass)); attributesHeight += 20; attributeLabels.push_back("turning:"); if(emptyMass == fullMass) attributeValues.push_back(Format::Number(60. * attributes.Get("turn") / fullMass)); else attributeValues.push_back(Format::Number(60. * attributes.Get("turn") / fullMass) + " / " + Format::Number(60. * attributes.Get("turn") / emptyMass)); attributesHeight += 20; // Find out how much outfit, engine, and weapon space the chassis has. map<string, double> chassis; static const string names[] = { "outfit space free:", "outfit space", " weapon capacity:", "weapon capacity", " engine capacity:", "engine capacity", "guns ports free:", "gun ports", "turret mounts free:", "turret mounts" }; static const int NAMES = sizeof(names) / sizeof(names[0]); for(int i = 1; i < NAMES; i += 2) chassis[names[i]] = attributes.Get(names[i]); for(const auto &it : ship.Outfits()) for(auto &cit : chassis) cit.second -= it.second * it.first->Get(cit.first); attributeLabels.push_back(string()); attributeValues.push_back(string()); attributesHeight += 10; for(int i = 0; i < NAMES; i += 2) { attributeLabels.push_back(names[i]); attributeValues.push_back(Format::Number(attributes.Get(names[i + 1])) + " / " + Format::Number(chassis[names[i + 1]])); attributesHeight += 20; } if(ship.DroneBaysFree()) { attributeLabels.push_back("drone bays:"); attributeValues.push_back(to_string(ship.DroneBaysFree())); attributesHeight += 20; } if(ship.FighterBaysFree()) { attributeLabels.push_back("fighter bays:"); attributeValues.push_back(to_string(ship.FighterBaysFree())); attributesHeight += 20; } tableLabels.clear(); energyTable.clear(); heatTable.clear(); // Skip a spacer and the table header. attributesHeight += 30; tableLabels.push_back("idle:"); energyTable.push_back(Format::Number(60. * attributes.Get("energy generation"))); heatTable.push_back(Format::Number( 60. * (attributes.Get("heat generation") - attributes.Get("cooling")))); attributesHeight += 20; tableLabels.push_back("moving:"); energyTable.push_back(Format::Number( -60. * (attributes.Get("thrusting energy") + attributes.Get("turning energy")))); heatTable.push_back(Format::Number( 60. * (attributes.Get("thrusting heat") + attributes.Get("turning heat")))); attributesHeight += 20; double firingEnergy = 0.; double firingHeat = 0.; for(const auto &it : ship.Outfits()) if(it.first->IsWeapon() && it.first->Reload()) { firingEnergy += it.second * it.first->FiringEnergy() / it.first->Reload(); firingHeat += it.second * it.first->FiringHeat() / it.first->Reload(); } tableLabels.push_back("firing:"); energyTable.push_back(Format::Number(-60. * firingEnergy)); heatTable.push_back(Format::Number(60. * firingHeat)); attributesHeight += 20; tableLabels.push_back("max:"); energyTable.push_back(Format::Number(attributes.Get("energy capacity"))); heatTable.push_back(Format::Number(60. * emptyMass * .1 * attributes.Get("heat dissipation"))); // Pad by 10 pixels on the top and bottom. attributesHeight += 30; }