00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "launcher.h"
00023
00024 #include <sstream>
00025
00026 #include "explosion.h"
00027 #include "../game/config.h"
00028 #include "../game/time.h"
00029 #include "../graphic/video.h"
00030 #include "../include/action_handler.h"
00031 #include "../include/app.h"
00032 #include "../interface/game_msg.h"
00033 #include "../map/camera.h"
00034 #include "../object/objects_list.h"
00035 #include "../team/macro.h"
00036 #include "../team/teams_list.h"
00037 #include "../tool/debug.h"
00038 #include "../tool/math_tools.h"
00039 #include "../tool/i18n.h"
00040
00041 #ifdef DEBUG
00042
00043 #endif
00044
00045 WeaponBullet::WeaponBullet(const std::string &name,
00046 ExplosiveWeaponConfig& cfg,
00047 WeaponLauncher * p_launcher) :
00048 WeaponProjectile(name, cfg, p_launcher)
00049 {
00050 explode_colliding_character = true;
00051 ResetTimeOut();
00052 }
00053
00054
00055 void WeaponBullet::SignalGroundCollision()
00056 {
00057 jukebox.Play("share", "weapon/ricoche1");
00058 WeaponProjectile::SignalGroundCollision();
00059 launcher->IncMissedShots();
00060 }
00061
00062 void WeaponBullet::SignalOutOfMap()
00063 {
00064 WeaponProjectile::SignalOutOfMap();
00065 launcher->IncMissedShots();
00066 }
00067
00068 void WeaponBullet::SignalObjectCollision(PhysicalObj * obj)
00069 {
00070 if (typeid(*obj) != typeid(Character)) {
00071 obj->AddDamage(cfg.damage);
00072 Explosion();
00073 } else {
00074 Character * tmp = (Character*)(obj);
00075 tmp -> SetEnergyDelta (-cfg.damage);
00076 tmp -> AddSpeed (2, GetSpeedAngle());
00077 Ghost();
00078 }
00079 }
00080
00081 void WeaponBullet::Refresh()
00082 {
00083 WeaponProjectile::Refresh();
00084 image->SetRotation_rad(GetSpeedAngle());
00085 }
00086
00087 void WeaponBullet::DoExplosion()
00088 {
00089 Point2i pos = GetCenter();
00090 ApplyExplosion (pos, cfg, "", false, ParticleEngine::LittleESmoke);
00091 }
00092
00093
00094
00095 WeaponProjectile::WeaponProjectile (const std::string &name,
00096 ExplosiveWeaponConfig& p_cfg,
00097 WeaponLauncher * p_launcher)
00098 : PhysicalObj (name), cfg(p_cfg)
00099 {
00100 m_allow_negative_y = true;
00101 SetCollisionModel(false, true, true);
00102 launcher = p_launcher;
00103
00104 explode_colliding_character = false;
00105 explode_with_timeout = true;
00106 explode_with_collision = true;
00107
00108 image = resource_manager.LoadSprite( weapons_res_profile, name);
00109 image->EnableRotationCache(32);
00110 SetSize(image->GetSize());
00111
00112
00113 int dx = image->GetWidth()/2-1;
00114 int dy = image->GetHeight()/2-1;
00115 SetTestRect (dx, dx, dy, dy);
00116
00117 ResetTimeOut();
00118 }
00119
00120 WeaponProjectile::~WeaponProjectile()
00121 {
00122
00123 }
00124
00125 void WeaponProjectile::Shoot(double strength)
00126 {
00127 MSG_DEBUG("weapon_projectile", "shoot.\n");
00128
00129 Init();
00130
00131 if (launcher != NULL) launcher->IncActiveProjectile();
00132
00133
00134 ResetConstants();
00135
00136
00137 SetXY(launcher->GetGunHolePosition());
00138 SetOverlappingObject(&ActiveCharacter());
00139
00140
00141 double angle = ActiveCharacter().GetFiringAngle();
00142 RandomizeShoot(angle,strength);
00143 SetSpeed (strength, angle);
00144 PutOutOfGround(angle);
00145
00146 begin_time = Time::GetInstance()->Read();
00147
00148 ShootSound();
00149
00150 lst_objects.AddObject (this);
00151 camera.FollowObject(this, true, true, true);
00152 }
00153
00154 void WeaponProjectile::ShootSound()
00155 {
00156 jukebox.Play(ActiveTeam().GetSoundProfile(), "fire");
00157 }
00158
00159 void WeaponProjectile::Refresh()
00160 {
00161
00162 double tmp = Time::GetInstance()->Read() - begin_time;
00163
00164 if(cfg.timeout && tmp > 1000 * (GetTotalTimeout())) SignalTimeout();
00165 }
00166
00167 void WeaponProjectile::Draw()
00168 {
00169 image->Draw(GetPosition());
00170
00171 int tmp = GetTotalTimeout();
00172
00173 if (cfg.timeout && tmp != 0)
00174 {
00175 tmp -= (int)((Time::GetInstance()->Read() - begin_time) / 1000);
00176 if (tmp >= 0)
00177 {
00178 std::ostringstream ss;
00179 ss << tmp ;
00180 int txt_x = GetX() + GetWidth() / 2;
00181 int txt_y = GetY() - GetHeight();
00182 (*Font::GetInstance(Font::FONT_SMALL)).WriteCenterTop( Point2i(txt_x, txt_y) - camera.GetPosition(),
00183 ss.str(), white_color);
00184 }
00185 }
00186 }
00187
00188 bool WeaponProjectile::IsImmobile() const
00189 {
00190 if(explode_with_timeout && begin_time + GetTotalTimeout() * 1000 > Time::GetInstance()->Read())
00191 return false;
00192 return PhysicalObj::IsImmobile();
00193 }
00194
00195
00196 void WeaponProjectile::SignalObjectCollision(PhysicalObj * obj)
00197 {
00198 assert (obj != NULL);
00199
00200 if (explode_colliding_character)
00201 Explosion();
00202 }
00203
00204
00205 void WeaponProjectile::SignalGroundCollision()
00206 {
00207 if (explode_with_collision)
00208 Explosion();
00209 }
00210
00211
00212 void WeaponProjectile::SignalCollision()
00213 {
00214 if (launcher != NULL && !launcher->ignore_collision_signal) launcher->SignalProjectileCollision();
00215 }
00216
00217
00218 void WeaponProjectile::SignalDrowning()
00219 {
00220 PhysicalObj::SignalDrowning();
00221 if (launcher != NULL && !launcher->ignore_drowning_signal)
00222 launcher->SignalProjectileDrowning();
00223 }
00224
00225
00226 void WeaponProjectile::SignalGhostState(bool)
00227 {
00228 if (launcher != NULL && !launcher->ignore_ghost_state_signal)
00229 launcher->SignalProjectileGhostState();
00230 }
00231
00232 void WeaponProjectile::SignalOutOfMap()
00233 {
00234 }
00235
00236
00237 void WeaponProjectile::RandomizeShoot(double &angle,double &strength)
00238 {
00239 }
00240
00241
00242 void WeaponProjectile::Explosion()
00243 {
00244 MSG_DEBUG (m_name.c_str(), "Explosion");
00245 DoExplosion();
00246 SignalExplosion();
00247 Ghost();
00248 }
00249
00250 void WeaponProjectile::SignalExplosion()
00251 {
00252 if (launcher != NULL && !launcher->ignore_explosion_signal)
00253 launcher->SignalProjectileExplosion();
00254 }
00255
00256 void WeaponProjectile::DoExplosion()
00257 {
00258 Point2i pos = GetCenter();
00259 ApplyExplosion (pos, cfg);
00260 }
00261
00262 void WeaponProjectile::IncrementTimeOut()
00263 {
00264 if (cfg.allow_change_timeout && GetTotalTimeout()<(int)cfg.timeout*2)
00265 m_timeout_modifier += 1 ;
00266 }
00267
00268 void WeaponProjectile::DecrementTimeOut()
00269 {
00270
00271 if (cfg.allow_change_timeout && GetTotalTimeout()>1)
00272 m_timeout_modifier -= 1 ;
00273 }
00274
00275 void WeaponProjectile::SetTimeOut(int timeout)
00276 {
00277 if (cfg.allow_change_timeout && timeout <= (int)cfg.timeout*2 && timeout >= 1)
00278 m_timeout_modifier = timeout - cfg.timeout ;
00279 }
00280
00281 void WeaponProjectile::ResetTimeOut()
00282 {
00283 m_timeout_modifier = 0 ;
00284 }
00285
00286 int WeaponProjectile::GetTotalTimeout() const
00287 {
00288 return (int)(cfg.timeout)+m_timeout_modifier;
00289 }
00290
00291
00292 void WeaponProjectile::SignalTimeout()
00293 {
00294 if (launcher != NULL && !launcher->ignore_timeout_signal) launcher->SignalProjectileTimeout();
00295 if (explode_with_timeout) Explosion();
00296 }
00297
00298
00299 bool WeaponProjectile::change_timeout_allowed()
00300 {
00301 return cfg.allow_change_timeout;
00302 }
00303
00304
00305
00306 WeaponLauncher::WeaponLauncher(Weapon_type type,
00307 const std::string &id,
00308 EmptyWeaponConfig * params,
00309 weapon_visibility_t visibility) :
00310 Weapon(type, id, params, visibility)
00311 {
00312 projectile = NULL;
00313 nb_active_projectile = 0;
00314 missed_shots = 0;
00315 announce_missed_shots = true;
00316 ignore_timeout_signal = false;
00317 ignore_collision_signal = false;
00318 ignore_explosion_signal = false;
00319 ignore_ghost_state_signal = false;
00320 ignore_drowning_signal = false;
00321 }
00322
00323 WeaponLauncher::~WeaponLauncher()
00324 {
00325 if (projectile) delete projectile;
00326 }
00327
00328 bool WeaponLauncher::p_Shoot ()
00329 {
00330
00331
00332
00333
00334
00335
00336 projectile->Shoot (m_strength);
00337 projectile = NULL;
00338 ReloadLauncher();
00339 return true;
00340 }
00341
00342 bool WeaponLauncher::ReloadLauncher()
00343 {
00344 if (projectile) return false;
00345 projectile = GetProjectileInstance();
00346 return true;
00347 }
00348
00349
00350 void WeaponLauncher::DirectExplosion()
00351 {
00352 Point2i pos = ActiveCharacter().GetCenter();
00353 ApplyExplosion (pos, cfg());
00354 }
00355
00356
00357 void WeaponLauncher::SignalProjectileExplosion()
00358 {
00359 DecActiveProjectile();
00360 m_is_active = false;
00361 }
00362
00363
00364 void WeaponLauncher::SignalProjectileCollision()
00365 {
00366 m_is_active = false;
00367 }
00368
00369
00370 void WeaponLauncher::SignalProjectileGhostState()
00371 {
00372 m_is_active = false;
00373 }
00374
00375
00376 void WeaponLauncher::SignalProjectileTimeout()
00377 {
00378 m_is_active = false;
00379 }
00380
00381
00382 void WeaponLauncher::SignalProjectileDrowning()
00383 {
00384 m_is_active = false;
00385 }
00386
00387
00388 void WeaponLauncher::IncActiveProjectile()
00389 {
00390 ++nb_active_projectile;
00391 }
00392
00393 void WeaponLauncher::DecActiveProjectile()
00394 {
00395 --nb_active_projectile;
00396 }
00397
00398
00399 void WeaponLauncher::Refresh()
00400 {
00401 }
00402
00403 void WeaponLauncher::Draw()
00404 {
00405
00406 if (projectile->change_timeout_allowed())
00407 {
00408 if( IsActive() )
00409 return;
00410
00411 int tmp = projectile->GetTotalTimeout();
00412 std::ostringstream ss;
00413 ss << tmp;
00414 ss << "s";
00415 int txt_x = ActiveCharacter().GetX() + ActiveCharacter().GetWidth() / 2;
00416 int txt_y = ActiveCharacter().GetY() - ActiveCharacter().GetHeight();
00417 (*Font::GetInstance(Font::FONT_SMALL)).WriteCenterTop( Point2i(txt_x, txt_y) - camera.GetPosition(),
00418 ss.str(), white_color);
00419 }
00420
00421 Weapon::Draw();
00422
00423 #ifdef DEBUG_EXPLOSION_CONFIG
00424 ExplosiveWeaponConfig* cfg = dynamic_cast<ExplosiveWeaponConfig*>(extra_params);
00425 if( cfg != NULL )
00426 {
00427 Point2i p = ActiveCharacter().GetHandPosition() - camera.GetPosition();
00428
00429 AppWormux::GetInstance()->video.window.CircleColor(p.x, p.y, (int)cfg->blast_range, c_red);
00430
00431 AppWormux::GetInstance()->video.window.CircleColor(p.x, p.y, (int)cfg->explosion_range, c_black);
00432 }
00433 AppWormux::GetInstance()->video.window.CircleColor(GetGunHolePosition().x-camera.GetPositionX(), GetGunHolePosition().y-camera.GetPositionY(), 5, c_black);
00434 #endif
00435 }
00436
00437 void WeaponLauncher::p_Select()
00438 {
00439 missed_shots = 0;
00440 if (projectile->change_timeout_allowed())
00441 {
00442 force_override_keys = true;
00443 projectile->ResetTimeOut();
00444 }
00445 Weapon::p_Select();
00446 }
00447
00448 void WeaponLauncher::p_Deselect()
00449 {
00450 if (projectile->change_timeout_allowed())
00451 {
00452 force_override_keys = false;
00453 }
00454 }
00455
00456 void WeaponLauncher::IncMissedShots()
00457 {
00458 missed_shots++;
00459 if(announce_missed_shots)
00460 GameMessages::GetInstance()->Add (_("Your shot has missed!"));
00461 }
00462
00463 void WeaponLauncher::HandleKeyEvent(Action::Action_t action, Keyboard::Key_Event_t event_type)
00464 {
00465 if (event_type == Keyboard::KEY_RELEASED)
00466 switch (action) {
00467 case Action::ACTION_WEAPON_1:
00468 projectile->SetTimeOut(1);
00469 break;
00470 case Action::ACTION_WEAPON_2:
00471 projectile->SetTimeOut(2);
00472 break;
00473 case Action::ACTION_WEAPON_3:
00474 projectile->SetTimeOut(3);
00475 break;
00476 case Action::ACTION_WEAPON_4:
00477 projectile->SetTimeOut(4);
00478 break;
00479 case Action::ACTION_WEAPON_5:
00480 projectile->SetTimeOut(5);
00481 break;
00482 case Action::ACTION_WEAPON_6:
00483 projectile->SetTimeOut(6);
00484 break;
00485 case Action::ACTION_WEAPON_7:
00486 projectile->SetTimeOut(7);
00487 break;
00488 case Action::ACTION_WEAPON_8:
00489 projectile->SetTimeOut(8);
00490 break;
00491 case Action::ACTION_WEAPON_9:
00492 projectile->SetTimeOut(9);
00493 break;
00494
00495 case Action::ACTION_WEAPON_MORE:
00496 projectile->IncrementTimeOut();
00497 break ;
00498
00499 case Action::ACTION_WEAPON_LESS:
00500 projectile->DecrementTimeOut();
00501 break ;
00502
00503 default:
00504 break ;
00505
00506 };
00507
00508 if((action >= Action::ACTION_WEAPON_1 && action <= Action::ACTION_WEAPON_9)
00509 || action == Action::ACTION_WEAPON_MORE || action == Action::ACTION_WEAPON_LESS)
00510 ActionHandler::GetInstance()->NewAction(new Action(Action::ACTION_SET_TIMEOUT, projectile->m_timeout_modifier));
00511
00512 ActiveCharacter().HandleKeyEvent(action, event_type);
00513 }
00514
00515
00516 void WeaponLauncher::ActionUp()
00517 {
00518 projectile->IncrementTimeOut();
00519 }
00520
00521
00522 void WeaponLauncher::ActionDown()
00523 {
00524 projectile->DecrementTimeOut();
00525 }
00526
00527 ExplosiveWeaponConfig& WeaponLauncher::cfg()
00528 {
00529 return static_cast<ExplosiveWeaponConfig&>(*extra_params);
00530 }