예제 #1
0
파일: save.c 프로젝트: isfos/naev
/**
 * @brief Actually loads a new game based on file.
 *
 *    @param file File that contains the new game.
 *    @return 0 on success.
 */
static int load_game( const char* file )
{
   xmlNodePtr node;
   xmlDocPtr doc;

   /* Make sure it exists. */
   if (!nfile_fileExists(file)) {
      dialogue_alert("Savegame file seems to have been deleted.");
      return -1;
   }

   /* Load the XML. */
   doc   = xmlParseFile(file);
   if (doc == NULL)
      goto err;
   node  = doc->xmlChildrenNode; /* base node */
   if (node == NULL)
      goto err_doc;

   /* Clean up possible stuff that should be cleaned. */
   player_cleanup();
   diff_clear();
   var_cleanup();
   missions_cleanup();
   events_cleanup();

   /* Welcome message - must be before space_init. */
   player_message( "\egWelcome to "APPNAME"!" );
   player_message( "\eg v%d.%d.%d", VMAJOR, VMINOR, VREV );

   /* Now begin to load. */
   diff_load(node); /* Must load first to work properly. */
   pfaction_load(node); /* Must be loaded before player so the messages show up properly. */
   player_load(node);
   var_load(node);
   missions_loadActive(node);
   hook_load(node);
   space_sysLoad(node);

   /* Initialize the economy. */
   economy_init();

   /* Need to run takeoff hooks since player just "took off" */
   hooks_run("takeoff");
   player_addEscorts();
   hooks_run("enter");
   events_trigger( EVENT_TRIGGER_ENTER );

   xmlFreeDoc(doc);
   xmlCleanupParser();
   
   return 0;

err_doc:
   xmlFreeDoc(doc);
   xmlCleanupParser();
err:
   WARN("Savegame '%s' invalid!", file);
   return -1;
}
예제 #2
0
파일: land.c 프로젝트: mchelen/naev
/**
 * @brief Opens up all the land dialogue stuff.
 *    @param p Planet to open stuff for.
 *    @param load Whether or not loading the game.
 */
void land( Planet* p, int load )
{
   /* Do not land twice. */
   if (landed)
      return;

   /* Resets the player's heat. */
   pilot_heatReset( player.p );

   /* Stop player sounds. */
   player_soundStop();

   /* Load stuff */
   land_planet = p;
   gfx_exterior = gl_newImage( p->gfx_exterior, 0 );

   /* Generate the news. */
   if (planet_hasService(land_planet, PLANET_SERVICE_BAR))
      news_load();

   /* Clear the NPC. */
   npc_clear();

   /* Create all the windows. */
   land_genWindows( load, 0 );

   /* Hack so that load can run player.takeoff(). */
   if (load)
      hooks_run( "load" );

   /* Mission forced take off. */
   if (land_takeoff)
      takeoff(0);
}
예제 #3
0
파일: nlua_player.c 프로젝트: Delll/naev
/**
 * @brief Teleports the player to a new system.
 *
 * Does not change the position nor velocity of the player, which will probably be wrong in the new system.
 *
 * @usage player.teleport( system.get("Arcanis") ) -- Teleports the player to arcanis.
 *
 *    @luaparam sys System to teleport the player to.
 * @luafunc teleport( sys )
 */
static int playerL_teleport( lua_State *L )
{
   LuaSystem *sys;

   /* Get a system. */
   sys = luaL_checksystem(L,1);

   /* Go to the new system. */
   space_init( sys->s->name );

   /* Run hooks - order is important. */
   hooks_run( "jumpout" );
   hooks_run( "jumpin" );
   hooks_run( "enter" );

   /* Map gets deformed when jumping this way. */
   map_clear();

   return 0;
}
예제 #4
0
파일: nlua_player.c 프로젝트: s0be/naev
/**
 * @brief Teleports the player to a new system (only if not landed).
 *
 * Does not change the position nor velocity of the player.p, which will probably be wrong in the new system.
 *
 * @usage player.teleport( system.get("Arcanis") ) -- Teleports the player to arcanis.
 * @usage player.teleport( "Arcanis" ) -- Teleports the player to arcanis.
 *
 *    @luaparam sys System or name of a system to teleport the player to.
 * @luafunc teleport( sys )
 */
