00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "mine.h"
00024 #include <iostream>
00025 #include <sstream>
00026 #include "explosion.h"
00027 #include "../game/config.h"
00028 #include "../game/time.h"
00029 #include "../graphic/sprite.h"
00030 #include "../include/app.h"
00031 #include "../include/constant.h"
00032 #include "../interface/game_msg.h"
00033 #include "../map/map.h"
00034 #include "../object/objects_list.h"
00035 #include "../team/macro.h"
00036 #include "../tool/debug.h"
00037 #include "../tool/i18n.h"
00038 #include "../network/randomsync.h"
00039 #include "../tool/resource_manager.h"
00040
00041 #ifdef __MINGW32__
00042 #undef LoadImage
00043 #endif
00044
00045 const double DEPART_FONCTIONNEMENT = 5;
00046
00047 ObjMine::ObjMine(MineConfig& cfg,
00048 WeaponLauncher * p_launcher) :
00049 WeaponProjectile("mine", cfg, p_launcher)
00050 {
00051 m_allow_negative_y = true;
00052 animation = false;
00053 channel = -1;
00054 is_active = true;
00055 explode_with_collision = false;
00056
00057 escape_time = 0;
00058
00059
00060 fake = !(randomSync.GetLong(0, 9));
00061 }
00062
00063 void ObjMine::FakeExplosion()
00064 {
00065 MSG_DEBUG("mine", "Fake explosion");
00066
00067 jukebox.Play("share", "weapon/mine_fake");
00068 ParticleEngine::AddNow(GetPosition(), 5, particle_SMOKE, true);
00069
00070 if ( animation )
00071 {
00072 MSG_DEBUG("mine", "Desactive detection..");
00073
00074 animation = false;
00075 image->SetCurrentFrame(0);
00076 }
00077 if (launcher != NULL) launcher->SignalProjectileTimeout();
00078
00079 SetCollisionModel(false, false, false);
00080 }
00081
00082 void ObjMine::StartTimeout()
00083 {
00084 if (!animation)
00085 {
00086 animation=true;
00087 MSG_DEBUG("mine", "EnableDetection - CurrentTime : %d",Time::GetInstance()->ReadSec() );
00088 attente = Time::GetInstance()->ReadSec() + cfg.timeout;
00089 MSG_DEBUG("mine", "EnableDetection : %d", attente);
00090
00091 channel = jukebox.Play("share", "weapon/mine_beep", -1);
00092 }
00093 }
00094
00095 void ObjMine::Detection()
00096 {
00097 uint current_time = Time::GetInstance()->ReadSec();
00098
00099 if (escape_time == 0)
00100 {
00101 escape_time = current_time + static_cast<MineConfig&>(cfg).escape_time;
00102 MSG_DEBUG("mine", "Initialize escape_time : %d", current_time);
00103 return;
00104 }
00105
00106 if (current_time < escape_time) return;
00107
00108 MSG_DEBUG("mine", "Escape_time is finished : %d", current_time);
00109
00110 FOR_ALL_LIVING_CHARACTERS(equipe, ver)
00111 {
00112 if (MeterDistance (GetCenter(), ver->GetCenter()) < static_cast<MineConfig&>(cfg).detection_range
00113 && !animation)
00114 {
00115 std::string txt = Format(_("%s is next to a mine!"),
00116 ver -> GetName().c_str());
00117 GameMessages::GetInstance()->Add (txt);
00118 StartTimeout();
00119 return;
00120 }
00121 }
00122 }
00123
00124 void ObjMine::Refresh()
00125 {
00126
00127
00128 if (!is_active)
00129 {
00130 jukebox.Stop(channel);
00131 channel = -1;
00132 escape_time = 0;
00133 return;
00134 }
00135
00136
00137 if (!animation)
00138 {
00139 Detection();
00140 }
00141 else
00142 {
00143 image->Update();
00144
00145
00146 if (attente < Time::GetInstance()->ReadSec())
00147 {
00148 is_active = false;
00149 jukebox.Stop(channel);
00150 channel = -1;
00151 if (!fake) Explosion();
00152 else FakeExplosion();
00153 if (launcher != NULL) launcher->SignalProjectileTimeout();
00154 }
00155 }
00156 }
00157
00158 bool ObjMine::IsImmobile() const
00159 {
00160 if (is_active && animation) return false;
00161 return PhysicalObj::IsImmobile();
00162 }
00163
00164 void ObjMine::Draw()
00165 {
00166 image->Draw(GetPosition());
00167 }
00168
00169
00170 MineConfig * MineConfig::singleton = NULL;
00171
00172 MineConfig * MineConfig::GetInstance()
00173 {
00174 if (singleton == NULL) {
00175 singleton = new MineConfig();
00176 }
00177 return singleton;
00178 }
00179
00180
00181
00182 Mine::Mine() : WeaponLauncher(WEAPON_MINE, "minelauncher", MineConfig::GetInstance(), VISIBLE_ONLY_WHEN_INACTIVE)
00183 {
00184 m_name = _("Mine");
00185 ReloadLauncher();
00186 }
00187
00188 WeaponProjectile * Mine::GetProjectileInstance()
00189 {
00190 return dynamic_cast<WeaponProjectile *>
00191 (new ObjMine(cfg(), dynamic_cast<WeaponLauncher *>(this)));
00192 }
00193
00194 bool Mine::p_Shoot()
00195 {
00196 int x,y;
00197 PosXY (x,y);
00198 Add (x, y);
00199
00200 return true;
00201 }
00202
00203 void Mine::Add (int x, int y)
00204 {
00205 projectile -> SetXY ( Point2i(x, y) );
00206 projectile -> SetOverlappingObject(&ActiveCharacter());
00207
00208 Point2d speed_vector;
00209 ActiveCharacter().GetSpeedXY(speed_vector);
00210 projectile -> SetSpeedXY (speed_vector);
00211 lst_objects.AddObject (projectile);
00212 projectile = NULL;
00213 ReloadLauncher();
00214 }
00215
00216 MineConfig& Mine::cfg()
00217 {
00218 return static_cast<MineConfig&>(*extra_params);
00219 }
00220
00221 MineConfig::MineConfig()
00222 {
00223 detection_range= 1;
00224 timeout = 3;
00225 escape_time = 2;
00226 }
00227
00228 void MineConfig::LoadXml(xmlpp::Element *elem)
00229 {
00230 ExplosiveWeaponConfig::LoadXml (elem);
00231 XmlReader::ReadUint(elem, "escape_time", escape_time);
00232 XmlReader::ReadDouble(elem, "detection_range", detection_range);
00233 }