1 /**
2  * @file
3  */
4 
5 /*
6 Copyright (C) 2002-2013 UFO: Alien Invasion.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 */
23 
24 #include "../../cl_shared.h"
25 #include "cp_campaign.h"
26 #include "cp_capacity.h"
27 #include "cp_aircraft.h"
28 #include "cp_missions.h"
29 #include "cp_geoscape.h"
30 #include "cp_popup.h"
31 #include "cp_time.h"
32 #include "cp_ufo.h"
33 
34 /**
35  * @brief Remove exceeding antimatter if an antimatter tank has been destroyed.
36  * @param[in] base Pointer to the base.
37  */
CAP_RemoveAntimatterExceedingCapacity(base_t * base)38 void CAP_RemoveAntimatterExceedingCapacity (base_t* base)
39 {
40 	const int amount = CAP_GetCurrent(base, CAP_ANTIMATTER) - CAP_GetMax(base, CAP_ANTIMATTER);
41 	if (amount <= 0)
42 		return;
43 
44 	B_ManageAntimatter(base, amount, false);
45 }
46 
47 /**
48  * @brief Update Storage Capacity.
49  * @param[in] base Pointer to the base
50  * @sa B_ResetAllStatusAndCapacities_f
51  */
CAP_UpdateStorageCap(base_t * base)52 void CAP_UpdateStorageCap (base_t* base)
53 {
54 	int i;
55 
56 	CAP_SetCurrent(base, CAP_ITEMS, 0);
57 
58 	for (i = 0; i < cgi->csi->numODs; i++) {
59 		const objDef_t* obj = INVSH_GetItemByIDX(i);
60 
61 		if (!B_ItemIsStoredInBaseStorage(obj))
62 			continue;
63 
64 		CAP_AddCurrent(base, CAP_ITEMS, B_ItemInBase(obj, base) * obj->size);
65 	}
66 
67 	/* UGV takes room in storage capacity */
68 	CAP_AddCurrent(base, CAP_ITEMS, UGV_SIZE * E_CountHired(base, EMPL_ROBOT));
69 }
70 
71 /**
72  * @brief Sets the maximal capacity on a base
73  * @param[in,out] base The base to set capacity at
74  * @param[in] capacity Capacity type
75  * @param[in] value New maximal capacity value
76  */
CAP_SetMax(base_t * base,baseCapacities_t capacity,int value)77 void CAP_SetMax (base_t* base, baseCapacities_t capacity, int value)
78 {
79 	base->capacities[capacity].max = std::max(0, value);
80 }
81 
82 /**
83  * @brief Changes the maximal capacity on a base
84  * @param[in,out] base The base to set capacity at
85  * @param[in] capacity Capacity type
86  * @param[in] value Capacity to add to the maximal capacity value (negative to decrease)
87  */
CAP_AddMax(base_t * base,baseCapacities_t capacity,int value)88 void CAP_AddMax (base_t* base, baseCapacities_t capacity, int value)
89 {
90 	base->capacities[capacity].max = std::max(0, base->capacities[capacity].max + value);
91 }
92 
93 /**
94  * @brief Sets the current (used) capacity on a base
95  * @param[in,out] base The base to set capacity at
96  * @param[in] capacity Capacity type
97  * @param[in] value New current (used) capacity value
98  */
CAP_SetCurrent(base_t * base,baseCapacities_t capacity,int value)99 void CAP_SetCurrent (base_t* base, baseCapacities_t capacity, int value)
100 {
101 	base->capacities[capacity].cur = std::max(0, value);
102 }
103 
104 /**
105  * @brief Changes the current (used) capacity on a base
106  * @param[in,out] base The base to set capacity at
107  * @param[in] capacity Capacity type
108  * @param[in] value Capacity to add to the current (used) capacity value (negative to decrease)
109  */
CAP_AddCurrent(base_t * base,baseCapacities_t capacity,int value)110 void CAP_AddCurrent (base_t* base, baseCapacities_t capacity, int value)
111 {
112 	base->capacities[capacity].cur = std::max(0, base->capacities[capacity].cur + value);
113 }
114 
115 /**
116  * @brief Returns the free capacity of a type
117  * @param[in] base Pointer to the base to check
118  * @param[in] capacityType Capacity type
119  * @sa baseCapacities_t
120  */
CAP_GetFreeCapacity(const base_t * base,baseCapacities_t capacityType)121 int CAP_GetFreeCapacity (const base_t* base, baseCapacities_t capacityType)
122 {
123 	const capacities_t* cap = CAP_Get(base, capacityType);
124 	return cap->max - cap->cur;
125 }
126 
127 /**
128  * @brief Checks capacity overflows on bases
129  * @sa CP_CampaignRun
130  */
CAP_CheckOverflow(void)131 void CAP_CheckOverflow (void)
132 {
133 	base_t* base = nullptr;
134 
135 	while ((base = B_GetNext(base)) != nullptr) {
136 		int i;
137 
138 		for (i = CAP_ALIENS; i < MAX_CAP; i++) {
139 			baseCapacities_t capacityType = (baseCapacities_t)i;
140 			capacities_t* cap = CAP_Get(base, capacityType);
141 
142 			if (cap->cur <= cap->max)
143 				continue;
144 
145 			switch (capacityType) {
146 			case CAP_ANTIMATTER:
147 				CAP_RemoveAntimatterExceedingCapacity(base);
148 				break;
149 			case CAP_WORKSPACE:
150 				PR_UpdateProductionCap(base);
151 				break;
152 			case CAP_LABSPACE:
153 				RS_RemoveScientistsExceedingCapacity(base);
154 				break;
155 			case CAP_AIRCRAFT_SMALL:
156 			case CAP_AIRCRAFT_BIG:
157 			case CAP_ALIENS:
158 			case CAP_EMPLOYEES:
159 			case CAP_ITEMS:
160 				if (base->baseStatus != BASE_DESTROYED) {
161 					const buildingType_t bldgType = B_GetBuildingTypeByCapacity((baseCapacities_t)i);
162 					const building_t* bldg = B_GetBuildingTemplateByType(bldgType);
163 					CP_GameTimeStop();
164 					cgi->Cmd_ExecuteString("ui_push popup_cap_overload base %d \"%s\" \"%s\" %d %d",
165 						base->idx, base->name, _(bldg->name), cap->max - cap->cur, cap->max);
166 				}
167 				break;
168 			default:
169 				/* nothing to do */
170 				break;
171 			}
172 		}
173 	}
174 }
175