src/weapon/auto_bazooka.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *  Wormux is a convivial mass murder game.
00003  *  Copyright (C) 2001-2004 Lawrence Azzoug.
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00018  ******************************************************************************
00019  * auto bazooka : launch a homing missile
00020  *****************************************************************************/
00021 
00022 #include "auto_bazooka.h"
00023 #include "explosion.h"
00024 #include "../game/time.h"
00025 #include "../graphic/video.h"
00026 #include "../include/app.h"
00027 #include "../interface/game_msg.h"
00028 #include "../interface/mouse.h"
00029 #include "../map/camera.h"
00030 #include "../map/map.h"
00031 #include "../map/wind.h"
00032 #include "../team/teams_list.h"
00033 #include "../tool/math_tools.h"
00034 #include "../tool/i18n.h"
00035 #include "../object/objects_list.h"
00036 #ifdef __MINGW32__
00037 #undef LoadImage
00038 #endif
00039 
00040 class AutomaticBazookaConfig : public ExplosiveWeaponConfig {
00041   public:
00042     double uncontrolled_turn_speed;
00043     double max_controlled_turn_speed;
00044     double fuel_time;
00045     double rocket_force;
00046     AutomaticBazookaConfig();
00047     void LoadXml(xmlpp::Element *elem);
00048 };
00049 
00050 RPG::RPG(AutomaticBazookaConfig& cfg,
00051                                          WeaponLauncher * p_launcher) :
00052   WeaponProjectile("rocket", cfg, p_launcher), smoke_engine(20), m_lastrefresh(0)
00053 {
00054   m_targeted = false;
00055   explode_colliding_character = true;
00056 }
00057 
00058 void RPG::Shoot (double strength)
00059 {
00060   WeaponProjectile::Shoot(strength);
00061   angle_local=ActiveCharacter().GetFiringAngle();
00062 }
00063 
00064 void RPG::Refresh()
00065 {
00066   AutomaticBazookaConfig &acfg = dynamic_cast<AutomaticBazookaConfig &>(cfg);
00067   uint time = Time::GetInstance()->Read();
00068   float flying_time = time - begin_time;
00069   uint timestep = time - m_lastrefresh;
00070   m_lastrefresh = time;
00071   if (!m_targeted)
00072   {
00073     // rocket is turning around herself
00074     angle_local += acfg.uncontrolled_turn_speed * timestep / 1000.;
00075     if(angle_local > M_PI) angle_local = -M_PI;
00076 
00077     // TPS_AV_ATTIRANCE msec later being launched, the rocket is homing to the target
00078     if(flying_time>1000 * GetTotalTimeout())
00079     {
00080       m_targeted = true;
00081       SetSpeed(0,0);
00082       angle_local = GetPosition().ComputeAngle( m_target );
00083       m_force = acfg.rocket_force;
00084       SetExternForce(m_force, angle_local);
00085       SetGravityFactor(0);
00086       SetWindFactor(0);
00087     }
00088   }
00089   else
00090   {
00091     SetExternForce(m_force, angle_local+M_PI_2); // reverse the force applyed on the last Refresh()
00092 
00093     if(flying_time - GetTotalTimeout() < acfg.fuel_time*1000.) {
00094       smoke_engine.AddPeriodic(Point2i(GetX() + GetWidth() / 2,
00095                                        GetY() + GetHeight()/ 2), particle_DARK_SMOKE, false, -1, 2.0);
00096       double wish_angle = GetPosition().ComputeAngle( m_target );
00097       double max_rotation = fabs(acfg.max_controlled_turn_speed * timestep / 1000.);
00098       double diff = fmod(wish_angle-angle_local, M_PI*2);
00099       if(diff < -M_PI) diff += M_PI*2;
00100       if(diff > M_PI) diff -= M_PI*2;
00101       //diff should now be between -M_PI and M_PI...
00102       if(diff > max_rotation) {
00103         angle_local += max_rotation;
00104       } else if (diff < -max_rotation) {
00105         angle_local -= max_rotation;
00106       } else {
00107         angle_local = wish_angle;
00108       }
00109       m_force = acfg.rocket_force * ((acfg.fuel_time*1300. - flying_time + GetTotalTimeout())/acfg.fuel_time/1300.);
00110       SetGravityFactor((flying_time - GetTotalTimeout())/acfg.fuel_time/1000.); // slowly increase gravity
00111       SetWindFactor((flying_time - GetTotalTimeout())/acfg.fuel_time/1000.); // slowly increase wind
00112     } else {
00113       SetGravityFactor(1);
00114       m_force = 0; //if there's no fuel left just let it crash into the ground somewhere
00115       if(!IsDrowned()) {
00116         angle_local += acfg.uncontrolled_turn_speed * timestep / 1000.;
00117         if(angle_local > M_PI) angle_local = - M_PI;
00118       } else {
00119         angle_local = M_PI_2;
00120       }
00121     }
00122 
00123     SetExternForce(m_force, angle_local);
00124 
00125   }
00126   image->SetRotation_rad(angle_local);
00127 }
00128 
00129 void RPG::SignalDrowning()
00130 {
00131   smoke_engine.Stop();
00132   WeaponProjectile::SignalDrowning();
00133 }
00134 
00135 void RPG::SignalOutOfMap()
00136 {
00137   GameMessages::GetInstance()->Add (_("The automatic rocket has left the battlefield..."));
00138   WeaponProjectile::SignalOutOfMap();
00139 }
00140 
00141 // Set the coordinate of the target
00142 void RPG::SetTarget (int x, int y)
00143 {
00144   m_target.x = x;
00145   m_target.y = y;
00146 }
00147 
00148 //-----------------------------------------------------------------------------
00149 
00150 AutomaticBazooka::AutomaticBazooka() :
00151   WeaponLauncher(WEAPON_AUTOMATIC_BAZOOKA, "automatic_bazooka",new AutomaticBazookaConfig() )
00152 {
00153   m_name = _("Automatic Bazooka");
00154   mouse_character_selection = false;
00155   m_allow_change_timeout = true;
00156   m_target.selected = false;
00157   m_target.image = resource_manager.LoadImage( weapons_res_profile, "baz_cible");
00158   ReloadLauncher();
00159 }
00160 
00161 WeaponProjectile * AutomaticBazooka::GetProjectileInstance()
00162 {
00163   return dynamic_cast<WeaponProjectile *>
00164       (new RPG(cfg(),dynamic_cast<WeaponLauncher *>(this)));
00165 }
00166 
00167 void AutomaticBazooka::Draw()
00168 {
00169   WeaponLauncher::Draw();
00170   DrawTarget();
00171 }
00172 
00173 void AutomaticBazooka::Refresh()
00174 {
00175   DrawTarget();
00176   WeaponLauncher::Refresh();
00177 }
00178 
00179 void AutomaticBazooka::p_Select()
00180 {
00181   WeaponLauncher::p_Select();
00182   m_target.selected = false;
00183 
00184   Mouse::GetInstance()->SetPointer(Mouse::POINTER_AIM);
00185 }
00186 
00187 void AutomaticBazooka::p_Deselect()
00188 {
00189   WeaponLauncher::p_Deselect();
00190   if (m_target.selected) {
00191     // need to clear the old target
00192     world.ToRedrawOnMap(Rectanglei(m_target.pos.x-m_target.image.GetWidth()/2,
00193                         m_target.pos.y-m_target.image.GetHeight()/2,
00194                         m_target.image.GetWidth(),
00195                         m_target.image.GetHeight()));
00196   }
00197 
00198   Mouse::GetInstance()->SetPointer(Mouse::POINTER_SELECT);
00199 }
00200 
00201 void AutomaticBazooka::ChooseTarget(Point2i mouse_pos)
00202 {
00203   if (m_target.selected) {
00204     // need to clear the old target
00205     world.ToRedrawOnMap(Rectanglei(m_target.pos.x-m_target.image.GetWidth()/2,
00206                         m_target.pos.y-m_target.image.GetHeight()/2,
00207                         m_target.image.GetWidth(),
00208                         m_target.image.GetHeight()));
00209   }
00210 
00211   m_target.pos = mouse_pos;
00212   m_target.selected = true;
00213 
00214   if(!ActiveTeam().IsLocal())
00215     camera.SetXYabs(mouse_pos - camera.GetSize()/2);
00216   DrawTarget();
00217   static_cast<RPG *>(projectile)->SetTarget(m_target.pos.x, m_target.pos.y);
00218 }
00219 
00220 void AutomaticBazooka::DrawTarget()
00221 {
00222   if( !m_target.selected ) return;
00223 
00224   AppWormux::GetInstance()->video.window.Blit(m_target.image, m_target.pos - m_target.image.GetSize()/2 - camera.GetPosition());
00225 }
00226 
00227 bool AutomaticBazooka::IsReady() const
00228 {
00229   return (EnoughAmmo() && m_target.selected);
00230 }
00231 
00232 AutomaticBazookaConfig &AutomaticBazooka::cfg() {
00233     return static_cast<AutomaticBazookaConfig &>(*extra_params);
00234 }
00235 
00236 AutomaticBazookaConfig::AutomaticBazookaConfig() {
00237     uncontrolled_turn_speed = M_PI*8;
00238     max_controlled_turn_speed = M_PI*4;
00239     fuel_time = 10;
00240     rocket_force = 2500;
00241 }
00242 
00243 void AutomaticBazookaConfig::LoadXml(xmlpp::Element *elem) {
00244     ExplosiveWeaponConfig::LoadXml(elem);
00245     XmlReader::ReadDouble(elem, "uncontrolled_turn_speed", uncontrolled_turn_speed);
00246     XmlReader::ReadDouble(elem, "max_controlled_turn_speed", max_controlled_turn_speed);
00247     XmlReader::ReadDouble(elem, "fuel_time", fuel_time);
00248     XmlReader::ReadDouble(elem, "rocket_force", rocket_force);
00249 }

Generated on Mon Jan 1 13:11:00 2007 for Wormux by  doxygen 1.4.7