From 980282f65538cb73dc8c151fbfa7f23aa918aa01 Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Sat, 14 Dec 2013 14:58:31 +0000
Subject: [PATCH] [Add] Implementing auto navigation.

---
 src/input.c  | 35 ++++++++++++++++++++++++++++-------
 src/map.c    |  2 +-
 src/pilot.c  |  4 ++++
 src/player.c | 28 +++++++++++++++++++++++++++-
 src/player.h |  2 ++
 5 files changed, 62 insertions(+), 9 deletions(-)

diff --git a/src/input.c b/src/input.c
index 39d34a6..05213aa 100644
--- a/src/input.c
+++ b/src/input.c
@@ -30,13 +30,20 @@ static Keybind** input_keybinds; /**< Contains the players keybindings. */
 
 /* Name of each keybinding. */
 const char* keybindNames[] = {
-  "accel", "left", "right", "reverse", /* Movement. */
-  "target", "target_nearest", "target_hostile", /* Targetting. */
-  "primary", "face", "board", /* Fighting. */
-  "secondary", "secondary_next", /* Secondary weapons. */
-  "target_planet", "land", "thyperspace","starmap", "jump", /* Navigation. */
-  "mapzoomin", "mapzoomout", "screenshot", "pause", "menu", "info", /* Misc. */
-  "end" }; /* Must terminate at the end. */
+	/* Movement. */
+  "accel", "left", "right", "reverse",
+  /* Targetting. */
+  "target", "target_nearest", "target_hostile",
+  /* Fighting. */
+  "primary", "face", "board",
+  /* Secondary weapons. */
+  "secondary", "secondary_next",
+  /* Space Navigation. */
+  "autonav", "target_planet", "land", "thyperspace","starmap", "jump",
+  /* Misc. */
+  "mapzoomin", "mapzoomout", "screenshot", "pause", "menu", "info",
+  "end" /* Must terminate at the end. */
+};
 
 /* Accel hacks. */
 static unsigned int input_accelLast  = 0;       /**< Used to see if double tap. */
@@ -71,6 +78,7 @@ void input_setDefault(void) {
   input_setKeybind("secondary",       KEYBIND_KEYBOARD, SDLK_LSHIFT,      0);
   input_setKeybind("secondary_next",  KEYBIND_KEYBOARD, SDLK_e,           0);
   /* Space */
+  input_setKeybind("autonav",					KEYBIND_KEYBOARD, SDLK_n,						0);
   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);
