UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cp_messages.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 2002-2020 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 #include "../../cl_shared.h"
25 #include "cp_campaign.h"
26 #include "cp_popup.h"
27 #include "cp_messages.h"
28 #include "cp_time.h"
29 #include "save/save_messages.h"
30 
32 
39 static void MS_TimestampedText (char* text, uiMessageListNodeMessage_t* message, size_t textsize)
40 {
41  dateLong_t date;
42  CP_DateConvertLong(&message->date, &date);
43  Com_sprintf(text, textsize, _("%i %s %02i, %02i:%02i: "), date.year,
44  Date_GetMonthName(date.month - 1), date.day, date.hour, date.min);
45 }
46 
61 uiMessageListNodeMessage_t* MS_AddNewMessage (const char* title, const char* text, messageType_t type, technology_t* pedia, bool popup, bool playSound)
62 {
63  assert(type < MSG_MAX);
64 
65  /* allocate memory for new message - delete this with every new game */
67 
68  switch (type) {
69  case MSG_DEBUG:
70  mess->iconName = "icons/message_debug";
71  break;
72  case MSG_INFO:
73  mess->iconName = "icons/message_info";
74  break;
75  case MSG_STANDARD:
76  mess->iconName = "icons/message_info";
77  break;
79  mess->iconName = "icons/message_research";
80  break;
82  mess->iconName = "icons/message_research";
83  break;
85  mess->iconName = "icons/message_research";
86  break;
87  case MSG_CONSTRUCTION:
88  mess->iconName = "icons/message_construction";
89  break;
90  case MSG_UFOSPOTTED:
91  mess->iconName = "icons/message_ufo";
92  break;
93  case MSG_TERRORSITE:
94  mess->iconName = "icons/message_ufo";
95  break;
96  case MSG_BASEATTACK:
97  mess->iconName = "icons/message_ufo";
98  break;
100  mess->iconName = "icons/message_transfer";
101  break;
102  case MSG_PROMOTION:
103  mess->iconName = "icons/message_promotion";
104  break;
105  case MSG_PRODUCTION:
106  mess->iconName = "icons/message_production";
107  break;
108  case MSG_DEATH:
109  mess->iconName = "icons/message_death";
110  break;
111  case MSG_CRASHSITE:
112  mess->iconName = "icons/message_ufo";
113  break;
114  case MSG_EVENT:
115  mess->iconName = "icons/message_info";
116  break;
117  default:
118  mess->iconName = "icons/message_info";
119  break;
120  }
121 
122  /* push the new message at the beginning of the stack */
123  cgi->UI_MessageAddStack(mess);
124 
125  mess->type = type;
126  mess->pedia = pedia; /* pointer to UFOpaedia entry */
127 
128  mess->date = ccs.date;
129 
130  Q_strncpyz(mess->title, title, sizeof(mess->title));
131  mess->text = cgi->PoolStrDup(text, cp_campaignPool, 0);
132 
133  /* get formatted date text */
134  MS_TimestampedText(mess->timestamp, mess, sizeof(mess->timestamp));
135 
136  /* they need to be translated already */
137  if (popup) {
138  CP_GameTimeStop();
139  CP_Popup(mess->title, "%s", mess->text);
140  }
141 
142  if (playSound) {
143  const char* sound = nullptr;
144  switch (type) {
145  case MSG_DEBUG:
146  break;
147  case MSG_STANDARD:
148  sound = "geoscape/standard";
149  break;
150  case MSG_INFO:
152  case MSG_DEATH:
153  case MSG_CONSTRUCTION:
154  case MSG_PRODUCTION:
155  sound = "geoscape/info";
156  break;
159  assert(pedia);
160  case MSG_RESEARCH_HALTED:
161  case MSG_EVENT:
162  case MSG_NEWS:
163  /* reread the new mails in UP_GetUnreadMails */
164  ccs.numUnreadMails = -1;
165  sound = "geoscape/mail";
166  break;
167  case MSG_UFOLOST:
168  sound = "geoscape/ufolost";
169  break;
170  case MSG_UFOSPOTTED:
171  sound = "geoscape/ufospotted";
172  break;
173  case MSG_BASEATTACK:
174  sound = "geoscape/basealert";
175  break;
176  case MSG_TERRORSITE:
177  sound = "geoscape/alien-activity";
178  break;
179  case MSG_CRASHSITE:
180  sound = "geoscape/newmission";
181  break;
182  case MSG_PROMOTION:
183  sound = "geoscape/promotion";
184  break;
185  case MSG_MAX:
186  break;
187  }
188 
189  cgi->S_StartLocalSample(sound, 1.0f);
190  }
191 
192  return mess;
193 }
194 
202 {
203  xmlNode_t* n;
204 
205  if (!message)
206  return;
207 
208  /* bottom up */
209  MS_MessageSaveXML(p, message->next);
210 
211  /* don't save these message types */
212  if (message->type == MSG_INFO)
213  return;
214 
215  cgi->Com_RegisterConstList(saveMessageConstants);
218  cgi->XML_AddStringValue(n, SAVE_MESSAGES_TITLE, message->title);
219  cgi->XML_AddStringValue(n, SAVE_MESSAGES_TEXT, message->text);
220  /* store script id of event mail */
221  if (message->type == MSG_EVENT) {
222  cgi->XML_AddString(n, SAVE_MESSAGES_EVENTMAILID, message->eventMail->id);
223  cgi->XML_AddBoolValue(n, SAVE_MESSAGES_EVENTMAILREAD, message->eventMail->read);
224  }
225  if (message->pedia)
226  cgi->XML_AddString(n, SAVE_MESSAGES_PEDIAID, message->pedia->id);
227  cgi->XML_AddDate(n, SAVE_MESSAGES_DATE, message->date.day, message->date.sec);
228  cgi->Com_UnregisterConstList(saveMessageConstants);
229 }
230 
237 {
239 
240  /* store message system items */
242  return true;
243 }
244 
252 {
253  int i;
254  xmlNode_t* n, *sn;
256 
257  if (!n)
258  return false;
259 
260  /* we have to set this a little bit higher here, otherwise the samples that are played when adding
261  * a message to the stack would all played a few milliseconds after each other - that doesn't sound
262  * nice */
263  cgi->S_SetSampleRepeatRate(500);
264 
265  cgi->Com_RegisterConstList(saveMessageConstants);
266  for (sn = cgi->XML_GetNode(n, SAVE_MESSAGES_MESSAGE), i = 0; sn; sn = cgi->XML_GetNextNode(sn, n, SAVE_MESSAGES_MESSAGE), i++) {
267  eventMail_t* mail;
268  const char* type = cgi->XML_GetString(sn, SAVE_MESSAGES_TYPE);
269  int mtype;
270  char title[MAX_VAR];
271  char text[MAX_MESSAGE_TEXT];
272  char id[MAX_VAR];
273  technology_t* tech = nullptr;
275 
276  if (!cgi->Com_GetConstIntFromNamespace(SAVE_MESSAGETYPE_NAMESPACE, type, (int*) &mtype)) {
277  cgi->Com_Printf("Invalid message type '%s'\n", type);
278  continue;
279  }
280 
281  /* can contain high bits due to utf8 */
282  Q_strncpyz(title, cgi->XML_GetString(sn, SAVE_MESSAGES_TITLE), sizeof(title));
283  Q_strncpyz(text, cgi->XML_GetString(sn, SAVE_MESSAGES_TEXT), sizeof(text));
284 
285  if (mtype == MSG_EVENT) {
287  if (mail)
288  mail->read = cgi->XML_GetBool(sn, SAVE_MESSAGES_EVENTMAILREAD, false);
289  } else
290  mail = nullptr;
291 
292  /* event and not mail means, dynamic mail - we don't save or load them */
293  if (mtype == MSG_EVENT && !mail)
294  continue;
295  if (mtype == MSG_DEBUG && cgi->Cvar_GetInteger("developer") == 0)
296  continue;
297 
299  if (id[0] != '\0')
300  tech = RS_GetTechByID(id);
301  if (!tech && (mtype == MSG_RESEARCH_PROPOSAL || mtype == MSG_RESEARCH_FINISHED)) {
303  continue;
304  }
305  mess = MS_AddNewMessage(title, text, (messageType_t)mtype, tech, false, false);
306  mess->eventMail = mail;
307  cgi->XML_GetDate(sn, SAVE_MESSAGES_DATE, &mess->date.day, &mess->date.sec);
308  /* redo timestamp text after setting date */
309  MS_TimestampedText(mess->timestamp, mess, sizeof(mess->timestamp));
310 
311  if (mail) {
312  dateLong_t date;
313  char dateBuf[MAX_VAR] = "";
314 
315  CP_DateConvertLong(&mess->date, &date);
316  Com_sprintf(dateBuf, sizeof(dateBuf), _("%i %s %02i"),
317  date.year, Date_GetMonthName(date.month - 1), date.day);
318  mail->date = cgi->PoolStrDup(dateBuf, cp_campaignPool, 0);
319  }
320  }
321  cgi->Com_UnregisterConstList(saveMessageConstants);
322 
323  /* reset the sample repeat rate */
324  cgi->S_SetSampleRepeatRate(0);
325 
326  return true;
327 }
328 
329 void MS_MessageInit (void)
330 {
331  MSO_Init();
332 }
byte hour
Definition: cp_time.h:38
XML tag constants for savegame.
struct uiMessageListNodeMessage_s *IMPORT * UI_MessageGetStack(void)
byte min
Definition: cp_time.h:39
QGL_EXTERN GLint GLenum type
Definition: r_gl.h:94
char * id
Definition: cp_event.h:39
int numUnreadMails
Definition: cp_campaign.h:325
#define SAVE_MESSAGES_TEXT
Definition: save_messages.h:30
char timestamp[TIMESTAMP_TEXT]
Definition: cp_messages.h:58
#define _(String)
Definition: cl_shared.h:43
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.
int day
Definition: common.h:291
date_t date
Definition: cp_campaign.h:245
messageType_t
Definition: cp_messages.h:30
byte day
Definition: cp_time.h:37
#define MAX_MESSAGE_TEXT
Definition: cp_messages.h:27
static void MS_MessageSaveXML(xmlNode_t *p, uiMessageListNodeMessage_t *message)
Save a list of messages to xml.
char * date
Definition: cp_event.h:46
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:61
memPool_t * cp_campaignPool
Definition: cp_campaign.cpp:61
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:317
bool read
Definition: cp_event.h:50
#define SAVE_MESSAGES_DATE
Definition: save_messages.h:35
#define xmlNode_t
Definition: xml.h:24
GLuint * id
Definition: r_gl.h:149
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
xmlNode_t *IMPORT * XML_GetDate(xmlNode_t *parent, const char *name, int *day, int *sec)
#define MAX_VAR
Definition: shared.h:36
void MSO_Init(void)
#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:473
const cgame_import_t * cgi
short year
Definition: cp_time.h:35
const char *IMPORT * Com_GetConstVariable(const char *space, int value)
This is the technology parsed from research.ufo.
Definition: cp_research.h:137
bool MS_SaveXML(xmlNode_t *p)
Save callback for messages.
ccs_t ccs
Definition: cp_campaign.cpp:62
#define SAVE_MESSAGES_MESSAGES
Definition: save_messages.h:27
byte month
Definition: cp_time.h:36
Campaign geoscape time header.
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
struct eventMail_s * eventMail
Definition: cp_messages.h:68
#define SAVE_MESSAGETYPE_NAMESPACE
Definition: save_messages.h:37
int sec
Definition: common.h:292
#define SAVE_MESSAGES_EVENTMAILREAD
Definition: save_messages.h:33
char cp_messageBuffer[MAX_MESSAGE_TEXT]
Definition: cp_messages.cpp:31
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
available mails for a tech - mail and mail_pre in script files
Definition: cp_event.h:38
#define SAVE_MESSAGES_TITLE
Definition: save_messages.h:29
Human readable time information in the game.
Definition: cp_time.h:34
QGL_EXTERN GLint i
Definition: r_gl.h:113
xmlNode_t *IMPORT * XML_GetNextNode(xmlNode_t *current, xmlNode_t *parent, const char *name)
struct technology_s * pedia
Definition: cp_messages.h:67
void CP_DateConvertLong(const date_t *date, dateLong_t *dateLong)
Converts a date from the engine in a (longer) human-readable format.
Definition: cp_time.cpp:72
static const constListEntry_t saveMessageConstants[]
Definition: save_messages.h:38
Header file for single player campaign control.
void MS_MessageInit(void)
xmlNode_t *IMPORT * XML_AddNode(xmlNode_t *parent, const char *name)
static void MS_TimestampedText(char *text, uiMessageListNodeMessage_t *message, size_t textsize)
Returns formatted text of a message timestamp.
Definition: cp_messages.cpp:39
char *IMPORT * PoolStrDup(const char *in, memPool_t *pool, const int tagNum)
#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:44
struct uiMessageListNodeMessage_s * next
Definition: cp_messages.h:63
const char *IMPORT * XML_GetString(xmlNode_t *parent, const char *name)
xmlNode_t *IMPORT * XML_GetNode(xmlNode_t *parent, const char *name)
#define SAVE_MESSAGES_EVENTMAILID
Definition: save_messages.h:32