1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
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 <target/TargetLife.h>
22 #include <target/TargetRenderer.h>
23 #include <target/TargetSpace.h>
24 #include <target/TargetState.h>
25 #include <target/Target.h>
26 #include <tank/TankType.h>
27 #include <engine/ScorchedContext.h>
28 #include <engine/ActionController.h>
29 #include <tankai/TankAIAdder.h>
30 #include <common/Defines.h>
31 #include <common/Logger.h>
33 TargetLife::TargetLife(ScorchedContext
&context
, unsigned int playerId
) :
34 context_(context
), sphereGeom_(true),
35 life_(0), maxLife_(1), target_(0),
36 size_(2, 2, 2), floatBoundingSize_(0.0f
)
40 TargetLife::~TargetLife()
46 void TargetLife::newGame()
51 void TargetLife::setLife(fixed life
)
55 if (life_
>= maxLife_
) life_
= maxLife_
;
59 setRotation(0); // Updates space too
68 void TargetLife::setSize(FixedVector
&size
)
76 void TargetLife::setTargetPositionAndRotation(FixedVector
&pos
, fixed rotation
)
78 targetPosition_
= pos
;
79 if (!context_
.getServerMode()) targetPosition_
.asVector(floatPosition_
);
81 FixedVector
zaxis(0, 0, 1);
82 quaternion_
.setQuatFromAxisAndAngle(zaxis
, rotation
/ 180 * fixed::XPI
);
83 if (!context_
.getServerMode()) quaternion_
.getOpenGLRotationMatrix(floatRotMatrix_
);
89 void TargetLife::setTargetPosition(FixedVector
&pos
)
91 targetPosition_
= pos
;
92 if (!context_
.getServerMode()) targetPosition_
.asVector(floatPosition_
);
97 void TargetLife::setRotation(fixed rotation
)
99 FixedVector
zaxis(0, 0, 1);
100 quaternion_
.setQuatFromAxisAndAngle(zaxis
, rotation
/ 180 * fixed::XPI
);
101 if (!context_
.getServerMode()) quaternion_
.getOpenGLRotationMatrix(floatRotMatrix_
);
107 FixedVector
&TargetLife::getCenterPosition()
109 static FixedVector result
;
110 result
= getTargetPosition();
111 result
[2] += getSize()[2] / 2;
115 Vector
&TargetLife::getFloatCenterPosition()
117 static Vector result
;
118 result
= getFloatPosition();
119 result
[2] += getFloatAabbSize()[2] / 2.0f
;
123 fixed
TargetLife::collisionDistance(FixedVector
&position
)
125 FixedVector
¤tPosition
= getCenterPosition();
126 FixedVector direction
= position
- currentPosition
;
129 // Get how close the explosion was
130 if (getBoundingSphere())
132 // Find how close the explosion was to the
133 // outside of the sphere
134 fixed sphereRadius
= MAX(MAX(size_
[0], size_
[1]), size_
[2]) / 2;
135 dist
= direction
.Magnitude() - sphereRadius
;
136 if (dist
< 0) dist
= 0;
140 // Make the direction relative to the geom
141 // incase the geom has been rotated
142 FixedVector relativeDirection
;
143 quaternion_
.getRelativeVector(relativeDirection
, direction
);
145 // Find how close the explosion was to the
146 // outside edge of the cube
147 FixedVector touchPosition
= relativeDirection
;
149 // Check each size of the cube to see if the point is outside.
150 // If it is, then scale it back until the point sits on the
151 // outside edge of the cube.
153 for (int i
=0; i
<3; i
++)
155 fixed halfSize
= size_
[i
] / 2;
156 if (touchPosition
[i
] < -halfSize
)
158 // Scale the point so it sits on this edge
159 fixed diff
= -halfSize
/ touchPosition
[i
];
160 touchPosition
*= diff
;
162 else if (touchPosition
[i
] > halfSize
)
164 // Scale the point so it sits on this edge
165 fixed diff
= halfSize
/ touchPosition
[i
];
166 touchPosition
*= diff
;
168 else inner
++; // The point is inside this edge
173 // We are inside the cube
178 // We are outside the cube
179 relativeDirection
-= touchPosition
;
180 dist
= relativeDirection
.Magnitude();
187 bool TargetLife::collision(FixedVector
&position
)
189 FixedVector
¤tPosition
= getCenterPosition();
190 FixedVector direction
= position
- currentPosition
;
192 // Check against bounding box
193 if (direction
[0] < -aabbSize_
[0] ||
194 direction
[0] > aabbSize_
[0] ||
195 direction
[1] < -aabbSize_
[1] ||
196 direction
[1] > aabbSize_
[1] ||
197 direction
[2] < -aabbSize_
[2] ||
198 direction
[2] > aabbSize_
[2])
203 // Check against actual bounds
206 fixed radius
= MAX(MAX(size_
[0], size_
[1]), size_
[2]) / 2;
207 if (direction
.Magnitude() > radius
) return false;
211 // Make the direction relative to the geom
212 // incase the geom has been rotated
213 FixedVector relativeDirection
;
214 quaternion_
.getRelativeVector(relativeDirection
, direction
);
216 // Check each side of the cube to see if the point is inside it
218 for (int i
=0; i
<3; i
++)
220 fixed halfSize
= size_
[i
] / 2;
221 if (-halfSize
< relativeDirection
[i
] &&
222 relativeDirection
[i
] < halfSize
)
224 inner
++; // The point is inside this edge
228 // We need the point to be inside each of the 6 edges
229 if (inner
< 3) return false;
235 void TargetLife::setBoundingSphere(bool sphereGeom
)
237 sphereGeom_
= sphereGeom
;
243 void TargetLife::updateSpace()
245 if (target_
->getRenderer()) target_
->getRenderer()->moved();
246 context_
.getTargetSpace().updateTarget(target_
);
249 bool TargetLife::writeMessage(NetBuffer
&buffer
)
251 buffer
.addToBuffer(maxLife_
);
252 buffer
.addToBuffer(life_
);
253 buffer
.addToBuffer(size_
);
254 buffer
.addToBuffer(velocity_
);
255 buffer
.addToBuffer(targetPosition_
);
256 buffer
.addToBuffer(quaternion_
);
260 bool TargetLife::readMessage(NetBufferReader
&reader
)
262 life_
= 0; // Suppress target space updates
265 if (!reader
.getFromBuffer(maxLife_
))
267 Logger::log("TargetLife::maxLife_ read failed");
270 if (!reader
.getFromBuffer(newLife
))
272 Logger::log("TargetLife::life_ read failed");
277 if (!reader
.getFromBuffer(newSize
))
279 Logger::log("TargetLife::size_ read failed");
284 if (!reader
.getFromBuffer(velocity_
))
286 Logger::log("TargetLife::velocity_ read failed");
290 FixedVector newPosition
;
291 if (!reader
.getFromBuffer(newPosition
))
293 Logger::log("TargetLife::targetPosition_ read failed");
296 setTargetPosition(newPosition
);
298 if (!reader
.getFromBuffer(quaternion_
))
300 Logger::log("TargetLife::quaternion_ read failed");
304 // Update target space
310 void TargetLife::updateAABB()
314 fixed radius
= MAX(MAX(size_
[0], size_
[1]), size_
[2]) / 2;
315 aabbSize_
= FixedVector(radius
* 2, radius
* 2, radius
* 2);
319 for (int i
=0; i
<8; i
++)
321 FixedVector position
;
325 position
= FixedVector(size_
[0], size_
[1], size_
[2]);
328 position
= FixedVector(-size_
[0], size_
[1], size_
[2]);
331 position
= FixedVector(size_
[0], -size_
[1], size_
[2]);
334 position
= FixedVector(-size_
[0], -size_
[1], size_
[2]);
337 position
= FixedVector(size_
[0], size_
[1], -size_
[2]);
340 position
= FixedVector(-size_
[0], size_
[1], -size_
[2]);
343 position
= FixedVector(size_
[0], -size_
[1], -size_
[2]);
346 position
= FixedVector(-size_
[0], -size_
[1], -size_
[2]);
351 quaternion_
.getRelativeVector(result
, position
);
353 if (i
== 0) aabbSize_
= result
;
356 aabbSize_
[0] = MAX(aabbSize_
[0], result
[0]);
357 aabbSize_
[1] = MAX(aabbSize_
[1], result
[1]);
358 aabbSize_
[2] = MAX(aabbSize_
[2], result
[2]);
362 if (!context_
.getServerMode())
364 aabbSize_
.asVector(floatAabbSize_
);
365 floatBoundingSize_
= floatAabbSize_
.Max();