diff --git a/data/gui/karts.stkgui b/data/gui/karts.stkgui
index 03c349e27..5e55e1235 100644
--- a/data/gui/karts.stkgui
+++ b/data/gui/karts.stkgui
@@ -10,6 +10,8 @@
         <placeholder id="playerskarts" width="100%" align="center" proportion="4">
             <!-- Contents is added programatically -->
         </placeholder>
+        <placeholder id="perPlayerDifficulty" width="100%" align="center" proportion="0">
+        </placeholder>
 
         <spacer height="15" width="25"/>
 
diff --git a/src/graphics/slip_stream.cpp b/src/graphics/slip_stream.cpp
index b662e8d92..e5c6c3941 100644
--- a/src/graphics/slip_stream.cpp
+++ b/src/graphics/slip_stream.cpp
@@ -69,9 +69,11 @@ SlipStream::SlipStream(AbstractKart* kart) : MovingTexture(0, 0), m_kart(kart)
     setTextureMatrix(&(m_node->getMaterial(0).getTextureMatrix(0)));
     m_slipstream_time      = 0.0f;
 
-    float length = m_kart->getKartProperties()->getSlipstreamLength();
+    float length = m_kart->getKartProperties()->getSlipstreamLength() *
+	               m_kart->getPlayerDifficulty()->getSlipstreamLength();
     float kw     = m_kart->getKartWidth();
-    float ew     = m_kart->getKartProperties()->getSlipstreamWidth();
+    float ew     = m_kart->getKartProperties()->getSlipstreamWidth() *
+	               m_kart->getPlayerDifficulty()->getSlipstreamWidth();
     float kl     = m_kart->getKartLength();
 
     Vec3 p[4];
@@ -299,7 +301,8 @@ void SlipStream::setIntensity(float f, const AbstractKart *kart)
 bool SlipStream::isSlipstreamReady() const
 {
     return m_slipstream_time>
-        m_kart->getKartProperties()->getSlipstreamCollectTime();
+        m_kart->getKartProperties()->getSlipstreamCollectTime() *
+        m_kart->getPlayerDifficulty()->getSlipstreamCollectTime();
 }   // isSlipstreamReady
 
 //-----------------------------------------------------------------------------
@@ -315,10 +318,14 @@ void SlipStream::updateSlipstreamPower()
         setIntensity(2.0f, NULL);
         const KartProperties *kp=m_kart->getKartProperties();
         m_kart->increaseMaxSpeed(MaxSpeed::MS_INCREASE_SLIPSTREAM,
-                                kp->getSlipstreamMaxSpeedIncrease(),
-                                kp->getSlipstreamAddPower(),
-                                kp->getSlipstreamDuration(),
-                                kp->getSlipstreamFadeOutTime()       );
+                                kp->getSlipstreamMaxSpeedIncrease() *
+                                m_kart->getPlayerDifficulty()->getSlipstreamMaxSpeedIncrease(),
+                                kp->getSlipstreamAddPower() *
+                                m_kart->getPlayerDifficulty()->getSlipstreamAddPower(),
+                                kp->getSlipstreamDuration() *
+                                m_kart->getPlayerDifficulty()->getSlipstreamDuration(),
+                                kp->getSlipstreamFadeOutTime() *
+                                m_kart->getPlayerDifficulty()->getSlipstreamFadeOutTime());
     }
 }   // upateSlipstreamPower
 
@@ -372,7 +379,8 @@ void SlipStream::update(float dt)
     // not moving. This is useful for debugging the graphics of SS-ing.
 #undef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
 #ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
