00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "../cl_shared.h"
00028 #include "../../shared/parse.h"
00029 #include "cp_campaign.h"
00030 #include "cp_mapfightequip.h"
00031 #include "cp_aircraft.h"
00032 #include "cp_missions.h"
00033 #include "cp_map.h"
00034 #include "cp_ufo.h"
00035 #include "cp_installation.h"
00036 #include "cp_installation_callbacks.h"
00037 #include "save/save_installation.h"
00038
00045 installationType_t INS_GetType (const installation_t *installation)
00046 {
00047 if (installation->installationTemplate->maxBatteries > 0)
00048 return INSTALLATION_DEFENCE;
00049 else if (installation->installationTemplate->maxUFOsStored > 0)
00050 return INSTALLATION_UFOYARD;
00051
00052
00053 return INSTALLATION_RADAR;
00054 }
00055
00061 installation_t* INS_GetInstallationByIDX (int instIdx)
00062 {
00063 if (instIdx < 0 || instIdx >= MAX_INSTALLATIONS)
00064 return NULL;
00065
00066 return &ccs.installations[instIdx];
00067 }
00068
00074 installation_t* INS_GetFoundedInstallationByIDX (int instIdx)
00075 {
00076 installation_t *installation = INS_GetInstallationByIDX(instIdx);
00077
00078 if (installation && installation->founded)
00079 return installation;
00080
00081 return NULL;
00082 }
00083
00089 installationTemplate_t* INS_GetInstallationTemplateFromInstallationID (const char *id)
00090 {
00091 int idx;
00092
00093 for (idx = 0; idx < ccs.numInstallationTemplates; idx++)
00094 if (!strcmp(ccs.installationTemplates[idx].id, id))
00095 return &ccs.installationTemplates[idx];
00096
00097 return NULL;
00098 }
00099
00107 void INS_SetUpInstallation (installation_t* installation, installationTemplate_t *installationTemplate, vec2_t pos)
00108 {
00109 const int newInstallationAlienInterest = 1.0f;
00110
00111 Vector2Copy(pos, installation->pos);
00112
00113 installation->idx = INS_GetInstallationIDX(installation);
00114 installation->founded = qtrue;
00115 installation->installationStatus = INSTALLATION_UNDER_CONSTRUCTION;
00116 installation->installationTemplate = installationTemplate;
00117 installation->buildStart = ccs.date.day;
00118
00119
00120 installation->alienInterest = newInstallationAlienInterest;
00121
00122
00123 installation->installationDamage = installation->installationTemplate->maxDamage;
00124
00125
00126 installation->ufoCapacity.max = 0;
00127 installation->ufoCapacity.cur = 0;
00128
00129 installation->numBatteries = 0;
00130
00131 RADAR_Initialise(&(installation->radar), 0.0f, 0.0f, 0.0f, qfalse);
00132
00133 Com_DPrintf(DEBUG_CLIENT, "INS_SetUpInstallation: Installation %s (idx: %i), type: %s has been set up. Will be finished in %i day(s).\n", installation->name, installation->idx, installation->installationTemplate->id, installation->installationTemplate->buildTime);
00134 }
00135
00141 installation_t *INS_GetFirstUnfoundedInstallation (void)
00142 {
00143 const int maxInstallations = B_GetInstallationLimit();
00144
00145 if (ccs.numInstallations >= maxInstallations)
00146 return NULL;
00147
00148 return INS_GetInstallationByIDX(ccs.numInstallations);
00149 }
00150
00155 void INS_DestroyInstallation (installation_t *installation)
00156 {
00157 storedUFO_t *ufo = NULL;
00158
00159 if (!installation)
00160 return;
00161 if (!installation->founded)
00162 return;
00163
00164
00165 RADAR_UpdateInstallationRadarCoverage(installation, 0, 0);
00166
00167 if (installation->ufoCapacity.max > 0) {
00168 installation->ufoCapacity.max = 0;
00169 US_RemoveUFOsExceedingCapacity(installation);
00170 }
00171
00172 CP_MissionNotifyInstallationDestroyed(installation);
00173
00174 Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Installation %s was destroyed."), installation->name);
00175 MSO_CheckAddNewMessage(NT_INSTALLATION_DESTROY, _("Installation destroyed"), cp_messageBuffer, qfalse, MSG_CONSTRUCTION, NULL);
00176
00177 REMOVE_ELEM_ADJUST_IDX(ccs.installations, installation->idx, ccs.numInstallations);
00178
00179 while ((ufo = US_GetNext(ufo)) != NULL) {
00180 if (ufo->installation >= installation)
00181 ufo->installation--;
00182 }
00183 Cvar_Set("mn_installation_count", va("%i", ccs.numInstallations));
00184 }
00185
00189 installation_t *INS_GetCurrentSelectedInstallation (void)
00190 {
00191 int i;
00192
00193 for (i = 0; i < MAX_INSTALLATIONS; i++) {
00194 installation_t *ins = INS_GetInstallationByIDX(i);
00195 if (ins->selected)
00196 return ins;
00197 }
00198
00199 return NULL;
00200 }
00201
00207 void INS_SetCurrentSelectedInstallation (const installation_t *installation)
00208 {
00209 int i;
00210
00211 for (i = 0; i < MAX_INSTALLATIONS; i++) {
00212 installation_t *ins = INS_GetInstallationByIDX(i);
00213 if (ins == installation) {
00214 ins->selected = qtrue;
00215 if (!ins->founded)
00216 Com_Error(ERR_DROP, "The installation you are trying to select is not founded yet");
00217 } else
00218 ins->selected = qfalse;
00219 }
00220
00221 if (installation) {
00222 B_SetCurrentSelectedBase(NULL);
00223 Cvar_Set("mn_installation_title", installation->name);
00224 Cvar_Set("mn_installation_type", installation->installationTemplate->id);
00225 } else {
00226 Cvar_Set("mn_installation_title", "");
00227 Cvar_Set("mn_installation_type", "");
00228 }
00229 }
00230
00237 static void INS_FinishInstallation (installation_t *installation)
00238 {
00239 if (!installation)
00240 Com_Error(ERR_DROP, "INS_FinishInstallation: No Installation.\n");
00241 if (!installation->installationTemplate)
00242 Com_Error(ERR_DROP, "INS_FinishInstallation: No Installation template.\n");
00243 if (!installation->founded)
00244 Com_Error(ERR_DROP, "INS_FinishInstallation: Finish a not founded Installation?\n");
00245 if (installation->installationStatus != INSTALLATION_UNDER_CONSTRUCTION) {
00246 Com_DPrintf(DEBUG_CLIENT, "INS_FinishInstallation: Installation is not being built.\n");
00247 return;
00248 }
00249
00250 installation->installationStatus = INSTALLATION_WORKING;
00251
00252 RADAR_UpdateInstallationRadarCoverage(installation, installation->installationTemplate->radarRange, installation->installationTemplate->trackingRange);
00253
00254 installation->numBatteries = installation->installationTemplate->maxBatteries;
00255 BDEF_InitialiseInstallationSlots(installation);
00256
00257 installation->ufoCapacity.max = installation->installationTemplate->maxUFOsStored;
00258 }
00259
00260 #ifdef DEBUG
00261
00268 static void INS_InstallationList_f (void)
00269 {
00270 int i;
00271
00272 for (i = 0; i < ccs.numInstallations; i++) {
00273 const installation_t *installation = INS_GetInstallationByIDX(i);
00274
00275 if (!installation->founded) {
00276 Com_Printf("Installation idx %i not founded\n\n", i);
00277 continue;
00278 }
00279
00280 Com_Printf("Installation idx %i\n", installation->idx);
00281 Com_Printf("Installation name %s\n", installation->name);
00282 Com_Printf("Installation founded %i\n", installation->founded);
00283 Com_Printf("Installation pos %.02f:%.02f\n", installation->pos[0], installation->pos[1]);
00284 Com_Printf("Installation Alien interest %f\n", installation->alienInterest);
00285
00286 Com_Printf("\nInstallation sensorWidth %i\n", installation->radar.range);
00287 Com_Printf("\nInstallation trackingWidth %i\n", installation->radar.trackingRange);
00288 Com_Printf("Installation numSensoredAircraft %i\n\n", installation->radar.numUFOs);
00289
00290 Com_Printf("\nInstallation numBatteries %i\n", installation->numBatteries);
00293 Com_Printf("\nInstallation stored UFOs %i/%i\n", installation->ufoCapacity.cur, installation->ufoCapacity.max);
00296 Com_Printf("\n\n");
00297 }
00298 }
00299
00303 static void INS_ConstructionFinished_f (void)
00304 {
00305 int i;
00306 int idx = -1;
00307
00308 if (Cmd_Argc() == 2) {
00309 idx = atoi(Cmd_Argv(1));
00310 if (idx < 0 || idx >= MAX_INSTALLATIONS) {
00311 Com_Printf("Usage: %s [installationIDX]\nWithout parameter it builds up all.\n", Cmd_Argv(0));
00312 return;
00313 }
00314 }
00315
00316 for (i = 0; i < ccs.numInstallations; i++) {
00317 installation_t *ins;
00318
00319 if (idx >= 0 && i != idx)
00320 continue;
00321
00322 ins = INS_GetInstallationByIDX(i);
00323
00324 if (ins && ins->founded)
00325 INS_FinishInstallation(ins);
00326 }
00327 }
00328 #endif
00329
00335 installation_t *INS_GetFirstUFOYard (qboolean free)
00336 {
00337 int i;
00338
00339 for (i = 0; i < ccs.numInstallations; i++) {
00340 installation_t *installation = INS_GetFoundedInstallationByIDX(i);
00341
00342 if (!installation)
00343 continue;
00344
00345 if (INS_GetType(installation) != INSTALLATION_UFOYARD)
00346 continue;
00347
00348 if (free && installation->ufoCapacity.cur >= installation->ufoCapacity.max)
00349 continue;
00350
00351 return installation;
00352 }
00353
00354 return NULL;
00355 }
00356
00361 void INS_InitStartup (void)
00362 {
00363 int idx;
00364
00365 Com_DPrintf(DEBUG_CLIENT, "Reset installation\n");
00366
00367 for (idx = 0; idx < ccs.numInstallationTemplates; idx++) {
00368 ccs.installationTemplates[idx].id = NULL;
00369 ccs.installationTemplates[idx].name = NULL;
00370 ccs.installationTemplates[idx].cost = 0;
00371 ccs.installationTemplates[idx].radarRange = 0.0f;
00372 ccs.installationTemplates[idx].trackingRange = 0.0f;
00373 ccs.installationTemplates[idx].maxUFOsStored = 0;
00374 ccs.installationTemplates[idx].maxBatteries = 0;
00375 }
00376
00377
00378 #ifdef DEBUG
00379 Cmd_AddCommand("debug_listinstallation", INS_InstallationList_f, "Print installation information to the game console");
00380 Cmd_AddCommand("debug_finishinstallation", INS_ConstructionFinished_f, "Finish construction of a specified or every installation");
00381 #endif
00382 }
00383
00388 void INS_UpdateInstallationData (void)
00389 {
00390 int instIdx;
00391
00392 for (instIdx = 0; instIdx < MAX_INSTALLATIONS; instIdx++) {
00393 installation_t *installation = INS_GetFoundedInstallationByIDX(instIdx);
00394 if (!installation)
00395 continue;
00396
00397 if ((installation->installationStatus == INSTALLATION_UNDER_CONSTRUCTION)
00398 && installation->buildStart
00399 && installation->buildStart + installation->installationTemplate->buildTime <= ccs.date.day) {
00400
00401 INS_FinishInstallation(installation);
00402
00403 Com_sprintf(cp_messageBuffer, lengthof(cp_messageBuffer), _("Construction of installation %s finished."), installation->name);
00404 MSO_CheckAddNewMessage(NT_INSTALLATION_BUILDFINISH, _("Installation finished"), cp_messageBuffer, qfalse, MSG_CONSTRUCTION, NULL);
00405 }
00406 }
00407 }
00408
00409 static const value_t installation_vals[] = {
00410 {"name", V_TRANSLATION_STRING, offsetof(installationTemplate_t, name), 0},
00411 {"description", V_TRANSLATION_STRING, offsetof(installationTemplate_t, description), 0},
00412 {"radar_range", V_INT, offsetof(installationTemplate_t, radarRange), MEMBER_SIZEOF(installationTemplate_t, radarRange)},
00413 {"radar_tracking_range", V_INT, offsetof(installationTemplate_t, trackingRange), MEMBER_SIZEOF(installationTemplate_t, trackingRange)},
00414 {"max_batteries", V_INT, offsetof(installationTemplate_t, maxBatteries), MEMBER_SIZEOF(installationTemplate_t, maxBatteries)},
00415 {"max_ufo_stored", V_INT, offsetof(installationTemplate_t, maxUFOsStored), MEMBER_SIZEOF(installationTemplate_t, maxUFOsStored)},
00416 {"max_damage", V_INT, offsetof(installationTemplate_t, maxDamage), MEMBER_SIZEOF(installationTemplate_t, maxDamage)},
00417 {"model", V_CLIENT_HUNK_STRING, offsetof(installationTemplate_t, model), 0},
00418 {"image", V_CLIENT_HUNK_STRING, offsetof(installationTemplate_t, image), 0},
00419
00420 {NULL, 0, 0, 0}
00421 };
00422
00430 void INS_ParseInstallations (const char *name, const char **text)
00431 {
00432 installationTemplate_t *installation;
00433 const char *errhead = "INS_ParseInstallations: unexpected end of file (names ";
00434 const char *token;
00435 const value_t *vp;
00436 int i;
00437
00438
00439 token = Com_Parse(text);
00440 if (!*text || *token != '{') {
00441 Com_Printf("INS_ParseInstallations: installation \"%s\" without body ignored\n", name);
00442 return;
00443 }
00444
00445 if (!name) {
00446 Com_Printf("INS_ParseInstallations: installation name not specified.\n");
00447 return;
00448 }
00449
00450 if (ccs.numInstallationTemplates >= MAX_INSTALLATION_TEMPLATES) {
00451 Com_Printf("INS_ParseInstallations: too many installation templates\n");
00452 ccs.numInstallationTemplates = MAX_INSTALLATION_TEMPLATES;
00453 return;
00454 }
00455
00456 for (i = 0; i < ccs.numInstallationTemplates; i++) {
00457 if (!strcmp(ccs.installationTemplates[i].name, name)) {
00458 Com_Printf("INS_ParseInstallations: Second installation with same name found (%s) - second ignored\n", name);
00459 return;
00460 }
00461 }
00462
00463
00464 installation = &ccs.installationTemplates[ccs.numInstallationTemplates];
00465 memset(installation, 0, sizeof(*installation));
00466 installation->id = Mem_PoolStrDup(name, cp_campaignPool, 0);
00467
00468 Com_DPrintf(DEBUG_CLIENT, "...found installation %s\n", installation->id);
00469
00470 ccs.numInstallationTemplates++;
00471 do {
00472
00473 token = Com_EParse(text, errhead, name);
00474 if (!*text)
00475 break;
00476 if (*token == '}')
00477 break;
00478
00479
00480 for (vp = installation_vals; vp->string; vp++)
00481 if (!strcmp(token, vp->string)) {
00482
00483 token = Com_EParse(text, errhead, name);
00484 if (!*text)
00485 return;
00486
00487 switch (vp->type) {
00488 case V_TRANSLATION_STRING:
00489 if (token[0] == '_')
00490 token++;
00491 case V_CLIENT_HUNK_STRING:
00492 Mem_PoolStrDupTo(token, (char**) ((char*)installation + (int)vp->ofs), cp_campaignPool, 0);
00493 break;
00494 default:
00495 if (Com_EParseValue(installation, token, vp->type, vp->ofs, vp->size) == -1)
00496 Com_Printf("INS_ParseInstallations: Wrong size for value %s\n", vp->string);
00497 break;
00498 }
00499 break;
00500 }
00501
00502
00503 if (!vp->string) {
00504 if (!strcmp(token, "cost")) {
00505 char cvarname[MAX_VAR] = "mn_installation_";
00506
00507 Q_strcat(cvarname, installation->id, MAX_VAR);
00508 Q_strcat(cvarname, "_cost", MAX_VAR);
00509
00510 token = Com_EParse(text, errhead, name);
00511 if (!*text)
00512 return;
00513 installation->cost = atoi(token);
00514
00515 Cvar_Set(cvarname, va(_("%d c"), atoi(token)));
00516 } else if (!strcmp(token, "buildtime")) {
00517 char cvarname[MAX_VAR];
00518
00519
00520 token = Com_EParse(text, errhead, name);
00521 if (!*text)
00522 return;
00523 installation->buildTime = atoi(token);
00524
00525 Com_sprintf(cvarname, sizeof(cvarname), "mn_installation_%s_buildtime", installation->id);
00526 Cvar_Set(cvarname, va(ngettext("%d day", "%d days", atoi(token)), atoi(token)));
00527 }
00528 }
00529 } while (*text);
00530 }
00531
00538 qboolean INS_SaveXML (mxml_node_t *p)
00539 {
00540 int i;
00541 mxml_node_t *n;
00542 n = mxml_AddNode(p, SAVE_INSTALLATION_INSTALLATIONS);
00543
00544 Com_RegisterConstList(saveInstallationConstants);
00545 for (i = 0; i < ccs.numInstallations; i++) {
00546 const installation_t *inst = INS_GetInstallationByIDX(i);
00547 mxml_node_t *s, *ss;
00548
00549 if (!inst->founded)
00550 continue;
00551
00552 s = mxml_AddNode(n, SAVE_INSTALLATION_INSTALLATION);
00553 mxml_AddString(s, SAVE_INSTALLATION_TEMPLATEID, inst->installationTemplate->id);
00554 mxml_AddString(s, SAVE_INSTALLATION_NAME, inst->name);
00555 mxml_AddPos3(s, SAVE_INSTALLATION_POS, inst->pos);
00556 mxml_AddString(s, SAVE_INSTALLATION_STATUS, Com_GetConstVariable(SAVE_INSTALLATIONSTATUS_NAMESPACE, inst->installationStatus));
00557 mxml_AddInt(s, SAVE_INSTALLATION_DAMAGE, inst->installationDamage);
00558 mxml_AddFloat(s, SAVE_INSTALLATION_ALIENINTEREST, inst->alienInterest);
00559 mxml_AddInt(s, SAVE_INSTALLATION_BUILDSTART, inst->buildStart);
00560
00561 ss = mxml_AddNode(s, SAVE_INSTALLATION_BATTERIES);
00562 mxml_AddIntValue(ss, SAVE_INSTALLATION_NUM, inst->numBatteries);
00563 B_SaveBaseSlotsXML(inst->batteries, inst->numBatteries, ss);
00564 }
00565 Com_UnregisterConstList(saveInstallationConstants);
00566 return qtrue;
00567 }
00568
00576 qboolean INS_LoadXML (mxml_node_t *p)
00577 {
00578 mxml_node_t *s;
00579 mxml_node_t *n = mxml_GetNode(p, SAVE_INSTALLATION_INSTALLATIONS);
00580 int i;
00581 qboolean success = qtrue;
00582
00583 if (!n)
00584 return qfalse;
00585
00586 Com_RegisterConstList(saveInstallationConstants);
00587 for (i = 0, s = mxml_GetNode(n, SAVE_INSTALLATION_INSTALLATION); s && i < MAX_INSTALLATIONS; s = mxml_GetNextNode(s,n, SAVE_INSTALLATION_INSTALLATION), i++) {
00588 mxml_node_t *ss;
00589 installation_t *inst = INS_GetInstallationByIDX(i);
00590 const char *instID = mxml_GetString(s, SAVE_INSTALLATION_TEMPLATEID);
00591 const char *instStat = mxml_GetString(s, SAVE_INSTALLATION_STATUS);
00592
00593 inst->idx = INS_GetInstallationIDX(inst);
00594 inst->founded = qtrue;
00595
00596 inst->installationTemplate = INS_GetInstallationTemplateFromInstallationID(instID);
00597 if (!inst->installationTemplate) {
00598 Com_Printf("Could not find installation template '%s'\n", instID);
00599 success = qfalse;
00600 break;
00601 }
00602
00603 if (!Com_GetConstIntFromNamespace(SAVE_INSTALLATIONSTATUS_NAMESPACE, instStat, (int*) &inst->installationStatus)) {
00604 Com_Printf("Invaild installation status '%s'\n", instStat);
00605 success = qfalse;
00606 break;
00607 }
00608
00609 Q_strncpyz(inst->name, mxml_GetString(s, SAVE_INSTALLATION_NAME), sizeof(inst->name));
00610 mxml_GetPos3(s, SAVE_INSTALLATION_POS, inst->pos);
00611
00612 inst->installationDamage = mxml_GetInt(s, SAVE_INSTALLATION_DAMAGE, 0);
00613 inst->alienInterest = mxml_GetFloat(s, SAVE_INSTALLATION_ALIENINTEREST, 0.0);
00614 inst->buildStart = mxml_GetInt(s, SAVE_INSTALLATION_BUILDSTART, 0);
00615
00616
00617 RADAR_InitialiseUFOs(&inst->radar);
00618 RADAR_Initialise(&(inst->radar), 0.0f, 0.0f, 1.0f, qtrue);
00619 if (inst->installationStatus == INSTALLATION_WORKING) {
00620 RADAR_UpdateInstallationRadarCoverage(inst, inst->installationTemplate->radarRange, inst->installationTemplate->trackingRange);
00621
00622 inst->ufoCapacity.max = inst->installationTemplate->maxUFOsStored;
00623 } else {
00624 inst->ufoCapacity.max = 0;
00625 }
00626 inst->ufoCapacity.cur = 0;
00627
00628
00629 BDEF_InitialiseInstallationSlots(inst);
00630 ss = mxml_GetNode(s, SAVE_INSTALLATION_BATTERIES);
00631 if (!ss) {
00632 Com_Printf("INS_LoadXML: Batteries not defined!\n");
00633 success = qfalse;
00634 break;
00635 }
00636 inst->numBatteries = mxml_GetInt(ss, SAVE_INSTALLATION_NUM, 0);
00637 if (inst->numBatteries > inst->installationTemplate->maxBatteries) {
00638 Com_Printf("Installation has more batteries than possible, using upper bound\n");
00639 inst->numBatteries = inst->installationTemplate->maxBatteries;
00640 }
00641 B_LoadBaseSlotsXML(inst->batteries, inst->numBatteries, ss);
00642
00643 ccs.numInstallations++;
00644 }
00645 Com_UnregisterConstList(saveInstallationConstants);
00646 Cvar_Set("mn_installation_count", va("%i", ccs.numInstallations));
00647
00648 return success;
00649 }
00650