00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <actions/Laser.h>
00022 #include <actions/TankDamage.h>
00023 #include <engine/ScorchedContext.h>
00024 #include <engine/ActionController.h>
00025 #include <weapons/AccessoryStore.h>
00026 #include <weapons/Shield.h>
00027 #include <actions/ShieldHit.h>
00028 #include <target/TargetContainer.h>
00029 #include <target/TargetShield.h>
00030 #include <target/TargetLife.h>
00031 #include <target/TargetSpace.h>
00032 #include <common/Defines.h>
00033 #include <common/Logger.h>
00034 #ifndef S3D_SERVER
00035 #include <GLEXT/GLState.h>
00036 #endif
00037 #include <math.h>
00038 #include <set>
00039
00040 Laser::Laser(Weapon *weapon, LaserParams *params,
00041 FixedVector &position, FixedVector &direction,
00042 WeaponFireContext &weaponContext) :
00043 ActionReferenced("Laser"),
00044 params_(params),
00045 totalTime_(0),
00046 drawLength_(0),
00047 firstTime_(true),
00048 weaponContext_(weaponContext),
00049 weapon_(weapon),
00050 position_(position),
00051 direction_(direction)
00052 {
00053 }
00054
00055 Laser::~Laser()
00056 {
00057 delete params_;
00058 }
00059
00060 void Laser::init()
00061 {
00062 fixed per = direction_.Magnitude() / 50;
00063 length_ = params_->getMinimumDistance() +
00064 (params_->getMaximumDistance() - params_->getMinimumDistance()) * per;
00065 damage_ = params_->getMinimumHurt() +
00066 (params_->getMaximumHurt() - params_->getMinimumHurt()) * (fixed(1) - per);
00067
00068 FixedVector dir = direction_.Normalize();
00069
00070 angXY_ = 180.0f - atan2f(dir[0].asFloat(), dir[1].asFloat()) / 3.14f * 180.0f;
00071 angYZ_ = acosf(dir[2].asFloat()) / 3.14f * 180.0f;
00072 }
00073
00074 std::string Laser::getActionDetails()
00075 {
00076 return S3D::formatStringBuffer("%i,%i,%i %i,%i,%i %s",
00077 position_[0].getInternal(), position_[1].getInternal(), position_[2].getInternal(),
00078 direction_[0].getInternal(), direction_[1].getInternal(), direction_[2].getInternal(),
00079 weapon_->getParent()->getName());
00080 }
00081
00082 void Laser::simulate(fixed frameTime, bool &remove)
00083 {
00084 if (firstTime_)
00085 {
00086 firstTime_ = false;
00087
00088
00089 laserTime_ = params_->getTotalTime();
00090 hurtRadius_ = params_->getHurtRadius();
00091
00092 if (damage_ > 0 && direction_.Magnitude() > 0)
00093 {
00094 std::set<unsigned int> damagedTargets_;
00095
00096
00097 FixedVector pos = position_;
00098 FixedVector dir = direction_.Normalize() / 4;
00099 bool end = false;
00100 while (!end)
00101 {
00102 std::map<unsigned int, Target *> collisionTargets;
00103 context_->getTargetSpace().getCollisionSet(pos,
00104 fixed(params_->getHurtRadius()), collisionTargets);
00105 std::map<unsigned int, Target *>::iterator itor;
00106 for (itor = collisionTargets.begin();
00107 itor != collisionTargets.end();
00108 itor++)
00109 {
00110 Target *current = (*itor).second;
00111 if (current->getAlive() &&
00112 ((current->getPlayerId() != weaponContext_.getPlayerId()) ||
00113 params_->getHurtFirer()))
00114 {
00115 Shield::ShieldLaserProofType laserProof = Shield::ShieldLaserProofNone;
00116 if (current->getShield().getCurrentShield())
00117 {
00118 Shield *shield = (Shield *)
00119 current->getShield().getCurrentShield()->getAction();
00120 if (shield->getLaserProof() != Shield::ShieldLaserProofNone)
00121 {
00122 laserProof = shield->getLaserProof();
00123 FixedVector offset = current->getLife().getTargetPosition() - pos;
00124 if (shield->inShield(offset))
00125 {
00126 context_->getActionController().addAction(
00127 new ShieldHit(current->getPlayerId(), pos, 0));
00128
00129 end = true;
00130 break;
00131 }
00132 }
00133 }
00134
00135 if (laserProof != Shield::ShieldLaserProofTotal)
00136 {
00137 FixedVector offset = current->getLife().getTargetPosition() - pos;
00138 fixed targetDistance = offset.Magnitude();
00139
00140 if (targetDistance < params_->getHurtRadius() +
00141 MAX(current->getLife().getSize()[0], current->getLife().getSize()[1]))
00142 {
00143 damagedTargets_.insert(current->getPlayerId());
00144 }
00145 }
00146 }
00147 }
00148
00149 if (!end)
00150 {
00151 pos += dir;
00152 drawLength_ = (pos - position_).Magnitude();
00153 if (drawLength_ > length_) end = true;
00154 }
00155 }
00156
00157
00158 std::set<unsigned int>::iterator itor;
00159 for (itor = damagedTargets_.begin();
00160 itor != damagedTargets_.end();
00161 itor++)
00162 {
00163 unsigned int damagedTarget = (*itor);
00164 context_->getActionController().addAction(
00165 new TankDamage(
00166 weapon_, damagedTarget, weaponContext_,
00167 damage_, false, false, false));
00168 }
00169 }
00170 }
00171
00172 totalTime_ += frameTime;
00173
00174 remove = (totalTime_ > laserTime_);
00175 Action::simulate(frameTime, remove);
00176 }
00177
00178 void Laser::draw()
00179 {
00180 #ifndef S3D_SERVER
00181 if (!context_->getServerMode() && (drawLength_ > 0))
00182 {
00183 static GLUquadric *obj = 0;
00184 if (!obj)
00185 {
00186 obj = gluNewQuadric();
00187 }
00188 float timePer = (1.0f - totalTime_.asFloat() / laserTime_.asFloat()) * 0.5f;
00189 float radius1 = 0.05f / 2.0f * hurtRadius_.asFloat();
00190 float radius2 = 0.2f / 2.0f * hurtRadius_.asFloat();
00191
00192 GLState glState(GLState::TEXTURE_OFF | GLState::BLEND_ON);
00193 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00194 glColor4f(1.0f, 1.0f, 1.0f, timePer);
00195 glPushMatrix();
00196 glTranslatef(
00197 position_[0].asFloat(),
00198 position_[1].asFloat(),
00199 position_[2].asFloat());
00200 glRotatef(angXY_, 0.0f, 0.0f, 1.0f);
00201 glRotatef(angYZ_, 1.0f, 0.0f, 0.0f);
00202
00203 glColor4f(1.0f, 1.0f, 1.0f, timePer);
00204 gluCylinder(obj, radius1, radius1, drawLength_.asFloat(), 3, 1);
00205
00206 glColor4f(
00207 params_->getColor()[0],
00208 params_->getColor()[1],
00209 params_->getColor()[2],
00210 timePer);
00211 gluCylinder(obj, radius2, radius2, drawLength_.asFloat(), 5, 1);
00212 glPopMatrix();
00213 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00214 }
00215 #endif // #ifndef S3D_SERVER
00216 }