-    if(m_kart->getSpeed()<m_kart->getKartProperties()->getSlipstreamMinSpeed())
+    if(m_kart->getSpeed()<m_kart->getKartProperties()->getSlipstreamMinSpeed() *
+		                  m_kart->getPlayerDifficulty()->getSlipstreamMinSpeed())
     {
         setIntensity(0, NULL);
         m_slipstream_mode = SS_NONE;
@@ -414,7 +422,8 @@ void SlipStream::update(float dt)
         // give karts different slipstream properties.
 #ifndef DISPLAY_SLIPSTREAM_WITH_0_SPEED_FOR_DEBUGGING
         if(m_target_kart->getSpeed() <
-            m_kart->getKartProperties()->getSlipstreamMinSpeed())
+            m_kart->getKartProperties()->getSlipstreamMinSpeed() *
+            m_kart->getPlayerDifficulty()->getSlipstreamMinSpeed())
         {
             if(UserConfigParams::m_slipstream_debug &&
                 m_kart->getController()->isPlayerController())
@@ -428,7 +437,8 @@ void SlipStream::update(float dt)
         // slipstream length+0.5*kart_length()+0.5*target_kart_length
         // away from the other kart
         Vec3 delta = m_kart->getXYZ() - m_target_kart->getXYZ();
-        float l    = m_target_kart->getKartProperties()->getSlipstreamLength()
+        float l    = m_kart->getKartProperties()->getSlipstreamLength() *
+	                 m_kart->getPlayerDifficulty()->getSlipstreamLength()
                    + 0.5f*( m_target_kart->getKartLength()
                            +m_kart->getKartLength()        );
         if(delta.length2_2d() > l*l)
@@ -469,7 +479,8 @@ void SlipStream::update(float dt)
                 m_slipstream_mode = SS_USE;
                 m_kart->handleZipper();
                 m_slipstream_time =
-                    m_kart->getKartProperties()->getSlipstreamCollectTime();
+                    m_kart->getKartProperties()->getSlipstreamCollectTime() *
+                    m_kart->getPlayerDifficulty()->getSlipstreamCollectTime();
                 return;
             }
         }
@@ -490,7 +501,8 @@ void SlipStream::update(float dt)
     setIntensity(m_slipstream_time, m_target_kart);
 
     m_slipstream_mode = SS_COLLECT;
-    if(m_slipstream_time>m_kart->getKartProperties()->getSlipstreamCollectTime())
+    if(m_slipstream_time>m_kart->getKartProperties()->getSlipstreamCollectTime() *
+		                 m_kart->getPlayerDifficulty()->getSlipstreamCollectTime())
     {
         setIntensity(1.0f, m_target_kart);
     }
diff --git a/src/guiengine/widgets/player_kart_widget.cpp b/src/guiengine/widgets/player_kart_widget.cpp
index 6ad0c716f..f6429e4fc 100644
--- a/src/guiengine/widgets/player_kart_widget.cpp
+++ b/src/guiengine/widgets/player_kart_widget.cpp
@@ -29,6 +29,7 @@
 #include <IGUIEnvironment.h>
 
 static int g_root_id;
+static int g_root_id2;
 static const char RANDOM_KART_ID[] = "randomkart";
 
 using namespace GUIEngine;
@@ -125,6 +126,7 @@ PlayerKartWidget::PlayerKartWidget(KartSelectionScreen* parent,
     if (irrlicht_widget_id == -1)
     {
         m_player_ident_spinner->m_tab_down_root = g_root_id;
+        m_difficulty->m_tab_down_root = g_root_id2;
     }
 
     spinnerID = StringUtils::insertValues("@p%i_spinner", m_player_id);
diff --git a/src/items/attachment.cpp b/src/items/attachment.cpp
index 804c84d5c..aefde5318 100644
--- a/src/items/attachment.cpp
+++ b/src/items/attachment.cpp
@@ -83,7 +83,7 @@ Attachment::~Attachment()
         sfx_manager->deleteSFX(m_bomb_sound);
         m_bomb_sound = NULL;
     }
-    
+
     if (m_bubble_explode_sound)
     {
         sfx_manager->deleteSFX(m_bubble_explode_sound);
@@ -125,7 +125,7 @@ void Attachment::set(AttachmentType type, float time,
 
     clear();
     m_node_scale = 0.3f;
-    
+
     // If necessary create the appropriate plugin which encapsulates
     // the associated behavior
     switch(type)
@@ -267,7 +267,8 @@ void Attachment::hitBanana(Item *item, int new_attachment)
         // same banana again once the explosion animation is finished, giving
         // the kart the same penalty twice.
         float f = std::max(item->getDisableTime(),
-                         m_kart->getKartProperties()->getExplosionTime()+2.0f);
+                         m_kart->getKartProperties()->getExplosionTime() *
+                         m_kart->getPlayerDifficulty()->getExplosionTime() + 2.0f);
         item->setDisableTime(f);
         break;
         }
