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  * AirHammer - Use it to dig
20  *****************************************************************************/
21 
22 #include "weapon/airhammer.h"
23 #include "weapon/explosion.h"
24 #include "weapon/weapon_cfg.h"
25 
26 //-----------------------------------------------------------------------------
27 #include <sstream>
28 #include "character/character.h"
29 #include "game/game.h"
30 #include "game/game_time.h"
31 #include "include/action_handler.h"
32 #include "interface/game_msg.h"
33 #include "map/map.h"
34 #include "object/objects_list.h"
35 #include "sound/jukebox.h"
36 #include "team/teams_list.h"
37 #include "team/macro.h"
38 #include "team/team.h"
39 #include "tool/resource_manager.h"
40 #include "tool/xml_document.h"
41 
42 //-----------------------------------------------------------------------------
43 
44 const uint MIN_TIME_BETWEEN_JOLT = 100; // in milliseconds
45 
46 //-----------------------------------------------------------------------------
47 
48 class AirhammerConfig : public WeaponConfig
49 {
50 public:
51   uint range;
52   AirhammerConfig();
53   void LoadXml(const xmlNode* elem);
54 };
55 
56 //-----------------------------------------------------------------------------
57 
Airhammer()58 Airhammer::Airhammer():
59   Weapon(WEAPON_AIR_HAMMER, "airhammer", new AirhammerConfig()),
60   active(false),
61   deactivation_requested(false)
62 {
63   UpdateTranslationStrings();
64 
65   m_category = TOOL;
66 
67   impact = GetResourceManager().LoadImage( weapons_res_profile, "airhammer_impact");
68   m_time_between_each_shot = MIN_TIME_BETWEEN_JOLT;
69   m_can_change_weapon = true;
70 }
71 
72 //-----------------------------------------------------------------------------
73 
UpdateTranslationStrings()74 void Airhammer::UpdateTranslationStrings()
75 {
76   m_name = _("Airhammer");
77   m_help = _("Press space to dig\nAmmo is used when counter reaches zero\nOne ammo per turn");
78 }
79 
80 //-----------------------------------------------------------------------------
81 
p_Shoot()82 bool Airhammer::p_Shoot()
83 {
84   // initiate movement ;-)
85   ActiveCharacter().SetRebounding(false);
86 
87   Point2i pos = Point2i(ActiveCharacter().GetX() + ActiveCharacter().GetWidth()/2 - impact.GetWidth()/2,
88                         ActiveCharacter().GetTestRect().GetPositionY() +
89                         ActiveCharacter().GetHeight()  -16);
90 
91   ParticleEngine::AddNow(pos + Point2i(impact.GetWidth()/4,9), 1, particle_AIR_HAMMER,
92                          true, -THREE * QUARTER_PI, 5.0 + GameTime::GetInstance()->Read() % 5);
93   ParticleEngine::AddNow(pos + Point2i(3*impact.GetWidth()/4,9), 1, particle_AIR_HAMMER,
94                          true, -QUARTER_PI, 5.0 + GameTime::GetInstance()->Read() % 5);
95   GetWorld().Dig(pos, impact);
96 
97   return true;
98 }
99 
100 //-----------------------------------------------------------------------------
p_Deselect()101 void Airhammer::p_Deselect()
102 {
103   drill_sound.Stop();
104   select_sound.Stop();
105   ActiveCharacter().SetMovement("breathe");
106   active = false;
107 }
108 
StartShooting()109 void Airhammer::StartShooting()
110 {
111   if (!EnoughAmmo())
112     return;
113   //if the sound isn't already playing, play it again.
114   select_sound.Stop();
115   if (!drill_sound.IsPlaying()) {
116     drill_sound.Play("default","weapon/airhammer", -1);
117   }
118 
119   active = true;
120   deactivation_requested = false;
121 }
122 
StopShooting()123 void Airhammer::StopShooting()
124 {
125   // The airhammer does not get deactivated in this method,
126   // because there could be a shot in progress.
127   // Explantion:
128   // The weapon calls PrepareShot of the active character
129   // which will then call p_Shot when it's ready
130   deactivation_requested = true;
131 }
132 
ShouldAmmoUnitsBeDrawn() const133 bool Airhammer::ShouldAmmoUnitsBeDrawn() const
134 {
135   // Hide that the units are actually at maximum and not at 0
136   // when the ammo counter is at 0.
137   return active || EnoughAmmo();
138 }
139 //-----------------------------------------------------------------------------
140 
Refresh()141 void Airhammer::Refresh()
142 {
143   if (active && deactivation_requested && !ActiveCharacter().IsPreparingShoot()) {
144     active = false;
145     drill_sound.Stop();
146     PlaySoundSelect();
147     ActiveTeam().AccessNbUnits() = 0;
148   }
149   if (EnoughAmmoUnit() && active) {
150     Weapon::RepeatShoot();
151   }
152 }
153 
PlaySoundSelect()154 void Airhammer::PlaySoundSelect()
155 {
156   select_sound.Play("default","weapon/airhammer_select",-1);
157 }
158 
p_Select()159 void Airhammer::p_Select()
160 {
161   PlaySoundSelect();
162 }
163 
GetWeaponWinString(const char * TeamName,uint items_count) const164 std::string Airhammer::GetWeaponWinString(const char *TeamName, uint items_count ) const
165 {
166   return Format(ngettext(
167             "%s team has won %u airhammer! Don't make too much noise with it! Thanks, your neighbours.",
168             "%s team has won %u airhammers! Don't make too much noise with them! Thanks, your neighbours.",
169             items_count), TeamName, items_count);
170 }
171 
172 
173 //-----------------------------------------------------------------------------
174 
cfg()175 AirhammerConfig& Airhammer::cfg()
176 {
177   return static_cast<AirhammerConfig&>(*extra_params);
178 }
179 
180 //-----------------------------------------------------------------------------
181 
AirhammerConfig()182 AirhammerConfig::AirhammerConfig()
183 {
184   range =  30;
185 }
186 
187 //-----------------------------------------------------------------------------
188 
LoadXml(const xmlNode * elem)189 void AirhammerConfig::LoadXml(const xmlNode* elem){
190   WeaponConfig::LoadXml(elem);
191   XmlReader::ReadUint(elem, "range", range);
192 }
193