1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2004
4 // This file is part of Scorched3D.
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>
35 #include <GLEXT/GLState.h>
40 Laser::Laser(Weapon
*weapon
, LaserParams
*params
,
41 FixedVector
&position
, FixedVector
&direction
,
42 WeaponFireContext
&weaponContext
) :
43 ActionReferenced("Laser"),
48 weaponContext_(weaponContext
),
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
)
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;
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();
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));
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());
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();
163 unsigned int damagedTarget
= (*itor
);
164 context_
->getActionController().addAction(
166 weapon_
, damagedTarget
, weaponContext_
,
167 damage_
, false, false, false));
172 totalTime_
+= frameTime
;
174 remove
= (totalTime_
> laserTime_
);
175 Action::simulate(frameTime
, remove
);
181 if (!context_
->getServerMode() && (drawLength_
> 0))
183 static GLUquadric
*obj
= 0;
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
);
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);
207 params_
->getColor()[0],
208 params_
->getColor()[1],
209 params_
->getColor()[2],
211 gluCylinder(obj
, radius2
, radius2
, drawLength_
.asFloat(), 5, 1);
213 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
215 #endif // #ifndef S3D_SERVER