static int playerL_teleport( lua_State *L )
{
   LuaSystem *sys;
   const char *name;

   /* Must not be landed. */
   if (landed)
      NLUA_ERROR(L,"Can not teleport the player while landed!");
   if (comm_isOpen())
      NLUA_ERROR(L,"Can not teleport the player while the comm is open!");
   if (player_isBoarded())
      NLUA_ERROR(L,"Can not teleport the player while he is boarded!");

   /* Get a system. */
   if (lua_issystem(L,1)) {
      sys   = lua_tosystem(L,1);
      name  = system_getIndex(sys->id)->name;
   }
   else if (lua_isstring(L,1))
      name = lua_tostring(L,1);
   else
      NLUA_INVALID_PARAMETER(L);

   /* Check if system exists. */
   if (!system_exists( name )) {
      NLUA_ERROR( L, "System '%s' does not exist.", name );
      return 0;
   }

   /* Jump out hook is run first. */
   hooks_run( "jumpout" );

   /* Just in case remove hyperspace flags. */
   pilot_rmFlag( player.p, PILOT_HYPERSPACE );
   pilot_rmFlag( player.p, PILOT_HYP_BEGIN );
   pilot_rmFlag( player.p, PILOT_HYP_BRAKE );
   pilot_rmFlag( player.p, PILOT_HYP_PREP );

   /* Free graphics. */
   space_gfxUnload( cur_system );

   /* Go to the new system. */
   space_init( name );

   /* Map gets deformed when jumping this way. */
   map_clear();

   /* Add the escorts. */
   player_addEscorts();

   /* Run hooks - order is important. */
   hooks_run( "jumpin" );
   hooks_run( "enter" );
   events_trigger( EVENT_TRIGGER_ENTER );

   /* Reset targets when teleporting */
   player_targetPlanetSet( -1 );
   player_targetHyperspaceSet( -1 );
   gui_setNav();
   return 0;
}
예제 #5
0
/**
 * @brief Teleports the player to a new planet or system (only if not landed).
 *
 * If the destination is a system, the coordinates of the player will not change.
 * If the destination is a planet, the player will be placed over that planet.
 *
 * @usage player.teleport( system.get("Arcanis") ) -- Teleports the player to Arcanis.
 * @usage player.teleport( "Arcanis" ) -- Teleports the player to Arcanis.
 * @usage player.teleport( "Dvaer Prime" ) -- Teleports the player to Dvaer, and relocates him to Dvaer Prime.
 *
 *    @luaparam dest System or name of a system or planet or name of a planet to teleport the player to.
 * @luafunc teleport( dest )
 */
