Merge from development branch heightmap to main.
[scorched3d.git] / src / common / actions / Laser.cpp
blob45f755c8a07a59d93c5963b6e3ffe97c1b10ca47
1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2004
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <actions/Laser.h>
22 #include <actions/TankDamage.h>
23 #include <engine/ScorchedContext.h>
24 #include <engine/ActionController.h>
25 #include <weapons/AccessoryStore.h>
26 #include <weapons/Shield.h>
27 #include <actions/ShieldHit.h>
28 #include <target/TargetContainer.h>
29 #include <target/TargetShield.h>
30 #include <target/TargetLife.h>
31 #include <target/TargetSpace.h>
32 #include <common/Defines.h>
33 #include <common/Logger.h>
34 #ifndef S3D_SERVER
35 #include <GLEXT/GLState.h>
36 #endif
37 #include <math.h>
38 #include <set>
40 Laser::Laser(Weapon *weapon, LaserParams *params,
41 FixedVector &position, FixedVector &direction,
42 WeaponFireContext &weaponContext) :
43 ActionReferenced("Laser"),
44 params_(params),
45 totalTime_(0),
46 drawLength_(0),
47 firstTime_(true),
48 weaponContext_(weaponContext),
49 weapon_(weapon),
50 position_(position),
51 direction_(direction)
55 Laser::~Laser()
57 delete params_;
60 void Laser::init()
62 fixed per = direction_.Magnitude() / 50;
63 length_ = params_->getMinimumDistance() +
64 (params_->getMaximumDistance() - params_->getMinimumDistance()) * per;
65 damage_ = params_->getMinimumHurt() +
66 (params_->getMaximumHurt() - params_->getMinimumHurt()) * (fixed(1) - per);
68 FixedVector dir = direction_.Normalize();
70 angXY_ = 180.0f - atan2f(dir[0].asFloat(), dir[1].asFloat()) / 3.14f * 180.0f;
71 angYZ_ = acosf(dir[2].asFloat()) / 3.14f * 180.0f;
74 std::string Laser::getActionDetails()
76 return S3D::formatStringBuffer("%i,%i,%i %i,%i,%i %s",
77 position_[0].getInternal(), position_[1].getInternal(), position_[2].getInternal(),
78 direction_[0].getInternal(), direction_[1].getInternal(), direction_[2].getInternal(),
79 weapon_->getParent()->getName());
82 void Laser::simulate(fixed frameTime, bool &remove)
84 if (firstTime_)
86 firstTime_ = false;
88 // preset some values from the numberparser expressions
89 laserTime_ = params_->getTotalTime();
90 hurtRadius_ = params_->getHurtRadius();
92 if (damage_ > 0 && direction_.Magnitude() > 0)
94 std::set<unsigned int> damagedTargets_;
96 // Build a set of all tanks in the path of the laser
97 FixedVector pos = position_;
98 FixedVector dir = direction_.Normalize() / 4;
99 bool end = false;
100 while (!end)
102 std::map<unsigned int, Target *> collisionTargets;
103 context_->getTargetSpace().getCollisionSet(pos,
104 fixed(params_->getHurtRadius()), collisionTargets);
105 std::map<unsigned int, Target *>::iterator itor;
106 for (itor = collisionTargets.begin();
107 itor != collisionTargets.end();
108 itor++)
110 Target *current = (*itor).second;
111 if (current->getAlive() &&
112 ((current->getPlayerId() != weaponContext_.getPlayerId()) ||
113 params_->getHurtFirer()))
115 Shield::ShieldLaserProofType laserProof = Shield::ShieldLaserProofNone;
116 if (current->getShield().getCurrentShield())
118 Shield *shield = (Shield *)
119 current->getShield().getCurrentShield()->getAction();
120 if (shield->getLaserProof() != Shield::ShieldLaserProofNone)
122 laserProof = shield->getLaserProof();
123 FixedVector offset = current->getLife().getTargetPosition() - pos;
124 if (shield->inShield(offset))
126 context_->getActionController().addAction(
127 new ShieldHit(current->getPlayerId(), pos, 0));
129 end = true;
130 break;
135 if (laserProof != Shield::ShieldLaserProofTotal)
137 FixedVector offset = current->getLife().getTargetPosition() - pos;
138 fixed targetDistance = offset.Magnitude();
140 if (targetDistance < params_->getHurtRadius() +
141 MAX(current->getLife().getSize()[0], current->getLife().getSize()[1]))
143 damagedTargets_.insert(current->getPlayerId());
149 if (!end)
151 pos += dir;
152 drawLength_ = (pos - position_).Magnitude();
153 if (drawLength_ > length_) end = true;
157 // Subtract set amount from all tanks
158 std::set<unsigned int>::iterator itor;
159 for (itor = damagedTargets_.begin();
160 itor != damagedTargets_.end();
161 itor++)
163 unsigned int damagedTarget = (*itor);
164 context_->getActionController().addAction(
165 new TankDamage(
166 weapon_, damagedTarget, weaponContext_,
167 damage_, false, false, false));
172 totalTime_ += frameTime;
174 remove = (totalTime_ > laserTime_);
175 Action::simulate(frameTime, remove);
178 void Laser::draw()
180 #ifndef S3D_SERVER
181 if (!context_->getServerMode() && (drawLength_ > 0))
183 static GLUquadric *obj = 0;
184 if (!obj)
186 obj = gluNewQuadric();
188 float timePer = (1.0f - totalTime_.asFloat() / laserTime_.asFloat()) * 0.5f;
189 float radius1 = 0.05f / 2.0f * hurtRadius_.asFloat();
190 float radius2 = 0.2f / 2.0f * hurtRadius_.asFloat();
192 GLState glState(GLState::TEXTURE_OFF | GLState::BLEND_ON);
193 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
194 glColor4f(1.0f, 1.0f, 1.0f, timePer);
195 glPushMatrix();
196 glTranslatef(
197 position_[0].asFloat(),
198 position_[1].asFloat(),
199 position_[2].asFloat());
200 glRotatef(angXY_, 0.0f, 0.0f, 1.0f);
201 glRotatef(angYZ_, 1.0f, 0.0f, 0.0f);
203 glColor4f(1.0f, 1.0f, 1.0f, timePer);
204 gluCylinder(obj, radius1, radius1, drawLength_.asFloat(), 3, 1);
206 glColor4f(
207 params_->getColor()[0],
208 params_->getColor()[1],
209 params_->getColor()[2],
210 timePer);
211 gluCylinder(obj, radius2, radius2, drawLength_.asFloat(), 5, 1);
212 glPopMatrix();
213 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
215 #endif // #ifndef S3D_SERVER