31#include "nlua_audio.h"
33#include "nlua_camera.h"
36#include "nlua_music.h"
46#define XML_EVENT_ID "Events"
47#define XML_EVENT_TAG "event"
49#define EVENT_FLAG_UNIQUE (1<<0)
54typedef struct EventData_ {
92static int event_cmp(
const void* a,
const void* b );
109 if (ev->
id == eventid)
134 if ((ret == 0) && (
id != NULL))
197 memset( ev, 0,
sizeof(
Event_t) );
198 if ((
id != NULL) && (*
id != 0))
209 ev->
env = nlua_newEnv();
221 nlua_setenv(naevL, ev->
env,
"mem");
224 if (nlua_dochunkenv(ev->
env, data->chunk, data->sourcefile) != 0) {
225 WARN(_(
"Error loading event file: %s\n"
227 "Most likely Lua file has improper syntax, please check"),
228 data->sourcefile, lua_tostring(naevL,-1));
233 if ((
id==NULL) || (*
id==0))
250 nlua_freeEnv(ev->
env);
273 if (ev->
id == eventid) {
283 WARN(_(
"Event ID '%u' not valid."), eventid);
307 if (ev->
data == data)
333 if ((trigger==EVENT_TRIGGER_LAND || trigger==EVENT_TRIGGER_LOAD) && (ed->
spob != NULL) && (strcmp(ed->
spob,
land_spob->
name)!=0))
352 if (trigger==EVENT_TRIGGER_ENTER)
354 else if (trigger==EVENT_TRIGGER_LOAD || trigger==EVENT_TRIGGER_LAND)
375 pcre2_match_data *match_data = pcre2_match_data_create_from_pattern( ed->
chapter_re, NULL );
377 pcre2_match_data_free( match_data );
380 case PCRE2_ERROR_NOMATCH:
383 WARN(_(
"Matching error %d"), rc );
393 if (ed->
cond != NULL) {
396 WARN(_(
"Conditional for event '%s' failed to run."), ed->
name);
427 temp->
chunk = LUA_NOREF;
428 temp->
trigger = EVENT_TRIGGER_NULL;
432 xmlr_attr_strd(parent,
"name", temp->
name);
433 if (temp->
name == NULL)
434 WARN(_(
"Event in %s has invalid or no name"), EVENT_DATA_PATH);
436 node = parent->xmlChildrenNode;
441 xmlr_strd(node,
"spob",temp->
spob);
442 xmlr_strd(node,
"system",temp->
system);
443 xmlr_strd(node,
"chapter",temp->
chapter);
445 xmlr_strd(node,
"cond",temp->
cond);
446 xmlr_float(node,
"chance",temp->
chance);
447 xmlr_int(node,
"priority",temp->
priority);
449 if (xml_isNode(node,
"faction")) {
457 if (xml_isNode(node,
"location")) {
458 char *buf = xml_get(node);
460 WARN(_(
"Event '%s': Null trigger type."), temp->
name);
461 else if (strcmp(buf,
"enter")==0)
462 temp->
trigger = EVENT_TRIGGER_ENTER;
463 else if (strcmp(buf,
"land")==0)
464 temp->
trigger = EVENT_TRIGGER_LAND;
465 else if (strcmp(buf,
"load")==0)
466 temp->
trigger = EVENT_TRIGGER_LOAD;
467 else if (strcmp(buf,
"none")==0)
468 temp->
trigger = EVENT_TRIGGER_NONE;
470 WARN(_(
"Event '%s' has invalid 'trigger' parameter: %s"), temp->
name, buf);
476 else if (xml_isNode(node,
"unique")) {
482 if (xml_isNode(node,
"tags")) {
483 xmlNodePtr cur = node->children;
487 if (xml_isNode(cur,
"tag")) {
488 const char *tmp = xml_get(cur);
493 WARN(_(
"Event '%s' has unknown node in tags '%s'."), temp->
name, cur->name );
494 }
while (xml_nextNode(cur));
499 else if (xml_isNode(node,
"notes"))
502 WARN(_(
"Unknown node '%s' in event '%s'"), node->name, temp->
name);
503 }
while (xml_nextNode(node));
509 if (temp->
cond != NULL) {
512 WARN(_(
"Event '%s' failed to compile Lua conditional!"), temp->
name);
518 PCRE2_SIZE erroroffset;
519 temp->
chapter_re = pcre2_compile( (PCRE2_SPTR)temp->
chapter, PCRE2_ZERO_TERMINATED, 0, &errornumber, &erroroffset, NULL );
521 PCRE2_UCHAR buffer[256];
522 pcre2_get_error_message( errornumber, buffer,
sizeof(buffer) );
523 WARN(_(
"Mission '%s' chapter PCRE2 compilation failed at offset %d: %s"), temp->
name, (
int)erroroffset, buffer );
527#define MELEMENT(o,s) \
528 if (o) WARN(_("Event '%s' missing/invalid '%s' element"), temp->name, s)
529 MELEMENT(temp->
trigger==EVENT_TRIGGER_NULL,
"location");
530 MELEMENT((temp->
trigger!=EVENT_TRIGGER_NONE) && (temp->
chance==0.),
"chance");
536static int event_cmp(
const void* a,
const void* b )
545 return strcmp( ea->
name, eb->
name );
556 Uint32 time = SDL_GetTicks();
562 for (
int i=0; i <
array_size( event_files ); i++) {
564 free( event_files[ i ] );
574 WARN(_(
"Duplicate event '%s'!"), ed->
name);
583 time = SDL_GetTicks() - time;
605 const char *pos, *start_pos;
610 if (filebuf == NULL) {
611 WARN(_(
"Unable to read data from '%s'"), file);
620 pos =
strnstr( filebuf,
"</event>", bufsize );
622 pos =
strnstr( filebuf,
"function create", bufsize );
623 if ((pos != NULL) && !strncmp(pos,
"--common",bufsize))
624 WARN(_(
"Event '%s' has create function but no XML header!"), file);
630 start_pos =
strnstr( filebuf,
"<?xml ", bufsize );
631 pos =
strnstr( filebuf,
"--]]", bufsize );
632 if (pos == NULL || start_pos == NULL) {
633 WARN(_(
"Event file '%s' has missing XML header!"), file);
638 doc = xmlParseMemory( start_pos, pos-start_pos );
640 WARN(_(
"Unable to parse document XML header for Event '%s'"), file);
645 node = doc->xmlChildrenNode;
647 WARN(_(
"Malformed '%s' file: missing root element '%s'"), file,
XML_EVENT_TAG);
654 temp->
lua = strdup(filebuf);
658 if (temp->
chunk != LUA_NOREF) {
659 luaL_unref( naevL, LUA_REGISTRYINDEX, temp->
chunk );
660 temp->
chunk = LUA_NOREF;
664 ret = luaL_loadbuffer(naevL, temp->
lua, strlen(temp->
lua), temp->
name );
665 if (ret == LUA_ERRSYNTAX)
666 WARN(_(
"Event Lua '%s' syntax error: %s"), file, lua_tostring(naevL,-1) );
668 temp->
chunk = luaL_ref( naevL, LUA_REGISTRYINDEX );
697 if (event->
chunk != LUA_NOREF)
698 luaL_unref( naevL, LUA_REGISTRYINDEX,event->
chunk );
701 luaL_unref( naevL, LUA_REGISTRYINDEX,event->
cond_chunk );
704 free(event->
tags[i]);
750 WARN(_(
"No event data found matching name '%s'."), evdata);
783 WARN(_(
"Trying to test claims of unknown event with id '%d'!"), eventid);
803 WARN(_(
"Detected event '%s' without any hooks and is therefore invalid. Removing event."),
818 xmlw_startElem(writer,
"events");
825 xmlw_startElem(writer,
"event");
828 xmlw_attr(writer,
"id",
"%u",ev->
id);
831 xmlw_startElem(writer,
"claims");
833 xmlw_endElem(writer);
836 xmlw_startElem(writer,
"lua");
838 xmlw_endElem(writer);
840 xmlw_endElem(writer);
843 xmlw_endElem(writer);
857 xmlNodePtr node = parent->xmlChildrenNode;
863 if (xml_isNode(node,
"events")) {
867 }
while (xml_nextNode(node));
880 xmlNodePtr node = parent->xmlChildrenNode;
888 if (!xml_isNode(node,
"event"))
891 xmlr_attr_strd(node,
"name",buf);
893 WARN(_(
"Event has missing 'name' attribute, skipping."));
898 WARN(_(
"Event in save has name '%s' but event data not found matching name. Skipping."), buf);
903 xmlr_attr_uint(node,
"id",
id);
905 WARN(_(
"Event with data '%s' has invalid 'id' attribute, skipping."),
event_dataName(data));
913 WARN(_(
"Event with data '%s' was not created, skipping."),
event_dataName(data));
919 cur = node->xmlChildrenNode;
921 if (xml_isNode(cur,
"lua")) {
924 WARN(_(
"Event with data '%s' failed to unpersist Lua, skipping."),
event_dataName(data));
929 }
while (xml_nextNode(cur));
932 if (xml_isNode(node,
"claims"))
934 }
while (xml_nextNode(node));
939int event_reload(
const char *name )
954void event_toLuaTable( lua_State *L,
int eventid )
960 lua_pushstring(L, data->name);
961 lua_setfield(L,-2,
"name");
964 lua_setfield(L,-2,
"unique");
967 for (
int j=0; j<
array_size(data->tags); j++) {
968 lua_pushboolean(L,1);
969 lua_setfield(L,-2,data->tags[j]);
971 lua_setfield(L,-2,
"tags");
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#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_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.
int claim_testSys(const Claim_t *claim, int sys)
Tests to see if a system is claimed by a system claim.
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.
void claim_activateAll(void)
Activates all the claims.
int cond_compile(const char *cond)
Compiles a conditional statement that can then be used as a reference.
static unsigned int event_genid
int event_start(const char *name, unsigned int *id)
Starts an event.
const char * event_dataName(int dataid)
Gets the event data name from id.
void events_exit(void)
Exits the event subsystem.
int event_alreadyRunning(int data)
Check to see if an event is already running.
static int event_parseFile(const char *file, EventData *temp)
Parses an event file.
const char * event_getData(unsigned int eventid)
Gets the name of the event data.
int events_loadActive(xmlNodePtr parent)
Loads the player's active events from a save.
void event_remove(unsigned int eventid)
Removes an event by ID.
Event_t * event_get(unsigned int eventid)
Gets an event.
static Event_t * event_active
void events_cleanup(void)
Cleans up and removes active events.
int event_dataID(const char *evdata)
Gets the event data id from name.
static void event_cleanup(Event_t *ev)
Cleans up an event.
static void event_freeData(EventData *event)
Frees an EventData structure.
int event_save(unsigned int eventid)
Checks to see if an event should be saved.
static int events_parseActive(xmlNodePtr parent)
Parses the actual individual event nodes.
int event_isUnique(unsigned int eventid)
Checks to see if an event is unique.
int events_load(void)
Loads all the events.
void event_activateClaims(void)
Activates all the active event claims.
void event_checkValidity(void)
Checks the event validity and cleans up after them.
void events_trigger(EventTrigger_t trigger)
Runs all the events matching a trigger.
int events_saveActive(xmlTextWriterPtr writer)
Saves the player's active events.
static int event_parseXML(EventData *temp, const xmlNodePtr parent)
Loads up an event from an XML node.
static unsigned int event_genID(void)
Generates a new event ID.
int event_testClaims(unsigned int eventid, int sys)
Tests to see if an event has claimed a system.
static EventData * event_data
#define EVENT_FLAG_UNIQUE
static int event_create(int dataid, unsigned int *id)
Creates an event.
int faction_get(const char *name)
Gets a faction ID by name.
int hook_hasEventParent(unsigned int parent)
Checks to see how many hooks there are with the same event parent.
void hook_rmEventParent(unsigned int parent)
Removes all hooks belonging to parent event.
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.
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
int nlua_loadBackground(nlua_env env)
Loads the graphics library.
int nlua_loadCamera(nlua_env env)
Loads the camera library.
int event_run(unsigned int eventid, const char *func)
Runs the event function.
int nlua_loadEvt(nlua_env env)
Loads the event Lua library.
int nlua_loadHook(nlua_env env)
Loads the hook Lua library.
int nlua_loadMusic(nlua_env env)
Music Lua module.
int nlua_loadTex(nlua_env env)
Loads the texture library.
int nlua_loadTk(nlua_env env)
Loads the Toolkit Lua library.
int npc_rm_parentEvent(unsigned int id)
Removes all the npc belonging to an event.
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".
int player_eventAlreadyDone(int id)
Checks to see if player has already completed a event.
Activated event structure.