static int playerL_teleport( lua_State *L )
{
    Planet *pnt;
    StarSystem *sys;
    const char *name, *pntname;

    /* Must not be landed. */
    if (landed)
        NLUA_ERROR(L,"Can not teleport the player while landed!");
    if (comm_isOpen())
        NLUA_ERROR(L,"Can not teleport the player while the comm is open!");
    if (player_isBoarded())
        NLUA_ERROR(L,"Can not teleport the player while he is boarded!");

    pnt = NULL;

    /* Get a system. */
    if (lua_issystem(L,1)) {
        sys   = luaL_validsystem(L,1);
        name  = system_getIndex(sys->id)->name;
    }
    /* Get a planet. */
    else if (lua_isplanet(L,1)) {
        pnt   = luaL_validplanet(L,1);
        name  = planet_getSystem( pnt->name );
        if (name == NULL) {
            NLUA_ERROR( L, "Planet '%s' does not belong to a system..", pnt->name );
            return 0;
        }
    }
    /* Get destination from string. */
    else if (lua_isstring(L,1)) {
        name = lua_tostring(L,1);
        if (!system_exists( name )) {
            if (!planet_exists( name )) {
                NLUA_ERROR( L, "'%s' is not a valid teleportation target.", name );
                return 0;
            }

            /* No system found, assume destination string is the name of a planet. */
            pntname = name;
            name = planet_getSystem( name );
            pnt  = planet_get( pntname );
            if (name == NULL) {
                NLUA_ERROR( L, "Planet '%s' does not belong to a system..", pntname );
                return 0;
            }
        }
    }
    else
        NLUA_INVALID_PARAMETER(L);

    /* Check if system exists. */
    if (!system_exists( name )) {
        NLUA_ERROR( L, "System '%s' does not exist.", name );
        return 0;
    }

    /* Jump out hook is run first. */
    hooks_run( "jumpout" );

    /* Just in case remove hyperspace flags. */
    pilot_rmFlag( player.p, PILOT_HYPERSPACE );
    pilot_rmFlag( player.p, PILOT_HYP_BEGIN );
    pilot_rmFlag( player.p, PILOT_HYP_BRAKE );
    pilot_rmFlag( player.p, PILOT_HYP_PREP );

    /* Free graphics. */
    space_gfxUnload( cur_system );

    /* Go to the new system. */
    space_init( name );

    /* Map gets deformed when jumping this way. */
    map_clear();

    /* Add the escorts. */
    player_addEscorts();

    /* Run hooks - order is important. */
    hooks_run( "jumpin" );
    hooks_run( "enter" );
    events_trigger( EVENT_TRIGGER_ENTER );
    missions_run( MIS_AVAIL_SPACE, -1, NULL, NULL );

    /* Reset targets when teleporting */
    player_targetPlanetSet( -1 );
    player_targetHyperspaceSet( -1 );
    gui_setNav();

    /* Move to planet. */
    if (pnt != NULL)
        vectcpy( &player.p->solid->pos, &pnt->pos );

    return 0;
}
예제 #6
0
파일: land.c 프로젝트: Dinth/naev
/**
 * @brief Makes the player take off if landed.
 *
 *    @param delay Whether or not to have time pass as if the player landed normally.
 */
void takeoff( int delay )
{
   int h;
   char *nt;
   double a, r;

   if (!landed)
      return;

   /* Clear queued takeoff. */
   land_takeoff = 0;

   /* Refuel if needed. */
   land_checkAddRefuel();

   /* In case we had paused messy sounds. */
   sound_stopAll();

   /* ze music */
   music_choose("takeoff");

   /* to randomize the takeoff a bit */
   a = RNGF() * 2. * M_PI;
   r = RNGF() * land_planet->radius;

   /* no longer authorized to land */
   player_rmFlag(PLAYER_LANDACK);
   pilot_rmFlag(player.p,PILOT_LANDING); /* No longer landing. */

   /* set player to another position with random facing direction and no vel */
   player_warp( land_planet->pos.x + r * cos(a), land_planet->pos.y + r * sin(a) );
   vect_pset( &player.p->solid->vel, 0., 0. );
   player.p->solid->dir = RNGF() * 2. * M_PI;
   cam_setTargetPilot( player.p->id, 0 );

   /* heal the player */
   player.p->armour = player.p->armour_max;
   player.p->shield = player.p->shield_max;
   player.p->energy = player.p->energy_max;
   player.p->stimer = 0.;

   /* initialize the new space */
   h = player.p->nav_hyperspace;
   space_init(NULL);
   player.p->nav_hyperspace = h;

   /* cleanup */
   if (save_all() < 0) { /* must be before cleaning up planet */
      dialogue_alert( "Failed to save game!  You should exit and check the log to see what happened and then file a bug report!" );
   }

   /* time goes by, triggers hook before takeoff */
   if (delay)
      ntime_inc( ntime_create( 0, 1, 0 ) ); /* 1 STP */
   nt = ntime_pretty( 0, 2 );
   player_message("\epTaking off from %s on %s.", land_planet->name, nt);
   free(nt);

   /* Hooks and stuff. */
   land_cleanup(); /* Cleanup stuff */
   hooks_run("takeoff"); /* Must be run after cleanup since we don't want the
                            missions to think we are landed. */
   if (menu_isOpen(MENU_MAIN))
      return;
   player_addEscorts();
   hooks_run("enter");
   if (menu_isOpen(MENU_MAIN))
      return;
   events_trigger( EVENT_TRIGGER_ENTER );
   if (menu_isOpen(MENU_MAIN))
      return;
   player.p->ptimer = PILOT_TAKEOFF_DELAY;
   pilot_setFlag( player.p, PILOT_TAKEOFF );
   pilot_setThrust( player.p, 0. );
   pilot_setTurn( player.p, 0. );
}
예제 #7
0
파일: land.c 프로젝트: Dinth/naev
/**
 * @brief Saves the last place the player was.
 *
 *    @param wid Unused.
 *    @param wgt Unused.
 *    @param tab Tab changed to.
 */
