forked from supertuxkart/stk-code
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcake.cpp
180 lines (153 loc) · 6.73 KB
/
cake.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2007-2015 Joerg Henrichs
//
// Physics improvements and linear intersection algorithm by
// Copyright (C) 2009-2015 David Mikos.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "items/cake.hpp"
#include "io/xml_node.hpp"
#include "karts/abstract_kart.hpp"
#include "utils/constants.hpp"
#include "utils/hit_processor.hpp"
#include "utils/random_generator.hpp"
#include "utils/log.hpp" //TODO: remove after debugging is done
float Cake::m_st_max_distance_squared;
float Cake::m_gravity;
Cake::Cake (AbstractKart *kart) : Flyable(kart, PowerupManager::POWERUP_CAKE)
{
m_target = NULL;
} // Cake
// -----------------------------------------------------------------------------
/** Initialises the object from an entry in the powerup.xml file.
* \param node The xml node for this object.
* \param cakde_model The mesh model of the cake.
*/
void Cake::init(const XMLNode &node, scene::IMesh *cake_model)
{
Flyable::init(node, cake_model, PowerupManager::POWERUP_CAKE);
float max_distance = 80.0f;
m_gravity = 9.8f;
node.get("max-distance", &max_distance );
m_st_max_distance_squared = max_distance*max_distance;
} // init
// ----------------------------------------------------------------------------
/** Callback from the physics in case that a kart or physical object is hit.
* The cake triggers an explosion when hit.
* \param kart The kart hit (NULL if no kart was hit).
* \param object The object that was hit (NULL if none).
* \returns True if there was actually a hit (i.e. not owner, and target is
* not immune), false otherwise.
*/
bool Cake::hit(AbstractKart* kart, PhysicalObject* obj)
{
auto hp = kart->getHitProcessor();
if (hp)
hp->setTeammateHitOwner(getOwnerId());
bool was_real_hit = Flyable::hit(kart, obj);
if (was_real_hit)
{
if (kart && kart->isShielded())
{
kart->decreaseShieldTime();
if (hp)
{
hp->registerTeammateHit(kart->getWorldKartId());
hp->handleTeammateHits();
}
return false; //Not sure if a shield hit is a real hit.
}
explode(kart, obj);
}
if (hp)
hp->handleTeammateHits();
return was_real_hit;
} // hit
// ----------------------------------------------------------------------------
void Cake::onFireFlyable()
{
Flyable::onFireFlyable();
setDoTerrainInfo(false);
btVector3 gravity_vector;
btQuaternion q = m_owner->getTrans().getRotation();
gravity_vector = Vec3(0, -1, 0).rotate(q.getAxis(), q.getAngle());
gravity_vector = gravity_vector.normalize() * m_gravity;
// A bit of a hack: the mass of this kinematic object is still 1.0
// (see flyable), which enables collisions. I tried setting
// collisionFilterGroup/mask, but still couldn't get this object to
// collide with the track. By setting the mass to 1, collisions happen.
// (if bullet is compiled with _DEBUG, a warning will be printed the first
// time a homing-track collision happens).
float forward_offset=m_owner->getKartLength()/2.0f + m_extend.getZ()/2.0f;
float up_velocity = m_speed/7.0f;
// give a speed proportional to kart speed. m_speed is defined in flyable
m_speed *= m_owner->getSpeed() / 23.0f;
//when going backwards, decrease speed of cake by less
if (m_owner->getSpeed() < 0) m_speed /= 3.6f;
m_speed += 16.0f;
if (m_speed < 1.0f) m_speed = 1.0f;
btTransform trans = m_owner->getTrans();
float heading=m_owner->getHeading();
float pitch = m_owner->getTerrainPitch(heading);
// Find closest kart in front of the current one
const bool backwards = m_owner->getControls().getLookBack();
const AbstractKart *closest_kart=NULL;
Vec3 direction;
float kart_dist_squared;
getClosestKart(&closest_kart, &kart_dist_squared, &direction,
m_owner /* search in front of this kart */, backwards);
// aim at this kart if 1) it's not too far, 2) if the aimed kart's speed
// allows the projectile to catch up with it
//
// this code finds the correct angle and upwards velocity to hit an opponents'
// vehicle if they were to continue travelling in the same direction and same speed
// (barring any obstacles in the way of course)
if(closest_kart != NULL && kart_dist_squared < m_st_max_distance_squared &&
m_speed>closest_kart->getSpeed())
{
m_target = (AbstractKart*)closest_kart;
float fire_angle = 0.0f;
getLinearKartItemIntersection (m_owner->getXYZ(), closest_kart,
m_speed, m_gravity, forward_offset,
&fire_angle, &up_velocity);
// apply transformation to the bullet object (without pitch)
btQuaternion q;
q = trans.getRotation() * btQuaternion(btVector3(0, 1, 0), fire_angle);
trans.setRotation(q);
m_initial_velocity = Vec3(0.0f, up_velocity, m_speed);
createPhysics(forward_offset, m_initial_velocity,
new btCylinderShape(0.5f*m_extend),
0.5f /* restitution */, gravity_vector,
true /* rotation */, false /* backwards */, &trans);
}
else
{
m_target = NULL;
// kart is too far to be hit. so throw the projectile in a generic way,
// straight ahead, without trying to hit anything in particular
trans = m_owner->getAlignedTransform(pitch);
m_initial_velocity = Vec3(0.0f, up_velocity, m_speed);
createPhysics(forward_offset, m_initial_velocity,
new btCylinderShape(0.5f*m_extend),
0.5f /* restitution */, gravity_vector,
true /* rotation */, backwards, &trans);
}
//do not adjust height according to terrain
setAdjustUpVelocity(false);
m_body->setActivationState(DISABLE_DEACTIVATION);
m_body->clearForces();
m_body->applyTorque(btVector3(5.0f, -3.0f, 7.0f));
} // onFireFlyable