00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00074 angle_local += acfg.uncontrolled_turn_speed * timestep / 1000.;
00075 if(angle_local > M_PI) angle_local = -M_PI;
00076
00077
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);
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
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.);
00111 SetWindFactor((flying_time - GetTotalTimeout())/acfg.fuel_time/1000.);
00112 } else {
00113 SetGravityFactor(1);
00114 m_force = 0;
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
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
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
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 }