cp_installation.c

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2002-2010 UFO: Alien Invasion.
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 
00019 See the GNU General Public License for more details.
00020 
00021 You should have received a copy of the GNU General Public License
00022 along with this program; if not, write to the Free Software
00023 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     /* default is radar */
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     /* a new installation is not discovered (yet) */
00120     installation->alienInterest = newInstallationAlienInterest;
00121 
00122     /* intialise hit points */
00123     installation->installationDamage = installation->installationTemplate->maxDamage;
00124 
00125     /* Reset UFO Yard capacities. */
00126     installation->ufoCapacity.max = 0;
00127     installation->ufoCapacity.cur = 0;
00128     /* Reset Batteries */
00129     installation->numBatteries = 0;
00130     /* Reset Radar */
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     /* Disable radar */
00165     RADAR_UpdateInstallationRadarCoverage(installation, 0, 0);
00166     /* Destroy stored UFOs */
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     /* Correct UFO store positions */
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     /* if Radar Tower */
00252     RADAR_UpdateInstallationRadarCoverage(installation, installation->installationTemplate->radarRange, installation->installationTemplate->trackingRange);
00253     /* if SAM Site */
00254     installation->numBatteries = installation->installationTemplate->maxBatteries;
00255     BDEF_InitialiseInstallationSlots(installation);
00256     /* if UFO Yard */
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     /* add commands and cvars */
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     /* get id list body */
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;  /* just in case it's bigger. */
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     /* new entry */
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         /* get the name type */
00473         token = Com_EParse(text, errhead, name);
00474         if (!*text)
00475             break;
00476         if (*token == '}')
00477             break;
00478 
00479         /* check for some standard values */
00480         for (vp = installation_vals; vp->string; vp++)
00481             if (!strcmp(token, vp->string)) {
00482                 /* found a definition */
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         /* other values */
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         /* Radar */
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             /* UFO Yard */
00622             inst->ufoCapacity.max = inst->installationTemplate->maxUFOsStored;
00623         } else {
00624             inst->ufoCapacity.max = 0;
00625         }
00626         inst->ufoCapacity.cur = 0;
00627 
00628         /* read battery slots */
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 

Generated by  doxygen 1.6.2