diff --git a/dat/planet.xml b/dat/planet.xml
index d766ed2..911a9a8 100644
--- a/dat/planet.xml
+++ b/dat/planet.xml
@@ -21,8 +21,8 @@
 	</planet>
 	<planet name="SaraCraft">
 		<pos>
-			<x>125</x>
-			<y>-345</y>
+			<x>0</x>
+			<y>0</y>
 		</pos>
 		<general>
 			<class>A</class>
diff --git a/dat/ssys.xml b/dat/ssys.xml
index c155b71..4e204e3 100644
--- a/dat/ssys.xml
+++ b/dat/ssys.xml
@@ -12,7 +12,6 @@
 		</general>
 		<planets>
 			<planet>KonoSphere</planet>
-      <planet>SaraCraft</planet>
 		</planets>
 		<fleets>
 			<fleet chance="100">Enemy Test</fleet>
@@ -23,6 +22,9 @@
 			<fleet chance="50">Sml Merchant Convoy</fleet>
 			<fleet chance="40">Sml Merchant Convoy</fleet>
 		</fleets>
+    <jumps>
+      <jump>KonoSys</jump>
+    </jumps>
 </ssys>
 	<ssys name="KonoSys">
 		<pos>
@@ -41,5 +43,9 @@
 			<fleet chance="80">Merchant Ship</fleet>
 			<fleet chance="60">Merchant Ship</fleet>
 		</fleets>
+    <jumps>
+      <jump>SaraSys</jump>
+    </jumps>
 	</ssys>
 </Systems>
+
diff --git a/src/ai.c b/src/ai.c
index bcc3be9..9d39d40 100644
--- a/src/ai.c
+++ b/src/ai.c
@@ -58,10 +58,6 @@
 // Don't run the function if (n) params aren't passed.
 #define MIN_ARGS(n) if(lua_gettop(L) < n) return 0
 
-#define MIN_DIR_ERR 1.0*M_PI/180.
-#define MAX_DIR_ERR 0.1*M_PI/180.
-#define MIN_VEL_ERR 0.5
-
 // Ai flags.
 #define ai_setFlag(f) (pilot_flags |= f)
 #define ai_isFlag(f)  (pilot_flags  & f)
diff --git a/src/ai.h b/src/ai.h
index b4467e4..0ba1fdf 100644
--- a/src/ai.h
+++ b/src/ai.h
@@ -1,6 +1,11 @@
 #pragma once
 #include "lua.h"
 
+#define MIN_DIR_ERR 1.0*M_PI/180.
+#define MAX_DIR_ERR 0.1*M_PI/180.
+#define MIN_VEL_ERR 0.5
+
+
 // Max number of AI timers.
 #define MAX_AI_TIMERS 2
 
diff --git a/src/input.c b/src/input.c
index fcfb883..3661516 100644
--- a/src/input.c
+++ b/src/input.c
@@ -24,14 +24,13 @@ static Keybind** input_keybinds; // Contains the players keybindings.
 const char* keybindNames[] = { "accel", "left", "right", "reverse", // Movement.
                               "primary", "target", "target_nearest", "face", "board", // Combat.
                               "secondary", "secondary_next", // Secondary weapons.
-                              "target_planet", "land", // Navigation.
+                              "target_planet", "land", "thyperspace", "jump", // Navigation.
                               "mapzoomin", "mapzoomout", "screenshot", "pause", "menu", // Misc.
                               "end" }; // Must terminate at the end.
 // From player.c
 extern double player_turn;
 extern double player_acc;
 extern unsigned int player_target;
-extern int planet_target;
 // Grabbed from main.c
 extern int show_fps;
 
