/* * Function: SpawnShipDocked * * Create a ship and place it inside the given <SpaceStation>. * * > ship = Space.SpawnShipDocked(type, station) * * Parameters: * * type - the name of the ship * * station - the <SpaceStation> to place the ship inside * * Return: * * ship - a <Ship> object for the new ship, or nil if there was no space * inside the station * * Availability: * * alpha 10 * * Status: * * stable */ static int l_space_spawn_ship_docked(lua_State *l) { if (!Pi::game) luaL_error(l, "Game is not started"); LUA_DEBUG_START(l); const char *type = luaL_checkstring(l, 1); if (! ShipType::Get(type)) luaL_error(l, "Unknown ship type '%s'", type); SpaceStation *station = LuaSpaceStation::CheckFromLua(2); int port = station->GetFreeDockingPort(); if (port < 0) return 0; Ship *ship = new Ship(type); assert(ship); ship->SetFrame(station->GetFrame()); Pi::game->GetSpace()->AddBody(ship); ship->SetDockedWith(station, port); LuaShip::PushToLua(ship); LUA_DEBUG_END(l, 1); return 1; }
void PlayerStatusBars :: Update (GameData& GlobalGameData) { PlayerDatabase* playerDb = GlobalGameData.GetPlayerDatabase(); player = playerDb->GetCurrentPlayer (); if (player == NULL) { PlayerName.clear(); NumberOfStationsBeingTracked = 0; } else { PlayerName = player->GetName(); NumberOfStationsBeingTracked = player->GetNumStations(); ShipArchetype* ship = player->GetShip (); PlayerShipTracking = static_cast<float>( ship->GetHealth () ); PlayerShipShieldTracking = static_cast<float>( ship->GetShieldLevel () ); for (int i=0; i<NumberOfStationsBeingTracked; i++) { SpaceStation* station = player->GetStation(i); StationTracking[i] = static_cast<float>( station->GetHealth () ); StationShieldTracking[i] = static_cast<float>( station->GetShieldLevel () ); } } }
Game::Game(const SystemPath &path, double time) : m_time(time), m_state(STATE_NORMAL), m_wantHyperspace(false), m_timeAccel(TIMEACCEL_1X), m_requestedTimeAccel(TIMEACCEL_1X), m_forceTimeAccel(false) { Pi::FlushCaches(); m_space.reset(new Space(this, path)); SpaceStation *station = static_cast<SpaceStation*>(m_space->FindBodyForPath(&path)); assert(station); m_player.reset(new Player("kanara")); m_space->AddBody(m_player.get()); m_player->SetFrame(station->GetFrame()); m_player->SetDockedWith(station, 0); Polit::Init(); CreateViews(); }
/* * Method: GetEquipmentPrice * * Get the price of an equipment or cargo item traded at this station * * > price = station:GetEquipmentPrice(equip) * * Parameters: * * equip - the <Constants.EquipType> string for the equipment or cargo item * * Returns: * * price - the price of the equipment or cargo item * * Availability: * * alpha 10 * * Status: * * experimental */ static int l_spacestation_get_equipment_price(lua_State *l) { SpaceStation *s = LuaSpaceStation::GetFromLua(1); Equip::Type e = static_cast<Equip::Type>(LuaConstants::GetConstant(l, "EquipType", luaL_checkstring(l, 2))); Sint64 cost = s->GetPrice(e); lua_pushnumber(l, cost * 0.01); return 1; }
/* * Method: GetGroundPosition * * Get latitude, longitude of a station on the ground or nil if this is an orbital station * * > latitude, longitude = station:GetGroundPosition() * * Returns: * * latitude - the latitude of the station in radians * longitude - the longitude of the station in radians * * Examples: * * > -- Get ground position of L.A. when starting on Earth * > local la = Game.player:GetDockedWith() * > local lat, long = la:GetGroundPosition() * > lat = math.rad2deg(lat) * > long = math.rad2deg(long) * * Availability: * * July 2013 * * Status: * * experimental */ static int l_spacestation_get_ground_position(lua_State *l) { SpaceStation *s = LuaObject<SpaceStation>::CheckFromLua(1); if (!s->IsGroundStation()) return 0; vector3d pos = s->GetPosition(); double latitude = atan2(pos.y, sqrt(pos.x*pos.x + pos.z * pos.z)); double longitude = atan2(pos.x, pos.z); lua_pushnumber(l, latitude); lua_pushnumber(l, longitude); return 2; }
/* * Method: AddAdvert * * Add an advertisement to the station's bulletin board * * > ref = station:AddAdvert(description, chatfunc, deletefunc) * * Parameters: * * description - text to display in the bulletin board * * chatfunc - function to call when the ad is activated. The function is * passed three parameters: a <ChatForm> object for the ad * conversation display, the ad reference returned by <AddAdvert> * when the ad was created, and an integer value corresponding to * the action that caused the activation. When the ad is initially * selected from the bulletin board, this value is 0. Additional * actions (and thus values) are defined by the script via * <ChatForm.AddAction>. * * deletefunc - optional. function to call when the ad is removed from the * bulletin board. This happens when <RemoveAdvert> is called, * when the ad is cleaned up after * <ChatForm.RemoveAdvertOnClose> is called, and when the * <SpaceStation> itself is destroyed (eg the player leaves the * system). * * Return: * * ref - an integer value for referring to the ad in the future. This value * will be passed to the ad's chat function and should be passed to * <RemoveAdvert> to remove the ad from the bulletin board. * * Example: * * > local ref = station:AddAdvert( * > "FAST SHIP to deliver a package to the Epsilon Eridani system.", * > function (ref, opt) ... end, * > function (ref) ... end * > ) * * Availability: * * alpha 10 * * Status: * * stable */ static int l_spacestation_add_advert(lua_State *l) { LUA_DEBUG_START(l); SpaceStation *s = LuaSpaceStation::GetFromLua(1); std::string description = luaL_checkstring(l, 2); if (!lua_isfunction(l, 3)) luaL_typerror(l, 3, lua_typename(l, LUA_TFUNCTION)); bool have_delete = false; if (lua_gettop(l) >= 4) { if (!lua_isnil(l, 4) && !lua_isfunction(l, 4)) luaL_typerror(l, 4, lua_typename(l, LUA_TFUNCTION)); have_delete = true; } int ref = s->AddBBAdvert(description, _create_chat_form); lua_getfield(l, LUA_REGISTRYINDEX, "PiAdverts"); if (lua_isnil(l, -1)) { lua_pop(l, 1); lua_newtable(l); lua_pushvalue(l, -1); lua_setfield(l, LUA_REGISTRYINDEX, "PiAdverts"); } lua_pushinteger(l, ref); lua_newtable(l); lua_pushstring(l, "onChat"); lua_pushvalue(l, 3); lua_settable(l, -3); if (have_delete) { lua_pushstring(l, "onDelete"); lua_pushvalue(l, 4); lua_settable(l, -3); } lua_settable(l, -3); lua_pop(l, 1); LUA_DEBUG_END(l,0); _register_for_station_delete(s); lua_pushinteger(l, ref); return 1; }
/* * Method: RemoveAdvert * * Remove an advertisement from the station's bulletin board * * > station:RemoveAdvert(ref) * * If the deletefunc parameter was supplied to <AddAdvert> when the ad was * created, it will be called as part of this call. * * Parameters: * * ref - the advert reference number returned by <AddAdvert> * * Availability: * * alpha 10 * * Status: * * stable */ static int l_spacestation_remove_advert(lua_State *l) { LUA_DEBUG_START(l); SpaceStation *s = LuaSpaceStation::GetFromLua(1); int ref = luaL_checkinteger(l, 2); if (!s->RemoveBBAdvert(ref)) return 0; lua_getfield(l, LUA_REGISTRYINDEX, "PiAdverts"); if (lua_isnil(l, -1)) { lua_pop(l, 1); return 0; } lua_pushinteger(l, ref); lua_gettable(l, -2); if (lua_isnil(l, -1)) { lua_pop(l, 2); return 0; } lua_getfield(l, -1, "onDelete"); if (lua_isnil(l, -1)) lua_pop(l, 1); else { lua_pushinteger(l, ref); pi_lua_protected_call(l, 1, 0); } lua_pop(l, 1); lua_pushinteger(l, ref); lua_pushnil(l); lua_settable(l, -3); lua_pop(l, 1); LUA_DEBUG_END(l,0); return 0; }
Game::Game(const SystemPath &path) : m_time(0), m_state(STATE_NORMAL), m_wantHyperspace(false), m_timeAccel(TIMEACCEL_1X), m_requestedTimeAccel(TIMEACCEL_1X), m_forceTimeAccel(false) { m_space.Reset(new Space(this, path)); SpaceStation *station = static_cast<SpaceStation*>(m_space->FindBodyForPath(&path)); assert(station); CreatePlayer(); m_space->AddBody(m_player.Get()); m_player->Enable(); m_player->SetFrame(station->GetFrame()); m_player->SetDockedWith(station, 0); CreateViews(); }
/* * Function: SpawnShipParked * * Create a ship and place it in one of the given <SpaceStation's> parking spots. * * > ship = Space.SpawnShipParked(type, station) * * For orbital stations the parking spots are some distance from the door, out * of the path of ships entering and leaving the station. For group stations * the parking spots are directly above the station, usually some distance * away. * * Parameters: * * type - the name of the ship * * station - the <SpaceStation> to place the near * * Return: * * ship - a <Ship> object for the new ship, or nil if there was no space * inside the station * Availability: * * alpha 10 * * Status: * * experimental */ static int l_space_spawn_ship_parked(lua_State *l) { if (!Pi::game) luaL_error(l, "Game is not started"); LUA_DEBUG_START(l); const char *type = luaL_checkstring(l, 1); if (! ShipType::Get(type)) luaL_error(l, "Unknown ship type '%s'", type); SpaceStation *station = LuaObject<SpaceStation>::CheckFromLua(2); int slot; if (!station->AllocateStaticSlot(slot)) return 0; Ship *ship = new Ship(type); assert(ship); double parkDist = station->GetStationType()->parkingDistance; parkDist -= ship->GetPhysRadius(); // park inside parking radius double parkOffset = 0.5 * station->GetStationType()->parkingGapSize; parkOffset += ship->GetPhysRadius(); // but outside the docking gap double xpos = (slot == 0 || slot == 3) ? -parkOffset : parkOffset; double zpos = (slot == 0 || slot == 1) ? -parkOffset : parkOffset; vector3d parkPos = vector3d(xpos, parkDist, zpos); parkPos = station->GetPosition() + station->GetOrient() * parkPos; // orbital stations have Y as axis of rotation matrix3x3d rot = matrix3x3d::RotateX(M_PI/2) * station->GetOrient(); ship->SetFrame(station->GetFrame()); ship->SetVelocity(vector3d(0.0)); ship->SetPosition(parkPos); ship->SetOrient(rot); Pi::game->GetSpace()->AddBody(ship); ship->AIHoldPosition(); LuaObject<Ship>::PushToLua(ship); LUA_DEBUG_END(l, 1); return 1; }
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 NotifyOfCrime(Ship *s, enum Crime crime) { // ignore crimes of NPCs for the time being if (s != (Ship*)Pi::player) return; // find nearest starport to this evil criminal SpaceStation *station = static_cast<SpaceStation*>(Space::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(512, "%s cannot be tolerated here.", crimeNames[crimeIdx])); float lawlessness = Pi::currentSystem->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 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; } } }
/* * Attribute: numShipsDocked * * The number of ships docked at spacestation * * Availability: * * 201404 * * Status: * * experimental */ static int l_spacestation_attr_num_ships_docked(lua_State *l) { SpaceStation *s = LuaObject<SpaceStation>::CheckFromLua(1); lua_pushinteger(l, s->NumShipsDocked()); return 1; }
void Pi::HandleEvents() { SDL_Event event; Pi::mouseMotion[0] = Pi::mouseMotion[1] = 0; while (SDL_PollEvent(&event)) { Gui::HandleSDLEvent(&event); switch (event.type) { case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) { // only accessible once game started if (currentView != 0) { if (currentView != gameMenuView) { RequestTimeAccel(0); SetTimeAccel(0); SetView(gameMenuView); } else RequestTimeAccel(1); } break; } // special keys. LCTRL+turd if ((KeyState(SDLK_LCTRL) || (KeyState(SDLK_RCTRL)))) { if (event.key.keysym.sym == SDLK_q) Pi::Quit(); if (event.key.keysym.sym == SDLK_s) { Render::ToggleShaders(); } if (event.key.keysym.sym == SDLK_h) { Render::ToggleHDR(); } if (event.key.keysym.sym == SDLK_i) Pi::showDebugInfo = !Pi::showDebugInfo; if (event.key.keysym.sym == SDLK_p) { Sint64 crime, fine; Polit::GetCrime(&crime, &fine); printf("Criminal record: %llx, $%lld\n", crime, fine); Polit::AddCrime(0x1, 100); Polit::GetCrime(&crime, &fine); printf("Criminal record now: %llx, $%lld\n", crime, fine); } if (event.key.keysym.sym == SDLK_PRINT) { 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.tga", _tm); Screendump(buf); fprintf(stderr, "Screendump to %s\n", buf); } #ifdef DEBUG if (event.key.keysym.sym == SDLK_m) { Pi::player->SetMoney(Pi::player->GetMoney() + 10000000); } if (event.key.keysym.sym == SDLK_F12) { matrix4x4d m; Pi::player->GetRotMatrix(m); vector3d dir = m*vector3d(0,0,-1); /* add test object */ if (KeyState(SDLK_RSHIFT)) { Missile *missile = new Missile(ShipType::MISSILE_GUIDED, Pi::player, Pi::player->GetCombatTarget()); missile->SetRotMatrix(m); missile->SetFrame(Pi::player->GetFrame()); missile->SetPosition(Pi::player->GetPosition()+50.0*dir); missile->SetVelocity(Pi::player->GetVelocity()); Space::AddBody(missile); } else if (KeyState(SDLK_LSHIFT)) { SpaceStation *s = static_cast<SpaceStation*>(Pi::player->GetNavTarget()); if (s) { int port = s->GetFreeDockingPort(); if (port != -1) { printf("Putting ship into station\n"); // Make police ship intent on killing the player Ship *ship = new Ship(ShipType::LADYBIRD); ship->AIKill(Pi::player); ship->SetFrame(Pi::player->GetFrame()); ship->SetDockedWith(s, port); Space::AddBody(ship); } else { printf("No docking ports free dude\n"); } } else { printf("Select a space station...\n"); } } else { Ship *ship = new Ship(ShipType::LADYBIRD); ship->m_equipment.Set(Equip::SLOT_LASER, 0, Equip::PULSECANNON_1MW); ship->AIKill(Pi::player); ship->SetFrame(Pi::player->GetFrame()); ship->SetPosition(Pi::player->GetPosition()+100.0*dir); ship->SetVelocity(Pi::player->GetVelocity()); ship->m_equipment.Add(Equip::DRIVE_CLASS2); ship->m_equipment.Add(Equip::RADAR_MAPPER); ship->m_equipment.Add(Equip::SCANNER); ship->m_equipment.Add(Equip::SHIELD_GENERATOR); ship->m_equipment.Add(Equip::HYDROGEN, 10); Space::AddBody(ship); } } #endif /* DEBUG */ // XXX only works on X11 //if (event.key.keysym.sym == SDLK_F11) SDL_WM_ToggleFullScreen(Pi::scrSurface); if (event.key.keysym.sym == SDLK_F10) Pi::SetView(Pi::objectViewerView); if (event.key.keysym.sym == SDLK_F9) { std::string name = join_path(GetFullSavefileDirPath().c_str(), "_quicksave", 0); Serializer::SaveGame(name.c_str()); Pi::cpan->MsgLog()->Message("", "Game saved to "+name); } } Pi::keyState[event.key.keysym.sym] = 1; Pi::keyModState = event.key.keysym.mod; Pi::onKeyPress.emit(&event.key.keysym); break; case SDL_KEYUP: Pi::keyState[event.key.keysym.sym] = 0; Pi::keyModState = event.key.keysym.mod; Pi::onKeyRelease.emit(&event.key.keysym); break; case SDL_MOUSEBUTTONDOWN: Pi::mouseButton[event.button.button] = 1; Pi::onMouseButtonDown.emit(event.button.button, event.button.x, event.button.y); break; case SDL_MOUSEBUTTONUP: Pi::mouseButton[event.button.button] = 0; Pi::onMouseButtonUp.emit(event.button.button, event.button.x, event.button.y); 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 == NULL) 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 == NULL) break; joysticks[event.jbutton.which].buttons[event.jbutton.button] = event.jbutton.state != 0; break; case SDL_JOYHATMOTION: if (joysticks[event.jaxis.which].joystick == NULL) break; joysticks[event.jhat.which].hats[event.jhat.hat] = event.jhat.value; break; case SDL_QUIT: Pi::Quit(); break; } } }
void Pi::Start() { WorldView *view = new WorldView(); Gui::Fixed *splash = new Gui::Fixed(Gui::Screen::GetWidth(), Gui::Screen::GetHeight()); Gui::Screen::AddBaseWidget(splash, 0, 0); splash->SetTransparency(true); const float w = Gui::Screen::GetWidth() / 2; const float h = Gui::Screen::GetHeight() / 2; const int OPTS = 5; Gui::ToggleButton *opts[OPTS]; opts[0] = new Gui::ToggleButton(); opts[0]->SetShortcut(SDLK_1, KMOD_NONE); opts[1] = new Gui::ToggleButton(); opts[1]->SetShortcut(SDLK_2, KMOD_NONE); opts[2] = new Gui::ToggleButton(); opts[2]->SetShortcut(SDLK_3, KMOD_NONE); opts[3] = new Gui::ToggleButton(); opts[3]->SetShortcut(SDLK_4, KMOD_NONE); opts[4] = new Gui::ToggleButton(); opts[4]->SetShortcut(SDLK_5, KMOD_NONE); splash->Add(opts[0], w, h-64); splash->Add(new Gui::Label("New game starting on Earth"), w+32, h-64); splash->Add(opts[1], w, h-32); splash->Add(new Gui::Label("New game starting on Epsilon Eridani"), w+32, h-32); splash->Add(opts[2], w, h); splash->Add(new Gui::Label("New game starting on debug point"), w+32, h); splash->Add(opts[3], w, h+32); splash->Add(new Gui::Label("Load a saved game"), w+32, h+32); splash->Add(opts[4], w, h+64); splash->Add(new Gui::Label("Quit"), w+32, h+64); splash->ShowAll(); int choice = 0; Uint32 last_time = SDL_GetTicks(); float _time = 0; do { Pi::HandleEvents(); Render::PrepareFrame(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float fracH = 1.0 / Pi::GetScrAspect(); glFrustum(-1, 1, -fracH, fracH, 1.0f, 10000.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SDL_ShowCursor(1); SDL_WM_GrabInput(SDL_GRAB_OFF); draw_intro(view, _time); Render::PostProcess(); Gui::Draw(); Render::SwapBuffers(); Pi::frameTime = 0.001*(SDL_GetTicks() - last_time); _time += Pi::frameTime; last_time = SDL_GetTicks(); // poll ui instead of using callbacks :-J for (int i=0; i<OPTS; i++) if (opts[i]->GetPressed()) choice = i+1; } while (!choice); splash->HideAll(); Gui::Screen::RemoveBaseWidget(splash); delete splash; delete view; InitGame(); if (choice == 1) { /* Earth start point */ SBodyPath path(0,0,0); Space::DoHyperspaceTo(&path); //Frame *pframe = *(++(++(Space::rootFrame->m_children.begin()))); //player->SetFrame(pframe); // XXX there isn't a sensible way to find stations for a planet. SpaceStation *station = 0; for (Space::bodiesIter_t i = Space::bodies.begin(); i!=Space::bodies.end(); i++) { if ((*i)->IsType(Object::SPACESTATION)) { station = (SpaceStation*)*i; break; } } assert(station); player->SetPosition(vector3d(0,0,0)); player->SetFrame(station->GetFrame()); player->SetDockedWith(station, 0); MainLoop(); } else if (choice == 2) { /* Epsilon Eridani start point */ SBodyPath path(1,0,2); Space::DoHyperspaceTo(&path); // XXX there isn't a sensible way to find stations for a planet. SpaceStation *station = 0; for (Space::bodiesIter_t i = Space::bodies.begin(); i!=Space::bodies.end(); i++) { if ((*i)->IsType(Object::SPACESTATION)) { station = (SpaceStation*)*i; if (!station->IsGroundStation()) break; } } assert(station); player->SetPosition(vector3d(0,0,0)); player->SetFrame(station->GetFrame()); player->SetDockedWith(station, 0); MainLoop(); } else if (choice == 3) { /* debug start point */ SBodyPath path(1,0,2); path.sbodyId = 6; Space::DoHyperspaceTo(&path); player->SetPosition(vector3d(2*EARTH_RADIUS,0,0)); player->SetVelocity(vector3d(0,0,0)); player->m_equipment.Add(Equip::HYPERCLOUD_ANALYZER); Ship *enemy = new Ship(ShipType::EAGLE_LRF); enemy->SetFrame(player->GetFrame()); enemy->SetPosition(player->GetPosition()+vector3d(0,0,-9000.0)); enemy->SetVelocity(vector3d(0,0,0)); enemy->m_equipment.Add(Equip::PULSECANNON_1MW); enemy->AIKill(player); Space::AddBody(enemy); player->SetCombatTarget(enemy); const ShipType *shipdef; double mass, acc1, acc2, acc3; printf("Player ship mass = %.0fkg, Enemy ship mass = %.0fkg\n", player->GetMass(), enemy->GetMass()); shipdef = &player->GetShipType(); mass = player->GetMass(); acc1 = shipdef->linThrust[ShipType::THRUSTER_FORWARD] / (9.81*mass); acc2 = shipdef->linThrust[ShipType::THRUSTER_REVERSE] / (9.81*mass); acc3 = shipdef->linThrust[ShipType::THRUSTER_UP] / (9.81*mass); printf("Player ship thrust = %.1fg, %.1fg, %.1fg\n", acc1, acc2, acc3); shipdef = &enemy->GetShipType(); mass = enemy->GetMass(); acc1 = shipdef->linThrust[ShipType::THRUSTER_FORWARD] / (9.81*mass); acc2 = shipdef->linThrust[ShipType::THRUSTER_REVERSE] / (9.81*mass); acc3 = shipdef->linThrust[ShipType::THRUSTER_UP] / (9.81*mass); printf("Enemy ship thrust = %.1fg, %.1fg, %.1fg\n", acc1, acc2, acc3); /* Frame *stationFrame = new Frame(pframe, "Station frame..."); stationFrame->SetRadius(5000); stationFrame->m_sbody = 0; stationFrame->SetPosition(vector3d(0,0,zpos)); stationFrame->SetAngVelocity(vector3d(0,0,0.5)); for (int i=0; i<4; i++) { Ship *body = new Ship(ShipType::LADYBIRD); char buf[64]; snprintf(buf,sizeof(buf),"X%c-0%02d", 'A'+i, i); body->SetLabel(buf); body->SetFrame(stationFrame); body->SetPosition(vector3d(200*(i+1), 0, 2000)); Space::AddBody(body); } SpaceStation *station = new SpaceStation(SpaceStation::JJHOOP); station->SetLabel("Poemi-chan's Folly"); station->SetFrame(stationFrame); station->SetPosition(vector3d(0,0,0)); Space::AddBody(station); SpaceStation *station2 = new SpaceStation(SpaceStation::GROUND_FLAVOURED); station2->SetLabel("Conor's End"); station2->SetFrame(*pframe->m_children.begin()); // rotating frame of planet station2->OrientOnSurface(EARTH_RADIUS, M_PI/4, M_PI/4); Space::AddBody(station2); */ // player->SetDockedWith(station2, 0); MainLoop(); } else if (choice == 4) { if (Pi::player) { Pi::player->MarkDead(); Space::bodies.remove(Pi::player); delete Pi::player; Pi::player = 0; } Pi::gameMenuView->OpenLoadDialog(); do { Gui::MainLoopIteration(); } while (Pi::currentView != Pi::worldView); if (Pi::isGameStarted) MainLoop(); } else { Pi::Quit(); } UninitGame(); }
/* * Function: SpawnShipParked * * Create a ship and place it in one of the given <SpaceStation's> parking spots. * * > ship = Space.SpawnShipParked(type, station) * * For orbital stations the parking spots are some distance from the door, out * of the path of ships entering and leaving the station. For group stations * the parking spots are directly above the station, usually some distance * away. * * Parameters: * * type - the name of the ship * * station - the <SpaceStation> to place the near * * Return: * * ship - a <Ship> object for the new ship, or nil if there was no space * inside the station * Availability: * * alpha 10 * * Status: * * experimental */ static int l_space_spawn_ship_parked(lua_State *l) { if (!Pi::game) luaL_error(l, "Game is not started"); LUA_DEBUG_START(l); const char *type = luaL_checkstring(l, 1); if (! ShipType::Get(type)) luaL_error(l, "Unknown ship type '%s'", type); SpaceStation *station = LuaSpaceStation::CheckFromLua(2); int slot; if (!station->AllocateStaticSlot(slot)) return 0; Ship *ship = new Ship(type); assert(ship); vector3d pos, vel; matrix4x4d rot = matrix4x4d::Identity(); if (station->GetSystemBody()->type == SystemBody::TYPE_STARPORT_SURFACE) { vel = vector3d(0.0); // XXX on tiny planets eg asteroids force this to be larger so the // are out of the docking path pos = station->GetPosition() * 1.1; station->GetRotMatrix(rot); vector3d axis1, axis2; axis1 = pos.Cross(vector3d(0.0,1.0,0.0)); axis2 = pos.Cross(axis1); double ang = atan((140 + ship->GetLmrCollMesh()->GetBoundingRadius()) / pos.Length()); if (slot<2) ang = -ang; vector3d axis = (slot == 0 || slot == 3) ? axis1 : axis2; pos.ArbRotate(axis, ang); } else { double dist = 100 + ship->GetLmrCollMesh()->GetBoundingRadius(); double xpos = (slot == 0 || slot == 3) ? -dist : dist; double zpos = (slot == 0 || slot == 1) ? -dist : dist; pos = vector3d(xpos,5000,zpos); vel = vector3d(0.0); rot.RotateX(M_PI/2); } ship->SetFrame(station->GetFrame()); ship->SetVelocity(vel); ship->SetPosition(pos); ship->SetRotMatrix(rot); Pi::game->GetSpace()->AddBody(ship); ship->AIHoldPosition(); LuaShip::PushToLua(ship); LUA_DEBUG_END(l, 1); return 1; }
void Pi::HandleEvents() { SDL_Event event; Pi::mouseMotion[0] = Pi::mouseMotion[1] = 0; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { if (Pi::game) Pi::EndGame(); Pi::Quit(); } else if (ui->DispatchSDLEvent(event)) continue; Gui::HandleSDLEvent(&event); if (!Pi::IsConsoleActive()) KeyBindings::DispatchSDLEvent(&event); else KeyBindings::toggleLuaConsole.CheckSDLEventAndDispatch(&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 != gameMenuView) { Pi::game->SetTimeAccel(Game::TIMEACCEL_PAUSED); SetView(gameMenuView); } else { Pi::game->RequestTimeAccel(Game::TIMEACCEL_1X); SetView(Pi::player->IsDead() ? static_cast<View*>(deathView) : static_cast<View*>(worldView)); } } } 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_PRINT: // 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); Screendump(buf, Graphics::GetScreenWidth(), Graphics::GetScreenHeight()); break; } #if WITH_DEVKEYS case SDLK_i: // Toggle Debug info Pi::showDebugInfo = !Pi::showDebugInfo; break; case SDLK_m: // Gimme money! if(Pi::game) { Pi::player->SetMoney(Pi::player->GetMoney() + 10000000); } break; 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, Pi::player->GetCombatTarget()); 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); } else if (KeyState(SDLK_LSHIFT)) { SpaceStation *s = static_cast<SpaceStation*>(Pi::player->GetNavTarget()); if (s) { int port = s->GetFreeDockingPort(); if (port != -1) { printf("Putting ship into station\n"); // Make police ship intent on killing the player Ship *ship = new Ship(ShipType::LADYBIRD); ship->AIKill(Pi::player); ship->SetFrame(Pi::player->GetFrame()); ship->SetDockedWith(s, port); game->GetSpace()->AddBody(ship); } else { printf("No docking ports free dude\n"); } } else { printf("Select a space station...\n"); } } else { Ship *ship = new Ship(ShipType::LADYBIRD); ship->m_equipment.Set(Equip::SLOT_LASER, 0, Equip::PULSECANNON_1MW); ship->AIKill(Pi::player); ship->SetFrame(Pi::player->GetFrame()); ship->SetPosition(Pi::player->GetPosition()+100.0*dir); ship->SetVelocity(Pi::player->GetVelocity()); ship->m_equipment.Add(Equip::DRIVE_CLASS2); ship->m_equipment.Add(Equip::RADAR_MAPPER); ship->m_equipment.Add(Equip::SCANNER); ship->m_equipment.Add(Equip::SHIELD_GENERATOR); ship->m_equipment.Add(Equip::HYDROGEN, 10); ship->UpdateStats(); game->GetSpace()->AddBody(ship); } } break; } #endif /* DEVKEYS */ #if WITH_OBJECTVIEWER case SDLK_F10: Pi::SetView(Pi::objectViewerView); 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::cpan->MsgLog()->Message("", 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::cpan->MsgLog()->Message("", Lang::GAME_SAVED_TO + path); } catch (CouldNotOpenFileException) { Pi::cpan->MsgLog()->Message("", stringf(Lang::COULD_NOT_OPEN_FILENAME, formatarg("path", path))); } catch (CouldNotWriteToFileException) { Pi::cpan->MsgLog()->Message("", Lang::GAME_SAVE_CANNOT_WRITE); } } } break; } default: break; // This does nothing but it stops the compiler warnings } } Pi::keyState[event.key.keysym.sym] = 1; Pi::keyModState = event.key.keysym.mod; Pi::onKeyPress.emit(&event.key.keysym); break; case SDL_KEYUP: Pi::keyState[event.key.keysym.sym] = 0; 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_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 == NULL) 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 == NULL) break; joysticks[event.jbutton.which].buttons[event.jbutton.button] = event.jbutton.state != 0; break; case SDL_JOYHATMOTION: if (joysticks[event.jaxis.which].joystick == NULL) break; joysticks[event.jhat.which].hats[event.jhat.hat] = event.jhat.value; break; } } }
/* * Attribute: isGroundStation * * true if station is on the ground, false if its an orbital * * Availability: * * alpha 30 * * Status: * * experimental */ static int l_spacestation_attr_is_ground_station(lua_State *l) { SpaceStation *s = LuaObject<SpaceStation>::CheckFromLua(1); lua_pushboolean(l, s->IsGroundStation()); return 1; }
/* * Attribute: numDocks * * The number of docking ports a spacestation has. * * Availability: * * alpha 21 * * Status: * * experimental */ static int l_spacestation_attr_num_docks(lua_State *l) { SpaceStation *s = LuaObject<SpaceStation>::CheckFromLua(1); lua_pushinteger(l, s->GetDockingPortCount()); return 1; }
void Pi::HandleKeyDown(SDL_Keysym *key) { if (key->sym == SDLK_ESCAPE) { if (Pi::game) { // only accessible once game started HandleEscKey(); } return; } const bool CTRL = input.KeyState(SDLK_LCTRL) || input.KeyState(SDLK_RCTRL); // special keys. if (CTRL) { switch (key->sym) { case SDLK_q: // Quit Pi::RequestQuit(); 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; } case SDLK_SCROLLLOCK: // toggle video recording Pi::isRecordingVideo = !Pi::isRecordingVideo; if (Pi::isRecordingVideo) { char videoName[256]; const time_t t = time(0); struct tm *_tm = localtime(&t); strftime(videoName, sizeof(videoName), "pioneer-%Y%m%d-%H%M%S", _tm); const std::string dir = "videos"; FileSystem::userFiles.MakeDirectory(dir); const std::string fname = FileSystem::JoinPathBelow(FileSystem::userFiles.GetRoot() + "/" + dir, videoName); Output("Video Recording started to %s.\n", fname.c_str()); // start ffmpeg telling it to expect raw rgba 720p-60hz frames // -i - tells it to read frames from stdin // if given no frame rate (-r 60), it will just use vfr char cmd[256] = { 0 }; snprintf(cmd, sizeof(cmd), "ffmpeg -f rawvideo -pix_fmt rgba -s %dx%d -i - -threads 0 -preset fast -y -pix_fmt yuv420p -crf 21 -vf vflip %s.mp4", config->Int("ScrWidth"), config->Int("ScrHeight"), fname.c_str()); // open pipe to ffmpeg's stdin in binary write mode #if defined(_MSC_VER) || defined(__MINGW32__) Pi::ffmpegFile = _popen(cmd, "wb"); #else Pi::ffmpegFile = _popen(cmd, "w"); #endif } else { Output("Video Recording ended.\n"); if (Pi::ffmpegFile != nullptr) { _pclose(Pi::ffmpegFile); Pi::ffmpegFile = nullptr; } } 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 (input.KeyState(SDLK_LSHIFT) || input.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 (input.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 (input.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 (!input.KeyState(SDLK_LALT)) { //Left ALT = no AI if (!input.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 } } }