From fc94c4f29a7ad245361b88194c3d37075f802c41 Mon Sep 17 00:00:00 2001 From: Wouters Dorian Date: Thu, 9 Jul 2015 02:40:43 +0200 Subject: [PATCH] Improve [item_drop] --- mods/item_drop/init.lua | 122 ++++++++++++++++++++------------ other_things/update_sources.txt | 2 + 2 files changed, 78 insertions(+), 46 deletions(-) diff --git a/mods/item_drop/init.lua b/mods/item_drop/init.lua index 63deb33a..f04ce33f 100755 --- a/mods/item_drop/init.lua +++ b/mods/item_drop/init.lua @@ -2,63 +2,93 @@ local enable_damage = minetest.setting_getbool("enable_damage") local creative_mode = minetest.setting_getbool("creative_mode") +-- Following edits by gravgun +-- Idea is to have a radius pickup range around the player, whatever the height +-- We need to have a radius that will at least contain 1 node distance at the player's feet +-- Using simple trigonometry, we get that we need a radius of +-- sqrt(pickup_range² + player_half_height²) +local pickup_range = 1.3 +local pickup_range_squared = pickup_range*pickup_range +local player_half_height = 0.9 +local scan_range = math.sqrt(player_half_height*player_half_height + pickup_range_squared) +-- Node drops are insta-pickup, everything else (player drops) are not +local delay_before_playerdrop_pickup = 2 +-- Time in which the node comes to the player +local pickup_duration = 0.2 +-- Little treshold so the items aren't already on the player's middle +local pickup_inv_duration = 1/pickup_duration-0.2 + minetest.register_globalstep(function(dtime) for _,player in ipairs(minetest.get_connected_players()) do if player:get_hp() > 0 or not enable_damage then local pos = player:getpos() + pos.y = pos.y + 0.9 local inv = player:get_inventory() - for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do - if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" then - if inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then - inv:add_item("main", ItemStack(object:get_luaentity().itemstring)) - if object:get_luaentity().itemstring ~= "" then - minetest.sound_play("item_drop_pickup", {pos = pos, gain = 0.5, max_hear_distance = 16}) + for _,object in ipairs(minetest.get_objects_inside_radius(pos, scan_range)) do + local luaEnt = object:get_luaentity() + if not object:is_player() and luaEnt and luaEnt.name == "__builtin:item" then + if not luaEnt.always_collect then + local ticky = luaEnt.item_drop_delay or delay_before_playerdrop_pickup + ticky = ticky - dtime + if ticky <= 0 then + luaEnt.always_collect = true + luaEnt.item_drop_delay = nil + else + luaEnt.item_drop_delay = ticky end - object:get_luaentity().itemstring = "" - object:remove() end - end - end + if luaEnt.always_collect and luaEnt.item_drop_nopickup == nil then + -- Point-line distance computation, heavily simplified since the wanted line, + -- being the player, is completely upright (no variation on X or Z) + local pos2 = object:getpos() + -- No sqrt, avoid useless computation + -- (just take the radius, compare it to the square of what you want) + -- Pos order doesn't really matter, we're squaring the result + -- (but don't change it, we use the cached values afterwards) + local dX = pos.x-pos2.x + local dZ = pos.z-pos2.z + local playerDistance = dX*dX+dZ*dZ + if playerDistance <= pickup_range_squared then + local itemStack = ItemStack(luaEnt.itemstring) + if inv and inv:room_for_item("main", itemStack) then + local pos1 = pos + pos1.y = pos1.y-player_half_height+0.5 + local vec = {x=dX, y=pos1.y-pos2.y, z=dZ} + vec.x = vec.x*pickup_inv_duration + vec.y = vec.y*pickup_inv_duration + vec.z = vec.z*pickup_inv_duration + object:setvelocity(vec) + luaEnt.physical_state = false + luaEnt.object:set_properties({ + physical = false + }) + -- Mark the object as already picking up + luaEnt.item_drop_nopickup = true - for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do - if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" then - if object:get_luaentity().always_collect then - if inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then - local pos1 = pos - pos1.y = pos1.y+0.2 - local pos2 = object:getpos() - local vec = {x=pos1.x-pos2.x, y=pos1.y-pos2.y, z=pos1.z-pos2.z} - vec.x = vec.x*3 - vec.y = vec.y*3 - vec.z = vec.z*3 - object:setvelocity(vec) - object:get_luaentity().physical_state = false - object:get_luaentity().object:set_properties({ - physical = false - }) - - minetest.after(1, function(args) - local lua = object:get_luaentity() - if object == nil or lua == nil or lua.itemstring == nil then - return - end - if inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then - inv:add_item("main", ItemStack(object:get_luaentity().itemstring)) - if object:get_luaentity().itemstring ~= "" then - minetest.sound_play("item_drop_pickup", {pos = pos, gain = 0.3, max_hear_distance = 16}) + minetest.after(pickup_duration, function(args) + local lua = luaEnt + if object == nil or lua == nil or lua.itemstring == nil then + return end - object:get_luaentity().itemstring = "" - object:remove() - else - object:setvelocity({x = 0,y = 0,z = 0}) - object:get_luaentity().physical_state = true - object:get_luaentity().object:set_properties({ - physical = true - }) - end - end, {player, object}) + if inv:room_for_item("main", itemStack) then + inv:add_item("main", itemStack) + if luaEnt.itemstring ~= "" then + minetest.sound_play("item_drop_pickup", {pos = pos, gain = 0.3, max_hear_distance = 8}) + end + luaEnt.itemstring = "" + object:remove() + else + object:setvelocity({x = 0,y = 0,z = 0}) + luaEnt.physical_state = true + luaEnt.object:set_properties({ + physical = true + }) + luaEnt.item_drop_nopickup = nil + end + end, {player, object}) + end end end end diff --git a/other_things/update_sources.txt b/other_things/update_sources.txt index c26549b7..7f0802c9 100755 --- a/other_things/update_sources.txt +++ b/other_things/update_sources.txt @@ -252,6 +252,8 @@ web: https://forum.minetest.net/viewtopic.php?id=5275 [Item drop] dir: item_drop git: http://github.com/PilzAdam/item_drop.git +mff-edit: Improved by gravgun (smooth pickup animation, cylinder radius) +mff-edit-fr: Amélioré par gravgun (animation de récup, rayon en cylindre) [Jukebox] dir: jukebox