From 1b3d884f7e071764fdb0135f5e06c0320885c5fd Mon Sep 17 00:00:00 2001
From: Allanis <allanis@saracraft.net>
Date: Tue, 9 Apr 2013 01:14:16 +0100
Subject: [PATCH] [Add] Unique missions are now actually.. Unique.

---
 dat/missions/cargo.lua    |  4 ++--
 dat/missions/empire00.lua |  2 +-
 src/misn_lua.c            | 12 ++++++++++++
 src/mission.c             | 13 +++++++++++++
 src/mission.h             |  3 +++
 src/player.c              | 32 ++++++++++++++++++++++++++++++++
 src/player.h              |  4 ++++
 7 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/dat/missions/cargo.lua b/dat/missions/cargo.lua
index 84dcbb0..61ac2a9 100644
--- a/dat/missions/cargo.lua
+++ b/dat/missions/cargo.lua
@@ -31,7 +31,7 @@ function create()
   until planet ~= space.landName() or i > 10
   -- Protect agains inf loop.
   if i > 10 then
-    misn.finish()
+    misn.finish(false)
   end
 
   -- Missions generic.
@@ -67,7 +67,7 @@ function land()
     if player.rmCargo(carg_id) then
       player.pay(reward)
       tk.msg(finish_title, string.format(finish_msg, carg_type))
-      misn_finish()
+      misn_finish(true)
     else
       tk.msg(miss_title, string.format(miss_msg, carg_mass, carg_type))
     end
diff --git a/dat/missions/empire00.lua b/dat/missions/empire00.lua
index f74e1ed..3f5be6f 100644
--- a/dat/missions/empire00.lua
+++ b/dat/missions/empire00.lua
@@ -46,7 +46,7 @@ function land()
       player.pay(reward)
       -- More flavour text :)
       tk.msg(title[3], string.format(text[4], dest))
-      misn.finish()
+      misn.finish(true)
     end
   end
 end
diff --git a/src/misn_lua.c b/src/misn_lua.c
index abbe76c..7e9323c 100644
--- a/src/misn_lua.c
+++ b/src/misn_lua.c
@@ -10,6 +10,7 @@
 #include "space.h"
 #include "toolkit.h"
 #include "land.h"
+#include "player.h"
 #include "misn_lua.h"
 
 // FUCK LUA!!!                                                                  
@@ -215,8 +216,19 @@ static int misn_accept(lua_State* L) {
 }
 
 static int misn_finish(lua_State* L) {
+  int b;
+
+  if(lua_isboolean(L, -1)) b = lua_toboolean(L, -1);
+  else {
+    DEBUG("Mission '%s' trying to finish without specifying if mission is complete",
+        cur_mission->data->name);
+    return 0;
+  }
   misn_delete = 1;
 
+  if(b && mis_isFlag(cur_mission->data, MISSION_UNIQUE))
+    player_missionFinished(mission_getID(cur_mission->data));
+
   lua_pushstring(L, "Mission Finished");
   lua_error(L); // Should not return..
 
diff --git a/src/mission.c b/src/mission.c
index 7f34d1f..19b7623 100644
--- a/src/mission.c
+++ b/src/mission.c
@@ -43,6 +43,17 @@ static int  mission_matchFaction(MissionData* misn, int faction);
 static int mission_location(char* loc);
 static MissionData* mission_parse(const xmlNodePtr parent);
 
+// Gets the ID of a MissionData.
+int mission_getID(MissionData* misn) {
+  int i;
+  for(i = 0; i < mission_nstack; i++)
+    if(misn == &mission_stack[i])
+      return i;
+
+  DEBUG("Mission '%s' not found in stack", misn->name);
+  return -1;
+}
+
 // Initialize a mission.
 static int mission_init(Mission* mission, MissionData* misn) {
   char* buf;
@@ -103,6 +114,8 @@ void missions_bar(int faction, char* planet, char* system) {
         (((misn->avail.planet && strcmp(misn->avail.planet, planet)==0)) ||
          (misn->avail.system && (strcmp(misn->avail.system, system)==0)) ||
          mission_matchFaction(misn, faction))) {
+
+      if(player_missionAlreadyDone(i)) continue; // Already done the mission.
       
       chance = (double)(misn->avail.chance % 100)/100.;
 
diff --git a/src/mission.h b/src/mission.h
index add1471..2d0aed7 100644
--- a/src/mission.h
+++ b/src/mission.h
@@ -65,6 +65,9 @@ Mission* missions_computer(int* n, int faction, char* planet, char* system);
 void mission_accept(Mission* mission);
 void mission_bar(int faction, char* planet, char* system);
 
+// Misc.
+int mission_getID(MissionData* misn);
+
 // Cargo stuff.
 void mission_linkCargo(Mission* misn, unsigned int cargo_id);
 void mission_unlinkCargo(Mission* misn, unsigned int cargo_id);
diff --git a/src/player.c b/src/player.c
index 0d31f7c..78a1265 100644
--- a/src/player.c
+++ b/src/player.c
@@ -15,6 +15,7 @@
 #include "pause.h"
 #include "menu.h"
 #include "toolkit.h"
+#include "mission.h"
 #include "player.h"
 
 #define XML_GUI_ID    "GUIs" // XML section identifier.
@@ -52,6 +53,10 @@ int hyperspace_target = -1;   // Target hyperspace route.
 static unsigned int player_timer = 0;
 static Vec2 player_cam;
 
+static int* missions_done = NULL; // Saves position.
+static int  missions_mdone = 0;
+static int  missions_ndone = 0;
+
 // Pilot stuff for GUI.
 extern Pilot** pilot_stack;
 extern int pilots;
@@ -310,6 +315,12 @@ void player_cleanup(void) {
     // Nothing left.
     player_nstack = 0;
   }
+  if(missions_done) {
+    free(missions_done);
+    missions_done   = NULL;
+    missions_ndone  = 0;
+    missions_mdone  = 0;
+  }
 }
 
 void player_message(const char* fmt, ...) {
@@ -1369,3 +1380,24 @@ void player_setLoc(char* shipname, char* loc) {
   WARN("Player ship '%s' not found in stack", shipname);
 }
 
+// Marks a mission as completed.
+void player_missionFinished(int id) {
+  missions_ndone++;
+  if(missions_ndone > missions_mdone) {
+    // Need to grow.
+    missions_mdone += 25;
+    missions_done = realloc(missions_done, sizeof(int) * missions_mdone);
+  }
+  missions_done[missions_ndone-1] = id;
+}
+
+// has player already completed a mission?
+int player_missionAlreadyDone(int id) {
+  int i;
+
+  for(i = 0; i < missions_ndone; i++)
+    if(missions_done[i] == id)
+      return 1;
+  return 0;
+}
+
diff --git a/src/player.h b/src/player.h
index d985c0d..6bfbc36 100644
--- a/src/player.h
+++ b/src/player.h
@@ -58,6 +58,10 @@ char*  player_getLoc(char* shipname);
 void   player_setLoc(char* shipname, char* loc);
 void   player_swapShip(char* shipname);
 
+// Player missions.
+void player_missionFinished(int id);
+int player_missionAlreadyDone(int id);
+
 // Keybind actions.
 void player_setRadarRel(int mod);
 void player_secondaryNext(void);