From 692fb388df013bd46dfe6a815e9a4dca5b42089b Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Wed, 26 Jun 2013 00:28:16 +0100
Subject: [PATCH] [Add] Missions can now mark systems. [Fix] Seg fault when
 switching pilots.

---
 dat/missions/cargo.lua |  1 +
 src/map.c              | 25 +++++++++++++++++++-----
 src/misn_lua.c         | 31 ++++++++++++++++++++++-------
 src/mission.c          | 44 ++++++++++++++++++++++++++++++++----------
 src/mission.h          |  3 +++
 src/player.c           |  3 ++-
 src/space.c            |  8 ++++++++
 src/space.h            |  4 +++-
 8 files changed, 95 insertions(+), 24 deletions(-)

diff --git a/dat/missions/cargo.lua b/dat/missions/cargo.lua
index ac36c31..48dc702 100644
--- a/dat/missions/cargo.lua
+++ b/dat/missions/cargo.lua
@@ -43,6 +43,7 @@ function create()
     misn.finish(false)
   end
   system = space.getSystem(planet)
+  misn.setMarker(system) -- Mark the system.
   misn_dist = space.jumpDist(system)
 
   -- Mission generics.
diff --git a/src/map.c b/src/map.c
index 36ed00c..1c25bd3 100644
--- a/src/map.c
+++ b/src/map.c
@@ -7,6 +7,7 @@
 #include "toolkit.h"
 #include "space.h"
 #include "opengl.h"
+#include "mission.h"
 #include "map.h"
 
 #define WINDOW_WIDTH  550
