diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp index b595794c6..9664a02f7 100644 --- a/src/graphics/material.cpp +++ b/src/graphics/material.cpp @@ -71,14 +71,15 @@ Material::Material(const XMLNode *node, int index) node->get("light", &m_lighting ); node->get("sphere", &m_sphere_map ); node->get("friction", &m_friction ); - node->get("reset", &m_resetter ); + node->get("reset", &m_drive_reset ); + node->get("crash-reset", &m_crash_reset ); node->get("below-surface", &m_below_surface ); node->get("falling-effect", &m_falling_effect ); // A terrain with falling effect has to force a reset - // since. So to make it easier for artists, force - // the reset flag in this case. + // when the kart is on it. So to make it easier for artists, + // force the reset flag in this case. if(m_falling_effect) - m_resetter=true; + m_drive_reset=true; node->get("surface", &m_surface ); node->get("ignore", &m_ignore ); @@ -219,7 +220,8 @@ void Material::init(unsigned int index) m_falling_effect = false; m_surface = false; m_ignore = false; - m_resetter = false; + m_drive_reset = false; + m_crash_reset = false; m_add = false; m_disable_z_write = false; m_max_speed_fraction = 1.0f; diff --git a/src/graphics/material.hpp b/src/graphics/material.hpp index 22d39f512..c2d583568 100644 --- a/src/graphics/material.hpp +++ b/src/graphics/material.hpp @@ -72,8 +72,10 @@ private: bool m_surface; /** If the material is a zipper, i.e. gives a speed boost. */ bool m_zipper; - /** If a kart is rescued when touching this surface. */ - bool m_resetter; + /** If a kart is rescued when driving on this surface. */ + bool m_drive_reset; + /** If a kart is rescued when crashing into this surface. */ + bool m_crash_reset; /** If the property should be ignored in the physics. Example would be * plants that a kart can just drive through. */ bool m_ignore; @@ -163,7 +165,12 @@ public: /** Returns true if this material is a zipper. */ bool isZipper () const { return m_zipper; } bool isSphereMap () const { return m_sphere_map; } - bool isReset () const { return m_resetter; } + /** Returns if this material should trigger a rescue if a kart + * is driving on it. */ + bool isDriveReset () const { return m_drive_reset; } + /** Returns if this material should trigger a rescue if a kart + * crashes against it. */ + bool isCrashReset () const { return m_crash_reset; } float getFriction () const { return m_friction; } const std::string& getTexFname () const { return m_texname; } diff --git a/src/items/bowling.cpp b/src/items/bowling.cpp index 7d22b6835..e6d441a23 100644 --- a/src/items/bowling.cpp +++ b/src/items/bowling.cpp @@ -117,7 +117,7 @@ void Bowling::update(float dt) if(hat-0.5f*m_extend.getY()<0.01f) { const Material *material = getMaterial(); - if(!material || material->isReset()) + if(!material || material->isDriveReset()) { hit(NULL); return; diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 8b1751306..f2a1dc038 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -863,8 +863,10 @@ void Kart::update(float dt) else { handleMaterialSFX(material); - if (material->isReset() && isOnGround()) forceRescue(); - else if(material->isZipper() && isOnGround()) handleZipper(material); + if (material->isDriveReset() && isOnGround()) + forceRescue(); + else if(material->isZipper() && isOnGround()) + handleZipper(material); else { MaxSpeed::setSlowdown(MaxSpeed::MS_DECREASE_TERRAIN, @@ -1236,9 +1238,10 @@ void Kart::resetBrakes() // ----------------------------------------------------------------------------- /** Called when the kart crashes against the track (k=NULL) or another kart. - * \params k Either a kart if a kart was hit, or NULL if the track was hit. + * \param k Either a kart if a kart was hit, or NULL if the track was hit. + * \param m */ -void Kart::crashed(Kart *k) +void Kart::crashed(Kart *k, const Material *m) { m_controller->crashed(); /** If a kart is crashing against the track, the collision is often @@ -1246,6 +1249,8 @@ void Kart::crashed(Kart *k) * long disabling of the engine. Therefore, this reaction is disabled * for 0.5 seconds after a crash. */ + if(m && m->isCrashReset() && !playingEmergencyAnimation()) + forceRescue(); if(World::getWorld()->getTime()-m_time_last_crash < 0.5f) return; m_time_last_crash = World::getWorld()->getTime(); diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index 1f829f9d3..9fa1d912a 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -218,7 +218,7 @@ public: virtual void collectedItem (Item *item, int random_attachment); virtual void reset (); virtual void handleZipper (const Material *m=NULL, bool play_sound=false); - virtual void crashed (Kart *k); + virtual void crashed (Kart *k, const Material *m=NULL); virtual void update (float dt); virtual void finishedRace (float time); diff --git a/src/modes/world.cpp b/src/modes/world.cpp index fda32aea4..c1c6e2c9a 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -372,7 +372,7 @@ void World::resetAllKarts() const Vec3 &xyz = kart->getTrans().getOrigin()+Vec3(0,0.3f,0); ((TerrainInfo*)kart)->update(xyz); const Material *material = kart->getMaterial(); - if(!material || material->isReset()) + if(!material || material->isDriveReset()) kart_over_ground = false; } if(!kart_over_ground) diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index 3e3d405c4..00ff2718c 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -25,6 +25,7 @@ #include "physics/btKart.hpp" #include "physics/btUprightConstraint.hpp" #include "physics/irr_debug_drawer.hpp" +#include "physics/triangle_mesh.hpp" #include "tracks/track.hpp" // ---------------------------------------------------------------------------- @@ -290,7 +291,6 @@ btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies, // FIXME: Must be a moving physics object // FIXME: A rocket should explode here! - if(!upA || !upB) continue; // 1) object A is a track // ======================= @@ -302,7 +302,11 @@ btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies, { Kart *kart=upB->getPointerKart(); race_state->addCollision(kart->getWorldKartId()); - kart->crashed(NULL); + int n = contactManifold->getContactPoint(0).m_index0; + const Material *m + = n>=0 ? upA->getPointerTriangleMesh()->getMaterial(n) + : NULL; + kart->crashed(NULL, m); } } // 2) object a is a kart @@ -313,7 +317,11 @@ btScalar Physics::solveGroup(btCollisionObject** bodies, int numBodies, { Kart *kart = upA->getPointerKart(); race_state->addCollision(kart->getWorldKartId()); - kart->crashed(NULL); // Kart hit track + int n = contactManifold->getContactPoint(0).m_index1; + const Material *m + = n>=0 ? upB->getPointerTriangleMesh()->getMaterial(n) + : NULL; + kart->crashed(NULL, m); // Kart hit track } else if(upB->is(UserPointer::UP_FLYABLE)) m_all_collisions.push_back(upB, upA); // 2.1 projectile hits kart