27#include "nlua_faction.h"
30#include "nlua_shiplog.h"
37#include "player_fleet.h"
41#define XML_MISSION_TAG "mission"
65 const Spob *pnt,
const StarSystem *sys );
104 WARN(_(
"Mission '%s' not found in stack"), name);
145 memset( mission, 0,
sizeof(
Mission) );
146 mission->
env = LUA_NOREF;
153 mission->
data = misn;
156 mission->
desc = strdup(_(
"No description."));
160 mission->
env = nlua_newEnv();
166 nlua_setenv(naevL, mission->
env,
"mem");
170 WARN(_(
"Error loading mission file: %s\n"
172 "Most likely Lua file has improper syntax, please check"),
180 int ret =
misn_run( mission,
"create");
201 return misn_run( mission,
"accept" );
229 const Spob *pnt,
const StarSystem *sys )
239 else if (spob_isFlag(pnt, SPOB_NOMISNSPAWN))
248 pcre2_match_data *match_data = pcre2_match_data_create_from_pattern( misn->
avail.
chapter_re, NULL );
250 pcre2_match_data_free( match_data );
253 case PCRE2_ERROR_NOMATCH:
256 WARN(_(
"Matching error %d"), rc );
269 if (mis_isFlag(misn,MISSION_UNIQUE) &&
278 WARN(_(
"Conditional for mission '%s' failed to run"), misn->
name);
301void missions_run( MissionAvailability loc,
int faction,
const Spob *pnt,
const StarSystem *sys )
321 if (RNGF() < chance) {
366 case SYSMARKER_COMPUTER:
371 case SPOBMARKER_COMPUTER:
373 case SPOBMARKER_HIGH:
374 case SPOBMARKER_PLOT:
377 WARN(_(
"Unknown marker type."));
382MissionMarkerType mission_markerTypeSpobToSystem( MissionMarkerType t )
385 case SYSMARKER_COMPUTER:
390 case SPOBMARKER_COMPUTER:
391 return SYSMARKER_COMPUTER;
393 return SYSMARKER_LOW;
394 case SPOBMARKER_HIGH:
395 return SYSMARKER_HIGH;
396 case SPOBMARKER_PLOT:
397 return SYSMARKER_PLOT;
399 WARN(_(
"Unknown marker type."));
404MissionMarkerType mission_markerTypeSystemToSpob( MissionMarkerType t )
407 case SYSMARKER_COMPUTER:
408 return SPOBMARKER_COMPUTER;
410 return SPOBMARKER_LOW;
412 return SPOBMARKER_HIGH;
414 return SPOBMARKER_PLOT;
415 case SPOBMARKER_COMPUTER:
417 case SPOBMARKER_HIGH:
418 case SPOBMARKER_PLOT:
421 WARN(_(
"Unknown marker type."));
426void mission_toLuaTable( lua_State *L ,
const MissionData *m )
430 lua_pushstring(L, m->
name);
431 lua_setfield(L,-2,
"name");
433 lua_pushboolean(L,mis_isFlag(m,MISSION_UNIQUE));
434 lua_setfield(L,-2,
"unique");
438 lua_pushboolean(L,1);
439 lua_setfield(L,-2,m->
tags[j]);
441 lua_setfield(L,-2,
"tags");
450 MissionMarkerType type;
454 xmlr_attr_int_def( node,
"id",
id, -1 );
455 xmlr_attr_int_def( node,
"type", type, -1 );
458 case SYSMARKER_COMPUTER:
464 WARN( _(
"Mission Marker to system '%s' does not exist"), xml_get( node ) );
468 case SPOBMARKER_COMPUTER:
470 case SPOBMARKER_HIGH:
471 case SPOBMARKER_PLOT:
474 WARN( _(
"Mission Marker to spob '%s' does not exist"), xml_get( node ) );
479 WARN(_(
"Unknown marker type."));
507 marker->
objid = objid;
543 StarSystem *firstsys = NULL;
556 case SYSMARKER_COMPUTER:
562 case SPOBMARKER_COMPUTER:
564 case SPOBMARKER_HIGH:
565 case SPOBMARKER_PLOT:
569 WARN(_(
"Marked spob '%s' is not in any system!"), pnt->
name);
575 WARN(_(
"Unknown marker type."));
580 sys_setFlag( sys, SYSTEM_CMARKED );
604 case SYSMARKER_COMPUTER:
610 case SPOBMARKER_COMPUTER:
612 case SPOBMARKER_HIGH:
613 case SPOBMARKER_PLOT:
617 WARN(_(
"Marked spob '%s' is not in any system!"), pnt->
name);
623 WARN(_(
"Unknown marker type."));
641 if (misn->
cargo == NULL)
658 if (misn->
cargo[i] == cargo_id)
662 DEBUG(_(
"Mission '%s' attempting to unlink nonexistent cargo %d."),
663 misn->
title, cargo_id);
690 WARN(_(
"Failed to remove mission cargo '%d' for mission '%s'."), misn->
cargo[i], misn->
title);
695 osd_destroy(misn->
osd);
701 if (misn->
env != LUA_NOREF)
702 nlua_freeEnv(misn->
env);
720 memset( misn, 0,
sizeof(
Mission) );
721 misn->
env = LUA_NOREF;
766 free(mission->
tags[i]);
824 if ((m1->
npc != NULL) && (m2->
npc != NULL))
825 return strcmp( m1->
npc, m2->
npc );
828 if ((m1->
title != NULL) && (m2->
title != NULL))
847 const Spob *pnt,
const StarSystem *sys, MissionAvailability loc )
874 for (
int j=0; j<rep; j++) {
884 tmp = realloc( tmp,
sizeof(
Mission) * alloced );
912 if (strcasecmp( loc,
"None" ) == 0)
913 return MIS_AVAIL_NONE;
914 else if (strcasecmp( loc,
"Computer" ) == 0)
915 return MIS_AVAIL_COMPUTER;
916 else if (strcasecmp( loc,
"Bar" ) == 0)
917 return MIS_AVAIL_BAR;
918 else if (strcasecmp( loc,
"Land" ) == 0)
919 return MIS_AVAIL_LAND;
920 else if (strcasecmp( loc,
"Enter" ) == 0)
921 return MIS_AVAIL_ENTER;
945 xmlr_attr_strd(parent,
"name",temp->
name);
946 if (temp->
name == NULL)
947 WARN( _(
"Mission in %s has invalid or no name"), MISSION_DATA_PATH );
949 node = parent->xmlChildrenNode;
955 if (xml_isNode(node,
"unique")) {
956 mis_setFlag(temp,MISSION_UNIQUE);
959 if (xml_isNode(node,
"location")) {
962 WARN(_(
"Mission '%s' has unknown location '%s'!"), temp->
name, xml_get(node) );
969 if (xml_isNode(node,
"faction")) {
979 if (xml_isNode(node,
"tags")) {
980 xmlNodePtr cur = node->children;
984 if (xml_isNode(cur,
"tag")) {
985 char *tmp = xml_get(cur);
990 WARN(_(
"Mission '%s' has unknown node in tags '%s'."), temp->
name, cur->name );
991 }
while (xml_nextNode(cur));
994 else if (xml_isNode(node,
"notes"))
continue;
996 WARN(_(
"Unknown node '%s' in mission '%s'"),node->name,temp->
name);
997 }
while (xml_nextNode(node));
1001 PCRE2_SIZE erroroffset;
1002 temp->
avail.
chapter_re = pcre2_compile( (PCRE2_SPTR)temp->
avail.
chapter, PCRE2_ZERO_TERMINATED, 0, &errornumber, &erroroffset, NULL );
1004 PCRE2_UCHAR buffer[256];
1005 pcre2_get_error_message( errornumber, buffer,
sizeof(buffer) );
1006 WARN(_(
"Mission '%s' chapter PCRE2 compilation failed at offset %d: %s"), temp->
name, (
int)erroroffset, buffer );
1010#define MELEMENT(o,s) \
1011 if (o) WARN( _("Mission '%s' missing/invalid '%s' element"), temp->name, s)
1012 MELEMENT(temp->
avail.
loc==MIS_AVAIL_UNSET,
"location");
1033 return strcmp( ma->
name, mb->
name );
1043 char **mission_files;
1044 Uint32 time = SDL_GetTicks();
1049 for (
int i=0; i <
array_size( mission_files ); i++) {
1051 free( mission_files[i] );
1061 WARN(_(
"Duplicate event '%s'!"), md->
name);
1069 time = SDL_GetTicks() - time;
1090 const char *pos, *start_pos;
1094 if (filebuf == NULL) {
1095 WARN(_(
"Unable to read data from '%s'"), file);
1104 pos =
strnstr( filebuf,
"</mission>", bufsize );
1106 pos =
strnstr( filebuf,
"function create", bufsize );
1107 if ((pos != NULL) && !strncmp(pos,
"--common",bufsize))
1108 WARN(_(
"Mission '%s' has create function but no XML header!"), file);
1114 start_pos =
strnstr( filebuf,
"<?xml ", bufsize );
1115 pos =
strnstr( filebuf,
"--]]", bufsize );
1116 if (pos == NULL || start_pos == NULL) {
1117 WARN(_(
"Mission file '%s' has missing XML header!"), file);
1122 doc = xmlParseMemory( start_pos, pos-start_pos);
1124 WARN(_(
"Unable to parse document XML header for Mission '%s'"), file);
1128 node = doc->xmlChildrenNode;
1130 ERR( _(
"Malformed XML header for '%s' mission: missing root element '%s'"), file,
XML_MISSION_TAG );
1137 temp->
lua = filebuf;
1142 int ret = luaL_loadbuffer(naevL, temp->
lua, strlen(temp->
lua), temp->
name );
1143 if (ret == LUA_ERRSYNTAX) {
1144 WARN(_(
"Mission Lua '%s' syntax error: %s"),
1145 file, lua_tostring(naevL,-1) );
1198 xmlw_startElem(writer,
"temporary_cargo");
1203 xmlw_startElem(writer,
"cargo");
1205 xmlw_endElem(writer);
1207 xmlw_endElem(writer);
1210 xmlw_startElem(writer,
"missions");
1213 xmlw_startElem(writer,
"mission");
1224 xmlw_startElem( writer,
"markers" );
1227 xmlw_startElem(writer,
"marker");
1228 xmlw_attr(writer,
"id",
"%d",m->
id);
1229 xmlw_attr(writer,
"type",
"%d",m->
type);
1231 xmlw_endElem(writer);
1233 xmlw_endElem( writer );
1236 xmlw_startElem(writer,
"cargos");
1239 xmlw_endElem(writer);
1245 xmlw_startElem(writer,
"osd");
1249 xmlw_attr(writer,
"nitems",
"%d",
array_size(items));
1250 xmlw_attr(writer,
"active",
"%d",osd_getActive(
player_missions[i]->osd));
1254 xmlw_elem(writer,
"msg",
"%s",items[j]);
1256 xmlw_endElem(writer);
1260 xmlw_startElem(writer,
"claims");
1262 xmlw_endElem(writer);
1265 xmlw_startElem(writer,
"lua");
1267 xmlw_endElem(writer);
1269 xmlw_endElem(writer);
1272 xmlw_endElem(writer);
1286 xmlw_attr( writer,
"name",
"%s",
c->name );
1287 xmlw_attr( writer,
"description",
"%s",
c->description );
1288 for (
int j=0; j <
array_size(
c->illegalto ); j++)
1289 xmlw_elem( writer,
"illegalto",
"%s",
faction_name(
c->illegalto[ j ] ) );
1304 node = parent->xmlChildrenNode;
1306 xml_onlyNodes(node);
1309 if (xml_isNode(node,
"temporary_cargo") || xml_isNode(node,
"mission_cargo")) {
1310 xmlNodePtr cur = node->xmlChildrenNode;
1313 if (xml_isNode( cur,
"cargo" ))
1315 }
while (xml_nextNode( cur ));
1318 }
while (xml_nextNode( node ));
1335 xmlr_attr_strd( cur,
"name", name );
1336 if ( name == NULL ) {
1337 WARN( _(
"Mission cargo without name!" ) );
1341 c = commodity_getW( name );
1347 xmlr_attr_strd( cur,
"description", desc );
1348 if ( desc == NULL ) {
1349 WARN( _(
"Mission temporary cargo '%s' missing description!" ), name );
1354 c = commodity_newTemp( name, desc );
1356 ccur = cur->xmlChildrenNode;
1358 xml_onlyNodes( ccur );
1359 if ( xml_isNode( ccur,
"illegalto" ) ) {
1361 commodity_tempIllegalto(
c, f );
1363 }
while ( xml_nextNode( ccur ) );
1384 node = parent->xmlChildrenNode;
1386 xml_onlyNodes(node);
1387 if (xml_isNode(node,
"missions")) {
1392 }
while (xml_nextNode(node));
1414 node = parent->xmlChildrenNode;
1416 if (xml_isNode(node,
"mission")) {
1423 xmlr_attr_strd(node,
"data", buf);
1426 WARN(_(
"Mission '%s' from saved game not found in game - ignoring."), buf);
1432 WARN(_(
"Mission '%s' from saved game failed to load properly - ignoring."), buf);
1441 xmlr_attr_int(node,
"id", misn->
id);
1443 cur = node->xmlChildrenNode;
1445 xmlr_strd(cur,
"title",misn->
title);
1446 xmlr_strd(cur,
"desc",misn->
desc);
1447 xmlr_strd(cur,
"reward",misn->
reward);
1450 if (xml_isNode(cur,
"markers")) {
1451 xmlNodePtr nest = cur->xmlChildrenNode;
1453 if (xml_isNode(nest,
"marker"))
1455 }
while (xml_nextNode(nest));
1459 if (xml_isNode(cur,
"cargos")) {
1460 xmlNodePtr nest = cur->xmlChildrenNode;
1462 if (xml_isNode(nest,
"cargo"))
1464 }
while (xml_nextNode(nest));
1468 if (xml_isNode(cur,
"osd")) {
1471 xmlr_attr_int_def( cur,
"nitems", nitems, -1 );
1474 xmlr_attr_strd(cur,
"title",title);
1475 items = malloc( nitems *
sizeof(
char*) );
1476 nest = cur->xmlChildrenNode;
1478 if (xml_isNode(nest,
"msg")) {
1480 WARN(_(
"Inconsistency with 'nitems' in save file."));
1483 items[i] = xml_get(nest);
1486 }
while (xml_nextNode(nest));
1489 misn->
osd = osd_create( title, nitems, items, data->avail.priority );
1494 xmlr_attr_int_def( cur,
"active", active, -1 );
1496 osd_active( misn->
osd, active );
1500 if (xml_isNode(cur,
"claims"))
1503 if (xml_isNode(cur,
"lua"))
1507 }
while (xml_nextNode(cur));
1509 }
while (xml_nextNode(node));
1514int mission_reload(
const char *name )
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#define array_end(array)
Returns a pointer to the end of the reserved memory space.
#define array_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
#define array_shrink(ptr_array)
Shrinks memory to fit only ‘size’ elements.
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
#define array_begin(array)
Returns a pointer to the beginning of the reserved memory space.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
void claim_destroy(Claim_t *claim)
Destroys a system claim.
void claim_activate(Claim_t *claim)
Activates a claim on a system.
Claim_t * claim_xmlLoad(xmlNodePtr parent)
Loads a claim.
int claim_xmlSave(xmlTextWriterPtr writer, const Claim_t *claim)
Saves all the systems in a claim in XML.
int cond_check(const char *cond)
Checks to see if a condition is true.
const char * faction_name(int f)
Gets a factions "real" (internal) name.
int faction_get(const char *name)
Gets a faction ID by name.
void hook_rmMisnParent(unsigned int parent)
Removes all hooks belonging to parent mission.
int mission_accept(Mission *mission)
Small wrapper for misn_run.
int missions_saveTempCommodity(xmlTextWriterPtr writer, const Commodity *c)
Saves a temporary commodity's defintion into the current node.
Mission ** player_missions
static int mission_markerLoad(Mission *misn, xmlNodePtr node)
Loads a mission marker from xml.
const StarSystem * mission_getSystemMarker(const Mission *misn)
Gets the first system that has been marked by a mission.
Mission * missions_genList(int *n, int faction, const Spob *pnt, const StarSystem *sys, MissionAvailability loc)
Generates a mission list. This runs create() so won't work with all missions.
void mission_cleanup(Mission *misn)
Cleans up a mission.
int mission_addMarker(Mission *misn, int id, int objid, MissionMarkerType type)
Adds a system marker to a mission.
const StarSystem * mission_sysComputerMark(const Mission *misn)
Marks the system of the computer mission to reflect where it will head to.
const MissionData * mission_getFromName(const char *name)
Gets mission data from a name.
void missions_free(void)
Frees all the mission data.
int mission_alreadyRunning(const MissionData *misn)
Checks to see if mission is already running.
static int mission_matchFaction(const MissionData *misn, int faction)
Checks to see if a mission matches the faction requirements.
int mission_linkCargo(Mission *misn, unsigned int cargo_id)
Links cargo to the mission for posterior cleanup.
void missions_activateClaims(void)
Activates mission claims.
void mission_sysMark(void)
Marks all active systems that need marking.
static const char * mission_markerTarget(MissionMarker *m)
Gets the name of the mission marker target.
void missions_run(MissionAvailability loc, int faction, const Spob *pnt, const StarSystem *sys)
Runs missions matching location, all Lua side and one-shot.
static MissionData * mission_stack
int missions_loadActive(xmlNodePtr parent)
Loads the player's active missions from a save.
static int mission_parseFile(const char *file, MissionData *temp)
Parses a single mission.
static int mission_parseXML(MissionData *temp, const xmlNodePtr parent)
Parses a node of a mission.
static int missions_parseActive(xmlNodePtr parent)
Parses the actual individual mission nodes.
void mission_shift(int pos)
Puts the specified mission at the end of the player_missions array.
int missions_load(void)
Loads all the mission data.
static int missions_cmp(const void *a, const void *b)
Ordering function for missions.
Commodity * missions_loadTempCommodity(xmlNodePtr cur)
Loads a temporary commodity.
static int mission_meetReq(const MissionData *misn, int faction, const Spob *pnt, const StarSystem *sys)
Checks to see if a mission meets the requirements.
int mission_start(const char *name, unsigned int *id)
Starts a mission.
int mission_getID(const char *name)
Gets id from mission name.
int missions_saveActive(xmlTextWriterPtr writer)
Saves the player's active missions.
static int mission_compare(const void *arg1, const void *arg2)
Compares to missions to see which has more priority.
static unsigned int mission_genID(void)
Generates a new id for the mission.
static unsigned int mission_id
static void mission_freeData(MissionData *mission)
Frees MissionData.
static int mission_location(const char *loc)
Gets location based on a human readable string.
static int mission_init(Mission *mission, const MissionData *misn, int genid, int create, unsigned int *id)
Initializes a mission.
int mission_unlinkCargo(Mission *misn, unsigned int cargo_id)
Unlinks cargo from the mission, removes it from the player.
int missions_loadCommodity(xmlNodePtr parent)
Loads the player's special mission commodities.
void missions_cleanup(void)
Cleans up all the player's active missions.
const MissionData * mission_get(int id)
Gets a MissionData based on ID.
int naev_isQuit(void)
Get if Naev is trying to quit.
Header file with generic functions and naev-specifics.
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
static char buf[NEWS_MAX_LENGTH]
int misn_loadLibs(nlua_env env)
Registers all the mission libraries.
int misn_run(Mission *misn, const char *func)
Runs a mission function.
void npc_patchMission(Mission *misn)
Patches a new mission bar npc into the bar system.
int npc_rm_parentMission(unsigned int mid)
Removes all the npc belonging to a mission.
char * strnstr(const char *haystack, const char *needle, size_t size)
A bounded version of strstr. Conforms to BSD semantics.
int nxml_persistLua(nlua_env env, xmlTextWriterPtr writer)
Persists all the nxml Lua data.
int nxml_unpersistLua(nlua_env env, xmlNodePtr parent)
Unpersists Lua data into a table named "mem".
void gl_freeTexture(glTexture *texture)
Frees a texture.
int pilot_rmMissionCargo(Pilot *pilot, unsigned int cargo_id, int jettison)
Removes special mission cargo based on id.
int player_missionAlreadyDone(int id)
Checks to see if player has already completed a mission.
PilotCommodity * pfleet_cargoList(void)
Gets a list of all the cargo in the fleet.
Spob * spob_get(const char *spobname)
Gets a spob based on its name.
StarSystem * system_getIndex(int id)
Get the system by its index.
int spob_index(const Spob *p)
Gets the ID of a spob.
StarSystem * system_get(const char *sysname)
Get the system from its name.
char * spob_getSystem(const char *spobname)
Get the name of a system from a spobname.
int space_addMarker(int objid, MissionMarkerType type)
Adds a marker to a system.
void space_clearMarkers(void)
Clears all system markers.
Spob * spob_getIndex(int ind)
Gets spob by index.
void space_clearComputerMarkers(void)
Clears all the system computer markers.
int system_index(const StarSystem *sys)
Gets the index of a star system.
Represents an active mission.
Stores a pilot commodity.
const Commodity * commodity
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...