@@ -55,6 +56,9 @@ void map_open(void) {
   map_xpos = cur_system->pos.x;
   map_ypos = cur_system->pos.y;
 
+  /* Mark systems as needed. */
+  mission_sysMark();
+
   map_wid = window_create("Star Map", -1, -1, WINDOW_WIDTH, WINDOW_HEIGHT);
 
   window_addText(map_wid, -20, -20, 100, 20, 1, "txtSysname",
@@ -175,8 +179,8 @@ static void map_render(double bx, double by, double w, double h) {
   for(i = 0; i < systems_nstack; i++) {
     sys = &systems_stack[i];
 
-    /* Check to make sure system is known of adjacent to known. */
-    if(!space_sysReachable(sys)) continue;
+    /* Check to make sure system is known of adjacent to known (or marked). */
+    if(!sys_isMarked(sys) && !space_sysReachable(sys)) continue;
 
     /* System Colours. */
     if(sys == cur_system) COLOUR(cRadar_targ);
@@ -184,9 +188,20 @@ static void map_render(double bx, double by, double w, double h) {
     else if(areEnemies(player->faction, sys->faction)) COLOUR(cRed);
     else COLOUR(cYellow);
 
-    gl_drawCircleInRect(x + sys->pos.x*map_zoom,
-                        y + sys->pos.y*map_zoom,
-                        r, bx, by, w, h);
+    /* Draw the system. */
+    tx = x + sys->pos.x * map_zoom;
+    ty = y + sys->pos.y * map_zoom;
+    gl_drawCircleInRect(tx, ty, r, bx, by, w, h);
+
+    /* Mark the system if needed. */
+    if(sys_isMarked(sys)) {
+      COLOUR(cRed);
+      glBegin(GL_TRIANGLES);
+        glVertex2d(tx+r+9, ty+r+3);
+        glVertex2d(tx+r+3, ty+r+3);
+        glVertex2d(tx+r+3, ty+r+9);
+      glEnd();
+    }
 
     /* Draw the system name. */
     if(sys_isKnown(sys)) {
diff --git a/src/misn_lua.c b/src/misn_lua.c
index 444f3a6..205acab 100644
--- a/src/misn_lua.c
+++ b/src/misn_lua.c
@@ -54,6 +54,8 @@ static unsigned int  hook_generic(lua_State* L, char* stack);
 int misn_run(Mission* misn, char* func);
 int var_save(xmlTextWriterPtr writer);
 int var_load(xmlNodePtr parent);
+/* External. */
+extern void mission_sysMark(void);
 
 /* -- Libraries. -- */
 
@@ -61,6 +63,7 @@ int var_load(xmlNodePtr parent);
 static int misn_setTitle(lua_State* L);
 static int misn_setDesc(lua_State* L);
 static int misn_setReward(lua_State* L);
+static int misn_setMarker(lua_State* L);
 static int misn_factions(lua_State* L);
 static int misn_accept(lua_State* L);
 static int misn_finish(lua_State* L);
@@ -68,6 +71,7 @@ static const luaL_reg misn_methods[] = {
   { "setTitle",     misn_setTitle   },
   { "setDesc",      misn_setDesc    },
   { "setReward",    misn_setReward  },
+  { "setMarker",    misn_setMarker  },
   { "factions",     misn_factions   },
   { "accept",       misn_accept     },
   { "finish",       misn_finish     },
@@ -333,34 +337,47 @@ static int var_add(misn_var* new_var) {
 
 static int misn_setTitle(lua_State* L) {
   LLUA_MIN_ARGS(1);
-  if(lua_isstring(L, -1)) {
+  if(lua_isstring(L, 1)) {
     if(cur_mission->title)
       /* Cleanup the old title. */
       free(cur_mission->title);
-    cur_mission->title = strdup((char*)lua_tostring(L, -1));
+    cur_mission->title = strdup((char*)lua_tostring(L, 1));
   }
   return 0;
 }
 
 static int misn_setDesc(lua_State* L) {
   LLUA_MIN_ARGS(1);
-  if(lua_isstring(L, -1)) {
+  if(lua_isstring(L, 1)) {
     if(cur_mission->desc)
       /* Cleanup the old description. */
       free(cur_mission->desc);
-    cur_mission->desc = strdup((char*)lua_tostring(L, -1));
+    cur_mission->desc = strdup((char*)lua_tostring(L, 1));
   }
   return 0;
 }
 
 static int misn_setReward(lua_State* L) {
   LLUA_MIN_ARGS(1);
-  if(lua_isstring(L, -1)) {
-    if(cur_mission->reward)
+  if(lua_isstring(L, 1)) {
+    if(cur_mission->reward != NULL) /* Cleanup old reward. */
       /* Cleanup the old reward. */
       free(cur_mission->reward);
-    cur_mission->reward = strdup((char*)lua_tostring(L, -1));
+    cur_mission->reward = strdup((char*)lua_tostring(L, 1));
   }
+  else LLUA_INVALID_PARAMETER();
+  return 0;
+}
+
+static int misn_setMarker(lua_State* L) {
+  LLUA_MIN_ARGS(1);
+  if(lua_isstring(L, 1)) {
+    if(cur_mission->sys_marker != NULL) /* Cleanup old markers. */
+      free(cur_mission->sys_marker);
+    cur_mission->sys_marker = strdup((char*)lua_tostring(L, 1));
+    mission_sysMark();
+  }
+  else LLUA_INVALID_PARAMETER();
   return 0;
 }
 
diff --git a/src/mission.c b/src/mission.c
index 39cc20a..f3243fe 100644
--- a/src/mission.c
+++ b/src/mission.c
@@ -12,6 +12,8 @@
 #include "xml.h"
 #include "faction.h"
 #include "player.h"
+#include "base64.h"
+#include "space.h"
 #include "mission.h"
 
 #define XML_MISSION_ID    "Missions"  /* XML section identifier. */
@@ -28,6 +30,10 @@ Mission player_missions[MISSION_MAX];
 static MissionData* mission_stack = NULL; /* Unmuteable after creation. */
 static int mission_nstack = 0;
 
+/* External space stack. */
+extern StarSystem* systems_stack;
+extern int systems_nstack;
+
 /* Extern. */
 extern int misn_run(Mission* misn, char* func);
 
@@ -83,6 +89,9 @@ static int mission_init(Mission* mission, MissionData* misn, int load) {
   char* buf;
   uint32_t bufsize;
 
+  /* Clear the mission. */
+  memset(mission, 0, sizeof(Mission));
+
   if(load != 0)
     mission->id = 0;
   else
@@ -90,13 +99,6 @@ static int mission_init(Mission* mission, MissionData* misn, int load) {
 
   mission->data = misn;
 
-  /* Sane defaults. */
-  mission->title    = NULL;
-  mission->desc     = NULL;
-  mission->reward   = NULL;
-  mission->cargo    = NULL;
-  mission->ncargo   = 0;
-
   /* Init lua. */
   mission->L = luaL_newstate();
   if(mission->L == NULL) {
@@ -243,6 +245,21 @@ void missions_bar(int faction, char* planet, char* system) {
   }
 }
 
+/* Mark all active systems that need marking. */
+void mission_sysMark(void) {
+  int i;
+  StarSystem* sys;
+
+  space_clearMarkers();
+
+  for(i = 0; i < MISSION_MAX; i++) {
+    if(player_missions[i].sys_marker != NULL) {
+      sys = system_get(player_missions[i].sys_marker);
+      sys_setFlag(sys, SYSTEM_MARKED);
+    }
+  }
+}
+
 /* Links cargo to the mission for posterior cleanup. */
 void mission_linkCargo(Mission* misn, unsigned int cargo_id) {
   misn->ncargo++;
@@ -287,12 +304,16 @@ void mission_cleanup(Mission* misn) {
     free(misn->desc);
     misn->desc = NULL;
   }
-  if(misn->reward) {
+  if(misn->reward != NULL) {
     free(misn->reward);
     misn->reward = NULL;
   }
-  if(misn->cargo) {
-    for(i = 0; i < misn->ncargo; i++)
+  if(misn->sys_marker != NULL) {
+    free(misn->sys_marker);
+    misn->sys_marker = NULL;
+  }
+  if(misn->cargo != NULL) {
+    for(i = 0; i < misn->ncargo; i++) /* Must unlink all the cargo. */
       mission_unlinkCargo(misn, misn->cargo[i]);
     free(misn->cargo);
     misn->cargo = NULL;
@@ -594,6 +615,8 @@ int missions_saveActive(xmlTextWriterPtr writer) {
       xmlw_elem(writer, "title", player_missions[i].title);
       xmlw_elem(writer, "desc", player_missions[i].desc);
       xmlw_elem(writer, "reward", player_missions[i].reward);
+      if(player_missions[i].sys_marker != NULL)
+        xmlw_elem(writer, "marked", player_missions[i].sys_marker);
 
       xmlw_startElem(writer, "cargos");
       for(j = 0; j < player_missions[i].ncargo; j++)
@@ -659,6 +682,7 @@ static int missions_parseActive(xmlNodePtr parent) {
         xmlr_strd(cur, "title", misn->title);
         xmlr_strd(cur, "desc",  misn->desc);
         xmlr_strd(cur, "reward", misn->reward);
+        xmlr_strd(cur, "marker", misn->sys_marker);
 
         if(xml_isNode(cur, "cargos")) {
           nest = cur->xmlChildrenNode;
diff --git a/src/mission.h b/src/mission.h
index bcae8de..b99e2a9 100644
--- a/src/mission.h
+++ b/src/mission.h
@@ -55,6 +55,8 @@ typedef struct Mission_ {
   unsigned int* cargo;
   int ncargo;
 
+  char* sys_marker; /* Marked system. */
+
   lua_State* L; /* The state of the running lua code. */
 } Mission;
 
@@ -70,6 +72,7 @@ void missions_bar(int faction, char* planet, char* system);
 /* Misc. */
 int mission_getID(char* name);
 MissionData* mission_get(int id);
+void mission_sysMark(void);
 
 /* Cargo stuff. */
 void mission_linkCargo(Mission* misn, unsigned int cargo_id);
diff --git a/src/player.c b/src/player.c
index 6a0a5ca..324afc8 100644
--- a/src/player.c
+++ b/src/player.c
@@ -514,7 +514,8 @@ int player_cargoOwned(const char* commodityname) {
 void player_rmMissionCargo(unsigned int cargo_id) {
   int i;
 
-  if(!pilot_rmMissionCargo(player, cargo_id)) return; /* Already done. */
+  /* Check if already done. */
+  if((player != NULL) && !pilot_rmMissionCargo(player, cargo_id)) return;
 
   for(i = 0; i < player_nstack; i++)
     if(!pilot_rmMissionCargo(player_stack[i], cargo_id))
diff --git a/src/space.c b/src/space.c
index 2db9713..fe7a34d 100644
--- a/src/space.c
+++ b/src/space.c
@@ -925,12 +925,20 @@ void space_exit(void) {
   nstars  = 0;
 }
 
+/* Clear all system knowledge. */
 void space_clearKnown(void) {
   int i;
   for(i = 0; i < systems_nstack; i++)
     sys_rmFlag(&systems_stack[i], SYSTEM_KNOWN);
 }
 
+/* Clear all system markers. */
+void space_clearMarkers(void) {
+  int i;
+  for( i = 0; i < systems_nstack; i++)
+    sys_rmFlag(&systems_stack[i], SYSTEM_MARKED);
+}
+
 /* Save what is needed to be saved for space. */
 int space_sysSave(xmlTextWriterPtr writer) {
   int i;
diff --git a/src/space.h b/src/space.h
index 08de89b..d094b0a 100644
--- a/src/space.h
+++ b/src/space.h
@@ -76,7 +76,8 @@ typedef struct Planet_ {
 #define sys_isFlag(s,f)   ((s)->flags & (f))
 #define sys_setFlag(s,f)  if(!sys_isFlag(s,f)) (s)->flags |= (f)
 #define sys_rmFlag(s,f)   if(sys_isFlag(s,f))  (s)->flags ^= (f)
-#define sys_isKnown(s)    ((s)->flags & SYSTEM_KNOWN)
+#define sys_isKnown(s)    sys_isFlag(s, SYSTEM_KNOWN)
+#define sys_isMarked(s)   sys_isFlag(s, SYSTEM_MARKED)
 
 /* Star systems. */
 typedef struct SystemFleet_ {
@@ -130,5 +131,6 @@ int space_sysReachable(StarSystem* sys);
 char** space_getFactionPlanet(int* nplanets, int* factions, int nfactions);
 char* space_getRndPlanet(void);
 void  space_clearKnown(void);
+void  space_clearMarkers(void);
 extern char* stardate;