17
17
// along with this program; if not, write to the Free Software
18
18
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
#include "rubber_band.hpp"
20
#include "items/rubber_band.hpp"
22
#include "material_manager.hpp"
23
#include "race_manager.hpp"
24
#include "graphics/scene.hpp"
22
#include "graphics/irr_driver.hpp"
23
#include "graphics/material_manager.hpp"
25
24
#include "items/plunger.hpp"
26
25
#include "items/projectile_manager.hpp"
27
26
#include "karts/kart.hpp"
28
27
#include "modes/world.hpp"
29
28
#include "physics/physics.hpp"
29
#include "race/race_manager.hpp"
30
#include "utils/string_utils.hpp"
33
const wchar_t* getPlungerString()
35
const int PLUNGER_STRINGS_AMOUNT = 3;
38
const int id = r.get(PLUNGER_STRINGS_AMOUNT);
42
//I18N: shown when hit by plunger. %0 is the victim, %1 is the attacker
43
case 0: return _("%0 bites %1's bait");
44
//I18N: shown when hit by plunger. %0 is the victim, %1 is the attacker
45
case 1: return _("%1 latches onto %0 for a free ride");
46
//I18N: shown when hit by plunger. %0 is the victim, %1 is the attacker
47
case 2: return _("%1 tests a tractor beam on %0");
48
default: assert(false); return L""; // avoid warning about no return value
31
53
/** RubberBand constructor. It creates a simple quad and attaches it to the
32
54
* root(!) of the graph. It's easier this way to get the right coordinates
36
58
* can trigger an explosion)
37
59
* \param kart Reference to the kart.
39
RubberBand::RubberBand(Plunger *plunger, const Kart &kart)
40
: ssgVtxTable(GL_QUADS, new ssgVertexArray,
61
RubberBand::RubberBand(Plunger *plunger, Kart *kart) :
44
62
m_plunger(plunger), m_owner(kart)
64
video::SColor color(77, 179, 0, 0);
66
m.AmbientColor = color;
67
m.DiffuseColor = color;
68
m.EmissiveColor = color;
69
m.BackfaceCulling = false;
70
m_mesh = irr_driver->createQuadMesh(&m, /*create_one_quad*/ true);
71
m_buffer = m_mesh->getMeshBuffer(0);
72
m_attached_state = RB_TO_PLUNGER;
73
assert(m_buffer->getVertexType()==video::EVT_STANDARD);
76
m_node = irr_driver->addMesh(m_mesh);
47
setName("rubber_band");
78
std::string debug_name = m_owner->getIdent()+" (rubber-band)";
79
m_node->setName(debug_name.c_str());
50
// The call to update defines the actual coordinates, only the entries are added for now.
51
vertices->add(0, 0, 0); vertices->add(0, 0, 0);
52
vertices->add(0, 0, 0); vertices->add(0, 0, 0);
53
m_attached_state = RB_TO_PLUNGER;
57
sgSetVec3(norm, 1/sqrt(2.0f), 0, 1/sqrt(2.0f));
58
normals->add(norm);normals->add(norm);
59
normals->add(norm);normals->add(norm);
62
sgSetVec4(colour, 0.7f, 0.0f, 0.0f, 0.3f);
63
colours->add(colour);colours->add(colour);
64
colours->add(colour);colours->add(colour);
65
m_state = new ssgSimpleState();
66
m_state->disable(GL_CULL_FACE);
68
//setState(material_manager->getMaterial("chrome.rgb")->getState());
73
// ----------------------------------------------------------------------------
74
/** Removes the rubber band from the scene. Is called when the plunger
84
// ----------------------------------------------------------------------------
85
RubberBand::~RubberBand()
87
irr_driver->removeNode(m_node);
89
// This mesh is self made and so not stored in the
90
// mesh cache. So no reason to call
91
// irr_driver->removeMesh(m_mesh);
92
// But it was implicitly 'grabbed' during creation, so we have
97
// ----------------------------------------------------------------------------
98
/** Updates the position of the rubber band. It especially sets the
99
* end position of the rubber band, i.e. the side attached to the plunger,
100
* track, or kart hit.
77
void RubberBand::removeFromScene()
82
// ----------------------------------------------------------------------------
83
/** Updates the position of the rubber band. It especially sets the
84
* end position of the rubber band, i.e. the side attached to the plunger,
87
102
void RubberBand::updatePosition()
89
const Vec3 &k = m_owner.getXYZ();
91
// Get the position to which the band is attached
92
// ----------------------------------------------
93
switch(m_attached_state)
95
case RB_TO_KART: m_end_position = m_hit_kart->getXYZ(); break;
96
case RB_TO_TRACK: m_end_position = m_hit_position; break;
97
case RB_TO_PLUNGER: m_end_position = m_plunger->getXYZ();
98
checkForHit(k, m_end_position); break;
99
} // switch(m_attached_state);
101
// Update the rubber band positions
102
// --------------------------------
103
// Todo: make height dependent on length (i.e. rubber band gets
104
// thinner). And call explosion if the band is too long.
105
const float hh=.1f; // half height of the band
106
const Vec3 &p=m_end_position; // for shorter typing
107
float *f = vertices->get(0);
108
f[0] = p.getX()-hh; f[1] = p.getY(); f[2] = p.getZ()-hh;
109
f = vertices->get(1);
110
f[0] = p.getX()+hh; f[1] = p.getY(); f[2] = p.getZ()+hh;
111
f = vertices->get(2);
112
f[0] = k.getX()+hh; f[1] = k.getY(); f[2] = k.getZ()+hh;
113
f = vertices->get(3);
114
f[0] = k.getX()-hh; f[1] = k.getY(); f[2] = k.getZ()-hh;
104
const Vec3 &k = m_owner->getXYZ();
106
// Get the position to which the band is attached
107
// ----------------------------------------------
108
switch(m_attached_state)
110
case RB_TO_KART: m_end_position = m_hit_kart->getXYZ(); break;
111
case RB_TO_TRACK: m_end_position = m_hit_position; break;
112
case RB_TO_PLUNGER: m_end_position = m_plunger->getXYZ();
113
checkForHit(k, m_end_position); break;
114
} // switch(m_attached_state);
116
// Update the rubber band positions
117
// --------------------------------
118
// Todo: make height dependent on length (i.e. rubber band gets
119
// thinner). And call explosion if the band is too long.
120
const float hh=.1f; // half height of the band
121
const Vec3 &p=m_end_position; // for shorter typing
122
irr::video::S3DVertex* v=(video::S3DVertex*)m_buffer->getVertices();
123
v[0].Pos.X = p.getX()-hh; v[0].Pos.Y=p.getY(); v[0].Pos.Z = p.getZ()-hh;
124
v[1].Pos.X = p.getX()+hh; v[1].Pos.Y=p.getY(); v[1].Pos.Z = p.getZ()+hh;
125
v[2].Pos.X = k.getX()+hh; v[2].Pos.Y=k.getY(); v[2].Pos.Z = k.getZ()+hh;
126
v[3].Pos.X = k.getX()-hh; v[3].Pos.Y=k.getY(); v[3].Pos.Z = k.getZ()-hh;
127
m_buffer->recalculateBoundingBox();
128
m_mesh->setBoundingBox(m_buffer->getBoundingBox());
118
131
// ----------------------------------------------------------------------------
119
132
/** Updates the rubber band. It takes the new position of the kart and the
120
133
* plunger, and sets the quad representing the rubber band appropriately.
185
202
short int old_kart_group=0;
187
204
// If the owner is being rescued, the broadphase handle does not exist!
188
if(m_owner.getBody()->getBroadphaseHandle())
189
old_kart_group = m_owner.getBody()->getBroadphaseHandle()->m_collisionFilterGroup;
205
if(m_owner->getBody()->getBroadphaseHandle())
206
old_kart_group = m_owner->getBody()->getBroadphaseHandle()->m_collisionFilterGroup;
190
207
m_plunger->getBody()->getBroadphaseHandle()->m_collisionFilterGroup = 0;
191
if(m_owner.getBody()->getBroadphaseHandle())
192
m_owner.getBody()->getBroadphaseHandle()->m_collisionFilterGroup = 0;
208
if(m_owner->getBody()->getBroadphaseHandle())
209
m_owner->getBody()->getBroadphaseHandle()->m_collisionFilterGroup = 0;
194
211
// Do the raycast
195
RaceManager::getWorld()->getPhysics()->getPhysicsWorld()->rayTest(k, p,
212
World::getWorld()->getPhysics()->getPhysicsWorld()->rayTest(k, p,
197
214
// Reset collision groups
198
215
m_plunger->getBody()->getBroadphaseHandle()->m_collisionFilterGroup = old_plunger_group;
199
if(m_owner.getBody()->getBroadphaseHandle())
200
m_owner.getBody()->getBroadphaseHandle()->m_collisionFilterGroup = old_kart_group;
216
if(m_owner->getBody()->getBroadphaseHandle())
217
m_owner->getBody()->getBroadphaseHandle()->m_collisionFilterGroup = old_kart_group;
201
218
if(ray_callback.HasHit())
203
220
Vec3 pos(ray_callback.m_hitPointWorld);