1 /**
2  * @file
3  * @brief Most of the hospital related stuff
4  * @note Hospital functions prefix: HOS_
5  */
6 
7 /*
8 Copyright (C) 2002-2013 UFO: Alien Invasion.
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 See the GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24 
25 */
26 
27 #include "../../cl_shared.h"
28 #include "cp_campaign.h"
29 #include "cp_hospital.h"
30 
31 #define GET_HP_HEALING( ab ) (1 + (ab) * 15/MAX_SKILL)
32 
HOS_HealWounds(character_t * chr,int healing)33 static void HOS_HealWounds (character_t* chr, int healing)
34 {
35 	woundInfo_t& wounds = chr->wounds;
36 
37 	for (int bodyPart = 0; bodyPart < chr->teamDef->bodyTemplate->numBodyParts(); ++bodyPart) {
38 		if (wounds.treatmentLevel[bodyPart] <= 0)
39 			continue;
40 		wounds.treatmentLevel[bodyPart] = std::max(0, wounds.treatmentLevel[bodyPart] - healing);
41 	}
42 }
43 
44 /**
45  * @brief Heals character.
46  * @param[in] chr Character data of an employee
47  * @param[in] hospital True if we call this function for hospital healing (false when autoheal).
48  * @sa HOS_HealEmployee
49  * @return true if soldiers becomes healed - false otherwise
50  */
HOS_HealCharacter(character_t * chr,bool hospital)51 bool HOS_HealCharacter (character_t* chr, bool hospital)
52 {
53 	assert(chr);
54 	float healing = ccs.curCampaign->healingRate;
55 
56 	if (hospital) {
57 		healing *= GET_HP_HEALING(chr->score.skills[ABILITY_POWER]);
58 		HOS_HealWounds(chr, healing);
59 	}
60 
61 	if (chr->HP < chr->maxHP) {
62 		/* if the character has less that 100 hitpoints, he will be disadvantaged by using the percentage
63 		 * method of allocating hitpoints.  So just give the character "healing" as Hitpoints, otherwise
64 		 * allocate "healing" as a percentage of the characters total hitpoints. */
65 		if (chr->maxHP < INITIAL_HP)
66 			chr->HP = std::min(chr->HP + static_cast<int>(healing), chr->maxHP);
67 		else
68 			chr->HP = std::min(chr->HP + static_cast<int>(((healing / 100.0f) * chr->maxHP)), chr->maxHP);
69 
70 		if (chr->HP == chr->maxHP)
71 			return false;
72 		return true;
73 	}
74 	return false;
75 }
76 
77 /**
78  * @brief Checks health status of all employees in all bases.
79  * @sa CP_CampaignRun
80  * @note Called every day.
81  */
HOS_HospitalRun(void)82 void HOS_HospitalRun (void)
83 {
84 	for (int i = 0; i < MAX_EMPL; i++) {
85 		const employeeType_t type = (employeeType_t)i;
86 		E_Foreach(type, employee) {
87 			if (!employee->isHired())
88 				continue;
89 			const bool hospital = B_GetBuildingStatus(employee->baseHired, B_HOSPITAL);
90 			HOS_HealCharacter(&(employee->chr), hospital);
91 			CHRSH_UpdateImplants(employee->chr);
92 		}
93 	}
94 }
95 
96 /**
97  * @brief Callback for HOS_HealCharacter() in hospital.
98  * @param[in] employee Pointer to the employee to heal.
99  * @sa HOS_HealCharacter
100  * @sa HOS_HealAll
101  */
HOS_HealEmployee(Employee * employee)102 bool HOS_HealEmployee (Employee* employee)
103 {
104 	assert(employee);
105 	return HOS_HealCharacter(&employee->chr, true);
106 }
107 
108 /**
109  * @brief Heal all employees in the given base
110  * @param[in] base The base the employees should become healed
111  * @sa HOS_HealEmployee
112  */
HOS_HealAll(const base_t * const base)113 void HOS_HealAll (const base_t* const base)
114 {
115 	int type;
116 
117 	assert(base);
118 
119 	for (type = 0; type < MAX_EMPL; type++) {
120 		E_Foreach(type, employee) {
121 			if (!employee->isHiredInBase(base))
122 				continue;
123 			HOS_HealEmployee(employee);
124 		}
125 	}
126 }
127 
128 
129 #ifdef DEBUG
130 /**
131  * @brief Set the character HP field to maxHP.
132  */
HOS_HealAll_f(void)133 static void HOS_HealAll_f (void)
134 {
135 	int type;
136 	base_t* base = B_GetCurrentSelectedBase();
137 
138 	if (!base)
139 		return;
140 
141 	for (type = 0; type < MAX_EMPL; type++) {
142 		E_Foreach(type, employee) {
143 			if (!employee->isHiredInBase(base))
144 				continue;
145 			employee->chr.HP = employee->chr.maxHP;
146 		}
147 	}
148 }
149 
150 /**
151  * @brief Decrement the character HP field by one.
152  */
HOS_HurtAll_f(void)153 static void HOS_HurtAll_f (void)
154 {
155 	int type, amount;
156 	base_t* base = B_GetCurrentSelectedBase();
157 
158 	if (!base)
159 		return;
160 
161 	if (cgi->Cmd_Argc() == 2)
162 		amount = atoi(cgi->Cmd_Argv(1));
163 	else
164 		amount = 1;
165 
166 	for (type = 0; type < MAX_EMPL; type++) {
167 		E_Foreach(type, employee) {
168 			/* only those employees, that are in the current base */
169 			if (!employee->isHiredInBase(base))
170 				continue;
171 			employee->chr.HP = std::max(0, employee->chr.HP - amount);
172 		}
173 	}
174 }
175 #endif
176 
177 /**
178  * @brief Initial stuff for hospitals
179  * Bind some of the functions in this file to console-commands that you can call ingame.
180  * Called from UI_InitStartup resp. CL_InitLocal
181  */
HOS_InitStartup(void)182 void HOS_InitStartup (void)
183 {
184 #ifdef DEBUG
185 	cgi->Cmd_AddCommand("debug_hosp_hurt_all", HOS_HurtAll_f, "Debug function to hurt all employees in the current base by one");
186 	cgi->Cmd_AddCommand("debug_hosp_heal_all", HOS_HealAll_f, "Debug function to heal all employees in the current base completely");
187 #endif
188 }
189 
190 /**
191  * @brief Saving function for hospital related data
192  * @sa HOS_LoadXML
193  * @sa SAV_GameSaveXML
194  */
HOS_SaveXML(xmlNode_t * p)195 bool HOS_SaveXML (xmlNode_t* p)
196 {
197 	/* nothing to save here */
198 	return true;
199 }
200 
201 /**
202  * @brief Saving function for hospital related data
203  * @sa HOS_SaveXML
204  * @sa SAV_GameLoadXML
205  */
HOS_LoadXML(xmlNode_t * p)206 bool HOS_LoadXML (xmlNode_t* p)
207 {
208 	return true;
209 }
210 
211 /**
212  * @brief Returns true if you can enter in the hospital
213  * @sa B_BaseInit_f
214  */
HOS_HospitalAllowed(const base_t * base)215 bool HOS_HospitalAllowed (const base_t* base)
216 {
217 	return !B_IsUnderAttack(base) && B_GetBuildingStatus(base, B_HOSPITAL);
218 }
219