/* * Attribute: shipId * * The internal id of the ship type. This value can be passed to * <ShipType.GetShipType> to retrieve information about this ship type. * * Availability: * * alpha 28 * * Status: * * stable */ static int l_ship_attr_ship_id(lua_State *l) { Ship *s = LuaObject<Ship>::CheckFromLua(1); const ShipType &st = s->GetShipType(); lua_pushstring(l, st.id.c_str()); return 1; }
void Game::SwitchToNormalSpace() { // remove the player from hyperspace m_space->RemoveBody(m_player.Get()); // create a new space for the system const SystemPath &dest = m_player->GetHyperspaceDest(); m_space.Reset(new Space(this, dest)); // put the player in it m_player->SetFrame(m_space->GetRootFrame()); m_space->AddBody(m_player.Get()); // place it m_player->SetPosition(m_space->GetHyperspaceExitPoint(m_hyperspaceSource)); m_player->SetVelocity(vector3d(0,0,-100.0)); m_player->SetRotMatrix(matrix4x4d::Identity()); // place the exit cloud HyperspaceCloud *cloud = new HyperspaceCloud(0, Pi::game->GetTime(), true); cloud->SetFrame(m_space->GetRootFrame()); cloud->SetPosition(m_player->GetPosition()); m_space->AddBody(cloud); for (std::list<HyperspaceCloud*>::iterator i = m_hyperspaceClouds.begin(); i != m_hyperspaceClouds.end(); ++i) { cloud = *i; cloud->SetFrame(m_space->GetRootFrame()); cloud->SetPosition(m_space->GetHyperspaceExitPoint(m_hyperspaceSource)); m_space->AddBody(cloud); if (cloud->GetDueDate() < Pi::game->GetTime()) { // they emerged from hyperspace some time ago Ship *ship = cloud->EvictShip(); ship->SetFrame(m_space->GetRootFrame()); ship->SetVelocity(vector3d(0,0,-100.0)); ship->SetRotMatrix(matrix4x4d::Identity()); ship->Enable(); ship->SetFlightState(Ship::FLYING); const SystemPath &sdest = ship->GetHyperspaceDest(); if (sdest.IsSystemPath()) { // travelling to the system as a whole, so just dump them on // the cloud - we can't do any better in this case ship->SetPosition(cloud->GetPosition()); } else { // on their way to a body. they're already in-system so we // want to simulate some travel to their destination. we // naively assume full accel for half the distance, flip and // full brake for the rest. Body *target_body = m_space->FindBodyForPath(&sdest); double dist_to_target = cloud->GetPositionRelTo(target_body).Length(); double half_dist_to_target = dist_to_target / 2.0; double accel = -(ship->GetShipType().linThrust[ShipType::THRUSTER_FORWARD] / ship->GetMass()); double travel_time = Pi::game->GetTime() - cloud->GetDueDate(); // I can't help but feel some actual math would do better here double speed = 0; double dist = 0; while (travel_time > 0 && dist <= half_dist_to_target) { speed += accel; dist += speed; travel_time--; } while (travel_time > 0 && dist < dist_to_target) { speed -= accel; dist += speed; travel_time--; } if (travel_time <= 0) { vector3d pos = target_body->GetPositionRelTo(m_space->GetRootFrame()) + cloud->GetPositionRelTo(target_body).Normalized() * (dist_to_target - dist); ship->SetPosition(pos); } else { // ship made it with time to spare. just put it somewhere // near the body. the script should be issuing a dock or // flyto command in onEnterSystem so it should sort it // itself out long before the player can get near SystemBody *sbody = m_space->GetStarSystem()->GetBodyByPath(&sdest); if (sbody->type == SystemBody::TYPE_STARPORT_ORBITAL) { ship->SetFrame(target_body->GetFrame()); ship->SetPosition(MathUtil::RandomPointOnSphere(1000.0)*1000.0); // somewhere 1000km out } else { if (sbody->type == SystemBody::TYPE_STARPORT_SURFACE) { sbody = sbody->parent; SystemPath path = m_space->GetStarSystem()->GetPathOf(sbody); target_body = m_space->FindBodyForPath(&path); } double sdist = sbody->GetRadius()*2.0; ship->SetFrame(target_body->GetFrame()); ship->SetPosition(MathUtil::RandomPointOnSphere(sdist)); } } } m_space->AddBody(ship); LuaEvent::Queue("onEnterSystem", ship); } } m_hyperspaceClouds.clear(); m_state = STATE_NORMAL; }
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(); }
void Ship::UpdateAlertState() { // no alerts if no scanner if (m_equipment.Get(Equip::SLOT_SCANNER) == Equip::NONE) { // clear existing alert state if there was one if (GetAlertState() != ALERT_NONE) { SetAlertState(ALERT_NONE); LuaEvent::Queue("onShipAlertChanged", this, LuaConstants::GetConstantString(Lua::manager->GetLuaState(), "ShipAlertStatus", ALERT_NONE)); } return; } bool ship_is_near = false, ship_is_firing = false; for (Space::BodyIterator i = Pi::game->GetSpace()->BodiesBegin(); i != Pi::game->GetSpace()->BodiesEnd(); ++i) { if ((*i) == this) continue; if (!(*i)->IsType(Object::SHIP) || (*i)->IsType(Object::MISSILE)) continue; Ship *ship = static_cast<Ship*>(*i); if (ship->GetShipType().tag == ShipType::TAG_STATIC_SHIP) continue; if (ship->GetFlightState() == LANDED || ship->GetFlightState() == DOCKED) continue; if (GetPositionRelTo(ship).LengthSqr() < 100000.0*100000.0) { ship_is_near = true; Uint32 gunstate = 0; for (int j = 0; j < ShipType::GUNMOUNT_MAX; j++) gunstate |= ship->m_gunState[j]; if (gunstate) { ship_is_firing = true; break; } } } bool changed = false; switch (m_alertState) { case ALERT_NONE: if (ship_is_near) { SetAlertState(ALERT_SHIP_NEARBY); changed = true; } if (ship_is_firing) { m_lastFiringAlert = Pi::game->GetTime(); SetAlertState(ALERT_SHIP_FIRING); changed = true; } break; case ALERT_SHIP_NEARBY: if (!ship_is_near) { SetAlertState(ALERT_NONE); changed = true; } else if (ship_is_firing) { m_lastFiringAlert = Pi::game->GetTime(); SetAlertState(ALERT_SHIP_FIRING); changed = true; } break; case ALERT_SHIP_FIRING: if (!ship_is_near) { SetAlertState(ALERT_NONE); changed = true; } else if (ship_is_firing) { m_lastFiringAlert = Pi::game->GetTime(); } else if (m_lastFiringAlert + 60.0 <= Pi::game->GetTime()) { SetAlertState(ALERT_SHIP_NEARBY); changed = true; } break; } if (changed) LuaEvent::Queue("onShipAlertChanged", this, LuaConstants::GetConstantString(Lua::manager->GetLuaState(), "ShipAlertStatus", GetAlertState())); }