Page 1 of 1

How to determine the pick being used?

PostPosted: Tue May 28, 2013 20:52
by cypher-neo
So, I had this idea which I'd like to code into something playable.
Here's my idea: Better drops when you use better (or more efficient picks). So a wood pick will only ever drop 1 block, but better picks have higher chances of dropping multiples...

I figured I would have to program this individually into each block type. So it would probably look something like:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_node("default:stone", {
    description = "Stone",
    tiles = {"default_stone.png"},
    is_ground_content = true,
    groups = {cracky=3, stone=1},
    drop = {
        max_items = 1,
        items = {
                         if wood.pick then { items = {'default:cobble 1}, rarity = 1 },
                         elseif stone.pick then { items = {'default:cobble 1}, rarity = 2 },
                                 { items = {'default:cobble 2}, rarity = 2 },
                         elseif bronze.pick then { items = {'default:cobble 1}, rarity = 2 },
                                 { items = {'default:cobble 2}, rarity = 2 }
                                 { items = {'default:cobble 3}, rarity = 3 }, etc etc etc
            }
    },
    legacy_mineral = true,
    sounds = default.node_sound_stone_defaults(),
})


My issue is, I don't know how to get the type of pick wielded by the player in LUA, nor am I 100% clear on how to make a variable call there. Any help?

PostPosted: Tue May 28, 2013 21:20
by PilzAdam
You could use the max_drop_level that is defined in the groupcaps. It has no other use.

PostPosted: Tue May 28, 2013 22:21
by RealBadAngel
check the player who dug it and his wielded item
you can use for example after_dig_node = func(pos, oldnode, oldmetadata, digger),
so player with get one cobble by now already, then you can check for wielded tool and add some more

methods to get wielded item:
https://github.com/minetest/minetest/blob/master/doc/lua_api.txt#L1343

PostPosted: Tue May 28, 2013 22:44
by cypher-neo
PilzAdam wrote:You could use the max_drop_level that is defined in the groupcaps. It has no other use.


I guess I've never understood what max_drop_level does either. Could you provide a snippet of code to explain how to use it in this instance?

PostPosted: Tue May 28, 2013 23:09
by PilzAdam
cypher-neo wrote:
PilzAdam wrote:You could use the max_drop_level that is defined in the groupcaps. It has no other use.


I guess I've never understood what max_drop_level does either. Could you provide a snippet of code to explain how to use it in this instance?

Assume we have the itemstack of the tool being used:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local level = itemstack:get_tool_capabilities().max_drop_level
if level == 0 then
-- drop stuff for stone and wooden pick
elseif level == 1 then
-- drop stuff for steel and copper pick
elseif level == 2 then
-- not used in default picks
elseif level >= 3 then
-- drop stuff for mese and diamond pick
end

PostPosted: Tue May 28, 2013 23:09
by cypher-neo
cypher-neo wrote:
PilzAdam wrote:You could use the max_drop_level that is defined in the groupcaps. It has no other use.


I guess I've never understood what max_drop_level does either. Could you provide a snippet of code to explain how to use it in this instance?


So how would I call that?

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
drop = {
        max_items = 1,
        items = {
                         { items = {'default:cobble {max_drop_level}}, rarity = 1 },
            }
    },

PostPosted: Tue May 28, 2013 23:10
by cypher-neo
PilzAdam wrote:
cypher-neo wrote:
PilzAdam wrote:You could use the max_drop_level that is defined in the groupcaps. It has no other use.


I guess I've never understood what max_drop_level does either. Could you provide a snippet of code to explain how to use it in this instance?

Assume we have the itemstack of the tool being used:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local level = itemstack:get_tool_capabilities().max_drop_level
if level == 0 then
-- drop stuff for stone and wooden pick
elseif level == 1 then
-- drop stuff for steel and copper pick
elseif level == 2 then
-- not used in default picks
elseif level >= 3 then
-- drop stuff for mese and diamond pick
end


Thanks Pilz! Learned something new in LUA today.

PostPosted: Tue May 28, 2013 23:11
by PilzAdam
cypher-neo wrote:
PilzAdam wrote:
cypher-neo wrote:
I guess I've never understood what max_drop_level does either. Could you provide a snippet of code to explain how to use it in this instance?

Assume we have the itemstack of the tool being used:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local level = itemstack:get_tool_capabilities().max_drop_level
if level == 0 then
-- drop stuff for stone and wooden pick
elseif level == 1 then
-- drop stuff for steel and copper pick
elseif level == 2 then
-- not used in default picks
elseif level >= 3 then
-- drop stuff for mese and diamond pick
end


Thanks Pilz! Learned something new in LUA today.

Note that this code is best in after_dig_node.

PostPosted: Tue May 28, 2013 23:25
by cypher-neo
PilzAdam wrote:Assume we have the itemstack of the tool being used:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local level = itemstack:get_tool_capabilities().max_drop_level
if level == 0 then
-- drop stuff for stone and wooden pick
elseif level == 1 then
-- drop stuff for steel and copper pick
elseif level == 2 then
-- not used in default picks
elseif level >= 3 then
-- drop stuff for mese and diamond pick
end


Well, as I am still learning and trying to understand this function... my first attempt failed horribly. Can someone untangle this mess?

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_node("default:stone", {
    description = "Stone",
    tiles = {"default_stone.png"},
    is_ground_content = true,
    groups = {cracky=3, stone=1},
    drop = {
    items {
      local level = itemstack:get_tool_capabilities().max_drop_level
        if level == 0 then
              -- drop stuff for stone and wooden pick
              { items = {'default:cobble 1'}, rarity = 2 }
        elseif level == 1 then
              -- drop stuff for steel and copper pick
              { items = {'default:cobble 2'}, rarity = 1 }
        elseif level == 2 then
              -- not used in default picks
              { items = {'default:cobble 3'}, rarity = 1 }
        elseif level >= 3 then
              -- drop stuff for mese and diamond pick
              { items = {'default:cobble 10'}, rarity = 1 }
end
    },
    legacy_mineral = true,
    sounds = default.node_sound_stone_defaults(),
})

PostPosted: Tue May 28, 2013 23:29
by PilzAdam
cypher-neo wrote:
PilzAdam wrote:Assume we have the itemstack of the tool being used:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local level = itemstack:get_tool_capabilities().max_drop_level
if level == 0 then
-- drop stuff for stone and wooden pick
elseif level == 1 then
-- drop stuff for steel and copper pick
elseif level == 2 then
-- not used in default picks
elseif level >= 3 then
-- drop stuff for mese and diamond pick
end


Well, as I am still learning and trying to understand this function... my first attempt failed horribly. Can someone untangle this mess?

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_node("default:stone", {
    description = "Stone",
    tiles = {"default_stone.png"},
    is_ground_content = true,
    groups = {cracky=3, stone=1},
    drop = {
    items {
      local level = itemstack:get_tool_capabilities().max_drop_level
        if level == 0 then
              -- drop stuff for stone and wooden pick
              { items = {'default:cobble 1'}, rarity = 2 }
        elseif level == 1 then
              -- drop stuff for steel and copper pick
              { items = {'default:cobble 2'}, rarity = 1 }
        elseif level == 2 then
              -- not used in default picks
              { items = {'default:cobble 3'}, rarity = 1 }
        elseif level >= 3 then
              -- drop stuff for mese and diamond pick
              { items = {'default:cobble 10'}, rarity = 1 }
end
    },
    legacy_mineral = true,
    sounds = default.node_sound_stone_defaults(),
})

Well, first of all this doesnt belong into the drop field. You need to use the after_dig_node function.
Here is an example usage in my MiniTest game: https://github.com/PilzAdam/MiniTest/blob/master/mods/default/nodes.lua#L184

PostPosted: Tue May 28, 2013 23:53
by cypher-neo
Thanks for all the help PilzAdam! I feel closer to accomplishing my goal of understanding this, but my latest attempt has also failed. Help again?

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_node("default:stone", {
    description = "Stone",
    tiles = {"default_stone.png"},
    is_ground_content = true,
    groups = {cracky=3, stone=1},
    drop = ""
    after_dig_node = (pos, oldnode, oldmetadata, digger)
      local level = itemstack:get_tool_capabilities().max_drop_level
      local inv = digger:get_inventory()
        if level == 0 then
              -- drop stuff for stone and wooden pick
              inv:add_item("default:stone 1")
        elseif level == 1 then
              -- drop stuff for steel and copper pick
              inv:add_item("default:stone 5")
        elseif level == 2 then
              -- not used in default picks
              inv:add_item("default:stone 10")
        elseif level >= 3 then
              -- drop stuff for mese and diamond pick
              inv:add_item("default:stone 20")
end,
    legacy_mineral = true,
    sounds = default.node_sound_stone_defaults(),
})

PostPosted: Wed May 29, 2013 00:18
by PilzAdam
cypher-neo wrote:Thanks for all the help PilzAdam! I feel closer to accomplishing my goal of understanding this, but my latest attempt has also failed. Help again?

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_node("default:stone", {
    description = "Stone",
    tiles = {"default_stone.png"},
    is_ground_content = true,
    groups = {cracky=3, stone=1},
    drop = ""
    after_dig_node = (pos, oldnode, oldmetadata, digger)
      local level = itemstack:get_tool_capabilities().max_drop_level
        if level == 0 then
              -- drop stuff for stone and wooden pick
              inv:add_item("default:stone 1")
        elseif level == 1 then
              -- drop stuff for steel and copper pick
              inv:add_item("default:stone 5")
        elseif level == 2 then
              -- not used in default picks
              inv:add_item("default:stone 10")
        elseif level >= 3 then
              -- drop stuff for mese and diamond pick
              inv:add_item("default:stone 20")
end,
    legacy_mineral = true,
    sounds = default.node_sound_stone_defaults(),
})

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_node("default:stone", {
    description = "Stone",
    tiles = {"default_stone.png"},
    is_ground_content = true,
    groups = {cracky=3, stone=1},
    drop = "",
    after_dig_node = function(pos, oldnode, oldmetadata, digger)
      local inv = digger:get_inventory()
      local itemstack = digger:get_wielded_item()
      local level = itemstack:get_tool_capabilities().max_drop_level
      local inv = digger:get_inventory()
        if level == 0 then
              -- drop stuff for stone and wooden pick
              inv:add_item("default:stone 1")
        elseif level == 1 then
              -- drop stuff for steel and copper pick
              inv:add_item("default:stone 5")
        elseif level == 2 then
              -- not used in default picks
              inv:add_item("default:stone 10")
        elseif level >= 3 then
              -- drop stuff for mese and diamond pick
              inv:add_item("default:stone 20")
        end
    end,
    legacy_mineral = true,
    sounds = default.node_sound_stone_defaults(),
})

Fixed some errors in defining the function and initialized the variable itemstack.

PostPosted: Wed May 29, 2013 00:26
by RealBadAngel
i suggest add there checking if digger is a player
(not only players can dig nodes)

PostPosted: Wed May 29, 2013 02:31
by cypher-neo
PilzAdam wrote:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_node("default:stone", {
    description = "Stone",
    tiles = {"default_stone.png"},
    is_ground_content = true,
    groups = {cracky=3, stone=1},
    drop = "",
    after_dig_node = function(pos, oldnode, oldmetadata, digger)
      local inv = digger:get_inventory()
      local itemstack = digger:get_wielded_item()
      local level = itemstack:get_tool_capabilities().max_drop_level
      local inv = digger:get_inventory()
        if level == 0 then
              -- drop stuff for stone and wooden pick
              inv:add_item("default:stone 1")
        elseif level == 1 then
              -- drop stuff for steel and copper pick
              inv:add_item("default:stone 5")
        elseif level == 2 then
              -- not used in default picks
              inv:add_item("default:stone 10")
        elseif level >= 3 then
              -- drop stuff for mese and diamond pick
              inv:add_item("default:stone 20")
        end
    end,
    legacy_mineral = true,
    sounds = default.node_sound_stone_defaults(),
})

Fixed some errors in defining the function and initialized the variable itemstack.


Although it loaded okay, which is a definite improvement over the last several code experiments I've run, this one generates a huge error when digging.

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
22:28:21: ERROR[main]: ServerError: LuaError: Expecting itemstack, itemstring, table or nil
22:28:21: ERROR[main]: stack traceback:
22:28:21: ERROR[main]:     [C]: in function 'add_item'
22:28:21: ERROR[main]:     ...sean/.minetest/games/glooplava/mods/default/init.lua:1230: in function 'after_dig_node'
22:28:21: ERROR[main]:     /usr/share/minetest/builtin/item.lua:354: in function </usr/share/minetest/builtin/item.lua:313>
22:28:21: ERROR[main]:     (tail call): ?

PostPosted: Wed May 29, 2013 11:08
by PilzAdam
cypher-neo wrote:
PilzAdam wrote:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_node("default:stone", {
    description = "Stone",
    tiles = {"default_stone.png"},
    is_ground_content = true,
    groups = {cracky=3, stone=1},
    drop = "",
    after_dig_node = function(pos, oldnode, oldmetadata, digger)
      local inv = digger:get_inventory()
      local itemstack = digger:get_wielded_item()
      local level = itemstack:get_tool_capabilities().max_drop_level
      local inv = digger:get_inventory()
        if level == 0 then
              -- drop stuff for stone and wooden pick
              inv:add_item("default:stone 1")
        elseif level == 1 then
              -- drop stuff for steel and copper pick
              inv:add_item("default:stone 5")
        elseif level == 2 then
              -- not used in default picks
              inv:add_item("default:stone 10")
        elseif level >= 3 then
              -- drop stuff for mese and diamond pick
              inv:add_item("default:stone 20")
        end
    end,
    legacy_mineral = true,
    sounds = default.node_sound_stone_defaults(),
})

Fixed some errors in defining the function and initialized the variable itemstack.


Although it loaded okay, which is a definite improvement over the last several code experiments I've run, this one generates a huge error when digging.

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
22:28:21: ERROR[main]: ServerError: LuaError: Expecting itemstack, itemstring, table or nil
22:28:21: ERROR[main]: stack traceback:
22:28:21: ERROR[main]:     [C]: in function 'add_item'
22:28:21: ERROR[main]:     ...sean/.minetest/games/glooplava/mods/default/init.lua:1230: in function 'after_dig_node'
22:28:21: ERROR[main]:     /usr/share/minetest/builtin/item.lua:354: in function </usr/share/minetest/builtin/item.lua:313>
22:28:21: ERROR[main]:     (tail call): ?

The correct syntax for add_item() is
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
add_item(list, item)

So in your case:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
inv:add_item("main", "default:stone")

PostPosted: Wed May 29, 2013 18:03
by tinoesroho
... Also remember, if you're wanting to release a mod, you'll want to override the default rather than rewrite it. That means adding a colon in front of the node name like so:

minetest.register_node(":default:whatever"