20
23
#include "items/plunger.hpp"
22
#include "race_manager.hpp"
23
#include "graphics/scene.hpp"
25
#include "graphics/irr_driver.hpp"
26
#include "io/xml_node.hpp"
24
27
#include "items/rubber_band.hpp"
25
28
#include "items/projectile_manager.hpp"
26
#include "karts/player_kart.hpp"
29
#include "karts/kart.hpp"
27
30
#include "modes/world.hpp"
28
#include "physics/moving_physics.hpp"
31
#include "physics/physical_object.hpp"
29
32
#include "tracks/track.hpp"
30
33
#include "utils/constants.hpp"
34
#include "utils/string_utils.hpp"
37
const wchar_t* getPlungerInFaceString()
39
const int PLUNGER_IN_FACE_STRINGS_AMOUNT = 2;
42
const int id = r.get(PLUNGER_IN_FACE_STRINGS_AMOUNT);
46
//I18N: shown when a player receives a plunger in his face
47
case 0: return _("%0 gets a fancy mask from %1");
48
//I18N: shown when a player receives a plunger in his face
49
case 1: return _("%1 merges %0's face with a plunger");
50
default:assert(false); return L""; // avoid compiler warning
32
55
// -----------------------------------------------------------------------------
33
Plunger::Plunger(Kart *kart) : Flyable(kart, POWERUP_PLUNGER)
56
Plunger::Plunger(Kart *kart) : Flyable(kart, PowerupManager::POWERUP_PLUNGER)
35
float y_offset = 0.5f*kart->getKartLength()+0.5f*m_extend.getY();
58
const float gravity = 0.0f;
60
float forward_offset = 0.5f*kart->getKartLength()+0.5f*m_extend.getZ();
61
float up_velocity = 0.0f;
62
float plunger_speed = 2 * m_speed;
37
64
// if the kart is looking backwards, release from the back
38
65
m_reverse_mode = kart->getControls().m_look_back;
40
67
// find closest kart in front of the current one
41
const Kart *closest_kart=0; btVector3 direction; float kartDistSquared;
42
getClosestKart(&closest_kart, &kartDistSquared, &direction, kart /* search in front of this kart */, m_reverse_mode);
44
btTransform trans = kart->getTrans();
46
btMatrix3x3 thisKartDirMatrix = kart->getKartHeading().getBasis();
47
btVector3 thisKartDirVector(thisKartDirMatrix[0][1],
48
thisKartDirMatrix[1][1],
49
thisKartDirMatrix[2][1]);
51
float heading=atan2(-thisKartDirVector.getX(), thisKartDirVector.getY());
52
float pitch = kart->getTerrainPitch(heading);
68
const Kart *closest_kart=0;
71
getClosestKart(&closest_kart, &kart_dist_2, &direction,
72
kart /* search in front of this kart */, m_reverse_mode);
74
btTransform kart_transform = kart->getKartTransform();
75
btMatrix3x3 kart_rotation = kart_transform.getBasis();
76
// The current forward vector is rotation*(0,0,1), or:
77
btVector3 forward(kart_rotation.getColumn(2));
79
float heading =kart->getHeading();
80
float pitch = kart->getTerrainPitch(heading);
54
82
// aim at this kart if it's not too far
55
if(closest_kart != NULL && kartDistSquared < 30*30)
83
if(closest_kart != NULL && kart_dist_2 < 30*30)
57
btVector3 closestKartLoc = closest_kart->getTrans().getOrigin();
59
if(!m_reverse_mode) // substracting speeds doesn't work backwards, since both speeds go in opposite directions
61
// FIXME - this approximation will be wrong if both karts' directions are not colinear
62
const float time = sqrt(kartDistSquared) / (m_speed - closest_kart->getSpeed());
64
// calculate the approximate location of the aimed kart in 'time' seconds
65
closestKartLoc += time*closest_kart->getVelocity();
68
// calculate the angle at which the projectile should be thrown
69
// to hit the aimed kart
70
float projectileAngle=atan2(-(closestKartLoc.getX() - kart->getTrans().getOrigin().getX()),
71
closestKartLoc.getY() - kart->getTrans().getOrigin().getY() );
73
// apply transformation to the bullet object
75
m.setEulerZYX(pitch, 0.0f, projectileAngle);
78
createPhysics(y_offset, btVector3(0.0f, m_speed*2, 0.0f),
79
new btCylinderShape(0.5f*m_extend), 0.0f /* gravity */, false /* rotates */, false, &trans );
85
float fire_angle = 0.0f;
86
getLinearKartItemIntersection (kart->getXYZ(), closest_kart,
87
plunger_speed, gravity, forward_offset,
88
&fire_angle, &up_velocity);
90
btTransform trans = kart->getTrans();
92
trans.setRotation(btQuaternion(btVector3(0, 1, 0), fire_angle));
94
m_initial_velocity = btVector3(0.0f, up_velocity, plunger_speed);
96
createPhysics(forward_offset, m_initial_velocity,
97
new btCylinderShape(0.5f*m_extend), gravity,
98
/* rotates */false , /*turn around*/false, &trans );
83
trans = kart->getKartHeading();
85
createPhysics(y_offset, btVector3(0.0f, m_speed*2, 0.0f),
86
new btCylinderShape(0.5f*m_extend), 0.0f /* gravity */, false /* rotates */, m_reverse_mode, &trans );
102
createPhysics(forward_offset, btVector3(pitch, 0.0f, plunger_speed),
103
new btCylinderShape(0.5f*m_extend), gravity,
104
false /* rotates */, m_reverse_mode, &kart_transform );
107
//adjust height according to terrain
108
setAdjustUpVelocity(false);
89
110
// pulling back makes no sense in battle mode, since this mode is not a race.
90
111
// so in battle mode, always hide view
91
if( m_reverse_mode || race_manager->isBattleMode(race_manager->getMinorMode()) )
112
if( m_reverse_mode || race_manager->isBattleMode() )
92
113
m_rubber_band = NULL;
95
m_rubber_band = new RubberBand(this, *kart);
116
m_rubber_band = new RubberBand(this, kart);
98
118
m_keep_alive = -1;
154
160
* Instead it stays around (though not as a graphical or physical object)
155
161
* till the rubber band expires.
156
162
* \param kart Pointer to the kart hit (NULL if not a kart).
157
* \param mp Pointer to MovingPhysics object if hit (NULL otherwise).
163
* \param obj Pointer to PhysicalObject object if hit (NULL otherwise).
159
void Plunger::hit(Kart *kart, MovingPhysics *mp)
165
void Plunger::hit(Kart *kart, PhysicalObject *obj)
161
167
if(isOwnerImmunity(kart)) return;
169
RaceGUIBase* gui = World::getWorld()->getRaceGUI();
170
irr::core::stringw hit_message;
163
172
// pulling back makes no sense in battle mode, since this mode is not a race.
164
173
// so in battle mode, always hide view
165
if( m_reverse_mode || race_manager->isBattleMode(race_manager->getMinorMode()) )
174
if( m_reverse_mode || race_manager->isBattleMode() )
167
if(kart) kart->blockViewWithPlunger();
178
kart->blockViewWithPlunger();
180
hit_message += StringUtils::insertValues(getPlungerInFaceString(),
181
kart->getName().c_str(),
182
m_owner->getName().c_str()
184
gui->addMessage(hit_message, NULL, 3.0f, 40, video::SColor(255, 255, 255, 255), false);
169
187
m_keep_alive = 0;
170
// Make this object invisible by placing it faaar down. Not that if this
188
// Make this object invisible by placing it faaar down. Note that if this
171
189
// objects is simply removed from the scene graph, it might be auto-deleted
172
190
// because the ref count reaches zero.
173
Vec3 hell(0, 0, -10000);
174
getModelTransform()->setTransform(hell.toFloat());
175
RaceManager::getWorld()->getPhysics()->removeBody(getBody());
191
getNode()->setVisible(false);
192
World::getWorld()->getPhysics()->removeBody(getBody());