diff --git a/data/gfx/nitro.xml b/data/gfx/nitro.xml index bccbdce4d..aaa3785b0 100644 --- a/data/gfx/nitro.xml +++ b/data/gfx/nitro.xml @@ -1,5 +1,5 @@ - + diff --git a/data/gfx/skid0.xml b/data/gfx/skid0.xml new file mode 100644 index 000000000..3265dffb8 --- /dev/null +++ b/data/gfx/skid0.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/data/gfx/skid1.xml b/data/gfx/skid1.xml index 34d0ceab0..f0bf251b3 100644 --- a/data/gfx/skid1.xml +++ b/data/gfx/skid1.xml @@ -1,29 +1,29 @@ - + - + + y="0.008" + z="-0.015" /> - + - + - + - diff --git a/data/gfx/skid2.xml b/data/gfx/skid2.xml index 1b94634b0..40de5c81c 100644 --- a/data/gfx/skid2.xml +++ b/data/gfx/skid2.xml @@ -1,29 +1,29 @@ - + - + + y="0.008" + z="-0.015" /> - + - + - + - + diff --git a/data/kart_characteristics.xml b/data/kart_characteristics.xml index 146d2c593..f8ff73651 100644 --- a/data/kart_characteristics.xml +++ b/data/kart_characteristics.xml @@ -404,16 +404,16 @@ - - - + + + + - - - + + diff --git a/src/graphics/slip_stream.cpp b/src/graphics/slip_stream.cpp index bf1f3fc07..c87a8add5 100644 --- a/src/graphics/slip_stream.cpp +++ b/src/graphics/slip_stream.cpp @@ -829,8 +829,7 @@ void SlipStream::update(int ticks) kp->getSlipstreamMaxSpeedIncrease(), kp->getSlipstreamMaxSpeedIncrease(), kp->getSlipstreamAddPower(), - m_bonus_time, - stk_config->ticks2Time(fade_out) ); + stk_config->time2Ticks(m_bonus_time), fade_out); } if(!is_sstreaming) diff --git a/src/items/rubber_band.cpp b/src/items/rubber_band.cpp index e22435b57..d135c5573 100644 --- a/src/items/rubber_band.cpp +++ b/src/items/rubber_band.cpp @@ -194,10 +194,10 @@ void RubberBand::update(int ticks) diff.normalize(); // diff can't be zero here m_owner->getBody()->applyCentralForce(diff*force); m_owner->increaseMaxSpeed(MaxSpeed::MS_INCREASE_RUBBER, - kp->getPlungerBandSpeedIncrease(), - /*engine_force*/ 0.0f, - /*duration*/stk_config->time2Ticks(0.1f), - kp->getPlungerBandFadeOutTicks()); + kp->getPlungerBandSpeedIncrease(), + /*engine_force*/ 0.0f, + /*duration*/stk_config->time2Ticks(0.1f), + kp->getPlungerBandFadeOutTicks() ); if(m_attached_state==RB_TO_KART) m_hit_kart->getBody()->applyCentralForce(diff*(-force)); } diff --git a/src/karts/abstract_kart.hpp b/src/karts/abstract_kart.hpp index 4dbad3203..7d786df86 100644 --- a/src/karts/abstract_kart.hpp +++ b/src/karts/abstract_kart.hpp @@ -307,8 +307,8 @@ public: * \param fade_out_time How long the maximum speed will fade out linearly. */ virtual void increaseMaxSpeed(unsigned int category, float add_speed, - float engine_force, float duration, - float fade_out_time) = 0; + float engine_force, int duration, + int fade_out_time) = 0; // ---------------------------------------------------------------------------- /** This adjusts the top speed using increaseMaxSpeed, but additionally @@ -323,8 +323,8 @@ public: * \param fade_out_time How long the maximum speed will fade out linearly. */ virtual void instantSpeedIncrease(unsigned int category, float add_max_speed, - float speed_boost, float engine_force, float duration, - float fade_out_time) = 0; + float speed_boost, float engine_force, + int duration, int fade_out_time) = 0; // ------------------------------------------------------------------------ /** Defines a slowdown, which is in fraction of top speed. diff --git a/src/karts/controller/local_player_controller.cpp b/src/karts/controller/local_player_controller.cpp index 3107b2857..31bf11edb 100644 --- a/src/karts/controller/local_player_controller.cpp +++ b/src/karts/controller/local_player_controller.cpp @@ -74,6 +74,9 @@ LocalPlayerController::LocalPlayerController(AbstractKart *kart, m_ugh_sound = SFXManager::get()->getBuffer("ugh"); m_grab_sound = SFXManager::get()->getBuffer("grab_collectable"); m_full_sound = SFXManager::get()->getBuffer("energy_bar_full"); + m_unfull_sound = SFXManager::get()->getBuffer("energy_bar_unfull"); + + m_is_above_nitro_target = false; // Attach Particle System Track *track = Track::getCurrentTrack(); @@ -235,6 +238,10 @@ void LocalPlayerController::update(int ticks) } } } + + if (m_is_above_nitro_target == true && + m_kart->getEnergy() < race_manager->getCoinTarget()) + nitroNotFullSound(); #endif if (m_kart->getKartAnimation() && m_sound_schedule == false) { @@ -347,9 +354,10 @@ void LocalPlayerController::collectedItem(const Item &item, int add_info, } else if (race_manager->getCoinTarget() > 0 && old_energy < race_manager->getCoinTarget() && - m_kart->getEnergy() == race_manager->getCoinTarget()) + m_kart->getEnergy() >= race_manager->getCoinTarget()) { m_kart->playSound(m_full_sound); + m_is_above_nitro_target = true; } else { @@ -373,6 +381,15 @@ void LocalPlayerController::collectedItem(const Item &item, int add_info, } } // collectedItem +//----------------------------------------------------------------------------- +/** If the nitro level has gone under the nitro goal, play a bad effect sound + */ +void LocalPlayerController::nitroNotFullSound() +{ + m_kart->playSound(m_unfull_sound); + m_is_above_nitro_target = false; +} //nitroNotFullSound + // ---------------------------------------------------------------------------- /** Returns true if the player of this controller can collect achievements. * At the moment only the current player can collect them. diff --git a/src/karts/controller/local_player_controller.hpp b/src/karts/controller/local_player_controller.hpp index 2e64e8c1d..c0dd9f787 100644 --- a/src/karts/controller/local_player_controller.hpp +++ b/src/karts/controller/local_player_controller.hpp @@ -55,9 +55,13 @@ private: SFXBuffer *m_ugh_sound; SFXBuffer *m_grab_sound; SFXBuffer *m_full_sound; + SFXBuffer *m_unfull_sound; + + bool m_is_above_nitro_target; virtual void steer(int, int) OVERRIDE; virtual void displayPenaltyWarning() OVERRIDE; + void nitroNotFullSound(); public: LocalPlayerController(AbstractKart *kart, const int local_player_id, diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 87df99f58..5cfa9cc1a 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -197,6 +197,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id, m_skid_sound = SFXManager::get()->createSoundSource( "skid" ); m_nitro_sound = SFXManager::get()->createSoundSource( "nitro" ); m_terrain_sound = NULL; + m_last_sound_material = NULL; m_previous_terrain_sound = NULL; } // Kart @@ -460,23 +461,20 @@ void Kart::setXYZ(const Vec3& a) // ----------------------------------------------------------------------------- void Kart::increaseMaxSpeed(unsigned int category, float add_speed, - float engine_force, float duration, - float fade_out_time) + float engine_force, int duration, + int fade_out_time) { m_max_speed->increaseMaxSpeed(category, add_speed, engine_force, - stk_config->time2Ticks(duration), - stk_config->time2Ticks(fade_out_time)); + duration, fade_out_time); } // increaseMaxSpeed // ----------------------------------------------------------------------------- void Kart::instantSpeedIncrease(unsigned int category, float add_max_speed, - float speed_boost, float engine_force, float duration, - float fade_out_time) + float speed_boost, float engine_force, + int duration, int fade_out_time) { m_max_speed->instantSpeedIncrease(category, add_max_speed, speed_boost, - engine_force, - stk_config->time2Ticks(duration), - stk_config->time2Ticks(fade_out_time) ); + engine_force, duration, fade_out_time); } // instantSpeedIncrease // ----------------------------------------------------------------------------- @@ -1205,7 +1203,8 @@ float Kart::getShieldTime() const // ------------------------------------------------------------------------ /** * Decreases the kart's shield time. - * \param t The time substracted from the shield timer. If t == 0.0f, the default amout of time is substracted. + * \param t The time substracted from the shield timer. If t == 0.0f, the + default amout of time is substracted. */ void Kart::decreaseShieldTime() { @@ -1586,7 +1585,6 @@ void Kart::update(int ticks) } body->setGravity(gravity); } // if !flying - handleMaterialSFX(material); if (material->isDriveReset() && isOnGround()) { new RescueAnimation(this); @@ -1780,7 +1778,7 @@ void Kart::setSquash(float time, float slowdown) //----------------------------------------------------------------------------- /** Plays any terrain specific sound effect. */ -void Kart::handleMaterialSFX(const Material *material) +void Kart::handleMaterialSFX() { // If a terrain specific sfx is already being played, when a new // terrain is entered, an old sfx should be finished (once, not @@ -1793,7 +1791,14 @@ void Kart::handleMaterialSFX(const Material *material) // FIXME: if there are already two sfx playing, don't add another // one. This should reduce the performance impact when driving // on the bridge in Cocoa. - if(getLastMaterial()!=material && !m_previous_terrain_sound) + const Material *material = m_terrain_info->getMaterial(); + + // We can not use getLastMaterial() since, since the last material might + // be updated several times during the physics updates, not indicating + // that we have reached a new material with regards to the sound effect. + // So we separately save the material last used for a sound effect and + // then use this for comparison. + if(m_last_sound_material!=material) { // First stop any previously playing terrain sound // and remove it, so that m_previous_terrain_sound @@ -1802,19 +1807,21 @@ void Kart::handleMaterialSFX(const Material *material) { m_previous_terrain_sound->deleteSFX(); } - m_previous_terrain_sound = m_terrain_sound; - if(m_previous_terrain_sound) - m_previous_terrain_sound->setLoop(false); - const std::string &s = material->getSFXName(); + // Disable looping for the current terrain sound, and + // make it the previous terrain sound. + if (m_terrain_sound) m_terrain_sound->setLoop(false); + m_previous_terrain_sound = m_terrain_sound; + + const std::string &sound_name = material ? material->getSFXName() : ""; // In multiplayer mode sounds are NOT positional, because we have // multiple listeners. This would make the sounds of all AIs be // audible at all times. So silence AI karts. - if (s.size()!=0 && (race_manager->getNumPlayers()==1 || - m_controller->isLocalPlayerController() ) ) + if (!sound_name.empty() && (race_manager->getNumPlayers()==1 || + m_controller->isLocalPlayerController() ) ) { - m_terrain_sound = SFXManager::get()->createSoundSource(s); + m_terrain_sound = SFXManager::get()->createSoundSource(sound_name); m_terrain_sound->play(); m_terrain_sound->setLoop(true); } @@ -1824,6 +1831,8 @@ void Kart::handleMaterialSFX(const Material *material) } } + // Check if a previous terrain sound (now not looped anymore) + // is finished and can be deleted. if(m_previous_terrain_sound && m_previous_terrain_sound->getStatus()==SFXBase::SFX_STOPPED) { @@ -1840,14 +1849,16 @@ void Kart::handleMaterialSFX(const Material *material) // terrain sound is not necessarily a looping sound so check its status before // setting its speed, to avoid 'ressuscitating' sounds that had already stopped - if(m_terrain_sound && main_loop->isLastSubstep() && - (m_terrain_sound->getStatus()==SFXBase::SFX_PLAYING || - m_terrain_sound->getStatus()==SFXBase::SFX_PAUSED)) + if(m_terrain_sound && + (m_terrain_sound->getStatus()==SFXBase::SFX_PLAYING || + m_terrain_sound->getStatus()==SFXBase::SFX_PAUSED) ) { m_terrain_sound->setPosition(getXYZ()); - material->setSFXSpeed(m_terrain_sound, m_speed, m_schedule_pause); + if(material) + material->setSFXSpeed(m_terrain_sound, m_speed, m_schedule_pause); } + m_last_sound_material = material; } // handleMaterialSFX //----------------------------------------------------------------------------- @@ -3041,7 +3052,7 @@ void Kart::updateGraphics(float dt) handleMaterialGFX(dt); updateEngineSFX(dt); - + handleMaterialSFX(); } // updateGraphics // ---------------------------------------------------------------------------- diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index e53d5b70c..7f4f7a87a 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -226,7 +226,12 @@ protected: static const int EMITTER_COUNT = 3; SFXBase *m_emitters[EMITTER_COUNT]; SFXBase *m_engine_sound; + /** Sound to be played depending on terrain. */ SFXBase *m_terrain_sound; + + /** The material for which the last sound effect was played. */ + const Material *m_last_sound_material; + SFXBase *m_nitro_sound; /** A pointer to the previous terrain sound needs to be saved so that an * 'older' sfx can be finished and an abrupt end of the sfx is avoided. */ @@ -244,7 +249,7 @@ protected: int m_min_nitro_ticks; void updatePhysics(int ticks); - void handleMaterialSFX(const Material *material); + void handleMaterialSFX(); void handleMaterialGFX(float dt); void updateFlying(); void updateSliding(); @@ -278,11 +283,11 @@ public: virtual void startEngineSFX (); virtual void adjustSpeed (float f); virtual void increaseMaxSpeed(unsigned int category, float add_speed, - float engine_force, float duration, - float fade_out_time); + float engine_force, int duration, + int fade_out_time) OVERRIDE; virtual void instantSpeedIncrease(unsigned int category, float add_max_speed, - float speed_boost, float engine_force, float duration, - float fade_out_time); + float speed_boost, float engine_force, + int duration, int fade_out_time) OVERRIDE; virtual void setSlowdown(unsigned int category, float max_speed_fraction, int fade_in_time); virtual int getSpeedIncreaseTicksLeft(unsigned int category) const; diff --git a/src/karts/kart_gfx.cpp b/src/karts/kart_gfx.cpp index d344d49e3..ac83547b9 100644 --- a/src/karts/kart_gfx.cpp +++ b/src/karts/kart_gfx.cpp @@ -78,7 +78,7 @@ KartGFX::KartGFX(const AbstractKart *kart, bool is_day) m_skidding_light_2 = irr_driver->addLight(core::vector3df(0.0f, 0.1f, -0.5f * length - 0.05f), /* force */0.4f, /*radius*/4.0f, - 1.0f, 0.0f, 0.0f, false, node); + 1.0f, 0.2f, 0.0f, false, node); m_skidding_light_2->setVisible(false); m_skidding_light_2->setName(("skidding emitter 2 (" + m_kart->getIdent() + ")").c_str() ); @@ -117,6 +117,8 @@ KartGFX::KartGFX(const AbstractKart *kart, bool is_day) addEffect(KGFX_SKID1R, "skid1.xml", rear_right, true ); addEffect(KGFX_SKID2L, "skid2.xml", rear_left, true ); addEffect(KGFX_SKID2R, "skid2.xml", rear_right, true ); + addEffect(KGFX_SKID0L, "skid0.xml", rear_left, true ); + addEffect(KGFX_SKID0R, "skid0.xml", rear_right, true ); if (!kart->getKartModel()->getExhaustXML().empty()) { const std::string& ex = kart->getKartModel()->getExhaustXML(); @@ -180,9 +182,9 @@ void KartGFX::addEffect(KartGFXType type, const std::string &file_name, kind = ParticleKindManager::get()->getParticles(file_name); //kind = new ParticleKind(file_manager->getGfxFile(file_name)); - // Skid2 is only used to store the emitter type, and a wheeless - // kart has no terrain effects. - if(type==KGFX_SKID2L || type==KGFX_SKID2R || + // Skid0 and Skid2 are only used to store the emitter type, and a + // wheeless kart has no terrain effects. + if(type==KGFX_SKID0L || type==KGFX_SKID0R || type==KGFX_SKID2L || type==KGFX_SKID2R || (type==KGFX_TERRAIN && m_kart->isWheeless()) ) emitter = NULL; else if(type==KGFX_TERRAIN) @@ -206,7 +208,9 @@ void KartGFX::addEffect(KartGFXType type, const std::string &file_name, } assert((int)m_all_emitters.size()==type); m_all_emitters.push_back(emitter); - if(type==KGFX_SKID1L || type==KGFX_SKID1R) + if (type==KGFX_SKID0L || type==KGFX_SKID0R) + m_skid_kind0 = kind; + else if(type==KGFX_SKID1L || type==KGFX_SKID1R) m_skid_kind1 = kind; else if (type==KGFX_SKID2L || type==KGFX_SKID2R) m_skid_kind2 = kind; @@ -234,15 +238,28 @@ void KartGFX::reset() // ---------------------------------------------------------------------------- /** Selects the correct skidding particle type depending on skid bonus level. - * \param level Must be 1 (accumulated enough for level 1 bonus) or 2 - * (accumulated enough for level 2 bonus). + * \param level Must be 0 (no bonus, showing tiny sparks), 1 (accumulated enough + * for level 1 bonus), or 2 (accumulated enough for level 2 bonus). */ void KartGFX::setSkidLevel(const unsigned int level) { - assert(level >= 1); + assert(level >= 0); assert(level <= 2); m_skid_level = level; - const ParticleKind *pk = level==1 ? m_skid_kind1 : m_skid_kind2; + const ParticleKind *pk; + if (level == 0) + { + pk = m_skid_kind0; + } + else if (level == 1) + { + pk = m_skid_kind1; + } + else + { + pk = m_skid_kind2; + } +// const ParticleKind *pk = level==1 ? m_skid_kind1 : m_skid_kind2; #ifndef SERVER_ONLY if(m_all_emitters[KGFX_SKID1L]) m_all_emitters[KGFX_SKID1L]->setParticleType(pk); diff --git a/src/karts/kart_gfx.hpp b/src/karts/kart_gfx.hpp index 016b35479..6515d07a5 100644 --- a/src/karts/kart_gfx.hpp +++ b/src/karts/kart_gfx.hpp @@ -40,9 +40,9 @@ class KartGFX { public: /** All particle effects supported by this object. - * Nitro, zipper, terrain, and skidding effects. Two different + * Nitro, zipper, terrain, and skidding effects. Three different * skid types are supported, but only one emitter node will be - * created. So KGFX_SKID1/2 store the two types, and KGFX_SKID + * created. So KGFX_SKID1/2/3 store the two types, and KGFX_SKID * = KGFX_SKID1 stores the actual emitter node. KGFX_COUNT * is the number of entries and must therefore be last. */ enum KartGFXType { KGFX_NITRO1=0, @@ -57,11 +57,16 @@ public: KGFX_SKID1R = KGFX_SKIDR, KGFX_SKID2L, KGFX_SKID2R, + KGFX_SKID0L, + KGFX_SKID0R, KGFX_EXHAUST1, KGFX_EXHAUST2, KGFX_COUNT}; private: + /** The particle kind for skidding bonus level 0. */ + const ParticleKind *m_skid_kind0; + /** The particle kind for skidding bonus level 1. */ const ParticleKind *m_skid_kind1; diff --git a/src/karts/skidding.cpp b/src/karts/skidding.cpp index becf2fdaa..221366499 100644 --- a/src/karts/skidding.cpp +++ b/src/karts/skidding.cpp @@ -87,8 +87,8 @@ void Skidding::reset() // ---------------------------------------------------------------------------- /** Save the skidding state of a kart. It only saves the important physics * values including m_remaining_jump_time (while this is mostly a graphical - * effect, ou ycan't skid while still doing a jump, so it does affect the - * staet), but not visual only values like m_visual_rotation. Similarly + * effect, you can't skid while still doing a jump, so it does affect the + * state), but not visual only values like m_visual_rotation. Similarly * m_real_steering is output of updateRewind() and will be recomputed every * frame when update() is called, and similar for m_skid_bonus_ready * \param buffer Buffer for the state information. @@ -429,8 +429,12 @@ void Skidding::update(int ticks, bool is_on_ground, float bonus_time, bonus_speed, bonus_force; unsigned int level = getSkidBonus(&bonus_time, &bonus_speed, &bonus_force); + + // Show tiny sparks if bonus not yet reached + if (level == 0 && m_remaining_jump_time <= 0.0f) + m_kart->getKartGFX()->setSkidLevel(level); // If at least level 1 bonus is reached, show appropriate gfx - if(level>0) + else if (level>=1) { m_skid_bonus_ready = true; m_kart->getKartGFX()->setSkidLevel(level); diff --git a/src/main_loop.hpp b/src/main_loop.hpp index f76dc9d91..574628a48 100644 --- a/src/main_loop.hpp +++ b/src/main_loop.hpp @@ -54,10 +54,6 @@ public: /** Returns true if STK is to be stoppe. */ bool isAborted() const { return m_abort; } // ------------------------------------------------------------------------ - /** Returns if this is the last substep. Used to reduce the amount - * of updates (e.g. to sfx position) to once per rendered frame. */ - bool isLastSubstep() const { return m_is_last_substep; } - // ------------------------------------------------------------------------ void setFrameBeforeLoadingWorld() { m_frame_before_loading_world = true; } }; // MainLoop diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 45bd45901..267cf5749 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -1315,8 +1315,7 @@ void World::unpause() //----------------------------------------------------------------------------- void World::escapePressed() { - if (!(NetworkConfig::get()->isNetworking() && - getPhase() < MUSIC_PHASE)) + if (NetworkConfig::get()->isNetworking() || getPhase() >= MUSIC_PHASE) new RacePausedDialog(0.8f, 0.6f); } // escapePressed diff --git a/src/states_screens/dialogs/race_paused_dialog.cpp b/src/states_screens/dialogs/race_paused_dialog.cpp index b5fd49f58..70241696a 100644 --- a/src/states_screens/dialogs/race_paused_dialog.cpp +++ b/src/states_screens/dialogs/race_paused_dialog.cpp @@ -25,6 +25,8 @@ #include "guiengine/scalable_font.hpp" #include "guiengine/widgets/icon_button_widget.hpp" #include "guiengine/widgets/ribbon_widget.hpp" +#include "karts/controller/controller.hpp" +#include "karts/kart.hpp" #include "input/input_manager.hpp" #include "io/file_manager.hpp" #include "modes/overworld.hpp" @@ -66,6 +68,18 @@ RacePausedDialog::RacePausedDialog(const float percentWidth, { music_manager->pauseMusic(); SFXManager::get()->pauseAll(); + for (unsigned i = 0; i < World::getWorld()->getNumKarts(); i++) + { + for (unsigned j = 0; j < PA_PAUSE_RACE; j++) + { + if (World::getWorld()->getKart(i)->isEliminated() || + !World::getWorld()->getKart(i)->getController() + ->isLocalPlayerController()) + break; + World::getWorld()->getKart(i)->getController() + ->action((PlayerAction)j, 0); + } + } } else {