Add slippery group for nodes (players/items slide)
authorWuzzy <almikes@aol.com>
Fri, 11 Aug 2017 19:16:09 +0000 (21:16 +0200)
committerparamat <mat.gregory@virginmedia.com>
Sun, 13 Aug 2017 20:39:08 +0000 (21:39 +0100)
builtin/game/item_entity.lua
doc/lua_api.txt
src/client.cpp
src/localplayer.cpp
src/localplayer.h

index c0e36be2d2b1ee275f859441683e7458d57803a8..c1e3061d2333ac88ab6901208fbf162f6cd3ae20 100644 (file)
@@ -99,8 +99,8 @@ core.register_entity(":__builtin:item", {
                        self.itemstring = staticdata
                end
                self.object:set_armor_groups({immortal = 1})
-               self.object:setvelocity({x = 0, y = 2, z = 0})
-               self.object:setacceleration({x = 0, y = -10, z = 0})
+               self.object:set_velocity({x = 0, y = 2, z = 0})
+               self.object:set_acceleration({x = 0, y = -10, z = 0})
                self:set_item(self.itemstring)
        end,
 
@@ -177,8 +177,8 @@ core.register_entity(":__builtin:item", {
                local in_unloaded = (node == nil)
                if in_unloaded then
                        -- Don't infinetly fall into unloaded map
-                       self.object:setvelocity({x = 0, y = 0, z = 0})
-                       self.object:setacceleration({x = 0, y = 0, z = 0})
+                       self.object:set_velocity({x = 0, y = 0, z = 0})
+                       self.object:set_acceleration({x = 0, y = 0, z = 0})
                        self.physical_state = false
                        self.object:set_properties({physical = false})
                        return
@@ -186,7 +186,8 @@ core.register_entity(":__builtin:item", {
                local nn = node.name
                -- If node is not registered or node is walkably solid and resting on nodebox
                local v = self.object:getvelocity()
-               if not core.registered_nodes[nn] or core.registered_nodes[nn].walkable and v.y == 0 then
+               if not core.registered_nodes[nn] or (core.registered_nodes[nn].walkable and
+                               core.get_item_group(nn, "slippery") == 0) and v.y == 0 then
                        if self.physical_state then
                                local own_stack = ItemStack(self.object:get_luaentity().itemstring)
                                -- Merge with close entities of the same item
@@ -199,17 +200,28 @@ core.register_entity(":__builtin:item", {
                                                end
                                        end
                                end
-                               self.object:setvelocity({x = 0, y = 0, z = 0})
-                               self.object:setacceleration({x = 0, y = 0, z = 0})
+                               self.object:set_velocity({x = 0, y = 0, z = 0})
+                               self.object:set_acceleration({x = 0, y = 0, z = 0})
                                self.physical_state = false
                                self.object:set_properties({physical = false})
                        end
                else
                        if not self.physical_state then
-                               self.object:setvelocity({x = 0, y = 0, z = 0})
-                               self.object:setacceleration({x = 0, y = -10, z = 0})
+                               self.object:set_velocity({x = 0, y = 0, z = 0})
+                               self.object:set_acceleration({x = 0, y = -10, z = 0})
                                self.physical_state = true
                                self.object:set_properties({physical = true})
+                       elseif minetest.get_item_group(nn, "slippery") ~= 0 then
+                               if math.abs(v.x) < 0.2 and math.abs(v.z) < 0.2 then
+                                       self.object:set_velocity({x = 0, y = 0, z = 0})
+                                       self.object:set_acceleration({x = 0, y = 0, z = 0})
+                                       self.physical_state = false
+                                       self.object:set_properties({
+                                               physical = false
+                                       })
+                               else
+                                       self.object:set_acceleration({x = -v.x, y = -10, z = -v.z})
+                               end
                        end
                end
        end,
index b5ab30d58c7387972c1133a68bb788af270d78f2..66f8ccb2520230680355c7a03faaec4f9b7e4155 100644 (file)
@@ -1424,6 +1424,9 @@ Another example: Make red wool from white wool and red dye:
 * `soil`: saplings will grow on nodes in this group
 * `connect_to_raillike`: makes nodes of raillike drawtype with same group value
   connect to each other
+* `slippery`: Players and items will slide on the node.
+  Only use `slippery = 3` for now to ensure forwards compatibility.
+
 
 ### Known damage and digging time defining groups
 * `crumbly`: dirt, sand
index 39bb1e2ff7526809a01f8f5a9d6a008068c1a00a..f7834a02b46117ad030ebe1b6a11572b6980a45f 100644 (file)
@@ -403,7 +403,7 @@ void Client::step(float dtime)
        // Control local player (0ms)
        LocalPlayer *player = m_env.getLocalPlayer();
        assert(player);
-       player->applyControl(dtime);
+       player->applyControl(dtime, &m_env);
 
        // Step environment
        m_env.step(dtime);
index f04be07d69ce9a533ca2e72bf4d0383c7784cf44..f72da1b1807410427dd8f02380df18e9dc4350c1 100644 (file)
@@ -444,7 +444,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d)
        move(dtime, env, pos_max_d, NULL);
 }
 
-void LocalPlayer::applyControl(float dtime)
+void LocalPlayer::applyControl(float dtime, ClientEnvironment *env)
 {
        // Clear stuff
        swimming_vertical = false;
@@ -660,9 +660,16 @@ void LocalPlayer::applyControl(float dtime)
        else
                incH = incV = movement_acceleration_default * BS * dtime;
 
+       INodeDefManager *nodemgr = env->getGameDef()->ndef();
+       Map *map = &env->getMap();
+       bool slippery = false;
+       const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos()));
+       slippery = itemgroup_get(f.groups, "slippery");
        // Accelerate to target speed with maximum increment
-       accelerateHorizontal(speedH * physics_override_speed, incH * physics_override_speed);
-       accelerateVertical(speedV * physics_override_speed, incV * physics_override_speed);
+       accelerateHorizontal(speedH * physics_override_speed,
+                       incH * physics_override_speed, slippery);
+       accelerateVertical(speedV * physics_override_speed,
+                       incV * physics_override_speed);
 }
 
 v3s16 LocalPlayer::getStandingNodePos()
@@ -699,12 +706,20 @@ v3f LocalPlayer::getEyeOffset() const
 }
 
 // Horizontal acceleration (X and Z), Y direction is ignored
-void LocalPlayer::accelerateHorizontal(const v3f &target_speed, const f32 max_increase)
+void LocalPlayer::accelerateHorizontal(const v3f &target_speed,
+       const f32 max_increase, bool slippery)
 {
         if (max_increase == 0)
                 return;
 
-        v3f d_wanted = target_speed - m_speed;
+       v3f d_wanted = target_speed - m_speed;
+       if (slippery) {
+               if (target_speed == v3f(0))
+                       d_wanted = -m_speed * 0.05f;
+               else
+                       d_wanted = target_speed * 0.1f - m_speed * 0.1f;
+       }
+
         d_wanted.Y = 0;
         f32 dl = d_wanted.getLength();
         if (dl > max_increase)
index 9f7e921286eb6a850b22078830f75e3ca9da633c..67b22b65636eecc1f3d1eef96c9c356ff513000a 100644 (file)
@@ -29,6 +29,7 @@ class Client;
 class Environment;
 class GenericCAO;
 class ClientActiveObject;
+class ClientEnvironment;
 class IGameDef;
 
 enum LocalPlayerAnimations
@@ -78,7 +79,7 @@ public:
        void old_move(f32 dtime, Environment *env, f32 pos_max_d,
                        std::vector<CollisionInfo> *collision_info);
 
-       void applyControl(float dtime);
+       void applyControl(float dtime, ClientEnvironment *env);
 
        v3s16 getStandingNodePos();
        v3s16 getFootstepNodePos();
@@ -143,7 +144,8 @@ public:
        void setCollisionbox(const aabb3f &box) { m_collisionbox = box; }
 
 private:
-       void accelerateHorizontal(const v3f &target_speed, const f32 max_increase);
+       void accelerateHorizontal(const v3f &target_speed,
+               const f32 max_increase, bool slippery);
        void accelerateVertical(const v3f &target_speed, const f32 max_increase);
        bool updateSneakNode(Map *map, const v3f &position, const v3f &sneak_max);