static void land_changeTab( unsigned int wid, char *wgt, int tab )
{
   int i;
   (void) wid;
   (void) wgt;
   unsigned int w;
   const char *torun_hook;
   unsigned int to_visit;

   /* Sane defaults. */
   torun_hook = NULL;
   to_visit   = 0;

   /* Find what switched. */
   for (i=0; i<LAND_NUMWINDOWS; i++) {
      if (land_windowsMap[i] == tab) {
         last_window = i;
         w = land_getWid( i );

         /* Must regenerate outfits. */
         switch (i) {
            case LAND_WINDOW_MAIN:
               land_checkAddRefuel();
               break;
            case LAND_WINDOW_OUTFITS:
               outfits_update( w, NULL );
               outfits_updateQuantities( w );
               to_visit   = VISITED_OUTFITS;
               torun_hook = "outfits";
               break;
            case LAND_WINDOW_SHIPYARD:
               shipyard_update( w, NULL );
               to_visit   = VISITED_SHIPYARD;
               torun_hook = "shipyard";
               break;
            case LAND_WINDOW_BAR:
               bar_update( w, NULL );
               to_visit   = VISITED_BAR;
               torun_hook = "bar";
               break;
            case LAND_WINDOW_MISSION:
               misn_update( w, NULL );
               to_visit   = VISITED_MISSION;
               torun_hook = "mission";
               break;
            case LAND_WINDOW_COMMODITY:
               commodity_update( w, NULL );
               to_visit   = VISITED_COMMODITY;
               torun_hook = "commodity";
               break;
            case LAND_WINDOW_EQUIPMENT:
               equipment_updateShips( w, NULL );
               equipment_updateOutfits( w, NULL );
               to_visit   = VISITED_EQUIPMENT;
               torun_hook = "equipment";
               break;

            default:
               break;
         }

         /* Clear markers if closing Mission Computer. */
         if (i != LAND_WINDOW_MISSION) {
            space_clearComputerMarkers();
         }

         break;
      }
   }

   /* Check land missions - always run hooks. */
   /*if ((to_visit != 0) && !has_visited(to_visit)) {*/
   {
      /* Run hooks, run after music in case hook wants to change music. */
      if (torun_hook != NULL)
         if (hooks_run( torun_hook ) > 0)
            bar_genList( land_getWid(LAND_WINDOW_BAR) );

      visited(to_visit);

      if (land_takeoff)
         takeoff(1);
   }
}
예제 #8
0
파일: land.c 프로젝트: Dinth/naev
/**
 * @brief Recreates the land windows.
 *
 *    @param load Is loading game?
 *    @param changetab Should it change to the last open tab?
 */
