bool SpaceStation::GetDockingClearance(Ship *s, std::string &outMsg) { assert(m_shipDocking.size() == m_type->NumDockingPorts()); for (Uint32 i=0; i<m_shipDocking.size(); i++) { if (m_shipDocking[i].ship == s) { outMsg = stringf(Lang::CLEARANCE_ALREADY_GRANTED_BAY_N, formatarg("bay", i+1)); return (m_shipDocking[i].stage > 0); // grant docking only if the ship is not already docked/undocking } } const Aabb &bbox = s->GetAabb(); const double bboxRad = bbox.GetRadius(); for (Uint32 i=0; i<m_shipDocking.size(); i++) { // initial unoccupied check if (m_shipDocking[i].ship != 0) continue; // size-of-ship vs size-of-bay check const SpaceStationType::SPort *const pPort = m_type->FindPortByBay(i); if( !pPort ) continue; if( pPort->minShipSize < bboxRad && bboxRad < pPort->maxShipSize ) { shipDocking_t &sd = m_shipDocking[i]; sd.ship = s; sd.stage = 1; sd.stagePos = 0; outMsg = stringf(Lang::CLEARANCE_GRANTED_BAY_N, formatarg("bay", i+1)); return true; } } outMsg = Lang::CLEARANCE_DENIED_NO_BAYS; return false; }
std::string AxisBinding::Description() const { const char *axis_names[] = {Lang::X, Lang::Y, Lang::Z}; std::ostringstream ossaxisnum; ossaxisnum << int(axis); return stringf(Lang::JOY_AXIS, formatarg("sign", direction == KeyBindings::NEGATIVE ? "-" : ""), // no + sign if positive formatarg("signp", direction == KeyBindings::NEGATIVE ? "-" : "+"), // optional with + sign formatarg("joynum", joystick), formatarg("axis", axis >= 0 && axis < 3 ? axis_names[axis] : ossaxisnum.str()) ); }
/* * Function: LoadGame * * Load a saved game. * * > Game.LoadGame(filename) * * Parameters: * * filename - Filename to load. It will be loaded from the 'savefiles' * directory in the user's game directory. * * Availability: * * alpha 28 * * Status: * * experimental */ static int l_game_load_game(lua_State *l) { if (Pi::game) { luaL_error(l, "can't load a game while a game is already running"); return 0; } const std::string filename(luaL_checkstring(l, 1)); try { Pi::game = Game::LoadGame(filename); } catch (SavedGameCorruptException) { luaL_error(l, Lang::GAME_LOAD_CORRUPT); } catch (SavedGameWrongVersionException) { luaL_error(l, Lang::GAME_LOAD_WRONG_VERSION); } catch (CouldNotOpenFileException) { const std::string msg = stringf(Lang::GAME_LOAD_CANNOT_OPEN, formatarg("filename", filename)); luaL_error(l, msg.c_str()); } return 0; }
/* * Function: SaveGame * * Save the current game. * * > path = Game.SaveGame(filename) * * Parameters: * * filename - Filename to save to. The file will be placed the 'savefiles' * directory in the user's game directory. * * Return: * * path - the full path to the saved file (so it can be displayed) * * Availability: * * June 2013 * * Status: * * experimental */ static int l_game_save_game(lua_State *l) { if (!Pi::game) { return luaL_error(l, "can't save when no game is running"); } const std::string filename(luaL_checkstring(l, 1)); const std::string path = FileSystem::JoinPathBelow(Pi::GetSaveDir(), filename); try { Game::SaveGame(filename, Pi::game); lua_pushlstring(l, path.c_str(), path.size()); return 1; } catch (CannotSaveInHyperspace) { return luaL_error(l, "%s", Lang::CANT_SAVE_IN_HYPERSPACE); } catch (CannotSaveDeadPlayer) { return luaL_error(l, "%s", Lang::CANT_SAVE_DEAD_PLAYER); } catch (CouldNotOpenFileException) { const std::string message = stringf(Lang::COULD_NOT_OPEN_FILENAME, formatarg("path", path)); lua_pushlstring(l, message.c_str(), message.size()); return lua_error(l); } catch (CouldNotWriteToFileException) { return luaL_error(l, "%s", Lang::GAME_SAVE_CANNOT_WRITE); } }
static int l_format_accel_g(lua_State *l) { double a = luaL_checknumber(l, 1); const std::string str = stringf(Lang::NUMBER_G, formatarg("acceleration", a)); lua_pushlstring(l, str.c_str(), str.size()); return 1; }
static int l_format_mass_tonnes(lua_State *l) { double t = luaL_checknumber(l, 1); const std::string str = stringf(Lang::NUMBER_TONNES, formatarg("mass", t)); lua_pushlstring(l, str.c_str(), str.size()); return 1; }
StationShipyardForm::StationShipyardForm(FormController *controller) : FaceForm(controller) { SetTitle(stringf(Lang::SOMEWHERE_SHIPYARD, formatarg("station", Pi::player->GetDockedWith()->GetLabel()))); Gui::SolidButton *b = new Gui::SolidButton(); b->SetShortcut(SDLK_1, KMOD_NONE); b->onClick.connect(sigc::mem_fun(this, &StationShipyardForm::EquipmentMarket)); Add(b, 30, 140); Gui::Label *l = new Gui::Label(Lang::SHIP_EQUIPMENT); Add(l, 55, 140); b = new Gui::SolidButton(); b->SetShortcut(SDLK_2, KMOD_NONE); b->onClick.connect(sigc::mem_fun(this, &StationShipyardForm::Repairs)); Add(b, 30, 200); l = new Gui::Label(Lang::REPAIRS_AND_SERVICING); Add(l, 55, 200); b = new Gui::SolidButton(); b->SetShortcut(SDLK_3, KMOD_NONE); b->onClick.connect(sigc::mem_fun(this, &StationShipyardForm::ShipMarket)); Add(b, 30, 260); l = new Gui::Label(Lang::NEW_AND_RECONDITIONED_SHIPS); Add(l, 55, 260); }
void StationShipMarketForm::UpdateShipList() { m_shiplistBox->DeleteAllChildren(); float line_height = Gui::Screen::GetFontHeight(); std::vector<ShipFlavour> &ships = m_station->GetShipsOnSale(); int num = 0; for (std::vector<ShipFlavour>::iterator i = ships.begin(); i!=ships.end(); ++i) { Gui::Fixed *f = new Gui::Fixed(450, line_height*1.5f); Gui::Label *l = new Gui::Label(ShipType::types[(*i).type].name); f->Add(l,0,0); f->Add(new Gui::Label(format_money((*i).price)), 200, 0); f->Add(new Gui::Label(format_money((*i).price - Pi::player->GetFlavour()->price) ), 275, 0); f->Add(new Gui::Label(stringf(Lang::NUMBER_TONNES, formatarg("mass", ShipType::types[(*i).type].capacity))), 370, 0); Gui::SolidButton *sb = new Gui::SolidButton(); sb->onClick.connect(sigc::bind(sigc::mem_fun(this, &StationShipMarketForm::ViewShip), num)); f->Add(sb, 430, 0); m_shiplistBox->PackEnd(f); num++; } }
NumberLabel *NumberLabel::SetValue(double v) { m_value = v; switch (m_format) { case FORMAT_NUMBER_2DP: SetText(to_string(v, "f.2")); break; case FORMAT_INTEGER: SetText(to_string(Uint32(v+0.5), "u")); break; case FORMAT_PERCENT: SetText(stringf("%0{f.2}%%", v*100.0)); break; case FORMAT_PERCENT_INTEGER: SetText(stringf("%0{u}%%", Uint32(v*100.0+0.5))); break; case FORMAT_MASS_TONNES: SetText(stringf(Lang::NUMBER_TONNES, formatarg("mass", v))); break; case FORMAT_MONEY: SetText(format_money(Sint64(v*100))); break; case FORMAT_DISTANCE_M: SetText(format_distance(v, 3)); break; case FORMAT_DISTANCE_LY: SetText(stringf(Lang::NUMBER_LY, formatarg("distance", v))); break; default: case FORMAT_NUMBER: SetText(to_string(v, "f")); break; } return this; }
static void draw_progress(UI::Gauge *gauge, UI::Label *label, float progress) { gauge->SetValue(progress); label->SetText(stringf(Lang::SIMULATING_UNIVERSE_EVOLUTION_N_BYEARS, formatarg("age", progress * 13.7f))); Pi::renderer->ClearScreen(); Pi::ui->Update(); Pi::ui->Draw(); Pi::renderer->SwapBuffers(); }
bool Player::CanSell(Equip::Type t, bool verbose) const { Equip::Slot slot = Equip::types[int(t)].slot; bool cansell = (m_equipment.Count(slot, t) > 0); if (verbose) { if (!cansell) { Pi::Message(stringf(Lang::YOU_DO_NOT_HAVE_ANY_X, formatarg("item", Equip::types[int(t)].name))); } } return cansell; }
static void draw_progress(float progress) { float w, h; Pi::renderer->BeginFrame(); Pi::renderer->EndFrame(); Gui::Screen::EnterOrtho(); std::string msg = stringf(Lang::SIMULATING_UNIVERSE_EVOLUTION_N_BYEARS, formatarg("age", progress * 13.7f)); Gui::Screen::MeasureString(msg, w, h); Gui::Screen::RenderString(msg, 0.5f*(Gui::Screen::GetWidth()-w), 0.5f*(Gui::Screen::GetHeight()-h)); Gui::Screen::LeaveOrtho(); Pi::renderer->SwapBuffers(); }
void SystemView::OnClickObject(SBody *b) { m_selectedObject = b; std::string desc; std::string data; desc += std::string(Lang::NAME); desc += ":\n"; data += b->name+"\n"; desc += std::string(Lang::DAY_LENGTH); desc += std::string(Lang::ROTATIONAL_PERIOD); desc += ":\n"; data += stringf(Lang::N_DAYS, formatarg("days", b->rotationPeriod.ToFloat())) + "\n"; desc += std::string(Lang::RADIUS); desc += ":\n"; data += format_distance(b->GetRadius())+"\n"; if (b->parent) { desc += std::string(Lang::SEMI_MAJOR_AXIS); desc += ":\n"; data += format_distance(b->orbit.semiMajorAxis)+"\n"; desc += std::string(Lang::ORBITAL_PERIOD); desc += ":\n"; data += stringf(Lang::N_DAYS, formatarg("days", b->orbit.period / (24*60*60))) + "\n"; } m_infoLabel->SetText(desc); m_infoText->SetText(data); if (Pi::KeyState(SDLK_LSHIFT) || Pi::KeyState(SDLK_RSHIFT)) { SystemPath path = m_system->GetPathOf(b); if (Pi::game->GetSpace()->GetStarSystem()->GetPath() == m_system->GetPath()) { Body* body = Pi::game->GetSpace()->FindBodyForPath(&path); if (body != 0) Pi::player->SetNavTarget(body); } } }
bool SpaceStation::GetDockingClearance(Ship *s, std::string &outMsg) { for (int i=0; i<MAX_DOCKING_PORTS; i++) { if (i >= m_type->numDockingPorts) break; if ((m_shipDocking[i].ship == s) && (m_shipDocking[i].stage > 0)) { outMsg = stringf(Lang::CLEARANCE_ALREADY_GRANTED_BAY_N, formatarg("bay", i+1)); return true; } } for (int i=0; i<MAX_DOCKING_PORTS; i++) { if (i >= m_type->numDockingPorts) break; if (m_shipDocking[i].ship != 0) continue; shipDocking_t &sd = m_shipDocking[i]; sd.ship = s; sd.stage = 1; sd.stagePos = 0; outMsg = stringf(Lang::CLEARANCE_GRANTED_BAY_N, formatarg("bay", i+1)); return true; } outMsg = Lang::CLEARANCE_DENIED_NO_BAYS; return false; }
bool Ship::OnCollision(Object *b, Uint32 flags, double relVel) { // hitting space station docking surfaces shouldn't do damage if (b->IsType(Object::SPACESTATION) && (flags & 0x10)) { return true; } // hitting cargo scoop surface shouldn't do damage int cargoscoop_cap = 0; Properties().Get("cargo_scoop_cap", cargoscoop_cap); if (cargoscoop_cap > 0 && b->IsType(Object::CARGOBODY) && !dynamic_cast<Body*>(b)->IsDead()) { LuaRef item = dynamic_cast<CargoBody*>(b)->GetCargoType(); if (LuaObject<Ship>::CallMethod<int>(this, "AddEquip", item) > 0) { // try to add it to the ship cargo. Pi::game->GetSpace()->KillBody(dynamic_cast<Body*>(b)); if (this->IsType(Object::PLAYER)) Pi::game->log->Add(stringf(Lang::CARGO_SCOOP_ACTIVE_1_TONNE_X_COLLECTED, formatarg("item", ScopedTable(item).CallMethod<std::string>("GetName")))); // XXX SfxManager::Add(this, TYPE_SCOOP); UpdateEquipStats(); return true; } if (this->IsType(Object::PLAYER)) Pi::game->log->Add(Lang::CARGO_SCOOP_ATTEMPTED); } if (b->IsType(Object::PLANET)) { // geoms still enabled when landed if (m_flightState != FLYING) return false; else { if (GetVelocity().Length() < MAX_LANDING_SPEED) { m_testLanded = true; return true; } } } if ( b->IsType(Object::CITYONPLANET) || b->IsType(Object::SHIP) || b->IsType(Object::PLAYER) || b->IsType(Object::SPACESTATION) || b->IsType(Object::PLANET) || b->IsType(Object::STAR) || b->IsType(Object::CARGOBODY)) { LuaEvent::Queue("onShipCollided", this, b->IsType(Object::CITYONPLANET) ? dynamic_cast<CityOnPlanet*>(b)->GetPlanet() : dynamic_cast<Body*>(b)); } return DynamicBody::OnCollision(b, flags, relVel); }
void GalacticView::Update() { const float frameTime = Pi::GetFrameTime(); if (m_zoomInButton->IsPressed()) m_zoom *= pow(4.0f, frameTime); if (m_zoomOutButton->IsPressed()) m_zoom *= pow(0.25f, frameTime); // XXX ugly hack checking for console here if (!Pi::IsConsoleActive()) { if (Pi::KeyState(SDLK_EQUALS)) m_zoom *= pow(4.0f, frameTime); if (Pi::KeyState(SDLK_MINUS)) m_zoom *= pow(0.25f, frameTime); } m_zoom = Clamp(m_zoom, 0.5f, 100.0f); m_scaleReadout->SetText(stringf(Lang::INT_LY, formatarg("scale", int(0.5*Galaxy::GALAXY_RADIUS/m_zoom)))); }
bool Ship::OnCollision(Object *b, Uint32 flags, double relVel) { // hitting space station docking surfaces shouldn't do damage if (b->IsType(Object::SPACESTATION) && (flags & 0x10)) { return true; } // hitting cargo scoop surface shouldn't do damage if ((m_equipment.Get(Equip::SLOT_CARGOSCOOP) != Equip::NONE) && b->IsType(Object::CARGOBODY) && m_stats.free_capacity) { Equip::Type item = dynamic_cast<CargoBody*>(b)->GetCargoType(); Pi::game->GetSpace()->KillBody(dynamic_cast<Body*>(b)); m_equipment.Add(item); UpdateEquipStats(); if (this->IsType(Object::PLAYER)) Pi::Message(stringf(Lang::CARGO_SCOOP_ACTIVE_1_TONNE_X_COLLECTED, formatarg("item", Equip::types[item].name))); // XXX Sfx::Add(this, Sfx::TYPE_SCOOP); return true; } if (b->IsType(Object::PLANET)) { // geoms still enabled when landed if (m_flightState != FLYING) return false; else { if (GetVelocity().Length() < MAX_LANDING_SPEED) { m_testLanded = true; return true; } } } if ( b->IsType(Object::CITYONPLANET) || b->IsType(Object::SHIP) || b->IsType(Object::PLAYER) || b->IsType(Object::SPACESTATION) || b->IsType(Object::PLANET) || b->IsType(Object::STAR) || b->IsType(Object::CARGOBODY)) { LuaEvent::Queue("onShipCollided", this, b->IsType(Object::CITYONPLANET) ? dynamic_cast<CityOnPlanet*>(b)->GetPlanet() : dynamic_cast<Body*>(b)); } return DynamicBody::OnCollision(b, flags, relVel); }
StationShipRepairForm::StationShipRepairForm(FormController *controller) : FaceForm(controller) { m_station = Pi::player->GetDockedWith(); SetTitle(stringf(Lang::SOMEWHERE_SHIP_REPAIRS, formatarg("station", m_station->GetLabel()))); m_working = new Gui::Label(Lang::SHIP_IS_ALREADY_FULLY_REPAIRED); Add(m_working, 0, 0); m_tableBox = new Gui::HBox(); m_tableBox->SetSpacing(15.0f); Add(m_tableBox, 0, 0); Gui::VBox *columnBox = new Gui::VBox(); m_tableBox->PackEnd(columnBox); Gui::HBox *buttonBox = new Gui::HBox(); buttonBox->SetSpacing(5.0f); Gui::Button *b = new Gui::SolidButton(); b->onClick.connect(sigc::bind(sigc::mem_fun(this, &StationShipRepairForm::RepairHull), 1.0f)); buttonBox->PackEnd(b); buttonBox->PackEnd(new Gui::Label(Lang::REPAIR_1_PERCENT_HULL)); columnBox->PackEnd(buttonBox); buttonBox = new Gui::HBox(); buttonBox->SetSpacing(5.0f); b = new Gui::SolidButton(); b->onClick.connect(sigc::bind(sigc::mem_fun(this, &StationShipRepairForm::RepairHull), 100.0f)); buttonBox->PackEnd(b); m_repairAllDesc = new Gui::Label(""); buttonBox->PackEnd(m_repairAllDesc); columnBox->PackEnd(buttonBox); columnBox = new Gui::VBox(); m_tableBox->PackEnd(columnBox); m_repairOneCost = new Gui::Label(""); columnBox->PackEnd(m_repairOneCost); m_repairAllCost = new Gui::Label(""); columnBox->PackEnd(m_repairAllCost); UpdateLabels(); }
StationShipMarketForm::StationShipMarketForm(FormController *controller) : FaceForm(controller) { m_station = Pi::player->GetDockedWith(); SetTitle(stringf(Lang::SOMEWHERE_SHIP_MARKET, formatarg("station", m_station->GetLabel()))); Gui::VScrollBar *scroll = new Gui::VScrollBar(); Gui::VScrollPortal *portal = new Gui::VScrollPortal(450); scroll->SetAdjustment(&portal->vscrollAdjust); float line_height = Gui::Screen::GetFontHeight(); m_shiplistBox = new Gui::VBox(); m_shiplistBox->SetSpacing(line_height*0.5f); UpdateShipList(); m_shiplistBox->ShowAll(); portal->Add(m_shiplistBox); portal->ShowAll(); Gui::VBox *outerbox = new Gui::VBox(); outerbox->SetSpacing(line_height); Gui::Fixed *heading = new Gui::Fixed(470, Gui::Screen::GetFontHeight()); const float *col = Gui::Theme::Colors::tableHeading; heading->Add((new Gui::Label(Lang::SHIP))->Color(col), 0, 0); heading->Add((new Gui::Label(Lang::PRICE))->Color(col), 200, 0); heading->Add((new Gui::Label(Lang::PART_EX))->Color(col), 275, 0); heading->Add((new Gui::Label(Lang::CAPACITY))->Color(col), 370, 0); heading->Add((new Gui::Label(Lang::VIEW))->Color(col), 430, 0); outerbox->PackEnd(heading); Gui::HBox *body = new Gui::HBox(); body->PackEnd(portal); body->PackEnd(scroll); outerbox->PackEnd(body); Add(outerbox, 0, 0); ShowAll(); m_onShipsForSaleChangedConnection = m_station->onShipsForSaleChanged.connect(sigc::mem_fun(this, &StationShipMarketForm::OnShipsForSaleChanged)); }
void StationShipRepairForm::UpdateLabels() { float hullPercent = Pi::player->GetPercentHull(); if (hullPercent >= 100.0f) { m_working->Show(); m_tableBox->Hide(); } else { m_repairAllDesc->SetText(stringf(Lang::REPAIR_ENTIRE_HULL, formatarg("repairpercent", 100.0f - hullPercent))); const float hullDamage = 100.0f - hullPercent; m_repairOneCost->SetText(format_money(GetRepairCost(std::min(hullDamage, 1.0f)))); m_repairAllCost->SetText(format_money(GetRepairCost(hullDamage))); m_working->Hide(); m_tableBox->Show(); } }
void MsgLogWidget::ShowNext() { if (m_msgQueue.empty()) { // current message expired and queue empty m_msgLabel->SetText(""); m_msgAge = 0; onUngrabFocus.emit(); } else { // current message expired and more in queue Pi::BoinkNoise(); Pi::SetTimeAccel(1); Pi::RequestTimeAccel(1); message_t msg("","",NONE); // use MUST_SEE messages first for (std::list<message_t>::iterator i = m_msgQueue.begin(); i != m_msgQueue.end(); ++i) { if ((*i).type == MUST_SEE) { msg = *i; m_msgQueue.erase(i); break; } } if (msg.type == NONE) { msg = m_msgQueue.front(); m_msgQueue.pop_front(); } if (msg.sender == "") { m_msgLabel->SetText("#0f0" + msg.message); } else { m_msgLabel->SetText( std::string("#ca0") + stringf(Lang::MESSAGE_FROM_X, formatarg("sender", msg.sender)) + std::string("\n#0f0") + msg.message); } m_msgAge = SDL_GetTicks(); m_curMsgType = msg.type; onGrabFocus.emit(); } }
void LuaChatForm::OnClickSell(int t) { lua_State *l = Lua::manager->GetLuaState(); LUA_DEBUG_START(l); _get_trade_function(l, GetAdvert()->ref, "onClickSell"); lua_pushinteger(l, GetAdvert()->ref); lua_pushstring(l, EnumStrings::GetString("EquipType", t)); pi_lua_protected_call(l, 2, 1); bool allow_sell = lua_toboolean(l, -1) != 0; lua_pop(l, 1); LUA_DEBUG_END(l, 0); if (allow_sell) { if (BuyFrom(Pi::player, static_cast<Equip::Type>(t), true)) { Pi::Message(stringf(Lang::SOLD_1T_OF, formatarg("commodity", Equip::types[t].name))); } m_commodityTradeWidget->UpdateStock(t); } }
void NotifyOfCrime(Ship *s, enum Crime crime) { // ignore crimes of NPCs for the time being if (!s->IsType(Object::PLAYER)) return; // find nearest starport to this evil criminal SpaceStation *station = static_cast<SpaceStation*>(Pi::game->GetSpace()->FindNearestTo(s, Object::SPACESTATION)); if (station) { double dist = station->GetPositionRelTo(s).Length(); // too far away for crime to be noticed :) if (dist > 100000.0) return; const int crimeIdx = GetCrimeIdxFromEnum(crime); Pi::cpan->MsgLog()->ImportantMessage(station->GetLabel(), stringf(Lang::X_CANNOT_BE_TOLERATED_HERE, formatarg("crime", crimeNames[crimeIdx]))); float lawlessness = Pi::game->GetSpace()->GetStarSystem()->GetSysPolit().lawlessness.ToFloat(); Sint64 oldCrimes, oldFine; GetCrime(&oldCrimes, &oldFine); Sint64 newFine = std::max(1, 1 + int(crimeBaseFine[crimeIdx] * (1.0-lawlessness))); // don't keep compounding fines (maybe should for murder, etc...) if ( (!(crime & CRIME_MURDER)) && (newFine < oldFine) ) newFine = 0; AddCrime(crime, newFine); } }
void SystemInfoView::SystemChanged(const SystemPath &path) { DeleteAllChildren(); m_tabs = 0; m_bodyIcons.clear(); if (!path.HasValidSystem()) return; m_system = StarSystemCache::GetCached(path); m_sbodyInfoTab = new Gui::Fixed(float(Gui::Screen::GetWidth()), float(Gui::Screen::GetHeight()-100)); if (m_system->GetUnexplored()) { Add(m_sbodyInfoTab, 0, 0); std::string _info = Lang::UNEXPLORED_SYSTEM_STAR_INFO_ONLY; Gui::Label *l = (new Gui::Label(_info))->Color(255,255,0); m_sbodyInfoTab->Add(l, 35, 300); m_selectedBodyPath = SystemPath(); ShowAll(); return; } m_econInfoTab = new Gui::Fixed(float(Gui::Screen::GetWidth()), float(Gui::Screen::GetHeight()-100)); Gui::Fixed *demographicsTab = new Gui::Fixed(); m_tabs = new Gui::Tabbed(); m_tabs->AddPage(new Gui::Label(Lang::PLANETARY_INFO), m_sbodyInfoTab); m_tabs->AddPage(new Gui::Label(Lang::ECONOMIC_INFO), m_econInfoTab); m_tabs->AddPage(new Gui::Label(Lang::DEMOGRAPHICS), demographicsTab); Add(m_tabs, 0, 0); m_sbodyInfoTab->onMouseButtonEvent.connect(sigc::mem_fun(this, &SystemInfoView::OnClickBackground)); int majorBodies, starports, onSurface; { float pos[2] = { 0, 0 }; float psize = -1; majorBodies = starports = onSurface = 0; PutBodies(m_system->GetRootBody().Get(), m_econInfoTab, 1, pos, majorBodies, starports, onSurface, psize); majorBodies = starports = onSurface = 0; pos[0] = pos[1] = 0; psize = -1; PutBodies(m_system->GetRootBody().Get(), m_sbodyInfoTab, 1, pos, majorBodies, starports, onSurface, psize); majorBodies = starports = onSurface = 0; pos[0] = pos[1] = 0; psize = -1; PutBodies(m_system->GetRootBody().Get(), demographicsTab, 1, pos, majorBodies, starports, onSurface, psize); } std::string _info = stringf( Lang::STABLE_SYSTEM_WITH_N_MAJOR_BODIES_STARPORTS, formatarg("bodycount", majorBodies), formatarg("body(s)", std::string(majorBodies == 1 ? Lang::BODY : Lang::BODIES)), formatarg("portcount", starports), formatarg("starport(s)", std::string(starports == 1 ? Lang::STARPORT : Lang::COUNT_STARPORTS))); if (starports > 0) _info += stringf(Lang::COUNT_ON_SURFACE, formatarg("surfacecount", onSurface)); _info += ".\n\n"; _info += m_system->GetLongDescription(); { // astronomical body info tab m_infoBox = new Gui::VBox(); Gui::HBox *scrollBox = new Gui::HBox(); scrollBox->SetSpacing(5); m_sbodyInfoTab->Add(scrollBox, 35, 250); Gui::VScrollBar *scroll = new Gui::VScrollBar(); Gui::VScrollPortal *portal = new Gui::VScrollPortal(730); scroll->SetAdjustment(&portal->vscrollAdjust); Gui::Label *l = (new Gui::Label(_info))->Color(255,255,0); m_infoBox->PackStart(l); portal->Add(m_infoBox); scrollBox->PackStart(scroll); scrollBox->PackStart(portal); } { // economy tab Gui::HBox *scrollBox2 = new Gui::HBox(); scrollBox2->SetSpacing(5); m_econInfoTab->Add(scrollBox2, 35, 300); Gui::VScrollBar *scroll2 = new Gui::VScrollBar(); Gui::VScrollPortal *portal2 = new Gui::VScrollPortal(730); scroll2->SetAdjustment(&portal2->vscrollAdjust); scrollBox2->PackStart(scroll2); scrollBox2->PackStart(portal2); m_econInfo = new Gui::Label(""); m_econInfoTab->Add(m_econInfo, 35, 250); Gui::Fixed *f = new Gui::Fixed(); m_econMajImport = new Gui::Label(""); m_econMinImport = new Gui::Label(""); m_econMajExport = new Gui::Label(""); m_econMinExport = new Gui::Label(""); m_econIllegal = new Gui::Label(""); m_econMajImport->Color(255,255,0); m_econMinImport->Color(255,255,0); m_econMajExport->Color(255,255,0); m_econMinExport->Color(255,255,0); m_econIllegal->Color(255,255,0); f->Add(m_econMajImport, 0, 0); f->Add(m_econMinImport, 150, 0); f->Add(m_econMajExport, 300, 0); f->Add(m_econMinExport, 450, 0); f->Add(m_econIllegal, 600, 0); portal2->Add(f); UpdateEconomyTab(); } { Gui::Fixed *col1 = new Gui::Fixed(); demographicsTab->Add(col1, 200, 300); Gui::Fixed *col2 = new Gui::Fixed(); demographicsTab->Add(col2, 400, 300); const float YSEP = Gui::Screen::GetFontHeight() * 1.2f; col1->Add((new Gui::Label(Lang::SYSTEM_TYPE))->Color(255,255,0), 0, 0); col2->Add(new Gui::Label(m_system->GetShortDescription()), 0, 0); col1->Add((new Gui::Label(Lang::GOVERNMENT_TYPE))->Color(255,255,0), 0, 2*YSEP); col2->Add(new Gui::Label(m_system->GetSysPolit().GetGovernmentDesc()), 0, 2*YSEP); col1->Add((new Gui::Label(Lang::ECONOMY_TYPE))->Color(255,255,0), 0, 3*YSEP); col2->Add(new Gui::Label(m_system->GetSysPolit().GetEconomicDesc()), 0, 3*YSEP); col1->Add((new Gui::Label(Lang::ALLEGIANCE))->Color(255,255,0), 0, 4*YSEP); col2->Add(new Gui::Label(m_system->GetFaction()->name.c_str()), 0, 4*YSEP); col1->Add((new Gui::Label(Lang::POPULATION))->Color(255,255,0), 0, 5*YSEP); std::string popmsg; fixed pop = m_system->GetTotalPop(); if (pop >= fixed(1,1)) { popmsg = stringf(Lang::OVER_N_BILLION, formatarg("population", pop.ToInt32())); } else if (pop >= fixed(1,1000)) { popmsg = stringf(Lang::OVER_N_MILLION, formatarg("population", (pop*1000).ToInt32())); } else if (pop != fixed(0)) { popmsg = Lang::A_FEW_THOUSAND; } else { popmsg = Lang::NO_REGISTERED_INHABITANTS; } col2->Add(new Gui::Label(popmsg), 0, 5*YSEP); col1->Add((new Gui::Label(Lang::SECTOR_COORDINATES))->Color(255,255,0), 0, 6*YSEP); col2->Add(new Gui::Label(stringf("%0{d}, %1{d}, %2{d}", path.sectorX, path.sectorY, path.sectorZ)), 0, 6*YSEP); col1->Add((new Gui::Label(Lang::SYSTEM_NUMBER))->Color(255,255,0), 0, 7*YSEP); col2->Add(new Gui::Label(stringf("%0", path.systemIndex)), 0, 7*YSEP); } UpdateIconSelections(); ShowAll(); }
void Pi::HandleEvents() { PROFILE_SCOPED() SDL_Event event; // XXX for most keypresses SDL will generate KEYUP/KEYDOWN and TEXTINPUT // events. keybindings run off KEYUP/KEYDOWN. the console is opened/closed // via keybinding. the console TextInput widget uses TEXTINPUT events. thus // after switching the console, the stray TEXTINPUT event causes the // console key (backtick) to appear in the text entry field. we hack around // this by setting this flag if the console was switched. if its set, we // swallow the TEXTINPUT event this hack must remain until we have a // unified input system bool skipTextInput = false; Pi::mouseMotion[0] = Pi::mouseMotion[1] = 0; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { if (Pi::game) Pi::EndGame(); Pi::Quit(); } if (skipTextInput && event.type == SDL_TEXTINPUT) { skipTextInput = false; continue; } if (ui->DispatchSDLEvent(event)) continue; bool consoleActive = Pi::IsConsoleActive(); if (!consoleActive) KeyBindings::DispatchSDLEvent(&event); else KeyBindings::toggleLuaConsole.CheckSDLEventAndDispatch(&event); if (consoleActive != Pi::IsConsoleActive()) { skipTextInput = true; continue; } if (Pi::IsConsoleActive()) continue; Gui::HandleSDLEvent(&event); switch (event.type) { case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) { if (Pi::game) { // only accessible once game started if (currentView != 0) { if (currentView != Pi::game->GetSettingsView()) { Pi::game->SetTimeAccel(Game::TIMEACCEL_PAUSED); SetView(Pi::game->GetSettingsView()); } else { Pi::game->RequestTimeAccel(Game::TIMEACCEL_1X); SetView(Pi::player->IsDead() ? static_cast<View*>(Pi::game->GetDeathView()) : static_cast<View*>(Pi::game->GetWorldView())); } } } break; } // special keys. LCTRL+turd if ((KeyState(SDLK_LCTRL) || (KeyState(SDLK_RCTRL)))) { switch (event.key.keysym.sym) { case SDLK_q: // Quit if (Pi::game) Pi::EndGame(); Pi::Quit(); break; case SDLK_PRINTSCREEN: // print case SDLK_KP_MULTIPLY: // screen { char buf[256]; const time_t t = time(0); struct tm *_tm = localtime(&t); strftime(buf, sizeof(buf), "screenshot-%Y%m%d-%H%M%S.png", _tm); Graphics::ScreendumpState sd; Pi::renderer->Screendump(sd); write_screenshot(sd, buf); break; } #if WITH_DEVKEYS case SDLK_i: // Toggle Debug info Pi::showDebugInfo = !Pi::showDebugInfo; break; #ifdef PIONEER_PROFILER case SDLK_p: // alert it that we want to profile if (KeyState(SDLK_LSHIFT) || KeyState(SDLK_RSHIFT)) Pi::doProfileOne = true; else { Pi::doProfileSlow = !Pi::doProfileSlow; Output("slow frame profiling %s\n", Pi::doProfileSlow ? "enabled" : "disabled"); } break; #endif case SDLK_F12: { if(Pi::game) { vector3d dir = -Pi::player->GetOrient().VectorZ(); /* add test object */ if (KeyState(SDLK_RSHIFT)) { Missile *missile = new Missile(ShipType::MISSILE_GUIDED, Pi::player); missile->SetOrient(Pi::player->GetOrient()); missile->SetFrame(Pi::player->GetFrame()); missile->SetPosition(Pi::player->GetPosition()+50.0*dir); missile->SetVelocity(Pi::player->GetVelocity()); game->GetSpace()->AddBody(missile); missile->AIKamikaze(Pi::player->GetCombatTarget()); } else if (KeyState(SDLK_LSHIFT)) { SpaceStation *s = static_cast<SpaceStation*>(Pi::player->GetNavTarget()); if (s) { Ship *ship = new Ship(ShipType::POLICE); int port = s->GetFreeDockingPort(ship); if (port != -1) { Output("Putting ship into station\n"); // Make police ship intent on killing the player ship->AIKill(Pi::player); ship->SetFrame(Pi::player->GetFrame()); ship->SetDockedWith(s, port); game->GetSpace()->AddBody(ship); } else { delete ship; Output("No docking ports free dude\n"); } } else { Output("Select a space station...\n"); } } else { Ship *ship = new Ship(ShipType::POLICE); if( KeyState(SDLK_LCTRL) ) ship->AIFlyTo(Pi::player); // a less lethal option else ship->AIKill(Pi::player); // a really lethal option! lua_State *l = Lua::manager->GetLuaState(); pi_lua_import(l, "Equipment"); LuaTable equip(l, -1); LuaObject<Ship>::CallMethod<>(ship, "AddEquip", equip.Sub("laser").Sub("pulsecannon_dual_1mw")); LuaObject<Ship>::CallMethod<>(ship, "AddEquip", equip.Sub("misc").Sub("laser_cooling_booster")); LuaObject<Ship>::CallMethod<>(ship, "AddEquip", equip.Sub("misc").Sub("atmospheric_shielding")); lua_pop(l, 5); ship->SetFrame(Pi::player->GetFrame()); ship->SetPosition(Pi::player->GetPosition()+100.0*dir); ship->SetVelocity(Pi::player->GetVelocity()); ship->UpdateEquipStats(); game->GetSpace()->AddBody(ship); } } break; } #endif /* DEVKEYS */ #if WITH_OBJECTVIEWER case SDLK_F10: Pi::SetView(Pi::game->GetObjectViewerView()); break; #endif case SDLK_F11: // XXX only works on X11 //SDL_WM_ToggleFullScreen(Pi::scrSurface); #if WITH_DEVKEYS renderer->ReloadShaders(); #endif break; case SDLK_F9: // Quicksave { if(Pi::game) { if (Pi::game->IsHyperspace()) Pi::game->log->Add(Lang::CANT_SAVE_IN_HYPERSPACE); else { const std::string name = "_quicksave"; const std::string path = FileSystem::JoinPath(GetSaveDir(), name); try { Game::SaveGame(name, Pi::game); Pi::game->log->Add(Lang::GAME_SAVED_TO + path); } catch (CouldNotOpenFileException) { Pi::game->log->Add(stringf(Lang::COULD_NOT_OPEN_FILENAME, formatarg("path", path))); } catch (CouldNotWriteToFileException) { Pi::game->log->Add(Lang::GAME_SAVE_CANNOT_WRITE); } } } break; } default: break; // This does nothing but it stops the compiler warnings } } Pi::keyState[event.key.keysym.sym] = true; Pi::keyModState = event.key.keysym.mod; Pi::onKeyPress.emit(&event.key.keysym); break; case SDL_KEYUP: Pi::keyState[event.key.keysym.sym] = false; Pi::keyModState = event.key.keysym.mod; Pi::onKeyRelease.emit(&event.key.keysym); break; case SDL_MOUSEBUTTONDOWN: if (event.button.button < COUNTOF(Pi::mouseButton)) { Pi::mouseButton[event.button.button] = 1; Pi::onMouseButtonDown.emit(event.button.button, event.button.x, event.button.y); } break; case SDL_MOUSEBUTTONUP: if (event.button.button < COUNTOF(Pi::mouseButton)) { Pi::mouseButton[event.button.button] = 0; Pi::onMouseButtonUp.emit(event.button.button, event.button.x, event.button.y); } break; case SDL_MOUSEWHEEL: Pi::onMouseWheel.emit(event.wheel.y > 0); // true = up break; case SDL_MOUSEMOTION: Pi::mouseMotion[0] += event.motion.xrel; Pi::mouseMotion[1] += event.motion.yrel; // SDL_GetRelativeMouseState(&Pi::mouseMotion[0], &Pi::mouseMotion[1]); break; case SDL_JOYAXISMOTION: if (!joysticks[event.jaxis.which].joystick) break; if (event.jaxis.value == -32768) joysticks[event.jaxis.which].axes[event.jaxis.axis] = 1.f; else joysticks[event.jaxis.which].axes[event.jaxis.axis] = -event.jaxis.value / 32767.f; break; case SDL_JOYBUTTONUP: case SDL_JOYBUTTONDOWN: if (!joysticks[event.jaxis.which].joystick) break; joysticks[event.jbutton.which].buttons[event.jbutton.button] = event.jbutton.state != 0; break; case SDL_JOYHATMOTION: if (!joysticks[event.jaxis.which].joystick) break; joysticks[event.jhat.which].hats[event.jhat.hat] = event.jhat.value; break; } } }
void SystemInfoView::OnBodyViewed(SystemBody *b) { std::string desc, data; m_infoBox->DeleteAllChildren(); Gui::Fixed *outer = new Gui::Fixed(600, 200); m_infoBox->PackStart(outer); Gui::VBox *col1 = new Gui::VBox(); Gui::VBox *col2 = new Gui::VBox(); outer->Add(col1, 0, 0); outer->Add(col2, 300, 0); #define _add_label_and_value(label, value) { \ Gui::Label *l = (new Gui::Label(label))->Color(255,255,0); \ col1->PackEnd(l); \ l = (new Gui::Label(value))->Color(255,255,0); \ col2->PackEnd(l); \ } bool multiple = (b->GetSuperType() == SystemBody::SUPERTYPE_STAR && b->GetParent() && b->GetParent()->GetType() == SystemBody::TYPE_GRAVPOINT && b->GetParent()->GetParent()); { Gui::Label *l = new Gui::Label(b->GetName() + ": " + b->GetAstroDescription() + (multiple ? (std::string(" (")+b->GetParent()->GetName() + ")") : "")); l->Color(255,255,0); m_infoBox->PackStart(l); } _add_label_and_value(Lang::MASS, stringf(Lang::N_WHATEVER_MASSES, formatarg("mass", b->GetMassAsFixed().ToDouble()), formatarg("units", std::string(b->GetSuperType() == SystemBody::SUPERTYPE_STAR ? Lang::SOLAR : Lang::EARTH)))); _add_label_and_value(Lang::RADIUS, stringf(Lang::N_WHATEVER_RADII, formatarg("radius", b->GetRadiusAsFixed().ToDouble()), formatarg("units", std::string(b->GetSuperType() == SystemBody::SUPERTYPE_STAR ? Lang::SOLAR : Lang::EARTH)), formatarg("radkm", b->GetRadius() / 1000.0))); if (b->GetSuperType() == SystemBody::SUPERTYPE_STAR) { _add_label_and_value(Lang::EQUATORIAL_RADIUS_TO_POLAR_RADIUS_RATIO, stringf("%0{f.3}", b->GetAspectRatio())); } if (b->GetType() != SystemBody::TYPE_STARPORT_ORBITAL) { _add_label_and_value(Lang::SURFACE_TEMPERATURE, stringf(Lang::N_CELSIUS, formatarg("temperature", b->GetAverageTemp()-273))); _add_label_and_value(Lang::SURFACE_GRAVITY, stringf("%0{f.3} m/s^2", b->CalcSurfaceGravity())); } if (b->GetParent()) { float days = float(b->GetOrbit().Period()) / float(60*60*24); if (days > 1000) { data = stringf(Lang::N_YEARS, formatarg("years", days/365)); } else { data = stringf(Lang::N_DAYS, formatarg("days", b->GetOrbit().Period() / (60*60*24))); } if (multiple) { float pdays = float(b->GetParent()->GetOrbit().Period()) /float(60*60*24); data += " (" + (pdays > 1000 ? stringf(Lang::N_YEARS, formatarg("years", pdays/365)) : stringf(Lang::N_DAYS, formatarg("days", b->GetParent()->GetOrbit().Period() / (60*60*24)))) + ")"; } _add_label_and_value(Lang::ORBITAL_PERIOD, data); _add_label_and_value(Lang::PERIAPSIS_DISTANCE, format_distance(b->GetOrbMin()*AU, 3) + (multiple ? (std::string(" (") + format_distance(b->GetParent()->GetOrbMin()*AU, 3)+ ")") : "")); _add_label_and_value(Lang::APOAPSIS_DISTANCE, format_distance(b->GetOrbMax()*AU, 3) + (multiple ? (std::string(" (") + format_distance(b->GetParent()->GetOrbMax()*AU, 3)+ ")") : "")); _add_label_and_value(Lang::ECCENTRICITY, stringf("%0{f.2}", b->GetOrbit().GetEccentricity()) + (multiple ? (std::string(" (") + stringf("%0{f.2}", b->GetParent()->GetOrbit().GetEccentricity()) + ")") : "")); if (b->GetType() != SystemBody::TYPE_STARPORT_ORBITAL) { _add_label_and_value(Lang::AXIAL_TILT, stringf(Lang::N_DEGREES, formatarg("angle", b->GetAxialTilt() * (180.0/M_PI)))); if (b->IsRotating()) { _add_label_and_value( std::string(Lang::DAY_LENGTH)+std::string(Lang::ROTATIONAL_PERIOD), stringf(Lang::N_EARTH_DAYS, formatarg("days", b->GetRotationPeriodInDays()))); } } int numSurfaceStarports = 0; std::string nameList; for (const SystemBody* kid : b->GetChildren()) { if (kid->GetType() == SystemBody::TYPE_STARPORT_SURFACE) { nameList += (numSurfaceStarports ? ", " : "") + kid->GetName(); numSurfaceStarports++; } } if (numSurfaceStarports) { _add_label_and_value(Lang::STARPORTS, nameList); } } m_infoBox->ShowAll(); m_infoBox->ResizeRequest(); }
virtual void UpdateInfo() { char buf[512]; std::string col1, col2; const ShipType &stype = Pi::player->GetShipType(); col1 = std::string(Lang::SHIP_INFORMATION_HEADER)+std::string(stype.name); col1 += "\n\n"; col1 += std::string(Lang::HYPERDRIVE); col1 += ":\n\n"; col1 += std::string(Lang::CAPACITY); col1 += ":\n"; col1 += std::string(Lang::FREE); col1 += ":\n"; col1 += std::string(Lang::USED); col1 += ":\n"; col1 += std::string(Lang::TOTAL_WEIGHT); col1 += ":\n\n"; col1 += std::string(Lang::FRONT_WEAPON); col1 += ":\n"; col1 += std::string(Lang::REAR_WEAPON); col1 += ":\n\n"; col1 += std::string(Lang::HYPERSPACE_RANGE); col1 += ":\n\n"; col2 = "\n\n"; Equip::Type e = Pi::player->m_equipment.Get(Equip::SLOT_ENGINE); col2 += std::string(EquipType::types[e].name); const shipstats_t *stats; stats = Pi::player->CalcStats(); snprintf(buf, sizeof(buf), "\n\n%dt\n" "%dt\n" "%dt\n" "%dt", stats->max_capacity, stats->free_capacity, stats->used_capacity, stats->total_mass); col2 += std::string(buf); int numLasers = Pi::player->m_equipment.GetSlotSize(Equip::SLOT_LASER); if (numLasers >= 1) { e = Pi::player->m_equipment.Get(Equip::SLOT_LASER, 0); col2 += std::string("\n\n")+EquipType::types[e].name; } else { col2 += "\n\n"; col2 += std::string(Lang::NO_MOUNTING); } if (numLasers >= 2) { e = Pi::player->m_equipment.Get(Equip::SLOT_LASER, 1); col2 += std::string("\n")+EquipType::types[e].name; } else { col2 += "\n"; col2 += std::string(Lang::NO_MOUNTING); } col2 += "\n\n"; col2 += stringf(Lang::N_LIGHT_YEARS_N_MAX, formatarg("distance", stats->hyperspace_range), formatarg("maxdistance", stats->hyperspace_range_max)); for (int i=Equip::FIRST_SHIPEQUIP; i<=Equip::LAST_SHIPEQUIP; i++) { Equip::Type t = Equip::Type(i) ; Equip::Slot s = EquipType::types[t].slot; if ((s == Equip::SLOT_MISSILE) || (s == Equip::SLOT_ENGINE) || (s == Equip::SLOT_LASER)) continue; int num = Pi::player->m_equipment.Count(s, t); if (num == 1) { col1 += stringf("%0\n", EquipType::types[t].name); } else if (num > 1) { col1 += stringf("%0{d} %1s\n", num, EquipType::types[t].name); } } info1->SetText(col1); info2->SetText(col2); this->ResizeRequest(); }
void JettisonCargo(Equip::Type t) { if (Pi::player->Jettison(t)) { Pi::cpan->MsgLog()->Message("", stringf(Lang::JETTISONED_1T_OF_X, formatarg("commodity", EquipType::types[t].name))); m_infoView->UpdateInfo(); } }
void test_stringf() { TEST0("", ""); TEST0("Hello.", "Hello."); TEST0("backslash: \\", "backslash: \\"); TEST0("2-backslash: \\\\", "2-backslash: \\\\"); TEST0("%%", "%"); TEST0("Hello: %%", "Hello: %"); TEST0("%%: Hello", "%: Hello"); TEST0("foo %% bar", "foo % bar"); TEST0("%", "%(err: unfinished reference)"); TEST0("Hello: %", "Hello: %(err: unfinished reference)"); TEST0("% xyz", "%(err: unfinished reference) xyz"); TEST0("%0", "%(err: unknown arg '0')"); TEST0("%1", "%(err: unknown arg '1')"); TEST0("%10", "%(err: unknown arg '10')"); TEST0("%1.", "%(err: unknown arg '1')."); TEST0("Hello: %1.", "Hello: %(err: unknown arg '1')."); TEST0("Hello: %xyz", "Hello: %(err: unknown arg 'xyz')"); TEST0("Hello: %xyz-hello", "Hello: %(err: unknown arg 'xyz')-hello"); TEST0("Hello: %{xyz-he}llo", "Hello: %(err: unknown arg 'xyz-he')llo"); TEST0("Hello: %{} end", "Hello: %(err: blank reference) end"); TEST0("Hello: %_hello end", "Hello: %(err: unknown arg '_hello') end"); TEST1("Hello: %xyz end", formatarg("x", 42), "Hello: %(err: unknown arg 'xyz') end"); TEST1("Hello: %x end", formatarg("xyz", 42), "Hello: %(err: unknown arg 'x') end"); TEST1("Hello: %1 end", formatarg("x", 42), "Hello: %(err: unknown arg '1') end"); TEST1("Hello: %0 end", formatarg("x", 42), "Hello: 42 end"); TEST1("Hello: %xyz end", formatarg("xyz", 42), "Hello: 42 end"); TEST1("Hello: %{xyz} end", formatarg("xyz", 42), "Hello: 42 end"); TEST1("Hello: %xyz%xyz end", formatarg("xyz", 42), "Hello: 4242 end"); TEST1("Hello: %xyz %xyz end", formatarg("xyz", 42), "Hello: 42 42 end"); TEST3("[%x, %y, %z]", formatarg("x", "X"), formatarg("y", "Y"), formatarg("z", "Z"), "[X, Y, Z]"); TEST3("[%z, %y, %x]", formatarg("x", "X"), formatarg("y", "Y"), formatarg("z", "Z"), "[Z, Y, X]"); TEST3("[%z, %y, %z]", formatarg("x", "X"), formatarg("y", "Y"), formatarg("z", "Z"), "[Z, Y, Z]"); TEST3("[%0x, %1y, %2z]", formatarg("x", "X"), formatarg("y", "Y"), formatarg("z", "Z"), "[Xx, Yy, Zz]"); TEST3("[%0x, %1y, %2z]", formatarg("x", "X"), formatarg("y", "Y"), formatarg("z", "Z"), "[Xx, Yy, Zz]"); TESTPF1("%0{f}", 42.125, "%f"); TESTPF1("%0{g}", 42.125, "%g"); TESTPF1("%0{G}", 42.125, "%G"); TESTPF1("%0{g}", 42.125e10, "%g"); TESTPF1("%0{G}", 42.125e10, "%G"); TESTPF1("%0{e}", 42.125, "%e"); TESTPF1("%0{E}", 42.125, "%E"); TESTPF1("%0{f.5}", 42.125, "%.5f"); TESTPF1("%0{f.0}", 42.125, "%.0f"); TESTPF1("%0{f8}", 42.125, "%8f"); TESTPF1("%0{f0}", 42.125, "%0f"); TESTPF1("%0{f#}", 42.125, "%#f"); TESTPF1("%0{f+}", 42.125, "%+f"); TESTPF1("%0{f-8.1}", 42.125, "%-8.1f"); TESTPF1("%0{f08}", 42.125, "%08f"); TESTPF1("%0{f+08}", 42.125, "%+08f"); TESTPF1("%0{f+08.2}", 42.125, "%+08.2f"); TESTPF1("%0{f08.2}", 42.125, "%08.2f"); TESTPF1("%0{f.5}", 42.0, "%.5f"); TESTPF1("%0{f.0}", 42.0, "%.0f"); TESTPF1("%0{f8}", 42.0, "%8f"); TESTPF1("%0{f0}", 42.0, "%0f"); TESTPF1("%0{f#}", 42.0, "%#f"); TESTPF1("%0{f+}", 42.0, "%+f"); TESTPF1("%0{f-8.1}", 42.0, "%-8.1f"); TESTPF1("%0{f08}", 42.0, "%08f"); TESTPF1("%0{f+08}", 42.0, "%+08f"); TESTPF1("%0{f+08.2}", 42.0, "%+08.2f"); TESTPF1("%0{f08.2}", 42.0, "%08.2f"); TEST1("%0{f }", 42.0, "%(err: bad format)"); TESTPF1("%0{i8}", 42, "%8i"); TESTPF1("%0{i0}", 42, "%0i"); TESTPF1("%0{i+}", 42, "%+i"); TESTPF1("%0{i-8}", 42, "%-8i"); TESTPF1("%0{i08}", 42, "%08i"); TESTPF1("%0{i+08}", 42, "%+08i"); TESTPF1("%0{i+8}", 42, "%+8i"); TESTPF1("%0{x02}", 93u, "%02x"); TEST1("%0{i.0}", 42, "%(err: bad format)"); TEST1("%0{i }", 42, "%(err: bad format)"); }
StationShipViewForm::StationShipViewForm(FormController *controller, int marketIndex) : BlankForm(controller), m_marketIndex(marketIndex) { m_station = Pi::player->GetDockedWith(); m_flavour = m_station->GetShipsOnSale()[marketIndex]; const ShipType &type = ShipType::types[m_flavour.type]; SetTitle(stringf(Lang::SOMEWHERE_SHIP_MARKET, formatarg("station", m_station->GetLabel()))); Add(new ShipSpinnerWidget(m_flavour, 400, 400), 0, 0); Gui::VBox *layoutBox = new Gui::VBox(); layoutBox->SetSpacing(10.0f); Add(layoutBox, 420, 0); Gui::HBox *statsBox = new Gui::HBox(); statsBox->SetSpacing(20.0f); layoutBox->PackEnd(statsBox); Gui::VBox *labelBox = new Gui::VBox(); labelBox->PackEnd(new Gui::Label(Lang::SHIP_TYPE)); labelBox->PackEnd(new Gui::Label(Lang::PRICE)); labelBox->PackEnd(new Gui::Label(Lang::PART_EX)); labelBox->PackEnd(new Gui::Label(Lang::REGISTRATION_ID)); labelBox->PackEnd(new Gui::Label(" ")); labelBox->PackEnd(new Gui::Label(Lang::WEIGHT_EMPTY)); labelBox->PackEnd(new Gui::Label(Lang::WEIGHT_FULLY_LADEN)); labelBox->PackEnd(new Gui::Label(Lang::CAPACITY)); labelBox->PackEnd(new Gui::Label(" ")); labelBox->PackEnd(new Gui::Label(Lang::FORWARD_ACCEL_EMPTY)); labelBox->PackEnd(new Gui::Label(Lang::FORWARD_ACCEL_LADEN)); labelBox->PackEnd(new Gui::Label(Lang::REVERSE_ACCEL_EMPTY)); labelBox->PackEnd(new Gui::Label(Lang::REVERSE_ACCEL_LADEN)); labelBox->PackEnd(new Gui::Label(" ")); labelBox->PackEnd(new Gui::Label(Lang::HYPERDRIVE_FITTED)); statsBox->PackEnd(labelBox); float forward_accel_empty = type.linThrust[ShipType::THRUSTER_FORWARD] / (-9.81f*1000.0f*(type.hullMass)); float forward_accel_laden = type.linThrust[ShipType::THRUSTER_FORWARD] / (-9.81f*1000.0f*(type.hullMass+type.capacity)); float reverse_accel_empty = -type.linThrust[ShipType::THRUSTER_REVERSE] / (-9.81f*1000.0f*(type.hullMass)); float reverse_accel_laden = -type.linThrust[ShipType::THRUSTER_REVERSE] / (-9.81f*1000.0f*(type.hullMass+type.capacity)); Gui::VBox *dataBox = new Gui::VBox(); dataBox->PackEnd(new Gui::Label(type.name)); dataBox->PackEnd(new Gui::Label(format_money(m_flavour.price))); dataBox->PackEnd(new Gui::Label(format_money(m_flavour.price - Pi::player->GetFlavour()->price))); dataBox->PackEnd(new Gui::Label(m_flavour.regid)); dataBox->PackEnd(new Gui::Label(" ")); dataBox->PackEnd(new Gui::Label(stringf(Lang::NUMBER_TONNES, formatarg("mass", type.hullMass)))); dataBox->PackEnd(new Gui::Label(stringf(Lang::NUMBER_TONNES, formatarg("mass", type.hullMass + type.capacity)))); dataBox->PackEnd(new Gui::Label(stringf( Lang::NUMBER_TONNES, formatarg("mass", type.capacity)))); dataBox->PackEnd(new Gui::Label(" ")); dataBox->PackEnd(new Gui::Label(stringf(Lang::NUMBER_G, formatarg("acceleration", forward_accel_empty)))); dataBox->PackEnd(new Gui::Label(stringf(Lang::NUMBER_G, formatarg("acceleration", forward_accel_laden)))); dataBox->PackEnd(new Gui::Label(stringf(Lang::NUMBER_G, formatarg("acceleration", reverse_accel_empty)))); dataBox->PackEnd(new Gui::Label(stringf(Lang::NUMBER_G, formatarg("acceleration", reverse_accel_laden)))); dataBox->PackEnd(new Gui::Label(" ")); dataBox->PackEnd(new Gui::Label(EquipType::types[type.hyperdrive].name)); statsBox->PackEnd(dataBox); Gui::HBox *row = new Gui::HBox(); row->SetSpacing(10.0f); int row_size = 5, pos = 0; for (int drivetype = Equip::DRIVE_CLASS1; drivetype <= Equip::DRIVE_CLASS9; drivetype++) { if (type.capacity < EquipType::types[drivetype].mass) break; int hyperclass = EquipType::types[drivetype].pval; // for the sake of hyperspace range, we count ships mass as 60% of original. float range = Pi::CalcHyperspaceRange(hyperclass, type.hullMass + type.capacity); Gui::VBox *cell = new Gui::VBox(); row->PackEnd(cell); cell->PackEnd(new Gui::Label(stringf(Lang::CLASS_NUMBER, formatarg("class", hyperclass)))); if (type.capacity < EquipType::types[drivetype].mass) cell->PackEnd(new Gui::Label("---")); else cell->PackEnd(new Gui::Label(stringf(Lang::NUMBER_LY, formatarg("distance", range)))); if (++pos == row_size) { layoutBox->PackEnd(row); row = new Gui::HBox(); row->SetSpacing(15.0f); pos = 0; } } if (pos > 0) layoutBox->PackEnd(row); Gui::HBox *buttonBox = new Gui::HBox(); buttonBox->SetSpacing(5.0f); Gui::SolidButton *b = new Gui::SolidButton(); b->onClick.connect(sigc::mem_fun(this, &StationShipViewForm::BuyShip)); buttonBox->PackEnd(b); buttonBox->PackEnd(new Gui::Label(Lang::BUY_THIS_SHIP)); Add(buttonBox, 650, 30); }