rendered paste bodyIndex: src/client/campaign/cp_base.h
===================================================================
--- src/client/campaign/cp_base.h (revision 25743)
+++ src/client/campaign/cp_base.h (working copy)
@@ -305,7 +305,6 @@
void B_RemoveAircraftExceedingCapacity(base_t* base, buildingType_t buildingType);
void B_DrawBuilding(base_t* base, building_t* building);
void B_RemoveItemsExceedingCapacity(base_t *base);
-void B_RemoveUFOsExceedingCapacity(base_t *base, const buildingType_t buildingType);
void B_RemoveAntimatterExceedingCapacity(base_t *base);
void B_ManageAntimatter(base_t *base, int amount, qboolean add);
void B_UpdateStorageCap(base_t *base);
Index: src/client/campaign/cp_campaign.h
===================================================================
--- src/client/campaign/cp_campaign.h (revision 25743)
+++ src/client/campaign/cp_campaign.h (working copy)
@@ -4,7 +4,7 @@
*/
/*
-Copyright (C) 2002-2007 UFO: Alien Invasion team.
+Copyright (C) 2002-2009 UFO: Alien Invasion team.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -32,6 +32,7 @@
struct installation_s;
struct employee_s;
struct menuNode_s; /**< @todo remove this once the menuNode_t usage is cleaned up */
+struct storedUFO_s;
#define MAX_ASSEMBLIES 16
#define ANTIMATTER_SIZE 10
@@ -467,6 +468,10 @@
int numComponents;
components_t components[MAX_ASSEMBLIES];
+ /** stored UFOs */
+ storedUFO_t storedUFOs[MAX_STOREDUFOS];
+ int numStoredUFOs;
+
/* Alien Team Definitions. */
int numAliensTD;
Index: src/client/campaign/cp_installation.c
===================================================================
--- src/client/campaign/cp_installation.c (revision 25743)
+++ src/client/campaign/cp_installation.c (working copy)
@@ -151,18 +151,36 @@
*/
void INS_DestroyInstallation (installation_t *installation)
{
+ int i;
+
if (!installation)
return;
if (!installation->founded)
return;
+ /* Disable radar */
RADAR_UpdateInstallationRadarCoverage(installation, 0, 0);
+ /* Destroy stored UFOs */
+ if (installation->ufoCapacity.max) {
+ installation->ufoCapacity.max = 0;
+ US_RemoveUFOsExceedingCapacity(installation);
+ }
+
CP_MissionNotifyInstallationDestroyed(installation);
Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Installation %s was destroyed."), installation->name);
MSO_CheckAddNewMessage(NT_INSTALLATION_DESTROY, _("Installation destroyed"), cp_messageBuffer, qfalse, MSG_CONSTRUCTION, NULL);
REMOVE_ELEM_ADJUST_IDX(ccs.installations, installation->idx, ccs.numInstallations);
+ /* Correct UFO store positions */
+ for (i = 0; i < ccs.numStoredUFOs; i++) {
+ storedUFO_t *ufo = US_GetStoredUFOByIDX(i);
+
+ if (!ufo)
+ continue;
+ if (ufo->installation >= installation)
+ ufo->installation--;
+ }
Cvar_Set("mn_installation_count", va("%i", ccs.numInstallations));
}
@@ -306,7 +324,33 @@
}
#endif
+/**
+ * @brief returns the first installation with (free) ufostoring capacity
+ * @param[in] free On qtrue it gives the first UFO Yard with free space
+ * @return installation_t Pointer to the UFO Yard
+ **/
+installation_t *INS_GetFirstUFOYard (qboolean free)
+{
+ int i;
+ for (i = 0; i < ccs.numInstallations; i++) {
+ installation_t *installation = INS_GetFoundedInstallationByIDX(i);
+
+ if (!installation)
+ continue;
+
+ if (INS_GetType(installation) != INSTALLATION_UFOYARD)
+ continue;
+
+ if (free && installation->ufoCapacity.cur >= installation->ufoCapacity.max)
+ continue;
+
+ return installation;
+ }
+
+ return NULL;
+}
+
/**
* @brief Resets console commands.
* @sa MN_ResetMenus
Index: src/client/campaign/cp_installation.h
===================================================================
--- src/client/campaign/cp_installation.h (revision 25743)
+++ src/client/campaign/cp_installation.h (working copy)
@@ -103,13 +103,15 @@
/* Functions */
installation_t *INS_GetInstallationByIDX(int instIdx);
-installation_t* INS_GetFoundedInstallationByIDX(int installationIdx);
+installation_t *INS_GetFoundedInstallationByIDX(int installationIdx);
installation_t *INS_GetFirstUnfoundedInstallation(void);
-installationTemplate_t* INS_GetInstallationTemplateFromInstallationID(const char *id);
+installationTemplate_t *INS_GetInstallationTemplateFromInstallationID(const char *id);
installationType_t INS_GetType(const installation_t *installation);
+installation_t *INS_GetFirstUFOYard(qboolean free);
+
void INS_SetUpInstallation(installation_t* installation, installationTemplate_t *installationTemplate, vec2_t pos);
installation_t *INS_GetCurrentSelectedInstallation(void);
Index: src/client/campaign/cp_uforecovery.c
===================================================================
--- src/client/campaign/cp_uforecovery.c (revision 25743)
+++ src/client/campaign/cp_uforecovery.c (working copy)
@@ -1,11 +1,12 @@
/**
* @file cp_uforecovery.c
- * @brief UFO recovery
- * @note Functions with UR_*
+ * @brief UFO recovery and storing
+ * @note UFO recovery functions with UR_*
+ * @note UFO storing functions with US_*
*/
/*
-Copyright (C) 2002-2007 UFO: Alien Invasion team.
+Copyright (C) 2002-2009 UFO: Alien Invasion team.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -28,6 +29,7 @@
#include "../menu/m_main.h"
#include "cp_campaign.h"
#include "cp_ufo.h"
+#include "cp_map.h"
#include "cp_uforecovery.h"
#include "cp_uforecovery_callbacks.h"
#include "cp_aircraft.h"
@@ -41,7 +43,7 @@
* @sa CL_EventAddMail_f
* @sa CL_NewEventMail
*/
-static void UR_SendMail (const aircraft_t *ufocraft, const base_t *base)
+static void UR_SendMail (const aircraft_t *ufocraft, const char *baseName)
{
int i;
components_t *comp;
@@ -49,7 +51,7 @@
char body[512] = "";
assert(ufocraft);
- assert(base);
+ assert(baseName);
if (ccs.missionResults.crashsite) {
/* take the source mail and create a copy of it */
@@ -95,96 +97,20 @@
assert(mail);
/* don't free the old mail body here - it's the string of the source mail */
- mail->body = Mem_PoolStrDup(va(_(mail->body), UFO_TypeToName(ccs.missionResults.ufotype), base->name, body), cp_campaignPool, 0);
+ mail->body = Mem_PoolStrDup(va(_(mail->body), UFO_TypeToName(ccs.missionResults.ufotype), baseName, body), cp_campaignPool, 0);
/* update subject */
/* Insert name of the mission in the template */
- mail->subject = Mem_PoolStrDup(va(_(mail->subject), base->name), cp_campaignPool, 0);
+ mail->subject = Mem_PoolStrDup(va(_(mail->subject), baseName), cp_campaignPool, 0);
/* Add the mail to unread mail */
Cmd_ExecuteString(va("addeventmail %s", mail->id));
}
/**
- * @brief Prepares UFO recovery in global recoveries array.
- * @param[in] base Pointer to the base, where the UFO recovery will be made.
- * @sa UR_ProcessActive
- * @sa UR_ConditionsForStoring
- */
-void UR_Prepare (base_t *base, ufoType_t ufoType)
-{
- int i;
- ufoRecoveries_t *recovery = NULL;
- aircraft_t *ufocraft = NULL;
- date_t event;
-
- assert(base);
-
- /* Find ufo sample of given ufotype. */
- for (i = 0; i < ccs.numAircraftTemplates; i++) {
- ufocraft = &ccs.aircraftTemplates[i];
- if (ufocraft->type != AIRCRAFT_UFO)
- continue;
- if (ufocraft->ufotype == ufoType)
- break;
- }
- if (ufocraft == NULL) {
- Com_DPrintf(DEBUG_CLIENT, "UR_Prepare: no ufo with the type %i found.\n", ufoType);
- return;
- }
-
- /* Find free uforecovery slot. */
- for (i = 0; i < MAX_RECOVERIES; i++) {
- if (!ccs.recoveries[i].active) {
- /* Make sure it is empty here. */
- memset(&ccs.recoveries[i], 0, sizeof(ccs.recoveries[i]));
- recovery = &ccs.recoveries[i];
- break;
- }
- }
- if (!recovery) {
- Com_DPrintf(DEBUG_CLIENT, "UR_Prepare: free recovery slot not found.\n");
- return;
- }
-
- /* Prepare date of the recovery event - always two days after mission. */
- event = ccs.date;
- /* if you change these 2 days to something other you
- * have to review all translations, too */
- event.day += 2;
- /* Prepare recovery. */
- recovery->active = qtrue;
- recovery->base = base;
- recovery->ufoTemplate = ufocraft->tpl;
- recovery->event = event;
-
- /* Update base capacity. */
- if (ufocraft->size == AIRCRAFT_LARGE) {
- /* Large UFOs can only fit in large UFO hangars */
- if (base->capacities[CAP_UFOHANGARS_LARGE].max > base->capacities[CAP_UFOHANGARS_LARGE].cur)
- base->capacities[CAP_UFOHANGARS_LARGE].cur++;
- else
- /* no more room -- this shouldn't happen as we've used UR_ConditionsForStoring */
- Com_Error(ERR_DROP, "UR_Prepare: No room in large UFO hangars to store %s", ufocraft->id);
- } else {
- /* Small UFOs can only fit in small UFO hangars */
- if (base->capacities[CAP_UFOHANGARS_SMALL].max > base->capacities[CAP_UFOHANGARS_SMALL].cur)
- base->capacities[CAP_UFOHANGARS_SMALL].cur++;
- else
- /* no more room -- this shouldn't happen as we've used UR_ConditionsForStoring */
- Com_Error(ERR_DROP, "UR_Prepare: No room in small UFO hangars to store %s", ufocraft->id);
- }
-
- Com_DPrintf(DEBUG_CLIENT, "UR_Prepare: the recovery entry in global array is done; base: %s, ufotype: %s, date: %i\n",
- base->name, recovery->ufoTemplate->id, recovery->event.day);
-
- /* Send an email */
- UR_SendMail(ufocraft, base);
-}
-
-/**
* @brief Function to process crashed UFO.
* @note Command to call this: cp_ufocrashed.
+ * @todo is this still used? Remove or fix.
*/
static void CP_UFOCrashed_f (void)
{
@@ -237,7 +163,7 @@
cargo = aircraft->itemcargo;
/* Find components definition. */
- comp = CL_GetComponentsByItem(INVSH_GetItemByID(ufocraft->id));
+ comp = CL_GetComponentsByID(ufocraft->id);
assert(comp);
/* Add components of crashed UFO to dropship. */
@@ -256,7 +182,8 @@
ccs.missionResults.ufotype = ufocraft->ufotype;
/* send mail */
- UR_SendMail(ufocraft, aircraft->homebase);
+ assert(aircraft->homebase);
+ UR_SendMail(ufocraft, aircraft->homebase->name);
}
/*==================================
@@ -264,125 +191,315 @@
==================================*/
/**
- * @brief Updates current capacities for UFO hangars in given base.
- * @param[in] base The base where you want the update to be done
+ * @brief Function to process active recoveries.
+ * @sa CL_CampaignRun
+ * @sa UR_Prepare
*/
-void UR_UpdateUFOHangarCapForAll (base_t *base)
+void UR_ProcessActive (void)
{
int i;
- aircraft_t *ufocraft;
- if (!base) {
-#ifdef DEBUG
- Com_Printf("UR_UpdateUFOHangarCapForAll: no base given!\n");
-#endif
- return;
+ for (i = 0; i < ccs.numStoredUFOs; i++) {
+ storedUFO_t *ufo = US_GetStoredUFOByIDX(i);
+
+ if (!ufo)
+ continue;
+ assert(ufo->ufoTemplate);
+ assert(ufo->ufoTemplate->tech);
+ if (ufo->ufoTemplate->tech->statusCollected)
+ continue;
+ if (ufo->arrive.day > ccs.date.day || (ufo->arrive.day == ccs.date.day && ufo->arrive.sec > ccs.date.sec))
+ continue;
+
+ RS_MarkCollected(ufo->ufoTemplate->tech);
}
+}
- /* Reset current capacities for UFO hangar. */
- base->capacities[CAP_UFOHANGARS_LARGE].cur = 0;
- base->capacities[CAP_UFOHANGARS_SMALL].cur = 0;
+/* ==== UFO Storing stuff ==== */
- for (i = 0; i < csi.numODs; i++) {
- /* we are looking for UFO */
- if (csi.ods[i].tech->type != RS_CRAFT)
+/**
+ * @brief Returns an ufostore place
+ * @param[in] idx index of ufostore place
+ * @return storedUFO_t Pointer
+ */
+storedUFO_t* US_GetStoredUFOPlaceByIDX (const int idx)
+{
+ if (idx < 0 || idx >= MAX_STOREDUFOS)
+ return NULL;
+ return &(ccs.storedUFOs[idx]);
+}
+
+/**
+ * @brief Returns a stored ufo
+ * @param[in] idx index of ufostore place
+ * @return storedUFO_t Pointer
+ */
+storedUFO_t* US_GetStoredUFOByIDX (const int idx)
+{
+ if (idx < 0 || idx >= ccs.numStoredUFOs)
+ return NULL;
+ return &(ccs.storedUFOs[idx]);
+}
+
+/**
+ * @brief Adds an UFO to the storage
+ * @param[in] ufoTemplate Pointer to the aircraft(ufo)Template to add
+ * @param[in] installation Pointer to the installation it should be added to
+ * @param[in] date Date when UFO is arrives to the storage (recovery || transfer)
+ * @return storedUFO_t pointer to the newly stored UFO (or NULL if failed)
+ */
+storedUFO_t *US_StoreUFO (aircraft_t *ufoTemplate, installation_t *installation, date_t date)
+{
+ storedUFO_t *ufo;
+
+ if (!ufoTemplate) {
+ Com_DPrintf(DEBUG_CLIENT, "US_StoreUFO: Invalid aircraft (UFO) Template.\n");
+ return NULL;
+ }
+
+ if (!installation) {
+ Com_DPrintf(DEBUG_CLIENT, "US_StoreUFO: Invalid Installation\n");
+ return NULL;
+ }
+
+ if (ccs.numStoredUFOs >= MAX_STOREDUFOS) {
+ Com_DPrintf(DEBUG_CLIENT, "US_StoreUFO: stored UFOs array is full.\n");
+ return NULL;
+ }
+
+ if (installation->ufoCapacity.cur >= installation->ufoCapacity.max) {
+ Com_DPrintf(DEBUG_CLIENT, "US_StoreUFO: Installation is full with UFOs.\n");
+ return NULL;
+ }
+
+ /* we can store it there */
+ ufo = US_GetStoredUFOPlaceByIDX(ccs.numStoredUFOs); /* Select first empty place */
+ ufo->idx = ccs.numStoredUFOs;
+ Q_strncpyz(ufo->id, ufoTemplate->id, sizeof(ufo->id));
+ ufo->comp = CL_GetComponentsByID(ufo->id);
+ assert(ufo->comp);
+
+ ufo->installation = installation;
+ installation->ufoCapacity.cur++;
+
+ assert(ufoTemplate->tech);
+
+ ufo->ufoTemplate = ufoTemplate;
+ ufo->disassembly = NULL;
+
+ ufo->arrive = date;
+ if (date.day < ccs.date.day || (date.day == ccs.date.day && date.sec <= ccs.date.sec))
+ RS_MarkCollected(ufo->ufoTemplate->tech);
+
+ ccs.numStoredUFOs++;
+
+ return ufo;
+}
+
+/**
+ * @brief Removes an UFO from the storage
+ * @param[in] ufo stored UFO to remove
+ */
+void US_RemoveStoredUFO (storedUFO_t *ufo)
+{
+ int ufoCount;
+ int i;
+
+ assert(ufo);
+
+ /* Stop disassembling */
+ if (ufo->disassembly) {
+ base_t *prodBase = PR_ProductionBase(ufo->disassembly);
+
+ assert(prodBase);
+
+ PR_QueueDelete(prodBase, &ccs.productions[prodBase->idx], ufo->disassembly->idx);
+ }
+
+ /* Stop running research if this is the only UFO from this type
+ * also clear collected status */
+ assert(ufo->ufoTemplate);
+ ufoCount = US_UFOsInStorage(ufo->ufoTemplate, NULL);
+ if (ufoCount <= 1 && ufo->ufoTemplate->tech->statusResearch == RS_RUNNING) {
+ RS_StopResearch(ufo->ufoTemplate->tech);
+ ufo->ufoTemplate->tech->statusCollected = qfalse;
+ }
+
+ /* remove ufo */
+ ufo->installation->ufoCapacity.cur--;
+ REMOVE_ELEM_ADJUST_IDX(ccs.storedUFOs, ufo->idx, ccs.numStoredUFOs);
+
+ /* Adjust UFO pointer of other disassemblies */
+ for (i = 0; i < ccs.numBases; i++) {
+ int j;
+ for (j = 0; j < ccs.productions[i].numItems; j++) {
+ production_t *prod = &(ccs.productions[i].items[j]);
+
+ if (!prod->ufo)
+ continue;
+ if (prod->ufo > ufo)
+ prod->ufo--;
+ }
+ }
+}
+
+
+/**
+ * @brief Returns the number of UFOs stored (on an installation or anywhere)
+ * @param[in] ufoTemplate aircraftTemplate of the ufo
+ * @param[in] installation Pointer to the installation to count at
+ * @returns the number of ufos stored of the given ufotype at given installation or overall
+ * @note installation == NULL means count on every ufoyards
+ */
+int US_UFOsInStorage (const aircraft_t *ufoTemplate, const installation_t *installation)
+{
+ int i;
+ int count = 0;
+
+ for (i = 0; i < ccs.numStoredUFOs; i++) {
+ const storedUFO_t *ufo = US_GetStoredUFOByIDX(i);
+
+ if (!ufo)
continue;
+ if (ufo->ufoTemplate != ufoTemplate)
+ continue;
+ if (installation && ufo->installation != installation)
+ continue;
+ if (ufo->arrive.day > ccs.date.day
+ || (ufo->arrive.day == ccs.date.day && ufo->arrive.sec > ccs.date.sec))
+ continue;
- /* do we have UFO of this type ? */
- if (!base->storage.num[i])
+ count++;
+ }
+
+ return count;
+}
+
+/**
+ * @brief Removes ufos which are over the storing capacity
+ * @param[in] installation pointer to the ufoyard the ufos are stored in
+ */
+void US_RemoveUFOsExceedingCapacity (installation_t *installation)
+{
+ int i;
+ capacities_t *ufoCap;
+
+ if (!installation)
+ Com_Error(ERR_DROP, "US_RemoveUFOsExceedingCapacity: No installation given!\n");
+
+ ufoCap = &(installation->ufoCapacity);
+
+ /* loop ufos backwards */
+ for (i = ccs.numStoredUFOs - 1; i >= 0; i--) {
+ storedUFO_t *ufo = US_GetStoredUFOByIDX(i);
+
+ assert(ufo);
+
+ if (ufo->installation != installation)
continue;
- /* look for corresponding aircraft in global array */
- ufocraft = AIR_GetAircraft(csi.ods[i].id);
- if (!ufocraft) {
- Com_Printf("UR_UpdateUFOHangarCapForAll: Did not find UFO %s\n", csi.ods[i].id);
+ if (ufoCap->cur > ufoCap->max)
+ US_RemoveStoredUFO(ufo);
+ }
+}
+
+/**
+ * @brief get the closest stored ufo (of a type) to a base
+ * @param[in] ufoTemplate Pointer to the aircraft (ufo) template to look for (NULL for any type)
+ * @param[in] base Pointer to the base. If it's NULL the function simply return the first stored UFO of type
+ * @return storedUFO_t Pointer to the first stored UFO matches the conditions
+ */
+storedUFO_t *US_GetClosestStoredUFO (const aircraft_t *ufoTemplate, const base_t *base)
+{
+ int i;
+ float minDistance = -1;
+ storedUFO_t *closestUFO = NULL;
+
+ for (i = 0; i < ccs.numStoredUFOs; i++) {
+ storedUFO_t *ufo = US_GetStoredUFOByIDX(i);
+ float distance = 0;
+
+ if (!ufo)
continue;
- }
- /* Update base capacity. */
- if (ufocraft->size == AIRCRAFT_LARGE)
- base->capacities[CAP_UFOHANGARS_LARGE].cur += base->storage.num[i];
- else
- base->capacities[CAP_UFOHANGARS_SMALL].cur += base->storage.num[i];
+ if (ufoTemplate && ufo->ufoTemplate != ufoTemplate)
+ continue;
+
+ if (ufo->arrive.day > ccs.date.day
+ || (ufo->arrive.day == ccs.date.day && ufo->arrive.sec > ccs.date.sec))
+ continue;
+
+ assert(ufo->installation);
+ if (base)
+ distance = MAP_GetDistance(ufo->installation->pos, base->pos);
+
+ if (minDistance < 0 || minDistance > distance) {
+ minDistance = distance;
+ closestUFO = ufo;
+ }
}
-
- Com_DPrintf(DEBUG_CLIENT, "UR_UpdateUFOHangarCapForAll: base capacities.cur: small: %i big: %i\n", base->capacities[CAP_UFOHANGARS_SMALL].cur, base->capacities[CAP_UFOHANGARS_LARGE].cur);
+ return closestUFO;
}
+
/**
- * @brief Function to process active recoveries.
- * @sa CL_CampaignRun
- * @sa UR_Prepare
+ * @brief Save callback for savegames in XML Format
+ * @sa US_LoadXML
+ * @sa SAV_GameSaveXML
*/
-void UR_ProcessActive (void)
+qboolean US_SaveXML (mxml_node_t *p)
{
int i;
+ mxml_node_t *node = mxml_AddNode(p, "storedufos");
+ for (i = 0; i < ccs.numStoredUFOs; i++) {
+ const storedUFO_t *ufo = US_GetStoredUFOByIDX(i);
+ mxml_node_t * snode = mxml_AddNode(node, "ufo");
- for (i = 0; i < MAX_RECOVERIES; i++) {
- ufoRecoveries_t *recovery = &ccs.recoveries[i];
- if (recovery->active && recovery->event.day == ccs.date.day) {
- objDef_t *od;
- const aircraft_t *ufocraft;
- base_t *base = recovery->base;
- if (!base->founded) {
- /* Destination base was destroyed meanwhile. */
- /* UFO is lost, send proper message to the user.*/
- recovery->active = qfalse;
- /** @todo prepare MS_AddNewMessage() here */
- return;
- }
- /* Get ufocraft. */
- ufocraft = recovery->ufoTemplate;
- assert(ufocraft);
- /* Get item. */
- /* We can do this because aircraft id is the same as dummy item id. */
- od = INVSH_GetItemByID(ufocraft->id);
- if (!od)
- Com_Error(ERR_DROP, "Could not find ufo with id '%s'\n", ufocraft->id);
+ mxml_AddString(snode, "ufoid", ufo->id);
+ mxml_AddInt(snode, "day", ufo->arrive.day);
+ mxml_AddInt(snode, "sec", ufo->arrive.sec);
- /* Process UFO recovery. */
- /* don't call B_UpdateStorageAndCapacity here - it's a dummy item */
- base->storage.num[od->idx]++; /* Add dummy UFO item to enable research topic. */
- RS_MarkCollected(od->tech); /* Enable research topic. */
- /* Reset this recovery. */
- memset(&ccs.recoveries[i], 0, sizeof(ccs.recoveries[i]));
- }
+ if (ufo->installation)
+ mxml_AddInt(snode, "installationidx", ufo->installation->idx);
}
+ return qtrue;
}
/**
- * @brief Checks conditions for storing given ufo in given base.
- * @param[in] base Pointer to the base, where we are going to store UFO.
- * @param[in] ufocraft Pointer to ufocraft which we are going to store.
- * @return qtrue if given base can store given ufo.
+ * @brief Load callback for xml savegames
+ * @sa US_SaveXML
+ * @sa SAV_GameLoadXML
*/
-qboolean UR_ConditionsForStoring (const base_t *base, const aircraft_t *ufocraft)
+qboolean US_LoadXML (mxml_node_t *p)
{
- assert(base && ufocraft);
+ int i;
+ mxml_node_t *node, *snode;
- if (ufocraft->size == AIRCRAFT_LARGE) {
- /* Large UFOs can only fit large UFO hangars */
- if (!B_GetBuildingStatus(base, B_UFO_HANGAR))
- return qfalse;
+ node = mxml_GetNode(p, "storedufos");
- /* Check there is still enough room for this UFO */
- if (base->capacities[CAP_UFOHANGARS_LARGE].max <= base->capacities[CAP_UFOHANGARS_LARGE].cur)
+ for (i = 0, snode = mxml_GetNode(node, "ufo"); i < MAX_STOREDUFOS && snode;
+ i++, snode = mxml_GetNextNode(snode, node, "ufo")) {
+ aircraft_t *ufoTemplate = AIR_GetAircraft(mxml_GetString(snode, "ufoid"));
+ int instIDX = mxml_GetInt(snode, "installationidx", MAX_INSTALLATIONS);
+ installation_t *inst = (instIDX == MAX_INSTALLATIONS) ? NULL : INS_GetFoundedInstallationByIDX(instIDX);
+ date_t arrive;
+
+ arrive.day = mxml_GetInt(snode, "day", 0);
+ arrive.sec = mxml_GetInt(snode, "sec", 0);
+
+ if (!ufoTemplate)
return qfalse;
- } else {
- /* This is a small UFO, can only fit in small hangar */
- /* There's no small hangar functional */
- if (!B_GetBuildingStatus(base, B_UFO_SMALL_HANGAR))
+ if (!inst)
return qfalse;
- /* Check there is still enough room for this UFO */
- if (base->capacities[CAP_UFOHANGARS_SMALL].max <= base->capacities[CAP_UFOHANGARS_SMALL].cur)
- return qfalse;
+ if (!US_StoreUFO(ufoTemplate, inst, arrive))
+ Com_Printf("Cannot store ufo %s at installation idx=%i.\n", ufoTemplate->id, instIDX);
}
-
return qtrue;
}
+
void UR_InitStartup (void)
{
Cmd_AddCommand("cp_ufocrashed", CP_UFOCrashed_f, "Function to process crashed UFO after a mission.");
Index: src/client/campaign/cp_parse.c
===================================================================
--- src/client/campaign/cp_parse.c (revision 25743)
+++ src/client/campaign/cp_parse.c (working copy)
@@ -605,6 +605,24 @@
}
/**
+ * @brief Returns components definition by ID.
+ * @param[in] id assemblyId of the component definition.
+ * @return comp Pointer to components_t definition.
+ */
+components_t *CL_GetComponentsByID(const char *id)
+{
+ int i;
+
+ for (i = 0; i < ccs.numComponents; i++) {
+ components_t *comp = &ccs.components[i];
+ if (!strcmp(comp->assemblyId, id)) {
+ return comp;
+ }
+ }
+ Com_Error(ERR_DROP, "CL_GetComponentsByItem: could not find components id for: %s", id);
+}
+
+/**
* @brief Parsing only for singleplayer
*
* parsed if we are no dedicated server
Index: src/client/campaign/cp_uforecovery.h
===================================================================
--- src/client/campaign/cp_uforecovery.h (revision 25743)
+++ src/client/campaign/cp_uforecovery.h (working copy)
@@ -1,10 +1,10 @@
/**
* @file cp_uforecovery.h
- * @brief UFO recovery
+ * @brief UFO recovery and storing
*/
/*
-Copyright (C) 2002-2007 UFO: Alien Invasion team.
+Copyright (C) 2002-2009 UFO: Alien Invasion team.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -33,15 +33,42 @@
* @sa ufoRecovery_t */
typedef struct ufoRecoveries_s {
qboolean active; /**< True if the recovery is under processing. */
- base_t *base; /**< Base where the recovery will be processed. */
+ installation_t *installation; /**< UFO Yard where the recovery will be processed. */
aircraft_t *ufoTemplate; /**< Entry of UFO in aircraftTemplates array. */
date_t event; /**< When the process will start (UFO got transported to base). */
} ufoRecoveries_t;
-void UR_Prepare(base_t *base, ufoType_t ufoType);
-void UR_UpdateUFOHangarCapForAll(base_t *base);
+#define MAX_STOREDUFOS 128
+
+/* time the recovery takes in days */
+#define RECOVERY_DELAY 2.0f
+
+/** @brief Structure for stored UFOs */
+typedef struct storedUFO_s {
+ int idx;
+ char id[MAX_VAR];
+ components_t *comp;
+ aircraft_t *ufoTemplate;
+
+ /* arrival date (recovery/transfer) */
+ date_t arrive;
+
+ /* installation UFO is stored */
+ installation_t *installation;
+
+ /* link to disassembly item */
+ production_t *disassembly;
+} storedUFO_t;
+
void UR_ProcessActive(void);
-qboolean UR_ConditionsForStoring(const base_t *base, const aircraft_t *ufocraft);
void UR_InitStartup(void);
+storedUFO_t *US_StoreUFO(aircraft_t *ufoTemplate, installation_t *installation, date_t date);
+storedUFO_t *US_GetStoredUFOPlaceByIDX(const int idx);
+storedUFO_t *US_GetStoredUFOByIDX(const int idx);
+storedUFO_t *US_GetClosestStoredUFO(const aircraft_t *ufoTemplate, const base_t *base);
+void US_RemoveStoredUFO(storedUFO_t *ufo);
+int US_UFOsInStorage(const aircraft_t *ufoTemplate, const installation_t *installation);
+void US_RemoveUFOsExceedingCapacity(installation_t *installation);
+
#endif
Index: src/client/campaign/cp_parse.h
===================================================================
--- src/client/campaign/cp_parse.h (revision 25743)
+++ src/client/campaign/cp_parse.h (working copy)
@@ -47,5 +47,6 @@
void CL_ParseCampaign(const char *name, const char **text);
void CL_ScriptSanityCheck(void);
components_t *CL_GetComponentsByItem(const objDef_t *item);
+components_t *CL_GetComponentsByID(const char *id);
#endif
Index: src/client/campaign/cp_research_callbacks.c
===================================================================
--- src/client/campaign/cp_research_callbacks.c (revision 25743)
+++ src/client/campaign/cp_research_callbacks.c (working copy)
@@ -608,10 +608,7 @@
switch (tech->statusResearch) {
case RS_RUNNING:
- /* Remove all scis from it and set the status to paused (i.e. it's differnet from a RS_NONE since it may have a little bit of progress already). */
- while (tech->scientists > 0)
- RS_RemoveScientist(tech, NULL);
- assert(tech->statusResearch == RS_PAUSED);
+ RS_StopResearch(tech);
break;
case RS_PAUSED:
/** @todo remove? Popup info how much is already researched? */
Index: src/client/campaign/cp_aircraft.c
===================================================================
--- src/client/campaign/cp_aircraft.c (revision 25743)
+++ src/client/campaign/cp_aircraft.c (working copy)
@@ -802,20 +802,11 @@
int AIR_GetCapacityByAircraftWeight (const aircraft_t *aircraft)
{
- if (aircraft->ufotype == UFO_MAX) {
- switch (aircraft->size) {
- case AIRCRAFT_SMALL:
- return CAP_AIRCRAFT_SMALL;
- case AIRCRAFT_LARGE:
- return CAP_AIRCRAFT_BIG;
- }
- } else {
- switch (aircraft->size) {
- case AIRCRAFT_SMALL:
- return CAP_UFOHANGARS_SMALL;
- case AIRCRAFT_LARGE:
- return CAP_UFOHANGARS_LARGE;
- }
+ switch (aircraft->size) {
+ case AIRCRAFT_SMALL:
+ return CAP_AIRCRAFT_SMALL;
+ case AIRCRAFT_LARGE:
+ return CAP_AIRCRAFT_BIG;
}
Com_Error(ERR_DROP, "AIR_GetCapacityByAircraftWeight: Unkown weight of aircraft '%i'\n", aircraft->size);
}
@@ -2604,22 +2595,6 @@
mxml_AddBool(snode, "laser", ccs.projectiles[i].laser);
}
- /* Save recoveries. */
- for (i = 0; i < MAX_RECOVERIES; i++) {
- /*check, if the transfer is active */
- /** @todo Check if we can really ignore them if active is false */
- if (!ccs.recoveries[i].active)
- continue;
- snode = mxml_AddNode(node, "recovery");
- /* mxml_AddBool(snode, "active", ccs.recoveries[i].active); */
- if (ccs.recoveries[i].base)
- mxml_AddInt(snode, "targetbase", ccs.recoveries[i].base->idx);
- /** @todo At some point we really need to save a unique string here. */
- if (ccs.recoveries[i].ufoTemplate)
- mxml_AddInt(snode, "ufotemplateidx", ccs.recoveries[i].ufoTemplate->idx);
- mxml_AddInt(snode, "day", ccs.recoveries[i].event.day);
- mxml_AddInt(snode, "sec", ccs.recoveries[i].event.sec);
- }
return qtrue;
}
@@ -2931,17 +2906,28 @@
ccs.numProjectiles = i;
- for (i = 0, snode = mxml_GetNode(node, "recovery"); snode && i < MAX_RECOVERIES;
- snode = mxml_GetNextNode(snode, node, "recovery"), i++) {
- byte base, ufotype;
- ccs.recoveries[i].active = qtrue;
- base = mxml_GetInt(snode, "targetbase", BYTES_NONE);
- ccs.recoveries[i].base = (base != BYTES_NONE) ? B_GetBaseByIDX((byte)base) : NULL;
- assert(ccs.numAircraftTemplates);
- ufotype = mxml_GetInt(snode, "ufotemplateidx", BYTES_NONE);
- ccs.recoveries[i].ufoTemplate = (ufotype != BYTES_NONE) ? &ccs.aircraftTemplates[ufotype] : NULL;
- ccs.recoveries[i].event.day = mxml_GetInt(snode, "day", 0);
- ccs.recoveries[i].event.sec = mxml_GetInt(snode, "sec", 0);
+ /* fallback code to keep compatibility with UFO Hangars */
+ /* @todo remove this on release or after a time */
+ for (snode = mxml_GetNode(node, "recovery"); snode;
+ snode = mxml_GetNextNode(snode, node, "recovery")) {
+ installation_t *inst = INS_GetFirstUFOYard(qtrue);
+ byte ufotype = mxml_GetInt(snode, "ufotemplateidx", BYTES_NONE);
+ date_t event;
+
+ if (!inst) {
+ Com_Printf("AIR_LoadXML: No more free UFOYards for recovery\n");
+ break;
+ }
+
+ event.day = mxml_GetInt(snode, "day", 0);
+ event.sec = mxml_GetInt(snode, "sec", 0);
+
+ if (ufotype >= ccs.numAircraftTemplates) {
+ Com_Printf("AIR_LoadXML: Invalid template idx %i\n", ufotype);
+ continue;
+ }
+
+ US_StoreUFO(&(ccs.aircraftTemplates[ufotype]), inst, event);
}
for (i = ccs.numUFOs - 1; i >= 0; i--) {
Index: src/client/campaign/cp_base_callbacks.c
===================================================================
--- src/client/campaign/cp_base_callbacks.c (revision 25743)
+++ src/client/campaign/cp_base_callbacks.c (working copy)
@@ -33,6 +33,7 @@
#include "cp_base.h"
#include "cp_map.h"
#include "cp_popup.h"
+#include "cp_ufo.h"
/** @brief Used from menu scripts as parameter for mn_select_base */
#define CREATE_NEW_BASE_ID -1
@@ -377,10 +378,6 @@
case B_SMALL_HANGAR:
B_RemoveAircraftExceedingCapacity(base, buildingType);
break;
- case B_UFO_HANGAR:
- case B_UFO_SMALL_HANGAR:
- B_RemoveUFOsExceedingCapacity(base, buildingType);
- break;
case B_QUARTERS:
E_DeleteEmployeesExceedingCapacity(base);
break;
@@ -853,8 +850,17 @@
const production_t *production = &queue->items[i];
const objDef_t *objDef = production->item;
const aircraft_t *aircraft = production->aircraft;
- const char *name = objDef ? _(objDef->name) : _(aircraft->name);
- assert(name);
+ const storedUFO_t *ufo = production->ufo;
+ const char *name;
+
+ if (objDef)
+ name = _(objDef->name);
+ else if (aircraft)
+ name = _(aircraft->name);
+ else if (ufo)
+ name = _(UFO_TypeToName(ufo->ufoTemplate->ufotype));
+ else
+ Com_Error(ERR_DROP, "BaseSummary_Init: Invalid production type (not item, not aircraft, not disassembly)\n");
/** @todo use the same method as we do in PR_ProductionInfo */
Q_strcat(textStatsBuffer, va(_("%s\t\t\t\t\t\t%d\t\t\t\t%.2f%%\n"), name,
Index: src/client/campaign/cp_transfer.c
===================================================================
--- src/client/campaign/cp_transfer.c (revision 25743)
+++ src/client/campaign/cp_transfer.c (working copy)
@@ -111,8 +111,9 @@
*/
static int TR_CheckItem (const objDef_t *od, const base_t *destbase, int amount)
{
- int i, intransfer = 0, amtransfer = 0;
- int smallufotransfer = 0, bigufotransfer = 0;
+ int i;
+ int intransfer = 0;
+ int amtransfer = 0;
assert(od);
assert(destbase);
@@ -122,14 +123,7 @@
if (td.trItemsTmp[i] > 0) {
if (!strcmp(csi.ods[i].id, ANTIMATTER_TECH_ID))
amtransfer = ANTIMATTER_SIZE * td.trItemsTmp[i];
- if (od->tech->type == RS_CRAFT) {
- aircraft_t *ufocraft = AIR_GetAircraft(od->tech->provides);
- assert(ufocraft);
- if (ufocraft->size == AIRCRAFT_LARGE)
- bigufotransfer++;
- else
- smallufotransfer++;
- } else
+ else
intransfer += csi.ods[i].size * td.trItemsTmp[i];
}
}
@@ -151,33 +145,7 @@
/* amount to transfer can't be bigger than what we have */
amount = min(amount, (destbase->capacities[CAP_ANTIMATTER].max - destbase->capacities[CAP_ANTIMATTER].cur - amtransfer) / ANTIMATTER_SIZE);
}
- } else if (od->tech->type == RS_CRAFT) { /* This is UFO craft */
- aircraft_t *ufocraft = AIR_GetAircraft(od->tech->provides);
- assert(ufocraft);
- if (ufocraft->size == AIRCRAFT_LARGE) {
- if (!B_GetBuildingStatus(destbase, B_UFO_HANGAR)) {
- MN_Popup(_("Missing Large UFO Hangar"), _("Destination base does not have functional Large UFO Hangar.\n"));
- return 0;
- } else {
- amount = min(amount, destbase->capacities[CAP_UFOHANGARS_LARGE].max - destbase->capacities[CAP_UFOHANGARS_LARGE].cur - bigufotransfer);
- if (amount <= 0) {
- MN_Popup(_("Missing Large UFO Hangar"), _("Destination base does not have enough Large UFO Hangar.\n"));
- return 0;
- }
- }
- } else if (ufocraft->size == AIRCRAFT_SMALL) {
- if (!B_GetBuildingStatus(destbase, B_UFO_SMALL_HANGAR)) {
- MN_Popup(_("Missing Small UFO Hangar"), _("Destination base does not have functional Small UFO Hangar.\n"));
- return qfalse;
- } else {
- amount = min(amount, destbase->capacities[CAP_UFOHANGARS_SMALL].max - destbase->capacities[CAP_UFOHANGARS_SMALL].cur - smallufotransfer);
- if (amount <= 0) {
- MN_Popup(_("Missing Small UFO Hangar"), _("Destination base does not have enough Small UFO Hangar.\n"));
- return 0;
- }
- }
- }
- } else { /*This is not antimatter*/
+ } else { /*This is not antimatter */
if (!B_GetBuildingStatus(destbase, B_STORAGE)) /* Return if the target base doesn't have storage or power. */
return 0;
@@ -689,16 +657,7 @@
if (td.trItemsTmp[i] > 0) {
if (!strcmp(csi.ods[i].id, ANTIMATTER_TECH_ID))
B_ManageAntimatter(base, td.trItemsTmp[i], qtrue);
- else if (csi.ods[i].tech->type == RS_CRAFT) { /* This is UFO craft */
- const aircraft_t *ufocraft = AIR_GetAircraft(csi.ods[i].tech->provides);
- assert(ufocraft);
- /* don't use B_UpdateStorageAndCapacity: UFO are not stored in storage */
- base->storage.num[i] += td.trItemsTmp[i];
- if (ufocraft->size == AIRCRAFT_LARGE)
- base->capacities[CAP_UFOHANGARS_LARGE].cur++;
- else
- base->capacities[CAP_UFOHANGARS_SMALL].cur++;
- } else
+ else
B_UpdateStorageAndCapacity(base, &csi.ods[i], td.trItemsTmp[i], qfalse, qfalse);
}
}
@@ -744,20 +703,7 @@
if (transfer->itemAmount[i] > 0) {
if (!strcmp(csi.ods[i].id, ANTIMATTER_TECH_ID))
B_ManageAntimatter(destination, transfer->itemAmount[i], qtrue);
- else if (csi.ods[i].tech->type == RS_CRAFT) { /* This is UFO craft */
- const aircraft_t *ufocraft = AIR_GetAircraft(csi.ods[i].tech->provides);
- assert(ufocraft);
- for (j = 0; j < transfer->itemAmount[i]; j++) {
- if (UR_ConditionsForStoring(destination, ufocraft)) {
- /* don't use B_UpdateStorageAndCapacity: UFO are not stored in storage */
- destination->storage.num[i]++;
- if (ufocraft->size == AIRCRAFT_LARGE)
- destination->capacities[CAP_UFOHANGARS_LARGE].cur++;
- else
- destination->capacities[CAP_UFOHANGARS_SMALL].cur++;
- }
- }
- } else
+ else
B_UpdateStorageAndCapacity(destination, &csi.ods[i], transfer->itemAmount[i], qfalse, qtrue);
}
}
@@ -1202,16 +1148,7 @@
td.trItemsTmp[i] += amount;
if (!strcmp(od->id, ANTIMATTER_TECH_ID))
B_ManageAntimatter(base, amount, qfalse);
- else if (od->tech->type == RS_CRAFT) { /* This is UFO craft */
- const aircraft_t *ufocraft = AIR_GetAircraft(csi.ods[i].tech->provides);
- assert(ufocraft);
- /* don't use B_UpdateStorageAndCapacity: UFO are not stored in storage */
- base->storage.num[i] -= amount;
- if (ufocraft->size == AIRCRAFT_LARGE)
- base->capacities[CAP_UFOHANGARS_LARGE].cur -= amount;
- else
- base->capacities[CAP_UFOHANGARS_SMALL].cur -= amount;
- } else
+ else
B_UpdateStorageAndCapacity(base, od, -amount, qfalse, qfalse);
break;
} else
@@ -1569,16 +1506,7 @@
td.trItemsTmp[i] -= amount;
if (!strcmp(csi.ods[i].id, ANTIMATTER_TECH_ID))
B_ManageAntimatter(base, amount, qfalse);
- else if (csi.ods[i].tech->type == RS_CRAFT) { /* This is UFO craft */
- const aircraft_t *ufocraft = AIR_GetAircraft(csi.ods[i].tech->provides);
- assert(ufocraft);
- /* don't use B_UpdateStorageAndCapacity: UFO are not stored in storage */
- base->storage.num[i] += amount;
- if (ufocraft->size == AIRCRAFT_LARGE)
- base->capacities[CAP_UFOHANGARS_LARGE].cur += amount;
- else
- base->capacities[CAP_UFOHANGARS_SMALL].cur += amount;
- } else
+ else
B_UpdateStorageAndCapacity(base, &csi.ods[i], amount, qfalse, qfalse);
break;
}
Index: src/client/campaign/cp_save.c
===================================================================
--- src/client/campaign/cp_save.c (revision 25743)
+++ src/client/campaign/cp_save.c (working copy)
@@ -650,6 +650,7 @@
static saveSubsystems_t xvi_subsystemXML = {"xvirate", XVI_SaveXML, XVI_LoadXML};
static saveSubsystems_t ins_subsystemXML = {"installation", INS_SaveXML, INS_LoadXML};
static saveSubsystems_t mso_subsystemXML = {"messageoptions", MSO_SaveXML, MSO_LoadXML};
+ static saveSubsystems_t us_subsystemXML = {"ufostores", US_SaveXML, US_LoadXML};
saveSubsystemsAmount = 0;
memset(&saveSubsystems, 0, sizeof(saveSubsystems));
@@ -664,15 +665,16 @@
SAV_AddSubsystem(&rs_subsystemXML);
SAV_AddSubsystem(&e_subsystemXML);
SAV_AddSubsystem(&ac_subsystemXML);
+ SAV_AddSubsystem(&air_subsystemXML);
+ SAV_AddSubsystem(&ins_subsystemXML);
+ SAV_AddSubsystem(&us_subsystemXML);
SAV_AddSubsystem(&pr_subsystemXML);
- SAV_AddSubsystem(&air_subsystemXML);
SAV_AddSubsystem(&ms_subsystemXML);
SAV_AddSubsystem(&stats_subsystemXML);
SAV_AddSubsystem(&na_subsystemXML);
SAV_AddSubsystem(&trans_subsystemXML);
SAV_AddSubsystem(&ab_subsystemXML);
SAV_AddSubsystem(&xvi_subsystemXML);
- SAV_AddSubsystem(&ins_subsystemXML);
SAV_AddSubsystem(&mso_subsystemXML);
Cmd_AddCommand("game_quickloadinit", SAV_GameQuickLoadInit_f, "Check whether there is a quicksave at all");
Index: src/client/campaign/cp_produce_callbacks.c
===================================================================
--- src/client/campaign/cp_produce_callbacks.c (revision 25743)
+++ src/client/campaign/cp_produce_callbacks.c (working copy)
@@ -5,7 +5,7 @@
*/
/*
-Copyright (C) 1997-2008 UFO:AI Team
+Copyright (C) 1997-2009 UFO:AI Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -29,6 +29,7 @@
#include "../menu/m_popup.h"
#include "cp_campaign.h"
#include "cp_market.h"
+#include "cp_ufo.h"
#include "cp_produce.h"
#include "cp_produce_callbacks.h"
@@ -50,7 +51,7 @@
/** Currently selected entry in the productionItemList (depends on content) */
static objDef_t *selectedItem = NULL;
-static components_t *selectedDisassembly = NULL;
+static storedUFO_t *selectedDisassembly = NULL;
static aircraft_t *selectedAircraft = NULL;
/** @brief Number of blank lines between queued items and tech list. */
@@ -68,28 +69,6 @@
}
/**
- * @brief Conditions for disassembling.
- * @param[in] base Pointer to base where the component is stored.
- * @param[in] comp Pointer to components definition.
- * @return qtrue if disassembling is ready, qfalse otherwise.
- */
-static qboolean PR_ConditionsDisassembly (const base_t *base, const components_t *comp)
-{
- const objDef_t *od;
-
- assert(base);
- assert(comp);
-
- od = comp->assemblyItem;
- assert(od);
-
- if (RS_IsResearched_ptr(od->tech) && base->storage.num[od->idx] > 0)
- return qtrue;
- else
- return qfalse;
-}
-
-/**
* @brief Checks if the production requirements are met for a defined amount.
* @param[in] amount How many items are planned to be produced.
* @param[in] reqs The production requirements of the item that is to be produced.
@@ -112,6 +91,12 @@
producible = qfalse;
}
}
+ if (req->type == RS_LINK_UFO) {
+ /* The same code is used in "RS_RequirementsMet" */
+ Com_DPrintf(DEBUG_CLIENT, "PR_RequirementsMet: %s\n", req->id);
+ if (US_UFOsInStorage(req->link, NULL) < req->amount)
+ producible = qfalse;
+ }
}
if (producible)
producibleAmount++;
@@ -130,13 +115,13 @@
* @param[in] amount Desired amount to produce.
* @param[in] disassembling True if this is disassembling, false if production.
*/
-static production_t *PR_QueueNew (base_t *base, production_queue_t *queue, objDef_t *item, aircraft_t *aircraftTemplate, signed int amount, qboolean disassembling)
+static production_t *PR_QueueNew (base_t *base, production_queue_t *queue, objDef_t *item, aircraft_t *aircraftTemplate, storedUFO_t *ufo, signed int amount)
{
int numWorkshops = 0;
production_t *prod;
const technology_t *tech;
- assert((item && !aircraftTemplate) || (!item && aircraftTemplate));
+ assert((item && !aircraftTemplate && !ufo) || (!item && aircraftTemplate && !ufo) || (!item && !aircraftTemplate && ufo));
assert(base);
if (queue->numItems >= MAX_PRODUCTIONS)
@@ -161,13 +146,15 @@
/* self-reference. */
prod->idx = queue->numItems;
- if (produceCategory != FILTER_AIRCRAFT)
+ if (item)
tech = item->tech;
- else
+ else if (aircraftTemplate)
tech = aircraftTemplate->tech;
+ else
+ tech = ufo->ufoTemplate->tech;
/* We cannot queue new aircraft if no free hangar space. */
- if (produceCategory == FILTER_AIRCRAFT) {
+ if (aircraftTemplate) {
if (!B_GetBuildingStatus(base, B_COMMAND)) {
MN_Popup(_("Hangars not ready"), _("You cannot queue aircraft.\nNo command centre in this base.\n"));
return NULL;
@@ -184,18 +171,20 @@
prod->item = item;
prod->aircraft = aircraftTemplate;
- prod->amount = amount;
- if (disassembling) {
+ prod->ufo = ufo;
+
+ if (ufo) {
/* Disassembling. */
prod->production = qfalse;
+ prod->amount = 1;
- /* We have to remove amount of items being disassembled from base storage. */
- base->storage.num[item->idx] -= amount;
+ ufo->disassembly = prod;
/* Now find related components definition. */
prod->percentDone = 0.0f;
} else {
/* Production. */
prod->production = qtrue;
+ prod->amount = amount;
/* Don't try to add to queue an item which is not producible. */
if (tech->produceTime < 0)
@@ -227,12 +216,12 @@
/* First add all the queue items ... */
for (i = 0; i < queue->numItems; i++) {
const production_t *prod = &queue->items[i];
- if (!prod->aircraft) {
+ if (prod->item) {
const objDef_t *od = prod->item;
LIST_AddString(&productionList, va("%s", _(od->name)));
LIST_AddString(&productionAmount, va("%i", base->storage.num[prod->item->idx]));
LIST_AddString(&productionQueued, va("%i", prod->amount));
- } else {
+ } else if (prod->aircraft) {
const aircraft_t *aircraftTemplate = prod->aircraft;
LIST_AddString(&productionList, va("%s", _(aircraftTemplate->name)));
for (j = 0, counter = 0; j < ccs.numAircraft; j++) {
@@ -243,6 +232,12 @@
}
LIST_AddString(&productionAmount, va("%i", counter));
LIST_AddString(&productionQueued, va("%i", prod->amount));
+ } else if (prod->ufo) {
+ const storedUFO_t *ufo = prod->ufo;
+
+ LIST_AddString(&productionList, va("%s (at %s)", _(UFO_TypeToName(ufo->ufoTemplate->ufotype)), ufo->installation->name));
+ LIST_AddString(&productionAmount, va("%i", US_UFOsInStorage(ufo->ufoTemplate, ufo->installation)));
+ LIST_AddString(&productionQueued, "1");
}
}
@@ -257,18 +252,26 @@
/* Then go through all object definitions ... */
if (produceCategory == FILTER_DISASSEMBLY) {
- for (i = 0; i < ccs.numComponents; i++) {
- const objDef_t *asOd = ccs.components[i].assemblyItem;
- components_t *comp = &ccs.components[i];
- if (!asOd)
+ /** UFOs at UFO stores */
+ for (i = 0; i < ccs.numStoredUFOs; i++) {
+ storedUFO_t *ufo = US_GetStoredUFOByIDX(i);
+
+ if (!ufo)
continue;
- if (PR_ConditionsDisassembly(base, comp)) {
- LIST_AddPointer(&productionItemList, comp);
+ /* The UFO is being disassembled aready */
+ if (ufo->disassembly)
+ continue;
+ /* UFO not researched */
+ if (!RS_IsResearched_ptr(ufo->ufoTemplate->tech))
+ continue;
+ /* UFO is being transported */
+ if (ufo->arrive.day > ccs.date.day || (ufo->arrive.day == ccs.date.day && ufo->arrive.sec > ccs.date.sec))
+ continue;
- LIST_AddString(&productionList, va("%s", _(asOd->name)));
- LIST_AddString(&productionAmount, va("%i", base->storage.num[asOd->idx]));
- LIST_AddString(&productionQueued, "");
- }
+ LIST_AddPointer(&productionItemList, ufo);
+ LIST_AddString(&productionList, va("%s (at %s)", _(UFO_TypeToName(ufo->ufoTemplate->ufotype)), ufo->installation->name));
+ LIST_AddString(&productionAmount, va("%i", US_UFOsInStorage(ufo->ufoTemplate, ufo->installation)));
+ LIST_AddString(&productionQueued, "");
}
} else if (produceCategory == FILTER_AIRCRAFT) {
for (i = 0; i < ccs.numAircraftTemplates; i++) {
@@ -343,7 +346,7 @@
Com_sprintf(productionInfo, sizeof(productionInfo), _("No item selected"));
Cvar_Set("mn_item", "");
} else {
- prodPerHour = PR_CalculateProductionPercentDone(base, od->tech, NULL, qfalse);
+ prodPerHour = PR_CalculateProductionPercentDone(base, od->tech, NULL);
/* If you entered production menu, that means that prodPerHour > 0 (must not divide by 0) */
assert(prodPerHour > 0);
time = ceil((1.0f - percentDone) / prodPerHour);
@@ -363,35 +366,35 @@
* @param[in] base Pointer to the base where informations should be printed.
* @sa PR_ProductionInfo
*/
-static void PR_DisassemblyInfo (const base_t *base, const objDef_t *od, const components_t *comp, float percentDone)
+static void PR_DisassemblyInfo (const base_t *base, const storedUFO_t *ufo, float percentDone)
{
static char productionInfo[512];
int time, i;
float prodPerHour;
assert(base);
- assert(od);
- assert(comp);
- assert(od->tech);
+ assert(ufo);
+ assert(ufo->ufoTemplate);
+ assert(ufo->ufoTemplate->tech);
- prodPerHour = PR_CalculateProductionPercentDone(base, od->tech, comp, qtrue);
+ prodPerHour = PR_CalculateProductionPercentDone(base, ufo->ufoTemplate->tech, ufo->comp);
/* If you entered production menu, that means that prodPerHour > 0 (must not divide by 0) */
assert(prodPerHour > 0);
time = ceil((1.0f - percentDone) / prodPerHour);
- Com_sprintf(productionInfo, sizeof(productionInfo), _("%s - disassembly\n"), _(od->name));
- Q_strcat(productionInfo, _("Components: "), sizeof(productionInfo));
+ Com_sprintf(productionInfo, sizeof(productionInfo), _("%s - disassembly\n"), _(UFO_TypeToName(ufo->ufoTemplate->ufotype)));
+ Q_strcat(productionInfo, _("Components:\n"), sizeof(productionInfo));
/* Print components. */
- for (i = 0; i < comp->numItemtypes; i++) {
- const objDef_t *compOd = comp->items[i];
+ for (i = 0; i < ufo->comp->numItemtypes; i++) {
+ const objDef_t *compOd = ufo->comp->items[i];
assert(compOd);
- Q_strcat(productionInfo, va(_("%s (%i) "), _(compOd->name), comp->itemAmount[i]),
+ Q_strcat(productionInfo, va(" %s (%i)\n", _(compOd->name), ufo->comp->itemAmount[i]),
sizeof(productionInfo));
}
Q_strcat(productionInfo, "\n", sizeof(productionInfo));
Q_strcat(productionInfo, va(_("Disassembly time\t%ih\n"), time), sizeof(productionInfo));
- Cvar_Set("mn_item", od->id);
MN_RegisterText(TEXT_PRODUCTION_INFO, productionInfo);
+ Cvar_Set("mn_item", ufo->id);
}
/**
@@ -427,10 +430,15 @@
MN_ExecuteConfunc("prod_taskselected");
if (prod->aircraft) {
PR_AircraftInfo(prod->aircraft);
- } else if (prod->production) {
+ MN_ExecuteConfunc("amountsetter enable");
+ } else if (prod->item) {
PR_ItemProductionInfo(base, prod->item, prod->percentDone);
+ MN_ExecuteConfunc("amountsetter enable");
+ } else if (prod->ufo) {
+ PR_DisassemblyInfo(base, prod->ufo, prod->percentDone);
+ MN_ExecuteConfunc("amountsetter disable");
} else {
- PR_DisassemblyInfo(base, prod->item, CL_GetComponentsByItem(prod->item), prod->percentDone);
+ Com_Error(ERR_DROP, "PR_ProductionInfo: Selected production is not item nor aircraft nor ufo.\n");
}
Cvar_SetValue("mn_production_amount", selectedProduction->amount);
} else {
@@ -448,7 +456,7 @@
} else if (selectedItem) {
PR_ItemProductionInfo(base, selectedItem, 0.0);
} else if (selectedDisassembly) {
- PR_DisassemblyInfo(base, selectedDisassembly->assemblyItem, selectedDisassembly, 0.0);
+ PR_DisassemblyInfo(base, selectedDisassembly, 0.0);
}
}
}
@@ -485,10 +493,12 @@
if (selectedProduction->aircraft) {
assert(selectedProduction->aircraft->tech);
UP_OpenWith(selectedProduction->aircraft->tech->id);
- } else {
+ } else if (selectedProduction->item) {
const objDef_t *od = selectedProduction->item;
assert(od->tech);
UP_OpenWith(od->tech->id);
+ } else if (selectedProduction->ufo) {
+ UP_OpenWith(selectedProduction->ufo->ufoTemplate->tech->id);
}
} else if (num >= queue->numItems + QUEUE_SPACERS) {
/* Clicked in the item list. */
@@ -502,9 +512,9 @@
if (aircraftTemplate && aircraftTemplate->tech)
UP_OpenWith(aircraftTemplate->tech->id);
} else if (produceCategory == FILTER_DISASSEMBLY) {
- components_t *comp = (components_t*)LIST_GetByIdx(productionItemList, idx);
- if (comp && comp->assemblyItem && comp->assemblyItem->tech) {
- UP_OpenWith(comp->assemblyItem->tech->id);
+ storedUFO_t *ufo = (storedUFO_t*)LIST_GetByIdx(productionItemList, idx);
+ if (ufo && ufo->ufoTemplate && ufo->ufoTemplate->tech) {
+ UP_OpenWith(ufo->ufoTemplate->tech->id);
}
} else {
objDef_t *od = (objDef_t*)LIST_GetByIdx(productionItemList, idx);
@@ -568,10 +578,10 @@
const int idx = num - queue->numItems - QUEUE_SPACERS;
if (produceCategory == FILTER_DISASSEMBLY) {
- components_t *comp = (components_t*)LIST_GetByIdx(productionItemList, idx);
+ storedUFO_t *ufo = (storedUFO_t*)LIST_GetByIdx(productionItemList, idx);
PR_ClearSelected();
- selectedDisassembly = comp;
+ selectedDisassembly = ufo;
PR_ProductionInfo(base);
} else if (produceCategory == FILTER_AIRCRAFT) {
@@ -650,7 +660,7 @@
if (produceCategory == FILTER_AIRCRAFT)
selectedAircraft = (aircraft_t*)LIST_GetByIdx(productionItemList, 0);
else if (produceCategory == FILTER_DISASSEMBLY)
- selectedDisassembly = (components_t*)LIST_GetByIdx(productionItemList, 0);
+ selectedDisassembly = (storedUFO_t*)LIST_GetByIdx(productionItemList, 0);
else
selectedItem = (objDef_t*)LIST_GetByIdx(productionItemList, 0);
}
@@ -702,7 +712,7 @@
*/
static void PR_ProductionIncrease_f (void)
{
- int amount = 1, amountTemp = 0;
+ int amount = 1;
production_queue_t *queue;
production_t *prod;
base_t *base = B_GetCurrentSelectedBase();
@@ -741,26 +751,8 @@
prod->amount += amount;
}
} else { /* Disassembling. */
- /* We can disassembly only as many items as we have in base storage. */
- if (base->storage.num[prod->item->idx] > amount)
- amountTemp = amount;
- else
- amountTemp = base->storage.num[prod->item->idx];
- Com_DPrintf(DEBUG_CLIENT, "PR_ProductionIncrease_f: amounts: storage: %i, param: %i, temp: %i\n", base->storage.num[prod->item->idx], amount, amountTemp);
-
- /* Now check if we can add more items and
- * remove the amount we just added to queue from base storage. */
- if (prod->amount + amountTemp > MAX_PRODUCTION_AMOUNT) {
- if (MAX_PRODUCTION_AMOUNT - prod->amount >= 0) {
- /* Calculate the maximum allowed amount to be added. */
- amountTemp = MAX_PRODUCTION_AMOUNT - prod->amount;
- } else {
- return;
- }
- }
-
- base->storage.num[prod->item->idx] -= amountTemp;
- prod->amount += amountTemp;
+ /* We can disassembly UFOs only one-by-one. */
+ return;
}
} else {
if (!selectedDisassembly) {
@@ -768,23 +760,10 @@
MN_Popup(_("Hangars not ready"), _("You cannot queue aircraft.\nNo free space in hangars.\n"));
return;
}
- prod = PR_QueueNew(base, queue, selectedItem, selectedAircraft, amount, qfalse); /* Production. (only of of the "selected" pointer can be nonNULL) */
+ prod = PR_QueueNew(base, queue, selectedItem, selectedAircraft, NULL, amount); /* Production. (only of of the "selected" pointer can be nonNULL) */
} else {
- /* We can disassemble only as many items as we have in base storage. */
- assert(selectedDisassembly && selectedDisassembly->assemblyItem);
-
- if (base->storage.num[selectedDisassembly->assemblyItem->idx] > amount)
- amountTemp = amount;
- else
- amountTemp = base->storage.num[selectedDisassembly->assemblyItem->idx];
-
- /* Check if we can add more items. */
- if (amountTemp > MAX_PRODUCTION_AMOUNT) {
- /* Add as many items as possible. */
- amountTemp = MAX_PRODUCTION_AMOUNT;
- }
-
- prod = PR_QueueNew(base, queue, selectedDisassembly->assemblyItem, NULL, amountTemp, qtrue); /* Disassembling. */
+ /* We can disassemble UFOs only one-by-one. */
+ prod = PR_QueueNew(base, queue, NULL, NULL, selectedDisassembly, 1); /* Disassembling. */
}
/** prod is NULL when queue limit is reached
@@ -796,7 +775,8 @@
} else
MN_ExecuteConfunc("prod_selectline %i", prod->idx);
- if (produceCategory != FILTER_AIRCRAFT) {
+
+ if (prod->item) {
/* Get technology of the item in the selected queue-entry. */
const objDef_t *od = prod->item;
int producibleAmount = amount;
@@ -816,13 +796,8 @@
amount, producibleAmount));
}
- if (!selectedDisassembly) {
- Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Production of %s started"), _(od->name));
- MSO_CheckAddNewMessage(NT_PRODUCTION_STARTED, _("Production started"), cp_messageBuffer, qfalse, MSG_PRODUCTION, od->tech);
- } else {
- Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Disassembling of %s started"), _(od->name));
- MSO_CheckAddNewMessage(NT_PRODUCTION_STARTED, _("Production started"), cp_messageBuffer, qfalse, MSG_PRODUCTION, od->tech);
- }
+ Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Production of %s started"), _(od->name));
+ MSO_CheckAddNewMessage(NT_PRODUCTION_STARTED, _("Production started"), cp_messageBuffer, qfalse, MSG_PRODUCTION, od->tech);
/* Now we select the item we just created. */
PR_ClearSelected();
@@ -835,7 +810,7 @@
* This info should also be displayed in the item-info.
* -) can can (if possible) change the 'amount' to a vlalue that _can_ be produced (i.e. the maximum amount possible).*/
}
- } else {
+ } else if (prod->aircraft) {
const aircraft_t *aircraftTemplate = prod->aircraft;
assert(aircraftTemplate);
assert(aircraftTemplate == aircraftTemplate->tpl);
@@ -846,6 +821,14 @@
/* Now we select the item we just created. */
PR_ClearSelected();
selectedProduction = &queue->items[queue->numItems - 1];
+ } else { /* Disassembly */
+ storedUFO_t *ufo = prod->ufo;
+
+ Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Disassembling of %s started"), _(UFO_TypeToName(ufo->ufoTemplate->ufotype)));
+ MSO_CheckAddNewMessage(NT_PRODUCTION_STARTED, _("Production started"), cp_messageBuffer, qfalse, MSG_PRODUCTION, ufo->ufoTemplate->tech);
+
+ PR_ClearSelected();
+ selectedProduction = &queue->items[queue->numItems - 1];
}
}
@@ -860,20 +843,22 @@
{
production_queue_t *queue;
base_t *base = B_GetCurrentSelectedBase();
+ int prodIDX;
if (!base || !selectedProduction)
return;
+ prodIDX = selectedProduction->idx;
queue = &ccs.productions[base->idx];
- PR_QueueDelete(base, queue, selectedProduction->idx);
+ PR_QueueDelete(base, queue, prodIDX);
if (queue->numItems == 0) {
selectedProduction = NULL;
MN_ExecuteConfunc("prod_selectline -1");
- } else if (selectedProduction->idx >= queue->numItems) {
+ } else if (prodIDX >= queue->numItems) {
selectedProduction = &queue->items[queue->numItems - 1];
- MN_ExecuteConfunc("prod_selectline %i", selectedProduction->idx);
+ MN_ExecuteConfunc("prod_selectline %i", prodIDX);
}
PR_ProductionInfo(base);
@@ -904,9 +889,6 @@
amountTemp = prod->amount;
prod->amount -= amountTemp;
- /* We need to readd items being disassembled to base storage. */
- if (!prod->production)
- base->storage.num[prod->item->idx] += amountTemp;
if (prod->amount <= 0) {
PR_ProductionStop_f();
Index: src/client/campaign/cp_produce.c
===================================================================
--- src/client/campaign/cp_produce.c (revision 25743)
+++ src/client/campaign/cp_produce.c (working copy)
@@ -5,7 +5,7 @@
*/
/*
-Copyright (C) 2002-2007 UFO: Alien Invasion team.
+Copyright (C) 2002-2009 UFO: Alien Invasion team.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -31,6 +31,7 @@
#include "../menu/m_nodes.h"
#include "../mxml/mxml_ufoai.h"
#include "cp_campaign.h"
+#include "cp_ufo.h"
#include "cp_produce_callbacks.h"
/** @brief Used in production costs (to allow reducing prices below 1x). */
@@ -56,7 +57,7 @@
* @sa PR_DisassemblyInfo
* @return 0 if the production does not make any progress, 1 if the whole item is built in 1 hour
*/
-float PR_CalculateProductionPercentDone (const base_t *base, const technology_t *tech, const components_t *comp, qboolean disassembly)
+float PR_CalculateProductionPercentDone (const base_t *base, const technology_t *tech, const components_t *comp)
{
signed int allworkers = 0, maxworkers = 0;
signed int timeDefault = 0;
@@ -72,11 +73,10 @@
maxworkers = allworkers;
}
- if (!disassembly) {
+ if (!comp) {
assert(tech);
timeDefault = tech->produceTime; /* This is the default production time for 10 workers. */
} else {
- assert(comp);
timeDefault = comp->time; /* This is the default disassembly time for 10 workers. */
}
@@ -148,7 +148,6 @@
*/
void PR_QueueDelete (base_t *base, production_queue_t *queue, int index)
{
- int i;
const objDef_t *od;
production_t *prod;
@@ -156,7 +155,9 @@
assert(base);
- if (prod->itemsCached && !prod->aircraft) {
+ if (prod->ufo) {
+ prod->ufo->disassembly = NULL;
+ } else if (prod->itemsCached && !prod->aircraft) {
/* Get technology of the item in the selected queue-entry. */
od = prod->item;
if (od->tech) {
@@ -168,20 +169,7 @@
prod->itemsCached = qfalse;
}
- /* Read disassembly to base storage. */
- if (!prod->production)
- base->storage.num[prod->item->idx] += prod->amount;
-
- queue->numItems--;
- if (queue->numItems < 0)
- queue->numItems = 0;
-
- /* Copy up other items. */
- for (i = index; i < queue->numItems; i++) {
- queue->items[i] = queue->items[i + 1];
- /* Fix index in list */
- queue->items[i].idx = i;
- }
+ REMOVE_ELEM_ADJUST_IDX(queue->items, index, queue->numItems);
}
/**
@@ -205,17 +193,23 @@
for (i = index; i < newIndex; i++) {
queue->items[i] = queue->items[i + 1];
queue->items[i].idx = i;
+ if (queue->items[i].ufo)
+ queue->items[i].ufo->disassembly = &(queue->items[i]);
}
/* copy down */
for (i = index; i > newIndex; i--) {
queue->items[i] = queue->items[i - 1];
queue->items[i].idx = i;
+ if (queue->items[i].ufo)
+ queue->items[i].ufo->disassembly = &(queue->items[i]);
}
/* insert item */
queue->items[newIndex] = saved;
queue->items[newIndex].idx = newIndex;
+ if (queue->items[newIndex].ufo)
+ queue->items[newIndex].ufo->disassembly = &(queue->items[newIndex]);
}
/**
@@ -310,6 +304,7 @@
int i;
const objDef_t *od;
const aircraft_t *aircraft;
+ storedUFO_t *ufo;
production_t *prod;
/* Loop through all founded bases. Then check productions
@@ -333,14 +328,20 @@
if (prod->item) {
od = prod->item;
aircraft = NULL;
- } else {
+ ufo = NULL;
+ } else if (prod->aircraft) {
assert(prod->aircraft);
od = NULL;
aircraft = prod->aircraft;
+ ufo = NULL;
+ } else {
+ od = NULL;
+ aircraft = NULL;
+ ufo = prod->ufo;
}
if (prod->production) { /* This is production, not disassembling. */
- if (!prod->aircraft) {
+ if (od) {
/* Not enough money to produce more items in this base. */
if (od->price * PRODUCE_FACTOR / PRODUCE_DIVISOR > ccs.credits) {
if (!prod->creditMessage) {
@@ -384,7 +385,7 @@
}
}
} else { /* This is disassembling. */
- if (base->capacities[CAP_ITEMS].max - base->capacities[CAP_ITEMS].cur < PR_DisassembleItem(NULL, CL_GetComponentsByItem(prod->item), qtrue)) {
+ if (base->capacities[CAP_ITEMS].max - base->capacities[CAP_ITEMS].cur < PR_DisassembleItem(NULL, ufo->comp, qtrue)) {
if (!prod->spaceMessage) {
Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Not enough free storage space in base %s. Disassembling postponed.\n"), base->name);
MSO_CheckAddNewMessage(NT_PRODUCTION_FAILED, _("Notice"), cp_messageBuffer, qfalse, MSG_STANDARD, NULL);
@@ -395,16 +396,13 @@
}
}
- if (!prod->aircraft && !od->tech)
- Com_Error(ERR_FATAL, "PR_ProductionRun: No tech pointer for object %s ('%s')", prod->item->id, od->id);
-
if (prod->production) { /* This is production, not disassembling. */
if (!prod->aircraft)
- prod->percentDone += (PR_CalculateProductionPercentDone(base, od->tech, NULL, qfalse) / MINUTES_PER_HOUR);
+ prod->percentDone += (PR_CalculateProductionPercentDone(base, od->tech, NULL) / MINUTES_PER_HOUR);
else
- prod->percentDone += (PR_CalculateProductionPercentDone(base, aircraft->tech, NULL, qfalse) / MINUTES_PER_HOUR);
+ prod->percentDone += (PR_CalculateProductionPercentDone(base, aircraft->tech, NULL) / MINUTES_PER_HOUR);
} else /* This is disassembling. */
- prod->percentDone += (PR_CalculateProductionPercentDone(base, od->tech, CL_GetComponentsByItem(prod->item), qtrue) / MINUTES_PER_HOUR);
+ prod->percentDone += (PR_CalculateProductionPercentDone(base, ufo->ufoTemplate->tech, ufo->comp) / MINUTES_PER_HOUR);
if (prod->percentDone >= 1.0f) {
if (prod->production) { /* This is production, not disassembling. */
@@ -435,28 +433,14 @@
}
}
} else { /* This is disassembling. */
- base->capacities[CAP_ITEMS].cur += PR_DisassembleItem(base, CL_GetComponentsByItem(prod->item), qfalse);
+ base->capacities[CAP_ITEMS].cur += PR_DisassembleItem(base, ufo->comp, qfalse);
prod->percentDone = 0.0f;
prod->amount--;
- /* If this is aircraft dummy item, update UFO hangars capacity. */
- if (od->tech->type == RS_CRAFT) {
- const aircraft_t *ufocraft = AIR_GetAircraft(od->id);
- assert(ufocraft);
- if (ufocraft->size == AIRCRAFT_LARGE) {
- /* Large UFOs can only be stored in Large UFO Hangar */
- if (base->capacities[CAP_UFOHANGARS_LARGE].cur > 0)
- base->capacities[CAP_UFOHANGARS_LARGE].cur--;
- } else {
- /* Small UFOs can only be stored in Small UFO Hangar */
- if (base->capacities[CAP_UFOHANGARS_SMALL].cur > 0)
- base->capacities[CAP_UFOHANGARS_SMALL].cur--;
- }
- }
- if (prod->amount <= 0) {
- Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("The disassembling of %s has finished."), _(od->name));
- MSO_CheckAddNewMessage(NT_PRODUCTION_FINISHED, _("Production finished"), cp_messageBuffer, qfalse, MSG_PRODUCTION, od->tech);
- PR_QueueNext(base);
- }
+
+ Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("The disassembling of %s has finished."), _(UFO_TypeToName(ufo->ufoTemplate->ufotype)));
+ MSO_CheckAddNewMessage(NT_PRODUCTION_FINISHED, _("Production finished"), cp_messageBuffer, qfalse, MSG_PRODUCTION, ufo->ufoTemplate->tech);
+
+ US_RemoveStoredUFO(ufo);
}
}
}
@@ -517,6 +501,23 @@
}
/**
+ * @brief Returns the base pointer the production belongs to
+ * @param[in] production pointer to the production entry
+ * @returns base_t pointer to the base
+ */
+base_t *PR_ProductionBase (production_t *production) {
+ int i;
+ for (i = 0; i < ccs.numBases; i++) {
+ base_t *base = B_GetBaseByIDX(i);
+ const ptrdiff_t diff = ((ptrdiff_t)((production) - ccs.productions[i].items));
+
+ if (diff >= 0 && diff < MAX_PRODUCTIONS)
+ return base;
+ }
+ return NULL;
+}
+
+/**
* @brief Save callback for savegames in XML Format
* @sa PR_LoadXML
* @sa SAV_GameSaveXML
@@ -528,21 +529,25 @@
for (i = 0; i < MAX_BASES; i++) {
const production_queue_t *pq = &ccs.productions[i];
int j;
- mxml_node_t * snode = mxml_AddNode(node, "queue");
+ mxml_node_t *snode = mxml_AddNode(node, "queue");
+
mxml_AddInt(snode, "numitems", pq->numItems);
+
for (j = 0; j < pq->numItems; j++) {
- /** @todo This will crash */
const objDef_t *item = pq->items[j].item;
const aircraft_t *aircraft = pq->items[j].aircraft;
+ const storedUFO_t *ufo = pq->items[j].ufo;
+
mxml_node_t * ssnode = mxml_AddNode(snode, "item");
- assert(item || aircraft);
+ assert(item || aircraft || ufo);
if (item)
mxml_AddString(ssnode, "itemid", item->id);
+ else if (aircraft)
+ mxml_AddString(ssnode, "aircraftid", aircraft->id);
+ else if (ufo)
+ mxml_AddInt(ssnode, "ufoidx", ufo->idx);
mxml_AddInt(ssnode, "amount", pq->items[j].amount);
mxml_AddFloat(ssnode, "percentdone", pq->items[j].percentDone);
- mxml_AddBool(ssnode, "prod", pq->items[j].production);
- if (aircraft)
- mxml_AddString(ssnode, "aircraftid", aircraft->id);
mxml_AddBool(ssnode, "items_cached", pq->items[j].itemsCached);
}
}
@@ -566,23 +571,84 @@
int j;
mxml_node_t *ssnode;
production_queue_t *pq = &ccs.productions[i];
+
pq->numItems = mxml_GetInt(snode, "numitems", 0);
+
+ if (pq->numItems > MAX_PRODUCTIONS) {
+ Com_Printf("PR_Load: Too much productions (%i), last %i dropped (baseidx=%i).\n", pq->numItems, pq->numItems - MAX_PRODUCTIONS, i);
+ pq->numItems = MAX_PRODUCTIONS;
+ }
+
for (j = 0, ssnode = mxml_GetNode(snode, "item"); j < pq->numItems && ssnode;
j++, ssnode = mxml_GetNextNode(ssnode, snode, "item")) {
const char *s1 = mxml_GetString(ssnode, "itemid");
const char *s2;
+ int ufoIDX;
+
+ pq->items[j].idx = j;
+ pq->items[j].amount = mxml_GetInt(ssnode, "amount", 0);
+ pq->items[j].percentDone = mxml_GetFloat(ssnode, "percentdone", 0.0);
+
if (s1 && s1[0] != '\0')
pq->items[j].item = INVSH_GetItemByID(s1);
- pq->items[j].idx = j;
- pq->items[j].amount = mxml_GetInt(ssnode, "amount", 0);
+
+ /* This if block is for keeping compatibility with base-stored ufos */
+ /* @todo remove this on release (or after time) */
+ if (!mxml_GetBool(ssnode, "prod", qtrue)) {
+ const int amount = pq->items[j].amount;
+ int k;
+ aircraft_t *ufoTemplate = (pq->items[j].item) ? AIR_GetAircraft(pq->items[j].item->id) : NULL;
+
+ for (k = 0; k < amount; k++) {
+ installation_t *installation = INS_GetFirstUFOYard(qtrue);
+ storedUFO_t *ufo = NULL;
+
+ if (ufoTemplate && installation)
+ ufo = US_StoreUFO(ufoTemplate, installation, ccs.date);
+
+ if (ufo) {
+ pq->items[j + k].idx = j + k;
+ pq->items[j + k].item = NULL;
+ pq->items[j + k].ufo = ufo;
+ pq->items[j + k].amount = 1;
+ pq->items[j + k].percentDone = (k) ? 0.0 : pq->items[j + k].percentDone;
+ pq->items[j + k].production = qfalse;
+ ufo->disassembly = &(pq->items[j + k]);
+ } else {
+ Com_Printf("PR_Load: Could not add ufo to the UFO Yards, disassembly dropped (baseidx=%i, production idx=%i).\n", i, j);
+ j--;
+ pq->numItems--;
+ continue;
+ }
+ }
+ j += k - 1;
+ pq->numItems += k - 1;
+ continue;
+ }
+
if (pq->items[j].amount <= 0) {
Com_Printf("PR_Load: Production with amount <= 0 dropped (baseidx=%i, production idx=%i).\n", i, j);
j--;
pq->numItems--;
continue;
}
- pq->items[j].percentDone = mxml_GetFloat(ssnode, "percentdone", 0.0);
- pq->items[j].production = mxml_GetBool(ssnode, "prod", qfalse);
+
+ ufoIDX = mxml_GetInt(ssnode, "ufoidx", MAX_STOREDUFOS);
+ if (ufoIDX != MAX_STOREDUFOS) {
+ storedUFO_t *ufo = US_GetStoredUFOByIDX(ufoIDX);
+
+ if (!ufo) {
+ Com_Printf("PR_Load: Could not find ufo idx: %i\n", ufoIDX);
+ return qfalse;
+ }
+
+ pq->items[j].ufo = ufo;
+ pq->items[j].production = qfalse;
+ pq->items[j].ufo->disassembly = &(pq->items[j]);
+ } else {
+ pq->items[j].production = qtrue;
+ }
+
s2 = mxml_GetString(ssnode, "aircraftid");
if (s2 && s2[0] != '\0')
pq->items[j].aircraft = AIR_GetAircraft(s2);
Index: src/client/campaign/cp_save.h
===================================================================
--- src/client/campaign/cp_save.h (revision 25743)
+++ src/client/campaign/cp_save.h (working copy)
@@ -4,7 +4,7 @@
*/
/*
-Copyright (C) 2002-2007 UFO: Alien Invasion team.
+Copyright (C) 2002-2009 UFO: Alien Invasion team.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -87,6 +87,8 @@
qboolean INS_LoadXML(mxml_node_t *parent);
qboolean MSO_SaveXML(mxml_node_t *parent);
qboolean MSO_LoadXML(mxml_node_t *parent);
+qboolean US_SaveXML(mxml_node_t *parent);
+qboolean US_LoadXML(mxml_node_t *parent);
void B_PostLoadInit(void);
Index: src/client/campaign/cp_missions.c
===================================================================
--- src/client/campaign/cp_missions.c (revision 25743)
+++ src/client/campaign/cp_missions.c (working copy)
@@ -342,7 +342,7 @@
shortUFOType = Com_UFOTypeToShortName(ccs.selectedMission->ufo->ufotype);
}
- Com_sprintf(mission->onwin, sizeof(mission->onwin), "cp_uforecovery_init %i;", mission->ufo->ufotype);
+ Com_sprintf(mission->onwin, sizeof(mission->onwin), "cp_uforecovery_init %s", mission->ufo->id);
/* Set random map UFO if this is a random map */
if (mission->mapDef->map[0] == '+') {
/* set rm_ufo to the ufo type used */
Index: src/client/campaign/cp_produce_callbacks.h
===================================================================
--- src/client/campaign/cp_produce_callbacks.h (revision 25743)
+++ src/client/campaign/cp_produce_callbacks.h (working copy)
@@ -4,7 +4,7 @@
*/
/*
- Copyright (C) 1997-2008 UFO:AI Team
+ Copyright (C) 1997-2009 UFO:AI Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -23,10 +23,10 @@
*/
-#ifndef CLIENT_CL_PRODUCE_CALLBACKS_H
-#define CLIENT_CL_PRODUCE_CALLBACKS_H
+#ifndef CLIENT_CP_PRODUCE_CALLBACKS_H
+#define CLIENT_CP_PRODUCE_CALLBACKS_H
void PR_InitCallbacks (void);
void PR_ShutdownCallbacks (void);
-#endif /* CLIENT_CL_PRODUCE_CALLBACKS_H */
+#endif /* CLIENT_CP_PRODUCE_CALLBACKS_H */
Index: src/client/campaign/cp_produce.h
===================================================================
--- src/client/campaign/cp_produce.h (revision 25743)
+++ src/client/campaign/cp_produce.h (working copy)
@@ -4,7 +4,7 @@
*/
/*
-Copyright (C) 2002-2007 UFO: Alien Invasion team.
+Copyright (C) 2002-2009 UFO: Alien Invasion team.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -23,8 +23,8 @@
*/
-#ifndef CLIENT_CL_PROOUCE
-#define CLIENT_CL_PROOUCE
+#ifndef CLIENT_CP_PRODUCE
+#define CLIENT_CP_PRODUCE
#include "../cl_inventory.h"
@@ -50,7 +50,8 @@
* @todo Make this a union
*/
objDef_t *item; /**< Item to be produced. */
- struct aircraft_s *aircraft; /**< Aircraft (sample) to be produced. @todo Is there any way to make this const without cl_produce.c to break?*/
+ struct aircraft_s *aircraft; /**< Aircraft (sample) to be produced. @todo Is there any way to make this const without cp_produce.c to break?*/
+ struct storedUFO_s *ufo;
signed int amount; /**< How much are we producing. */
float percentDone; /**< Fraction of the item which is already produced.
@@ -80,6 +81,7 @@
void PR_QueueMove (production_queue_t *queue, int index, int dir);
void PR_QueueDelete (base_t *base, production_queue_t *queue, int index);
void PR_UpdateRequiredItemsInBasestorage (base_t *base, int amount, requirements_t *reqs);
-float PR_CalculateProductionPercentDone (const base_t *base, const technology_t *tech, const components_t *comp, qboolean disassembly);
+float PR_CalculateProductionPercentDone (const base_t *base, const technology_t *tech, const components_t *comp);
+base_t *PR_ProductionBase(production_t *production);
-#endif /* CLIENT_CL_PROOUCE */
+#endif /* CLIENT_CP_PRODUCE */
Index: src/client/campaign/cp_uforecovery_callbacks.c
===================================================================
--- src/client/campaign/cp_uforecovery_callbacks.c (revision 25743)
+++ src/client/campaign/cp_uforecovery_callbacks.c (working copy)
@@ -1,11 +1,12 @@
/**
* @file cp_uforecovery_callbacks.c
- * @brief UFO recovery callback functions
- * @note Functions with UR_*
+ * @brief UFO recovery and storing callback functions
+ * @note UFO recovery functions with UR_*
+ * @note UFO storing functions with US_*
*/
/*
-Copyright (C) 2002-2007 UFO: Alien Invasion team.
+Copyright (C) 2002-2009 UFO: Alien Invasion team.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -33,24 +34,18 @@
#include "../menu/m_main.h"
#include "../menu/node/m_node_text.h"
-typedef struct ufoRecoveryStorage_s {
- base_t *base; /**< base where actual ufo is located */
- aircraft_t *ufoTemplate; /**< template of ufo for storage id and name */
- objDef_t *ufoItem; /**< object definition of aircraft, used for capacity check */
-} ufoRecoveryStorage_t;
+#ifdef DEBUG
+#include "cp_time.h"
+#endif
/** @sa ufoRecoveries_t */
typedef struct ufoRecovery_s {
- base_t *base; /**< selected base for current selected ufo recovery */
- ufoType_t ufoType; /**< the ufo type of the current ufo recovery */
+ installation_t *installation; /**< selected ufoyard for current selected ufo recovery */
+ aircraft_t *ufoTemplate; /**< the ufo type of the current ufo recovery */
nation_t *nation; /**< selected nation to sell to for current ufo recovery */
qboolean recoveryDone; /**< recoveryDone? Then the buttons are disabled */
- base_t *UFObases[MAX_BASES]; /**< Array of base indexes where we can store UFO. */
- int baseHasUFOHangarCount; /**< number of entries in the UFObases array */
+
int UFOprices[MAX_NATIONS]; /**< Array of prices proposed by nation. */
- ufoRecoveryStorage_t replaceUFOs[MAX_BASES * UFO_MAX]; /**< Array of replaceable ufos in all bases */
- ufoRecoveryStorage_t *selectedStorage; /**< selected storage for replace */
- int replaceCount; /**< number of replaceable ufos in all bases */
} ufoRecovery_t;
static ufoRecovery_t ufoRecovery;
@@ -64,365 +59,132 @@
}
/**
- * @brief Checks conditions for storing given ufo in given base.
- * @param[in] base Pointer to the base, where we are going to store UFO.
- * @param[in] ufocraft Pointer to ufocraft which we are going to store.
- * @return qtrue if given base can store given ufo.
- */
-static int UR_GetBaseCapacityForUfotype (const base_t *base, const aircraft_t *ufocraft)
-{
- assert(base && ufocraft);
-
- if (ufocraft->size == AIRCRAFT_LARGE) {
- /* Large UFOs can only fit large UFO hangars */
- if (!B_GetBuildingStatus(base, B_UFO_HANGAR))
- return -1;
-
- /* Check there is still enough room for this UFO */
- return base->capacities[CAP_UFOHANGARS_LARGE].max;
- } else {
- /* This is a small UFO, can only fit in small hangar */
-
- /* There's no small hangar functional */
- if (!B_GetBuildingStatus(base, B_UFO_SMALL_HANGAR))
- return -1;
-
- /* Check there is still enough room for this UFO */
- return base->capacities[CAP_UFOHANGARS_SMALL].max;
- }
-}
-
-
-/**
- * @brief Select appropriate the base or replace option from list
- * @param num selected index must be within valid range
- */
-static void UR_DialogSelectStorageBase (const int num)
-{
- qboolean useBase = qtrue;
- if (num < ufoRecovery.baseHasUFOHangarCount) {
- if (!ufoRecovery.UFObases[num])
- return;
- } else {
- useBase = qfalse;
- if (!ufoRecovery.replaceUFOs[num - ufoRecovery.baseHasUFOHangarCount].base)
- return;
- }
-
- if (useBase) {
- ufoRecovery.base = ufoRecovery.UFObases[num];
- Com_DPrintf(DEBUG_CLIENT, "CP_UFORecoveryBaseSelectPopup_f: picked base: %s\n", ufoRecovery.base->name);
- MN_ExecuteConfunc("btbasesel_enable");
- } else {
- ufoRecovery.selectedStorage = &ufoRecovery.replaceUFOs[num - ufoRecovery.baseHasUFOHangarCount];
- Com_DPrintf(DEBUG_CLIENT, "CP_UFORecoveryBaseSelectPopup_f: picked replace ufo %s from base %s\n",
- ufoRecovery.selectedStorage->ufoTemplate->id, ufoRecovery.selectedStorage->base->name);
- ufoRecovery.base = ufoRecovery.selectedStorage->base;
- MN_ExecuteConfunc("btbaserepl_enable");
- }
- Cvar_Set("mission_recoverybase", ufoRecovery.base->name);
-}
-
-/**
* @brief Function to trigger UFO Recovered event.
* @note This function prepares related cvars for the recovery dialog.
* @note Command to call this: cp_uforecovery_init.
*/
static void UR_DialogInit_f (void)
{
- int i;
- ufoType_t UFOtype;
- aircraft_t *ufocraft;
- qboolean ufofound = qfalse;
+ char ufoID[MAX_VAR];
+ aircraft_t *ufoCraft = NULL;
if (Cmd_Argc() < 2) {
- Com_Printf("Usage: %s <UFOType>\n", Cmd_Argv(0));
+ Com_Printf("Usage: %s <ufoID>\n", Cmd_Argv(0));
return;
}
- if ((atoi(Cmd_Argv(1)) >= 0) && (atoi(Cmd_Argv(1)) < UFO_MAX)) {
- UFOtype = atoi(Cmd_Argv(1));
- } else {
- Com_Printf("CP_UFORecovered: UFOType: %i does not exist!\n", atoi(Cmd_Argv(1)));
- return;
- }
-
- ufocraft = NULL;
- /* Find ufo sample of given ufotype. */
- for (i = 0; i < ccs.numAircraftTemplates; i++) {
- ufocraft = &ccs.aircraftTemplates[i];
- if (ufocraft->type != AIRCRAFT_UFO)
- continue;
- if (ufocraft->ufotype == UFOtype) {
- ufofound = qtrue;
- break;
- }
- }
+ Q_strncpyz(ufoID, Cmd_Argv(1), sizeof(ufoID));
+ ufoCraft = AIR_GetAircraft(ufoID);
/* Do nothing without UFO of this type. */
- if (!ufofound) {
- Com_Printf("CP_UFORecovered: UFOType: %i does not have valid craft definition!\n", atoi(Cmd_Argv(1)));
+ if (!ufoCraft) {
+ Com_Printf("CP_UFORecovered: UFO Type: %s is not a valid craft definition!\n", ufoID);
return;
}
/* Put relevant info into missionResults array. */
ccs.missionResults.recovery = qtrue;
ccs.missionResults.crashsite = qfalse;
- ccs.missionResults.ufotype = ufocraft->ufotype;
+ ccs.missionResults.ufotype = ufoCraft->ufotype;
/* Prepare related cvars. */
Cvar_SetValue("mission_uforecovered", 1); /* This is used in menus to enable UFO Recovery nodes. */
memset(&ufoRecovery, 0, sizeof(ufoRecovery));
- ufoRecovery.ufoType = UFOtype;
+ ufoRecovery.ufoTemplate = ufoCraft;
+ Cvar_Set("mn_uforecovery_actualufo", UFO_MissionResultToString());
}
/**
- * @brief Function calculates prices for actual ufo to sell and initializes menu text.
- * @param ufocraft the ufo type to sell
- * @note called by UR_DialogInitSell_f and UR_DialogStartReplace
- */
-static void UR_DialogInitSell (aircraft_t *ufocraft)
-{
- int i, nations = 0;
- static char recoveryNationSelectPopup[MAX_SMALLMENUTEXTLEN];
-
- recoveryNationSelectPopup[0] = '\0';
-
- for (i = 0; i < ccs.numNations; i++) {
- const nation_t *nation = &ccs.nations[i];
- nations++;
- /* Calculate price offered by nation only if this is first popup opening. */
- if (!ufoRecovery.nation) {
- ufoRecovery.UFOprices[i] = (int) (ufocraft->price * (.85f + frand() * .3f));
- /* Nation will pay less if corrupted */
- ufoRecovery.UFOprices[i] = (int) (ufoRecovery.UFOprices[i] * exp(-nation->stats[0].xviInfection / 20.0f));
- }
- Com_sprintf(recoveryNationSelectPopup + strlen(recoveryNationSelectPopup), sizeof(recoveryNationSelectPopup),
- "%s\t\t\t%i\t\t%s\n", _(nation->name), ufoRecovery.UFOprices[i], NAT_GetHappinessString(nation));
- }
-
- /* Do nothing without at least one nation. */
- if (nations == 0)
- return;
-
- MN_RegisterText(TEXT_UFORECOVERY_NATIONS, recoveryNationSelectPopup);
-}
-
-/**
* @brief Function to initialize list of storage locations for recovered UFO.
* @note Command to call this: cp_uforecovery_store_init.
* @sa UR_ConditionsForStoring
*/
static void UR_DialogInitStore_f (void)
{
- int i,j, replaceTemplates = 0;
- aircraft_t *ufocraft;
- linkedList_t *recoveryBaseSelectPopup = NULL;
- qboolean ufofound = qfalse;
- linkedList_t *validReplaceTemplateList = NULL, *replaceObjDefList = NULL;
+ int i;
+ int count = 0;
+ linkedList_t *recoveryYardSelectPopup = NULL;
- /* Do nothing without any base. */
- if (!ccs.numBases)
- return;
-
/* Do nothing if recovery process is finished. */
if (ufoRecovery.recoveryDone)
return;
- /* Find ufo sample of given ufotype. */
- for (i = 0; i < ccs.numAircraftTemplates; i++) {
- ufocraft = &ccs.aircraftTemplates[i];
- if (ufocraft->type != AIRCRAFT_UFO)
- continue;
- if (ufocraft->ufotype == ufoRecovery.ufoType) {
- ufofound = qtrue;
- break;
- }
- }
+ /* Check how many bases can store this UFO. */
+ for (i = 0; i < ccs.numInstallations; i++) {
+ installation_t *installation = INS_GetFoundedInstallationByIDX(i);
- /* Do nothing without UFO of this type. */
- if (!ufofound) {
- Com_Printf("CP_UFORecoveredStore_f: UFOType: %i does not have valid craft definition!\n", ufoRecovery.ufoType);
- return;
- }
-
- /* find valid replace templates */
- for (i = 0; i < ccs.numAircraftTemplates; i++) {
- aircraft_t *tempcraft = &ccs.aircraftTemplates[i];
- if (tempcraft == ufocraft)
+ if (!installation)
continue;
- if (tempcraft->type != AIRCRAFT_UFO)
- continue;
- if (tempcraft->size == ufocraft->size) {
- LIST_AddPointer(&validReplaceTemplateList,tempcraft);
- LIST_AddPointer(&replaceObjDefList,INVSH_GetItemByID(tempcraft->id));
- replaceTemplates++;
- }
- }
- /* Clear UFObases. */
- memset(ufoRecovery.UFObases, 0, sizeof(ufoRecovery.UFObases));
-
- /* Check how many bases can store this UFO. */
- for (i = 0; i < MAX_BASES; i++) {
- base_t *base = B_GetFoundedBaseByIDX(i);
- if (!base)
- continue;
- if (UR_ConditionsForStoring(base, ufocraft)) {
- LIST_AddString(&recoveryBaseSelectPopup, base->name);
- ufoRecovery.UFObases[ufoRecovery.baseHasUFOHangarCount++] = base;
- } else {
- int baseCapacity = UR_GetBaseCapacityForUfotype(base, ufocraft);
- if (baseCapacity > 0)
- {
- linkedList_t *curTemplate = validReplaceTemplateList;
- linkedList_t *curObjID = replaceObjDefList;
- for (j = 0; j < replaceTemplates; j++) {
- objDef_t *obj = (objDef_t*)curObjID->data;
- aircraft_t *craft = (aircraft_t *)curTemplate->data;
- if (base->storage.num[obj->idx] > 0) {
- /* found a valid replace, add it */
- ufoRecoveryStorage_t *store = &ufoRecovery.replaceUFOs[ufoRecovery.replaceCount];
- store->base = base;
- store->ufoItem = obj;
- store->ufoTemplate = craft;
- ufoRecovery.replaceCount++;
- }
- curObjID = curObjID->next;
- curTemplate = curTemplate->next;
- }
- }
+ if (installation->ufoCapacity.max > 0
+ && installation->ufoCapacity.max > installation->ufoCapacity.cur) {
+ LIST_AddString(&recoveryYardSelectPopup, installation->name);
+ count++;
}
}
- for (i = 0; i < ufoRecovery.replaceCount; i++)
- {
- ufoRecoveryStorage_t store = ufoRecovery.replaceUFOs[i];
- LIST_AddString(&recoveryBaseSelectPopup, va(_("Replace %s at %s (%i stored available)\n"), _(store.ufoItem->name), store.base->name, store.base->storage.num[store.ufoItem->idx] ));
- }
-
- /* If only one base with UFO hangars, the recovery will be done in this base. */
- switch (ufoRecovery.baseHasUFOHangarCount + ufoRecovery.replaceCount) {
- case 0:
+ Cvar_Set("mn_uforecovery_actualufo", UFO_MissionResultToString());
+ if (count == 0) {
/* No UFO base with proper conditions, show a hint and disable list. */
- LIST_AddString(&recoveryBaseSelectPopup, _("No ufo hangar or ufo yard available."));
- MN_ExecuteConfunc("cp_basesel_disable");
- break;
- case 1:
- /* there should only be one entry in UFObases - so use that one. */
- if (ufoRecovery.baseHasUFOHangarCount)
- ufoRecovery.base = ufoRecovery.UFObases[0];
- else
- ufoRecovery.selectedStorage = &ufoRecovery.replaceUFOs[0];
- UR_DialogSelectStorageBase(0);
- /** @todo some better way to do so without the need of a confunc? */
- MN_ExecuteConfunc("cp_basesel_select");
- break;
- default:
- /** @todo check whether this is needed */
- if (!ufoRecovery.base)
- ufoRecovery.base = ufoRecovery.UFObases[0];
- if (ufoRecovery.base)
- Cvar_Set("mission_recoverybase", ufoRecovery.base->name);
- break;
+ LIST_AddString(&recoveryYardSelectPopup, _("No free ufo yard available."));
+ MN_ExecuteConfunc("uforecovery_tabselect sell");
+ MN_ExecuteConfunc("btbasesel disable");
+ } else {
+ MN_ExecuteConfunc("cp_basesel_select 0");
+ MN_ExecuteConfunc("btbasesel enable");
}
- Cvar_Set("mn_uforecovery_actualufo",UFO_MissionResultToString());
- MN_RegisterLinkedListText(TEXT_UFORECOVERY_BASESTORAGE, recoveryBaseSelectPopup);
+ MN_RegisterLinkedListText(TEXT_UFORECOVERY_BASESTORAGE, recoveryYardSelectPopup);
}
/**
- * @brief Finds the destination base for UFO recovery.
- * @note The base selection is being done here.
- * @note Callback command: cp_uforecovery_baselist_click.
+ * @brief Function to start UFO recovery process.
+ * @note Command to call this: cp_uforecovery_store_start.
*/
-static void UR_DialogSelectStorageBase_f (void)
+static void UR_DialogStartStore_f (void)
{
- int num;
+ installation_t *UFOYard = NULL;
+ int idx;
+ int i;
+ int count = 0;
+ date_t date;
if (Cmd_Argc() < 2) {
- Com_Printf("Usage: %s <baseid>\n", Cmd_Argv(0));
+ Com_Printf("Usage: %s <installationIDX>\n", Cmd_Argv(0));
return;
}
- num = atoi(Cmd_Argv(1));
- if (num < 0 || num >= ufoRecovery.replaceCount + ufoRecovery.baseHasUFOHangarCount)
- return;
+ idx = atoi(Cmd_Argv(1));
- UR_DialogSelectStorageBase(num);
-}
+ for (i = 0; i < ccs.numInstallations; i++) {
+ installation_t *installation = INS_GetFoundedInstallationByIDX(i);
-/**
- * @brief Function starts the UFO recovery process.
- * @note Called by UR_DialogStartStore_f and UR_DialogStartReplace_f
- * @note uforecovery base value must be set
- * @param finish flag indicating whether uforecovery should me marked as done
- */
-static void UR_DialogStartStore (qboolean finish)
-{
- base_t *base = ufoRecovery.base;
- Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Recovered %s from the battlefield. UFO is being transported to base %s."), UFO_TypeToName(
- ufoRecovery.ufoType), base->name);
- MS_AddNewMessage(_("UFO Recovery"), cp_messageBuffer, qfalse, MSG_STANDARD, NULL);
- UR_Prepare(base, ufoRecovery.ufoType);
+ if (!installation)
+ continue;
- if (finish)
- /* UFO recovery process is done, disable buttons. */
- UR_DialogRecoveryDone();
-}
+ if (installation->ufoCapacity.max <= 0
+ || installation->ufoCapacity.max <= installation->ufoCapacity.cur)
+ continue;
+
+ if (count == idx) {
+ UFOYard = installation;
+ break;
+ }
+ count++;
+ }
-/**
- * @brief Function to start UFO recovery process.
- * @note Command to call this: cp_uforecovery_store_start.
- * @note This needs the ufoRecovery base value set
- */
-static void UR_DialogStartStore_f (void)
-{
- base_t *base = ufoRecovery.base;
- if (!base)
+ if (!UFOYard)
return;
- UR_DialogStartStore(qtrue);
-}
+ Com_sprintf(cp_messageBuffer, lengthof(cp_messageBuffer), _("Recovered %s from the battlefield. UFO is being transported to %s."), _(UFO_TypeToName(ufoRecovery.ufoTemplate->ufotype)), UFOYard->name);
+ MS_AddNewMessage(_("UFO Recovery"), cp_messageBuffer, qfalse, MSG_STANDARD, NULL);
+/* UR_Prepare(UFOYard, ufoRecovery.ufoTemplate->ufotype); */
+ date = ccs.date;
+ date.day += (int) RECOVERY_DELAY;
+/* date.sec += (RECOVERY_DELAY - (int) RECOVERY_DELAY) % SECONDS_PER_DAY;*/
-/**
- * @brief Function to start replace process
- * @note Command to call this: cp_uforecovery_replace
- * @note This needs the uforecovery selectedStorage value set
- */
-static void UR_DialogStartReplace_f (void)
-{
- linkedList_t *replacetext = NULL;
- ufoRecoveryStorage_t *storage = ufoRecovery.selectedStorage;
- if (!storage)
- return;
- /** @todo can these asserts be merged into one? */
- assert(storage->base);
- assert(storage->ufoItem);
- assert(storage->ufoTemplate);
+ US_StoreUFO(ufoRecovery.ufoTemplate, UFOYard, date);
- /* update hangar cap, remove old ufo*/
- storage->base->storage.num[storage->ufoItem->idx]--;
- if (storage->ufoTemplate->size == AIRCRAFT_LARGE) {
- if (storage->base->capacities[CAP_UFOHANGARS_LARGE].cur > 0)
- storage->base->capacities[CAP_UFOHANGARS_LARGE].cur--;
- else
- Com_Printf("UR_DialogStartReplace_f: Large UFO-hangar capacity is not greater than zero for replacing a UFO.");
- } else {
- if (storage->base->capacities[CAP_UFOHANGARS_SMALL].cur > 0)
- storage->base->capacities[CAP_UFOHANGARS_SMALL].cur--;
- else
- Com_Printf("UR_DialogStartReplace_f: Small UFO-hangar capacity is not greater than zero for replacing a UFO.");
- }
- /* reinit sell values for replaced ufo */
- memset(ufoRecovery.UFOprices,-1,sizeof(ufoRecovery.UFOprices));
- ufoRecovery.nation = NULL;
- UR_DialogInitSell(storage->ufoTemplate);
- /* update other menu texts */
- Cvar_Set("mn_uforecovery_actualufo",va(_("previously recovered %s from base %s"),UFO_TypeToName(storage->ufoTemplate->type), storage->base->name));
- LIST_AddString(&replacetext, va(_("Storage process for captured %s ongoing."), UFO_TypeToName(ufoRecovery.ufoType)));
- MN_RegisterLinkedListText(TEXT_UFORECOVERY_BASESTORAGE, replacetext);
- /* start storage process for recovered ufo */
- UR_DialogStartStore(qfalse);
+ UR_DialogRecoveryDone();
}
/**
@@ -432,27 +194,39 @@
static void UR_DialogInitSell_f (void)
{
int i;
- aircraft_t *ufocraft;
+ int nations = 0;
+ static char recoveryNationSelectPopup[MAX_SMALLMENUTEXTLEN];
/* Do nothing if recovery process is finished. */
if (ufoRecovery.recoveryDone)
return;
- ufocraft = NULL;
- /* Find ufo sample of given ufotype. */
- for (i = 0; i < ccs.numAircraftTemplates; i++) {
- ufocraft = &ccs.aircraftTemplates[i];
- if (ufocraft->type != AIRCRAFT_UFO)
- continue;
- if (ufocraft->ufotype == ufoRecovery.ufoType)
- break;
- }
- if (!ufocraft)
+ if (!ufoRecovery.ufoTemplate)
return;
memset(ufoRecovery.UFOprices, -1, sizeof(ufoRecovery.UFOprices));
- UR_DialogInitSell(ufocraft);
+ recoveryNationSelectPopup[0] = '\0';
+
+ for (i = 0; i < ccs.numNations; i++) {
+ const nation_t *nation = &ccs.nations[i];
+ nations++;
+ /* Calculate price offered by nation only if this is first popup opening. */
+ if (!ufoRecovery.nation) {
+ ufoRecovery.UFOprices[i] = (int) (ufoRecovery.ufoTemplate->price * (.85f + frand() * .3f));
+ /* Nation will pay less if corrupted */
+ ufoRecovery.UFOprices[i] = (int) (ufoRecovery.UFOprices[i] * exp(-nation->stats[0].xviInfection / 20.0f));
+ }
+ Com_sprintf(recoveryNationSelectPopup + strlen(recoveryNationSelectPopup), lengthof(recoveryNationSelectPopup),
+ "%s\t\t\t%i\t\t%s\n", _(nation->name), ufoRecovery.UFOprices[i], NAT_GetHappinessString(nation));
+ }
+
+ /* Do nothing without at least one nation. */
+ if (nations == 0)
+ return;
+
+ MN_RegisterText(TEXT_UFORECOVERY_NATIONS, recoveryNationSelectPopup);
+ MN_ExecuteConfunc("btnatsel disable");
}
/**
@@ -481,7 +255,7 @@
Com_DPrintf(DEBUG_CLIENT, "CP_UFORecoveryNationSelectPopup_f: picked nation: %s\n", nation->name);
Cvar_Set("mission_recoverynation", _(nation->name));
- MN_ExecuteConfunc("btnatsel_enable");
+ MN_ExecuteConfunc("btnatsel enable");
}
/**
@@ -502,13 +276,15 @@
Com_Printf("CP_UFOSellStart_f: Error: ufo price of -1 - nation: '%s'\n", nation->id);
return;
}
+#if 0
if (ufoRecovery.selectedStorage) {
Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Sold previously recovered %s from %s to nation %s, gained %i credits."), UFO_TypeToName(
ufoRecovery.selectedStorage->ufoTemplate->ufotype), ufoRecovery.selectedStorage->base->name, _(nation->name), ufoRecovery.UFOprices[nation->idx]);
} else {
+#endif
Com_sprintf(cp_messageBuffer, sizeof(cp_messageBuffer), _("Recovered %s from the battlefield. UFO sold to nation %s, gained %i credits."), UFO_TypeToName(
- ufoRecovery.ufoType), _(nation->name), ufoRecovery.UFOprices[nation->idx]);
- }
+ ufoRecovery.ufoTemplate->ufotype), _(nation->name), ufoRecovery.UFOprices[nation->idx]);
+/* }*/
MS_AddNewMessage(_("UFO Recovery"), cp_messageBuffer, qfalse, MSG_STANDARD, NULL);
CL_UpdateCredits(ccs.credits + ufoRecovery.UFOprices[nation->idx]);
@@ -526,16 +302,121 @@
UR_DialogRecoveryDone();
}
+
+/* === UFO Storing === */
+
+#ifdef DEBUG
+/**
+ * @brief Debug callback to list ufostores
+ */
+static void US_ListStoredUFOs_f (void)
+{
+ int i;
+
+ Com_Printf("Number of stored UFOs: %i\n", ccs.numStoredUFOs);
+ for (i = 0; i < ccs.numStoredUFOs; i++) {
+ const storedUFO_t *ufo = US_GetStoredUFOByIDX(i);
+ const base_t *prodBase = PR_ProductionBase(ufo->disassembly);
+ dateLong_t date;
+
+ Com_Printf("IDX: %i\n", ufo->idx);
+ Com_Printf("id: %s\n", ufo->id);
+ Com_Printf("stored at %s\n", (ufo->installation) ? ufo->installation->name : "NOWHERE");
+
+ CL_DateConvertLong(&(ufo->arrive), &date);
+ Com_Printf("arrived at: %i %s %02i, %02i:%02i\n", date.year,
+ Date_GetMonthName(date.month - 1), date.day, date.hour, date.min);
+
+ if (ufo->ufoTemplate->tech->base)
+ Com_Printf("tech being researched at %s\n", ufo->ufoTemplate->tech->base->name);
+ if (prodBase)
+ Com_Printf("being disassembled at %s\n", prodBase->name);
+ }
+}
+
+/**
+ * @brief Adds an UFO to the stores
+ */
+static void US_StoreUFO_f (void)
+{
+ char ufoId[MAX_VAR];
+ int installationIDX;
+ installation_t *installation;
+ aircraft_t *ufoType = NULL;
+ int i;
+
+ if (Cmd_Argc() <= 2) {
+ Com_Printf("Usage: %s <ufoType> <installationIdx>\n", Cmd_Argv(0));
+ return;
+ }
+
+ Q_strncpyz(ufoId, Cmd_Argv(1), sizeof(ufoId));
+ installationIDX = atoi(Cmd_Argv(2));
+
+ /* Get The UFO Yard */
+ if (installationIDX < 0 || installationIDX >= MAX_INSTALLATIONS) {
+ Com_Printf("US_StoreUFO_f: Invalid Installation index.\n");
+ return;
+ }
+ installation = INS_GetFoundedInstallationByIDX(installationIDX);
+ if (!installation) {
+ Com_Printf("US_StoreUFO_f: There is no Installation: idx=%i.\n", installationIDX);
+ return;
+ }
+
+ /** Get UFO Type */
+ for (i = 0; i < ccs.numAircraftTemplates; i++) {
+ if (strstr(ccs.aircraftTemplates[i].id, ufoId)) {
+ ufoType = &ccs.aircraftTemplates[i];
+ break;
+ }
+ }
+ if (ufoType == NULL) {
+ Com_Printf("US_StoreUFO_f: In valid UFO Id.\n");
+ return;
+ }
+
+ US_StoreUFO(ufoType, installation, ccs.date);
+}
+
+/**
+ * @brief Removes an UFO from the stores
+ */
+static void US_RemoveStoredUFO_f (void)
+{
+ int idx;
+
+ if (Cmd_Argc() < 2) {
+ Com_Printf("Usage: %s <idx>\n", Cmd_Argv(0));
+ return;
+ }
+ idx = atoi(Cmd_Argv(1));
+
+ if (idx < 0 || idx >= ccs.numStoredUFOs) {
+ Com_Printf("US_RemoveStoredUFO_f: No such ufo index.\n");
+ return;
+ }
+
+ US_RemoveStoredUFO(US_GetStoredUFOByIDX(idx));
+}
+
+
+#endif
+
void UR_InitCallbacks (void)
{
Cmd_AddCommand("cp_uforecovery_init", UR_DialogInit_f, "Function to trigger UFO Recovered event");
Cmd_AddCommand("cp_uforecovery_sell_init", UR_DialogInitSell_f, "Function to initialize sell recovered UFO to desired nation.");
Cmd_AddCommand("cp_uforecovery_store_init", UR_DialogInitStore_f, "Function to initialize store recovered UFO in desired base.");
Cmd_AddCommand("cp_uforecovery_nationlist_click", UR_DialogSelectSellNation_f, "Callback for recovery sell to nation list.");
- Cmd_AddCommand("cp_uforecovery_baselist_click", UR_DialogSelectStorageBase_f, "Callback for recovery store in base list.");
Cmd_AddCommand("cp_uforecovery_store_start", UR_DialogStartStore_f, "Function to start UFO recovery processing.");
Cmd_AddCommand("cp_uforecovery_sell_start", UR_DialogStartSell_f, "Function to start UFO selling processing.");
- Cmd_AddCommand("cp_uforecovery_replace", UR_DialogStartReplace_f, "Function to start replace UFO in base processing. Sell is needed for replaced UFO.");
+
+#ifdef DEBUG
+ Cmd_AddCommand("debug_liststoredufos", US_ListStoredUFOs_f, "Debug function to list UFOs in Hangars.");
+ Cmd_AddCommand("debug_storeufo", US_StoreUFO_f, "Debug function to Add UFO to Hangars.");
+ Cmd_AddCommand("debug_removestoredufo", US_RemoveStoredUFO_f, "Debug function to Remove UFO from Hangars.");
+#endif
}
void UR_ShutdownCallbacks (void)
@@ -544,8 +425,11 @@
Cmd_RemoveCommand("cp_uforecovery_sell_init");
Cmd_RemoveCommand("cp_uforecovery_store_init");
Cmd_RemoveCommand("cp_uforecovery_nationlist_click");
- Cmd_RemoveCommand("cp_uforecovery_baselist_click");
Cmd_RemoveCommand("cp_uforecovery_store_start");
Cmd_RemoveCommand("cp_uforecovery_sell_start");
- Cmd_RemoveCommand("cp_uforecovery_replace");
+#ifdef DEBUG
+ Cmd_RemoveCommand("debug_liststoredufos");
+ Cmd_RemoveCommand("debug_storeufo");
+ Cmd_RemoveCommand("debug_removestoredufo");
+#endif
}
Index: src/client/campaign/cp_uforecovery_callbacks.h
===================================================================
--- src/client/campaign/cp_uforecovery_callbacks.h (revision 25743)
+++ src/client/campaign/cp_uforecovery_callbacks.h (working copy)
@@ -1,10 +1,10 @@
/**
* @file cp_uforecovery_callbacks.h
- * @brief UFO recovery callback header file
+ * @brief UFO recovery and storing callback header file
*/
/*
-Copyright (C) 2002-2007 UFO: Alien Invasion team.
+Copyright (C) 2002-2009 UFO: Alien Invasion team.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -23,8 +23,8 @@
*/
-#ifndef CLIENT_CL_UFORECOVERY_CALLBACKS_H
-#define CLIENT_CL_UFORECOVERY_CALLBACKS_H
+#ifndef CLIENT_CP_UFORECOVERY_CALLBACKS_H
+#define CLIENT_CP_UFORECOVERY_CALLBACKS_H
void UR_InitCallbacks(void);
void UR_ShutdownCallbacks(void);
Index: src/client/campaign/cp_alienbase.c
===================================================================
--- src/client/campaign/cp_alienbase.c (revision 25743)
+++ src/client/campaign/cp_alienbase.c (working copy)
@@ -80,6 +80,8 @@
counter++;
}
+ if (counter == maxLoopPosition)
+ Vector2Copy(randomPos, pos);
}
/**
Index: src/client/campaign/cp_research.c
===================================================================
--- src/client/campaign/cp_research.c (revision 25743)
+++ src/client/campaign/cp_research.c (working copy)
@@ -10,7 +10,7 @@
*/
/*
-Copyright (C) 2002-2007 UFO: Alien Invasion team.
+Copyright (C) 2002-2009 UFO: Alien Invasion team.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -88,6 +88,18 @@
}
/**
+ * @brief Stops a research (Removes scientists from it)
+ * @param[in] tech The technology that is being researched.
+ */
+void RS_StopResearch (technology_t* tech)
+{
+ assert(tech);
+ while (tech->scientists > 0)
+ RS_RemoveScientist(tech, NULL);
+ assert(tech->statusResearch == RS_PAUSED);
+}
+
+/**
* @brief Marks one tech as researchable.
* @param tech The technology to be marked.
* @sa RS_MarkCollected
@@ -197,6 +209,11 @@
if (AL_CountAll() < req->amount)
met_AND = qfalse;
break;
+ case RS_LINK_UFO:
+ assert(req->link);
+ if (US_UFOsInStorage(req->link, NULL) < req->amount)
+ met_AND = qfalse;
+ break;
default:
break;
}
@@ -243,6 +260,11 @@
if (AL_CountAll() >= req->amount)
met_OR = qtrue;
break;
+ case RS_LINK_UFO:
+ assert(req->link);
+ if (US_UFOsInStorage(req->link, NULL) >= req->amount)
+ met_OR = qtrue;
+ break;
default:
break;
}
@@ -410,6 +432,9 @@
if (!req->link)
Com_Error(ERR_DROP, "RS_AssignTechLinks: Could not get alien type (alien or alien_dead) definition for '%s'", req->id);
break;
+ case RS_LINK_UFO:
+ req->link = AIR_GetAircraft(req->id);
+ break;
default:
break;
}
@@ -872,6 +897,8 @@
return ((teamDef_t*)req->link)->id;
case RS_LINK_ALIEN_GLOBAL:
return "global alien count";
+ case RS_LINK_UFO:
+ return ((aircraft_t*)req->link)->id;
default:
return "unknown";
}
@@ -894,6 +921,8 @@
return "alien_dead";
case RS_LINK_ALIEN_GLOBAL:
return "alienglobal";
+ case RS_LINK_UFO:
+ return "ufo";
default:
return "unknown";
}
@@ -1341,6 +1370,20 @@
} else {
Com_Printf("RS_ParseTechnologies: \"%s\" Too many 'required' defined. Limit is %i - ignored.\n", name, MAX_TECHLINKS);
}
+ } else if (!strcmp(token, "ufo")) {
+ /* Defines what ufos need to be collected for this item to be researchable. */
+ if (requiredTemp->numLinks < MAX_TECHLINKS) {
+ /* Set requirement-type. */
+ requiredTemp->links[requiredTemp->numLinks].type = RS_LINK_UFO;
+ /* Set requirement-name (id). */
+ token = Com_Parse(text);
+ requiredTemp->links[requiredTemp->numLinks].id = Mem_PoolStrDup(token, cp_campaignPool, 0);
+ /* Set requirement-amount of item. */
+ token = Com_Parse(text);
+ requiredTemp->links[requiredTemp->numLinks].amount = atoi(token);
+ Com_DPrintf(DEBUG_CLIENT, "RS_ParseTechnologies: require-ufo - %s - %i\n", requiredTemp->links[requiredTemp->numLinks].id, requiredTemp->links[requiredTemp->numLinks].amount);
+ requiredTemp->numLinks++;
+ }
} else {
Com_Printf("RS_ParseTechnologies: \"%s\" unknown requirement-type: \"%s\" - ignored.\n", name, token);
}
Index: src/client/campaign/cp_research.h
===================================================================
--- src/client/campaign/cp_research.h (revision 25743)
+++ src/client/campaign/cp_research.h (working copy)
@@ -70,6 +70,7 @@
RS_LINK_ALIEN,
RS_LINK_ALIEN_DEAD,
RS_LINK_ALIEN_GLOBAL,
+ RS_LINK_UFO,
MAX_RS_LINKTYPES
} requirementType_t;
@@ -84,6 +85,7 @@
* RS_LINK_ALIEN -> teamDef_t*
* RS_LINK_ALIEN_DEAD -> teamDef_t*
* RS_LINK_ALIEN_GLOBAL -> NULL
+ * RS_LINK_UFO -> aircraft_t*
*/
int amount; /**< How many items are needed for research ... if any. (fix) */
int collected; /**< How many items have been collected. (varies) */
@@ -219,6 +221,7 @@
void RS_MarkCollected(technology_t *tech) __attribute__((nonnull));
void RS_MarkResearchable(qboolean init, const struct base_s *base);
void RS_ResearchFinish(technology_t* tech);
+void RS_StopResearch(technology_t* tech);
void RS_MarkOneResearchable(technology_t *tech);
void RS_AssignScientist(technology_t* tech, struct base_s *base);
Index: src/client/campaign/cp_base.c
===================================================================
--- src/client/campaign/cp_base.c (revision 25743)
+++ src/client/campaign/cp_base.c (working copy)
@@ -523,10 +523,6 @@
if (B_GetBuildingStatus(base, B_GetBuildingTypeByCapacity(CAP_WORKSPACE)))
PR_UpdateProductionCap(base);
- if (B_GetBuildingStatus(base, B_GetBuildingTypeByCapacity(CAP_UFOHANGARS_SMALL)) ||
- B_GetBuildingStatus(base, B_GetBuildingTypeByCapacity(CAP_UFOHANGARS_LARGE)))
- UR_UpdateUFOHangarCapForAll(base);
-
if (B_GetBuildingStatus(base, B_GetBuildingTypeByCapacity(CAP_ANTIMATTER)))
B_UpdateAntimatterCap(base);
@@ -2575,8 +2571,8 @@
case CAP_ITEMS: /**< Update items capacity in base. */
case CAP_AIRCRAFT_SMALL: /**< Update aircraft capacity in base. */
case CAP_AIRCRAFT_BIG: /**< Update aircraft capacity in base. */
- case CAP_UFOHANGARS_SMALL: /**< Base capacities for UFO hangars. */
- case CAP_UFOHANGARS_LARGE: /**< Base capacities for UFO hangars. */
+ case CAP_UFOHANGARS_SMALL: /**< Base capacities for UFO hangars. */
+ case CAP_UFOHANGARS_LARGE: /**< Base capacities for UFO hangars. */
case CAP_ANTIMATTER: /**< Update antimatter capacity in base. */
/* Reset given capacity in current base. */
base->capacities[cap].max = 0;
@@ -2789,12 +2785,52 @@
}
/**
+ * @brief Moves the UFOs stored in the base's storage structure to UFO Yards' storedUFOs structure
+ * @note this is a temporary function to keep savegame compatibility
+ * @todo remove this before release (or after a time)
+ */
+static void B_PostLoadMoveUFOsToUFOYards (void)
+{
+ int i;
+
+ /* loop throught bases */
+ for (i = 0; i < ccs.numBases; i++) {
+ int j;
+ base_t * base = B_GetFoundedBaseByIDX(i);
+
+ if (!base)
+ continue;
+
+ /* find ufos in storage */
+ for (j = 0; j < csi.numODs; j++) {
+ objDef_t *od = INVSH_GetItemByIDX(j);
+
+ if (!od)
+ continue;
+ assert(od->tech);
+ if (od->tech->type != RS_CRAFT)
+ continue;
+
+ /* add each to an ufoyard */
+ for (;0 < base->storage.num[od->idx];) {
+ installation_t *UFOYard = INS_GetFirstUFOYard(qtrue);
+
+ if (UFOYard)
+ US_StoreUFO(AIR_GetAircraft(od->id), UFOYard, ccs.date);
+ base->storage.num[od->idx]--;
+ }
+ }
+ }
+}
+
+/**
* @brief Set the capacity stuff for all the bases after loading a savegame
* @sa SAV_GameActionsAfterLoad
*/
void B_PostLoadInit (void)
{
B_PostLoadInitCapacity();
+ B_PostLoadMoveUFOsToUFOYards();
}
qboolean B_LoadStorageXML (mxml_node_t *parent, equipDef_t *equip)
@@ -2874,6 +2910,8 @@
} else
*building = *B_GetBuildingTemplate(buildingType);
+ if (!building)
+ continue;
building->idx = B_GetBuildingIDX(b, building);
if (building->idx != buildId) {
Com_Printf("building ID doesn't match\n");
@@ -2944,6 +2982,7 @@
/** @todo can't we use something like INVSH_DestroyInventory here? */
/* clear the mess of stray loaded pointers */
memset(&b->bEquipment, 0, sizeof(b->bEquipment));
+ /* reset capacities */
}
ccs.numBases = B_GetFoundedBaseCount();
@@ -2963,6 +3002,7 @@
if (!strcmp(obj->id, ANTIMATTER_TECH_ID))
return qfalse;
+ /* @todo: remove this condition - I keep it for compatibility for now. -geever */
/* aircraft are stored in hangars */
assert(obj->tech);
if (obj->tech->type == RS_CRAFT)
@@ -3118,74 +3158,6 @@
}
/**
- * @brief Remove ufos until everything fits in ufo hangars.
- * @param[in] base Pointer to the base
- * @param[in] buildingType type
- */
-void B_RemoveUFOsExceedingCapacity (base_t *base, const buildingType_t buildingType)
-{
- const baseCapacities_t capacityType = B_GetCapacityFromBuildingType(buildingType);
- int i;
- int objIdx[MAX_OBJDEFS]; /**< Will contain idx of items that can be removed */
- int num;
-
- if (capacityType != CAP_UFOHANGARS_SMALL && capacityType != CAP_UFOHANGARS_LARGE)
- return;
-
- if (base->capacities[capacityType].cur <= base->capacities[capacityType].max)
- return;
-
- for (i = 0, num = 0; i < csi.numODs; i++) {
- const objDef_t *obj = &csi.ods[i];
- aircraft_t *ufocraft;
-
- /* Don't count what isn't an aircraft */
- assert(obj->tech);
- if (obj->tech->type != RS_CRAFT)
- continue;
-
- /* look for corresponding aircraft in global array */
- ufocraft = AIR_GetAircraft(obj->id);
- if (!ufocraft) {
- Com_DPrintf(DEBUG_CLIENT, "B_RemoveUFOsExceedingCapacity: Did not find UFO %s\n", obj->id);
- continue;
- }
-
- if (ufocraft->size == AIRCRAFT_LARGE && capacityType != CAP_UFOHANGARS_LARGE)
- continue;
- if (ufocraft->size == AIRCRAFT_SMALL && capacityType != CAP_UFOHANGARS_SMALL)
- continue;
-
- /* Don't count item that we don't have in base */
- if (!base->storage.num[i])
- continue;
-
- objIdx[num++] = i;
- }
-
- while (num && base->capacities[capacityType].cur > base->capacities[capacityType].max) {
- /* Select the item to remove */
- const int randNumber = rand() % num;
- /* items are destroyed. We guess that all items of a given type are stored in the same location
- * => destroy all items of this type */
- const int idx = objIdx[randNumber];
-
- assert(idx >= 0);
- assert(idx < MAX_OBJDEFS);
- B_UpdateStorageAndCapacity(base, &csi.ods[idx], -base->storage.num[idx], qfalse, qfalse);
-
- REMOVE_ELEM(objIdx, randNumber, num);
- UR_UpdateUFOHangarCapForAll(base);
-
- /* Make sure that we don't have an infinite loop */
- if (num <= 0)
- break;
- }
- Com_DPrintf(DEBUG_CLIENT, "B_RemoveUFOsExceedingCapacity: Remains %i in storage for a maximum of %i\n",
- base->capacities[capacityType].cur, base->capacities[capacityType].max);
-}
-
-/**
* @brief Update Storage Capacity.
* @param[in] base Pointer to the base
* @sa B_ResetAllStatusAndCapacities_f
Index: base/ufos/installation.ufo
===================================================================
--- base/ufos/installation.ufo (revision 25743)
+++ base/ufos/installation.ufo (working copy)
@@ -24,7 +24,7 @@
cost 30000
radar_range 0
max_batteries 0
- max_ufo_stored 10
+ max_ufo_stored 6
max_damage 100
buildtime 11
}
Index: base/ufos/research.ufo
===================================================================
--- base/ufos/research.ufo (revision 25743)
+++ base/ufos/research.ufo (working copy)
@@ -627,15 +627,15 @@
require_OR
{
- item craft_ufo_ripper 1
- item craft_ufo_gunboat 1
- item craft_ufo_scout 1
- item craft_ufo_fighter 1
- item craft_ufo_supply 1
- item craft_ufo_carrier 1
- item craft_ufo_bomber 1
- item craft_ufo_corrupter 1
- item craft_ufo_harvester 1
+ ufo craft_ufo_ripper 1
+ ufo craft_ufo_gunboat 1
+ ufo craft_ufo_scout 1
+ ufo craft_ufo_fighter 1
+ ufo craft_ufo_supply 1
+ ufo craft_ufo_carrier 1
+ ufo craft_ufo_bomber 1
+ ufo craft_ufo_corrupter 1
+ ufo craft_ufo_harvester 1
}
time 3000
@@ -3503,7 +3503,7 @@
require_AND
{
- item craft_ufo_scout 1
+ ufo craft_ufo_scout 1
tech rs_alien_ufo_theory
}
@@ -3546,7 +3546,7 @@
// FIXME
require_AND
{
- item craft_ufo_fighter 1
+ ufo craft_ufo_fighter 1
tech rs_alien_ufo_theory
}
@@ -3590,7 +3590,7 @@
require_AND
{
tech rs_alien_ufo_theory
- item craft_ufo_supply 1
+ ufo craft_ufo_supply 1
}
provides "craft_ufo_supply"
@@ -3633,7 +3633,7 @@
require_AND
{
tech rs_alien_ufo_theory
- item craft_ufo_carrier 1
+ ufo craft_ufo_carrier 1
}
provides "craft_ufo_carrier"
@@ -3676,7 +3676,7 @@
require_AND
{
tech rs_alien_ufo_theory
- item craft_ufo_bomber 1
+ ufo craft_ufo_bomber 1
}
provides "craft_ufo_bomber"
@@ -3719,7 +3719,7 @@
require_AND
{
tech rs_alien_ufo_theory
- item craft_ufo_corrupter 1
+ ufo craft_ufo_corrupter 1
}
provides "craft_ufo_corrupter"
@@ -3762,7 +3762,7 @@
require_AND
{
tech rs_alien_ufo_theory
- item craft_ufo_gunboat 1
+ ufo craft_ufo_gunboat 1
}
provides "craft_ufo_gunboat"
@@ -3805,7 +3805,7 @@
require_AND
{
tech rs_alien_ufo_theory
- item craft_ufo_ripper 1
+ ufo craft_ufo_ripper 1
}
provides "craft_ufo_ripper"
@@ -3848,7 +3848,7 @@
require_AND
{
tech rs_alien_ufo_theory
- item craft_ufo_harvester 1
+ ufo craft_ufo_harvester 1
}
provides "craft_ufo_harvester"
@@ -3891,7 +3891,7 @@
require_AND
{
tech rs_alien_ufo_theory
- item craft_ufo_mothership 1
+ ufo craft_ufo_mothership 1
}
provides "craft_ufo_mothership"
Index: base/ufos/basemanagement.ufo
===================================================================
--- base/ufos/basemanagement.ufo (revision 25743)
+++ base/ufos/basemanagement.ufo (working copy)
@@ -233,6 +233,7 @@
ondestroy "building_ondestroy"
capacity 1
type smallufohangar
+ max_count 0
}
building building_large_ufo_hangar
@@ -249,6 +250,7 @@
pedia rs_building_large_ufo_hangar
needs building_large_ufo_hangar2
type ufohangar
+ max_count 0
}
building building_large_ufo_hangar2
Index: base/ufos/ui/lostwon.ufo
===================================================================
--- base/ufos/ui/lostwon.ufo (revision 25743)
+++ base/ufos/ui/lostwon.ufo (working copy)
@@ -166,17 +166,17 @@
pos "17 125"
size "667 38"
cvar *cvar:mn_uforecovery_tab
+ onChange {
+ cmd "uforecovery_tabselect <cvar:mn_uforecovery_tab> ;"
+ }
option store {
label "_Store UFO"
- value "0"
+ value "store"
}
option sell {
label "_Sell UFO"
- value "1"
+ value "sell"
}
- onChange {
- cmd "uforecovery_tabchange;"
- }
}
string actualufo
@@ -214,7 +214,6 @@
lineheight 16
tabwidth 100
rows "8"
- onClick { cmd "cp_uforecovery_baselist_click <lineselected>" }
onViewChange {
*(abstractscrollbar)store_panel.cp_ur_baselist_scroll@fullsize <fullsize>
*(abstractscrollbar)store_panel.cp_ur_baselist_scroll@current <viewpos>
@@ -232,18 +231,6 @@
onChange { *store_panel.cp_uforecovery_baselist@viewpos <current> }
}
- string selected_base_str
- {
- string "Selected base:"
- pos "30 186"
- }
-
- string selected_base_val
- {
- string *cvar:mission_recoverybase
- pos "160 186"
- }
-
button bt_basesel
{
string "_Recover"
@@ -253,26 +240,15 @@
size "176 32"
font f_menu
color "0 0.5 0 1"
- onClick { cmd "cp_uforecovery_store_start;mn_pop;" }
+ onClick { cmd "cp_uforecovery_store_start <node:root.store_panel.cp_uforecovery_baselist@lineselected>; mn_pop;" }
}
-
- button bt_basereplace
- {
- string "_Replace UFO"
- tooltip "_Replace stored UFO with actual recovered one"
- image ui/button_green_small
- pos "375 210"
- size "176 32"
- font f_menu
- color "0 0.5 0 1"
- onClick { cmd "start_replace;" }
- }
}
//
// sell panel
//
- panel sell_panel {
+ panel sell_panel
+ {
{
pos "20 165"
size "660 255"
@@ -360,66 +336,56 @@
}
}
- //
- // function to manage tab
- //
- confunc uforecovery_tabchange {
- *store_panel@invis true
- *sell_panel@invis true
- if ( *cvar:mn_uforecovery_tab == 0 ) {
+ /*
+ * function to manage tab
+ */
+ confunc uforecovery_tabselect {
+ *cvar:mn_uforecovery_tab = <1>
+ if ( *cvar:mn_uforecovery_tab eq "store" ) {
*store_panel@invis false
+ *sell_panel@invis true
}
- if ( *cvar:mn_uforecovery_tab == 1 ) {
+ if ( *cvar:mn_uforecovery_tab eq "sell" ) {
*sell_panel@invis false
+ *store_panel@invis true
}
}
- confunc btnatsel_enable {
- *sell_panel.bt_natsel@disabled false
+ confunc btnatsel {
+ *cvar:tmp = <1>
+ if ( *cvar:tmp eq "enable" ) {
+ *sell_panel.bt_natsel@disabled false
+ } else {
+ *sell_panel.bt_natsel@disabled true
+ }
+ delete *cvar:tmp
}
-
- confunc btbasesel_enable {
- *store_panel.bt_basesel@disabled false
+
+ confunc btbasesel {
+ *cvar:tmp = <1>
+ if ( *cvar:tmp eq "enable" ) {
+ *store_panel.bt_basesel@disabled false
+ } else {
+ *store_panel.bt_basesel@disabled true
+ }
+ delete *cvar:tmp
}
- confunc btbaserepl_enable {
- *store_panel.bt_basereplace@disabled false
- }
- confunc cp_basesel_disable {
- *store_panel.cp_uforecovery_baselist@disabled true
- }
-
- // @todo perhaps a shorter way to do so?
confunc cp_basesel_select {
- *store_panel.cp_uforecovery_baselist@lineselected 0
+ *store_panel.cp_uforecovery_baselist@lineselected <1>
}
- confunc start_replace {
- *cvar:mn_uforecovery_tab 1
- call uforecovery_tabchange
- cmd "cp_uforecovery_replace;"
- *store_panel.cp_uforecovery_baselist@disabled true
- *store_panel.cp_uforecovery_baselist@lineselected -1
- *store_panel.bt_basesel@disabled true
- *store_panel.bt_basereplace@disabled true
- *sell_panel.cp_uforecovery_nationlist@lineselected -1
- *sell_panel.bt_natsel@disabled true
- *cvar:mission_recoverynation ""
- }
-
func onInit {
- *store_panel.cp_uforecovery_baselist@lineselected -1
- *store_panel.cp_uforecovery_baselist@disabled false
- *store_panel.bt_basereplace@disabled true
- *store_panel.bt_basesel@disabled true
- *sell_panel.cp_uforecovery_nationlist@lineselected -1
- *sell_panel.bt_natsel@disabled true
- *cvar:mn_uforecovery_tab 0
- cmd "del mission_recoverybase;del mission_recoverynation;uforecovery_tabchange;cp_uforecovery_sell_init;cp_uforecovery_store_init;"
+ cmd "uforecovery_tabselect store"
+ *store_panel.cp_uforecovery_baselist@lineselected = -1
+ *sell_panel.cp_uforecovery_nationlist@lineselected = -1
+ *cvar:mission_recoverynation = ""
+ cmd "cp_uforecovery_sell_init;cp_uforecovery_store_init;"
}
func onClose {
- cmd "del mn_uforecovery_tab;del mn_uforecovery_actualufo;"
+ delete *cvar:mn_uforecovery_tab
+ delete *cvar:mn_uforecovery_actualufo
}
}
Index: base/ufos/ui/production.ufo
===================================================================
--- base/ufos/ui/production.ufo (revision 25743)
+++ base/ufos/ui/production.ufo (working copy)
@@ -528,10 +528,10 @@
{
dataid TEXT_PRODUCTION_INFO
pos "610 528"
- size "346 100"
+ size "346 200"
lineheight 20
tabwidth 260
- rows "5"
+ rows "10"
onViewChange {
*(abstractscrollbar)description_scroll@fullsize <fullsize>
*(abstractscrollbar)description_scroll@current <viewpos>
@@ -544,8 +544,8 @@
pos "960 528"
height "100"
current 0
- viewsize 5
- fullsize 5
+ viewsize 10
+ fullsize 10
hidewhenunused true
onChange { *description@viewpos <current> }
}
@@ -554,6 +554,18 @@
// init function
// ==================
+ confunc amountsetter {
+ *cvar:tmp = <1>
+ if ( *cvar:tmp eq "disable" ) {
+ *prod_change@disabled = true
+ *prod_change_10@disabled = true
+ } else {
+ *prod_change@disabled = false
+ *prod_change_10@disabled = false
+ }
+ delete *cvar:tmp
+ }
+
func onInit
{
cmd "prod_init; prod_type *mn_itemtype;"