void land_genWindows( int load, int changetab )
{
   int i, j;
   const char *names[LAND_NUMWINDOWS];
   int w, h;
   Planet *p;
   int regen;

   /* Destroy old window if exists. */
   if (land_wid > 0) {
      land_regen = 2; /* Mark we're regenning. */
      window_destroy(land_wid);
   }
   land_loaded = 0;

   /* Get planet. */
   p     = land_planet;
   regen = landed;

   /* Create window. */
   if ((SCREEN_W < 1024) || (SCREEN_H < 768)) {
      w = -1; /* Fullscreen. */
      h = -1;
   }
   else {
      w = 800 + 0.5 * (SCREEN_W - 800);
      h = 600 + 0.5 * (SCREEN_H - 600);
   }
   land_wid = window_create( p->name, -1, -1, w, h );
   window_onClose( land_wid, land_cleanupWindow );

   /* Set window map to invalid. */
   for (i=0; i<LAND_NUMWINDOWS; i++)
      land_windowsMap[i] = -1;

   /* See what is available. */
   j = 0;
   /* Main. */
   land_windowsMap[LAND_WINDOW_MAIN] = j;
   names[j++] = land_windowNames[LAND_WINDOW_MAIN];
   /* Bar. */
   if (planet_hasService(land_planet, PLANET_SERVICE_BAR)) {
      land_windowsMap[LAND_WINDOW_BAR] = j;
      names[j++] = land_windowNames[LAND_WINDOW_BAR];
   }
   /* Missions. */
   if (planet_hasService(land_planet, PLANET_SERVICE_MISSIONS)) {
      land_windowsMap[LAND_WINDOW_MISSION] = j;
      names[j++] = land_windowNames[LAND_WINDOW_MISSION];
   }
   /* Outfits. */
   if (planet_hasService(land_planet, PLANET_SERVICE_OUTFITS)) {
      land_windowsMap[LAND_WINDOW_OUTFITS] = j;
      names[j++] = land_windowNames[LAND_WINDOW_OUTFITS];
   }
   /* Shipyard. */
   if (planet_hasService(land_planet, PLANET_SERVICE_SHIPYARD)) {
      land_windowsMap[LAND_WINDOW_SHIPYARD] = j;
      names[j++] = land_windowNames[LAND_WINDOW_SHIPYARD];
   }
   /* Equipment. */
   if (planet_hasService(land_planet, PLANET_SERVICE_OUTFITS) ||
         planet_hasService(land_planet, PLANET_SERVICE_SHIPYARD)) {
      land_windowsMap[LAND_WINDOW_EQUIPMENT] = j;
      names[j++] = land_windowNames[LAND_WINDOW_EQUIPMENT];
   }
   /* Commodity. */
   if (planet_hasService(land_planet, PLANET_SERVICE_COMMODITY)) {
      land_windowsMap[LAND_WINDOW_COMMODITY] = j;
      names[j++] = land_windowNames[LAND_WINDOW_COMMODITY];
   }

   /* Create tabbed window. */
   land_windows = window_addTabbedWindow( land_wid, -1, -1, -1, -1, "tabLand", j, names );

   /*
    * Order here is very important:
    *
    *  1) Create main tab - must have decent background.
    *  2) Set landed, play music and run land hooks - so hooks run well.
    *  3) Generate missions - so that campaigns are fluid.
    *  4) Create other tabs - lists depend on NPC and missions.
    */

   /* 1) Create main tab. */
   land_createMainTab( land_getWid(LAND_WINDOW_MAIN) );

   /* 2) Set as landed and run hooks. */
   if (!regen) {
      landed = 1;
      music_choose("land"); /* Must be before hooks in case hooks change music. */
      if (!load) {
         events_trigger( EVENT_TRIGGER_LAND );
         hooks_run("land");
      }

      /* 3) Generate computer and bar missions. */
      if (planet_hasService(land_planet, PLANET_SERVICE_MISSIONS))
         mission_computer = missions_genList( &mission_ncomputer,
               land_planet->faction, land_planet->name, cur_system->name,
               MIS_AVAIL_COMPUTER );
      if (planet_hasService(land_planet, PLANET_SERVICE_BAR))
         npc_generate(); /* Generate bar npc. */
   }

   /* 4) Create other tabs. */
   /* Basic - bar + missions */
   if (planet_hasService(land_planet, PLANET_SERVICE_BAR))
      bar_open( land_getWid(LAND_WINDOW_BAR) );
   if (planet_hasService(land_planet, PLANET_SERVICE_MISSIONS))
      misn_open( land_getWid(LAND_WINDOW_MISSION) );
   /* Outfits. */
   if (planet_hasService(land_planet, PLANET_SERVICE_OUTFITS))
      outfits_open( land_getWid(LAND_WINDOW_OUTFITS) );
   /* Shipyard. */
   if (planet_hasService(land_planet, PLANET_SERVICE_SHIPYARD))
      shipyard_open( land_getWid(LAND_WINDOW_SHIPYARD) );
   /* Equipment. */
   if (planet_hasService(land_planet, PLANET_SERVICE_OUTFITS) ||
         planet_hasService(land_planet, PLANET_SERVICE_SHIPYARD))
      equipment_open( land_getWid(LAND_WINDOW_EQUIPMENT) );
   /* Commodity. */
   if (planet_hasService(land_planet, PLANET_SERVICE_COMMODITY))
      commodity_exchange_open( land_getWid(LAND_WINDOW_COMMODITY) );

   if (!regen) {
      /* Reset markers if needed. */
      mission_sysMark();

      /* Check land missions. */
      if (!has_visited(VISITED_LAND)) {
         missions_run(MIS_AVAIL_LAND, land_planet->faction,
               land_planet->name, cur_system->name);
         visited(VISITED_LAND);
      }
   }

   /* Go to last open tab. */
   window_tabWinOnChange( land_wid, "tabLand", land_changeTab );
   if (changetab && land_windowsMap[ last_window ] != -1)
      window_tabWinSetActive( land_wid, "tabLand", land_windowsMap[ last_window ] );

   /* Add fuel button if needed - AFTER missions pay :). */
   land_checkAddRefuel();

   /* Finished loading. */
   land_loaded = 1;
}
예제 #9
0
파일: land.c 프로젝트: Kinniken/naev
/**
 * @brief Makes the player take off if landed.
 *
 *    @param delay Whether or not to have time pass as if the player landed normally.
 */
