diff --git a/dat/mission.xml b/dat/mission.xml index 957c8e6..81c620b 100644 --- a/dat/mission.xml +++ b/dat/mission.xml @@ -32,7 +32,7 @@ es_cargo - es_cargo + var.peek("es_cargo") == true 350 Computer Empire United diff --git a/dat/missions/emp_scout00.lua b/dat/missions/emp_scout00.lua index 37e0035..4f86485 100644 --- a/dat/missions/emp_scout00.lua +++ b/dat/missions/emp_scout00.lua @@ -3,7 +3,7 @@ if lang == "es" then -- Not translated atm. else -- Default english. misn_title = "Collective Scout" - misn_reward = "" + misn_reward = "None" misn_desc = {} misn_desc[1] = "Find a scout near %s." misn_desc[2] = "Travel back to %s in %s." diff --git a/src/misn_lua.c b/src/misn_lua.c index b12154e..ef18d60 100644 --- a/src/misn_lua.c +++ b/src/misn_lua.c @@ -94,6 +94,12 @@ static const luaL_reg var_methods[] = { {0, 0} }; +// Only conditional. +static const luaL_reg var_cond_methods[] = { + { "peek", var_peek }, + {0, 0 } +}; + // Space. static int space_getPlanet(lua_State* L); static int space_getSystem(lua_State* L); @@ -200,6 +206,12 @@ int misn_loadLibs(lua_State* L) { return 0; } +int misn_loadCondLibs(lua_State* L) { + luaL_register(L, "time", time_methods); + luaL_register(L, "var", var_cond_methods); + return 0; +} + // Run a mission function. // // -1 on error, 1 on misn.finish() call and 0 normally. diff --git a/src/misn_lua.h b/src/misn_lua.h index ce4283e..f5aedaf 100644 --- a/src/misn_lua.h +++ b/src/misn_lua.h @@ -8,4 +8,5 @@ void var_cleanup(void); // Load the libraries for a lua state. int misn_loadLibs(lua_State* L); +int misn_loadCondLibs(lua_State* L); // Safe read only stuff. diff --git a/src/mission.c b/src/mission.c index 3fbb77d..1181762 100644 --- a/src/mission.c +++ b/src/mission.c @@ -38,9 +38,10 @@ extern int misn_run(Mission* misn, char* func); // Static. static unsigned int mission_genID(void); -static int mission_init(Mission* mission, MissionData* misn); +static int mission_init(Mission* mission, MissionData* misn, int load); static void mission_freeData(MissionData* mission); static int mission_alreadyRunning(MissionData* misn); +static int mission_meetCond(MissionData* misn); static int mission_meetReq(int mission, int faction, char* planet, char* system); static int mission_matchFaction(MissionData* misn, int faction); static int mission_location(char* loc); @@ -80,15 +81,16 @@ MissionData* mission_get(int id) { } // Initialize a mission. -static int mission_init(Mission* mission, MissionData* misn) { +static int mission_init(Mission* mission, MissionData* misn, int load) { char* buf; uint32_t bufsize; - if(misn != NULL) { - // Don't set the data either. + if(load != 0) + mission->id = 0; + else mission->id = mission_genID(); - mission->data = misn; - } + + mission->data = misn; // Sane defaults. mission->title = NULL; @@ -108,21 +110,18 @@ static int mission_init(Mission* mission, MissionData* misn) { luaopen_string(mission->L); // string.format can be very useful. misn_loadLibs(mission->L); // Load our custom libraries. - // Don't load it with data. - if(misn != NULL) { - // Load the file. - buf = pack_readfile(DATA, misn->lua, &bufsize); - if(luaL_dobuffer(mission->L, buf, bufsize, misn->lua) != 0) { - ERR("Error loading mission file: %s", misn->lua); - ERR("%s", lua_tostring(mission->L, -1)); - WARN("Most likely Lua file has improper syntax, please check"); - return -1; - } + buf = pack_readfile(DATA, misn->lua, &bufsize); + if(luaL_dobuffer(mission->L, buf, bufsize, misn->lua) != 0) { + ERR("Error loading mission file: %s", misn->lua); + ERR("%s", lua_tostring(mission->L, -1)); + WARN("Most likely Lua file has improper syntax, please check"); + return -1; } free(buf); // Run create function. - misn_run(mission, "create"); + if(load == 0) // Never run when loading. + misn_run(mission, "create"); return mission->id; } @@ -145,6 +144,60 @@ static int mission_alreadyRunning(MissionData* misn) { return 0; } +// Is the lua condition for misn met? +static lua_State* mission_cond_L = NULL; +static int mission_meetCond(MissionData* misn) { + int ret; + char buf[256]; + + if(mission_cond_L == NULL) { + // Must create the conditional environment. + mission_cond_L = luaL_newstate(); + misn_loadCondLibs(mission_cond_L); + } + + snprintf(buf, 256, "return %s", misn->avail.cond); + ret = luaL_loadstring(mission_cond_L, buf); + + switch(ret) { + case LUA_ERRSYNTAX: + WARN("Missions '%s' Lua Conditional syntax error", misn->name); + return 0; + case LUA_ERRMEM: + WARN("Mission '%s' Lua Conditional ran out of memory", misn->name); + return 0; + default: + break; + } + + ret = lua_pcall(mission_cond_L, 0, 1, 0); + + switch(ret) { + case LUA_ERRRUN: + WARN("Mission '%s' Lua Conditional had a runtime error: %s", + misn->name, lua_tostring(mission_cond_L, -1)); + return 0; + case LUA_ERRMEM: + WARN("Mission '%s' Lua Conditional ran out of memory", misn->name); + return 0; + case LUA_ERRERR: + WARN("Mission '%s' Lua Conditional had an error while handling error function", + misn->name); + return 0; + default: + break; + } + + if(lua_isboolean(mission_cond_L, -1)) { + if(lua_toboolean(mission_cond_L, -1)) + return 1; + else + return 0; + } + WARN("Mission '%s' Conditional Lua didn't return a boolean", misn->name); + return 0; +} + // Does the mission meet the minimum requirements? static int mission_meetReq(int mission, int faction, char* planet, char* system) { MissionData* misn; @@ -162,8 +215,8 @@ static int mission_meetReq(int mission, int faction, char* planet, char* system) mission_alreadyRunning(misn))) return 0; - if((misn->avail.req != NULL) && // Mission doesn't meet the requirement. - !var_checkflag(misn->avail.req)) + if((misn->avail.cond != NULL) && // Mission doesn't meet the requirement. + !mission_meetCond(misn)) return 0; return 1; @@ -185,7 +238,7 @@ void missions_bar(int faction, char* planet, char* system) { chance = (double)(misn->avail.chance % 100)/100.; if(RNGF() < chance) { - mission_init(&mission, misn); + mission_init(&mission, misn, 0); mission_cleanup(&mission); // It better clean up for itself or we do it. } } @@ -300,7 +353,7 @@ Mission* missions_computer(int* n, int faction, char* planet, char* system) { // Random chance of rep appearances. if(RNGF() < chance) { tmp = realloc(tmp, sizeof(Mission) * ++m); - mission_init(&tmp[m-1], misn); + mission_init(&tmp[m-1], misn, 0); } } } @@ -373,8 +426,8 @@ static MissionData* mission_parse(const xmlNodePtr parent) { tmp->avail.factions[tmp->avail.nfactions-1] = faction_get(xml_get(cur)); } - else if(xml_isNode(cur, "req")) - tmp->avail.req = strdup(xml_get(cur)); + else if(xml_isNode(cur, "cond")) + tmp->avail.cond = strdup(xml_get(cur)); } while(xml_nextNode(cur)); } } while(xml_nextNode(node)); @@ -438,6 +491,11 @@ void missions_free(void) { free(mission_stack); mission_stack = NULL; mission_nstack = 0; + + if(mission_cond_L != NULL) { + lua_close(mission_cond_L); + mission_cond_L = NULL; + } } void missions_cleanup(void) { @@ -590,7 +648,7 @@ static int missions_parseActive(xmlNodePtr parent) { // Process the attributes to create the mission. xmlr_attr(node, "data", buf); - mission_init(misn, mission_get(mission_getID(buf))); + mission_init(misn, mission_get(mission_getID(buf)), 1); free(buf); // This will orphan an identifier. diff --git a/src/mission.h b/src/mission.h index 4b1d4cc..5a1b075 100644 --- a/src/mission.h +++ b/src/mission.h @@ -33,7 +33,7 @@ typedef struct MissionData_ { int* factions; int nfactions; - char* req; // Required variable. + char* cond; // Conditional that must be met. } avail; unsigned int flags; // Flags to store binary properties.