00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "explosion.h"
00023 #include "../graphic/surface.h"
00024 #include "../graphic/video.h"
00025 #include "../include/action_handler.h"
00026 #include "../map/camera.h"
00027 #include "../map/map.h"
00028 #include "../network/network.h"
00029 #include "../object/objects_list.h"
00030 #include "../particles/particle.h"
00031 #include "../object/physical_obj.h"
00032 #include "../sound/jukebox.h"
00033 #include "../team/macro.h"
00034 #include "../tool/debug.h"
00035 #include "../tool/math_tools.h"
00036
00037 Profile *weapons_res_profile = NULL;
00038
00039
00040 void ApplyExplosion_server (const Point2i &pos,
00041 const ExplosiveWeaponConfig &config,
00042 const std::string& son,
00043 bool fire_particle,
00044 ParticleEngine::ESmokeStyle smoke);
00045
00046 void ApplyExplosion (const Point2i &pos,
00047 const ExplosiveWeaponConfig &config,
00048 const std::string& son,
00049 bool fire_particle,
00050 ParticleEngine::ESmokeStyle smoke
00051 )
00052 {
00053 if(network.IsLocal())
00054 ApplyExplosion_common(pos, config, son, fire_particle, smoke);
00055 else
00056 if(network.IsServer())
00057 ApplyExplosion_server(pos, config, son, fire_particle, smoke);
00058 else
00059 if(network.IsClient())
00060 return;
00061
00062 }
00063
00064 void ApplyExplosion_common (const Point2i &pos,
00065 const ExplosiveWeaponConfig &config,
00066 const std::string& son,
00067 bool fire_particle,
00068 ParticleEngine::ESmokeStyle smoke
00069 )
00070 {
00071 MSG_DEBUG("explosion", "explosion range : %i\n", config.explosion_range);
00072
00073 #ifdef HAVE_A_REALLY_BIG_CPU
00074
00075 if(config.explosion_range >= 15)
00076 {
00077 for(int y=-config.explosion_range; y < (int)config.explosion_range; y += 10)
00078 {
00079 int dx = (int) (cos(asin((float)y / config.explosion_range)) * (float) y);
00080 for(int x=-dx; x < dx; x += 10)
00081 ParticleEngine::AddNow(pos + Point2i(x-5,y-5), 1, particle_GROUND, true);
00082 }
00083 }
00084 else
00085 ParticleEngine::AddNow(pos, 1, particle_GROUND, true);
00086 #endif
00087
00088
00089 world.Dig(pos, config.explosion_range);
00090
00091
00092 jukebox.Play("share", son);
00093
00094
00095
00096 double highest_force = 0.0;
00097 Character* fastest_character = NULL;
00098 FOR_ALL_CHARACTERS(equipe,ver)
00099 {
00100 double distance = pos.Distance(ver -> GetCenter());
00101 if(distance < 1.0)
00102 distance = 1.0;
00103
00104
00105 if (distance <= config.explosion_range)
00106 {
00107 MSG_DEBUG("explosion", "\n*Character %s : distance= %f", ver->GetName().c_str(), distance);
00108 double dmg = cos(M_PI_2 * distance / config.explosion_range);
00109 dmg *= config.damage;
00110 MSG_DEBUG("explosion", "hit_point_loss energy= %i", ver->GetName().c_str(), dmg);
00111 ver -> SetEnergyDelta (-(int)dmg);
00112 }
00113
00114
00115 if (distance <= config.blast_range)
00116 {
00117 double angle;
00118 double force = cos(M_PI_2 * distance / config.blast_range);
00119 force *= config.blast_force;
00120
00121 if ( force > highest_force )
00122 {
00123 fastest_character = &(*ver);
00124 highest_force = force;
00125 }
00126
00127 if (!EgalZero(distance))
00128 {
00129 angle = pos.ComputeAngle(ver -> GetCenter());
00130 if( angle > 0 )
00131 angle = - angle;
00132 }
00133 else
00134 angle = -M_PI/2;
00135
00136
00137 MSG_DEBUG("explosion", "force = %f", force);
00138 ver->AddSpeed (force / ver->GetMass(), angle);
00139 ver->SignalExplosion();
00140 }
00141 }
00142
00143 if(fastest_character != NULL)
00144 camera.FollowObject (fastest_character, true, true);
00145
00146
00147 FOR_EACH_OBJECT(it)
00148 {
00149 PhysicalObj *obj = *it;
00150 if (!obj->GoesThroughWall() && !obj->IsGhost())
00151 {
00152 double distance = pos.Distance(obj->GetCenter());
00153 if(distance < 1.0)
00154 distance = 1.0;
00155
00156 if (distance <= config.explosion_range)
00157 {
00158 double dmg = cos(M_PI_2 * distance / config.explosion_range);
00159 dmg *= config.damage;
00160 obj->AddDamage (config.damage);
00161 }
00162
00163 if (distance <= config.blast_range)
00164 {
00165 double angle;
00166 double force = cos(M_PI_2 * distance / config.blast_range);
00167 force *= config.blast_force;
00168
00169 if (!EgalZero(distance))
00170 angle = pos.ComputeAngle(obj->GetCenter());
00171 else
00172 angle = -M_PI_2;
00173
00174 if(fastest_character != NULL)
00175 camera.FollowObject (obj, true, true);
00176 obj->AddSpeed (force / obj->GetMass(), angle);
00177 }
00178 }
00179 }
00180
00181 ParticleEngine::AddExplosionSmoke(pos, config.particle_range, smoke);
00182
00183
00184 if (fire_particle)
00185 ParticleEngine::AddNow(pos , 5, particle_FIRE, true);
00186 }
00187
00188 void ApplyExplosion_server (const Point2i &pos,
00189 const ExplosiveWeaponConfig &config,
00190 const std::string& son,
00191 bool fire_particle,
00192 ParticleEngine::ESmokeStyle smoke
00193 )
00194 {
00195 ActionHandler* action_handler = ActionHandler::GetInstance();
00196
00197 Action a_begin_sync(Action::ACTION_SYNC_BEGIN);
00198 network.SendAction(&a_begin_sync);
00199
00200 TeamsList::iterator
00201 it=teams_list.playing_list.begin(),
00202 end=teams_list.playing_list.end();
00203
00204 Action* send_char = new Action(Action::ACTION_SET_CHARACTER_PHYSICS);
00205
00206 for (int team_no = 0; it != end; ++it, ++team_no)
00207 {
00208 Team& team = **it;
00209 Team::iterator
00210 tit = team.begin(),
00211 tend = team.end();
00212
00213 for (int char_no = 0; tit != tend; ++tit, ++char_no)
00214 {
00215 Character &character = *tit;
00216
00217 double distance = pos.Distance( character.GetCenter());
00218
00219
00220 if (distance <= config.explosion_range || distance < config.blast_range)
00221 {
00222
00223 send_char->StoreCharacter(team_no, char_no);
00224 }
00225 }
00226 }
00227 action_handler->NewAction(send_char);
00228
00229 Action* a = new Action(Action::ACTION_EXPLOSION);
00230 a->Push(pos.x);
00231 a->Push(pos.y);
00232 a->Push((int)config.explosion_range);
00233 a->Push((int)config.particle_range);
00234 a->Push((int)config.damage);
00235 a->Push(config.blast_range);
00236 a->Push(config.blast_force);
00237 a->Push(son);
00238 a->Push(fire_particle);
00239 a->Push(smoke);
00240
00241 action_handler->NewAction(a);
00242 Action a_sync_end(Action::ACTION_SYNC_END);
00243 network.SendAction(&a_sync_end);
00244 }