UFO: Alien Invasion
cp_event.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2022 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24 */
25 
26 #include "../../DateTime.h"
27 #include "../../cl_shared.h"
28 #include "../../../shared/parse.h"
29 #include "../../../common/binaryexpressionparser.h"
30 #include "cp_campaign.h"
31 #include "cp_time.h"
32 #include "cp_xvi.h"
33 #include "cp_event_callbacks.h"
35 
36 static linkedList_t* eventMails = nullptr;
37 
45 eventMail_t* CL_GetEventMail (const char* id)
46 {
47  int i;
48 
49  for (i = 0; i < ccs.numEventMails; i++) {
50  eventMail_t* mail = &ccs.eventMails[i];
51  if (Q_streq(mail->id, id))
52  return mail;
53  }
54 
55  LIST_Foreach(eventMails, eventMail_t, listMail) {
56  if (Q_streq(listMail->id, id))
57  return listMail;
58  }
59 
60  return nullptr;
61 }
62 
68 {
69  /* the pointers are not freed, this is done with the
70  * pool clear in CP_ResetCampaignData */
71  cgi->LIST_Delete(&eventMails);
72 }
73 
75 static const value_t eventMail_vals[] = {
76  {"subject", V_TRANSLATION_STRING, offsetof(eventMail_t, subject), 0},
77  {"from", V_TRANSLATION_STRING, offsetof(eventMail_t, from), 0},
78  {"to", V_TRANSLATION_STRING, offsetof(eventMail_t, to), 0},
79  {"cc", V_TRANSLATION_STRING, offsetof(eventMail_t, cc), 0},
80  {"date", V_TRANSLATION_STRING, offsetof(eventMail_t, date), 0},
81  {"body", V_TRANSLATION_STRING, offsetof(eventMail_t, body), 0},
82  {"icon", V_HUNK_STRING, offsetof(eventMail_t, icon), 0},
83  {"model", V_HUNK_STRING, offsetof(eventMail_t, model), 0},
84  {"skipmessage", V_BOOL, offsetof(eventMail_t, skipMessage), MEMBER_SIZEOF(eventMail_t, skipMessage)},
85 
86  {nullptr, V_NULL, 0, 0}
87 };
88 
93 void CL_ParseEventMails (const char* name, const char** text)
94 {
95  eventMail_t* eventMail;
96 
98  cgi->Com_Printf("CL_ParseEventMails: mail def \"%s\" with same name found, second ignored\n", name);
99  return;
100  }
101 
102  /* initialize the eventMail */
103  eventMail = &ccs.eventMails[ccs.numEventMails++];
104  OBJZERO(*eventMail);
105 
106  cgi->Com_DPrintf(DEBUG_CLIENT, "...found eventMail %s\n", name);
107 
108  eventMail->id = cgi->PoolStrDup(name, cp_campaignPool, 0);
109 
110  cgi->Com_ParseBlock(name, text, eventMail, eventMail_vals, cp_campaignPool);
111 }
112 
114 {
115  const campaignEvents_t* events = campaign->events;
116  int i;
117 
118  /* no events for the current campaign */
119  if (!events)
120  return;
121 
122  /* no events in that definition */
123  if (!events->numCampaignEvents)
124  return;
125 
126  for (i = 0; i < events->numCampaignEvents; i++) {
127  const campaignEvent_t* event = &events->campaignEvents[i];
128  if (event->interest <= ccs.overallInterest) {
129  RS_MarkStoryLineEventResearched(event->tech);
130  }
131  }
132 }
133 
140 {
141  for (int i = 0; i < ccs.numCampaignEventDefinitions; i++) {
143  if (Q_streq(events->id, name)) {
144  for (int j = 0; j < events->numCampaignEvents; j++) {
145  const campaignEvent_t* event = &events->campaignEvents[j];
146  if (!RS_GetTechByID(event->tech))
147  Sys_Error("Illegal tech '%s' given in events '%s'", event->tech, events->id);
148  }
149  return events;
150  }
151  }
152 
153  return nullptr;
154 }
155 
156 static int CP_CheckTriggerEvent (const char* expression, const void* userdata)
157 {
158  if (Q_strnull(expression))
159  return -1;
160 
161  const char* type;
162 
163  /* check that a particular installation type is built already */
164  type = Q_strstart(expression, "installation");
165  if (type != nullptr) {
166  if (strlen(type) <= 1)
167  return -1;
168  char value[MAX_VAR];
169  Q_strncpyz(value, type + 1, sizeof(value));
170  value[strlen(value) - 1] = '\0';
171  const installationType_t insType = INS_GetType(value);
172  if (INS_HasType(insType, INSTALLATION_NOT_USED))
173  return 1;
174  return 0;
175  }
176 
177  /* check whether a particular ufo was detected */
178  type = Q_strstart(expression, "ufo");
179  if (type != nullptr) {
180  if (strlen(type) <= 1)
181  return -1;
182  char value[MAX_VAR];
183  Q_strncpyz(value, type + 1, sizeof(value));
184  value[strlen(value) - 1] = '\0';
185  const char* detectedUFO = static_cast<const char*>(userdata);
186  if (Q_strnull(detectedUFO))
187  return -1;
188  return Q_streq(detectedUFO, value);
189  }
190 
191  /* check that the given xvi level is reached in any nation */
192  type = Q_strstart(expression, "xvi");
193  if (type != nullptr) {
194  int xvi;
195  if (sscanf(type, "[%i]", &xvi) != 1)
196  return -1;
197  /* check for XVI infection rate */
198  NAT_Foreach(nation) {
199  const nationInfo_t* stats = NAT_GetCurrentMonthInfo(nation);
200  if (stats->xviInfection >= xvi)
201  return 1;
202  }
203  return 0;
204  }
205 
206  /* check that the given tech is already researched */
207  type = Q_strstart(expression, "researched");
208  if (type != nullptr) {
209  if (strlen(type) <= 1)
210  return -1;
211  char value[MAX_VAR];
212  Q_strncpyz(value, type + 1, sizeof(value));
213  value[strlen(value) - 1] = '\0';
214  technology_t* tech = RS_GetTechByID(value);
215  if (tech == nullptr)
216  return -1;
217  if (RS_IsResearched_ptr(tech))
218  return 1;
219  return 0;
220  }
221 
222  /* check for nation happiness - also see the lost conditions in the campaign */
223  type = Q_strstart(expression, "nationhappiness");
224  if (type != nullptr) {
225  int nationAmount;
226 
227  if (sscanf(type, "[%i]", &nationAmount) != 1)
228  return -1;
229 
230  int nationBelowLimit = 0;
231  NAT_Foreach(nation) {
232  const nationInfo_t* stats = NAT_GetCurrentMonthInfo(nation);
233  if (stats->happiness < ccs.curCampaign->minhappiness) {
234  nationBelowLimit++;
235  if (nationBelowLimit >= nationAmount)
236  return 1;
237  }
238  }
239  return 0;
240  }
241 
242  /* check that the given average xvi level is reached */
243  type = Q_strstart(expression, "averagexvi");
244  if (type != nullptr) {
245  int xvipercent;
246  if (sscanf(type, "[%i]", &xvipercent) != 1)
247  return -1;
248  if (xvipercent < 0 || xvipercent > 100)
249  return -1;
250  const int xvi = CP_GetAverageXVIRate();
251  if (xvi > ccs.curCampaign->maxAllowedXVIRateUntilLost * xvipercent / 100)
252  return 1;
253  return 0;
254  }
255 
256  type = Q_strstart(expression, "difficulty");
257  if (type != nullptr) {
258  int difficulty;
259  if (sscanf(type, "[%i]", &difficulty) != 1)
260  return -1;
261  return ccs.curCampaign->difficulty == difficulty;
262  }
263 
264  /* check that these days have passed in the campaign */
265  type = Q_strstart(expression, "days");
266  if (type != nullptr) {
267  int days;
268  if (sscanf(type, "[%i]", &days) != 1)
269  return -1;
270  if ((ccs.curCampaign->date + DateTime(days, 0)) <= ccs.date)
271  return 1;
272  return 0;
273  }
274 
275  type = Q_strstart(expression, "alienscaptured");
276  if (type != nullptr) {
278  return 1;
279  return 0;
280  }
281 
282  type = Q_strstart(expression, "samsitearmed");
283  if (type != nullptr) {
285  return 1;
286 
287  INS_ForeachOfType(installation, INSTALLATION_DEFENCE) {
288  if (installation->installationStatus == INSTALLATION_WORKING) {
289  for (int i = 0; i < installation->installationTemplate->maxBatteries; i++) {
290  const aircraftSlot_t* slot = &installation->batteries[i].slot;
291  if (slot->ammoLeft > 0)
292  return 1;
293  }
294  }
295  }
296 
297  return 0;
298  }
299 
300  cgi->Com_Printf("unknown expression given: '%s'\n", expression);
301 
302  return -1;
303 }
304 
310 void CP_TriggerEvent (campaignTriggerEventType_t type, const void* userdata)
311 {
312  int i;
313 
314  for (i = 0; i < ccs.numCampaignTriggerEvents; i++) {
316  if (event->type != type || (!event->active && event->reactivate == nullptr))
317  continue;
318 
319  if (event->active) {
320  if (!cgi->BEP_Evaluate(event->require, CP_CheckTriggerEvent, userdata))
321  continue;
322  if (Q_strvalid(event->command)) {
324  cgi->Cmd_ExecuteString("%s", event->command);
326  }
327 
328  if (event->once) {
329  event->active = false;
330  }
331  } else {
332  event->active = cgi->BEP_Evaluate(event->reactivate, CP_CheckTriggerEvent, userdata);
333  }
334  }
335 }
336 
338 static const value_t event_vals[] = {
340  {"require", V_HUNK_STRING, offsetof(campaignTriggerEvent_t, require), 0},
341  {"reactivate", V_HUNK_STRING, offsetof(campaignTriggerEvent_t, reactivate), 0},
342  {"command", V_HUNK_STRING, offsetof(campaignTriggerEvent_t, command), 0},
343  {"once", V_BOOL, offsetof(campaignTriggerEvent_t, once), MEMBER_SIZEOF(campaignTriggerEvent_t, once)},
344 
345  {nullptr, V_NULL, 0, 0}
346 };
347 
348 #define EVENTCONSTANTS_NAMESPACE "eventTrigger::"
350  {EVENTCONSTANTS_NAMESPACE "new_day", NEW_DAY},
351  {EVENTCONSTANTS_NAMESPACE "ufo_detection", UFO_DETECTION},
352  {EVENTCONSTANTS_NAMESPACE "captured_aliens_died", CAPTURED_ALIENS_DIED},
353  {EVENTCONSTANTS_NAMESPACE "captured_aliens", CAPTURED_ALIENS},
354  {EVENTCONSTANTS_NAMESPACE "alienbase_discovered", ALIENBASE_DISCOVERED},
355 
356  {nullptr, -1}
357 };
358 
359 void CP_ParseEventTrigger (const char* name, const char** text)
360 {
361  const char* errhead = "CP_ParseEventTrigger: unexpected end of file (event ";
362  const char* token;
363 
365  cgi->Com_Printf("CP_ParseEventTrigger: max event def limit hit\n");
366  return;
367  }
368 
369  token = cgi->Com_EParse(text, errhead, name);
370  if (!*text)
371  return;
372 
373  if (!*text || token[0] != '{') {
374  cgi->Com_Printf("CP_ParseEventTrigger: event def '%s' without body ignored\n", name);
375  return;
376  }
377 
378  cgi->Com_RegisterConstList(eventConstants);
379 
381  OBJZERO(*event);
382  cgi->Com_DPrintf(DEBUG_CLIENT, "...found event %s\n", name);
384  event->active = true;
385  event->id = cgi->PoolStrDup(name, cp_campaignPool, 0);
386 
387  do {
388  token = cgi->Com_EParse(text, errhead, name);
389  if (!*text)
390  break;
391  if (*token == '}')
392  break;
393  if (!cgi->Com_ParseBlockToken(name, text, event, event_vals, cp_campaignPool, token)) {
394  cgi->Com_Printf("CP_ParseEventTrigger: Ignoring unknown event value '%s'\n", token);
395  }
396  } while (*text);
397 
398  cgi->Com_UnregisterConstList(eventConstants);
399 }
400 
402 {
404  int i;
405 
406  for (i = 0; i < ccs.numCampaignTriggerEvents; i++) {
408  if (event->active)
409  continue;
411 
412  cgi->XML_AddString(s, SAVE_TRIGGEREVENTS_NAME, event->id);
413  cgi->XML_AddBool(s, SAVE_TRIGGEREVENTS_STATE, event->active);
414  }
415 
416  return true;
417 }
418 
420 {
421  xmlNode_t* n, *s;
422 
424  if (!n)
425  return true;
426 
428  const char* id = cgi->XML_GetString(s, SAVE_TRIGGEREVENTS_NAME);
429  const bool state = cgi->XML_GetBool(s, SAVE_TRIGGEREVENTS_STATE, true);
430 
431  int i;
432  for (i = 0; i < ccs.numCampaignTriggerEvents; i++) {
434  if (Q_streq(event->id, id)) {
435  event->active = state;
436  break;
437  }
438  }
439  }
440 
441  return true;
442 }
443 
448 void CL_ParseCampaignEvents (const char* name, const char** text)
449 {
450  const char* errhead = "CL_ParseCampaignEvents: unexpected end of file (events ";
451  const char* token;
453 
455  cgi->Com_Printf("CL_ParseCampaignEvents: max events def limit hit\n");
456  return;
457  }
458 
459  token = cgi->Com_EParse(text, errhead, name);
460  if (!*text)
461  return;
462 
463  if (!*text || token[0] != '{') {
464  cgi->Com_Printf("CL_ParseCampaignEvents: events def '%s' without body ignored\n", name);
465  return;
466  }
467 
469  OBJZERO(*events);
470  cgi->Com_DPrintf(DEBUG_CLIENT, "...found events %s\n", name);
473 
474  do {
475  campaignEvent_t* event;
476  token = cgi->Com_EParse(text, errhead, name);
477  if (!*text)
478  break;
479  if (*token == '}')
480  break;
481 
482  if (events->numCampaignEvents >= MAX_CAMPAIGNEVENTS) {
483  cgi->Com_Printf("CL_ParseCampaignEvents: max events per event definition limit hit\n");
484  return;
485  }
486 
487  /* initialize the eventMail */
488  event = &events->campaignEvents[events->numCampaignEvents++];
489  OBJZERO(*event);
490 
491  event->tech = cgi->PoolStrDup(token, cp_campaignPool, 0);
492 
493  token = cgi->Com_EParse(text, errhead, name);
494  if (!*text)
495  return;
496 
497  cgi->Com_EParseValue(event, token, V_INT, offsetof(campaignEvent_t, interest), sizeof(int));
498 
499  if (event->interest < 0)
500  Sys_Error("Illegal interest value in events definition '%s' for tech '%s'", events->id, event->tech);
501  } while (*text);
502 }
503 
507 void CL_EventAddMail (const char* eventMailId)
508 {
509  eventMail_t* eventMail = CL_GetEventMail(eventMailId);
510  if (!eventMail) {
511  cgi->Com_Printf("CL_EventAddMail: Could not find eventmail with id '%s'\n", eventMailId);
512  return;
513  }
514 
515  if (eventMail->sent) {
516  return;
517  }
518 
519  if (!eventMail->from || !eventMail->to || !eventMail->subject || !eventMail->body) {
520  cgi->Com_Printf("CL_EventAddMail: mail with id '%s' has incomplete data\n", eventMailId);
521  return;
522  }
523 
524  if (!eventMail->date) {
525  dateLong_t date;
526  char dateBuf[MAX_VAR] = "";
527 
528  CP_DateConvertLong(ccs.date, &date);
529  Com_sprintf(dateBuf, sizeof(dateBuf), _("%i %s %02i"),
530  date.year, Date_GetMonthName(date.month - 1), date.day);
531  eventMail->date = cgi->PoolStrDup(dateBuf, cp_campaignPool, 0);
532  }
533 
534  eventMail->sent = true;
535 
536  if (!eventMail->skipMessage) {
537  uiMessageListNodeMessage_t* m = MS_AddNewMessage("", va(_("You've got a new mail: %s"), _(eventMail->subject)), MSG_EVENT);
538  if (m)
539  m->eventMail = eventMail;
540  else
541  cgi->Com_Printf("CL_EventAddMail: Could not add message with id: %s\n", eventMailId);
542  }
543 
544  UP_OpenEventMail(eventMailId);
545 }
546 
553 void CL_EventAddMail_f (void)
554 {
555  if (cgi->Cmd_Argc() < 2) {
556  cgi->Com_Printf("Usage: %s <event_mail_id>\n", cgi->Cmd_Argv(0));
557  return;
558  }
559 
561 }
bool Q_strnull(const char *string)
Definition: shared.h:138
int CP_GetAverageXVIRate(void)
Return the average XVI rate.
Definition: cp_xvi.cpp:163
int overallInterest
Definition: cp_campaign.h:239
xmlNode_t *IMPORT * XML_GetNode(xmlNode_t *parent, const char *name)
const nationInfo_t * NAT_GetCurrentMonthInfo(const nation_t *const nation)
Get the current month nation stats.
Definition: cp_nation.cpp:133
installationType_t INS_GetType(const char *type)
XML tag constants for savegame.
char * body
Definition: cp_event.h:47
int numEventMails
Definition: cp_campaign.h:329
void Sys_Error(const char *error,...)
Definition: g_main.cpp:421
#define MAX_CAMPAIGNS
Definition: cp_campaign.h:31
bool RS_IsResearched_ptr(const technology_t *tech)
Checks whether an item is already researched.
QGL_EXTERN GLint GLenum type
Definition: r_gl.h:94
int maxAllowedXVIRateUntilLost
Definition: cp_campaign.h:189
char * to
Definition: cp_event.h:41
byte month
Definition: cp_time.h:38
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don&#39;t need to have varargs versions of all text functi...
Definition: shared.cpp:410
#define SAVE_TRIGGEREVENTS_TRIGGEREVENT
short year
Definition: cp_time.h:37
void UP_OpenEventMail(const char *eventMailID)
void CL_EventAddMail(const char *eventMailId)
Adds the event mail to the message stack. This message is going to be added to the savegame...
Definition: cp_event.cpp:507
bool INS_HasType(installationType_t type, installationStatus_t status)
Checks whether the given installation type is available.
#define _(String)
Definition: cl_shared.h:44
char * date
Definition: cp_event.h:46
char * from
Definition: cp_event.h:40
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
Detailed information about the nation relationship (currently per month, but could be used elsewhere)...
Definition: cp_nation.h:35
Class describing a point of time.
Definition: DateTime.h:30
#define EVENTCONSTANTS_NAMESPACE
Definition: cp_event.cpp:348
#define SAVE_TRIGGEREVENTS_NAME
#define INS_ForeachOfType(var, installationType)
char * tech
Definition: cp_event.h:65
byte day
Definition: cp_time.h:39
const char *IMPORT * Cmd_Argv(int n)
int capturedAliens
Definition: cp_statistics.h:39
#define MAX_CAMPAIGNEVENTS
Definition: cp_event.h:29
bool CP_TriggerEventSaveXML(xmlNode_t *p)
Definition: cp_event.cpp:401
uiMessageListNodeMessage_t * MS_AddNewMessage(const char *title, const char *text, messageType_t type, technology_t *pedia, bool popup, bool playSound)
Adds a new message to message stack.
Definition: cp_messages.cpp:63
memPool_t * cp_campaignPool
Definition: cp_campaign.cpp:62
const char * Date_GetMonthName(int month)
Returns the short monthame to the given month index.
Definition: cp_time.cpp:250
#define Q_strvalid(string)
Definition: shared.h:141
char *IMPORT * PoolStrDup(const char *in, memPool_t *pool, const int tagNum)
bool sent
Definition: cp_event.h:51
#define xmlNode_t
Definition: xml.h:24
void CL_ParseCampaignEvents(const char *name, const char **text)
Definition: cp_event.cpp:448
void CP_CampaignTriggerFunctions(bool add)
Add/Remove temporary mission trigger functions.
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
static const constListEntry_t eventConstants[]
Definition: cp_event.cpp:349
Campaign XVI header.
int xviInfection
Definition: cp_nation.h:40
float happiness
Definition: cp_nation.h:39
installationType_t
#define DEBUG_CLIENT
Definition: defines.h:59
#define NAT_Foreach(var)
iterates trough nations
Definition: cp_nation.h:80
bool RS_MarkStoryLineEventResearched(const char *techID)
class DateTime date
Definition: cp_campaign.h:191
#define OBJZERO(obj)
Definition: shared.h:178
void CP_ParseEventTrigger(const char *name, const char **text)
Definition: cp_event.cpp:359
#define MAX_VAR
Definition: shared.h:36
static int CP_CheckTriggerEvent(const char *expression, const void *userdata)
Definition: cp_event.cpp:156
float minhappiness
Definition: cp_campaign.h:187
#define SAVE_TRIGGEREVENTS_TRIGGEREVENTS
char * subject
Definition: cp_event.h:43
int numCampaignTriggerEvents
Definition: cp_campaign.h:335
campaignTriggerEvent_t campaignTriggerEvents[MAX_CAMPAIGN_TRIGGER_EVENTS]
Definition: cp_campaign.h:334
void CL_EventAddMail_f(void)
Definition: cp_event.cpp:553
const char *IMPORT * XML_GetString(xmlNode_t *parent, const char *name)
Human readable time information in the game.
Definition: cp_time.h:36
const cgame_import_t * cgi
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition: shared.cpp:587
campaignEvents_t campaignEvents[MAX_CAMPAIGNS]
Definition: cp_campaign.h:331
ccs_t ccs
Definition: cp_campaign.cpp:63
void CP_TriggerEvent(campaignTriggerEventType_t type, const void *userdata)
Triggers a campaign event with a special type.
Definition: cp_event.cpp:310
const campaignEvents_t * CP_GetEventsByID(const char *name)
Definition: cp_event.cpp:139
Defines campaign events when story related technologies should be researched.
Definition: cp_event.h:64
Campaign geoscape time header.
xmlNode_t *IMPORT * XML_GetNextNode(xmlNode_t *current, xmlNode_t *parent, const char *name)
static const value_t event_vals[]
Valid event mail parameters.
Definition: cp_event.cpp:338
technology_t * RS_GetTechByID(const char *id)
return a pointer to the technology identified by given id string
void CP_FreeDynamicEventMail(void)
Make sure, that the linked list is freed with every new game.
Definition: cp_event.cpp:67
#define MAX_EVENTMAILS
Definition: cp_event.h:28
eventMail_t eventMails[MAX_EVENTMAILS]
Definition: cp_campaign.h:328
Definition: scripts.h:49
const eventRegister_t events[]
List of functions to register nodes.
Definition: e_main.cpp:92
campaign_t * curCampaign
Definition: cp_campaign.h:378
stats_t campaignStats
Definition: cp_campaign.h:379
QGL_EXTERN GLint i
Definition: r_gl.h:113
void CP_CheckCampaignEvents(campaign_t *campaign)
Definition: cp_event.cpp:113
Definition: scripts.h:50
#define MAX_CAMPAIGN_TRIGGER_EVENTS
Definition: cp_event.h:96
This is the technology parsed from research.ufo.
Definition: cp_research.h:139
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
class DateTime date
Definition: cp_campaign.h:246
list of script aliases to register
Definition: scripts.h:231
#define MEMBER_SIZEOF(TYPE, MEMBER)
Definition: scripts.h:34
char * id
Definition: cp_event.h:39
#define LIST_Foreach(list, type, var)
Iterates over a linked list, it&#39;s safe to delete the returned entry from the list while looping over ...
Definition: list.h:41
static linkedList_t * eventMails
Definition: cp_event.cpp:36
Header file for single player campaign control.
Definition: scripts.h:52
signed int difficulty
Definition: cp_campaign.h:186
#define SAVE_TRIGGEREVENTS_STATE
slot of aircraft
Definition: cp_aircraft.h:78
const campaignEvents_t * events
Definition: cp_campaign.h:195
xmlNode_t *IMPORT * XML_AddNode(xmlNode_t *parent, const char *name)
available mails for a tech - mail and mail_pre in script files
Definition: cp_event.h:38
#define Q_streq(a, b)
Definition: shared.h:136
void CP_DateConvertLong(const DateTime &date, dateLong_t *dateLong)
Converts a date from the engine in a (longer) human-readable format.
Definition: cp_time.cpp:73
eventMail_t * CL_GetEventMail(const char *id)
Searches all event mails for a given id.
Definition: cp_event.cpp:45
bool CP_TriggerEventLoadXML(xmlNode_t *p)
Definition: cp_event.cpp:419
campaignTriggerEventType_t
events that are triggered by the campaign
Definition: cp_event.h:78
void CL_ParseEventMails(const char *name, const char **text)
Definition: cp_event.cpp:93
const char *IMPORT * Com_EParse(const char **text, const char *errhead, const char *errinfo)
static struct mdfour * m
Definition: md4.cpp:35
bool skipMessage
Definition: cp_event.h:52
static const value_t eventMail_vals[]
Valid event mail parameters.
Definition: cp_event.cpp:75
int numCampaignEventDefinitions
Definition: cp_campaign.h:332