1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2011
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.
10 //
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.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 ////////////////////////////////////////////////////////////////////////////////
20
21 #include <actions/ShotBounce.h>
22 #include <actions/CameraPositionAction.h>
23 #include <engine/ScorchedContext.h>
24 #include <engine/ActionController.h>
25 #include <weapons/WeaponRoller.h>
26 #include <weapons/AccessoryStore.h>
27 #include <common/OptionsScorched.h>
28 #include <tank/TankViewPoints.h>
29 #ifndef S3D_SERVER
30 #include <GLEXT/GLState.h>
31 #include <graph/ModelRenderer.h>
32 #include <graph/ModelRendererStore.h>
33 #include <graph/ModelRendererSimulator.h>
34 #endif
35 #include <3dsparse/Model.h>
36 #include <string.h>
37
ShotBounce(WeaponRoller * weapon,FixedVector & startPosition,FixedVector & velocity,WeaponFireContext & weaponContext)38 ShotBounce::ShotBounce(WeaponRoller *weapon,
39 FixedVector &startPosition, FixedVector &velocity,
40 WeaponFireContext &weaponContext) :
41 PhysicsParticle(weaponContext.getInternalContext().getReferenced()),
42 startPosition_(startPosition),
43 velocity_(velocity), weapon_(weapon), weaponContext_(weaponContext),
44 totalTime_(0), simulateTime_(0),
45 model_(0), vPoint_(0), groups_(0)
46 {
47 }
48
init()49 void ShotBounce::init()
50 {
51 PhysicsParticleInfo info(ParticleTypeBounce, weaponContext_.getPlayerId(), this);
52 setPhysics(info, startPosition_, velocity_,
53 1, 5, weapon_->getWindFactor(*context_), weapon_->getGravityFactor(*context_), false,
54 weapon_->getRoll(), true, weapon_->getStickyShields());
55 stepSize_ = weapon_->getStepSize() *
56 fixed(true, context_->getOptionsGame().getWeaponSpeed());
57 weaponTime_ = weapon_->getTime(*context_);
58 scale_ = weapon_->getScale(*context_).asFloat();
59 if (!context_->getServerMode())
60 {
61 if (!weapon_->getNoCameraTrack())
62 {
63 vPoint_ = new TankViewPointProvider();
64 vPoint_->incrementReference();
65 vPoint_->setValues(startPosition_);
66
67 // Point the action camera at this event
68 CameraPositionAction *pos = new CameraPositionAction(
69 weaponContext_.getPlayerId(), vPoint_, 5, 5, false);
70 context_->getActionController().addAction(pos);
71 }
72 }
73
74 if (weapon_->getLocalGroups().hasGroups() || weapon_->getGlobalGroups().hasGroups())
75 {
76 groups_ = new ParticleGroup(*context_, this, &weaponContext_);
77 weapon_->getLocalGroups().addToGroups(weaponContext_.getInternalContext().getLocalGroups(), groups_);
78 weapon_->getGlobalGroups().addToGroups(context_->getObjectGroups(), groups_);
79 }
80 }
81
~ShotBounce()82 ShotBounce::~ShotBounce()
83 {
84 #ifndef S3D_SERVER
85 delete model_;
86 #endif
87 if (vPoint_) vPoint_->decrementReference();
88 delete groups_;
89 }
90
getActionDetails()91 std::string ShotBounce::getActionDetails()
92 {
93 return S3D::formatStringBuffer("%s %s %s",
94 startPosition_.asQuickString(),
95 velocity_.asQuickString(),
96 weapon_->getParent()->getName());
97 }
98
collision(PhysicsParticleObject & position,ScorchedCollisionId collisionId)99 void ShotBounce::collision(PhysicsParticleObject &position,
100 ScorchedCollisionId collisionId)
101 {
102 if (!collision_)
103 {
104 doCollision();
105 }
106 PhysicsParticle::collision(position, collisionId);
107 }
108
simulate(fixed frameTime,bool & remove)109 void ShotBounce::simulate(fixed frameTime, bool &remove)
110 {
111 totalTime_ += frameTime;
112 if (totalTime_ > weaponTime_)
113 {
114 doCollision();
115 remove = true;
116 }
117
118 simulateTime_ += frameTime;
119 while (simulateTime_ > stepSize_)
120 {
121 PhysicsParticle::simulate(stepSize_, remove);
122 simulateTime_ -= stepSize_;
123 }
124 }
125
draw()126 void ShotBounce::draw()
127 {
128 #ifndef S3D_SERVER
129 if (!context_->getServerMode())
130 {
131 static float rotMatrix[16];
132 getRotationQuat().getOpenGLRotationMatrix(rotMatrix);
133
134 if (!model_)
135 {
136 ModelID &id = ((WeaponRoller *) weapon_)->getRollerModelID();
137 model_ = new ModelRendererSimulator(
138 ModelRendererStore::instance()->loadModel(id));
139 }
140
141 if (vPoint_)
142 {
143 vPoint_->setValues(getCurrentPosition(), lookFrom_);
144 }
145
146 GLState state(GLState::TEXTURE_OFF);
147 glPushMatrix();
148 glTranslatef(
149 getCurrentPosition()[0].asFloat(),
150 getCurrentPosition()[1].asFloat(),
151 getCurrentPosition()[2].asFloat() -
152 model_->getRenderer()->getModel()->getMin()[2].asFloat() * 0.08f);
153
154 glMultMatrixf(rotMatrix);
155 glScalef(0.08f * scale_, 0.08f * scale_, 0.08f * scale_);
156 model_->draw();
157 glPopMatrix();
158 }
159 #endif // #ifndef S3D_SERVER
160 }
161
doCollision()162 void ShotBounce::doCollision()
163 {
164 WeaponRoller *proj = (WeaponRoller *) weapon_;
165 proj->getCollisionAction()->fire(
166 *context_, weaponContext_, getCurrentPosition(), getCurrentVelocity());
167 }
168