UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cp_installation.cpp
Go to the documentation of this file.
1 
7 /*
8 Copyright (C) 2002-2020 UFO: Alien Invasion.
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 See the GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25 */
26 
27 #include "../../cl_shared.h"
28 #include "../../../shared/parse.h"
29 #include "cp_campaign.h"
30 #include "cp_mapfightequip.h"
31 #include "cp_aircraft.h"
32 #include "cp_missions.h"
33 #include "cp_installation.h"
34 #include "save/save_installation.h"
35 
39 int INS_GetCount (void)
40 {
41  return cgi->LIST_Count(ccs.installations);
42 }
43 
45 {
46  if (Q_streq(type, "samsite"))
47  return INSTALLATION_DEFENCE;
48  else if (Q_streq(type, "ufoyard"))
49  return INSTALLATION_UFOYARD;
50  else if (Q_streq(type, "radartower"))
51  return INSTALLATION_RADAR;
52  else if (Q_streq(type, "orbit"))
53  return INSTALLATION_ORBIT;
54 
55  cgi->Com_Printf("unknown type given '%s'\n", type);
56  return INSTALLATION_RADAR;
57 }
58 
64 {
65  INS_Foreach(installation) {
66  if (status == INSTALLATION_NOT_USED || installation->installationStatus == status)
67  return true;
68  }
69 
70  return false;
71 }
72 
79 {
80  INS_ForeachOfType(installation, type) {
81  if (status == INSTALLATION_NOT_USED || installation->installationStatus == status)
82  return true;
83  }
84 
85  return false;
86 }
87 
94 {
95  INS_Foreach(installation) {
96  if (installation->idx == idx)
97  return installation;
98  }
99 
100  return nullptr;
101 }
102 
109 {
110  int idx;
111 
112  for (idx = 0; idx < ccs.numInstallationTemplates; idx++) {
114  if (Q_streq(t->id, id))
115  return t;
116  }
117 
118  return nullptr;
119 }
120 
127 {
128  int idx;
129 
130  for (idx = 0; idx < ccs.numInstallationTemplates; idx++) {
132  if (t->type == type)
133  return t;
134  }
135 
136  return nullptr;
137 }
138 
145 installation_t* INS_Build (const installationTemplate_t* installationTemplate, const vec2_t pos, const char* name)
146 {
147  installation_t installation;
148  const int newInstallationAlienInterest = 1.0f;
149 
150  OBJZERO(installation);
151 
152  Vector2Copy(pos, installation.pos);
153  Q_strncpyz(installation.name, name, sizeof(installation.name));
154  installation.idx = ccs.campaignStats.installationsBuilt;
156  installation.installationTemplate = installationTemplate;
157  installation.buildStart = ccs.date.day;
158 
159  /* a new installation is not discovered (yet) */
160  installation.alienInterest = newInstallationAlienInterest;
161 
162  /* intialise hit points */
163  installation.installationDamage = installation.installationTemplate->maxDamage;
164 
165  /* Reset Radar */
166  RADAR_Initialise(&(installation.radar), 0.0f, 0.0f, 0.0f, false);
167 
169  return &LIST_Add(&ccs.installations, installation);
170 }
171 
177 {
178  if (!installation)
179  return;
180  /* Disable radar */
181  RADAR_UpdateInstallationRadarCoverage(installation, 0, 0);
182  /* Destroy stored UFOs */
183  if (installation->ufoCapacity.max > 0) {
184  installation->ufoCapacity.max = 0;
185  US_RemoveUFOsExceedingCapacity(installation);
186  }
188 
189  Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Installation %s was destroyed."), installation->name);
191 
192  cgi->LIST_Remove(&ccs.installations, installation);
193  cgi->Cvar_Set("mn_installation_count", "%i", INS_GetCount());
194 }
195 
200 {
201  INS_Foreach(installation) {
202  if (installation->selected)
203  return installation;
204  }
205 
206  return nullptr;
207 }
208 
215 {
216  INS_Foreach(ins)
217  ins->selected = (ins == installation);
218 
219  if (installation) {
220  cgi->Cvar_Set("mn_installation_title", "%s", installation->name);
221  cgi->Cvar_Set("mn_installation_type", "%s", installation->installationTemplate->id);
222  } else {
223  cgi->Cvar_Set("mn_installation_title", "");
224  cgi->Cvar_Set("mn_installation_type", "");
225  }
226 }
227 
234 static void INS_FinishInstallation (installation_t* installation)
235 {
236  if (!installation)
237  cgi->Com_Error(ERR_DROP, "INS_FinishInstallation: No Installation.\n");
238  if (!installation->installationTemplate)
239  cgi->Com_Error(ERR_DROP, "INS_FinishInstallation: No Installation template.\n");
241  cgi->Com_DPrintf(DEBUG_CLIENT, "INS_FinishInstallation: Installation is not being built.\n");
242  return;
243  }
244 
246  /* if Radar Tower */
248  /* if SAM Site */
249  installation->numBatteries = installation->installationTemplate->maxBatteries;
250  BDEF_InitialiseInstallationSlots(installation);
251  /* if UFO Yard */
252  installation->ufoCapacity.max = installation->installationTemplate->maxUFOsStored;
253 }
254 
255 #ifdef DEBUG
256 
262 static void INS_InstallationList_f (void)
263 {
264  INS_Foreach(installation) {
265  cgi->Com_Printf("Installation idx %i\n", installation->idx);
266  cgi->Com_Printf("Installation name %s\n", installation->name);
267  cgi->Com_Printf("Installation pos %.02f:%.02f\n", installation->pos[0], installation->pos[1]);
268  cgi->Com_Printf("Installation Alien interest %f\n", installation->alienInterest);
269 
270  cgi->Com_Printf("\nInstallation sensorWidth %i\n", installation->radar.range);
271  cgi->Com_Printf("\nInstallation trackingWidth %i\n", installation->radar.trackingRange);
272  cgi->Com_Printf("Installation numSensoredAircraft %i\n\n", installation->radar.numUFOs);
273 
274  cgi->Com_Printf("\nInstallation numBatteries %i\n", installation->numBatteries);
277  cgi->Com_Printf("\nInstallation stored UFOs %i/%i\n", installation->ufoCapacity.cur, installation->ufoCapacity.max);
280  cgi->Com_Printf("\n\n");
281  }
282 }
283 
287 static void INS_ConstructionFinished_f (void)
288 {
289  int idx = -1;
290 
291  if (cgi->Cmd_Argc() == 2) {
292  idx = atoi(cgi->Cmd_Argv(1));
293  if (idx < 0) {
294  cgi->Com_Printf("Usage: %s [installationIDX]\nWithout parameter it builds up all.\n", cgi->Cmd_Argv(0));
295  return;
296  }
297  }
298 
299  INS_Foreach(ins) {
300  if (idx >= 0 && ins->idx != idx)
301  continue;
302 
304  }
305 }
306 #endif
307 
314 {
315  INS_ForeachOfType(installation, INSTALLATION_UFOYARD) {
316  if (free && installation->ufoCapacity.cur >= installation->ufoCapacity.max)
317  continue;
318 
319  return installation;
320  }
321 
322  return nullptr;
323 }
324 
326 #ifdef DEBUG
327  {"debug_listinstallation", INS_InstallationList_f, "Print installation information to the game console"},
328  {"debug_finishinstallation", INS_ConstructionFinished_f, "Finish construction of a specified or every installation"},
329 #endif
330  {nullptr, nullptr, nullptr}
331 };
335 void INS_InitStartup (void)
336 {
337  cgi->Cmd_TableAddList(debugInstallationCmds);
338 }
339 
343 void INS_Shutdown (void)
344 {
345  cgi->LIST_Delete(&ccs.installations);
346  cgi->Cmd_TableRemoveList(debugInstallationCmds);
347 }
348 
354 {
355  INS_Foreach(installation) {
356  if (installation->installationStatus == INSTALLATION_UNDER_CONSTRUCTION
357  && installation->buildStart
358  && installation->buildStart + installation->installationTemplate->buildTime <= ccs.date.day) {
359  INS_FinishInstallation(installation);
360 
361  Com_sprintf(cp_messageBuffer, lengthof(cp_messageBuffer), _("Construction of installation %s finished."), installation->name);
363  }
364  }
365 }
366 
367 static const value_t installation_vals[] = {
368  {"name", V_TRANSLATION_STRING, offsetof(installationTemplate_t, name), 0},
369  {"description", V_TRANSLATION_STRING, offsetof(installationTemplate_t, description), 0},
370  {"radar_range", V_INT, offsetof(installationTemplate_t, radarRange), MEMBER_SIZEOF(installationTemplate_t, radarRange)},
371  {"radar_tracking_range", V_INT, offsetof(installationTemplate_t, trackingRange), MEMBER_SIZEOF(installationTemplate_t, trackingRange)},
372  {"max_batteries", V_INT, offsetof(installationTemplate_t, maxBatteries), MEMBER_SIZEOF(installationTemplate_t, maxBatteries)},
373  {"max_ufo_stored", V_INT, offsetof(installationTemplate_t, maxUFOsStored), MEMBER_SIZEOF(installationTemplate_t, maxUFOsStored)},
374  {"max_damage", V_INT, offsetof(installationTemplate_t, maxDamage), MEMBER_SIZEOF(installationTemplate_t, maxDamage)},
375  {"cost", V_INT, offsetof(installationTemplate_t, cost), MEMBER_SIZEOF(installationTemplate_t, cost)},
376  {"buildtime", V_INT, offsetof(installationTemplate_t, buildTime), MEMBER_SIZEOF(installationTemplate_t, buildTime)},
377  {"once", V_BOOL, offsetof(installationTemplate_t, once), MEMBER_SIZEOF(installationTemplate_t, once)},
378  {"model", V_HUNK_STRING, offsetof(installationTemplate_t, model), 0},
379  {"image", V_HUNK_STRING, offsetof(installationTemplate_t, image), 0},
380 
381  {nullptr, V_NULL, 0, 0}
382 };
383 
391 void INS_ParseInstallations (const char* name, const char** text)
392 {
393  /* get id list body */
394  const char* token = Com_Parse(text);
395  if (!*text || *token != '{') {
396  cgi->Com_Printf("INS_ParseInstallations: installation \"%s\" without body ignored\n", name);
397  return;
398  }
399 
400  if (!name) {
401  cgi->Com_Printf("INS_ParseInstallations: installation name not specified.\n");
402  return;
403  }
404 
406  cgi->Com_Printf("INS_ParseInstallations: too many installation templates\n");
407  ccs.numInstallationTemplates = MAX_INSTALLATION_TEMPLATES; /* just in case it's bigger. */
408  return;
409  }
410 
411  for (int i = 0; i < ccs.numInstallationTemplates; i++) {
412  if (Q_streq(ccs.installationTemplates[i].name, name)) {
413  cgi->Com_Printf("INS_ParseInstallations: Second installation with same name found (%s) - second ignored\n", name);
414  return;
415  }
416  }
417 
418  /* new entry */
420  OBJZERO(*installation);
421  installation->id = cgi->PoolStrDup(name, cp_campaignPool, 0);
422  installation->type = INSTALLATION_RADAR;
423 
424  cgi->Com_DPrintf(DEBUG_CLIENT, "...found installation %s\n", installation->id);
425 
427  const char* errhead = "INS_ParseInstallations: unexpected end of file (names ";
428  do {
429  /* get the name type */
430  token = cgi->Com_EParse(text, errhead, name);
431  if (!*text)
432  break;
433  if (*token == '}')
434  break;
435 
436  /* check for some standard values */
437  if (!cgi->Com_ParseBlockToken(name, text, installation, installation_vals, cp_campaignPool, token)) {
438  /* other values */
439  if (Q_streq(token, "type")) {
440  token = cgi->Com_EParse(text, errhead, name);
441  if (!*text)
442  return;
443 
444  installation->type = INS_GetType(token);
445  }
446  }
447  } while (*text);
448 }
449 
451 {
452  for (int i = 0; i < ccs.numInstallationTemplates; i++) {
454  technology_t* techLink = RS_GetTechByProvided(ins->id);
455  if (techLink)
456  ins->tech = techLink;
457  }
458 }
459 
467 {
469  cgi->Com_RegisterConstList(saveInstallationConstants);
470  INS_Foreach(inst) {
471  xmlNode_t* s, *ss;
472 
474  cgi->XML_AddString(s, SAVE_INSTALLATION_TEMPLATEID, inst->installationTemplate->id);
475  cgi->XML_AddInt(s, SAVE_INSTALLATION_IDX, inst->idx);
476  cgi->XML_AddString(s, SAVE_INSTALLATION_NAME, inst->name);
477  cgi->XML_AddPos3(s, SAVE_INSTALLATION_POS, inst->pos);
478  cgi->XML_AddString(s, SAVE_INSTALLATION_STATUS, cgi->Com_GetConstVariable(SAVE_INSTALLATIONSTATUS_NAMESPACE, inst->installationStatus));
479  cgi->XML_AddInt(s, SAVE_INSTALLATION_DAMAGE, inst->installationDamage);
480  cgi->XML_AddFloat(s, SAVE_INSTALLATION_ALIENINTEREST, inst->alienInterest);
481  cgi->XML_AddInt(s, SAVE_INSTALLATION_BUILDSTART, inst->buildStart);
482 
484  cgi->XML_AddIntValue(ss, SAVE_INSTALLATION_NUM, inst->numBatteries);
485  B_SaveBaseSlotsXML(inst->batteries, inst->numBatteries, ss);
486  }
487  cgi->Com_UnregisterConstList(saveInstallationConstants);
488  return true;
489 }
490 
499 {
501  xmlNode_t* s;
502  bool success = true;
503 
504  if (!n)
505  return false;
506 
507  cgi->Com_RegisterConstList(saveInstallationConstants);
509  xmlNode_t* ss;
510  installation_t inst;
511  const char* instID = cgi->XML_GetString(s, SAVE_INSTALLATION_TEMPLATEID);
512  const char* instStat = cgi->XML_GetString(s, SAVE_INSTALLATION_STATUS);
513 
514  OBJZERO(inst);
515  inst.idx = cgi->XML_GetInt(s, SAVE_INSTALLATION_IDX, -1);
516  if (inst.idx < 0) {
517  cgi->Com_Printf("Invalid installation index %i\n", inst.idx);
518  success = false;
519  break;
520  }
521  const installationType_t type = INS_GetType(instID);
523  if (!inst.installationTemplate) {
524  cgi->Com_Printf("Could not find installation template '%s'\n", instID);
525  success = false;
526  break;
527  }
528 
529  if (!cgi->Com_GetConstIntFromNamespace(SAVE_INSTALLATIONSTATUS_NAMESPACE, instStat, (int*) &inst.installationStatus)) {
530  cgi->Com_Printf("Invalid installation status '%s'\n", instStat);
531  success = false;
532  break;
533  }
534 
535  Q_strncpyz(inst.name, cgi->XML_GetString(s, SAVE_INSTALLATION_NAME), sizeof(inst.name));
537 
538  inst.installationDamage = cgi->XML_GetInt(s, SAVE_INSTALLATION_DAMAGE, 0);
539  inst.alienInterest = cgi->XML_GetFloat(s, SAVE_INSTALLATION_ALIENINTEREST, 0.0);
540  inst.buildStart = cgi->XML_GetInt(s, SAVE_INSTALLATION_BUILDSTART, 0);
541 
542  /* Radar */
544  RADAR_Initialise(&(inst.radar), 0.0f, 0.0f, 1.0f, true);
547  /* UFO Yard */
549  } else {
550  inst.ufoCapacity.max = 0;
551  }
552  inst.ufoCapacity.cur = 0;
553 
554  /* read battery slots */
556  if (!ss) {
557  cgi->Com_Printf("INS_LoadXML: Batteries not defined!\n");
558  success = false;
559  break;
560  }
561  inst.numBatteries = cgi->XML_GetInt(ss, SAVE_INSTALLATION_NUM, 0);
563  cgi->Com_Printf("Installation has more batteries than possible, using upper bound\n");
565  }
566 
567  installation_t& instp = LIST_Add(&ccs.installations, inst);
569  B_LoadBaseSlotsXML(instp.batteries, instp.numBatteries, ss);
570  }
571  cgi->Com_UnregisterConstList(saveInstallationConstants);
572  cgi->Cvar_Set("mn_installation_count", "%i", INS_GetCount());
573 
574  return success;
575 }
#define SAVE_INSTALLATION_NAME
installationType_t INS_GetType(const char *type)
void INS_LinkTechnologies(void)
void RADAR_Initialise(radar_t *radar, float range, float trackingRange, float level, bool updateSourceRadarMap)
Set radar range to new value.
Definition: cp_radar.cpp:239
installationStatus_t installationStatus
void INS_InitStartup(void)
Resets console commands.
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...
const installationTemplate_t * INS_GetInstallationTemplateByType(installationType_t type)
Returns the installation Template for a given installation type.
void BDEF_InitialiseInstallationSlots(installation_t *installation)
Initialise all values of installation slot defence.
A installation with all it's data.
QGL_EXTERN GLint GLenum type
Definition: r_gl.h:94
installationStatus_t
Possible installation states.
bool INS_HasType(installationType_t type, installationStatus_t status)
Checks whether the given installation type is available.
#define _(String)
Definition: cl_shared.h:43
void INS_UpdateInstallationData(void)
Check if some installation are build.
#define SAVE_INSTALLATION_BATTERIES
#define SAVE_INSTALLATION_DAMAGE
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
int numInstallationTemplates
Definition: cp_campaign.h:348
Header for installation management related stuff.
installationTemplate_t installationTemplates[MAX_INSTALLATION_TEMPLATES]
Definition: cp_campaign.h:347
int day
Definition: common.h:291
date_t date
Definition: cp_campaign.h:245
#define SAVE_INSTALLATION_INSTALLATIONS
xmlNode_t *IMPORT * XML_GetPos3(xmlNode_t *parent, const char *name, vec3_t pos)
void INS_SetCurrentSelectedInstallation(const installation_t *installation)
Sets the currently selected installation.
#define SAVE_INSTALLATION_NUM
bool INS_SaveXML(xmlNode_t *p)
Save callback for savegames in xml.
#define INS_ForeachOfType(var, installationType)
bool INS_HasAny(installationStatus_t status)
Checks whether any installation is available.
void RADAR_UpdateInstallationRadarCoverage(installation_t *installation, const float radarRange, const float trackingRadarRange)
Update radar coverage when building/destroying new radar.
Definition: cp_radar.cpp:311
void US_RemoveUFOsExceedingCapacity(installation_t *installation)
Removes ufos which are over the storing capacity.
int INS_GetCount(void)
Get number of installations.
memPool_t * cp_campaignPool
Definition: cp_campaign.cpp:61
#define INS_Foreach(var)
#define xmlNode_t
Definition: xml.h:24
void RADAR_InitialiseUFOs(radar_t *radar)
Reset UFO sensored on radar.
Definition: cp_radar.cpp:265
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
cvar_t *IMPORT * Cvar_Set(const char *varName, const char *value,...) __attribute__((format(__printf__
void INS_Shutdown(void)
Closing operations for installations subsystem.
#define ERR_DROP
Definition: common.h:211
installationType_t
#define DEBUG_CLIENT
Definition: defines.h:59
#define OBJZERO(obj)
Definition: shared.h:178
void INS_ParseInstallations(const char *name, const char **text)
Copies an entry from the installation description file into the list of installation templates...
Campaign missions headers.
const cgame_import_t * cgi
struct radar_s radar
const char *IMPORT * Com_GetConstVariable(const char *space, int value)
This is the technology parsed from research.ufo.
Definition: cp_research.h:137
static const constListEntry_t saveInstallationConstants[]
struct technology_s * tech
ccs_t ccs
Definition: cp_campaign.cpp:62
stats_t campaignStats
Definition: cp_campaign.h:378
capacities_t ufoCapacity
Definition: cmd.h:86
void B_SaveBaseSlotsXML(const baseWeapon_t *weapons, const int numWeapons, xmlNode_t *node)
Saves the missile and laser slots of a base or sam site.
Definition: cp_base.cpp:2229
#define SAVE_INSTALLATION_INSTALLATION
bool INS_LoadXML(xmlNode_t *p)
Load callback for savegames.
int installationsBuilt
Definition: cp_statistics.h:34
const installationTemplate_t * installationTemplate
#define SAVE_INSTALLATION_STATUS
#define MAX_INSTALLATION_TEMPLATES
char name[MAX_VAR]
installation_t * INS_Build(const installationTemplate_t *installationTemplate, const vec2_t pos, const char *name)
Build a new installation.
#define SAVE_INSTALLATION_IDX
linkedList_t * installations
Definition: cp_campaign.h:351
char cp_messageBuffer[MAX_MESSAGE_TEXT]
Definition: cp_messages.cpp:31
XML tag constants for savegame.
CGAME_HARD_LINKED_FUNCTIONS linkedList_t * LIST_Add(linkedList_t **listDest, void const *data, size_t length)
installationType_t type
#define SAVE_INSTALLATION_TEMPLATEID
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition: parse.cpp:107
static const cmdList_t debugInstallationCmds[]
Definition: scripts.h:49
static const value_t installation_vals[]
Header file for aircraft stuff.
int B_LoadBaseSlotsXML(baseWeapon_t *weapons, int max, xmlNode_t *p)
Loads the missile and laser slots of a base or sam site.
Definition: cp_base.cpp:2348
QGL_EXTERN GLint i
Definition: r_gl.h:113
installation_t * INS_GetFirstUFOYard(bool free)
returns the first installation with (free) ufostoring capacity
Definition: scripts.h:50
xmlNode_t *IMPORT * XML_GetNextNode(xmlNode_t *current, xmlNode_t *parent, const char *name)
Header for slot management related stuff.
void CP_MissionNotifyInstallationDestroyed(const installation_t *installation)
Notify missions that an installation has been destroyed.
#define SAVE_INSTALLATIONSTATUS_NAMESPACE
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
static void INS_FinishInstallation(installation_t *installation)
Finishes an installation.
#define MEMBER_SIZEOF(TYPE, MEMBER)
Definition: scripts.h:34
installation_t * INS_GetCurrentSelectedInstallation(void)
Returns the current selected installation.
#define Vector2Copy(src, dest)
Definition: vector.h:52
vec_t vec2_t[2]
Definition: ufotypes.h:38
Header file for single player campaign control.
Definition: scripts.h:52
xmlNode_t *IMPORT * XML_AddNode(xmlNode_t *parent, const char *name)
#define SAVE_INSTALLATION_ALIENINTEREST
const char *IMPORT * Com_EParse(const char **text, const char *errhead, const char *errinfo)
technology_t * RS_GetTechByProvided(const char *idProvided)
returns a pointer to the item tech (as listed in "provides")
#define lengthof(x)
Definition: shared.h:105
#define Q_streq(a, b)
Definition: shared.h:136
char *IMPORT * PoolStrDup(const char *in, memPool_t *pool, const int tagNum)
#define SAVE_INSTALLATION_POS
const installationTemplate_t * INS_GetInstallationTemplateByID(const char *id)
Returns the installation Template for a given installation ID.
vec2_t pos
Definition: cp_missions.h:104
const char *IMPORT * Cmd_Argv(int n)
const char *IMPORT * XML_GetString(xmlNode_t *parent, const char *name)
void INS_DestroyInstallation(installation_t *installation)
Destroys an installation.
#define SAVE_INSTALLATION_BUILDSTART
xmlNode_t *IMPORT * XML_GetNode(xmlNode_t *parent, const char *name)
baseWeapon_t batteries[MAX_INSTALLATION_BATTERIES]
installation_t * INS_GetByIDX(int idx)
Get installation by it's index.