@@ -56,6 +55,9 @@ void input_setDefault(void) {
   // Space
   input_setKeybind("target_planet",   KEYBIND_KEYBOARD, SDLK_p,       0);
   input_setKeybind("land",            KEYBIND_KEYBOARD, SDLK_l,       0);
+  input_setKeybind("thyperspace",     KEYBIND_KEYBOARD, SDLK_h,       0);
+  input_setKeybind("jump",            KEYBIND_KEYBOARD, SDLK_j,       0);
+
   // Misc.
   input_setKeybind("mapzoomin",       KEYBIND_KEYBOARD, SDLK_UP,      0);
   input_setKeybind("mapzoomout",      KEYBIND_KEYBOARD, SDLK_DOWN,    0);
@@ -175,7 +177,7 @@ static void input_key(int keynum, double value, int abs) {
   else if(KEY("board") && !paused) {
     if(value == KEY_PRESS) player_board();
   }
-  // Selecting secondary weapon.
+  // Shooting secondary weapon.
   else if(KEY("secondary") && !paused) {
     if(value == KEY_PRESS) player_setFlag(PLAYER_SECONDARY);
     else if(value == KEY_RELEASE) player_rmFlag(PLAYER_SECONDARY);
@@ -184,15 +186,6 @@ static void input_key(int keynum, double value, int abs) {
   else if(KEY("secondary_next") && !paused) {
     if(value == KEY_PRESS) player_secondaryNext();
   }
-  // Selecting secondary weapon.
-  else if(KEY("secondary")) {
-    if(value == KEY_PRESS) player_setFlag(PLAYER_SECONDARY);
-    else if(value == KEY_RELEASE) player_rmFlag(PLAYER_SECONDARY);
-  }
-  // Selecting secondary weapon.
-  else if(KEY("secondary_next") && !paused) {
-    if(value == KEY_PRESS) player_secondaryNext();
-  }
   // Space.
   // Target planet (cycles just like target).
   else if(KEY("target_planet") && !paused) {
@@ -202,6 +195,12 @@ static void input_key(int keynum, double value, int abs) {
   else if(KEY("land") && !paused) {
     if(value == KEY_PRESS) player_land();
   }
+  else if(KEY("thyperspace") && !paused) {
+    if(value == KEY_PRESS) player_targetHyperspace();
+  }
+  else if(KEY("jump") && !paused) {
+    if(value == KEY_PRESS) player_jump();
+  }
   // Zoom in.
   else if(KEY("mapzoomin")) {
     if(value == KEY_PRESS) player_setRadarRel(1);
diff --git a/src/land.c b/src/land.c
index 9a96d65..024e147 100644
--- a/src/land.c
+++ b/src/land.c
@@ -144,8 +144,7 @@ void takeoff(void) {
   sh = planet->gfx_space->h;
 
   // Set player to another position with random facing direction and no velocity.
-  vect_cset(&player->solid->pos,
-        planet->pos.x + RNG(-sw/2, sw/2), planet->pos.y + RNG(-sh/2, sh/2));
+  player_warp(planet->pos.x + RNG(-sw/2, sw/2), planet->pos.y + RNG(-sh/2, sh/2));
   vect_pset(&player->solid->vel, 0., 0.);
   player->solid->dir = RNG(0, 359) * M_PI/180.;
 
diff --git a/src/menu.h b/src/menu.h
index 7e094ce..54eebfc 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -1,4 +1,4 @@
-#pragma one
+#pragma once
 
 void menu_small(void);
 
diff --git a/src/pilot.c b/src/pilot.c
index caa21ee..acc5d2d 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -32,10 +32,12 @@ static int nfleets = 0;
 extern void ai_destroy(Pilot* p); // Ai.
 extern void ai_think(Pilot* pilot); // Ai.c
 extern void player_think(Pilot* pilot); // Player.c
+extern void player_brokeHyperspace(void); // Player.c
 extern int gui_load(const char* name); // Player.c
 // Internal.
 static void pilot_shootWeapon(Pilot* p, PilotOutfit* w, const unsigned int t);
 static void pilot_update(Pilot* pilot, const double dt);
+static void pilot_hyperspace(Pilot* pilot);
 void pilot_render(Pilot* pilot);
 static void pilot_free(Pilot* p);
 static Fleet* fleet_parse(const xmlNodePtr parent);
@@ -107,6 +109,23 @@ Pilot* pilot_get(const unsigned int id) {
   return NULL;
 }
 
+// Attempt to turn the pilot to face dir.
+double pilot_face(Pilot* p, const float dir) {
+  double diff, turn;
+
+  diff = angle_diff(p->solid->dir, dir);
+
+  turn = -10.*diff;
+  if(turn > 1.) turn = 1.;
+  else if(turn < -1.) turn = -1.;
+
+  p->solid->dir_vel = 0.;
+  if(turn)
+    p->solid->dir_vel -= p->ship->turn * turn;
+
+  return diff;
+}
+
 // Mkay, this is how we shoot. Listen up.
 void pilot_shoot(Pilot* p, const unsigned int target, const int secondary) {
   int i;
@@ -230,9 +249,40 @@ static void pilot_update(Pilot* pilot, const double dt) {
   // Update the solid.
   (*pilot->solid->update)(pilot->solid, dt);
   
-  if(VMOD(pilot->solid->vel) > pilot->ship->speed) {
+  if(!pilot_isFlag(pilot, PILOT_HYPERSPACE) && VMOD(pilot->solid->vel) > 
+        pilot->ship->speed)
     // Should not go faster.
     vect_pset(&pilot->solid->vel, pilot->ship->speed, VANGLE(pilot->solid->vel));
+}
+
+// Pilot is getting ready or is in, hyperspace.
+static void pilot_hyperspace(Pilot* p) {
+  if(pilot_isFlag(p, PILOT_HYPERSPACE)) {
+    // Pilot is actually in hyperspace.
+    if(SDL_GetTicks() > p->ptimer) {
+      if(p == player) {
+        player_brokeHyperspace();
+      } else
+        pilot_setFlag(p, PILOT_DELETE); // Set flag to delete pilot.
+      return;
+    }
+    vect_pset(&p->solid->force, p->ship->thrust * 3., p->solid->dir);
+  }
+  else if(pilot_isFlag(p, PILOT_HYP_BEGIN)) {
+    if(SDL_GetTicks() > p->ptimer) {
+      // Engines are ready.
+      p->ptimer = SDL_GetTicks() + HYPERSPACE_FLY_DELAY;
+      pilot_setFlag(p, PILOT_HYPERSPACE);
+    }
+  } else {
+    double diff = pilot_face(p, VANGLE(player->solid->pos));
+
+    if(diff < MAX_DIR_ERR) {
+      // We can now prepare the jump.
+      p->solid->dir_vel = 0.;
+      p->ptimer = SDL_GetTicks() + HYPERSPACE_ENGINE_DELAY;
+      pilot_setFlag(p, PILOT_HYP_BEGIN);
+    }
   }
 }
 
@@ -296,7 +346,7 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profi
 
   if(flags & PILOT_PLAYER) {
     pilot->think = player_think; // Players don't need to thing! :P
-    pilot->render = NULL;
+    pilot->render = NULL; // Render will be called from player_think
     pilot_setFlag(pilot, PILOT_PLAYER); // It's a player!
     player = pilot;
     gui_load(pilot->ship->gui); // Load the GUI.
@@ -382,12 +432,19 @@ void pilots_clean(void) {
 void pilots_update(double dt) {
   int i;
   for(i = 0; i < pilots; i++) {
-    if(pilot_stack[i]->think && !pilot_isDisabled(pilot_stack[i]))
-      pilot_stack[i]->think(pilot_stack[i]);
-    if(pilot_stack[i]->update)
-      pilot_stack[i]->update(pilot_stack[i], dt);
-    if(pilot_stack[i]->render)
-      pilot_stack[i]->render(pilot_stack[i]);
+    if(pilot_stack[i]->think && !pilot_isDisabled(pilot_stack[i])) {
+      // Hyperspace gets special treatment.
+      if(pilot_isFlag(pilot_stack[i], PILOT_HYP_PREP))
+        pilot_hyperspace(pilot_stack[i]);
+      else
+        pilot_stack[i]->think(pilot_stack[i]);
+    }
+    if(pilot_stack[i]->update) {
+      if(pilot_isFlag(pilot_stack[i], PILOT_DELETE))
+        pilot_destroy(pilot_stack[i]);
+      else
+        pilot_stack[i]->update(pilot_stack[i], dt);
+    }
   }
 }
 
diff --git a/src/pilot.h b/src/pilot.h
index 1d2a50f..53b8bbd 100644
--- a/src/pilot.h
+++ b/src/pilot.h
@@ -8,6 +8,9 @@
 
 #define PLAYER_ID 1
 
+#define HYPERSPACE_FLY_DELAY    5000
+#define HYPERSPACE_ENGINE_DELAY 3000
+
 // Aproximation for pilot size.
 #define PILOT_SIZE_APROX      0.8
 #define PILOT_DISABLED_ARMOUR 0.2 // Based on armour percentage.
@@ -21,8 +24,12 @@
 // Dynamic.
 #define PILOT_HOSTILE       (1<<1)  // Pilot is hostile to the player.
 #define PILOT_COMBAT        (1<<2)  // Pilot is engaged in combat.
-#define PILOT_HYPERSPACE    (1<<3)  // Pilot is in hyperspace.
-#define PILOT_DISABLED      (1<<4)  // Pilot is disabled.
+#define PILOT_HYP_PREP      (1<<5)  // Pilot is getting ready for hyperspace.
+#define PILOT_HYP_BEGIN     (1<<6)  // Pilot is starting engines.
+#define PILOT_HYPERSPACE    (1<<7)  // Pilot is in hyperspace.
+#define PILOT_DISABLED      (1<<9)  // Pilot is disabled.
+#define PILOT_DELETE        (1<<10) // Pilot will get delete asap.
+
 // Just makes life simpler.
 #define pilot_isPlayer(p)   ((p)->flags & PILOT_PLAYER)
 #define pilot_isDisabled(p) ((p)->flags & PILOT_DISABLED)
@@ -60,6 +67,7 @@ typedef struct Pilot {
   PilotOutfit* ammo;      // Secondary ammo (if needed).
 
   unsigned int flags; // Used for AI etc.
+  unsigned int ptimer;  // Generic timer for internal pilot use.
 
   // AI.
   AI_Profile* ai; // Ai personality profile.
@@ -97,6 +105,7 @@ Fleet* fleet_get(const char* name);
 void pilot_shoot(Pilot* p, const unsigned int target, const int secondary);
 void pilot_hit(Pilot* p, const double damage_shield, const double damage_armour);
 void pilot_setAmmo(Pilot* p);
+double pilot_face(Pilot* p, const float dir);
 
 // Creation.
 void pilot_init(Pilot* dest, Ship* ship, char* name, Faction* faction, AI_Profile* ai,
diff --git a/src/player.c b/src/player.c
index a526f5e..6ba2e69 100644
--- a/src/player.c
+++ b/src/player.c
@@ -35,12 +35,16 @@ unsigned int player_flags = 0; // Player flags.
 double player_turn = 0.; // Turn velocity from input.
 double player_acc  = 0.; // Accel velocity from input.
 unsigned int player_target = PLAYER_ID; // Targetted pilot.
-int planet_target = -1; // Targetted planet.
+static int planet_target = -1; // Targetted planet.
+static int hyperspace_target = -1; // Target hyperspace route.
 
 // Pilot stuff for GUI.
 extern Pilot** pilot_stack;
 extern int pilots;
 
+// Space stuff for GUI.
+extern StarSystem* systems;
+
 // GUI crap.
 typedef struct {
   double x,y; // Position.
@@ -196,10 +200,15 @@ void player_message(const char* fmt, ...) {
     msg_stack[0].t = SDL_GetTicks() + msg_timeout;
 }
 
+void player_warp(const double x, const double y) {
+  vect_cset(&player->solid->pos, x, y);
+}
+
 // Clear the targets.
 void player_clear(void) {
   player_target = PLAYER_ID;
   planet_target = -1;
+  hyperspace_target = -1;
 }
 
 // Render the background player stuff, namely planet target
@@ -320,8 +329,17 @@ void player_render(void) {
     gl_printMid(&gl_smallFont, (int)gui.nav.w, gui.nav.x, gui.nav.y - 10 - gl_smallFont.h,
           NULL, "%s", cur_system->planets[planet_target].name);
   }
-  else if(planet_target == -1) {
-    // No planet target.
+  else if(hyperspace_target >= 0) {
+    // Hyperspace target.
+    c = space_canHyperspace(player) ? &cConsole : NULL;
+    gl_printMid(NULL, (int)gui.nav.w, gui.nav.x, gui.nav.y - 5,
+          c, "Hyperspace");
+
+    gl_printMid(&gl_smallFont, (int)gui.nav.w, gui.nav.x, gui.nav.y - 10 - gl_smallFont.h,
+          NULL, "%s", systems[cur_system->jumps[hyperspace_target]].name);
+  }
+  else {
+    // No NAV target.
     gl_printMid(NULL, (int)gui.nav.w, gui.nav.x,
           gui.nav.y - 5, &cConsole, "Navigation");
     gl_printMid(&gl_smallFont, (int)gui.nav.w, gui.nav.x,
@@ -744,23 +762,21 @@ void gui_free(void) {
 // Used in pilot.c
 // Basically uses keyboard input instead of AI input.
 void player_think(Pilot* player) {
-  double diff;
-  if(player_isFlag(PLAYER_FACE) && (player_target != PLAYER_ID)) {
-    diff = angle_diff(player->solid->dir,
+  // PLAYER_FACE will take over navigation.
+  if(player_isFlag(PLAYER_FACE) && (player_target != PLAYER_ID))
+    pilot_face(player,
           vect_angle(&player->solid->pos, &pilot_get(player_target)->solid->pos));
-    player_turn = -10.*diff;
-    if(player_turn > 1.) player_turn = 1.;
-    else if(player_turn < -1.) player_turn = -1.;
+
+  // PLAYER_REVERSE will take over navigation.
+  else if(player_isFlag(PLAYER_REVERSE) && (VMOD(player->solid->vel) > 0.))
+    pilot_face(player, VANGLE(player->solid->vel) + M_PI);
+  
+  // Normal navigation sheme.
+  else {
+    player->solid->dir_vel = 0.;
+    if(player_turn)
+      player->solid->dir_vel -= player->ship->turn * player_turn;
   }
-  else if(player_isFlag(PLAYER_REVERSE) && (VMOD(player->solid->vel) > 0.)) {
-    diff = angle_diff(player->solid->dir, VANGLE(player->solid->vel));
-    player_turn = 10.*diff;
-    if(player_turn >= 0.) player_turn = 1.;
-    else if(player_turn < 0.) player_turn = -1;
-  }
-  player->solid->dir_vel = 0.;
-  if(player_turn)
-    player->solid->dir_vel -= player->ship->turn * player_turn;
 
   if(player_isFlag(PLAYER_PRIMARY)) pilot_shoot(player, 0, 0);
   if(player_isFlag(PLAYER_SECONDARY)) // Needs a target.
@@ -801,7 +817,7 @@ void player_board(void) {
   if((pow2(VX(player->solid->vel)-VX(p->solid->vel)) + 
         pow2(VY(player->solid->vel)-VY(p->solid->vel))) > (double)pow2(MAX_HYPERSPACE_VEL)) {
     
-    player_message("You are going too fact to board the ship");
+    player_message("You are going too fast to board the ship");
     return;
   }
   player_message("Boarding ship %s", p->name);
@@ -844,6 +860,8 @@ void player_secondaryNext(void) {
 
 // Cycle through planet targets.
 void player_targetPlanet(void) {
+  hyperspace_target = -1;
+
   if((planet_target == -1) && (cur_system->nplanets > 0)) {
     // No target.
     planet_target = 0;
@@ -894,6 +912,41 @@ void player_land(void) {
   }
 }
 
+void player_targetHyperspace(void) {
+  planet_target = -1; // Remove planet target.
+  hyperspace_target++;
+
+  if(hyperspace_target >= cur_system->njumps)
+    hyperspace_target = -1;
+}
+
+// Actually attempt to jump into hyperspace.
+void player_jump(void) {
+  if(hyperspace_target == -1) return;
+
+  int i = space_hyperspace(player);
+
+  if(i == -1)
+    player_message("You are too close to gravity centers to initiate hyperspace.");
+  else if(i == -2)
+    player_message("You are moving too fast to enter hyperspace.");
+  else
+    player_message("Preparing for hyperspace");
+}
+
+// Player actually broke hyperspace (Let's enter a new system).
+void player_brokeHyperspace(void) {
+  // Enter the new system.
+  space_init(systems[cur_system->jumps[hyperspace_target]].name);
+
+  // Set position, pilot_update will handle the lowering of velocity.
+  player_warp(-cos(player->solid->dir) * MIN_HYPERSPACE_DIST * 1.2,
+        -sin(player->solid->dir) * MIN_HYPERSPACE_DIST * 1.2);
+
+  // Stop hyperspace.
+  pilot_rmFlag(player, PILOT_HYPERSPACE | PILOT_HYP_BEGIN | PILOT_HYP_PREP);
+}
+
 // Take a screenshot.
 void player_screenshot(void) {
   char filename[20];
diff --git a/src/player.h b/src/player.h
index 5278627..cc27499 100644
--- a/src/player.h
+++ b/src/player.h
@@ -2,12 +2,12 @@
 #include "pilot.h"
 
 // Flag definitions.
-#define PLAYER_TURN_LEFT  (1<<0)  // Player is turning left.
-#define PLAYER_TURN_RIGHT (1<<1)  // Player is turning right.
-#define PLAYER_REVERSE    (1<<2)
-#define PLAYER_FACE       (1<<10)  // Player is facing target.
-#define PLAYER_PRIMARY    (1<<11)  // Player is shooting primary weapon.
-#define PLAYER_SECONDARY  (1<<12)  // Player is shooting secondary weapon.
+#define PLAYER_TURN_LEFT  (1<<0)    // Player is turning left.
+#define PLAYER_TURN_RIGHT (1<<1)    // Player is turning right.
+#define PLAYER_REVERSE    (1<<2)    // Player is facint opposite vel.
+#define PLAYER_FACE       (1<<10)   // Player is facing target.
+#define PLAYER_PRIMARY    (1<<11)   // Player is shooting primary weapon.
+#define PLAYER_SECONDARY  (1<<12)   // Player is shooting secondary weapon.
 
 // Flag functions.
 #define player_isFlag(f)  (player_flags  & f)
@@ -33,6 +33,7 @@ void player_renderBG(void); // Render BG layer.
 // Misc.
 void player_message(const char* fmt, ...);
 void player_clear(void);
+void player_warp(const double x, const double y);
 
 // Keybind actions.
 void player_setRadarRel(int mod);
@@ -40,5 +41,7 @@ void player_board(void);
 void player_secondaryNext(void);
 void player_targetPlanet(void);
 void player_land(void);
+void player_targetHyperspace(void);
+void player_jump(void);
 void player_screenshot(void);
 
diff --git a/src/space.c b/src/space.c
index 58ce2c6..29c8ddb 100644
--- a/src/space.c
+++ b/src/space.c
@@ -35,7 +35,7 @@
 #define FLAG_ASTEROIDSSET   (1<<2)
 #define FLAG_INTEFERENCESET (1<<3)
 
-static StarSystem* systems = NULL;
+StarSystem* systems = NULL;
 static int nsystems = 0;
 StarSystem* cur_system = NULL; // Current star system.
 
@@ -56,6 +56,7 @@ static int mstars = 0;
 // Intern
 static Planet* planet_get(const char* name);
 static StarSystem* system_parse(const xmlNodePtr parent);
+static void system_parseJumps(const xmlNodePtr parent);
 static PlanetClass planetclass_get(const char a);
 // Extern.
 extern void player_message(const char* fmt, ...);
@@ -151,24 +152,26 @@ static PlanetClass planetclass_get(const char a) {
   };
 }
 
-// Hyperspaces, return 0 if entering hyperspace, or distance otherwise.
-int space_hyperspace(Pilot* p) {
+// Check distance to ensure we can go into hyperspace.
+int space_canHyperspace(Pilot* p) {
   int i;
   double d;
   for(i = 0; i < cur_system->nplanets; i++) {
     d = vect_dist(&p->solid->pos, &cur_system->planets[i].pos);
     if(d < MIN_HYPERSPACE_DIST)
-      return (int)(MIN_HYPERSPACE_DIST - d);
+      return 0;
   }
-  // Too fast.
-  if(VMOD(p->solid->vel) > MAX_HYPERSPACE_VEL) return -1;
+  return 1;
+}
 
-  // TODO: All hyperspace worky work.
-  if(p == player) {
-    // Player crap.
-  } else {
-    
-  }
+// Hyperspace, returns 0 if entering hyperspace, or the distance if not.
+int space_hyperspace(Pilot* p) {
+  if(!space_canHyperspace(p)) return -1;
+  // Too fast.
+  if(VMOD(p->solid->vel) > MAX_HYPERSPACE_VEL) return -2;
+
+  // Pilot is now going to get automatically ready for hyperspace.
+  pilot_setFlag(p, PILOT_HYP_PREP);
 
   return 0;
 }
@@ -432,7 +435,47 @@ static StarSystem* system_parse(const xmlNodePtr parent) {
   return tmp;
 }
 
+// Load the jumps into a system.
+static void system_parseJumps(const xmlNodePtr parent) {
+  int i;
+  StarSystem* system;
+  char* name;
+  xmlNodePtr cur, node;
+
+  name = xml_nodeProp(parent, "name"); // Already mallocs.
+  for(i = 0; i < nsystems; i++)
+    if(strcmp(systems[i].name, name)==0) {
+      system = &systems[i];
+      break;
+    }
+    if(i == nsystems) WARN("System '%s' was not found in the stack for some reason", name);
+    free(name); // No need for it now.
+
+    node = parent->xmlChildrenNode;
+
+    do {
+      // Load the data.
+      if(xml_isNode(node, "jumps")) {
+        cur = node->children;
+        do {
+          if(xml_isNode(cur, "jump")) {
+            for(i = 0; i < nsystems; i++)
+              if(strcmp(systems[i].name, xml_get(cur))==0) {
+                system->njumps++;
+                system->jumps = realloc(system->jumps, system->njumps*sizeof(int));
+                system->jumps[system->njumps-1] = i;
+                break;
+              }
+            if(i == nsystems)
+              WARN("System '%s' not found for jump linking", xml_get(cur));
+          }
+        } while((cur = cur->next));
+      }
+    } while((node = node->next));
+}
+
 // Load the ENTIRE universe into RAM. -- WOAH! -- Wasn't that bad. :P
+// -- Used a two system pass to first load the star systems and then set jump routes.
 int space_load(void) {
   uint32_t bufsize;
   char* buf = pack_readfile(DATA, SYSTEM_DATA, &bufsize);
@@ -452,6 +495,7 @@ int space_load(void) {
     ERR("Malformed "SYSTEM_DATA" file: does not contain elements");
     return -1;
   }
+  // Fist pass - Load all the star systems.
   do {
     if(xml_isNode(node, XML_SYSTEM_TAG)) {
       tmp = system_parse(node);
@@ -461,6 +505,14 @@ int space_load(void) {
     }
   } while((node = node->next));
 
+  // Second pass - Load all the jump routes.
+  node = doc->xmlChildrenNode->xmlChildrenNode;
+  do {
+    if(xml_isNode(node, XML_SYSTEM_TAG))
+      system_parseJumps(node); // Automatically load the jumps into the system.
+  } while((node = node->next));
+
+  // Cleanup.
   xmlFreeDoc(doc);
   free(buf);
   xmlCleanupParser();
@@ -506,10 +558,17 @@ void space_exit(void) {
     free(systems[i].name);
     if(systems[i].fleets)
       free(systems[i].fleets);
+    if(systems[i].jumps)
+      free(systems[i].jumps);
+
     for(j = 0; j < systems[i].nplanets; j++) {
       free(systems[i].planets[j].name);
       if(systems[i].planets[j].description)
         free(systems[i].planets[j].description);
+      if(systems[i].planets[j].bar_description)
+        free(systems[i].planets[j].bar_description);
+
+      // Graphics.
       if(systems[i].planets[j].gfx_space)
         gl_freeTexture(systems[i].planets[j].gfx_space);
       if(systems[i].planets[j].gfx_exterior)
diff --git a/src/space.h b/src/space.h
index 8169e0b..9c0380e 100644
--- a/src/space.h
+++ b/src/space.h
@@ -4,7 +4,7 @@
 #include "pilot.h"
 
 #define MIN_HYPERSPACE_DIST 1500
-#define MAX_HYPERSPACE_VEL  15
+#define MAX_HYPERSPACE_VEL  25
 
 // Planet types. I didn't take them from Star Trek, I promise.
 typedef enum {
@@ -72,6 +72,9 @@ typedef struct {
 
   SystemFleet* fleets; // Fleets that can appear in the current system.
   int nfleets;  // Total number of fleets.
+
+  int* jumps; // Adjacent star system index number.
+  int njumps; // Number of adjacent jumps.
 } StarSystem;
 
 extern StarSystem* cur_system; // Current star system.
@@ -86,6 +89,7 @@ void space_render(double dt);
 void planets_render(void);
 
 // Misc.
+int space_canHyperspace(Pilot* p);
 int space_hyperspace(Pilot* p);
 extern char* stardate;
 
diff --git a/src/toolkit.c b/src/toolkit.c
index dc88def..0b71861 100644
--- a/src/toolkit.c
+++ b/src/toolkit.c
@@ -7,7 +7,8 @@ typedef enum {
   WIDGET_NULL,
   WIDGET_BUTTON,
   WIDGET_TEXT,
-  WIDGET_IMAGE
+  WIDGET_IMAGE,
+  WIDGET_LIST
 } WidgetType;
 
 typedef enum {
@@ -33,7 +34,7 @@ typedef struct {
     };
     // Widget text.
     struct {
-      char* text;
+      char* text; // Use printMid for centered printText if not.
       glFont* font;
       glColour* colour;
       int centered;
@@ -42,6 +43,12 @@ typedef struct {
       // Widget image.
       glTexture* image;
     };
+    struct {
+      // Widget list.
+      char** options; // Pointer to the options.
+      int noptions;   // total number of options.
+      int selected;   // Currently selected option.
+    };
   };
 } Widget;
 
@@ -139,6 +146,26 @@ void window_addImage(const unsigned int wid, const int x, const int y,
   else wgt->y = (double)y;
 }
 
+void window_addList(const unsigned int wid, const int x, const int y,
+      const int w, const int h, char* name, char** items, int nitems, int defitem) {
+
+  Window *wdw = window_wget(wid);
+  Widget* wgt = window_newWidget(wdw);
+
+  wgt->type = WIDGET_LIST;
+  wgt->name = strdup(name);
+
+  wgt->options = items;
+  wgt->noptions = nitems;
+  wgt->selected = defitem; // -1 would be none.
+  wgt->w = (double) w;
+  wgt->h = (double) h;
+  if(x < 0) wgt->x = wdw->w - wgt->w + x;
+  else wgt->x = (double) x;
+  if(y < 0) wgt->y = wdw->h - wgt->h + y;
+  else wgt->y = (double) y;
+}
+
 // Return pointer to newly allocated widget.
 static Widget* window_newWidget(Window* w) {
   Widget* wgt = NULL;
@@ -458,6 +485,9 @@ static void window_render(Window* w) {
       case WIDGET_IMAGE:
         toolkit_renderImage(&w->widgets[i], x, y);
         break;
+      case WIDGET_LIST:
+        // TODO widget list rendering.
+        break;
     }
   }
 }