@@ -330,7 +331,7 @@ void Attachment::hitBanana(Item *item, int new_attachment)
 void Attachment::handleCollisionWithKart(AbstractKart *other)
 {
     Attachment *attachment_other=other->getAttachment();
-    
+
     if(getType()==Attachment::ATTACH_BOMB)
     {
         // Don't attach a bomb when the kart is shielded
@@ -387,11 +388,11 @@ void Attachment::update(float dt)
 {
     if(m_type==ATTACH_NOTHING) return;
     m_time_left -=dt;
-    
-    
+
+
     bool is_shield = (m_type == ATTACH_BUBBLEGUM_SHIELD|| m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD);
     float m_wanted_node_scale = is_shield ? std::max(1.0f, m_kart->getHighestPoint()*1.1f) : 1.0f;
-    
+
     if (m_node_scale < m_wanted_node_scale)
     {
         m_node_scale += dt*1.5f;
@@ -478,7 +479,7 @@ void Attachment::update(float dt)
             m_bubble_explode_sound = sfx_manager->createSoundSource("bubblegum_explode");
             m_bubble_explode_sound->position(m_kart->getXYZ());
             m_bubble_explode_sound->play();
-            
+
             // drop a small bubble gum
             Vec3 hit_point;
             Vec3 normal;
@@ -495,7 +496,7 @@ void Attachment::update(float dt)
                 normal.normalize();
 
                 pos.setY(hit_point.getY()-0.05f);
-                
+
                 ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, normal, m_kart);
             }
         }
diff --git a/src/items/plunger.cpp b/src/items/plunger.cpp
index 1ef5a6104..7853117d7 100644
--- a/src/items/plunger.cpp
+++ b/src/items/plunger.cpp
@@ -158,7 +158,7 @@ bool Plunger::updateAndDelete(float dt)
 bool Plunger::hit(AbstractKart *kart, PhysicalObject *obj)
 {
     if(isOwnerImmunity(kart)) return false;
-    
+
     // pulling back makes no sense in battle mode, since this mode is not a race.
     // so in battle mode, always hide view
     if( m_reverse_mode || race_manager->isBattleMode() )
@@ -177,7 +177,8 @@ bool Plunger::hit(AbstractKart *kart, PhysicalObject *obj)
     }
     else
     {
-        m_keep_alive = m_owner->getKartProperties()->getRubberBandDuration();
+        m_keep_alive = m_owner->getKartProperties()->getRubberBandDuration() *
+	                   m_owner->getPlayerDifficulty()->getRubberBandDuration();
 
         // Make this object invisible by placing it faaar down. Not that if this
         // objects is simply removed from the scene graph, it might be auto-deleted
diff --git a/src/items/powerup.cpp b/src/items/powerup.cpp
index e355d5c90..28299f2c4 100644
--- a/src/items/powerup.cpp
+++ b/src/items/powerup.cpp
@@ -224,7 +224,8 @@ void Powerup::use()
     case PowerupManager::POWERUP_SWATTER:
         m_owner->getAttachment()
                 ->set(Attachment::ATTACH_SWATTER,
-                      m_owner->getKartProperties()->getSwatterDuration());
+                      m_owner->getKartProperties()->getSwatterDuration() *
+                      m_owner->getPlayerDifficulty()->getSwatterDuration());
         break;
 
     case PowerupManager::POWERUP_BUBBLEGUM:
diff --git a/src/items/rubber_band.cpp b/src/items/rubber_band.cpp
index d978c3926..eab386f66 100644
--- a/src/items/rubber_band.cpp
+++ b/src/items/rubber_band.cpp
@@ -146,7 +146,8 @@ void RubberBand::update(float dt)
     // Check for rubber band snapping
     // ------------------------------
     float l = (m_end_position-k).length2();
-    float max_len = m_owner->getKartProperties()->getRubberBandMaxLength();
+    float max_len = m_owner->getKartProperties()->getRubberBandMaxLength() *
+	                m_owner->getPlayerDifficulty()->getRubberBandMaxLength();
     if(l>max_len*max_len)
     {
         // Rubber band snaps
@@ -159,7 +160,8 @@ void RubberBand::update(float dt)
     // ----------------------------
     if(m_attached_state!=RB_TO_PLUNGER)
     {
-        float force = m_owner->getKartProperties()->getRubberBandForce();
+        float force = m_owner->getKartProperties()->getRubberBandForce() *
+	                  m_owner->getPlayerDifficulty()->getRubberBandForce();
         Vec3 diff   = m_end_position-k;
 
         // detach rubber band if kart gets very close to hit point
@@ -175,10 +177,12 @@ void RubberBand::update(float dt)
         diff.normalize();   // diff can't be zero here
         m_owner->getBody()->applyCentralForce(diff*force);
         m_owner->increaseMaxSpeed(MaxSpeed::MS_INCREASE_RUBBER,
-            m_owner->getKartProperties()->getRubberBandSpeedIncrease(),
+            m_owner->getKartProperties()->getRubberBandSpeedIncrease() *
+            m_owner->getPlayerDifficulty()->getRubberBandSpeedIncrease(),
             /*engine_force*/ 0.0f,
             /*duration*/0.1f,
-            m_owner->getKartProperties()->getRubberBandFadeOutTime());
+            m_owner->getKartProperties()->getRubberBandFadeOutTime() *
+            m_owner->getPlayerDifficulty()->getRubberBandFadeOutTime());
         if(m_attached_state==RB_TO_KART)
             m_hit_kart->getBody()->applyCentralForce(diff*(-force));
     }
diff --git a/src/items/swatter.cpp b/src/items/swatter.cpp
index a9450bd50..92b64d552 100644
--- a/src/items/swatter.cpp
+++ b/src/items/swatter.cpp
@@ -293,7 +293,8 @@ void Swatter::squashThingsAround()
 
         if(dist2 >= min_dist2) continue;   // too far away, ignore this kart
 
-        kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown());
+        kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(),
+		    kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown());
 
         if (kart->getAttachment()->getType()==Attachment::ATTACH_BOMB)
         {   // make bomb explode
diff --git a/src/karts/explosion_animation.cpp b/src/karts/explosion_animation.cpp
index 53cb0e198..1b45912ff 100644
--- a/src/karts/explosion_animation.cpp
+++ b/src/karts/explosion_animation.cpp
@@ -39,7 +39,7 @@ ExplosionAnimation *ExplosionAnimation::create(AbstractKart *kart,
                                                bool direct_hit)
 {
     if(kart->isInvulnerable()) return NULL;
-    
+
     float r = kart->getKartProperties()->getExplosionRadius();
 
     // Ignore explosion that are too far away.
@@ -78,7 +78,8 @@ ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
     m_xyz = m_kart->getXYZ();
     m_orig_y = m_xyz.getY();
     m_kart->playCustomSFX(SFXManager::CUSTOM_EXPLODE);
-    m_timer     = m_kart->getKartProperties()->getExplosionTime();
+    m_timer = m_kart->getKartProperties()->getExplosionTime() *
+	          m_kart->getPlayerDifficulty()->getExplosionTime();
 
     // Non-direct hits will be only affected half as much.
     if(!direct_hit) m_timer*=0.5f;
@@ -105,7 +106,8 @@ ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
     m_add_rotation.setRoll(    (rand()%(2*max_rotation+1)-max_rotation)*f );
 
     // Set invulnerable time, and graphical effects
-    float t = m_kart->getKartProperties()->getExplosionInvulnerabilityTime();
+    float t = m_kart->getKartProperties()->getExplosionInvulnerabilityTime() *
+	          m_kart->getPlayerDifficulty()->getExplosionInvulnerabilityTime();
     m_kart->setInvulnerableTime(t);
     if ( UserConfigParams::m_graphical_effects )
     {
diff --git a/src/karts/kart_gfx.cpp b/src/karts/kart_gfx.cpp
index 42a5c94f6..a4efea30b 100644
--- a/src/karts/kart_gfx.cpp
+++ b/src/karts/kart_gfx.cpp
@@ -49,7 +49,7 @@ KartGFX::KartGFX(const AbstractKart *kart)
 
     Vec3 rear_center(0, kart->getKartHeight()*0.35f,
                        -kart->getKartLength()*0.35f);
-                       
+
     Vec3 rear_nitro_center(0, kart->getKartHeight()*0.2f,
                        -kart->getKartLength()*0.1f);
 
@@ -275,7 +275,8 @@ void KartGFX::updateTerrain(const ParticleKind *pk)
     if (skidding > 1.0f && on_ground)
         rate = fabsf(m_kart->getControls().m_steer) > 0.8 ? skidding - 1 : 0;
     else if (speed >= 0.5f && on_ground)
-        rate = speed/m_kart->getKartProperties()->getMaxSpeed();
+        rate = speed/m_kart->getKartProperties()->getMaxSpeed() *
+	           m_kart->getPlayerDifficulty()->getMaxSpeed();
     else
     {
         pe->setCreationRateAbsolute(0);
diff --git a/src/karts/max_speed.cpp b/src/karts/max_speed.cpp
index f3643c600..911080616 100644
--- a/src/karts/max_speed.cpp
+++ b/src/karts/max_speed.cpp
@@ -60,7 +60,8 @@ MaxSpeed::MaxSpeed(AbstractKart *kart)
  */
 void MaxSpeed::reset()
 {
-    m_current_max_speed = m_kart->getKartProperties()->getMaxSpeed();
+    m_current_max_speed = m_kart->getKartProperties()->getMaxSpeed() *
+	                      m_kart->getPlayerDifficulty()->getMaxSpeed();
     m_min_speed         = -1.0f;
 
     for(unsigned int i=MS_DECREASE_MIN; i<MS_DECREASE_MAX; i++)
@@ -240,7 +241,8 @@ void MaxSpeed::update(float dt)
     }
 
     m_add_engine_force  = 0;
-    m_current_max_speed = m_kart->getKartProperties()->getMaxSpeed();
+    m_current_max_speed = m_kart->getKartProperties()->getMaxSpeed() *
+	                      m_kart->getPlayerDifficulty()->getMaxSpeed();
 
     // Then add the speed increase from each category
     // ----------------------------------------------
diff --git a/src/karts/player_difficulty.hpp b/src/karts/player_difficulty.hpp
index 03b33d8bf..6a43f9993 100644
--- a/src/karts/player_difficulty.hpp
+++ b/src/karts/player_difficulty.hpp
@@ -179,10 +179,6 @@ public:
     /** Returns the maximum speed dependent on the difficult level. */
     float getMaxSpeed               () const { return m_max_speed;            }
 
-    // ------------------------------------------------------------------------
-    /** Return the absolute maximum speed, independent on the difficulty. */
-    float getAbsMaxSpeed            () const { return m_max_speed;            }
-
     // ------------------------------------------------------------------------
     /** Returns the nitro consumption. */
     float getNitroConsumption       () const {return m_nitro_consumption;     }
diff --git a/src/karts/rescue_animation.cpp b/src/karts/rescue_animation.cpp
index 62330f421..749ec5382 100644
--- a/src/karts/rescue_animation.cpp
+++ b/src/karts/rescue_animation.cpp
@@ -39,7 +39,8 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
 {
     m_referee     = new Referee(*m_kart);
     m_kart->getNode()->addChild(m_referee->getSceneNode());
-    m_timer       = m_kart->getKartProperties()->getRescueTime();
+    m_timer       = m_kart->getKartProperties()->getRescueTime() *
+	                m_kart->getPlayerDifficulty()->getRescueTime();
     m_velocity    = m_kart->getKartProperties()->getRescueHeight() / m_timer;
     m_xyz         = m_kart->getXYZ();
 
diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp
index b1d9c2c71..dadf3f6a1 100644
--- a/src/physics/physics.cpp
+++ b/src/physics/physics.cpp
@@ -189,7 +189,8 @@ void Physics::update(float dt)
             {
                 AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                 const KartProperties* kp = kart->getKartProperties();
-                kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown());
+                kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(),
+		            kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown());
             }
             else if(obj->isSoccerBall())
             {
@@ -218,7 +219,8 @@ void Physics::update(float dt)
             {
                 AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                 const KartProperties* kp = kart->getKartProperties();
-                kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown());
+                kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(),
+		            kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown());
             }
             continue;
 
diff --git a/src/states_screens/kart_selection.cpp b/src/states_screens/kart_selection.cpp
index 7f2b6279c..4e551ec43 100644
--- a/src/states_screens/kart_selection.cpp
+++ b/src/states_screens/kart_selection.cpp
@@ -54,6 +54,7 @@ static const char ID_LOCKED[] = "locked/";
 KartSelectionScreen* KartSelectionScreen::m_instance_ptr = NULL;
 
 static int g_root_id;
+static int g_root_id2;
 
 /** Currently, navigation for multiple players at the same time is implemented
     in a somewhat clunky way. An invisible "dispatcher" widget is added above
@@ -338,13 +339,16 @@ void KartSelectionScreen::init()
 
     Widget* placeholder = getWidget("playerskarts");
     assert(placeholder != NULL);
+    Widget* placeholder2 = getWidget("perPlayerDifficulty");
+    assert(placeholder2 != NULL);
 
     // FIXME : The reserved id value is -1 when we switch from KSS to NKSS and vice-versa
 
     g_dispatcher->setRootID(placeholder->m_reserved_id);
-    g_dispatcher2->setRootID(placeholder->m_reserved_id);
+    g_dispatcher2->setRootID(placeholder2->m_reserved_id);
 
     g_root_id = placeholder->m_reserved_id;
+    g_root_id2 = placeholder2->m_reserved_id;
     if (!m_widgets.contains(g_dispatcher))
     {
         m_widgets.push_back(g_dispatcher);