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) 2010  Bohdan Stelmakh <chamel@users.sourceforge.net> *
10  *   Copyright (C) 2011  Benoit Blancard <benblan@users.sourceforge.net>*
11  *   Copyright (C) 2011  Joey Parrish  <joey.parrish@gmail.com>         *
12  *                                                                      *
13  *    This program is free software;  you can redistribute it and / or  *
14  *  modify it  under the  terms of the  GNU General  Public License as  *
15  *  published by the Free Software Foundation; either version 2 of the  *
16  *  License, or (at your option) any later version.                     *
17  *                                                                      *
18  *    This program is  distributed in the hope that it will be useful,  *
19  *  but WITHOUT  ANY WARRANTY;  without even  the implied  warranty of  *
20  *  MERCHANTABILITY  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  *
21  *  General Public License for more details.                            *
22  *                                                                      *
23  *    You can view the GNU  General Public License, online, at the GNU  *
24  *  project's  web  site;  see <http://www.gnu.org/licenses/gpl.html>.  *
25  *  The full text of the license is also included in the file COPYING.  *
26  *                                                                      *
27  ************************************************************************/
28 
29 #include <stdio.h>
30 #include <assert.h>
31 
32 #include "app.h"
33 #include "utils/log.h"
34 #include "utils/file.h"
35 #include "utils/configfile.h"
36 
WeaponManager()37 WeaponManager::WeaponManager() {
38     all_game_weapons_.reserve(18);
39 }
40 
destroy()41 void WeaponManager::destroy() {
42     preFetch_.clear();
43     availableWeapons_.clear();
44 }
45 
~WeaponManager()46 WeaponManager::~WeaponManager() {
47     destroy();
48     for (std::vector<Weapon *>::iterator it = all_game_weapons_.begin();
49         it != all_game_weapons_.end();it++)
50     {
51         delete (*it);
52     }
53     all_game_weapons_.clear();
54 
55 }
56 
reset()57 void WeaponManager::reset() {
58     destroy();
59 
60     all_game_weapons_.clear();
61     all_game_weapons_.push_back(loadWeapon(Weapon::Persuadatron));
62     all_game_weapons_.push_back(loadWeapon(Weapon::Pistol));
63     all_game_weapons_.push_back(loadWeapon(Weapon::Shotgun));
64     all_game_weapons_.push_back(loadWeapon(Weapon::Uzi));
65     all_game_weapons_.push_back(loadWeapon(Weapon::Scanner));
66     all_game_weapons_.push_back(loadWeapon(Weapon::MediKit));
67     all_game_weapons_.push_back(loadWeapon(Weapon::Minigun));
68     all_game_weapons_.push_back(loadWeapon(Weapon::Flamer));
69     all_game_weapons_.push_back(loadWeapon(Weapon::LongRange));
70     all_game_weapons_.push_back(loadWeapon(Weapon::EnergyShield));
71     all_game_weapons_.push_back(loadWeapon(Weapon::Laser));
72     all_game_weapons_.push_back(loadWeapon(Weapon::GaussGun));
73     all_game_weapons_.push_back(loadWeapon(Weapon::AccessCard));
74     all_game_weapons_.push_back(loadWeapon(Weapon::TimeBomb));
75 
76     // Enables default weapons
77     enableWeapon(Weapon::Persuadatron);
78     enableWeapon(Weapon::Pistol);
79     enableWeapon(Weapon::Shotgun);
80     enableWeapon(Weapon::Scanner);
81     enableWeapon(Weapon::MediKit);
82 }
83 
cheatEnableAllWeapons()84 void WeaponManager::cheatEnableAllWeapons() {
85     enableWeapon(Weapon::Persuadatron);
86     enableWeapon(Weapon::Pistol);
87     enableWeapon(Weapon::Shotgun);
88     enableWeapon(Weapon::Uzi);
89     enableWeapon(Weapon::Scanner);
90     enableWeapon(Weapon::MediKit);
91     enableWeapon(Weapon::Minigun);
92     enableWeapon(Weapon::Flamer);
93     enableWeapon(Weapon::LongRange);
94     enableWeapon(Weapon::EnergyShield);
95     enableWeapon(Weapon::Laser);
96     enableWeapon(Weapon::GaussGun);
97     enableWeapon(Weapon::AccessCard);
98     enableWeapon(Weapon::TimeBomb);
99 }
100 
enableWeapon(Weapon::WeaponType wt)101 void WeaponManager::enableWeapon(Weapon::WeaponType wt) {
102     // First check if weapon is not already available
103     for (unsigned i = 0; i != availableWeapons_.size(); ++i) {
104         if (wt == availableWeapons_.get(i)->getWeaponType())
105             return;
106     }
107 
108     // Then get weapon
109     Weapon *pWeapon = getWeapon(wt);
110 
111     // removes it from cache
112     for (std::vector < Weapon * >::iterator it = preFetch_.begin();
113          it != preFetch_.end(); it++) {
114              if (pWeapon == *it) {
115                 preFetch_.erase(it);
116                 break;
117              }
118     }
119 
120     // make it available
121     for (unsigned i = 0; i != availableWeapons_.size(); ++i) {
122         if (pWeapon->getWeaponType() < availableWeapons_.get(i)->getWeaponType()) {
123             // The new weapon is inserted in the order of the WeaponType constants
124             availableWeapons_.insertAt(i, pWeapon);
125             return;
126         }
127     }
128     // If we're here, it's because the new weapon comes at the end of the list
129     availableWeapons_.add(pWeapon);
130 }
131 
getWeapon(Weapon::WeaponType wt)132 Weapon * WeaponManager::getWeapon(Weapon::WeaponType wt) {
133     // Search in prefetched weapons first
134     for (unsigned int i = 0; i < preFetch_.size(); i++) {
135         if (wt == preFetch_[i]->getWeaponType())
136             return preFetch_[i];
137     }
138 
139     // Then search in available weapons
140     for (unsigned i = 0; i != availableWeapons_.size(); ++i) {
141         if (wt == availableWeapons_.get(i)->getWeaponType())
142             return availableWeapons_.get(i);
143     }
144 
145     // Weapon was not found so loads it
146     Weapon *pWeapon = NULL;
147 
148     for (std::vector<Weapon *>::iterator it = all_game_weapons_.begin();
149         it != all_game_weapons_.end();it++)
150     {
151         if ((*it)->getWeaponType() == wt) {
152             pWeapon = *it;
153             break;
154         }
155     }
156     assert(pWeapon);
157     // Stores it in cache
158     preFetch_.push_back(pWeapon);
159 
160     return pWeapon;
161 }
162 
isAvailable(Weapon * pWeapon)163 bool WeaponManager::isAvailable(Weapon *pWeapon) {
164     // search in available weapons
165     for (unsigned i = 0; i != availableWeapons_.size(); ++i) {
166         if (pWeapon->getWeaponType() == availableWeapons_.get(i)->getWeaponType())
167             return true;
168     }
169 
170     // No weapon of that type has been found
171     return false;
172 }
173 
getAvailable(Weapon::WeaponType wpn)174 Weapon * WeaponManager::getAvailable(Weapon::WeaponType wpn) {
175     // search in available weapons
176     for (unsigned i = 0; i != availableWeapons_.size(); ++i) {
177         if (wpn == availableWeapons_.get(i)->getWeaponType())
178             return availableWeapons_.get(i);
179     }
180 
181     // No weapon of that type has been found
182     return NULL;
183 }
184 
getAvailable(uint32 dmg_type,std::vector<Weapon * > & wpns)185 void WeaponManager::getAvailable(uint32 dmg_type, std::vector <Weapon *> &wpns)
186 {
187     // search in available weapons
188     for (unsigned i = 0; i != availableWeapons_.size(); ++i) {
189         if ((availableWeapons_.get(i)->dmgType() & dmg_type) != 0)
190             wpns.push_back(availableWeapons_.get(i));
191     }
192 }
193 
loadWeapon(Weapon::WeaponType wt)194 Weapon * WeaponManager::loadWeapon(Weapon::WeaponType wt) {
195     /* NOTE: small icon 27 exists and looks like an N with an arrow above it.
196        the corresponding large icon is actually the "all" button on the
197        select menu.  It would appear Bullfrog was going to have another
198        weapon here but it got scrapped early on and they used the large
199        icon space to implement the all button.
200      */
201     std::string filename(File::dataFullPath("ref/weapons.dat"));
202     try {
203         // Loads configuration file
204         ConfigFile conf(filename);
205         // TODO:calibrate weapon time for shot and reload, angle, accuracy
206         return new Weapon(wt, conf);
207     } catch (...) {
208         FSERR(Log::k_FLG_IO, "WeaponManager", "loadWeapon", ("File %s cannot be read", filename.c_str()))
209         return NULL;
210     }
211 }
212 
saveToFile(PortableFile & file)213 bool WeaponManager::saveToFile(PortableFile &file) {
214     file.write32(availableWeapons_.size());
215 
216     for(unsigned int i=0; i<availableWeapons_.size(); i++) {
217         Weapon *pWeapon = availableWeapons_.get(i);
218         file.write32(pWeapon->getWeaponType());
219     }
220 
221     return true;
222 }
223 
loadFromFile(PortableFile & infile,const FormatVersion & v)224 bool WeaponManager::loadFromFile(PortableFile &infile, const FormatVersion& v) {
225     int nbWeap = infile.read32();
226 
227     for (int i = 0; i < nbWeap; i++) {
228         int type = infile.read32();
229         Weapon::WeaponType wt = Weapon::Unknown;
230         switch (type) {
231             case Weapon::Persuadatron:
232                 wt = Weapon::Persuadatron;
233                 break;
234             case Weapon::Pistol:
235                 wt = Weapon::Pistol;
236                 break;
237             case Weapon::GaussGun:
238                 wt = Weapon::GaussGun;
239                 break;
240             case Weapon::Shotgun:
241                 wt = Weapon::Shotgun;
242                 break;
243             case Weapon::Uzi:
244                 wt = Weapon::Uzi;
245                 break;
246             case Weapon::Minigun:
247                 wt = Weapon::Minigun;
248                 break;
249             case Weapon::Laser:
250                 wt = Weapon::Laser;
251                 break;
252             case Weapon::Flamer:
253                 wt = Weapon::Flamer;
254                 break;
255             case Weapon::LongRange:
256                 wt = Weapon::LongRange;
257                 break;
258             case Weapon::Scanner:
259                 wt = Weapon::Scanner;
260                 break;
261             case Weapon::MediKit:
262                 wt = Weapon::MediKit;
263                 break;
264             case Weapon::TimeBomb:
265                 wt = Weapon::TimeBomb;
266                 break;
267             case Weapon::AccessCard:
268                 wt = Weapon::AccessCard;
269                 break;
270             case Weapon::EnergyShield:
271                 wt = Weapon::EnergyShield;
272                 break;
273             default:
274                 wt = Weapon::Unknown;
275         }
276         // enable weapon
277         enableWeapon(wt);
278     }
279 
280     return true;
281 }
282 
checkDmgTypeCanShootStrict(uint32 dmg,bool & can_shoot)283 bool WeaponManager::checkDmgTypeCanShootStrict(uint32 dmg, bool &can_shoot)
284 {
285     bool found = false;
286     can_shoot = false;
287 
288     for (std::vector<Weapon *>::iterator it = all_game_weapons_.begin();
289         it != all_game_weapons_.end();it++)
290     {
291         if ((*it)->dmgType() == dmg) {
292             found = true;
293             if (((*it)->shotProperty() & Weapon::spe_CanShoot) != 0)
294                 can_shoot = true;
295         }
296     }
297 
298     return found;
299 }
300 
checkDmgTypeCanShootNonStrict(uint32 dmg,bool & can_shoot)301 bool WeaponManager::checkDmgTypeCanShootNonStrict(uint32 dmg, bool &can_shoot)
302 {
303     bool found = false;
304     can_shoot = false;
305 
306     for (std::vector<Weapon *>::iterator it = all_game_weapons_.begin();
307         it != all_game_weapons_.end();it++)
308     {
309         if (((*it)->dmgType() & dmg) != 0) {
310             found = true;
311             if ((*it)->canShoot())
312                 can_shoot = true;
313         }
314     }
315 
316     return found;
317 
318 }
319 
320