void takeoff( int delay )
{
   int h;
   char *nt;
   double a, r;

   if (!landed)
      return;

   /* Player's ship is not able to fly. */
   if (!player_canTakeoff()) {
      char message[512];
      pilot_reportSpaceworthy( player.p, message, sizeof(message) );
      dialogue_msg( "Ship not fit for flight", message );

      /* Check whether the player needs rescuing. */
      land_stranded();

      return;
   }

   /* Clear queued takeoff. */
   land_takeoff = 0;

   /* Refuel if needed. */
   land_refuel();

   /* In case we had paused messy sounds. */
   sound_stopAll();

   /* ze music */
   music_choose("takeoff");

   /* to randomize the takeoff a bit */
   a = RNGF() * 2. * M_PI;
   r = RNGF() * land_planet->radius;

   /* no longer authorized to land */
   player_rmFlag(PLAYER_LANDACK);
   pilot_rmFlag(player.p,PILOT_LANDING); /* No longer landing. */

   /* set player to another position with random facing direction and no vel */
   player_warp( land_planet->pos.x + r * cos(a), land_planet->pos.y + r * sin(a) );
   vect_pset( &player.p->solid->vel, 0., 0. );
   player.p->solid->dir = RNGF() * 2. * M_PI;
   cam_setTargetPilot( player.p->id, 0 );

   /* heal the player */
   pilot_healLanded( player.p );

   /* Clear planet target. Allows for easier autonav out of the system. */
   player_targetPlanetSet( -1 );

   /* initialize the new space */
   h = player.p->nav_hyperspace;
   space_init(NULL);
   player.p->nav_hyperspace = h;

   /* cleanup */
   if (save_all() < 0) /* must be before cleaning up planet */
      dialogue_alert( "Failed to save game! You should exit and check the log to see what happened and then file a bug report!" );

   /* time goes by, triggers hook before takeoff */
   if (delay)
      ntime_inc( ntime_create( 0, 1, 0 ) ); /* 1 STP */
   nt = ntime_pretty( 0, 2 );
   player_message("\epTaking off from %s on %s.", land_planet->name, nt);
   free(nt);

   /* Hooks and stuff. */
   land_cleanup(); /* Cleanup stuff */
   hooks_run("takeoff"); /* Must be run after cleanup since we don't want the
                            missions to think we are landed. */
   if (menu_isOpen(MENU_MAIN))
      return;
   player_addEscorts();
   hooks_run("enter");
   if (menu_isOpen(MENU_MAIN))
      return;
   events_trigger( EVENT_TRIGGER_ENTER );
   missions_run( MIS_AVAIL_SPACE, -1, NULL, NULL );
   if (menu_isOpen(MENU_MAIN))
      return;
   player.p->ptimer = PILOT_TAKEOFF_DELAY;
   pilot_setFlag( player.p, PILOT_TAKEOFF );
   pilot_setThrust( player.p, 0. );
   pilot_setTurn( player.p, 0. );
   }
