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