1 /******************************************************************************
2  *  Warmux is a convivial mass murder game.
3  *  Copyright (C) 2001-2011 Warmux Team.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18  ******************************************************************************
19  * Refresh des armes.
20  *****************************************************************************/
21 
22 #include "weapon/weapons_list.h"
23 //-----------------------------------------------------------------------------
24 #include <algorithm>
25 #include "weapon/all.h"
26 #include "weapon/explosion.h"
27 #include "interface/interface.h"
28 #include "map/camera.h"
29 #include "map/maps_list.h"
30 #include "object/objects_list.h"
31 #include "team/macro.h"
32 #include "team/team.h"
33 #include "tool/resource_manager.h"
34 #include "network/randomsync.h"
35 //-----------------------------------------------------------------------------
36 
37 //-----------------------------------------------------------------------------
38 
~WeaponsList()39 WeaponsList::~WeaponsList()
40 {
41   weapons_list_it it=m_weapons_list.begin(), end=m_weapons_list.end();
42   for (; it != end; ++it)
43     delete *it;
44 
45   // no need to delete objects in m_weapons_launcher_list nor clear the 2 lists !
46   // no need either to release profile, ResourceManager will do it on exit
47   weapons_res_profile = NULL;
48 }
49 
50 //-----------------------------------------------------------------------------
51 
WeaponsList(const xmlNode * weapons_xml)52 WeaponsList::WeaponsList(const xmlNode* weapons_xml)
53 {
54   weapons_res_profile = GetResourceManager().LoadXMLProfile("weapons.xml", false);
55 
56   // First launcher weapons
57   m_launcher_weapons_list.push_back(new AnvilLauncher);
58   m_launcher_weapons_list.push_back(new TuxLauncher);
59   m_launcher_weapons_list.push_back(new GnuLauncher);
60   m_launcher_weapons_list.push_back(new PolecatLauncher);
61   m_launcher_weapons_list.push_back(new BounceBallLauncher);
62   m_launcher_weapons_list.push_back(new AutomaticBazooka);
63   m_launcher_weapons_list.push_back(new GrenadeLauncher);
64   m_launcher_weapons_list.push_back(new DiscoGrenadeLauncher);
65   m_launcher_weapons_list.push_back(new ClusterLauncher);
66   m_launcher_weapons_list.push_back(new FootBombLauncher);
67   m_launcher_weapons_list.push_back(new Bazooka);
68   m_launcher_weapons_list.push_back(new RiotBomb);
69   m_launcher_weapons_list.push_back(new Cluzooka);
70   m_launcher_weapons_list.push_back(new SubMachineGun);
71   m_launcher_weapons_list.push_back(new Gun);
72   m_launcher_weapons_list.push_back(new Shotgun);
73   m_launcher_weapons_list.push_back(new SnipeRifle);
74   m_launcher_weapons_list.push_back(new RailGun);
75   m_launcher_weapons_list.push_back(new Dynamite);
76   m_launcher_weapons_list.push_back(new FlameThrower);
77   m_launcher_weapons_list.push_back(new Mine);
78 
79   // Copy launcher weapons to normal list
80   //m_weapons_list = m_launcher_weapons_list;
81   m_weapons_list.insert(m_weapons_list.end(),
82                         m_launcher_weapons_list.begin(),
83                         m_launcher_weapons_list.end());
84 
85 
86   // Add other weapons
87   m_weapons_list.push_back(new Baseball);
88   m_weapons_list.push_back(new AirAttack);
89   m_weapons_list.push_back(new Slap);
90   m_weapons_list.push_back(new Teleportation);
91   m_weapons_list.push_back(new Parachute);
92   m_weapons_list.push_back(new Suicide);
93   m_weapons_list.push_back(new SkipTurn);
94   m_weapons_list.push_back(new JetPack);
95   m_weapons_list.push_back(new Airhammer);
96   m_weapons_list.push_back(new Construct);
97   m_weapons_list.push_back(new LowGrav);
98   m_weapons_list.push_back(new Grapple);
99   m_weapons_list.push_back(new Blowtorch);
100   m_weapons_list.push_back(new Syringe);
101 
102   std::list<Weapon*>::iterator
103     itw = m_weapons_list.begin(),
104     end = m_weapons_list.end();
105 
106   for (; itw != end ; ++itw) {
107     (*itw)->LoadXml(weapons_xml);
108   }
109 }
110 
111 
112 //-----------------------------------------------------------------------------
113 
UpdateTranslation()114 void WeaponsList::UpdateTranslation()
115 {
116   weapons_list_it it;
117   for (it = m_weapons_list.begin(); it != m_weapons_list.end(); it++) {
118     (*it)->UpdateTranslationStrings();
119   }
120 }
121 
122 //-----------------------------------------------------------------------------
123 
GetWeaponBySort(Weapon::category_t sort,Weapon::Weapon_type & type)124 bool WeaponsList::GetWeaponBySort(Weapon::category_t sort, Weapon::Weapon_type &type)
125 {
126   weapons_list_it it, end=m_weapons_list.end();
127   bool open = ActiveMap()->LoadedData()->IsOpened();
128 
129   /* find the current position */
130   it = std::find(m_weapons_list.begin(),
131                  m_weapons_list.end(),
132                  &ActiveTeam().GetWeapon());
133 
134   /* if the current weapon match the criteria */
135   if (it != end && ActiveTeam().GetWeapon().Category() == sort)
136     {
137       /* try to find the next weapon matching our criteria */
138       do {
139         ++it;
140       } while(it != end
141               && ((*it)->Category() != sort
142                   || ActiveTeam().ReadNbAmmos((*it)->GetType()) == 0
143                   || (!((*it)->CanBeUsedOnClosedMap()) && !open))
144               );
145 
146       /* Ok, a weapon was found let's return it */
147       if (it != end && (*it)->Category() == sort)
148         {
149           type = (*it)->GetType();
150           return true;
151         }
152     }
153   /* we didn't find a valid weapon after the current one ; lets wrap:
154    * restart from the begining and try to find the first one matching
155    * our criteria */
156   it = m_weapons_list.begin();
157   while(it != end && (*it)->Category() != sort)
158     ++it;
159 
160   /* no weapon of this sort was found -> give up... */
161   if (it == end)
162     return false;
163 
164   /* try to find the next weapon matching our criteria */
165   while(it != end
166       && ((*it)->Category() != sort
167         || ActiveTeam().ReadNbAmmos((*it)->GetType()) == 0
168             || (!(*it)->CanBeUsedOnClosedMap() && open)))
169     ++it;
170 
171   /* Ok, a weapon was found let's return it if it is not the one active */
172   if (it != end && (*it)->Category() == sort && (*it) != &ActiveTeam().GetWeapon())
173     {
174       type = (*it)->GetType();
175       return true;
176     }
177 
178   /* we definitly found nothing... */
179   return false;
180 }
181 
GetRandomWeaponToDrop()182 Weapon * WeaponsList::GetRandomWeaponToDrop()
183 {
184   std::list<Weapon*>::iterator it;
185   Double probability_sum = 0;
186   for (it = m_weapons_list.begin(); it != m_weapons_list.end(); ++it) {
187     probability_sum += (*it)->GetDropProbability();
188   }
189   ASSERT(probability_sum > 0);
190 
191   MSG_DEBUG("random.get", "WeaponList::GetRandomWeaponToDrop()");
192   Double num = RandomSync().GetDouble(0, probability_sum);
193   Double total_bf_weapon = 0;
194   Double total_after_weapon = 0;
195 
196   for (it = m_weapons_list.begin(); it != m_weapons_list.end(); it++) {
197     Weapon * weapon = *it;
198     total_after_weapon = total_bf_weapon + weapon->GetDropProbability();
199     if (total_bf_weapon < num && num <= total_after_weapon) {
200       MSG_DEBUG("bonus","Weapon choosed: %s", weapon->GetName().c_str());
201       return weapon;
202     }
203     total_bf_weapon = total_after_weapon;
204   }
205   ASSERT(false);
206   return NULL;
207 }
208 
209 //-----------------------------------------------------------------------------
210 
211 class test_weapon_type {
212   private:
213     Weapon::Weapon_type m_type;
214   public:
test_weapon_type(const Weapon::Weapon_type & type)215     test_weapon_type(const Weapon::Weapon_type &type) :  m_type(type){ }
operator ()(const Weapon * w) const216     bool operator() (const Weapon* w) const { return w->GetType()==m_type; }
217 };
218 
GetWeapon(Weapon::Weapon_type type) const219 Weapon* WeaponsList::GetWeapon (Weapon::Weapon_type type) const
220 {
221   weapons_list_it it;
222   it = std::find_if(m_weapons_list.begin(), m_weapons_list.end(), test_weapon_type(type));
223   ASSERT (it != m_weapons_list.end());
224   return *it;
225 }
226 
GetWeaponLauncher(Weapon::Weapon_type type) const227 WeaponLauncher* WeaponsList::GetWeaponLauncher(Weapon::Weapon_type type) const
228 {
229   launcher_weapons_list_it it;
230   it = std::find_if(m_launcher_weapons_list.begin(), m_launcher_weapons_list.end(), test_weapon_type(type));
231   ASSERT (it != m_launcher_weapons_list.end());
232   return *it;
233 }
234 
235 //-----------------------------------------------------------------------------
236