Lightning.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <actions/Lightning.h>
00022 #include <common/Defines.h>
00023 #include <common/RandomGenerator.h>
00024 #ifndef S3D_SERVER
00025         #include <sound/SoundUtils.h>
00026         #include <graph/TextureStore.h>
00027         #include <GLEXT/GLState.h>
00028         #include <GLEXT/GLCamera.h>
00029         #include <sprites/ExplosionTextures.h>
00030 #endif
00031 #include <target/TargetContainer.h>
00032 #include <target/TargetDamageCalc.h>
00033 #include <target/TargetLife.h>
00034 #include <target/TargetSpace.h>
00035 #include <engine/ActionController.h>
00036 #include <weapons/AccessoryStore.h>
00037 #include <math.h>
00038 
00039 Lightning::Lightning(WeaponLightning *weapon,
00040                 WeaponFireContext &weaponContext,
00041                 FixedVector &position, FixedVector &velocity) :
00042         ActionReferenced("Lightning"),
00043         totalTime_(0),
00044         weapon_(weapon),
00045         weaponContext_(weaponContext),
00046         position_(position), velocity_(velocity),
00047         texture_(0)
00048 {
00049 }
00050 
00051 Lightning::~Lightning()
00052 {
00053 }
00054 
00055 void Lightning::init()
00056 {
00057         FixedVector direction = velocity_.Normalize();
00058         std::map<unsigned int, fixed> hurtMap;
00059 
00060         generateLightning(0, 1, weapon_->getSize(), 
00061                 position_, direction, position_, direction,
00062                 hurtMap);
00063 
00064         std::map<unsigned int, fixed>::iterator hurtItor;
00065         for (hurtItor = hurtMap.begin();
00066                 hurtItor != hurtMap.end();
00067                 hurtItor++)
00068         {
00069                 unsigned int playerId = (*hurtItor).first;
00070                 fixed damage = (*hurtItor).second;
00071 
00072                 Target *target = context_->getTargetContainer().getTargetById(playerId);
00073                 if (target)
00074                 {
00075                         TargetDamageCalc::damageTarget(
00076                                 *context_, target, weapon_, weaponContext_, 
00077                                 damage, true, false, false);
00078                 }
00079         }
00080 }
00081 
00082 std::string Lightning::getActionDetails()
00083 {
00084         return S3D::formatStringBuffer("%i,%i,%i %i,%i,%i %s",
00085                 position_[0].getInternal(), position_[1].getInternal(), position_[2].getInternal(),
00086                 velocity_[0].getInternal(), velocity_[1].getInternal(), velocity_[2].getInternal(),
00087                 weapon_->getParent()->getName());
00088 }
00089 
00090 void Lightning::simulate(fixed frameTime, bool &remove)
00091 {
00092 #ifndef S3D_SERVER
00093         if (!context_->getServerMode())
00094         {   
00095                 if (firstTime_)
00096                 { 
00097                         firstTime_ = false;
00098                         if (weapon_->getSound() &&
00099                                 0 != strcmp("none", weapon_->getSound()))
00100                         {
00101                                 SoundBuffer *expSound =
00102                                         Sound::instance()->fetchOrCreateBuffer(
00103                                                 S3D::getDataFile(weapon_->getSound()));
00104                                 SoundUtils::playAbsoluteSound(VirtualSoundPriority::eAction,
00105                                         expSound, position_.asVector());
00106                         }
00107                 } 
00108         }
00109 #endif // #ifndef S3D_SERVER
00110 
00111         totalTime_ += frameTime;
00112         remove = (totalTime_ > weapon_->getTotalTime());
00113         Action::simulate(frameTime, remove);
00114 }
00115 
00116 void Lightning::draw()
00117 {
00118 #ifndef S3D_SERVER
00119         if (!context_->getServerMode())
00120         {
00121                 Vector &cameraPos = 
00122                         GLCamera::getCurrentCamera()->getCurrentPos();
00123 
00124                 GLState state(GLState::TEXTURE_ON | GLState::BLEND_ON);
00125                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00126                 glDepthMask(GL_FALSE);
00127                 glColor4f(1.0f, 1.0f, 1.0f, 
00128                         1.0f - totalTime_.asFloat() / weapon_->getTotalTime().asFloat());
00129 
00130                 if (!texture_)
00131                 {
00132                         std::string file4 = S3D::getDataFile(weapon_->getTexture());
00133                         texture_ = TextureStore::instance()->loadTexture(
00134                                 file4.c_str(), file4.c_str(), false);
00135                 }
00136                 texture_->draw();
00137                 
00138                 Vector offset(0.0f, 0.0f, 0.5f);
00139                 bool began = false; 
00140                 float texCoord = 0.0f;
00141                 std::list<Segment>::iterator itor;
00142                 for (itor = segments_.begin();
00143                         itor != segments_.end();
00144                         itor++)
00145                 {
00146                         Segment &segment = (*itor);
00147                         Vector cameraDir = (segment.start.asVector() - cameraPos).Normalize();
00148                         Vector offset = (segment.direction.asVector() * cameraDir).Normalize();
00149                         offset *= 0.4f;
00150 
00151                         if (!began)
00152                         {
00153                                 began = true;
00154                                 glBegin(GL_QUAD_STRIP);
00155                         }
00156 
00157                         glTexCoord2f(1.0f, texCoord);
00158                         glVertex3fv(segment.start.asVector() + offset * segment.size.asFloat());
00159                         glTexCoord2f(0.0f, texCoord);
00160                         glVertex3fv(segment.start.asVector() - offset * segment.size.asFloat());
00161                         texCoord += 1.0f;
00162 
00163                         if (segment.endsegment)
00164                         {
00165                                 glTexCoord2f(0.0f, texCoord);
00166                                 glVertex3fv(segment.end.asVector() - offset * segment.size.asFloat());
00167                                 glTexCoord2f(1.0f, texCoord);
00168                                 glVertex3fv(segment.end.asVector() + offset * segment.size.asFloat());
00169                                 texCoord += 1.0f;
00170 
00171                                 began = false;
00172                                 glEnd();
00173                         }
00174                 }
00175 
00176                 glDepthMask(GL_TRUE);
00177                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00178         }
00179 #endif // #ifndef S3D_SERVER
00180 }
00181 
00182 void Lightning::dispaceDirection(FixedVector &direction, 
00183         FixedVector &originalDirection, fixed angle)
00184 {
00185         RandomGenerator &generator = context_->getActionController().getRandom();
00186 
00187         int breakCount = 0;
00188 
00189         FixedVector newdir;
00190         while (breakCount++ < 1000)
00191         {
00192                 newdir[0] = (generator.getRandFixed() - fixed(true, 5000)) * 2;
00193                 newdir[1] = (generator.getRandFixed() - fixed(true, 5000)) * 2;
00194                 newdir[2] = (generator.getRandFixed() - fixed(true, 5000)) * 2;
00195                 newdir.StoreNormalize();
00196 
00197                 fixed a = newdir[0] * direction[0] + 
00198                         newdir[1] * direction[1] + 
00199                         newdir[2] * direction[2];
00200                 if (a < angle) continue;
00201 
00202                 fixed b = newdir[0] * originalDirection[0] + 
00203                         newdir[1] * originalDirection[1] + 
00204                         newdir[2] * originalDirection[2];
00205                 if (b >= weapon_->getDerivAngle())
00206                 {
00207                         direction = newdir;
00208                         return;
00209                 }
00210         }       
00211 }
00212 
00213 void Lightning::generateLightning(int id, int depth, fixed size, 
00214         FixedVector &originalPosition, FixedVector &originalDirection,
00215         FixedVector &start, FixedVector &direction,
00216         std::map<unsigned int, fixed> &hurtMap)
00217 {
00218         if (id > 100) return;
00219 
00220         RandomGenerator &generator = context_->getActionController().getRandom();
00221         fixed length = weapon_->getSegLength() + 
00222                 weapon_->getSegVar() * generator.getRandFixed();
00223         FixedVector end = start + direction * length;
00224 
00225         // Add the new lightning segment
00226         segments_.push_back(Segment());
00227         Segment &segment = segments_.back();
00228 
00229         // Set the segment
00230         segment.start = start;
00231         segment.end = end;
00232         segment.size = size;
00233         segment.direction = direction;
00234         segment.endsegment = false;
00235 
00236         // Damage any tanks
00237         damageTargets(segment.end, hurtMap);
00238 
00239         // Rand posibility that we stop
00240         if (depth > 1 && generator.getRandFixed() < 
00241                 weapon_->getDeathProb())
00242         {
00243                 segment.endsegment = true;
00244                 return;
00245         }
00246 
00247         // Check if we have gone too far
00248         if ((originalPosition - end).Magnitude() > 
00249                 weapon_->getConeLength()) 
00250         {
00251                 segment.endsegment = true;
00252                 return;
00253         }
00254 
00255         // Continue this lightning strand
00256         {
00257                 FixedVector newdirection = end - start;
00258                 dispaceDirection(newdirection, originalDirection, 
00259                         weapon_->getAngleVar() * fixed(true, 2500));
00260                 generateLightning(id + 1, depth, size, 
00261                         originalPosition, originalDirection, 
00262                         end, newdirection,
00263                         hurtMap);       
00264         }
00265 
00266         // Make a new strand
00267         if (generator.getRandFixed() <= 
00268                 weapon_->getSplitProb() - fixed(depth - 1) * weapon_->getSplitVar())
00269     {
00270                 fixed newsize = size + weapon_->getSizeVar();
00271                 if (newsize < weapon_->getMinSize()) 
00272                         newsize = weapon_->getMinSize();
00273 
00274                 FixedVector newdirection = end - start;
00275                 dispaceDirection(newdirection, originalDirection, 
00276                         weapon_->getAngleVar());
00277                 generateLightning(id + 1, depth + 1, newsize, 
00278                         originalPosition, originalDirection, 
00279                         end, newdirection,
00280                         hurtMap);       
00281         }
00282 }
00283 
00284 void Lightning::damageTargets(FixedVector &position, 
00285                 std::map<unsigned int, fixed> &hurtMap)
00286 {
00287         if (weapon_->getSegHurt() <= 0) return;
00288 
00289         std::map<unsigned int, Target *> collisionTargets;
00290         context_->getTargetSpace().getCollisionSet(position, 
00291                 weapon_->getSegHurtRadius() * fixed(true, 15000), collisionTargets);
00292         std::map<unsigned int, Target *>::iterator itor;
00293         for (itor = collisionTargets.begin();
00294                 itor != collisionTargets.end();
00295                 itor++)
00296         {
00297                 Target *target = (*itor).second;
00298                 if (target->getAlive() &&
00299                         target->getPlayerId() != weaponContext_.getPlayerId())
00300                 {
00301                         fixed distance = (target->getLife().getTargetPosition() -
00302                                 position).Magnitude();
00303                         if (distance < weapon_->getSegHurtRadius() + 
00304                                 MAX(target->getLife().getSize()[0], target->getLife().getSize()[1]))
00305                         {
00306                                 std::map<unsigned int, fixed>::iterator findItor = 
00307                                         hurtMap.find(target->getPlayerId());
00308                                 if (findItor == hurtMap.end())
00309                                 {
00310                                         hurtMap[target->getPlayerId()] = weapon_->getSegHurt();
00311                                 }
00312                                 else
00313                                 {
00314                                         hurtMap[target->getPlayerId()] += weapon_->getSegHurt();
00315                                 }
00316                         }
00317                 }
00318         }
00319 }

Generated on Mon Feb 16 15:14:48 2009 for Scorched3D by  doxygen 1.5.3