diff --git a/dat/mission.xml b/dat/mission.xml
new file mode 100644
index 0000000..b118828
--- /dev/null
+++ b/dat/mission.xml
@@ -0,0 +1,17 @@
+
+
+ welcome
+
+ None
+
+
+
+ cargo
+
+ Computer
+ Neutral
+ Empire United
+
+
+
+
diff --git a/dat/missions/cargo.lua b/dat/missions/cargo.lua
new file mode 100644
index 0000000..ea9ba8a
--- /dev/null
+++ b/dat/missions/cargo.lua
@@ -0,0 +1,37 @@
+-- Create the mission.
+function create()
+ -- Target destination.
+ planet = space.getPlanet(misn.factions())
+
+ -- Missions generic.
+ misn_type = "Rush"
+ misn_setTitle("Rush Delivery to " .. planet)
+
+ -- More mission specifics.
+ carg_mass = rnd.int(10, 30)
+ carg.type = rnd.setDesc(string.format(
+ "%s needs a rush delivery of %d tons of %s by %s.",
+ planet, carg_mass, carg_type, "SOMEDAY"))
+ misn_reward = carg_mass * 1000 + rnd.int(0, 5000)
+ misn.setReward(string.format("%d Scred" misn_reward))
+
+ -- Set the hooks.
+ hook.land("land")
+end
+
+function accept()
+ player.addCargo(carg_type, carg_mass)
+ toolkit.msg("Mission Accepted",
+ string.format("The workers load the %d tons of %s onto your ship."
+ carg_mass, carg_type))
+end
+
+function land()
+ if planet.name() == planet then
+ player.rmCargo(carg_type, carg_mass)
+ player.pay(misn_reward)
+ toolkit.msg("Mission Accomplished",
+ string.format("The workers unload the %s at the docks.", carg_type))
+ end
+end
+
diff --git a/src/lephisto.c b/src/lephisto.c
index 49d0729..5afc26b 100644
--- a/src/lephisto.c
+++ b/src/lephisto.c
@@ -27,6 +27,7 @@
#include "spfx.h"
#include "economy.h"
#include "menu.h"
+#include "mission.h"
#include "music.h"
#define XML_START_ID "Start"
@@ -207,7 +208,8 @@ int main(int argc, char** argv) {
void load_all(void) {
// Ordering of these is very important as they are interdependent.
commodity_load();
- factions_load();
+ factions_load(); // Dep for fleet, space, missions.
+ missions_load(); // No dep.
spfx_load();
outfit_load();
ships_load();
@@ -221,6 +223,7 @@ void unload_all(void) {
ships_free();
outfit_free();
spfx_free(); // Remove the special effects.
+ missions_free();
factions_free();
commodity_free();
}
diff --git a/src/mission.c b/src/mission.c
index 5d86650..51d01e7 100644
--- a/src/mission.c
+++ b/src/mission.c
@@ -1,3 +1,4 @@
+#include
#include
#include
@@ -8,8 +9,16 @@
#include "lephisto.h"
#include "log.h"
#include "hook.h"
+#include "pack.h"
+#include "xml.h"
#include "mission.h"
+#define XML_MISSION_ID "Missions" // XML section identifier.
+#define XML_MISSION_TAG "mission"
+
+#define MISSION_DATA "../dat/mission.xml"
+#define MISSION_LUA_PATH "../dat/missions/"
+
// Current player missions.
static unsigned int mission_id = 0;
Mission player_missions[MISSION_MAX];
@@ -24,6 +33,8 @@ extern int misn_run(Mission* misn, char* func);
// Static.
static void mission_cleanup(Mission* misn);
static void mission_free(MissionData* mission);
+static int mission_location(char* loc);
+static MissionData* mission_parse(const xmlNodePtr parent);
// Create a mission.
int mission_create(MissionData* misn) {
@@ -84,25 +95,98 @@ static void mission_free(MissionData* mission) {
}
}
+// Return location based on string.
+static int mission_location(char* loc) {
+ if(strcmp(loc, "None")==0) return MIS_AVAIL_NONE;
+ else if(strcmp(loc, "Computer")==0) return MIS_AVAIL_COMPUTER;
+ else if(strcmp(loc, "Bar")==0) return MIS_AVAIL_BAR;
+ else if(strcmp(loc, "Outfit")==0) return MIS_AVAIL_OUTFIT;
+ else if(strcmp(loc, "Shipyard")==0) return MIS_AVAIL_SHIPYARD;
+ else if(strcmp(loc, "Land")==0) return MIS_AVAIL_LAND;
+
+ return -1;
+}
+
+// Parse a node of a mission.
+static MissionData* mission_parse(const xmlNodePtr parent) {
+ MissionData* tmp;
+ xmlNodePtr cur, node;
+
+ tmp = malloc(sizeof(MissionData));
+ memset(tmp, 0, sizeof(MissionData));
+
+ // Get the name.
+ tmp->name = xml_nodeProp(parent, "name");
+ if(tmp->name == NULL) WARN("Mission in "MISSION_DATA" has invalid or no name");
+
+ node = parent->xmlChildrenNode;
+
+ char str[PATH_MAX] = "\0";
+
+ // Load all the data.
+ do {
+ if(xml_isNode(node, "lua")) {
+ snprintf(str, PATH_MAX, MISSION_LUA_PATH"%s.lua", xml_get(node));
+ tmp->lua = strdup(str);
+ str[0] = '\0';
+ }
+ else if(xml_isNode(node, "avail")) {
+ cur = node->children;
+ do {
+ if(xml_isNode(cur, "location"))
+ tmp->avail.loc = mission_location(xml_get(cur));
+ /*else if(xml_isNode(cur, "")) // Need to parse other thingies.
+ tmp->u.amm.damage_shield = xml_getFloat(cur);*/
+ } while((cur = cur->next));
+ }
+ } while((node = node->next));
+#define MELEMENT(o,s) \
+ if(o) WARN("Mission '%s' missing/invalid '"s"' element", tmp->name)
+ MELEMENT(tmp->lua==NULL, "lua");
+ MELEMENT(tmp->avail.loc==-1, "location");
+#undef MELEMENT
+
+ return tmp;
+}
+
// Load/Free.
int missions_load(void) {
-#if 0
- yaml_parser_t parser;
- yaml_event_t input_event;
+ uint32_t bufsize;
+ char* buf = pack_readfile(DATA, MISSION_DATA, &bufsize);
- memset(&parser, 0, sizeof(parser));
- memset(&input_event, 0, sizeof(input_event));
+ MissionData* tmp;
- // Set up parser.
- if(!yaml_parser_initialize(&parser)) {
- ERR("Could not initialize the parser object");
+ xmlNodePtr node;
+ xmlDocPtr doc = xmlParseMemory(buf, bufsize);
+
+ node = doc->xmlChildrenNode;
+ if(!xml_isNode(node, XML_MISSION_ID)) {
+ ERR("Malformed '"MISSION_DATA"' file: missing root element '" \
+ XML_MISSION_ID"'");
return -1;
}
- // Cleanup parser.
- yaml_event_delete(&input_event);
- yaml_parser_delete(&parser);
-#endif
+ node = node->xmlChildrenNode; // First mission node.
+ if(node == NULL) {
+ ERR("Malformed '"MISSION_DATA"' file: does not contain elements");
+ return -1;
+ }
+
+ do {
+ if(xml_isNode(node, XML_MISSION_TAG)) {
+ tmp = mission_parse(node);
+ mission_stack =
+ realloc(mission_stack, sizeof(MissionData)*(++mission_nstack));
+ memcpy(mission_stack+mission_nstack-1, tmp, sizeof(MissionData));
+ free(tmp);
+ }
+ } while((node = node->next));
+
+ xmlFreeDoc(doc);
+ free(buf);
+ xmlCleanupParser();
+
+ DEBUG("Loaded %d Mission%s", mission_nstack, (mission_nstack==1) ? "" : "s");
return 0;
}
diff --git a/src/mission.h b/src/mission.h
index 826ca35..606c3e1 100644
--- a/src/mission.h
+++ b/src/mission.h
@@ -2,6 +2,8 @@
#include "faction.h"
#include "misn_lua.h"
+// Availability by location.
+#define MIS_AVAIL_NONE 0
#define MIS_AVAIL_COMPUTER 1
#define MIS_AVAIL_BAR 2
#define MIS_AVAIL_OUTFIT 3
@@ -30,6 +32,10 @@ typedef struct MissionData_ {
Faction* factions;
int nfactions;
} avail;
+
+ unsigned int flags; // Flags to store binary properties.
+
+ char* lua;
} MissionData;
// Active mission.