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 }