UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cp_uforecovery.cpp
Go to the documentation of this file.
1 
8 /*
9 Copyright (C) 2002-2020 UFO: Alien Invasion.
10 
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 
20 See the GNU General Public License for more details.
21 
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26 
27 #include "../../cl_shared.h"
28 #include "cp_campaign.h"
29 #include "cp_ufo.h"
30 #include "cp_geoscape.h"
31 #include "cp_time.h"
32 #include "cp_uforecovery.h"
34 #include "cp_aircraft.h"
35 #include "save/save_uforecovery.h"
36 #include "cp_component.h"
37 
38 /*==================================
39 Backend functions
40 ==================================*/
41 
46 void UR_ProcessActive (void)
47 {
48  US_Foreach(ufo) {
49  assert(ufo->ufoTemplate);
50  assert(ufo->ufoTemplate->tech);
51 
52  if (ufo->status == SUFO_STORED)
53  continue;
54  if (Date_LaterThan(&ufo->arrive, &ccs.date))
55  continue;
56 
57  Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("%s was transferred to %s."), UFO_GetName(ufo->ufoTemplate), ufo->installation->name);
58  switch (ufo->status) {
59  case SUFO_RECOVERED:
61  break;
62  case SUFO_TRANSFERED:
64  break;
65  default:
66  break;
67  }
68  ufo->status = SUFO_STORED;
69 
70  if (!ufo->ufoTemplate->tech->statusCollected)
71  RS_MarkCollected(ufo->ufoTemplate->tech);
72  }
73 }
74 
75 /* ==== UFO Storing stuff ==== */
76 
83 {
84  US_Foreach(ufo) {
85  if (ufo->idx == idx)
86  return ufo;
87  }
88  return nullptr;
89 }
90 
99 storedUFO_t* US_StoreUFO (const aircraft_t* ufoTemplate, installation_t* installation, date_t date, float condition)
100 {
101  if (!ufoTemplate) {
102  cgi->Com_DPrintf(DEBUG_CLIENT, "US_StoreUFO: Invalid aircraft (UFO) Template.\n");
103  return nullptr;
104  }
105 
106  if (!installation) {
107  cgi->Com_DPrintf(DEBUG_CLIENT, "US_StoreUFO: Invalid Installation\n");
108  return nullptr;
109  }
110 
111  if (installation->ufoCapacity.cur >= installation->ufoCapacity.max) {
112  cgi->Com_DPrintf(DEBUG_CLIENT, "US_StoreUFO: Installation is full with UFOs.\n");
113  return nullptr;
114  }
115 
116  /* we can store it there */
117  storedUFO_t ufo;
119  Q_strncpyz(ufo.id, ufoTemplate->id, sizeof(ufo.id));
120  ufo.comp = COMP_GetComponentsByID(ufo.id);
121  assert(ufo.comp);
122 
123  ufo.installation = installation;
124  installation->ufoCapacity.cur++;
125 
126  assert(ufoTemplate->tech);
127 
128  ufo.ufoTemplate = ufoTemplate;
129  ufo.disassembly = nullptr;
130 
131  ufo.arrive = date;
132  if (Date_LaterThan(&ccs.date, &ufo.arrive)) {
133  ufo.status = SUFO_STORED;
135  } else {
136  ufo.status = SUFO_RECOVERED;
137  }
138  ufo.condition = std::min(std::max(0.0f, condition), 1.0f);
139 
140  return &LIST_Add(&ccs.storedUFOs, ufo);
141 }
142 
148 {
149  assert(ufo);
150 
151  /* Stop disassembling */
152  if (ufo->disassembly) {
153  base_t* prodBase = PR_ProductionBase(ufo->disassembly);
154 
155  assert(prodBase);
156 
157  if (ufo->disassembly->idx == 0)
158  PR_QueueNext(prodBase);
159  else
160  PR_QueueDelete(prodBase, PR_GetProductionForBase(prodBase), ufo->disassembly->idx);
161  }
162 
163  /* Check all researches their requirements may broke */
165 
166  /* remove ufo */
167  ufo->installation->ufoCapacity.cur--;
168  cgi->LIST_Remove(&ccs.storedUFOs, (void*)ufo);
169 }
170 
171 
179 int US_UFOsInStorage (const aircraft_t* ufoTemplate, const installation_t* installation)
180 {
181  int count = 0;
182 
183  US_Foreach(ufo) {
184  if (ufo->ufoTemplate != ufoTemplate)
185  continue;
186  if (installation && ufo->installation != installation)
187  continue;
188  if (ufo->status != SUFO_STORED)
189  continue;
190 
191  count++;
192  }
193 
194  return count;
195 }
196 
202 {
203  if (!installation)
204  cgi->Com_Error(ERR_DROP, "US_RemoveUFOsExceedingCapacity: No installation given!\n");
205 
206  const capacities_t* ufoCap = &installation->ufoCapacity;
207 
208  US_Foreach(ufo) {
209  if (ufoCap->cur <= ufoCap->max)
210  break;
211  if (ufo->installation != installation) {
212  continue;
213  }
214  US_RemoveStoredUFO(ufo);
215  }
216 }
217 
225 {
226  date_t date;
227 
228  if (!ufo)
229  cgi->Com_Error(ERR_DROP, "No UFO cannot be transferred!");
230  if (!ufoyard)
231  cgi->Com_Error(ERR_DROP, "UFO cannot be transferred to void!");
232  /* only stored ufo can be transferred */
233  if (ufo->status != SUFO_STORED)
234  return false;
235  /* UFO being disassembled cannot be transferred*/
236  if (ufo->disassembly != nullptr)
237  return false;
238  /* UFO is in the same yard - no need of transfer */
239  if (ufo->installation == ufoyard)
240  return false;
241  if (ufoyard->ufoCapacity.cur >= ufoyard->ufoCapacity.max)
242  return false;
243 
244  date = ccs.date;
245  date.day += (int) RECOVERY_DELAY;
246 
247  ufo->installation->ufoCapacity.cur--;
248  ufo->status = SUFO_TRANSFERED;
249  ufo->arrive = date;
250  ufo->installation = ufoyard;
251  ufoyard->ufoCapacity.cur++;
252 
253  Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("UFO transport started, cargo is being transported to %s"), ufoyard->name);
255 
256  return true;
257 }
258 
266 {
267  float minDistance = -1;
268  storedUFO_t* closestUFO = nullptr;
269 
270  US_Foreach(ufo) {
271  float distance = 0;
272 
273  if (ufoTemplate && ufo->ufoTemplate != ufoTemplate)
274  continue;
275  if (ufo->status != SUFO_STORED)
276  continue;
277  assert(ufo->installation);
278  if (base)
279  distance = GetDistanceOnGlobe(ufo->installation->pos, base->pos);
280 
281  if (minDistance < 0 || minDistance > distance) {
282  minDistance = distance;
283  closestUFO = ufo;
284  }
285  }
286  return closestUFO;
287 }
288 
293 {
294  return cgi->LIST_Count(ccs.storedUFOs);
295 }
296 
304 {
306 
307  cgi->Com_RegisterConstList(saveStoredUFOConstants);
308  US_Foreach(ufo) {
310 
311  cgi->XML_AddInt(snode, SAVE_UFORECOVERY_UFOIDX, ufo->idx);
312  cgi->XML_AddString(snode, SAVE_UFORECOVERY_UFOID, ufo->id);
313  cgi->XML_AddDate(snode, SAVE_UFORECOVERY_DATE, ufo->arrive.day, ufo->arrive.sec);
315  cgi->XML_AddFloat(snode, SAVE_UFORECOVERY_CONDITION, ufo->condition);
316 
317  if (ufo->installation)
318  cgi->XML_AddInt(snode, SAVE_UFORECOVERY_INSTALLATIONIDX, ufo->installation->idx);
319  }
320  cgi->Com_UnregisterConstList(saveStoredUFOConstants);
321  return true;
322 }
323 
331 {
332  xmlNode_t* node, *snode;
333 
335 
336  cgi->Com_RegisterConstList(saveStoredUFOConstants);
337  for (snode = cgi->XML_GetNode(node, SAVE_UFORECOVERY_UFO); snode;
338  snode = cgi->XML_GetNextNode(snode, node, SAVE_UFORECOVERY_UFO)) {
339  const char* id = cgi->XML_GetString(snode, SAVE_UFORECOVERY_STATUS);
340  storedUFO_t ufo;
341  int statusIDX;
342 
343  /* ufo->idx */
344  ufo.idx = cgi->XML_GetInt(snode, SAVE_UFORECOVERY_UFOIDX, -1);
345  if (ufo.idx < 0) {
346  cgi->Com_Printf("Invalid or no IDX defined for stored UFO.\n");
347  continue;
348  }
349  /* ufo->status */
350  if (!cgi->Com_GetConstIntFromNamespace(SAVE_STOREDUFOSTATUS_NAMESPACE, id, &statusIDX)) {
351  cgi->Com_Printf("Invalid storedUFOStatus '%s'\n", id);
352  continue;
353  }
354  ufo.status = (storedUFOStatus_t)statusIDX;
355  /* ufo->installation */
356  ufo.installation = INS_GetByIDX(cgi->XML_GetInt(snode, SAVE_UFORECOVERY_INSTALLATIONIDX, -1));
357  if (!ufo.installation) {
358  cgi->Com_Printf("UFO has no/invalid installation assigned\n");
359  continue;
360  }
362  cgi->Com_Printf("UFO Yard %i if full!\n", ufo.installation->idx);
363  continue;
364  }
366  /* ufo->id */
367  Q_strncpyz(ufo.id, cgi->XML_GetString(snode, SAVE_UFORECOVERY_UFOID), sizeof(ufo.id));
368  /* ufo->ufoTemplate */
369  ufo.ufoTemplate = AIR_GetAircraft(ufo.id);
370  if (!ufo.ufoTemplate) {
371  cgi->Com_Printf("UFO has no/invalid aircraftTemplare assigned\n");
372  continue;
373  }
374  ufo.comp = COMP_GetComponentsByID(ufo.id);
375  if (!ufo.comp) {
376  cgi->Com_Printf("UFO has no/invalid components set\n");
377  continue;
378  }
380  ufo.condition = cgi->XML_GetFloat(snode, SAVE_UFORECOVERY_CONDITION, 1.0f);
381  /* disassembly is set by production savesystem later but only for UFOs that are being disassembled */
382  ufo.disassembly = nullptr;
383  LIST_Add(&ccs.storedUFOs, ufo);
384  }
385  cgi->Com_UnregisterConstList(saveStoredUFOConstants);
386  return true;
387 }
388 
389 #ifdef DEBUG
390 
393 static void US_ListStoredUFOs_f (void)
394 {
395  US_Foreach(ufo) {
396  const base_t* prodBase = PR_ProductionBase(ufo->disassembly);
397  dateLong_t date;
398 
399  cgi->Com_Printf("IDX: %i\n", ufo->idx);
400  cgi->Com_Printf("id: %s\n", ufo->id);
401  cgi->Com_Printf("stored at %s\n", (ufo->installation) ? ufo->installation->name : "NOWHERE");
402 
403  CP_DateConvertLong(&(ufo->arrive), &date);
404  cgi->Com_Printf("arrived at: %i %s %02i, %02i:%02i\n", date.year,
405  Date_GetMonthName(date.month - 1), date.day, date.hour, date.min);
406 
407  if (ufo->ufoTemplate->tech->base)
408  cgi->Com_Printf("tech being researched at %s\n", ufo->ufoTemplate->tech->base->name);
409  if (prodBase)
410  cgi->Com_Printf("being disassembled at %s\n", prodBase->name);
411  }
412 }
413 
417 static void US_StoreUFO_f (void)
418 {
419  char ufoId[MAX_VAR];
420 
421  if (cgi->Cmd_Argc() <= 2) {
422  cgi->Com_Printf("Usage: %s <ufoType> <installationIdx>\n", cgi->Cmd_Argv(0));
423  return;
424  }
425 
426  Q_strncpyz(ufoId, cgi->Cmd_Argv(1), sizeof(ufoId));
427  int installationIDX = atoi(cgi->Cmd_Argv(2));
428 
429  /* Get The UFO Yard */
430  if (installationIDX < 0) {
431  cgi->Com_Printf("US_StoreUFO_f: Invalid Installation index.\n");
432  return;
433  }
434  installation_t* installation = INS_GetByIDX(installationIDX);
435  if (!installation) {
436  cgi->Com_Printf("US_StoreUFO_f: There is no Installation: idx=%i.\n", installationIDX);
437  return;
438  }
439 
440  /* Get UFO Type */
442  aircraft_t* ufoType = nullptr;
443  for (int i = 0; i < ccs.numAircraftTemplates; i++) {
444  if (strstr(ccs.aircraftTemplates[i].id, ufoId)) {
445  ufoType = &ccs.aircraftTemplates[i];
446  break;
447  }
448  }
449  if (ufoType == nullptr) {
450  cgi->Com_Printf("US_StoreUFO_f: In valid UFO Id.\n");
451  return;
452  }
453 
454  US_StoreUFO(ufoType, installation, ccs.date, 1.0f);
455 }
456 
460 static void US_RemoveStoredUFO_f (void)
461 {
462  if (cgi->Cmd_Argc() < 2) {
463  cgi->Com_Printf("Usage: %s <idx>\n", cgi->Cmd_Argv(0));
464  return;
465  } else {
466  const int idx = atoi(cgi->Cmd_Argv(1));
467  storedUFO_t* storedUFO = US_GetStoredUFOByIDX(idx);
468  if (!storedUFO) {
469  cgi->Com_Printf("US_RemoveStoredUFO_f: No such ufo index.\n");
470  return;
471  }
472  US_RemoveStoredUFO(storedUFO);
473  }
474 }
475 #endif
476 
477 static const cmdList_t debugStoredUfosCmds[] = {
478 #ifdef DEBUG
479  {"debug_liststoredufos", US_ListStoredUFOs_f, "Debug function to list UFOs in Hangars."},
480  {"debug_storeufo", US_StoreUFO_f, "Debug function to Add UFO to Hangars."},
481  {"debug_removestoredufo", US_RemoveStoredUFO_f, "Debug function to Remove UFO from Hangars."},
482 #endif
483  {nullptr, nullptr, nullptr}
484 };
489 void UR_InitStartup (void)
490 {
492  cgi->Cmd_TableAddList(debugStoredUfosCmds);
493 }
494 
498 void UR_Shutdown (void)
499 {
500  cgi->LIST_Delete(&ccs.storedUFOs);
501 
503  cgi->Cmd_TableRemoveList(debugStoredUfosCmds);
504 }
void UR_ShutdownCallbacks(void)
byte hour
Definition: cp_time.h:38
storedUFOStatus_t status
Header file for Aircraft and item components.
byte min
Definition: cp_time.h:39
uiMessageListNodeMessage_t * MSO_CheckAddNewMessage(const notify_t messagecategory, const char *title, const char *text, messageType_t type, technology_t *pedia, bool popup)
Adds a new message to message stack. It uses message settings to verify whether sound should be playe...
storedUFO_t * US_StoreUFO(const aircraft_t *ufoTemplate, installation_t *installation, date_t date, float condition)
Adds an UFO to the storage.
A installation with all it's data.
char * id
Definition: cp_aircraft.h:119
char id[MAX_VAR]
#define _(String)
Definition: cl_shared.h:43
int US_StoredUFOCount(void)
Returns the number of storedUFOs.
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
char name[MAX_VAR]
Definition: cp_base.h:86
#define PR_GetProductionForBase(base)
Definition: cp_produce.h:96
#define SAVE_UFORECOVERY_UFOIDX
const aircraft_t * ufoTemplate
int day
Definition: common.h:291
date_t date
Definition: cp_campaign.h:245
struct base_s * base
Definition: cp_research.h:167
const aircraft_t * AIR_GetAircraft(const char *name)
Searches the global array of aircraft types for a given aircraft.
#define SAVE_UFORECOVERY_UFO
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
#define SAVE_UFORECOVERY_DATE
int US_UFOsInStorage(const aircraft_t *ufoTemplate, const installation_t *installation)
Returns the number of UFOs stored (on an installation or anywhere)
byte day
Definition: cp_time.h:37
const char * UFO_GetName(const aircraft_t *ufocraft)
Returns name of the UFO if UFO has been researched.
Definition: cp_ufo.cpp:243
void US_RemoveUFOsExceedingCapacity(installation_t *installation)
Removes ufos which are over the storing capacity.
#define SAVE_UFORECOVERY_UFOID
int numAircraftTemplates
Definition: cp_campaign.h:384
void PR_QueueNext(base_t *base)
Queues the next production in the queue.
Definition: cp_produce.cpp:344
bool Date_LaterThan(const date_t *now, const date_t *compare)
Check whether the given date and time is later than current date.
Definition: cp_time.cpp:239
UFO recovery and storing callback header file.
A base with all it's data.
Definition: cp_base.h:84
const char * Date_GetMonthName(int month)
Returns the short monthame to the given month index.
Definition: cp_time.cpp:317
void UR_InitStartup(void)
Init actions for ufostoring-subsystem.
components_t * COMP_GetComponentsByID(const char *id)
Returns components definition by ID.
#define xmlNode_t
Definition: xml.h:24
bool US_LoadXML(xmlNode_t *p)
Load callback for xml savegames.
struct technology_s * tech
Definition: cp_aircraft.h:162
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
xmlNode_t *IMPORT * XML_GetDate(xmlNode_t *parent, const char *name, int *day, int *sec)
#define SAVE_STOREDUFOSTATUS_NAMESPACE
void US_RemoveStoredUFO(storedUFO_t *ufo)
Removes an UFO from the storage.
XML tag constants for savegame.
#define ERR_DROP
Definition: common.h:211
#define DEBUG_CLIENT
Definition: defines.h:59
void UR_InitCallbacks(void)
#define MAX_VAR
Definition: shared.h:36
#define US_Foreach(var)
void UR_ProcessActive(void)
Function to process active recoveries.
void RS_MarkCollected(technology_t *tech)
Marks a give technology as collected.
base_t * PR_ProductionBase(const production_t *production)
Returns the base pointer the production belongs to.
Definition: cp_produce.cpp:650
installation_t * installation
const cgame_import_t * cgi
linkedList_t * storedUFOs
Definition: cp_campaign.h:314
short year
Definition: cp_time.h:35
Structure for stored UFOs.
bool US_SaveXML(xmlNode_t *p)
Save callback for savegames in XML Format.
const char *IMPORT * Com_GetConstVariable(const char *space, int value)
UFO recovery and storing.
ccs_t ccs
Definition: cp_campaign.cpp:62
stats_t campaignStats
Definition: cp_campaign.h:378
capacities_t ufoCapacity
Definition: cmd.h:86
Engine-side time information in the game.
Definition: common.h:290
byte month
Definition: cp_time.h:36
aircraft_t aircraftTemplates[MAX_AIRCRAFT]
Definition: cp_campaign.h:383
Campaign geoscape time header.
production_t * disassembly
Header for Geoscape management.
static const constListEntry_t saveStoredUFOConstants[]
void PR_QueueDelete(base_t *base, production_queue_t *queue, int index)
Delete the selected entry from the queue.
Definition: cp_produce.cpp:280
char name[MAX_VAR]
int sec
Definition: common.h:292
char cp_messageBuffer[MAX_MESSAGE_TEXT]
Definition: cp_messages.cpp:31
QGL_EXTERN GLuint count
Definition: r_gl.h:99
CGAME_HARD_LINKED_FUNCTIONS linkedList_t * LIST_Add(linkedList_t **listDest, void const *data, size_t length)
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
storedUFO_t * US_GetStoredUFOByIDX(const int idx)
Returns a stored ufo.
void RS_CheckRequirements(void)
Checks if running researches still meet their requirements.
void UR_Shutdown(void)
Closing actions for ufostoring-subsystem.
int ufosStored
Definition: cp_statistics.h:48
#define RECOVERY_DELAY
Header file for aircraft stuff.
storedUFOStatus_t
different statuses for a stored UFO
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)
#define SAVE_UFORECOVERY_STOREDUFOS
#define SAVE_UFORECOVERY_INSTALLATIONIDX
bool US_TransferUFO(storedUFO_t *ufo, installation_t *ufoyard)
Start transferring of a stored UFO.
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 cmdList_t debugStoredUfosCmds[]
storedUFO_t * US_GetClosestStoredUFO(const aircraft_t *ufoTemplate, const base_t *base)
get the closest stored ufo (of a type) from a base
Header file for single player campaign control.
xmlNode_t *IMPORT * XML_AddNode(xmlNode_t *parent, const char *name)
#define SAVE_UFORECOVERY_STATUS
vec3_t pos
Definition: cp_base.h:91
Store capacities in base.
Definition: cp_capacity.h:41
An aircraft with all it's data.
Definition: cp_aircraft.h:114
#define SAVE_UFORECOVERY_CONDITION
const char *IMPORT * Cmd_Argv(int n)
const char *IMPORT * XML_GetString(xmlNode_t *parent, const char *name)
xmlNode_t *IMPORT * XML_GetNode(xmlNode_t *parent, const char *name)
struct components_s * comp
double GetDistanceOnGlobe(const vec2_t pos1, const vec2_t pos2)
Calculate distance on the geoscape.
Definition: mathlib.cpp:171
installation_t * INS_GetByIDX(int idx)
Get installation by it's index.