Implement live change kart model of kart

This commit is contained in:
Benau 2018-12-29 13:14:07 +08:00
parent 43761e4d9e
commit 9068483d56
13 changed files with 297 additions and 216 deletions

View File

@ -365,13 +365,13 @@ void Flyable::setAnimation(AbstractKartAnimation *animation)
if (animation) if (animation)
{ {
assert(m_animation == NULL); assert(m_animation == NULL);
Physics::getInstance()->removeBody(m_body); Physics::getInstance()->removeBody(getBody());
} }
else // animation = NULL else // animation = NULL
{ {
assert(m_animation != NULL); assert(m_animation != NULL);
m_body->setWorldTransform(getTrans()); m_body->setWorldTransform(getTrans());
Physics::getInstance()->addBody(m_body); Physics::getInstance()->addBody(getBody());
} }
m_animation = animation; m_animation = animation;
} // addAnimation } // addAnimation
@ -617,7 +617,7 @@ BareNetworkString* Flyable::saveState(std::vector<std::string>* ru)
BareNetworkString *buffer = new BareNetworkString(); BareNetworkString *buffer = new BareNetworkString();
CompressNetworkBody::compress(m_body->getWorldTransform(), CompressNetworkBody::compress(m_body->getWorldTransform(),
m_body->getLinearVelocity(), m_body->getAngularVelocity(), buffer, m_body->getLinearVelocity(), m_body->getAngularVelocity(), buffer,
m_body, m_motion_state); m_body.get(), m_motion_state.get());
buffer->addUInt16(m_ticks_since_thrown); buffer->addUInt16(m_ticks_since_thrown);
return buffer; return buffer;
} // saveState } // saveState

View File

@ -19,11 +19,13 @@
#include "karts/abstract_kart.hpp" #include "karts/abstract_kart.hpp"
#include "items/attachment.hpp"
#include "items/powerup.hpp" #include "items/powerup.hpp"
#include "karts/abstract_kart_animation.hpp" #include "karts/abstract_kart_animation.hpp"
#include "karts/kart_model.hpp" #include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp" #include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp" #include "karts/kart_properties_manager.hpp"
#include "physics/physics.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
/** Creates a kart. /** Creates a kart.
@ -40,38 +42,12 @@ AbstractKart::AbstractKart(const std::string& ident,
: Moveable() : Moveable()
{ {
m_world_kart_id = world_kart_id; m_world_kart_id = world_kart_id;
m_kart_properties.reset(new KartProperties()); loadKartProperties(ident, difficulty, ri);
const KartProperties* kp = kart_properties_manager->getKart(ident);
if (kp == NULL)
{
Log::warn("Abstract_Kart", "Unknown kart %s, fallback to tux",
ident.c_str());
kp = kart_properties_manager->getKart(std::string("tux"));
}
m_kart_properties->copyForPlayer(kp, difficulty);
m_difficulty = difficulty;
m_kart_animation = NULL;
assert(m_kart_properties);
// We have to take a copy of the kart model, since otherwise
// the animations will be mixed up (i.e. different instances of
// the same model will set different animation frames).
// Technically the mesh in m_kart_model needs to be grab'ed and
// released when the kart is deleted, but since the original
// kart_model is stored in the kart_properties all the time,
// there is no risk of a mesh being deleted too early.
m_kart_model = m_kart_properties->getKartModelCopy(ri);
m_kart_width = m_kart_model->getWidth();
m_kart_height = m_kart_model->getHeight();
m_kart_length = m_kart_model->getLength();
m_kart_highest_point = m_kart_model->getHighestPoint();
m_wheel_graphics_position = m_kart_model->getWheelsGraphicsPosition();
} // AbstractKart } // AbstractKart
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
AbstractKart::~AbstractKart() AbstractKart::~AbstractKart()
{ {
delete m_kart_model;
if (m_kart_animation) if (m_kart_animation)
{ {
m_kart_animation->handleResetRace(); m_kart_animation->handleResetRace();
@ -94,6 +70,51 @@ void AbstractKart::reset()
Moveable::reset(); Moveable::reset();
} // reset } // reset
// ----------------------------------------------------------------------------
void AbstractKart::loadKartProperties(const std::string& new_ident,
PerPlayerDifficulty difficulty,
std::shared_ptr<RenderInfo> ri)
{
m_kart_properties.reset(new KartProperties());
const KartProperties* kp = kart_properties_manager->getKart(new_ident);
if (kp == NULL)
{
Log::warn("Abstract_Kart", "Unknown kart %s, fallback to tux",
new_ident.c_str());
kp = kart_properties_manager->getKart(std::string("tux"));
}
m_kart_properties->copyForPlayer(kp, difficulty);
m_difficulty = difficulty;
m_kart_animation = NULL;
assert(m_kart_properties);
// We have to take a copy of the kart model, since otherwise
// the animations will be mixed up (i.e. different instances of
// the same model will set different animation frames).
// Technically the mesh in m_kart_model needs to be grab'ed and
// released when the kart is deleted, but since the original
// kart_model is stored in the kart_properties all the time,
// there is no risk of a mesh being deleted too early.
m_kart_model.reset(m_kart_properties->getKartModelCopy(ri));
m_kart_width = m_kart_model->getWidth();
m_kart_height = m_kart_model->getHeight();
m_kart_length = m_kart_model->getLength();
m_kart_highest_point = m_kart_model->getHighestPoint();
m_wheel_graphics_position = m_kart_model->getWheelsGraphicsPosition();
} // loadKartProperties
// ----------------------------------------------------------------------------
void AbstractKart::changeKart(const std::string& new_ident,
PerPlayerDifficulty difficulty,
std::shared_ptr<RenderInfo> ri)
{
// Reset previous kart (including delete old animation above)
reset();
// Remove kart body
Physics::getInstance()->removeKart(this);
loadKartProperties(new_ident, difficulty, ri);
} // changeKart
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Returns a name to be displayed for this kart. */ /** Returns a name to be displayed for this kart. */
core::stringw AbstractKart::getName() const core::stringw AbstractKart::getName() const

