1 /************************************************************************
2 * *
3 * FreeSynd - a remake of the classic Bullfrog game "Syndicate". *
4 * *
5 * Copyright (C) 2005 Stuart Binge <skbinge@gmail.com> *
6 * Copyright (C) 2005 Joost Peters <joostp@users.sourceforge.net> *
7 * Copyright (C) 2006 Trent Waddington <qg@biodome.org> *
8 * Copyright (C) 2006 Tarjei Knapstad <tarjei.knapstad@gmail.com> *
9 * Copyright (C) 2011 Joey Parrish <joey.parrish@gmail.com> *
10 * *
11 * This program is free software; you can redistribute it and / or *
12 * modify it under the terms of the GNU General Public License as *
13 * published by the Free Software Foundation; either version 2 of the *
14 * License, or (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19 * General Public License for more details. *
20 * *
21 * You can view the GNU General Public License, online, at the GNU *
22 * project's web site; see <http://www.gnu.org/licenses/gpl.html>. *
23 * The full text of the license is also included in the file COPYING. *
24 * *
25 ************************************************************************/
26
27 #include <stdio.h>
28 #include <assert.h>
29
30 #include "agentmanager.h"
31 #include "weaponmanager.h"
32 #include "modmanager.h"
33
34 const char * const g_AgentNames[] = {
35 "AFSHAR",
36 "ARNOLD",
37 "BAIRD",
38 "BALDWIN",
39 "BLACK",
40 "BOYD",
41 "BOYESEN",
42 "BRAZIER",
43 "BROWN",
44 "BUSH",
45 "CARR",
46 "CHRISMAS",
47 "CLINTON",
48 "COOPER",
49 "CORPES",
50 "COX",
51 "DAWSON",
52 "DONKIN",
53 "DISKETT",
54 "DUNNE",
55 "EDGAR",
56 "EVANS",
57 "FAIRLEY",
58 "FAWCETT",
59 "FLINT",
60 "FLOYD",
61 "GRIFFITHS",
62 "HARRIS",
63 "HASTINGS",
64 "HERBERT",
65 "HICKMAN",
66 "HICKS",
67 "HILL",
68 "JAMES",
69 "JEFFERY",
70 "JOESEPH",
71 "JOHNSON",
72 "JOHNSTON",
73 "JONES",
74 "LEWIS",
75 "LINDSELL",
76 "LOCKLEY",
77 "MARTIN",
78 "MCENTEE",
79 "MCLAUGHIN",
80 "MOLYNEUX",
81 "MUNRO",
82 "MORRIS",
83 "MUMFORD",
84 "NIXON",
85 "PARKER",
86 "PRATT",
87 "REID",
88 "RENNIE",
89 "RICE",
90 "RIPLEY",
91 "ROBERTSON",
92 "ROMANO",
93 "SEAT",
94 "SEN",
95 "SHAW",
96 "SIMMONS",
97 "SNELLING",
98 "TAYLOR",
99 "TROWERS",
100 "WEBLEY",
101 "WELLESLEY",
102 "WILD",
103 "WILLIS",
104 0
105 };
106 const int g_NumAgentNames = (sizeof(g_AgentNames) / sizeof(char *)) - 1; // minus one accounts for the NULL at the end of the names list
107
108 int const AgentManager::MAX_AGENT = 18;
109 const size_t AgentManager::kMaxSlot = 4;
110 const size_t AgentManager::kSlot1 = 0;
111 const size_t AgentManager::kSlot2 = 1;
112 const size_t AgentManager::kSlot3 = 2;
113 const size_t AgentManager::kSlot4 = 3;
114
AgentManager()115 AgentManager::AgentManager() {
116 nextName_ = 0;
117 for (int i = 0; i != MAX_AGENT; ++i)
118 agents_.add(NULL);
119 }
120
~AgentManager()121 AgentManager::~AgentManager() {
122 for (int i = 0; i != MAX_AGENT; ++i) {
123 if (agents_.get(i)) {
124 delete agents_.get(i);
125 }
126 }
127
128 agents_.clear();
129 clearSquad();
130 }
131
loadAgents()132 void AgentManager::loadAgents() {
133 // TODO : load names from file
134 }
135
reset(bool onlyWomen)136 void AgentManager::reset(bool onlyWomen) {
137 nextName_ = 0;
138 // First delete existing agents
139 clearSquad();
140 for (int i = 0; i < MAX_AGENT; i++) {
141 if (agents_.get(i)) {
142 delete agents_.get(i);
143 agents_.setAt(i, NULL);
144 }
145 }
146
147 // Then recreate the first 8 available agents
148 for (size_t i = 0; i < 8; i++) {
149 Agent * pAgent = new Agent(g_AgentNames[nextName_], onlyWomen ? true : ((i % 2) == 0));
150 pAgent->addWeapon(WeaponInstance::createInstance(pWeaponManager_->getWeapon(Weapon::Pistol)));
151
152 agents_.setAt(i, pAgent);
153 // Adds the first 4 agents to the squad
154 if (i < kMaxSlot) {
155 setSquadMember(i, pAgent);
156 }
157 nextName_++;
158 }
159 }
160
destroyAgentSlot(size_t squadSlot)161 void AgentManager::destroyAgentSlot(size_t squadSlot) {
162 Agent *p_agent = squadMember(squadSlot);
163 p_agent->removeAllWeapons();
164 p_agent->clearSlots();
165 setSquadMember(squadSlot, NULL);
166 for (int inc = 0; inc < AgentManager::MAX_AGENT; inc++) {
167 if (agent(inc) == p_agent) {
168 delete agents_.get(inc);
169 agents_.setAt(inc, NULL);
170 return;
171 }
172 }
173 }
174
saveToFile(PortableFile & file)175 bool AgentManager::saveToFile(PortableFile &file) {
176 file.write32(nextName_);
177 for (int i=0; i<AgentManager::MAX_AGENT; i++) {
178 Agent *pAgent = agents_.get(i);
179 // This flag tells if there is an agent on this slot
180 file.write8b(pAgent != 0);
181 if (pAgent) {
182 pAgent->saveToFile(file);
183 }
184 }
185
186 // save current squad
187 for (size_t i=0; i<kMaxSlot; i++) {
188 Agent *pAgent = squadMember(i);
189 int id = pAgent ? pAgent->getId() : 0;
190 file.write32(id);
191 }
192 return true;
193 }
194
loadFromFile(PortableFile & infile,const FormatVersion & v)195 bool AgentManager::loadFromFile(PortableFile &infile, const FormatVersion& v) {
196 nextName_ = infile.read32();
197 for (int i=0; i<AgentManager::MAX_AGENT; i++) {
198 bool isAgent = infile.read8b();
199 if (isAgent) {
200 Agent *pAgent = agents_.get(i);
201 if (pAgent == NULL) {
202 // Create an empty agent
203 pAgent = new Agent("", true);
204 }
205 pAgent->loadFromFile(infile, v);
206
207 // Mods
208 int nb = infile.read32();
209 for (int mIndex = 0; mIndex < nb; mIndex++) {
210 int type = infile.read32();
211 Mod::EModType mt = Mod::Unknown;
212 Mod::EModVersion mv = Mod::MOD_V1;
213 switch (type) {
214 case 0: mt = Mod::MOD_LEGS;break;
215 case 1: mt = Mod::MOD_ARMS;break;
216 case 2: mt = Mod::MOD_CHEST;break;
217 case 3: mt = Mod::MOD_HEART;break;
218 case 4: mt = Mod::MOD_EYES;break;
219 case 5: mt = Mod::MOD_BRAIN;break;
220 default: mt = Mod::Unknown;
221 }
222
223 int ver = infile.read32();
224 switch (ver) {
225 case 0: mv = Mod::MOD_V1;break;
226 case 1: mv = Mod::MOD_V2;break;
227 case 2: mv = Mod::MOD_V3;break;
228 default: mv = Mod::MOD_V1;
229 }
230 // add the mod
231 if (mt != Mod::Unknown) {
232 pAgent->addMod(pModManager_->getMod(mt, mv));
233 }
234 }
235 // Weapons
236 nb = infile.read32();
237 for (int wIndex = 0; wIndex < nb; wIndex++) {
238 int type = infile.read32();
239 Weapon::WeaponType wt = Weapon::Unknown;
240 switch (type) {
241 case Weapon::Persuadatron:
242 wt = Weapon::Persuadatron;
243 break;
244 case Weapon::Pistol:
245 wt = Weapon::Pistol;
246 break;
247 case Weapon::GaussGun:
248 wt = Weapon::GaussGun;
249 break;
250 case Weapon::Shotgun:
251 wt = Weapon::Shotgun;
252 break;
253 case Weapon::Uzi:
254 wt = Weapon::Uzi;
255 break;
256 case Weapon::Minigun:
257 wt = Weapon::Minigun;
258 break;
259 case Weapon::Laser:
260 wt = Weapon::Laser;
261 break;
262 case Weapon::Flamer:
263 wt = Weapon::Flamer;
264 break;
265 case Weapon::LongRange:
266 wt = Weapon::LongRange;
267 break;
268 case Weapon::Scanner:
269 wt = Weapon::Scanner;
270 break;
271 case Weapon::MediKit:
272 wt = Weapon::MediKit;
273 break;
274 case Weapon::TimeBomb:
275 wt = Weapon::TimeBomb;
276 break;
277 case Weapon::AccessCard:
278 wt = Weapon::AccessCard;
279 break;
280 case Weapon::EnergyShield:
281 wt = Weapon::EnergyShield;
282 break;
283 default:
284 wt = Weapon::Unknown;
285 }
286 if (wt != Weapon::Unknown) {
287 WeaponInstance *pInst = WeaponInstance::createInstance(pWeaponManager_->getWeapon(wt));
288 int ammo = infile.read32();
289 pInst->setAmmoRemaining(ammo);
290 pAgent->addWeapon(pInst);
291 } else
292 // if not read, we will corrupt loading
293 infile.read32();
294 }
295 } else if (agents_.get(i)) {
296 destroyAgentSlot(i);
297 }
298 }
299
300 // Read squad
301 for (size_t squadInd=0; squadInd<kMaxSlot; squadInd++) {
302 int id = infile.read32();
303 if (id != 0) {
304 for (int iAgnt=0; iAgnt<MAX_AGENT; iAgnt++) {
305 Agent *pAgent = agent(iAgnt);
306 if (pAgent && pAgent->getId() == id) {
307 setSquadMember(squadInd, pAgent);
308 break;
309 }
310 }
311 } else {
312 setSquadMember(squadInd, NULL);
313 }
314 }
315 return true;
316 }
317
createAgent(bool onlyWomen)318 Agent* AgentManager::createAgent(bool onlyWomen)
319 {
320 for (int i = 0; i < MAX_AGENT; i++) {
321 if (agents_.get(i) == NULL) {
322 Agent * pAgent = new Agent(g_AgentNames[rand() % g_NumAgentNames],
323 onlyWomen ? true : ((rand() % 2) == 0));
324 agents_.setAt(i, pAgent);
325 return pAgent;
326 }
327 }
328 return NULL;
329 }
330
clearSquad()331 void AgentManager::clearSquad() {
332 for (size_t s=0; s<kMaxSlot; s++) {
333 a_squad_[s] = NULL;
334 }
335 }
336
337 //! Returns true if the slot holds an agent and if he's active
isSquadSlotActive(size_t slotId)338 bool AgentManager::isSquadSlotActive(size_t slotId) {
339 assert(slotId < kMaxSlot);
340 return a_squad_[slotId] && a_squad_[slotId]->isActive();
341 }
342
343 //! Return the slot that holds the given agent or -1 if ni agent is found
getSquadSlotForAgent(Agent * pAgent)344 int AgentManager::getSquadSlotForAgent(Agent *pAgent) {
345 if (pAgent) {
346 for (size_t i=0; i<kMaxSlot; i++) {
347 if (pAgent == a_squad_[i]) {
348 return i;
349 }
350 }
351 }
352 return -1;
353 }