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