@@ -177,6 +185,7 @@ static void input_key(int keynum, double value, int kabs) {
 
   /* Accelerating. */
   if(KEY("accel")) {
+  	player_abortAutonav();
     if(kabs)player_accel(value);
     else {
       /* Prevent it from getting stuck. */
@@ -196,6 +205,7 @@ static void input_key(int keynum, double value, int kabs) {
   }
   /* Turning left. */
   else if(KEY("left")) {
+  	player_abortAutonav();
     /* Set flags for facing correction. */
     if(value == KEY_PRESS) { player_setFlag(PLAYER_TURN_LEFT); }
     else if(value == KEY_RELEASE) { player_rmFlag(PLAYER_TURN_LEFT); }
@@ -206,6 +216,7 @@ static void input_key(int keynum, double value, int kabs) {
   }
   /* Turning right. */
   else if(KEY("right")) {
+  	player_abortAutonav();
     /* Set flags for facing correction. */
     if(value == KEY_PRESS) { player_setFlag(PLAYER_TURN_RIGHT); }
     else if(value == KEY_RELEASE) { player_rmFlag(PLAYER_TURN_RIGHT); }
@@ -217,6 +228,7 @@ static void input_key(int keynum, double value, int kabs) {
   }
   /* Turn around to face vel. */
   else if(KEY("reverse")) {
+  	player_abortAutonav();
     if(value == KEY_PRESS) { player_setFlag(PLAYER_REVERSE); }
     else if(value == KEY_RELEASE) {
       player_rmFlag(PLAYER_REVERSE);
@@ -227,6 +239,7 @@ static void input_key(int keynum, double value, int kabs) {
   }
   /* Shoot primary weapon. BOOM BOOM. */
   else if(KEY("primary")) {
+  	player_abortAutonav();
     if(value == KEY_PRESS) { player_setFlag(PLAYER_PRIMARY); }
     else if(value == KEY_RELEASE) { player_rmFlag(PLAYER_PRIMARY); }
   }
@@ -242,6 +255,7 @@ static void input_key(int keynum, double value, int kabs) {
   }
   /* Face the target. */
   else if(KEY("face")) {
+  	player_abortAutonav();
     if(value == KEY_PRESS) { player_setFlag(PLAYER_FACE); }
     else if(value == KEY_RELEASE) {
       player_rmFlag(PLAYER_FACE);
@@ -254,6 +268,7 @@ static void input_key(int keynum, double value, int kabs) {
   }
   /* Board those ships. */
   else if(KEY("board") && INGAME() && NOHYP()) {
+  	player_abortAutonav();
     if(value == KEY_PRESS) player_board();
   }
   /* Shooting secondary weapon. */
@@ -266,21 +281,27 @@ static void input_key(int keynum, double value, int kabs) {
     if(value == KEY_PRESS) player_secondaryNext();
   }
   /* Space. */
+  else if(KEY("autonav") && INGAME() && NOHYP()) {
+  	if(value == KEY_PRESS) player_startAutonav();
+  }
   /* Target planet (cycles just like target). */
   else if(KEY("target_planet") && INGAME() && NOHYP()) {
     if(value == KEY_PRESS) player_targetPlanet();
   }
   /* Target nearest planet or attempt to land. */
   else if(KEY("land") && INGAME() && NOHYP()) {
+  	player_abortAutonav();
     if(value == KEY_PRESS) player_land();
   }
   else if(KEY("thyperspace") && INGAME() && NOHYP()) {
+  	player_abortAutonav();
     if(value == KEY_PRESS) player_targetHyperspace();
   }
   else if(KEY("starmap") && NOHYP()) {
     if(value == KEY_PRESS) map_open();
   }
   else if(KEY("jump") && INGAME()) {
+  	player_abortAutonav();
     if(value == KEY_PRESS) player_jump();
   }
   /* Zoom in. */
diff --git a/src/map.c b/src/map.c
index 1b1d08a..5fc0e19 100644
--- a/src/map.c
+++ b/src/map.c
@@ -25,7 +25,7 @@ static double map_xpos  = 0.;         /* Map position. */
 static double map_ypos  = 0.;
 static int map_selected = -1;
 static StarSystem** map_path = NULL;  /* The path to current selected system. */
-static int map_npath = 0;
+int map_npath = 0;
 
 static int map_drag = 0;              /* Is the user dragging the map? */
 
diff --git a/src/pilot.c b/src/pilot.c
index 995e135..5a1b523 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -38,6 +38,7 @@ static int pilot_mstack = 0; /** Memory allocated for pilot_stack. */
 
 extern Pilot* player;
 extern unsigned int player_crating; /**< Players combat rating. */
+extern void player_abortAutonav(void);
 
 /* Stack of fleets. */
 static Fleet* fleet_stack = NULL; /** Fleet stack. */
@@ -371,6 +372,9 @@ void pilot_hit(Pilot* p, const Solid* w, const unsigned int shooter,
   /* Calculate the damage. */
   outfit_calcDamage(&damage_shield, &damage_armour, &knockback,  dtype, damage);
 
+  if(p->id == PLAYER_ID)
+  	player_abortAutonav();
+
   if(p->shield - damage_shield > 0.) { /* Shields take the whole blow. */
     p->shield -= damage_shield;
     dam_mod = damage_shield/p->shield_max;
diff --git a/src/player.c b/src/player.c
index 9b6cfb2..9ed93d4 100644
--- a/src/player.c
+++ b/src/player.c
@@ -95,6 +95,9 @@ extern int pilot_nstack;
 /* Space stuff for GUI. */
 extern StarSystem* systems_stack;
 
+/* Map stuff for autonav. */
+extern int map_npath;
+
 /**
  * @struct Radar
  *
@@ -1466,8 +1469,16 @@ void gui_free(void) {
   free(msg_stack);
 }
 
+/**
+ * @fn void player_startAutonav(void)
+ *
+ * @brief Start autonav.
+ */
 void player_startAutonav(void) {
-  player_message("Autonav continuing.");
+  if(hyperspace_target == -1)
+  	return;
+
+  player_message("Autonav initialized");
   player_setFlag(PLAYER_AUTONAV);
 }
 
@@ -1505,6 +1516,10 @@ void player_think(Pilot* pplayer) {
 
     if(space_canHyperspace(pplayer))
       player_jump();
+  	else {
+      pilot_face(pplayer, VANGLE(pplayer->solid->pos));
+      player_acc = 1.;
+  	}
   }
 
   /* PLAYER_FACE will take over navigation. */
@@ -1795,6 +1810,17 @@ void player_brokeHyperspace(void) {
   /* Update the map. */
   map_jump();
 
+  /* Disable autonavigation if arrived. */
+  if(player_isFlag(PLAYER_AUTONAV)) {
+    if(hyperspace_target == -1) {
+      player_message("Autonav arrived at destination.");
+      player_rmFlag(PLAYER_AUTONAV);
+    } else {
+      player_message("Autonav continuing until destination (%d jumps left).",
+          map_npath);
+    }
+  }
+  
   /* Run the jump hooks. */
   hooks_run("jump");
   hooks_run("enter");
diff --git a/src/player.h b/src/player.h
index 7777d3c..2315a34 100644
--- a/src/player.h
+++ b/src/player.h
@@ -86,4 +86,6 @@ void player_afterburn(void);
 void player_afterburnOver(void);
 void player_accel(double acc);
 void player_accelOver(void);
+void player_startAutonav(void);
+void player_abortAutonav(void);