naev 0.11.5
event.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
14#include "nstring.h"
15#include <stdint.h>
16#include <stdlib.h>
17
18#include "naev.h"
21#include "event.h"
22
23#include "conf.h"
24#include "array.h"
25#include "cond.h"
26#include "hook.h"
27#include "log.h"
28#include "land.h"
29#include "ndata.h"
30#include "nlua.h"
31#include "nlua_audio.h"
32#include "nlua_bkg.h"
33#include "nlua_camera.h"
34#include "nlua_evt.h"
35#include "nlua_hook.h"
36#include "nlua_music.h"
37#include "nlua_tex.h"
38#include "nlua_tk.h"
39#include "nluadef.h"
40#include "npc.h"
41#include "nxml.h"
42#include "nxml_lua.h"
43#include "player.h"
44#include "rng.h"
45
46#define XML_EVENT_ID "Events"
47#define XML_EVENT_TAG "event"
49#define EVENT_FLAG_UNIQUE (1<<0)
54typedef struct EventData_ {
55 char *name;
56 char *sourcefile;
57 char *lua;
58 int chunk;
59 unsigned int flags;
61 /* For specific cases. */
62 char *spob;
63 char *system;
64 char *chapter;
65 int *factions;
66 pcre2_code *chapter_re;
68 EventTrigger_t trigger;
69 char *cond;
71 double chance;
74 char **tags;
75} EventData;
76
77/*
78 * Event data.
79 */
80static EventData *event_data = NULL;
82/*
83 * Active events.
84 */
85static unsigned int event_genid = 0;
86static Event_t *event_active = NULL;
88/*
89 * Prototypes.
90 */
91static unsigned int event_genID (void);
92static int event_cmp( const void* a, const void* b );
93static int event_parseFile( const char* file, EventData *temp );
94static int event_parseXML( EventData *temp, const xmlNodePtr parent );
95static void event_freeData( EventData *event );
96static int event_create( int dataid, unsigned int *id );
97int events_saveActive( xmlTextWriterPtr writer );
98int events_loadActive( xmlNodePtr parent );
99static int events_parseActive( xmlNodePtr parent );
100
104Event_t *event_get( unsigned int eventid )
105{
106 /* Iterate. */
107 for (int i=0; i<array_size(event_active); i++) {
108 Event_t *ev = &event_active[i];
109 if (ev->id == eventid)
110 return ev;
111 }
112
113 return NULL;
114}
115
123int event_start( const char *name, unsigned int *id )
124{
125 int ret, edat;
126 unsigned int eid;
127
128 edat = event_dataID( name );
129 if (edat < 0)
130 return -1;
131 eid = 0;
132 ret = event_create( edat, &eid );
133
134 if ((ret == 0) && (id != NULL))
135 *id = eid;
136 return ret;
137}
138
145const char *event_getData( unsigned int eventid )
146{
147 const Event_t *ev = event_get( eventid );
148 if (ev == NULL)
149 return NULL;
150 return event_data[ ev->data ].name;
151}
152
159int event_isUnique( unsigned int eventid )
160{
161 const Event_t *ev = event_get( eventid );
162 if (ev == NULL)
163 return -1;
164 return !!(event_data[ ev->data ].flags & EVENT_FLAG_UNIQUE);
165}
166
170static unsigned int event_genID (void)
171{
172 unsigned int id;
173 do {
174 id = ++event_genid; /* Create unique ID. */
175 } while (event_get(id) != NULL);
176 return id;
177}
178
186static int event_create( int dataid, unsigned int *id )
187{
188 Event_t *ev;
189 EventData *data;
190 unsigned int eid;
191
192 if (event_active==NULL)
194
195 /* Create the event. */
196 ev = &array_grow( &event_active );
197 memset( ev, 0, sizeof(Event_t) );
198 if ((id != NULL) && (*id != 0))
199 eid = *id;
200 else
201 eid = event_genID();
202 ev->id = eid;
203
204 /* Add the data. */
205 ev->data = dataid;
206 data = &event_data[dataid];
207
208 /* Open the new state. */
209 ev->env = nlua_newEnv();
211 nlua_loadEvt(ev->env);
212 nlua_loadHook(ev->env);
213 nlua_loadCamera(ev->env);
214 nlua_loadTex(ev->env);
216 nlua_loadMusic(ev->env);
217 nlua_loadTk(ev->env);
218
219 /* Create the "mem" table for persistence. */
220 lua_newtable(naevL);
221 nlua_setenv(naevL, ev->env, "mem");
222
223 /* Load file. */
224 if (nlua_dochunkenv(ev->env, data->chunk, data->sourcefile) != 0) {
225 WARN(_("Error loading event file: %s\n"
226 "%s\n"
227 "Most likely Lua file has improper syntax, please check"),
228 data->sourcefile, lua_tostring(naevL,-1));
229 return -1;
230 }
231
232 /* Run Lua. */
233 if ((id==NULL) || (*id==0))
234 event_run( ev->id, "create" );
235 if (id != NULL)
236 *id = eid; /* The ev pointer can change and be invalidated in event_run,
237 so we pass eid instead of ev->id. */
238
239 return 0;
240}
241
247static void event_cleanup( Event_t *ev )
248{
249 /* Free lua env. */
250 nlua_freeEnv(ev->env);
251
252 /* Free hooks. */
254
255 /* Free NPC. */
257
258 /* Free claims. */
259 if (ev->claims != NULL)
260 claim_destroy( ev->claims );
261}
262
268void event_remove( unsigned int eventid )
269{
270 /* Find the event. */
271 for (int i=0; i<array_size(event_active); i++) {
272 Event_t *ev = &event_active[i];
273 if (ev->id == eventid) {
274 /* Clean up event. */
275 event_cleanup(ev);
276
277 /* Move memory. */
279 return;
280 }
281 }
282
283 WARN(_("Event ID '%u' not valid."), eventid);
284}
285
289int event_save( unsigned int eventid )
290{
291 const Event_t *ev = event_get(eventid);
292 if (ev == NULL)
293 return 0;
294 return ev->save;
295}
296
302int event_alreadyRunning( int data )
303{
304 /* Find events. */
305 for (int i=0; i<array_size(event_active); i++) {
306 const Event_t *ev = &event_active[i];
307 if (ev->data == data)
308 return 1;
309 }
310
311 return 0;
312}
313
319void events_trigger( EventTrigger_t trigger )
320{
321 int created = 0;
322 for (int i=0; i<array_size(event_data); i++) {
323 EventData *ed = &event_data[i];
324
325 if (naev_isQuit())
326 return;
327
328 /* Make sure trigger matches. */
329 if (ed->trigger != trigger)
330 continue;
331
332 /* Spob. */
333 if ((trigger==EVENT_TRIGGER_LAND || trigger==EVENT_TRIGGER_LOAD) && (ed->spob != NULL) && (strcmp(ed->spob,land_spob->name)!=0))
334 continue;
335
336 /* System. */
337 if ((ed->system != NULL) && (strcmp(ed->system,cur_system->name)!=0))
338 continue;
339
340 /* Make sure chance is succeeded. */
341 if (RNGF() > ed->chance)
342 continue;
343
344 /* Test uniqueness. */
345 if ((ed->flags & EVENT_FLAG_UNIQUE) &&
347 continue;
348
349 /* Test factions. */
350 if (ed->factions != NULL) {
351 int fct, match = 0;
352 if (trigger==EVENT_TRIGGER_ENTER)
353 fct = cur_system->faction;
354 else if (trigger==EVENT_TRIGGER_LOAD || trigger==EVENT_TRIGGER_LAND)
356 else {
357 fct = -1;
358 match = -1; /* Don't hae to check factions. */
359 }
360
361 if (match==0) {
362 for (int j=0; j<array_size(ed->factions); j++) {
363 if (fct == ed->factions[j]) {
364 match = 1;
365 break;
366 }
367 }
368 if (!match)
369 continue;
370 }
371 }
372
373 /* If chapter, must match chapter regex. */
374 if (ed->chapter_re != NULL) {
375 pcre2_match_data *match_data = pcre2_match_data_create_from_pattern( ed->chapter_re, NULL );
376 int rc = pcre2_match( ed->chapter_re, (PCRE2_SPTR)player.chapter, strlen(player.chapter), 0, 0, match_data, NULL );
377 pcre2_match_data_free( match_data );
378 if (rc < 0) {
379 switch (rc) {
380 case PCRE2_ERROR_NOMATCH:
381 continue;
382 default:
383 WARN(_("Matching error %d"), rc );
384 break;
385 }
386 continue;
387 }
388 else if (rc == 0)
389 continue;
390 }
391
392 /* Test conditional. */
393 if (ed->cond != NULL) {
394 int c = cond_checkChunk( ed->cond_chunk, ed->cond );
395 if (c<0) {
396 WARN(_("Conditional for event '%s' failed to run."), ed->name);
397 continue;
398 }
399 else if (!c)
400 continue;
401 }
402
403 /* Create the event. */
404 event_create( i, NULL );
405 created++;
406 }
407
408 /* Run claims if necessary. */
409 if (created)
411}
412
420static int event_parseXML( EventData *temp, const xmlNodePtr parent )
421{
422 xmlNodePtr node;
423
424 memset( temp, 0, sizeof(EventData) );
425
426 /* Defaults. */
427 temp->chunk = LUA_NOREF;
428 temp->trigger = EVENT_TRIGGER_NULL;
429 temp->cond_chunk = LUA_NOREF;
430
431 /* get the name */
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);
435
436 node = parent->xmlChildrenNode;
437 do { /* load all the data */
438 /* Only check nodes. */
439 xml_onlyNodes(node);
440
441 xmlr_strd(node,"spob",temp->spob);
442 xmlr_strd(node,"system",temp->system);
443 xmlr_strd(node,"chapter",temp->chapter);
444
445 xmlr_strd(node,"cond",temp->cond);
446 xmlr_float(node,"chance",temp->chance);
447 xmlr_int(node,"priority",temp->priority);
448
449 if (xml_isNode(node,"faction")) {
450 if (temp->factions == NULL)
451 temp->factions = array_create( int );
452 array_push_back( &temp->factions, faction_get( xml_get(node) ) );
453 continue;
454 }
455
456 /* Trigger. */
457 if (xml_isNode(node,"location")) {
458 char *buf = xml_get(node);
459 if (buf == NULL)
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;
469 else
470 WARN(_("Event '%s' has invalid 'trigger' parameter: %s"), temp->name, buf);
471
472 continue;
473 }
474
475 /* Flags. */
476 else if (xml_isNode(node,"unique")) { /* unique event. */
477 temp->flags |= EVENT_FLAG_UNIQUE;
478 continue;
479 }
480
481 /* Tags. */
482 if (xml_isNode(node,"tags")) {
483 xmlNodePtr cur = node->children;
484 temp->tags = array_create( char* );
485 do {
486 xml_onlyNodes(cur);
487 if (xml_isNode(cur, "tag")) {
488 const char *tmp = xml_get(cur);
489 if (tmp != NULL)
490 array_push_back( &temp->tags, strdup(tmp) );
491 continue;
492 }
493 WARN(_("Event '%s' has unknown node in tags '%s'."), temp->name, cur->name );
494 } while (xml_nextNode(cur));
495 continue;
496 }
497
498 /* Notes for the python mission mapping script. */
499 else if (xml_isNode(node,"notes"))
500 continue;
501
502 WARN(_("Unknown node '%s' in event '%s'"), node->name, temp->name);
503 } while (xml_nextNode(node));
504
505 /* Process. */
506 temp->chance /= 100.;
507
508 /* Compile conditional chunk. */
509 if (temp->cond != NULL) {
510 temp->cond_chunk = cond_compile( temp->cond );
511 if (temp->cond_chunk == LUA_NOREF || temp->cond_chunk == LUA_REFNIL)
512 WARN(_("Event '%s' failed to compile Lua conditional!"), temp->name);
513 }
514
515 /* Compile regex for chapter matching. */
516 if (temp->chapter != NULL) {
517 int errornumber;
518 PCRE2_SIZE erroroffset;
519 temp->chapter_re = pcre2_compile( (PCRE2_SPTR)temp->chapter, PCRE2_ZERO_TERMINATED, 0, &errornumber, &erroroffset, NULL );
520 if (temp->chapter_re == 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 );
524 }
525 }
526
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");
531#undef MELEMENT
532
533 return 0;
534}
535
536static int event_cmp( const void* a, const void* b )
537{
538 const EventData *ea, *eb;
539 ea = (const EventData*) a;
540 eb = (const EventData*) b;
541 if (ea->priority < eb->priority)
542 return -1;
543 else if (ea->priority > eb->priority)
544 return +1;
545 return strcmp( ea->name, eb->name );
546}
547
553int events_load (void)
554{
555#if DEBUGGING
556 Uint32 time = SDL_GetTicks();
557#endif /* DEBUGGING */
558 char **event_files = ndata_listRecursive( EVENT_DATA_PATH );
559
560 /* Run over events. */
562 for (int i=0; i < array_size( event_files ); i++) {
563 event_parseFile( event_files[i], NULL );
564 free( event_files[ i ] );
565 }
566 array_free( event_files );
568
569#ifdef DEBUGGING
570 for (int i=0; i<array_size(event_data); i++) {
571 EventData *ed = &event_data[i];
572 for (int j=i+1; j<array_size(event_data); j++)
573 if (strcmp( ed->name, event_data[j].name )==0)
574 WARN(_("Duplicate event '%s'!"), ed->name);
575 }
576#endif /* DEBUGGING */
577
578 /* Sort based on priority so higher priority missions can establish claims first. */
579 qsort( event_data, array_size(event_data), sizeof(EventData), event_cmp );
580
581#if DEBUGGING
582 if (conf.devmode) {
583 time = SDL_GetTicks() - time;
584 DEBUG( n_("Loaded %d Event in %.3f s", "Loaded %d Events in %.3f s", array_size(event_data) ), array_size(event_data), time/1000. );
585 }
586 else
587 DEBUG( n_("Loaded %d Event", "Loaded %d Events", array_size(event_data) ), array_size(event_data) );
588#endif /* DEBUGGING */
589
590 return 0;
591}
592
599static int event_parseFile( const char* file, EventData *temp )
600{
601 size_t bufsize;
602 xmlNodePtr node;
603 xmlDocPtr doc;
604 char *filebuf;
605 const char *pos, *start_pos;
606 int ret;
607
608 /* Load string. */
609 filebuf = ndata_read( file, &bufsize );
610 if (filebuf == NULL) {
611 WARN(_("Unable to read data from '%s'"), file);
612 return -1;
613 }
614 if (bufsize == 0) {
615 free( filebuf );
616 return -1;
617 }
618
619 /* Skip if no XML. */
620 pos = strnstr( filebuf, "</event>", bufsize );
621 if (pos==NULL) {
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);
625 free(filebuf);
626 return 0;
627 }
628
629 /* Separate XML header and Lua. */
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);
634 return -1;
635 }
636
637 /* Parse the header. */
638 doc = xmlParseMemory( start_pos, pos-start_pos );
639 if (doc == NULL) {
640 WARN(_("Unable to parse document XML header for Event '%s'"), file);
641 return -1;
642 }
643
644 /* Get the root node. */
645 node = doc->xmlChildrenNode;
646 if (!xml_isNode(node,XML_EVENT_TAG)) {
647 WARN(_("Malformed '%s' file: missing root element '%s'"), file, XML_EVENT_TAG);
648 return -1;
649 }
650
651 if (temp == NULL)
652 temp = &array_grow(&event_data);
653 event_parseXML( temp, node );
654 temp->lua = strdup(filebuf);
655 temp->sourcefile = strdup(file);
656
657 /* Clear chunk if already loaded. */
658 if (temp->chunk != LUA_NOREF) {
659 luaL_unref( naevL, LUA_REGISTRYINDEX, temp->chunk );
660 temp->chunk = LUA_NOREF;
661 }
662
663 /* Check to see if syntax is valid. */
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) );
667 else
668 temp->chunk = luaL_ref( naevL, LUA_REGISTRYINDEX );
669
670 /* Clean up. */
671 xmlFreeDoc(doc);
672 free(filebuf);
673
674 return 0;
675}
676
682static void event_freeData( EventData *event )
683{
684 free( event->name );
685 free( event->sourcefile );
686 free( event->lua );
687
688 free( event->spob );
689 free( event->system );
690 free( event->chapter );
691 pcre2_code_free( event->chapter_re );
692
693 array_free( event->factions );
694
695 free( event->cond );
696
697 if (event->chunk != LUA_NOREF)
698 luaL_unref( naevL, LUA_REGISTRYINDEX,event->chunk );
699
700 if (event->cond_chunk != LUA_NOREF)
701 luaL_unref( naevL, LUA_REGISTRYINDEX,event->cond_chunk );
702
703 for (int i=0; i<array_size(event->tags); i++)
704 free(event->tags[i]);
705 array_free(event->tags);
706
707 /* Clear the memory. */
708#if DEBUGGING
709 memset( event, 0, sizeof(EventData) );
710#endif /* DEBUGGING */
711}
712
716void events_cleanup (void)
717{
718 /* Free active events. */
719 for (int i=0; i<array_size(event_active); i++)
722 event_active = NULL;
723}
724
728void events_exit (void)
729{
731
732 /* Free data. */
733 for (int i=0; i<array_size(event_data); i++)
736 event_data = NULL;
737}
738
745int event_dataID( const char *evdata )
746{
747 for (int i=0; i<array_size(event_data); i++)
748 if (strcmp(event_data[i].name, evdata)==0)
749 return i;
750 WARN(_("No event data found matching name '%s'."), evdata);
751 return -1;
752}
753
760const char *event_dataName( int dataid )
761{
762 return event_data[dataid].name;
763}
764
769{
770 /* Free active events. */
771 for (int i=0; i<array_size(event_active); i++)
772 if (event_active[i].claims != NULL)
773 claim_activate( event_active[i].claims );
774}
775
779int event_testClaims( unsigned int eventid, int sys )
780{
781 const Event_t *ev = event_get( eventid );
782 if (ev==NULL) {
783 WARN(_("Trying to test claims of unknown event with id '%d'!"), eventid);
784 return 0;
785 }
786 return claim_testSys( ev->claims, sys );
787}
788
793{
794 /* Iterate. */
795 for (int i=0; i<array_size(event_active); i++) {
796 const Event_t *ev = &event_active[i];
797
798 /* Check if has children. */
799 if (hook_hasEventParent( ev->id ) > 0)
800 continue;
801
802 /* Must delete. */
803 WARN(_("Detected event '%s' without any hooks and is therefore invalid. Removing event."),
804 event_dataName( ev->data ));
805 event_remove( ev->id );
806 i--; /* Keep iteration safe. */
807 }
808}
809
816int events_saveActive( xmlTextWriterPtr writer )
817{
818 xmlw_startElem(writer,"events");
819
820 for (int i=0; i<array_size(event_active); i++) {
821 Event_t *ev = &event_active[i];
822 if (!ev->save) /* Only save events that want to be saved. */
823 continue;
824
825 xmlw_startElem(writer,"event");
826
827 xmlw_attr(writer,"name","%s",event_dataName(ev->data));
828 xmlw_attr(writer,"id","%u",ev->id);
829
830 /* Claims. */
831 xmlw_startElem(writer,"claims");
832 claim_xmlSave( writer, ev->claims );
833 xmlw_endElem(writer); /* "claims" */
834
835 /* Write Lua magic */
836 xmlw_startElem(writer,"lua");
837 nxml_persistLua( ev->env, writer );
838 xmlw_endElem(writer); /* "lua" */
839
840 xmlw_endElem(writer); /* "event" */
841 }
842
843 xmlw_endElem(writer); /* "events" */
844
845 return 0;
846}
847
854int events_loadActive( xmlNodePtr parent )
855{
856 int failed = 0;
857 xmlNodePtr node = parent->xmlChildrenNode;
858
859 /* cleanup old events */
861
862 do {
863 if (xml_isNode(node,"events")) {
864 int ret = events_parseActive( node );
865 failed |= ret;
866 }
867 } while (xml_nextNode(node));
868
869 return failed;
870}
871
878static int events_parseActive( xmlNodePtr parent )
879{
880 xmlNodePtr node = parent->xmlChildrenNode;
881 do {
882 char *buf;
883 unsigned int id;
884 int data;
885 xmlNodePtr cur;
886 Event_t *ev;
887
888 if (!xml_isNode(node,"event"))
889 continue;
890
891 xmlr_attr_strd(node,"name",buf);
892 if (buf==NULL) {
893 WARN(_("Event has missing 'name' attribute, skipping."));
894 continue;
895 }
896 data = event_dataID( buf );
897 if (data < 0) {
898 WARN(_("Event in save has name '%s' but event data not found matching name. Skipping."), buf);
899 free(buf);
900 continue;
901 }
902 free(buf);
903 xmlr_attr_uint(node,"id",id);
904 if (id==0) {
905 WARN(_("Event with data '%s' has invalid 'id' attribute, skipping."), event_dataName(data));
906 continue;
907 }
908
909 /* Create the event. */
910 event_create( data, &id );
911 ev = event_get( id );
912 if (ev == NULL) {
913 WARN(_("Event with data '%s' was not created, skipping."), event_dataName(data));
914 continue;
915 }
916 ev->save = 1; /* Should save by default again. */
917
918 /* Get the data. */
919 cur = node->xmlChildrenNode;
920 do {
921 if (xml_isNode(cur,"lua")) {
922 int ret = nxml_unpersistLua( ev->env, cur );
923 if (ret) {
924 WARN(_("Event with data '%s' failed to unpersist Lua, skipping."), event_dataName(data));
925 event_remove( id );
926 return -1;
927 }
928 }
929 } while (xml_nextNode(cur));
930
931 /* Claims. */
932 if (xml_isNode(node,"claims"))
933 ev->claims = claim_xmlLoad( node );
934 } while (xml_nextNode(node));
935
936 return 0;
937}
938
939int event_reload( const char *name )
940{
941 int res, edat = event_dataID( name );
942 EventData save, *temp = edat<0 ? NULL : &event_data[edat];
943 if (temp == NULL)
944 return -1;
945 save = *temp;
946 res = event_parseFile( save.sourcefile, temp );
947 if (res == 0)
948 event_freeData( &save );
949 else
950 *temp = save;
951 return res;
952}
953
954void event_toLuaTable( lua_State *L, int eventid )
955{
956 const EventData *data = &event_data[ eventid ];
957
958 lua_newtable(L);
959
960 lua_pushstring(L, data->name);
961 lua_setfield(L,-2,"name");
962
963 lua_pushboolean(L, (data->flags & EVENT_FLAG_UNIQUE));
964 lua_setfield(L,-2,"unique");
965
966 lua_newtable(L);
967 for (int j=0; j<array_size(data->tags); j++) {
968 lua_pushboolean(L,1);
969 lua_setfield(L,-2,data->tags[j]);
970 }
971 lua_setfield(L,-2,"tags");
972}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:158
#define array_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
Definition array.h:102
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
Definition array.h:140
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:168
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
Definition array.h:119
#define array_shrink(ptr_array)
Shrinks memory to fit only ‘size’ elements.
Definition array.h:149
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition array.h:129
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
void claim_destroy(Claim_t *claim)
Destroys a system claim.
Definition claim.c:189
void claim_activate(Claim_t *claim)
Activates a claim on a system.
Definition claim.c:251
int claim_testSys(const Claim_t *claim, int sys)
Tests to see if a system is claimed by a system claim.
Definition claim.c:170
Claim_t * claim_xmlLoad(xmlNodePtr parent)
Loads a claim.
Definition claim.c:305
int claim_xmlSave(xmlTextWriterPtr writer, const Claim_t *claim)
Saves all the systems in a claim in XML.
Definition claim.c:278
void claim_activateAll(void)
Activates all the claims.
Definition claim.c:239
int cond_compile(const char *cond)
Compiles a conditional statement that can then be used as a reference.
Definition cond.c:53
static unsigned int event_genid
Definition event.c:85
int event_start(const char *name, unsigned int *id)
Starts an event.
Definition event.c:123
const char * event_dataName(int dataid)
Gets the event data name from id.
Definition event.c:760
void events_exit(void)
Exits the event subsystem.
Definition event.c:728
int event_alreadyRunning(int data)
Check to see if an event is already running.
Definition event.c:302
static int event_parseFile(const char *file, EventData *temp)
Parses an event file.
Definition event.c:599
const char * event_getData(unsigned int eventid)
Gets the name of the event data.
Definition event.c:145
int events_loadActive(xmlNodePtr parent)
Loads the player's active events from a save.
Definition event.c:854
void event_remove(unsigned int eventid)
Removes an event by ID.
Definition event.c:268
Event_t * event_get(unsigned int eventid)
Gets an event.
Definition event.c:104
static Event_t * event_active
Definition event.c:86
void events_cleanup(void)
Cleans up and removes active events.
Definition event.c:716
int event_dataID(const char *evdata)
Gets the event data id from name.
Definition event.c:745
static void event_cleanup(Event_t *ev)
Cleans up an event.
Definition event.c:247
static void event_freeData(EventData *event)
Frees an EventData structure.
Definition event.c:682
int event_save(unsigned int eventid)
Checks to see if an event should be saved.
Definition event.c:289
static int events_parseActive(xmlNodePtr parent)
Parses the actual individual event nodes.
Definition event.c:878
#define XML_EVENT_TAG
Definition event.c:47
int event_isUnique(unsigned int eventid)
Checks to see if an event is unique.
Definition event.c:159
int events_load(void)
Loads all the events.
Definition event.c:553
void event_activateClaims(void)
Activates all the active event claims.
Definition event.c:768
void event_checkValidity(void)
Checks the event validity and cleans up after them.
Definition event.c:792
void events_trigger(EventTrigger_t trigger)
Runs all the events matching a trigger.
Definition event.c:319
int events_saveActive(xmlTextWriterPtr writer)
Saves the player's active events.
Definition event.c:816
static int event_parseXML(EventData *temp, const xmlNodePtr parent)
Loads up an event from an XML node.
Definition event.c:420
static unsigned int event_genID(void)
Generates a new event ID.
Definition event.c:170
int event_testClaims(unsigned int eventid, int sys)
Tests to see if an event has claimed a system.
Definition event.c:779
static EventData * event_data
Definition event.c:80
#define EVENT_FLAG_UNIQUE
Definition event.c:49
static int event_create(int dataid, unsigned int *id)
Creates an event.
Definition event.c:186
int faction_get(const char *name)
Gets a faction ID by name.
Definition faction.c:184
int hook_hasEventParent(unsigned int parent)
Checks to see how many hooks there are with the same event parent.
Definition hook.c:862
void hook_rmEventParent(unsigned int parent)
Removes all hooks belonging to parent event.
Definition hook.c:833
Spob * land_spob
Definition land.c:83
int naev_isQuit(void)
Get if Naev is trying to quit.
Definition naev.c:158
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).
Definition ndata.c:154
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
Definition ndata.c:231
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
Definition nlua.c:798
int nlua_loadBackground(nlua_env env)
Loads the graphics library.
Definition nlua_bkg.c:38
int nlua_loadCamera(nlua_env env)
Loads the camera library.
Definition nlua_camera.c:49
int event_run(unsigned int eventid, const char *func)
Runs the event function.
Definition nlua_evt.c:101
int nlua_loadEvt(nlua_env env)
Loads the event Lua library.
Definition nlua_evt.c:69
int nlua_loadHook(nlua_env env)
Loads the hook Lua library.
Definition nlua_hook.c:125
int nlua_loadMusic(nlua_env env)
Music Lua module.
Definition nlua_music.c:58
int nlua_loadTex(nlua_env env)
Loads the texture library.
Definition nlua_tex.c:62
int nlua_loadTk(nlua_env env)
Loads the Toolkit Lua library.
Definition nlua_tk.c:93
int npc_rm_parentEvent(unsigned int id)
Removes all the npc belonging to an event.
Definition npc.c:278
char * strnstr(const char *haystack, const char *needle, size_t size)
A bounded version of strstr. Conforms to BSD semantics.
Definition nstring.c:26
int nxml_persistLua(nlua_env env, xmlTextWriterPtr writer)
Persists all the nxml Lua data.
Definition nxml_lua.c:368
int nxml_unpersistLua(nlua_env env, xmlNodePtr parent)
Unpersists Lua data into a table named "mem".
Definition nxml_lua.c:530
int player_eventAlreadyDone(int id)
Checks to see if player has already completed a event.
Definition player.c:3014
Player_t player
Definition player.c:74
static const double c[]
Definition rng.c:264
StarSystem * cur_system
Definition space.c:106
Event data structure.
Definition event.c:54
char * chapter
Definition event.c:64
char * name
Definition event.c:55
char * cond
Definition event.c:69
int cond_chunk
Definition event.c:70
char ** tags
Definition event.c:74
int chunk
Definition event.c:58
double chance
Definition event.c:71
char * lua
Definition event.c:57
int * factions
Definition event.c:65
int priority
Definition event.c:72
EventTrigger_t trigger
Definition event.c:68
pcre2_code * chapter_re
Definition event.c:66
unsigned int flags
Definition event.c:59
char * spob
Definition event.c:62
char * system
Definition event.c:63
char * sourcefile
Definition event.c:56
Activated event structure.
Definition event.h:12
unsigned int id
Definition event.h:13
int save
Definition event.h:16
int data
Definition event.h:14
nlua_env env
Definition event.h:15
Claim_t * claims
Definition event.h:17
int devmode
Definition conf.h:157
char * chapter
Definition player.h:111
int faction
Definition space.h:67
char * name
Definition space.h:91
SpobPresence presence
Definition space.h:104