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.