예제 #10
0
파일: land.c 프로젝트: naev/naev
/**
 * @brief Recreates the land windows.
 *
 *    @param load Is loading game?
 *    @param changetab Should it change to the last open tab?
 */
void land_genWindows( int load, int changetab )
{
   int i, j;
   const char *names[LAND_NUMWINDOWS];
   int w, h;
   Planet *p;
   int regen;

   /* Destroy old window if exists. */
   if (land_wid > 0) {
      land_regen = 2; /* Mark we're regenning. */
      window_destroy(land_wid);

      /* Mark tabs as not generated. */
      land_generated = 0;
   }
   land_loaded = 0;

   /* Get planet. */
   p     = land_planet;
   regen = landed;

   /* Create window. */
   if ((gl_screen.rw < 1024) || (gl_screen.rh < 768)) {
      w = -1; /* Fullscreen. */
      h = -1;
   }
   else {
      w = 800 + 0.5 * (SCREEN_W - 800);
      h = 600 + 0.5 * (SCREEN_H - 600);
   }
   land_wid = window_create( p->name, -1, -1, w, h );
   window_onClose( land_wid, land_cleanupWindow );

   /* Set window map to invalid. */
   for (i=0; i<LAND_NUMWINDOWS; i++)
      land_windowsMap[i] = -1;

   /* See what is available. */
   j = 0;
   /* Main. */
   land_windowsMap[LAND_WINDOW_MAIN] = j;
   names[j++] = _("Landing Main");
   /* Bar. */
   if (planet_hasService(land_planet, PLANET_SERVICE_BAR)) {
      land_windowsMap[LAND_WINDOW_BAR] = j;
      names[j++] = _("Spaceport Bar");
   }
   /* Missions. */
   if (planet_hasService(land_planet, PLANET_SERVICE_MISSIONS)) {
      land_windowsMap[LAND_WINDOW_MISSION] = j;
      names[j++] = _("Missions");
   }
   /* Outfits. */
   if (planet_hasService(land_planet, PLANET_SERVICE_OUTFITS)) {
      land_windowsMap[LAND_WINDOW_OUTFITS] = j;
      names[j++] = _("Outfits");
   }
   /* Shipyard. */
   if (planet_hasService(land_planet, PLANET_SERVICE_SHIPYARD)) {
      land_windowsMap[LAND_WINDOW_SHIPYARD] = j;
      names[j++] = _("Shipyard");
   }
   /* Equipment. */
   if (planet_hasService(land_planet, PLANET_SERVICE_OUTFITS) ||
         planet_hasService(land_planet, PLANET_SERVICE_SHIPYARD)) {
      land_windowsMap[LAND_WINDOW_EQUIPMENT] = j;
      names[j++] = _("Equipment");
   }
   /* Commodity. */
   if (planet_hasService(land_planet, PLANET_SERVICE_COMMODITY)) {
      land_windowsMap[LAND_WINDOW_COMMODITY] = j;
      names[j++] = _("Commodity");
   }

   /* Create tabbed window. */
   land_windows = window_addTabbedWindow( land_wid, -1, -1, -1, -1, "tabLand", j, names, 0 );

   /*
    * Order here is very important:
    *
    *  1) Create main tab - must have decent background.
    *  2) Set landed, play music and run land hooks - so hooks run well.
    *  3) Generate missions - so that campaigns are fluid.
    *  4) Create other tabs - lists depend on NPC and missions.
    */

   /* 1) Create main tab. */
   land_createMainTab( land_getWid(LAND_WINDOW_MAIN) );

   /* Add local system map button. */
   land_checkAddMap();

   /* 2) Set as landed and run hooks. */
   if (!regen) {
      landed = 1;
      music_choose("land"); /* Must be before hooks in case hooks change music. */
      if (!load) {
         hooks_run("land");
      }
      events_trigger( EVENT_TRIGGER_LAND );

      /* 3) Generate computer and bar missions. */
      if (planet_hasService(land_planet, PLANET_SERVICE_MISSIONS))
         mission_computer = missions_genList( &mission_ncomputer,
               land_planet->faction, land_planet->name, cur_system->name,
               MIS_AVAIL_COMPUTER );
      if (planet_hasService(land_planet, PLANET_SERVICE_BAR))
         npc_generate(); /* Generate bar npc. */
   }

   /* 4) Create other tabs. */
#define should_open(s, w) \
   (planet_hasService(land_planet, s) && (!land_tabGenerated(w)))

   /* Things get a bit hairy here. Hooks may have triggered a GUI reload via
    * e.g. player.swapShip, so the land tabs may have been generated already
    * and we need to check that before regenerating them.
    */

   /* Basic - bar + missions */
   if (should_open( PLANET_SERVICE_BAR, LAND_WINDOW_BAR ))
      bar_open( land_getWid(LAND_WINDOW_BAR) );
   if (should_open( PLANET_SERVICE_MISSIONS, LAND_WINDOW_MISSION ))
      misn_open( land_getWid(LAND_WINDOW_MISSION) );
   /* Outfits. */
   if (should_open( PLANET_SERVICE_OUTFITS, LAND_WINDOW_OUTFITS ))
      outfits_open( land_getWid(LAND_WINDOW_OUTFITS) );
   /* Shipyard. */
   if (should_open( PLANET_SERVICE_SHIPYARD, LAND_WINDOW_SHIPYARD ))
      shipyard_open( land_getWid(LAND_WINDOW_SHIPYARD) );
   /* Equipment. */
   if ((planet_hasService(land_planet, PLANET_SERVICE_OUTFITS) ||
         planet_hasService(land_planet, PLANET_SERVICE_SHIPYARD)) &&
         !land_tabGenerated( LAND_WINDOW_EQUIPMENT ))
      equipment_open( land_getWid(LAND_WINDOW_EQUIPMENT) );
   /* Commodity. */
   if (should_open( PLANET_SERVICE_COMMODITY, LAND_WINDOW_COMMODITY ))
      commodity_exchange_open( land_getWid(LAND_WINDOW_COMMODITY) );
#undef should_open

   if (!regen) {
      /* Reset markers if needed. */
      mission_sysMark();

      /* Check land missions. */
      if (!has_visited(VISITED_LAND)) {
         missions_run(MIS_AVAIL_LAND, land_planet->faction,
               land_planet->name, cur_system->name);
         visited(VISITED_LAND);
      }
   }

   /* Go to last open tab. */
   window_tabWinOnChange( land_wid, "tabLand", land_changeTab );
   if (changetab && land_windowsMap[ last_window ] != -1)
      window_tabWinSetActive( land_wid, "tabLand", land_windowsMap[ last_window ] );

   /* Refresh the map button in case the player couldn't afford it prior to
    * mission payment.
    */
   land_checkAddMap();

   /* Refuel if necessary. */
   land_refuel();

   /* Finished loading. */
   land_loaded = 1;
}