View File

@ -76,6 +76,10 @@ private:
unsigned int m_world_kart_id; unsigned int m_world_kart_id;
btTransform m_starting_transform; btTransform m_starting_transform;
// ------------------------------------------------------------------------
void loadKartProperties(const std::string& new_ident,
PerPlayerDifficulty difficulty,
std::shared_ptr<RenderInfo> ri);
protected: protected:
/** The kart properties. */ /** The kart properties. */
std::unique_ptr<KartProperties> m_kart_properties; std::unique_ptr<KartProperties> m_kart_properties;
@ -86,10 +90,10 @@ protected:
/** This stores a copy of the kart model. It has to be a copy /** This stores a copy of the kart model. It has to be a copy
* since otherwise incosistencies can happen if the same kart * since otherwise incosistencies can happen if the same kart
* is used more than once. */ * is used more than once. */
KartModel* m_kart_model; std::unique_ptr<KartModel> m_kart_model;
/** Handles the attachment the kart might have. */ /** Handles the attachment the kart might have. */
Attachment *m_attachment; std::unique_ptr<Attachment> m_attachment;
/** The kart controls (e.g. steering, fire, ...). */ /** The kart controls (e.g. steering, fire, ...). */
KartControl m_controls; KartControl m_controls;
@ -127,7 +131,11 @@ public:
/** Returns the kart properties of this kart. */ /** Returns the kart properties of this kart. */
const KartProperties* getKartProperties() const const KartProperties* getKartProperties() const
{ return m_kart_properties.get(); } { return m_kart_properties.get(); }
// ========================================================================
/** Change to new kart instancely (used in network live join). */
virtual void changeKart(const std::string& new_ident,
PerPlayerDifficulty difficulty,
std::shared_ptr<RenderInfo> ri);
// ======================================================================== // ========================================================================
// Access to the per-player difficulty. // Access to the per-player difficulty.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -160,16 +168,16 @@ public:
// Attachment related functions. // Attachment related functions.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the current attachment. */ /** Returns the current attachment. */
const Attachment* getAttachment() const {return m_attachment; } const Attachment* getAttachment() const {return m_attachment.get(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the current attachment, non-const version. */ /** Returns the current attachment, non-const version. */
Attachment* getAttachment() {return m_attachment; } Attachment* getAttachment() {return m_attachment.get(); }
// ======================================================================== // ========================================================================
// Access to the graphical kart model. // Access to the graphical kart model.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns this kart's kart model. */ /** Returns this kart's kart model. */
KartModel* getKartModel() const { return m_kart_model; } KartModel* getKartModel() const { return m_kart_model.get(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the length of the kart. */ /** Returns the length of the kart. */
float getKartLength() const { return m_kart_length; } float getKartLength() const { return m_kart_length; }

View File

@ -59,7 +59,7 @@
LocalPlayerController::LocalPlayerController(AbstractKart *kart, LocalPlayerController::LocalPlayerController(AbstractKart *kart,
const int local_player_id, const int local_player_id,
PerPlayerDifficulty d) PerPlayerDifficulty d)
: PlayerController(kart), m_sky_particles_emitter(NULL) : PlayerController(kart)
{ {
m_has_started = false; m_has_started = false;
m_difficulty = d; m_difficulty = d;
@ -80,26 +80,7 @@ LocalPlayerController::LocalPlayerController(AbstractKart *kart,
m_unfull_sound = SFXManager::get()->getBuffer("energy_bar_unfull"); m_unfull_sound = SFXManager::get()->getBuffer("energy_bar_unfull");
m_is_above_nitro_target = false; m_is_above_nitro_target = false;
initParticleEmitter();
// Attach Particle System
Track *track = Track::getCurrentTrack();
#ifndef SERVER_ONLY
if (UserConfigParams::m_particles_effects > 1 &&
track->getSkyParticles() != NULL)
{
track->getSkyParticles()->setBoxSizeXZ(150.0f, 150.0f);
m_sky_particles_emitter =
new ParticleEmitter(track->getSkyParticles(),
core::vector3df(0.0f, 30.0f, 100.0f),
m_kart->getNode(),
true);
// FIXME: in multiplayer mode, this will result in several instances
// of the heightmap being calculated and kept in memory
m_sky_particles_emitter->addHeightMapAffector(track);
}
#endif
} // LocalPlayerController } // LocalPlayerController
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -108,11 +89,33 @@ LocalPlayerController::LocalPlayerController(AbstractKart *kart,
LocalPlayerController::~LocalPlayerController() LocalPlayerController::~LocalPlayerController()
{ {
m_wee_sound->deleteSFX(); m_wee_sound->deleteSFX();
if (m_sky_particles_emitter)
delete m_sky_particles_emitter;
} // ~LocalPlayerController } // ~LocalPlayerController
//-----------------------------------------------------------------------------
void LocalPlayerController::initParticleEmitter()
{
// Attach Particle System
m_sky_particles_emitter = nullptr;
Track *track = Track::getCurrentTrack();
#ifndef SERVER_ONLY
if (UserConfigParams::m_particles_effects > 1 &&
track->getSkyParticles() != NULL)
{
track->getSkyParticles()->setBoxSizeXZ(150.0f, 150.0f);
m_sky_particles_emitter.reset(
new ParticleEmitter(track->getSkyParticles(),
core::vector3df(0.0f, 30.0f, 100.0f),
m_kart->getNode(),
true));
// FIXME: in multiplayer mode, this will result in several instances
// of the heightmap being calculated and kept in memory
m_sky_particles_emitter->addHeightMapAffector(track);
}
#endif
} // initParticleEmitter
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Resets the player kart for a new or restarted race. /** Resets the player kart for a new or restarted race.
*/ */

View File

@ -22,6 +22,7 @@
#define HEADER_LOCAL_PLAYER_CONTROLLER_HPP #define HEADER_LOCAL_PLAYER_CONTROLLER_HPP
#include "karts/controller/player_controller.hpp" #include "karts/controller/player_controller.hpp"
#include <memory>
class AbstractKart; class AbstractKart;
class ParticleEmitter; class ParticleEmitter;
@ -44,7 +45,7 @@ private:
bool m_has_started; bool m_has_started;
bool m_is_above_nitro_target; bool m_is_above_nitro_target;
ParticleEmitter* m_sky_particles_emitter; std::unique_ptr<ParticleEmitter> m_sky_particles_emitter;
/** The index of the camera attached to the kart for this controller. The /** The index of the camera attached to the kart for this controller. The
* camera object is managed in the Camera class, so no need to free it. */ * camera object is managed in the Camera class, so no need to free it. */
@ -72,6 +73,7 @@ public:
void update (int ticks) OVERRIDE; void update (int ticks) OVERRIDE;
bool action (PlayerAction action, int value, bool action (PlayerAction action, int value,
bool dry_run=false) OVERRIDE; bool dry_run=false) OVERRIDE;
void initParticleEmitter();
virtual void handleZipper (bool play_sound) OVERRIDE; virtual void handleZipper (bool play_sound) OVERRIDE;
void collectedItem (const ItemState &item, void collectedItem (const ItemState &item,
float previous_energy=0) OVERRIDE; float previous_energy=0) OVERRIDE;

View File

@ -49,6 +49,7 @@
#include "karts/abstract_characteristic.hpp" #include "karts/abstract_characteristic.hpp"
#include "karts/abstract_kart_animation.hpp" #include "karts/abstract_kart_animation.hpp"
#include "karts/cached_characteristic.hpp" #include "karts/cached_characteristic.hpp"
#include "karts/controller/local_player_controller.hpp"
#include "karts/controller/end_controller.hpp" #include "karts/controller/end_controller.hpp"
#include "karts/controller/spare_tire_ai.hpp" #include "karts/controller/spare_tire_ai.hpp"
#include "karts/explosion_animation.hpp" #include "karts/explosion_animation.hpp"
@ -118,21 +119,17 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
m_max_speed = new MaxSpeed(this); m_max_speed = new MaxSpeed(this);
m_terrain_info = new TerrainInfo(); m_terrain_info = new TerrainInfo();
m_powerup = new Powerup(this); m_powerup = new Powerup(this);
m_vehicle = NULL;
m_initial_position = position; m_initial_position = position;
m_race_result = false; m_race_result = false;
m_shadow = NULL;
m_wheel_box = NULL; m_wheel_box = NULL;
m_collision_particles = NULL; m_collision_particles = NULL;
m_slipstream = NULL;
m_skidmarks = NULL;
m_controller = NULL; m_controller = NULL;
m_saved_controller = NULL; m_saved_controller = NULL;
m_stars_effect = NULL; m_stars_effect = NULL;
m_consumption_per_tick = stk_config->ticks2Time(1) * m_consumption_per_tick = stk_config->ticks2Time(1) *
m_kart_properties->getNitroConsumption(); m_kart_properties->getNitroConsumption();
m_fire_clicked = 0; m_fire_clicked = 0;
m_default_suspension_force = 0.0f;
m_boosted_ai = false; m_boosted_ai = false;
m_type = RaceManager::KT_AI; m_type = RaceManager::KT_AI;
m_flying = false; m_flying = false;
@ -224,14 +221,48 @@ void Kart::init(RaceManager::KartType type)
#endif #endif
loadData(type, animations); loadData(type, animations);
m_kart_gfx = new KartGFX(this, Track::getCurrentTrack()->getIsDuringDay());
m_skidding = new Skidding(this);
// Create the stars effect
m_stars_effect = new Stars(this);
reset(); reset();
} // init } // init
// ----------------------------------------------------------------------------
void Kart::changeKart(const std::string& new_ident,
PerPlayerDifficulty difficulty,
std::shared_ptr<RenderInfo> ri)
{
AbstractKart::changeKart(new_ident, difficulty, ri);
m_kart_model->setKart(this);
#ifdef SERVER_ONLY
bool animations = false; // server never animates
#else
bool animations = UserConfigParams::m_animated_characters;
#endif
scene::ISceneNode* old_node = m_node;
loadData(m_type, animations);
m_wheel_box = NULL;
if (LocalPlayerController* lpc =
dynamic_cast<LocalPlayerController*>(getController()))
lpc->initParticleEmitter();
if (old_node)
old_node->remove();
// Reset 1 more time (add back the body)
reset();
for (int i = 0; i < m_vehicle->getNumWheels(); i++)
{
btWheelInfo &wi = m_vehicle->getWheelInfo(i);
wi.m_raycastInfo.m_suspensionLength = m_default_suspension_force /
m_vehicle->getNumWheels();
}
m_graphical_y_offset = -m_default_suspension_force /
m_vehicle->getNumWheels() + m_kart_model->getLowestPoint();
m_kart_model->setDefaultSuspension();
} // changeKart
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** The destructor frees the memory of this kart, but note that the actual kart /** The destructor frees the memory of this kart, but note that the actual kart
* model is still stored in the kart_properties (m_kart_model variable), so * model is still stored in the kart_properties (m_kart_model variable), so
@ -254,18 +285,9 @@ Kart::~Kart()
m_emitters[i]->deleteSFX(); m_emitters[i]->deleteSFX();
m_nitro_sound ->deleteSFX(); m_nitro_sound ->deleteSFX();
delete m_kart_gfx;
if(m_terrain_sound) m_terrain_sound->deleteSFX(); if(m_terrain_sound) m_terrain_sound->deleteSFX();
if(m_previous_terrain_sound) m_previous_terrain_sound->deleteSFX(); if(m_previous_terrain_sound) m_previous_terrain_sound->deleteSFX();
if(m_collision_particles) delete m_collision_particles; if(m_collision_particles) delete m_collision_particles;
if(m_slipstream) delete m_slipstream;
if(m_attachment) delete m_attachment;
if(m_stars_effect) delete m_stars_effect;
#ifndef SERVER_ONLY
delete m_shadow;
if(m_skidmarks) delete m_skidmarks ;
#endif
if (m_wheel_box) m_wheel_box->remove(); if (m_wheel_box) m_wheel_box->remove();
@ -273,15 +295,8 @@ Kart::~Kart()
if(m_body) if(m_body)
{ {
Physics::getInstance()->removeKart(this); Physics::getInstance()->removeKart(this);
delete m_vehicle;
delete m_vehicle_raycaster;
} }
for(int i=0; i<m_kart_chassis.getNumChildShapes(); i++)
{
delete m_kart_chassis.getChildShape(i);
}
delete m_skidding;
delete m_max_speed; delete m_max_speed;
delete m_terrain_info; delete m_terrain_info;
delete m_powerup; delete m_powerup;
@ -708,7 +723,8 @@ void Kart::createPhysics()
// Shift center of gravity downwards, so that the kart // Shift center of gravity downwards, so that the kart
// won't topple over too easy. // won't topple over too easy.
shiftCenterOfGravity.setOrigin(m_kart_properties->getGravityCenterShift()); shiftCenterOfGravity.setOrigin(m_kart_properties->getGravityCenterShift());
m_kart_chassis.addChildShape(shiftCenterOfGravity, hull); m_kart_chassis.reset(new btCompoundShape());
m_kart_chassis->addChildShape(shiftCenterOfGravity, hull);
// Set mass and inertia // Set mass and inertia
// -------------------- // --------------------
@ -718,7 +734,7 @@ void Kart::createPhysics()
// -------------------- // --------------------
btTransform trans; btTransform trans;
trans.setIdentity(); trans.setIdentity();
createBody(mass, trans, &m_kart_chassis, createBody(mass, trans, m_kart_chassis.get(),
m_kart_properties->getRestitution(0.0f)); m_kart_properties->getRestitution(0.0f));
std::vector<float> ang_fact = m_kart_properties->getStabilityAngularFactor(); std::vector<float> ang_fact = m_kart_properties->getStabilityAngularFactor();
// The angular factor (with X and Z values <1) helps to keep the kart // The angular factor (with X and Z values <1) helps to keep the kart
@ -736,11 +752,11 @@ void Kart::createPhysics()
// Create the actual vehicle // Create the actual vehicle
// ------------------------- // -------------------------
m_vehicle_raycaster = m_vehicle_raycaster.reset(
new btKartRaycaster(Physics::getInstance()->getPhysicsWorld(), new btKartRaycaster(Physics::getInstance()->getPhysicsWorld(),
stk_config->m_smooth_normals && stk_config->m_smooth_normals &&
Track::getCurrentTrack()->smoothNormals()); Track::getCurrentTrack()->smoothNormals()));
m_vehicle = new btKart(m_body, m_vehicle_raycaster, this); m_vehicle.reset(new btKart(m_body.get(), m_vehicle_raycaster.get(), this));
// never deactivate the vehicle // never deactivate the vehicle
m_body->setActivationState(DISABLE_DEACTIVATION); m_body->setActivationState(DISABLE_DEACTIVATION);
@ -862,7 +878,7 @@ void Kart::updateWeight()
{ {
m_weight = mass; m_weight = mass;
btVector3 inertia; btVector3 inertia;
m_kart_chassis.calculateLocalInertia(mass, inertia); m_kart_chassis->calculateLocalInertia(mass, inertia);
m_body->setMassProps(mass, inertia); m_body->setMassProps(mass, inertia);
} }
} // updateWeight } // updateWeight
@ -2939,24 +2955,33 @@ void Kart::loadData(RaceManager::KartType type, bool is_animated_model)
// scene node will exist (to which the attachment is added). But the // scene node will exist (to which the attachment is added). But the
// attachment is needed in createPhysics (which gets the mass, which // attachment is needed in createPhysics (which gets the mass, which
// is dependent on the attachment). // is dependent on the attachment).
m_attachment = new Attachment(this); m_attachment.reset(new Attachment(this));
createPhysics(); createPhysics();
m_slipstream = new SlipStream(this); m_slipstream.reset(new SlipStream(this));
m_skidmarks = nullptr;
m_shadow = nullptr;
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
if (m_kart_properties->getSkidEnabled() && CVS->isGLSL()) if (m_kart_properties->getSkidEnabled() && CVS->isGLSL())
{ {
m_skidmarks = new SkidMarks(*this); m_skidmarks.reset(new SkidMarks(*this));
} }
if (CVS->isGLSL() && !CVS->isShadowEnabled() && m_kart_properties if (CVS->isGLSL() && !CVS->isShadowEnabled() && m_kart_properties
->getShadowMaterial()->getSamplerPath(0) != "unicolor_white") ->getShadowMaterial()->getSamplerPath(0) != "unicolor_white")
{ {
m_shadow = new Shadow(m_kart_properties->getShadowMaterial(), *this); m_shadow.reset(new Shadow(m_kart_properties->getShadowMaterial(),
*this));
} }
#endif #endif
World::getWorld()->kartAdded(this, m_node); World::getWorld()->kartAdded(this, m_node);
m_kart_gfx.reset(
new KartGFX(this, Track::getCurrentTrack()->getIsDuringDay()));
m_skidding.reset(new Skidding(this));
// Create the stars effect
m_stars_effect.reset(new Stars(this));
} // loadData } // loadData
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -2998,11 +3023,11 @@ void Kart::applyEngineForce(float force)
void Kart::kartIsInRestNow() void Kart::kartIsInRestNow()
{ {
AbstractKart::kartIsInRestNow(); AbstractKart::kartIsInRestNow();
float f = 0; m_default_suspension_force = 0.0f;
for(int i=0; i<m_vehicle->getNumWheels(); i++) for (int i = 0; i < m_vehicle->getNumWheels(); i++)
{ {
const btWheelInfo &wi = m_vehicle->getWheelInfo(i); const btWheelInfo &wi = m_vehicle->getWheelInfo(i);
f += wi.m_raycastInfo.m_suspensionLength; m_default_suspension_force += wi.m_raycastInfo.m_suspensionLength;
} }
// The offset 'lowest point' is added to avoid that the // The offset 'lowest point' is added to avoid that the
@ -3010,8 +3035,8 @@ void Kart::kartIsInRestNow()
// constant, there is no real reason to use the lowest point // constant, there is no real reason to use the lowest point
// but that value has worked good in the past). See documentation // but that value has worked good in the past). See documentation
// for updateGraphics() for full details. // for updateGraphics() for full details.
m_graphical_y_offset = -f / m_vehicle->getNumWheels() m_graphical_y_offset = -m_default_suspension_force /
+ m_kart_model->getLowestPoint(); m_vehicle->getNumWheels() + m_kart_model->getLowestPoint();
m_kart_model->setDefaultSuspension(); m_kart_model->setDefaultSuspension();
} // kartIsInRestNow } // kartIsInRestNow

View File

@ -106,21 +106,47 @@ protected:
/** Handles the powerup of a kart. */ /** Handles the powerup of a kart. */
Powerup *m_powerup; Powerup *m_powerup;
/** Remember the last **used** powerup type of a kart for AI purposes. */
PowerupManager::PowerupType m_last_used_powerup;
/** True if kart is flying (for debug purposes only). */ std::unique_ptr<btVehicleRaycaster> m_vehicle_raycaster;
bool m_flying;
/** Set when hitting bubblegum */ std::unique_ptr<btKart> m_vehicle;
bool m_has_caught_nolok_bubblegum;
/** Reset position. */
btTransform m_reset_transform;
/** This object handles all skidding. */ /** This object handles all skidding. */
Skidding *m_skidding; std::unique_ptr<Skidding> m_skidding;
/** For stars rotating around head effect */
std::unique_ptr<Stars> m_stars_effect;
// Graphical effects
// -----------------
/** The shadow of a kart. */
std::unique_ptr<Shadow> m_shadow;
/** All particle effects. */
std::unique_ptr<KartGFX> m_kart_gfx;
/** Handles all slipstreaming. */
std::unique_ptr<SlipStream> m_slipstream;
/** The skidmarks object for this kart. */
std::unique_ptr<SkidMarks> m_skidmarks;
// Bullet physics parameters
// -------------------------
struct btCompoundShapeDeleter
{
void operator()(btCompoundShape* p) const
{
for(int i = 0; i< p->getNumChildShapes(); i++)
delete p->getChildShape(i);
delete p;
}
};
std::unique_ptr<btCompoundShape, btCompoundShapeDeleter> m_kart_chassis;
/** For collisions */
ParticleEmitter *m_collision_particles;
/** The main controller of this object, used for driving. This /** The main controller of this object, used for driving. This
* controller is used to run the kart. It will be replaced * controller is used to run the kart. It will be replaced
@ -132,11 +158,14 @@ protected:
* the controller do not need to be reinitialised. */ * the controller do not need to be reinitialised. */
Controller *m_saved_controller; Controller *m_saved_controller;
/** Initial rank of the kart. */ /** Remember the last **used** powerup type of a kart for AI purposes. */
int m_initial_position; PowerupManager::PowerupType m_last_used_powerup;
/** Current race position (1-num_karts). */ /** True if kart is flying (for debug purposes only). */
int m_race_position; bool m_flying;
/** Set when hitting bubblegum */
bool m_has_caught_nolok_bubblegum;
/** True if the kart wins, false otherwise. */ /** True if the kart wins, false otherwise. */
bool m_race_result; bool m_race_result;
@ -144,8 +173,11 @@ protected:
/** True if the kart is eliminated. */ /** True if the kart is eliminated. */
bool m_eliminated; bool m_eliminated;
/** For stars rotating around head effect */ /** Initial rank of the kart. */
Stars *m_stars_effect; int m_initial_position;
/** Current race position (1-num_karts). */
int m_race_position;
/** Maximum engine rpm's for the current gear. */ /** Maximum engine rpm's for the current gear. */
float m_max_gear_rpm; float m_max_gear_rpm;
@ -161,14 +193,18 @@ protected:
/** Time a kart is invulnerable. */ /** Time a kart is invulnerable. */
int16_t m_invulnerable_ticks; int16_t m_invulnerable_ticks;
/** Current leaning of the kart. */
float m_current_lean;
/** If > 0 then bubble gum effect is on. This is the sliding when hitting a gum on the floor, not the shield. */ /** If > 0 then bubble gum effect is on. This is the sliding when hitting a gum on the floor, not the shield. */
int16_t m_bubblegum_ticks; int16_t m_bubblegum_ticks;
/** The torque to apply after hitting a bubble gum. */ /** When a kart has its view blocked by the plunger, this variable will be
float m_bubblegum_torque; * > 0 the number it contains is the time left before removing plunger. */
int16_t m_view_blocked_by_plunger;
/** Current leaning of the kart. */
float m_current_lean;
/** To prevent using nitro in too short bursts */
int8_t m_min_nitro_ticks;
/** True if fire button was pushed and not released */ /** True if fire button was pushed and not released */
bool m_fire_clicked; bool m_fire_clicked;
@ -176,11 +212,12 @@ protected:
/** True if the kart has been selected to have a boosted ai */ /** True if the kart has been selected to have a boosted ai */
bool m_boosted_ai; bool m_boosted_ai;
// Bullet physics parameters bool m_finished_race;
// -------------------------
btCompoundShape m_kart_chassis; float m_finish_time;
btVehicleRaycaster *m_vehicle_raycaster;
btKart *m_vehicle; /** The torque to apply after hitting a bubble gum. */
float m_bubblegum_torque;
/** The amount of energy collected with nitro cans. Note that it /** The amount of energy collected with nitro cans. Note that it
* must be float, since dt is subtraced in each timestep. */ * must be float, since dt is subtraced in each timestep. */
@ -190,42 +227,24 @@ protected:
float m_energy_to_min_ratio; float m_energy_to_min_ratio;
// Graphical effects
// -----------------
/** The shadow of a kart. */
Shadow *m_shadow;
/** All particle effects. */
KartGFX *m_kart_gfx;
/** For collisions */
ParticleEmitter *m_collision_particles;
/** Handles all slipstreaming. */
SlipStream *m_slipstream;
/** The skidmarks object for this kart. */
SkidMarks *m_skidmarks;
float m_startup_boost; float m_startup_boost;
float m_finish_time;
bool m_finished_race;
float m_falling_time; float m_falling_time;
float m_weight; float m_weight;
/** When a kart has its view blocked by the plunger, this variable will be
* > 0 the number it contains is the time left before removing plunger. */
int16_t m_view_blocked_by_plunger;
/** The current speed (i.e. length of velocity vector) of this kart. */ /** The current speed (i.e. length of velocity vector) of this kart. */
float m_speed; float m_speed;
/** For smoothing engine sound**/ /** For smoothing engine sound**/
float m_last_factor_engine_sound; float m_last_factor_engine_sound;
/** For changeKart**/
float m_default_suspension_force;
/** Reset position. */
btTransform m_reset_transform;
std::vector<SFXBase*> m_custom_sounds; std::vector<SFXBase*> m_custom_sounds;
int m_emitter_id = 0; int m_emitter_id = 0;
static const int EMITTER_COUNT = 3; static const int EMITTER_COUNT = 3;
@ -250,9 +269,6 @@ protected:
int m_ticks_last_crash; int m_ticks_last_crash;
RaceManager::KartType m_type; RaceManager::KartType m_type;
/** To prevent using nitro in too short bursts */
int8_t m_min_nitro_ticks;
void updatePhysics(int ticks); void updatePhysics(int ticks);
void handleMaterialSFX(); void handleMaterialSFX();
void handleMaterialGFX(float dt); void handleMaterialGFX(float dt);
@ -327,7 +343,9 @@ public:
virtual bool playCustomSFX (unsigned int type) OVERRIDE; virtual bool playCustomSFX (unsigned int type) OVERRIDE;
virtual void setController(Controller *controller) OVERRIDE; virtual void setController(Controller *controller) OVERRIDE;
virtual void setXYZ(const Vec3& a) OVERRIDE; virtual void setXYZ(const Vec3& a) OVERRIDE;
virtual void changeKart(const std::string& new_ident,
PerPlayerDifficulty difficulty,
std::shared_ptr<RenderInfo> ri) OVERRIDE;
// ======================================================================== // ========================================================================
// Powerup related functions. // Powerup related functions.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -353,7 +371,7 @@ public:
virtual int getNumPowerup() const OVERRIDE; virtual int getNumPowerup() const OVERRIDE;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns a points to this kart's graphical effects. */ /** Returns a points to this kart's graphical effects. */
virtual KartGFX* getKartGFX() OVERRIDE { return m_kart_gfx; } virtual KartGFX* getKartGFX() OVERRIDE { return m_kart_gfx.get(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the remaining collected energy. */ /** Returns the remaining collected energy. */
virtual float getEnergy() const OVERRIDE virtual float getEnergy() const OVERRIDE
@ -417,16 +435,17 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the skidding object for this kart (which can be used to query /** Returns the skidding object for this kart (which can be used to query
* skidding related values). */ * skidding related values). */
virtual const Skidding *getSkidding() const OVERRIDE { return m_skidding; } virtual const Skidding *getSkidding() const OVERRIDE
{ return m_skidding.get(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the skidding object for this kart (which can be used to query /** Returns the skidding object for this kart (which can be used to query
* skidding related values) - non-const. */ * skidding related values) - non-const. */
virtual Skidding *getSkidding() OVERRIDE { return m_skidding; } virtual Skidding *getSkidding() OVERRIDE { return m_skidding.get(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual RaceManager::KartType getType() const OVERRIDE { return m_type; } virtual RaceManager::KartType getType() const OVERRIDE { return m_type; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the bullet vehicle which represents this kart. */ /** Returns the bullet vehicle which represents this kart. */
virtual btKart *getVehicle() const OVERRIDE { return m_vehicle; } virtual btKart *getVehicle() const OVERRIDE { return m_vehicle.get(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the speed of the kart in meters/second. */ /** Returns the speed of the kart in meters/second. */
virtual float getSpeed() const OVERRIDE { return m_speed; } virtual float getSpeed() const OVERRIDE { return m_speed; }
@ -438,10 +457,11 @@ public:
virtual btQuaternion getVisualRotation() const OVERRIDE; virtual btQuaternion getVisualRotation() const OVERRIDE;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the slipstream object of this kart. */ /** Returns the slipstream object of this kart. */
virtual const SlipStream* getSlipstream() const OVERRIDE { return m_slipstream; } virtual const SlipStream* getSlipstream() const OVERRIDE
{ return m_slipstream.get(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the slipstream object of this kart. */ /** Returns the slipstream object of this kart. */
virtual SlipStream* getSlipstream() OVERRIDE {return m_slipstream; } virtual SlipStream* getSlipstream() OVERRIDE {return m_slipstream.get(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Activates a slipstream effect, atm that is display some nitro. */ /** Activates a slipstream effect, atm that is display some nitro. */
virtual void setSlipstreamEffect(float f) OVERRIDE; virtual void setSlipstreamEffect(float f) OVERRIDE;
@ -552,7 +572,8 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual bool isVisible() OVERRIDE; virtual bool isVisible() OVERRIDE;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual Stars* getStarsEffect() const OVERRIDE { return m_stars_effect; } virtual Stars* getStarsEffect() const OVERRIDE
{ return m_stars_effect.get(); }
}; // Kart }; // Kart

View File

@ -64,6 +64,8 @@ void KartRewinder::reset()
m_has_server_state = false; m_has_server_state = false;
} // reset } // reset
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** This function is called immediately before a rewind is done and saves /** This function is called immediately before a rewind is done and saves
* the current transform for the kart. The difference between this saved * the current transform for the kart. The difference between this saved

View File

@ -35,7 +35,6 @@ Moveable::Moveable()
{ {
m_body = 0; m_body = 0;
m_motion_state = 0; m_motion_state = 0;
m_mesh = NULL;
m_node = NULL; m_node = NULL;
m_heading = 0; m_heading = 0;
} // Moveable } // Moveable
@ -44,10 +43,7 @@ Moveable::Moveable()
Moveable::~Moveable() Moveable::~Moveable()
{ {
// The body is being removed from the world in kart/projectile // The body is being removed from the world in kart/projectile
if(m_body) delete m_body;
if(m_motion_state) delete m_motion_state;
if(m_node) irr_driver->removeNode(m_node); if(m_node) irr_driver->removeNode(m_node);
if(m_mesh) irr_driver->removeMeshFromCache(m_mesh);
} // ~Moveable } // ~Moveable
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -191,16 +187,16 @@ void Moveable::createBody(float mass, btTransform& trans,
btVector3 inertia; btVector3 inertia;
shape->calculateLocalInertia(mass, inertia); shape->calculateLocalInertia(mass, inertia);
m_transform = trans; m_transform = trans;
m_motion_state = new KartMotionState(trans); m_motion_state.reset(new KartMotionState(trans));
btRigidBody::btRigidBodyConstructionInfo info(mass, m_motion_state, btRigidBody::btRigidBodyConstructionInfo info(mass, m_motion_state.get(),
shape, inertia); shape, inertia);
info.m_restitution = restitution; info.m_restitution = restitution;
info.m_friction = stk_config->m_default_moveable_friction; info.m_friction = stk_config->m_default_moveable_friction;
// Then create a rigid body // Then create a rigid body
// ------------------------ // ------------------------
m_body = new btRigidBody(info); m_body.reset(new btRigidBody(info));
if(mass==0) if(mass==0)
{ {
// Create a kinematic object // Create a kinematic object

View File

@ -33,6 +33,7 @@ using namespace irr;
#include "utils/no_copy.hpp" #include "utils/no_copy.hpp"
#include "utils/vec3.hpp" #include "utils/vec3.hpp"
#include <memory>
#include <string> #include <string>
class Material; class Material;
@ -55,10 +56,9 @@ private:
float m_roll; float m_roll;
protected: protected:
UserPointer m_user_pointer; UserPointer m_user_pointer;
scene::IMesh *m_mesh;
scene::ISceneNode *m_node; scene::ISceneNode *m_node;
btRigidBody *m_body; std::unique_ptr<btRigidBody> m_body;
KartMotionState *m_motion_state; std::unique_ptr<KartMotionState> m_motion_state;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void updateSmoothedGraphics(float dt); void updateSmoothedGraphics(float dt);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -119,7 +119,7 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual void reset(); virtual void reset();
virtual void update(int ticks) ; virtual void update(int ticks) ;
btRigidBody *getBody() const {return m_body; } btRigidBody *getBody() const {return m_body.get(); }
void createBody(float mass, btTransform& trans, void createBody(float mass, btTransform& trans,
btCollisionShape *shape, btCollisionShape *shape,
float restitution); float restitution);

View File

@ -70,6 +70,8 @@ CaptureTheFlag::CaptureTheFlag() : FreeForAll()
CaptureTheFlag::~CaptureTheFlag() CaptureTheFlag::~CaptureTheFlag()
{ {
#ifndef SERVER_ONLY #ifndef SERVER_ONLY
m_red_flag_node->drop();
m_blue_flag_node->drop();
irr_driver->dropAllTextures(m_red_flag_mesh); irr_driver->dropAllTextures(m_red_flag_mesh);
irr_driver->dropAllTextures(m_blue_flag_mesh); irr_driver->dropAllTextures(m_blue_flag_mesh);
irr_driver->removeMeshFromCache(m_red_flag_mesh); irr_driver->removeMeshFromCache(m_red_flag_mesh);
@ -98,6 +100,8 @@ void CaptureTheFlag::init()
"blue_flag"); "blue_flag");
assert(m_red_flag_node); assert(m_red_flag_node);
assert(m_blue_flag_node); assert(m_blue_flag_node);
m_red_flag_node->grab();
m_blue_flag_node->grab();
std::string red_path = std::string red_path =
file_manager->getAsset(FileManager::GUI_ICON, "red_arrow.png"); file_manager->getAsset(FileManager::GUI_ICON, "red_arrow.png");

View File

@ -262,10 +262,46 @@ void World::init()
} // if server with graphics of is watching replay } // if server with graphics of is watching replay
} // if getNumCameras()==0 } // if getNumCameras()==0
initTeamArrows();
const unsigned int kart_amount = (unsigned int)m_karts.size();
for (unsigned int i = 0; i < kart_amount; i++)
initTeamArrows(m_karts[i].get());
main_loop->renderGUI(7300); main_loop->renderGUI(7300);
} // init } // init
//-----------------------------------------------------------------------------
void World::initTeamArrows(AbstractKart* k)
{
if (!hasTeam())
return;
#ifndef SERVER_ONLY
//Loading the indicator textures
std::string red_path =
file_manager->getAsset(FileManager::GUI_ICON, "red_arrow.png");
std::string blue_path =
file_manager->getAsset(FileManager::GUI_ICON, "blue_arrow.png");
// Assigning indicators
scene::ISceneNode *arrow_node = NULL;
KartModel* km = k->getKartModel();
// Color of karts can be changed using shaders if the model supports
if (km->supportColorization() && CVS->isGLSL())
return;
float arrow_pos_height = km->getHeight() + 0.5f;
KartTeam team = getKartTeam(k->getWorldKartId());
arrow_node = irr_driver->addBillboard(
core::dimension2d<irr::f32>(0.3f,0.3f),
team == KART_TEAM_BLUE ? blue_path : red_path,
k->getNode());
arrow_node->setPosition(core::vector3df(0, arrow_pos_height, 0));
#endif
} // initTeamArrows
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** This function is called before a race is started (i.e. either after /** This function is called before a race is started (i.e. either after
* calling init() when starting a race for the first time, or after * calling init() when starting a race for the first time, or after
@ -1490,44 +1526,6 @@ KartTeam World::getKartTeam(unsigned int kart_id) const
return n->second; return n->second;
} // getKartTeam } // getKartTeam
//-----------------------------------------------------------------------------
void World::initTeamArrows()
{
if (!hasTeam())
return;
#ifndef SERVER_ONLY
const unsigned int kart_amount = (unsigned int)m_karts.size();
//Loading the indicator textures
std::string red_path =
file_manager->getAsset(FileManager::GUI_ICON, "red_arrow.png");
std::string blue_path =
file_manager->getAsset(FileManager::GUI_ICON, "blue_arrow.png");
//Assigning indicators
for(unsigned int i = 0; i < kart_amount; i++)
{
scene::ISceneNode *arrow_node = NULL;
KartModel* km = m_karts[i]->getKartModel();
// Color of karts can be changed using shaders if the model supports
if (km->supportColorization() && CVS->isGLSL()) continue;
float arrow_pos_height = km->getHeight() + 0.5f;
KartTeam team = getKartTeam(i);
arrow_node = irr_driver->addBillboard(
core::dimension2d<irr::f32>(0.3f,0.3f),
team == KART_TEAM_BLUE ? blue_path : red_path,
m_karts[i]->getNode());
arrow_node->setPosition(core::vector3df(0, arrow_pos_height, 0));
}
#endif
} // initTeamArrows
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void World::setAITeam() void World::setAITeam()
{ {

View File

@ -194,8 +194,6 @@ protected:
*/ */
virtual float estimateFinishTimeForKart(AbstractKart* kart) virtual float estimateFinishTimeForKart(AbstractKart* kart)
{return getTime(); } {return getTime(); }
/** Set the team arrow on karts if necessary*/
void initTeamArrows();
void updateAchievementDataEndRace(); void updateAchievementDataEndRace();
void updateAchievementModeCounters(bool start); void updateAchievementModeCounters(bool start);
@ -363,6 +361,9 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
bool isNetworkWorld() const { return m_is_network_world; } bool isNetworkWorld() const { return m_is_network_world; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Set the team arrow on karts if necessary*/
void initTeamArrows(AbstractKart* k);
// ------------------------------------------------------------------------
/** Used by server to get the current started game progress in either or /** Used by server to get the current started game progress in either or
* both remaining time or progress in percent. uint32_t max for either or * both remaining time or progress in percent. uint32_t max for either or
* both if not available. */ * both if not available. */