UFO: Alien Invasion
Doxygen documentation generating
cp_messages.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 2002-2023 UFO: Alien Invasion.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23 */
24 
25 #include "../../DateTime.h"
26 #include "../../cl_shared.h"
27 #include "cp_campaign.h"
28 #include "cp_popup.h"
29 #include "cp_messages.h"
30 #include "cp_time.h"
31 #include "save/save_messages.h"
32 
34 
41 static void MS_TimestampedText (char* text, uiMessageListNodeMessage_t* message, size_t textsize)
42 {
43  dateLong_t date;
44  CP_DateConvertLong(message->date, &date);
45  Com_sprintf(text, textsize, _("%i %s %02i, %02i:%02i: "), date.year,
46  Date_GetMonthName(date.month - 1), date.day, date.hour, date.min);
47 }
48 
63 uiMessageListNodeMessage_t* MS_AddNewMessage (const char* title, const char* text, messageType_t type, technology_t* pedia, bool popup, bool playSound)
64 {
65  assert(type < MSG_MAX);
66 
67  /* allocate memory for new message - delete this with every new game */
69 
70  switch (type) {
71  case MSG_DEBUG:
72  mess->iconName = "icons/message_debug";
73  break;
74  case MSG_INFO:
75  mess->iconName = "icons/message_info";
76  break;
77  case MSG_STANDARD:
78  mess->iconName = "icons/message_info";
79  break;
81  mess->iconName = "icons/message_research";
82  break;
84  mess->iconName = "icons/message_research";
85  break;
87  mess->iconName = "icons/message_research";
88  break;
89  case MSG_CONSTRUCTION:
90  mess->iconName = "icons/message_construction";
91  break;
92  case MSG_UFOSPOTTED:
93  mess->iconName = "icons/message_ufo";
94  break;
95  case MSG_TERRORSITE:
96  mess->iconName = "icons/message_ufo";
97  break;
98  case MSG_BASEATTACK:
99  mess->iconName = "icons/message_ufo";
100  break;
102  mess->iconName = "icons/message_transfer";
103  break;
104  case MSG_PROMOTION:
105  mess->iconName = "icons/message_promotion";
106  break;
107  case MSG_PRODUCTION:
108  mess->iconName = "icons/message_production";
109  break;
110  case MSG_DEATH:
111  mess->iconName = "icons/message_death";
112  break;
113  case MSG_CRASHSITE:
114  mess->iconName = "icons/message_ufo";
115  break;
116  case MSG_EVENT:
117  mess->iconName = "icons/message_info";
118  break;
119  default:
120  mess->iconName = "icons/message_info";
121  break;
122  }
123 
124  /* push the new message at the beginning of the stack */
125  cgi->UI_MessageAddStack(mess);
126 
127  mess->type = type;
128  mess->pedia = pedia; /* pointer to UFOpaedia entry */
129 
130  mess->date = ccs.date;
131 
132  Q_strncpyz(mess->title, title, sizeof(mess->title));
133  mess->text = cgi->PoolStrDup(text, cp_campaignPool, 0);
134 
135  /* get formatted date text */
136  MS_TimestampedText(mess->timestamp, mess, sizeof(mess->timestamp));
137 
138  /* they need to be translated already */
139  if (popup) {
140  CP_GameTimeStop();
141  CP_Popup(mess->title, "%s", mess->text);
142  }
143 
144  if (playSound) {
145  const char* sound = nullptr;
146  switch (type) {
147  case MSG_DEBUG:
148  break;
149  case MSG_STANDARD:
150  sound = "geoscape/standard";
151  break;
152  case MSG_INFO:
154  case MSG_DEATH:
155  case MSG_CONSTRUCTION:
156  case MSG_PRODUCTION:
157  sound = "geoscape/info";
158  break;
161  assert(pedia);
162  case MSG_RESEARCH_HALTED:
163  case MSG_EVENT:
164  case MSG_NEWS:
165  /* reread the new mails in UP_GetUnreadMails */
166  ccs.numUnreadMails = -1;
167  sound = "geoscape/mail";
168  break;
169  case MSG_UFOLOST:
170  sound = "geoscape/ufolost";
171  break;
172  case MSG_UFOSPOTTED:
173  sound = "geoscape/ufospotted";
174  break;
175  case MSG_BASEATTACK:
176  sound = "geoscape/basealert";
177  break;
178  case MSG_TERRORSITE:
179  sound = "geoscape/alien-activity";
180  break;
181  case MSG_CRASHSITE:
182  sound = "geoscape/newmission";
183  break;
184  case MSG_PROMOTION:
185  sound = "geoscape/promotion";
186  break;
187  case MSG_MAX:
188  break;
189  }
190 
191  cgi->S_StartLocalSample(sound, 1.0f);
192  }
193 
194  return mess;
195 }
196 
204 {
205  xmlNode_t* n;
206 
207  if (!message)
208  return;
209 
210  /* bottom up */
211  MS_MessageSaveXML(p, message->next);
212 
213  /* don't save these message types */
214  if (message->type == MSG_INFO)
215  return;
216 
217  cgi->Com_RegisterConstList(saveMessageConstants);
219  cgi->XML_AddString(n, SAVE_MESSAGES_TYPE, cgi->Com_GetConstVariable(SAVE_MESSAGETYPE_NAMESPACE, message->type));
220  cgi->XML_AddStringValue(n, SAVE_MESSAGES_TITLE, message->title);
221  cgi->XML_AddStringValue(n, SAVE_MESSAGES_TEXT, message->text);
222  /* store script id of event mail */
223  if (message->type == MSG_EVENT) {
224  cgi->XML_AddString(n, SAVE_MESSAGES_EVENTMAILID, message->eventMail->id);
225  cgi->XML_AddBoolValue(n, SAVE_MESSAGES_EVENTMAILREAD, message->eventMail->read);
226  }
227  if (message->pedia)
228  cgi->XML_AddString(n, SAVE_MESSAGES_PEDIAID, message->pedia->id);
229  cgi->XML_AddDate(n, SAVE_MESSAGES_DATE, message->date.getDateAsDays(), message->date.getTimeAsSeconds());
230  cgi->Com_UnregisterConstList(saveMessageConstants);
231 }
232 
239 {
241 
242  /* store message system items */
244  return true;
245 }
246 
254 {
255  int i;
256  xmlNode_t* n, *sn;
258 
259  if (!n)
260  return false;
261 
262  /* we have to set this a little bit higher here, otherwise the samples that are played when adding
263  * a message to the stack would all played a few milliseconds after each other - that doesn't sound
264  * nice */
265  cgi->S_SetSampleRepeatRate(500);
266 
267  cgi->Com_RegisterConstList(saveMessageConstants);
268  for (sn = cgi->XML_GetNode(n, SAVE_MESSAGES_MESSAGE), i = 0; sn; sn = cgi->XML_GetNextNode(sn, n, SAVE_MESSAGES_MESSAGE), i++) {
269  eventMail_t* mail;
270  const char* type = cgi->XML_GetString(sn, SAVE_MESSAGES_TYPE);
271  int mtype;
272  char title[MAX_VAR];
273  char text[MAX_MESSAGE_TEXT];
274  char id[MAX_VAR];
275  technology_t* tech = nullptr;
277 
278  if (!cgi->Com_GetConstIntFromNamespace(SAVE_MESSAGETYPE_NAMESPACE, type, (int*) &mtype)) {
279  cgi->Com_Printf("Invalid message type '%s'\n", type);
280  continue;
281  }
282 
283  /* can contain high bits due to utf8 */
284  Q_strncpyz(title, cgi->XML_GetString(sn, SAVE_MESSAGES_TITLE), sizeof(title));
285  Q_strncpyz(text, cgi->XML_GetString(sn, SAVE_MESSAGES_TEXT), sizeof(text));
286 
287  if (mtype == MSG_EVENT) {
289  if (mail)
290  mail->read = cgi->XML_GetBool(sn, SAVE_MESSAGES_EVENTMAILREAD, false);
291  } else
292  mail = nullptr;
293 
294  /* event and not mail means, dynamic mail - we don't save or load them */
295  if (mtype == MSG_EVENT && !mail)
296  continue;
297  if (mtype == MSG_DEBUG && cgi->Cvar_GetInteger("developer") == 0)
298  continue;
299 
301  if (id[0] != '\0')
302  tech = RS_GetTechByID(id);
303  if (!tech && (mtype == MSG_RESEARCH_PROPOSAL || mtype == MSG_RESEARCH_FINISHED)) {
305  continue;
306  }
307  mess = MS_AddNewMessage(title, text, (messageType_t)mtype, tech, false, false);
308  mess->eventMail = mail;
309  int date;
310  int time;
311  cgi->XML_GetDate(sn, SAVE_MESSAGES_DATE, &date, &time);
312  mess->date = DateTime(date, time);
313  /* redo timestamp text after setting date */
314  MS_TimestampedText(mess->timestamp, mess, sizeof(mess->timestamp));
315 
316  if (mail) {
317  dateLong_t date;
318  char dateBuf[MAX_VAR] = "";
319 
320  CP_DateConvertLong(mess->date, &date);
321  Com_sprintf(dateBuf, sizeof(dateBuf), _("%i %s %02i"),
322  date.year, Date_GetMonthName(date.month - 1), date.day);
323  mail->date = cgi->PoolStrDup(dateBuf, cp_campaignPool, 0);
324  }
325  }
326  cgi->Com_UnregisterConstList(saveMessageConstants);
327 
328  /* reset the sample repeat rate */
329  cgi->S_SetSampleRepeatRate(0);
330 
331  return true;
332 }
333 
334 void MS_MessageInit (void)
335 {
336  MSO_Init();
337 }
char timestamp[TIMESTAMP_TEXT]
xmlNode_t *IMPORT * XML_GetNode(xmlNode_t *parent, const char *name)
Class describing a point of time.
Definition: DateTime.h:30
byte min
Definition: cp_time.h:41
XML tag constants for savegame.
QGL_EXTERN GLint GLenum type
Definition: r_gl.h:94
char * date
Definition: cp_event.h:46
#define SAVE_MESSAGES_TEXT
Definition: save_messages.h:30
#define _(String)
Definition: cl_shared.h:44
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
bool MS_LoadXML(xmlNode_t *p)
Load callback for messages.
messageType_t
Definition: cp_messages.h:32
byte day
Definition: cp_time.h:39
QGL_EXTERN GLuint * id
Definition: r_gl.h:86
#define MAX_MESSAGE_TEXT
Definition: cp_messages.h:29
static void MS_MessageSaveXML(xmlNode_t *p, uiMessageListNodeMessage_t *message)
Save a list of messages to xml.
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
void CP_GameTimeStop(void)
Stop game time speed.
Definition: cp_time.cpp:126
const char * Date_GetMonthName(int month)
Returns the short monthame to the given month index.
Definition: cp_time.cpp:250
char *IMPORT * PoolStrDup(const char *in, memPool_t *pool, const int tagNum)
byte hour
Definition: cp_time.h:40
#define SAVE_MESSAGES_DATE
Definition: save_messages.h:35
#define xmlNode_t
Definition: xml.h:24
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
#define SAVE_MESSAGES_MESSAGE
Definition: save_messages.h:28
struct uiMessageListNodeMessage_s *IMPORT * UI_MessageGetStack(void)
struct uiMessageListNodeMessage_s * next
int numUnreadMails
Definition: cp_campaign.h:326
#define MAX_VAR
Definition: shared.h:36
void MSO_Init(void)
xmlNode_t *IMPORT * XML_GetDate(xmlNode_t *parent, const char *name, int *day, int *sec)
#define SAVE_MESSAGES_PEDIAID
Definition: save_messages.h:34
void CP_Popup(const char *title, const char *text,...)
Wrapper around UI_Popup.
Definition: cp_popup.cpp:474
const char *IMPORT * XML_GetString(xmlNode_t *parent, const char *name)
const cgame_import_t * cgi
Human readable time information in the game.
Definition: cp_time.h:36
bool MS_SaveXML(xmlNode_t *p)
Save callback for messages.
int getTimeAsSeconds() const
Return the time part of the DateTime as seconds.
Definition: DateTime.cpp:54
ccs_t ccs
Definition: cp_campaign.cpp:63
#define SAVE_MESSAGES_MESSAGES
Definition: save_messages.h:27
short year
Definition: cp_time.h:37
Campaign geoscape time header.
xmlNode_t *IMPORT * XML_GetNextNode(xmlNode_t *current, xmlNode_t *parent, const char *name)
technology_t * RS_GetTechByID(const char *id)
return a pointer to the technology identified by given id string
#define SAVE_MESSAGES_TYPE
Definition: save_messages.h:31
#define SAVE_MESSAGETYPE_NAMESPACE
Definition: save_messages.h:37
#define SAVE_MESSAGES_EVENTMAILREAD
Definition: save_messages.h:33
char cp_messageBuffer[MAX_MESSAGE_TEXT]
Definition: cp_messages.cpp:33
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
int getDateAsDays() const
Return the date part of the DateTime as days.
Definition: DateTime.cpp:46
#define SAVE_MESSAGES_TITLE
Definition: save_messages.h:29
QGL_EXTERN GLint i
Definition: r_gl.h:113
This is the technology parsed from research.ufo.
Definition: cp_research.h:139
class DateTime date
Definition: cp_campaign.h:246
static const constListEntry_t saveMessageConstants[]
Definition: save_messages.h:38
Header file for single player campaign control.
void MS_MessageInit(void)
static void MS_TimestampedText(char *text, uiMessageListNodeMessage_t *message, size_t textsize)
Returns formatted text of a message timestamp.
Definition: cp_messages.cpp:41
bool read
Definition: cp_event.h:50
xmlNode_t *IMPORT * XML_AddNode(xmlNode_t *parent, const char *name)
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
#define Mem_PoolAllocType(type, pool)
Definition: mem.h:43
eventMail_t * CL_GetEventMail(const char *id)
Searches all event mails for a given id.
Definition: cp_event.cpp:45
const char *IMPORT * Com_GetConstVariable(const char *space, int value)
available mails for a tech - mail and mail_pre in script files
Definition: cp_event.h:38
#define SAVE_MESSAGES_EVENTMAILID
Definition: save_messages.h:32
byte month
Definition: cp_time.h:38